UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

55 lines (54 loc) 1.87 kB
"use client"; import { useCallbackRef } from "../utils/use-callback-ref/use-callback-ref.mjs"; import { useCallback, useEffect, useRef, useState } from "react"; //#region packages/@mantine/hooks/src/use-focus-within/use-focus-within.ts function containsRelatedTarget(event) { if (event.currentTarget instanceof HTMLElement && event.relatedTarget instanceof HTMLElement) return event.currentTarget.contains(event.relatedTarget); return false; } function useFocusWithin({ onBlur, onFocus } = {}) { const [focused, setFocused] = useState(false); const focusedRef = useRef(false); const previousNode = useRef(null); const onFocusRef = useCallbackRef(onFocus); const onBlurRef = useCallbackRef(onBlur); const _setFocused = useCallback((value) => { setFocused(value); focusedRef.current = value; }, []); const handleFocusIn = useCallback((event) => { if (!focusedRef.current) { _setFocused(true); onFocusRef(event); } }, []); const handleFocusOut = useCallback((event) => { if (focusedRef.current && !containsRelatedTarget(event)) { _setFocused(false); onBlurRef(event); } }, []); const callbackRef = useCallback((node) => { if (!node) return; if (previousNode.current) { previousNode.current.removeEventListener("focusin", handleFocusIn); previousNode.current.removeEventListener("focusout", handleFocusOut); } node.addEventListener("focusin", handleFocusIn); node.addEventListener("focusout", handleFocusOut); previousNode.current = node; }, [handleFocusIn, handleFocusOut]); useEffect(() => () => { if (previousNode.current) { previousNode.current.removeEventListener("focusin", handleFocusIn); previousNode.current.removeEventListener("focusout", handleFocusOut); } }, []); return { ref: callbackRef, focused }; } //#endregion export { useFocusWithin }; //# sourceMappingURL=use-focus-within.mjs.map