@tanstack/hotkeys 0.9.0 → 0.10.1
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.
- package/dist/_event-target.js +1 -2
- package/dist/_keyboard-event.js +1 -2
- package/dist/_match.js +1 -2
- package/dist/_named-keys.d.ts +3 -5
- package/dist/_named-keys.js +1 -2
- package/dist/_recorder-chord.js +1 -2
- package/dist/_recording-guard.js +1 -2
- package/dist/_registration.js +1 -2
- package/dist/conflicts.d.ts +4 -7
- package/dist/conflicts.js +1 -2
- package/dist/constants.d.ts +14 -17
- package/dist/constants.js +8 -9
- package/dist/display-labels.d.ts +7 -10
- package/dist/display-labels.js +1 -2
- package/dist/format.d.ts +12 -14
- package/dist/format.js +17 -7
- package/dist/hint.d.ts +3 -6
- package/dist/hint.js +1 -2
- package/dist/hotkey-manager.d.ts +8 -10
- package/dist/hotkey-manager.js +21 -3
- package/dist/hotkey-recorder.d.ts +4 -7
- package/dist/hotkey-recorder.js +9 -6
- package/dist/hotkey-sequence-recorder.d.ts +5 -8
- package/dist/hotkey-sequence-recorder.js +6 -7
- package/dist/hotkey.types.d.ts +15 -18
- package/dist/key-state-tracker.d.ts +4 -7
- package/dist/key-state-tracker.js +6 -3
- package/dist/key.types.d.ts +17 -20
- package/dist/match.d.ts +8 -11
- package/dist/match.js +1 -2
- package/dist/parse.d.ts +11 -14
- package/dist/parse.js +5 -4
- package/dist/platform.d.ts +3 -6
- package/dist/platform.js +1 -2
- package/dist/recorder-options.d.ts +6 -9
- package/dist/sequence-manager.d.ts +11 -14
- package/dist/sequence-manager.js +12 -7
- package/dist/validate.d.ts +5 -8
- package/dist/validate.js +1 -2
- package/package.json +8 -13
- package/dist/_event-target.cjs +0 -73
- package/dist/_event-target.cjs.map +0 -1
- package/dist/_event-target.js.map +0 -1
- package/dist/_keyboard-event.cjs +0 -83
- package/dist/_keyboard-event.cjs.map +0 -1
- package/dist/_keyboard-event.js.map +0 -1
- package/dist/_match.cjs +0 -49
- package/dist/_match.cjs.map +0 -1
- package/dist/_match.js.map +0 -1
- package/dist/_named-keys.cjs +0 -68
- package/dist/_named-keys.cjs.map +0 -1
- package/dist/_named-keys.d.cts +0 -8
- package/dist/_named-keys.js.map +0 -1
- package/dist/_recorder-chord.cjs +0 -44
- package/dist/_recorder-chord.cjs.map +0 -1
- package/dist/_recorder-chord.js.map +0 -1
- package/dist/_recording-guard.cjs +0 -59
- package/dist/_recording-guard.cjs.map +0 -1
- package/dist/_recording-guard.js.map +0 -1
- package/dist/_registration.cjs +0 -54
- package/dist/_registration.cjs.map +0 -1
- package/dist/_registration.js.map +0 -1
- package/dist/conflicts.cjs +0 -55
- package/dist/conflicts.cjs.map +0 -1
- package/dist/conflicts.d.cts +0 -39
- package/dist/conflicts.js.map +0 -1
- package/dist/constants.cjs +0 -410
- package/dist/constants.cjs.map +0 -1
- package/dist/constants.d.cts +0 -165
- package/dist/constants.js.map +0 -1
- package/dist/display-labels.cjs +0 -119
- package/dist/display-labels.cjs.map +0 -1
- package/dist/display-labels.d.cts +0 -93
- package/dist/display-labels.js.map +0 -1
- package/dist/format.cjs +0 -85
- package/dist/format.cjs.map +0 -1
- package/dist/format.d.cts +0 -99
- package/dist/format.js.map +0 -1
- package/dist/hint.cjs +0 -24
- package/dist/hint.cjs.map +0 -1
- package/dist/hint.d.cts +0 -23
- package/dist/hint.js.map +0 -1
- package/dist/hotkey-manager.cjs +0 -414
- package/dist/hotkey-manager.cjs.map +0 -1
- package/dist/hotkey-manager.d.cts +0 -234
- package/dist/hotkey-manager.js.map +0 -1
- package/dist/hotkey-recorder.cjs +0 -235
- package/dist/hotkey-recorder.cjs.map +0 -1
- package/dist/hotkey-recorder.d.cts +0 -119
- package/dist/hotkey-recorder.js.map +0 -1
- package/dist/hotkey-sequence-recorder.cjs +0 -255
- package/dist/hotkey-sequence-recorder.cjs.map +0 -1
- package/dist/hotkey-sequence-recorder.d.cts +0 -86
- package/dist/hotkey-sequence-recorder.js.map +0 -1
- package/dist/hotkey.types.d.cts +0 -236
- package/dist/index.cjs +0 -71
- package/dist/index.d.cts +0 -18
- package/dist/key-state-tracker.cjs +0 -197
- package/dist/key-state-tracker.cjs.map +0 -1
- package/dist/key-state-tracker.d.cts +0 -107
- package/dist/key-state-tracker.js.map +0 -1
- package/dist/key.types.d.cts +0 -82
- package/dist/match.cjs +0 -144
- package/dist/match.cjs.map +0 -1
- package/dist/match.d.cts +0 -101
- package/dist/match.js.map +0 -1
- package/dist/parse.cjs +0 -245
- package/dist/parse.cjs.map +0 -1
- package/dist/parse.d.cts +0 -134
- package/dist/parse.js.map +0 -1
- package/dist/platform.cjs +0 -55
- package/dist/platform.cjs.map +0 -1
- package/dist/platform.d.cts +0 -44
- package/dist/platform.js.map +0 -1
- package/dist/recorder-options.d.cts +0 -34
- package/dist/sequence-manager.cjs +0 -441
- package/dist/sequence-manager.cjs.map +0 -1
- package/dist/sequence-manager.d.cts +0 -172
- package/dist/sequence-manager.js.map +0 -1
- package/dist/validate.cjs +0 -112
- package/dist/validate.cjs.map +0 -1
- package/dist/validate.d.cts +0 -67
- package/dist/validate.js.map +0 -1
- package/src/_event-target.ts +0 -157
- package/src/_keyboard-event.ts +0 -101
- package/src/_match.ts +0 -96
- package/src/_named-keys.ts +0 -62
- package/src/_recorder-chord.ts +0 -76
- package/src/_recording-guard.ts +0 -63
- package/src/_registration.ts +0 -79
- package/src/conflicts.ts +0 -125
- package/src/constants.ts +0 -455
- package/src/display-labels.ts +0 -123
- package/src/format.ts +0 -201
- package/src/hint.ts +0 -42
- package/src/hotkey-manager.ts +0 -814
- package/src/hotkey-recorder.ts +0 -348
- package/src/hotkey-sequence-recorder.ts +0 -410
- package/src/hotkey.types.ts +0 -269
- package/src/index.ts +0 -17
- package/src/key-state-tracker.ts +0 -261
- package/src/key.types.ts +0 -268
- package/src/match.ts +0 -210
- package/src/parse.ts +0 -369
- package/src/platform.ts +0 -66
- package/src/recorder-options.ts +0 -34
- package/src/sequence-manager.ts +0 -769
- 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
|
-
}
|