'use client' import * as React from 'react' import * as DialogPrimitive from '@radix-ui/react-dialog' import { cn } from '../../lib/utils' interface DialogContextValue { isLoading: boolean setIsLoading: (loading: boolean) => void canClose: boolean setCanClose: (canClose: boolean) => void } const DialogContext = React.createContext(null) function useDialogContext() { const context = React.useContext(DialogContext) if (!context) { throw new Error('Dialog components must be used within BaseDialog') } return context } export interface BaseDialogProps { open: boolean onOpenChange: (open: boolean) => void children: React.ReactNode size?: 'sm' | 'md' | 'lg' loading?: boolean } const sizeClasses = { sm: 'max-w-sm', md: 'max-w-md', lg: 'max-w-lg', } export function BaseDialog({ open, onOpenChange, children, size = 'md', loading = false, }: BaseDialogProps) { const [isLoading, setIsLoading] = React.useState(loading) const [canClose, setCanClose] = React.useState(!loading) React.useEffect(() => { setIsLoading(loading) setCanClose(!loading) }, [loading]) const handleOpenChange = React.useCallback( (newOpen: boolean) => { if (!newOpen && !canClose) { return } onOpenChange(newOpen) }, [canClose, onOpenChange] ) const contextValue = React.useMemo( () => ({ isLoading, setIsLoading, canClose, setCanClose }), [isLoading, canClose] ) return ( { if (!canClose) e.preventDefault() }} onEscapeKeyDown={(e) => { if (!canClose) e.preventDefault() }} > {children} ) } export interface DialogHeaderProps { children: React.ReactNode className?: string } function DialogHeader({ children, className }: DialogHeaderProps) { const { canClose } = useDialogContext() return (
{children}
Close
) } export interface DialogTitleProps { children: React.ReactNode className?: string } function DialogTitle({ children, className }: DialogTitleProps) { return ( {children} ) } export interface DialogBodyProps { children: React.ReactNode className?: string } function DialogBody({ children, className }: DialogBodyProps) { return (
{children}
) } export interface DialogFooterProps { children: React.ReactNode className?: string } function DialogFooter({ children, className }: DialogFooterProps) { return (
{children}
) } // Compound component pattern BaseDialog.Header = DialogHeader BaseDialog.Title = DialogTitle BaseDialog.Body = DialogBody BaseDialog.Footer = DialogFooter export { useDialogContext }