{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "command-palette",
  "title": "Command Palette",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/command-palette/command-palette.component.ts",
      "content": "import {\n  Component,\n  EventEmitter,\n  Input,\n  Output,\n  booleanAttribute,\n  signal,\n  ChangeDetectionStrategy,\n} from '@angular/core'\nimport {\n  FileText,\n  Inbox,\n  KanbanSquare,\n  LayoutDashboard,\n  LucideAngularModule,\n  Search,\n  Settings,\n  Users,\n  type LucideIconData,\n} from 'lucide-angular'\nimport {\n  UiCommandDialogComponent,\n  UiCommandEmptyComponent,\n  UiCommandGroupComponent,\n  UiCommandInputComponent,\n  UiCommandItemComponent,\n  UiCommandListComponent,\n  UiCommandSeparatorComponent,\n  UiCommandShortcutComponent,\n} from '@/ui/command/command.component'\n\nexport interface CommandPaletteItem {\n  label: string\n  value?: string\n  hint?: string\n  icon?: LucideIconData\n  onSelect?: () => void\n}\n\nexport interface CommandPaletteGroup {\n  heading: string\n  items: CommandPaletteItem[]\n}\n\nconst defaultGroups: CommandPaletteGroup[] = [\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\n/**\n * CommandPalette -- the React block, 1:1: a slim header search trigger (with a\n * platform-aware Cmd-K / Ctrl-K hint) plus the modal CommandDialog. Drop it once and\n * the global keyboard shortcut wires itself. `[showTrigger]=\"false\"` hides the inline\n * button; open it from elsewhere through a template ref (`palette.show()` / `toggle()`).\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-command-palette, [ui-command-palette]',\n  standalone: true,\n  // React renders a fragment (trigger + dialog): keep this wrapper out of the layout.\n  host: { class: 'contents', '(window:keydown)': 'onKeydown($event)' },\n  imports: [\n    LucideAngularModule,\n    UiCommandDialogComponent,\n    UiCommandEmptyComponent,\n    UiCommandGroupComponent,\n    UiCommandInputComponent,\n    UiCommandItemComponent,\n    UiCommandListComponent,\n    UiCommandSeparatorComponent,\n    UiCommandShortcutComponent,\n  ],\n  template: `\n    @if (showTrigger) {\n      <button\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-[220px] lg:w-[300px]\"\n        aria-label=\"Open command palette\"\n        (click)=\"show()\"\n      >\n        <lucide-icon [img]=\"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    }\n\n    <ui-command-dialog\n      [open]=\"open()\"\n      (openChange)=\"setOpen($event)\"\n      title=\"Command palette\"\n      description=\"Search pages and run commands\"\n    >\n      <ui-command-input [placeholder]=\"placeholder\" />\n      <ui-command-list class=\"max-h-[480px]\">\n        <ui-command-empty>No matches.</ui-command-empty>\n        @for (group of groups; track group.heading; let last = $last) {\n          <ui-command-group [heading]=\"group.heading\">\n            @for (item of group.items; track item.label) {\n              <ui-command-item\n                data-slot=\"command-palette\"\n                [value]=\"group.heading + ' ' + item.label + ' ' + (item.hint ?? '')\"\n                (select)=\"pick(item)\"\n              >\n                @if (item.icon) {\n                  <lucide-icon [img]=\"item.icon\" class=\"size-4\" />\n                }\n                <span>{{ item.label }}</span>\n                @if (item.hint) {\n                  <ui-command-shortcut class=\"text-muted-foreground/70\">{{ item.hint }}</ui-command-shortcut>\n                }\n              </ui-command-item>\n            }\n          </ui-command-group>\n          @if (!last) {\n            <ui-command-separator />\n          }\n        }\n      </ui-command-list>\n    </ui-command-dialog>\n  `,\n})\nexport class UiCommandPaletteComponent {\n  protected readonly Search = Search\n\n  @Input() groups: CommandPaletteGroup[] = defaultGroups\n  @Input() placeholder = 'Search pages, commands…'\n  @Input() triggerLabel = 'Search pages, commands…'\n  @Input({ transform: booleanAttribute }) showTrigger = true\n  /** Fires after an item's own `onSelect`, with the picked item (React `onSelect`). */\n  @Output() select = new EventEmitter<CommandPaletteItem>()\n\n  readonly open = signal(false)\n  readonly triggerShortcut =\n    typeof navigator === 'undefined' ? '⌘K' : /Mac|iPhone|iPad/i.test(navigator.platform) ? '⌘K' : 'Ctrl K'\n\n  setOpen(value: boolean): void {\n    if (value === this.open()) return\n    this.open.set(value)\n  }\n\n  show(): void {\n    this.setOpen(true)\n  }\n\n  hide(): void {\n    this.setOpen(false)\n  }\n\n  toggle(): void {\n    this.setOpen(!this.open())\n  }\n\n  pick(item: CommandPaletteItem): void {\n    this.hide()\n    item.onSelect?.()\n    this.select.emit(item)\n  }\n\n  onKeydown(e: KeyboardEvent): void {\n    if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n      e.preventDefault()\n      this.toggle()\n    }\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/command-palette/command-palette.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/command-palette/index.ts",
      "content": "export {\n  UiCommandPaletteComponent,\n  type CommandPaletteGroup,\n  type CommandPaletteItem,\n} from './command-palette.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/command-palette/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/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 emits `select`. `show-trigger=false` hides the inline button so the consumer can fire it from elsewhere via the exposed `show()` / `toggle()` methods.",
  "categories": [
    "layout",
    "dashboard",
    "overlay",
    "navigation"
  ]
}