@tanstack/hotkeys 0.15.1 → 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.
- package/README.md +1 -1
- package/dist/_keyboard-event.js +2 -2
- package/dist/_match.js +2 -2
- package/dist/_recorder-chord.js +3 -3
- package/dist/_registration.js +8 -5
- package/dist/adapter.d.ts +53 -6
- package/dist/adapter.js +45 -3
- package/dist/app-hotkeys.d.ts +11 -8
- package/dist/app-hotkeys.js +13 -7
- package/dist/conflicts.js +5 -5
- package/dist/format.d.ts +13 -9
- package/dist/format.js +7 -16
- package/dist/hint.js +2 -2
- package/dist/hotkey-manager.d.ts +94 -11
- package/dist/hotkey-manager.js +208 -31
- package/dist/hotkey-recorder.d.ts +20 -10
- package/dist/hotkey-recorder.js +9 -5
- package/dist/hotkey.types.d.ts +59 -32
- package/dist/index.d.ts +6 -6
- package/dist/index.js +3 -3
- package/dist/match.d.ts +19 -18
- package/dist/match.js +24 -21
- package/dist/parse.d.ts +35 -73
- package/dist/parse.js +39 -108
- package/dist/validate.js +2 -2
- package/package.json +1 -1
package/dist/hotkey-recorder.js
CHANGED
|
@@ -37,7 +37,7 @@ const initialState = {
|
|
|
37
37
|
* })
|
|
38
38
|
*
|
|
39
39
|
* const sequenceRecorder = new HotkeyRecorder({
|
|
40
|
-
* maxSteps:
|
|
40
|
+
* maxSteps: Infinity,
|
|
41
41
|
* onRecord: (hotkey) => {
|
|
42
42
|
* console.log('Recorded:', hotkey) // 'Mod+S' or ['G', 'H']
|
|
43
43
|
* },
|
|
@@ -198,13 +198,17 @@ var HotkeyRecorder = class {
|
|
|
198
198
|
}
|
|
199
199
|
options.onReject?.(rejection);
|
|
200
200
|
};
|
|
201
|
-
const parsedSequence =
|
|
202
|
-
const
|
|
201
|
+
const parsedSequence = parseHotkey(steps, platform);
|
|
202
|
+
const context = steps.length === 1 ? {
|
|
203
|
+
kind: "chord",
|
|
203
204
|
event: this.#events[this.#events.length - 1],
|
|
204
|
-
|
|
205
|
+
parsedChord: parsedSequence[0]
|
|
206
|
+
} : {
|
|
207
|
+
kind: "sequence",
|
|
205
208
|
events: [...this.#events],
|
|
206
209
|
parsedSequence
|
|
207
|
-
}
|
|
210
|
+
};
|
|
211
|
+
const accepted = options.validate?.(hotkey, context);
|
|
208
212
|
if (accepted !== void 0 && accepted !== true) {
|
|
209
213
|
rejectAndKeepRecording({
|
|
210
214
|
reason: "validation",
|
package/dist/hotkey.types.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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 |
|
|
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,15 +112,15 @@ export interface ParsedModifiers {
|
|
|
112
112
|
modifiers: Array<CanonicalModifier>;
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
* A parsed
|
|
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, ... }
|
|
121
|
+
* parseHotkey('Alt+[KeyS]') // { code: 'KeyS', alt: true, ... } with no key property
|
|
122
122
|
*/
|
|
123
|
-
export type
|
|
123
|
+
export type ParsedHotkeyChord = ParsedModifiers & ({
|
|
124
124
|
key: LogicalKey | (string & {});
|
|
125
125
|
code?: never;
|
|
126
126
|
} | {
|
|
@@ -141,15 +141,12 @@ export interface RawModifiers {
|
|
|
141
141
|
meta?: boolean;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
* A
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* and with optional modifier booleans (default to `false` when omitted).
|
|
148
|
-
* Use with `HotkeyManager.register()` and `useHotkey()` when you prefer
|
|
149
|
-
* 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`.
|
|
150
147
|
*
|
|
151
148
|
* The `mod` modifier is platform-adaptive: Command on macOS, Control on Windows/Linux.
|
|
152
|
-
*
|
|
149
|
+
* Sequence steps can be objects too: `[{ key: 'K', mod: true }, 'C']`.
|
|
153
150
|
*
|
|
154
151
|
* @example
|
|
155
152
|
* ```ts
|
|
@@ -162,7 +159,7 @@ export interface RawModifiers {
|
|
|
162
159
|
* useHotkey({ code: 'NumpadAdd', mod: true }, handler) // Physical numpad plus
|
|
163
160
|
* ```
|
|
164
161
|
*/
|
|
165
|
-
export type
|
|
162
|
+
export type RawHotkeyChord = ({
|
|
166
163
|
key: LogicalKey | (string & {});
|
|
167
164
|
code?: never;
|
|
168
165
|
} & RawModifiers) | ({
|
|
@@ -170,7 +167,9 @@ export type RawHotkey = ({
|
|
|
170
167
|
key?: never;
|
|
171
168
|
} & RawModifiers);
|
|
172
169
|
/**
|
|
173
|
-
* A sequence of
|
|
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}.
|
|
174
173
|
*
|
|
175
174
|
* Steps may include modifiers; the same modifier can appear on consecutive
|
|
176
175
|
* steps (e.g. `['Shift+R', 'Shift+T']`). Modifier-only key events do not
|
|
@@ -182,36 +181,64 @@ export type HotkeySequence = ReadonlyArray<HotkeyChord>;
|
|
|
182
181
|
* A hotkey: one chord (`'Mod+S'`) or a sequence of chords (`['G', 'G']`).
|
|
183
182
|
*/
|
|
184
183
|
export type Hotkey = HotkeyChord | HotkeySequence;
|
|
185
|
-
/** A single chord as a type-safe string (`HotkeyChord`) or
|
|
186
|
-
export type RegisterableHotkeyChord = HotkeyChord |
|
|
184
|
+
/** A single chord as a type-safe string (`HotkeyChord`) or an object (`RawHotkeyChord`). */
|
|
185
|
+
export type RegisterableHotkeyChord = HotkeyChord | RawHotkeyChord;
|
|
187
186
|
/**
|
|
188
|
-
*
|
|
187
|
+
* A sequence whose steps are chord strings or chord objects, such as
|
|
188
|
+
* `['G', { key: 'H', shift: true }]`.
|
|
189
189
|
*/
|
|
190
|
-
export type
|
|
190
|
+
export type RegisterableHotkeySequence = ReadonlyArray<RegisterableHotkeyChord>;
|
|
191
191
|
/**
|
|
192
|
-
*
|
|
192
|
+
* Anything that can be registered: a chord or a sequence, with each chord
|
|
193
|
+
* written as a string or an object.
|
|
193
194
|
*/
|
|
194
|
-
export
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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>;
|
|
199
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;
|
|
200
223
|
/**
|
|
201
224
|
* Callback function type for hotkey handlers.
|
|
202
225
|
*
|
|
203
226
|
* @param event - The keyboard event that triggered the hotkey
|
|
204
|
-
* @param context -
|
|
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.
|
|
205
229
|
*
|
|
206
230
|
* @example
|
|
207
231
|
* ```ts
|
|
208
|
-
* const handler: HotkeyCallback = (event,
|
|
209
|
-
*
|
|
210
|
-
*
|
|
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
|
+
* }
|
|
211
238
|
* }
|
|
212
239
|
* ```
|
|
213
240
|
*/
|
|
214
|
-
export type HotkeyCallback = (event: KeyboardEvent, context:
|
|
241
|
+
export type HotkeyCallback<TContext extends HotkeyCallbackContext = HotkeyCallbackContext> = (event: KeyboardEvent, context: TContext) => void;
|
|
215
242
|
/**
|
|
216
243
|
* Metadata for hotkey registrations, chords and sequences alike.
|
|
217
244
|
* Includes `name`, `description`, and `group` by default. Extend via declaration merging:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +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,
|
|
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,
|
|
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 {
|
|
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 { HotkeyChordRecorderOptions, HotkeyRecorder, HotkeyRecorderCommitKeys, HotkeyRecorderOptions, HotkeyRecorderState, HotkeyRecorderValidationContext, HotkeySequenceRecorderOptions, RecorderKeyMode, RecorderOptions, RecorderRejection } from "./hotkey-recorder.js";
|
|
16
|
-
export { ALL_KEYS, AppHotkey, AppHotkeyChordOptions, AppHotkeyDefaultKind, AppHotkeyId, AppHotkeyInput, AppHotkeyListItem, AppHotkeyOptions, AppHotkeySequenceOptions, AppHotkeyStatus, AppHotkeys, AppHotkeysState, AppHotkeysStore, AppHotkeysStoreOptions, CanonicalModifier, ConflictBehavior,
|
|
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,
|
|
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,
|
|
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,
|
|
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 };
|
package/dist/match.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HotkeyCallback, HotkeyChord,
|
|
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
|
|
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
|
|
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,
|
|
41
|
+
export declare function matchesKeyboardEvent(event: KeyboardEvent, chord: HotkeyChord | ParsedHotkeyChord, platform?: 'mac' | 'windows' | 'linux'): boolean;
|
|
42
42
|
/**
|
|
43
|
-
* Options for creating a
|
|
43
|
+
* Options for creating a chord handler.
|
|
44
44
|
*/
|
|
45
|
-
export interface
|
|
46
|
-
/** Prevent the default browser action when the
|
|
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
|
|
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
|
|
54
|
+
* Creates a keyboard event handler that calls the callback when the chord
|
|
55
|
+
* matches. For sequences, use `createSequenceMatcher`.
|
|
55
56
|
*
|
|
56
|
-
* @param
|
|
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 =
|
|
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
|
|
72
|
-
export type
|
|
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
|
|
75
|
+
* Creates a handler that matches several chords.
|
|
75
76
|
*
|
|
76
|
-
* @param handlers - A map of
|
|
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 =
|
|
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
|
|
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:
|
|
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,9 +1,9 @@
|
|
|
1
1
|
import { normalizeKeyName } from "./constants.js";
|
|
2
2
|
import { detectPlatform } from "./platform.js";
|
|
3
3
|
import { normalizeKeyboardEvent } from "./_keyboard-event.js";
|
|
4
|
-
import { isHotkeySequence, isModifierKey, parseHotkey
|
|
4
|
+
import { isHotkeySequence, isModifierKey, parseHotkey } from "./parse.js";
|
|
5
5
|
import { formatHotkey } from "./format.js";
|
|
6
|
-
import { matchKeyboardEvent,
|
|
6
|
+
import { matchKeyboardEvent, parsedChordsEqual } from "./_match.js";
|
|
7
7
|
|
|
8
8
|
//#region src/match.ts
|
|
9
9
|
/**
|
|
@@ -21,9 +21,9 @@ import { matchKeyboardEvent, parsedHotkeysEqual } from "./_match.js";
|
|
|
21
21
|
* In these cases, `event.code` is used to determine the physical key.
|
|
22
22
|
*
|
|
23
23
|
* @param event - The KeyboardEvent to check
|
|
24
|
-
* @param
|
|
24
|
+
* @param chord - The chord string or parsed chord to match against
|
|
25
25
|
* @param platform - The target platform for resolving 'Mod' (defaults to auto-detection)
|
|
26
|
-
* @returns True if the event matches the
|
|
26
|
+
* @returns True if the event matches the chord
|
|
27
27
|
*
|
|
28
28
|
* @example
|
|
29
29
|
* ```ts
|
|
@@ -35,20 +35,21 @@ import { matchKeyboardEvent, parsedHotkeysEqual } from "./_match.js";
|
|
|
35
35
|
* })
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
|
-
function matchesKeyboardEvent(event,
|
|
39
|
-
return matchKeyboardEvent(event,
|
|
38
|
+
function matchesKeyboardEvent(event, chord, platform = detectPlatform()) {
|
|
39
|
+
return matchKeyboardEvent(event, chord, platform).matched;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Creates a keyboard event handler that calls the callback when the
|
|
42
|
+
* Creates a keyboard event handler that calls the callback when the chord
|
|
43
|
+
* matches. For sequences, use `createSequenceMatcher`.
|
|
43
44
|
*
|
|
44
|
-
* @param
|
|
45
|
+
* @param chord - The chord string or parsed chord to match
|
|
45
46
|
* @param callback - The function to call when the hotkey matches
|
|
46
47
|
* @param options - Options for matching and handling
|
|
47
48
|
* @returns A function that can be used as an event handler
|
|
48
49
|
*
|
|
49
50
|
* @example
|
|
50
51
|
* ```ts
|
|
51
|
-
* const handler =
|
|
52
|
+
* const handler = createHotkeyChordHandler('Mod+S', (event, { hotkey, parsedChord }) => {
|
|
52
53
|
* console.log(`${hotkey} was pressed`)
|
|
53
54
|
* handleSave()
|
|
54
55
|
* })
|
|
@@ -56,14 +57,15 @@ function matchesKeyboardEvent(event, hotkey, platform = detectPlatform()) {
|
|
|
56
57
|
* document.addEventListener('keydown', handler)
|
|
57
58
|
* ```
|
|
58
59
|
*/
|
|
59
|
-
function
|
|
60
|
+
function createHotkeyChordHandler(chord, callback, options = {}) {
|
|
60
61
|
const { preventDefault = true, stopPropagation = true, platform } = options;
|
|
61
62
|
const resolvedPlatform = platform ?? detectPlatform();
|
|
62
|
-
const hotkeyString = typeof
|
|
63
|
-
const parsed = typeof
|
|
63
|
+
const hotkeyString = typeof chord === "string" ? chord : formatHotkey(chord);
|
|
64
|
+
const parsed = typeof chord === "string" ? parseHotkey(chord, resolvedPlatform) : chord;
|
|
64
65
|
const context = {
|
|
66
|
+
kind: "chord",
|
|
65
67
|
hotkey: hotkeyString,
|
|
66
|
-
|
|
68
|
+
parsedChord: parsed
|
|
67
69
|
};
|
|
68
70
|
return (event) => {
|
|
69
71
|
if (matchesKeyboardEvent(event, parsed, resolvedPlatform)) {
|
|
@@ -74,15 +76,15 @@ function createHotkeyHandler(hotkey, callback, options = {}) {
|
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
77
|
-
* Creates a handler that matches
|
|
79
|
+
* Creates a handler that matches several chords.
|
|
78
80
|
*
|
|
79
|
-
* @param handlers - A map of
|
|
81
|
+
* @param handlers - A map of chord strings to their handlers
|
|
80
82
|
* @param options - Options for matching and handling
|
|
81
83
|
* @returns A function that can be used as an event handler
|
|
82
84
|
*
|
|
83
85
|
* @example
|
|
84
86
|
* ```ts
|
|
85
|
-
* const handler =
|
|
87
|
+
* const handler = createMultiHotkeyChordHandler({
|
|
86
88
|
* 'Mod+S': (event, { hotkey }) => handleSave(),
|
|
87
89
|
* 'Mod+Z': (event, { hotkey }) => handleUndo(),
|
|
88
90
|
* 'Mod+Shift+Z': (event, { hotkey }) => handleRedo(),
|
|
@@ -91,7 +93,7 @@ function createHotkeyHandler(hotkey, callback, options = {}) {
|
|
|
91
93
|
* document.addEventListener('keydown', handler)
|
|
92
94
|
* ```
|
|
93
95
|
*/
|
|
94
|
-
function
|
|
96
|
+
function createMultiHotkeyChordHandler(handlers, options = {}) {
|
|
95
97
|
const { preventDefault = true, stopPropagation = true, platform } = options;
|
|
96
98
|
const resolvedPlatform = platform ?? detectPlatform();
|
|
97
99
|
const parsedHandlers = Object.entries(handlers).filter((entry) => Boolean(entry[1])).map(([hotkey, handler]) => {
|
|
@@ -100,8 +102,9 @@ function createMultiHotkeyHandler(handlers, options = {}) {
|
|
|
100
102
|
parsed,
|
|
101
103
|
handler,
|
|
102
104
|
context: {
|
|
105
|
+
kind: "chord",
|
|
103
106
|
hotkey,
|
|
104
|
-
|
|
107
|
+
parsedChord: parsed
|
|
105
108
|
}
|
|
106
109
|
};
|
|
107
110
|
});
|
|
@@ -123,7 +126,7 @@ function createMultiHotkeyHandler(handlers, options = {}) {
|
|
|
123
126
|
function areHotkeysEqual(left, right, platform = detectPlatform()) {
|
|
124
127
|
const a = isHotkeySequence(left) ? left : [left];
|
|
125
128
|
const b = isHotkeySequence(right) ? right : [right];
|
|
126
|
-
return a.length === b.length && a.every((step, index) =>
|
|
129
|
+
return a.length === b.length && a.every((step, index) => parsedChordsEqual(parseHotkey(step, platform), parseHotkey(b[index], platform)));
|
|
127
130
|
}
|
|
128
131
|
/** Default timeout between sequence steps (in milliseconds). */
|
|
129
132
|
const DEFAULT_SEQUENCE_TIMEOUT = 1e3;
|
|
@@ -152,7 +155,7 @@ const DEFAULT_SEQUENCE_TIMEOUT = 1e3;
|
|
|
152
155
|
function createSequenceMatcher(sequence, options = {}) {
|
|
153
156
|
const platform = options.platform ?? detectPlatform();
|
|
154
157
|
const timeout = options.timeout ?? 1e3;
|
|
155
|
-
const parsedSequence =
|
|
158
|
+
const parsedSequence = parseHotkey(sequence, platform);
|
|
156
159
|
let currentIndex = 0;
|
|
157
160
|
let lastKeyTime = 0;
|
|
158
161
|
return {
|
|
@@ -188,4 +191,4 @@ function createSequenceMatcher(sequence, options = {}) {
|
|
|
188
191
|
}
|
|
189
192
|
|
|
190
193
|
//#endregion
|
|
191
|
-
export { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual,
|
|
194
|
+
export { DEFAULT_SEQUENCE_TIMEOUT, areHotkeysEqual, createHotkeyChordHandler, createMultiHotkeyChordHandler, createSequenceMatcher, matchesKeyboardEvent };
|