-
Notifications
You must be signed in to change notification settings - Fork 0
Core API
Complete API for modern-cmdk — the framework-agnostic core engine.
Creates a new command palette state machine instance. Returns a Disposable object (use with using keyword).
using machine = createCommandMachine({
search: customSearchEngine, // optional: pluggable SearchEngine
frecency: frecencyEngine, // optional: FrecencyEngine instance
loop: true, // optional: wrap navigation (default: false)
initialSearch: '', // optional: initial search query
});| Method | Signature | Description |
|---|---|---|
send |
(event: CommandEvent) => void |
Dispatch an event to the state machine |
getState |
() => CommandState |
Get current immutable state snapshot |
subscribe |
(listener: (state: CommandState) => void) => () => void |
Subscribe to state changes; returns unsubscribe function |
[Symbol.dispose] |
() => void |
Clean up resources |
interface CommandState {
search: string;
activeItemId: ItemId | null;
items: ReadonlyMap<ItemId, CommandItem>;
filteredIds: readonly ItemId[];
groupedIds: ReadonlyMap<GroupId, readonly ItemId[]>;
pages: readonly string[];
open: boolean;
lastUpdated: Temporal.Instant;
}| Event Type | Payload | Description |
|---|---|---|
SEARCH_CHANGE |
{ search: string } |
Update search query |
REGISTER_ITEM |
{ item: CommandItem } |
Register a new item |
DEREGISTER_ITEM |
{ id: ItemId } |
Remove an item |
NAVIGATE |
{ direction: 'next' | 'prev' | 'first' | 'last' } |
Move active item |
ITEM_SELECT |
{ id: ItemId } |
Select the active item |
ITEM_ACTIVATE |
{ id: ItemId } |
Set a specific active item |
OPEN |
{} |
Open dialog |
CLOSE |
{} |
Close dialog |
TOGGLE |
{} |
Toggle open/close |
PAGE_PUSH |
{ page: string } |
Push a sub-page |
PAGE_POP |
{} |
Pop current page |
interface CommandItem {
id: ItemId;
value: string;
label?: string;
groupId?: GroupId;
keywords?: readonly string[];
disabled?: boolean;
onSelect?: () => void;
}Creates a branded ItemId from a plain string. Ensures type safety across the API.
const id = itemId('my-item');Creates a branded GroupId from a plain string.
const gid = groupId('settings');Creates the default TypeScript fuzzy search engine with substring + boundary matching.
interface SearchEngine {
index(items: readonly CommandItem[]): void;
search(query: string, items: readonly CommandItem[]): IteratorObject<SearchResult>;
remove(ids: ReadonlySet<ItemId>): void;
clear(): void;
}interface SearchResult {
id: ItemId;
score: number;
matches: readonly { start: number; end: number }[];
}Frequency x recency ranking engine using Temporal.Duration decay buckets.
using engine = new FrecencyEngine({
storage: new MemoryFrecencyStorage(), // or IdbFrecencyStorage
namespace: 'my-app', // optional: storage namespace
weights: { // optional: custom decay weights
recent: 100, // < 1 hour
day: 80, // < 1 day
week: 60, // < 1 week
month: 40, // < 1 month
old: 20, // > 1 month
},
});| Method | Signature | Description |
|---|---|---|
recordSelection |
(id: ItemId) => void |
Record an item selection |
getBonus |
(id: ItemId) => number |
Get frecency bonus for an item |
getAllBonuses |
(now?: Temporal.Instant) => Map<ItemId, number> |
Get all bonuses |
[Symbol.dispose] |
() => void |
Save data and clean up |
Pure function for calculating a frecency bonus from a FrecencyRecord:
const bonus = computeFrecencyBonus(record, Temporal.Now.instant());In-memory storage, no persistence. Default if none provided.
IndexedDB persistence via idb-keyval. Data survives page reloads.
import { IdbFrecencyStorage } from 'modern-cmdk';
using storage = new IdbFrecencyStorage();
using engine = new FrecencyEngine({ storage, namespace: 'app' });Creates a keyboard shortcut registry with RegExp.escape-based parser and Object.groupBy conflict detection.
const registry = createKeyboardShortcutRegistry();
registry.register({
key: 'ctrl+k',
handler: () => machine.send({ type: 'TOGGLE' }),
description: 'Toggle command palette',
});
// Detect conflicts
const conflicts = registry.detectConflicts();All major objects implement Disposable:
// Automatic cleanup with 'using'
using machine = createCommandMachine();
using engine = new FrecencyEngine({ storage: new MemoryFrecencyStorage() });
// Resources are cleaned up when scope exits