import { X } from "lucide-react"; import * as React from "react"; import { createPortal } from "react-dom"; import { cn } from "../../lib/utils"; type DialogContextValue = { open: boolean; setOpen: (open: boolean) => void; }; const DialogContext = React.createContext(null); function useDialogContext(componentName: string) { const context = React.useContext(DialogContext); if (!context) { throw new Error(`${componentName} must be used within Dialog`); } return context; } function composeEventHandlers( theirs: ((event: E) => void) | undefined, ours: (event: E) => void, ) { return (event: E) => { theirs?.(event); if (!event.defaultPrevented) { ours(event); } }; } type DialogProps = { open?: boolean; defaultOpen?: boolean; onOpenChange?: (open: boolean) => void; children?: React.ReactNode; }; function Dialog({ open, defaultOpen = false, onOpenChange, children, }: DialogProps) { const [internalOpen, setInternalOpen] = React.useState(defaultOpen); const isControlled = open !== undefined; const currentOpen = isControlled ? open : internalOpen; const setOpen = React.useCallback( (nextOpen: boolean) => { if (!isControlled) { setInternalOpen(nextOpen); } onOpenChange?.(nextOpen); }, [isControlled, onOpenChange], ); const value = React.useMemo( () => ({ open: currentOpen, setOpen }), [currentOpen, setOpen], ); return ( {children} ); } type DialogTriggerProps = React.ButtonHTMLAttributes & { asChild?: boolean; }; const DialogTrigger = React.forwardRef( ({ asChild = false, children, onClick, ...props }, ref) => { const { setOpen } = useDialogContext("DialogTrigger"); const handleOpen = (event: React.MouseEvent) => { onClick?.(event); if (!event.defaultPrevented) { setOpen(true); } }; if (asChild && React.isValidElement(children)) { const child = children as React.ReactElement<{ onClick?: React.MouseEventHandler; }>; return React.cloneElement(child, { ...props, onClick: composeEventHandlers( child.props.onClick as React.MouseEventHandler, () => setOpen(true), ), }); } return ( ); }, ); DialogTrigger.displayName = "DialogTrigger"; const DialogPortal = ({ children }: { children?: React.ReactNode }) => { if (typeof document === "undefined") { return null; } return createPortal(children, document.body); }; DialogPortal.displayName = "DialogPortal"; const DialogClose = React.forwardRef( ({ asChild = false, children, onClick, ...props }, ref) => { const { setOpen } = useDialogContext("DialogClose"); const handleClose = (event: React.MouseEvent) => { onClick?.(event); if (!event.defaultPrevented) { setOpen(false); } }; if (asChild && React.isValidElement(children)) { const child = children as React.ReactElement<{ onClick?: React.MouseEventHandler; }>; return React.cloneElement(child, { ...props, onClick: composeEventHandlers( child.props.onClick as React.MouseEventHandler, () => setOpen(false), ), }); } return ( ); }, ); DialogClose.displayName = "DialogClose"; const DialogOverlay = React.forwardRef< HTMLButtonElement, React.ButtonHTMLAttributes >(({ className, onMouseDown, ...props }, ref) => { const { setOpen } = useDialogContext("DialogOverlay"); return (