20 lines
7.7 KiB
JSON
20 lines
7.7 KiB
JSON
{
|
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
"name": "radix-dialog",
|
|
"type": "registry:ui",
|
|
"title": "Dialog",
|
|
"description": "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.",
|
|
"dependencies": [
|
|
"motion",
|
|
"lucide-react",
|
|
"radix-ui"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "registry/radix/dialog/index.tsx",
|
|
"content": "'use client';\n\nimport * as React from 'react';\nimport { Dialog as DialogPrimitive } from 'radix-ui';\nimport { X } from 'lucide-react';\nimport {\n AnimatePresence,\n motion,\n type HTMLMotionProps,\n type Transition,\n} from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype DialogContextType = {\n isOpen: boolean;\n};\n\nconst DialogContext = React.createContext<DialogContextType | undefined>(\n undefined,\n);\n\nconst useDialog = (): DialogContextType => {\n const context = React.useContext(DialogContext);\n if (!context) {\n throw new Error('useDialog must be used within a Dialog');\n }\n return context;\n};\n\ntype DialogProps = React.ComponentProps<typeof DialogPrimitive.Root>;\n\nfunction Dialog({ children, ...props }: DialogProps) {\n const [isOpen, setIsOpen] = React.useState(\n props?.open ?? props?.defaultOpen ?? false,\n );\n\n React.useEffect(() => {\n if (props?.open !== undefined) setIsOpen(props.open);\n }, [props?.open]);\n\n const handleOpenChange = React.useCallback(\n (open: boolean) => {\n setIsOpen(open);\n props.onOpenChange?.(open);\n },\n [props],\n );\n\n return (\n <DialogContext.Provider value={{ isOpen }}>\n <DialogPrimitive.Root\n data-slot=\"dialog\"\n {...props}\n onOpenChange={handleOpenChange}\n >\n {children}\n </DialogPrimitive.Root>\n </DialogContext.Provider>\n );\n}\n\ntype DialogTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\n\nfunction DialogTrigger(props: DialogTriggerProps) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\ntype DialogPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>;\n\nfunction DialogPortal(props: DialogPortalProps) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\ntype DialogCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\nfunction DialogClose(props: DialogCloseProps) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\ntype DialogOverlayProps = React.ComponentProps<typeof DialogPrimitive.Overlay>;\n\nfunction DialogOverlay({ className, ...props }: DialogOverlayProps) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className,\n )}\n {...props}\n />\n );\n}\n\ntype FlipDirection = 'top' | 'bottom' | 'left' | 'right';\n\ntype DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> &\n HTMLMotionProps<'div'> & {\n from?: FlipDirection;\n transition?: Transition;\n };\n\nfunction DialogContent({\n className,\n children,\n from = 'top',\n transition = { type: 'spring', stiffness: 150, damping: 25 },\n ...props\n}: DialogContentProps) {\n const { isOpen } = useDialog();\n\n const initialRotation =\n from === 'top' || from === 'left' ? '20deg' : '-20deg';\n const isVertical = from === 'top' || from === 'bottom';\n const rotateAxis = isVertical ? 'rotateX' : 'rotateY';\n\n return (\n <AnimatePresence>\n {isOpen && (\n <DialogPortal forceMount data-slot=\"dialog-portal\">\n <DialogOverlay asChild forceMount>\n <motion.div\n key=\"dialog-overlay\"\n initial={{ opacity: 0, filter: 'blur(4px)' }}\n animate={{ opacity: 1, filter: 'blur(0px)' }}\n exit={{ opacity: 0, filter: 'blur(4px)' }}\n transition={{ duration: 0.2, ease: 'easeInOut' }}\n />\n </DialogOverlay>\n <DialogPrimitive.Content asChild forceMount {...props}>\n <motion.div\n key=\"dialog-content\"\n data-slot=\"dialog-content\"\n initial={{\n opacity: 0,\n filter: 'blur(4px)',\n transform: `perspective(500px) ${rotateAxis}(${initialRotation}) scale(0.8)`,\n }}\n animate={{\n opacity: 1,\n filter: 'blur(0px)',\n transform: `perspective(500px) ${rotateAxis}(0deg) scale(1)`,\n }}\n exit={{\n opacity: 0,\n filter: 'blur(4px)',\n transform: `perspective(500px) ${rotateAxis}(${initialRotation}) scale(0.8)`,\n }}\n transition={transition}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg rounded-xl',\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </motion.div>\n </DialogPrimitive.Content>\n </DialogPortal>\n )}\n </AnimatePresence>\n );\n}\n\ntype DialogHeaderProps = React.ComponentProps<'div'>;\n\nfunction DialogHeader({ className, ...props }: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\n 'flex flex-col space-y-1.5 text-center sm:text-left',\n className,\n )}\n {...props}\n />\n );\n}\n\ntype DialogFooterProps = React.ComponentProps<'div'>;\n\nfunction DialogFooter({ className, ...props }: DialogFooterProps) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end gap-2',\n className,\n )}\n {...props}\n />\n );\n}\n\ntype DialogTitleProps = React.ComponentProps<typeof DialogPrimitive.Title>;\n\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className,\n )}\n {...props}\n />\n );\n}\n\ntype DialogDescriptionProps = React.ComponentProps<\n typeof DialogPrimitive.Description\n>;\n\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n useDialog,\n type DialogContextType,\n type DialogProps,\n type DialogTriggerProps,\n type DialogPortalProps,\n type DialogCloseProps,\n type DialogOverlayProps,\n type DialogContentProps,\n type DialogHeaderProps,\n type DialogFooterProps,\n type DialogTitleProps,\n type DialogDescriptionProps,\n};\n",
|
|
"type": "registry:ui",
|
|
"target": "components/animate-ui/radix/dialog.tsx"
|
|
}
|
|
]
|
|
} |