UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

45 lines 2.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useFocusOutside = useFocusOutside; const react_1 = require("react"); const hooks_1 = require("../../../util/hooks"); const dispatchCustomEvent_1 = require("./dispatchCustomEvent"); /** * Tracks focus outside a React subtree. Returns props for the subtree root. */ function useFocusOutside(callback, ownerDocument = globalThis === null || globalThis === void 0 ? void 0 : globalThis.document) { const handleFocusOutside = (0, hooks_1.useCallbackRef)(callback); const isFocusInsideReactTreeRef = (0, react_1.useRef)(false); (0, react_1.useEffect)(() => { const handleFocus = (event) => { if (event.target && !isFocusInsideReactTreeRef.current) { const eventDetail = { originalEvent: event }; /** * The `DismisableLayer`-API is based on the ability to stop events from propagating and in the end calling `onDismiss` * if `useFocusOutside`-callback runs `event.preventDefault()`. * * Because of the `focusin`-event not being cancelable, * we need to use a custom event to ensure that the event is cancelable. * https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event * > The focusin event is not cancelable. */ (0, dispatchCustomEvent_1.dispatchCustomEvent)(dispatchCustomEvent_1.CUSTOM_EVENTS.FOCUS_OUTSIDE, handleFocusOutside, eventDetail); } }; ownerDocument.addEventListener("focusin", handleFocus); return () => ownerDocument.removeEventListener("focusin", handleFocus); }, [ownerDocument, handleFocusOutside]); /** * By directly setting isFocusInsideReactTreeRef on focus-events at the root of the "dismissable" element, * we can eliminate the need for DOM traversal to verify if the focused element is within the react tree. */ return { onFocusCapture: () => { isFocusInsideReactTreeRef.current = true; }, onBlurCapture: () => { isFocusInsideReactTreeRef.current = false; }, }; } //# sourceMappingURL=useFocusOutside.js.map