UNPKG

@ariakit/react-core

Version:

Ariakit React core

136 lines (123 loc) 5.18 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); var _5RIUFRY2cjs = require('./5RIUFRY2.cjs'); var _26P4PLHIcjs = require('./26P4PLHI.cjs'); var _RDNUVX4Vcjs = require('./RDNUVX4V.cjs'); var _4KGS3DOWcjs = require('./4KGS3DOW.cjs'); // src/dialog/utils/use-hide-on-interact-outside.ts var _dom = require('@ariakit/core/utils/dom'); var _events = require('@ariakit/core/utils/events'); var _react = require('react'); function isInDocument(target) { if (target.tagName === "HTML") return true; return _dom.contains.call(void 0, _dom.getDocument.call(void 0, target).body, target); } function isDisclosure(disclosure, target) { if (!disclosure) return false; if (_dom.contains.call(void 0, disclosure, target)) return true; const activeId = target.getAttribute("aria-activedescendant"); if (activeId) { const activeElement = _dom.getDocument.call(void 0, disclosure).getElementById(activeId); if (activeElement) { return _dom.contains.call(void 0, disclosure, activeElement); } } return false; } function isMouseEventOnDialog(event, dialog) { if (!("clientY" in event)) return false; const rect = dialog.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return false; return rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width; } function useEventOutside({ store, type, listener, capture, domReady }) { const callListener = _4KGS3DOWcjs.useEvent.call(void 0, listener); const open = _RDNUVX4Vcjs.useStoreState.call(void 0, store, "open"); const contentElement = _RDNUVX4Vcjs.useStoreState.call(void 0, store, "contentElement"); const focusedRef = _react.useRef.call(void 0, false); _4KGS3DOWcjs.useSafeLayoutEffect.call(void 0, () => { if (!open) return; if (!domReady) return; if (!contentElement) return; const onFocus = () => { focusedRef.current = true; }; contentElement.addEventListener("focusin", onFocus, true); return () => contentElement.removeEventListener("focusin", onFocus, true); }, [open, domReady, contentElement]); _react.useEffect.call(void 0, () => { if (!open) return; const onEvent = (event) => { const { contentElement: contentElement2, disclosureElement } = store.getState(); const target = event.target; if (!contentElement2) return; if (!target) return; if (!isInDocument(target)) return; if (_dom.contains.call(void 0, contentElement2, target)) return; if (isDisclosure(disclosureElement, target)) return; if (target.hasAttribute("data-focus-trap")) return; if (isMouseEventOnDialog(event, contentElement2)) return; const focused = focusedRef.current; if (focused && !_26P4PLHIcjs.isElementMarked.call(void 0, target, contentElement2.id)) return; callListener(event); }; const win = contentElement ? _dom.getWindow.call(void 0, contentElement) : void 0; return _events.addGlobalEventListener.call(void 0, type, onEvent, capture, win); }, [open, capture, store, type, callListener, contentElement]); } function shouldHideOnInteractOutside(hideOnInteractOutside, event) { if (typeof hideOnInteractOutside === "function") { return hideOnInteractOutside(event); } return !!hideOnInteractOutside; } function useHideOnInteractOutside(store, hideOnInteractOutside, domReady, interactedOutsideRef) { const open = _RDNUVX4Vcjs.useStoreState.call(void 0, store, "open"); const contentElement = _RDNUVX4Vcjs.useStoreState.call(void 0, store, "contentElement"); const contentWindow = contentElement ? _dom.getWindow.call(void 0, contentElement) : void 0; const previousMouseDownRef = _5RIUFRY2cjs.usePreviousMouseDownRef.call(void 0, open, contentWindow); const props = { store, domReady, capture: true }; useEventOutside({ ...props, type: "click", listener: (event) => { const { contentElement: contentElement2 } = store.getState(); const previousMouseDown = previousMouseDownRef.current; if (!previousMouseDown) return; if (!_26P4PLHIcjs.isElementMarked.call(void 0, previousMouseDown, contentElement2 == null ? void 0 : contentElement2.id)) return; if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return; if (interactedOutsideRef) { interactedOutsideRef.current = true; } store.hide(); } }); useEventOutside({ ...props, type: "focusin", listener: (event) => { const { contentElement: contentElement2 } = store.getState(); if (!contentElement2) return; if (event.target === _dom.getDocument.call(void 0, contentElement2)) return; if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return; store.hide(); } }); useEventOutside({ ...props, type: "contextmenu", listener: (event) => { if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return; if (interactedOutsideRef) { interactedOutsideRef.current = true; } store.hide(); } }); } exports.useHideOnInteractOutside = useHideOnInteractOutside;