{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "command-palette",
  "title": "Command Palette",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/command-palette/CommandPalette.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Component } from 'svelte'\n\n  export interface CommandPaletteItem {\n    label: string\n    value?: string\n    hint?: string\n    icon?: Component\n    onSelect?: () => void\n  }\n\n  export interface CommandPaletteGroup {\n    heading: string\n    items: CommandPaletteItem[]\n  }\n\n  export interface CommandPaletteProps {\n    groups?: CommandPaletteGroup[]\n    placeholder?: string\n    triggerLabel?: string\n    showTrigger?: boolean\n    /** Controlled open state (`bind:open`) — the Svelte counterpart of the Vue twin's exposed show()/hide()/toggle(). */\n    open?: boolean\n    onOpenChange?: (open: boolean) => void\n    onSelect?: (item: CommandPaletteItem) => void\n  }\n</script>\n\n<script lang=\"ts\">\n  import { onMount } from 'svelte'\n  import { FileText, Inbox, KanbanSquare, LayoutDashboard, Search, Settings, Users } from '@lucide/svelte'\n  import {\n    CommandDialog,\n    CommandEmpty,\n    CommandGroup,\n    CommandInput,\n    CommandItem,\n    CommandList,\n    CommandSeparator,\n    CommandShortcut,\n  } from '$lib/components/ui/command'\n\n  let {\n    groups = [\n      {\n        heading: 'Navigate',\n        items: [\n          { label: 'Dashboard', hint: '/dashboard', icon: LayoutDashboard },\n          { label: 'Inbox', hint: '/inbox', icon: Inbox },\n          { label: 'Kanban', hint: '/kanban', icon: KanbanSquare },\n          { label: 'Team', hint: '/team', icon: Users },\n        ],\n      },\n      {\n        heading: 'Settings',\n        items: [\n          { label: 'Profile', hint: '/profile', icon: FileText },\n          { label: 'Settings', hint: '/settings', icon: Settings },\n        ],\n      },\n    ],\n    placeholder = 'Search pages, commands…',\n    triggerLabel = 'Search pages, commands…',\n    showTrigger = true,\n    open = $bindable(false),\n    onOpenChange,\n    onSelect,\n  }: CommandPaletteProps = $props()\n\n  function setOpen(next: boolean) {\n    open = next\n    onOpenChange?.(next)\n  }\n\n  function pick(item: CommandPaletteItem) {\n    setOpen(false)\n    item.onSelect?.()\n    onSelect?.(item)\n  }\n\n  function onKeydown(e: KeyboardEvent) {\n    if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n      e.preventDefault()\n      setOpen(!open)\n    }\n  }\n\n  const triggerShortcut = $derived.by(() => {\n    if (typeof navigator === 'undefined') return '⌘K'\n    return /Mac|iPhone|iPad/i.test(navigator.platform) ? '⌘K' : 'Ctrl K'\n  })\n\n  onMount(() => {\n    window.addEventListener('keydown', onKeydown)\n    return () => window.removeEventListener('keydown', onKeydown)\n  })\n</script>\n\n{#if showTrigger}\n  <button\n    data-slot=\"command-palette\"\n    type=\"button\"\n    class=\"bg-secondary/50 hover:bg-secondary text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 relative hidden h-8 w-full items-center gap-2 rounded-lg border border-transparent px-2.5 text-sm shadow-none transition-colors outline-none focus-visible:ring-[3px] sm:flex md:w-56 lg:w-80\"\n    aria-label=\"Open command palette\"\n    onclick={() => setOpen(true)}\n  >\n    <Search class=\"size-3.5 shrink-0\" />\n    <span class=\"flex-1 truncate text-left\">{triggerLabel}</span>\n    <kbd\n      class=\"bg-muted/80 text-muted-foreground pointer-events-none flex h-5 items-center justify-center rounded-md border px-1.5 font-mono text-xs font-medium\"\n    >\n      <span>{triggerShortcut}</span>\n    </kbd>\n  </button>\n{/if}\n\n<CommandDialog bind:open {onOpenChange} title=\"Command palette\" description=\"Search pages and run commands\">\n  <CommandInput {placeholder} />\n  <CommandList class=\"max-h-[30rem]\">\n    <CommandEmpty>No matches.</CommandEmpty>\n    {#each groups as group, gi (group.heading)}\n      <CommandGroup heading={group.heading}>\n        {#each group.items as item (`${group.heading}-${item.label}`)}\n          {@const ItemIcon = item.icon}\n          <CommandItem value={`${group.heading} ${item.label} ${item.hint ?? ''}`} onSelect={() => pick(item)}>\n            {#if ItemIcon}\n              <ItemIcon class=\"size-4\" />\n            {/if}\n            <span>{item.label}</span>\n            {#if item.hint}\n              <CommandShortcut class=\"text-muted-foreground/70\">{item.hint}</CommandShortcut>\n            {/if}\n          </CommandItem>\n        {/each}\n      </CommandGroup>\n      {#if gi < groups.length - 1}\n        <CommandSeparator />\n      {/if}\n    {/each}\n  </CommandList>\n</CommandDialog>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/command-palette/CommandPalette.svelte"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/command.json"
  ],
  "description": "Header-grade search/command palette. Bundles the slim trigger button (with platform-aware ⌘K/Ctrl-K kbd hint) AND the modal CommandDialog into one block; consumers drop it once and the global keyboard shortcut wires itself. Takes a `groups` array of `{ heading, items: [{ label, hint, icon, onSelect }] }` and an `onSelect` callback. `showTrigger=false` hides the inline button so the consumer can fire it from elsewhere via `bind:open`.",
  "categories": [
    "layout",
    "dashboard",
    "overlay",
    "navigation"
  ]
}