{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "menubar",
  "title": "Menubar",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/menubar/Menubar.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarProps extends HTMLAttributes<HTMLDivElement> {\n    /** Controlled open menu id. When omitted the menubar is uncontrolled. */\n    value?: string\n    defaultValue?: string\n    /** When false, arrow keys stop at the first/last trigger instead of wrapping. */\n    loop?: boolean\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { setMenubarRootContext } from './MenubarContext'\n\n  let {\n    class: className,\n    value = $bindable(),\n    defaultValue,\n    loop = true,\n    children,\n    ref = $bindable(null),\n    ...restProps\n  }: MenubarProps = $props()\n\n  let seeded = false\n  $effect.pre(() => {\n    if (!seeded && value === undefined && defaultValue !== undefined) {\n      value = defaultValue\n    }\n    seeded = true\n  })\n\n  let rootEl: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = rootEl\n  })\n\n  const triggers: Array<{ id: string; getEl: () => HTMLElement | null }> = []\n\n  function focusTriggerById(id: string) {\n    triggers.find((t) => t.id === id)?.getEl()?.focus()\n  }\n\n  setMenubarRootContext({\n    getOpenMenu: () => value ?? null,\n    setOpenMenu: (id, refocusTrigger = false) => {\n      const prev = value ?? null\n      value = id ?? undefined\n      if (refocusTrigger && prev) {\n        requestAnimationFrame(() => focusTriggerById(prev))\n      }\n    },\n    registerTrigger(id, getEl) {\n      const entry = { id, getEl }\n      triggers.push(entry)\n      return () => {\n        const i = triggers.indexOf(entry)\n        if (i >= 0) triggers.splice(i, 1)\n      }\n    },\n    focusSiblingTrigger(id, dir) {\n      const live = triggers.filter((t) => t.getEl()?.isConnected)\n      if (live.length === 0) return null\n      const index = Math.max(0, live.findIndex((t) => t.id === id))\n      let next = index + dir\n      if (loop) next = (next + live.length) % live.length\n      else next = Math.min(live.length - 1, Math.max(0, next))\n      const target = live[next]!\n      target.getEl()?.focus()\n      return target.id\n    },\n    getRootEl: () => rootEl,\n  })\n\n  // Outside pointer down closes the open menu (no portal here — the open\n  // content renders inline inside its menu, so \"outside root\" is the test).\n  $effect(() => {\n    if (value == null) return\n    function onPointerDown(e: PointerEvent) {\n      if (rootEl && !rootEl.contains(e.target as Node)) value = undefined\n    }\n    // Register async so the opening click itself doesn't immediately close.\n    const t = setTimeout(() => document.addEventListener('pointerdown', onPointerDown), 0)\n    return () => {\n      clearTimeout(t)\n      document.removeEventListener('pointerdown', onPointerDown)\n    }\n  })\n</script>\n\n<div\n  bind:this={rootEl}\n  role=\"menubar\"\n  aria-orientation=\"horizontal\"\n  data-uipkge=\"\"\n  data-slot=\"menubar\"\n  class={cn('bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs', className)}\n  {...restProps}\n>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/Menubar.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarCheckboxItem.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarCheckboxItemProps extends HTMLAttributes<HTMLDivElement> {\n    checked?: boolean | 'indeterminate'\n    defaultChecked?: boolean\n    disabled?: boolean\n    /** Indicator icon override (default: Check). */\n    indicatorIcon?: Snippet\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { Check } from '@lucide/svelte'\n  import { cn } from '$lib/utils'\n  import { getMenubarScopeContext } from './MenubarContext'\n\n  let {\n    class: className,\n    checked = $bindable(),\n    defaultChecked = false,\n    disabled = false,\n    indicatorIcon,\n    children,\n    ref = $bindable(null),\n    onclick,\n    onkeydown,\n    ...restProps\n  }: MenubarCheckboxItemProps = $props()\n\n  const scope = getMenubarScopeContext()\n\n  let seeded = false\n  $effect.pre(() => {\n    if (!seeded && checked === undefined) checked = defaultChecked\n    seeded = true\n  })\n\n  let el: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = el\n  })\n  $effect(() => {\n    if (el && scope) {\n      const isDisabled = () => disabled\n      return scope.registerItem(el, isDisabled)\n    }\n  })\n\n  // NOTE: named `checkState`, not `state` — a local `state` variable shadows\n  // the `$state` rune (Svelte reads `$state` as a store subscription then).\n  const checkState = $derived(checked === 'indeterminate' ? 'indeterminate' : checked ? 'checked' : 'unchecked')\n</script>\n\n<div\n  bind:this={el}\n  role=\"menuitemcheckbox\"\n  tabindex=\"-1\"\n  aria-checked={checked === 'indeterminate' ? 'mixed' : Boolean(checked)}\n  aria-disabled={disabled || undefined}\n  data-uipkge=\"\"\n  data-slot=\"menubar-checkbox-item\"\n  data-state={checkState}\n  data-disabled={disabled ? '' : undefined}\n  class={cn(\n    \"focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus-visible:ring-2 focus-visible:ring-inset data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n    className,\n  )}\n  onclick={(e) => {\n    if (disabled) return\n    checked = checked === true ? false : true\n    // Checkbox items toggle without closing the menu.\n    onclick?.(e)\n  }}\n  onmouseenter={(e) => {\n    if (!disabled) (e.currentTarget as HTMLElement).focus({ preventScroll: true })\n  }}\n  onkeydown={(e) => {\n    const target = e.currentTarget as HTMLElement\n    if (e.key === 'ArrowDown') {\n      e.preventDefault()\n      scope?.moveFocus(target, 1)\n    } else if (e.key === 'ArrowUp') {\n      e.preventDefault()\n      scope?.moveFocus(target, -1)\n    } else if (e.key === 'Home') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'first')\n    } else if (e.key === 'End') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'last')\n    } else if (e.key === 'Enter' || e.key === ' ') {\n      if (!disabled) {\n        e.preventDefault()\n        target.click()\n      }\n    }\n    onkeydown?.(e)\n  }}\n  {...restProps}\n>\n  <span class=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n    {#if checked === 'indeterminate'}\n      <span class=\"size-2 rounded-[1px] bg-current\" aria-hidden=\"true\"></span>\n    {:else if checked}\n      {#if indicatorIcon}\n        {@render indicatorIcon()}\n      {:else}\n        <Check class=\"size-4\" aria-hidden=\"true\" />\n      {/if}\n    {/if}\n  </span>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarCheckboxItem.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarContent.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarContentProps extends HTMLAttributes<HTMLDivElement> {\n    align?: 'start' | 'center' | 'end'\n    alignOffset?: number\n    sideOffset?: number\n    /** When false, arrow keys stop at the first/last item instead of wrapping. */\n    loop?: boolean\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { getMenubarMenuContext, getMenubarRootContext } from './MenubarContext'\n\n  let {\n    class: className,\n    align = 'start',\n    alignOffset = -4,\n    sideOffset = 8,\n    loop: _loop = true,\n    children,\n    ref = $bindable(null),\n    onkeydown,\n    ...restProps\n  }: MenubarContentProps = $props()\n\n  // Roving wrap is handled by the shared scope (always loops, like reka's\n  // default); the prop is destructured for API parity and otherwise unused.\n\n  const root = getMenubarRootContext()\n  const menu = getMenubarMenuContext()\n\n  let el: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = el\n    menu?.setContentEl(el)\n  })\n\n  const isOpen = $derived(menu?.isOpen() ?? false)\n</script>\n\n{#if isOpen && menu}\n  <!-- No portal: the content renders inline, absolutely positioned under its\n       trigger (the menu wrapper is relative). Exit animations don't run on\n       unmount — enter animations still play via data-[state=open]. -->\n  <div\n    bind:this={el}\n    role=\"menu\"\n    id={menu.contentId}\n    aria-labelledby={menu.triggerId}\n    aria-orientation=\"vertical\"\n    data-uipkge=\"\"\n    data-slot=\"menubar-content\"\n    data-state=\"open\"\n    data-align={align}\n    class={cn(\n      'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 absolute top-full z-50 min-w-48 origin-top overflow-hidden rounded-md border p-1 shadow-md',\n      align === 'start' && 'left-0',\n      align === 'center' && 'left-1/2 -translate-x-1/2',\n      align === 'end' && 'right-0',\n      className,\n    )}\n    style:margin-top=\"{sideOffset}px\"\n    style:margin-left={align === 'start' || align === 'center' ? `${alignOffset}px` : undefined}\n    style:margin-right={align === 'end' ? `${-alignOffset}px` : undefined}\n    onkeydown={(e) => {\n      if (e.key === 'Escape') {\n        e.preventDefault()\n        root?.setOpenMenu(null, true)\n      } else if (e.key === 'Tab') {\n        root?.setOpenMenu(null)\n      }\n      onkeydown?.(e)\n    }}\n    {...restProps}\n  >\n    {@render children?.()}\n  </div>\n{/if}\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarContent.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarContext.ts",
      "content": "import { getContext, setContext } from 'svelte'\n\n/** Root-level open-menu state + trigger registry for sibling navigation. */\nexport interface MenubarRootContextValue {\n  getOpenMenu: () => string | null\n  setOpenMenu: (id: string | null, refocusTrigger?: boolean) => void\n  registerTrigger: (id: string, getEl: () => HTMLElement | null) => () => void\n  /** Focus the sibling trigger in `dir`; returns the newly focused menu id. */\n  focusSiblingTrigger: (id: string, dir: 1 | -1) => string | null\n  getRootEl: () => HTMLElement | null\n}\n\n/** Trigger/content pairing for one top-level menu. */\nexport interface MenubarMenuContextValue {\n  id: string\n  triggerId: string\n  contentId: string\n  isOpen: () => boolean\n  getTriggerEl: () => HTMLElement | null\n  setTriggerEl: (el: HTMLElement | null) => void\n  getContentEl: () => HTMLElement | null\n  setContentEl: (el: HTMLElement | null) => void\n}\n\n/**\n * Roving-focus scope. Provided by MenubarMenu for its content and shadowed by\n * MenubarSub for its flyout, so arrow keys stay inside the nearest open menu.\n */\nexport interface MenubarScopeContextValue {\n  registerItem: (el: HTMLElement, isDisabled: () => boolean) => () => void\n  moveFocus: (current: HTMLElement | null, target: 1 | -1 | 'first' | 'last') => void\n  closeScope: (refocusTrigger: boolean) => void\n}\n\n/** Open state for one submenu. */\nexport interface MenubarSubContextValue {\n  isOpen: () => boolean\n  setOpen: (open: boolean) => void\n  getTriggerEl: () => HTMLElement | null\n  setTriggerEl: (el: HTMLElement | null) => void\n  /**\n   * The scope enclosing the submenu (captured before the sub shadows it).\n   * The sub trigger registers here so parent-menu arrows flow through it.\n   */\n  parentScope: MenubarScopeContextValue | null\n}\n\n/** Selected value for one radio group. */\nexport interface MenubarRadioContextValue {\n  getValue: () => string | undefined\n  setValue: (value: string) => void\n}\n\nconst RootKey = Symbol('MenubarRoot')\nconst MenuKey = Symbol('MenubarMenu')\nconst ScopeKey = Symbol('MenubarScope')\nconst SubKey = Symbol('MenubarSub')\nconst RadioKey = Symbol('MenubarRadio')\n\nexport function setMenubarRootContext(v: MenubarRootContextValue) {\n  setContext(RootKey, v)\n}\nexport function getMenubarRootContext(): MenubarRootContextValue | null {\n  return getContext<MenubarRootContextValue | null>(RootKey) ?? null\n}\n\nexport function setMenubarMenuContext(v: MenubarMenuContextValue) {\n  setContext(MenuKey, v)\n}\nexport function getMenubarMenuContext(): MenubarMenuContextValue | null {\n  return getContext<MenubarMenuContextValue | null>(MenuKey) ?? null\n}\n\nexport function setMenubarScopeContext(v: MenubarScopeContextValue) {\n  setContext(ScopeKey, v)\n}\nexport function getMenubarScopeContext(): MenubarScopeContextValue | null {\n  return getContext<MenubarScopeContextValue | null>(ScopeKey) ?? null\n}\n\nexport function setMenubarSubContext(v: MenubarSubContextValue) {\n  setContext(SubKey, v)\n}\nexport function getMenubarSubContext(): MenubarSubContextValue | null {\n  return getContext<MenubarSubContextValue | null>(SubKey) ?? null\n}\n\nexport function setMenubarRadioContext(v: MenubarRadioContextValue) {\n  setContext(RadioKey, v)\n}\nexport function getMenubarRadioContext(): MenubarRadioContextValue | null {\n  return getContext<MenubarRadioContextValue | null>(RadioKey) ?? null\n}\n\n/** Shared roving-focus list with wrap-around (reka `loop` default). */\nexport function createItemScope(closeScope: (refocusTrigger: boolean) => void): MenubarScopeContextValue {\n  const entries: Array<{ el: HTMLElement; isDisabled: () => boolean }> = []\n  return {\n    registerItem(el, isDisabled) {\n      const entry = { el, isDisabled }\n      entries.push(entry)\n      return () => {\n        const i = entries.indexOf(entry)\n        if (i >= 0) entries.splice(i, 1)\n      }\n    },\n    moveFocus(current, target) {\n      const enabled = entries.filter((e) => e.el.isConnected && !e.isDisabled())\n      if (enabled.length === 0) return\n      let index: number\n      if (target === 'first') index = 0\n      else if (target === 'last') index = enabled.length - 1\n      else {\n        const currentIndex = current ? enabled.findIndex((e) => e.el === current) : -1\n        index = (currentIndex + target + enabled.length) % enabled.length\n      }\n      enabled[index]?.el.focus({ preventScroll: true })\n    },\n    closeScope,\n  }\n}\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarContext.ts"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarGroup.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarGroupProps extends HTMLAttributes<HTMLDivElement> {\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let { class: className, children, ref = $bindable(null), ...restProps }: MenubarGroupProps = $props()\n</script>\n\n<div bind:this={ref} role=\"group\" data-uipkge=\"\" data-slot=\"menubar-group\" class={cn(className)} {...restProps}>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarGroup.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarItem.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarItemProps extends HTMLAttributes<HTMLDivElement> {\n    disabled?: boolean\n    inset?: boolean\n    variant?: 'default' | 'destructive'\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { getMenubarRootContext, getMenubarScopeContext } from './MenubarContext'\n\n  let {\n    class: className,\n    disabled = false,\n    inset = false,\n    variant = 'default',\n    children,\n    ref = $bindable(null),\n    onclick,\n    onkeydown,\n    ...restProps\n  }: MenubarItemProps = $props()\n\n  const root = getMenubarRootContext()\n  const scope = getMenubarScopeContext()\n\n  let el: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = el\n  })\n  $effect(() => {\n    if (el && scope) {\n      const isDisabled = () => disabled\n      return scope.registerItem(el, isDisabled)\n    }\n  })\n</script>\n\n<div\n  bind:this={el}\n  role=\"menuitem\"\n  tabindex=\"-1\"\n  aria-disabled={disabled || undefined}\n  data-uipkge=\"\"\n  data-slot=\"menubar-item\"\n  data-inset={inset ? '' : undefined}\n  data-variant={variant}\n  data-disabled={disabled ? '' : undefined}\n  class={cn(\n    \"focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus-visible:ring-2 focus-visible:ring-inset data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n    className,\n  )}\n  onclick={(e) => {\n    if (disabled) return\n    onclick?.(e)\n    // Plain items select + close; sub scopes bubble the close to the root.\n    scope?.closeScope(false)\n    root?.setOpenMenu(null)\n  }}\n  onmouseenter={(e) => {\n    if (!disabled) (e.currentTarget as HTMLElement).focus({ preventScroll: true })\n  }}\n  onkeydown={(e) => {\n    const target = e.currentTarget as HTMLElement\n    if (e.key === 'ArrowDown') {\n      e.preventDefault()\n      scope?.moveFocus(target, 1)\n    } else if (e.key === 'ArrowUp') {\n      e.preventDefault()\n      scope?.moveFocus(target, -1)\n    } else if (e.key === 'Home') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'first')\n    } else if (e.key === 'End') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'last')\n    } else if (e.key === 'Enter' || e.key === ' ') {\n      if (!disabled) {\n        e.preventDefault()\n        target.click()\n      }\n    }\n    onkeydown?.(e)\n  }}\n  {...restProps}\n>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarItem.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarLabel.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarLabelProps extends HTMLAttributes<HTMLDivElement> {\n    inset?: boolean\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let { class: className, inset = false, children, ref = $bindable(null), ...restProps }: MenubarLabelProps = $props()\n</script>\n\n<div\n  bind:this={ref}\n  data-uipkge=\"\"\n  data-slot=\"menubar-label\"\n  data-inset={inset ? '' : undefined}\n  class={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}\n  {...restProps}\n>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarLabel.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarMenu.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n\n  export interface MenubarMenuProps {\n    /**\n     * Stable id for this menu. Defaults to a generated id. Pass one when\n     * controlling the open menu through the root `value` / `defaultValue`.\n     */\n    value?: string\n    children?: Snippet\n  }\n\n  let menuCounter = 0\n</script>\n\n<script lang=\"ts\">\n  import { untrack } from 'svelte'\n  import { getMenubarRootContext, setMenubarMenuContext, setMenubarScopeContext, createItemScope } from './MenubarContext'\n\n  let { value, children }: MenubarMenuProps = $props()\n\n  const root = getMenubarRootContext()\n  // Computed once: ids must stay stable for the component's lifetime (aria\n  // references + root tracking depend on it).\n  const id = untrack(() => value ?? `menu-${++menuCounter}`)\n  const triggerId = `menubar-trigger-${id}`\n  const contentId = `menubar-content-${id}`\n\n  // The root is the single source of open state (see its `value` prop).\n  const isOpen = $derived(root?.getOpenMenu() === id)\n\n  function setOpen(next: boolean, refocusTrigger = false) {\n    root?.setOpenMenu(next ? id : null, refocusTrigger)\n  }\n\n  let triggerEl: HTMLElement | null = $state(null)\n  let contentEl: HTMLElement | null = $state(null)\n\n  setMenubarMenuContext({\n    id,\n    triggerId,\n    contentId,\n    isOpen: () => isOpen,\n    getTriggerEl: () => triggerEl,\n    setTriggerEl: (el) => {\n      triggerEl = el\n    },\n    getContentEl: () => contentEl,\n    setContentEl: (el) => {\n      contentEl = el\n    },\n  })\n\n  setMenubarScopeContext(createItemScope((refocusTrigger) => setOpen(false, refocusTrigger)))\n</script>\n\n<div data-uipkge=\"\" data-slot=\"menubar-menu\" data-state={isOpen ? 'open' : 'closed'} class=\"relative\">\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarMenu.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarRadioGroup.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n\n  export interface MenubarRadioGroupProps {\n    value?: string\n    defaultValue?: string\n    children?: Snippet\n  }\n</script>\n\n<script lang=\"ts\">\n  import { setMenubarRadioContext } from './MenubarContext'\n\n  let { value = $bindable(), defaultValue, children }: MenubarRadioGroupProps = $props()\n\n  let seeded = false\n  $effect.pre(() => {\n    if (!seeded && value === undefined && defaultValue !== undefined) value = defaultValue\n    seeded = true\n  })\n\n  setMenubarRadioContext({\n    getValue: () => value,\n    setValue: (v) => {\n      value = v\n    },\n  })\n</script>\n\n<div role=\"group\" data-uipkge=\"\" data-slot=\"menubar-radio-group\">\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarRadioGroup.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarRadioItem.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarRadioItemProps extends HTMLAttributes<HTMLDivElement> {\n    value: string\n    disabled?: boolean\n    /** Indicator icon override (default: filled Circle). */\n    indicatorIcon?: Snippet\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { Circle } from '@lucide/svelte'\n  import { cn } from '$lib/utils'\n  import { getMenubarRadioContext, getMenubarScopeContext } from './MenubarContext'\n\n  let {\n    class: className,\n    value,\n    disabled = false,\n    indicatorIcon,\n    children,\n    ref = $bindable(null),\n    onclick,\n    onkeydown,\n    ...restProps\n  }: MenubarRadioItemProps = $props()\n\n  const scope = getMenubarScopeContext()\n  const radio = getMenubarRadioContext()\n\n  let el: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = el\n  })\n  $effect(() => {\n    if (el && scope) {\n      const isDisabled = () => disabled\n      return scope.registerItem(el, isDisabled)\n    }\n  })\n\n  const isChecked = $derived(radio?.getValue() === value)\n</script>\n\n<div\n  bind:this={el}\n  role=\"menuitemradio\"\n  tabindex=\"-1\"\n  aria-checked={isChecked}\n  aria-disabled={disabled || undefined}\n  data-uipkge=\"\"\n  data-slot=\"menubar-radio-item\"\n  data-state={isChecked ? 'checked' : 'unchecked'}\n  data-disabled={disabled ? '' : undefined}\n  class={cn(\n    \"focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus-visible:ring-2 focus-visible:ring-inset data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n    className,\n  )}\n  onclick={(e) => {\n    if (disabled) return\n    radio?.setValue(value)\n    // Radio items select without closing the menu.\n    onclick?.(e)\n  }}\n  onmouseenter={(e) => {\n    if (!disabled) (e.currentTarget as HTMLElement).focus({ preventScroll: true })\n  }}\n  onkeydown={(e) => {\n    const target = e.currentTarget as HTMLElement\n    if (e.key === 'ArrowDown') {\n      e.preventDefault()\n      scope?.moveFocus(target, 1)\n    } else if (e.key === 'ArrowUp') {\n      e.preventDefault()\n      scope?.moveFocus(target, -1)\n    } else if (e.key === 'Home') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'first')\n    } else if (e.key === 'End') {\n      e.preventDefault()\n      scope?.moveFocus(target, 'last')\n    } else if (e.key === 'Enter' || e.key === ' ') {\n      if (!disabled) {\n        e.preventDefault()\n        target.click()\n      }\n    }\n    onkeydown?.(e)\n  }}\n  {...restProps}\n>\n  <span class=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n    {#if isChecked}\n      {#if indicatorIcon}\n        {@render indicatorIcon()}\n      {:else}\n        <Circle class=\"size-2 fill-current\" aria-hidden=\"true\" />\n      {/if}\n    {/if}\n  </span>\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarRadioItem.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarSeparator.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarSeparatorProps extends HTMLAttributes<HTMLDivElement> {\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let { class: className, ref = $bindable(null), ...restProps }: MenubarSeparatorProps = $props()\n</script>\n\n<div\n  bind:this={ref}\n  role=\"separator\"\n  aria-orientation=\"horizontal\"\n  data-uipkge=\"\"\n  data-slot=\"menubar-separator\"\n  class={cn('bg-border -mx-1 my-1 h-px', className)}\n  {...restProps}\n></div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarSeparator.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarShortcut.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarShortcutProps extends HTMLAttributes<HTMLElement> {\n    ref?: HTMLElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let { class: className, children, ref = $bindable(null), ...restProps }: MenubarShortcutProps = $props()\n</script>\n\n<span\n  bind:this={ref}\n  data-uipkge=\"\"\n  data-slot=\"menubar-shortcut\"\n  class={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}\n  {...restProps}\n>\n  {@render children?.()}\n</span>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarShortcut.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarSub.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n\n  export interface MenubarSubProps {\n    open?: boolean\n    defaultOpen?: boolean\n    children?: Snippet\n  }\n</script>\n\n<script lang=\"ts\">\n  import { tick } from 'svelte'\n  import {\n    createItemScope,\n    getMenubarScopeContext,\n    setMenubarScopeContext,\n    setMenubarSubContext,\n  } from './MenubarContext'\n\n  let { open = $bindable(false), defaultOpen = false, children }: MenubarSubProps = $props()\n\n  let seeded = false\n  $effect.pre(() => {\n    if (!seeded && !open && defaultOpen) open = true\n    seeded = true\n  })\n\n  let triggerEl: HTMLElement | null = $state(null)\n\n  function setOpen(next: boolean, refocusTrigger = false) {\n    open = next\n    if (refocusTrigger && !next) tick().then(() => triggerEl?.focus({ preventScroll: true }))\n  }\n\n  // Capture the enclosing scope BEFORE shadowing it below.\n  const parentScope = getMenubarScopeContext()\n\n  setMenubarSubContext({\n    isOpen: () => open,\n    setOpen,\n    getTriggerEl: () => triggerEl,\n    setTriggerEl: (el) => {\n      triggerEl = el\n    },\n    parentScope,\n  })\n\n  // Shadow the parent menu's roving scope so arrows stay inside the flyout.\n  setMenubarScopeContext(createItemScope((refocusTrigger) => setOpen(false, refocusTrigger)))\n</script>\n\n<div data-uipkge=\"\" data-slot=\"menubar-sub\" data-state={open ? 'open' : 'closed'} class=\"relative\">\n  {@render children?.()}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarSub.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarSubContent.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarSubContentProps extends HTMLAttributes<HTMLDivElement> {\n    alignOffset?: number\n    sideOffset?: number\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { getMenubarSubContext } from './MenubarContext'\n\n  let {\n    class: className,\n    alignOffset = 0,\n    sideOffset = 8,\n    children,\n    ref = $bindable(null),\n    onkeydown,\n    ...restProps\n  }: MenubarSubContentProps = $props()\n\n  const sub = getMenubarSubContext()\n  const isOpen = $derived(sub?.isOpen() ?? false)\n</script>\n\n{#if isOpen}\n  <!-- No portal: the flyout renders inline, absolutely positioned to the\n       right of its trigger (the sub wrapper is relative). -->\n  <div\n    bind:this={ref}\n    role=\"menu\"\n    aria-orientation=\"vertical\"\n    data-uipkge=\"\"\n    data-slot=\"menubar-sub-content\"\n    data-state=\"open\"\n    class={cn(\n      'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 absolute top-0 left-full z-50 min-w-[8rem] origin-top-left overflow-hidden rounded-md border p-1 shadow-lg',\n      className,\n    )}\n    style:margin-left=\"{sideOffset}px\"\n    style:margin-top=\"{alignOffset}px\"\n    onkeydown={(e) => {\n      if (e.key === 'Escape' || e.key === 'ArrowLeft') {\n        e.preventDefault()\n        e.stopPropagation()\n        sub?.setOpen(false)\n        sub?.getTriggerEl()?.focus({ preventScroll: true })\n      } else if (e.key === 'Tab') {\n        sub?.setOpen(false)\n      }\n      onkeydown?.(e)\n    }}\n    {...restProps}\n  >\n    {@render children?.()}\n  </div>\n{/if}\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarSubContent.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarSubTrigger.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface MenubarSubTriggerProps extends HTMLAttributes<HTMLDivElement> {\n    disabled?: boolean\n    inset?: boolean\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { tick } from 'svelte'\n  import { ChevronRight } from '@lucide/svelte'\n  import { cn } from '$lib/utils'\n  import { getMenubarScopeContext, getMenubarSubContext } from './MenubarContext'\n\n  let {\n    class: className,\n    disabled = false,\n    inset = false,\n    children,\n    ref = $bindable(null),\n    onclick,\n    onkeydown,\n    ...restProps\n  }: MenubarSubTriggerProps = $props()\n\n  const sub = getMenubarSubContext()\n  // The sub shadows the parent scope for its *content*, but the trigger\n  // itself registers with the parent scope so arrows flow through it.\n  const parentScope = $derived(sub?.parentScope ?? null)\n  const subScope = getMenubarScopeContext()\n\n  let el: HTMLDivElement | null = $state(null)\n  $effect(() => {\n    ref = el\n    sub?.setTriggerEl(el)\n  })\n  $effect(() => {\n    if (el && parentScope) {\n      const isDisabled = () => disabled\n      return parentScope.registerItem(el, isDisabled)\n    }\n  })\n\n  const isOpen = $derived(sub?.isOpen() ?? false)\n</script>\n\n<div\n  bind:this={el}\n  role=\"menuitem\"\n  tabindex=\"-1\"\n  aria-haspopup=\"menu\"\n  aria-expanded={isOpen}\n  aria-disabled={disabled || undefined}\n  data-uipkge=\"\"\n  data-slot=\"menubar-sub-trigger\"\n  data-state={isOpen ? 'open' : 'closed'}\n  data-inset={inset ? '' : undefined}\n  data-disabled={disabled ? '' : undefined}\n  class={cn(\n    'focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none focus-visible:ring-2 focus-visible:ring-inset data-[inset]:pl-8',\n    className,\n  )}\n  onclick={(e) => {\n    if (disabled) return\n    sub?.setOpen(!isOpen)\n    onclick?.(e)\n  }}\n  onmouseenter={(e) => {\n    if (disabled) return\n    ;(e.currentTarget as HTMLElement).focus({ preventScroll: true })\n    sub?.setOpen(true)\n  }}\n  onkeydown={(e) => {\n    const target = e.currentTarget as HTMLElement\n    if (e.key === 'ArrowDown') {\n      e.preventDefault()\n      parentScope?.moveFocus(target, 1)\n    } else if (e.key === 'ArrowUp') {\n      e.preventDefault()\n      parentScope?.moveFocus(target, -1)\n    } else if (e.key === 'Home') {\n      e.preventDefault()\n      parentScope?.moveFocus(target, 'first')\n    } else if (e.key === 'End') {\n      e.preventDefault()\n      parentScope?.moveFocus(target, 'last')\n    } else if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {\n      if (!disabled) {\n        e.preventDefault()\n        sub?.setOpen(true)\n        tick().then(() => subScope?.moveFocus(null, 'first'))\n      }\n    }\n    onkeydown?.(e)\n  }}\n  {...restProps}\n>\n  {@render children?.()}\n  <ChevronRight class=\"ml-auto size-4\" aria-hidden=\"true\" />\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarSubTrigger.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarTrigger.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLButtonAttributes } from 'svelte/elements'\n\n  export interface MenubarTriggerProps extends HTMLButtonAttributes {\n    disabled?: boolean\n    ref?: HTMLButtonElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { tick } from 'svelte'\n  import { cn } from '$lib/utils'\n  import { getMenubarMenuContext, getMenubarRootContext, getMenubarScopeContext } from './MenubarContext'\n\n  let {\n    class: className,\n    disabled,\n    children,\n    ref = $bindable(null),\n    onclick,\n    onkeydown,\n    onmouseenter,\n    ...restProps\n  }: MenubarTriggerProps = $props()\n\n  const root = getMenubarRootContext()\n  const menu = getMenubarMenuContext()\n  const scope = getMenubarScopeContext()\n\n  let el: HTMLButtonElement | null = $state(null)\n  $effect(() => {\n    ref = el\n    menu?.setTriggerEl(el)\n  })\n  $effect(() => {\n    if (menu && root) return root.registerTrigger(menu.id, () => el)\n  })\n\n  const isOpen = $derived(menu?.isOpen() ?? false)\n\n  function openAndFocusFirst() {\n    if (!menu || !root) return\n    if (!isOpen) root.setOpenMenu(menu.id)\n    tick().then(() => scope?.moveFocus(null, 'first'))\n  }\n</script>\n\n<button\n  bind:this={el}\n  type=\"button\"\n  id={menu?.triggerId}\n  aria-haspopup=\"menu\"\n  aria-expanded={isOpen}\n  aria-controls={menu?.contentId}\n  aria-disabled={disabled || undefined}\n  data-uipkge=\"\"\n  data-slot=\"menubar-trigger\"\n  data-state={isOpen ? 'open' : 'closed'}\n  data-disabled={disabled ? '' : undefined}\n  {disabled}\n  class={cn(\n    'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none',\n    className,\n  )}\n  onclick={(e) => {\n    if (disabled) return\n    if (menu && root) root.setOpenMenu(isOpen ? null : menu.id)\n    onclick?.(e)\n  }}\n  onmouseenter={(e) => {\n    // Hovering a sibling trigger while a menu is open switches to it.\n    if (!disabled && menu && root && root.getOpenMenu() !== null && root.getOpenMenu() !== menu.id) {\n      root.setOpenMenu(menu.id)\n    }\n    onmouseenter?.(e)\n  }}\n  onkeydown={(e) => {\n    if (disabled) {\n      onkeydown?.(e)\n      return\n    }\n    if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n      e.preventDefault()\n      openAndFocusFirst()\n    } else if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {\n      e.preventDefault()\n      if (menu && root) {\n        const next = root.focusSiblingTrigger(menu.id, e.key === 'ArrowRight' ? 1 : -1)\n        // When a menu is already open, arrows switch the open menu.\n        if (next && root.getOpenMenu() !== null) root.setOpenMenu(next)\n      }\n    } else if (e.key === 'Escape') {\n      if (isOpen && menu && root) {\n        e.preventDefault()\n        root.setOpenMenu(null)\n      }\n    }\n    onkeydown?.(e)\n  }}\n  {...restProps}\n>\n  {@render children?.()}\n</button>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarTrigger.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/MenubarPortal.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n\n  export interface MenubarPortalProps {\n    children?: Snippet\n  }\n</script>\n\n<script lang=\"ts\">\n  let { children }: MenubarPortalProps = $props()\n</script>\n\n<!-- Pass-through (not a real portal): menubar content is absolutely positioned\n     relative to its menu wrapper, so moving it to document.body would break\n     placement. This part exists for React import parity — wrapping content in\n     it renders exactly as unwrapped. -->\n<span data-uipkge=\"\" data-slot=\"menubar-portal\" class=\"contents\">\n  {@render children?.()}\n</span>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/MenubarPortal.svelte"
    },
    {
      "path": "packages/registry-svelte/components/menubar/index.ts",
      "content": "export { default as Menubar, type MenubarProps } from './Menubar.svelte'\nexport { default as MenubarCheckboxItem, type MenubarCheckboxItemProps } from './MenubarCheckboxItem.svelte'\nexport { default as MenubarContent, type MenubarContentProps } from './MenubarContent.svelte'\nexport { default as MenubarGroup, type MenubarGroupProps } from './MenubarGroup.svelte'\nexport { default as MenubarItem, type MenubarItemProps } from './MenubarItem.svelte'\nexport { default as MenubarLabel, type MenubarLabelProps } from './MenubarLabel.svelte'\nexport { default as MenubarMenu, type MenubarMenuProps } from './MenubarMenu.svelte'\nexport { default as MenubarPortal, type MenubarPortalProps } from './MenubarPortal.svelte'\nexport { default as MenubarRadioGroup, type MenubarRadioGroupProps } from './MenubarRadioGroup.svelte'\nexport { default as MenubarRadioItem, type MenubarRadioItemProps } from './MenubarRadioItem.svelte'\nexport { default as MenubarSeparator, type MenubarSeparatorProps } from './MenubarSeparator.svelte'\nexport { default as MenubarShortcut, type MenubarShortcutProps } from './MenubarShortcut.svelte'\nexport { default as MenubarSub, type MenubarSubProps } from './MenubarSub.svelte'\nexport { default as MenubarSubContent, type MenubarSubContentProps } from './MenubarSubContent.svelte'\nexport { default as MenubarSubTrigger, type MenubarSubTriggerProps } from './MenubarSubTrigger.svelte'\nexport { default as MenubarTrigger, type MenubarTriggerProps } from './MenubarTrigger.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/menubar/index.ts"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Top-level menu bar — File / Edit / View — for desktop-style apps. Same primitives as Dropdown Menu but laid out horizontally and keyboard-navigable across siblings (left/right arrows).",
  "categories": [
    "navigation"
  ]
}