@ariakit/react-core
Version:
Ariakit React core
136 lines (123 loc) • 5.18 kB
JavaScript
"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;