UNPKG

@ariakit/react-core

Version:

Ariakit React core

229 lines (227 loc) 7.08 kB
"use client"; import { MenuContextProvider, useMenuProviderContext } from "../__chunks/6UXSIZXV.js"; import "../__chunks/5FUUHUOH.js"; import { useHovercardAnchor } from "../__chunks/6BBQKQO4.js"; import "../__chunks/4LEWR5KQ.js"; import { useCompositeTypeahead } from "../__chunks/O5G4B22L.js"; import { usePopoverDisclosure } from "../__chunks/VZ7LL2SH.js"; import "../__chunks/CTFM4U6G.js"; import "../__chunks/UBWVN2JP.js"; import "../__chunks/W3FWC72U.js"; import "../__chunks/7NJRHOSP.js"; import { Role } from "../__chunks/AB647VKY.js"; import "../__chunks/467XRHWL.js"; import "../__chunks/2LVHRIRC.js"; import "../__chunks/FYYAZUDI.js"; import "../__chunks/NO3UEYQ2.js"; import "../__chunks/XTCKRCGH.js"; import "../__chunks/EZ4UPVW6.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 { useEvent, useId, useMergeRefs, useWrapElement } from "../__chunks/W2TDKEPX.js"; import "../__chunks/AZVQSWGA.js"; // src/menu/menu-button.tsx import { getPopupItemRole, getPopupRole } from "@ariakit/core/utils/dom"; import { disabledFromElement, disabledFromProps, invariant } from "@ariakit/core/utils/misc"; import { useRef } from "react"; import { jsx } from "react/jsx-runtime"; var TagName = "button"; function getInitialFocus(event, dir) { const keyMap = { ArrowDown: dir === "bottom" || dir === "top" ? "first" : false, ArrowUp: dir === "bottom" || dir === "top" ? "last" : false, ArrowRight: dir === "right" ? "first" : false, ArrowLeft: dir === "left" ? "first" : false }; return keyMap[event.key]; } function hasActiveItem(items, excludeElement) { return !!(items == null ? void 0 : items.some((item) => { if (!item.element) return false; if (item.element === excludeElement) return false; return item.element.getAttribute("aria-expanded") === "true"; })); } var useMenuButton = createHook( function useMenuButton2({ store, focusable, accessibleWhenDisabled, showOnHover, ...props }) { const context = useMenuProviderContext(); store = store || context; invariant( store, process.env.NODE_ENV !== "production" && "MenuButton 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 disabled = disabledFromProps(props); const isDisabled = (element) => disabled || disabledFromElement(element); const showMenu = () => { const trigger = ref.current; if (!trigger) return; store == null ? void 0 : store.setDisclosureElement(trigger); store == null ? void 0 : store.setAnchorElement(trigger); store == null ? void 0 : store.show(); }; const onFocusProp = props.onFocus; const onFocus = useEvent((event) => { onFocusProp == null ? void 0 : onFocusProp(event); if (isDisabled(event.currentTarget)) return; if (event.defaultPrevented) return; store == null ? void 0 : store.setAutoFocusOnShow(false); store == null ? void 0 : store.setActiveId(null); if (!parentMenubar) return; if (!parentIsMenubar) return; const { items } = parentMenubar.getState(); if (hasActiveItem(items, event.currentTarget)) { showMenu(); } }); const dir = useStoreState( store, (state) => state.placement.split("-")[0] ); const onKeyDownProp = props.onKeyDown; const onKeyDown = useEvent((event) => { onKeyDownProp == null ? void 0 : onKeyDownProp(event); if (isDisabled(event.currentTarget)) return; if (event.defaultPrevented) return; const initialFocus = getInitialFocus(event, dir); if (initialFocus) { event.preventDefault(); showMenu(); store == null ? void 0 : store.setAutoFocusOnShow(true); store == null ? void 0 : store.setInitialFocus(initialFocus); } }); const onClickProp = props.onClick; const onClick = useEvent((event) => { onClickProp == null ? void 0 : onClickProp(event); if (event.defaultPrevented) return; if (!store) return; const isKeyboardClick = !event.detail; const { open } = store.getState(); if (!open || isKeyboardClick) { if (!hasParentMenu || isKeyboardClick) { store.setAutoFocusOnShow(true); } store.setInitialFocus(isKeyboardClick ? "first" : "container"); } if (hasParentMenu) { showMenu(); } }); props = useWrapElement( props, (element) => /* @__PURE__ */ jsx(MenuContextProvider, { value: store, children: element }), [store] ); if (hasParentMenu) { props = { ...props, render: /* @__PURE__ */ jsx(Role.div, { render: props.render }) }; } const id = useId(props.id); const parentContentElement = useStoreState( (parentMenu == null ? void 0 : parentMenu.combobox) || parentMenu, "contentElement" ); const role = hasParentMenu || parentIsMenubar ? getPopupItemRole(parentContentElement, "menuitem") : void 0; const contentElement = useStoreState(store, "contentElement"); const hasCombobox = !!store.combobox; const popupRole = getPopupRole( contentElement, hasCombobox ? "dialog" : "menu" ); props = { role, "aria-haspopup": popupRole, ...props, id, ref: useMergeRefs(ref, props.ref), onFocus, onKeyDown, onClick }; props = useHovercardAnchor({ store, focusable, accessibleWhenDisabled, ...props, showOnHover: (event) => { const getShowOnHover = () => { if (typeof showOnHover === "function") return showOnHover(event); if (showOnHover != null) return showOnHover; if (hasParentMenu) return true; if (!parentMenubar) return false; const { items } = parentMenubar.getState(); return parentIsMenubar && hasActiveItem(items); }; const canShowOnHover = getShowOnHover(); if (!canShowOnHover) return false; const parent = parentIsMenubar ? parentMenubar : parentMenu; if (!parent) return true; parent.setActiveId(event.currentTarget.id); return true; } }); props = usePopoverDisclosure({ store, toggleOnClick: !hasParentMenu, focusable, accessibleWhenDisabled, ...props }); props = useCompositeTypeahead({ store, typeahead: parentIsMenubar, ...props }); return props; } ); var MenuButton = forwardRef(function MenuButton2(props) { const htmlProps = useMenuButton(props); return createElement(TagName, htmlProps); }); export { MenuButton, useMenuButton };