"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/navigation-menu/src/index.ts var src_exports = {}; __export(src_exports, { Content: () => Content, Indicator: () => Indicator, Item: () => Item, Link: () => Link, List: () => List, NavigationMenu: () => NavigationMenu, NavigationMenuContent: () => NavigationMenuContent, NavigationMenuIndicator: () => NavigationMenuIndicator, NavigationMenuItem: () => NavigationMenuItem, NavigationMenuLink: () => NavigationMenuLink, NavigationMenuList: () => NavigationMenuList, NavigationMenuSub: () => NavigationMenuSub, NavigationMenuTrigger: () => NavigationMenuTrigger, NavigationMenuViewport: () => NavigationMenuViewport, Root: () => Root2, Sub: () => Sub, Trigger: () => Trigger, Viewport: () => Viewport, createNavigationMenuScope: () => createNavigationMenuScope }); module.exports = __toCommonJS(src_exports); // packages/react/navigation-menu/src/NavigationMenu.tsx var React = __toESM(require("react")); var import_react_dom = __toESM(require("react-dom")); var import_react_context = require("@radix-ui/react-context"); var import_primitive = require("@radix-ui/primitive"); var import_react_primitive = require("@radix-ui/react-primitive"); var import_react_use_controllable_state = require("@radix-ui/react-use-controllable-state"); var import_react_compose_refs = require("@radix-ui/react-compose-refs"); var import_react_direction = require("@radix-ui/react-direction"); var import_react_presence = require("@radix-ui/react-presence"); var import_react_id = require("@radix-ui/react-id"); var import_react_collection = require("@radix-ui/react-collection"); var import_react_dismissable_layer = require("@radix-ui/react-dismissable-layer"); var import_react_use_previous = require("@radix-ui/react-use-previous"); var import_react_use_layout_effect = require("@radix-ui/react-use-layout-effect"); var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref"); var VisuallyHiddenPrimitive = __toESM(require("@radix-ui/react-visually-hidden")); var import_jsx_runtime = require("react/jsx-runtime"); var NAVIGATION_MENU_NAME = "NavigationMenu"; var [Collection, useCollection, createCollectionScope] = (0, import_react_collection.createCollection)(NAVIGATION_MENU_NAME); var [FocusGroupCollection, useFocusGroupCollection, createFocusGroupCollectionScope] = (0, import_react_collection.createCollection)(NAVIGATION_MENU_NAME); var [createNavigationMenuContext, createNavigationMenuScope] = (0, import_react_context.createContextScope)( NAVIGATION_MENU_NAME, [createCollectionScope, createFocusGroupCollectionScope] ); var [NavigationMenuProviderImpl, useNavigationMenuContext] = createNavigationMenuContext(NAVIGATION_MENU_NAME); var [ViewportContentProvider, useViewportContentContext] = createNavigationMenuContext(NAVIGATION_MENU_NAME); var NavigationMenu = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, value: valueProp, onValueChange, defaultValue, delayDuration = 200, skipDelayDuration = 300, orientation = "horizontal", dir, ...NavigationMenuProps } = props; const [navigationMenu, setNavigationMenu] = React.useState(null); const composedRef = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setNavigationMenu(node)); const direction = (0, import_react_direction.useDirection)(dir); const openTimerRef = React.useRef(0); const closeTimerRef = React.useRef(0); const skipDelayTimerRef = React.useRef(0); const [isOpenDelayed, setIsOpenDelayed] = React.useState(true); const [value = "", setValue] = (0, import_react_use_controllable_state.useControllableState)({ prop: valueProp, onChange: (value2) => { const isOpen = value2 !== ""; const hasSkipDelayDuration = skipDelayDuration > 0; if (isOpen) { window.clearTimeout(skipDelayTimerRef.current); if (hasSkipDelayDuration) setIsOpenDelayed(false); } else { window.clearTimeout(skipDelayTimerRef.current); skipDelayTimerRef.current = window.setTimeout( () => setIsOpenDelayed(true), skipDelayDuration ); } onValueChange?.(value2); }, defaultProp: defaultValue }); const startCloseTimer = React.useCallback(() => { window.clearTimeout(closeTimerRef.current); closeTimerRef.current = window.setTimeout(() => setValue(""), 150); }, [setValue]); const handleOpen = React.useCallback( (itemValue) => { window.clearTimeout(closeTimerRef.current); setValue(itemValue); }, [setValue] ); const handleDelayedOpen = React.useCallback( (itemValue) => { const isOpenItem = value === itemValue; if (isOpenItem) { window.clearTimeout(closeTimerRef.current); } else { openTimerRef.current = window.setTimeout(() => { window.clearTimeout(closeTimerRef.current); setValue(itemValue); }, delayDuration); } }, [value, setValue, delayDuration] ); React.useEffect(() => { return () => { window.clearTimeout(openTimerRef.current); window.clearTimeout(closeTimerRef.current); window.clearTimeout(skipDelayTimerRef.current); }; }, []); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuProvider, { scope: __scopeNavigationMenu, isRootMenu: true, value, dir: direction, orientation, rootNavigationMenu: navigationMenu, onTriggerEnter: (itemValue) => { window.clearTimeout(openTimerRef.current); if (isOpenDelayed) handleDelayedOpen(itemValue); else handleOpen(itemValue); }, onTriggerLeave: () => { window.clearTimeout(openTimerRef.current); startCloseTimer(); }, onContentEnter: () => window.clearTimeout(closeTimerRef.current), onContentLeave: startCloseTimer, onItemSelect: (itemValue) => { setValue((prevValue) => prevValue === itemValue ? "" : itemValue); }, onItemDismiss: () => setValue(""), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.nav, { "aria-label": "Main", "data-orientation": orientation, dir: direction, ...NavigationMenuProps, ref: composedRef } ) } ); } ); NavigationMenu.displayName = NAVIGATION_MENU_NAME; var SUB_NAME = "NavigationMenuSub"; var NavigationMenuSub = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, value: valueProp, onValueChange, defaultValue, orientation = "horizontal", ...subProps } = props; const context = useNavigationMenuContext(SUB_NAME, __scopeNavigationMenu); const [value = "", setValue] = (0, import_react_use_controllable_state.useControllableState)({ prop: valueProp, onChange: onValueChange, defaultProp: defaultValue }); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuProvider, { scope: __scopeNavigationMenu, isRootMenu: false, value, dir: context.dir, orientation, rootNavigationMenu: context.rootNavigationMenu, onTriggerEnter: (itemValue) => setValue(itemValue), onItemSelect: (itemValue) => setValue(itemValue), onItemDismiss: () => setValue(""), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { "data-orientation": orientation, ...subProps, ref: forwardedRef }) } ); } ); NavigationMenuSub.displayName = SUB_NAME; var NavigationMenuProvider = (props) => { const { scope, isRootMenu, rootNavigationMenu, dir, orientation, children, value, onItemSelect, onItemDismiss, onTriggerEnter, onTriggerLeave, onContentEnter, onContentLeave } = props; const [viewport, setViewport] = React.useState(null); const [viewportContent, setViewportContent] = React.useState(/* @__PURE__ */ new Map()); const [indicatorTrack, setIndicatorTrack] = React.useState(null); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuProviderImpl, { scope, isRootMenu, rootNavigationMenu, value, previousValue: (0, import_react_use_previous.usePrevious)(value), baseId: (0, import_react_id.useId)(), dir, orientation, viewport, onViewportChange: setViewport, indicatorTrack, onIndicatorTrackChange: setIndicatorTrack, onTriggerEnter: (0, import_react_use_callback_ref.useCallbackRef)(onTriggerEnter), onTriggerLeave: (0, import_react_use_callback_ref.useCallbackRef)(onTriggerLeave), onContentEnter: (0, import_react_use_callback_ref.useCallbackRef)(onContentEnter), onContentLeave: (0, import_react_use_callback_ref.useCallbackRef)(onContentLeave), onItemSelect: (0, import_react_use_callback_ref.useCallbackRef)(onItemSelect), onItemDismiss: (0, import_react_use_callback_ref.useCallbackRef)(onItemDismiss), onViewportContentChange: React.useCallback((contentValue, contentData) => { setViewportContent((prevContent) => { prevContent.set(contentValue, contentData); return new Map(prevContent); }); }, []), onViewportContentRemove: React.useCallback((contentValue) => { setViewportContent((prevContent) => { if (!prevContent.has(contentValue)) return prevContent; prevContent.delete(contentValue); return new Map(prevContent); }); }, []), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, { scope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewportContentProvider, { scope, items: viewportContent, children }) }) } ); }; var LIST_NAME = "NavigationMenuList"; var NavigationMenuList = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, ...listProps } = props; const context = useNavigationMenuContext(LIST_NAME, __scopeNavigationMenu); const list = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.ul, { "data-orientation": context.orientation, ...listProps, ref: forwardedRef }); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { style: { position: "relative" }, ref: context.onIndicatorTrackChange, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, { scope: __scopeNavigationMenu, children: context.isRootMenu ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroup, { asChild: true, children: list }) : list }) }); } ); NavigationMenuList.displayName = LIST_NAME; var ITEM_NAME = "NavigationMenuItem"; var [NavigationMenuItemContextProvider, useNavigationMenuItemContext] = createNavigationMenuContext(ITEM_NAME); var NavigationMenuItem = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, value: valueProp, ...itemProps } = props; const autoValue = (0, import_react_id.useId)(); const value = valueProp || autoValue || "LEGACY_REACT_AUTO_VALUE"; const contentRef = React.useRef(null); const triggerRef = React.useRef(null); const focusProxyRef = React.useRef(null); const restoreContentTabOrderRef = React.useRef(() => { }); const wasEscapeCloseRef = React.useRef(false); const handleContentEntry = React.useCallback((side = "start") => { if (contentRef.current) { restoreContentTabOrderRef.current(); const candidates = getTabbableCandidates(contentRef.current); if (candidates.length) focusFirst(side === "start" ? candidates : candidates.reverse()); } }, []); const handleContentExit = React.useCallback(() => { if (contentRef.current) { const candidates = getTabbableCandidates(contentRef.current); if (candidates.length) restoreContentTabOrderRef.current = removeFromTabOrder(candidates); } }, []); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuItemContextProvider, { scope: __scopeNavigationMenu, value, triggerRef, contentRef, focusProxyRef, wasEscapeCloseRef, onEntryKeyDown: handleContentEntry, onFocusProxyEnter: handleContentEntry, onRootContentClose: handleContentExit, onContentFocusOutside: handleContentExit, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.li, { ...itemProps, ref: forwardedRef }) } ); } ); NavigationMenuItem.displayName = ITEM_NAME; var TRIGGER_NAME = "NavigationMenuTrigger"; var NavigationMenuTrigger = React.forwardRef((props, forwardedRef) => { const { __scopeNavigationMenu, disabled, ...triggerProps } = props; const context = useNavigationMenuContext(TRIGGER_NAME, props.__scopeNavigationMenu); const itemContext = useNavigationMenuItemContext(TRIGGER_NAME, props.__scopeNavigationMenu); const ref = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(ref, itemContext.triggerRef, forwardedRef); const triggerId = makeTriggerId(context.baseId, itemContext.value); const contentId = makeContentId(context.baseId, itemContext.value); const hasPointerMoveOpenedRef = React.useRef(false); const wasClickCloseRef = React.useRef(false); const open = itemContext.value === context.value; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.ItemSlot, { scope: __scopeNavigationMenu, value: itemContext.value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroupItem, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.button, { id: triggerId, disabled, "data-disabled": disabled ? "" : void 0, "data-state": getOpenState(open), "aria-expanded": open, "aria-controls": contentId, ...triggerProps, ref: composedRefs, onPointerEnter: (0, import_primitive.composeEventHandlers)(props.onPointerEnter, () => { wasClickCloseRef.current = false; itemContext.wasEscapeCloseRef.current = false; }), onPointerMove: (0, import_primitive.composeEventHandlers)( props.onPointerMove, whenMouse(() => { if (disabled || wasClickCloseRef.current || itemContext.wasEscapeCloseRef.current || hasPointerMoveOpenedRef.current) return; context.onTriggerEnter(itemContext.value); hasPointerMoveOpenedRef.current = true; }) ), onPointerLeave: (0, import_primitive.composeEventHandlers)( props.onPointerLeave, whenMouse(() => { if (disabled) return; context.onTriggerLeave(); hasPointerMoveOpenedRef.current = false; }) ), onClick: (0, import_primitive.composeEventHandlers)(props.onClick, () => { context.onItemSelect(itemContext.value); wasClickCloseRef.current = open; }), onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const verticalEntryKey = context.dir === "rtl" ? "ArrowLeft" : "ArrowRight"; const entryKey = { horizontal: "ArrowDown", vertical: verticalEntryKey }[context.orientation]; if (open && event.key === entryKey) { itemContext.onEntryKeyDown(); event.preventDefault(); } }) } ) }) }), open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( VisuallyHiddenPrimitive.Root, { "aria-hidden": true, tabIndex: 0, ref: itemContext.focusProxyRef, onFocus: (event) => { const content = itemContext.contentRef.current; const prevFocusedElement = event.relatedTarget; const wasTriggerFocused = prevFocusedElement === ref.current; const wasFocusFromContent = content?.contains(prevFocusedElement); if (wasTriggerFocused || !wasFocusFromContent) { itemContext.onFocusProxyEnter(wasTriggerFocused ? "start" : "end"); } } } ), context.viewport && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-owns": contentId }) ] }) ] }); }); NavigationMenuTrigger.displayName = TRIGGER_NAME; var LINK_NAME = "NavigationMenuLink"; var LINK_SELECT = "navigationMenu.linkSelect"; var NavigationMenuLink = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, active, onSelect, ...linkProps } = props; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroupItem, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.a, { "data-active": active ? "" : void 0, "aria-current": active ? "page" : void 0, ...linkProps, ref: forwardedRef, onClick: (0, import_primitive.composeEventHandlers)( props.onClick, (event) => { const target = event.target; const linkSelectEvent = new CustomEvent(LINK_SELECT, { bubbles: true, cancelable: true }); target.addEventListener(LINK_SELECT, (event2) => onSelect?.(event2), { once: true }); (0, import_react_primitive.dispatchDiscreteCustomEvent)(target, linkSelectEvent); if (!linkSelectEvent.defaultPrevented && !event.metaKey) { const rootContentDismissEvent = new CustomEvent(ROOT_CONTENT_DISMISS, { bubbles: true, cancelable: true }); (0, import_react_primitive.dispatchDiscreteCustomEvent)(target, rootContentDismissEvent); } }, { checkForDefaultPrevented: false } ) } ) }); } ); NavigationMenuLink.displayName = LINK_NAME; var INDICATOR_NAME = "NavigationMenuIndicator"; var NavigationMenuIndicator = React.forwardRef((props, forwardedRef) => { const { forceMount, ...indicatorProps } = props; const context = useNavigationMenuContext(INDICATOR_NAME, props.__scopeNavigationMenu); const isVisible = Boolean(context.value); return context.indicatorTrack ? import_react_dom.default.createPortal( /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || isVisible, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationMenuIndicatorImpl, { ...indicatorProps, ref: forwardedRef }) }), context.indicatorTrack ) : null; }); NavigationMenuIndicator.displayName = INDICATOR_NAME; var NavigationMenuIndicatorImpl = React.forwardRef((props, forwardedRef) => { const { __scopeNavigationMenu, ...indicatorProps } = props; const context = useNavigationMenuContext(INDICATOR_NAME, __scopeNavigationMenu); const getItems = useCollection(__scopeNavigationMenu); const [activeTrigger, setActiveTrigger] = React.useState( null ); const [position, setPosition] = React.useState(null); const isHorizontal = context.orientation === "horizontal"; const isVisible = Boolean(context.value); React.useEffect(() => { const items = getItems(); const triggerNode = items.find((item) => item.value === context.value)?.ref.current; if (triggerNode) setActiveTrigger(triggerNode); }, [getItems, context.value]); const handlePositionChange = () => { if (activeTrigger) { setPosition({ size: isHorizontal ? activeTrigger.offsetWidth : activeTrigger.offsetHeight, offset: isHorizontal ? activeTrigger.offsetLeft : activeTrigger.offsetTop }); } }; useResizeObserver(activeTrigger, handlePositionChange); useResizeObserver(context.indicatorTrack, handlePositionChange); return position ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { "aria-hidden": true, "data-state": isVisible ? "visible" : "hidden", "data-orientation": context.orientation, ...indicatorProps, ref: forwardedRef, style: { position: "absolute", ...isHorizontal ? { left: 0, width: position.size + "px", transform: `translateX(${position.offset}px)` } : { top: 0, height: position.size + "px", transform: `translateY(${position.offset}px)` }, ...indicatorProps.style } } ) : null; }); var CONTENT_NAME = "NavigationMenuContent"; var NavigationMenuContent = React.forwardRef((props, forwardedRef) => { const { forceMount, ...contentProps } = props; const context = useNavigationMenuContext(CONTENT_NAME, props.__scopeNavigationMenu); const itemContext = useNavigationMenuItemContext(CONTENT_NAME, props.__scopeNavigationMenu); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(itemContext.contentRef, forwardedRef); const open = itemContext.value === context.value; const commonProps = { value: itemContext.value, triggerRef: itemContext.triggerRef, focusProxyRef: itemContext.focusProxyRef, wasEscapeCloseRef: itemContext.wasEscapeCloseRef, onContentFocusOutside: itemContext.onContentFocusOutside, onRootContentClose: itemContext.onRootContentClose, ...contentProps }; return !context.viewport ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || open, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuContentImpl, { "data-state": getOpenState(open), ...commonProps, ref: composedRefs, onPointerEnter: (0, import_primitive.composeEventHandlers)(props.onPointerEnter, context.onContentEnter), onPointerLeave: (0, import_primitive.composeEventHandlers)( props.onPointerLeave, whenMouse(context.onContentLeave) ), style: { // Prevent interaction when animating out pointerEvents: !open && context.isRootMenu ? "none" : void 0, ...commonProps.style } } ) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewportContentMounter, { forceMount, ...commonProps, ref: composedRefs }); }); NavigationMenuContent.displayName = CONTENT_NAME; var ViewportContentMounter = React.forwardRef((props, forwardedRef) => { const context = useNavigationMenuContext(CONTENT_NAME, props.__scopeNavigationMenu); const { onViewportContentChange, onViewportContentRemove } = context; (0, import_react_use_layout_effect.useLayoutEffect)(() => { onViewportContentChange(props.value, { ref: forwardedRef, ...props }); }, [props, forwardedRef, onViewportContentChange]); (0, import_react_use_layout_effect.useLayoutEffect)(() => { return () => onViewportContentRemove(props.value); }, [props.value, onViewportContentRemove]); return null; }); var ROOT_CONTENT_DISMISS = "navigationMenu.rootContentDismiss"; var NavigationMenuContentImpl = React.forwardRef((props, forwardedRef) => { const { __scopeNavigationMenu, value, triggerRef, focusProxyRef, wasEscapeCloseRef, onRootContentClose, onContentFocusOutside, ...contentProps } = props; const context = useNavigationMenuContext(CONTENT_NAME, __scopeNavigationMenu); const ref = React.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(ref, forwardedRef); const triggerId = makeTriggerId(context.baseId, value); const contentId = makeContentId(context.baseId, value); const getItems = useCollection(__scopeNavigationMenu); const prevMotionAttributeRef = React.useRef(null); const { onItemDismiss } = context; React.useEffect(() => { const content = ref.current; if (context.isRootMenu && content) { const handleClose = () => { onItemDismiss(); onRootContentClose(); if (content.contains(document.activeElement)) triggerRef.current?.focus(); }; content.addEventListener(ROOT_CONTENT_DISMISS, handleClose); return () => content.removeEventListener(ROOT_CONTENT_DISMISS, handleClose); } }, [context.isRootMenu, props.value, triggerRef, onItemDismiss, onRootContentClose]); const motionAttribute = React.useMemo(() => { const items = getItems(); const values = items.map((item) => item.value); if (context.dir === "rtl") values.reverse(); const index = values.indexOf(context.value); const prevIndex = values.indexOf(context.previousValue); const isSelected = value === context.value; const wasSelected = prevIndex === values.indexOf(value); if (!isSelected && !wasSelected) return prevMotionAttributeRef.current; const attribute = (() => { if (index !== prevIndex) { if (isSelected && prevIndex !== -1) return index > prevIndex ? "from-end" : "from-start"; if (wasSelected && index !== -1) return index > prevIndex ? "to-start" : "to-end"; } return null; })(); prevMotionAttributeRef.current = attribute; return attribute; }, [context.previousValue, context.value, context.dir, getItems, value]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroup, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_dismissable_layer.DismissableLayer, { id: contentId, "aria-labelledby": triggerId, "data-motion": motionAttribute, "data-orientation": context.orientation, ...contentProps, ref: composedRefs, disableOutsidePointerEvents: false, onDismiss: () => { const rootContentDismissEvent = new Event(ROOT_CONTENT_DISMISS, { bubbles: true, cancelable: true }); ref.current?.dispatchEvent(rootContentDismissEvent); }, onFocusOutside: (0, import_primitive.composeEventHandlers)(props.onFocusOutside, (event) => { onContentFocusOutside(); const target = event.target; if (context.rootNavigationMenu?.contains(target)) event.preventDefault(); }), onPointerDownOutside: (0, import_primitive.composeEventHandlers)(props.onPointerDownOutside, (event) => { const target = event.target; const isTrigger = getItems().some((item) => item.ref.current?.contains(target)); const isRootViewport = context.isRootMenu && context.viewport?.contains(target); if (isTrigger || isRootViewport || !context.isRootMenu) event.preventDefault(); }), onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const isMetaKey = event.altKey || event.ctrlKey || event.metaKey; const isTabKey = event.key === "Tab" && !isMetaKey; if (isTabKey) { const candidates = getTabbableCandidates(event.currentTarget); const focusedElement = document.activeElement; const index = candidates.findIndex((candidate) => candidate === focusedElement); const isMovingBackwards = event.shiftKey; const nextCandidates = isMovingBackwards ? candidates.slice(0, index).reverse() : candidates.slice(index + 1, candidates.length); if (focusFirst(nextCandidates)) { event.preventDefault(); } else { focusProxyRef.current?.focus(); } } }), onEscapeKeyDown: (0, import_primitive.composeEventHandlers)(props.onEscapeKeyDown, (event) => { wasEscapeCloseRef.current = true; }) } ) }); }); var VIEWPORT_NAME = "NavigationMenuViewport"; var NavigationMenuViewport = React.forwardRef((props, forwardedRef) => { const { forceMount, ...viewportProps } = props; const context = useNavigationMenuContext(VIEWPORT_NAME, props.__scopeNavigationMenu); const open = Boolean(context.value); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || open, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationMenuViewportImpl, { ...viewportProps, ref: forwardedRef }) }); }); NavigationMenuViewport.displayName = VIEWPORT_NAME; var NavigationMenuViewportImpl = React.forwardRef((props, forwardedRef) => { const { __scopeNavigationMenu, children, ...viewportImplProps } = props; const context = useNavigationMenuContext(VIEWPORT_NAME, __scopeNavigationMenu); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, context.onViewportChange); const viewportContentContext = useViewportContentContext( CONTENT_NAME, props.__scopeNavigationMenu ); const [size, setSize] = React.useState(null); const [content, setContent] = React.useState(null); const viewportWidth = size ? size?.width + "px" : void 0; const viewportHeight = size ? size?.height + "px" : void 0; const open = Boolean(context.value); const activeContentValue = open ? context.value : context.previousValue; const handleSizeChange = () => { if (content) setSize({ width: content.offsetWidth, height: content.offsetHeight }); }; useResizeObserver(content, handleSizeChange); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { "data-state": getOpenState(open), "data-orientation": context.orientation, ...viewportImplProps, ref: composedRefs, style: { // Prevent interaction when animating out pointerEvents: !open && context.isRootMenu ? "none" : void 0, ["--radix-navigation-menu-viewport-width"]: viewportWidth, ["--radix-navigation-menu-viewport-height"]: viewportHeight, ...viewportImplProps.style }, onPointerEnter: (0, import_primitive.composeEventHandlers)(props.onPointerEnter, context.onContentEnter), onPointerLeave: (0, import_primitive.composeEventHandlers)(props.onPointerLeave, whenMouse(context.onContentLeave)), children: Array.from(viewportContentContext.items).map(([value, { ref, forceMount, ...props2 }]) => { const isActive = activeContentValue === value; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || isActive, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( NavigationMenuContentImpl, { ...props2, ref: (0, import_react_compose_refs.composeRefs)(ref, (node) => { if (isActive && node) setContent(node); }) } ) }, value); }) } ); }); var FOCUS_GROUP_NAME = "FocusGroup"; var FocusGroup = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, ...groupProps } = props; const context = useNavigationMenuContext(FOCUS_GROUP_NAME, __scopeNavigationMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroupCollection.Provider, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroupCollection.Slot, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { dir: context.dir, ...groupProps, ref: forwardedRef }) }) }); } ); var ARROW_KEYS = ["ArrowRight", "ArrowLeft", "ArrowUp", "ArrowDown"]; var FOCUS_GROUP_ITEM_NAME = "FocusGroupItem"; var FocusGroupItem = React.forwardRef( (props, forwardedRef) => { const { __scopeNavigationMenu, ...groupProps } = props; const getItems = useFocusGroupCollection(__scopeNavigationMenu); const context = useNavigationMenuContext(FOCUS_GROUP_ITEM_NAME, __scopeNavigationMenu); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusGroupCollection.ItemSlot, { scope: __scopeNavigationMenu, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.button, { ...groupProps, ref: forwardedRef, onKeyDown: (0, import_primitive.composeEventHandlers)(props.onKeyDown, (event) => { const isFocusNavigationKey = ["Home", "End", ...ARROW_KEYS].includes(event.key); if (isFocusNavigationKey) { let candidateNodes = getItems().map((item) => item.ref.current); const prevItemKey = context.dir === "rtl" ? "ArrowRight" : "ArrowLeft"; const prevKeys = [prevItemKey, "ArrowUp", "End"]; if (prevKeys.includes(event.key)) candidateNodes.reverse(); if (ARROW_KEYS.includes(event.key)) { const currentIndex = candidateNodes.indexOf(event.currentTarget); candidateNodes = candidateNodes.slice(currentIndex + 1); } setTimeout(() => focusFirst(candidateNodes)); event.preventDefault(); } }) } ) }); } ); function getTabbableCandidates(container) { const nodes = []; const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, { acceptNode: (node) => { const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden"; if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP; return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; } }); while (walker.nextNode()) nodes.push(walker.currentNode); return nodes; } function focusFirst(candidates) { const previouslyFocusedElement = document.activeElement; return candidates.some((candidate) => { if (candidate === previouslyFocusedElement) return true; candidate.focus(); return document.activeElement !== previouslyFocusedElement; }); } function removeFromTabOrder(candidates) { candidates.forEach((candidate) => { candidate.dataset.tabindex = candidate.getAttribute("tabindex") || ""; candidate.setAttribute("tabindex", "-1"); }); return () => { candidates.forEach((candidate) => { const prevTabIndex = candidate.dataset.tabindex; candidate.setAttribute("tabindex", prevTabIndex); }); }; } function useResizeObserver(element, onResize) { const handleResize = (0, import_react_use_callback_ref.useCallbackRef)(onResize); (0, import_react_use_layout_effect.useLayoutEffect)(() => { let rAF = 0; if (element) { const resizeObserver = new ResizeObserver(() => { cancelAnimationFrame(rAF); rAF = window.requestAnimationFrame(handleResize); }); resizeObserver.observe(element); return () => { window.cancelAnimationFrame(rAF); resizeObserver.unobserve(element); }; } }, [element, handleResize]); } function getOpenState(open) { return open ? "open" : "closed"; } function makeTriggerId(baseId, value) { return `${baseId}-trigger-${value}`; } function makeContentId(baseId, value) { return `${baseId}-content-${value}`; } function whenMouse(handler) { return (event) => event.pointerType === "mouse" ? handler(event) : void 0; } var Root2 = NavigationMenu; var Sub = NavigationMenuSub; var List = NavigationMenuList; var Item = NavigationMenuItem; var Trigger = NavigationMenuTrigger; var Link = NavigationMenuLink; var Indicator = NavigationMenuIndicator; var Content = NavigationMenuContent; var Viewport = NavigationMenuViewport; //# sourceMappingURL=index.js.map