Spaces:
Runtime error
Runtime error
| ; | |
| "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); | |
| // src/index.ts | |
| var index_exports = {}; | |
| __export(index_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(index_exports); | |
| // 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 Slot = (0, import_react_slot.createSlot)("MenuContent.ScrollLock"); | |
| 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: 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 ii = polygon[i]; | |
| const jj = polygon[j]; | |
| const xi = ii.x; | |
| const yi = ii.y; | |
| const xj = jj.x; | |
| const yj = jj.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 | |