@ariakit/react-core
Version:
Ariakit React core
132 lines (117 loc) • 4.73 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
var _ENNAUHNHcjs = require('./ENNAUHNH.cjs');
var _26P4PLHIcjs = require('./26P4PLHI.cjs');
var _YAKNSXYIcjs = require('./YAKNSXYI.cjs');
var _EMYYI4CZcjs = require('./EMYYI4CZ.cjs');
var _MZ2HG624cjs = require('./MZ2HG624.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 = _MZ2HG624cjs.useEvent.call(void 0, listener);
const open = _EMYYI4CZcjs.useStoreState.call(void 0, store, "open");
const focusedRef = _react.useRef.call(void 0, false);
_MZ2HG624cjs.useSafeLayoutEffect.call(void 0, () => {
if (!open) return;
if (!domReady) return;
const { contentElement } = store.getState();
if (!contentElement) return;
const onFocus = () => {
focusedRef.current = true;
};
contentElement.addEventListener("focusin", onFocus, true);
return () => contentElement.removeEventListener("focusin", onFocus, true);
}, [store, open, domReady]);
_react.useEffect.call(void 0, () => {
if (!open) return;
const onEvent = (event) => {
const { contentElement, disclosureElement } = store.getState();
const target = event.target;
if (!contentElement) return;
if (!target) return;
if (!isInDocument(target)) return;
if (_dom.contains.call(void 0, contentElement, target)) return;
if (isDisclosure(disclosureElement, target)) return;
if (target.hasAttribute("data-focus-trap")) return;
if (isMouseEventOnDialog(event, contentElement)) return;
const focused = focusedRef.current;
if (focused && !_26P4PLHIcjs.isElementMarked.call(void 0, target, contentElement.id)) return;
if (_YAKNSXYIcjs.isSafariFocusAncestor.call(void 0, target)) return;
callListener(event);
};
return _events.addGlobalEventListener.call(void 0, type, onEvent, capture);
}, [open, capture]);
}
function shouldHideOnInteractOutside(hideOnInteractOutside, event) {
if (typeof hideOnInteractOutside === "function") {
return hideOnInteractOutside(event);
}
return !!hideOnInteractOutside;
}
function useHideOnInteractOutside(store, hideOnInteractOutside, domReady) {
const open = _EMYYI4CZcjs.useStoreState.call(void 0, store, "open");
const previousMouseDownRef = _ENNAUHNHcjs.usePreviousMouseDownRef.call(void 0, open);
const props = { store, domReady, capture: true };
useEventOutside({
...props,
type: "click",
listener: (event) => {
const { contentElement } = store.getState();
const previousMouseDown = previousMouseDownRef.current;
if (!previousMouseDown) return;
if (!_dom.isVisible.call(void 0, previousMouseDown)) return;
if (!_26P4PLHIcjs.isElementMarked.call(void 0, previousMouseDown, contentElement == null ? void 0 : contentElement.id)) return;
if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return;
store.hide();
}
});
useEventOutside({
...props,
type: "focusin",
listener: (event) => {
const { contentElement } = store.getState();
if (!contentElement) return;
if (event.target === _dom.getDocument.call(void 0, contentElement)) return;
if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return;
store.hide();
}
});
useEventOutside({
...props,
type: "contextmenu",
listener: (event) => {
if (!shouldHideOnInteractOutside(hideOnInteractOutside, event)) return;
store.hide();
}
});
}
exports.useHideOnInteractOutside = useHideOnInteractOutside;