import React, { useState, useCallback, useContext, createContext } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { cn } from '@/lib/utils'; interface DialogContextType { open: boolean; setOpen: (open: boolean) => void; } const DialogContext = createContext(undefined); function useDialog() { const context = useContext(DialogContext); if (!context) { throw new Error('Dialog components must be used within a Dialog'); } return context; } interface DialogProps { open?: boolean; onOpenChange?: (open: boolean) => void; children: React.ReactNode; } function Dialog({ open: controlledOpen, onOpenChange, children }: DialogProps) { const [internalOpen, setInternalOpen] = useState(false); const isControlled = controlledOpen !== undefined; const open = isControlled ? controlledOpen : internalOpen; const setOpen = useCallback( (newOpen: boolean) => { if (!isControlled) { setInternalOpen(newOpen); } onOpenChange?.(newOpen); }, [isControlled, onOpenChange] ); return ( {children} ); } function DialogTrigger({ children, asChild, ...props }: React.ButtonHTMLAttributes & { asChild?: boolean }) { const { setOpen } = useDialog(); if (asChild && React.isValidElement(children)) { return React.cloneElement(children as React.ReactElement, { ...props, onClick: (e: React.MouseEvent) => { setOpen(true); children.props.onClick?.(e); }, }); } return ( ); } function DialogPortal({ children }: { children: React.ReactNode }) { const [mounted, setMounted] = React.useState(false); React.useEffect(() => { setMounted(true); }, []); if (!mounted) return null; return createPortal(children, document.body); } function DialogClose({ children, asChild, ...props }: React.ButtonHTMLAttributes & { asChild?: boolean }) { const { setOpen } = useDialog(); if (asChild && React.isValidElement(children)) { return React.cloneElement(children as React.ReactElement, { ...props, onClick: (e: React.MouseEvent) => { setOpen(false); children.props.onClick?.(e); }, }); } return ( ); } interface DialogOverlayProps extends React.HTMLAttributes {} function DialogOverlay({ className, onClick, ...props }: DialogOverlayProps) { const { setOpen } = useDialog(); return ( { setOpen(false); onClick?.(e as any); }} {...props} /> ); } interface DialogContentProps extends React.HTMLAttributes { showCloseButton?: boolean; } function DialogContent({ className, children, showCloseButton = true, ...props }: DialogContentProps) { const { open } = useDialog(); return ( {open && ( <> {children} {showCloseButton && ( )} )} ); } function DialogHeader({ className, ...props }: React.HTMLAttributes) { return (
); } function DialogFooter({ className, ...props }: React.HTMLAttributes) { return (
); } function DialogTitle({ className, ...props }: React.HTMLAttributes) { return (

); } function DialogDescription({ className, ...props }: React.HTMLAttributes) { return (

); } export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, AnimatePresence, };