UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

45 lines (44 loc) 1.67 kB
import { useCallback, useEffect, useMemo } from "react"; //#region src/hooks/useOnOutsideClick.tsx const stopPropagation = true; /** * Calls all handlers in reverse order * @param event The MouseEvent generated by the click event. */ function handleClick(event) { if (!event.defaultPrevented) { for (const handler of Object.values(registry).reverse()) if (handler(event) === stopPropagation || event.defaultPrevented) break; } } const registry = {}; function register(id, handler) { registry[id] = handler; } function deregister(id) { delete registry[id]; } let handlerId = 0; const useOnOutsideClick = ({ containerRef, ignoreClickRefs, onClickOutside }) => { const id = useMemo(() => handlerId++, []); const handler = useCallback((event) => { var _containerRef$current; if (event instanceof MouseEvent && event.button > 0) return stopPropagation; if ((_containerRef$current = containerRef.current) !== null && _containerRef$current !== void 0 && _containerRef$current.contains(event.target)) return stopPropagation; if (ignoreClickRefs && ignoreClickRefs.some(({ current }) => current === null || current === void 0 ? void 0 : current.contains(event.target))) return stopPropagation; onClickOutside(event); }, [ containerRef, ignoreClickRefs, onClickOutside ]); useEffect(() => { if (Object.keys(registry).length === 0) document.addEventListener("mousedown", handleClick, { capture: true }); register(id, handler); return () => { deregister(id); if (Object.keys(registry).length === 0) document.removeEventListener("mousedown", handleClick, { capture: true }); }; }, [id, handler]); }; //#endregion export { useOnOutsideClick };