UNPKG

@ariakit/react-core

Version:

Ariakit React core

217 lines (215 loc) 7.1 kB
"use client"; import { useMenuList } from "../__chunks/T7IYZ6JK.js"; import { useHovercard } from "../__chunks/7QZRSZWP.js"; import "../__chunks/X7QOZUD3.js"; import { useMenuProviderContext } from "../__chunks/SPU3NB66.js"; import "../__chunks/TGNQMQ45.js"; import "../__chunks/2WDBOH5E.js"; import "../__chunks/WXLNFAIL.js"; import "../__chunks/4Z6JSVUY.js"; import { createDialogComponent } from "../__chunks/2S4Q4M35.js"; import "../__chunks/SWBQ42SL.js"; import "../__chunks/AOQQTIBO.js"; import "../__chunks/5M6RIVE2.js"; import "../__chunks/IEBFIEPB.js"; import "../__chunks/RBTTLCIN.js"; import "../__chunks/UG4JNWMY.js"; import "../__chunks/6GXEOXGT.js"; import "../__chunks/Y7OMCS5T.js"; import "../__chunks/HLTQOHKZ.js"; import "../__chunks/DJAL6CN3.js"; import "../__chunks/NQXOL4RD.js"; import "../__chunks/NE2XEEQN.js"; import "../__chunks/CZ4GFWYL.js"; import "../__chunks/Z5GCVBAY.js"; import "../__chunks/IGR4SXG2.js"; import "../__chunks/677M2CI3.js"; import "../__chunks/S7U6BLGA.js"; import "../__chunks/LVVSG7VH.js"; import "../__chunks/3NDVDEB4.js"; import "../__chunks/AOUGVQZ3.js"; import "../__chunks/K2ZF5NU7.js"; import "../__chunks/63XF7ACK.js"; import "../__chunks/HAX24JB7.js"; import "../__chunks/5NIUVND5.js"; import "../__chunks/33YRLYNQ.js"; import "../__chunks/E7PWFDGB.js"; import "../__chunks/5VQZOHHZ.js"; import "../__chunks/HIN2NSI2.js"; import "../__chunks/MWF5B7KS.js"; import "../__chunks/63N3TCQX.js"; import "../__chunks/FFSBKSAM.js"; import "../__chunks/72IB6YNO.js"; import "../__chunks/US3TW2XI.js"; import "../__chunks/SWN3JYXT.js"; import { useStoreState } from "../__chunks/Q3KUZPD7.js"; import "../__chunks/45YOMIF3.js"; import { createElement, createHook, forwardRef } from "../__chunks/ILRXHV7V.js"; import { useMergeRefs } from "../__chunks/K2XTQB3X.js"; import "../__chunks/YXGXYGQX.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; props = { ...props, ref: useMergeRefs(ref, props.ref) }; const { "aria-labelledby": ariaLabelledBy, ...menuListProps } = useMenuList({ store, alwaysVisible, ...props }); props = menuListProps; const [initialFocusRef, setInitialFocusRef] = useState(); const autoFocusOnShowState = store.useState("autoFocusOnShow"); const initialFocus = store.useState("initialFocus"); const baseElement = store.useState("baseElement"); const items = store.useState("renderedItems"); useEffect(() => { let cleaning = false; setInitialFocusRef((prevInitialFocusRef) => { var _a, _b, _c; if (cleaning) return; if (!autoFocusOnShowState) return; if ((_a = prevInitialFocusRef == null ? void 0 : prevInitialFocusRef.current) == null ? void 0 : _a.isConnected) return prevInitialFocusRef; const ref2 = createRef(); switch (initialFocus) { // TODO: Refactor case "first": ref2.current = ((_b = items.find((item) => !item.disabled && item.element)) == null ? void 0 : _b.element) || null; break; case "last": ref2.current = ((_c = [...items].reverse().find((item) => !item.disabled && item.element)) == null ? void 0 : _c.element) || null; break; default: ref2.current = baseElement; } return ref2; }); return () => { cleaning = true; }; }, [store, autoFocusOnShowState, initialFocus, items, baseElement]); const modal = hasParentMenu ? false : modalProp; 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 };