modern-cmdk 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemod/cli.mjs +1 -3
- package/dist/codemod/transforms/data-attrs.d.mts +1 -2
- package/dist/codemod/transforms/data-attrs.mjs +0 -2
- package/dist/codemod/transforms/forward-ref.d.mts +1 -2
- package/dist/codemod/transforms/forward-ref.mjs +0 -2
- package/dist/codemod/transforms/import-rewrite.d.mts +1 -2
- package/dist/codemod/transforms/import-rewrite.mjs +0 -2
- package/dist/codemod/transforms/should-filter.d.mts +1 -2
- package/dist/codemod/transforms/should-filter.mjs +0 -2
- package/dist/core/index.d.mts +568 -2
- package/dist/core/index.mjs +1268 -1
- package/dist/react/index.d.mts +349 -3
- package/dist/react/index.mjs +1292 -209
- package/package.json +26 -12
- package/dist/codemod/cli.mjs.map +0 -1
- package/dist/codemod/transforms/data-attrs.d.mts.map +0 -1
- package/dist/codemod/transforms/data-attrs.mjs.map +0 -1
- package/dist/codemod/transforms/forward-ref.d.mts.map +0 -1
- package/dist/codemod/transforms/forward-ref.mjs.map +0 -1
- package/dist/codemod/transforms/import-rewrite.d.mts.map +0 -1
- package/dist/codemod/transforms/import-rewrite.mjs.map +0 -1
- package/dist/codemod/transforms/should-filter.d.mts.map +0 -1
- package/dist/codemod/transforms/should-filter.mjs.map +0 -1
- package/dist/core-CgQYpHK3.mjs +0 -1235
- package/dist/core-CgQYpHK3.mjs.map +0 -1
- package/dist/index-C6g94P7V.d.mts +0 -563
- package/dist/index-C6g94P7V.d.mts.map +0 -1
- package/dist/react/index.d.mts.map +0 -1
- package/dist/react/index.mjs.map +0 -1
- /package/{src → dist}/react/styles.css +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core-CgQYpHK3.mjs","names":["#store","#disposed","#store","#storage","#namespace","#config","#data","#dirty","#enabled","#attachGlobalListener","#bindings","#globalListener","#detachGlobalListener","#cachedItems","#cachedGroups","#items","#itemOrderSet","#itemOrder","#invalidateCache","#groups","#invalidateGroupCache","#listeners"],"sources":["../src/core/frecency/idb-storage.ts","../src/core/types.ts","../src/core/frecency/memory-storage.ts","../src/core/frecency/index.ts","../src/core/keyboard/matcher.ts","../src/core/keyboard/parser.ts","../src/core/keyboard/index.ts","../src/core/registry.ts","../src/core/search/default-scorer.ts","../src/core/search/index.ts","../src/core/utils/event-emitter.ts","../src/core/utils/scheduler.ts","../src/core/machine.ts","../src/core/search/fuzzy-scorer.ts","../src/core/telemetry.ts"],"sourcesContent":["// packages/command/src/frecency/idb-storage.ts\n// IndexedDB-backed frecency persistence — idb-keyval 6.2.2\n// Implements both Disposable and AsyncDisposable for await using support\n// ES2026: Iterator Helpers, Temporal, using/await using\n\nimport { createStore, del, get, set, type UseStore } from 'idb-keyval';\nimport type { FrecencyData, FrecencyRecord, FrecencyStorage, ItemId } from '../types.js';\n\n/** JSON-safe serialized form of a FrecencyRecord */\ninterface SerializedFrecencyRecord {\n readonly frequency: number;\n /** Temporal.Instant epochNanoseconds as string (bigint serialization) */\n readonly lastUsedNs: string;\n}\n\n/** JSON-safe serialized form of FrecencyData stored in IndexedDB */\ninterface SerializedFrecencyData {\n readonly records: ReadonlyArray<readonly [string, SerializedFrecencyRecord]>;\n}\n\n/** Serialize a FrecencyRecord to a JSON-safe format */\nfunction serializeRecord(record: FrecencyRecord): SerializedFrecencyRecord {\n return {\n frequency: record.frequency,\n lastUsedNs: record.lastUsed.epochNanoseconds.toString(),\n };\n}\n\n/** Deserialize a FrecencyRecord from its JSON-safe form */\nfunction deserializeRecord(serialized: SerializedFrecencyRecord): FrecencyRecord {\n return {\n frequency: serialized.frequency,\n lastUsed: Temporal.Instant.fromEpochNanoseconds(BigInt(serialized.lastUsedNs)),\n };\n}\n\n/** Serialize FrecencyData for IndexedDB storage — uses Iterator Helpers */\nfunction serializeData(data: FrecencyData): SerializedFrecencyData {\n return {\n records: data.records\n .entries()\n .map(([id, record]) => [id, serializeRecord(record)] as const)\n .toArray(),\n };\n}\n\n/** Deserialize FrecencyData from IndexedDB storage — uses Iterator Helpers */\nfunction deserializeData(serialized: SerializedFrecencyData): FrecencyData {\n const entries = serialized.records\n .values()\n .map(([id, record]) => [id as ItemId, deserializeRecord(record)] as const)\n .toArray();\n\n return {\n records: new Map<ItemId, FrecencyRecord>(entries),\n };\n}\n\n/** Build the namespaced IDB key — String.toWellFormed() (ES2026) ensures valid Unicode in key */\nfunction storageKey(namespace: string): string {\n const safeNamespace = namespace.isWellFormed() ? namespace : namespace.toWellFormed();\n return `frecency:${safeNamespace}`;\n}\n\n/**\n * IndexedDB-backed frecency storage using idb-keyval 6.2.2.\n *\n * Persists frecency data across browser sessions. Implements both\n * `Disposable` and `AsyncDisposable` for use with `using` and `await using`.\n *\n * @example\n * ```ts\n * await using storage = new IdbFrecencyStorage();\n * const data = await storage.load('my-app');\n * ```\n */\nexport class IdbFrecencyStorage implements FrecencyStorage, AsyncDisposable {\n readonly #store: UseStore | undefined;\n #disposed = false;\n\n /**\n * Create an IDB-backed frecency storage.\n *\n * @param dbName — IndexedDB database name (default: 'modern-cmdk')\n * @param storeName — IndexedDB object store name (default: 'frecency')\n */\n constructor(dbName: string = 'modern-cmdk', storeName: string = 'frecency') {\n this.#store = createStore(dbName, storeName);\n }\n\n /** Load frecency data from IndexedDB for the given namespace */\n async load(namespace: string): Promise<FrecencyData> {\n if (this.#disposed) {\n return { records: new Map<ItemId, FrecencyRecord>() };\n }\n\n const key = storageKey(namespace);\n const serialized = await get<SerializedFrecencyData>(key, this.#store);\n\n if (!serialized) {\n return { records: new Map<ItemId, FrecencyRecord>() };\n }\n\n return deserializeData(serialized);\n }\n\n /** Save frecency data to IndexedDB for the given namespace */\n async save(namespace: string, data: FrecencyData): Promise<void> {\n if (this.#disposed) return;\n\n const key = storageKey(namespace);\n const serialized = serializeData(data);\n await set(key, serialized, this.#store);\n }\n\n /** Delete frecency data for a namespace from IndexedDB */\n async delete(namespace: string): Promise<void> {\n if (this.#disposed) return;\n\n const key = storageKey(namespace);\n await del(key, this.#store);\n }\n\n /** Synchronous dispose — marks as disposed (best-effort cleanup) */\n [Symbol.dispose](): void {\n this.#disposed = true;\n }\n\n /** Async dispose — marks as disposed, suitable for `await using` */\n async [Symbol.asyncDispose](): Promise<void> {\n this.#disposed = true;\n }\n}\n","// packages/command/src/types.ts\n// TypeScript 6.0.1-rc — ES2026 target — all modern type features\n// Branded types, const type params, NoInfer<T>, satisfies on values, Temporal\n\n/**\n * Branded type for command item IDs.\n * Prevents accidental mixing with plain strings at the type level.\n *\n * @example\n * ```ts\n * const id = itemId('copy');\n * // id has type ItemId, not string — catches type errors at compile time\n * ```\n */\ndeclare const __itemIdBrand: unique symbol;\nexport type ItemId = string & { readonly [__itemIdBrand]: never };\n\n/**\n * Branded type for group IDs.\n * Prevents accidental mixing with plain strings or ItemId at the type level.\n */\ndeclare const __groupIdBrand: unique symbol;\nexport type GroupId = string & { readonly [__groupIdBrand]: never };\n\n/** Create a branded {@link ItemId} from a plain string. Ensures well-formed Unicode (ES2026). */\nexport function itemId(id: string): ItemId {\n return (id.isWellFormed() ? id : id.toWellFormed()) as ItemId;\n}\n\n/** Create a branded {@link GroupId} from a plain string. Ensures well-formed Unicode (ES2026). */\nexport function groupId(id: string): GroupId {\n return (id.isWellFormed() ? id : id.toWellFormed()) as GroupId;\n}\n\n/**\n * A registered command item in the palette.\n * All fields are readonly — state machine creates new items on update.\n */\nexport interface CommandItem {\n /** Unique identifier (branded type) */\n readonly id: ItemId;\n /** Display text — also used as the primary search target */\n readonly value: string;\n /** Additional searchable terms (matched but not displayed) */\n readonly keywords?: readonly string[] | undefined;\n /** Group this item belongs to (items without groupId are ungrouped) */\n readonly groupId?: GroupId | undefined;\n /** Keyboard shortcut string (e.g., \"Ctrl+C\", \"Mod+K\") */\n readonly shortcut?: string | undefined;\n /** Whether this item is disabled (excluded from filtering and selection) */\n readonly disabled?: boolean | undefined;\n /** Callback fired when this item is selected */\n readonly onSelect?: (() => void) | undefined;\n /** Arbitrary metadata attached to the item */\n readonly data?: Readonly<Record<string, unknown>> | undefined;\n}\n\n/**\n * A command group for categorizing items.\n * Groups are rendered with headings and sorted by priority.\n */\nexport interface CommandGroup {\n /** Unique identifier (branded type) */\n readonly id: GroupId;\n /** Display heading text (rendered above the group's items) */\n readonly heading?: string | undefined;\n /** Sort priority — lower values appear first (default: 0) */\n readonly priority?: number | undefined;\n}\n\n/**\n * Immutable state snapshot of the command palette.\n * Consumed by React via `useSyncExternalStore` — each mutation\n * produces a new object reference for efficient re-render detection.\n */\nexport interface CommandState {\n /** Current search query string */\n readonly search: string;\n /** Currently active (highlighted) item ID, or null if none */\n readonly activeId: ItemId | null;\n /** Ordered list of item IDs that pass the current filter */\n readonly filteredIds: readonly ItemId[];\n /** Map of group IDs to their visible item IDs */\n readonly groupedIds: ReadonlyMap<GroupId, readonly ItemId[]>;\n /** Count of visible items (shortcut for `filteredIds.length`) */\n readonly filteredCount: number;\n /** Whether async items are currently loading */\n readonly loading: boolean;\n /** Current page identifier (for multi-page navigation) */\n readonly page: string;\n /** Stack of previous pages for back-navigation */\n readonly pageStack: readonly string[];\n /** Whether the command palette dialog is open */\n readonly open: boolean;\n /** Temporal.Instant of the last state mutation (ES2026) */\n readonly lastUpdated: Temporal.Instant;\n}\n\n/** All possible events the state machine accepts */\nexport type CommandEvent =\n | { readonly type: 'SEARCH_CHANGE'; readonly query: string }\n | { readonly type: 'ITEM_SELECT'; readonly id: ItemId }\n | { readonly type: 'ITEM_ACTIVATE'; readonly id: ItemId }\n | { readonly type: 'NAVIGATE'; readonly direction: 'next' | 'prev' | 'first' | 'last' }\n | { readonly type: 'PAGE_PUSH'; readonly page: string }\n | { readonly type: 'PAGE_POP' }\n | { readonly type: 'OPEN' }\n | { readonly type: 'CLOSE' }\n | { readonly type: 'TOGGLE' }\n | { readonly type: 'ITEMS_LOADED'; readonly items: readonly CommandItem[] }\n | { readonly type: 'REGISTER_ITEM'; readonly item: CommandItem }\n | { readonly type: 'UNREGISTER_ITEM'; readonly id: ItemId }\n | { readonly type: 'REGISTER_GROUP'; readonly group: CommandGroup }\n | { readonly type: 'UNREGISTER_GROUP'; readonly id: GroupId };\n\n/** Frecency record for a single item */\nexport interface FrecencyRecord {\n readonly frequency: number;\n readonly lastUsed: Temporal.Instant;\n}\n\n/** Complete frecency data for persistence */\nexport interface FrecencyData {\n readonly records: ReadonlyMap<ItemId, FrecencyRecord>;\n}\n\n/** Pluggable frecency storage interface */\nexport interface FrecencyStorage extends Disposable {\n load(namespace: string): FrecencyData | Promise<FrecencyData>;\n save(namespace: string, data: FrecencyData): void | Promise<void>;\n [Symbol.dispose](): void;\n}\n\n/** Frecency exponential decay bucket configuration */\nexport interface FrecencyDecayConfig {\n readonly hourWeight?: number | undefined;\n readonly dayWeight?: number | undefined;\n readonly weekWeight?: number | undefined;\n readonly monthWeight?: number | undefined;\n readonly olderWeight?: number | undefined;\n}\n\n/** Frecency configuration options */\nexport interface FrecencyOptions {\n readonly enabled: boolean;\n readonly storage?: FrecencyStorage | undefined;\n readonly namespace?: string | undefined;\n readonly decayConfig?: FrecencyDecayConfig | undefined;\n}\n\n/** Default frecency decay configuration — satisfies on value, not interface */\nexport const DEFAULT_FRECENCY_DECAY: Required<FrecencyDecayConfig> = {\n hourWeight: 4.0,\n dayWeight: 2.0,\n weekWeight: 1.5,\n monthWeight: 1.0,\n olderWeight: 0.5,\n} as const satisfies Required<FrecencyDecayConfig>;\n\n/** Options for creating a command machine — const type param for narrowed option inference */\nexport interface CommandMachineOptions {\n /** Pre-registered items to populate on creation */\n readonly items?: readonly CommandItem[] | undefined;\n /** Pre-registered groups for item categorization */\n readonly groups?: readonly CommandGroup[] | undefined;\n /** Custom filter function, or `false` to disable filtering entirely */\n readonly filter?:\n | ((item: CommandItem, query: NoInfer<string>) => number | false)\n | false\n | undefined;\n /** Accessible label for the command palette */\n readonly label?: string | undefined;\n /** Initial open state */\n readonly open?: boolean | undefined;\n /** Frecency configuration for usage-aware ranking */\n readonly frecency?: FrecencyOptions | undefined;\n /** Pluggable search engine — drop-in replacement for the default scorer (e.g., WASM engine) */\n readonly search?: import('./search/types.js').SearchEngine | undefined;\n /** Callback fired when an item is selected */\n readonly onSelect?: ((id: NoInfer<ItemId>) => void) | undefined;\n /** Callback fired when the active (highlighted) item changes */\n readonly onActiveChange?: ((id: NoInfer<ItemId | null>) => void) | undefined;\n /** Callback fired when the dialog open state changes */\n readonly onOpenChange?: ((open: boolean) => void) | undefined;\n /** Callback fired when the search query changes */\n readonly onSearchChange?: ((query: string) => void) | undefined;\n /** Whether keyboard navigation loops from last to first item (default: true) */\n readonly loop?: boolean | undefined;\n /** Item count threshold for automatic virtualization (default: 100) */\n readonly virtualizeThreshold?: number | undefined;\n}\n\n/** Default machine options — satisfies on value */\nexport const DEFAULT_MACHINE_OPTIONS: Partial<CommandMachineOptions> = {\n loop: true,\n virtualizeThreshold: 100,\n open: false,\n} as const satisfies Partial<CommandMachineOptions>;\n\n/** Initial state factory */\nexport function createInitialState(options?: CommandMachineOptions): CommandState {\n return {\n search: '',\n activeId: null,\n filteredIds: [],\n groupedIds: new Map(),\n filteredCount: 0,\n loading: false,\n page: 'root',\n pageStack: [],\n open: options?.open ?? false,\n lastUpdated: Temporal.Now.instant(),\n };\n}\n","// packages/command/src/frecency/memory-storage.ts\n// In-memory storage (default) — Map with Iterator.prototype.toArray()\n\nimport type { FrecencyData, FrecencyRecord, FrecencyStorage, ItemId } from '../types.js';\n\n/**\n * In-memory implementation of FrecencyStorage using a Map.\n * Data does not persist across page reloads. Suitable for ephemeral\n * sessions or as the default when no persistent storage is configured.\n */\nexport class MemoryFrecencyStorage implements FrecencyStorage {\n #store = new Map<string, FrecencyData>();\n\n load(namespace: string): FrecencyData {\n return this.#store.get(namespace) ?? { records: new Map<ItemId, FrecencyRecord>() };\n }\n\n save(namespace: string, data: FrecencyData): void {\n this.#store.set(namespace, data);\n }\n\n /** Serialize all stored data — Iterator Helpers pipeline (ES2026) */\n toJSON(): Record<string, { records: Array<[string, FrecencyRecord]> }> {\n return Object.fromEntries(\n this.#store\n .entries()\n .map(([namespace, data]) => [namespace, { records: data.records.entries().toArray() }]),\n );\n }\n\n [Symbol.dispose](): void {\n this.#store.clear();\n }\n}\n","// packages/command/src/frecency/index.ts\n// Uses: Temporal (ES2026), Iterator Helpers, Temporal.Duration for readable bucket boundaries\n\nimport type {\n FrecencyData,\n FrecencyDecayConfig,\n FrecencyOptions,\n FrecencyRecord,\n FrecencyStorage,\n ItemId,\n} from '../types.js';\nimport { DEFAULT_FRECENCY_DECAY } from '../types.js';\nimport { MemoryFrecencyStorage } from './memory-storage.js';\n\n/** Shared empty bonus map — avoids allocation when no frecency records exist */\nconst EMPTY_BONUS_MAP: ReadonlyMap<ItemId, number> = new Map();\n\n/** Pre-computed bucket boundaries in hours — avoids Duration.total() per call */\nconst BUCKET_HOURS = {\n hour: 1,\n day: 24,\n week: 7 * 24,\n month: 30 * 24,\n} as const;\n\n/**\n * Computes a frecency bonus for an item based on usage frequency and recency.\n * Uses Temporal.Duration bucket boundaries (hour/day/week/month) with\n * configurable exponential decay weights per time bucket.\n */\nexport function computeFrecencyBonus(\n history: FrecencyRecord,\n now: Temporal.Instant = Temporal.Now.instant(),\n config: FrecencyDecayConfig = DEFAULT_FRECENCY_DECAY,\n): number {\n const elapsed = now.since(history.lastUsed);\n const hours = elapsed.total('hours');\n\n const {\n hourWeight = 4.0,\n dayWeight = 2.0,\n weekWeight = 1.5,\n monthWeight = 1.0,\n olderWeight = 0.5,\n } = config;\n\n // Exponential decay with pre-computed bucket boundaries\n const recencyWeight =\n hours < BUCKET_HOURS.hour\n ? hourWeight\n : hours < BUCKET_HOURS.day\n ? dayWeight\n : hours < BUCKET_HOURS.week\n ? weekWeight\n : hours < BUCKET_HOURS.month\n ? monthWeight\n : olderWeight;\n\n return history.frequency * recencyWeight;\n}\n\n/**\n * Stateful frecency engine that tracks item selection history and provides\n * ranking boosts for search results. Supports pluggable storage backends\n * and automatic flush on dispose. Uses Temporal.Now.instant() for timestamps.\n */\nexport class FrecencyEngine implements Disposable {\n #storage: FrecencyStorage;\n #namespace: string;\n #data: FrecencyData;\n #config: FrecencyDecayConfig;\n #dirty = false;\n\n constructor(options: FrecencyOptions) {\n this.#storage = options.storage ?? new MemoryFrecencyStorage();\n this.#namespace = options.namespace ?? 'default';\n this.#config = options.decayConfig ?? DEFAULT_FRECENCY_DECAY;\n this.#data = { records: new Map() };\n }\n\n /** Load frecency data from storage */\n async load(): Promise<void> {\n const data = await this.#storage.load(this.#namespace);\n this.#data = data;\n }\n\n /** Record a selection event for an item */\n recordSelection(itemId: ItemId): void {\n const now = Temporal.Now.instant();\n const existing = this.#data.records.get(itemId);\n\n const updated: FrecencyRecord = {\n frequency: (existing?.frequency ?? 0) + 1,\n lastUsed: now,\n };\n\n // Mutate internal map directly — ReadonlyMap is a compile-time constraint only\n (this.#data.records as Map<ItemId, FrecencyRecord>).set(itemId, updated);\n this.#dirty = true;\n }\n\n /** Get frecency bonus for an item */\n getBonus(itemId: ItemId, now?: Temporal.Instant): number {\n const record = this.#data.records.get(itemId);\n if (!record) return 0;\n return computeFrecencyBonus(record, now, this.#config);\n }\n\n /** Get all frecency bonuses as a map — for...of for hot ranking path (no closure overhead) */\n getAllBonuses(now: Temporal.Instant = Temporal.Now.instant()): ReadonlyMap<ItemId, number> {\n if (this.#data.records.size === 0) return EMPTY_BONUS_MAP;\n const bonuses = new Map<ItemId, number>();\n for (const [id, record] of this.#data.records) {\n bonuses.set(id, computeFrecencyBonus(record, now, this.#config));\n }\n return bonuses;\n }\n\n /** Get the decay configuration */\n getConfig(): FrecencyDecayConfig {\n return this.#config;\n }\n\n /** Update decay configuration at runtime */\n setConfig(config: FrecencyDecayConfig): void {\n this.#config = { ...this.#config, ...config };\n }\n\n /** Flush dirty data to storage */\n async flush(): Promise<void> {\n if (!this.#dirty) return;\n await this.#storage.save(this.#namespace, this.#data);\n this.#dirty = false;\n }\n\n /** Get the raw frecency data */\n getData(): FrecencyData {\n return this.#data;\n }\n\n [Symbol.dispose](): void {\n // Attempt to flush synchronously (best effort for memory storage)\n if (this.#dirty) {\n const result = this.#storage.save(this.#namespace, this.#data);\n if (result instanceof Promise) {\n // Can't await in dispose — fire and forget for async storage\n result.catch(() => {\n // Silently ignore — data loss is acceptable on dispose\n });\n }\n }\n this.#storage[Symbol.dispose]();\n }\n}\n","// packages/command/src/keyboard/matcher.ts\n// KeyboardEvent → Shortcut matcher — Map.groupBy (ES2026) for conflict detection\n\nimport type { ParsedShortcut } from './parser.js';\n\n/**\n * Tests whether a KeyboardEvent exactly matches a ParsedShortcut,\n * comparing all four modifier keys (meta, ctrl, shift, alt) and the primary key.\n */\nexport function matchesShortcut(event: KeyboardEvent, shortcut: ParsedShortcut): boolean {\n // Check modifier keys\n if (shortcut.meta !== event.metaKey) return false;\n if (shortcut.ctrl !== event.ctrlKey) return false;\n if (shortcut.shift !== event.shiftKey) return false;\n if (shortcut.alt !== event.altKey) return false;\n\n // Check the primary key\n const eventKey = event.key.toLowerCase();\n return eventKey === shortcut.key;\n}\n\n/** Match a KeyboardEvent against a list of shortcuts — Iterator Helpers .find() */\nexport function findMatchingShortcut(\n event: KeyboardEvent,\n shortcuts: readonly ParsedShortcut[],\n): ParsedShortcut | null {\n return shortcuts.values().find((shortcut) => matchesShortcut(event, shortcut)) ?? null;\n}\n\n/**\n * Detects conflicting shortcut bindings by grouping on their normalized form\n * via Map.groupBy (ES2026). Returns only groups with two or more colliding shortcuts.\n * Map.groupBy returns a Map directly — no Object.entries conversion needed.\n */\nexport function detectConflicts(\n shortcuts: readonly ParsedShortcut[],\n): ReadonlyMap<string, readonly ParsedShortcut[]> {\n // Map.groupBy (ES2026) — returns Map<string, ParsedShortcut[]> directly\n const grouped = Map.groupBy(shortcuts, (s) => s.normalized);\n\n // Iterator Helpers pipeline — filter to only conflicting groups (2+ collisions)\n return new Map(\n grouped.entries().filter((entry): entry is [string, ParsedShortcut[]] => entry[1].length > 1),\n );\n}\n","// packages/command/src/keyboard/parser.ts\n// Shortcut string parser (\"Mod+K\")\n\n/**\n * Structured representation of a keyboard shortcut after parsing.\n * The `normalized` field provides a deterministic string for dedup and comparison.\n */\nexport interface ParsedShortcut {\n readonly key: string;\n readonly meta: boolean;\n readonly ctrl: boolean;\n readonly shift: boolean;\n readonly alt: boolean;\n readonly raw: string;\n readonly normalized: string;\n}\n\n/** Platform detection regex — matches Apple device platform strings */\nconst MAC_PLATFORM_RE: RegExp = /Mac|iPod|iPhone|iPad/;\n\n// Prefer navigator.userAgentData (modern) over deprecated navigator.platform\nconst isMac: boolean =\n typeof navigator !== 'undefined' &&\n ((navigator as { userAgentData?: { platform?: string } }).userAgentData?.platform === 'macOS' ||\n MAC_PLATFORM_RE.test(navigator.platform));\n\n/** Modifier aliases — cross-platform Mod resolution */\nconst MODIFIER_MAP: Readonly<\n Record<string, keyof Pick<ParsedShortcut, 'meta' | 'ctrl' | 'shift' | 'alt'>>\n> = {\n mod: isMac ? 'meta' : 'ctrl',\n meta: 'meta',\n cmd: 'meta',\n command: 'meta',\n ctrl: 'ctrl',\n control: 'ctrl',\n shift: 'shift',\n alt: 'alt',\n option: 'alt',\n opt: 'alt',\n};\n\n/**\n * Parse a shortcut string like \"Mod+Shift+K\" into a structured ParsedShortcut.\n * Uses String.isWellFormed() (ES2026) to ensure valid Unicode input.\n */\nexport function parseShortcut(shortcut: string): ParsedShortcut {\n // String.isWellFormed() (ES2026) — validate Unicode before processing\n const safeShortcut = shortcut.isWellFormed() ? shortcut : shortcut.toWellFormed();\n\n const parts = safeShortcut.split('+').map((p) => p.trim().toLowerCase());\n\n let meta = false;\n let ctrl = false;\n let shift = false;\n let alt = false;\n let key = '';\n\n for (const part of parts) {\n const modifier = MODIFIER_MAP[part];\n if (modifier) {\n switch (modifier) {\n case 'meta':\n meta = true;\n break;\n case 'ctrl':\n ctrl = true;\n break;\n case 'shift':\n shift = true;\n break;\n case 'alt':\n alt = true;\n break;\n }\n } else {\n key = part;\n }\n }\n\n // Build normalized string — deterministic modifier order for dedup/comparison\n const modifiers: string[] = [];\n if (meta) modifiers.push('meta');\n if (ctrl) modifiers.push('ctrl');\n if (shift) modifiers.push('shift');\n if (alt) modifiers.push('alt');\n modifiers.push(key);\n\n return {\n key,\n meta,\n ctrl,\n shift,\n alt,\n raw: safeShortcut,\n normalized: modifiers.join('+'),\n };\n}\n\n/**\n * Formats a ParsedShortcut for display using platform-appropriate symbols.\n * On macOS: renders glyphs (⌘, ⇧, ⌥, ⌃). On other platforms: text labels joined by \"+\".\n */\nexport function formatShortcut(parsed: ParsedShortcut): string {\n const parts: string[] = [];\n\n if (parsed.meta) parts.push(isMac ? '\\u2318' : 'Ctrl');\n if (parsed.ctrl && !(!isMac && parsed.meta)) parts.push(isMac ? '\\u2303' : 'Ctrl');\n if (parsed.shift) parts.push(isMac ? '\\u21E7' : 'Shift');\n if (parsed.alt) parts.push(isMac ? '\\u2325' : 'Alt');\n\n // Capitalize key for display\n const displayKey =\n parsed.key.length === 1\n ? parsed.key.toUpperCase()\n : parsed.key.charAt(0).toUpperCase() + parsed.key.slice(1);\n\n parts.push(displayKey);\n\n return isMac ? parts.join('') : parts.join('+');\n}\n","// packages/command/src/keyboard/index.ts\n// Keyboard shortcut registry — `using` for listener cleanup\n\nimport type { ItemId } from '../types.js';\nimport { detectConflicts, matchesShortcut } from './matcher.js';\nimport type { ParsedShortcut } from './parser.js';\nimport { parseShortcut } from './parser.js';\n\nexport { detectConflicts, findMatchingShortcut, matchesShortcut } from './matcher.js';\nexport { formatShortcut, parseShortcut } from './parser.js';\n\ninterface ShortcutBinding {\n readonly shortcut: ParsedShortcut;\n readonly itemId: ItemId;\n readonly handler: () => void;\n}\n\n/**\n * Manages keyboard shortcut bindings with global keydown listening.\n * Supports `using` for automatic cleanup of both individual bindings and the\n * global document listener. Detects conflicts via Map.groupBy (ES2026).\n */\nexport class KeyboardShortcutRegistry implements Disposable {\n #bindings = new Map<string, ShortcutBinding>();\n #globalListener: ((event: KeyboardEvent) => void) | null = null;\n #enabled = true;\n\n constructor(options?: { enabled?: boolean }) {\n this.#enabled = options?.enabled ?? true;\n this.#attachGlobalListener();\n }\n\n /** Register a shortcut binding — returns Disposable for `using` auto-deregister */\n register(shortcutStr: string, itemId: ItemId, handler: () => void): Disposable {\n const shortcut = parseShortcut(shortcutStr);\n\n this.#bindings.set(shortcut.normalized, {\n shortcut,\n itemId,\n handler,\n });\n\n return {\n [Symbol.dispose]: (): void => {\n this.#bindings.delete(shortcut.normalized);\n },\n };\n }\n\n /** Unregister a shortcut by its string representation */\n unregister(shortcutStr: string): void {\n const shortcut = parseShortcut(shortcutStr);\n this.#bindings.delete(shortcut.normalized);\n }\n\n /** Unregister all shortcuts for a given item — Map spec allows deletion during iteration */\n unregisterByItem(itemId: ItemId): void {\n for (const [key, binding] of this.#bindings) {\n if (binding.itemId === itemId) this.#bindings.delete(key);\n }\n }\n\n /** Check for conflicting shortcuts */\n getConflicts(): ReadonlyMap<string, readonly ParsedShortcut[]> {\n const shortcuts = this.#bindings\n .values()\n .map((b) => b.shortcut)\n .toArray();\n return detectConflicts(shortcuts);\n }\n\n /** Enable or disable global shortcut listening */\n setEnabled(enabled: boolean): void {\n this.#enabled = enabled;\n }\n\n /** Get all registered bindings */\n getBindings(): ReadonlyMap<string, ShortcutBinding> {\n return this.#bindings;\n }\n\n #attachGlobalListener(): void {\n if (typeof document === 'undefined') return;\n\n this.#globalListener = (event: KeyboardEvent): void => {\n if (!this.#enabled) return;\n\n // for...of — hot keydown path, short-circuits on first match (no closure overhead)\n for (const binding of this.#bindings.values()) {\n if (matchesShortcut(event, binding.shortcut)) {\n event.preventDefault();\n event.stopPropagation();\n binding.handler();\n return;\n }\n }\n };\n\n document.addEventListener('keydown', this.#globalListener);\n }\n\n #detachGlobalListener(): void {\n if (this.#globalListener && typeof document !== 'undefined') {\n document.removeEventListener('keydown', this.#globalListener);\n this.#globalListener = null;\n }\n }\n\n [Symbol.dispose](): void {\n this.#detachGlobalListener();\n this.#bindings.clear();\n }\n}\n","// packages/command/src/registry.ts\n// Command/item registration — Set methods (union/intersection/difference) for ID management\n// Performance: O(1) registration/lookup via Map + Set, O(1) order tracking via array + Set guard\n\nimport type { CommandGroup, CommandItem, GroupId, ItemId } from './types.js';\n\n/**\n * Manages registration and lookup of command items and groups.\n * Uses ES2026 Set methods (union/intersection/difference) for efficient ID operations.\n * All registration methods return Disposable for automatic cleanup via `using`.\n */\nexport class CommandRegistry implements Disposable {\n #items = new Map<ItemId, CommandItem>();\n #groups = new Map<GroupId, CommandGroup>();\n #itemOrder: ItemId[] = [];\n #itemOrderSet = new Set<ItemId>(); // O(1) duplicate check during registration\n #cachedItems: readonly CommandItem[] | null = null; // Invalidated on mutation\n #cachedGroups: readonly CommandGroup[] | null = null; // Invalidated on group mutation\n\n #invalidateCache(): void {\n this.#cachedItems = null;\n }\n\n #invalidateGroupCache(): void {\n this.#cachedGroups = null;\n }\n\n /** Register an item — returns Disposable for `using` auto-deregister */\n registerItem(item: CommandItem): Disposable {\n this.#items.set(item.id, item);\n if (!this.#itemOrderSet.has(item.id)) {\n this.#itemOrder.push(item.id);\n this.#itemOrderSet.add(item.id);\n }\n this.#invalidateCache();\n\n return {\n [Symbol.dispose]: (): void => {\n this.unregisterItem(item.id);\n },\n };\n }\n\n /** Register multiple items at once — single Disposable for batch cleanup. for...of for hot path. */\n registerItems(items: readonly CommandItem[]): Disposable {\n for (const item of items) {\n this.#items.set(item.id, item);\n if (!this.#itemOrderSet.has(item.id)) {\n this.#itemOrder.push(item.id);\n this.#itemOrderSet.add(item.id);\n }\n }\n this.#invalidateCache();\n\n const ids = new Set(items.values().map((i) => i.id));\n return {\n [Symbol.dispose]: (): void => {\n for (const id of ids) this.unregisterItem(id);\n },\n };\n }\n\n /** Unregister a single item — O(1) Map delete + Set delete, O(n) order rebuild */\n unregisterItem(id: ItemId): void {\n if (!this.#items.has(id)) return;\n this.#items.delete(id);\n this.#itemOrderSet.delete(id);\n this.#itemOrder = this.#itemOrder.filter((orderId) => orderId !== id);\n this.#invalidateCache();\n }\n\n /** Bulk unregister using Set.difference (ES2026) — for...of for hot path */\n unregisterItems(ids: ReadonlySet<ItemId>): void {\n for (const id of ids) {\n this.#items.delete(id);\n }\n this.#itemOrderSet = this.#itemOrderSet.difference(ids);\n this.#itemOrder = this.#itemOrder.filter((id) => !ids.has(id));\n this.#invalidateCache();\n }\n\n /** Register a group */\n registerGroup(group: CommandGroup): Disposable {\n this.#groups.set(group.id, group);\n this.#invalidateGroupCache();\n return {\n [Symbol.dispose]: (): void => {\n this.#groups.delete(group.id);\n this.#invalidateGroupCache();\n },\n };\n }\n\n /** Unregister a group */\n unregisterGroup(id: GroupId): void {\n this.#groups.delete(id);\n this.#invalidateGroupCache();\n }\n\n /** Get an item by ID — O(1) */\n getItem(id: ItemId): CommandItem | undefined {\n return this.#items.get(id);\n }\n\n /** Get a group by ID — O(1) */\n getGroup(id: GroupId): CommandGroup | undefined {\n return this.#groups.get(id);\n }\n\n /** Get all registered items in insertion order — cached between mutations */\n getItems(): readonly CommandItem[] {\n if (this.#cachedItems !== null) return this.#cachedItems;\n this.#cachedItems = this.#itemOrder\n .values()\n .map((id) => this.#items.get(id))\n .filter((item): item is CommandItem => item != null)\n .toArray();\n return this.#cachedItems;\n }\n\n /** Get all registered groups sorted by priority — cached between group mutations */\n getGroups(): readonly CommandGroup[] {\n if (this.#cachedGroups !== null) return this.#cachedGroups;\n this.#cachedGroups = this.#groups\n .values()\n .toArray()\n .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));\n return this.#cachedGroups;\n }\n\n /** Get items grouped by groupId using Map.groupBy (ES2026) — direct Map, no Object.entries conversion */\n getGroupedItems(): ReadonlyMap<GroupId, readonly CommandItem[]> {\n const items = this.getItems();\n // Map.groupBy (ES2026) — returns Map<GroupId, CommandItem[]> directly\n const grouped = Map.groupBy(items, (item) => item.groupId ?? ('__ungrouped' as GroupId));\n\n // Build result in group priority order, then append ungrouped\n const result = new Map<GroupId, readonly CommandItem[]>();\n\n for (const group of this.getGroups()) {\n const groupItems = grouped.get(group.id);\n if (groupItems != null) {\n result.set(group.id, groupItems);\n }\n }\n\n // Add ungrouped items\n const ungrouped = grouped.get('__ungrouped' as GroupId);\n if (ungrouped) {\n result.set('__ungrouped' as GroupId, ungrouped);\n }\n\n return result;\n }\n\n /** Get item IDs as a Set — returns internal set (O(1), no allocation) */\n getItemIds(): ReadonlySet<ItemId> {\n return this.#itemOrderSet;\n }\n\n /** Find intersection of registered items with a candidate set (ES2026 Set.intersection) */\n intersectWith(candidateIds: ReadonlySet<ItemId>): ReadonlySet<ItemId> {\n return this.#itemOrderSet.intersection(candidateIds);\n }\n\n /** Find items registered but not in a given set (ES2026 Set.difference) */\n differenceFrom(otherIds: ReadonlySet<ItemId>): ReadonlySet<ItemId> {\n return this.#itemOrderSet.difference(otherIds);\n }\n\n /** Union of registered IDs with another set (ES2026 Set.union) */\n unionWith(otherIds: ReadonlySet<ItemId>): ReadonlySet<ItemId> {\n return this.#itemOrderSet.union(otherIds);\n }\n\n /** Check if registered items are a subset of the given set (ES2026 Set.isSubsetOf) */\n isSubsetOf(otherIds: ReadonlySet<ItemId>): boolean {\n return this.#itemOrderSet.isSubsetOf(otherIds);\n }\n\n /** Check if registered items are a superset of the given set (ES2026 Set.isSupersetOf) */\n isSupersetOf(otherIds: ReadonlySet<ItemId>): boolean {\n return this.#itemOrderSet.isSupersetOf(otherIds);\n }\n\n /** Check if registered items share no IDs with the given set (ES2026 Set.isDisjointFrom) */\n isDisjointFrom(otherIds: ReadonlySet<ItemId>): boolean {\n return this.#itemOrderSet.isDisjointFrom(otherIds);\n }\n\n /** Symmetric difference between registered IDs and another set (ES2026 Set.symmetricDifference) */\n symmetricDifferenceWith(otherIds: ReadonlySet<ItemId>): ReadonlySet<ItemId> {\n return this.#itemOrderSet.symmetricDifference(otherIds);\n }\n\n /** Total number of registered items */\n get size(): number {\n return this.#items.size;\n }\n\n /** Total number of registered groups */\n get groupCount(): number {\n return this.#groups.size;\n }\n\n /** Clear all items and groups */\n clear(): void {\n this.#items.clear();\n this.#groups.clear();\n this.#itemOrder = [];\n this.#itemOrderSet.clear();\n this.#invalidateCache();\n this.#invalidateGroupCache();\n }\n\n [Symbol.dispose](): void {\n this.clear();\n }\n}\n","// packages/command/src/search/default-scorer.ts\n// Hot-path optimized: toLowerCase (not locale), inline iteration, no regex split,\n// plain arithmetic (no Math.sumPrecise on 2-5 values), zero unnecessary allocations.\n// Items validated at itemId() creation — no isWellFormed() re-checks in scoring.\n\nimport type { CommandItem } from '../types.js';\nimport type { SearchResult } from './types.js';\n\n// ── Word boundary detection via charCode — no regex, no split, no allocation ──\nfunction isWordSeparator(code: number): boolean {\n // space(32) tab(9) hyphen(45) underscore(95) period(46) slash(47) backslash(92)\n return (\n code === 32 ||\n code === 9 ||\n code === 45 ||\n code === 95 ||\n code === 46 ||\n code === 47 ||\n code === 92\n );\n}\n\n/**\n * Public API: scores a command item against a search query.\n * Multi-strategy: exact → prefix → substring → word-boundary → fuzzy.\n * Returns null if no match. For batch use, prefer the search engine\n * which pre-caches lowercase and normalizes query once.\n */\nexport function scoreItem(query: string, item: CommandItem): SearchResult | null {\n if (query === '') {\n return { id: item.id, score: 1, matches: [] };\n }\n\n const lowerQuery = query.toLowerCase();\n\n // Inline target iteration — no array allocation\n // Score value first, then keywords, keep best\n let bestScore = 0;\n let bestMatches: Array<readonly [number, number]> | null = null;\n\n const valueResult = scoreTarget(lowerQuery, item.value.toLowerCase());\n if (valueResult !== null) {\n bestScore = valueResult.score;\n bestMatches = valueResult.matches;\n if (bestScore >= 1) return { id: item.id, score: 1, matches: bestMatches };\n }\n\n const kw = item.keywords;\n if (kw !== undefined) {\n for (let i = 0; i < kw.length; i++) {\n const result = scoreTarget(lowerQuery, (kw[i] as string).toLowerCase());\n if (result !== null && result.score > bestScore) {\n bestScore = result.score;\n bestMatches = result.matches;\n if (bestScore >= 1) break;\n }\n }\n }\n\n return bestMatches !== null ? { id: item.id, score: bestScore, matches: bestMatches } : null;\n}\n\n/**\n * Internal fast path: called by search engine with pre-lowered query and targets.\n * Eliminates all toLowerCase() calls on the hot path.\n */\nexport function scoreItemPreLowered(\n lowerQuery: string,\n id: import('../types.js').ItemId,\n lowerValue: string,\n lowerKeywords: readonly string[] | undefined,\n): SearchResult | null {\n let bestScore = 0;\n let bestMatches: Array<readonly [number, number]> | null = null;\n\n const valueResult = scoreTarget(lowerQuery, lowerValue);\n if (valueResult !== null) {\n bestScore = valueResult.score;\n bestMatches = valueResult.matches;\n if (bestScore >= 1) return { id, score: 1, matches: bestMatches };\n }\n\n if (lowerKeywords !== undefined) {\n for (let i = 0; i < lowerKeywords.length; i++) {\n const result = scoreTarget(lowerQuery, lowerKeywords[i] as string);\n if (result !== null && result.score > bestScore) {\n bestScore = result.score;\n bestMatches = result.matches;\n if (bestScore >= 1) break;\n }\n }\n }\n\n return bestMatches !== null ? { id, score: bestScore, matches: bestMatches } : null;\n}\n\nfunction scoreTarget(\n query: string,\n lowerTarget: string,\n): { score: number; matches: Array<readonly [number, number]> } | null {\n const tLen = lowerTarget.length;\n if (tLen === 0) return null;\n\n const qLen = query.length;\n if (qLen === 0) return { score: 1, matches: [] };\n\n // Early bailout: query longer than target can never fully match\n if (qLen > tLen) {\n return scoreFuzzy(query, qLen, lowerTarget, tLen);\n }\n\n // Exact match — highest score\n if (lowerTarget === query) {\n return { score: 1, matches: [[0, qLen]] };\n }\n\n // Starts-with match — very high score\n if (lowerTarget.startsWith(query)) {\n return { score: 0.9 + 0.1 * (qLen / tLen), matches: [[0, qLen]] };\n }\n\n // Substring match — medium-high score with position bonus\n const substringIdx = lowerTarget.indexOf(query);\n if (substringIdx !== -1) {\n const positionBonus = 1 - substringIdx / tLen;\n const lengthRatio = qLen / tLen;\n return {\n score: 0.5 + 0.3 * positionBonus + 0.2 * lengthRatio,\n matches: [[substringIdx, substringIdx + qLen]],\n };\n }\n\n // Word boundary match — charCode scan, no regex, no split\n const wordBoundaryResult = scoreWordBoundary(query, qLen, lowerTarget, tLen);\n if (wordBoundaryResult) return wordBoundaryResult;\n\n // Character-by-character fuzzy match\n return scoreFuzzy(query, qLen, lowerTarget, tLen);\n}\n\nfunction scoreWordBoundary(\n query: string,\n qLen: number,\n lowerTarget: string,\n tLen: number,\n): { score: number; matches: Array<readonly [number, number]> } | null {\n let queryIdx = 0;\n const matches: Array<readonly [number, number]> = [];\n let totalWeightedLen = 0;\n\n // Scan for word starts using charCode — zero allocation\n let i = 0;\n while (i < tLen && queryIdx < qLen) {\n // Detect word start: position 0 or preceded by separator\n const atWordStart = i === 0 || isWordSeparator(lowerTarget.charCodeAt(i - 1));\n\n if (atWordStart && lowerTarget.charCodeAt(i) === query.charCodeAt(queryIdx)) {\n const matchStart = i;\n let matchLen = 0;\n\n // Consume contiguous matching characters within this word\n while (\n queryIdx < qLen &&\n i < tLen &&\n !isWordSeparator(lowerTarget.charCodeAt(i)) &&\n lowerTarget.charCodeAt(i) === query.charCodeAt(queryIdx)\n ) {\n queryIdx++;\n i++;\n matchLen++;\n }\n\n matches.push([matchStart, matchStart + matchLen]);\n totalWeightedLen += matchLen * 2; // Word boundary matches get 2x weight\n } else {\n i++;\n }\n }\n\n if (queryIdx !== qLen) return null;\n\n const maxPossible = qLen * 2;\n\n return {\n score: 0.3 + 0.4 * (totalWeightedLen / maxPossible),\n matches,\n };\n}\n\nfunction scoreFuzzy(\n query: string,\n qLen: number,\n lowerTarget: string,\n tLen: number,\n): { score: number; matches: Array<readonly [number, number]> } | null {\n let queryIdx = 0;\n let targetIdx = 0;\n const matches: Array<readonly [number, number]> = [];\n let currentMatchStart = -1;\n let contiguityScore = 0;\n\n while (queryIdx < qLen && targetIdx < tLen) {\n if (query.charCodeAt(queryIdx) === lowerTarget.charCodeAt(targetIdx)) {\n if (currentMatchStart === -1) {\n currentMatchStart = targetIdx;\n }\n queryIdx++;\n targetIdx++;\n } else {\n if (currentMatchStart !== -1) {\n const segmentLen = targetIdx - currentMatchStart;\n matches.push([currentMatchStart, targetIdx]);\n contiguityScore += segmentLen * segmentLen;\n currentMatchStart = -1;\n }\n targetIdx++;\n }\n }\n\n // Close any remaining match segment\n if (currentMatchStart !== -1) {\n const segmentLen = targetIdx - currentMatchStart;\n matches.push([currentMatchStart, targetIdx]);\n contiguityScore += segmentLen * segmentLen;\n }\n\n // All query chars must be matched\n if (queryIdx !== qLen) return null;\n\n const maxContiguity = qLen * qLen;\n const contiguityRatio = contiguityScore / maxContiguity;\n\n // Position bonus — matches earlier in target are better\n const firstMatchPos = matches[0]?.[0] ?? 0;\n const positionBonus = 1 - firstMatchPos / tLen;\n\n // Length ratio — longer queries matching shorter targets = better\n const lengthRatio = qLen / tLen;\n\n const score = 0.1 + 0.3 * contiguityRatio + 0.15 * positionBonus + 0.1 * lengthRatio;\n\n return { score, matches };\n}\n","// packages/command/src/search/index.ts\n// Search engine factory with pluggable scorer — Iterator Helpers (ES2026) for result pipelines\n// Incremental filtering: query-append optimization using Set.difference for candidate pruning\n// Performance: pre-cached lowercase at index time, charCode comparison, zero redundant allocation\n\nimport type { CommandItem, ItemId } from '../types.js';\nimport { scoreItemPreLowered } from './default-scorer.js';\nimport type { ScorerFn, SearchEngine, SearchResult } from './types.js';\n\n// Dev-only leak detection via FinalizationRegistry — warns if a search engine\n// instance is garbage collected without being explicitly disposed\nconst __DEV__: boolean = (globalThis as Record<string, unknown>).process\n ? ((globalThis as Record<string, unknown>).process as { env: Record<string, string | undefined> })\n .env.NODE_ENV !== 'production'\n : false;\nlet leakRegistry: FinalizationRegistry<string> | undefined;\nif (__DEV__) {\n leakRegistry = new FinalizationRegistry((_label) => {});\n}\n\ninterface SearchEngineOptions {\n readonly scorer?: ScorerFn | undefined;\n}\n\n/** Pre-computed lowercase cache entry — avoids re-lowering on every search */\ninterface IndexedEntry {\n readonly item: CommandItem;\n readonly lowerValue: string;\n readonly lowerKeywords: readonly string[] | undefined;\n}\n\n/**\n * Creates a search engine with pluggable scorer and incremental filtering.\n * When the query extends the previous one, only prior matches are re-scored.\n * Pre-caches lowercase at index time — zero toLowerCase() calls during search.\n * Uses Iterator Helpers (ES2026) for result pipelines and Set.difference for pruning.\n */\nexport function createSearchEngine(options?: SearchEngineOptions): SearchEngine {\n const customScorer: ScorerFn | undefined = options?.scorer;\n const useDefaultScorer = customScorer === undefined;\n\n // Pre-cached lowercase index — avoids toLowerCase() on every search\n const indexedEntries = new Map<ItemId, IndexedEntry>();\n let previousQuery = '';\n let previousResults = new Set<ItemId>();\n\n // Leak detection sentinel — weak reference target for FinalizationRegistry\n const sentinel = {};\n if (__DEV__ && leakRegistry) {\n leakRegistry.register(sentinel, 'SearchEngine', sentinel);\n }\n\n return {\n index(items: readonly CommandItem[]): void {\n // Pre-compute and cache lowercase at index time — one-time cost\n for (const item of items) {\n indexedEntries.set(item.id, {\n item,\n lowerValue: item.value.toLowerCase(),\n lowerKeywords: item.keywords?.map((k) => k.toLowerCase()),\n });\n }\n },\n\n search(query: string, items: readonly CommandItem[]): IteratorObject<SearchResult> {\n if (query === '') {\n previousQuery = '';\n previousResults = new Set(items.values().map((i) => i.id));\n // Return all items with score 1, in order — Iterator Helper pipeline\n return items.values().map((item) => ({\n id: item.id,\n score: 1,\n matches: [] as ReadonlyArray<readonly [number, number]>,\n }));\n }\n\n // Lowercase query ONCE for the entire search — not per-item\n const lowerQuery = query.toLowerCase();\n\n // Incremental filtering: if new query extends previous, only re-score previous matches\n const isIncremental = query.startsWith(previousQuery) && previousQuery.length > 0;\n const candidateItems: Iterable<CommandItem> = isIncremental\n ? items.values().filter((item) => previousResults.has(item.id))\n : items;\n\n // Score candidates — hot path with pre-lowered data\n const results: SearchResult[] = [];\n\n if (useDefaultScorer) {\n // Fast path: use pre-cached lowercase + internal scorer (no toLowerCase per item)\n for (const item of candidateItems) {\n const entry = indexedEntries.get(item.id);\n const result = entry\n ? scoreItemPreLowered(lowerQuery, item.id, entry.lowerValue, entry.lowerKeywords)\n : scoreItemPreLowered(\n lowerQuery,\n item.id,\n item.value.toLowerCase(),\n item.keywords?.map((k) => k.toLowerCase()),\n );\n if (result !== null) results.push(result);\n }\n } else {\n // Custom scorer path — use the user-provided scorer as-is\n for (const item of candidateItems) {\n const result = customScorer(query, item);\n if (result != null) results.push(result);\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n\n // Update tracking for incremental filtering\n previousQuery = query;\n previousResults = new Set(results.values().map((r) => r.id));\n\n // Return sorted results as an iterator\n return results.values();\n },\n\n remove(ids: ReadonlySet<ItemId>): void {\n // O(k) deletes instead of O(n) Map rebuild\n for (const id of ids) {\n indexedEntries.delete(id);\n }\n // Prune incremental cache\n previousResults = previousResults.difference(ids);\n },\n\n clear(): void {\n indexedEntries.clear();\n previousQuery = '';\n previousResults.clear();\n },\n\n [Symbol.dispose](): void {\n indexedEntries.clear();\n previousResults.clear();\n // Unregister from leak detector — this engine was properly disposed\n if (__DEV__ && leakRegistry) {\n leakRegistry.unregister(sentinel);\n }\n },\n };\n}\n","// packages/command/src/utils/event-emitter.ts\n// Type-safe event emitter — strong refs for reliable delivery, `using` for auto-unsub\n// Performance: for...of in hot emit() path, Iterator Helpers for listenerCount()\n\ntype EventMap = { [key: string]: unknown };\n\n/**\n * Type-safe event emitter with strong references and Disposable subscriptions.\n * Returns Disposable from `on()` for automatic unsubscription via `using`.\n */\nexport class TypedEmitter<T extends EventMap> implements Disposable {\n #listeners = new Map<keyof T, Set<(data: never) => void>>();\n\n /** Subscribe to an event. Returns a Disposable that removes the listener when disposed. */\n on<K extends keyof T>(event: K, listener: (data: T[K]) => void): Disposable {\n const set = this.#listeners.get(event) ?? new Set();\n const fn = listener as (data: never) => void;\n set.add(fn);\n this.#listeners.set(event, set);\n\n return {\n [Symbol.dispose]: (): void => {\n set.delete(fn);\n },\n };\n }\n\n /** Emit an event to all listeners. Hot path — for...of, zero allocation. */\n emit<K extends keyof T>(event: K, data: T[K]): void {\n const set = this.#listeners.get(event);\n if (!set) return;\n\n // for...of — hot emit path, avoids closure allocation overhead\n for (const fn of set) {\n fn(data as never);\n }\n }\n\n /** Check if any listeners exist for an event */\n has<K extends keyof T>(event: K): boolean {\n const set = this.#listeners.get(event);\n return set !== undefined && set.size > 0;\n }\n\n /** Get count of listeners for an event */\n listenerCount<K extends keyof T>(event: K): number {\n return this.#listeners.get(event)?.size ?? 0;\n }\n\n /** Remove all listeners */\n removeAll(): void {\n this.#listeners.clear();\n }\n\n [Symbol.dispose](): void {\n this.#listeners.clear();\n }\n}\n","// packages/command/src/utils/scheduler.ts\n// Batched update scheduler — rAF in browsers, queueMicrotask in Node.js/tests\n// Uses scheduler.yield() when available for input-responsive large batches\n\n/**\n * Batched update scheduler that coalesces state updates into a single tick.\n * Uses requestAnimationFrame in browsers, queueMicrotask in Node.js/tests.\n */\nexport interface Scheduler extends Disposable {\n schedule(update: () => void): void;\n flush(): void;\n [Symbol.dispose](): void;\n}\n\n/** Whether we're in a browser environment with rAF available */\nconst hasRAF: boolean = typeof requestAnimationFrame === 'function';\n\n/** Feature detection for cutting-edge scheduling APIs */\nconst canYield: boolean = typeof globalThis.scheduler?.yield === 'function';\nconst hasInputPending: boolean = typeof navigator?.scheduling?.isInputPending === 'function';\n\n/**\n * Creates a batched update scheduler. Coalesces rapid state updates into a single\n * execution pass using rAF (browser) or queueMicrotask (Node.js).\n */\nexport function createScheduler(): Scheduler {\n let pending: Array<() => void> = [];\n let rafId: number | null = null;\n let microtaskScheduled = false;\n\n function executeBatch(): void {\n // Snapshot and clear BEFORE execution — new updates during execution\n // go into a fresh array, preventing the race condition\n const batch = pending;\n pending = [];\n rafId = null;\n microtaskScheduled = false;\n\n // For large batches, check if the browser has pending user input\n // and yield to the main thread to keep the UI responsive\n if (batch.length > 10 && hasInputPending && navigator.scheduling?.isInputPending?.()) {\n // Re-queue unprocessed updates so user input is handled first\n pending = [...batch, ...pending];\n if (canYield) {\n void globalThis.scheduler?.yield?.().then(() => void executeBatch());\n } else {\n rafId ??= requestAnimationFrame(() => void executeBatch());\n }\n return;\n }\n\n // Execute each update with error isolation — one failing update\n // must not kill the rest of the batch\n for (const update of batch) {\n try {\n update();\n } catch (error: unknown) {\n // Report without breaking the batch — use queueMicrotask to throw\n // asynchronously so the error is surfaced but doesn't halt processing\n queueMicrotask(() => {\n throw error;\n });\n }\n }\n }\n\n function flush(): void {\n executeBatch();\n }\n\n return {\n schedule(update: () => void): void {\n pending.push(update);\n\n if (hasRAF) {\n // Browser: coalesce into a single rAF for visual sync\n rafId ??= requestAnimationFrame(() => void executeBatch());\n } else if (!microtaskScheduled) {\n // Node.js/test: use queueMicrotask for fast synchronous-like execution\n microtaskScheduled = true;\n queueMicrotask(executeBatch);\n }\n },\n\n flush,\n\n [Symbol.dispose](): void {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n microtaskScheduled = false;\n pending = [];\n },\n };\n}\n","// packages/command/src/machine.ts\n// Core state machine — pure functions, `using` for subscription cleanup\n// Implements Disposable, useSyncExternalStore-compatible API\n\nimport { FrecencyEngine } from './frecency/index.js';\nimport { KeyboardShortcutRegistry } from './keyboard/index.js';\nimport { CommandRegistry } from './registry.js';\nimport { createSearchEngine } from './search/index.js';\nimport type { SearchEngine, SearchResult } from './search/types.js';\nimport type {\n CommandEvent,\n CommandItem,\n CommandMachineOptions,\n CommandState,\n GroupId,\n ItemId,\n} from './types.js';\nimport { createInitialState } from './types.js';\nimport { TypedEmitter } from './utils/event-emitter.js';\nimport type { Scheduler } from './utils/scheduler.js';\nimport { createScheduler } from './utils/scheduler.js';\n\n/** Events emitted by the machine for external listening */\ntype MachineEvents = {\n stateChange: CommandState;\n select: ItemId;\n openChange: boolean;\n};\n\n/** Command machine — explicit resource management via `using` */\nexport interface CommandMachine extends Disposable {\n getState(): CommandState;\n send(event: CommandEvent): void;\n /** Subscribe to state changes — useSyncExternalStore-compatible (returns cleanup function) */\n subscribe(listener: () => void): () => void;\n /** Subscribe to full state changes — returns Disposable for `using` pattern */\n subscribeState(listener: (state: CommandState) => void): Disposable;\n getRegistry(): CommandRegistry;\n getKeyboardRegistry(): KeyboardShortcutRegistry;\n /** Get the current set of filtered item IDs — O(1) membership checks */\n getFilteredIdSet(): ReadonlySet<ItemId>;\n [Symbol.dispose](): void;\n}\n\n/**\n * Creates a headless command palette state machine with search, frecency,\n * and keyboard shortcut support. Implements Disposable for `using` cleanup.\n *\n * @example\n * ```ts\n * using machine = createCommandMachine({ items, loop: true });\n * machine.subscribe(() => console.log(machine.getState()));\n * ```\n */\nexport function createCommandMachine(options: CommandMachineOptions = {}): CommandMachine {\n let state: CommandState = createInitialState(options);\n\n // O(1) membership check — kept in sync with filteredIds\n let filteredIdSet = new Set<ItemId>();\n // O(1) index lookup — kept in sync with filteredIds for navigate()\n let filteredIdIndex = new Map<ItemId, number>();\n\n const registry = new CommandRegistry();\n // Pluggable search engine: use options.search if provided, otherwise create default.\n const searchEngine: SearchEngine =\n options.search ??\n createSearchEngine(\n typeof options.filter === 'function'\n ? {\n scorer: (query: string, item: CommandItem) => {\n const score = (\n options.filter as (item: CommandItem, query: string) => number | false\n )(item, query);\n if (score === false) return null;\n return { id: item.id, score, matches: [] };\n },\n }\n : undefined,\n );\n const scheduler: Scheduler = createScheduler();\n const emitter = new TypedEmitter<MachineEvents>();\n const keyboardRegistry = new KeyboardShortcutRegistry();\n\n let frecencyEngine: FrecencyEngine | null = null;\n if (options.frecency?.enabled) {\n frecencyEngine = new FrecencyEngine(options.frecency);\n }\n\n // Register initial items and groups\n if (options.items) {\n registry.registerItems(options.items);\n searchEngine.index(options.items);\n // Auto-register keyboard shortcuts from items\n for (const item of options.items) {\n if (item.shortcut != null && item.onSelect != null) {\n keyboardRegistry.register(item.shortcut, item.id, item.onSelect);\n }\n }\n }\n if (options.groups) {\n for (const group of options.groups) {\n registry.registerGroup(group);\n }\n }\n\n // Run initial filter\n refilter('');\n\n function setState(newState: CommandState): void {\n state = newState;\n emitter.emit('stateChange', state);\n }\n\n function refilter(query: string): void {\n const items = registry.getItems();\n const disableFilter = options.filter === false;\n\n let filteredIds: ItemId[];\n\n if (disableFilter || query === '') {\n filteredIds = [];\n for (const i of items) {\n if (!i.disabled) filteredIds.push(i.id);\n }\n } else {\n const results: SearchResult[] = searchEngine.search(query, items).toArray();\n\n // Apply frecency re-ranking if enabled\n if (frecencyEngine) {\n const bonuses = frecencyEngine.getAllBonuses();\n results.sort((a, b) => {\n const aBonus = bonuses.get(a.id) ?? 0;\n const bBonus = bonuses.get(b.id) ?? 0;\n return b.score + bBonus - (a.score + aBonus);\n });\n }\n\n filteredIds = results.map((r) => r.id);\n }\n\n // Update the O(1) membership set and index map — single pass instead of two separate constructions\n filteredIdSet = new Set<ItemId>();\n filteredIdIndex = new Map<ItemId, number>();\n for (let i = 0; i < filteredIds.length; i++) {\n const id = filteredIds[i]!;\n filteredIdSet.add(id);\n filteredIdIndex.set(id, i);\n }\n\n // Build grouped IDs — Map.groupBy (ES2026)\n const groupedIds = Map.groupBy(filteredIds, (id) => {\n const item = registry.getItem(id);\n return (item?.groupId ?? ('__ungrouped' as GroupId)) as GroupId;\n });\n\n // Select first item if no active or active is no longer visible\n const activeId =\n state.activeId && filteredIdSet.has(state.activeId)\n ? state.activeId\n : (filteredIds[0] ?? null);\n\n setState({\n ...state,\n search: query,\n filteredIds,\n groupedIds,\n filteredCount: filteredIds.length,\n activeId,\n lastUpdated: Temporal.Now.instant(),\n });\n }\n\n function navigate(direction: 'next' | 'prev' | 'first' | 'last'): void {\n const { filteredIds, activeId } = state;\n if (filteredIds.length === 0) return;\n\n // Fast path for first/last — skip indexOf entirely\n if (direction === 'first') {\n const newActiveId = filteredIds[0] ?? null;\n if (newActiveId !== activeId) {\n setState({ ...state, activeId: newActiveId, lastUpdated: Temporal.Now.instant() });\n options.onActiveChange?.(newActiveId);\n }\n return;\n }\n if (direction === 'last') {\n const newActiveId = filteredIds[filteredIds.length - 1] ?? null;\n if (newActiveId !== activeId) {\n setState({ ...state, activeId: newActiveId, lastUpdated: Temporal.Now.instant() });\n options.onActiveChange?.(newActiveId);\n }\n return;\n }\n\n const loop = options.loop ?? true;\n // O(1) index lookup via Map instead of O(n) indexOf\n const currentIdx = activeId ? (filteredIdIndex.get(activeId) ?? -1) : -1;\n let newIdx: number;\n\n if (direction === 'next') {\n if (currentIdx === -1 || currentIdx >= filteredIds.length - 1) {\n newIdx = loop ? 0 : filteredIds.length - 1;\n } else {\n newIdx = currentIdx + 1;\n }\n } else {\n // direction === 'prev'\n if (currentIdx <= 0) {\n newIdx = loop ? filteredIds.length - 1 : 0;\n } else {\n newIdx = currentIdx - 1;\n }\n }\n\n const newActiveId = filteredIds[newIdx] ?? null;\n if (newActiveId !== activeId) {\n setState({\n ...state,\n activeId: newActiveId,\n lastUpdated: Temporal.Now.instant(),\n });\n options.onActiveChange?.(newActiveId);\n }\n }\n\n function handleEvent(event: CommandEvent): void {\n switch (event.type) {\n case 'SEARCH_CHANGE':\n refilter(event.query);\n options.onSearchChange?.(event.query);\n break;\n\n case 'ITEM_SELECT': {\n const item = registry.getItem(event.id);\n if (item && !item.disabled) {\n item.onSelect?.();\n frecencyEngine?.recordSelection(event.id);\n emitter.emit('select', event.id);\n options.onSelect?.(event.id);\n }\n break;\n }\n\n case 'ITEM_ACTIVATE':\n // O(1) Set.has instead of O(n) Array.includes\n if (filteredIdSet.has(event.id)) {\n setState({\n ...state,\n activeId: event.id,\n lastUpdated: Temporal.Now.instant(),\n });\n options.onActiveChange?.(event.id);\n }\n break;\n\n case 'NAVIGATE':\n navigate(event.direction);\n break;\n\n case 'PAGE_PUSH':\n setState({\n ...state,\n page: event.page,\n pageStack: [...state.pageStack, state.page],\n lastUpdated: Temporal.Now.instant(),\n });\n break;\n\n case 'PAGE_POP': {\n const prevPage = state.pageStack.at(-1);\n if (prevPage != null) {\n setState({\n ...state,\n page: prevPage,\n pageStack: state.pageStack.slice(0, -1),\n lastUpdated: Temporal.Now.instant(),\n });\n }\n break;\n }\n\n case 'OPEN':\n setState({ ...state, open: true, lastUpdated: Temporal.Now.instant() });\n emitter.emit('openChange', true);\n options.onOpenChange?.(true);\n break;\n\n case 'CLOSE':\n setState({ ...state, open: false, lastUpdated: Temporal.Now.instant() });\n emitter.emit('openChange', false);\n options.onOpenChange?.(false);\n break;\n\n case 'TOGGLE': {\n const newOpen = !state.open;\n setState({ ...state, open: newOpen, lastUpdated: Temporal.Now.instant() });\n emitter.emit('openChange', newOpen);\n options.onOpenChange?.(newOpen);\n break;\n }\n\n case 'ITEMS_LOADED':\n registry.registerItems(event.items);\n searchEngine.index(event.items);\n // Single refilter handles both loading:false and filter — no double setState\n state = { ...state, loading: false };\n refilter(state.search);\n break;\n\n case 'REGISTER_ITEM':\n registry.registerItem(event.item);\n searchEngine.index([event.item]);\n if (event.item.shortcut && event.item.onSelect) {\n keyboardRegistry.register(event.item.shortcut, event.item.id, event.item.onSelect);\n }\n refilter(state.search);\n break;\n\n case 'UNREGISTER_ITEM':\n registry.unregisterItem(event.id);\n searchEngine.remove(new Set([event.id]));\n keyboardRegistry.unregisterByItem(event.id);\n refilter(state.search);\n break;\n\n case 'REGISTER_GROUP':\n registry.registerGroup(event.group);\n refilter(state.search);\n break;\n\n case 'UNREGISTER_GROUP':\n registry.unregisterGroup(event.id);\n refilter(state.search);\n break;\n }\n }\n\n const machine: CommandMachine = {\n getState(): CommandState {\n return state;\n },\n\n send(event: CommandEvent): void {\n scheduler.schedule(() => handleEvent(event));\n },\n\n /** useSyncExternalStore-compatible subscribe — returns cleanup function */\n subscribe(listener: () => void): () => void {\n const disposable = emitter.on('stateChange', listener as (data: CommandState) => void);\n return () => disposable[Symbol.dispose]();\n },\n\n /** Full state subscribe — returns Disposable for `using` pattern */\n subscribeState(listener: (state: CommandState) => void): Disposable {\n return emitter.on('stateChange', listener);\n },\n\n getRegistry(): CommandRegistry {\n return registry;\n },\n\n getKeyboardRegistry(): KeyboardShortcutRegistry {\n return keyboardRegistry;\n },\n\n getFilteredIdSet(): ReadonlySet<ItemId> {\n return filteredIdSet;\n },\n\n [Symbol.dispose](): void {\n scheduler[Symbol.dispose]();\n registry[Symbol.dispose]();\n searchEngine[Symbol.dispose]();\n emitter[Symbol.dispose]();\n keyboardRegistry[Symbol.dispose]();\n frecencyEngine?.[Symbol.dispose]();\n },\n };\n\n return machine;\n}\n","// packages/command/src/search/fuzzy-scorer.ts\n// Advanced fuzzy matcher (pure TS) — Promise.try for safe async scoring, Array.fromAsync for batch\n\nimport type { CommandItem } from '../types.js';\nimport { scoreItem } from './default-scorer.js';\nimport type { SearchResult } from './types.js';\n\n/**\n * Async-safe fuzzy scorer — wraps scoring in Promise.try (ES2026) for error resilience.\n * Falls back gracefully on error via Promise.try's synchronous-throw capture.\n */\nexport async function scoreItemAsync(\n query: string,\n item: CommandItem,\n): Promise<SearchResult | null> {\n return Promise.try(() => scoreItem(query, item));\n}\n\n/**\n * Async generator that yields score results for each item.\n * Enables streaming consumption and lazy evaluation of scoring operations.\n */\nasync function* scoreItemsGenerator(\n query: string,\n items: readonly CommandItem[],\n): AsyncGenerator<SearchResult | null> {\n for (const item of items) {\n yield Promise.try(() => scoreItem(query, item)).catch(() => null);\n }\n}\n\n/**\n * Batch score items using Array.fromAsync (ES2026) with an async generator pipeline.\n * Uses Promise.try for safe execution of each scoring operation and Array.fromAsync\n * for materializing the async iterable into a concrete array.\n */\nexport async function batchScoreItems(\n query: string,\n items: readonly CommandItem[],\n): Promise<SearchResult[]> {\n // Array.fromAsync (ES2026) — materializes async generator into array\n const results = await Array.fromAsync(scoreItemsGenerator(query, items));\n\n return results.filter((r): r is SearchResult => r != null).sort((a, b) => b.score - a.score);\n}\n","// Opt-in telemetry hooks for enterprise observability\n// Measures: open->select latency, search->result time, command usage frequency\n// Zero overhead when not configured — all hooks are optional\n// ES2026: Temporal.Now.instant() for all time measurements\n\nimport type { ItemId } from './types.js';\n\nexport interface CommandTelemetryHooks {\n /** Called when the command palette opens */\n readonly onPaletteOpen?: () => void;\n /** Called when the command palette closes, with session duration in ms */\n readonly onPaletteClose?: (durationMs: number) => void;\n /** Called after each search completes, with query, result count, and latency */\n readonly onSearchComplete?: (query: string, resultCount: number, durationMs: number) => void;\n /** Called when an item is selected, with item ID, active query, and position in list */\n readonly onItemSelected?: (itemId: ItemId, searchQuery: string, position: number) => void;\n}\n\nexport interface TelemetryMiddleware {\n readonly onOpen: () => void;\n readonly onClose: () => void;\n readonly onSearch: (query: string, resultCount: number, startTime: Temporal.Instant) => void;\n readonly onSelect: (itemId: ItemId, query: string, position: number) => void;\n}\n\n/**\n * Creates a telemetry middleware that measures command palette interactions.\n * Uses Temporal.Now.instant() (ES2026) for nanosecond-precision timestamps\n * and Temporal.Instant.since() for accurate duration computation.\n *\n * @example\n * ```ts\n * const telemetry = createTelemetryMiddleware({\n * onPaletteOpen: () => analytics.track('palette_opened'),\n * onItemSelected: (id, query, pos) => analytics.track('item_selected', { id, query, position: pos }),\n * });\n * ```\n */\nexport function createTelemetryMiddleware(hooks: CommandTelemetryHooks): TelemetryMiddleware {\n let openTimestamp: Temporal.Instant | null = null;\n\n return {\n onOpen(): void {\n openTimestamp = Temporal.Now.instant();\n hooks.onPaletteOpen?.();\n },\n\n onClose(): void {\n if (openTimestamp != null) {\n const elapsed = Temporal.Now.instant().since(openTimestamp);\n hooks.onPaletteClose?.(elapsed.total('milliseconds'));\n openTimestamp = null;\n }\n },\n\n onSearch(query: string, resultCount: number, startTime: Temporal.Instant): void {\n const elapsed = Temporal.Now.instant().since(startTime);\n hooks.onSearchComplete?.(query, resultCount, elapsed.total('milliseconds'));\n },\n\n onSelect(itemId: ItemId, query: string, position: number): void {\n hooks.onItemSelected?.(itemId, query, position);\n },\n };\n}\n"],"mappings":"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"}
|