@ariakit/react-core
Version:
Ariakit React core
224 lines (222 loc) • 7.33 kB
JavaScript
"use client";
import {
useMenuList
} from "../__chunks/KLX75WFW.js";
import {
useHovercard
} from "../__chunks/HXWJHWVX.js";
import "../__chunks/PYFWN42T.js";
import {
useMenuProviderContext
} from "../__chunks/6UXSIZXV.js";
import "../__chunks/5FUUHUOH.js";
import "../__chunks/4LEWR5KQ.js";
import "../__chunks/O5G4B22L.js";
import "../__chunks/AOOXE4FT.js";
import {
createDialogComponent
} from "../__chunks/KOWQMA5P.js";
import "../__chunks/27UGDV3K.js";
import "../__chunks/AOQQTIBO.js";
import "../__chunks/5M6RIVE2.js";
import "../__chunks/5L75JEQF.js";
import "../__chunks/POCYREJH.js";
import "../__chunks/GDMALITU.js";
import "../__chunks/6GXEOXGT.js";
import "../__chunks/VKPF3GCK.js";
import "../__chunks/R3NHSIAL.js";
import "../__chunks/SUN7W7XS.js";
import "../__chunks/336RKHJD.js";
import "../__chunks/QDZPIHAY.js";
import "../__chunks/CZ4GFWYL.js";
import "../__chunks/Z5GCVBAY.js";
import "../__chunks/IGR4SXG2.js";
import "../__chunks/677M2CI3.js";
import "../__chunks/S7U6BLGA.js";
import "../__chunks/QXEZ5Q7H.js";
import "../__chunks/3NDVDEB4.js";
import "../__chunks/AOUGVQZ3.js";
import "../__chunks/K2ZF5NU7.js";
import "../__chunks/63XF7ACK.js";
import "../__chunks/HIPI64MW.js";
import "../__chunks/NGV5ZW5X.js";
import "../__chunks/H5Z3PUKM.js";
import "../__chunks/NLF4OZJK.js";
import "../__chunks/7NJRHOSP.js";
import "../__chunks/AB647VKY.js";
import "../__chunks/467XRHWL.js";
import "../__chunks/2LVHRIRC.js";
import "../__chunks/FYYAZUDI.js";
import "../__chunks/NO3UEYQ2.js";
import "../__chunks/3F6D4KUU.js";
import "../__chunks/SWN3JYXT.js";
import {
useStoreState
} from "../__chunks/SOQQIDO4.js";
import "../__chunks/CTVD4XJH.js";
import {
createElement,
createHook,
forwardRef
} from "../__chunks/L4OUMOCQ.js";
import {
useMergeRefs
} from "../__chunks/W2TDKEPX.js";
import "../__chunks/AZVQSWGA.js";
// src/menu/menu.tsx
import { fireEvent } from "@ariakit/core/utils/events";
import { hasFocusWithin } from "@ariakit/core/utils/focus";
import { invariant, isFalsyBooleanCallback } from "@ariakit/core/utils/misc";
import { createRef, useEffect, useMemo, useRef, useState } from "react";
var TagName = "div";
var useMenu = createHook(function useMenu2({
store,
modal: modalProp = false,
portal = modalProp,
hideOnEscape = true,
autoFocusOnShow = true,
hideOnHoverOutside,
alwaysVisible,
...props
}) {
const context = useMenuProviderContext();
store = store || context;
invariant(
store,
process.env.NODE_ENV !== "production" && "Menu must receive a `store` prop or be wrapped in a MenuProvider component."
);
const ref = useRef(null);
const parentMenu = store.parent;
const parentMenubar = store.menubar;
const hasParentMenu = !!parentMenu;
const parentIsMenubar = !!parentMenubar && !hasParentMenu;
const modal = hasParentMenu ? false : modalProp;
props = {
...props,
ref: useMergeRefs(ref, props.ref)
};
const { "aria-labelledby": ariaLabelledBy, ...menuListProps } = useMenuList({
store,
alwaysVisible,
...props
});
props = menuListProps;
const [initialFocusRef, setInitialFocusRef] = useState();
const autoFocusOnShowState = useStoreState(store, "autoFocusOnShow");
const initialFocus = useStoreState(store, "initialFocus");
const baseElement = useStoreState(store, "baseElement");
const items = useStoreState(store, "renderedItems");
useEffect(() => {
let cleaning = false;
setInitialFocusRef((prevInitialFocusRef) => {
var _a, _b, _c;
if (cleaning) return;
if (modal && ((_a = prevInitialFocusRef == null ? void 0 : prevInitialFocusRef.current) == null ? void 0 : _a.isConnected)) {
return prevInitialFocusRef;
}
if (!autoFocusOnShowState) return;
let element;
switch (initialFocus) {
// TODO: Refactor
case "first":
element = ((_b = items.find((item) => !item.disabled && item.element)) == null ? void 0 : _b.element) || null;
break;
case "last":
element = ((_c = [...items].reverse().find((item) => !item.disabled && item.element)) == null ? void 0 : _c.element) || null;
break;
default:
element = baseElement;
}
if (element && element === (prevInitialFocusRef == null ? void 0 : prevInitialFocusRef.current)) {
return prevInitialFocusRef;
}
const ref2 = createRef();
ref2.current = element;
return ref2;
});
return () => {
cleaning = true;
};
}, [store, modal, autoFocusOnShowState, initialFocus, items, baseElement]);
const mayAutoFocusOnShow = !!autoFocusOnShow;
const canAutoFocusOnShow = !!initialFocusRef || !!props.initialFocus || modal;
const contentElement = useStoreState(
store.combobox || store,
"contentElement"
);
const parentContentElement = useStoreState(
(parentMenu == null ? void 0 : parentMenu.combobox) || parentMenu,
"contentElement"
);
const preserveTabOrderAnchor = useMemo(() => {
if (!parentContentElement) return;
if (!contentElement) return;
const role = contentElement.getAttribute("role");
const parentRole = parentContentElement.getAttribute("role");
const parentIsMenuOrMenubar = parentRole === "menu" || parentRole === "menubar";
if (parentIsMenuOrMenubar && role === "menu") return;
return parentContentElement;
}, [contentElement, parentContentElement]);
if (preserveTabOrderAnchor !== void 0) {
props = {
preserveTabOrderAnchor,
...props
};
}
props = useHovercard({
store,
alwaysVisible,
initialFocus: initialFocusRef,
autoFocusOnShow: mayAutoFocusOnShow ? canAutoFocusOnShow && autoFocusOnShow : autoFocusOnShowState || modal,
...props,
hideOnEscape(event) {
if (isFalsyBooleanCallback(hideOnEscape, event)) return false;
store == null ? void 0 : store.hideAll();
return true;
},
hideOnHoverOutside(event) {
const disclosureElement = store == null ? void 0 : store.getState().disclosureElement;
const getHideOnHoverOutside = () => {
if (typeof hideOnHoverOutside === "function") {
return hideOnHoverOutside(event);
}
if (hideOnHoverOutside != null) return hideOnHoverOutside;
if (hasParentMenu) return true;
if (!parentIsMenubar) return false;
if (!disclosureElement) return true;
if (hasFocusWithin(disclosureElement)) return false;
return true;
};
if (!getHideOnHoverOutside()) return false;
if (event.defaultPrevented) return true;
if (!hasParentMenu) return true;
if (!disclosureElement) return true;
fireEvent(disclosureElement, "mouseout", event);
if (!hasFocusWithin(disclosureElement)) return true;
requestAnimationFrame(() => {
if (hasFocusWithin(disclosureElement)) return;
store == null ? void 0 : store.hide();
});
return false;
},
modal,
portal,
backdrop: hasParentMenu ? false : props.backdrop
});
props = {
"aria-labelledby": ariaLabelledBy,
...props
};
return props;
});
var Menu = createDialogComponent(
forwardRef(function Menu2(props) {
const htmlProps = useMenu(props);
return createElement(TagName, htmlProps);
}),
useMenuProviderContext
);
export {
Menu,
useMenu
};