@tanstack/hotkeys 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +15 -1
  2. package/dist/{manager.utils.js → _event-target.cjs} +5 -41
  3. package/dist/_event-target.cjs.map +1 -0
  4. package/dist/{manager.utils.cjs → _event-target.js} +3 -47
  5. package/dist/_event-target.js.map +1 -0
  6. package/dist/_keyboard-event.cjs +83 -0
  7. package/dist/_keyboard-event.cjs.map +1 -0
  8. package/dist/_keyboard-event.js +76 -0
  9. package/dist/_keyboard-event.js.map +1 -0
  10. package/dist/_match.cjs +49 -0
  11. package/dist/_match.cjs.map +1 -0
  12. package/dist/_match.js +49 -0
  13. package/dist/_match.js.map +1 -0
  14. package/dist/_named-keys.cjs +68 -0
  15. package/dist/_named-keys.cjs.map +1 -0
  16. package/dist/_named-keys.d.cts +8 -0
  17. package/dist/_named-keys.d.ts +8 -0
  18. package/dist/_named-keys.js +66 -0
  19. package/dist/_named-keys.js.map +1 -0
  20. package/dist/_recorder-chord.cjs +44 -0
  21. package/dist/_recorder-chord.cjs.map +1 -0
  22. package/dist/_recorder-chord.js +43 -0
  23. package/dist/_recorder-chord.js.map +1 -0
  24. package/dist/_recording-guard.cjs +59 -0
  25. package/dist/_recording-guard.cjs.map +1 -0
  26. package/dist/_recording-guard.js +56 -0
  27. package/dist/_recording-guard.js.map +1 -0
  28. package/dist/_registration.cjs +54 -0
  29. package/dist/_registration.cjs.map +1 -0
  30. package/dist/_registration.js +50 -0
  31. package/dist/_registration.js.map +1 -0
  32. package/dist/conflicts.cjs +55 -0
  33. package/dist/conflicts.cjs.map +1 -0
  34. package/dist/conflicts.d.cts +39 -0
  35. package/dist/conflicts.d.ts +39 -0
  36. package/dist/conflicts.js +55 -0
  37. package/dist/conflicts.js.map +1 -0
  38. package/dist/constants.cjs +46 -171
  39. package/dist/constants.cjs.map +1 -1
  40. package/dist/constants.d.cts +4 -129
  41. package/dist/constants.d.ts +4 -129
  42. package/dist/constants.js +48 -164
  43. package/dist/constants.js.map +1 -1
  44. package/dist/display-labels.cjs +119 -0
  45. package/dist/display-labels.cjs.map +1 -0
  46. package/dist/display-labels.d.cts +93 -0
  47. package/dist/display-labels.d.ts +93 -0
  48. package/dist/display-labels.js +113 -0
  49. package/dist/display-labels.js.map +1 -0
  50. package/dist/format.cjs +30 -36
  51. package/dist/format.cjs.map +1 -1
  52. package/dist/format.d.cts +46 -7
  53. package/dist/format.d.ts +46 -7
  54. package/dist/format.js +31 -37
  55. package/dist/format.js.map +1 -1
  56. package/dist/hint.cjs +24 -0
  57. package/dist/hint.cjs.map +1 -0
  58. package/dist/hint.d.cts +23 -0
  59. package/dist/hint.d.ts +23 -0
  60. package/dist/hint.js +24 -0
  61. package/dist/hint.js.map +1 -0
  62. package/dist/hotkey-manager.cjs +53 -22
  63. package/dist/hotkey-manager.cjs.map +1 -1
  64. package/dist/hotkey-manager.d.cts +6 -2
  65. package/dist/hotkey-manager.d.ts +6 -2
  66. package/dist/hotkey-manager.js +49 -18
  67. package/dist/hotkey-manager.js.map +1 -1
  68. package/dist/hotkey-recorder.cjs +67 -11
  69. package/dist/hotkey-recorder.cjs.map +1 -1
  70. package/dist/hotkey-recorder.d.cts +6 -3
  71. package/dist/hotkey-recorder.d.ts +6 -3
  72. package/dist/hotkey-recorder.js +66 -10
  73. package/dist/hotkey-recorder.js.map +1 -1
  74. package/dist/hotkey-sequence-recorder.cjs +85 -22
  75. package/dist/hotkey-sequence-recorder.cjs.map +1 -1
  76. package/dist/hotkey-sequence-recorder.d.cts +9 -2
  77. package/dist/hotkey-sequence-recorder.d.ts +9 -2
  78. package/dist/hotkey-sequence-recorder.js +84 -21
  79. package/dist/hotkey-sequence-recorder.js.map +1 -1
  80. package/dist/{hotkey.d.ts → hotkey.types.d.cts} +55 -120
  81. package/dist/{hotkey.d.cts → hotkey.types.d.ts} +55 -120
  82. package/dist/index.cjs +18 -10
  83. package/dist/index.d.cts +14 -9
  84. package/dist/index.d.ts +14 -9
  85. package/dist/index.js +10 -6
  86. package/dist/key-state-tracker.cjs +24 -24
  87. package/dist/key-state-tracker.cjs.map +1 -1
  88. package/dist/key-state-tracker.js +24 -24
  89. package/dist/key-state-tracker.js.map +1 -1
  90. package/dist/key.types.d.cts +82 -0
  91. package/dist/key.types.d.ts +82 -0
  92. package/dist/match.cjs +21 -30
  93. package/dist/match.cjs.map +1 -1
  94. package/dist/match.d.cts +19 -3
  95. package/dist/match.d.ts +19 -3
  96. package/dist/match.js +19 -29
  97. package/dist/match.js.map +1 -1
  98. package/dist/parse.cjs +43 -26
  99. package/dist/parse.cjs.map +1 -1
  100. package/dist/parse.d.cts +10 -4
  101. package/dist/parse.d.ts +10 -4
  102. package/dist/parse.js +35 -19
  103. package/dist/parse.js.map +1 -1
  104. package/dist/platform.cjs +55 -0
  105. package/dist/platform.cjs.map +1 -0
  106. package/dist/platform.d.cts +44 -0
  107. package/dist/platform.d.ts +44 -0
  108. package/dist/platform.js +53 -0
  109. package/dist/platform.js.map +1 -0
  110. package/dist/recorder-options.d.cts +34 -0
  111. package/dist/recorder-options.d.ts +34 -0
  112. package/dist/sequence-manager.cjs +54 -28
  113. package/dist/sequence-manager.cjs.map +1 -1
  114. package/dist/sequence-manager.d.cts +18 -3
  115. package/dist/sequence-manager.d.ts +18 -3
  116. package/dist/sequence-manager.js +49 -23
  117. package/dist/sequence-manager.js.map +1 -1
  118. package/dist/validate.cjs +6 -10
  119. package/dist/validate.cjs.map +1 -1
  120. package/dist/validate.d.cts +13 -2
  121. package/dist/validate.d.ts +13 -2
  122. package/dist/validate.js +7 -11
  123. package/dist/validate.js.map +1 -1
  124. package/package.json +2 -2
  125. package/src/{manager.utils.ts → _event-target.ts} +0 -74
  126. package/src/_keyboard-event.ts +101 -0
  127. package/src/_match.ts +96 -0
  128. package/src/_named-keys.ts +62 -0
  129. package/src/_recorder-chord.ts +76 -0
  130. package/src/_recording-guard.ts +63 -0
  131. package/src/_registration.ts +79 -0
  132. package/src/conflicts.ts +125 -0
  133. package/src/constants.ts +48 -196
  134. package/src/display-labels.ts +123 -0
  135. package/src/format.ts +111 -52
  136. package/src/hint.ts +42 -0
  137. package/src/hotkey-manager.ts +95 -40
  138. package/src/hotkey-recorder.ts +92 -16
  139. package/src/hotkey-sequence-recorder.ts +110 -28
  140. package/src/{hotkey.ts → hotkey.types.ts} +57 -224
  141. package/src/index.ts +11 -5
  142. package/src/key-state-tracker.ts +36 -24
  143. package/src/key.types.ts +268 -0
  144. package/src/match.ts +41 -90
  145. package/src/parse.ts +67 -26
  146. package/src/platform.ts +66 -0
  147. package/src/recorder-options.ts +34 -0
  148. package/src/sequence-manager.ts +77 -42
  149. package/src/validate.ts +29 -21
  150. package/dist/manager.utils.cjs.map +0 -1
  151. package/dist/manager.utils.d.cts +0 -13
  152. package/dist/manager.utils.d.ts +0 -13
  153. package/dist/manager.utils.js.map +0 -1
  154. package/dist/recorder-chord.cjs +0 -18
  155. package/dist/recorder-chord.cjs.map +0 -1
  156. package/dist/recorder-chord.js +0 -18
  157. package/dist/recorder-chord.js.map +0 -1
  158. package/src/recorder-chord.ts +0 -25
package/README.md CHANGED
@@ -1,5 +1,19 @@
1
1
  <div align="center">
2
- <img src="./media/header_hotkeys.png" alt="TanStack Hotkeys" />
2
+ <picture>
3
+ <source
4
+ media="(prefers-color-scheme: dark)"
5
+ srcset="https://tanstack.com/api/readme/hotkeys.png?theme=dark"
6
+ />
7
+ <source
8
+ media="(prefers-color-scheme: light)"
9
+ srcset="https://tanstack.com/api/readme/hotkeys.png"
10
+ />
11
+ <img
12
+ src="https://tanstack.com/api/readme/hotkeys.png"
13
+ alt="TanStack Hotkeys"
14
+ width="900"
15
+ />
16
+ </picture>
3
17
  </div>
4
18
 
5
19
  <br />
@@ -1,25 +1,5 @@
1
- //#region src/manager.utils.ts
2
- /**
3
- * Default options for hotkey/sequence registration.
4
- * Omitted: platform, target (resolved at registration), requireReset (HotkeyManager only).
5
- */
6
- const defaultHotkeyOptions = {
7
- preventDefault: true,
8
- stopPropagation: true,
9
- eventType: "keydown",
10
- enabled: true,
11
- ignoreInputs: true,
12
- conflictBehavior: "warn"
13
- };
14
- /**
15
- * Computes the default ignoreInputs value based on the hotkey.
16
- * Ctrl/Meta shortcuts and Escape fire in inputs; single keys and Shift/Alt combos are ignored.
17
- */
18
- function getDefaultIgnoreInputs(parsedHotkey) {
19
- if (parsedHotkey.ctrl || parsedHotkey.meta) return false;
20
- if (parsedHotkey.key === "Escape") return false;
21
- return true;
22
- }
1
+
2
+ //#region src/_event-target.ts
23
3
  /**
24
4
  * Checks if an element is an input-like element that should be ignored for hotkeys.
25
5
  *
@@ -86,24 +66,8 @@ function isEventForTarget(event, target) {
86
66
  }
87
67
  return false;
88
68
  }
89
- /**
90
- * Handles conflicts between registrations based on conflict behavior.
91
- *
92
- * @param conflictingId - The ID of the conflicting registration
93
- * @param keyDisplay - Display string for the conflicting key/sequence (for error messages)
94
- * @param conflictBehavior - How to handle the conflict
95
- * @param unregister - Function to unregister by ID
96
- */
97
- function handleConflict(conflictingId, keyDisplay, conflictBehavior, unregister) {
98
- if (conflictBehavior === "allow") return;
99
- if (conflictBehavior === "warn") {
100
- console.warn(`'${keyDisplay}' is already registered. Multiple handlers will be triggered. Use conflictBehavior: 'replace' to replace the existing handler, or conflictBehavior: 'allow' to suppress this warning.`);
101
- return;
102
- }
103
- if (conflictBehavior === "error") throw new Error(`'${keyDisplay}' is already registered. Use conflictBehavior: 'replace' to replace the existing handler, or conflictBehavior: 'allow' to allow multiple registrations.`);
104
- unregister(conflictingId);
105
- }
106
69
 
107
70
  //#endregion
108
- export { defaultHotkeyOptions, getDefaultIgnoreInputs, handleConflict, isEventForTarget, isInputElement, shouldIgnoreInputEvent };
109
- //# sourceMappingURL=manager.utils.js.map
71
+ exports.isEventForTarget = isEventForTarget;
72
+ exports.shouldIgnoreInputEvent = shouldIgnoreInputEvent;
73
+ //# sourceMappingURL=_event-target.cjs.map
@@ -0,0 +1 @@
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,26 +1,4 @@
1
-
2
- //#region src/manager.utils.ts
3
- /**
4
- * Default options for hotkey/sequence registration.
5
- * Omitted: platform, target (resolved at registration), requireReset (HotkeyManager only).
6
- */
7
- const defaultHotkeyOptions = {
8
- preventDefault: true,
9
- stopPropagation: true,
10
- eventType: "keydown",
11
- enabled: true,
12
- ignoreInputs: true,
13
- conflictBehavior: "warn"
14
- };
15
- /**
16
- * Computes the default ignoreInputs value based on the hotkey.
17
- * Ctrl/Meta shortcuts and Escape fire in inputs; single keys and Shift/Alt combos are ignored.
18
- */
19
- function getDefaultIgnoreInputs(parsedHotkey) {
20
- if (parsedHotkey.ctrl || parsedHotkey.meta) return false;
21
- if (parsedHotkey.key === "Escape") return false;
22
- return true;
23
- }
1
+ //#region src/_event-target.ts
24
2
  /**
25
3
  * Checks if an element is an input-like element that should be ignored for hotkeys.
26
4
  *
@@ -87,29 +65,7 @@ function isEventForTarget(event, target) {
87
65
  }
88
66
  return false;
89
67
  }
90
- /**
91
- * Handles conflicts between registrations based on conflict behavior.
92
- *
93
- * @param conflictingId - The ID of the conflicting registration
94
- * @param keyDisplay - Display string for the conflicting key/sequence (for error messages)
95
- * @param conflictBehavior - How to handle the conflict
96
- * @param unregister - Function to unregister by ID
97
- */
98
- function handleConflict(conflictingId, keyDisplay, conflictBehavior, unregister) {
99
- if (conflictBehavior === "allow") return;
100
- if (conflictBehavior === "warn") {
101
- console.warn(`'${keyDisplay}' is already registered. Multiple handlers will be triggered. Use conflictBehavior: 'replace' to replace the existing handler, or conflictBehavior: 'allow' to suppress this warning.`);
102
- return;
103
- }
104
- if (conflictBehavior === "error") throw new Error(`'${keyDisplay}' is already registered. Use conflictBehavior: 'replace' to replace the existing handler, or conflictBehavior: 'allow' to allow multiple registrations.`);
105
- unregister(conflictingId);
106
- }
107
68
 
108
69
  //#endregion
109
- exports.defaultHotkeyOptions = defaultHotkeyOptions;
110
- exports.getDefaultIgnoreInputs = getDefaultIgnoreInputs;
111
- exports.handleConflict = handleConflict;
112
- exports.isEventForTarget = isEventForTarget;
113
- exports.isInputElement = isInputElement;
114
- exports.shouldIgnoreInputEvent = shouldIgnoreInputEvent;
115
- //# sourceMappingURL=manager.utils.cjs.map
70
+ export { isEventForTarget, shouldIgnoreInputEvent };
71
+ //# sourceMappingURL=_event-target.js.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,83 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,76 @@
1
+ import { PUNCTUATION_CODE_MAP, normalizeKeyName } from "./constants.js";
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: 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 = 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
+ export { assertLogicalKey, codeToLogicalKey, isAsciiLetter, isLatinLetter, isPrintableKey, keysEqual, normalizeKeyboardEvent, splitHotkeyParts };
76
+ //# sourceMappingURL=_keyboard-event.js.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,49 @@
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
@@ -0,0 +1 @@
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 ADDED
@@ -0,0 +1,49 @@
1
+ import { detectPlatform } from "./platform.js";
2
+ import { codeToLogicalKey, isAsciiLetter, isLatinLetter, isPrintableKey, keysEqual, normalizeKeyboardEvent } from "./_keyboard-event.js";
3
+ import { parseHotkey } from "./parse.js";
4
+
5
+ //#region src/_match.ts
6
+ /** Matches an event and reports the winning candidate and release identity. */
7
+ function matchKeyboardEvent(event, hotkey, platform = detectPlatform()) {
8
+ const parsed = typeof hotkey === "string" ? parseHotkey(hotkey, platform) : hotkey;
9
+ const normalized = normalizeKeyboardEvent(event, platform);
10
+ const noMatch = {
11
+ matched: false,
12
+ score: 0
13
+ };
14
+ if (normalized.isComposing && (parsed.code !== void 0 || 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 = keysEqual(normalized.key, parsed.key);
21
+ const implicitShift = direct && 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 (isAsciiLetter(normalized.key) || isLatinLetter(normalized.key) && normalized.code.startsWith("Key") && !normalized.alt) return noMatch;
24
+ if (!modifiersMatch(normalized, parsed, false)) return noMatch;
25
+ const fallbackKey = codeToLogicalKey(normalized.code);
26
+ return fallbackKey !== void 0 && 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
+ export { matchKeyboardEvent };
49
+ //# sourceMappingURL=_match.js.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,68 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,8 @@
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.ts.map