import { useEffect, type RefObject } from "react"; /** While `active`, close (call `onClose`) on Escape or a mousedown outside ALL of the given * element(s). The reusable half of the popover/dropdown pattern that several components each * hand-rolled; positioning stays with the caller (it varies per popover). Pass the panel ref * (and optionally a trigger ref so clicking the trigger doesn't immediately re-close). */ export function useDismiss( active: boolean, onClose: () => void, refs: RefObject | RefObject[], ): void { useEffect(() => { if (!active) return; const list = Array.isArray(refs) ? refs : [refs]; const onDown = (e: MouseEvent) => { const target = e.target as Node; if (!list.some((r) => r.current?.contains(target))) onClose(); }; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; document.addEventListener("mousedown", onDown); document.addEventListener("keydown", onKey); return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onKey); }; // Matches the original effects: (re)subscribe only when open/closed toggles. Refs are // stable and onClose is read fresh from this run's closure. // eslint-disable-next-line react-hooks/exhaustive-deps }, [active]); }