import { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; export function Modal({ isOpen, onClose, children, maxW, h }: { isOpen: boolean; onClose: () => void; children: React.ReactNode; maxW?: number; h?: number; }) { const modalRef = useRef(null); const [shouldRender, setShouldRender] = useState(isOpen); const [isClosing, setIsClosing] = useState(false); // Show/hide logic useEffect(() => { if (isOpen) { setShouldRender(true); setIsClosing(false); } else if (shouldRender) { setIsClosing(true); const timeout = setTimeout(() => { setShouldRender(false); }, 100); // Match fade-out duration return () => clearTimeout(timeout); } }, [isOpen, shouldRender]); // Close on Escape key useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; if (isOpen) document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [isOpen, onClose]); // Close on outside click useEffect(() => { const handleClick = (e: MouseEvent) => { if ( modalRef.current && !modalRef.current.contains(e.target as Node) ) { onClose(); } }; if (isOpen) document.addEventListener('mousedown', handleClick); return () => document.removeEventListener('mousedown', handleClick); }, [isOpen, onClose]); if (!shouldRender) return null; return ReactDOM.createPortal(
{children}
, document.body ); }