import { useEffect, useRef, type ReactNode } from "react"; import { createPortal } from "react-dom"; import { ScrollableContent } from "../virtual/ScrollableContent"; import controls from "./Controls.module.scss"; import styles from "./Modal.module.scss"; export function Modal({ id, open, title, children, busy, wide, onClose, onSubmit, secondaryAction, closeLabel = t("取消"), submitLabel = t("保存") }: { id?: string; open: boolean; title: string; children: ReactNode; busy?: boolean; wide?: boolean; onClose: () => void; onSubmit?: () => void; secondaryAction?: ReactNode; closeLabel?: string; submitLabel?: string }) { const dialog = useRef(null); const closeRef = useRef(onClose); const busyRef = useRef(Boolean(busy)); closeRef.current = onClose; busyRef.current = Boolean(busy); useEffect(() => { if (!open) return; const previous = document.activeElement as HTMLElement | null; const onKey = (event: KeyboardEvent) => { if (event.key === "Escape" && !busyRef.current) closeRef.current(); }; document.addEventListener("keydown", onKey); requestAnimationFrame(() => dialog.current?.querySelector("input,button")?.focus()); return () => { document.removeEventListener("keydown", onKey); if (previous && document.contains(previous)) previous.focus(); }; }, [open]); if (!open) return null; return createPortal(
, document.body); }