"use strict"; "use client"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/react/menu/src/index.ts var src_exports = {}; __export(src_exports, { Anchor: () => Anchor2, Arrow: () => Arrow2, CheckboxItem: () => CheckboxItem, Content: () => Content2, Group: () => Group, Item: () => Item2, ItemIndicator: () => ItemIndicator, Label: () => Label, Menu: () => Menu, MenuAnchor: () => MenuAnchor, MenuArrow: () => MenuArrow, MenuCheckboxItem: () => MenuCheckboxItem, MenuContent: () => MenuContent, MenuGroup: () => MenuGroup, MenuItem: () => MenuItem, MenuItemIndicator: () => MenuItemIndicator, MenuLabel: () => MenuLabel, MenuPortal: () => MenuPortal, MenuRadioGroup: () => MenuRadioGroup, MenuRadioItem: () => MenuRadioItem, MenuSeparator: () => MenuSeparator, MenuSub: () => MenuSub, MenuSubContent: () => MenuSubContent, MenuSubTrigger: () => MenuSubTrigger, Portal: () => Portal, RadioGroup: () => RadioGroup, RadioItem: () => RadioItem, Root: () => Root3, Separator: () => Separator, Sub: () => Sub, SubContent: () => SubContent, SubTrigger: () => SubTrigger, createMenuScope: () => createMenuScope }); module.exports = __toCommonJS(src_exports); // packages/react/menu/src/Menu.tsx var React = __toESM(require("react")); var import_primitive = require("@radix-ui/primitive"); var import_react_collection = require("@radix-ui/react-collection"); var import_react_compose_refs = require("@radix-ui/react-compose-refs"); var import_react_context = require("@radix-ui/react-context"); var import_react_direction = require("@radix-ui/react-direction"); var import_react_dismissable_layer = require("@radix-ui/react-dismissable-layer"); var import_react_focus_guards = require("@radix-ui/react-focus-guards"); var import_react_focus_scope = require("@radix-ui/react-focus-scope"); var import_react_id = require("@radix-ui/react-id"); var PopperPrimitive = __toESM(require("@radix-ui/react-popper")); var import_react_popper = require("@radix-ui/react-popper"); var import_react_portal = require("@radix-ui/react-portal"); var import_react_presence = require("@radix-ui/react-presence"); var import_react_primitive = require("@radix-ui/react-primitive"); var RovingFocusGroup = __toESM(require("@radix-ui/react-roving-focus")); var import_react_roving_focus = require("@radix-ui/react-roving-focus"); var import_react_slot = require("@radix-ui/react-slot"); var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref"); var import_aria_hidden = require("aria-hidden"); var import_react_remove_scroll = require("react-remove-scroll"); var import_jsx_runtime = require("react/jsx-runtime"); var SELECTION_KEYS = ["Enter", " "]; var FIRST_KEYS = ["ArrowDown", "PageUp", "Home"]; var LAST_KEYS = ["ArrowUp", "PageDown", "End"]; var FIRST_LAST_KEYS = [...FIRST_KEYS, ...LAST_KEYS]; var SUB_OPEN_KEYS = { ltr: [...SELECTION_KEYS, "ArrowRight"], rtl: [...SELECTION_KEYS, "ArrowLeft"] }; var SUB_CLOSE_KEYS = { ltr: ["ArrowLeft"], rtl: ["ArrowRight"] }; var MENU_NAME = "Menu"; var [Collection, useCollection, createCollectionScope] = (0, import_react_collection.createCollection)(MENU_NAME); var [createMenuContext, createMenuScope] = (0, import_react_context.createContextScope)(MENU_NAME, [ createCollectionScope, import_react_popper.createPopperScope, import_react_roving_focus.createRovingFocusGroupScope ]); var usePopperScope = (0, import_react_popper.createPopperScope)(); var useRovingFocusGroupScope = (0, import_react_roving_focus.createRovingFocusGroupScope)(); var [MenuProvider, useMenuContext] = createMenuContext(MENU_NAME); var [MenuRootProvider, useMenuRootContext] = createMenuContext(MENU_NAME); var Menu = (props) => { const { __scopeMenu, open = false, children, dir, onOpenChange, modal = true } = props; const popperScope = usePopperScope(__scopeMenu); const [content, setContent] = React.useState(null); const isUsingKeyboardRef = React.useRef(false); const handleOpenChange = (0, import_react_use_callback_ref.useCallbackRef)(onOpenChange); const direction = (0, import_react_direction.useDirection)(dir); React.useEffect(() => { const handleKeyDown = () => { isUsingKeyboardRef.current = true; document.addEventListener("pointerdown", handlePointer, { capture: true, once: true }); document.addEventListener("pointermove", handlePointer, { capture: true, once: true }); }; const handlePointer = () => isUsingKeyboardRef.current = false; document.addEventListener("keydown", handleKeyDown, { capture: true }); return () => { document.removeEventListener("keydown", handleKeyDown, { capture: true }); document.removeEventListener("pointerdown", handlePointer, { capture: true }); document.removeEventListener("pointermove", handlePointer, { capture: true }); }; }, []); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuProvider, { scope: __scopeMenu, open, onOpenChange: handleOpenChange, content, onContentChange: setContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuRootProvider, { scope: __scopeMenu, onClose: React.useCallback(() => handleOpenChange(false), [handleOpenChange]), isUsingKeyboardRef, dir: direction, modal, children } ) } ) }); }; Menu.displayName = MENU_NAME; var ANCHOR_NAME = "MenuAnchor"; var MenuAnchor = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, ...anchorProps } = props; const popperScope = usePopperScope(__scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef }); } ); MenuAnchor.displayName = ANCHOR_NAME; var PORTAL_NAME = "MenuPortal"; var [PortalProvider, usePortalContext] = createMenuContext(PORTAL_NAME, { forceMount: void 0 }); var MenuPortal = (props) => { const { __scopeMenu, forceMount, children, container } = props; const context = useMenuContext(PORTAL_NAME, __scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PortalProvider, { scope: __scopeMenu, forceMount, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || context.open, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_portal.Portal, { asChild: true, container, children }) }) }); }; MenuPortal.displayName = PORTAL_NAME; var CONTENT_NAME = "MenuContent"; var [MenuContentProvider, useMenuContentContext] = createMenuContext(CONTENT_NAME); var MenuContent = React.forwardRef( (props, forwardedRef) => { const portalContext = usePortalContext(CONTENT_NAME, props.__scopeMenu); const { forceMount = portalContext.forceMount, ...contentProps } = props; const context = useMenuContext(CONTENT_NAME, props.__scopeMenu); const rootContext = useMenuRootContext(CONTENT_NAME, props.__scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || context.open, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, { scope: props.__scopeMenu, children: rootContext.modal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuRootContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuRootContentNonModal, { ...contentProps, ref: forwardedRef }) }) }) }); } ); var MenuRootContentModal = React.forwardRef( (props, forwardedRef) => { const context = useMenuContext(CONTENT_NAME, props.__scopeMenu); const ref = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref); React.useEffect(() => { const content = ref.current; if (content) return (0, import_aria_hidden.hideOthers)(content); }, []); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuContentImpl, { ...props, ref: composedRefs, trapFocus: context.open, disableOutsidePointerEvents: context.open, disableOutsideScroll: true, onFocusOutside: (0, import_primitive.composeEventHandlers)( props.onFocusOutside, (event) => event.preventDefault(), { checkForDefaultPrevented: false } ), onDismiss: () => context.onOpenChange(false) } ); } ); var MenuRootContentNonModal = React.forwardRef((props, forwardedRef) => { const context = useMenuContext(CONTENT_NAME, props.__scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuContentImpl, { ...props, ref: forwardedRef, trapFocus: false, disableOutsidePointerEvents: false, disableOutsideScroll: false, onDismiss: () => context.onOpenChange(false) } ); }); var MenuContentImpl = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, loop = false, trapFocus, onOpenAutoFocus, onCloseAutoFocus, disableOutsidePointerEvents, onEntryFocus, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, onDismiss, disableOutsideScroll, ...contentProps } = props; const context = useMenuContext(CONTENT_NAME, __scopeMenu); const rootContext = useMenuRootContext(CONTENT_NAME, __scopeMenu); const popperScope = usePopperScope(__scopeMenu); const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeMenu); const getItems = useCollection(__scopeMenu); const [currentItemId, setCurrentItemId] = React.useState(null); const contentRef = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, contentRef, context.onContentChange); const timerRef = React.useRef(0); const searchRef = React.useRef(""); const pointerGraceTimerRef = React.useRef(0); const pointerGraceIntentRef = React.useRef(null); const pointerDirRef = React.useRef("right"); const lastPointerXRef = React.useRef(0); const ScrollLockWrapper = disableOutsideScroll ? import_react_remove_scroll.RemoveScroll : React.Fragment; const scrollLockWrapperProps = disableOutsideScroll ? { as: import_react_slot.Slot, allowPinchZoom: true } : void 0; const handleTypeaheadSearch = (key) => { const search = searchRef.current + key; const items = getItems().filter((item) => !item.disabled); const currentItem = document.activeElement; const currentMatch = items.find((item) => item.ref.current === currentItem)?.textValue; const values = items.map((item) => item.textValue); const nextMatch = getNextMatch(values, search, currentMatch); const newItem = items.find((item) => item.textValue === nextMatch)?.ref.current; (function updateSearch(value) { searchRef.current = value; window.clearTimeout(timerRef.current); if (value !== "") timerRef.current = window.setTimeout(() => updateSearch(""), 1e3); })(search); if (newItem) { setTimeout(() => newItem.focus()); } }; React.useEffect(() => { return () => window.clearTimeout(timerRef.current); }, []); (0, import_react_focus_guards.useFocusGuards)(); const isPointerMovingToSubmenu = React.useCallback((event) => { const isMovingTowards = pointerDirRef.current === pointerGraceIntentRef.current?.side; return isMovingTowards && isPointerInGraceArea(event, pointerGraceIntentRef.current?.area); }, []); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuContentProvider, { scope: __scopeMenu, searchRef, onItemEnter: React.useCallback( (event) => { if (isPointerMovingToSubmenu(event)) event.preventDefault(); }, [isPointerMovingToSubmenu] ), onItemLeave: React.useCallback( (event) => { if (isPointerMovingToSubmenu(event)) return; contentRef.current?.focus(); setCurrentItemId(null); }, [isPointerMovingToSubmenu] ), onTriggerLeave: React.useCallback( (event) => { if (isPointerMovingToSubmenu(event)) event.preventDefault(); }, [isPointerMovingToSubmenu] ), pointerGraceTimerRef, onPointerGraceIntentChange: React.useCallback((intent) => { pointerGraceIntentRef.current = intent; }, []), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollLockWrapper, { ...scrollLockWrapperProps, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_focus_scope.FocusScope, { asChild: true, trapped: trapFocus, onMountAutoFocus: (0, import_primitive.composeEventHandlers)(onOpenAutoFocus, (event) => { event.preventDefault(); contentRef.current?.focus({ preventScroll: true }); }), onUnmountAutoFocus: onCloseAutoFocus, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_dismissable_layer.DismissableLayer, { asChild: true, disableOutsidePointerEvents, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, onDismiss, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( RovingFocusGroup.Root, { asChild: true, ...rovingFocusGroupScope, dir: rootContext.dir, orientation: "vertical", loop, currentTabStopId: currentItemId, onCurrentTabStopIdChange: setCurrentItemId, onEntryFocus: (0, import_primitive.composeEventHandlers)(onEntryFocus, (event) => { if (!rootContext.isUsingKeyboardRef.current) event.preventDefault(); }), preventScrollOnEntryFocus: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( PopperPrimitive.Content, { role: "menu", "aria-orientation": "vertical", "data-state": getOpenState(context.open), "data-radix-menu-content": "", dir: rootContext.dir, ...popperScope, ...contentProps, ref: composedRefs, style: { outline: "none", ...contentProps.style }, onKeyDown: (0, import_primitive.composeEventHandlers)(contentProps.onKeyDown, (event) => { const target = event.target; const isKeyDownInside = target.closest("[data-radix-menu-content]") === event.currentTarget; const isModifierKey = event.ctrlKey || event.altKey || event.metaKey; const isCharacterKey = event.key.length === 1; if (isKeyDownInside) { if (event.key === "Tab") event.preventDefault(); if (!isModifierKey && isCharacterKey) handleTypeaheadSearch(event.key); } const content = contentRef.current; if (event.target !== content) return; if (!FIRST_LAST_KEYS.includes(event.key)) return; event.preventDefault(); const items = getItems().filter((item) => !item.disabled); const candidateNodes = items.map((item) => item.ref.current); if (LAST_KEYS.includes(event.key)) candidateNodes.reverse(); focusFirst(candidateNodes); }), onBlur: (0, import_primitive.composeEventHandlers)(props.onBlur, (event) => { if (!event.currentTarget.contains(event.target)) { window.clearTimeout(timerRef.current); searchRef.current = ""; } }), onPointerMove: (0, import_primitive.composeEventHandlers)( props.onPointerMove, whenMouse((event) => { const target = event.target; const pointerXHasChanged = lastPointerXRef.current !== event.clientX; if (event.currentTarget.contains(target) && pointerXHasChanged) { const newDir = event.clientX > lastPointerXRef.current ? "right" : "left"; pointerDirRef.current = newDir; lastPointerXRef.current = event.clientX; } }) ) } ) } ) } ) } ) }) } ); } ); MenuContent.displayName = CONTENT_NAME; var GROUP_NAME = "MenuGroup"; var MenuGroup = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, ...groupProps } = props; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { role: "group", ...groupProps, ref: forwardedRef }); } ); MenuGroup.displayName = GROUP_NAME; var LABEL_NAME = "MenuLabel"; var MenuLabel = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, ...labelProps } = props; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...labelProps, ref: forwardedRef }); } ); MenuLabel.displayName = LABEL_NAME; var ITEM_NAME = "MenuItem"; var ITEM_SELECT = "menu.itemSelect"; var MenuItem = React.forwardRef( (props, forwardedRef) => { const { disabled = false, onSelect, ...itemProps } = props; const ref = React.useRef(null); const rootContext = useMenuRootContext(ITEM_NAME, props.__scopeMenu); const contentContext = useMenuContentContext(ITEM_NAME, props.__scopeMenu); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref); const isPointerDownRef = React.useRef(false); const handleSelect = () => { const menuItem = ref.current; if (!disabled && menuItem) { const itemSelectEvent = new CustomEvent(ITEM_SELECT, { bubbles: true, cancelable: true }); menuItem.addEventListener(ITEM_SELECT, (event) => onSelect?.(event), { once: true }); (0, import_react_primitive.dispatchDiscreteCustomEvent)(menuItem, itemSelectEvent); if (itemSelectEvent.defaultPrevented) { isPointerDownRef.current = false; } else { rootContext.onClose(); } } }; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuItemImpl, { ...itemProps, ref: composedRefs, disabled, onClick: (0, import_primitive.composeEventHandlers)(props.onClick, handleSelect), onPointerDown: (event) => { props.onPointerDown?.(event); isPointerDownRef.current = true; }, onPointerUp: (0, import_primitive.composeEventHandlers)(props.onPointerUp, (event) => { if (!isPointerDownRef.current) event.currentTarget?.click(); }), onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const isTypingAhead = contentContext.searchRef.current !== ""; if (disabled || isTypingAhead && event.key === " ") return; if (SELECTION_KEYS.includes(event.key)) { event.currentTarget.click(); event.preventDefault(); } }) } ); } ); MenuItem.displayName = ITEM_NAME; var MenuItemImpl = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, disabled = false, textValue, ...itemProps } = props; const contentContext = useMenuContentContext(ITEM_NAME, __scopeMenu); const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeMenu); const ref = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref); const [isFocused, setIsFocused] = React.useState(false); const [textContent, setTextContent] = React.useState(""); React.useEffect(() => { const menuItem = ref.current; if (menuItem) { setTextContent((menuItem.textContent ?? "").trim()); } }, [itemProps.children]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( Collection.ItemSlot, { scope: __scopeMenu, disabled, textValue: textValue ?? textContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RovingFocusGroup.Item, { asChild: true, ...rovingFocusGroupScope, focusable: !disabled, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { role: "menuitem", "data-highlighted": isFocused ? "" : void 0, "aria-disabled": disabled || void 0, "data-disabled": disabled ? "" : void 0, ...itemProps, ref: composedRefs, onPointerMove: (0, import_primitive.composeEventHandlers)( props.onPointerMove, whenMouse((event) => { if (disabled) { contentContext.onItemLeave(event); } else { contentContext.onItemEnter(event); if (!event.defaultPrevented) { const item = event.currentTarget; item.focus({ preventScroll: true }); } } }) ), onPointerLeave: (0, import_primitive.composeEventHandlers)( props.onPointerLeave, whenMouse((event) => contentContext.onItemLeave(event)) ), onFocus: (0, import_primitive.composeEventHandlers)(props.onFocus, () => setIsFocused(true)), onBlur: (0, import_primitive.composeEventHandlers)(props.onBlur, () => setIsFocused(false)) } ) }) } ); } ); var CHECKBOX_ITEM_NAME = "MenuCheckboxItem"; var MenuCheckboxItem = React.forwardRef( (props, forwardedRef) => { const { checked = false, onCheckedChange, ...checkboxItemProps } = props; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuItem, { role: "menuitemcheckbox", "aria-checked": isIndeterminate(checked) ? "mixed" : checked, ...checkboxItemProps, ref: forwardedRef, "data-state": getCheckedState(checked), onSelect: (0, import_primitive.composeEventHandlers)( checkboxItemProps.onSelect, () => onCheckedChange?.(isIndeterminate(checked) ? true : !checked), { checkForDefaultPrevented: false } ) } ) }); } ); MenuCheckboxItem.displayName = CHECKBOX_ITEM_NAME; var RADIO_GROUP_NAME = "MenuRadioGroup"; var [RadioGroupProvider, useRadioGroupContext] = createMenuContext( RADIO_GROUP_NAME, { value: void 0, onValueChange: () => { } } ); var MenuRadioGroup = React.forwardRef( (props, forwardedRef) => { const { value, onValueChange, ...groupProps } = props; const handleValueChange = (0, import_react_use_callback_ref.useCallbackRef)(onValueChange); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RadioGroupProvider, { scope: props.__scopeMenu, value, onValueChange: handleValueChange, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuGroup, { ...groupProps, ref: forwardedRef }) }); } ); MenuRadioGroup.displayName = RADIO_GROUP_NAME; var RADIO_ITEM_NAME = "MenuRadioItem"; var MenuRadioItem = React.forwardRef( (props, forwardedRef) => { const { value, ...radioItemProps } = props; const context = useRadioGroupContext(RADIO_ITEM_NAME, props.__scopeMenu); const checked = value === context.value; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuItem, { role: "menuitemradio", "aria-checked": checked, ...radioItemProps, ref: forwardedRef, "data-state": getCheckedState(checked), onSelect: (0, import_primitive.composeEventHandlers)( radioItemProps.onSelect, () => context.onValueChange?.(value), { checkForDefaultPrevented: false } ) } ) }); } ); MenuRadioItem.displayName = RADIO_ITEM_NAME; var ITEM_INDICATOR_NAME = "MenuItemIndicator"; var [ItemIndicatorProvider, useItemIndicatorContext] = createMenuContext( ITEM_INDICATOR_NAME, { checked: false } ); var MenuItemIndicator = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, forceMount, ...itemIndicatorProps } = props; const indicatorContext = useItemIndicatorContext(ITEM_INDICATOR_NAME, __scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_presence.Presence, { present: forceMount || isIndeterminate(indicatorContext.checked) || indicatorContext.checked === true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.span, { ...itemIndicatorProps, ref: forwardedRef, "data-state": getCheckedState(indicatorContext.checked) } ) } ); } ); MenuItemIndicator.displayName = ITEM_INDICATOR_NAME; var SEPARATOR_NAME = "MenuSeparator"; var MenuSeparator = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, ...separatorProps } = props; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { role: "separator", "aria-orientation": "horizontal", ...separatorProps, ref: forwardedRef } ); } ); MenuSeparator.displayName = SEPARATOR_NAME; var ARROW_NAME = "MenuArrow"; var MenuArrow = React.forwardRef( (props, forwardedRef) => { const { __scopeMenu, ...arrowProps } = props; const popperScope = usePopperScope(__scopeMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef }); } ); MenuArrow.displayName = ARROW_NAME; var SUB_NAME = "MenuSub"; var [MenuSubProvider, useMenuSubContext] = createMenuContext(SUB_NAME); var MenuSub = (props) => { const { __scopeMenu, children, open = false, onOpenChange } = props; const parentMenuContext = useMenuContext(SUB_NAME, __scopeMenu); const popperScope = usePopperScope(__scopeMenu); const [trigger, setTrigger] = React.useState(null); const [content, setContent] = React.useState(null); const handleOpenChange = (0, import_react_use_callback_ref.useCallbackRef)(onOpenChange); React.useEffect(() => { if (parentMenuContext.open === false) handleOpenChange(false); return () => handleOpenChange(false); }, [parentMenuContext.open, handleOpenChange]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuProvider, { scope: __scopeMenu, open, onOpenChange: handleOpenChange, content, onContentChange: setContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuSubProvider, { scope: __scopeMenu, contentId: (0, import_react_id.useId)(), triggerId: (0, import_react_id.useId)(), trigger, onTriggerChange: setTrigger, children } ) } ) }); }; MenuSub.displayName = SUB_NAME; var SUB_TRIGGER_NAME = "MenuSubTrigger"; var MenuSubTrigger = React.forwardRef( (props, forwardedRef) => { const context = useMenuContext(SUB_TRIGGER_NAME, props.__scopeMenu); const rootContext = useMenuRootContext(SUB_TRIGGER_NAME, props.__scopeMenu); const subContext = useMenuSubContext(SUB_TRIGGER_NAME, props.__scopeMenu); const contentContext = useMenuContentContext(SUB_TRIGGER_NAME, props.__scopeMenu); const openTimerRef = React.useRef(null); const { pointerGraceTimerRef, onPointerGraceIntentChange } = contentContext; const scope = { __scopeMenu: props.__scopeMenu }; const clearOpenTimer = React.useCallback(() => { if (openTimerRef.current) window.clearTimeout(openTimerRef.current); openTimerRef.current = null; }, []); React.useEffect(() => clearOpenTimer, [clearOpenTimer]); React.useEffect(() => { const pointerGraceTimer = pointerGraceTimerRef.current; return () => { window.clearTimeout(pointerGraceTimer); onPointerGraceIntentChange(null); }; }, [pointerGraceTimerRef, onPointerGraceIntentChange]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuAnchor, { asChild: true, ...scope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuItemImpl, { id: subContext.triggerId, "aria-haspopup": "menu", "aria-expanded": context.open, "aria-controls": subContext.contentId, "data-state": getOpenState(context.open), ...props, ref: (0, import_react_compose_refs.composeRefs)(forwardedRef, subContext.onTriggerChange), onClick: (event) => { props.onClick?.(event); if (props.disabled || event.defaultPrevented) return; event.currentTarget.focus(); if (!context.open) context.onOpenChange(true); }, onPointerMove: (0, import_primitive.composeEventHandlers)( props.onPointerMove, whenMouse((event) => { contentContext.onItemEnter(event); if (event.defaultPrevented) return; if (!props.disabled && !context.open && !openTimerRef.current) { contentContext.onPointerGraceIntentChange(null); openTimerRef.current = window.setTimeout(() => { context.onOpenChange(true); clearOpenTimer(); }, 100); } }) ), onPointerLeave: (0, import_primitive.composeEventHandlers)( props.onPointerLeave, whenMouse((event) => { clearOpenTimer(); const contentRect = context.content?.getBoundingClientRect(); if (contentRect) { const side = context.content?.dataset.side; const rightSide = side === "right"; const bleed = rightSide ? -5 : 5; const contentNearEdge = contentRect[rightSide ? "left" : "right"]; const contentFarEdge = contentRect[rightSide ? "right" : "left"]; contentContext.onPointerGraceIntentChange({ area: [ // Apply a bleed on clientX to ensure that our exit point is // consistently within polygon bounds { x: event.clientX + bleed, y: event.clientY }, { x: contentNearEdge, y: contentRect.top }, { x: contentFarEdge, y: contentRect.top }, { x: contentFarEdge, y: contentRect.bottom }, { x: contentNearEdge, y: contentRect.bottom } ], side }); window.clearTimeout(pointerGraceTimerRef.current); pointerGraceTimerRef.current = window.setTimeout( () => contentContext.onPointerGraceIntentChange(null), 300 ); } else { contentContext.onTriggerLeave(event); if (event.defaultPrevented) return; contentContext.onPointerGraceIntentChange(null); } }) ), onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const isTypingAhead = contentContext.searchRef.current !== ""; if (props.disabled || isTypingAhead && event.key === " ") return; if (SUB_OPEN_KEYS[rootContext.dir].includes(event.key)) { context.onOpenChange(true); context.content?.focus(); event.preventDefault(); } }) } ) }); } ); MenuSubTrigger.displayName = SUB_TRIGGER_NAME; var SUB_CONTENT_NAME = "MenuSubContent"; var MenuSubContent = React.forwardRef( (props, forwardedRef) => { const portalContext = usePortalContext(CONTENT_NAME, props.__scopeMenu); const { forceMount = portalContext.forceMount, ...subContentProps } = props; const context = useMenuContext(CONTENT_NAME, props.__scopeMenu); const rootContext = useMenuRootContext(CONTENT_NAME, props.__scopeMenu); const subContext = useMenuSubContext(SUB_CONTENT_NAME, props.__scopeMenu); const ref = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || context.open, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, { scope: props.__scopeMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( MenuContentImpl, { id: subContext.contentId, "aria-labelledby": subContext.triggerId, ...subContentProps, ref: composedRefs, align: "start", side: rootContext.dir === "rtl" ? "left" : "right", disableOutsidePointerEvents: false, disableOutsideScroll: false, trapFocus: false, onOpenAutoFocus: (event) => { if (rootContext.isUsingKeyboardRef.current) ref.current?.focus(); event.preventDefault(); }, onCloseAutoFocus: (event) => event.preventDefault(), onFocusOutside: (0, import_primitive.composeEventHandlers)(props.onFocusOutside, (event) => { if (event.target !== subContext.trigger) context.onOpenChange(false); }), onEscapeKeyDown: (0, import_primitive.composeEventHandlers)(props.onEscapeKeyDown, (event) => { rootContext.onClose(); event.preventDefault(); }), onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const isKeyDownInside = event.currentTarget.contains(event.target); const isCloseKey = SUB_CLOSE_KEYS[rootContext.dir].includes(event.key); if (isKeyDownInside && isCloseKey) { context.onOpenChange(false); subContext.trigger?.focus(); event.preventDefault(); } }) } ) }) }) }); } ); MenuSubContent.displayName = SUB_CONTENT_NAME; function getOpenState(open) { return open ? "open" : "closed"; } function isIndeterminate(checked) { return checked === "indeterminate"; } function getCheckedState(checked) { return isIndeterminate(checked) ? "indeterminate" : checked ? "checked" : "unchecked"; } function focusFirst(candidates) { const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement; for (const candidate of candidates) { if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return; candidate.focus(); if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return; } } function wrapArray(array, startIndex) { return array.map((_, index) => array[(startIndex + index) % array.length]); } function getNextMatch(values, search, currentMatch) { const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]); const normalizedSearch = isRepeated ? search[0] : search; const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1; let wrappedValues = wrapArray(values, Math.max(currentMatchIndex, 0)); const excludeCurrentMatch = normalizedSearch.length === 1; if (excludeCurrentMatch) wrappedValues = wrappedValues.filter((v) => v !== currentMatch); const nextMatch = wrappedValues.find( (value) => value.toLowerCase().startsWith(normalizedSearch.toLowerCase()) ); return nextMatch !== currentMatch ? nextMatch : void 0; } function isPointInPolygon(point, polygon) { const { x, y } = point; let inside = false; for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { const xi = polygon[i].x; const yi = polygon[i].y; const xj = polygon[j].x; const yj = polygon[j].y; const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi; if (intersect) inside = !inside; } return inside; } function isPointerInGraceArea(event, area) { if (!area) return false; const cursorPos = { x: event.clientX, y: event.clientY }; return isPointInPolygon(cursorPos, area); } function whenMouse(handler) { return (event) => event.pointerType === "mouse" ? handler(event) : void 0; } var Root3 = Menu; var Anchor2 = MenuAnchor; var Portal = MenuPortal; var Content2 = MenuContent; var Group = MenuGroup; var Label = MenuLabel; var Item2 = MenuItem; var CheckboxItem = MenuCheckboxItem; var RadioGroup = MenuRadioGroup; var RadioItem = MenuRadioItem; var ItemIndicator = MenuItemIndicator; var Separator = MenuSeparator; var Arrow2 = MenuArrow; var Sub = MenuSub; var SubTrigger = MenuSubTrigger; var SubContent = MenuSubContent; //# sourceMappingURL=index.js.map