{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "navigation-menu",
  "title": "Navigation menu",
  "author": "andongmin94",
  "dependencies": [
    "@base-ui/react"
  ],
  "files": [
    {
      "path": "src/components/ui/navigation-menu.tsx",
      "content": "\"use client\";\n\nimport { DirectionProvider } from \"@base-ui/react/direction-provider\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { NavigationMenu as NavigationMenuPrimitive } from \"@base-ui/react/navigation-menu\";\nimport { cva } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { ChevronDownIcon } from \"lucide-react\";\n\ntype NavigationMenuLifecycleHandler<EventType extends Event = Event> = {\n  bivarianceHack(event: EventType): void;\n}[\"bivarianceHack\"];\n\ntype NavigationMenuOutsideEvent = CustomEvent<{ originalEvent: Event }>;\n\ntype NavigationMenuDismissHandlers = {\n  onEscapeKeyDown?: NavigationMenuLifecycleHandler<KeyboardEvent>;\n  onFocusOutside?: NavigationMenuLifecycleHandler<NavigationMenuOutsideEvent>;\n  onInteractOutside?: NavigationMenuLifecycleHandler<NavigationMenuOutsideEvent>;\n  onPointerDownOutside?: NavigationMenuLifecycleHandler<NavigationMenuOutsideEvent>;\n};\n\ntype NavigationMenuItemRecord = {\n  element: HTMLLIElement;\n  forceMount: boolean;\n};\n\ntype NavigationMenuAdapterContextValue = {\n  align: NavigationMenuPrimitive.Positioner.Props[\"align\"];\n  contentForceMount: boolean;\n  contentHandlersRef: React.MutableRefObject<Map<HTMLElement, NavigationMenuDismissHandlers>>;\n  orientation: \"horizontal\" | \"vertical\";\n  portalContainer: HTMLLIElement | null;\n  registerItem: (value: string, element: HTMLLIElement | null, forceMount: boolean) => void;\n  rootElement: HTMLElement | null;\n  value: string;\n  viewport: boolean;\n};\n\nconst NavigationMenuAdapterContext = React.createContext<NavigationMenuAdapterContextValue | null>(\n  null,\n);\n\ntype NavigationMenuProps = Omit<\n  NavigationMenuPrimitive.Root.Props<string>,\n  \"defaultValue\" | \"onValueChange\" | \"value\"\n> &\n  Pick<NavigationMenuPrimitive.Positioner.Props, \"align\"> & {\n    asChild?: boolean;\n    children?: React.ReactNode;\n    defaultValue?: string;\n    delayDuration?: number;\n    dir?: \"ltr\" | \"rtl\";\n    onValueChange?: (value: string) => void;\n    skipDelayDuration?: number;\n    value?: string;\n    viewport?: boolean;\n  };\n\ntype NavigationMenuContentProps = Omit<\n  React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Content>,\n  \"keepMounted\"\n> &\n  NavigationMenuDismissHandlers & {\n    asChild?: boolean;\n    children?: React.ReactNode;\n    forceMount?: boolean;\n    keepMounted?: boolean;\n  };\n\ntype NavigationMenuViewportProps = React.ComponentPropsWithRef<\"div\"> & {\n  asChild?: boolean;\n  children?: React.ReactNode;\n  forceMount?: boolean;\n  render?: NavigationMenuPrimitive.Viewport.Props[\"render\"];\n};\n\ntype NavigationMenuPositionerProps = NavigationMenuPrimitive.Positioner.Props & {\n  forceMount?: boolean;\n  portalContainer?: NavigationMenuPrimitive.Portal.Props[\"container\"];\n  viewport?: boolean;\n  viewportProps?: NavigationMenuViewportProps;\n};\n\ntype NavigationMenuCssProperties = React.CSSProperties & {\n  \"--radix-navigation-menu-indicator-translate-x\"?: string;\n  \"--radix-navigation-menu-indicator-translate-y\"?: string;\n  \"--radix-navigation-menu-viewport-height\"?: string;\n  \"--radix-navigation-menu-viewport-width\"?: string;\n};\n\nfunction setReactRef<T>(ref: React.Ref<T> | null | undefined, value: T | null) {\n  if (typeof ref === \"function\") {\n    ref(value);\n  } else if (ref) {\n    ref.current = value;\n  }\n}\n\nfunction preserveRadixEventCancellation(child: React.ReactElement) {\n  const childProps = child.props as Record<string, unknown>;\n  const eventProps: Record<string, unknown> = {};\n\n  for (const [name, handler] of Object.entries(childProps)) {\n    if (/^on[A-Z]/.test(name) && typeof handler === \"function\") {\n      eventProps[name] = (...args: unknown[]) => {\n        (handler as (...handlerArgs: unknown[]) => void)(...args);\n        const event = args[0] as\n          | { defaultPrevented?: boolean; preventBaseUIHandler?: () => void }\n          | undefined;\n        if (event?.defaultPrevented) event.preventBaseUIHandler?.();\n      };\n    }\n  }\n\n  return React.cloneElement(child, eventProps);\n}\n\nfunction getRenderElement<Render>(\n  asChild: boolean,\n  children: React.ReactNode,\n  render: Render,\n): React.ReactElement | Render {\n  return asChild\n    ? preserveRadixEventCancellation(\n        React.Children.toArray(children).find(React.isValidElement) as React.ReactElement,\n      )\n    : render;\n}\n\nfunction mergeRenderElement(\n  render: React.ReactElement,\n  elementProps: React.HTMLAttributes<HTMLElement> & { ref?: React.Ref<HTMLElement> },\n) {\n  const renderProps = render.props as React.HTMLAttributes<HTMLElement> & {\n    ref?: React.Ref<HTMLElement>;\n  };\n  const mergedProps = mergeProps<\"div\">(\n    elementProps as React.ComponentPropsWithRef<\"div\">,\n    renderProps as React.ComponentPropsWithRef<\"div\">,\n  );\n  const elementRef = elementProps.ref;\n  const renderRef = renderProps.ref;\n\n  mergedProps.ref = (node: HTMLDivElement | null) => {\n    setReactRef(elementRef, node);\n    setReactRef(renderRef, node);\n  };\n\n  return React.cloneElement(render, mergedProps);\n}\n\nfunction getRadixNavigationMenuMotion(state: NavigationMenuPrimitive.Content.State) {\n  const direction = state.activationDirection;\n  if (\n    !direction ||\n    (state.transitionStatus !== \"starting\" && state.transitionStatus !== \"ending\")\n  ) {\n    return undefined;\n  }\n\n  const movingTowardEnd = direction === \"right\" || direction === \"down\";\n  if (state.transitionStatus === \"starting\") {\n    return movingTowardEnd ? \"from-end\" : \"from-start\";\n  }\n\n  return movingTowardEnd ? \"to-start\" : \"to-end\";\n}\n\nfunction adaptNavigationMenuTriggerRender(\n  render: NavigationMenuPrimitive.Trigger.Props[\"render\"],\n): NavigationMenuPrimitive.Trigger.Props[\"render\"] {\n  return (elementProps, state) => {\n    const compatProps = mergeProps<\"button\">(elementProps, {\n      \"data-state\": state.open ? \"open\" : \"closed\",\n    } as React.ComponentPropsWithRef<\"button\">);\n\n    if (typeof render === \"function\") {\n      return render(compatProps, state);\n    }\n\n    if (render) {\n      return mergeRenderElement(\n        render,\n        compatProps as React.HTMLAttributes<HTMLElement> & { ref?: React.Ref<HTMLElement> },\n      );\n    }\n\n    return <button {...compatProps} />;\n  };\n}\n\nfunction adaptNavigationMenuContentRender(\n  render: NavigationMenuPrimitive.Content.Props[\"render\"],\n): NavigationMenuPrimitive.Content.Props[\"render\"] {\n  return (elementProps, state) => {\n    const compatProps = mergeProps<\"div\">(elementProps, {\n      \"data-motion\": getRadixNavigationMenuMotion(state),\n      \"data-state\": state.open ? \"open\" : \"closed\",\n    } as React.ComponentPropsWithRef<\"div\">);\n\n    if (typeof render === \"function\") {\n      return render(compatProps, state);\n    }\n\n    if (render) {\n      return mergeRenderElement(render, compatProps);\n    }\n\n    return <div {...compatProps} />;\n  };\n}\n\nfunction hasForceMountedContent(children: React.ReactNode): boolean {\n  let found = false;\n\n  React.Children.forEach(children, (child) => {\n    if (\n      found ||\n      !React.isValidElement<{\n        children?: React.ReactNode;\n        forceMount?: boolean;\n        keepMounted?: boolean;\n      }>(child)\n    ) {\n      return;\n    }\n    if (\n      child.type === NavigationMenuContent &&\n      (child.props.forceMount || child.props.keepMounted)\n    ) {\n      found = true;\n      return;\n    }\n    if (child.props.children) found = hasForceMountedContent(child.props.children);\n  });\n\n  return found;\n}\n\nfunction hasExplicitViewport(children: React.ReactNode): boolean {\n  let found = false;\n\n  React.Children.forEach(children, (child) => {\n    if (found || !React.isValidElement<{ children?: React.ReactNode }>(child)) return;\n    if (child.type === NavigationMenuViewport || child.type === NavigationMenuPositioner) {\n      found = true;\n      return;\n    }\n    if (child.type === React.Fragment && child.props.children) {\n      found = hasExplicitViewport(child.props.children);\n    }\n  });\n\n  return found;\n}\n\nfunction getActiveContentHandlers(handlers: Map<HTMLElement, NavigationMenuDismissHandlers>) {\n  for (const [element, value] of Array.from(handlers.entries())) {\n    if (element.isConnected && element.hasAttribute(\"data-open\")) return value;\n  }\n  return undefined;\n}\n\nfunction isNavigationMenuDismissPrevented(\n  handlers: NavigationMenuDismissHandlers | undefined,\n  reason: NavigationMenuPrimitive.Root.ChangeEventDetails[\"reason\"],\n  originalEvent: Event,\n) {\n  if (!handlers) return false;\n\n  if (reason === \"escape-key\") {\n    if (!(originalEvent instanceof KeyboardEvent)) return false;\n    handlers.onEscapeKeyDown?.(originalEvent);\n    return originalEvent.defaultPrevented;\n  }\n\n  if (reason === \"outside-press\") {\n    const outsideEvent = new CustomEvent<{ originalEvent: Event }>(\"pointerDownOutside\", {\n      cancelable: true,\n      detail: { originalEvent },\n    });\n    handlers.onPointerDownOutside?.(outsideEvent);\n    handlers.onInteractOutside?.(outsideEvent);\n    return outsideEvent.defaultPrevented;\n  }\n\n  if (reason === \"focus-out\") {\n    const outsideEvent = new CustomEvent<{ originalEvent: Event }>(\"focusOutside\", {\n      cancelable: true,\n      detail: { originalEvent },\n    });\n    handlers.onFocusOutside?.(outsideEvent);\n    handlers.onInteractOutside?.(outsideEvent);\n    return outsideEvent.defaultPrevented;\n  }\n\n  return false;\n}\n\nfunction NavigationMenu({\n  align = \"start\",\n  asChild = false,\n  className,\n  children,\n  closeDelay = 150,\n  defaultValue = \"\",\n  delay,\n  delayDuration = 200,\n  dir,\n  onValueChange,\n  orientation = \"horizontal\",\n  ref,\n  render,\n  skipDelayDuration = 300,\n  value: valueProp,\n  viewport = true,\n  ...props\n}: NavigationMenuProps) {\n  const controlled = valueProp !== undefined;\n  const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);\n  const value = valueProp ?? uncontrolledValue;\n  const [isOpenDelayed, setIsOpenDelayed] = React.useState(true);\n  const skipDelayTimerRef = React.useRef(0);\n  const contentHandlersRef = React.useRef(new Map<HTMLElement, NavigationMenuDismissHandlers>());\n  const itemRecordsRef = React.useRef(new Map<string, NavigationMenuItemRecord>());\n  const lastValueRef = React.useRef(value);\n  const [itemRevision, bumpItemRevision] = React.useReducer((revision) => revision + 1, 0);\n  const [rootElement, setRootElement] = React.useState<HTMLElement | null>(null);\n  const contentForceMount = hasForceMountedContent(children);\n  const explicitViewport = hasExplicitViewport(children);\n\n  if (value) lastValueRef.current = value;\n\n  const registerItem = React.useCallback(\n    (itemValue: string, element: HTMLLIElement | null, forceMount: boolean) => {\n      const current = itemRecordsRef.current.get(itemValue);\n      if (!element) {\n        if (current) {\n          itemRecordsRef.current.delete(itemValue);\n          bumpItemRevision();\n        }\n        return;\n      }\n      if (current?.element === element && current.forceMount === forceMount) return;\n      itemRecordsRef.current.set(itemValue, { element, forceMount });\n      bumpItemRevision();\n    },\n    [],\n  );\n\n  const portalContainer = (() => {\n    void itemRevision;\n    const ownerValue = value || lastValueRef.current;\n    const owner = ownerValue ? itemRecordsRef.current.get(ownerValue) : undefined;\n    if (owner) return owner.element;\n    if (contentForceMount) {\n      for (const record of Array.from(itemRecordsRef.current.values())) {\n        if (record.forceMount) return record.element;\n      }\n    }\n    return null;\n  })();\n\n  React.useEffect(\n    () => () => {\n      if (skipDelayTimerRef.current) window.clearTimeout(skipDelayTimerRef.current);\n    },\n    [],\n  );\n\n  const handleValueChange = React.useCallback(\n    (nextValue: string | null, eventDetails: NavigationMenuPrimitive.Root.ChangeEventDetails) => {\n      const adaptedValue = nextValue ?? \"\";\n      if (\n        !nextValue &&\n        isNavigationMenuDismissPrevented(\n          getActiveContentHandlers(contentHandlersRef.current),\n          eventDetails.reason,\n          eventDetails.event,\n        )\n      ) {\n        eventDetails.cancel();\n        return;\n      }\n\n      if (skipDelayTimerRef.current) window.clearTimeout(skipDelayTimerRef.current);\n      if (adaptedValue) {\n        if (skipDelayDuration > 0) setIsOpenDelayed(false);\n      } else {\n        skipDelayTimerRef.current = window.setTimeout(\n          () => setIsOpenDelayed(true),\n          skipDelayDuration,\n        );\n      }\n\n      if (!controlled) setUncontrolledValue(adaptedValue);\n      onValueChange?.(adaptedValue);\n    },\n    [controlled, onValueChange, skipDelayDuration],\n  );\n\n  const context = React.useMemo<NavigationMenuAdapterContextValue>(\n    () => ({\n      align,\n      contentForceMount,\n      contentHandlersRef,\n      orientation,\n      portalContainer,\n      registerItem,\n      rootElement,\n      value,\n      viewport,\n    }),\n    [\n      align,\n      contentForceMount,\n      orientation,\n      portalContainer,\n      registerItem,\n      rootElement,\n      value,\n      viewport,\n    ],\n  );\n\n  const setNavigationRootRef = React.useCallback(\n    (node: HTMLElement | null) => {\n      setRootElement(node);\n      setReactRef(ref, node);\n    },\n    [ref],\n  );\n\n  const rootChild = React.Children.toArray(children).find(\n    React.isValidElement,\n  ) as React.ReactElement<{ children?: React.ReactNode }>;\n  const rootChildren = (\n    <>\n      {asChild ? rootChild.props.children : children}\n      {viewport ? (\n        !explicitViewport && <NavigationMenuViewport />\n      ) : (\n        <NavigationMenuPositioner\n          align={align}\n          forceMount={contentForceMount}\n          portalContainer={portalContainer}\n          viewport={false}\n        />\n      )}\n    </>\n  );\n  const renderElement = asChild ? React.cloneElement(rootChild, undefined, rootChildren) : render;\n\n  const menu = (\n    <NavigationMenuPrimitive.Root\n      ref={setNavigationRootRef}\n      data-slot=\"navigation-menu\"\n      data-orientation={orientation}\n      data-state={value ? \"open\" : \"closed\"}\n      data-viewport={viewport}\n      defaultValue={valueProp === undefined ? defaultValue || null : undefined}\n      delay={delay ?? (isOpenDelayed ? delayDuration : 0)}\n      closeDelay={closeDelay}\n      dir={dir}\n      onValueChange={handleValueChange}\n      orientation={orientation}\n      render={renderElement}\n      value={valueProp === undefined ? undefined : valueProp || null}\n      className={cn(\n        \"group/navigation-menu relative z-10 flex max-w-max flex-1 items-center justify-center rounded-base border-2 border-border bg-main p-1 font-heading\",\n        className,\n      )}\n      {...props}\n    >\n      {asChild ? undefined : rootChildren}\n    </NavigationMenuPrimitive.Root>\n  );\n\n  return (\n    <NavigationMenuAdapterContext.Provider value={context}>\n      {dir ? <DirectionProvider direction={dir}>{menu}</DirectionProvider> : menu}\n    </NavigationMenuAdapterContext.Provider>\n  );\n}\n\nfunction NavigationMenuList({\n  asChild = false,\n  children,\n  className,\n  render,\n  ...props\n}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List> & {\n  asChild?: boolean;\n  children?: React.ReactNode;\n}) {\n  const adapter = React.useContext(NavigationMenuAdapterContext);\n  const renderElement = getRenderElement(asChild, children, render);\n\n  return (\n    <NavigationMenuPrimitive.List\n      data-slot=\"navigation-menu-list\"\n      data-orientation={adapter?.orientation ?? \"horizontal\"}\n      render={renderElement}\n      className={cn(\n        \"group flex flex-1 list-none items-center justify-center gap-1 font-heading\",\n        className,\n      )}\n      {...props}\n    >\n      {asChild ? undefined : children}\n    </NavigationMenuPrimitive.List>\n  );\n}\n\nfunction NavigationMenuItem({\n  asChild = false,\n  children,\n  className,\n  ref,\n  render,\n  value: valueProp,\n  ...props\n}: Omit<React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>, \"value\"> & {\n  asChild?: boolean;\n  children?: React.ReactNode;\n  value?: string;\n}) {\n  const adapter = React.useContext(NavigationMenuAdapterContext);\n  const generatedValue = React.useId();\n  const value = valueProp ?? generatedValue;\n  const forceMount = hasForceMountedContent(children);\n  const renderElement = getRenderElement(asChild, children, render);\n  const setItemRef = React.useCallback(\n    (node: HTMLLIElement | null) => {\n      adapter?.registerItem(value, node, forceMount);\n      setReactRef(ref, node);\n    },\n    [adapter, forceMount, ref, value],\n  );\n\n  return (\n    <NavigationMenuPrimitive.Item\n      ref={setItemRef}\n      data-slot=\"navigation-menu-item\"\n      data-value={value}\n      value={value}\n      render={renderElement}\n      className={cn(\"relative\", className)}\n      {...props}\n    >\n      {asChild ? undefined : children}\n    </NavigationMenuPrimitive.Item>\n  );\n}\n\nconst navigationMenuTriggerStyle = cva(\n  \"group/navigation-menu-trigger inline-flex h-10 w-max items-center justify-center rounded-base bg-main px-4 py-2 text-sm font-heading text-main-foreground transition-colors outline-none focus:outline-none disabled:pointer-events-none disabled:opacity-50\",\n);\n\nfunction NavigationMenuTrigger({\n  asChild = false,\n  className,\n  children,\n  render,\n  ...props\n}: NavigationMenuPrimitive.Trigger.Props & {\n  asChild?: boolean;\n  children?: React.ReactNode;\n}) {\n  const triggerChild = asChild\n    ? (preserveRadixEventCancellation(\n        React.Children.toArray(children).find(React.isValidElement) as React.ReactElement<{\n          children?: React.ReactNode;\n        }>,\n      ) as React.ReactElement<{ children?: React.ReactNode }>)\n    : undefined;\n  const chevron = (\n    <ChevronDownIcon\n      className=\"relative top-px ml-2 size-4 transition duration-200 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-open/navigation-menu-trigger:rotate-180 group-data-[state=open]/navigation-menu-trigger:rotate-180\"\n      aria-hidden=\"true\"\n    />\n  );\n  const renderElement = asChild\n    ? React.cloneElement(triggerChild!, undefined, triggerChild!.props.children, \" \", chevron)\n    : render;\n\n  return (\n    <NavigationMenuPrimitive.Trigger\n      data-slot=\"navigation-menu-trigger\"\n      render={adaptNavigationMenuTriggerRender(renderElement)}\n      className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n      {...props}\n    >\n      {asChild ? undefined : children}\n      {asChild ? undefined : \" \"}\n      {asChild ? undefined : chevron}\n    </NavigationMenuPrimitive.Trigger>\n  );\n}\n\nfunction NavigationMenuContent({\n  asChild = false,\n  children,\n  className,\n  forceMount,\n  keepMounted,\n  onEscapeKeyDown,\n  onFocusOutside,\n  onInteractOutside,\n  onPointerDownOutside,\n  ref,\n  render,\n  ...props\n}: NavigationMenuContentProps) {\n  const adapter = React.useContext(NavigationMenuAdapterContext);\n  const handlersRef = React.useRef<NavigationMenuDismissHandlers>({});\n  const contentElementRef = React.useRef<HTMLDivElement | null>(null);\n  handlersRef.current = {\n    onEscapeKeyDown,\n    onFocusOutside,\n    onInteractOutside,\n    onPointerDownOutside,\n  };\n  if (contentElementRef.current && adapter) {\n    adapter.contentHandlersRef.current.set(contentElementRef.current, handlersRef.current);\n  }\n  const renderElement = getRenderElement(asChild, children, render);\n\n  const setContentRef = React.useCallback(\n    (node: HTMLDivElement | null) => {\n      const handlers = adapter?.contentHandlersRef.current;\n      if (contentElementRef.current) handlers?.delete(contentElementRef.current);\n      contentElementRef.current = node;\n      if (node) handlers?.set(node, handlersRef.current);\n      setReactRef(ref, node);\n    },\n    [adapter, ref],\n  );\n\n  return (\n    <NavigationMenuPrimitive.Content\n      ref={setContentRef}\n      data-slot=\"navigation-menu-content\"\n      data-orientation={adapter?.orientation ?? \"horizontal\"}\n      keepMounted={forceMount ?? keepMounted}\n      render={adaptNavigationMenuContentRender(renderElement)}\n      className={cn(\n        \"h-full w-auto p-2 pr-2.5 transition-[opacity,transform,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[activation-direction=down]:data-ending-style:-translate-y-1/2 data-[activation-direction=down]:data-starting-style:translate-y-1/2 data-[activation-direction=left]:data-ending-style:translate-x-1/2 data-[activation-direction=left]:data-starting-style:-translate-x-1/2 data-[activation-direction=right]:data-ending-style:-translate-x-1/2 data-[activation-direction=right]:data-starting-style:translate-x-1/2 data-[activation-direction=up]:data-ending-style:translate-y-1/2 data-[activation-direction=up]:data-starting-style:-translate-y-1/2 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none\",\n        !adapter?.viewport &&\n          \"rounded-base border-2 border-border bg-main text-main-foreground duration-300 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n        className,\n      )}\n      {...props}\n    >\n      {asChild ? undefined : children}\n    </NavigationMenuPrimitive.Content>\n  );\n}\n\nfunction NavigationMenuPositioner({\n  align = \"start\",\n  alignOffset = 0,\n  className,\n  forceMount,\n  portalContainer,\n  side = \"bottom\",\n  sideOffset = 8,\n  viewport: viewportProp,\n  viewportProps,\n  ...props\n}: NavigationMenuPositionerProps) {\n  const adapter = React.useContext(NavigationMenuAdapterContext);\n  const viewport = viewportProp ?? adapter?.viewport ?? true;\n  const keepMounted = Boolean(forceMount || adapter?.contentForceMount);\n  const container = viewport ? undefined : (portalContainer ?? adapter?.portalContainer);\n  const {\n    asChild: viewportAsChild = false,\n    children: viewportChildren,\n    className: viewportClassName,\n    forceMount: viewportForceMount,\n    ref: viewportRef,\n    render: viewportRender,\n    style: viewportStyle,\n    ...viewportElementProps\n  } = viewportProps ?? {};\n  const viewportRenderElement = getRenderElement(viewportAsChild, viewportChildren, viewportRender);\n\n  if (!viewport && !container) return null;\n\n  const radixStyle: NavigationMenuCssProperties = {\n    \"--radix-navigation-menu-viewport-height\": \"var(--popup-height)\",\n    \"--radix-navigation-menu-viewport-width\": \"var(--popup-width)\",\n    ...viewportStyle,\n  };\n  const viewportElement = (\n    <NavigationMenuPrimitive.Viewport\n      {...viewportElementProps}\n      ref={viewportRef}\n      data-slot={viewport ? \"navigation-menu-viewport\" : \"navigation-menu-content-container\"}\n      data-state={adapter?.value ? \"open\" : \"closed\"}\n      data-orientation={adapter?.orientation ?? \"horizontal\"}\n      render={viewportRenderElement}\n      className={cn(\n        \"relative h-(--radix-navigation-menu-viewport-height) w-(--radix-navigation-menu-viewport-width)\",\n        viewport\n          ? \"overflow-hidden rounded-base bg-main shadow-[inset_0_0_0_2px_var(--border)]\"\n          : \"overflow-visible\",\n        viewportClassName,\n      )}\n      style={radixStyle}\n    >\n      {viewportAsChild ? undefined : viewportChildren}\n    </NavigationMenuPrimitive.Viewport>\n  );\n\n  return (\n    <NavigationMenuPrimitive.Portal\n      container={container}\n      keepMounted={keepMounted || Boolean(viewportForceMount)}\n    >\n      <NavigationMenuPrimitive.Positioner\n        side={side}\n        sideOffset={sideOffset}\n        align={align}\n        alignOffset={alignOffset}\n        className={cn(\n          \"isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0\",\n          className,\n        )}\n        {...props}\n      >\n        <NavigationMenuPrimitive.Popup\n          render={viewportElement}\n          data-viewport={viewport}\n          className={cn(\n            \"data-[ending-style]:easing-[ease] xs:w-(--popup-width) relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) text-main-foreground transition-[opacity,transform,width,height,scale,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0\",\n            !viewport && \"overflow-visible bg-transparent\",\n          )}\n        />\n      </NavigationMenuPrimitive.Positioner>\n    </NavigationMenuPrimitive.Portal>\n  );\n}\n\nfunction NavigationMenuViewport({\n  asChild = false,\n  children,\n  forceMount,\n  render,\n  ...props\n}: NavigationMenuViewportProps) {\n  const adapter = React.useContext(NavigationMenuAdapterContext);\n  if (adapter && !adapter.viewport) return null;\n\n  return (\n    <NavigationMenuPositioner\n      align={adapter?.align ?? \"start\"}\n      forceMount={Boolean(forceMount || adapter?.contentForceMount)}\n      viewportProps={{ asChild, children, forceMount, render, ...props }}\n    />\n  );\n}\n\nfunction NavigationMenuLink({\n  active,\n  className,\n  asChild = false,\n  children,\n  closeOnClick = true,\n  onClick,\n  onSelect,\n  render,\n  ...props\n}: NavigationMenuPrimitive.Link.Props & {\n  asChild?: boolean;\n  children?: React.ReactNode;\n  onSelect?: NavigationMenuLifecycleHandler;\n}) {\n  const renderElement = asChild\n    ? preserveRadixEventCancellation(\n        React.Children.toArray(children).find(React.isValidElement) as React.ReactElement,\n      )\n    : render;\n\n  return (\n    <NavigationMenuPrimitive.Link\n      data-slot=\"navigation-menu-link\"\n      data-active={active ? \"\" : undefined}\n      active={active}\n      closeOnClick={closeOnClick}\n      render={renderElement}\n      className={cn(\n        \"block space-y-1 rounded-base p-2 leading-none no-underline transition-colors outline-none select-none focus-visible:ring-4 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      onClick={(event) => {\n        onClick?.(event);\n        const selectEvent = new CustomEvent(\"navigationMenu.linkSelect\", {\n          bubbles: true,\n          cancelable: true,\n        });\n        const handleSelect = (customEvent: Event) => onSelect?.(customEvent);\n        event.currentTarget.addEventListener(selectEvent.type, handleSelect, { once: true });\n        event.currentTarget.dispatchEvent(selectEvent);\n\n        if (!closeOnClick || selectEvent.defaultPrevented || event.metaKey) {\n          event.preventBaseUIHandler();\n        }\n      }}\n      {...props}\n    >\n      {asChild ? undefined : children}\n    </NavigationMenuPrimitive.Link>\n  );\n}\n\ntype NavigationMenuIndicatorProps = React.ComponentPropsWithoutRef<\"div\"> & {\n  asChild?: boolean;\n  forceMount?: boolean;\n  render?: NavigationMenuPrimitive.Viewport.Props[\"render\"];\n};\n\ntype NavigationMenuIndicatorPosition = {\n  offset: number;\n  size: number;\n};\n\nconst NavigationMenuIndicator = React.forwardRef<HTMLDivElement, NavigationMenuIndicatorProps>(\n  function NavigationMenuIndicator(\n    { asChild = false, children, className, forceMount, render, style, ...props },\n    ref,\n  ) {\n    const adapter = React.useContext(NavigationMenuAdapterContext);\n    const [position, setPosition] = React.useState<NavigationMenuIndicatorPosition | null>(null);\n    const visible = Boolean(adapter?.value);\n\n    React.useLayoutEffect(() => {\n      const root = adapter?.rootElement;\n      if (!root) return undefined;\n      const rootElement = root;\n\n      let observedTrigger: HTMLElement | null = null;\n      const resizeObserver =\n        typeof ResizeObserver === \"function\" ? new ResizeObserver(updatePosition) : null;\n\n      function getActiveTrigger() {\n        const triggers = rootElement.querySelectorAll<HTMLElement>(\n          \"[data-slot='navigation-menu-trigger'][data-popup-open], [data-slot='navigation-menu-trigger'][aria-expanded='true']\",\n        );\n        return Array.from(triggers ?? []).find(\n          (trigger) =>\n            trigger.closest<HTMLElement>(\"[data-slot='navigation-menu']\") === rootElement,\n        );\n      }\n\n      function updatePosition() {\n        const trigger = getActiveTrigger();\n        if (!trigger || !adapter?.value) return;\n\n        if (trigger !== observedTrigger) {\n          resizeObserver?.disconnect();\n          resizeObserver?.observe(rootElement);\n          resizeObserver?.observe(trigger);\n          observedTrigger = trigger;\n        }\n\n        const rootRect = rootElement.getBoundingClientRect();\n        const triggerRect = trigger.getBoundingClientRect();\n        const horizontal = adapter.orientation === \"horizontal\";\n        const nextPosition = {\n          offset: horizontal\n            ? triggerRect.left - rootRect.left + rootElement.scrollLeft\n            : triggerRect.top - rootRect.top + rootElement.scrollTop,\n          size: horizontal ? triggerRect.width : triggerRect.height,\n        };\n        setPosition((current) =>\n          current?.offset === nextPosition.offset && current.size === nextPosition.size\n            ? current\n            : nextPosition,\n        );\n      }\n\n      const mutationObserver = new MutationObserver(updatePosition);\n      updatePosition();\n      mutationObserver.observe(rootElement, {\n        attributeFilter: [\"aria-expanded\", \"data-popup-open\"],\n        attributes: true,\n        subtree: true,\n      });\n      window.addEventListener(\"resize\", updatePosition);\n\n      return () => {\n        resizeObserver?.disconnect();\n        mutationObserver.disconnect();\n        window.removeEventListener(\"resize\", updatePosition);\n      };\n    }, [adapter]);\n\n    if ((!forceMount && !visible) || !position || !adapter?.rootElement) return null;\n\n    const horizontal = adapter.orientation === \"horizontal\";\n    const indicatorStyle: NavigationMenuCssProperties = horizontal\n      ? {\n          left: 0,\n          transform: `translateX(${position.offset}px)`,\n          width: position.size,\n          \"--radix-navigation-menu-indicator-translate-x\": `${position.offset}px`,\n          ...style,\n        }\n      : {\n          height: position.size,\n          top: 0,\n          transform: `translateY(${position.offset}px)`,\n          \"--radix-navigation-menu-indicator-translate-y\": `${position.offset}px`,\n          ...style,\n        };\n    const renderElement = getRenderElement(asChild, children, render);\n    const indicatorChildren =\n      asChild && React.isValidElement<{ children?: React.ReactNode }>(renderElement)\n        ? renderElement.props.children\n        : children;\n    const indicatorProps = {\n      ...props,\n      \"aria-hidden\": true,\n      \"data-slot\": \"navigation-menu-indicator\",\n      \"data-orientation\": adapter.orientation,\n      \"data-state\": visible ? \"visible\" : \"hidden\",\n      className: cn(\n        \"absolute top-full z-1 flex h-1.5 items-end justify-center overflow-hidden transition-[transform,width,height,opacity] data-[state=hidden]:pointer-events-none data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:animate-in data-[state=visible]:fade-in\",\n        !horizontal && \"top-0 right-0 h-auto w-1.5 items-center\",\n        className,\n      ),\n      ref,\n      style: indicatorStyle,\n    } as React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> };\n    const indicator =\n      typeof renderElement === \"function\" ? (\n        renderElement(indicatorProps, {})\n      ) : renderElement ? (\n        mergeRenderElement(\n          renderElement,\n          indicatorProps as React.HTMLAttributes<HTMLElement> & { ref?: React.Ref<HTMLElement> },\n        )\n      ) : (\n        <div {...indicatorProps}>{children}</div>\n      );\n\n    return (\n      <NavigationMenuPrimitive.Portal container={adapter.rootElement} keepMounted>\n        {React.cloneElement(\n          indicator,\n          undefined,\n          indicatorChildren,\n          <div className=\"relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md\" />,\n        )}\n      </NavigationMenuPrimitive.Portal>\n    );\n  },\n);\n\nexport {\n  NavigationMenu,\n  NavigationMenuContent,\n  NavigationMenuIndicator,\n  NavigationMenuItem,\n  NavigationMenuLink,\n  NavigationMenuList,\n  NavigationMenuTrigger,\n  NavigationMenuViewport,\n  navigationMenuTriggerStyle,\n  NavigationMenuPositioner,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}