Skip to content

Allow disabling individual keyboard controls with null (#333)#365

Merged
CarlosNZ merged 3 commits into
v2.0-devfrom
333-handle-disable-key-settings-with-null
Jun 16, 2026
Merged

Allow disabling individual keyboard controls with null (#333)#365
CarlosNZ merged 3 commits into
v2.0-devfrom
333-handle-disable-key-settings-with-null

Conversation

@CarlosNZ

Copy link
Copy Markdown
Owner

Closes #333.

What

Lets consumers disable any keyboardControls binding by setting it to null. A disabled binding is no longer intercepted, so the key falls through to its native browser behaviour. The motivating case is Tab: { tabForward: null, tabBack: null } turns off node-to-node Tab navigation so Tab/Shift-Tab resume normal focus traversal — useful for data sets where the built-in Tab behaviour isn't appropriate.

This supersedes the issue's "define a nonsense/unreachable key" hypothesis: that works by accident (a non-matching control never preventDefault()s) but is undiscoverable and doesn't read as intent. null states it in both the config and the types.

How

  • eventMatch treats a null control as "never matches". Because handleKeyPress only calls preventDefault() on a match, a disabled key passes straight through to the browser.
  • getFullKeyboardControlMap now distinguishes undefined (not supplied → keep default) from null (disable). The old truthy guard conflated them. The two modifier-array controls (clipboardModifier/collapseModifier) store [] when disabled, so their .includes() consumers stay null-safe and those fields remain real arrays.
  • The generic-confirm fallback now checks === undefined, so an explicitly disabled per-type confirm (e.g. stringConfirm: null) isn't silently re-enabled.
  • Types: every KeyboardControls field accepts | null; KeyboardControlsFull's KeyEvent-valued entries become KeyEvent | null.

Tests

  • New unit tests in test/keyboard.test.ts: map behaviour (null KeyEventnull, null modifier → [], disabled per-type confirm not re-enabled) and behavioural assertions on handleKeyPress (a disabled binding fires neither its action nor preventDefault; a default binding still does).
  • Regression check: removing the eventMatch guard makes the suite fail to compile against the new KeyEvent | null type — the guard is load-bearing.
  • Full suite green (496 passing), lint and pnpm compile clean.

Note

jsdom doesn't move focus on Tab, so the unit tests pin the contract we control (no preventDefault, no node-move). Native focus traversal after disabling is worth a quick manual confirm in a real browser.

Docs: README "Keyboard customisation" gains a bullet documenting the null disable. Changeset included (minor).

🤖 Generated with Claude Code

Any `keyboardControls` binding can now be set to `null` to disable it.
A disabled binding is no longer intercepted, so the key falls through to
its native browser behaviour — e.g. `{ tabForward: null, tabBack: null }`
restores normal Tab/Shift-Tab focus traversal instead of moving between
editable nodes.

- `eventMatch` treats a `null` control as "never matches"; since
  `handleKeyPress` only `preventDefault()`s on a match, native behaviour
  passes through.
- `getFullKeyboardControlMap` now distinguishes `undefined` (keep
  default) from `null` (disable). The two modifier-array controls store
  `[]` when disabled so their `.includes()` consumers stay null-safe.
- An explicitly disabled per-type confirm is no longer re-enabled by the
  generic `confirm` fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

Bundle size impact

json-edit-react

Format Base raw PR raw Δ raw Base gzip PR gzip Δ gzip
esm 56.43 KB 56.52 KB 🔺 +87 B (+0.15%) 20.12 KB 20.15 KB 🔺 +31 B (+0.15%)
cjs 57.93 KB 58.02 KB 🔺 +87 B (+0.15%) 20.21 KB 20.24 KB 🔺 +34 B (+0.16%)

Measured from build/index.{cjs,esm}.js. Gzip at level 9.

CarlosNZ and others added 2 commits June 16, 2026 12:45
The generic `confirm` already cascades its *value* to `stringConfirm` /
`numberConfirm` / `booleanConfirm`, but a `null` (disable) was skipped by
the fallback, so `confirm: null` left Enter-to-submit working on those
nodes. Treat "explicitly provided" (value or `null`) as cascading and
only "not provided" (`undefined`) as keeping the per-type defaults, so
`confirm: null` disables Enter-submit across string, number, boolean and
null editors at once. An explicit per-type confirm still wins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CarlosNZ CarlosNZ linked an issue Jun 16, 2026 that may be closed by this pull request
@CarlosNZ CarlosNZ merged commit ffb32b3 into v2.0-dev Jun 16, 2026
2 checks passed
@CarlosNZ CarlosNZ deleted the 333-handle-disable-key-settings-with-null branch June 16, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check that we can disable certain keyboard controls

1 participant