UNPKG

@ariakit/react-core

Version:

Ariakit React core

141 lines (138 loc) 4.29 kB
"use client"; import { useMenuScopedContext } from "./SPU3NB66.js"; import { useMenubarScopedContext } from "./TGNQMQ45.js"; import { useCompositeHover } from "./RIJYZEV5.js"; import { useCompositeItem } from "./FIT2LC3L.js"; import { useStoreState } from "./Q3KUZPD7.js"; import { createElement, createHook, forwardRef, memo } from "./ILRXHV7V.js"; import { useBooleanEvent, useEvent } from "./K2XTQB3X.js"; // src/menu/menu-item.tsx import { getDocument, getPopupItemRole } from "@ariakit/core/utils/dom"; import { isDownloading, isOpeningInNewTab } from "@ariakit/core/utils/events"; import { hasFocusWithin } from "@ariakit/core/utils/focus"; import { invariant } from "@ariakit/core/utils/misc"; var TagName = "div"; function menuHasFocus(baseElement, items, currentTarget) { var _a; if (!baseElement) return false; if (hasFocusWithin(baseElement)) return true; const expandedItem = items == null ? void 0 : items.find((item) => { var _a2; if (item.element === currentTarget) return false; return ((_a2 = item.element) == null ? void 0 : _a2.getAttribute("aria-expanded")) === "true"; }); const expandedMenuId = (_a = expandedItem == null ? void 0 : expandedItem.element) == null ? void 0 : _a.getAttribute("aria-controls"); if (!expandedMenuId) return false; const doc = getDocument(baseElement); const expandedMenu = doc.getElementById(expandedMenuId); if (!expandedMenu) return false; if (hasFocusWithin(expandedMenu)) return true; return !!expandedMenu.querySelector("[role=menuitem][aria-expanded=true]"); } var useMenuItem = createHook( function useMenuItem2({ store, hideOnClick = true, preventScrollOnKeyDown = true, focusOnHover, blurOnHoverEnd, ...props }) { const menuContext = useMenuScopedContext(true); const menubarContext = useMenubarScopedContext(); store = store || menuContext || menubarContext; invariant( store, process.env.NODE_ENV !== "production" && "MenuItem must be wrapped in a MenuList, Menu or Menubar component" ); const onClickProp = props.onClick; const hideOnClickProp = useBooleanEvent(hideOnClick); const hideMenu = "hideAll" in store ? store.hideAll : void 0; const isWithinMenu = !!hideMenu; const onClick = useEvent((event) => { onClickProp == null ? void 0 : onClickProp(event); if (event.defaultPrevented) return; if (isDownloading(event)) return; if (isOpeningInNewTab(event)) return; if (!hideMenu) return; const popupType = event.currentTarget.getAttribute("aria-haspopup"); if (popupType === "menu") return; if (!hideOnClickProp(event)) return; hideMenu(); }); const contentElement = useStoreState( store, (state) => "contentElement" in state ? state.contentElement : null ); const role = getPopupItemRole(contentElement, "menuitem"); props = { role, ...props, onClick }; props = useCompositeItem({ store, preventScrollOnKeyDown, ...props }); props = useCompositeHover({ store, ...props, focusOnHover(event) { const getFocusOnHover = () => { if (typeof focusOnHover === "function") return focusOnHover(event); if (focusOnHover != null) return focusOnHover; return true; }; if (!store) return false; if (!getFocusOnHover()) return false; const { baseElement, items } = store.getState(); if (isWithinMenu) { if (event.currentTarget.hasAttribute("aria-expanded")) { event.currentTarget.focus(); } return true; } if (menuHasFocus(baseElement, items, event.currentTarget)) { event.currentTarget.focus(); return true; } return false; }, blurOnHoverEnd(event) { if (typeof blurOnHoverEnd === "function") return blurOnHoverEnd(event); if (blurOnHoverEnd != null) return blurOnHoverEnd; return isWithinMenu; } }); return props; } ); var MenuItem = memo( forwardRef(function MenuItem2(props) { const htmlProps = useMenuItem(props); return createElement(TagName, htmlProps); }) ); export { useMenuItem, MenuItem };