Core API reference
The core package is framework-agnostic. Most apps need createKeybindingEngine and the types; lower-level exports exist for custom adapters, inspectors, and settings UIs.
createKeybindingEngine(options?)
Section titled “createKeybindingEngine(options?)”Creates an engine instance. This is a factory, not a global singleton — each instance owns its own registry, context, and listeners.
import { createKeybindingEngine } from '@tactile-js/core';
const kb = createKeybindingEngine({ defaultMatch: 'hybrid', sequenceTimeout: 1000, debug: false,});Returns a KeybindingEngine. See Engine options for every option.
KeybindingEngine
Section titled “KeybindingEngine”add(rule): () => void
Section titled “add(rule): () => void”Register a rule. Returns an unbind function.
const off = kb.add({ id: 'palette.open', keys: 'mod+k', when: "scope == 'global'", group: 'Navigation', description: 'Open command palette', priority: 0, handler: (event, info) => { openPalette(); // return false to skip preventDefault() },});
off(); // unregistercontext: ContextStore
Section titled “context: ContextStore”The context-key store driving when expressions. See Context & when expressions.
kb.context.set('scope', 'editor');kb.context.set('readOnly', false);kb.context.get('scope'); // 'editor'kb.context.has('readOnly'); // truekb.context.delete('readOnly');kb.context.assign({ scope: 'global', modalOpen: false });kb.context.snapshot(); // { scope: 'global', modalOpen: false }
const unsub = kb.context.subscribe(() => { console.log('context changed', kb.context.snapshot());});getKeymap(): ResolvedBinding[]
Section titled “getKeymap(): ResolvedBinding[]”Every registered rule with platform-formatted labels — the source of truth for help dialogs.
kb.getKeymap();// [{// id: 'palette.open',// keys: ['mod+k'],// labels: ['⌘K'], // or ['Ctrl+K'] on Windows/Linux// when: "scope == 'global'",// group: 'Navigation',// description: 'Open command palette',// priority: 0,// }]getKeymapForContext(snapshot): ResolvedBinding[]
Section titled “getKeymapForContext(snapshot): ResolvedBinding[]”Like getKeymap(), but only rules whose when holds in the given snapshot.
const active = kb.getKeymapForContext(kb.context.snapshot());getCollisions(): Collision[]
Section titled “getCollisions(): Collision[]”Rules competing for the same keystroke. See Collision detection.
recordShortcut(callback): () => void
Section titled “recordShortcut(callback): () => void”Capture the next complete keystroke. Returns a stop function. Used for “press a key to rebind” UIs.
const stop = kb.recordShortcut(({ binding, label }) => { console.log(binding); // 'ctrl+shift+k' console.log(label); // '⇧⌘K' on macOS});// stop(); // cancel without capturingformat(binding, platform?): string
Section titled “format(binding, platform?): string”Render a binding string as a display label.
kb.format('mod+shift+p'); // '⇧⌘P' on macOS, 'Ctrl+Shift+P' elsewheresubscribeKeymap(listener): () => void
Section titled “subscribeKeymap(listener): () => void”Notified when rules are added or removed.
dispose(): void
Section titled “dispose(): void”Detach all listeners and reset internal state.
KeybindingRule
Section titled “KeybindingRule”| Field | Type | Default | Description |
|---|---|---|---|
id |
string |
required | Stable command id, e.g. 'palette.open'. |
keys |
string | string[] |
required | Binding string or alternatives. See Key syntax. |
handler |
KeybindingHandler |
required | Called on match. Return false to skip preventDefault. |
when |
string |
— | Boolean expression over context keys. |
priority |
number |
0 |
Higher wins collisions. |
group |
string |
— | Category for help UIs. |
description |
string |
— | Human-readable label for help UIs. |
match |
'hybrid' | 'physical' | 'logical' |
engine default | Per-rule match mode override. |
enableInFormFields |
boolean |
false |
Fire even while typing in inputs/textareas/contenteditable. Chords only — see Engine options → ignore. |
preventDefault |
boolean | (event) => boolean |
true |
Whether to call preventDefault on match. |
eventType |
'keydown' | 'keyup' |
'keydown' |
Which event to listen on. |
KeybindingHandler
Section titled “KeybindingHandler”type KeybindingHandler = ( event: KeyEvent, info: MatchInfo,) => void | boolean;MatchInfo
Section titled “MatchInfo”| Field | Type | Description |
|---|---|---|
id |
string |
The matched rule’s id. |
keys |
string |
The specific binding string that matched. |
sequence |
boolean |
true if match came from a multi-stroke sequence like g i. |
KeyEvent
Section titled “KeyEvent”Structural subset of DOM KeyboardEvent — real browser events satisfy it; tests can pass plain objects.
| Field | Type |
|---|---|
key |
string |
code |
string |
ctrlKey, shiftKey, altKey, metaKey |
boolean |
repeat |
boolean (optional) |
target |
EventTarget | null (optional) |
preventDefault |
() => void (optional) |
ResolvedBinding
Section titled “ResolvedBinding”Output of getKeymap() — a rule plus presentation data.
Collision
Section titled “Collision”interface Collision { keys: string; rules: Array<{ id: string; when?: string; priority: number }>;}RecordedShortcut
Section titled “RecordedShortcut”interface RecordedShortcut { binding: string; // canonical, re-parseable: 'ctrl+shift+k' label: string; // display: '⇧⌘K'}Lower-level helpers
Section titled “Lower-level helpers”Exported for tooling and custom adapters:
| Export | Purpose |
|---|---|
createDomSource(target?) |
Default DOM event source bound to document. |
defaultIgnore(event) |
Default predicate that skips inputs and contenteditable. |
ContextStore |
Standalone context store (also available as engine.context). |
parseBinding(input, platform) |
Parse a binding string into chords. |
formatBinding(binding, platform) |
Format a binding for display. |
matchChord(chord, event, mode) |
Match a single chord against an event. |
compileWhen(expression) |
Parse a when string into an AST (cached). |
evaluateWhen(node, snapshot) |
Evaluate a compiled when AST. |
matchWhen(expression, snapshot) |
Compile + evaluate in one call. |
detectPlatform() |
'mac' or 'other'. |
resolveMod(platform) |
'meta' on Mac, 'ctrl' elsewhere. |
KeybindingParseError |
Thrown on invalid binding strings. |
WhenExpressionError |
Thrown on invalid when expressions. |
For non-DOM hosts (Electron, tests), inject a custom event source — see
Engine options → source.
Lifecycle pattern
Section titled “Lifecycle pattern”const kb = createKeybindingEngine();
// Register rulesconst rules = [ kb.add({ id: 'a', keys: 'mod+k', handler: a }), kb.add({ id: 'b', keys: 'mod+s', handler: b }),];
// Update context as UI state changeskb.context.set('scope', 'editor');
// Introspectkb.getKeymap();kb.getCollisions();
// Cleanuprules.forEach((off) => off());kb.dispose();Next steps
Section titled “Next steps”- Engine options — every constructor option in depth
- Key syntax — everything
keysaccepts - Recipes — the API applied to palettes, help dialogs, and rebinding UIs