{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "navdock",
  "type": "registry:ui",
  "title": "NavDock",
  "description": "Motion-powered dock navigation with icon-first items, hover and focus magnification, title reveal modes, route-current matching, disclosure submenus, placements, positioning, separators, responsive collapsed rails, and token-backed variants.",
  "dependencies": [
    "motion@^12.43.0"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/navdock/navdock.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/navdock/navdock.tsx",
      "content": "import {\n  Children,\n  cloneElement,\n  createContext,\n  forwardRef,\n  isValidElement,\n  useCallback,\n  useContext,\n  useEffect,\n  useId,\n  useLayoutEffect,\n  useMemo,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  type AnchorHTMLAttributes,\n  type CSSProperties,\n  type FocusEventHandler,\n  type HTMLAttributes,\n  type KeyboardEventHandler,\n  type LiHTMLAttributes,\n  type MouseEventHandler,\n  type PointerEventHandler,\n  type ReactElement,\n  type ReactNode,\n  type Ref,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n  AnimatePresence,\n  MotionConfig,\n  motion as motionElement,\n  useMotionValue,\n  useReducedMotion,\n  useSpring,\n  useTransform,\n  type HTMLMotionProps,\n  type MotionValue,\n  type SpringOptions,\n  type TargetAndTransition,\n  type Transition,\n} from \"motion/react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type NavDockPlacement = \"bottom\" | \"top\" | \"left\" | \"right\";\nexport type NavDockPosition = \"static\" | \"absolute\" | \"fixed\";\nexport type NavDockVariant = \"default\" | \"glass\" | \"solid\";\nexport type NavDockSize = \"sm\" | \"md\" | \"lg\";\nexport type NavDockShowTitle = \"never\" | \"hover\" | \"always\";\nexport type NavDockMotion = \"none\" | \"subtle\" | \"standard\" | \"expressive\";\nexport type NavDockCollapseMode = \"none\" | \"auto\" | \"always\";\nexport type NavDockCurrent = boolean | \"page\" | \"location\";\ntype NavDockMotionState = \"active\" | \"neighbor\" | \"idle\";\ntype NavDockOrientation = \"horizontal\" | \"vertical\";\ntype NavDockOverflowAxis = \"x\" | \"y\";\ntype NavDockLayerOffsetVariable = \"--dt-space-2\" | \"--navdock-submenu-offset\";\n\nconst NavDockAutoCollapseMediaQuery = \"(max-width: 640px), (pointer: coarse)\";\nconst NavDockCollapsedAnchorPlacement: NavDockPlacement = \"bottom\";\nconst NavDockCollapsedLayoutPlacement: NavDockPlacement = \"left\";\n\nexport type NavDockCurrentContext = {\n  currentValue?: string;\n};\n\ntype NavDockItemDataBase = {\n  badge?: ReactNode;\n  description?: ReactNode;\n  disabled?: boolean;\n  disabledReason?: ReactNode;\n  icon: ReactNode;\n  title: ReactNode;\n  value: string;\n};\n\nexport type NavDockLinkItemData = NavDockItemDataBase & {\n  ariaCurrent?: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-current\"];\n  current?: NavDockCurrent;\n  external?: boolean;\n  href: string;\n  onAction?: never;\n  rel?: string;\n  submenu?: never;\n  target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\n};\n\nexport type NavDockActionItemData = NavDockItemDataBase & {\n  current?: never;\n  external?: never;\n  href?: never;\n  onAction: (item: NavDockActionItemData) => void;\n  rel?: never;\n  submenu?: never;\n  target?: never;\n};\n\nexport type NavDockSubmenuChildData =\n  | {\n      ariaCurrent?: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-current\"];\n      badge?: ReactNode;\n      description?: ReactNode;\n      disabled?: boolean;\n      disabledReason?: ReactNode;\n      external?: boolean;\n      href: string;\n      kind?: \"link\";\n      rel?: string;\n      target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\n      title: ReactNode;\n      value: string;\n    }\n  | {\n      badge?: ReactNode;\n      description?: ReactNode;\n      disabled?: boolean;\n      disabledReason?: ReactNode;\n      kind: \"action\";\n      onAction: () => void;\n      title: ReactNode;\n      value: string;\n    }\n  | {\n      kind: \"label\";\n      title: ReactNode;\n      value: string;\n    }\n  | {\n      kind: \"separator\";\n      value: string;\n    };\n\nexport type NavDockSubmenuItemData = NavDockItemDataBase & {\n  current?: never;\n  external?: never;\n  href?: never;\n  onAction?: never;\n  rel?: never;\n  submenu: NavDockSubmenuChildData[];\n  target?: never;\n};\n\nexport type NavDockItemData =\n  NavDockLinkItemData | NavDockActionItemData | NavDockSubmenuItemData;\n\nexport type NavDockCurrentMatcher = (\n  item: NavDockItemData,\n  context: NavDockCurrentContext,\n) => NavDockCurrent | undefined;\n\nexport interface NavDockProps extends Omit<\n  HTMLAttributes<HTMLElement>,\n  \"defaultValue\"\n> {\n  collapseMode?: NavDockCollapseMode;\n  collapsed?: boolean;\n  currentValue?: string;\n  defaultCollapsed?: boolean;\n  defaultOpenValue?: string | null;\n  defaultValue?: string | null;\n  isItemCurrent?: NavDockCurrentMatcher;\n  items?: NavDockItemData[];\n  motion?: NavDockMotion;\n  onCollapsedChange?: (collapsed: boolean) => void;\n  onOpenValueChange?: (value: string | null) => void;\n  onValueChange?: (value: string | null) => void;\n  openValue?: string | null;\n  placement?: NavDockPlacement;\n  position?: NavDockPosition;\n  showTitle?: NavDockShowTitle;\n  size?: NavDockSize;\n  triggerIcon?: ReactNode;\n  triggerLabel?: string;\n  collapseLabel?: string;\n  value?: string | null;\n  variant?: NavDockVariant;\n}\n\nexport interface CollapseDockProps extends Omit<\n  HTMLMotionProps<\"div\">,\n  \"children\"\n> {\n  children?: ReactNode;\n  collapseLabel?: string;\n  collapseMode?: NavDockCollapseMode;\n  collapsed?: boolean;\n  defaultCollapsed?: boolean;\n  items?: NavDockItemData[];\n  mode?: NavDockCollapseMode;\n  onCollapsedChange?: (collapsed: boolean) => void;\n  triggerIcon?: ReactNode;\n  triggerLabel?: string;\n}\n\nexport type NavDockListProps = HTMLAttributes<HTMLUListElement>;\n\nexport type NavDockSeparatorProps = Omit<\n  LiHTMLAttributes<HTMLLIElement>,\n  \"children\"\n> & {\n  children?: never;\n};\n\nexport interface NavDockItemProps extends Omit<\n  LiHTMLAttributes<HTMLLIElement>,\n  \"title\"\n> {\n  disabled?: boolean;\n  disabledReason?: ReactNode;\n  icon?: ReactNode;\n  title?: ReactNode;\n  value?: string;\n}\n\ntype NavDockInteractiveBaseProps = {\n  badge?: ReactNode;\n  description?: ReactNode;\n  disabled?: boolean;\n  disabledReason?: ReactNode;\n  icon?: ReactNode;\n  title?: ReactNode;\n};\n\ntype NavDockLinkBaseProps = NavDockInteractiveBaseProps & {\n  asChild?: boolean;\n  current?: NavDockCurrent;\n  external?: boolean;\n};\n\ntype NativeNavDockAnchorProps = Omit<\n  HTMLMotionProps<\"a\">,\n  \"children\" | \"href\" | \"title\"\n>;\n\ntype NativeNavDockLinkProps = NativeNavDockAnchorProps &\n  NavDockLinkBaseProps & {\n    asChild?: false;\n    children?: ReactNode;\n    href: string;\n  };\n\ntype ChildNavDockLinkProps = Omit<\n  AnchorHTMLAttributes<HTMLAnchorElement>,\n  \"children\" | \"href\" | \"title\"\n> &\n  NavDockLinkBaseProps & {\n    asChild: true;\n    children: ReactElement<NavDockLinkSlotProps>;\n    href?: string;\n  };\n\nexport type NavDockLinkProps = NativeNavDockLinkProps | ChildNavDockLinkProps;\n\nexport type NavDockButtonProps = Omit<\n  HTMLMotionProps<\"button\">,\n  \"children\" | \"title\"\n> &\n  NavDockInteractiveBaseProps & {\n    children?: ReactNode;\n    current?: NavDockCurrent;\n    onAction?: () => void;\n  };\n\nexport interface NavDockSubmenuProps extends HTMLAttributes<HTMLDivElement> {\n  value?: string;\n}\n\nexport type NavDockSubmenuTriggerProps = Omit<\n  NavDockButtonProps,\n  \"current\" | \"onAction\"\n>;\n\nexport interface NavDockSubmenuContentProps extends Omit<\n  HTMLMotionProps<\"div\">,\n  \"children\"\n> {\n  children?: ReactNode;\n  panelClassName?: string;\n}\n\ntype NavDockLinkSlotProps = Record<string, unknown> & {\n  children?: ReactNode;\n  className?: string;\n  href?: string;\n  onClick?: MouseEventHandler<HTMLElement>;\n  ref?: Ref<HTMLElement>;\n  rel?: string;\n  target?: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"];\n  \"aria-current\"?: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-current\"];\n  \"aria-describedby\"?: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-describedby\"];\n  \"aria-disabled\"?: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-disabled\"];\n  tabIndex?: number;\n};\n\ntype NavDockContextValue = {\n  activeValue: string | null;\n  collapsed: boolean;\n  collapseModeActive: boolean;\n  collapseMode: NavDockCollapseMode;\n  collapseTriggerRef: { current: HTMLButtonElement | null };\n  currentValue?: string;\n  isItemCurrent?: NavDockCurrentMatcher;\n  itemValues: string[];\n  listId: string;\n  motion: NavDockMotion;\n  openValue: string | null;\n  placement: NavDockPlacement;\n  position: NavDockPosition;\n  registerListId: (id: string) => () => void;\n  registerItemValue?: (value: string) => () => void;\n  renderedListId: string;\n  rootId: string;\n  setActiveValue: (value: string | null) => void;\n  setCollapsed: (collapsed: boolean) => void;\n  setOpenValue: (value: string | null) => void;\n  showTitle: NavDockShowTitle;\n  size: NavDockSize;\n  variant: NavDockVariant;\n};\n\ntype NavDockListContextValue = {\n  overflowing: boolean;\n  pointerPosition: MotionValue<number>;\n};\n\ntype NavDockItemContextValue = {\n  disabled?: boolean;\n  disabledReason?: ReactNode;\n  icon?: ReactNode;\n  motionState: NavDockMotionState;\n  title?: ReactNode;\n  value?: string;\n};\n\ntype NavDockSubmenuContextValue = {\n  cancelClose: () => void;\n  contentElement: HTMLDivElement | null;\n  contentId: string;\n  consumeHoverOpenClickGuard: () => boolean;\n  open: boolean;\n  scheduleClose: () => void;\n  setContentElement: (element: HTMLDivElement | null) => void;\n  setOpen: (open: boolean) => void;\n  setTriggerElement: (element: HTMLButtonElement | null) => void;\n  triggerElement: HTMLButtonElement | null;\n  triggerId: string;\n  value?: string;\n};\n\nconst NavDockContext = createContext<NavDockContextValue | null>(null);\nconst NavDockItemContext = createContext<NavDockItemContextValue | null>(null);\nconst NavDockListContext = createContext<NavDockListContextValue | null>(null);\nconst NavDockSubmenuContext = createContext<NavDockSubmenuContextValue | null>(\n  null,\n);\nconst useIsomorphicLayoutEffect =\n  typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nconst navDockBaseClasses =\n  \"group/navdock relative h-fit w-fit max-w-full min-w-0 gap-[var(--dt-space-1)] text-foreground [--navdock-icon-size:1.5rem] [--navdock-item-radius:calc(var(--dt-radius-lg)+var(--dt-radius-lg))] [--navdock-item-size:3.25rem] [--navdock-position-offset:var(--dt-space-4)] [--navdock-radius:calc(var(--dt-radius-lg)+var(--dt-radius-lg)+var(--dt-radius-lg)+var(--dt-radius-lg))] [--navdock-submenu-offset:var(--dt-space-4)]\";\n\nconst navDockPlacementClasses: Record<NavDockPlacement, string> = {\n  bottom: \"inline-flex flex-col items-center\",\n  top: \"inline-flex flex-col-reverse items-center\",\n  left: \"inline-flex flex-row items-center\",\n  right: \"inline-flex flex-row-reverse items-center\",\n};\n\nconst navDockPositionClasses: Record<NavDockPosition, string> = {\n  static: \"static\",\n  absolute: \"absolute z-40\",\n  fixed: \"fixed z-40\",\n};\n\nconst navDockPositionPlacementClasses: Record<\n  NavDockPosition,\n  Record<NavDockPlacement, string>\n> = {\n  static: {\n    bottom: \"\",\n    top: \"\",\n    left: \"\",\n    right: \"\",\n  },\n  absolute: {\n    bottom: \"bottom-[var(--navdock-position-offset)] left-1/2 -translate-x-1/2\",\n    top: \"left-1/2 top-[var(--navdock-position-offset)] -translate-x-1/2\",\n    left: \"left-[var(--navdock-position-offset)] top-1/2 -translate-y-1/2\",\n    right: \"right-[var(--navdock-position-offset)] top-1/2 -translate-y-1/2\",\n  },\n  fixed: {\n    bottom:\n      \"bottom-[calc(var(--navdock-position-offset)+env(safe-area-inset-bottom))] left-1/2 -translate-x-1/2\",\n    top: \"left-1/2 top-[calc(var(--navdock-position-offset)+env(safe-area-inset-top))] -translate-x-1/2\",\n    left: \"left-[calc(var(--navdock-position-offset)+env(safe-area-inset-left))] top-1/2 -translate-y-1/2\",\n    right:\n      \"right-[calc(var(--navdock-position-offset)+env(safe-area-inset-right))] top-1/2 -translate-y-1/2\",\n  },\n};\n\nconst navDockVariantClasses: Record<NavDockVariant, string> = {\n  default:\n    \"rounded-[var(--navdock-radius)] border border-border/70 bg-background/95 shadow-[0_24px_60px_-34px_rgb(0_0_0/0.45),0_6px_18px_-14px_rgb(0_0_0/0.25)]\",\n  glass:\n    \"rounded-[var(--navdock-radius)] border border-border/60 bg-background/80 shadow-[0_24px_60px_-34px_rgb(0_0_0/0.45),0_6px_18px_-14px_rgb(0_0_0/0.25)] backdrop-blur\",\n  solid:\n    \"rounded-[var(--navdock-radius)] border border-border/70 bg-muted text-foreground shadow-[0_18px_48px_-32px_rgb(0_0_0/0.4)]\",\n};\n\nconst navDockSizeClasses: Record<NavDockSize, string> = {\n  sm: \"[--navdock-icon-size:1.25rem] [--navdock-item-size:2.75rem]\",\n  md: \"[--navdock-icon-size:1.5rem] [--navdock-item-size:3.25rem]\",\n  lg: \"[--navdock-icon-size:1.75rem] [--navdock-item-size:3.75rem]\",\n};\n\nconst navDockListBaseClasses =\n  \"flex list-none gap-[var(--dt-space-1)] overscroll-contain p-[var(--dt-space-2)] [scrollbar-gutter:stable] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden\";\n\nconst navDockListPlacementClasses: Record<NavDockPlacement, string> = {\n  bottom:\n    \"max-w-[min(100%,calc(100vw-var(--dt-space-4)))] flex-row items-end [scroll-padding-inline:var(--dt-space-2)]\",\n  top: \"max-w-[min(100%,calc(100vw-var(--dt-space-4)))] flex-row items-start [scroll-padding-inline:var(--dt-space-2)]\",\n  left: \"max-h-[min(100%,calc(100dvh-var(--dt-space-4)))] max-w-full flex-col items-start [scroll-padding-block:var(--dt-space-2)] group-data-[show-title=always]/navdock:items-center\",\n  right:\n    \"max-h-[min(100%,calc(100dvh-var(--dt-space-4)))] max-w-full flex-col items-end [scroll-padding-block:var(--dt-space-2)] group-data-[show-title=always]/navdock:items-center\",\n};\n\nconst navDockListOverflowClasses: Record<NavDockOverflowAxis | \"none\", string> =\n  {\n    none: \"overflow-visible\",\n    x: \"overflow-x-auto overflow-y-visible\",\n    y: \"overflow-x-visible overflow-y-auto\",\n  };\n\nconst navDockSeparatorBaseClasses = \"shrink-0 bg-border/70\";\n\nconst navDockSeparatorPlacementClasses: Record<NavDockPlacement, string> = {\n  bottom: \"mx-[var(--dt-space-1)] h-8 w-px self-center\",\n  top: \"mx-[var(--dt-space-1)] h-8 w-px self-center\",\n  left: \"my-[var(--dt-space-1)] h-px w-8 self-center\",\n  right: \"my-[var(--dt-space-1)] h-px w-8 self-center\",\n};\n\nconst navDockItemBaseClasses =\n  \"group/navdock-item relative shrink-0 scroll-m-[var(--dt-space-2)]\";\n\nconst navDockInteractiveBaseClasses =\n  \"group/navdock-link relative inline-flex min-w-[var(--navdock-item-size)] items-center justify-center gap-[var(--dt-space-1)] rounded-[var(--navdock-item-radius)] border border-transparent px-[var(--dt-space-2)] py-[var(--dt-space-1)] text-center text-sm font-medium text-foreground/80 outline-none motion-safe:transition-[background-color,border-color,box-shadow,color,opacity] motion-safe:duration-150 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background data-[active=true]:z-10 data-[active=true]:text-foreground data-[current=true]:text-primary data-[active=true]:data-[current=true]:text-primary data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50\";\n\nconst navDockInteractivePlacementClasses: Record<NavDockPlacement, string> = {\n  bottom: \"min-h-[var(--navdock-item-size)] flex-col\",\n  top: \"min-h-[var(--navdock-item-size)] flex-col-reverse\",\n  // Vertical docks stack the (optional) inline title below the icon, matching\n  // the top/bottom caption layout instead of crowding the label beside the icon.\n  left: \"min-h-[var(--navdock-item-size)] flex-row group-data-[show-title=always]/navdock:flex-col\",\n  right:\n    \"min-h-[var(--navdock-item-size)] flex-row-reverse group-data-[show-title=always]/navdock:flex-col\",\n};\n\nconst navDockIconClasses =\n  \"inline-flex size-[var(--navdock-icon-size)] shrink-0 transform-gpu items-center justify-center will-change-transform data-[reduced-motion=true]:will-change-auto [&>svg]:size-[var(--navdock-icon-size)] [&>svg]:shrink-0\";\n\nconst navDockCollapseTriggerClasses =\n  \"group/navdock-collapse-trigger shrink-0 data-[state=open]:text-foreground\";\n\nconst navDockCollapseTriggerIconClasses =\n  \"pointer-events-none inline-flex size-[var(--navdock-icon-size)] items-center justify-center [&>svg]:size-[var(--navdock-icon-size)] [&>svg]:shrink-0\";\n\nconst navDockCollapsedRootClasses =\n  \"border-transparent bg-transparent shadow-none backdrop-blur-none\";\n\nconst navDockCollapsedStaticRootClasses = \"relative\";\n\nconst navDockCollapsedPlaceholderClasses =\n  \"pointer-events-none block min-h-[calc(var(--navdock-item-size)+var(--dt-space-4))] min-w-[calc(var(--navdock-item-size)+var(--dt-space-4))] shrink-0\";\n\nconst navDockCollapsedShellBaseClasses =\n  \"absolute bottom-0 left-0 z-20 inline-flex h-fit w-fit min-w-[calc(var(--navdock-item-size)+var(--dt-space-4))] flex-col items-center justify-end gap-[var(--dt-space-1)] overflow-visible p-[var(--dt-space-2)] text-foreground\";\n\nconst navDockCollapsedContentClasses = \"min-w-0 max-w-full shrink-0\";\n\nconst navDockCollapsedListClasses = \"items-center p-0\";\n\nconst navDockTitleBaseClasses =\n  \"min-w-0 max-w-28 truncate text-xs font-medium leading-none\";\n\nconst navDockTitleVisibilityClasses: Record<NavDockShowTitle, string> = {\n  always: \"block\",\n  hover: \"sr-only\",\n  never: \"sr-only\",\n};\n\nconst navDockHoverTitleBaseClasses =\n  \"pointer-events-none z-20 max-w-40 whitespace-nowrap rounded-md border border-border bg-background px-[var(--dt-space-2)] py-[var(--dt-space-1)] text-xs font-medium leading-none text-foreground shadow-md\";\n\nconst navDockHoverTitlePlacementClasses: Record<NavDockPlacement, string> = {\n  bottom:\n    \"absolute bottom-[calc(100%+var(--dt-space-2))] left-1/2 -translate-x-1/2\",\n  top: \"absolute left-1/2 top-[calc(100%+var(--dt-space-2))] -translate-x-1/2\",\n  left: \"absolute left-[calc(100%+var(--dt-space-2))] top-1/2 -translate-y-1/2\",\n  right:\n    \"absolute right-[calc(100%+var(--dt-space-2))] top-1/2 -translate-y-1/2\",\n};\n\nconst navDockHoverTitlePortalledClasses = \"fixed z-50\";\n\nconst navDockMotionTransitions: Record<NavDockMotion, Transition> = {\n  none: { duration: 0 },\n  subtle: { type: \"spring\", stiffness: 520, damping: 42, mass: 0.7 },\n  standard: { type: \"spring\", stiffness: 420, damping: 30, mass: 0.75 },\n  expressive: { type: \"spring\", stiffness: 360, damping: 22, mass: 0.8 },\n};\n\nconst navDockTitleTransitions: Record<NavDockMotion, Transition> = {\n  none: { duration: 0 },\n  subtle: { duration: 0.12, ease: \"easeOut\" },\n  standard: { duration: 0.16, ease: [0.16, 1, 0.3, 1] },\n  expressive: { type: \"spring\", stiffness: 420, damping: 26, mass: 0.7 },\n};\n\nconst navDockPointerIdle = Number.POSITIVE_INFINITY;\n\nconst navDockMagnifyScale: Record<NavDockMotion, number> = {\n  none: 1,\n  subtle: 1.3,\n  standard: 1.45,\n  expressive: 1.6,\n};\n\nconst navDockMagnifySpringOptions: Record<NavDockMotion, SpringOptions> = {\n  none: { stiffness: 1200, damping: 120, mass: 1 },\n  subtle: { stiffness: 480, damping: 44, mass: 0.7 },\n  standard: { stiffness: 400, damping: 34, mass: 0.7 },\n  expressive: { stiffness: 320, damping: 31, mass: 0.7 },\n};\n\nconst navDockPressSpringOptions: SpringOptions = {\n  stiffness: 700,\n  damping: 34,\n  mass: 0.6,\n};\n\n// Horizontal docks lift from their shelf. Vertical docks magnify around the\n// rail centerline so the icon does not drift sideways as the pointer moves.\nconst navDockMagnifyOriginByPlacement: Record<NavDockPlacement, string> = {\n  bottom: \"50% 100%\",\n  top: \"50% 0%\",\n  left: \"50% 50%\",\n  right: \"50% 50%\",\n};\n\nconst navDockSubmenuTransitions: Record<NavDockMotion, Transition> = {\n  none: { duration: 0 },\n  subtle: { type: \"spring\", stiffness: 520, damping: 40, mass: 0.8 },\n  standard: { type: \"spring\", stiffness: 420, damping: 30, mass: 0.8 },\n  expressive: { type: \"spring\", stiffness: 360, damping: 24, mass: 0.9 },\n};\n\nconst navDockSubmenuExitTransition: Transition = {\n  duration: 0.16,\n  ease: [0.4, 0, 1, 1],\n};\n\nconst navDockCollapsedShellSpringOptions: Record<NavDockMotion, SpringOptions> =\n  {\n    none: { stiffness: 1200, damping: 120, mass: 1 },\n    subtle: { stiffness: 420, damping: 42, mass: 1 },\n    standard: { stiffness: 340, damping: 38, mass: 1 },\n    expressive: { stiffness: 300, damping: 36, mass: 1 },\n  };\n\nconst navDockCollapsedContentTransitions: Record<NavDockMotion, Transition> = {\n  none: { duration: 0 },\n  subtle: { duration: 0.12, ease: \"easeOut\" },\n  standard: { duration: 0.16, ease: \"easeOut\" },\n  expressive: { duration: 0.2, ease: \"easeOut\" },\n};\n\nconst navDockCollapsedContentExitTransition: Transition = {\n  duration: 0.18,\n  ease: [0.4, 0, 1, 1],\n};\n\nconst navDockBadgeClasses =\n  \"pointer-events-none absolute -right-1 -top-1 inline-flex min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-semibold leading-4 text-primary-foreground\";\n\nconst navDockExternalIndicatorClasses =\n  \"pointer-events-none absolute right-1 top-1 rounded-sm text-[0.5rem] font-semibold uppercase leading-none text-muted-foreground\";\n\nconst navDockSubmenuBaseClasses = \"relative\";\n\nconst navDockSubmenuContentBaseClasses =\n  \"z-30 w-[var(--navdock-submenu-width,14rem)] max-w-[min(var(--navdock-submenu-max-width,18rem),calc(100vw_-_var(--dt-space-4)))] transform-gpu overflow-hidden rounded-md border border-border bg-background p-[var(--dt-space-1)] text-foreground shadow-lg outline-none will-change-transform data-[reduced-motion=true]:will-change-auto\";\n\nconst navDockSubmenuContentPlacementClasses: Record<NavDockPlacement, string> =\n  {\n    bottom:\n      \"absolute bottom-[calc(100%+var(--navdock-submenu-offset))] left-1/2 origin-bottom -translate-x-1/2\",\n    top: \"absolute left-1/2 top-[calc(100%+var(--navdock-submenu-offset))] origin-top -translate-x-1/2\",\n    left: \"absolute left-[calc(100%+var(--navdock-submenu-offset))] top-1/2 origin-left -translate-y-1/2\",\n    right:\n      \"absolute right-[calc(100%+var(--navdock-submenu-offset))] top-1/2 origin-right -translate-y-1/2\",\n  };\n\nconst navDockSubmenuContentPortalledClasses = \"fixed z-50 origin-center\";\n\nconst navDockSubmenuPanelClasses =\n  \"grid max-h-[min(var(--navdock-submenu-max-height,22rem),calc(100dvh_-_var(--dt-space-4)))] gap-0 overflow-auto outline-none\";\n\nconst navDockSubmenuItemClasses =\n  \"group/navdock-submenu-item grid min-h-9 grid-cols-[minmax(0,1fr)_auto] items-start gap-[var(--dt-space-2)] rounded-sm px-[var(--dt-space-2)] py-[var(--dt-space-1-5)] text-start text-sm leading-5 text-foreground no-underline outline-none motion-safe:transition-[background-color,color,box-shadow] motion-safe:duration-150 hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring data-[current=true]:bg-primary/10 data-[current=true]:text-primary data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\";\n\nconst navDockSubmenuItemTextClasses = \"grid min-w-0 gap-0.5\";\n\nconst navDockSubmenuItemLabelClasses = \"min-w-0 truncate font-medium\";\n\nconst navDockSubmenuItemDescriptionClasses =\n  \"min-w-0 text-xs leading-5 text-muted-foreground\";\n\nconst navDockSubmenuItemBadgeClasses =\n  \"ms-[var(--dt-space-2)] justify-self-end rounded-full bg-muted px-[var(--dt-space-1-5)] py-0.5 text-[0.6875rem] font-medium leading-4 text-muted-foreground\";\n\nconst navDockSubmenuItemExternalClasses =\n  \"ms-[var(--dt-space-2)] justify-self-end text-[0.625rem] font-semibold uppercase leading-5 text-muted-foreground\";\n\nconst navDockSubmenuLabelClasses =\n  \"px-[var(--dt-space-2)] py-[var(--dt-space-1-5)] text-xs font-semibold uppercase leading-5 text-muted-foreground\";\n\nconst navDockSubmenuSeparatorClasses = \"my-[var(--dt-space-1)] h-px bg-border\";\n\nexport function navDockClassNames({\n  placement = \"bottom\",\n  position = \"static\",\n  size = \"md\",\n  variant = \"default\",\n  className,\n}: Pick<\n  NavDockProps,\n  \"placement\" | \"position\" | \"size\" | \"variant\" | \"className\"\n> = {}) {\n  return cn(\n    navDockBaseClasses,\n    navDockPlacementClasses[placement],\n    navDockPositionClasses[position],\n    navDockPositionPlacementClasses[position][placement],\n    navDockVariantClasses[variant],\n    navDockSizeClasses[size],\n    className,\n  );\n}\n\nexport function navDockListClassNames({\n  placement = \"bottom\",\n  overflowing = false,\n  className,\n}: Pick<NavDockProps, \"placement\"> &\n  Pick<NavDockListProps, \"className\"> & {\n    overflowing?: boolean;\n  } = {}) {\n  const overflowAxis = overflowing ? getNavDockOverflowAxis(placement) : \"none\";\n\n  return cn(\n    navDockListBaseClasses,\n    navDockListPlacementClasses[placement],\n    navDockListOverflowClasses[overflowAxis],\n    className,\n  );\n}\n\nexport function navDockSeparatorClassNames({\n  placement = \"bottom\",\n  className,\n}: Pick<NavDockProps, \"placement\"> &\n  Pick<NavDockSeparatorProps, \"className\"> = {}) {\n  return cn(\n    navDockSeparatorBaseClasses,\n    navDockSeparatorPlacementClasses[placement],\n    className,\n  );\n}\n\nexport function navDockItemClassNames({\n  className,\n}: Pick<NavDockItemProps, \"className\"> = {}) {\n  return cn(navDockItemBaseClasses, className);\n}\n\nexport function navDockLinkClassNames({\n  placement = \"bottom\",\n  className,\n}: Pick<NavDockProps, \"placement\"> & Pick<NavDockLinkProps, \"className\"> = {}) {\n  return cn(\n    navDockInteractiveBaseClasses,\n    navDockInteractivePlacementClasses[placement],\n    className,\n  );\n}\n\nexport function navDockButtonClassNames({\n  placement = \"bottom\",\n  className,\n}: Pick<NavDockProps, \"placement\"> &\n  Pick<NavDockButtonProps, \"className\"> = {}) {\n  return cn(\n    navDockInteractiveBaseClasses,\n    navDockInteractivePlacementClasses[placement],\n    className,\n  );\n}\n\nfunction navDockCollapseTriggerClassNames({\n  placement = NavDockCollapsedLayoutPlacement,\n  className,\n}: Pick<NavDockProps, \"placement\"> & { className?: string } = {}) {\n  return cn(\n    navDockButtonClassNames({ placement }),\n    navDockCollapseTriggerClasses,\n    className,\n  );\n}\n\nfunction navDockCollapsedShellClassNames({\n  variant = \"default\",\n  className,\n}: Pick<NavDockProps, \"variant\"> & { className?: string } = {}) {\n  return cn(\n    navDockCollapsedShellBaseClasses,\n    navDockVariantClasses[variant],\n    className,\n  );\n}\n\nexport function navDockSubmenuClassNames({\n  className,\n}: Pick<NavDockSubmenuProps, \"className\"> = {}) {\n  return cn(navDockSubmenuBaseClasses, className);\n}\n\nexport function navDockSubmenuTriggerClassNames({\n  placement = \"bottom\",\n  className,\n}: Pick<NavDockProps, \"placement\"> &\n  Pick<NavDockSubmenuTriggerProps, \"className\"> = {}) {\n  return navDockButtonClassNames({ placement, className });\n}\n\nexport function navDockSubmenuContentClassNames({\n  placement = \"bottom\",\n  portalled = false,\n  className,\n}: Pick<NavDockProps, \"placement\"> &\n  Pick<NavDockSubmenuContentProps, \"className\"> & {\n    portalled?: boolean;\n  } = {}) {\n  return cn(\n    navDockSubmenuContentBaseClasses,\n    portalled\n      ? navDockSubmenuContentPortalledClasses\n      : navDockSubmenuContentPlacementClasses[placement],\n    className,\n  );\n}\n\nexport function navDockTitleClassNames({\n  showTitle = \"hover\",\n  className,\n}: Pick<NavDockProps, \"showTitle\"> & { className?: string } = {}) {\n  return cn(\n    navDockTitleBaseClasses,\n    navDockTitleVisibilityClasses[showTitle],\n    className,\n  );\n}\n\nfunction setRef<T>(ref: Ref<T> | undefined, node: T | null) {\n  if (typeof ref === \"function\") {\n    ref(node);\n    return;\n  }\n\n  if (ref) {\n    (ref as { current: T | null }).current = node;\n  }\n}\n\nfunction composeRefs<T>(...refs: Array<Ref<T> | undefined>) {\n  return (node: T | null) => {\n    for (const ref of refs) {\n      setRef(ref, node);\n    }\n  };\n}\n\nfunction composeClickHandlers(\n  componentHandler: MouseEventHandler<HTMLElement> | undefined,\n  childHandler: MouseEventHandler<HTMLElement> | undefined,\n) {\n  if (!componentHandler && !childHandler) {\n    return undefined;\n  }\n\n  return (event: React.MouseEvent<HTMLElement>) => {\n    componentHandler?.(event);\n\n    if (!event.defaultPrevented) {\n      childHandler?.(event);\n    }\n  };\n}\n\nfunction composeFocusHandlers<T extends HTMLElement>(\n  componentHandler: FocusEventHandler<T> | undefined,\n  consumerHandler: FocusEventHandler<T> | undefined,\n) {\n  if (!componentHandler && !consumerHandler) {\n    return undefined;\n  }\n\n  return (event: React.FocusEvent<T>) => {\n    componentHandler?.(event);\n    consumerHandler?.(event);\n  };\n}\n\nfunction useControllableValue({\n  value,\n  defaultValue,\n  onValueChange,\n}: {\n  defaultValue?: string | null;\n  onValueChange?: (value: string | null) => void;\n  value?: string | null;\n}) {\n  const [uncontrolledValue, setUncontrolledValue] = useState(\n    defaultValue ?? null,\n  );\n  const isControlled = value !== undefined;\n  const currentValue = isControlled ? value : uncontrolledValue;\n\n  const setValue = useCallback(\n    (nextValue: string | null) => {\n      if (!isControlled) {\n        setUncontrolledValue(nextValue);\n      }\n\n      onValueChange?.(nextValue);\n    },\n    [isControlled, onValueChange],\n  );\n\n  return [currentValue ?? null, setValue] as const;\n}\n\nfunction useControllableBoolean({\n  value,\n  defaultValue = false,\n  onValueChange,\n}: {\n  defaultValue?: boolean;\n  onValueChange?: (value: boolean) => void;\n  value?: boolean;\n}) {\n  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n  const isControlled = value !== undefined;\n  const currentValue = isControlled ? value : uncontrolledValue;\n\n  const setValue = useCallback(\n    (nextValue: boolean) => {\n      if (!isControlled) {\n        setUncontrolledValue(nextValue);\n      }\n\n      onValueChange?.(nextValue);\n    },\n    [isControlled, onValueChange],\n  );\n\n  return [currentValue, setValue, isControlled] as const;\n}\n\nfunction getAutoCollapseMediaQueryList() {\n  if (\n    typeof window === \"undefined\" ||\n    typeof window.matchMedia !== \"function\"\n  ) {\n    return null;\n  }\n\n  return window.matchMedia(NavDockAutoCollapseMediaQuery);\n}\n\nfunction subscribeAutoCollapse(onChange: () => void) {\n  const query = getAutoCollapseMediaQueryList();\n  if (!query) return () => {};\n  if (typeof query.addEventListener === \"function\") {\n    query.addEventListener(\"change\", onChange);\n    return () => query.removeEventListener(\"change\", onChange);\n  }\n  query.addListener(onChange);\n  return () => query.removeListener(onChange);\n}\nfunction getAutoCollapseSnapshot() {\n  return getAutoCollapseMediaQueryList()?.matches ?? false;\n}\nfunction getAutoCollapseServerSnapshot() {\n  return false;\n}\nfunction useAutoCollapseActive(collapseMode: NavDockCollapseMode) {\n  const matches = useSyncExternalStore(\n    subscribeAutoCollapse,\n    getAutoCollapseSnapshot,\n    getAutoCollapseServerSnapshot,\n  );\n  return collapseMode === \"always\" || (collapseMode !== \"none\" && matches);\n}\n\nfunction useCollapsedShellHeight({\n  motion,\n  open,\n  reducedMotion,\n}: {\n  motion: NavDockMotion;\n  open: boolean;\n  reducedMotion: boolean;\n}) {\n  const shellRef = useRef<HTMLDivElement | null>(null);\n  const [closedHeight, setClosedHeight] = useState<number | null>(null);\n  const [openHeight, setOpenHeight] = useState<number | null>(null);\n  const heightValue = useMotionValue(0);\n  const springHeight = useSpring(\n    heightValue,\n    navDockCollapsedShellSpringOptions[motion],\n  );\n\n  useIsomorphicLayoutEffect(() => {\n    const shell = shellRef.current;\n\n    if (!shell) {\n      return undefined;\n    }\n\n    const measure = () => {\n      const nextClosedHeight = getCollapsedShellClosedHeight(shell);\n\n      if (nextClosedHeight !== null) {\n        setClosedHeight(nextClosedHeight);\n      }\n\n      if (!open) {\n        return;\n      }\n\n      const content = shell.querySelector<HTMLElement>(\n        '[data-slot=\"navdock-collapsed-content\"]',\n      );\n      const gap = Number.parseFloat(window.getComputedStyle(shell).rowGap) || 0;\n      // Measure intrinsic children, never the shell whose height we animate.\n      // scrollHeight includes the animated box and feeds its overshoot back in.\n      const nextHeight =\n        content && nextClosedHeight !== null\n          ? nextClosedHeight + content.offsetHeight + gap\n          : 0;\n\n      if (nextHeight > 0) {\n        setOpenHeight(nextHeight);\n      }\n    };\n\n    measure();\n\n    if (typeof ResizeObserver === \"undefined\") {\n      return undefined;\n    }\n\n    const observer = new ResizeObserver(measure);\n\n    for (const child of shell.children) observer.observe(child);\n\n    return () => {\n      observer.disconnect();\n    };\n  }, [open]);\n\n  const hasSyncedHeightRef = useRef(false);\n\n  useIsomorphicLayoutEffect(() => {\n    const nextHeight = open\n      ? (openHeight ?? closedHeight)\n      : (closedHeight ?? openHeight);\n\n    if (nextHeight === null) {\n      return;\n    }\n\n    // The first measurement is layout, not a state change — snap to it so the\n    // shell does not animate from 0 on mount.\n    if (!hasSyncedHeightRef.current) {\n      hasSyncedHeightRef.current = true;\n      heightValue.jump(nextHeight);\n      springHeight.jump(nextHeight);\n      return;\n    }\n\n    heightValue.set(nextHeight);\n  }, [closedHeight, heightValue, open, openHeight, springHeight]);\n\n  const staticHeight = open\n    ? (openHeight ?? closedHeight ?? undefined)\n    : (closedHeight ?? undefined);\n\n  return [\n    shellRef,\n    {\n      closedHeight,\n      height: reducedMotion\n        ? staticHeight\n        : closedHeight === null\n          ? undefined\n          : springHeight,\n      openHeight,\n    },\n  ] as const;\n}\n\nfunction getCollapsedShellClosedHeight(shell: Element) {\n  const styles = window.getComputedStyle(shell);\n  const itemSize = parseCssLength(\n    styles.getPropertyValue(\"--navdock-item-size\"),\n    shell,\n  );\n  const shellBlockPadding = parseCssLength(\n    styles.getPropertyValue(\"--dt-space-4\"),\n    shell,\n  );\n\n  if (itemSize === null || shellBlockPadding === null) {\n    return null;\n  }\n\n  return Math.ceil(itemSize + shellBlockPadding);\n}\n\nfunction useNavDockContext() {\n  const context = useContext(NavDockContext);\n\n  if (!context) {\n    throw new Error(\"NavDock components must be rendered inside NavDock.\");\n  }\n\n  return context;\n}\n\nfunction useNavDockItemContext() {\n  return useContext(NavDockItemContext);\n}\n\nfunction useNavDockListContext() {\n  return useContext(NavDockListContext);\n}\n\nfunction useNavDockSubmenuContext() {\n  const context = useContext(NavDockSubmenuContext);\n\n  if (!context) {\n    throw new Error(\n      \"NavDock submenu parts must be rendered inside NavDockSubmenu.\",\n    );\n  }\n\n  return context;\n}\n\nfunction getPortalTarget() {\n  return typeof document === \"undefined\" ? null : document.body;\n}\n\nfunction parseCssLength(value: string, owner: Element | null): number | null {\n  const trimmedValue = value.trim();\n\n  if (!trimmedValue) {\n    return null;\n  }\n\n  if (trimmedValue.endsWith(\"px\")) {\n    return Number.parseFloat(trimmedValue);\n  }\n\n  if (trimmedValue.endsWith(\"rem\")) {\n    const rootFontSize =\n      typeof window === \"undefined\"\n        ? 16\n        : Number.parseFloat(\n            window.getComputedStyle(document.documentElement).fontSize,\n          );\n\n    return Number.parseFloat(trimmedValue) * rootFontSize;\n  }\n\n  if (trimmedValue.endsWith(\"em\") && owner) {\n    const fontSize = Number.parseFloat(window.getComputedStyle(owner).fontSize);\n\n    return Number.parseFloat(trimmedValue) * fontSize;\n  }\n\n  if (/^-?\\d+(\\.\\d+)?$/.test(trimmedValue)) {\n    return Number.parseFloat(trimmedValue);\n  }\n\n  return null;\n}\n\nfunction readCssLengthVariable({\n  anchorElement,\n  fallback,\n  variableName,\n}: {\n  anchorElement: HTMLElement;\n  fallback: number;\n  variableName: NavDockLayerOffsetVariable;\n}) {\n  const root = anchorElement.closest('[data-slot=\"navdock\"]') ?? anchorElement;\n  const rootStyles = window.getComputedStyle(root);\n  const directValue = rootStyles.getPropertyValue(variableName);\n  const directLength = parseCssLength(directValue, root);\n\n  if (directLength !== null) {\n    return directLength;\n  }\n\n  const variableMatch = directValue.match(/var\\((--[^,)]+)/);\n\n  if (variableMatch) {\n    const referencedValue = rootStyles.getPropertyValue(variableMatch[1]);\n    const referencedLength = parseCssLength(referencedValue, root);\n\n    if (referencedLength !== null) {\n      return referencedLength;\n    }\n  }\n\n  return fallback;\n}\n\nfunction getAnchoredLayerStyle({\n  anchorElement,\n  fallbackOffset,\n  placement,\n  variableName,\n}: {\n  anchorElement: HTMLElement;\n  fallbackOffset: number;\n  placement: NavDockPlacement;\n  variableName: NavDockLayerOffsetVariable;\n}): CSSProperties {\n  const rect = anchorElement.getBoundingClientRect();\n  const offset = readCssLengthVariable({\n    anchorElement,\n    fallback: fallbackOffset,\n    variableName,\n  });\n  const centerX = rect.left + rect.width / 2;\n  const centerY = rect.top + rect.height / 2;\n\n  switch (placement) {\n    case \"top\":\n      return {\n        left: centerX,\n        top: rect.bottom + offset,\n        translate: \"-50% 0\",\n      };\n    case \"left\":\n      return {\n        left: rect.right + offset,\n        top: centerY,\n        translate: \"0 -50%\",\n      };\n    case \"right\":\n      return {\n        left: rect.left - offset,\n        top: centerY,\n        translate: \"-100% -50%\",\n      };\n    case \"bottom\":\n    default:\n      return {\n        left: centerX,\n        top: rect.top - offset,\n        translate: \"-50% -100%\",\n      };\n  }\n}\n\nfunction useAnchoredLayerStyle({\n  anchorElement,\n  fallbackOffset,\n  open,\n  placement,\n  variableName,\n}: {\n  anchorElement: HTMLElement | null | undefined;\n  fallbackOffset: number;\n  open: boolean;\n  placement: NavDockPlacement;\n  variableName: NavDockLayerOffsetVariable;\n}) {\n  const currentStyle =\n    open && anchorElement && typeof window !== \"undefined\"\n      ? getAnchoredLayerStyle({\n          anchorElement,\n          fallbackOffset,\n          placement,\n          variableName,\n        })\n      : undefined;\n  const [style, setStyle] = useState<CSSProperties | undefined>(currentStyle);\n\n  useEffect(() => {\n    if (!open || !anchorElement || typeof window === \"undefined\") {\n      // eslint-disable-next-line react-hooks/set-state-in-effect -- Discard committed DOM measurements when hidden so reopening uses the anchor's current position.\n      setStyle(undefined);\n      return undefined;\n    }\n\n    const updateStyle = () => {\n      setStyle(\n        getAnchoredLayerStyle({\n          anchorElement,\n          fallbackOffset,\n          placement,\n          variableName,\n        }),\n      );\n    };\n\n    updateStyle();\n    window.addEventListener(\"resize\", updateStyle);\n    window.addEventListener(\"scroll\", updateStyle, true);\n\n    if (typeof ResizeObserver !== \"undefined\") {\n      const observer = new ResizeObserver(updateStyle);\n\n      observer.observe(anchorElement);\n\n      return () => {\n        observer.disconnect();\n        window.removeEventListener(\"resize\", updateStyle);\n        window.removeEventListener(\"scroll\", updateStyle, true);\n      };\n    }\n\n    return () => {\n      window.removeEventListener(\"resize\", updateStyle);\n      window.removeEventListener(\"scroll\", updateStyle, true);\n    };\n  }, [anchorElement, fallbackOffset, open, placement, variableName]);\n\n  return style ?? currentStyle;\n}\n\nfunction resolveAriaCurrent(\n  ariaCurrent: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-current\"],\n  current: NavDockCurrent | undefined,\n) {\n  if (ariaCurrent !== undefined) {\n    return ariaCurrent;\n  }\n\n  if (current === true) {\n    return \"page\";\n  }\n\n  if (current === \"page\" || current === \"location\") {\n    return current;\n  }\n\n  return undefined;\n}\n\nfunction hasCurrentState(\n  ariaCurrent: AnchorHTMLAttributes<HTMLAnchorElement>[\"aria-current\"],\n) {\n  return (\n    ariaCurrent !== undefined &&\n    ariaCurrent !== false &&\n    ariaCurrent !== \"false\"\n  );\n}\n\nfunction shouldReduceNavDockMotion(\n  motion: NavDockMotion,\n  prefersReducedMotion: boolean | null,\n) {\n  return motion === \"none\" || prefersReducedMotion === true;\n}\n\nfunction getNavDockOrientation(\n  placement: NavDockPlacement,\n): NavDockOrientation {\n  return placement === \"left\" || placement === \"right\"\n    ? \"vertical\"\n    : \"horizontal\";\n}\n\nfunction getNavDockOverflowAxis(\n  placement: NavDockPlacement,\n): NavDockOverflowAxis {\n  return getNavDockOrientation(placement) === \"vertical\" ? \"y\" : \"x\";\n}\n\nfunction getNavDockElementDirection(element: HTMLElement) {\n  const explicitDir = element.closest(\"[dir]\")?.getAttribute(\"dir\");\n\n  if (explicitDir === \"rtl\" || explicitDir === \"ltr\") {\n    return explicitDir;\n  }\n\n  return window.getComputedStyle(element).direction === \"rtl\" ? \"rtl\" : \"ltr\";\n}\n\nfunction getNavDockFocusableItems(list: HTMLElement) {\n  return Array.from(\n    list.querySelectorAll<HTMLElement>(\n      '[data-slot=\"navdock-link\"], [data-slot=\"navdock-button\"], [data-slot=\"navdock-submenu-trigger\"]',\n    ),\n  ).filter(\n    (element) =>\n      element.tabIndex >= 0 &&\n      !element.hasAttribute(\"disabled\") &&\n      element.getAttribute(\"aria-disabled\") !== \"true\",\n  );\n}\n\nfunction scrollNavDockItemIntoView(element: HTMLElement) {\n  if (typeof element.scrollIntoView !== \"function\") {\n    return;\n  }\n\n  element.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n}\n\nfunction focusNavDockItemAtIndex(\n  list: HTMLElement,\n  index: number,\n  focusableItems = getNavDockFocusableItems(list),\n) {\n  const nextItem = focusableItems[index];\n\n  if (!nextItem) {\n    return false;\n  }\n\n  nextItem.focus();\n  scrollNavDockItemIntoView(nextItem);\n\n  return true;\n}\n\nfunction focusNavDockItemByOffset({\n  list,\n  offset,\n  target,\n}: {\n  list: HTMLElement;\n  offset: number;\n  target: EventTarget | null;\n}) {\n  const focusableItems = getNavDockFocusableItems(list);\n\n  if (focusableItems.length === 0) {\n    return false;\n  }\n\n  const currentIndex = focusableItems.findIndex(\n    (element) => target instanceof Node && element.contains(target),\n  );\n\n  if (currentIndex === -1) {\n    return focusNavDockItemAtIndex(\n      list,\n      offset > 0 ? 0 : focusableItems.length - 1,\n      focusableItems,\n    );\n  }\n\n  const nextIndex = Math.min(\n    Math.max(currentIndex + offset, 0),\n    focusableItems.length - 1,\n  );\n\n  if (nextIndex === currentIndex) {\n    return false;\n  }\n\n  return focusNavDockItemAtIndex(list, nextIndex, focusableItems);\n}\n\nfunction getNavDockItemMotionState({\n  activeValue,\n  itemValues,\n  value,\n}: {\n  activeValue: string | null;\n  itemValues: string[];\n  value?: string;\n}): NavDockMotionState {\n  if (value === undefined || activeValue === null) {\n    return \"idle\";\n  }\n\n  if (value === activeValue) {\n    return \"active\";\n  }\n\n  const activeIndex = itemValues.indexOf(activeValue);\n  const itemIndex = itemValues.indexOf(value);\n\n  if (\n    activeIndex !== -1 &&\n    itemIndex !== -1 &&\n    Math.abs(activeIndex - itemIndex) === 1\n  ) {\n    return \"neighbor\";\n  }\n\n  return \"idle\";\n}\n\nfunction getNavDockMagnifiedScale({\n  distance,\n  magnifyScale,\n  radius,\n}: {\n  distance: number;\n  magnifyScale: number;\n  radius: number;\n}) {\n  if (radius <= 0 || distance >= radius) {\n    return 1;\n  }\n\n  // Cosine falloff peaks smoothly at the pointer and fades over `radius`.\n  const falloff = (1 + Math.cos((distance / radius) * Math.PI)) / 2;\n\n  return 1 + (magnifyScale - 1) * falloff;\n}\n\nfunction getPressMotionTarget({\n  disabled,\n  reducedMotion,\n}: {\n  disabled: boolean;\n  reducedMotion: boolean;\n}): TargetAndTransition | undefined {\n  if (disabled || reducedMotion) {\n    return undefined;\n  }\n\n  return { scale: 0.92 };\n}\n\nfunction getTitleMotionOffset(placement: NavDockPlacement) {\n  switch (placement) {\n    case \"top\":\n      return { x: 0, y: -4 };\n    case \"left\":\n      return { x: -4, y: 0 };\n    case \"right\":\n      return { x: 4, y: 0 };\n    case \"bottom\":\n    default:\n      return { x: 0, y: 4 };\n  }\n}\n\nfunction getTitleMotionState({\n  placement,\n  reducedMotion,\n}: {\n  placement: NavDockPlacement;\n  reducedMotion: boolean;\n}): TargetAndTransition {\n  const offset = reducedMotion\n    ? { x: 0, y: 0 }\n    : getTitleMotionOffset(placement);\n\n  return {\n    opacity: 0,\n    ...offset,\n  };\n}\n\nfunction getSubmenuMotionOffset(placement: NavDockPlacement) {\n  switch (placement) {\n    case \"top\":\n      return { x: 0, y: -8 };\n    case \"left\":\n      return { x: -8, y: 0 };\n    case \"right\":\n      return { x: 8, y: 0 };\n    case \"bottom\":\n    default:\n      return { x: 0, y: 8 };\n  }\n}\n\nfunction getSubmenuClosedMotionState({\n  placement,\n  reducedMotion,\n}: {\n  placement: NavDockPlacement;\n  reducedMotion: boolean;\n}): TargetAndTransition {\n  const offset = reducedMotion\n    ? { x: 0, y: 0 }\n    : getSubmenuMotionOffset(placement);\n\n  return {\n    opacity: 0,\n    scale: reducedMotion ? 1 : 0.92,\n    ...offset,\n  };\n}\n\nfunction getSubmenuOpenMotionState(): TargetAndTransition {\n  return {\n    opacity: 1,\n    scale: 1,\n    x: 0,\n    y: 0,\n  };\n}\n\nfunction mergeRelForTarget(\n  rel: string | undefined,\n  target: AnchorHTMLAttributes<HTMLAnchorElement>[\"target\"] | undefined,\n) {\n  if (target !== \"_blank\") {\n    return rel;\n  }\n\n  const tokens = new Set((rel ?? \"\").split(/\\s+/).filter(Boolean));\n  tokens.add(\"noopener\");\n\n  return Array.from(tokens).join(\" \");\n}\n\nfunction getChildRef(child: ReactElement<NavDockLinkSlotProps>) {\n  return child.props.ref;\n}\n\nfunction getItemRoleCount(item: Record<string, unknown>) {\n  return [item.href, item.onAction, item.submenu].filter(\n    (value) => value !== undefined,\n  ).length;\n}\n\nfunction assertValidItemRole(item: NavDockItemData) {\n  if (getItemRoleCount(item as Record<string, unknown>) > 1) {\n    throw new Error(\n      \"NavDock item data must define only one of href, onAction, or submenu.\",\n    );\n  }\n}\n\nfunction getCollapsedContentClosedMotionState({\n  reducedMotion,\n}: {\n  reducedMotion: boolean;\n}): TargetAndTransition {\n  if (reducedMotion) {\n    return { opacity: 0 };\n  }\n\n  return { opacity: 0 };\n}\n\nfunction getCollapsedContentExitMotionState({\n  reducedMotion,\n}: {\n  reducedMotion: boolean;\n}): TargetAndTransition {\n  if (reducedMotion) {\n    return { opacity: 0 };\n  }\n\n  // Keep the list anchored above the trigger while the shell contracts.\n  return {\n    opacity: 0,\n    transition: navDockCollapsedContentExitTransition,\n  };\n}\n\nfunction getCollapsedContentOpenMotionState(): TargetAndTransition {\n  return { opacity: 1 };\n}\n\nfunction getItemCurrent(\n  item: NavDockItemData,\n  currentValue: string | undefined,\n  isItemCurrent: NavDockCurrentMatcher | undefined,\n): NavDockCurrent | undefined {\n  if (\"current\" in item && item.current !== undefined) {\n    return item.current;\n  }\n\n  const matched = isItemCurrent?.(item, { currentValue });\n\n  if (matched !== undefined) {\n    return matched;\n  }\n\n  return currentValue !== undefined && item.value === currentValue\n    ? true\n    : undefined;\n}\n\nfunction NavDockHoverTitle({\n  active,\n  anchorElement,\n  motion,\n  placement,\n  portalled,\n  reducedMotion,\n  title,\n}: {\n  active: boolean;\n  anchorElement?: HTMLElement | null;\n  motion: NavDockMotion;\n  placement: NavDockPlacement;\n  portalled: boolean;\n  reducedMotion: boolean;\n  title: ReactNode;\n}) {\n  const portalTarget = portalled ? getPortalTarget() : null;\n  const portalledStyle = useAnchoredLayerStyle({\n    anchorElement,\n    fallbackOffset: 8,\n    open: active && portalled,\n    placement,\n    variableName: \"--dt-space-2\",\n  });\n  const shouldPortal = Boolean(portalled && portalTarget);\n  const titleNode = (\n    <motionElement.span\n      aria-hidden=\"true\"\n      key=\"navdock-hover-title\"\n      data-slot=\"navdock-hover-title\"\n      data-placement={placement}\n      data-portalled={shouldPortal ? \"true\" : undefined}\n      data-reduced-motion={reducedMotion ? \"true\" : undefined}\n      initial={\n        shouldPortal\n          ? { opacity: 0 }\n          : getTitleMotionState({ placement, reducedMotion })\n      }\n      animate={shouldPortal ? { opacity: 1 } : { opacity: 1, x: 0, y: 0 }}\n      exit={\n        shouldPortal\n          ? { opacity: 0 }\n          : getTitleMotionState({ placement, reducedMotion })\n      }\n      transition={\n        reducedMotion\n          ? navDockTitleTransitions.none\n          : navDockTitleTransitions[motion]\n      }\n      style={shouldPortal ? (portalledStyle ?? { left: 0, top: 0 }) : undefined}\n      className={cn(\n        navDockHoverTitleBaseClasses,\n        shouldPortal\n          ? navDockHoverTitlePortalledClasses\n          : navDockHoverTitlePlacementClasses[placement],\n      )}\n    >\n      {title}\n    </motionElement.span>\n  );\n\n  const titlePresence = (\n    <AnimatePresence initial={false}>\n      {active ? titleNode : null}\n    </AnimatePresence>\n  );\n\n  return shouldPortal && portalTarget\n    ? createPortal(titlePresence, portalTarget)\n    : titlePresence;\n}\n\nfunction NavDockItemIcon({\n  disabled,\n  icon,\n  motion,\n  motionState,\n  placement,\n  reducedMotion,\n}: {\n  disabled: boolean;\n  icon: ReactNode;\n  motion: NavDockMotion;\n  motionState: NavDockMotionState;\n  placement: NavDockPlacement;\n  reducedMotion: boolean;\n}) {\n  const listContext = useNavDockListContext();\n  const iconRef = useRef<HTMLSpanElement | null>(null);\n  const anchorRef = useRef<HTMLElement | null>(null);\n  const localPointerPosition = useMotionValue(navDockPointerIdle);\n  const pointerPosition = listContext?.pointerPosition ?? localPointerPosition;\n  const focusMagnify = useMotionValue(motionState === \"active\" ? 1 : 0);\n  const pressTarget = useMotionValue(1);\n  const press = useSpring(pressTarget, navDockPressSpringOptions);\n  const horizontal = getNavDockOrientation(placement) === \"horizontal\";\n  const magnifyScale = navDockMagnifyScale[motion];\n  const scaleTarget = useTransform(\n    [pointerPosition, focusMagnify],\n    ([pointer, focus]: number[]) => {\n      if (reducedMotion || disabled || magnifyScale <= 1) {\n        return 1;\n      }\n\n      // No pointer over the dock: keyboard focus still magnifies the item.\n      if (!Number.isFinite(pointer)) {\n        return focus > 0 ? magnifyScale : 1;\n      }\n\n      const anchor = anchorRef.current ?? iconRef.current;\n\n      if (!anchor) {\n        return 1;\n      }\n\n      const bounds = anchor.getBoundingClientRect();\n      const center = horizontal\n        ? bounds.left + bounds.width / 2\n        : bounds.top + bounds.height / 2;\n      const radius = (horizontal ? bounds.width : bounds.height) * 2;\n\n      return getNavDockMagnifiedScale({\n        distance: Math.abs(pointer - center),\n        magnifyScale,\n        radius,\n      });\n    },\n  );\n  const magnify = useSpring(scaleTarget, navDockMagnifySpringOptions[motion]);\n  const scale = useTransform(\n    [magnify, press],\n    ([magnifyValue, pressValue]: number[]) => magnifyValue * pressValue,\n  );\n\n  // The pointer distance must be measured against a stationary box, so anchor\n  // to the interactive element rather than the scaling icon itself.\n  useIsomorphicLayoutEffect(() => {\n    const iconElement = iconRef.current;\n\n    anchorRef.current =\n      iconElement?.closest<HTMLElement>(\n        '[data-slot=\"navdock-link\"], [data-slot=\"navdock-button\"], [data-slot=\"navdock-submenu-trigger\"]',\n      ) ?? iconElement;\n  }, []);\n\n  useEffect(() => {\n    focusMagnify.set(motionState === \"active\" ? 1 : 0);\n  }, [focusMagnify, motionState]);\n\n  useEffect(() => {\n    const anchor = anchorRef.current;\n\n    if (!anchor || reducedMotion || disabled) {\n      pressTarget.set(1);\n      return undefined;\n    }\n\n    const handlePress = () => pressTarget.set(0.94);\n    const releasePress = () => pressTarget.set(1);\n\n    anchor.addEventListener(\"pointerdown\", handlePress);\n    window.addEventListener(\"pointerup\", releasePress);\n    window.addEventListener(\"pointercancel\", releasePress);\n\n    return () => {\n      anchor.removeEventListener(\"pointerdown\", handlePress);\n      window.removeEventListener(\"pointerup\", releasePress);\n      window.removeEventListener(\"pointercancel\", releasePress);\n    };\n  }, [disabled, pressTarget, reducedMotion]);\n\n  return (\n    <motionElement.span\n      ref={iconRef}\n      aria-hidden=\"true\"\n      data-slot=\"navdock-item-icon\"\n      data-motion-state={motionState}\n      data-reduced-motion={reducedMotion ? \"true\" : undefined}\n      style={{\n        scale: reducedMotion ? 1 : scale,\n        transformOrigin: navDockMagnifyOriginByPlacement[placement],\n      }}\n      className={navDockIconClasses}\n    >\n      {icon}\n    </motionElement.span>\n  );\n}\n\nfunction getInteractiveContent({\n  active,\n  anchorElement,\n  badge,\n  children,\n  description,\n  disabled,\n  external,\n  icon,\n  motion,\n  motionState,\n  placement,\n  portalledLayer,\n  reducedMotion,\n  showTitle,\n  title,\n}: {\n  active: boolean;\n  anchorElement?: HTMLElement | null;\n  badge?: ReactNode;\n  children?: ReactNode;\n  description?: ReactNode;\n  disabled: boolean;\n  external?: boolean;\n  icon?: ReactNode;\n  motion: NavDockMotion;\n  motionState: NavDockMotionState;\n  placement: NavDockPlacement;\n  portalledLayer: boolean;\n  reducedMotion: boolean;\n  showTitle: NavDockShowTitle;\n  title?: ReactNode;\n}) {\n  if (children !== undefined) {\n    return children;\n  }\n\n  return (\n    <>\n      {icon !== undefined ? (\n        <NavDockItemIcon\n          disabled={disabled}\n          icon={icon}\n          motion={motion}\n          motionState={motionState}\n          placement={placement}\n          reducedMotion={reducedMotion}\n        />\n      ) : null}\n      {title !== undefined ? (\n        <>\n          <span\n            data-slot=\"navdock-item-title\"\n            data-motion-state={motionState}\n            data-reduced-motion={reducedMotion ? \"true\" : undefined}\n            className={navDockTitleClassNames({ showTitle })}\n          >\n            {title}\n          </span>\n          {showTitle === \"hover\" ? (\n            <NavDockHoverTitle\n              active={active}\n              anchorElement={anchorElement}\n              motion={motion}\n              placement={placement}\n              portalled={portalledLayer}\n              reducedMotion={reducedMotion}\n              title={title}\n            />\n          ) : null}\n        </>\n      ) : null}\n      {description !== undefined ? (\n        <span className=\"sr-only\"> {description}</span>\n      ) : null}\n      {badge !== undefined ? (\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"navdock-item-badge\"\n          className={navDockBadgeClasses}\n        >\n          {badge}\n        </span>\n      ) : null}\n      {external ? (\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"navdock-external-indicator\"\n          className={navDockExternalIndicatorClasses}\n        >\n          ext\n        </span>\n      ) : null}\n    </>\n  );\n}\n\nfunction getDescribedBy(\n  providedDescribedBy: string | undefined,\n  generatedId: string | undefined,\n) {\n  if (!generatedId) {\n    return providedDescribedBy;\n  }\n\n  return [providedDescribedBy, generatedId].filter(Boolean).join(\" \");\n}\n\nfunction DisabledReason({\n  id,\n  reason,\n}: {\n  id: string | undefined;\n  reason: ReactNode;\n}) {\n  if (!id) {\n    return null;\n  }\n\n  return (\n    <span id={id} className=\"sr-only\">\n      {reason}\n    </span>\n  );\n}\n\nfunction DefaultNavDockTriggerIcon() {\n  return (\n    <svg aria-hidden=\"true\" fill=\"none\" viewBox=\"0 0 24 24\">\n      <path\n        d=\"M5.75 7.25h4.5v4.5h-4.5zM13.75 7.25h4.5v4.5h-4.5zM5.75 15.25h4.5v1.5h-4.5zM13.75 15.25h4.5v1.5h-4.5z\"\n        stroke=\"currentColor\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"1.8\"\n      />\n    </svg>\n  );\n}\n\nexport const CollapseDock = forwardRef<HTMLDivElement, CollapseDockProps>(\n  (\n    {\n      children,\n      className,\n      collapseLabel = \"Close navigation dock\",\n      collapseMode: _collapseMode,\n      collapsed: _collapsed,\n      defaultCollapsed: _defaultCollapsed,\n      items,\n      mode: _mode,\n      onCollapsedChange: _onCollapsedChange,\n      style,\n      triggerIcon,\n      triggerLabel = \"Open navigation dock\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const prefersReducedMotion = useReducedMotion();\n    const reducedMotion = shouldReduceNavDockMotion(\n      context.motion,\n      prefersReducedMotion,\n    );\n    const [collapsedShellRef, collapsedShellHeight] = useCollapsedShellHeight({\n      motion: context.motion,\n      open: context.collapseModeActive && !context.collapsed,\n      reducedMotion,\n    });\n    const collapseDockContext = useMemo<NavDockContextValue>(\n      () => ({\n        ...context,\n        showTitle: \"never\",\n      }),\n      [context],\n    );\n    const dockContent = items ? (\n      <NavDockList key=\"collapse-dock-list\">\n        {items.map((item) =>\n          renderNavDockItemData(item, {\n            current: getItemCurrent(\n              item,\n              context.currentValue,\n              context.isItemCurrent,\n            ),\n          }),\n        )}\n      </NavDockList>\n    ) : (\n      children\n    );\n    const triggerAccessibleLabel = context.collapsed\n      ? triggerLabel\n      : collapseLabel;\n    const renderedTriggerIcon = triggerIcon ?? <DefaultNavDockTriggerIcon />;\n    const handleCollapseTriggerClick: MouseEventHandler<\n      HTMLButtonElement\n    > = () => {\n      const nextCollapsed = !context.collapsed;\n\n      context.setCollapsed(nextCollapsed);\n\n      if (nextCollapsed) {\n        context.setOpenValue(null);\n      }\n    };\n\n    if (!context.collapseModeActive) {\n      return (\n        <NavDockContext.Provider value={collapseDockContext}>\n          {dockContent}\n        </NavDockContext.Provider>\n      );\n    }\n\n    return (\n      <NavDockContext.Provider value={collapseDockContext}>\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"navdock-collapse-placeholder\"\n          className={navDockCollapsedPlaceholderClasses}\n        />\n        <motionElement.div\n          {...props}\n          ref={composeRefs(ref, collapsedShellRef)}\n          data-slot=\"navdock-collapsed-shell\"\n          data-placement={context.placement}\n          data-position={context.position}\n          data-reduced-motion={reducedMotion ? \"true\" : undefined}\n          data-size={context.size}\n          data-state={context.collapsed ? \"closed\" : \"open\"}\n          data-variant={context.variant}\n          initial={false}\n          style={{ ...style, height: collapsedShellHeight.height }}\n          className={navDockCollapsedShellClassNames({\n            variant: context.variant,\n            className,\n          })}\n        >\n          <AnimatePresence initial={false}>\n            {!context.collapsed ? (\n              <motionElement.div\n                key=\"navdock-collapsed-content\"\n                data-slot=\"navdock-collapsed-content\"\n                data-placement={context.placement}\n                data-state=\"open\"\n                data-reduced-motion={reducedMotion ? \"true\" : undefined}\n                initial={getCollapsedContentClosedMotionState({\n                  reducedMotion,\n                })}\n                animate={getCollapsedContentOpenMotionState()}\n                exit={getCollapsedContentExitMotionState({\n                  reducedMotion,\n                })}\n                transition={\n                  reducedMotion\n                    ? navDockMotionTransitions.none\n                    : navDockCollapsedContentTransitions[context.motion]\n                }\n                className={navDockCollapsedContentClasses}\n              >\n                {dockContent}\n              </motionElement.div>\n            ) : null}\n          </AnimatePresence>\n          <motionElement.button\n            ref={(node) => {\n              setRef(context.collapseTriggerRef, node);\n            }}\n            type=\"button\"\n            aria-controls={context.renderedListId}\n            aria-expanded={!context.collapsed}\n            data-slot=\"navdock-collapse-trigger\"\n            data-placement={context.placement}\n            data-position={context.position}\n            data-reduced-motion={reducedMotion ? \"true\" : undefined}\n            data-size={context.size}\n            data-state={context.collapsed ? \"closed\" : \"open\"}\n            data-variant={context.variant}\n            className={navDockCollapseTriggerClassNames({\n              placement: context.placement,\n            })}\n            initial={false}\n            whileTap={getPressMotionTarget({\n              disabled: false,\n              reducedMotion,\n            })}\n            transition={\n              reducedMotion\n                ? navDockMotionTransitions.none\n                : navDockMotionTransitions[context.motion]\n            }\n            onClick={handleCollapseTriggerClick}\n          >\n            <span\n              aria-hidden=\"true\"\n              data-slot=\"navdock-collapse-trigger-icon\"\n              className={navDockCollapseTriggerIconClasses}\n            >\n              {renderedTriggerIcon}\n            </span>\n            <span className=\"sr-only\">{triggerAccessibleLabel}</span>\n          </motionElement.button>\n        </motionElement.div>\n      </NavDockContext.Provider>\n    );\n  },\n);\n\nCollapseDock.displayName = \"CollapseDock\";\n\nfunction isCollapseDockElement(\n  child: ReactNode,\n): child is ReactElement<CollapseDockProps> {\n  return (\n    isValidElement<CollapseDockProps>(child) && child.type === CollapseDock\n  );\n}\n\nfunction getCollapseDockElement(\n  children: ReactNode,\n): ReactElement<CollapseDockProps> | null {\n  let collapseDockElement: ReactElement<CollapseDockProps> | null = null;\n\n  Children.forEach(children, (child) => {\n    if (!collapseDockElement && isCollapseDockElement(child)) {\n      collapseDockElement = child;\n    }\n  });\n\n  return collapseDockElement;\n}\n\nexport const NavDock = forwardRef<HTMLElement, NavDockProps>(\n  (\n    {\n      \"aria-label\": ariaLabel,\n      \"aria-labelledby\": ariaLabelledBy,\n      children,\n      className,\n      collapseLabel = \"Close navigation dock\",\n      collapseMode = \"auto\",\n      collapsed,\n      currentValue,\n      defaultCollapsed,\n      defaultOpenValue = null,\n      defaultValue = null,\n      isItemCurrent,\n      items,\n      motion = \"standard\",\n      onCollapsedChange,\n      onKeyDown,\n      onOpenValueChange,\n      onValueChange,\n      openValue,\n      placement = \"bottom\",\n      position = \"static\",\n      showTitle = \"hover\",\n      size = \"md\",\n      triggerIcon,\n      triggerLabel = \"Open navigation dock\",\n      value,\n      variant = \"default\",\n      ...props\n    },\n    ref,\n  ) => {\n    const collapseDockElement = items ? null : getCollapseDockElement(children);\n    const collapseDockProps = collapseDockElement?.props;\n    const resolvedCollapseMode =\n      collapseDockProps?.collapseMode ??\n      collapseDockProps?.mode ??\n      (collapseDockElement ? \"always\" : collapseMode);\n    const resolvedCollapsed = collapseDockProps?.collapsed ?? collapsed;\n    const resolvedDefaultCollapsed =\n      collapseDockProps?.defaultCollapsed ?? defaultCollapsed;\n    const resolvedOnCollapsedChange =\n      collapseDockProps?.onCollapsedChange ?? onCollapsedChange;\n    const [activeValue, setActiveValue] = useControllableValue({\n      defaultValue,\n      onValueChange,\n      value,\n    });\n    const [currentOpenValue, setOpenValue] = useControllableValue({\n      defaultValue: defaultOpenValue,\n      onValueChange: onOpenValueChange,\n      value: openValue,\n    });\n    const autoCollapseActive = useAutoCollapseActive(resolvedCollapseMode);\n    const collapseModeActive =\n      resolvedCollapseMode === \"always\" ||\n      (resolvedCollapseMode === \"auto\" && autoCollapseActive);\n    const [currentCollapsed, setCollapsed, isCollapsedControlled] =\n      useControllableBoolean({\n        defaultValue:\n          resolvedDefaultCollapsed ?? resolvedCollapseMode === \"always\",\n        onValueChange: resolvedOnCollapsedChange,\n        value: resolvedCollapsed,\n      });\n    const isCollapsed = collapseModeActive && currentCollapsed;\n    const anchorPlacement = collapseModeActive\n      ? NavDockCollapsedAnchorPlacement\n      : placement;\n    const layoutPlacement = collapseModeActive\n      ? NavDockCollapsedLayoutPlacement\n      : placement;\n    const rootRef = useRef<HTMLElement | null>(null);\n    const collapseTriggerRef = useRef<HTMLButtonElement | null>(null);\n    const rootId = useId();\n    const listId = useId();\n    const [renderedListId, setRenderedListId] = useState(listId);\n    const prefersReducedMotion = useReducedMotion();\n    const reducedMotion = shouldReduceNavDockMotion(\n      motion,\n      prefersReducedMotion,\n    );\n    const [collapsedShellRef, collapsedShellHeight] = useCollapsedShellHeight({\n      motion,\n      open: collapseModeActive && !collapseDockElement && !isCollapsed,\n      reducedMotion,\n    });\n    const [registeredItemValues, setRegisteredItemValues] = useState<string[]>(\n      [],\n    );\n    const dataItemValues = useMemo(\n      () => items?.map((item) => item.value) ?? [],\n      [items],\n    );\n    const itemValues = items ? dataItemValues : registeredItemValues;\n    const registerListId = useCallback(\n      (renderedId: string) => {\n        setRenderedListId(renderedId);\n\n        return () => {\n          setRenderedListId((currentRenderedId) =>\n            currentRenderedId === renderedId ? listId : currentRenderedId,\n          );\n        };\n      },\n      [listId],\n    );\n    const registerItemValue = useCallback((itemValue: string) => {\n      setRegisteredItemValues((values) =>\n        values.includes(itemValue) ? values : [...values, itemValue],\n      );\n\n      return () => {\n        setRegisteredItemValues((values) =>\n          values.filter((value) => value !== itemValue),\n        );\n      };\n    }, []);\n    const context = useMemo<NavDockContextValue>(\n      () => ({\n        activeValue,\n        collapsed: isCollapsed,\n        collapseMode: resolvedCollapseMode,\n        collapseModeActive,\n        collapseTriggerRef,\n        currentValue,\n        isItemCurrent,\n        itemValues,\n        listId,\n        motion,\n        openValue: currentOpenValue,\n        placement: layoutPlacement,\n        position,\n        registerListId,\n        registerItemValue: items ? undefined : registerItemValue,\n        renderedListId,\n        rootId,\n        setActiveValue,\n        setCollapsed,\n        setOpenValue,\n        showTitle,\n        size,\n        variant,\n      }),\n      [\n        activeValue,\n        collapseModeActive,\n        currentValue,\n        currentOpenValue,\n        isCollapsed,\n        isItemCurrent,\n        itemValues,\n        items,\n        layoutPlacement,\n        listId,\n        motion,\n        position,\n        registerListId,\n        registerItemValue,\n        renderedListId,\n        resolvedCollapseMode,\n        rootId,\n        setActiveValue,\n        setCollapsed,\n        setOpenValue,\n        showTitle,\n        size,\n        variant,\n      ],\n    );\n    const orientation = getNavDockOrientation(layoutPlacement);\n    const overflowAxis = getNavDockOverflowAxis(layoutPlacement);\n    useEffect(() => {\n      if (isCollapsedControlled || resolvedDefaultCollapsed !== undefined) {\n        return;\n      }\n\n      if (resolvedCollapseMode === \"none\") {\n        setCollapsed(false);\n      } else if (resolvedCollapseMode === \"always\") {\n        setCollapsed(true);\n      } else {\n        setCollapsed(autoCollapseActive);\n      }\n    }, [\n      autoCollapseActive,\n      resolvedCollapseMode,\n      resolvedDefaultCollapsed,\n      isCollapsedControlled,\n      setCollapsed,\n    ]);\n    useEffect(() => {\n      if (currentOpenValue === null) {\n        return undefined;\n      }\n\n      const handleDocumentPointerDown = (event: PointerEvent) => {\n        const root = rootRef.current;\n        const targetElement =\n          event.target instanceof Element ? event.target : null;\n        const submenuContent = targetElement?.closest(\n          '[data-slot=\"navdock-submenu-content\"]',\n        );\n\n        if (\n          root &&\n          event.target instanceof Node &&\n          !root.contains(event.target) &&\n          submenuContent?.getAttribute(\"data-navdock-root\") !== rootId\n        ) {\n          setOpenValue(null);\n        }\n      };\n\n      document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n\n      return () => {\n        document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n      };\n    }, [currentOpenValue, rootId, setOpenValue]);\n    useEffect(() => {\n      if (!collapseModeActive || isCollapsed) {\n        return undefined;\n      }\n\n      const handleDocumentPointerDown = (event: PointerEvent) => {\n        const root = rootRef.current;\n        const targetElement =\n          event.target instanceof Element ? event.target : null;\n        const submenuContent = targetElement?.closest(\n          '[data-slot=\"navdock-submenu-content\"]',\n        );\n\n        if (\n          root &&\n          event.target instanceof Node &&\n          !root.contains(event.target) &&\n          submenuContent?.getAttribute(\"data-navdock-root\") !== rootId\n        ) {\n          setCollapsed(true);\n          setOpenValue(null);\n        }\n      };\n\n      document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n\n      return () => {\n        document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n      };\n    }, [collapseModeActive, isCollapsed, rootId, setCollapsed, setOpenValue]);\n    const handleKeyDown: KeyboardEventHandler<HTMLElement> = (event) => {\n      onKeyDown?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      if (event.key === \"Escape\" && currentOpenValue !== null) {\n        setOpenValue(null);\n        event.preventDefault();\n      } else if (event.key === \"Escape\" && collapseModeActive && !isCollapsed) {\n        setCollapsed(true);\n        collapseTriggerRef.current?.focus();\n        event.preventDefault();\n      }\n    };\n    const handleCollapseTriggerClick: MouseEventHandler<\n      HTMLButtonElement\n    > = () => {\n      const nextCollapsed = !isCollapsed;\n\n      setCollapsed(nextCollapsed);\n\n      if (nextCollapsed) {\n        setOpenValue(null);\n      }\n    };\n    const navLabelProps =\n      ariaLabelledBy !== undefined\n        ? { \"aria-labelledby\": ariaLabelledBy }\n        : { \"aria-label\": ariaLabel ?? \"Navigation dock\" };\n    const collapsedDockContext = useMemo<NavDockContextValue>(\n      () => ({\n        ...context,\n        showTitle: \"never\",\n      }),\n      [context],\n    );\n    const dockContent = items ? (\n      <NavDockList key=\"navdock-list\">\n        {items.map((item) =>\n          renderNavDockItemData(item, {\n            current: getItemCurrent(item, currentValue, isItemCurrent),\n          }),\n        )}\n      </NavDockList>\n    ) : (\n      children\n    );\n    const triggerAccessibleLabel = isCollapsed ? triggerLabel : collapseLabel;\n    const renderedTriggerIcon = triggerIcon ?? <DefaultNavDockTriggerIcon />;\n    const renderedDockContent =\n      collapseModeActive && !collapseDockElement ? (\n        <>\n          <span\n            aria-hidden=\"true\"\n            data-slot=\"navdock-collapse-placeholder\"\n            className={navDockCollapsedPlaceholderClasses}\n          />\n          <motionElement.div\n            ref={collapsedShellRef}\n            data-slot=\"navdock-collapsed-shell\"\n            data-placement={layoutPlacement}\n            data-position={position}\n            data-reduced-motion={reducedMotion ? \"true\" : undefined}\n            data-size={size}\n            data-state={isCollapsed ? \"closed\" : \"open\"}\n            data-variant={variant}\n            initial={false}\n            style={{ height: collapsedShellHeight.height }}\n            className={navDockCollapsedShellClassNames({ variant })}\n          >\n            <AnimatePresence initial={false}>\n              {!isCollapsed ? (\n                <motionElement.div\n                  key=\"navdock-collapsed-content\"\n                  data-slot=\"navdock-collapsed-content\"\n                  data-placement={layoutPlacement}\n                  data-state=\"open\"\n                  data-reduced-motion={reducedMotion ? \"true\" : undefined}\n                  initial={getCollapsedContentClosedMotionState({\n                    reducedMotion,\n                  })}\n                  animate={getCollapsedContentOpenMotionState()}\n                  exit={getCollapsedContentExitMotionState({\n                    reducedMotion,\n                  })}\n                  transition={\n                    reducedMotion\n                      ? navDockMotionTransitions.none\n                      : navDockCollapsedContentTransitions[motion]\n                  }\n                  className={navDockCollapsedContentClasses}\n                >\n                  <NavDockContext.Provider value={collapsedDockContext}>\n                    {dockContent}\n                  </NavDockContext.Provider>\n                </motionElement.div>\n              ) : null}\n            </AnimatePresence>\n            <motionElement.button\n              ref={collapseTriggerRef}\n              type=\"button\"\n              aria-controls={renderedListId}\n              aria-expanded={!isCollapsed}\n              data-slot=\"navdock-collapse-trigger\"\n              data-placement={layoutPlacement}\n              data-position={position}\n              data-reduced-motion={reducedMotion ? \"true\" : undefined}\n              data-size={size}\n              data-state={isCollapsed ? \"closed\" : \"open\"}\n              data-variant={variant}\n              className={navDockCollapseTriggerClassNames({\n                placement: layoutPlacement,\n              })}\n              initial={false}\n              whileTap={getPressMotionTarget({\n                disabled: false,\n                reducedMotion,\n              })}\n              transition={\n                reducedMotion\n                  ? navDockMotionTransitions.none\n                  : navDockMotionTransitions[motion]\n              }\n              onClick={handleCollapseTriggerClick}\n            >\n              <span\n                aria-hidden=\"true\"\n                data-slot=\"navdock-collapse-trigger-icon\"\n                className={navDockCollapseTriggerIconClasses}\n              >\n                {renderedTriggerIcon}\n              </span>\n              <span className=\"sr-only\">{triggerAccessibleLabel}</span>\n            </motionElement.button>\n          </motionElement.div>\n        </>\n      ) : (\n        dockContent\n      );\n\n    return (\n      <MotionConfig reducedMotion={motion === \"none\" ? \"always\" : \"user\"}>\n        <NavDockContext.Provider value={context}>\n          {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Keyboard and pointer events delegate to the dock’s focusable links and buttons. */}\n          <nav\n            {...props}\n            {...navLabelProps}\n            ref={composeRefs(ref, rootRef)}\n            data-slot=\"navdock\"\n            data-navdock-root={rootId}\n            data-placement={placement}\n            data-anchor-placement={\n              collapseModeActive ? anchorPlacement : undefined\n            }\n            data-layout-placement={\n              collapseModeActive ? layoutPlacement : undefined\n            }\n            data-position={position}\n            data-variant={variant}\n            data-size={size}\n            data-orientation={orientation}\n            data-overflow-axis={overflowAxis}\n            data-motion={motion}\n            data-show-title={showTitle}\n            data-collapse-mode={resolvedCollapseMode}\n            data-collapse-active={collapseModeActive ? \"true\" : undefined}\n            data-collapsed={isCollapsed ? \"true\" : undefined}\n            data-value={activeValue ?? undefined}\n            data-open-value={currentOpenValue ?? undefined}\n            className={navDockClassNames({\n              placement: anchorPlacement,\n              position,\n              size,\n              variant,\n              className: cn(\n                className,\n                collapseModeActive\n                  ? cn(\n                      position === \"static\"\n                        ? navDockCollapsedStaticRootClasses\n                        : undefined,\n                      navDockCollapsedRootClasses,\n                    )\n                  : undefined,\n              ),\n            })}\n            onKeyDown={handleKeyDown}\n          >\n            {renderedDockContent}\n          </nav>\n        </NavDockContext.Provider>\n      </MotionConfig>\n    );\n  },\n);\n\nNavDock.displayName = \"NavDock\";\n\nexport const NavDockList = forwardRef<HTMLUListElement, NavDockListProps>(\n  (\n    {\n      className,\n      id,\n      onKeyDown,\n      onPointerLeave,\n      onPointerMove,\n      role = \"list\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const listRef = useRef<HTMLUListElement | null>(null);\n    const [overflowing, setOverflowing] = useState(false);\n    const renderedListId = id ?? context.listId;\n    const orientation = getNavDockOrientation(context.placement);\n    const overflowAxis = getNavDockOverflowAxis(context.placement);\n    const pointerPosition = useMotionValue(navDockPointerIdle);\n    const listContext = useMemo<NavDockListContextValue>(\n      () => ({ overflowing, pointerPosition }),\n      [overflowing, pointerPosition],\n    );\n    useEffect(() => {\n      const list = listRef.current;\n\n      if (!list) {\n        return undefined;\n      }\n\n      const measureOverflow = () => {\n        const nextOverflowing =\n          orientation === \"horizontal\"\n            ? list.scrollWidth > list.clientWidth + 1\n            : list.scrollHeight > list.clientHeight + 1;\n\n        setOverflowing(nextOverflowing);\n      };\n\n      measureOverflow();\n\n      if (typeof ResizeObserver !== \"undefined\") {\n        const observer = new ResizeObserver(measureOverflow);\n\n        observer.observe(list);\n\n        return () => {\n          observer.disconnect();\n        };\n      }\n\n      window.addEventListener(\"resize\", measureOverflow);\n\n      return () => {\n        window.removeEventListener(\"resize\", measureOverflow);\n      };\n    }, [context.itemValues.length, orientation]);\n    useIsomorphicLayoutEffect(\n      () => context.registerListId(renderedListId),\n      [context.registerListId, renderedListId],\n    );\n    const handleKeyDown: KeyboardEventHandler<HTMLUListElement> = (event) => {\n      onKeyDown?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      if (\n        event.target instanceof Element &&\n        event.target.closest('[data-slot=\"navdock-submenu-content\"]')\n      ) {\n        return;\n      }\n\n      let handled = false;\n\n      if (event.key === \"Home\") {\n        handled = focusNavDockItemAtIndex(event.currentTarget, 0);\n      } else if (event.key === \"End\") {\n        handled = focusNavDockItemAtIndex(\n          event.currentTarget,\n          getNavDockFocusableItems(event.currentTarget).length - 1,\n        );\n      } else if (orientation === \"horizontal\") {\n        const direction = getNavDockElementDirection(event.currentTarget);\n\n        if (event.key === \"ArrowRight\") {\n          handled = focusNavDockItemByOffset({\n            list: event.currentTarget,\n            offset: direction === \"rtl\" ? -1 : 1,\n            target: event.target,\n          });\n        } else if (event.key === \"ArrowLeft\") {\n          handled = focusNavDockItemByOffset({\n            list: event.currentTarget,\n            offset: direction === \"rtl\" ? 1 : -1,\n            target: event.target,\n          });\n        }\n      } else if (event.key === \"ArrowDown\") {\n        handled = focusNavDockItemByOffset({\n          list: event.currentTarget,\n          offset: 1,\n          target: event.target,\n        });\n      } else if (event.key === \"ArrowUp\") {\n        handled = focusNavDockItemByOffset({\n          list: event.currentTarget,\n          offset: -1,\n          target: event.target,\n        });\n      }\n\n      if (handled) {\n        event.preventDefault();\n      }\n    };\n    const handlePointerMove: PointerEventHandler<HTMLUListElement> = (\n      event,\n    ) => {\n      onPointerMove?.(event);\n\n      // Touch input has no hover; magnifying under a finger just obscures it.\n      if (event.pointerType !== \"touch\") {\n        pointerPosition.set(\n          orientation === \"horizontal\" ? event.clientX : event.clientY,\n        );\n      }\n    };\n    const handlePointerLeave: PointerEventHandler<HTMLUListElement> = (\n      event,\n    ) => {\n      onPointerLeave?.(event);\n      pointerPosition.set(navDockPointerIdle);\n    };\n\n    return (\n      <NavDockListContext.Provider value={listContext}>\n        {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Keyboard and pointer events delegate to the dock’s focusable links and buttons. */}\n        <ul\n          {...props}\n          ref={composeRefs(ref, listRef)}\n          id={renderedListId}\n          role={role}\n          data-slot=\"navdock-list\"\n          data-placement={context.placement}\n          data-position={context.position}\n          data-variant={context.variant}\n          data-size={context.size}\n          data-orientation={orientation}\n          data-overflow-axis={overflowAxis}\n          data-overflowing={overflowing ? \"true\" : undefined}\n          data-motion={context.motion}\n          className={navDockListClassNames({\n            placement: context.placement,\n            overflowing,\n            className: cn(\n              context.collapseModeActive && context.showTitle === \"never\"\n                ? navDockCollapsedListClasses\n                : undefined,\n              className,\n            ),\n          })}\n          onKeyDown={handleKeyDown}\n          onPointerLeave={handlePointerLeave}\n          onPointerMove={handlePointerMove}\n        />\n      </NavDockListContext.Provider>\n    );\n  },\n);\n\nNavDockList.displayName = \"NavDockList\";\n\nexport const NavDockSeparator = forwardRef<\n  HTMLLIElement,\n  NavDockSeparatorProps\n>(\n  (\n    {\n      \"aria-hidden\": ariaHidden = true,\n      className,\n      role = \"presentation\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const orientation =\n      context.placement === \"left\" || context.placement === \"right\"\n        ? \"horizontal\"\n        : \"vertical\";\n\n    return (\n      <li\n        {...props}\n        ref={ref}\n        aria-hidden={ariaHidden}\n        role={role}\n        data-slot=\"navdock-separator\"\n        data-orientation={orientation}\n        data-placement={context.placement}\n        className={navDockSeparatorClassNames({\n          placement: context.placement,\n          className,\n        })}\n      />\n    );\n  },\n);\n\nNavDockSeparator.displayName = \"NavDockSeparator\";\n\nexport const NavDockDivider = NavDockSeparator;\n\nexport const NavDockItem = forwardRef<HTMLLIElement, NavDockItemProps>(\n  (\n    {\n      children,\n      className,\n      disabled,\n      disabledReason,\n      icon,\n      onBlur,\n      onFocus,\n      onMouseEnter,\n      onMouseLeave,\n      title,\n      value,\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const isActive = value !== undefined && context.activeValue === value;\n    const motionState = getNavDockItemMotionState({\n      activeValue: context.activeValue,\n      itemValues: context.itemValues,\n      value,\n    });\n    const registerItemValue = context.registerItemValue;\n\n    const handleActivate = useCallback(() => {\n      if (value !== undefined && !disabled) {\n        context.setActiveValue(value);\n      }\n    }, [context, disabled, value]);\n    const handleDeactivate = useCallback(() => {\n      if (value !== undefined && context.activeValue === value) {\n        context.setActiveValue(null);\n      }\n    }, [context, value]);\n    const handleBlur: FocusEventHandler<HTMLLIElement> = (event) => {\n      if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n        handleDeactivate();\n      }\n    };\n    const handleFocus: FocusEventHandler<HTMLLIElement> = (event) => {\n      handleActivate();\n      scrollNavDockItemIntoView(event.currentTarget);\n    };\n    useEffect(() => {\n      if (value === undefined || registerItemValue === undefined) {\n        return undefined;\n      }\n\n      return registerItemValue(value);\n    }, [registerItemValue, value]);\n    const itemContext = useMemo<NavDockItemContextValue>(\n      () => ({ disabled, disabledReason, icon, motionState, title, value }),\n      [disabled, disabledReason, icon, motionState, title, value],\n    );\n\n    return (\n      <NavDockItemContext.Provider value={itemContext}>\n        <li\n          {...props}\n          ref={ref}\n          data-slot=\"navdock-item\"\n          data-value={value}\n          data-active={isActive ? \"true\" : undefined}\n          data-disabled={disabled ? \"true\" : undefined}\n          data-motion-state={motionState}\n          className={navDockItemClassNames({ className })}\n          onBlur={composeFocusHandlers(handleBlur, onBlur)}\n          onFocus={composeFocusHandlers(handleFocus, onFocus)}\n          onMouseEnter={(event) => {\n            handleActivate();\n            onMouseEnter?.(event);\n          }}\n          onMouseLeave={(event) => {\n            handleDeactivate();\n            onMouseLeave?.(event);\n          }}\n        >\n          {children}\n        </li>\n      </NavDockItemContext.Provider>\n    );\n  },\n);\n\nNavDockItem.displayName = \"NavDockItem\";\n\nexport const NavDockLink = forwardRef<HTMLAnchorElement, NavDockLinkProps>(\n  (\n    {\n      \"aria-current\": ariaCurrent,\n      \"aria-describedby\": ariaDescribedBy,\n      asChild = false,\n      badge,\n      children,\n      className,\n      current,\n      description,\n      disabled,\n      disabledReason,\n      external = false,\n      href,\n      icon,\n      onClick,\n      rel,\n      style,\n      target,\n      title,\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const item = useNavDockItemContext();\n    const listContext = useNavDockListContext();\n    const [anchorElement, setAnchorElement] = useState<HTMLElement | null>(\n      null,\n    );\n    const interactiveRef = useCallback(\n      (node: HTMLElement | null) => setAnchorElement(node),\n      [],\n    );\n    const prefersReducedMotion = useReducedMotion();\n    const resolvedDisabled = disabled ?? item?.disabled ?? false;\n    const reducedMotion = shouldReduceNavDockMotion(\n      context.motion,\n      prefersReducedMotion,\n    );\n    const resolvedDisabledReason = disabledReason ?? item?.disabledReason;\n    const disabledReasonId = useId();\n    const resolvedDisabledReasonId =\n      resolvedDisabled && resolvedDisabledReason !== undefined\n        ? disabledReasonId\n        : undefined;\n    const resolvedTitle = title ?? item?.title;\n    const resolvedIcon = icon ?? item?.icon;\n    const resolvedCurrent =\n      current ??\n      (item?.value !== undefined && context.currentValue === item.value\n        ? true\n        : undefined);\n    const resolvedAriaCurrent = resolveAriaCurrent(\n      ariaCurrent,\n      resolvedCurrent,\n    );\n    const isCurrent = hasCurrentState(resolvedAriaCurrent);\n    const isActive =\n      item?.value !== undefined && context.activeValue === item.value;\n    const motionState = item?.motionState ?? \"idle\";\n    const resolvedTarget = target ?? (external ? \"_blank\" : undefined);\n    const resolvedRel = mergeRelForTarget(\n      rel ?? (external ? \"noreferrer\" : undefined),\n      resolvedTarget,\n    );\n    const classes = navDockLinkClassNames({\n      placement: context.placement,\n      className,\n    });\n    const handleClick: MouseEventHandler<HTMLElement> = (event) => {\n      if (resolvedDisabled) {\n        event.preventDefault();\n        return;\n      }\n\n      onClick?.(event as React.MouseEvent<HTMLAnchorElement>);\n    };\n    const content = getInteractiveContent({\n      active: isActive,\n      anchorElement,\n      badge,\n      children: asChild ? undefined : children,\n      description,\n      disabled: resolvedDisabled,\n      external,\n      icon: resolvedIcon,\n      motion: context.motion,\n      motionState,\n      placement: context.placement,\n      portalledLayer: listContext?.overflowing ?? false,\n      reducedMotion,\n      showTitle: context.showTitle,\n      title: resolvedTitle,\n    });\n\n    if (asChild) {\n      const child = Children.only(children);\n\n      if (!isValidElement<NavDockLinkSlotProps>(child)) {\n        throw new Error(\n          \"NavDockLink with asChild expects a single React element child.\",\n        );\n      }\n\n      const childTarget = child.props.target ?? resolvedTarget;\n      const childRel = mergeRelForTarget(\n        child.props.rel ?? resolvedRel,\n        childTarget,\n      );\n      const childAriaCurrent =\n        child.props[\"aria-current\"] ?? resolvedAriaCurrent;\n      const childDescribedBy = getDescribedBy(\n        child.props[\"aria-describedby\"] ?? ariaDescribedBy,\n        resolvedDisabledReasonId,\n      );\n      const clonedProps: NavDockLinkSlotProps = {\n        ...props,\n        ...child.props,\n        ref: (node) => {\n          composeRefs(\n            ref as Ref<HTMLElement>,\n            getChildRef(child),\n            interactiveRef,\n          )(node);\n        },\n        \"aria-current\": childAriaCurrent,\n        \"aria-describedby\": childDescribedBy,\n        \"aria-disabled\": resolvedDisabled ? true : child.props[\"aria-disabled\"],\n        className: cn(classes, child.props.className),\n        \"data-active\": isActive ? \"true\" : undefined,\n        \"data-current\": hasCurrentState(childAriaCurrent) ? \"true\" : undefined,\n        \"data-disabled\": resolvedDisabled ? \"true\" : undefined,\n        \"data-external\": external ? \"true\" : undefined,\n        \"data-motion\": context.motion,\n        \"data-motion-state\": motionState,\n        \"data-placement\": context.placement,\n        \"data-reduced-motion\": reducedMotion ? \"true\" : undefined,\n        \"data-size\": context.size,\n        \"data-slot\": \"navdock-link\",\n        \"data-variant\": context.variant,\n        onClick: composeClickHandlers(handleClick, child.props.onClick),\n        tabIndex: resolvedDisabled ? -1 : child.props.tabIndex,\n      };\n\n      if (child.props.href !== undefined || href !== undefined) {\n        clonedProps.href = child.props.href ?? href;\n      }\n\n      if (childTarget !== undefined) {\n        clonedProps.target = childTarget;\n      }\n\n      if (childRel !== undefined) {\n        clonedProps.rel = childRel;\n      }\n\n      return (\n        <>\n          {/* eslint-disable-next-line react-hooks/refs -- React forwards this ref during commit; createElement/cloneElement does not read ref.current. */}\n          {cloneElement(child, clonedProps, content)}\n          <DisabledReason\n            id={resolvedDisabledReasonId}\n            reason={resolvedDisabledReason}\n          />\n        </>\n      );\n    }\n\n    const nativeProps = props as NativeNavDockAnchorProps;\n\n    return (\n      <>\n        <motionElement.a\n          {...nativeProps}\n          ref={composeRefs(\n            ref as Ref<HTMLAnchorElement>,\n            interactiveRef as Ref<HTMLAnchorElement>,\n          )}\n          aria-current={resolvedAriaCurrent}\n          aria-describedby={getDescribedBy(\n            ariaDescribedBy,\n            resolvedDisabledReasonId,\n          )}\n          aria-disabled={resolvedDisabled ? true : undefined}\n          data-slot=\"navdock-link\"\n          data-active={isActive ? \"true\" : undefined}\n          data-current={isCurrent ? \"true\" : undefined}\n          data-disabled={resolvedDisabled ? \"true\" : undefined}\n          data-external={external ? \"true\" : undefined}\n          data-motion={context.motion}\n          data-motion-state={motionState}\n          data-placement={context.placement}\n          data-reduced-motion={reducedMotion ? \"true\" : undefined}\n          data-size={context.size}\n          href={href}\n          rel={resolvedRel}\n          tabIndex={resolvedDisabled ? -1 : nativeProps.tabIndex}\n          target={resolvedTarget}\n          data-variant={context.variant}\n          style={style}\n          className={classes}\n          onClick={handleClick}\n        >\n          {content}\n        </motionElement.a>\n        <DisabledReason\n          id={resolvedDisabledReasonId}\n          reason={resolvedDisabledReason}\n        />\n      </>\n    );\n  },\n);\n\nNavDockLink.displayName = \"NavDockLink\";\n\nexport const NavDockButton = forwardRef<HTMLButtonElement, NavDockButtonProps>(\n  (\n    {\n      \"aria-current\": ariaCurrent,\n      \"aria-describedby\": ariaDescribedBy,\n      badge,\n      children,\n      className,\n      current,\n      description,\n      disabled,\n      disabledReason,\n      icon,\n      onAction,\n      onClick,\n      style,\n      title,\n      type = \"button\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const item = useNavDockItemContext();\n    const listContext = useNavDockListContext();\n    const [anchorElement, setAnchorElement] =\n      useState<HTMLButtonElement | null>(null);\n    const interactiveRef = useCallback(\n      (node: HTMLButtonElement | null) => setAnchorElement(node),\n      [],\n    );\n    const prefersReducedMotion = useReducedMotion();\n    const resolvedDisabled = disabled ?? item?.disabled ?? false;\n    const reducedMotion = shouldReduceNavDockMotion(\n      context.motion,\n      prefersReducedMotion,\n    );\n    const resolvedDisabledReason = disabledReason ?? item?.disabledReason;\n    const disabledReasonId = useId();\n    const resolvedDisabledReasonId =\n      resolvedDisabled && resolvedDisabledReason !== undefined\n        ? disabledReasonId\n        : undefined;\n    const resolvedTitle = title ?? item?.title;\n    const resolvedIcon = icon ?? item?.icon;\n    const resolvedCurrent =\n      current ??\n      (item?.value !== undefined && context.currentValue === item.value\n        ? true\n        : undefined);\n    // Buttons switch local panels, not pages, so a plain `true` stays `\"true\"`.\n    const resolvedAriaCurrent =\n      ariaCurrent ??\n      (resolvedCurrent === true\n        ? \"true\"\n        : resolvedCurrent === \"page\" || resolvedCurrent === \"location\"\n          ? resolvedCurrent\n          : undefined);\n    const isCurrent = hasCurrentState(resolvedAriaCurrent);\n    const isActive =\n      item?.value !== undefined && context.activeValue === item.value;\n    const motionState = item?.motionState ?? \"idle\";\n    const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n      if (resolvedDisabled) {\n        event.preventDefault();\n        return;\n      }\n\n      onClick?.(event);\n\n      if (!event.defaultPrevented) {\n        onAction?.();\n      }\n    };\n\n    return (\n      <>\n        <motionElement.button\n          {...props}\n          ref={composeRefs(ref, interactiveRef)}\n          type={type}\n          disabled={resolvedDisabled}\n          aria-current={resolvedAriaCurrent}\n          aria-describedby={getDescribedBy(\n            ariaDescribedBy,\n            resolvedDisabledReasonId,\n          )}\n          data-slot=\"navdock-button\"\n          data-active={isActive ? \"true\" : undefined}\n          data-current={isCurrent ? \"true\" : undefined}\n          data-disabled={resolvedDisabled ? \"true\" : undefined}\n          data-motion={context.motion}\n          data-motion-state={motionState}\n          data-placement={context.placement}\n          data-reduced-motion={reducedMotion ? \"true\" : undefined}\n          data-size={context.size}\n          data-variant={context.variant}\n          style={style}\n          className={navDockButtonClassNames({\n            placement: context.placement,\n            className,\n          })}\n          onClick={handleClick}\n        >\n          {getInteractiveContent({\n            active: isActive,\n            anchorElement,\n            badge,\n            children,\n            description,\n            disabled: resolvedDisabled,\n            icon: resolvedIcon,\n            motion: context.motion,\n            motionState,\n            placement: context.placement,\n            portalledLayer: listContext?.overflowing ?? false,\n            reducedMotion,\n            showTitle: context.showTitle,\n            title: resolvedTitle,\n          })}\n        </motionElement.button>\n        <DisabledReason\n          id={resolvedDisabledReasonId}\n          reason={resolvedDisabledReason}\n        />\n      </>\n    );\n  },\n);\n\nNavDockButton.displayName = \"NavDockButton\";\n\nexport const NavDockSubmenu = forwardRef<HTMLDivElement, NavDockSubmenuProps>(\n  (\n    {\n      children,\n      className,\n      onBlur,\n      onFocus,\n      onKeyDown,\n      onMouseEnter,\n      onMouseLeave,\n      onPointerDownCapture,\n      value,\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const item = useNavDockItemContext();\n    const submenuValue = value ?? item?.value;\n    const disabled = item?.disabled ?? false;\n    const contentId = useId();\n    const triggerId = useId();\n    const suppressFocusOpenRef = useRef(false);\n    const closeTimerRef = useRef<number | null>(null);\n    const hoverOpenClickGuardRef = useRef(false);\n    const hoverOpenClickGuardTimerRef = useRef<number | null>(null);\n    const [triggerElement, setTriggerElement] =\n      useState<HTMLButtonElement | null>(null);\n    const [contentElement, setContentElement] = useState<HTMLDivElement | null>(\n      null,\n    );\n    const open =\n      submenuValue !== undefined && context.openValue === submenuValue;\n    const setOpen = useCallback(\n      (nextOpen: boolean) => {\n        if (submenuValue === undefined || disabled) {\n          return;\n        }\n\n        context.setOpenValue(nextOpen ? submenuValue : null);\n      },\n      [context, disabled, submenuValue],\n    );\n    const cancelClose = useCallback(() => {\n      if (closeTimerRef.current !== null) {\n        window.clearTimeout(closeTimerRef.current);\n        closeTimerRef.current = null;\n      }\n    }, []);\n    const scheduleClose = useCallback(() => {\n      cancelClose();\n      closeTimerRef.current = window.setTimeout(() => {\n        closeTimerRef.current = null;\n        setOpen(false);\n      }, 180);\n    }, [cancelClose, setOpen]);\n    const clearHoverOpenClickGuard = useCallback(() => {\n      hoverOpenClickGuardRef.current = false;\n\n      if (hoverOpenClickGuardTimerRef.current !== null) {\n        window.clearTimeout(hoverOpenClickGuardTimerRef.current);\n        hoverOpenClickGuardTimerRef.current = null;\n      }\n    }, []);\n    const markHoverOpenClickGuard = useCallback(() => {\n      clearHoverOpenClickGuard();\n      hoverOpenClickGuardRef.current = true;\n      hoverOpenClickGuardTimerRef.current = window.setTimeout(() => {\n        hoverOpenClickGuardRef.current = false;\n        hoverOpenClickGuardTimerRef.current = null;\n      }, 300);\n    }, [clearHoverOpenClickGuard]);\n    const consumeHoverOpenClickGuard = useCallback(() => {\n      const shouldGuardClick = hoverOpenClickGuardRef.current;\n\n      clearHoverOpenClickGuard();\n\n      return shouldGuardClick;\n    }, [clearHoverOpenClickGuard]);\n    const submenuContext = useMemo<NavDockSubmenuContextValue>(\n      () => ({\n        cancelClose,\n        contentElement,\n        contentId,\n        consumeHoverOpenClickGuard,\n        open,\n        scheduleClose,\n        setContentElement,\n        setOpen,\n        setTriggerElement,\n        triggerElement,\n        triggerId,\n        value: submenuValue,\n      }),\n      [\n        cancelClose,\n        contentElement,\n        contentId,\n        consumeHoverOpenClickGuard,\n        open,\n        scheduleClose,\n        setOpen,\n        triggerElement,\n        triggerId,\n        submenuValue,\n      ],\n    );\n    useEffect(\n      () => () => {\n        cancelClose();\n        clearHoverOpenClickGuard();\n      },\n      [cancelClose, clearHoverOpenClickGuard],\n    );\n    const handleBlur: FocusEventHandler<HTMLDivElement> = (event) => {\n      onBlur?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      const nextFocused = event.relatedTarget as Node | null;\n\n      if (\n        !nextFocused ||\n        (!event.currentTarget.contains(nextFocused) &&\n          !contentElement?.contains(nextFocused))\n      ) {\n        setOpen(false);\n      }\n    };\n    const handleFocus: FocusEventHandler<HTMLDivElement> = (event) => {\n      cancelClose();\n\n      if (!suppressFocusOpenRef.current) {\n        setOpen(true);\n      }\n\n      onFocus?.(event);\n    };\n    const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {\n      onKeyDown?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      if (event.key === \"Escape\" && open) {\n        suppressFocusOpenRef.current = true;\n        setOpen(false);\n        triggerElement?.focus();\n        window.setTimeout(() => {\n          suppressFocusOpenRef.current = false;\n        }, 0);\n        event.preventDefault();\n      }\n    };\n\n    return (\n      <NavDockSubmenuContext.Provider value={submenuContext}>\n        {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- Keyboard and pointer events delegate to the dock’s focusable links and buttons. */}\n        <div\n          {...props}\n          ref={ref}\n          data-slot=\"navdock-submenu\"\n          data-state={open ? \"open\" : \"closed\"}\n          data-open={open ? \"true\" : undefined}\n          data-value={submenuValue}\n          className={navDockSubmenuClassNames({ className })}\n          onBlur={handleBlur}\n          onFocus={handleFocus}\n          onKeyDown={handleKeyDown}\n          onPointerDownCapture={(event) => {\n            suppressFocusOpenRef.current = true;\n            window.setTimeout(() => {\n              suppressFocusOpenRef.current = false;\n            }, 200);\n            onPointerDownCapture?.(event);\n          }}\n          onMouseEnter={(event) => {\n            const wasClosed = !open;\n\n            cancelClose();\n            setOpen(true);\n\n            if (wasClosed && !disabled) {\n              markHoverOpenClickGuard();\n            }\n\n            onMouseEnter?.(event);\n          }}\n          onMouseLeave={(event) => {\n            clearHoverOpenClickGuard();\n            scheduleClose();\n            onMouseLeave?.(event);\n          }}\n        >\n          {children}\n        </div>\n      </NavDockSubmenuContext.Provider>\n    );\n  },\n);\n\nNavDockSubmenu.displayName = \"NavDockSubmenu\";\n\nexport const NavDockSubmenuTrigger = forwardRef<\n  HTMLButtonElement,\n  NavDockSubmenuTriggerProps\n>(\n  (\n    {\n      \"aria-describedby\": ariaDescribedBy,\n      badge,\n      children,\n      className,\n      description,\n      disabled,\n      disabledReason,\n      icon,\n      id,\n      onClick,\n      onPointerDown,\n      style,\n      title,\n      type = \"button\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const item = useNavDockItemContext();\n    const listContext = useNavDockListContext();\n    const submenu = useNavDockSubmenuContext();\n    const [anchorElement, setAnchorElement] =\n      useState<HTMLButtonElement | null>(null);\n    const interactiveRef = useCallback(\n      (node: HTMLButtonElement | null) => setAnchorElement(node),\n      [],\n    );\n    const prefersReducedMotion = useReducedMotion();\n    const resolvedDisabled = disabled ?? item?.disabled ?? false;\n    const reducedMotion = shouldReduceNavDockMotion(\n      context.motion,\n      prefersReducedMotion,\n    );\n    const resolvedDisabledReason = disabledReason ?? item?.disabledReason;\n    const disabledReasonId = useId();\n    const resolvedDisabledReasonId =\n      resolvedDisabled && resolvedDisabledReason !== undefined\n        ? disabledReasonId\n        : undefined;\n    const resolvedTitle = title ?? item?.title;\n    const resolvedIcon = icon ?? item?.icon;\n    const isActive =\n      item?.value !== undefined && context.activeValue === item.value;\n    const motionState = item?.motionState ?? \"idle\";\n    const triggerId = id ?? submenu.triggerId;\n    const handlePointerDown: PointerEventHandler<HTMLButtonElement> = (\n      event,\n    ) => {\n      onPointerDown?.(event);\n    };\n    const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n      if (resolvedDisabled) {\n        event.preventDefault();\n        return;\n      }\n\n      onClick?.(event);\n\n      if (!event.defaultPrevented) {\n        if (submenu.open && submenu.consumeHoverOpenClickGuard()) {\n          submenu.setOpen(true);\n          return;\n        }\n\n        submenu.setOpen(!submenu.open);\n      }\n    };\n\n    return (\n      <>\n        <motionElement.button\n          {...props}\n          ref={composeRefs(ref, submenu.setTriggerElement, interactiveRef)}\n          id={triggerId}\n          type={type}\n          disabled={resolvedDisabled}\n          aria-controls={submenu.open ? submenu.contentId : undefined}\n          aria-describedby={getDescribedBy(\n            ariaDescribedBy,\n            resolvedDisabledReasonId,\n          )}\n          aria-expanded={submenu.open}\n          data-slot=\"navdock-submenu-trigger\"\n          data-active={isActive ? \"true\" : undefined}\n          data-disabled={resolvedDisabled ? \"true\" : undefined}\n          data-motion={context.motion}\n          data-motion-state={motionState}\n          data-placement={context.placement}\n          data-reduced-motion={reducedMotion ? \"true\" : undefined}\n          data-size={context.size}\n          data-state={submenu.open ? \"open\" : \"closed\"}\n          data-variant={context.variant}\n          style={style}\n          className={navDockSubmenuTriggerClassNames({\n            placement: context.placement,\n            className,\n          })}\n          onClick={handleClick}\n          onPointerDown={handlePointerDown}\n        >\n          {getInteractiveContent({\n            active: isActive,\n            anchorElement,\n            badge,\n            children,\n            description,\n            disabled: resolvedDisabled,\n            icon: resolvedIcon,\n            motion: context.motion,\n            motionState,\n            placement: context.placement,\n            portalledLayer: listContext?.overflowing ?? false,\n            reducedMotion,\n            showTitle: context.showTitle,\n            title: resolvedTitle,\n          })}\n        </motionElement.button>\n        <DisabledReason\n          id={resolvedDisabledReasonId}\n          reason={resolvedDisabledReason}\n        />\n      </>\n    );\n  },\n);\n\nNavDockSubmenuTrigger.displayName = \"NavDockSubmenuTrigger\";\n\nexport const NavDockSubmenuContent = forwardRef<\n  HTMLDivElement,\n  NavDockSubmenuContentProps\n>(\n  (\n    {\n      \"aria-labelledby\": ariaLabelledBy,\n      children,\n      className,\n      id,\n      onBlur,\n      onClick,\n      onMouseEnter,\n      onMouseLeave,\n      panelClassName,\n      role = \"group\",\n      ...props\n    },\n    ref,\n  ) => {\n    const context = useNavDockContext();\n    const listContext = useNavDockListContext();\n    const submenu = useNavDockSubmenuContext();\n    const prefersReducedMotion = useReducedMotion();\n    const reducedMotion = shouldReduceNavDockMotion(\n      context.motion,\n      prefersReducedMotion,\n    );\n    const portalled = Boolean(\n      listContext?.overflowing && submenu.triggerElement,\n    );\n    const portalTarget = portalled ? getPortalTarget() : null;\n    const portalledStyle = useAnchoredLayerStyle({\n      anchorElement: submenu.triggerElement,\n      fallbackOffset: 16,\n      open: submenu.open && portalled,\n      placement: context.placement,\n      variableName: \"--navdock-submenu-offset\",\n    });\n    const shouldPortal = Boolean(portalled && portalTarget);\n    const resolvedPortalledStyle = portalledStyle ?? { left: 0, top: 0 };\n    const handleClick: MouseEventHandler<HTMLDivElement> = (event) => {\n      onClick?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      const target = event.target;\n\n      if (!(target instanceof Element)) {\n        return;\n      }\n\n      const interactive = target.closest(\"a,button\");\n\n      if (interactive && event.currentTarget.contains(interactive)) {\n        submenu.setOpen(false);\n      }\n    };\n    const handleBlur: FocusEventHandler<HTMLDivElement> = (event) => {\n      onBlur?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      const nextFocused = event.relatedTarget as Node | null;\n\n      if (\n        !nextFocused ||\n        (!event.currentTarget.contains(nextFocused) &&\n          !submenu.triggerElement?.contains(nextFocused))\n      ) {\n        submenu.setOpen(false);\n      }\n    };\n    const handleMouseEnter: MouseEventHandler<HTMLDivElement> = (event) => {\n      submenu.cancelClose();\n      onMouseEnter?.(event);\n    };\n    const handleMouseLeave: MouseEventHandler<HTMLDivElement> = (event) => {\n      submenu.scheduleClose();\n      onMouseLeave?.(event);\n    };\n    const contentNode = (\n      <motionElement.div\n        {...props}\n        ref={composeRefs(ref, submenu.setContentElement)}\n        id={id ?? submenu.contentId}\n        role={role}\n        aria-labelledby={ariaLabelledBy ?? submenu.triggerId}\n        data-slot=\"navdock-submenu-content\"\n        data-navdock-root={context.rootId}\n        data-placement={context.placement}\n        data-portalled={shouldPortal ? \"true\" : undefined}\n        data-reduced-motion={reducedMotion ? \"true\" : undefined}\n        data-state=\"open\"\n        initial={\n          shouldPortal\n            ? { opacity: 0, scale: reducedMotion ? 1 : 0.96 }\n            : getSubmenuClosedMotionState({\n                placement: context.placement,\n                reducedMotion,\n              })\n        }\n        animate={\n          shouldPortal ? { opacity: 1, scale: 1 } : getSubmenuOpenMotionState()\n        }\n        exit={\n          shouldPortal\n            ? {\n                opacity: 0,\n                scale: reducedMotion ? 1 : 0.96,\n                transition: reducedMotion\n                  ? navDockSubmenuTransitions.none\n                  : navDockSubmenuExitTransition,\n              }\n            : {\n                ...getSubmenuClosedMotionState({\n                  placement: context.placement,\n                  reducedMotion,\n                }),\n                transition: reducedMotion\n                  ? navDockSubmenuTransitions.none\n                  : navDockSubmenuExitTransition,\n              }\n        }\n        transition={\n          reducedMotion\n            ? navDockSubmenuTransitions.none\n            : navDockSubmenuTransitions[context.motion]\n        }\n        style={shouldPortal ? resolvedPortalledStyle : undefined}\n        className={navDockSubmenuContentClassNames({\n          placement: context.placement,\n          portalled: shouldPortal,\n          className,\n        })}\n        onBlur={handleBlur}\n        onClick={handleClick}\n        onMouseEnter={handleMouseEnter}\n        onMouseLeave={handleMouseLeave}\n      >\n        <div\n          data-slot=\"navdock-submenu-panel\"\n          className={cn(navDockSubmenuPanelClasses, panelClassName)}\n        >\n          {children}\n        </div>\n      </motionElement.div>\n    );\n\n    const contentPresence = (\n      <AnimatePresence initial={false}>\n        {submenu.open ? contentNode : null}\n      </AnimatePresence>\n    );\n\n    return shouldPortal && portalTarget\n      ? createPortal(contentPresence, portalTarget)\n      : contentPresence;\n  },\n);\n\nNavDockSubmenuContent.displayName = \"NavDockSubmenuContent\";\n\nfunction renderSubmenuItemContent({\n  badge,\n  description,\n  external,\n  title,\n}: {\n  badge?: ReactNode;\n  description?: ReactNode;\n  external?: boolean;\n  title: ReactNode;\n}) {\n  return (\n    <>\n      <span\n        data-slot=\"navdock-submenu-item-text\"\n        className={navDockSubmenuItemTextClasses}\n      >\n        <span\n          data-slot=\"navdock-submenu-item-label\"\n          className={navDockSubmenuItemLabelClasses}\n        >\n          {title}\n        </span>\n        {description !== undefined ? (\n          <span\n            data-slot=\"navdock-submenu-item-description\"\n            className={navDockSubmenuItemDescriptionClasses}\n          >\n            {description}\n          </span>\n        ) : null}\n      </span>\n      {badge !== undefined ? (\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"navdock-submenu-item-badge\"\n          className={navDockSubmenuItemBadgeClasses}\n        >\n          {badge}\n        </span>\n      ) : external ? (\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"navdock-submenu-item-external\"\n          className={navDockSubmenuItemExternalClasses}\n        >\n          ext\n        </span>\n      ) : null}\n    </>\n  );\n}\n\nfunction renderNavDockSubmenuChildData(item: NavDockSubmenuChildData) {\n  if (item.kind === \"separator\") {\n    return (\n      <div\n        key={item.value}\n        aria-hidden=\"true\"\n        role=\"presentation\"\n        data-slot=\"navdock-submenu-separator\"\n        className={navDockSubmenuSeparatorClasses}\n      />\n    );\n  }\n\n  if (item.kind === \"label\") {\n    return (\n      <div\n        key={item.value}\n        data-slot=\"navdock-submenu-label\"\n        className={navDockSubmenuLabelClasses}\n      >\n        {item.title}\n      </div>\n    );\n  }\n\n  if (item.kind === \"action\") {\n    return (\n      <button\n        key={item.value}\n        type=\"button\"\n        disabled={item.disabled}\n        data-slot=\"navdock-submenu-action\"\n        data-disabled={item.disabled ? \"true\" : undefined}\n        className={navDockSubmenuItemClasses}\n        onClick={() => {\n          if (!item.disabled) {\n            item.onAction();\n          }\n        }}\n      >\n        {renderSubmenuItemContent({\n          badge: item.badge,\n          description: item.description ?? item.disabledReason,\n          title: item.title,\n        })}\n      </button>\n    );\n  }\n\n  const target = item.target ?? (item.external ? \"_blank\" : undefined);\n  const rel = mergeRelForTarget(\n    item.rel ?? (item.external ? \"noreferrer\" : undefined),\n    target,\n  );\n\n  return (\n    <a\n      key={item.value}\n      aria-current={item.ariaCurrent}\n      aria-disabled={item.disabled ? true : undefined}\n      data-slot=\"navdock-submenu-link\"\n      data-current={hasCurrentState(item.ariaCurrent) ? \"true\" : undefined}\n      data-disabled={item.disabled ? \"true\" : undefined}\n      data-external={item.external ? \"true\" : undefined}\n      href={item.href}\n      rel={rel}\n      tabIndex={item.disabled ? -1 : undefined}\n      target={target}\n      className={navDockSubmenuItemClasses}\n      onClick={(event) => {\n        if (item.disabled) {\n          event.preventDefault();\n        }\n      }}\n    >\n      {renderSubmenuItemContent({\n        badge: item.badge,\n        description: item.description ?? item.disabledReason,\n        external: item.external,\n        title: item.title,\n      })}\n    </a>\n  );\n}\n\nfunction renderNavDockItemData(\n  item: NavDockItemData,\n  { current }: { current?: NavDockCurrent },\n) {\n  assertValidItemRole(item);\n\n  if (\"href\" in item && item.href !== undefined) {\n    return (\n      <NavDockItem\n        key={item.value}\n        disabled={item.disabled}\n        disabledReason={item.disabledReason}\n        icon={item.icon}\n        title={item.title}\n        value={item.value}\n      >\n        <NavDockLink\n          aria-current={item.ariaCurrent}\n          badge={item.badge}\n          current={current}\n          description={item.description}\n          disabled={item.disabled}\n          disabledReason={item.disabledReason}\n          external={item.external}\n          href={item.href}\n          rel={item.rel}\n          target={item.target}\n        />\n      </NavDockItem>\n    );\n  }\n\n  if (\"onAction\" in item && item.onAction !== undefined) {\n    return (\n      <NavDockItem\n        key={item.value}\n        disabled={item.disabled}\n        disabledReason={item.disabledReason}\n        icon={item.icon}\n        title={item.title}\n        value={item.value}\n      >\n        <NavDockButton\n          badge={item.badge}\n          current={current}\n          description={item.description}\n          disabled={item.disabled}\n          disabledReason={item.disabledReason}\n          onAction={() => item.onAction(item)}\n        />\n      </NavDockItem>\n    );\n  }\n\n  return (\n    <NavDockItem\n      key={item.value}\n      disabled={item.disabled}\n      disabledReason={item.disabledReason}\n      icon={item.icon}\n      title={item.title}\n      value={item.value}\n    >\n      <NavDockSubmenu>\n        <NavDockSubmenuTrigger\n          badge={item.badge}\n          description={item.description}\n          disabled={item.disabled}\n          disabledReason={item.disabledReason}\n        />\n        <NavDockSubmenuContent>\n          {item.submenu.map(renderNavDockSubmenuChildData)}\n        </NavDockSubmenuContent>\n      </NavDockSubmenu>\n    </NavDockItem>\n  );\n}\n\nexport const __navDockTestUtils = {\n  getItemRoleCount,\n};\n"
    },
    {
      "path": "packages/components/src/components/navdock/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/navdock/index.ts",
      "content": "export {\n  CollapseDock,\n  NavDock,\n  NavDockButton,\n  NavDockDivider,\n  NavDockItem,\n  NavDockLink,\n  NavDockList,\n  NavDockSeparator,\n  NavDockSubmenu,\n  NavDockSubmenuContent,\n  NavDockSubmenuTrigger,\n  __navDockTestUtils,\n  navDockButtonClassNames,\n  navDockClassNames,\n  navDockItemClassNames,\n  navDockLinkClassNames,\n  navDockListClassNames,\n  navDockSeparatorClassNames,\n  navDockSubmenuClassNames,\n  navDockSubmenuContentClassNames,\n  navDockSubmenuTriggerClassNames,\n  navDockTitleClassNames,\n  type CollapseDockProps,\n  type NavDockActionItemData,\n  type NavDockButtonProps,\n  type NavDockCollapseMode,\n  type NavDockCurrent,\n  type NavDockCurrentContext,\n  type NavDockCurrentMatcher,\n  type NavDockItemData,\n  type NavDockItemProps,\n  type NavDockLinkItemData,\n  type NavDockLinkProps,\n  type NavDockListProps,\n  type NavDockMotion,\n  type NavDockPlacement,\n  type NavDockPosition,\n  type NavDockProps,\n  type NavDockSeparatorProps,\n  type NavDockShowTitle,\n  type NavDockSize,\n  type NavDockSubmenuChildData,\n  type NavDockSubmenuContentProps,\n  type NavDockSubmenuItemData,\n  type NavDockSubmenuProps,\n  type NavDockSubmenuTriggerProps,\n  type NavDockVariant,\n} from \"./navdock\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    }
  ]
}
