canvas/docs/plan-keyboard-gesture-integration.md

97 lines
2.7 KiB
Markdown
Raw Permalink Normal View History

2026-03-11 18:42:08 -07:00
# 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