import { useEffect, useRef } from 'react'; import { FocusTrap } from './focus-trap'; import { X } from 'lucide-react'; import { Button } from './button'; import { cn } from '@/lib/utils'; export interface ModalProps { open: boolean; onClose: () => void; children: React.ReactNode; title?: string; closeOnOverlayClick?: boolean; closeOnEscape?: boolean; size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'; className?: string; } const sizeClasses = { sm: 'max-w-sm', md: 'max-w-md', lg: 'max-w-lg', xl: 'max-w-xl', full: 'max-w-full mx-4', }; /** * Composant Modal réutilisable avec overlay, fermeture, et gestion du focus. */ export function Modal({ open, onClose, children, title, closeOnOverlayClick = true, closeOnEscape = true, size = 'md', className, }: ModalProps) { const modalRef = useRef(null); // Empêcher le scroll du body quand le modal est ouvert useEffect(() => { if (open) { document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = ''; }; } }, [open]); // Gérer le clic sur l'overlay const handleOverlayClick = (e: React.MouseEvent) => { if (closeOnOverlayClick && e.target === e.currentTarget) { onClose(); } }; // Ne pas rendre le modal s'il n'est pas ouvert if (!open) return null; return (
{/* Overlay */}
{/* Modal Content */}
e.stopPropagation()} > {/* Header */} {(title || closeOnEscape) && (
{title && ( )} {closeOnEscape && ( )}
)} {/* Content */}
{children}
); }