import type { Snippet } from 'svelte'; import type { IconComponent } from '../../icons/index.js'; import type { CommandPaletteSlots, CommandPaletteVariants } from './commandPalette.variants.js'; /** * A single item in the command palette. * * @example * ```ts * const item: CommandPaletteItem = { * id: 'new-file', * label: 'New File', * category: 'File', * shortcut: 'Ctrl+N', * }; * ``` */ export interface CommandPaletteItem { /** Unique identifier. Falls back to `label` when omitted. */ id?: string; /** Display text shown in the list. */ label: string; /** * Secondary line rendered under the label, truncated to one line. Use it for * context the label cannot carry — a description, or an excerpt around a * search match. */ excerpt?: string; /** Group header this item belongs to. Items with the same category are grouped together. */ category?: string; /** Optional keyboard shortcut displayed on the right side. */ shortcut?: string; /** * Leading icon component. Pass an icon directly (`import { SearchIcon } from * '@urbicon-ui/blocks'`), not an icon *name* — a name would have to be * resolved through the registry at runtime, and that dynamic lookup drags all * the entire icon set into the consumer bundle (see docs/ICON-DESIGN.md). Rendered at * the slot's own size, inheriting `currentColor`. */ icon?: IconComponent; /** Whether the item is non-selectable. @default false */ disabled?: boolean; /** Arbitrary payload forwarded to `onSelect`. */ data?: unknown; } /** * Props for the CommandPalette component. * * @summary Everything the app can do, one keystroke away. * @description Keyboard-driven command palette with search, grouped results, * and arrow-key navigation. Composes Dialog + search input into a ready-to-use overlay. * Open via bind:open or the built-in Cmd+K shortcut. * * @tag action * @related Dialog * @related Menu * @related Combobox * * @example * ```svelte * handleCommand(item)} * placeholder="Type a command..." * /> * ``` * * @example * ```svelte * runAction(item.id)} * size="md" * showFooter * /> * ``` */ export interface CommandPaletteProps { /** Items to display. Grouped automatically by `category`. */ items: CommandPaletteItem[]; /** Placeholder text for the search input. @default 'Search...' */ placeholder?: string; /** Message shown when the filter returns no results. @default 'No results found.' */ emptyText?: string; /** Show keyboard-shortcut hints in the footer. @default true */ showFooter?: boolean; /** Controls visibility. Supports `bind:open`. @default false */ open?: boolean; /** * Current search text. Supports `bind:query`. Reset to `''` whenever the * palette opens. * * For async or remote search, watch the bound `query`, fetch your own * results, and pass them back via `items` with `filter={() => true}` so the * built-in label match does not filter them a second time. * * @default '' */ query?: string; /** * Register a global keyboard shortcut that toggles the palette. `mod` is * Cmd on macOS and Ctrl elsewhere. Set to `false` to disable. * @default 'mod+k' */ shortcut?: string | false; /** * Custom filter function. Receives each item and the current query. * Return `true` to keep the item. When omitted, a case-insensitive * label + category substring match is used. */ filter?: (item: CommandPaletteItem, query: string) => boolean; /** Fired when an item is selected via click or Enter. */ onSelect?: (item: CommandPaletteItem) => void; /** Fired when the open state changes (close via Escape, backdrop, or selection). */ onOpenChange?: (open: boolean) => void; /** Custom item renderer. Receives the item, whether it is highlighted, and its flat index. */ customItem?: Snippet<[item: CommandPaletteItem, highlighted: boolean, index: number]>; /** Custom empty-state renderer. Receives the current query string. */ customEmpty?: Snippet<[query: string]>; /** Maximum width of the palette panel. @default 'md' */ size?: CommandPaletteVariants['size']; /** Additional CSS classes on the root wrapper. */ class?: string; /** Strip all default styles. @default false */ unstyled?: boolean; /** Per-slot class overrides. */ slotClasses?: Partial>; /** * Apply a named preset registered via ``. * Prefer this over `class` overrides when the requested look falls outside the * semantic intent palette — presets keep hover/active/dark-mode logic coherent * and make the custom look reusable across the project. */ preset?: string; } export { default as CommandPalette } from './CommandPalette.svelte'; export { type CommandPaletteVariants, commandPaletteVariants } from './commandPalette.variants.js';