# Keyboard Integration as Shared Input, Not as Gesture ## Decision Keyboard is not a `GestureType`. v2 treats pointer gestures and keyboard events as parallel input streams that share: - one context stack - one resolver - one action dispatcher - one provider-owned keyboard listener per active canvas ## Runtime Shape - Pointer stays gesture-native: - `tap` - `double-tap` - `triple-tap` - `long-press` - `drag` - `pinch` - `scroll` - Keyboard uses a separate event shape: - `kind: 'key'` - `phase: 'down' | 'up'` - `key` - `code` - `repeat` - Shared runtime event union: - `PointerGestureEvent` - `KeyInputEvent` - `InputEvent` - Held keyboard state is explicit: - `heldKeys.byKey` - `heldKeys.byCode` - Pointer events carry a held-key snapshot so bindings like `Space+drag` are modeled as pointer gestures with keyboard context. ## Resolver Rules - Pointer patterns still match pointer gesture types. - Keyboard patterns match `phase`, `key`, and/or `code`. - `key` score: `+64` - `code` score: `+64` - held-key positive score: `+16` - held-key negative score: `+8` - If both `key` and `code` are present, both must match. ## Ownership - `InputProvider` is the single keyboard owner for the active canvas. - The last canvas root to receive pointer interaction or focus becomes keyboard-active. - Keyboard routing is suppressed when: - target is `input` - target is `textarea` - target is `contentEditable` - IME composition is active - Held keys clear on `blur` and `visibilitychange`. ## Default Behavior - `/` opens command line - `Cmd/Ctrl+F` opens search - `Cmd/Ctrl+C/X/V/D` route through shared input actions - `Cmd/Ctrl+Z`, `Cmd/Ctrl+Shift+Z`, `Cmd/Ctrl+Y` route through shared input actions - `Delete` / `Backspace` delete current selection - `Escape` precedence: 1. cancel active interaction 2. exit keyboard manipulate mode 3. clear search / selection / close palette - `keyboardInteractionMode` is explicit: - `'navigate'` - `'manipulate'` - Navigate mode: - arrows move focus - `Enter` selects and enters manipulate mode - `Space` activates focused node - `Tab` cycles focus - Manipulate mode: - arrows nudge selection by `10` - `Shift+Arrow` nudges by `50` - `Escape` returns to navigate mode ## Cutoff - Remove keyboard ownership from: - `packages/canvas/src/commands/keyboard.ts` - `packages/canvas/src/hooks/useCanvasHistory.ts` - `packages/canvas/src/hooks/useArrowKeyNavigation.ts` - Keep those exports as compatibility shims only if needed for callers during the repo migration. ## Verification - resolver tests for key/code/held-key matching - runtime tests for `Space+drag`, `Escape`, copy/paste, undo/redo, and active-canvas ownership - behavior tests for navigate vs manipulate mode