@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
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Hotkey, HotkeyCallback, ParsedHotkey } from "./hotkey.types.js";
|
|
2
2
|
import { HotkeyOptions } from "./hotkey-manager.js";
|
|
3
3
|
import { Store } from "@tanstack/store";
|
|
4
|
-
|
|
5
4
|
//#region src/sequence-manager.d.ts
|
|
6
|
-
type Target = HTMLElement | Document | Window;
|
|
5
|
+
export type Target = HTMLElement | Document | Window;
|
|
7
6
|
/**
|
|
8
7
|
* Options for hotkey sequence matching.
|
|
9
8
|
* Extends HotkeyOptions but excludes requireReset (not applicable to sequences).
|
|
10
9
|
*/
|
|
11
|
-
interface SequenceOptions extends Omit<HotkeyOptions, 'requireReset'> {
|
|
10
|
+
export interface SequenceOptions extends Omit<HotkeyOptions, 'requireReset'> {
|
|
12
11
|
/** Timeout between keys in milliseconds. Default: 1000 */
|
|
13
12
|
timeout?: number;
|
|
14
13
|
}
|
|
@@ -28,17 +27,17 @@ interface SequenceOptions extends Omit<HotkeyOptions, 'requireReset'> {
|
|
|
28
27
|
* const chainedShift: HotkeySequence = ['Shift+R', 'Shift+T']
|
|
29
28
|
* ```
|
|
30
29
|
*/
|
|
31
|
-
type HotkeySequence = Array<Hotkey>;
|
|
30
|
+
export type HotkeySequence = Array<Hotkey>;
|
|
32
31
|
/**
|
|
33
32
|
* Default timeout between keys in a sequence (in milliseconds).
|
|
34
33
|
* Exported for consumers that display sequence state (e.g. devtools).
|
|
35
34
|
*/
|
|
36
|
-
declare const DEFAULT_SEQUENCE_TIMEOUT = 1000;
|
|
35
|
+
export declare const DEFAULT_SEQUENCE_TIMEOUT = 1000;
|
|
37
36
|
/**
|
|
38
37
|
* View of a sequence registration for devtools display.
|
|
39
38
|
* Progress fields reflect an in-progress match (between first key and completion or timeout).
|
|
40
39
|
*/
|
|
41
|
-
interface SequenceRegistrationView {
|
|
40
|
+
export interface SequenceRegistrationView {
|
|
42
41
|
id: string;
|
|
43
42
|
sequence: HotkeySequence;
|
|
44
43
|
options: SequenceOptions;
|
|
@@ -54,7 +53,7 @@ interface SequenceRegistrationView {
|
|
|
54
53
|
/**
|
|
55
54
|
* Internal representation of a sequence registration.
|
|
56
55
|
*/
|
|
57
|
-
interface SequenceRegistration {
|
|
56
|
+
export interface SequenceRegistration {
|
|
58
57
|
id: string;
|
|
59
58
|
sequence: HotkeySequence;
|
|
60
59
|
parsedSequence: Array<ParsedHotkey>;
|
|
@@ -79,14 +78,14 @@ interface SequenceRegistration {
|
|
|
79
78
|
* handle.unregister()
|
|
80
79
|
* ```
|
|
81
80
|
*/
|
|
82
|
-
interface SequenceRegistrationHandle {
|
|
81
|
+
export interface SequenceRegistrationHandle {
|
|
83
82
|
readonly id: string;
|
|
84
83
|
readonly isActive: boolean;
|
|
85
84
|
callback: HotkeyCallback;
|
|
86
85
|
setOptions: (options: Partial<SequenceOptions>) => void;
|
|
87
86
|
unregister: () => void;
|
|
88
87
|
}
|
|
89
|
-
declare class SequenceManager {
|
|
88
|
+
export declare class SequenceManager {
|
|
90
89
|
#private;
|
|
91
90
|
/**
|
|
92
91
|
* The TanStack Store containing sequence registration views for devtools.
|
|
@@ -136,7 +135,7 @@ declare class SequenceManager {
|
|
|
136
135
|
* Gets the singleton SequenceManager instance.
|
|
137
136
|
* Convenience function for accessing the manager.
|
|
138
137
|
*/
|
|
139
|
-
declare function getSequenceManager(): SequenceManager;
|
|
138
|
+
export declare function getSequenceManager(): SequenceManager;
|
|
140
139
|
/**
|
|
141
140
|
* Creates a simple sequence matcher for one-off use.
|
|
142
141
|
*
|
|
@@ -159,7 +158,7 @@ declare function getSequenceManager(): SequenceManager;
|
|
|
159
158
|
* })
|
|
160
159
|
* ```
|
|
161
160
|
*/
|
|
162
|
-
declare function createSequenceMatcher(sequence: HotkeySequence, options?: {
|
|
161
|
+
export declare function createSequenceMatcher(sequence: HotkeySequence, options?: {
|
|
163
162
|
timeout?: number;
|
|
164
163
|
platform?: 'mac' | 'windows' | 'linux';
|
|
165
164
|
}): {
|
|
@@ -167,6 +166,4 @@ declare function createSequenceMatcher(sequence: HotkeySequence, options?: {
|
|
|
167
166
|
reset: () => void;
|
|
168
167
|
getProgress: () => number;
|
|
169
168
|
};
|
|
170
|
-
//#endregion
|
|
171
|
-
export { DEFAULT_SEQUENCE_TIMEOUT, HotkeySequence, SequenceManager, SequenceOptions, SequenceRegistration, SequenceRegistrationHandle, SequenceRegistrationView, Target, createSequenceMatcher, getSequenceManager };
|
|
172
|
-
//# sourceMappingURL=sequence-manager.d.ts.map
|
|
169
|
+
//#endregion
|
package/dist/sequence-manager.js
CHANGED
|
@@ -67,12 +67,16 @@ function toRegistrationView(reg) {
|
|
|
67
67
|
}
|
|
68
68
|
var SequenceManager = class SequenceManager {
|
|
69
69
|
static #instance = null;
|
|
70
|
+
/**
|
|
71
|
+
* The TanStack Store containing sequence registration views for devtools.
|
|
72
|
+
* Subscribe to this to observe registration changes.
|
|
73
|
+
*/
|
|
74
|
+
registrations = new Store(/* @__PURE__ */ new Map());
|
|
70
75
|
#registrations = /* @__PURE__ */ new Map();
|
|
71
76
|
#targetListeners = /* @__PURE__ */ new Map();
|
|
72
77
|
#targetRegistrations = /* @__PURE__ */ new Map();
|
|
73
78
|
#platform;
|
|
74
79
|
constructor() {
|
|
75
|
-
this.registrations = new Store(/* @__PURE__ */ new Map());
|
|
76
80
|
this.#platform = detectPlatform();
|
|
77
81
|
}
|
|
78
82
|
/**
|
|
@@ -417,10 +421,12 @@ function createSequenceMatcher(sequence, options = {}) {
|
|
|
417
421
|
currentIndex = 0;
|
|
418
422
|
return true;
|
|
419
423
|
}
|
|
420
|
-
} else if (currentIndex > 0)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
+
} else if (currentIndex > 0) {
|
|
425
|
+
if (matchesKeyboardEvent(event, parsedSequence[0], platform)) {
|
|
426
|
+
currentIndex = 1;
|
|
427
|
+
lastKeyTime = now;
|
|
428
|
+
} else currentIndex = 0;
|
|
429
|
+
}
|
|
424
430
|
return false;
|
|
425
431
|
},
|
|
426
432
|
reset() {
|
|
@@ -434,5 +440,4 @@ function createSequenceMatcher(sequence, options = {}) {
|
|
|
434
440
|
}
|
|
435
441
|
|
|
436
442
|
//#endregion
|
|
437
|
-
export { DEFAULT_SEQUENCE_TIMEOUT, SequenceManager, createSequenceMatcher, getSequenceManager };
|
|
438
|
-
//# sourceMappingURL=sequence-manager.js.map
|
|
443
|
+
export { DEFAULT_SEQUENCE_TIMEOUT, SequenceManager, createSequenceMatcher, getSequenceManager };
|
package/dist/validate.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Hotkey } from "./hotkey.types.js";
|
|
2
|
-
|
|
3
2
|
//#region src/validate.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Validates a hotkey string and returns any warnings or errors.
|
|
@@ -21,7 +20,7 @@ import { Hotkey } from "./hotkey.types.js";
|
|
|
21
20
|
* // { valid: false, warnings: [], errors: ['Hotkey cannot be empty'] }
|
|
22
21
|
* ```
|
|
23
22
|
*/
|
|
24
|
-
declare function validateHotkey(hotkey: Hotkey | (string & {})): ValidationResult;
|
|
23
|
+
export declare function validateHotkey(hotkey: Hotkey | (string & {})): ValidationResult;
|
|
25
24
|
/**
|
|
26
25
|
* Validates a hotkey and throws an error if invalid.
|
|
27
26
|
* Useful for development-time validation.
|
|
@@ -35,7 +34,7 @@ declare function validateHotkey(hotkey: Hotkey | (string & {})): ValidationResul
|
|
|
35
34
|
* assertValidHotkey('') // Throws Error: Invalid hotkey: Hotkey cannot be empty
|
|
36
35
|
* ```
|
|
37
36
|
*/
|
|
38
|
-
declare function assertValidHotkey(hotkey: Hotkey | (string & {})): void;
|
|
37
|
+
export declare function assertValidHotkey(hotkey: Hotkey | (string & {})): void;
|
|
39
38
|
/**
|
|
40
39
|
* Validates a hotkey and logs warnings to the console.
|
|
41
40
|
* Useful for development-time feedback.
|
|
@@ -50,11 +49,11 @@ declare function assertValidHotkey(hotkey: Hotkey | (string & {})): void;
|
|
|
50
49
|
* // Returns: true
|
|
51
50
|
* ```
|
|
52
51
|
*/
|
|
53
|
-
declare function checkHotkey(hotkey: Hotkey | (string & {})): boolean;
|
|
52
|
+
export declare function checkHotkey(hotkey: Hotkey | (string & {})): boolean;
|
|
54
53
|
/**
|
|
55
54
|
* Result of validating a hotkey string.
|
|
56
55
|
*/
|
|
57
|
-
interface ValidationResult {
|
|
56
|
+
export interface ValidationResult {
|
|
58
57
|
/** Whether the hotkey is valid (can still have warnings) */
|
|
59
58
|
valid: boolean;
|
|
60
59
|
/** Warning messages about potential issues */
|
|
@@ -62,6 +61,4 @@ interface ValidationResult {
|
|
|
62
61
|
/** Error messages about invalid syntax */
|
|
63
62
|
errors: Array<string>;
|
|
64
63
|
}
|
|
65
|
-
//#endregion
|
|
66
|
-
export { ValidationResult, assertValidHotkey, checkHotkey, validateHotkey };
|
|
67
|
-
//# sourceMappingURL=validate.d.ts.map
|
|
64
|
+
//#endregion
|
package/dist/validate.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/hotkeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Type-safe, framework-agnostic keyboard hotkey management for the browser",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,26 +24,20 @@
|
|
|
24
24
|
"typescript"
|
|
25
25
|
],
|
|
26
26
|
"type": "module",
|
|
27
|
-
"
|
|
28
|
-
"module": "./dist/index.js",
|
|
29
|
-
"types": "./dist/index.d.cts",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
30
28
|
"exports": {
|
|
31
|
-
".":
|
|
32
|
-
"import": "./dist/index.js",
|
|
33
|
-
"require": "./dist/index.cjs"
|
|
34
|
-
},
|
|
29
|
+
".": "./dist/index.js",
|
|
35
30
|
"./package.json": "./package.json"
|
|
36
31
|
},
|
|
37
32
|
"sideEffects": false,
|
|
38
33
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
34
|
+
"node": ">=20"
|
|
40
35
|
},
|
|
41
36
|
"files": [
|
|
42
|
-
"dist
|
|
43
|
-
"src"
|
|
37
|
+
"dist"
|
|
44
38
|
],
|
|
45
39
|
"dependencies": {
|
|
46
|
-
"@tanstack/store": "^0.11.
|
|
40
|
+
"@tanstack/store": "^0.11.1"
|
|
47
41
|
},
|
|
48
42
|
"scripts": {
|
|
49
43
|
"clean": "premove ./build ./dist",
|
|
@@ -53,6 +47,7 @@
|
|
|
53
47
|
"test:lib": "vitest",
|
|
54
48
|
"test:lib:dev": "pnpm test:lib --watch",
|
|
55
49
|
"test:types": "tsc",
|
|
56
|
-
"build": "tsdown"
|
|
50
|
+
"build": "tsdown",
|
|
51
|
+
"test:build": "publint --strict && node ../../scripts/verify-package.ts"
|
|
57
52
|
}
|
|
58
53
|
}
|
package/dist/_event-target.cjs
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/_event-target.ts
|
|
3
|
-
/**
|
|
4
|
-
* Checks if an element is an input-like element that should be ignored for hotkeys.
|
|
5
|
-
*
|
|
6
|
-
* This includes:
|
|
7
|
-
* - HTMLInputElement (all input types except button, submit, reset)
|
|
8
|
-
* - HTMLTextAreaElement
|
|
9
|
-
* - HTMLSelectElement
|
|
10
|
-
* - Elements with contentEditable enabled
|
|
11
|
-
*
|
|
12
|
-
* Button-type inputs (button, submit, reset) are excluded so hotkeys like
|
|
13
|
-
* Mod+S and Escape fire when the user has tabbed to a form button.
|
|
14
|
-
*/
|
|
15
|
-
function isInputElement(element) {
|
|
16
|
-
if (!element) return false;
|
|
17
|
-
if (element instanceof HTMLInputElement) {
|
|
18
|
-
const type = element.type.toLowerCase();
|
|
19
|
-
if (type === "button" || type === "submit" || type === "reset") return false;
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
if (element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) return true;
|
|
23
|
-
if (element instanceof HTMLElement && element.isContentEditable) return true;
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Returns the focused element for the document associated with where hotkey
|
|
28
|
-
* listeners are attached (listener root). Use this instead of the global
|
|
29
|
-
* `document.activeElement` so registrations scoped to an iframe (or another
|
|
30
|
-
* document) read focus from the correct tree.
|
|
31
|
-
*/
|
|
32
|
-
function getActiveElementForListenerTarget(target) {
|
|
33
|
-
if (typeof document === "undefined") return null;
|
|
34
|
-
if (typeof Document !== "undefined" && target instanceof Document || typeof Node !== "undefined" && target.nodeType === Node.DOCUMENT_NODE) return target.activeElement;
|
|
35
|
-
if (typeof HTMLElement !== "undefined" && target instanceof HTMLElement) return target.ownerDocument.activeElement ?? null;
|
|
36
|
-
return target.document.activeElement ?? null;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Returns whether an event should be ignored because it originated from an
|
|
40
|
-
* input-like element other than the registration target.
|
|
41
|
-
*
|
|
42
|
-
* This checks:
|
|
43
|
-
* - the currently focused element for the listener target
|
|
44
|
-
* - the event's composed path (for shadow DOM)
|
|
45
|
-
* - the event target as a final fallback
|
|
46
|
-
*/
|
|
47
|
-
function shouldIgnoreInputEvent(event, listenerTarget, registrationTarget) {
|
|
48
|
-
const focused = getActiveElementForListenerTarget(listenerTarget);
|
|
49
|
-
if (focused && isInputElement(focused) && focused !== registrationTarget) return true;
|
|
50
|
-
if (event.composedPath().some((element) => isInputElement(element) && element !== registrationTarget)) return true;
|
|
51
|
-
return isInputElement(event.target) && event.target !== registrationTarget;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Checks if an event is for the given target (originated from or bubbled to it).
|
|
55
|
-
*
|
|
56
|
-
* For document/window targets, also accepts document.documentElement as currentTarget
|
|
57
|
-
* to handle Brave and other browsers where currentTarget may be documentElement
|
|
58
|
-
* instead of document when listeners are attached to document.
|
|
59
|
-
*/
|
|
60
|
-
function isEventForTarget(event, target) {
|
|
61
|
-
if (target === document || target === window) return event.currentTarget === target || event.currentTarget === document.documentElement;
|
|
62
|
-
if (target === window) return event.currentTarget === window || event.currentTarget === document || event.currentTarget === document.documentElement;
|
|
63
|
-
if (target instanceof HTMLElement) {
|
|
64
|
-
if (event.currentTarget === target) return true;
|
|
65
|
-
if (event.target instanceof Node && target.contains(event.target)) return true;
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
//#endregion
|
|
71
|
-
exports.isEventForTarget = isEventForTarget;
|
|
72
|
-
exports.shouldIgnoreInputEvent = shouldIgnoreInputEvent;
|
|
73
|
-
//# sourceMappingURL=_event-target.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_event-target.cjs","names":[],"sources":["../src/_event-target.ts"],"sourcesContent":["/**\n * Checks if an element is an input-like element that should be ignored for hotkeys.\n *\n * This includes:\n * - HTMLInputElement (all input types except button, submit, reset)\n * - HTMLTextAreaElement\n * - HTMLSelectElement\n * - Elements with contentEditable enabled\n *\n * Button-type inputs (button, submit, reset) are excluded so hotkeys like\n * Mod+S and Escape fire when the user has tabbed to a form button.\n */\nexport function isInputElement(element: EventTarget | null): boolean {\n if (!element) {\n return false\n }\n\n if (element instanceof HTMLInputElement) {\n const type = element.type.toLowerCase()\n if (type === 'button' || type === 'submit' || type === 'reset') {\n return false\n }\n return true\n }\n\n if (\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n return true\n }\n\n // Check for contenteditable elements (includes \"true\", \"\", \"plaintext-only\",\n // and inherited contenteditable from ancestor elements)\n if (element instanceof HTMLElement && element.isContentEditable) {\n return true\n }\n\n return false\n}\n\n/**\n * Returns the focused element for the document associated with where hotkey\n * listeners are attached (listener root). Use this instead of the global\n * `document.activeElement` so registrations scoped to an iframe (or another\n * document) read focus from the correct tree.\n */\nexport function getActiveElementForListenerTarget(\n target: HTMLElement | Document | Window,\n): Element | null {\n if (typeof document === 'undefined') {\n return null\n }\n\n // Document first (nodeType covers environments where `document instanceof Document` is false)\n if (\n (typeof Document !== 'undefined' && target instanceof Document) ||\n (typeof Node !== 'undefined' &&\n (target as Node).nodeType === Node.DOCUMENT_NODE)\n ) {\n return (target as Document).activeElement\n }\n\n if (typeof HTMLElement !== 'undefined' && target instanceof HTMLElement) {\n return target.ownerDocument.activeElement ?? null\n }\n\n // Window (global or iframe): avoid relying on `instanceof Window` alone (test DOM quirks)\n return (target as Window).document.activeElement ?? null\n}\n\n/**\n * Returns whether an event should be ignored because it originated from an\n * input-like element other than the registration target.\n *\n * This checks:\n * - the currently focused element for the listener target\n * - the event's composed path (for shadow DOM)\n * - the event target as a final fallback\n */\nexport function shouldIgnoreInputEvent(\n event: KeyboardEvent,\n listenerTarget: HTMLElement | Document | Window,\n registrationTarget: HTMLElement | Document | Window,\n): boolean {\n const focused = getActiveElementForListenerTarget(listenerTarget)\n if (focused && isInputElement(focused) && focused !== registrationTarget) {\n return true\n }\n\n if (\n event\n .composedPath()\n .some(\n (element) => isInputElement(element) && element !== registrationTarget,\n )\n ) {\n return true\n }\n\n return isInputElement(event.target) && event.target !== registrationTarget\n}\n\n/**\n * Checks if an event is for the given target (originated from or bubbled to it).\n *\n * For document/window targets, also accepts document.documentElement as currentTarget\n * to handle Brave and other browsers where currentTarget may be documentElement\n * instead of document when listeners are attached to document.\n */\nexport function isEventForTarget(\n event: KeyboardEvent,\n target: HTMLElement | Document | Window,\n): boolean {\n // For Document and Window, verify that our handler was indeed called for this target.\n //\n // Browser compatibility note:\n // Per the DOM spec, event.currentTarget should equal the element the listener was\n // attached to. However, some Chromium-based browsers (notably Brave) exhibit\n // non-standard behavior where event.currentTarget is set to document.documentElement\n // (<html>) instead of document when a listener is attached to document.\n // This may be related to privacy/fingerprinting protections.\n //\n // To ensure cross-browser compatibility, we accept both the expected target\n // and document.documentElement as valid currentTarget values.\n // See: https://dom.spec.whatwg.org/#dom-event-currenttarget\n if (target === document || target === window) {\n return (\n event.currentTarget === target ||\n event.currentTarget === document.documentElement\n )\n }\n\n // For Window, accept window, document, or document.documentElement (browser quirks)\n if (target === window) {\n return (\n event.currentTarget === window ||\n event.currentTarget === document ||\n event.currentTarget === document.documentElement\n )\n }\n\n // For HTMLElement, check if event originated from or bubbled to the element\n if (target instanceof HTMLElement) {\n // Check if the event's currentTarget is the target (capturing/bubbling)\n if (event.currentTarget === target) {\n return true\n }\n\n // Check if the event's target is a descendant of our target\n if (event.target instanceof Node && target.contains(event.target)) {\n return true\n }\n }\n\n return false\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,SAAgB,eAAe,SAAsC;AACnE,KAAI,CAAC,QACH,QAAO;AAGT,KAAI,mBAAmB,kBAAkB;EACvC,MAAM,OAAO,QAAQ,KAAK,aAAa;AACvC,MAAI,SAAS,YAAY,SAAS,YAAY,SAAS,QACrD,QAAO;AAET,SAAO;;AAGT,KACE,mBAAmB,uBACnB,mBAAmB,kBAEnB,QAAO;AAKT,KAAI,mBAAmB,eAAe,QAAQ,kBAC5C,QAAO;AAGT,QAAO;;;;;;;;AAST,SAAgB,kCACd,QACgB;AAChB,KAAI,OAAO,aAAa,YACtB,QAAO;AAIT,KACG,OAAO,aAAa,eAAe,kBAAkB,YACrD,OAAO,SAAS,eACd,OAAgB,aAAa,KAAK,cAErC,QAAQ,OAAoB;AAG9B,KAAI,OAAO,gBAAgB,eAAe,kBAAkB,YAC1D,QAAO,OAAO,cAAc,iBAAiB;AAI/C,QAAQ,OAAkB,SAAS,iBAAiB;;;;;;;;;;;AAYtD,SAAgB,uBACd,OACA,gBACA,oBACS;CACT,MAAM,UAAU,kCAAkC,eAAe;AACjE,KAAI,WAAW,eAAe,QAAQ,IAAI,YAAY,mBACpD,QAAO;AAGT,KACE,MACG,cAAc,CACd,MACE,YAAY,eAAe,QAAQ,IAAI,YAAY,mBACrD,CAEH,QAAO;AAGT,QAAO,eAAe,MAAM,OAAO,IAAI,MAAM,WAAW;;;;;;;;;AAU1D,SAAgB,iBACd,OACA,QACS;AAaT,KAAI,WAAW,YAAY,WAAW,OACpC,QACE,MAAM,kBAAkB,UACxB,MAAM,kBAAkB,SAAS;AAKrC,KAAI,WAAW,OACb,QACE,MAAM,kBAAkB,UACxB,MAAM,kBAAkB,YACxB,MAAM,kBAAkB,SAAS;AAKrC,KAAI,kBAAkB,aAAa;AAEjC,MAAI,MAAM,kBAAkB,OAC1B,QAAO;AAIT,MAAI,MAAM,kBAAkB,QAAQ,OAAO,SAAS,MAAM,OAAO,CAC/D,QAAO;;AAIX,QAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_event-target.js","names":[],"sources":["../src/_event-target.ts"],"sourcesContent":["/**\n * Checks if an element is an input-like element that should be ignored for hotkeys.\n *\n * This includes:\n * - HTMLInputElement (all input types except button, submit, reset)\n * - HTMLTextAreaElement\n * - HTMLSelectElement\n * - Elements with contentEditable enabled\n *\n * Button-type inputs (button, submit, reset) are excluded so hotkeys like\n * Mod+S and Escape fire when the user has tabbed to a form button.\n */\nexport function isInputElement(element: EventTarget | null): boolean {\n if (!element) {\n return false\n }\n\n if (element instanceof HTMLInputElement) {\n const type = element.type.toLowerCase()\n if (type === 'button' || type === 'submit' || type === 'reset') {\n return false\n }\n return true\n }\n\n if (\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n return true\n }\n\n // Check for contenteditable elements (includes \"true\", \"\", \"plaintext-only\",\n // and inherited contenteditable from ancestor elements)\n if (element instanceof HTMLElement && element.isContentEditable) {\n return true\n }\n\n return false\n}\n\n/**\n * Returns the focused element for the document associated with where hotkey\n * listeners are attached (listener root). Use this instead of the global\n * `document.activeElement` so registrations scoped to an iframe (or another\n * document) read focus from the correct tree.\n */\nexport function getActiveElementForListenerTarget(\n target: HTMLElement | Document | Window,\n): Element | null {\n if (typeof document === 'undefined') {\n return null\n }\n\n // Document first (nodeType covers environments where `document instanceof Document` is false)\n if (\n (typeof Document !== 'undefined' && target instanceof Document) ||\n (typeof Node !== 'undefined' &&\n (target as Node).nodeType === Node.DOCUMENT_NODE)\n ) {\n return (target as Document).activeElement\n }\n\n if (typeof HTMLElement !== 'undefined' && target instanceof HTMLElement) {\n return target.ownerDocument.activeElement ?? null\n }\n\n // Window (global or iframe): avoid relying on `instanceof Window` alone (test DOM quirks)\n return (target as Window).document.activeElement ?? null\n}\n\n/**\n * Returns whether an event should be ignored because it originated from an\n * input-like element other than the registration target.\n *\n * This checks:\n * - the currently focused element for the listener target\n * - the event's composed path (for shadow DOM)\n * - the event target as a final fallback\n */\nexport function shouldIgnoreInputEvent(\n event: KeyboardEvent,\n listenerTarget: HTMLElement | Document | Window,\n registrationTarget: HTMLElement | Document | Window,\n): boolean {\n const focused = getActiveElementForListenerTarget(listenerTarget)\n if (focused && isInputElement(focused) && focused !== registrationTarget) {\n return true\n }\n\n if (\n event\n .composedPath()\n .some(\n (element) => isInputElement(element) && element !== registrationTarget,\n )\n ) {\n return true\n }\n\n return isInputElement(event.target) && event.target !== registrationTarget\n}\n\n/**\n * Checks if an event is for the given target (originated from or bubbled to it).\n *\n * For document/window targets, also accepts document.documentElement as currentTarget\n * to handle Brave and other browsers where currentTarget may be documentElement\n * instead of document when listeners are attached to document.\n */\nexport function isEventForTarget(\n event: KeyboardEvent,\n target: HTMLElement | Document | Window,\n): boolean {\n // For Document and Window, verify that our handler was indeed called for this target.\n //\n // Browser compatibility note:\n // Per the DOM spec, event.currentTarget should equal the element the listener was\n // attached to. However, some Chromium-based browsers (notably Brave) exhibit\n // non-standard behavior where event.currentTarget is set to document.documentElement\n // (<html>) instead of document when a listener is attached to document.\n // This may be related to privacy/fingerprinting protections.\n //\n // To ensure cross-browser compatibility, we accept both the expected target\n // and document.documentElement as valid currentTarget values.\n // See: https://dom.spec.whatwg.org/#dom-event-currenttarget\n if (target === document || target === window) {\n return (\n event.currentTarget === target ||\n event.currentTarget === document.documentElement\n )\n }\n\n // For Window, accept window, document, or document.documentElement (browser quirks)\n if (target === window) {\n return (\n event.currentTarget === window ||\n event.currentTarget === document ||\n event.currentTarget === document.documentElement\n )\n }\n\n // For HTMLElement, check if event originated from or bubbled to the element\n if (target instanceof HTMLElement) {\n // Check if the event's currentTarget is the target (capturing/bubbling)\n if (event.currentTarget === target) {\n return true\n }\n\n // Check if the event's target is a descendant of our target\n if (event.target instanceof Node && target.contains(event.target)) {\n return true\n }\n }\n\n return false\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,eAAe,SAAsC;AACnE,KAAI,CAAC,QACH,QAAO;AAGT,KAAI,mBAAmB,kBAAkB;EACvC,MAAM,OAAO,QAAQ,KAAK,aAAa;AACvC,MAAI,SAAS,YAAY,SAAS,YAAY,SAAS,QACrD,QAAO;AAET,SAAO;;AAGT,KACE,mBAAmB,uBACnB,mBAAmB,kBAEnB,QAAO;AAKT,KAAI,mBAAmB,eAAe,QAAQ,kBAC5C,QAAO;AAGT,QAAO;;;;;;;;AAST,SAAgB,kCACd,QACgB;AAChB,KAAI,OAAO,aAAa,YACtB,QAAO;AAIT,KACG,OAAO,aAAa,eAAe,kBAAkB,YACrD,OAAO,SAAS,eACd,OAAgB,aAAa,KAAK,cAErC,QAAQ,OAAoB;AAG9B,KAAI,OAAO,gBAAgB,eAAe,kBAAkB,YAC1D,QAAO,OAAO,cAAc,iBAAiB;AAI/C,QAAQ,OAAkB,SAAS,iBAAiB;;;;;;;;;;;AAYtD,SAAgB,uBACd,OACA,gBACA,oBACS;CACT,MAAM,UAAU,kCAAkC,eAAe;AACjE,KAAI,WAAW,eAAe,QAAQ,IAAI,YAAY,mBACpD,QAAO;AAGT,KACE,MACG,cAAc,CACd,MACE,YAAY,eAAe,QAAQ,IAAI,YAAY,mBACrD,CAEH,QAAO;AAGT,QAAO,eAAe,MAAM,OAAO,IAAI,MAAM,WAAW;;;;;;;;;AAU1D,SAAgB,iBACd,OACA,QACS;AAaT,KAAI,WAAW,YAAY,WAAW,OACpC,QACE,MAAM,kBAAkB,UACxB,MAAM,kBAAkB,SAAS;AAKrC,KAAI,WAAW,OACb,QACE,MAAM,kBAAkB,UACxB,MAAM,kBAAkB,YACxB,MAAM,kBAAkB,SAAS;AAKrC,KAAI,kBAAkB,aAAa;AAEjC,MAAI,MAAM,kBAAkB,OAC1B,QAAO;AAIT,MAAI,MAAM,kBAAkB,QAAQ,OAAO,SAAS,MAAM,OAAO,CAC/D,QAAO;;AAIX,QAAO"}
|
package/dist/_keyboard-event.cjs
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const require_constants = require('./constants.cjs');
|
|
2
|
-
|
|
3
|
-
//#region src/_keyboard-event.ts
|
|
4
|
-
/** Normalizes Unicode key names and modifier flags while retaining physical code and IME state. */
|
|
5
|
-
function normalizeKeyboardEvent(event, platform) {
|
|
6
|
-
let altGraph = false;
|
|
7
|
-
try {
|
|
8
|
-
altGraph = platform !== "mac" && typeof event.getModifierState === "function" && event.getModifierState("AltGraph");
|
|
9
|
-
} catch {}
|
|
10
|
-
const key = (event.key || "").normalize("NFC");
|
|
11
|
-
return {
|
|
12
|
-
key: require_constants.normalizeKeyName(key),
|
|
13
|
-
code: event.code || "",
|
|
14
|
-
ctrl: Boolean(event.ctrlKey),
|
|
15
|
-
shift: Boolean(event.shiftKey),
|
|
16
|
-
alt: Boolean(event.altKey),
|
|
17
|
-
meta: Boolean(event.metaKey),
|
|
18
|
-
altGraph,
|
|
19
|
-
location: event.location,
|
|
20
|
-
isComposing: Boolean(event.isComposing) || key === "Process" || key === "Unidentified"
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Maps familiar positions to compatibility fallback keys for the logical matcher.
|
|
25
|
-
* This assumes conventional positions, not the active layout; never use it to
|
|
26
|
-
* turn recorded physical bindings into logical bindings or display labels.
|
|
27
|
-
*/
|
|
28
|
-
function codeToLogicalKey(code) {
|
|
29
|
-
if (/^Key[A-Z]$/i.test(code)) return code.slice(3).toUpperCase();
|
|
30
|
-
if (/^Digit[0-9]$/i.test(code)) return code.slice(5);
|
|
31
|
-
if (/^Numpad[0-9]$/i.test(code)) return code.slice(6);
|
|
32
|
-
const punctuation = require_constants.PUNCTUATION_CODE_MAP[code];
|
|
33
|
-
if (punctuation) return punctuation;
|
|
34
|
-
return {
|
|
35
|
-
NumpadAdd: "+",
|
|
36
|
-
NumpadSubtract: "-",
|
|
37
|
-
NumpadMultiply: "*",
|
|
38
|
-
NumpadDivide: "/",
|
|
39
|
-
NumpadDecimal: ".",
|
|
40
|
-
NumpadEnter: "Enter",
|
|
41
|
-
Space: "Space"
|
|
42
|
-
}[code];
|
|
43
|
-
}
|
|
44
|
-
/** Tests for one Unicode code point, including characters represented by a surrogate pair. */
|
|
45
|
-
function isPrintableKey(key) {
|
|
46
|
-
return key !== "" && Array.from(key).length === 1;
|
|
47
|
-
}
|
|
48
|
-
/** Splits modifier tokens while retaining a trailing literal plus: `Control++` → `['Control', '+']`. */
|
|
49
|
-
function splitHotkeyParts(hotkey) {
|
|
50
|
-
if (!hotkey.endsWith("+")) return hotkey.split("+");
|
|
51
|
-
const parts = hotkey.slice(0, -1).split("+");
|
|
52
|
-
if (parts.at(-1) === "") parts.pop();
|
|
53
|
-
parts.push("+");
|
|
54
|
-
return parts;
|
|
55
|
-
}
|
|
56
|
-
/** Identifies ASCII letters whose layout-produced value takes precedence over positional fallbacks. */
|
|
57
|
-
function isAsciiLetter(key) {
|
|
58
|
-
return /^[A-Za-z]$/.test(key);
|
|
59
|
-
}
|
|
60
|
-
/** Identifies a single Latin-script character, including accented letters. */
|
|
61
|
-
function isLatinLetter(key) {
|
|
62
|
-
return /^\p{Script_Extensions=Latin}$/u.test(key);
|
|
63
|
-
}
|
|
64
|
-
/** Compares letters without case, preserving accents and avoiding expansions such as ß → SS. */
|
|
65
|
-
function keysEqual(left, right) {
|
|
66
|
-
if (/^\p{Letter}$/u.test(left) && /^\p{Letter}$/u.test(right)) return left.localeCompare(right, void 0, { sensitivity: "accent" }) === 0;
|
|
67
|
-
return left === right;
|
|
68
|
-
}
|
|
69
|
-
/** Rejects reserved physical-token syntax in logical object fields while allowing Unicode characters. */
|
|
70
|
-
function assertLogicalKey(key) {
|
|
71
|
-
if (/^\[.*\]$/s.test(key.trim())) throw new Error("Logical key must not contain a bracketed physical code. Use the code field instead.");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
//#endregion
|
|
75
|
-
exports.assertLogicalKey = assertLogicalKey;
|
|
76
|
-
exports.codeToLogicalKey = codeToLogicalKey;
|
|
77
|
-
exports.isAsciiLetter = isAsciiLetter;
|
|
78
|
-
exports.isLatinLetter = isLatinLetter;
|
|
79
|
-
exports.isPrintableKey = isPrintableKey;
|
|
80
|
-
exports.keysEqual = keysEqual;
|
|
81
|
-
exports.normalizeKeyboardEvent = normalizeKeyboardEvent;
|
|
82
|
-
exports.splitHotkeyParts = splitHotkeyParts;
|
|
83
|
-
//# sourceMappingURL=_keyboard-event.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_keyboard-event.cjs","names":["normalizeKeyName","PUNCTUATION_CODE_MAP"],"sources":["../src/_keyboard-event.ts"],"sourcesContent":["import { PUNCTUATION_CODE_MAP, normalizeKeyName } from './constants'\nimport type { NormalizedKeyboardEvent } from './key.types'\n\n/** Normalizes Unicode key names and modifier flags while retaining physical code and IME state. */\nexport function normalizeKeyboardEvent(\n event: KeyboardEvent,\n platform?: 'mac' | 'windows' | 'linux',\n): NormalizedKeyboardEvent {\n let altGraph = false\n try {\n // WebKit reports AltGraph for Option on some macOS keyboard layouts. Option\n // remains a normal Alt shortcut modifier there, so only use this signal on\n // Windows/Linux where AltGraph synthesizes Control+Alt.\n altGraph =\n platform !== 'mac' &&\n typeof event.getModifierState === 'function' &&\n event.getModifierState('AltGraph')\n } catch {\n // Synthetic events and older browsers may not implement this reliably.\n }\n\n const key = (event.key || '').normalize('NFC')\n return {\n key: normalizeKeyName(key),\n code: event.code || '',\n ctrl: Boolean(event.ctrlKey),\n shift: Boolean(event.shiftKey),\n alt: Boolean(event.altKey),\n meta: Boolean(event.metaKey),\n altGraph,\n location: event.location,\n isComposing:\n Boolean(event.isComposing) || key === 'Process' || key === 'Unidentified',\n }\n}\n\n/**\n * Maps familiar positions to compatibility fallback keys for the logical matcher.\n * This assumes conventional positions, not the active layout; never use it to\n * turn recorded physical bindings into logical bindings or display labels.\n */\nexport function codeToLogicalKey(code: string): string | undefined {\n if (/^Key[A-Z]$/i.test(code)) return code.slice(3).toUpperCase()\n if (/^Digit[0-9]$/i.test(code)) return code.slice(5)\n if (/^Numpad[0-9]$/i.test(code)) return code.slice(6)\n\n const punctuation = PUNCTUATION_CODE_MAP[code]\n if (punctuation) return punctuation\n\n const named: Record<string, string> = {\n NumpadAdd: '+',\n NumpadSubtract: '-',\n NumpadMultiply: '*',\n NumpadDivide: '/',\n NumpadDecimal: '.',\n NumpadEnter: 'Enter',\n Space: 'Space',\n }\n return named[code]\n}\n\n/** Tests for one Unicode code point, including characters represented by a surrogate pair. */\nexport function isPrintableKey(key: string): boolean {\n return key !== '' && Array.from(key).length === 1\n}\n\n/** Splits modifier tokens while retaining a trailing literal plus: `Control++` → `['Control', '+']`. */\nexport function splitHotkeyParts(hotkey: string): Array<string> {\n if (!hotkey.endsWith('+')) return hotkey.split('+')\n const parts = hotkey.slice(0, -1).split('+')\n if (parts.at(-1) === '') parts.pop()\n parts.push('+')\n return parts\n}\n\n/** Identifies ASCII letters whose layout-produced value takes precedence over positional fallbacks. */\nexport function isAsciiLetter(key: string): boolean {\n return /^[A-Za-z]$/.test(key)\n}\n\n/** Identifies a single Latin-script character, including accented letters. */\nexport function isLatinLetter(key: string): boolean {\n return /^\\p{Script_Extensions=Latin}$/u.test(key)\n}\n\n/** Compares letters without case, preserving accents and avoiding expansions such as ß → SS. */\nexport function keysEqual(left: string, right: string): boolean {\n if (/^\\p{Letter}$/u.test(left) && /^\\p{Letter}$/u.test(right)) {\n return left.localeCompare(right, undefined, { sensitivity: 'accent' }) === 0\n }\n return left === right\n}\n\n/** Rejects reserved physical-token syntax in logical object fields while allowing Unicode characters. */\nexport function assertLogicalKey(key: string): void {\n if (/^\\[.*\\]$/s.test(key.trim())) {\n throw new Error(\n 'Logical key must not contain a bracketed physical code. Use the code field instead.',\n )\n }\n}\n"],"mappings":";;;;AAIA,SAAgB,uBACd,OACA,UACyB;CACzB,IAAI,WAAW;AACf,KAAI;AAIF,aACE,aAAa,SACb,OAAO,MAAM,qBAAqB,cAClC,MAAM,iBAAiB,WAAW;SAC9B;CAIR,MAAM,OAAO,MAAM,OAAO,IAAI,UAAU,MAAM;AAC9C,QAAO;EACL,KAAKA,mCAAiB,IAAI;EAC1B,MAAM,MAAM,QAAQ;EACpB,MAAM,QAAQ,MAAM,QAAQ;EAC5B,OAAO,QAAQ,MAAM,SAAS;EAC9B,KAAK,QAAQ,MAAM,OAAO;EAC1B,MAAM,QAAQ,MAAM,QAAQ;EAC5B;EACA,UAAU,MAAM;EAChB,aACE,QAAQ,MAAM,YAAY,IAAI,QAAQ,aAAa,QAAQ;EAC9D;;;;;;;AAQH,SAAgB,iBAAiB,MAAkC;AACjE,KAAI,cAAc,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE,CAAC,aAAa;AAChE,KAAI,gBAAgB,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE;AACpD,KAAI,iBAAiB,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE;CAErD,MAAM,cAAcC,uCAAqB;AACzC,KAAI,YAAa,QAAO;AAWxB,QATsC;EACpC,WAAW;EACX,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EACb,OAAO;EACR,CACY;;;AAIf,SAAgB,eAAe,KAAsB;AACnD,QAAO,QAAQ,MAAM,MAAM,KAAK,IAAI,CAAC,WAAW;;;AAIlD,SAAgB,iBAAiB,QAA+B;AAC9D,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,MAAM,IAAI;CACnD,MAAM,QAAQ,OAAO,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI;AAC5C,KAAI,MAAM,GAAG,GAAG,KAAK,GAAI,OAAM,KAAK;AACpC,OAAM,KAAK,IAAI;AACf,QAAO;;;AAIT,SAAgB,cAAc,KAAsB;AAClD,QAAO,aAAa,KAAK,IAAI;;;AAI/B,SAAgB,cAAc,KAAsB;AAClD,QAAO,iCAAiC,KAAK,IAAI;;;AAInD,SAAgB,UAAU,MAAc,OAAwB;AAC9D,KAAI,gBAAgB,KAAK,KAAK,IAAI,gBAAgB,KAAK,MAAM,CAC3D,QAAO,KAAK,cAAc,OAAO,QAAW,EAAE,aAAa,UAAU,CAAC,KAAK;AAE7E,QAAO,SAAS;;;AAIlB,SAAgB,iBAAiB,KAAmB;AAClD,KAAI,YAAY,KAAK,IAAI,MAAM,CAAC,CAC9B,OAAM,IAAI,MACR,sFACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_keyboard-event.js","names":[],"sources":["../src/_keyboard-event.ts"],"sourcesContent":["import { PUNCTUATION_CODE_MAP, normalizeKeyName } from './constants'\nimport type { NormalizedKeyboardEvent } from './key.types'\n\n/** Normalizes Unicode key names and modifier flags while retaining physical code and IME state. */\nexport function normalizeKeyboardEvent(\n event: KeyboardEvent,\n platform?: 'mac' | 'windows' | 'linux',\n): NormalizedKeyboardEvent {\n let altGraph = false\n try {\n // WebKit reports AltGraph for Option on some macOS keyboard layouts. Option\n // remains a normal Alt shortcut modifier there, so only use this signal on\n // Windows/Linux where AltGraph synthesizes Control+Alt.\n altGraph =\n platform !== 'mac' &&\n typeof event.getModifierState === 'function' &&\n event.getModifierState('AltGraph')\n } catch {\n // Synthetic events and older browsers may not implement this reliably.\n }\n\n const key = (event.key || '').normalize('NFC')\n return {\n key: normalizeKeyName(key),\n code: event.code || '',\n ctrl: Boolean(event.ctrlKey),\n shift: Boolean(event.shiftKey),\n alt: Boolean(event.altKey),\n meta: Boolean(event.metaKey),\n altGraph,\n location: event.location,\n isComposing:\n Boolean(event.isComposing) || key === 'Process' || key === 'Unidentified',\n }\n}\n\n/**\n * Maps familiar positions to compatibility fallback keys for the logical matcher.\n * This assumes conventional positions, not the active layout; never use it to\n * turn recorded physical bindings into logical bindings or display labels.\n */\nexport function codeToLogicalKey(code: string): string | undefined {\n if (/^Key[A-Z]$/i.test(code)) return code.slice(3).toUpperCase()\n if (/^Digit[0-9]$/i.test(code)) return code.slice(5)\n if (/^Numpad[0-9]$/i.test(code)) return code.slice(6)\n\n const punctuation = PUNCTUATION_CODE_MAP[code]\n if (punctuation) return punctuation\n\n const named: Record<string, string> = {\n NumpadAdd: '+',\n NumpadSubtract: '-',\n NumpadMultiply: '*',\n NumpadDivide: '/',\n NumpadDecimal: '.',\n NumpadEnter: 'Enter',\n Space: 'Space',\n }\n return named[code]\n}\n\n/** Tests for one Unicode code point, including characters represented by a surrogate pair. */\nexport function isPrintableKey(key: string): boolean {\n return key !== '' && Array.from(key).length === 1\n}\n\n/** Splits modifier tokens while retaining a trailing literal plus: `Control++` → `['Control', '+']`. */\nexport function splitHotkeyParts(hotkey: string): Array<string> {\n if (!hotkey.endsWith('+')) return hotkey.split('+')\n const parts = hotkey.slice(0, -1).split('+')\n if (parts.at(-1) === '') parts.pop()\n parts.push('+')\n return parts\n}\n\n/** Identifies ASCII letters whose layout-produced value takes precedence over positional fallbacks. */\nexport function isAsciiLetter(key: string): boolean {\n return /^[A-Za-z]$/.test(key)\n}\n\n/** Identifies a single Latin-script character, including accented letters. */\nexport function isLatinLetter(key: string): boolean {\n return /^\\p{Script_Extensions=Latin}$/u.test(key)\n}\n\n/** Compares letters without case, preserving accents and avoiding expansions such as ß → SS. */\nexport function keysEqual(left: string, right: string): boolean {\n if (/^\\p{Letter}$/u.test(left) && /^\\p{Letter}$/u.test(right)) {\n return left.localeCompare(right, undefined, { sensitivity: 'accent' }) === 0\n }\n return left === right\n}\n\n/** Rejects reserved physical-token syntax in logical object fields while allowing Unicode characters. */\nexport function assertLogicalKey(key: string): void {\n if (/^\\[.*\\]$/s.test(key.trim())) {\n throw new Error(\n 'Logical key must not contain a bracketed physical code. Use the code field instead.',\n )\n }\n}\n"],"mappings":";;;;AAIA,SAAgB,uBACd,OACA,UACyB;CACzB,IAAI,WAAW;AACf,KAAI;AAIF,aACE,aAAa,SACb,OAAO,MAAM,qBAAqB,cAClC,MAAM,iBAAiB,WAAW;SAC9B;CAIR,MAAM,OAAO,MAAM,OAAO,IAAI,UAAU,MAAM;AAC9C,QAAO;EACL,KAAK,iBAAiB,IAAI;EAC1B,MAAM,MAAM,QAAQ;EACpB,MAAM,QAAQ,MAAM,QAAQ;EAC5B,OAAO,QAAQ,MAAM,SAAS;EAC9B,KAAK,QAAQ,MAAM,OAAO;EAC1B,MAAM,QAAQ,MAAM,QAAQ;EAC5B;EACA,UAAU,MAAM;EAChB,aACE,QAAQ,MAAM,YAAY,IAAI,QAAQ,aAAa,QAAQ;EAC9D;;;;;;;AAQH,SAAgB,iBAAiB,MAAkC;AACjE,KAAI,cAAc,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE,CAAC,aAAa;AAChE,KAAI,gBAAgB,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE;AACpD,KAAI,iBAAiB,KAAK,KAAK,CAAE,QAAO,KAAK,MAAM,EAAE;CAErD,MAAM,cAAc,qBAAqB;AACzC,KAAI,YAAa,QAAO;AAWxB,QATsC;EACpC,WAAW;EACX,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EACb,OAAO;EACR,CACY;;;AAIf,SAAgB,eAAe,KAAsB;AACnD,QAAO,QAAQ,MAAM,MAAM,KAAK,IAAI,CAAC,WAAW;;;AAIlD,SAAgB,iBAAiB,QAA+B;AAC9D,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,MAAM,IAAI;CACnD,MAAM,QAAQ,OAAO,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI;AAC5C,KAAI,MAAM,GAAG,GAAG,KAAK,GAAI,OAAM,KAAK;AACpC,OAAM,KAAK,IAAI;AACf,QAAO;;;AAIT,SAAgB,cAAc,KAAsB;AAClD,QAAO,aAAa,KAAK,IAAI;;;AAI/B,SAAgB,cAAc,KAAsB;AAClD,QAAO,iCAAiC,KAAK,IAAI;;;AAInD,SAAgB,UAAU,MAAc,OAAwB;AAC9D,KAAI,gBAAgB,KAAK,KAAK,IAAI,gBAAgB,KAAK,MAAM,CAC3D,QAAO,KAAK,cAAc,OAAO,QAAW,EAAE,aAAa,UAAU,CAAC,KAAK;AAE7E,QAAO,SAAS;;;AAIlB,SAAgB,iBAAiB,KAAmB;AAClD,KAAI,YAAY,KAAK,IAAI,MAAM,CAAC,CAC9B,OAAM,IAAI,MACR,sFACD"}
|
package/dist/_match.cjs
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
const require_platform = require('./platform.cjs');
|
|
2
|
-
const require__keyboard_event = require('./_keyboard-event.cjs');
|
|
3
|
-
const require_parse = require('./parse.cjs');
|
|
4
|
-
|
|
5
|
-
//#region src/_match.ts
|
|
6
|
-
/** Matches an event and reports the winning candidate and release identity. */
|
|
7
|
-
function matchKeyboardEvent(event, hotkey, platform = require_platform.detectPlatform()) {
|
|
8
|
-
const parsed = typeof hotkey === "string" ? require_parse.parseHotkey(hotkey, platform) : hotkey;
|
|
9
|
-
const normalized = require__keyboard_event.normalizeKeyboardEvent(event, platform);
|
|
10
|
-
const noMatch = {
|
|
11
|
-
matched: false,
|
|
12
|
-
score: 0
|
|
13
|
-
};
|
|
14
|
-
if (normalized.isComposing && (parsed.code !== void 0 || require__keyboard_event.isPrintableKey(parsed.key))) return noMatch;
|
|
15
|
-
if (normalized.altGraph && (parsed.ctrl || parsed.alt)) return noMatch;
|
|
16
|
-
if (parsed.code !== void 0) {
|
|
17
|
-
if (!modifiersMatch(normalized, parsed, false)) return noMatch;
|
|
18
|
-
return normalized.code === parsed.code ? matched("code", 3) : noMatch;
|
|
19
|
-
}
|
|
20
|
-
const direct = require__keyboard_event.keysEqual(normalized.key, parsed.key);
|
|
21
|
-
const implicitShift = direct && require__keyboard_event.isPrintableKey(normalized.key) && !/^\p{Letter}$/u.test(normalized.key) && !parsed.shift;
|
|
22
|
-
if (direct && modifiersMatch(normalized, parsed, implicitShift)) return matched("key", implicitShift ? 2 : 3);
|
|
23
|
-
if (require__keyboard_event.isAsciiLetter(normalized.key) || require__keyboard_event.isLatinLetter(normalized.key) && normalized.code.startsWith("Key") && !normalized.alt) return noMatch;
|
|
24
|
-
if (!modifiersMatch(normalized, parsed, false)) return noMatch;
|
|
25
|
-
const fallbackKey = require__keyboard_event.codeToLogicalKey(normalized.code);
|
|
26
|
-
return fallbackKey !== void 0 && require__keyboard_event.keysEqual(fallbackKey, parsed.key) ? matched("fallback", 1) : noMatch;
|
|
27
|
-
function matched(source, score) {
|
|
28
|
-
return {
|
|
29
|
-
matched: true,
|
|
30
|
-
score,
|
|
31
|
-
source,
|
|
32
|
-
identity: {
|
|
33
|
-
key: normalized.key,
|
|
34
|
-
code: normalized.code
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/** Compares modifiers, excluding synthetic AltGr flags and optionally allowing Shift used to type a glyph. */
|
|
40
|
-
function modifiersMatch(event, parsed, allowImplicitShift) {
|
|
41
|
-
const ctrl = event.altGraph ? false : event.ctrl;
|
|
42
|
-
const alt = event.altGraph ? false : event.alt;
|
|
43
|
-
if (ctrl !== parsed.ctrl || alt !== parsed.alt || event.meta !== parsed.meta) return false;
|
|
44
|
-
return event.shift === parsed.shift || allowImplicitShift && event.shift;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
//#endregion
|
|
48
|
-
exports.matchKeyboardEvent = matchKeyboardEvent;
|
|
49
|
-
//# sourceMappingURL=_match.cjs.map
|
package/dist/_match.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_match.cjs","names":["detectPlatform","parseHotkey","normalizeKeyboardEvent","isPrintableKey","keysEqual","isAsciiLetter","isLatinLetter","codeToLogicalKey"],"sources":["../src/_match.ts"],"sourcesContent":["import { detectPlatform } from './platform'\nimport {\n codeToLogicalKey,\n isAsciiLetter,\n isLatinLetter,\n isPrintableKey,\n keysEqual,\n normalizeKeyboardEvent,\n} from './_keyboard-event'\nimport { parseHotkey } from './parse'\nimport type { KeyboardEventMatch } from './match'\nimport type { Hotkey, ParsedHotkey } from './hotkey.types'\n\n/** Matches an event and reports the winning candidate and release identity. */\nexport function matchKeyboardEvent(\n event: KeyboardEvent,\n hotkey: Hotkey | ParsedHotkey,\n platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): KeyboardEventMatch {\n const parsed =\n typeof hotkey === 'string' ? parseHotkey(hotkey, platform) : hotkey\n const normalized = normalizeKeyboardEvent(event, platform)\n const noMatch: KeyboardEventMatch = { matched: false, score: 0 }\n\n if (\n normalized.isComposing &&\n (parsed.code !== undefined || isPrintableKey(parsed.key))\n )\n return noMatch\n if (normalized.altGraph && (parsed.ctrl || parsed.alt)) return noMatch\n\n if (parsed.code !== undefined) {\n if (!modifiersMatch(normalized, parsed, false)) return noMatch\n return normalized.code === parsed.code ? matched('code', 3) : noMatch\n }\n\n const direct = keysEqual(normalized.key, parsed.key)\n const implicitShift =\n direct &&\n isPrintableKey(normalized.key) &&\n !/^\\p{Letter}$/u.test(normalized.key) &&\n !parsed.shift\n\n if (direct && modifiersMatch(normalized, parsed, implicitShift)) {\n return matched('key', implicitShift ? 2 : 3)\n }\n\n // ASCII alphabetic output is authoritative for Dvorak/Colemak/AZERTY.\n // Native Latin letters are also authoritative on Key* positions; Alt is the\n // exception because macOS Option commonly transforms a shortcut's glyph.\n if (\n isAsciiLetter(normalized.key) ||\n (isLatinLetter(normalized.key) &&\n normalized.code.startsWith('Key') &&\n !normalized.alt)\n ) {\n return noMatch\n }\n\n if (!modifiersMatch(normalized, parsed, false)) return noMatch\n const fallbackKey = codeToLogicalKey(normalized.code)\n return fallbackKey !== undefined && keysEqual(fallbackKey, parsed.key)\n ? matched('fallback', 1)\n : noMatch\n\n // Preserve the triggering code so keyup can reset a shortcut even if its character changes.\n function matched(\n source: 'key' | 'code' | 'fallback',\n score: 1 | 2 | 3,\n ): KeyboardEventMatch {\n return {\n matched: true,\n score,\n source,\n identity: { key: normalized.key, code: normalized.code },\n }\n }\n}\n\n/** Compares modifiers, excluding synthetic AltGr flags and optionally allowing Shift used to type a glyph. */\nfunction modifiersMatch(\n event: ReturnType<typeof normalizeKeyboardEvent>,\n parsed: ParsedHotkey,\n allowImplicitShift: boolean,\n): boolean {\n const ctrl = event.altGraph ? false : event.ctrl\n const alt = event.altGraph ? false : event.alt\n if (\n ctrl !== parsed.ctrl ||\n alt !== parsed.alt ||\n event.meta !== parsed.meta\n ) {\n return false\n }\n return event.shift === parsed.shift || (allowImplicitShift && event.shift)\n}\n"],"mappings":";;;;;;AAcA,SAAgB,mBACd,OACA,QACA,WAAwCA,iCAAgB,EACpC;CACpB,MAAM,SACJ,OAAO,WAAW,WAAWC,0BAAY,QAAQ,SAAS,GAAG;CAC/D,MAAM,aAAaC,+CAAuB,OAAO,SAAS;CAC1D,MAAM,UAA8B;EAAE,SAAS;EAAO,OAAO;EAAG;AAEhE,KACE,WAAW,gBACV,OAAO,SAAS,UAAaC,uCAAe,OAAO,IAAI,EAExD,QAAO;AACT,KAAI,WAAW,aAAa,OAAO,QAAQ,OAAO,KAAM,QAAO;AAE/D,KAAI,OAAO,SAAS,QAAW;AAC7B,MAAI,CAAC,eAAe,YAAY,QAAQ,MAAM,CAAE,QAAO;AACvD,SAAO,WAAW,SAAS,OAAO,OAAO,QAAQ,QAAQ,EAAE,GAAG;;CAGhE,MAAM,SAASC,kCAAU,WAAW,KAAK,OAAO,IAAI;CACpD,MAAM,gBACJ,UACAD,uCAAe,WAAW,IAAI,IAC9B,CAAC,gBAAgB,KAAK,WAAW,IAAI,IACrC,CAAC,OAAO;AAEV,KAAI,UAAU,eAAe,YAAY,QAAQ,cAAc,CAC7D,QAAO,QAAQ,OAAO,gBAAgB,IAAI,EAAE;AAM9C,KACEE,sCAAc,WAAW,IAAI,IAC5BC,sCAAc,WAAW,IAAI,IAC5B,WAAW,KAAK,WAAW,MAAM,IACjC,CAAC,WAAW,IAEd,QAAO;AAGT,KAAI,CAAC,eAAe,YAAY,QAAQ,MAAM,CAAE,QAAO;CACvD,MAAM,cAAcC,yCAAiB,WAAW,KAAK;AACrD,QAAO,gBAAgB,UAAaH,kCAAU,aAAa,OAAO,IAAI,GAClE,QAAQ,YAAY,EAAE,GACtB;CAGJ,SAAS,QACP,QACA,OACoB;AACpB,SAAO;GACL,SAAS;GACT;GACA;GACA,UAAU;IAAE,KAAK,WAAW;IAAK,MAAM,WAAW;IAAM;GACzD;;;;AAKL,SAAS,eACP,OACA,QACA,oBACS;CACT,MAAM,OAAO,MAAM,WAAW,QAAQ,MAAM;CAC5C,MAAM,MAAM,MAAM,WAAW,QAAQ,MAAM;AAC3C,KACE,SAAS,OAAO,QAChB,QAAQ,OAAO,OACf,MAAM,SAAS,OAAO,KAEtB,QAAO;AAET,QAAO,MAAM,UAAU,OAAO,SAAU,sBAAsB,MAAM"}
|
package/dist/_match.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_match.js","names":[],"sources":["../src/_match.ts"],"sourcesContent":["import { detectPlatform } from './platform'\nimport {\n codeToLogicalKey,\n isAsciiLetter,\n isLatinLetter,\n isPrintableKey,\n keysEqual,\n normalizeKeyboardEvent,\n} from './_keyboard-event'\nimport { parseHotkey } from './parse'\nimport type { KeyboardEventMatch } from './match'\nimport type { Hotkey, ParsedHotkey } from './hotkey.types'\n\n/** Matches an event and reports the winning candidate and release identity. */\nexport function matchKeyboardEvent(\n event: KeyboardEvent,\n hotkey: Hotkey | ParsedHotkey,\n platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): KeyboardEventMatch {\n const parsed =\n typeof hotkey === 'string' ? parseHotkey(hotkey, platform) : hotkey\n const normalized = normalizeKeyboardEvent(event, platform)\n const noMatch: KeyboardEventMatch = { matched: false, score: 0 }\n\n if (\n normalized.isComposing &&\n (parsed.code !== undefined || isPrintableKey(parsed.key))\n )\n return noMatch\n if (normalized.altGraph && (parsed.ctrl || parsed.alt)) return noMatch\n\n if (parsed.code !== undefined) {\n if (!modifiersMatch(normalized, parsed, false)) return noMatch\n return normalized.code === parsed.code ? matched('code', 3) : noMatch\n }\n\n const direct = keysEqual(normalized.key, parsed.key)\n const implicitShift =\n direct &&\n isPrintableKey(normalized.key) &&\n !/^\\p{Letter}$/u.test(normalized.key) &&\n !parsed.shift\n\n if (direct && modifiersMatch(normalized, parsed, implicitShift)) {\n return matched('key', implicitShift ? 2 : 3)\n }\n\n // ASCII alphabetic output is authoritative for Dvorak/Colemak/AZERTY.\n // Native Latin letters are also authoritative on Key* positions; Alt is the\n // exception because macOS Option commonly transforms a shortcut's glyph.\n if (\n isAsciiLetter(normalized.key) ||\n (isLatinLetter(normalized.key) &&\n normalized.code.startsWith('Key') &&\n !normalized.alt)\n ) {\n return noMatch\n }\n\n if (!modifiersMatch(normalized, parsed, false)) return noMatch\n const fallbackKey = codeToLogicalKey(normalized.code)\n return fallbackKey !== undefined && keysEqual(fallbackKey, parsed.key)\n ? matched('fallback', 1)\n : noMatch\n\n // Preserve the triggering code so keyup can reset a shortcut even if its character changes.\n function matched(\n source: 'key' | 'code' | 'fallback',\n score: 1 | 2 | 3,\n ): KeyboardEventMatch {\n return {\n matched: true,\n score,\n source,\n identity: { key: normalized.key, code: normalized.code },\n }\n }\n}\n\n/** Compares modifiers, excluding synthetic AltGr flags and optionally allowing Shift used to type a glyph. */\nfunction modifiersMatch(\n event: ReturnType<typeof normalizeKeyboardEvent>,\n parsed: ParsedHotkey,\n allowImplicitShift: boolean,\n): boolean {\n const ctrl = event.altGraph ? false : event.ctrl\n const alt = event.altGraph ? false : event.alt\n if (\n ctrl !== parsed.ctrl ||\n alt !== parsed.alt ||\n event.meta !== parsed.meta\n ) {\n return false\n }\n return event.shift === parsed.shift || (allowImplicitShift && event.shift)\n}\n"],"mappings":";;;;;;AAcA,SAAgB,mBACd,OACA,QACA,WAAwC,gBAAgB,EACpC;CACpB,MAAM,SACJ,OAAO,WAAW,WAAW,YAAY,QAAQ,SAAS,GAAG;CAC/D,MAAM,aAAa,uBAAuB,OAAO,SAAS;CAC1D,MAAM,UAA8B;EAAE,SAAS;EAAO,OAAO;EAAG;AAEhE,KACE,WAAW,gBACV,OAAO,SAAS,UAAa,eAAe,OAAO,IAAI,EAExD,QAAO;AACT,KAAI,WAAW,aAAa,OAAO,QAAQ,OAAO,KAAM,QAAO;AAE/D,KAAI,OAAO,SAAS,QAAW;AAC7B,MAAI,CAAC,eAAe,YAAY,QAAQ,MAAM,CAAE,QAAO;AACvD,SAAO,WAAW,SAAS,OAAO,OAAO,QAAQ,QAAQ,EAAE,GAAG;;CAGhE,MAAM,SAAS,UAAU,WAAW,KAAK,OAAO,IAAI;CACpD,MAAM,gBACJ,UACA,eAAe,WAAW,IAAI,IAC9B,CAAC,gBAAgB,KAAK,WAAW,IAAI,IACrC,CAAC,OAAO;AAEV,KAAI,UAAU,eAAe,YAAY,QAAQ,cAAc,CAC7D,QAAO,QAAQ,OAAO,gBAAgB,IAAI,EAAE;AAM9C,KACE,cAAc,WAAW,IAAI,IAC5B,cAAc,WAAW,IAAI,IAC5B,WAAW,KAAK,WAAW,MAAM,IACjC,CAAC,WAAW,IAEd,QAAO;AAGT,KAAI,CAAC,eAAe,YAAY,QAAQ,MAAM,CAAE,QAAO;CACvD,MAAM,cAAc,iBAAiB,WAAW,KAAK;AACrD,QAAO,gBAAgB,UAAa,UAAU,aAAa,OAAO,IAAI,GAClE,QAAQ,YAAY,EAAE,GACtB;CAGJ,SAAS,QACP,QACA,OACoB;AACpB,SAAO;GACL,SAAS;GACT;GACA;GACA,UAAU;IAAE,KAAK,WAAW;IAAK,MAAM,WAAW;IAAM;GACzD;;;;AAKL,SAAS,eACP,OACA,QACA,oBACS;CACT,MAAM,OAAO,MAAM,WAAW,QAAQ,MAAM;CAC5C,MAAM,MAAM,MAAM,WAAW,QAAQ,MAAM;AAC3C,KACE,SAAS,OAAO,QAChB,QAAQ,OAAO,OACf,MAAM,SAAS,OAAO,KAEtB,QAAO;AAET,QAAO,MAAM,UAAU,OAAO,SAAU,sBAAsB,MAAM"}
|
package/dist/_named-keys.cjs
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/_named-keys.ts
|
|
3
|
-
/** Names defined for both KeyboardEvent.key and KeyboardEvent.code, beyond the basic key groups. */
|
|
4
|
-
const SHARED_NAMED_KEYS = [
|
|
5
|
-
"CapsLock",
|
|
6
|
-
"ContextMenu",
|
|
7
|
-
"Convert",
|
|
8
|
-
"KanaMode",
|
|
9
|
-
"NonConvert",
|
|
10
|
-
"Help",
|
|
11
|
-
"Insert",
|
|
12
|
-
"NumLock",
|
|
13
|
-
"Fn",
|
|
14
|
-
"FnLock",
|
|
15
|
-
"PrintScreen",
|
|
16
|
-
"ScrollLock",
|
|
17
|
-
"Pause",
|
|
18
|
-
"BrowserBack",
|
|
19
|
-
"BrowserFavorites",
|
|
20
|
-
"BrowserForward",
|
|
21
|
-
"BrowserHome",
|
|
22
|
-
"BrowserRefresh",
|
|
23
|
-
"BrowserSearch",
|
|
24
|
-
"BrowserStop",
|
|
25
|
-
"Eject",
|
|
26
|
-
"LaunchMail",
|
|
27
|
-
"MediaPlayPause",
|
|
28
|
-
"MediaStop",
|
|
29
|
-
"MediaTrackNext",
|
|
30
|
-
"MediaTrackPrevious",
|
|
31
|
-
"Power",
|
|
32
|
-
"AudioVolumeDown",
|
|
33
|
-
"AudioVolumeMute",
|
|
34
|
-
"AudioVolumeUp",
|
|
35
|
-
"WakeUp",
|
|
36
|
-
"Hyper",
|
|
37
|
-
"Super",
|
|
38
|
-
"Again",
|
|
39
|
-
"Copy",
|
|
40
|
-
"Cut",
|
|
41
|
-
"Find",
|
|
42
|
-
"Open",
|
|
43
|
-
"Paste",
|
|
44
|
-
"Props",
|
|
45
|
-
"Select",
|
|
46
|
-
"Undo",
|
|
47
|
-
"Hiragana",
|
|
48
|
-
"Katakana"
|
|
49
|
-
];
|
|
50
|
-
/** Logical counterparts whose physical positions use different names (for example Sleep and Lang1). */
|
|
51
|
-
const LOGICAL_ONLY_NAMED_KEYS = [
|
|
52
|
-
"Clear",
|
|
53
|
-
"Cancel",
|
|
54
|
-
"Standby",
|
|
55
|
-
"LaunchApplication1",
|
|
56
|
-
"LaunchApplication2",
|
|
57
|
-
"LaunchMediaPlayer",
|
|
58
|
-
"HangulMode",
|
|
59
|
-
"HanjaMode",
|
|
60
|
-
"Zenkaku",
|
|
61
|
-
"Hankaku",
|
|
62
|
-
"ZenkakuHankaku"
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
//#endregion
|
|
66
|
-
exports.LOGICAL_ONLY_NAMED_KEYS = LOGICAL_ONLY_NAMED_KEYS;
|
|
67
|
-
exports.SHARED_NAMED_KEYS = SHARED_NAMED_KEYS;
|
|
68
|
-
//# sourceMappingURL=_named-keys.cjs.map
|
package/dist/_named-keys.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_named-keys.cjs","names":[],"sources":["../src/_named-keys.ts"],"sourcesContent":["/** Names defined for both KeyboardEvent.key and KeyboardEvent.code, beyond the basic key groups. */\nexport const SHARED_NAMED_KEYS = [\n 'CapsLock',\n 'ContextMenu',\n 'Convert',\n 'KanaMode',\n 'NonConvert',\n 'Help',\n 'Insert',\n 'NumLock',\n 'Fn',\n 'FnLock',\n 'PrintScreen',\n 'ScrollLock',\n 'Pause',\n 'BrowserBack',\n 'BrowserFavorites',\n 'BrowserForward',\n 'BrowserHome',\n 'BrowserRefresh',\n 'BrowserSearch',\n 'BrowserStop',\n 'Eject',\n 'LaunchMail',\n 'MediaPlayPause',\n 'MediaStop',\n 'MediaTrackNext',\n 'MediaTrackPrevious',\n 'Power',\n 'AudioVolumeDown',\n 'AudioVolumeMute',\n 'AudioVolumeUp',\n 'WakeUp',\n 'Hyper',\n 'Super',\n 'Again',\n 'Copy',\n 'Cut',\n 'Find',\n 'Open',\n 'Paste',\n 'Props',\n 'Select',\n 'Undo',\n 'Hiragana',\n 'Katakana',\n] as const\n\n/** Logical counterparts whose physical positions use different names (for example Sleep and Lang1). */\nexport const LOGICAL_ONLY_NAMED_KEYS = [\n 'Clear',\n 'Cancel',\n 'Standby',\n 'LaunchApplication1',\n 'LaunchApplication2',\n 'LaunchMediaPlayer',\n 'HangulMode',\n 'HanjaMode',\n 'Zenkaku',\n 'Hankaku',\n 'ZenkakuHankaku',\n] as const\n"],"mappings":";;;AACA,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;AAGD,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
|
package/dist/_named-keys.d.cts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region src/_named-keys.d.ts
|
|
2
|
-
/** Names defined for both KeyboardEvent.key and KeyboardEvent.code, beyond the basic key groups. */
|
|
3
|
-
declare const SHARED_NAMED_KEYS: readonly ["CapsLock", "ContextMenu", "Convert", "KanaMode", "NonConvert", "Help", "Insert", "NumLock", "Fn", "FnLock", "PrintScreen", "ScrollLock", "Pause", "BrowserBack", "BrowserFavorites", "BrowserForward", "BrowserHome", "BrowserRefresh", "BrowserSearch", "BrowserStop", "Eject", "LaunchMail", "MediaPlayPause", "MediaStop", "MediaTrackNext", "MediaTrackPrevious", "Power", "AudioVolumeDown", "AudioVolumeMute", "AudioVolumeUp", "WakeUp", "Hyper", "Super", "Again", "Copy", "Cut", "Find", "Open", "Paste", "Props", "Select", "Undo", "Hiragana", "Katakana"];
|
|
4
|
-
/** Logical counterparts whose physical positions use different names (for example Sleep and Lang1). */
|
|
5
|
-
declare const LOGICAL_ONLY_NAMED_KEYS: readonly ["Clear", "Cancel", "Standby", "LaunchApplication1", "LaunchApplication2", "LaunchMediaPlayer", "HangulMode", "HanjaMode", "Zenkaku", "Hankaku", "ZenkakuHankaku"];
|
|
6
|
-
//#endregion
|
|
7
|
-
export { LOGICAL_ONLY_NAMED_KEYS, SHARED_NAMED_KEYS };
|
|
8
|
-
//# sourceMappingURL=_named-keys.d.cts.map
|
package/dist/_named-keys.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_named-keys.js","names":[],"sources":["../src/_named-keys.ts"],"sourcesContent":["/** Names defined for both KeyboardEvent.key and KeyboardEvent.code, beyond the basic key groups. */\nexport const SHARED_NAMED_KEYS = [\n 'CapsLock',\n 'ContextMenu',\n 'Convert',\n 'KanaMode',\n 'NonConvert',\n 'Help',\n 'Insert',\n 'NumLock',\n 'Fn',\n 'FnLock',\n 'PrintScreen',\n 'ScrollLock',\n 'Pause',\n 'BrowserBack',\n 'BrowserFavorites',\n 'BrowserForward',\n 'BrowserHome',\n 'BrowserRefresh',\n 'BrowserSearch',\n 'BrowserStop',\n 'Eject',\n 'LaunchMail',\n 'MediaPlayPause',\n 'MediaStop',\n 'MediaTrackNext',\n 'MediaTrackPrevious',\n 'Power',\n 'AudioVolumeDown',\n 'AudioVolumeMute',\n 'AudioVolumeUp',\n 'WakeUp',\n 'Hyper',\n 'Super',\n 'Again',\n 'Copy',\n 'Cut',\n 'Find',\n 'Open',\n 'Paste',\n 'Props',\n 'Select',\n 'Undo',\n 'Hiragana',\n 'Katakana',\n] as const\n\n/** Logical counterparts whose physical positions use different names (for example Sleep and Lang1). */\nexport const LOGICAL_ONLY_NAMED_KEYS = [\n 'Clear',\n 'Cancel',\n 'Standby',\n 'LaunchApplication1',\n 'LaunchApplication2',\n 'LaunchMediaPlayer',\n 'HangulMode',\n 'HanjaMode',\n 'Zenkaku',\n 'Hankaku',\n 'ZenkakuHankaku',\n] as const\n"],"mappings":";;AACA,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;AAGD,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
|