Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
45 changes: 45 additions & 0 deletions .changeset/physical-recording-hints-display.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
'@tanstack/angular-hotkeys': minor
'@tanstack/hotkeys': minor
'@tanstack/hotkeys-devtools': minor
'@tanstack/lit-hotkeys': minor
'@tanstack/preact-hotkeys': minor
'@tanstack/preact-hotkeys-devtools': minor
'@tanstack/react-hotkeys': minor
'@tanstack/react-hotkeys-devtools': minor
'@tanstack/solid-hotkeys': minor
'@tanstack/solid-hotkeys-devtools': minor
'@tanstack/svelte-hotkeys': minor
'@tanstack/vue-hotkeys': minor
'@tanstack/vue-hotkeys-devtools': minor
---

- breaking: `RawHotkey` and `ParsedHotkey` are now unions containing either `key` or `code`. Use type intersections instead of extending them with interfaces.
- breaking: Recorders default to physical codes. Set `recordBy: 'key'` to record logical keys.
- breaking: Clearing a recording calls only `onClear`, without calling `onRecord` with an empty value.
- feat: Support typed physical bindings such as `Mod+[KeyS]` and `{ code: 'KeyS', mod: true }`.
- feat: Support F1–F24, additional named keys, and more punctuation shortcuts.
- feat: Add a platform option to `parseKeyboardEvent`.
- feat: Add recorder `recordBy`, `validate`, `detectConflicts`, and `onReject` options.
- feat: Add `findHotkeyConflicts`, including sequence-prefix checks.
- feat: Add `HotkeyMeta.group`.
- feat: Add `matchesHeldModifiers` and shortcut hint helpers for every framework adapter.
- feat: Add `formatForDisplay` support for parsed bindings, `parts`, separate modifier/key symbols, `keyLabels`, and a resolved `layoutMap`.
- fix: Improve shortcut matching across keyboard layouts, macOS Option keys, shifted punctuation, and numpad keys.
- fix: Prefer exact matches over physical-key fallbacks in hotkeys and sequences.
- fix: Handle literal plus shortcuts such as `Mod++` and Unicode key names correctly.
- fix: Avoid triggering shortcuts during IME composition and AltGraph character entry.
- fix: Clear held-key and `requireReset` state correctly when released keys produce different characters.
- fix: Prevent recording keystrokes, repeats, and releases from triggering registered shortcuts.
- fix: Display readable physical-key labels, such as `S` instead of `KeyS`.
- fix: Recognize equivalent hotkey aliases in registration lookups and conflict checks, including sequences.
- fix: Avoid unnecessary registration updates and handle target changes correctly in React and Preact.
- fix: Reject bracketed physical codes in logical `key` fields.
- fix: Reset shortcuts when keys are released inside inputs or while disabled.
- fix: Respect recorder `ignoreInputs` inside shadow roots.
- fix: Preserve Shift when recording logical AltGraph shortcuts.
- fix: Ignore modifier and composition events in standalone sequence matching.
- fix: Ignore repeated keydowns when matching sequences.
- fix: Prevent continuous rerenders when reading Preact hotkey registrations.
- fix: Allow Svelte recorder controls to be passed directly to event handlers.
- fix: Update devtools conflict reporting, plus-key formatting, group search, and key/code labels.
188 changes: 182 additions & 6 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,14 @@
{
"label": "IndividualKey",
"to": "reference/type-aliases/IndividualKey"
},
{
"label": "matchesHeldModifiers",
"to": "reference/functions/matchesHeldModifiers"
},
{
"label": "HeldModifierOptions",
"to": "reference/interfaces/HeldModifierOptions"
}
],
"frameworks": [
Expand All @@ -952,6 +960,10 @@
{
"label": "useHeldKeyCodes",
"to": "framework/react/reference/functions/useHeldKeyCodes"
},
{
"label": "useHotkeyHint",
"to": "framework/react/reference/functions/useHotkeyHint"
}
]
},
Expand All @@ -969,6 +981,10 @@
{
"label": "useHeldKeyCodes",
"to": "framework/preact/reference/functions/useHeldKeyCodes"
},
{
"label": "useHotkeyHint",
"to": "framework/preact/reference/functions/useHotkeyHint"
}
]
},
Expand All @@ -986,6 +1002,10 @@
{
"label": "createHeldKeyCodes",
"to": "framework/solid/reference/functions/createHeldKeyCodes"
},
{
"label": "createHotkeyHint",
"to": "framework/solid/reference/functions/createHotkeyHint"
}
]
},
Expand All @@ -1003,6 +1023,10 @@
{
"label": "injectHeldKeyCodes",
"to": "framework/angular/reference/functions/injectHeldKeyCodes"
},
{
"label": "injectHotkeyHint",
"to": "framework/angular/reference/functions/injectHotkeyHint"
}
]
},
Expand All @@ -1020,6 +1044,10 @@
{
"label": "useHeldKeyCodes",
"to": "framework/vue/reference/functions/useHeldKeyCodes"
},
{
"label": "useHotkeyHint",
"to": "framework/vue/reference/functions/useHotkeyHint"
}
]
},
Expand All @@ -1037,6 +1065,10 @@
{
"label": "HeldKeyCodesController",
"to": "framework/lit/reference/classes/HeldKeyCodesController"
},
{
"label": "HotkeyHintController",
"to": "framework/lit/reference/classes/HotkeyHintController"
}
]
},
Expand Down Expand Up @@ -1066,6 +1098,10 @@
{
"label": "SvelteHeldKeyCodesMap",
"to": "framework/svelte/reference/interfaces/SvelteHeldKeyCodesMap"
},
{
"label": "getHotkeyHint",
"to": "framework/svelte/reference/functions/getHotkeyHint"
}
]
}
Expand All @@ -1087,6 +1123,34 @@
{
"label": "HotkeyRecorderState",
"to": "reference/interfaces/HotkeyRecorderState"
},
{
"label": "findHotkeyConflicts",
"to": "reference/functions/findHotkeyConflicts"
},
{
"label": "HotkeyConflictOptions",
"to": "reference/interfaces/HotkeyConflictOptions"
},
{
"label": "HotkeyConflict",
"to": "reference/type-aliases/HotkeyConflict"
},
{
"label": "RecorderRejection",
"to": "reference/interfaces/RecorderRejection"
},
{
"label": "RecorderKeyMode",
"to": "reference/type-aliases/RecorderKeyMode"
},
{
"label": "RecorderOptions",
"to": "reference/interfaces/RecorderOptions"
},
{
"label": "HotkeyRecorderValidationContext",
"to": "reference/interfaces/HotkeyRecorderValidationContext"
}
],
"frameworks": [
Expand Down Expand Up @@ -1199,6 +1263,10 @@
{
"label": "HotkeySequenceRecorderCommitKeys",
"to": "reference/type-aliases/HotkeySequenceRecorderCommitKeys"
},
{
"label": "HotkeySequenceRecorderValidationContext",
"to": "reference/interfaces/HotkeySequenceRecorderValidationContext"
}
],
"frameworks": [
Expand Down Expand Up @@ -1363,21 +1431,105 @@
{
"label": "MODIFIER_KEYS",
"to": "reference/variables/MODIFIER_KEYS"
},
{
"label": "parseRegisterableHotkey",
"to": "reference/functions/parseRegisterableHotkey"
},
{
"label": "areHotkeysEqual",
"to": "reference/functions/areHotkeysEqual"
},
{
"label": "PhysicalKey",
"to": "reference/type-aliases/PhysicalKey"
},
{
"label": "Hotkey",
"to": "reference/type-aliases/Hotkey"
},
{
"label": "RegisterableHotkey",
"to": "reference/type-aliases/RegisterableHotkey"
},
{
"label": "RawHotkey",
"to": "reference/type-aliases/RawHotkey"
},
{
"label": "ParsedHotkey",
"to": "reference/type-aliases/ParsedHotkey"
},
{
"label": "LogicalKey",
"to": "reference/type-aliases/LogicalKey"
},
{
"label": "PhysicalKeyCode",
"to": "reference/type-aliases/PhysicalKeyCode"
},
{
"label": "DisplayHotkey",
"to": "reference/type-aliases/DisplayHotkey"
},
{
"label": "formatHotkeySequence",
"to": "reference/functions/formatHotkeySequence"
},
{
"label": "parseHotkey",
"to": "reference/functions/parseHotkey"
},
{
"label": "rawHotkeyToParsedHotkey",
"to": "reference/functions/rawHotkeyToParsedHotkey"
},
{
"label": "parseKeyboardEvent",
"to": "reference/functions/parseKeyboardEvent"
},
{
"label": "matchesKeyboardEvent",
"to": "reference/functions/matchesKeyboardEvent"
},
{
"label": "validateHotkey",
"to": "reference/functions/validateHotkey"
},
{
"label": "checkHotkey",
"to": "reference/functions/checkHotkey"
},
{
"label": "assertValidHotkey",
"to": "reference/functions/assertValidHotkey"
},
{
"label": "ValidationResult",
"to": "reference/interfaces/ValidationResult"
}
]
},
{
"label": "Examples",
"children": [
{
"label": "formatForDisplay",
"to": "framework/vanilla/examples/formatForDisplay"
}
],
"children": [],
"frameworks": [
{
"label": "vanilla",
"children": [
{
"label": "formatForDisplay",
"to": "framework/vanilla/examples/formatForDisplay"
}
]
},
{
"label": "react",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/react/examples/kitchen-sink"
},
{
"label": "useHotkey",
"to": "framework/react/examples/useHotkey"
Expand Down Expand Up @@ -1415,6 +1567,10 @@
{
"label": "preact",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/preact/examples/kitchen-sink"
},
{
"label": "useHotkey",
"to": "framework/preact/examples/useHotkey"
Expand Down Expand Up @@ -1452,6 +1608,10 @@
{
"label": "solid",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/solid/examples/kitchen-sink"
},
{
"label": "createHotkey",
"to": "framework/solid/examples/createHotkey"
Expand Down Expand Up @@ -1489,6 +1649,10 @@
{
"label": "angular",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/angular/examples/kitchen-sink"
},
{
"label": "injectHotkey",
"to": "framework/angular/examples/injectHotkey"
Expand Down Expand Up @@ -1526,6 +1690,10 @@
{
"label": "vue",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/vue/examples/kitchen-sink"
},
{
"label": "useHotkey",
"to": "framework/vue/examples/useHotkey"
Expand Down Expand Up @@ -1563,6 +1731,10 @@
{
"label": "lit",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/lit/examples/kitchen-sink"
},
{
"label": "hotkey",
"to": "framework/lit/examples/hotkey"
Expand Down Expand Up @@ -1592,6 +1764,10 @@
{
"label": "svelte",
"children": [
{
"label": "Kitchen Sink",
"to": "framework/svelte/examples/kitchen-sink"
},
{
"label": "createHotkey",
"to": "framework/svelte/examples/create-hotkey"
Expand Down
Loading
Loading