UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

70 lines (67 loc) 2 kB
'use client'; import { useRef, useCallback, useEffect } from 'react'; import { scopeTab } from './scope-tab.mjs'; import { FOCUS_SELECTOR, tabbable, focusable } from './tabbable.mjs'; function useFocusTrap(active = true) { const ref = useRef(null); const focusNode = (node) => { let focusElement = node.querySelector("[data-autofocus]"); if (!focusElement) { const children = Array.from(node.querySelectorAll(FOCUS_SELECTOR)); focusElement = children.find(tabbable) || children.find(focusable) || null; if (!focusElement && focusable(node)) { focusElement = node; } } if (focusElement) { focusElement.focus({ preventScroll: true }); } else if (process.env.NODE_ENV === "development") { console.warn( "[@mantine/hooks/use-focus-trap] Failed to find focusable element within provided node", node ); } }; const setRef = useCallback( (node) => { if (!active) { return; } if (node === null) { return; } if (ref.current === node) { return; } if (node) { setTimeout(() => { if (node.getRootNode()) { focusNode(node); } else if (process.env.NODE_ENV === "development") { console.warn("[@mantine/hooks/use-focus-trap] Ref node is not part of the dom", node); } }); ref.current = node; } else { ref.current = null; } }, [active] ); useEffect(() => { if (!active) { return void 0; } ref.current && setTimeout(() => focusNode(ref.current)); const handleKeyDown = (event) => { if (event.key === "Tab" && ref.current) { scopeTab(ref.current, event); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [active]); return setRef; } export { useFocusTrap }; //# sourceMappingURL=use-focus-trap.mjs.map