Why Keymap?
Browser keyboard handling is error-prone: modifier key normalisation, platform differences (ctrl vs meta), chord sequences, and cleanup all require boilerplate. Keymap handles all of it in a headless, zero-dependency package.
| Feature | Raw addEventListener | Keymap |
|---|---|---|
| Bundle size | 0 B (built-in) | 2.5 KB |
| Zero dependencies | ||
| Chord sequences | ||
| Modifier aliases | cmd, win, option → canonical | |
| Context guards | Manual if in handler | when() predicate per keymap |
| Headless / SSR-safe | DOM required | |
| Disposable | Manual removeEventListener | dispose() + using |
Use Keymap when you need chord sequences (g g, ctrl+k ctrl+s), modifier aliases, or context-scoped hotkeys that can be cleanly mounted and unmounted.
Stick with raw addEventListener when you have a single, static, never-removed hotkey and don't need chords.
Installation
sh
pnpm add @vielzeug/keymapsh
npm install @vielzeug/keymapsh
yarn add @vielzeug/keymapQuick Start
ts
import { createKeymap } from '@vielzeug/keymap';
const map = createKeymap({
'ctrl+k ctrl+s': () => save(),
'meta+shift+p': () => openPalette(),
'g g': () => goToTop(),
'escape': () => closePanel(),
});
const unmount = map.mount(document);
// Later:
unmount(); // remove from this target only
map.dispose(); // or: using map = createKeymap(…)Features
createKeymap()— Create a keymap from a bindings record; mount to anyEventTarget- Chord sequences —
"g g","ctrl+k ctrl+s"with configurable timeout (default 1 s) - Modifier aliases —
cmd/command/win→meta;opt/option→alt;mod→ platform-aware BindingOptions— per-binding{ handler, when?, trigger?, priority? }object syntaxmodKeyoption — explicit platform override for SSR and cross-platform testsformatShortcut()— platform-aware display (⇧⌘Pon Mac,Ctrl+Shift+Pelsewhere)createKeymapLayer()— scoped keymap stack withactivate()/deactivate()parseShortcut()/parseStep()/matchStep()— exposed for building custom matchers or testingcanonicalizeShortcut()— convert any shortcut alias to a stable key for conflict detectiondetectModKey()— platform modifier detection ('meta'on Mac,'ctrl'elsewhere)listBindings()— snapshot all active bindings (shortcut, trigger, priority) for palette UIsfindShortcutConflicts()— detect prefix/duplicate conflicts before binding a user-customized shortcut- Disposable —
dispose()+[Symbol.dispose]forusingdeclarations