{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"navigation-menu","type":"registry:ui","title":"Navigation Menu","description":"A site's main navigation, with menus that open a panel of links.","dependencies":["lucide-react","radix-ui"],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/lib-locale.json"],"files":[{"path":"registry/dashral/navigation-menu.tsx","type":"registry:file","target":"components/dashral/navigation-menu.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { NavigationMenu as NavigationMenuPrimitive } from \"radix-ui\"\nimport { ArrowUpRightIcon, ChevronDownIcon } from \"lucide-react\"\n\nimport { useLocale } from \"./lib/locale\"\nimport { cn } from \"./lib/utils\"\n\n/** A link in a menu's panel: a title, and optionally an icon and a line under it. */\ntype NavigationMenuLink = {\n  label: React.ReactNode\n  href: string\n  /** A line under the title: what's there. */\n  description?: React.ReactNode\n  icon?: React.ReactNode\n  /** Opens in a new tab, marked with an arrow. */\n  external?: boolean\n  /** The page you're on. */\n  active?: boolean\n}\n\n/** One entry on the bar: a plain link, a menu of links, or a panel of your own. */\ntype NavigationMenuItem =\n  | {\n      label: React.ReactNode\n      href: string\n      external?: boolean\n      /** The page you're on: marked, and announced as the current page. */\n      active?: boolean\n    }\n  | {\n      label: React.ReactNode\n      /** The panel's links. */\n      links: NavigationMenuLink[]\n      /** Links side by side from the md breakpoint up. */\n      columns?: 1 | 2\n      /** A card at the panel's start, e.g. the product with a picture and a line about it. */\n      featured?: React.ReactNode\n      /** Under the links, across the panel, e.g. \"See all integrations →\". */\n      footer?: React.ReactNode\n    }\n  | {\n      label: React.ReactNode\n      /** A panel of your own; it needs a width (w-[480px]) since the panel takes its size from what's in it. */\n      content: React.ReactNode\n    }\n\ntype NavigationMenuProps = Omit<React.ComponentProps<typeof NavigationMenuPrimitive.Root>, \"children\"> & {\n  items: NavigationMenuItem[]\n  /** Your router's link (Next.js Link), for every href. */\n  linkAs?: React.ElementType\n  /** Where the panel opens, under the bar: at its start (default) or centred. */\n  align?: \"start\" | \"center\"\n  /** Names the navigation for screen readers. \"Main\" by default. */\n  \"aria-label\"?: string\n  classNames?: { list?: string; trigger?: string; viewport?: string }\n}\n\nconst triggerClass =\n  \"inline-flex h-9 items-center justify-center gap-1 rounded-md px-3 text-sm font-medium text-muted-foreground outline-none transition-colors select-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 data-[state=open]:bg-accent/60 data-[state=open]:text-foreground data-[active]:text-foreground\"\n\n/**\n * A site's main navigation, in one tag: links, and menus that open a panel of links with icons and descriptions, as in\n * a landing page's header. One panel slides between menus as you move across, resizing to fit. On a phone, show the\n * same items in a Sheet instead (see the examples).\n */\nfunction NavigationMenu({ items, linkAs: Link = \"a\", align = \"start\", className, classNames, \"aria-label\": ariaLabel, ...props }: NavigationMenuProps) {\n  const { t } = useLocale()\n\n  /** A link through the router's component, or an <a> that opens a new tab. */\n  const link = (href: string, external: boolean | undefined, active: boolean | undefined, className: string, children: React.ReactNode) => (\n    <NavigationMenuPrimitive.Link asChild active={active}>\n      {external ? (\n        <a href={href} target=\"_blank\" rel=\"noreferrer\" className={className}>\n          {children}\n        </a>\n      ) : (\n        <Link href={href} aria-current={active ? \"page\" : undefined} className={className}>\n          {children}\n        </Link>\n      )}\n    </NavigationMenuPrimitive.Link>\n  )\n\n  return (\n    <NavigationMenuPrimitive.Root\n      data-slot=\"navigation-menu\"\n      aria-label={ariaLabel ?? t(\"navigation\")}\n      className={cn(\"relative z-10 flex max-w-[min(100%,max-content)] flex-1 items-center\", className)}\n      {...props}\n    >\n      <NavigationMenuPrimitive.List className={cn(\"flex flex-1 flex-wrap list-none items-center justify-center gap-1\", classNames?.list)}>\n        {items.map((item, i) => (\n          <NavigationMenuPrimitive.Item key={i}>\n            {\"href\" in item ? (\n              link(item.href, item.external, item.active, cn(triggerClass, classNames?.trigger), item.label)\n            ) : (\n              <>\n                <NavigationMenuPrimitive.Trigger className={cn(triggerClass, \"group/nav-trigger\", classNames?.trigger)}>\n                  {item.label}\n                  <ChevronDownIcon\n                    aria-hidden\n                    className=\"relative top-px size-3.5 opacity-70 transition-transform duration-(--duration-standard) ease-spring group-data-[state=open]/nav-trigger:rotate-180 motion-reduce:transition-none\"\n                  />\n                </NavigationMenuPrimitive.Trigger>\n                <NavigationMenuPrimitive.Content\n                  className={cn(\n                    \"start-0 top-0 w-full md:absolute md:w-auto\",\n                    // Moving between menus, the panels slide from the side you came from (logical sides, so it reverses\n                    // in Arabic); opening and closing, the viewport fades instead.\n                    \"data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out\",\n                    \"data-[motion=from-end]:slide-in-from-end-12 data-[motion=from-start]:slide-in-from-start-12 data-[motion=to-end]:slide-out-to-end-12 data-[motion=to-start]:slide-out-to-start-12\",\n                    \"data-[motion]:duration-(--duration-standard) data-[motion]:ease-standard motion-reduce:animate-none\"\n                  )}\n                >\n                  {\"content\" in item ? (\n                    item.content\n                  ) : (\n                    <div className={cn(\"grid gap-1 p-2\", item.featured && \"md:grid-cols-[13rem_1fr]\")}>\n                      {item.featured && <div className=\"max-md:hidden\">{item.featured}</div>}\n                      <div className=\"grid gap-1\">\n                        <ul className={cn(\"grid gap-0.5 w-full md:w-[22rem]\", item.columns === 2 && \"md:w-[36rem] md:grid-cols-2\")}>\n                          {item.links.map((entry, j) => (\n                            <li key={j}>\n                              {link(\n                                entry.href,\n                                entry.external,\n                                entry.active,\n                                cn(\n                                  \"flex gap-3 rounded-md p-2.5 outline-none transition-colors hover:bg-accent focus-visible:bg-accent focus-visible:ring-2 focus-visible:ring-ring/50\",\n                                  entry.active && \"bg-accent/60\"\n                                ),\n                                <>\n                                  {entry.icon && (\n                                    <span className=\"flex size-8 shrink-0 items-center justify-center rounded-md border bg-card text-muted-foreground shadow-xs [&_svg]:size-4\">\n                                      {entry.icon}\n                                    </span>\n                                  )}\n                                  <span className=\"grid min-w-0 gap-0.5\">\n                                    <span className=\"flex items-center gap-1 text-sm font-medium\">\n                                      {entry.label}\n                                      {entry.external && <ArrowUpRightIcon aria-hidden className=\"size-3.5 text-muted-foreground\" />}\n                                    </span>\n                                    {entry.description && <span className=\"line-clamp-2 text-xs leading-snug text-muted-foreground\">{entry.description}</span>}\n                                  </span>\n                                </>\n                              )}\n                            </li>\n                          ))}\n                        </ul>\n                        {item.footer && <div className=\"border-t px-2.5 pt-2 pb-1 text-sm\">{item.footer}</div>}\n                      </div>\n                    </div>\n                  )}\n                </NavigationMenuPrimitive.Content>\n              </>\n            )}\n          </NavigationMenuPrimitive.Item>\n        ))}\n      </NavigationMenuPrimitive.List>\n      <div className={cn(\"absolute top-full flex\", align === \"center\" ? \"inset-x-0 justify-center\" : \"start-0\")}>\n        <NavigationMenuPrimitive.Viewport\n          className={cn(\n            \"relative mt-2 h-(--radix-navigation-menu-viewport-height) w-[calc(100vw-2rem)] origin-[top_center] overflow-hidden rounded-lg border bg-popover text-popover-foreground shadow-lg md:w-(--radix-navigation-menu-viewport-width)\",\n            \"transition-[width,height] duration-(--duration-standard) ease-standard motion-reduce:transition-none\",\n            \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:duration-(--duration-standard) data-[state=open]:ease-standard\",\n            \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:duration-(--duration-fast) data-[state=closed]:ease-exit\",\n            classNames?.viewport\n          )}\n        />\n      </div>\n    </NavigationMenuPrimitive.Root>\n  )\n}\n\nexport { NavigationMenu, type NavigationMenuProps, type NavigationMenuItem, type NavigationMenuLink }\n"}],"cssVars":{"theme":{"ease-standard":"var(--ease-standard)","ease-enter":"var(--ease-enter)","ease-exit":"var(--ease-exit)","ease-spring":"var(--ease-spring)"},"light":{"duration-fast":"160ms","duration-standard":"240ms","duration-considered":"480ms","ease-standard":"cubic-bezier(0.2, 0, 0, 1)","ease-enter":"cubic-bezier(0, 0, 0, 1)","ease-exit":"cubic-bezier(0.3, 0, 1, 1)","ease-spring":"linear(0, 0.071 4%, 0.234 8%, 0.433 12%, 0.626 17%, 0.791 21%, 0.917 25%, 1.004 29%, 1.055 33%, 1.079 38%, 1.083 42%, 1.075 46%, 1.06 50%, 1.043 54%, 1.027 58%, 1.015 62%, 1.005 67%, 0.998 71%, 0.995 75%, 0.993 79%, 0.993 83%, 0.994 88%, 0.995 92%, 0.997 96%, 1)"},"dark":{}}}