@tanstack/hotkeys 0.15.0 → 0.16.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.
@@ -11,7 +11,7 @@ import { CanonicalModifier, Key, LogicalKey } from "./key.types.js";
11
11
  * This enables cross-platform hotkey definitions that automatically adapt to the platform.
12
12
  * For example, `Mod+S` becomes `Command+S` on Mac and `Ctrl+S` on Windows/Linux.
13
13
  */
14
- export type SingleModifierHotkey = `Control+${Key}` | `Alt+${Key}` | `Shift+${Key}` | `Meta+${Key}` | `Mod+${Key}`;
14
+ export type SingleModifierHotkeyChord = `Control+${Key}` | `Alt+${Key}` | `Shift+${Key}` | `Meta+${Key}` | `Mod+${Key}`;
15
15
  /**
16
16
  * Two modifier + key combinations.
17
17
  *
@@ -21,7 +21,7 @@ export type SingleModifierHotkey = `Control+${Key}` | `Alt+${Key}` | `Shift+${Ke
21
21
  * - `Mod+Control` duplicates `Control` on Windows/Linux (Mod = Control)
22
22
  * - `Mod+Meta` duplicates `Meta` on macOS (Mod = Meta)
23
23
  */
24
- export type TwoModifierHotkey = `Control+Alt+${Key}` | `Control+Shift+${Key}` | `Control+Meta+${Key}` | `Alt+Shift+${Key}` | `Alt+Meta+${Key}` | `Shift+Meta+${Key}` | `Mod+Alt+${Key}` | `Mod+Shift+${Key}`;
24
+ export type TwoModifierHotkeyChord = `Control+Alt+${Key}` | `Control+Shift+${Key}` | `Control+Meta+${Key}` | `Alt+Shift+${Key}` | `Alt+Meta+${Key}` | `Shift+Meta+${Key}` | `Mod+Alt+${Key}` | `Mod+Shift+${Key}`;
25
25
  /**
26
26
  * Three modifier + key combinations.
27
27
  *
@@ -31,7 +31,7 @@ export type TwoModifierHotkey = `Control+Alt+${Key}` | `Control+Shift+${Key}` |
31
31
  * - `Mod+Control+Shift` duplicates `Control` on Windows/Linux (Mod = Control)
32
32
  * - `Mod+Shift+Meta` duplicates `Meta` on macOS (Mod = Meta)
33
33
  */
34
- export type ThreeModifierHotkey = `Control+Alt+Shift+${Key}` | `Control+Alt+Meta+${Key}` | `Control+Shift+Meta+${Key}` | `Alt+Shift+Meta+${Key}` | `Mod+Alt+Shift+${Key}`;
34
+ export type ThreeModifierHotkeyChord = `Control+Alt+Shift+${Key}` | `Control+Alt+Meta+${Key}` | `Control+Shift+Meta+${Key}` | `Alt+Shift+Meta+${Key}` | `Mod+Alt+Shift+${Key}`;
35
35
  /**
36
36
  * Four modifier + key combinations.
37
37
  *
@@ -44,7 +44,7 @@ export type ThreeModifierHotkey = `Control+Alt+Shift+${Key}` | `Control+Alt+Meta
44
44
  * - `Mod+Control+Alt+Shift` → duplicates `Control` on Windows/Linux
45
45
  * - `Mod+Alt+Shift+Meta` → duplicates `Meta` on macOS
46
46
  */
47
- export type FourModifierHotkey = `Control+Alt+Shift+Meta+${Key}`;
47
+ export type FourModifierHotkeyChord = `Control+Alt+Shift+Meta+${Key}`;
48
48
  /**
49
49
  * A type-safe hotkey string.
50
50
  *
@@ -97,7 +97,7 @@ export type FourModifierHotkey = `Control+Alt+Shift+Meta+${Key}`;
97
97
  * const windowsOnly: HotkeyChord = 'Control+S' // Ctrl+S on Windows/Linux only
98
98
  * ```
99
99
  */
100
- export type HotkeyChord = Key | SingleModifierHotkey | TwoModifierHotkey | ThreeModifierHotkey | FourModifierHotkey;
100
+ export type HotkeyChord = Key | SingleModifierHotkeyChord | TwoModifierHotkeyChord | ThreeModifierHotkeyChord | FourModifierHotkeyChord;
101
101
  /** Resolved modifier flags shared by both parsed binding variants. */
102
102
  export interface ParsedModifiers {
103
103
  /** Whether Control is required. */
@@ -112,31 +112,41 @@ export interface ParsedModifiers {
112
112
  modifiers: Array<CanonicalModifier>;
113
113
  }
114
114
  /**
115
- * A parsed binding matches either a logical key or a physical code, never both.
115
+ * A parsed chord matches either a logical key or a physical code, never both.
116
116
  * Check `code !== undefined` to narrow to a physical binding. Its logical
117
117
  * character is unknown without a keyboard event and is not stored in `key`.
118
118
  *
119
119
  * @example
120
120
  * parseHotkey('Alt+S') // { key: 'S', alt: true, ... }
121
- * parseHotkey('Alt+[KeyS]') // { code: 'KeyS', alt: true, ... } — no key property
121
+ * parseHotkey('Alt+[KeyS]') // { code: 'KeyS', alt: true, ... } with no key property
122
122
  */
123
- export type ParsedHotkey = ParsedModifiers & ({
123
+ export type ParsedHotkeyChord = ParsedModifiers & ({
124
124
  key: LogicalKey | (string & {});
125
125
  code?: never;
126
126
  } | {
127
127
  code: string;
128
128
  key?: never;
129
129
  });
130
+ /** Modifier flags shared by logical-key and physical-code registrations. */
131
+ export interface RawModifiers {
132
+ /** Platform-adaptive modifier: Command on macOS, Control on Windows/Linux. Defaults to false. */
133
+ mod?: boolean;
134
+ /** Whether the Control key is required. Defaults to false. */
135
+ ctrl?: boolean;
136
+ /** Whether the Shift key is required. Defaults to false. */
137
+ shift?: boolean;
138
+ /** Whether the Alt key is required. Defaults to false. */
139
+ alt?: boolean;
140
+ /** Whether the Meta (Command) key is required. Defaults to false. */
141
+ meta?: boolean;
142
+ }
130
143
  /**
131
- * A raw hotkey object for programmatic registration.
132
- *
133
- * Like `ParsedHotkey` but without `modifiers` (derived from booleans)
134
- * and with optional modifier booleans (default to `false` when omitted).
135
- * Use with `HotkeyManager.register()` and `useHotkey()` when you prefer
136
- * object form over a string.
144
+ * A chord written as an object instead of a string, for building chords from
145
+ * data. Set `key` for a logical key or `code` for a physical one, and set a
146
+ * boolean for each modifier. Omitted modifiers default to `false`.
137
147
  *
138
148
  * The `mod` modifier is platform-adaptive: Command on macOS, Control on Windows/Linux.
139
- * Pass `platform` when converting to ParsedHotkey (e.g., via `options.platform`).
149
+ * Sequence steps can be objects too: `[{ key: 'K', mod: true }, 'C']`.
140
150
  *
141
151
  * @example
142
152
  * ```ts
@@ -149,21 +159,7 @@ export type ParsedHotkey = ParsedModifiers & ({
149
159
  * useHotkey({ code: 'NumpadAdd', mod: true }, handler) // Physical numpad plus
150
160
  * ```
151
161
  */
152
- /** Modifier flags shared by logical-key and physical-code registrations. */
153
- export interface RawModifiers {
154
- /** The non-modifier key (e.g., 'S', 'Escape', 'F1'). */
155
- /** Platform-adaptive modifier: Command on macOS, Control on Windows/Linux. Defaults to false. */
156
- mod?: boolean;
157
- /** Whether the Control key is required. Defaults to false. */
158
- ctrl?: boolean;
159
- /** Whether the Shift key is required. Defaults to false. */
160
- shift?: boolean;
161
- /** Whether the Alt key is required. Defaults to false. */
162
- alt?: boolean;
163
- /** Whether the Meta (Command) key is required. Defaults to false. */
164
- meta?: boolean;
165
- }
166
- export type RawHotkey = ({
162
+ export type RawHotkeyChord = ({
167
163
  key: LogicalKey | (string & {});
168
164
  code?: never;
169
165
  } & RawModifiers) | ({
@@ -171,7 +167,9 @@ export type RawHotkey = ({
171
167
  key?: never;
172
168
  } & RawModifiers);
173
169
  /**
174
- * A sequence of chords pressed one after another (Vim-style), such as `['G', 'G']`.
170
+ * A sequence of chord strings pressed one after another (Vim-style), such as
171
+ * `['G', 'G']`. Registered sequences are stored in this form. To register
172
+ * steps written as objects, see {@link RegisterableHotkeySequence}.
175
173
  *
176
174
  * Steps may include modifiers; the same modifier can appear on consecutive
177
175
  * steps (e.g. `['Shift+R', 'Shift+T']`). Modifier-only key events do not
@@ -183,36 +181,64 @@ export type HotkeySequence = ReadonlyArray<HotkeyChord>;
183
181
  * A hotkey: one chord (`'Mod+S'`) or a sequence of chords (`['G', 'G']`).
184
182
  */
185
183
  export type Hotkey = HotkeyChord | HotkeySequence;
186
- /** A single chord as a type-safe string (`HotkeyChord`) or a raw object (`RawHotkey`). */
187
- export type RegisterableHotkeyChord = HotkeyChord | RawHotkey;
184
+ /** A single chord as a type-safe string (`HotkeyChord`) or an object (`RawHotkeyChord`). */
185
+ export type RegisterableHotkeyChord = HotkeyChord | RawHotkeyChord;
188
186
  /**
189
- * Anything that can be registered: a chord string, a raw chord object, or a sequence.
187
+ * A sequence whose steps are chord strings or chord objects, such as
188
+ * `['G', { key: 'H', shift: true }]`.
190
189
  */
191
- export type RegisterableHotkey = RegisterableHotkeyChord | HotkeySequence;
190
+ export type RegisterableHotkeySequence = ReadonlyArray<RegisterableHotkeyChord>;
192
191
  /**
193
- * Context passed to hotkey callbacks along with the keyboard event.
192
+ * Anything that can be registered: a chord or a sequence, with each chord
193
+ * written as a string or an object.
194
194
  */
195
- export interface HotkeyCallbackContext {
196
- /** The registered hotkey: a chord string or a sequence */
197
- hotkey: Hotkey;
198
- /** The parsed chord that completed the match (the last step of a sequence) */
199
- parsedHotkey: ParsedHotkey;
195
+ export type RegisterableHotkey = RegisterableHotkeyChord | RegisterableHotkeySequence;
196
+ /** Context passed to a chord's callback. */
197
+ export interface HotkeyChordCallbackContext {
198
+ kind: 'chord';
199
+ /** The registered chord */
200
+ hotkey: HotkeyChord;
201
+ /** The chord with `Mod` resolved for the registration's platform */
202
+ parsedChord: ParsedHotkeyChord;
203
+ }
204
+ /** Context passed to a sequence's callback. */
205
+ export interface HotkeySequenceCallbackContext {
206
+ kind: 'sequence';
207
+ /** The registered sequence */
208
+ hotkey: HotkeySequence;
209
+ /** Each step with `Mod` resolved for the registration's platform */
210
+ parsedSequence: Array<ParsedHotkeyChord>;
200
211
  }
212
+ /**
213
+ * Context passed to hotkey callbacks along with the keyboard event.
214
+ * Narrow with `kind` to read `parsedChord` or `parsedSequence`.
215
+ */
216
+ export type HotkeyCallbackContext = HotkeyChordCallbackContext | HotkeySequenceCallbackContext;
217
+ /**
218
+ * The callback context for a hotkey: chord context for chords (including
219
+ * one-step tuples), sequence context for sequences, and either when the kind
220
+ * is not known statically.
221
+ */
222
+ export type HotkeyCallbackContextFor<T extends RegisterableHotkey> = [T] extends [never] ? HotkeyCallbackContext : T extends readonly [RegisterableHotkeyChord] ? HotkeyChordCallbackContext : T extends RegisterableHotkeySequence ? HotkeySequenceCallbackContext : HotkeyChordCallbackContext;
201
223
  /**
202
224
  * Callback function type for hotkey handlers.
203
225
  *
204
226
  * @param event - The keyboard event that triggered the hotkey
205
- * @param context - Additional context including the hotkey and parsed hotkey
227
+ * @param context - The registered hotkey and its parsed form. APIs that take
228
+ * one hotkey narrow it to chord or sequence context from the hotkey you pass.
206
229
  *
207
230
  * @example
208
231
  * ```ts
209
- * const handler: HotkeyCallback = (event, { hotkey, parsedHotkey }) => {
210
- * console.log(`Hotkey ${hotkey} was pressed`)
211
- * console.log(`Modifiers:`, parsedHotkey.modifiers)
232
+ * const handler: HotkeyCallback = (event, context) => {
233
+ * if (context.kind === 'chord') {
234
+ * console.log(context.hotkey, context.parsedChord.modifiers)
235
+ * } else {
236
+ * console.log(context.hotkey.join(' '), context.parsedSequence.length)
237
+ * }
212
238
  * }
213
239
  * ```
214
240
  */
215
- export type HotkeyCallback = (event: KeyboardEvent, context: HotkeyCallbackContext) => void;
241
+ export type HotkeyCallback<TContext extends HotkeyCallbackContext = HotkeyCallbackContext> = (event: KeyboardEvent, context: TContext) => void;
216
242
  /**
217
243
  * Metadata for hotkey registrations, chords and sequences alike.
218
244
  * Includes `name`, `description`, and `group` by default. Extend via declaration merging:
package/dist/index.d.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  import { CanonicalModifier, EditingKey, FunctionKey, IndividualKey, Key, LetterKey, LogicalKey, Modifier, NamedKey, NavigationKey, NonPunctuationKey, NormalizedKeyboardEvent, NumberKey, PhysicalKey, PhysicalKeyCode, PunctuationKey } from "./key.types.js";
2
- import { ConflictBehavior, FourModifierHotkey, Hotkey, HotkeyCallback, HotkeyCallbackContext, HotkeyChord, HotkeyMeta, HotkeySequence, ParsedHotkey, ParsedModifiers, RawHotkey, RawModifiers, RegisterableHotkey, RegisterableHotkeyChord, SingleModifierHotkey, ThreeModifierHotkey, TwoModifierHotkey } from "./hotkey.types.js";
3
- import { HotkeyChordOptions, HotkeyChordRegistration, HotkeyChordRegistrationView, HotkeyManager, HotkeyOptions, HotkeyOptionsFor, HotkeyRegistration, HotkeyRegistrationHandle, HotkeyRegistrationView, HotkeySequenceOptions, HotkeySequenceRegistration, HotkeySequenceRegistrationView, Target, getHotkeyManager, toHotkeyRegistrationView } from "./hotkey-manager.js";
2
+ import { ConflictBehavior, FourModifierHotkeyChord, Hotkey, HotkeyCallback, HotkeyCallbackContext, HotkeyCallbackContextFor, HotkeyChord, HotkeyChordCallbackContext, HotkeyMeta, HotkeySequence, HotkeySequenceCallbackContext, ParsedHotkeyChord, ParsedModifiers, RawHotkeyChord, RawModifiers, RegisterableHotkey, RegisterableHotkeyChord, RegisterableHotkeySequence, SingleModifierHotkeyChord, ThreeModifierHotkeyChord, TwoModifierHotkeyChord } from "./hotkey.types.js";
3
+ import { ActivateHotkeyScopeOptions, HotkeyChordOptions, HotkeyChordRegistration, HotkeyChordRegistrationView, HotkeyManager, HotkeyOptions, HotkeyOptionsFor, HotkeyRegistration, HotkeyRegistrationHandle, HotkeyRegistrationView, HotkeyScopesState, HotkeySequenceOptions, HotkeySequenceRegistration, HotkeySequenceRegistrationView, Target, getHotkeyManager, toHotkeyRegistrationView } from "./hotkey-manager.js";
4
4
  import { AppHotkey, AppHotkeyChordOptions, AppHotkeyDefaultKind, AppHotkeyId, AppHotkeyInput, AppHotkeyListItem, AppHotkeyOptions, AppHotkeySequenceOptions, AppHotkeyStatus, AppHotkeys, AppHotkeysState, AppHotkeysStore, AppHotkeysStoreOptions, CustomHotkeys, DefinedAppHotkeys, Register, RegisteredAppHotkeys, defineAppHotkeys, getAppHotkeyRegistrationOptions, isAppHotkey, isCustomHotkey, provideAppHotkeys, publishAppHotkeysStore, resolveAppHotkey } from "./app-hotkeys.js";
5
5
  import { ALL_KEYS, EDITING_KEYS, FUNCTION_KEYS, LETTER_KEYS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, NAVIGATION_KEYS, NUMBER_KEYS, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, isSingleLetterKey, normalizeKeyName } from "./constants.js";
6
6
  import { KEY_DISPLAY_SYMBOLS, LINUX_MODIFIER_LABELS, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, PUNCTUATION_KEY_DISPLAY_LABELS, WINDOWS_MODIFIER_LABELS } from "./display-labels.js";
7
7
  import { detectPlatform, resolveModifier } from "./platform.js";
8
8
  import { DisplayHotkey, DisplayHotkeyChord, FormatDisplayOptions, formatForDisplay, formatHotkey } from "./format.js";
9
- import { hasNonModifierKey, isHotkeySequence, isModifierKey, normalizeHotkey, normalizeHotkeyFromEvent, normalizeHotkeyFromParsed, normalizeRegisterableHotkey, parseHotkey, parseKeyboardEvent, parseRegisterableHotkey, rawHotkeyToParsedHotkey, simplifyHotkey } from "./parse.js";
9
+ import { hasNonModifierKey, isHotkeySequence, isModifierKey, normalizeHotkey, parseHotkey, parseKeyboardEvent, simplifyHotkey } from "./parse.js";
10
10
  import { ValidatableHotkey, ValidationResult, assertValidHotkey, checkHotkey, validateHotkey } from "./validate.js";
11
- import { CreateHotkeyHandlerOptions, DEFAULT_SEQUENCE_TIMEOUT, KeyboardEventMatch, MultiHotkeyHandler, areHotkeysEqual, createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher, matchesKeyboardEvent } from "./match.js";
11
+ import { CreateHotkeyChordHandlerOptions, DEFAULT_SEQUENCE_TIMEOUT, KeyboardEventMatch, MultiHotkeyChordHandler, areHotkeysEqual, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, matchesKeyboardEvent } from "./match.js";
12
12
  import { HeldModifierOptions, matchesHeldModifiers } from "./hint.js";
13
13
  import { HotkeyConflict, HotkeyConflictOptions, findHotkeyConflicts } from "./conflicts.js";
14
14
  import { KeyStateTracker, KeyStateTrackerState, getKeyStateTracker } from "./key-state-tracker.js";
15
- import { HotkeyRecorderValidationContext, RecorderKeyMode, RecorderOptions, RecorderRejection } from "./recorder-options.js";
16
- import { HotkeyChordRecorderOptions, HotkeyRecorder, HotkeyRecorderCommitKeys, HotkeyRecorderOptions, HotkeyRecorderState, HotkeySequenceRecorderOptions } from "./hotkey-recorder.js";
17
- export { ALL_KEYS, AppHotkey, AppHotkeyChordOptions, AppHotkeyDefaultKind, AppHotkeyId, AppHotkeyInput, AppHotkeyListItem, AppHotkeyOptions, AppHotkeySequenceOptions, AppHotkeyStatus, AppHotkeys, AppHotkeysState, AppHotkeysStore, AppHotkeysStoreOptions, CanonicalModifier, ConflictBehavior, CreateHotkeyHandlerOptions, CustomHotkeys, DEFAULT_SEQUENCE_TIMEOUT, DefinedAppHotkeys, DisplayHotkey, DisplayHotkeyChord, EDITING_KEYS, EditingKey, FUNCTION_KEYS, FormatDisplayOptions, FourModifierHotkey, FunctionKey, HeldModifierOptions, Hotkey, HotkeyCallback, HotkeyCallbackContext, HotkeyChord, HotkeyChordOptions, HotkeyChordRecorderOptions, HotkeyChordRegistration, HotkeyChordRegistrationView, HotkeyConflict, HotkeyConflictOptions, HotkeyManager, HotkeyMeta, HotkeyOptions, HotkeyOptionsFor, HotkeyRecorder, HotkeyRecorderCommitKeys, HotkeyRecorderOptions, HotkeyRecorderState, HotkeyRecorderValidationContext, HotkeyRegistration, HotkeyRegistrationHandle, HotkeyRegistrationView, HotkeySequence, HotkeySequenceOptions, HotkeySequenceRecorderOptions, HotkeySequenceRegistration, HotkeySequenceRegistrationView, IndividualKey, KEY_DISPLAY_SYMBOLS, Key, KeyStateTracker, KeyStateTrackerState, KeyboardEventMatch, LETTER_KEYS, LINUX_MODIFIER_LABELS, LetterKey, LogicalKey, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, Modifier, MultiHotkeyHandler, NAVIGATION_KEYS, NUMBER_KEYS, NamedKey, NavigationKey, NonPunctuationKey, NormalizedKeyboardEvent, NumberKey, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, PUNCTUATION_KEY_DISPLAY_LABELS, ParsedHotkey, ParsedModifiers, PhysicalKey, PhysicalKeyCode, PunctuationKey, RawHotkey, RawModifiers, RecorderKeyMode, RecorderOptions, RecorderRejection, Register, RegisterableHotkey, RegisterableHotkeyChord, RegisteredAppHotkeys, SingleModifierHotkey, Target, ThreeModifierHotkey, TwoModifierHotkey, ValidatableHotkey, ValidationResult, WINDOWS_MODIFIER_LABELS, areHotkeysEqual, assertValidHotkey, checkHotkey, createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher, defineAppHotkeys, detectPlatform, findHotkeyConflicts, formatForDisplay, formatHotkey, getAppHotkeyRegistrationOptions, getHotkeyManager, getKeyStateTracker, hasNonModifierKey, isAppHotkey, isCustomHotkey, isHotkeySequence, isModifierKey, isSingleLetterKey, matchesHeldModifiers, matchesKeyboardEvent, normalizeHotkey, normalizeHotkeyFromEvent, normalizeHotkeyFromParsed, normalizeKeyName, normalizeRegisterableHotkey, parseHotkey, parseKeyboardEvent, parseRegisterableHotkey, provideAppHotkeys, publishAppHotkeysStore, rawHotkeyToParsedHotkey, resolveAppHotkey, resolveModifier, simplifyHotkey, toHotkeyRegistrationView, validateHotkey };
15
+ import { HotkeyChordRecorderOptions, HotkeyChordRecorderValidationContext, HotkeyRecorder, HotkeyRecorderCommitKeys, HotkeyRecorderOptions, HotkeyRecorderState, HotkeyRecorderValidationContext, HotkeySequenceRecorderOptions, HotkeySequenceRecorderValidationContext, RecorderKeyMode, RecorderOptions, RecorderRejection } from "./hotkey-recorder.js";
16
+ export { ALL_KEYS, ActivateHotkeyScopeOptions, AppHotkey, AppHotkeyChordOptions, AppHotkeyDefaultKind, AppHotkeyId, AppHotkeyInput, AppHotkeyListItem, AppHotkeyOptions, AppHotkeySequenceOptions, AppHotkeyStatus, AppHotkeys, AppHotkeysState, AppHotkeysStore, AppHotkeysStoreOptions, CanonicalModifier, ConflictBehavior, CreateHotkeyChordHandlerOptions, CustomHotkeys, DEFAULT_SEQUENCE_TIMEOUT, DefinedAppHotkeys, DisplayHotkey, DisplayHotkeyChord, EDITING_KEYS, EditingKey, FUNCTION_KEYS, FormatDisplayOptions, FourModifierHotkeyChord, FunctionKey, HeldModifierOptions, Hotkey, HotkeyCallback, HotkeyCallbackContext, HotkeyCallbackContextFor, HotkeyChord, HotkeyChordCallbackContext, HotkeyChordOptions, HotkeyChordRecorderOptions, HotkeyChordRecorderValidationContext, HotkeyChordRegistration, HotkeyChordRegistrationView, HotkeyConflict, HotkeyConflictOptions, HotkeyManager, HotkeyMeta, HotkeyOptions, HotkeyOptionsFor, HotkeyRecorder, HotkeyRecorderCommitKeys, HotkeyRecorderOptions, HotkeyRecorderState, HotkeyRecorderValidationContext, HotkeyRegistration, HotkeyRegistrationHandle, HotkeyRegistrationView, HotkeyScopesState, HotkeySequence, HotkeySequenceCallbackContext, HotkeySequenceOptions, HotkeySequenceRecorderOptions, HotkeySequenceRecorderValidationContext, HotkeySequenceRegistration, HotkeySequenceRegistrationView, IndividualKey, KEY_DISPLAY_SYMBOLS, Key, KeyStateTracker, KeyStateTrackerState, KeyboardEventMatch, LETTER_KEYS, LINUX_MODIFIER_LABELS, LetterKey, LogicalKey, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, Modifier, MultiHotkeyChordHandler, NAVIGATION_KEYS, NUMBER_KEYS, NamedKey, NavigationKey, NonPunctuationKey, NormalizedKeyboardEvent, NumberKey, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, PUNCTUATION_KEY_DISPLAY_LABELS, ParsedHotkeyChord, ParsedModifiers, PhysicalKey, PhysicalKeyCode, PunctuationKey, RawHotkeyChord, RawModifiers, RecorderKeyMode, RecorderOptions, RecorderRejection, Register, RegisterableHotkey, RegisterableHotkeyChord, RegisterableHotkeySequence, RegisteredAppHotkeys, SingleModifierHotkeyChord, Target, ThreeModifierHotkeyChord, TwoModifierHotkeyChord, ValidatableHotkey, ValidationResult, WINDOWS_MODIFIER_LABELS, areHotkeysEqual, assertValidHotkey, checkHotkey, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, defineAppHotkeys, detectPlatform, findHotkeyConflicts, formatForDisplay, formatHotkey, getAppHotkeyRegistrationOptions, getHotkeyManager, getKeyStateTracker, hasNonModifierKey, isAppHotkey, isCustomHotkey, isHotkeySequence, isModifierKey, isSingleLetterKey, matchesHeldModifiers, matchesKeyboardEvent, normalizeHotkey, normalizeKeyName, parseHotkey, parseKeyboardEvent, provideAppHotkeys, publishAppHotkeysStore, resolveAppHotkey, resolveModifier, simplifyHotkey, toHotkeyRegistrationView, validateHotkey };
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { ALL_KEYS, EDITING_KEYS, FUNCTION_KEYS, LETTER_KEYS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, NAVIGATION_KEYS, NUMBER_KEYS, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, isSingleLetterKey, normalizeKeyName } from "./constants.js";
2
2
  import { KEY_DISPLAY_SYMBOLS, LINUX_MODIFIER_LABELS, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, PUNCTUATION_KEY_DISPLAY_LABELS, WINDOWS_MODIFIER_LABELS } from "./display-labels.js";
3
3
  import { detectPlatform, resolveModifier } from "./platform.js";
4
- import { hasNonModifierKey, isHotkeySequence, isModifierKey, normalizeHotkey, normalizeHotkeyFromEvent, normalizeHotkeyFromParsed, normalizeRegisterableHotkey, parseHotkey, parseKeyboardEvent, parseRegisterableHotkey, rawHotkeyToParsedHotkey, simplifyHotkey } from "./parse.js";
4
+ import { hasNonModifierKey, isHotkeySequence, isModifierKey, normalizeHotkey, parseHotkey, parseKeyboardEvent, simplifyHotkey } from "./parse.js";
5
5
  import { formatForDisplay, formatHotkey } from "./format.js";
6
6
  import { assertValidHotkey, checkHotkey, validateHotkey } from "./validate.js";
7
- import { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual, createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher, matchesKeyboardEvent } from "./match.js";
7
+ import { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, matchesKeyboardEvent } from "./match.js";
8
8
  import { matchesHeldModifiers } from "./hint.js";
9
9
  import { HotkeyManager, getHotkeyManager, toHotkeyRegistrationView } from "./hotkey-manager.js";
10
10
  import { findHotkeyConflicts } from "./conflicts.js";
@@ -12,4 +12,4 @@ import { AppHotkeysStore, defineAppHotkeys, getAppHotkeyRegistrationOptions, isA
12
12
  import { KeyStateTracker, getKeyStateTracker } from "./key-state-tracker.js";
13
13
  import { HotkeyRecorder } from "./hotkey-recorder.js";
14
14
 
15
- export { ALL_KEYS, AppHotkeysStore, DEFAULT_SEQUENCE_TIMEOUT, EDITING_KEYS, FUNCTION_KEYS, HotkeyManager, HotkeyRecorder, KEY_DISPLAY_SYMBOLS, KeyStateTracker, LETTER_KEYS, LINUX_MODIFIER_LABELS, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, NAVIGATION_KEYS, NUMBER_KEYS, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, PUNCTUATION_KEY_DISPLAY_LABELS, WINDOWS_MODIFIER_LABELS, areHotkeysEqual, assertValidHotkey, checkHotkey, createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher, defineAppHotkeys, detectPlatform, findHotkeyConflicts, formatForDisplay, formatHotkey, getAppHotkeyRegistrationOptions, getHotkeyManager, getKeyStateTracker, hasNonModifierKey, isAppHotkey, isCustomHotkey, isHotkeySequence, isModifierKey, isSingleLetterKey, matchesHeldModifiers, matchesKeyboardEvent, normalizeHotkey, normalizeHotkeyFromEvent, normalizeHotkeyFromParsed, normalizeKeyName, normalizeRegisterableHotkey, parseHotkey, parseKeyboardEvent, parseRegisterableHotkey, provideAppHotkeys, publishAppHotkeysStore, rawHotkeyToParsedHotkey, resolveAppHotkey, resolveModifier, simplifyHotkey, toHotkeyRegistrationView, validateHotkey };
15
+ export { ALL_KEYS, AppHotkeysStore, DEFAULT_SEQUENCE_TIMEOUT, EDITING_KEYS, FUNCTION_KEYS, HotkeyManager, HotkeyRecorder, KEY_DISPLAY_SYMBOLS, KeyStateTracker, LETTER_KEYS, LINUX_MODIFIER_LABELS, MAC_MODIFIER_LABELS, MAC_MODIFIER_SYMBOLS, MODIFIER_ALIASES, MODIFIER_KEYS, MODIFIER_ORDER, NAVIGATION_KEYS, NUMBER_KEYS, PUNCTUATION_CODE_MAP, PUNCTUATION_KEYS, PUNCTUATION_KEY_DISPLAY_LABELS, WINDOWS_MODIFIER_LABELS, areHotkeysEqual, assertValidHotkey, checkHotkey, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, defineAppHotkeys, detectPlatform, findHotkeyConflicts, formatForDisplay, formatHotkey, getAppHotkeyRegistrationOptions, getHotkeyManager, getKeyStateTracker, hasNonModifierKey, isAppHotkey, isCustomHotkey, isHotkeySequence, isModifierKey, isSingleLetterKey, matchesHeldModifiers, matchesKeyboardEvent, normalizeHotkey, normalizeKeyName, parseHotkey, parseKeyboardEvent, provideAppHotkeys, publishAppHotkeysStore, resolveAppHotkey, resolveModifier, simplifyHotkey, toHotkeyRegistrationView, validateHotkey };
@@ -53,10 +53,8 @@ var KeyStateTracker = class KeyStateTracker {
53
53
  */
54
54
  store = new Store(getDefaultKeyStateTrackerState());
55
55
  #heldEntries = /* @__PURE__ */ new Map();
56
- #keydownListener = null;
57
- #keyupListener = null;
58
- #mouseListener = null;
59
- #blurListener = null;
56
+ /** Window listeners as `[type, listener, capture]`, removed together on destroy. */
57
+ #listeners = [];
60
58
  constructor() {
61
59
  this.#setupListeners();
62
60
  }
@@ -81,7 +79,7 @@ var KeyStateTracker = class KeyStateTracker {
81
79
  */
82
80
  #setupListeners() {
83
81
  if (typeof document === "undefined") return;
84
- this.#keydownListener = (event) => {
82
+ const onKeydown = (event) => {
85
83
  let changed = this.#reconcileModifiers(event);
86
84
  const key = normalizeKeyName(event.key);
87
85
  const identity = event.code || `key:${key}`;
@@ -94,7 +92,7 @@ var KeyStateTracker = class KeyStateTracker {
94
92
  }
95
93
  if (changed) this.#syncState();
96
94
  };
97
- this.#keyupListener = (event) => {
95
+ const onKeyup = (event) => {
98
96
  const key = normalizeKeyName(event.key);
99
97
  const identity = event.code || `key:${key}`;
100
98
  this.#heldEntries.delete(identity);
@@ -107,20 +105,43 @@ var KeyStateTracker = class KeyStateTracker {
107
105
  }
108
106
  this.#syncState();
109
107
  };
110
- this.#mouseListener = (event) => {
108
+ const onMouse = (event) => {
111
109
  if (this.#reconcileModifiers(event)) this.#syncState();
112
110
  };
113
- this.#blurListener = () => {
111
+ const onBlur = () => {
114
112
  if (this.#heldEntries.size > 0) {
115
113
  this.#heldEntries.clear();
116
114
  this.#syncState();
117
115
  }
118
116
  };
119
- window.addEventListener("keydown", this.#keydownListener, true);
120
- window.addEventListener("keyup", this.#keyupListener, true);
121
- window.addEventListener("mousemove", this.#mouseListener, true);
122
- window.addEventListener("mousedown", this.#mouseListener, true);
123
- window.addEventListener("blur", this.#blurListener);
117
+ this.#listeners = [
118
+ [
119
+ "keydown",
120
+ onKeydown,
121
+ true
122
+ ],
123
+ [
124
+ "keyup",
125
+ onKeyup,
126
+ true
127
+ ],
128
+ [
129
+ "mousemove",
130
+ onMouse,
131
+ true
132
+ ],
133
+ [
134
+ "mousedown",
135
+ onMouse,
136
+ true
137
+ ],
138
+ [
139
+ "blur",
140
+ onBlur,
141
+ false
142
+ ]
143
+ ];
144
+ for (const [type, listener, capture] of this.#listeners) window.addEventListener(type, listener, capture);
124
145
  }
125
146
  /**
126
147
  * Removes modifiers whose release was missed without a window blur.
@@ -153,24 +174,8 @@ var KeyStateTracker = class KeyStateTracker {
153
174
  * Removes the keyboard event listeners.
154
175
  */
155
176
  #removeListeners() {
156
- if (typeof document === "undefined") return;
157
- if (this.#keydownListener) {
158
- window.removeEventListener("keydown", this.#keydownListener, true);
159
- this.#keydownListener = null;
160
- }
161
- if (this.#keyupListener) {
162
- window.removeEventListener("keyup", this.#keyupListener, true);
163
- this.#keyupListener = null;
164
- }
165
- if (this.#mouseListener) {
166
- window.removeEventListener("mousemove", this.#mouseListener, true);
167
- window.removeEventListener("mousedown", this.#mouseListener, true);
168
- this.#mouseListener = null;
169
- }
170
- if (this.#blurListener) {
171
- window.removeEventListener("blur", this.#blurListener);
172
- this.#blurListener = null;
173
- }
177
+ for (const [type, listener, capture] of this.#listeners) window.removeEventListener(type, listener, capture);
178
+ this.#listeners = [];
174
179
  }
175
180
  /**
176
181
  * Gets an array of currently held key names.
package/dist/match.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HotkeyCallback, HotkeyChord, HotkeySequence, ParsedHotkey, RegisterableHotkey } from "./hotkey.types.js";
1
+ import { HotkeyCallback, HotkeyChord, HotkeyChordCallbackContext, ParsedHotkeyChord, RegisterableHotkey, RegisterableHotkeySequence } from "./hotkey.types.js";
2
2
  //#region src/match.d.ts
3
3
  export interface KeyboardEventMatch {
4
4
  matched: boolean;
@@ -24,9 +24,9 @@ export interface KeyboardEventMatch {
24
24
  * In these cases, `event.code` is used to determine the physical key.
25
25
  *
26
26
  * @param event - The KeyboardEvent to check
27
- * @param hotkey - The hotkey string or ParsedHotkey to match against
27
+ * @param chord - The chord string or parsed chord to match against
28
28
  * @param platform - The target platform for resolving 'Mod' (defaults to auto-detection)
29
- * @returns True if the event matches the hotkey
29
+ * @returns True if the event matches the chord
30
30
  *
31
31
  * @example
32
32
  * ```ts
@@ -38,29 +38,30 @@ export interface KeyboardEventMatch {
38
38
  * })
39
39
  * ```
40
40
  */
41
- export declare function matchesKeyboardEvent(event: KeyboardEvent, hotkey: HotkeyChord | ParsedHotkey, platform?: 'mac' | 'windows' | 'linux'): boolean;
41
+ export declare function matchesKeyboardEvent(event: KeyboardEvent, chord: HotkeyChord | ParsedHotkeyChord, platform?: 'mac' | 'windows' | 'linux'): boolean;
42
42
  /**
43
- * Options for creating a hotkey handler.
43
+ * Options for creating a chord handler.
44
44
  */
45
- export interface CreateHotkeyHandlerOptions {
46
- /** Prevent the default browser action when the hotkey matches. Defaults to true */
45
+ export interface CreateHotkeyChordHandlerOptions {
46
+ /** Prevent the default browser action when the chord matches. Defaults to true */
47
47
  preventDefault?: boolean;
48
- /** Stop event propagation when the hotkey matches. Defaults to true */
48
+ /** Stop event propagation when the chord matches. Defaults to true */
49
49
  stopPropagation?: boolean;
50
50
  /** The target platform for resolving 'Mod' */
51
51
  platform?: 'mac' | 'windows' | 'linux';
52
52
  }
53
53
  /**
54
- * Creates a keyboard event handler that calls the callback when the hotkey matches.
54
+ * Creates a keyboard event handler that calls the callback when the chord
55
+ * matches. For sequences, use `createSequenceMatcher`.
55
56
  *
56
- * @param hotkey - The hotkey string or ParsedHotkey to match
57
+ * @param chord - The chord string or parsed chord to match
57
58
  * @param callback - The function to call when the hotkey matches
58
59
  * @param options - Options for matching and handling
59
60
  * @returns A function that can be used as an event handler
60
61
  *
61
62
  * @example
62
63
  * ```ts
63
- * const handler = createHotkeyHandler('Mod+S', (event, { hotkey, parsedHotkey }) => {
64
+ * const handler = createHotkeyChordHandler('Mod+S', (event, { hotkey, parsedChord }) => {
64
65
  * console.log(`${hotkey} was pressed`)
65
66
  * handleSave()
66
67
  * })
@@ -68,18 +69,18 @@ export interface CreateHotkeyHandlerOptions {
68
69
  * document.addEventListener('keydown', handler)
69
70
  * ```
70
71
  */
71
- export declare function createHotkeyHandler(hotkey: HotkeyChord | ParsedHotkey, callback: HotkeyCallback, options?: CreateHotkeyHandlerOptions): (event: KeyboardEvent) => void;
72
- export type MultiHotkeyHandler = { [K in HotkeyChord]?: HotkeyCallback; };
72
+ export declare function createHotkeyChordHandler(chord: HotkeyChord | ParsedHotkeyChord, callback: HotkeyCallback<HotkeyChordCallbackContext>, options?: CreateHotkeyChordHandlerOptions): (event: KeyboardEvent) => void;
73
+ export type MultiHotkeyChordHandler = { [K in HotkeyChord]?: HotkeyCallback<HotkeyChordCallbackContext>; };
73
74
  /**
74
- * Creates a handler that matches multiple hotkeys.
75
+ * Creates a handler that matches several chords.
75
76
  *
76
- * @param handlers - A map of hotkey strings to their handlers
77
+ * @param handlers - A map of chord strings to their handlers
77
78
  * @param options - Options for matching and handling
78
79
  * @returns A function that can be used as an event handler
79
80
  *
80
81
  * @example
81
82
  * ```ts
82
- * const handler = createMultiHotkeyHandler({
83
+ * const handler = createMultiHotkeyChordHandler({
83
84
  * 'Mod+S': (event, { hotkey }) => handleSave(),
84
85
  * 'Mod+Z': (event, { hotkey }) => handleUndo(),
85
86
  * 'Mod+Shift+Z': (event, { hotkey }) => handleRedo(),
@@ -88,7 +89,7 @@ export type MultiHotkeyHandler = { [K in HotkeyChord]?: HotkeyCallback; };
88
89
  * document.addEventListener('keydown', handler)
89
90
  * ```
90
91
  */
91
- export declare function createMultiHotkeyHandler(handlers: MultiHotkeyHandler, options?: CreateHotkeyHandlerOptions): (event: KeyboardEvent) => void;
92
+ export declare function createMultiHotkeyChordHandler(handlers: MultiHotkeyChordHandler, options?: CreateHotkeyChordHandlerOptions): (event: KeyboardEvent) => void;
92
93
  /**
93
94
  * Compares normalized hotkey identity, including all four modifiers.
94
95
  * Sequences are equal when every step is equal; a one-step sequence equals its chord.
@@ -120,7 +121,7 @@ export declare const DEFAULT_SEQUENCE_TIMEOUT = 1000;
120
121
  * })
121
122
  * ```
122
123
  */
123
- export declare function createSequenceMatcher(sequence: HotkeySequence, options?: {
124
+ export declare function createSequenceMatcher(sequence: RegisterableHotkeySequence, options?: {
124
125
  timeout?: number;
125
126
  platform?: 'mac' | 'windows' | 'linux';
126
127
  }): {
package/dist/match.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { normalizeKeyName } from "./constants.js";
2
2
  import { detectPlatform } from "./platform.js";
3
- import { keysEqual, normalizeKeyboardEvent } from "./_keyboard-event.js";
4
- import { isHotkeySequence, isModifierKey, parseHotkey, parseRegisterableHotkey } from "./parse.js";
5
- import { matchKeyboardEvent } from "./_match.js";
3
+ import { normalizeKeyboardEvent } from "./_keyboard-event.js";
4
+ import { isHotkeySequence, isModifierKey, parseHotkey } from "./parse.js";
5
+ import { formatHotkey } from "./format.js";
6
+ import { matchKeyboardEvent, parsedChordsEqual } from "./_match.js";
6
7
 
7
8
  //#region src/match.ts
8
9
  /**
@@ -20,9 +21,9 @@ import { matchKeyboardEvent } from "./_match.js";
20
21
  * In these cases, `event.code` is used to determine the physical key.
21
22
  *
22
23
  * @param event - The KeyboardEvent to check
23
- * @param hotkey - The hotkey string or ParsedHotkey to match against
24
+ * @param chord - The chord string or parsed chord to match against
24
25
  * @param platform - The target platform for resolving 'Mod' (defaults to auto-detection)
25
- * @returns True if the event matches the hotkey
26
+ * @returns True if the event matches the chord
26
27
  *
27
28
  * @example
28
29
  * ```ts
@@ -34,20 +35,21 @@ import { matchKeyboardEvent } from "./_match.js";
34
35
  * })
35
36
  * ```
36
37
  */
37
- function matchesKeyboardEvent(event, hotkey, platform = detectPlatform()) {
38
- return matchKeyboardEvent(event, hotkey, platform).matched;
38
+ function matchesKeyboardEvent(event, chord, platform = detectPlatform()) {
39
+ return matchKeyboardEvent(event, chord, platform).matched;
39
40
  }
40
41
  /**
41
- * Creates a keyboard event handler that calls the callback when the hotkey matches.
42
+ * Creates a keyboard event handler that calls the callback when the chord
43
+ * matches. For sequences, use `createSequenceMatcher`.
42
44
  *
43
- * @param hotkey - The hotkey string or ParsedHotkey to match
45
+ * @param chord - The chord string or parsed chord to match
44
46
  * @param callback - The function to call when the hotkey matches
45
47
  * @param options - Options for matching and handling
46
48
  * @returns A function that can be used as an event handler
47
49
  *
48
50
  * @example
49
51
  * ```ts
50
- * const handler = createHotkeyHandler('Mod+S', (event, { hotkey, parsedHotkey }) => {
52
+ * const handler = createHotkeyChordHandler('Mod+S', (event, { hotkey, parsedChord }) => {
51
53
  * console.log(`${hotkey} was pressed`)
52
54
  * handleSave()
53
55
  * })
@@ -55,14 +57,15 @@ function matchesKeyboardEvent(event, hotkey, platform = detectPlatform()) {
55
57
  * document.addEventListener('keydown', handler)
56
58
  * ```
57
59
  */
58
- function createHotkeyHandler(hotkey, callback, options = {}) {
60
+ function createHotkeyChordHandler(chord, callback, options = {}) {
59
61
  const { preventDefault = true, stopPropagation = true, platform } = options;
60
62
  const resolvedPlatform = platform ?? detectPlatform();
61
- const hotkeyString = typeof hotkey === "string" ? hotkey : formatParsedHotkey(hotkey);
62
- const parsed = typeof hotkey === "string" ? parseHotkey(hotkey, resolvedPlatform) : hotkey;
63
+ const hotkeyString = typeof chord === "string" ? chord : formatHotkey(chord);
64
+ const parsed = typeof chord === "string" ? parseHotkey(chord, resolvedPlatform) : chord;
63
65
  const context = {
66
+ kind: "chord",
64
67
  hotkey: hotkeyString,
65
- parsedHotkey: parsed
68
+ parsedChord: parsed
66
69
  };
67
70
  return (event) => {
68
71
  if (matchesKeyboardEvent(event, parsed, resolvedPlatform)) {
@@ -73,15 +76,15 @@ function createHotkeyHandler(hotkey, callback, options = {}) {
73
76
  };
74
77
  }
75
78
  /**
76
- * Creates a handler that matches multiple hotkeys.
79
+ * Creates a handler that matches several chords.
77
80
  *
78
- * @param handlers - A map of hotkey strings to their handlers
81
+ * @param handlers - A map of chord strings to their handlers
79
82
  * @param options - Options for matching and handling
80
83
  * @returns A function that can be used as an event handler
81
84
  *
82
85
  * @example
83
86
  * ```ts
84
- * const handler = createMultiHotkeyHandler({
87
+ * const handler = createMultiHotkeyChordHandler({
85
88
  * 'Mod+S': (event, { hotkey }) => handleSave(),
86
89
  * 'Mod+Z': (event, { hotkey }) => handleUndo(),
87
90
  * 'Mod+Shift+Z': (event, { hotkey }) => handleRedo(),
@@ -90,7 +93,7 @@ function createHotkeyHandler(hotkey, callback, options = {}) {
90
93
  * document.addEventListener('keydown', handler)
91
94
  * ```
92
95
  */
93
- function createMultiHotkeyHandler(handlers, options = {}) {
96
+ function createMultiHotkeyChordHandler(handlers, options = {}) {
94
97
  const { preventDefault = true, stopPropagation = true, platform } = options;
95
98
  const resolvedPlatform = platform ?? detectPlatform();
96
99
  const parsedHandlers = Object.entries(handlers).filter((entry) => Boolean(entry[1])).map(([hotkey, handler]) => {
@@ -99,8 +102,9 @@ function createMultiHotkeyHandler(handlers, options = {}) {
99
102
  parsed,
100
103
  handler,
101
104
  context: {
105
+ kind: "chord",
102
106
  hotkey,
103
- parsedHotkey: parsed
107
+ parsedChord: parsed
104
108
  }
105
109
  };
106
110
  });
@@ -114,19 +118,6 @@ function createMultiHotkeyHandler(handlers, options = {}) {
114
118
  };
115
119
  }
116
120
  /**
117
- * Formats a ParsedHotkey back to a hotkey string.
118
- * Used internally to provide the hotkey string in callback context.
119
- */
120
- function formatParsedHotkey(parsed) {
121
- const parts = [];
122
- if (parsed.ctrl) parts.push("Control");
123
- if (parsed.alt) parts.push("Alt");
124
- if (parsed.shift) parts.push("Shift");
125
- if (parsed.meta) parts.push("Meta");
126
- parts.push(parsed.code !== void 0 ? `[${parsed.code}]` : parsed.key);
127
- return parts.join("+");
128
- }
129
- /**
130
121
  * Compares normalized hotkey identity, including all four modifiers.
131
122
  * Sequences are equal when every step is equal; a one-step sequence equals its chord.
132
123
  * Aliases resolve on the supplied platform. A physical code and a logical key
@@ -135,12 +126,7 @@ function formatParsedHotkey(parsed) {
135
126
  function areHotkeysEqual(left, right, platform = detectPlatform()) {
136
127
  const a = isHotkeySequence(left) ? left : [left];
137
128
  const b = isHotkeySequence(right) ? right : [right];
138
- return a.length === b.length && a.every((step, index) => areChordsEqual(step, b[index], platform));
139
- }
140
- function areChordsEqual(left, right, platform) {
141
- const a = parseRegisterableHotkey(left, platform);
142
- const b = parseRegisterableHotkey(right, platform);
143
- return a.ctrl === b.ctrl && a.alt === b.alt && a.shift === b.shift && a.meta === b.meta && (a.code !== void 0 || b.code !== void 0 ? a.code === b.code : keysEqual(a.key, b.key));
129
+ return a.length === b.length && a.every((step, index) => parsedChordsEqual(parseHotkey(step, platform), parseHotkey(b[index], platform)));
144
130
  }
145
131
  /** Default timeout between sequence steps (in milliseconds). */
146
132
  const DEFAULT_SEQUENCE_TIMEOUT = 1e3;
@@ -169,7 +155,7 @@ const DEFAULT_SEQUENCE_TIMEOUT = 1e3;
169
155
  function createSequenceMatcher(sequence, options = {}) {
170
156
  const platform = options.platform ?? detectPlatform();
171
157
  const timeout = options.timeout ?? 1e3;
172
- const parsedSequence = sequence.map((hotkey) => parseHotkey(hotkey, platform));
158
+ const parsedSequence = parseHotkey(sequence, platform);
173
159
  let currentIndex = 0;
174
160
  let lastKeyTime = 0;
175
161
  return {
@@ -205,4 +191,4 @@ function createSequenceMatcher(sequence, options = {}) {
205
191
  }
206
192
 
207
193
  //#endregion
208
- export { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual, createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher, matchesKeyboardEvent };
194
+ export { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, matchesKeyboardEvent };