// src/components/ui/modal.tsx import * as DialogPrimitive from '@radix-ui/react-dialog'; import { Loader, X } from 'lucide-react'; import { FC, ReactNode, useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; interface ModalProps { open: boolean; onOpenChange?: (open: boolean) => void; title?: ReactNode; children: ReactNode; footer?: ReactNode; showfooter?: boolean; className?: string; size?: 'small' | 'default' | 'large'; closable?: boolean; closeIcon?: ReactNode; maskClosable?: boolean; destroyOnClose?: boolean; full?: boolean; confirmLoading?: boolean; cancelText?: ReactNode | string; okText?: ReactNode | string; onOk?: () => void; onCancel?: () => void; } export const Modal: FC = ({ open, onOpenChange, title, children, footer, showfooter = true, className = '', size = 'default', closable = true, closeIcon = , maskClosable = true, destroyOnClose = false, full = false, onOk, onCancel, confirmLoading, cancelText, okText, }) => { const sizeClasses = { small: 'max-w-md', default: 'max-w-2xl', large: 'max-w-4xl', }; const { t } = useTranslation(); // Handle ESC key close useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape' && maskClosable) { onOpenChange?.(false); } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [maskClosable, onOpenChange]); const handleCancel = useCallback(() => { onOpenChange?.(false); onCancel?.(); }, [onOpenChange, onCancel]); const handleOk = useCallback(() => { onOpenChange?.(true); onOk?.(); }, [onOpenChange, onOk]); const handleChange = (open: boolean) => { onOpenChange?.(open); if (open) { handleOk(); } if (!open) { handleCancel(); } }; const footEl = useMemo(() => { if (showfooter === false) { return <>; } let footerTemp; if (footer) { footerTemp = footer; } else { footerTemp = (
); } return (
{footerTemp}
); }, [ footer, cancelText, t, confirmLoading, okText, handleCancel, handleOk, showfooter, ]); return ( maskClosable && onOpenChange?.(false)} > e.stopPropagation()} > {/* title */} {title && (
{title} {closable && ( )}
)} {/* title */} {!title && ( )} {/* content */}
{destroyOnClose && !open ? null : children}
{/* footer */} {footEl}
); }; // example usage /* import { Modal } from '@/components/ui/modal'; function Demo() { const [open, setOpen] = useState(false); return (
} >
弹窗内容区域
弹窗内容区域
); } */