docs/solutions/developer-experience/2026-05-03-slate-hotkey-dependency-hard-cuts-need-owned-matchers-and-layout-contracts.md
Slate v2 depended on is-hotkey for editor keyboard intent, but the dependency
was stale, externally shaped, and already had local install corruption history.
Cutting it safely required more than deleting the package.
is-hotkey and @types/is-hotkey were active deps.site/examples/ts/* files imported is-hotkey directly.is-hotkey for keyboard shortcuts.node_modules/.bun/is-hotkey.../lib/index.js
and blocked docs routes before app code executed.Cmd+Z, Ctrl+Z, AltGraph, non-Latin
layouts, or remapped ASCII layouts.is-hotkey with a patch. That kept a dead dependency on the runtime
path and preserved the local install-corruption blast radius.is-hotkey. That would keep old semantics and make Slate own a fork
instead of owning the shortcut contract.slate-dom.bun check. Some contract files and hard-cut proof
rows need explicit path runs.is-hotkey tests still had
useful generic matcher cases for aliases, multiple specs, modifier-only
keydown, exact modifiers, optional modifiers, and invalid grammar.Own the matcher in slate-dom, keep the public Hotkeys surface stable, and
expose one direct generic helper for examples:
import { Hotkeys, isHotkey } from 'slate-dom'
if (Hotkeys.isUndo(event)) {
// Slate-owned undo intent
}
if (isHotkey('mod+b', event)) {
// Example-level mark toggle
}
The matcher contract should be explicit:
HotkeysisHotkey(spec, event) checks internally instead of exposing a
public curried matcher factorymod, shift, alt, ctrl, cmd, optional modifiers, and named
keysshift and meta['meta+a', 'meta+s']event.key firstevent.code === KeyX only for non-ASCII letter layoutsgetModifierState('AltGraph') is truectrlalt+kThe hard-cut sweep must cover manifests, source, examples, docs, and lockfiles:
rg -n "is-hotkey|@types/is-hotkey|isHotkey|isKeyHotkey" \
package.json packages site docs bun.lock \
--glob '!site/out/**' \
--glob '!**/node_modules/**' \
--glob '!**/dist/**'
Keep historical changelog mentions if they are truly historical. Cut active imports, recommendations, package deps, and generated stale source only when the repo owns that output.
Keyboard intent is editor runtime behavior, not generic app sugar. Slate needs a small, stable matcher that matches its own undo, redo, split, soft-break, and delete policies without inheriting an unmaintained package's assumptions.
The key detail is layout policy. event.key preserves user-visible remapped
ASCII shortcuts. event.code fallback is useful only for non-ASCII letter
layouts where the browser reports a non-Latin key for a shortcut that the user
still expects to map to the physical Latin key. AltGraph must stay out of
Ctrl+Alt shortcut matching because many international keyboards use it for
normal character entry.
bun install, then treat generated output and
historical changelog hits separately from active source.