import { useLayoutEffect, useRef, type ReactNode } from "react"; import { X } from "lucide-react"; import { Button } from "./primitives"; let openModals = 0; let previousOverflow = ""; /** Native top-layer dialog supplies focus containment and an inert background. */ export function Modal({ id, eyebrow, title, description, children, onClose, closeLabel = "Close dialog", busy = false, size = "wide", initialFocus, returnFocus }: { id: string; eyebrow?: string; title: ReactNode; description?: ReactNode; children: ReactNode; onClose?: () => void; closeLabel?: string; busy?: boolean; size?: "wide" | "compact"; initialFocus?: string; returnFocus?: () => HTMLElement | null; }) { const dialog = useRef(null); const heading = useRef(null); const pointerOnBackdrop = useRef(false); const mounted = useRef(false); useLayoutEffect(() => { mounted.current = true; const element = dialog.current!; const opener = returnFocus?.() ?? document.activeElement as HTMLElement | null; if (!openModals++) { previousOverflow = document.documentElement.style.overflow; document.documentElement.style.overflow = "hidden"; } element.showModal(); const target = initialFocus ? element.querySelector(initialFocus) : heading.current; target?.focus({ preventScroll: true }); return () => { mounted.current = false; element.close(); if (!--openModals) document.documentElement.style.overflow = previousOverflow; // A successful save may keep its opener disabled until the dashboard // refresh finishes. Restore focus when it becomes available again. window.requestAnimationFrame(() => window.requestAnimationFrame(() => { // Ignore React Strict Mode's setup/cleanup rehearsal. if (mounted.current || !opener?.isConnected) return; if (!opener.matches(":disabled")) { opener.focus({ preventScroll: true }); return; } const observer = new window.MutationObserver(() => { if (opener.matches(":disabled")) return; observer.disconnect(); window.clearTimeout(timeout); if (opener.isConnected && document.activeElement === document.body) opener.focus({ preventScroll: true }); }); observer.observe(opener, { attributes: true, attributeFilter: ["disabled"] }); const timeout = window.setTimeout(() => observer.disconnect(), 5000); })); }; }, []); const dismiss = () => { if (!busy) onClose?.(); }; return { event.preventDefault(); event.stopPropagation(); dismiss(); }} onKeyDown={event => { if (event.key !== "Tab") return; event.stopPropagation(); const controls = [...event.currentTarget.querySelectorAll('button, a[href], input, select, textarea, summary, [tabindex]')] .filter(element => element.tabIndex >= 0 && !element.matches(':disabled') && element.getClientRects().length > 0); const first = controls[0]; const last = controls.at(-1); if (!first || !last) { event.preventDefault(); heading.current?.focus(); return; } const active = document.activeElement; if (event.shiftKey && (active === first || !controls.includes(active as HTMLElement))) { event.preventDefault(); last.focus(); } else if (!event.shiftKey && active === last) { event.preventDefault(); first.focus(); } }} onPointerDown={event => { pointerOnBackdrop.current = event.target === event.currentTarget; }} onClick={event => { if (!pointerOnBackdrop.current || event.target !== event.currentTarget) return; const bounds = event.currentTarget.getBoundingClientRect(); if (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom) dismiss(); }}>
{eyebrow &&

{eyebrow}

}

{title}

{description &&

{description}

}
{children}
; }