@tanstack/hotkeys 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/_event-target.js +1 -2
  2. package/dist/_keyboard-event.js +1 -2
  3. package/dist/_match.js +1 -2
  4. package/dist/_named-keys.d.ts +3 -5
  5. package/dist/_named-keys.js +1 -2
  6. package/dist/_recorder-chord.js +1 -2
  7. package/dist/_recording-guard.js +1 -2
  8. package/dist/_registration.js +1 -2
  9. package/dist/conflicts.d.ts +4 -7
  10. package/dist/conflicts.js +1 -2
  11. package/dist/constants.d.ts +14 -17
  12. package/dist/constants.js +8 -9
  13. package/dist/display-labels.d.ts +7 -10
  14. package/dist/display-labels.js +1 -2
  15. package/dist/format.d.ts +9 -12
  16. package/dist/format.js +9 -7
  17. package/dist/hint.d.ts +3 -6
  18. package/dist/hint.js +1 -2
  19. package/dist/hotkey-manager.d.ts +8 -10
  20. package/dist/hotkey-manager.js +21 -3
  21. package/dist/hotkey-recorder.d.ts +4 -7
  22. package/dist/hotkey-recorder.js +9 -6
  23. package/dist/hotkey-sequence-recorder.d.ts +5 -8
  24. package/dist/hotkey-sequence-recorder.js +6 -7
  25. package/dist/hotkey.types.d.ts +15 -18
  26. package/dist/key-state-tracker.d.ts +4 -7
  27. package/dist/key-state-tracker.js +6 -3
  28. package/dist/key.types.d.ts +17 -20
  29. package/dist/match.d.ts +8 -11
  30. package/dist/match.js +1 -2
  31. package/dist/parse.d.ts +11 -14
  32. package/dist/parse.js +5 -4
  33. package/dist/platform.d.ts +3 -6
  34. package/dist/platform.js +1 -2
  35. package/dist/recorder-options.d.ts +6 -9
  36. package/dist/sequence-manager.d.ts +11 -14
  37. package/dist/sequence-manager.js +12 -7
  38. package/dist/validate.d.ts +5 -8
  39. package/dist/validate.js +1 -2
  40. package/package.json +8 -13
  41. package/dist/_event-target.cjs +0 -73
  42. package/dist/_event-target.cjs.map +0 -1
  43. package/dist/_event-target.js.map +0 -1
  44. package/dist/_keyboard-event.cjs +0 -83
  45. package/dist/_keyboard-event.cjs.map +0 -1
  46. package/dist/_keyboard-event.js.map +0 -1
  47. package/dist/_match.cjs +0 -49
  48. package/dist/_match.cjs.map +0 -1
  49. package/dist/_match.js.map +0 -1
  50. package/dist/_named-keys.cjs +0 -68
  51. package/dist/_named-keys.cjs.map +0 -1
  52. package/dist/_named-keys.d.cts +0 -8
  53. package/dist/_named-keys.js.map +0 -1
  54. package/dist/_recorder-chord.cjs +0 -44
  55. package/dist/_recorder-chord.cjs.map +0 -1
  56. package/dist/_recorder-chord.js.map +0 -1
  57. package/dist/_recording-guard.cjs +0 -59
  58. package/dist/_recording-guard.cjs.map +0 -1
  59. package/dist/_recording-guard.js.map +0 -1
  60. package/dist/_registration.cjs +0 -54
  61. package/dist/_registration.cjs.map +0 -1
  62. package/dist/_registration.js.map +0 -1
  63. package/dist/conflicts.cjs +0 -55
  64. package/dist/conflicts.cjs.map +0 -1
  65. package/dist/conflicts.d.cts +0 -39
  66. package/dist/conflicts.js.map +0 -1
  67. package/dist/constants.cjs +0 -410
  68. package/dist/constants.cjs.map +0 -1
  69. package/dist/constants.d.cts +0 -165
  70. package/dist/constants.js.map +0 -1
  71. package/dist/display-labels.cjs +0 -119
  72. package/dist/display-labels.cjs.map +0 -1
  73. package/dist/display-labels.d.cts +0 -93
  74. package/dist/display-labels.js.map +0 -1
  75. package/dist/format.cjs +0 -85
  76. package/dist/format.cjs.map +0 -1
  77. package/dist/format.d.cts +0 -99
  78. package/dist/format.js.map +0 -1
  79. package/dist/hint.cjs +0 -24
  80. package/dist/hint.cjs.map +0 -1
  81. package/dist/hint.d.cts +0 -23
  82. package/dist/hint.js.map +0 -1
  83. package/dist/hotkey-manager.cjs +0 -414
  84. package/dist/hotkey-manager.cjs.map +0 -1
  85. package/dist/hotkey-manager.d.cts +0 -234
  86. package/dist/hotkey-manager.js.map +0 -1
  87. package/dist/hotkey-recorder.cjs +0 -235
  88. package/dist/hotkey-recorder.cjs.map +0 -1
  89. package/dist/hotkey-recorder.d.cts +0 -119
  90. package/dist/hotkey-recorder.js.map +0 -1
  91. package/dist/hotkey-sequence-recorder.cjs +0 -255
  92. package/dist/hotkey-sequence-recorder.cjs.map +0 -1
  93. package/dist/hotkey-sequence-recorder.d.cts +0 -86
  94. package/dist/hotkey-sequence-recorder.js.map +0 -1
  95. package/dist/hotkey.types.d.cts +0 -236
  96. package/dist/index.cjs +0 -71
  97. package/dist/index.d.cts +0 -18
  98. package/dist/key-state-tracker.cjs +0 -197
  99. package/dist/key-state-tracker.cjs.map +0 -1
  100. package/dist/key-state-tracker.d.cts +0 -107
  101. package/dist/key-state-tracker.js.map +0 -1
  102. package/dist/key.types.d.cts +0 -82
  103. package/dist/match.cjs +0 -144
  104. package/dist/match.cjs.map +0 -1
  105. package/dist/match.d.cts +0 -101
  106. package/dist/match.js.map +0 -1
  107. package/dist/parse.cjs +0 -245
  108. package/dist/parse.cjs.map +0 -1
  109. package/dist/parse.d.cts +0 -134
  110. package/dist/parse.js.map +0 -1
  111. package/dist/platform.cjs +0 -55
  112. package/dist/platform.cjs.map +0 -1
  113. package/dist/platform.d.cts +0 -44
  114. package/dist/platform.js.map +0 -1
  115. package/dist/recorder-options.d.cts +0 -34
  116. package/dist/sequence-manager.cjs +0 -441
  117. package/dist/sequence-manager.cjs.map +0 -1
  118. package/dist/sequence-manager.d.cts +0 -172
  119. package/dist/sequence-manager.js.map +0 -1
  120. package/dist/validate.cjs +0 -112
  121. package/dist/validate.cjs.map +0 -1
  122. package/dist/validate.d.cts +0 -67
  123. package/dist/validate.js.map +0 -1
  124. package/src/_event-target.ts +0 -157
  125. package/src/_keyboard-event.ts +0 -101
  126. package/src/_match.ts +0 -96
  127. package/src/_named-keys.ts +0 -62
  128. package/src/_recorder-chord.ts +0 -76
  129. package/src/_recording-guard.ts +0 -63
  130. package/src/_registration.ts +0 -79
  131. package/src/conflicts.ts +0 -125
  132. package/src/constants.ts +0 -455
  133. package/src/display-labels.ts +0 -123
  134. package/src/format.ts +0 -201
  135. package/src/hint.ts +0 -42
  136. package/src/hotkey-manager.ts +0 -814
  137. package/src/hotkey-recorder.ts +0 -348
  138. package/src/hotkey-sequence-recorder.ts +0 -410
  139. package/src/hotkey.types.ts +0 -269
  140. package/src/index.ts +0 -17
  141. package/src/key-state-tracker.ts +0 -261
  142. package/src/key.types.ts +0 -268
  143. package/src/match.ts +0 -210
  144. package/src/parse.ts +0 -369
  145. package/src/platform.ts +0 -66
  146. package/src/recorder-options.ts +0 -34
  147. package/src/sequence-manager.ts +0 -769
  148. package/src/validate.ts +0 -179
package/src/format.ts DELETED
@@ -1,201 +0,0 @@
1
- import {
2
- KEY_DISPLAY_SYMBOLS,
3
- LINUX_MODIFIER_LABELS,
4
- MAC_MODIFIER_LABELS,
5
- MAC_MODIFIER_SYMBOLS,
6
- PUNCTUATION_KEY_DISPLAY_LABELS,
7
- WINDOWS_MODIFIER_LABELS,
8
- } from './display-labels'
9
- import {
10
- MODIFIER_ALIASES,
11
- MODIFIER_ORDER,
12
- PUNCTUATION_CODE_MAP,
13
- normalizeKeyName,
14
- } from './constants'
15
- import { detectPlatform } from './platform'
16
- import { assertLogicalKey, splitHotkeyParts } from './_keyboard-event'
17
- import {
18
- isModifierKey,
19
- normalizeHotkeyFromParsed,
20
- normalizeRegisterableHotkey,
21
- } from './parse'
22
- import type { CanonicalModifier } from './key.types'
23
- import type { Hotkey, ParsedHotkey, RegisterableHotkey } from './hotkey.types'
24
-
25
- /**
26
- * Joins stored sequence steps with spaces, preserving physical code tokens.
27
- * For user-facing labels, call formatForDisplay on each step instead.
28
- *
29
- * @param sequence - Array of hotkey strings that form the sequence
30
- * @returns A space-separated string (e.g. ['G','G'] → 'G G')
31
- *
32
- * @example
33
- * ```ts
34
- * formatHotkeySequence(['G', 'G']) // 'G G'
35
- * formatHotkeySequence(['D', 'I', 'W']) // 'D I W'
36
- * ```
37
- */
38
- export function formatHotkeySequence(sequence: Array<Hotkey>): string {
39
- return sequence.join(' ')
40
- }
41
-
42
- /**
43
- * Converts a ParsedHotkey back to a hotkey string.
44
- *
45
- * @param parsed - The parsed hotkey object
46
- * @returns A hotkey string in canonical form
47
- *
48
- * @example
49
- * ```ts
50
- * formatHotkey({ key: 'S', ctrl: true, shift: true, alt: false, meta: false, modifiers: ['Control', 'Shift'] })
51
- * // Returns: 'Control+Shift+S'
52
- * ```
53
- */
54
- export function formatHotkey(parsed: ParsedHotkey): string {
55
- if (parsed.code === undefined) assertLogicalKey(parsed.key)
56
- const parts: Array<string> = []
57
-
58
- // Add modifiers in canonical order
59
- for (const modifier of MODIFIER_ORDER) {
60
- if (parsed.modifiers.includes(modifier)) {
61
- parts.push(modifier)
62
- }
63
- }
64
-
65
- // Add the key
66
- parts.push(parsed.code !== undefined ? `[${parsed.code}]` : parsed.key)
67
-
68
- return parts.join('+')
69
- }
70
-
71
- export type DisplayHotkey = RegisterableHotkey | ParsedHotkey | (string & {})
72
-
73
- /**
74
- * Formats a hotkey for display in a user interface.
75
- *
76
- * On macOS, uses symbols (⌘⇧S) in the same modifier order as {@link normalizeHotkeyFromParsed}.
77
- * On Windows/Linux, uses text (Ctrl+Shift+S) with `+` separators.
78
- * The separator can be customized with `separatorToken`.
79
- * Physical codes use conventional display labels: `[KeyS]` becomes `S` and
80
- * `[Digit2]` becomes `2`. These labels do not infer the active keyboard layout
81
- * or change matching. Supply a resolved `layoutMap` for layout-aware labels;
82
- * `keyLabels` overrides both layout entries and fallback labels.
83
- *
84
- * @param hotkey - A logical or physical string, raw binding, or ParsedHotkey
85
- * @param options - Formatting options
86
- * @returns Display text, or individual key labels when parts is true
87
- *
88
- * @example
89
- * ```ts
90
- * formatForDisplay('Mod+Shift+S', { platform: 'mac' })
91
- * // Returns: '⌘ ⇧ S' (symbols separated by spaces on macOS)
92
- *
93
- * formatForDisplay('Mod+Shift+S', { platform: 'windows' })
94
- * // Returns: 'Ctrl+Shift+S'
95
- *
96
- * formatForDisplay('Escape')
97
- * // Returns: 'Esc' (on all platforms)
98
- * ```
99
- */
100
- export function formatForDisplay(
101
- hotkey: DisplayHotkey,
102
- options: FormatDisplayOptions & { parts: true },
103
- ): Array<string>
104
- export function formatForDisplay(
105
- hotkey: DisplayHotkey,
106
- options?: FormatDisplayOptions & { parts?: false },
107
- ): string
108
- export function formatForDisplay(
109
- hotkey: DisplayHotkey,
110
- options: FormatDisplayOptions,
111
- ): string | Array<string>
112
- export function formatForDisplay(
113
- hotkey: DisplayHotkey,
114
- options: FormatDisplayOptions = {},
115
- ): string | Array<string> {
116
- const platform = options.platform ?? detectPlatform()
117
- const symbols = options.useSymbols ?? true
118
- const modifierSymbols =
119
- typeof symbols === 'boolean' ? symbols : (symbols.modifiers ?? true)
120
- const keySymbols =
121
- typeof symbols === 'boolean' ? symbols : (symbols.keys ?? true)
122
- const separator =
123
- options.separatorToken ??
124
- (platform === 'mac' && modifierSymbols ? ' ' : '+')
125
- const normalized =
126
- typeof hotkey === 'object' && 'modifiers' in hotkey
127
- ? normalizeHotkeyFromParsed(hotkey, platform)
128
- : normalizeRegisterableHotkey(hotkey as RegisterableHotkey, platform)
129
- const parts = splitHotkeyParts(normalized).map((segment) => {
130
- if (isModifierKey(segment)) {
131
- const modifier = (MODIFIER_ALIASES[segment] ??
132
- MODIFIER_ALIASES[segment.toLowerCase()]) as CanonicalModifier | 'Mod'
133
- return platform === 'mac'
134
- ? modifierSymbols
135
- ? MAC_MODIFIER_SYMBOLS[modifier]
136
- : MAC_MODIFIER_LABELS[modifier]
137
- : platform === 'windows'
138
- ? WINDOWS_MODIFIER_LABELS[modifier]
139
- : LINUX_MODIFIER_LABELS[modifier]
140
- }
141
- const code = /^\[([A-Za-z][A-Za-z0-9]*)\]$/.exec(segment)?.[1]
142
- const label = options.keyLabels?.[code ?? segment]
143
- if (label !== undefined) return label
144
- // Shorten conventional position labels for display only; stored identity is unchanged.
145
- const numpad = code?.startsWith('Numpad') ?? false
146
- let displayKey = code ?? segment
147
- const mappedKey = code ? options.layoutMap?.get(code) : undefined
148
- if (mappedKey) {
149
- // Layout entries are logical labels; normalize their case and whitespace names.
150
- displayKey = normalizeKeyName(mappedKey)
151
- } else if (code) {
152
- if (/^Key[A-Z]$/.test(code)) displayKey = code.slice(3)
153
- else if (/^Digit[0-9]$/.test(code)) displayKey = code.slice(5)
154
- else if (numpad) displayKey = code.slice(6)
155
- else displayKey = PUNCTUATION_CODE_MAP[code] ?? code
156
- }
157
- const labels = keySymbols
158
- ? KEY_DISPLAY_SYMBOLS
159
- : PUNCTUATION_KEY_DISPLAY_LABELS
160
- const display =
161
- (labels as Partial<Record<string, string>>)[displayKey] ?? displayKey
162
- // Retain numpad identity while making longer names such as MemoryAdd readable.
163
- return numpad
164
- ? `Numpad ${display.replace(/([a-z])([A-Z])/g, '$1 $2')}`
165
- : display
166
- })
167
- return options.parts ? parts : parts.join(separator)
168
- }
169
-
170
- /**
171
- * @deprecated Use {@link formatForDisplay} instead with `useSymbols: false` option.
172
- */
173
- export function formatWithLabels(
174
- hotkey: RegisterableHotkey,
175
- options: Omit<FormatDisplayOptions, 'useSymbols' | 'parts'> = {},
176
- ): string {
177
- return formatForDisplay(hotkey, { ...options, useSymbols: false })
178
- }
179
-
180
- /**
181
- * Options for formatting hotkeys for display.
182
- */
183
- export interface FormatDisplayOptions {
184
- /** The target platform. Defaults to auto-detection. */
185
- platform?: 'mac' | 'windows' | 'linux'
186
- /** Whether to use symbols for the display. Defaults to true. */
187
- useSymbols?: boolean | { modifiers?: boolean; keys?: boolean }
188
- /** Return individual key labels instead of a joined string. Default: false. */
189
- parts?: boolean
190
- /**
191
- * An already-resolved code-to-key map, such as KeyboardLayoutMap or Map.
192
- * Used only for physical bindings. Mapped keys receive normal display formatting;
193
- * missing or empty entries use conventional fallback labels. The caller owns
194
- * loading and refreshing the map; this formatter never calls browser APIs.
195
- */
196
- layoutMap?: { get: (code: string) => string | undefined }
197
- /** Final display overrides for logical keys or physical codes; take precedence over layoutMap. Never changes matching. */
198
- keyLabels?: Readonly<Record<string, string>>
199
- /** Override the separator between display tokens. Defaults to platform-specific formatting when null/undefined. */
200
- separatorToken?: string | null
201
- }
package/src/hint.ts DELETED
@@ -1,42 +0,0 @@
1
- import { MODIFIER_KEYS, normalizeKeyName } from './constants'
2
- import { parseRegisterableHotkey } from './parse'
3
- import type { CanonicalModifier } from './key.types'
4
- import type { RegisterableHotkey } from './hotkey.types'
5
-
6
- export interface HeldModifierOptions {
7
- /** Resolve Mod for this platform. Defaults to platform detection. */
8
- platform?: 'mac' | 'windows' | 'linux'
9
- /** Require every binding modifier to be held. Default: false (nonempty subset). */
10
- exact?: boolean
11
- }
12
-
13
- /**
14
- * Returns whether held modifiers should reveal a shortcut hint.
15
- * By default, any nonempty subset of the binding's modifiers qualifies; an
16
- * unrelated modifier hides the hint. `exact` requires every binding modifier.
17
- * Nonmodifier keys are ignored. This does not check registration or focus.
18
- *
19
- * @example
20
- * matchesHeldModifiers('Alt+Shift+[KeyK]', ['Alt']) // true
21
- * matchesHeldModifiers('Alt+Shift+[KeyK]', ['Alt', 'Control']) // false
22
- */
23
- export function matchesHeldModifiers(
24
- hotkey: RegisterableHotkey,
25
- heldKeys: ReadonlyArray<string>,
26
- options: HeldModifierOptions = {},
27
- ): boolean {
28
- // AltGraph (AltGr) types alternate characters such as @ or € on many layouts.
29
- // It can synthesize Ctrl+Alt; character entry should not reveal shortcut hints.
30
- if (heldKeys.includes('AltGraph')) return false
31
- const held = [
32
- ...new Set(
33
- heldKeys.map(normalizeKeyName).filter((key) => MODIFIER_KEYS.has(key)),
34
- ),
35
- ]
36
- const { modifiers } = parseRegisterableHotkey(hotkey, options.platform)
37
- return (
38
- held.length > 0 &&
39
- held.every((key) => modifiers.includes(key as CanonicalModifier)) &&
40
- (!options.exact || held.length === modifiers.length)
41
- )
42
- }