{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "navigation-menu",
  "title": "Navigation Menu",
  "description": "Mega-menu nav with a shared viewport that resizes between preview panels.",
  "dependencies": [
    "@base-ui/react",
    "motion",
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "use-proximity-hover"
  ],
  "files": [
    {
      "path": "src/components/ui/navigation-menu.tsx",
      "content": "\"use client\";\n\nimport {\n  Children,\n  cloneElement,\n  createContext,\n  isValidElement,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  type ReactElement,\n  type ReactNode,\n} from \"react\";\nimport { NavigationMenu as NavigationMenuPrimitive } from \"@base-ui/react/navigation-menu\";\nimport { ChevronDownIcon } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { ProximityHoverPill } from \"@/components/ui/proximity-hover-pill\";\nimport { useProximityHover, type ItemRect } from \"@/hooks/use-proximity-hover\";\n\nconst viewportTransition =\n  \"transition-[top,left,right,bottom,width,height] delay-50 duration-200 ease-out data-ending-style:delay-0 data-ending-style:duration-150 data-instant:transition-none\";\nconst popupTransition =\n  \"transition-[opacity,transform,width,height] delay-50 duration-200 ease-out data-ending-style:delay-0 data-ending-style:duration-150\";\nconst contentTransition =\n  \"transition-[opacity,transform] duration-200 ease-out data-ending-style:duration-150\";\n\ninterface NavigationMenuProximityContextValue {\n  registerItem: (index: number, element: HTMLElement | null) => void;\n}\n\nconst NavigationMenuProximityContext = createContext<NavigationMenuProximityContextValue | null>(\n  null,\n);\n\ntype NavigationMenuIndexProp = { _index?: number };\n\nfunction indexNavigationMenuItems(children: ReactNode): ReactNode {\n  let index = -1;\n  return Children.map(children, (child) => {\n    if (!isValidElement(child) || child.type !== NavigationMenuItem) return child;\n    index += 1;\n    return cloneElement(child as ReactElement<NavigationMenuIndexProp>, { _index: index });\n  });\n}\n\nfunction NavigationMenu({\n  align = \"start\",\n  className,\n  children,\n  ...props\n}: NavigationMenuPrimitive.Root.Props & Pick<NavigationMenuPrimitive.Positioner.Props, \"align\">) {\n  return (\n    <NavigationMenuPrimitive.Root\n      data-slot=\"navigation-menu\"\n      className={cn(\n        \"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <NavigationMenuPositioner align={align} />\n    </NavigationMenuPrimitive.Root>\n  );\n}\n\nfunction NavigationMenuList({ className, children, ...props }: NavigationMenuPrimitive.List.Props) {\n  const containerRef = useRef<HTMLUListElement>(null);\n  const { activeIndex, itemRects, handlers, registerItem, measureItems } = useProximityHover(\n    containerRef,\n    { axis: \"x\" },\n  );\n\n  useEffect(() => {\n    measureItems();\n  }, [measureItems, children]);\n\n  const activeRect: ItemRect | null = activeIndex !== null ? itemRects[activeIndex] : null;\n  const proximityContextValue = useMemo(() => ({ registerItem }), [registerItem]);\n\n  return (\n    <NavigationMenuPrimitive.List\n      ref={containerRef}\n      data-slot=\"navigation-menu-list\"\n      className={cn(\n        \"group relative flex flex-1 list-none items-center justify-center gap-0.5\",\n        className,\n      )}\n      onMouseMove={handlers.onMouseMove}\n      onMouseEnter={handlers.onMouseEnter}\n      onMouseLeave={handlers.onMouseLeave}\n      {...props}\n    >\n      <ProximityHoverPill activeRect={activeRect} sessionKey={0} />\n      <NavigationMenuProximityContext.Provider value={proximityContextValue}>\n        {indexNavigationMenuItems(children)}\n      </NavigationMenuProximityContext.Provider>\n    </NavigationMenuPrimitive.List>\n  );\n}\n\nfunction NavigationMenuItem({\n  className,\n  _index,\n  ...props\n}: NavigationMenuPrimitive.Item.Props & NavigationMenuIndexProp) {\n  const ref = useRef<HTMLLIElement>(null);\n  const ctx = useContext(NavigationMenuProximityContext);\n\n  useEffect(() => {\n    if (_index === undefined || !ctx) return;\n    ctx.registerItem(_index, ref.current);\n    return () => ctx.registerItem(_index, null);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [_index, ctx]);\n\n  return (\n    <NavigationMenuPrimitive.Item\n      ref={ref}\n      data-slot=\"navigation-menu-item\"\n      className={cn(\"relative z-10\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction NavigationMenuTrigger({\n  className,\n  children,\n  ...props\n}: NavigationMenuPrimitive.Trigger.Props) {\n  return (\n    <NavigationMenuPrimitive.Trigger\n      data-slot=\"navigation-menu-trigger\"\n      className={cn(\n        \"group inline-flex h-8 w-max cursor-default items-center justify-center gap-1 rounded-lg px-2.5 text-control text-muted-foreground outline-none transition-colors select-none hover:bg-muted hover:text-foreground data-popup-open:bg-muted data-popup-open:text-foreground\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <ChevronDownIcon\n        aria-hidden=\"true\"\n        className=\"size-3 transition-transform duration-fast group-data-popup-open:rotate-180\"\n      />\n    </NavigationMenuPrimitive.Trigger>\n  );\n}\n\nfunction NavigationMenuContent({ className, ...props }: NavigationMenuPrimitive.Content.Props) {\n  return (\n    <NavigationMenuPrimitive.Content\n      data-slot=\"navigation-menu-content\"\n      className={cn(\n        \"h-full w-auto p-1 outline-none\",\n        contentTransition,\n        \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n        \"data-starting-style:data-[activation-direction=left]:-translate-x-1 data-starting-style:data-[activation-direction=right]:translate-x-1\",\n        \"data-starting-style:data-[activation-direction=up]:-translate-y-1 data-starting-style:data-[activation-direction=down]:translate-y-1\",\n        \"group-data-[viewport=false]/navigation-menu:rounded-lg group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow-popover\",\n        \"**:data-[slot=navigation-menu-link]:outline-none\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction NavigationMenuPositioner({\n  className,\n  side = \"bottom\",\n  sideOffset = 8,\n  align = \"start\",\n  alignOffset = 0,\n  ...props\n}: NavigationMenuPrimitive.Positioner.Props) {\n  return (\n    <NavigationMenuPrimitive.Portal>\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) before:absolute before:inset-x-0 before:content-[''] data-[side=bottom]:before:-top-2 data-[side=bottom]:before:h-2\",\n          viewportTransition,\n          className,\n        )}\n        {...props}\n      >\n        <NavigationMenuPrimitive.Popup\n          className={cn(\n            \"relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-popover outline-none\",\n            popupTransition,\n            \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n          )}\n        >\n          <NavigationMenuPrimitive.Viewport className=\"relative size-full overflow-hidden\" />\n        </NavigationMenuPrimitive.Popup>\n      </NavigationMenuPrimitive.Positioner>\n    </NavigationMenuPrimitive.Portal>\n  );\n}\n\nfunction NavigationMenuLink({ className, ...props }: NavigationMenuPrimitive.Link.Props) {\n  return (\n    <NavigationMenuPrimitive.Link\n      data-slot=\"navigation-menu-link\"\n      className={cn(\n        \"flex items-center gap-2 rounded-md p-2 text-control text-muted-foreground outline-none transition-colors select-none hover:bg-hover hover:text-foreground data-active:bg-active data-active:text-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport {\n  NavigationMenu,\n  NavigationMenuList,\n  NavigationMenuItem,\n  NavigationMenuTrigger,\n  NavigationMenuContent,\n  NavigationMenuLink,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}