@tanstack/angular-hotkeys 0.10.0 → 0.12.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 (86) hide show
  1. package/README.md +15 -1
  2. package/dist/hotkeys-provider.d.ts +7 -10
  3. package/dist/hotkeys-provider.js +1 -2
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.js +2 -1
  6. package/dist/injectHeldKeyCodes.d.ts +2 -5
  7. package/dist/injectHeldKeyCodes.js +3 -3
  8. package/dist/injectHeldKeys.d.ts +2 -5
  9. package/dist/injectHeldKeys.js +3 -3
  10. package/dist/injectHotkey.d.ts +3 -6
  11. package/dist/injectHotkey.js +3 -3
  12. package/dist/injectHotkeyHint.d.ts +12 -0
  13. package/dist/injectHotkeyHint.js +19 -0
  14. package/dist/injectHotkeyRecorder.d.ts +3 -6
  15. package/dist/injectHotkeyRecorder.js +4 -4
  16. package/dist/injectHotkeyRegistrations.d.ts +3 -6
  17. package/dist/injectHotkeyRegistrations.js +1 -2
  18. package/dist/injectHotkeySequence.d.ts +3 -6
  19. package/dist/injectHotkeySequence.js +1 -2
  20. package/dist/injectHotkeySequenceRecorder.d.ts +3 -6
  21. package/dist/injectHotkeySequenceRecorder.js +4 -4
  22. package/dist/injectHotkeySequences.d.ts +3 -6
  23. package/dist/injectHotkeySequences.js +1 -2
  24. package/dist/injectHotkeys.d.ts +3 -6
  25. package/dist/injectHotkeys.js +3 -3
  26. package/dist/injectKeyHold.d.ts +2 -5
  27. package/dist/injectKeyHold.js +3 -3
  28. package/package.json +12 -17
  29. package/dist/hotkeys-provider.cjs +0 -26
  30. package/dist/hotkeys-provider.cjs.map +0 -1
  31. package/dist/hotkeys-provider.d.cts +0 -22
  32. package/dist/hotkeys-provider.js.map +0 -1
  33. package/dist/index.cjs +0 -34
  34. package/dist/index.d.cts +0 -13
  35. package/dist/injectHeldKeyCodes.cjs +0 -34
  36. package/dist/injectHeldKeyCodes.cjs.map +0 -1
  37. package/dist/injectHeldKeyCodes.d.cts +0 -30
  38. package/dist/injectHeldKeyCodes.js.map +0 -1
  39. package/dist/injectHeldKeys.cjs +0 -29
  40. package/dist/injectHeldKeys.cjs.map +0 -1
  41. package/dist/injectHeldKeys.d.cts +0 -25
  42. package/dist/injectHeldKeys.js.map +0 -1
  43. package/dist/injectHotkey.cjs +0 -122
  44. package/dist/injectHotkey.cjs.map +0 -1
  45. package/dist/injectHotkey.d.cts +0 -75
  46. package/dist/injectHotkey.js.map +0 -1
  47. package/dist/injectHotkeyRecorder.cjs +0 -82
  48. package/dist/injectHotkeyRecorder.cjs.map +0 -1
  49. package/dist/injectHotkeyRecorder.d.cts +0 -49
  50. package/dist/injectHotkeyRecorder.js.map +0 -1
  51. package/dist/injectHotkeyRegistrations.cjs +0 -28
  52. package/dist/injectHotkeyRegistrations.cjs.map +0 -1
  53. package/dist/injectHotkeyRegistrations.d.cts +0 -29
  54. package/dist/injectHotkeyRegistrations.js.map +0 -1
  55. package/dist/injectHotkeySequence.cjs +0 -93
  56. package/dist/injectHotkeySequence.cjs.map +0 -1
  57. package/dist/injectHotkeySequence.d.cts +0 -48
  58. package/dist/injectHotkeySequence.js.map +0 -1
  59. package/dist/injectHotkeySequenceRecorder.cjs +0 -58
  60. package/dist/injectHotkeySequenceRecorder.cjs.map +0 -1
  61. package/dist/injectHotkeySequenceRecorder.d.cts +0 -19
  62. package/dist/injectHotkeySequenceRecorder.js.map +0 -1
  63. package/dist/injectHotkeySequences.cjs +0 -105
  64. package/dist/injectHotkeySequences.cjs.map +0 -1
  65. package/dist/injectHotkeySequences.d.cts +0 -47
  66. package/dist/injectHotkeySequences.js.map +0 -1
  67. package/dist/injectHotkeys.cjs +0 -120
  68. package/dist/injectHotkeys.cjs.map +0 -1
  69. package/dist/injectHotkeys.d.cts +0 -66
  70. package/dist/injectHotkeys.js.map +0 -1
  71. package/dist/injectKeyHold.cjs +0 -49
  72. package/dist/injectKeyHold.cjs.map +0 -1
  73. package/dist/injectKeyHold.d.cts +0 -41
  74. package/dist/injectKeyHold.js.map +0 -1
  75. package/src/hotkeys-provider.ts +0 -44
  76. package/src/index.ts +0 -17
  77. package/src/injectHeldKeyCodes.ts +0 -31
  78. package/src/injectHeldKeys.ts +0 -26
  79. package/src/injectHotkey.ts +0 -171
  80. package/src/injectHotkeyRecorder.ts +0 -128
  81. package/src/injectHotkeyRegistrations.ts +0 -48
  82. package/src/injectHotkeySequence.ts +0 -140
  83. package/src/injectHotkeySequenceRecorder.ts +0 -103
  84. package/src/injectHotkeySequences.ts +0 -176
  85. package/src/injectHotkeys.ts +0 -189
  86. package/src/injectKeyHold.ts +0 -57
package/dist/index.d.cts DELETED
@@ -1,13 +0,0 @@
1
- import { InjectHotkeyOptions, injectHotkey } from "./injectHotkey.cjs";
2
- import { InjectHotkeySequenceOptions, injectHotkeySequence } from "./injectHotkeySequence.cjs";
3
- import { HOTKEYS_INJECTION_TOKEN, HotkeysContextValue, HotkeysProviderOptions, injectDefaultHotkeysOptions, injectHotkeysContext, provideHotkeys } from "./hotkeys-provider.cjs";
4
- import { InjectHotkeyDefinition, injectHotkeys } from "./injectHotkeys.cjs";
5
- import { InjectHotkeySequenceDefinition, injectHotkeySequences } from "./injectHotkeySequences.cjs";
6
- import { injectHeldKeys } from "./injectHeldKeys.cjs";
7
- import { injectHeldKeyCodes } from "./injectHeldKeyCodes.cjs";
8
- import { injectKeyHold } from "./injectKeyHold.cjs";
9
- import { AngularHotkeyRecorder, injectHotkeyRecorder } from "./injectHotkeyRecorder.cjs";
10
- import { HotkeyRegistrationsResult, injectHotkeyRegistrations } from "./injectHotkeyRegistrations.cjs";
11
- import { AngularHotkeySequenceRecorder, injectHotkeySequenceRecorder } from "./injectHotkeySequenceRecorder.cjs";
12
- export * from "@tanstack/hotkeys";
13
- export { AngularHotkeyRecorder, AngularHotkeySequenceRecorder, HOTKEYS_INJECTION_TOKEN, HotkeyRegistrationsResult, HotkeysContextValue, HotkeysProviderOptions, InjectHotkeyDefinition, InjectHotkeyOptions, InjectHotkeySequenceDefinition, InjectHotkeySequenceOptions, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeyRegistrations, injectHotkeySequence, injectHotkeySequenceRecorder, injectHotkeySequences, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
@@ -1,34 +0,0 @@
1
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
2
- let _tanstack_angular_store = require("@tanstack/angular-store");
3
-
4
- //#region src/injectHeldKeyCodes.ts
5
- /**
6
- * Angular inject-based API that returns a signal of a map from held key names to their physical `event.code` values.
7
- *
8
- * Useful for debugging which physical key was pressed (e.g. distinguishing
9
- * left vs right Shift via "ShiftLeft" / "ShiftRight").
10
- *
11
- * @returns Signal of record mapping normalized key names to their `event.code` values
12
- *
13
- * @example
14
- * ```ts
15
- * @Component({
16
- * template: `
17
- * @for (key of heldKeys(); track key) {
18
- * <kbd>{{ key }} <small>{{ heldCodes()[key] }}</small></kbd>
19
- * }
20
- * `,
21
- * })
22
- * export class KeyDebugComponent {
23
- * heldKeys = injectHeldKeys()
24
- * heldCodes = injectHeldKeyCodes()
25
- * }
26
- * ```
27
- */
28
- function injectHeldKeyCodes() {
29
- return (0, _tanstack_angular_store.injectSelector)((0, _tanstack_hotkeys.getKeyStateTracker)().store, (state) => state.heldCodes);
30
- }
31
-
32
- //#endregion
33
- exports.injectHeldKeyCodes = injectHeldKeyCodes;
34
- //# sourceMappingURL=injectHeldKeyCodes.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHeldKeyCodes.cjs","names":[],"sources":["../src/injectHeldKeyCodes.ts"],"sourcesContent":["import { getKeyStateTracker } from '@tanstack/hotkeys'\nimport { injectSelector } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\n\n/**\n * Angular inject-based API that returns a signal of a map from held key names to their physical `event.code` values.\n *\n * Useful for debugging which physical key was pressed (e.g. distinguishing\n * left vs right Shift via \"ShiftLeft\" / \"ShiftRight\").\n *\n * @returns Signal of record mapping normalized key names to their `event.code` values\n *\n * @example\n * ```ts\n * @Component({\n * template: `\n * @for (key of heldKeys(); track key) {\n * <kbd>{{ key }} <small>{{ heldCodes()[key] }}</small></kbd>\n * }\n * `,\n * })\n * export class KeyDebugComponent {\n * heldKeys = injectHeldKeys()\n * heldCodes = injectHeldKeyCodes()\n * }\n * ```\n */\nexport function injectHeldKeyCodes(): Signal<Record<string, string>> {\n const tracker = getKeyStateTracker()\n return injectSelector(tracker.store, (state) => state.heldCodes)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,qBAAqD;AAEnE,+FADoC,CACN,QAAQ,UAAU,MAAM,UAAU"}
@@ -1,30 +0,0 @@
1
- import { Signal } from "@angular/core";
2
-
3
- //#region src/injectHeldKeyCodes.d.ts
4
- /**
5
- * Angular inject-based API that returns a signal of a map from held key names to their physical `event.code` values.
6
- *
7
- * Useful for debugging which physical key was pressed (e.g. distinguishing
8
- * left vs right Shift via "ShiftLeft" / "ShiftRight").
9
- *
10
- * @returns Signal of record mapping normalized key names to their `event.code` values
11
- *
12
- * @example
13
- * ```ts
14
- * @Component({
15
- * template: `
16
- * @for (key of heldKeys(); track key) {
17
- * <kbd>{{ key }} <small>{{ heldCodes()[key] }}</small></kbd>
18
- * }
19
- * `,
20
- * })
21
- * export class KeyDebugComponent {
22
- * heldKeys = injectHeldKeys()
23
- * heldCodes = injectHeldKeyCodes()
24
- * }
25
- * ```
26
- */
27
- declare function injectHeldKeyCodes(): Signal<Record<string, string>>;
28
- //#endregion
29
- export { injectHeldKeyCodes };
30
- //# sourceMappingURL=injectHeldKeyCodes.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHeldKeyCodes.js","names":[],"sources":["../src/injectHeldKeyCodes.ts"],"sourcesContent":["import { getKeyStateTracker } from '@tanstack/hotkeys'\nimport { injectSelector } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\n\n/**\n * Angular inject-based API that returns a signal of a map from held key names to their physical `event.code` values.\n *\n * Useful for debugging which physical key was pressed (e.g. distinguishing\n * left vs right Shift via \"ShiftLeft\" / \"ShiftRight\").\n *\n * @returns Signal of record mapping normalized key names to their `event.code` values\n *\n * @example\n * ```ts\n * @Component({\n * template: `\n * @for (key of heldKeys(); track key) {\n * <kbd>{{ key }} <small>{{ heldCodes()[key] }}</small></kbd>\n * }\n * `,\n * })\n * export class KeyDebugComponent {\n * heldKeys = injectHeldKeys()\n * heldCodes = injectHeldKeyCodes()\n * }\n * ```\n */\nexport function injectHeldKeyCodes(): Signal<Record<string, string>> {\n const tracker = getKeyStateTracker()\n return injectSelector(tracker.store, (state) => state.heldCodes)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,qBAAqD;AAEnE,QAAO,eADS,oBAAoB,CACN,QAAQ,UAAU,MAAM,UAAU"}
@@ -1,29 +0,0 @@
1
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
2
- let _tanstack_angular_store = require("@tanstack/angular-store");
3
-
4
- //#region src/injectHeldKeys.ts
5
- /**
6
- * Angular inject-based API that returns a signal of currently held keyboard keys.
7
- *
8
- * Subscribes to the global KeyStateTracker and updates whenever keys are
9
- * pressed or released.
10
- *
11
- * @returns Signal of array of currently held key names
12
- *
13
- * @example
14
- * ```ts
15
- * @Component({
16
- * template: `<div>Currently pressed: {{ heldKeys().join(' + ') || 'None' }}</div>`,
17
- * })
18
- * export class KeyDisplayComponent {
19
- * heldKeys = injectHeldKeys()
20
- * }
21
- * ```
22
- */
23
- function injectHeldKeys() {
24
- return (0, _tanstack_angular_store.injectSelector)((0, _tanstack_hotkeys.getKeyStateTracker)().store, (state) => state.heldKeys);
25
- }
26
-
27
- //#endregion
28
- exports.injectHeldKeys = injectHeldKeys;
29
- //# sourceMappingURL=injectHeldKeys.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHeldKeys.cjs","names":[],"sources":["../src/injectHeldKeys.ts"],"sourcesContent":["import { getKeyStateTracker } from '@tanstack/hotkeys'\nimport { injectSelector } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\n\n/**\n * Angular inject-based API that returns a signal of currently held keyboard keys.\n *\n * Subscribes to the global KeyStateTracker and updates whenever keys are\n * pressed or released.\n *\n * @returns Signal of array of currently held key names\n *\n * @example\n * ```ts\n * @Component({\n * template: `<div>Currently pressed: {{ heldKeys().join(' + ') || 'None' }}</div>`,\n * })\n * export class KeyDisplayComponent {\n * heldKeys = injectHeldKeys()\n * }\n * ```\n */\nexport function injectHeldKeys(): Signal<Array<string>> {\n const tracker = getKeyStateTracker()\n return injectSelector(tracker.store, (state) => state.heldKeys)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iBAAwC;AAEtD,+FADoC,CACN,QAAQ,UAAU,MAAM,SAAS"}
@@ -1,25 +0,0 @@
1
- import { Signal } from "@angular/core";
2
-
3
- //#region src/injectHeldKeys.d.ts
4
- /**
5
- * Angular inject-based API that returns a signal of currently held keyboard keys.
6
- *
7
- * Subscribes to the global KeyStateTracker and updates whenever keys are
8
- * pressed or released.
9
- *
10
- * @returns Signal of array of currently held key names
11
- *
12
- * @example
13
- * ```ts
14
- * @Component({
15
- * template: `<div>Currently pressed: {{ heldKeys().join(' + ') || 'None' }}</div>`,
16
- * })
17
- * export class KeyDisplayComponent {
18
- * heldKeys = injectHeldKeys()
19
- * }
20
- * ```
21
- */
22
- declare function injectHeldKeys(): Signal<Array<string>>;
23
- //#endregion
24
- export { injectHeldKeys };
25
- //# sourceMappingURL=injectHeldKeys.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHeldKeys.js","names":[],"sources":["../src/injectHeldKeys.ts"],"sourcesContent":["import { getKeyStateTracker } from '@tanstack/hotkeys'\nimport { injectSelector } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\n\n/**\n * Angular inject-based API that returns a signal of currently held keyboard keys.\n *\n * Subscribes to the global KeyStateTracker and updates whenever keys are\n * pressed or released.\n *\n * @returns Signal of array of currently held key names\n *\n * @example\n * ```ts\n * @Component({\n * template: `<div>Currently pressed: {{ heldKeys().join(' + ') || 'None' }}</div>`,\n * })\n * export class KeyDisplayComponent {\n * heldKeys = injectHeldKeys()\n * }\n * ```\n */\nexport function injectHeldKeys(): Signal<Array<string>> {\n const tracker = getKeyStateTracker()\n return injectSelector(tracker.store, (state) => state.heldKeys)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iBAAwC;AAEtD,QAAO,eADS,oBAAoB,CACN,QAAQ,UAAU,MAAM,SAAS"}
@@ -1,122 +0,0 @@
1
- const require_hotkeys_provider = require('./hotkeys-provider.cjs');
2
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
3
- let _angular_core = require("@angular/core");
4
-
5
- //#region src/injectHotkey.ts
6
- /**
7
- * Angular inject-based API for registering a keyboard hotkey.
8
- *
9
- * Uses the singleton HotkeyManager for efficient event handling.
10
- * The callback receives both the keyboard event and a context object
11
- * containing the hotkey string and parsed hotkey.
12
- *
13
- * Call in an injection context (e.g. constructor or field initializer).
14
- * Uses effect() to track reactive dependencies and update registration
15
- * when options or the callback change.
16
- * `enabled: false` keeps the registration (visible in devtools) and only suppresses firing; the same
17
- * handle is updated instead of unregistering and re-registering when identity is unchanged.
18
- *
19
- * @param hotkey - The hotkey string (e.g. 'Mod+S', 'Escape') or getter function
20
- * @param callback - The function to call when the hotkey is pressed
21
- * @param options - Options for the hotkey behavior, or getter for reactive options
22
- *
23
- * @example
24
- * ```ts
25
- * @Component({ ... })
26
- * export class SaveButtonComponent {
27
- * private readonly saveCount = signal(0)
28
- *
29
- * constructor() {
30
- * injectHotkey('Mod+S', (event, { hotkey }) => {
31
- * event.preventDefault()
32
- * this.saveCount.update(c => c + 1)
33
- * })
34
- * }
35
- * }
36
- * ```
37
- *
38
- * @example
39
- * ```ts
40
- * @Component({ ... })
41
- * export class ModalComponent {
42
- * isOpen = signal(true)
43
- *
44
- * constructor() {
45
- * injectHotkey('Escape', () => this.close(), () => ({ enabled: this.isOpen() }))
46
- * }
47
- * }
48
- * ```
49
- *
50
- * @example
51
- * ```ts
52
- * @Component({ ... })
53
- * export class EditorComponent {
54
- * private readonly editorRef = viewChild<ElementRef<HTMLDivElement>>('editorRef')
55
- *
56
- * constructor() {
57
- * injectHotkey('Mod+B', () => this.toggleBold(), () => ({
58
- * target: this.editorRef()?.nativeElement ?? null,
59
- * }))
60
- * }
61
- * }
62
- * ```
63
- */
64
- function injectHotkey(hotkey, callback, options = {}) {
65
- const defaultOptions = require_hotkeys_provider.injectDefaultHotkeysOptions();
66
- const manager = (0, _tanstack_hotkeys.getHotkeyManager)();
67
- const destroyRef = (0, _angular_core.inject)(_angular_core.DestroyRef);
68
- let registration = null;
69
- let lastHotkeyString = null;
70
- let lastTarget = null;
71
- destroyRef.onDestroy(() => {
72
- if (registration?.isActive) {
73
- registration.unregister();
74
- registration = null;
75
- }
76
- lastHotkeyString = null;
77
- lastTarget = null;
78
- });
79
- (0, _angular_core.effect)(() => {
80
- const resolvedHotkey = typeof hotkey === "function" ? hotkey() : hotkey;
81
- const resolvedOptions = typeof options === "function" ? options() : options;
82
- const mergedOptions = {
83
- ...defaultOptions.hotkey,
84
- ...resolvedOptions
85
- };
86
- const hotkeyString = (0, _tanstack_hotkeys.normalizeRegisterableHotkey)(resolvedHotkey, mergedOptions.platform ?? (0, _tanstack_hotkeys.detectPlatform)());
87
- const resolvedTarget = "target" in mergedOptions ? mergedOptions.target ?? null : typeof document !== "undefined" ? document : null;
88
- if (!resolvedTarget) {
89
- if (registration?.isActive) {
90
- registration.unregister();
91
- registration = null;
92
- }
93
- lastHotkeyString = null;
94
- lastTarget = null;
95
- return;
96
- }
97
- const { target: _target, ...optionsWithoutTarget } = mergedOptions;
98
- if (registration?.isActive && lastHotkeyString === hotkeyString && lastTarget === resolvedTarget) {
99
- registration.callback = callback;
100
- registration.setOptions(optionsWithoutTarget);
101
- return;
102
- }
103
- if (registration?.isActive) {
104
- registration.unregister();
105
- registration = null;
106
- }
107
- registration = manager.register(hotkeyString, callback, {
108
- ...optionsWithoutTarget,
109
- target: resolvedTarget
110
- });
111
- if (registration.isActive) {
112
- registration.callback = callback;
113
- registration.setOptions(optionsWithoutTarget);
114
- }
115
- lastHotkeyString = hotkeyString;
116
- lastTarget = resolvedTarget;
117
- });
118
- }
119
-
120
- //#endregion
121
- exports.injectHotkey = injectHotkey;
122
- //# sourceMappingURL=injectHotkey.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkey.cjs","names":["injectDefaultHotkeysOptions","DestroyRef"],"sources":["../src/injectHotkey.ts"],"sourcesContent":["import { DestroyRef, effect, inject } from '@angular/core'\nimport {\n detectPlatform,\n getHotkeyManager,\n normalizeRegisterableHotkey,\n} from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type {\n Hotkey,\n HotkeyCallback,\n HotkeyOptions,\n HotkeyRegistrationHandle,\n RegisterableHotkey,\n} from '@tanstack/hotkeys'\n\nexport interface InjectHotkeyOptions extends Omit<HotkeyOptions, 'target'> {\n /**\n * The DOM element to attach the event listener to.\n * Can be a direct DOM element, an accessor (for reactive targets that become\n * available after mount), or null. Defaults to document.\n * When using scoped targets, pass an accessor: () => ({ target: elementSignal() })\n * so the hotkey waits for the element to be attached before registering.\n */\n target?: HTMLElement | Document | Window | null\n}\n\n/**\n * Angular inject-based API for registering a keyboard hotkey.\n *\n * Uses the singleton HotkeyManager for efficient event handling.\n * The callback receives both the keyboard event and a context object\n * containing the hotkey string and parsed hotkey.\n *\n * Call in an injection context (e.g. constructor or field initializer).\n * Uses effect() to track reactive dependencies and update registration\n * when options or the callback change.\n * `enabled: false` keeps the registration (visible in devtools) and only suppresses firing; the same\n * handle is updated instead of unregistering and re-registering when identity is unchanged.\n *\n * @param hotkey - The hotkey string (e.g. 'Mod+S', 'Escape') or getter function\n * @param callback - The function to call when the hotkey is pressed\n * @param options - Options for the hotkey behavior, or getter for reactive options\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class SaveButtonComponent {\n * private readonly saveCount = signal(0)\n *\n * constructor() {\n * injectHotkey('Mod+S', (event, { hotkey }) => {\n * event.preventDefault()\n * this.saveCount.update(c => c + 1)\n * })\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class ModalComponent {\n * isOpen = signal(true)\n *\n * constructor() {\n * injectHotkey('Escape', () => this.close(), () => ({ enabled: this.isOpen() }))\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class EditorComponent {\n * private readonly editorRef = viewChild<ElementRef<HTMLDivElement>>('editorRef')\n *\n * constructor() {\n * injectHotkey('Mod+B', () => this.toggleBold(), () => ({\n * target: this.editorRef()?.nativeElement ?? null,\n * }))\n * }\n * }\n * ```\n */\nexport function injectHotkey(\n hotkey: RegisterableHotkey | (() => RegisterableHotkey),\n callback: HotkeyCallback,\n options: InjectHotkeyOptions | (() => InjectHotkeyOptions) = {},\n): void {\n const defaultOptions = injectDefaultHotkeysOptions()\n const manager = getHotkeyManager()\n const destroyRef = inject(DestroyRef)\n\n let registration: HotkeyRegistrationHandle | null = null\n let lastHotkeyString: Hotkey | null = null\n let lastTarget: HTMLElement | Document | Window | null = null\n\n destroyRef.onDestroy(() => {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastHotkeyString = null\n lastTarget = null\n })\n\n effect(() => {\n // Resolve reactive values\n const resolvedHotkey = typeof hotkey === 'function' ? hotkey() : hotkey\n const resolvedOptions = typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkey,\n ...resolvedOptions,\n } as InjectHotkeyOptions\n\n // Normalize to hotkey string\n const platform = mergedOptions.platform ?? detectPlatform()\n const hotkeyString = normalizeRegisterableHotkey(resolvedHotkey, platform)\n\n // Resolve target: when explicitly provided (even as null), use it and skip if null.\n // When not provided, default to document. Matches React's ref handling.\n const resolvedTarget =\n 'target' in mergedOptions\n ? (mergedOptions.target ?? null)\n : typeof document !== 'undefined'\n ? document\n : null\n\n if (!resolvedTarget) {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastHotkeyString = null\n lastTarget = null\n return\n }\n\n // Extract options without target (target is handled separately)\n const { target: _target, ...optionsWithoutTarget } = mergedOptions\n\n if (\n registration?.isActive &&\n lastHotkeyString === hotkeyString &&\n lastTarget === resolvedTarget\n ) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n return\n }\n\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n registration = manager.register(hotkeyString, callback, {\n ...optionsWithoutTarget,\n target: resolvedTarget,\n })\n\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n\n lastHotkeyString = hotkeyString\n lastTarget = resolvedTarget\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,SAAgB,aACd,QACA,UACA,UAA6D,EAAE,EACzD;CACN,MAAM,iBAAiBA,sDAA6B;CACpD,MAAM,mDAA4B;CAClC,MAAM,uCAAoBC,yBAAW;CAErC,IAAI,eAAgD;CACpD,IAAI,mBAAkC;CACtC,IAAI,aAAqD;AAEzD,YAAW,gBAAgB;AACzB,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAEjB,qBAAmB;AACnB,eAAa;GACb;AAEF,iCAAa;EAEX,MAAM,iBAAiB,OAAO,WAAW,aAAa,QAAQ,GAAG;EACjE,MAAM,kBAAkB,OAAO,YAAY,aAAa,SAAS,GAAG;EAEpE,MAAM,gBAAgB;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ;EAID,MAAM,kEAA2C,gBADhC,cAAc,mDAA4B,CACe;EAI1E,MAAM,iBACJ,YAAY,gBACP,cAAc,UAAU,OACzB,OAAO,aAAa,cAClB,WACA;AAER,MAAI,CAAC,gBAAgB;AACnB,OAAI,cAAc,UAAU;AAC1B,iBAAa,YAAY;AACzB,mBAAe;;AAEjB,sBAAmB;AACnB,gBAAa;AACb;;EAIF,MAAM,EAAE,QAAQ,SAAS,GAAG,yBAAyB;AAErD,MACE,cAAc,YACd,qBAAqB,gBACrB,eAAe,gBACf;AACA,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;AAC7C;;AAGF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAGjB,iBAAe,QAAQ,SAAS,cAAc,UAAU;GACtD,GAAG;GACH,QAAQ;GACT,CAAC;AAEF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;AAG/C,qBAAmB;AACnB,eAAa;GACb"}
@@ -1,75 +0,0 @@
1
- import { HotkeyCallback, HotkeyOptions, RegisterableHotkey } from "@tanstack/hotkeys";
2
-
3
- //#region src/injectHotkey.d.ts
4
- interface InjectHotkeyOptions extends Omit<HotkeyOptions, 'target'> {
5
- /**
6
- * The DOM element to attach the event listener to.
7
- * Can be a direct DOM element, an accessor (for reactive targets that become
8
- * available after mount), or null. Defaults to document.
9
- * When using scoped targets, pass an accessor: () => ({ target: elementSignal() })
10
- * so the hotkey waits for the element to be attached before registering.
11
- */
12
- target?: HTMLElement | Document | Window | null;
13
- }
14
- /**
15
- * Angular inject-based API for registering a keyboard hotkey.
16
- *
17
- * Uses the singleton HotkeyManager for efficient event handling.
18
- * The callback receives both the keyboard event and a context object
19
- * containing the hotkey string and parsed hotkey.
20
- *
21
- * Call in an injection context (e.g. constructor or field initializer).
22
- * Uses effect() to track reactive dependencies and update registration
23
- * when options or the callback change.
24
- * `enabled: false` keeps the registration (visible in devtools) and only suppresses firing; the same
25
- * handle is updated instead of unregistering and re-registering when identity is unchanged.
26
- *
27
- * @param hotkey - The hotkey string (e.g. 'Mod+S', 'Escape') or getter function
28
- * @param callback - The function to call when the hotkey is pressed
29
- * @param options - Options for the hotkey behavior, or getter for reactive options
30
- *
31
- * @example
32
- * ```ts
33
- * @Component({ ... })
34
- * export class SaveButtonComponent {
35
- * private readonly saveCount = signal(0)
36
- *
37
- * constructor() {
38
- * injectHotkey('Mod+S', (event, { hotkey }) => {
39
- * event.preventDefault()
40
- * this.saveCount.update(c => c + 1)
41
- * })
42
- * }
43
- * }
44
- * ```
45
- *
46
- * @example
47
- * ```ts
48
- * @Component({ ... })
49
- * export class ModalComponent {
50
- * isOpen = signal(true)
51
- *
52
- * constructor() {
53
- * injectHotkey('Escape', () => this.close(), () => ({ enabled: this.isOpen() }))
54
- * }
55
- * }
56
- * ```
57
- *
58
- * @example
59
- * ```ts
60
- * @Component({ ... })
61
- * export class EditorComponent {
62
- * private readonly editorRef = viewChild<ElementRef<HTMLDivElement>>('editorRef')
63
- *
64
- * constructor() {
65
- * injectHotkey('Mod+B', () => this.toggleBold(), () => ({
66
- * target: this.editorRef()?.nativeElement ?? null,
67
- * }))
68
- * }
69
- * }
70
- * ```
71
- */
72
- declare function injectHotkey(hotkey: RegisterableHotkey | (() => RegisterableHotkey), callback: HotkeyCallback, options?: InjectHotkeyOptions | (() => InjectHotkeyOptions)): void;
73
- //#endregion
74
- export { InjectHotkeyOptions, injectHotkey };
75
- //# sourceMappingURL=injectHotkey.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkey.js","names":[],"sources":["../src/injectHotkey.ts"],"sourcesContent":["import { DestroyRef, effect, inject } from '@angular/core'\nimport {\n detectPlatform,\n getHotkeyManager,\n normalizeRegisterableHotkey,\n} from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type {\n Hotkey,\n HotkeyCallback,\n HotkeyOptions,\n HotkeyRegistrationHandle,\n RegisterableHotkey,\n} from '@tanstack/hotkeys'\n\nexport interface InjectHotkeyOptions extends Omit<HotkeyOptions, 'target'> {\n /**\n * The DOM element to attach the event listener to.\n * Can be a direct DOM element, an accessor (for reactive targets that become\n * available after mount), or null. Defaults to document.\n * When using scoped targets, pass an accessor: () => ({ target: elementSignal() })\n * so the hotkey waits for the element to be attached before registering.\n */\n target?: HTMLElement | Document | Window | null\n}\n\n/**\n * Angular inject-based API for registering a keyboard hotkey.\n *\n * Uses the singleton HotkeyManager for efficient event handling.\n * The callback receives both the keyboard event and a context object\n * containing the hotkey string and parsed hotkey.\n *\n * Call in an injection context (e.g. constructor or field initializer).\n * Uses effect() to track reactive dependencies and update registration\n * when options or the callback change.\n * `enabled: false` keeps the registration (visible in devtools) and only suppresses firing; the same\n * handle is updated instead of unregistering and re-registering when identity is unchanged.\n *\n * @param hotkey - The hotkey string (e.g. 'Mod+S', 'Escape') or getter function\n * @param callback - The function to call when the hotkey is pressed\n * @param options - Options for the hotkey behavior, or getter for reactive options\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class SaveButtonComponent {\n * private readonly saveCount = signal(0)\n *\n * constructor() {\n * injectHotkey('Mod+S', (event, { hotkey }) => {\n * event.preventDefault()\n * this.saveCount.update(c => c + 1)\n * })\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class ModalComponent {\n * isOpen = signal(true)\n *\n * constructor() {\n * injectHotkey('Escape', () => this.close(), () => ({ enabled: this.isOpen() }))\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class EditorComponent {\n * private readonly editorRef = viewChild<ElementRef<HTMLDivElement>>('editorRef')\n *\n * constructor() {\n * injectHotkey('Mod+B', () => this.toggleBold(), () => ({\n * target: this.editorRef()?.nativeElement ?? null,\n * }))\n * }\n * }\n * ```\n */\nexport function injectHotkey(\n hotkey: RegisterableHotkey | (() => RegisterableHotkey),\n callback: HotkeyCallback,\n options: InjectHotkeyOptions | (() => InjectHotkeyOptions) = {},\n): void {\n const defaultOptions = injectDefaultHotkeysOptions()\n const manager = getHotkeyManager()\n const destroyRef = inject(DestroyRef)\n\n let registration: HotkeyRegistrationHandle | null = null\n let lastHotkeyString: Hotkey | null = null\n let lastTarget: HTMLElement | Document | Window | null = null\n\n destroyRef.onDestroy(() => {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastHotkeyString = null\n lastTarget = null\n })\n\n effect(() => {\n // Resolve reactive values\n const resolvedHotkey = typeof hotkey === 'function' ? hotkey() : hotkey\n const resolvedOptions = typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkey,\n ...resolvedOptions,\n } as InjectHotkeyOptions\n\n // Normalize to hotkey string\n const platform = mergedOptions.platform ?? detectPlatform()\n const hotkeyString = normalizeRegisterableHotkey(resolvedHotkey, platform)\n\n // Resolve target: when explicitly provided (even as null), use it and skip if null.\n // When not provided, default to document. Matches React's ref handling.\n const resolvedTarget =\n 'target' in mergedOptions\n ? (mergedOptions.target ?? null)\n : typeof document !== 'undefined'\n ? document\n : null\n\n if (!resolvedTarget) {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastHotkeyString = null\n lastTarget = null\n return\n }\n\n // Extract options without target (target is handled separately)\n const { target: _target, ...optionsWithoutTarget } = mergedOptions\n\n if (\n registration?.isActive &&\n lastHotkeyString === hotkeyString &&\n lastTarget === resolvedTarget\n ) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n return\n }\n\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n registration = manager.register(hotkeyString, callback, {\n ...optionsWithoutTarget,\n target: resolvedTarget,\n })\n\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n\n lastHotkeyString = hotkeyString\n lastTarget = resolvedTarget\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,SAAgB,aACd,QACA,UACA,UAA6D,EAAE,EACzD;CACN,MAAM,iBAAiB,6BAA6B;CACpD,MAAM,UAAU,kBAAkB;CAClC,MAAM,aAAa,OAAO,WAAW;CAErC,IAAI,eAAgD;CACpD,IAAI,mBAAkC;CACtC,IAAI,aAAqD;AAEzD,YAAW,gBAAgB;AACzB,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAEjB,qBAAmB;AACnB,eAAa;GACb;AAEF,cAAa;EAEX,MAAM,iBAAiB,OAAO,WAAW,aAAa,QAAQ,GAAG;EACjE,MAAM,kBAAkB,OAAO,YAAY,aAAa,SAAS,GAAG;EAEpE,MAAM,gBAAgB;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ;EAID,MAAM,eAAe,4BAA4B,gBADhC,cAAc,YAAY,gBAAgB,CACe;EAI1E,MAAM,iBACJ,YAAY,gBACP,cAAc,UAAU,OACzB,OAAO,aAAa,cAClB,WACA;AAER,MAAI,CAAC,gBAAgB;AACnB,OAAI,cAAc,UAAU;AAC1B,iBAAa,YAAY;AACzB,mBAAe;;AAEjB,sBAAmB;AACnB,gBAAa;AACb;;EAIF,MAAM,EAAE,QAAQ,SAAS,GAAG,yBAAyB;AAErD,MACE,cAAc,YACd,qBAAqB,gBACrB,eAAe,gBACf;AACA,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;AAC7C;;AAGF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAGjB,iBAAe,QAAQ,SAAS,cAAc,UAAU;GACtD,GAAG;GACH,QAAQ;GACT,CAAC;AAEF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;AAG/C,qBAAmB;AACnB,eAAa;GACb"}
@@ -1,82 +0,0 @@
1
- const require_hotkeys_provider = require('./hotkeys-provider.cjs');
2
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
3
- let _angular_core = require("@angular/core");
4
-
5
- //#region src/injectHotkeyRecorder.ts
6
- /**
7
- * Angular inject-based API for recording keyboard shortcuts.
8
- *
9
- * Thin wrapper around the framework-agnostic HotkeyRecorder class: captures
10
- * keyboard events, converts them to hotkey strings, and handles Escape to
11
- * cancel or Backspace/Delete to clear.
12
- *
13
- * @param options - Configuration options for the recorder (or getter)
14
- * @returns Object with recording state signals and control functions
15
- *
16
- * @example
17
- * ```ts
18
- * @Component({ ... })
19
- * export class ShortcutSettingsComponent {
20
- * shortcut = signal<Hotkey>('Mod+S')
21
- * recorder = injectHotkeyRecorder({
22
- * onRecord: (hotkey) => this.shortcut.set(hotkey),
23
- * onCancel: () => console.log('Recording cancelled'),
24
- * })
25
- *
26
- * constructor() {
27
- * injectHotkey(
28
- * () => this.shortcut(),
29
- * () => this.handleSave(),
30
- * () => ({ enabled: !this.recorder.isRecording() }),
31
- * )
32
- * }
33
- * }
34
- * ```
35
- */
36
- function injectHotkeyRecorder(options) {
37
- const defaultOptions = require_hotkeys_provider.injectDefaultHotkeysOptions();
38
- const destroyRef = (0, _angular_core.inject)(_angular_core.DestroyRef);
39
- const recorderSignal = (0, _angular_core.computed)(() => (0, _angular_core.untracked)(() => {
40
- const resolvedOptions = typeof options === "function" ? options() : options;
41
- return new _tanstack_hotkeys.HotkeyRecorder({
42
- ...defaultOptions.hotkeyRecorder,
43
- ...resolvedOptions
44
- });
45
- }));
46
- const recorderStore = (0, _angular_core.computed)(() => (0, _angular_core.untracked)(() => recorderSignal().store));
47
- const isRecording = injectLazyStore(recorderStore, (state) => state.isRecording);
48
- const recordedHotkey = injectLazyStore(recorderStore, (state) => state.recordedHotkey);
49
- (0, _angular_core.effect)(() => {
50
- const resolved = typeof options === "function" ? options() : options;
51
- recorderSignal().setOptions({
52
- ...defaultOptions.hotkeyRecorder,
53
- ...resolved
54
- });
55
- });
56
- destroyRef.onDestroy(() => {
57
- recorderSignal().destroy();
58
- });
59
- return {
60
- isRecording,
61
- recordedHotkey,
62
- startRecording: () => recorderSignal().start(),
63
- stopRecording: () => recorderSignal().stop(),
64
- cancelRecording: () => recorderSignal().cancel()
65
- };
66
- }
67
- function injectLazyStore(storeSignal, selector) {
68
- const slice = (0, _angular_core.linkedSignal)(() => selector(storeSignal().get()));
69
- (0, _angular_core.effect)((onCleanup) => {
70
- const currentStore = storeSignal();
71
- slice.set(selector(currentStore.get()));
72
- const { unsubscribe } = currentStore.subscribe((s) => {
73
- slice.set(selector(s));
74
- });
75
- onCleanup(() => unsubscribe());
76
- });
77
- return slice.asReadonly();
78
- }
79
-
80
- //#endregion
81
- exports.injectHotkeyRecorder = injectHotkeyRecorder;
82
- //# sourceMappingURL=injectHotkeyRecorder.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkeyRecorder.cjs","names":["injectDefaultHotkeysOptions","DestroyRef","HotkeyRecorder"],"sources":["../src/injectHotkeyRecorder.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n linkedSignal,\n untracked,\n} from '@angular/core'\nimport { HotkeyRecorder } from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type { Atom, ReadonlyAtom } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\nimport type { Hotkey, HotkeyRecorderOptions } from '@tanstack/hotkeys'\n\nexport interface AngularHotkeyRecorder {\n /** Whether recording is currently active */\n readonly isRecording: () => boolean\n /** The currently recorded hotkey (for live preview) */\n readonly recordedHotkey: () => Hotkey | null\n /** Start recording a new hotkey */\n readonly startRecording: () => void\n /** Stop recording (same as cancel) */\n readonly stopRecording: () => void\n /** Cancel recording without saving */\n readonly cancelRecording: () => void\n}\n\n/**\n * Angular inject-based API for recording keyboard shortcuts.\n *\n * Thin wrapper around the framework-agnostic HotkeyRecorder class: captures\n * keyboard events, converts them to hotkey strings, and handles Escape to\n * cancel or Backspace/Delete to clear.\n *\n * @param options - Configuration options for the recorder (or getter)\n * @returns Object with recording state signals and control functions\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class ShortcutSettingsComponent {\n * shortcut = signal<Hotkey>('Mod+S')\n * recorder = injectHotkeyRecorder({\n * onRecord: (hotkey) => this.shortcut.set(hotkey),\n * onCancel: () => console.log('Recording cancelled'),\n * })\n *\n * constructor() {\n * injectHotkey(\n * () => this.shortcut(),\n * () => this.handleSave(),\n * () => ({ enabled: !this.recorder.isRecording() }),\n * )\n * }\n * }\n * ```\n */\nexport function injectHotkeyRecorder(\n options: HotkeyRecorderOptions | (() => HotkeyRecorderOptions),\n): AngularHotkeyRecorder {\n const defaultOptions = injectDefaultHotkeysOptions()\n const destroyRef = inject(DestroyRef)\n\n // Stable signal to lazy initialize the recorder\n const recorderSignal = computed(() =>\n untracked(() => {\n const resolvedOptions =\n typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkeyRecorder,\n ...resolvedOptions,\n } as HotkeyRecorderOptions\n\n return new HotkeyRecorder(mergedOptions)\n }),\n )\n\n // Subscribe to recorder state\n const recorderStore = computed(() => untracked(() => recorderSignal().store))\n const isRecording = injectLazyStore(\n recorderStore,\n (state) => state.isRecording,\n )\n const recordedHotkey = injectLazyStore(\n recorderStore,\n (state) => state.recordedHotkey,\n )\n\n // Sync options on every effect run (matches React's sync on render)\n effect(() => {\n const resolved = typeof options === 'function' ? options() : options\n recorderSignal().setOptions({\n ...defaultOptions.hotkeyRecorder,\n ...resolved,\n } as HotkeyRecorderOptions)\n })\n\n destroyRef.onDestroy(() => {\n recorderSignal().destroy()\n })\n\n return {\n isRecording,\n recordedHotkey,\n startRecording: () => recorderSignal().start(),\n stopRecording: () => recorderSignal().stop(),\n cancelRecording: () => recorderSignal().cancel(),\n }\n}\n\nfunction injectLazyStore<TState, TSelected = NoInfer<TState>>(\n storeSignal: Signal<Atom<TState> | ReadonlyAtom<TState>>,\n selector: (state: NoInfer<TState>) => TSelected,\n): Signal<TSelected> {\n const slice = linkedSignal(() => selector(storeSignal().get()))\n\n effect((onCleanup) => {\n const currentStore = storeSignal()\n slice.set(selector(currentStore.get()))\n const { unsubscribe } = currentStore.subscribe((s) => {\n slice.set(selector(s))\n })\n onCleanup(() => unsubscribe())\n })\n\n return slice.asReadonly()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,SAAgB,qBACd,SACuB;CACvB,MAAM,iBAAiBA,sDAA6B;CACpD,MAAM,uCAAoBC,yBAAW;CAGrC,MAAM,sFACY;EACd,MAAM,kBACJ,OAAO,YAAY,aAAa,SAAS,GAAG;AAO9C,SAAO,IAAIC,iCALW;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ,CAEuC;GACxC,CACH;CAGD,MAAM,qFAA+C,gBAAgB,CAAC,MAAM,CAAC;CAC7E,MAAM,cAAc,gBAClB,gBACC,UAAU,MAAM,YAClB;CACD,MAAM,iBAAiB,gBACrB,gBACC,UAAU,MAAM,eAClB;AAGD,iCAAa;EACX,MAAM,WAAW,OAAO,YAAY,aAAa,SAAS,GAAG;AAC7D,kBAAgB,CAAC,WAAW;GAC1B,GAAG,eAAe;GAClB,GAAG;GACJ,CAA0B;GAC3B;AAEF,YAAW,gBAAgB;AACzB,kBAAgB,CAAC,SAAS;GAC1B;AAEF,QAAO;EACL;EACA;EACA,sBAAsB,gBAAgB,CAAC,OAAO;EAC9C,qBAAqB,gBAAgB,CAAC,MAAM;EAC5C,uBAAuB,gBAAgB,CAAC,QAAQ;EACjD;;AAGH,SAAS,gBACP,aACA,UACmB;CACnB,MAAM,8CAA2B,SAAS,aAAa,CAAC,KAAK,CAAC,CAAC;AAE/D,4BAAQ,cAAc;EACpB,MAAM,eAAe,aAAa;AAClC,QAAM,IAAI,SAAS,aAAa,KAAK,CAAC,CAAC;EACvC,MAAM,EAAE,gBAAgB,aAAa,WAAW,MAAM;AACpD,SAAM,IAAI,SAAS,EAAE,CAAC;IACtB;AACF,kBAAgB,aAAa,CAAC;GAC9B;AAEF,QAAO,MAAM,YAAY"}
@@ -1,49 +0,0 @@
1
- import { Hotkey, HotkeyRecorderOptions } from "@tanstack/hotkeys";
2
-
3
- //#region src/injectHotkeyRecorder.d.ts
4
- interface AngularHotkeyRecorder {
5
- /** Whether recording is currently active */
6
- readonly isRecording: () => boolean;
7
- /** The currently recorded hotkey (for live preview) */
8
- readonly recordedHotkey: () => Hotkey | null;
9
- /** Start recording a new hotkey */
10
- readonly startRecording: () => void;
11
- /** Stop recording (same as cancel) */
12
- readonly stopRecording: () => void;
13
- /** Cancel recording without saving */
14
- readonly cancelRecording: () => void;
15
- }
16
- /**
17
- * Angular inject-based API for recording keyboard shortcuts.
18
- *
19
- * Thin wrapper around the framework-agnostic HotkeyRecorder class: captures
20
- * keyboard events, converts them to hotkey strings, and handles Escape to
21
- * cancel or Backspace/Delete to clear.
22
- *
23
- * @param options - Configuration options for the recorder (or getter)
24
- * @returns Object with recording state signals and control functions
25
- *
26
- * @example
27
- * ```ts
28
- * @Component({ ... })
29
- * export class ShortcutSettingsComponent {
30
- * shortcut = signal<Hotkey>('Mod+S')
31
- * recorder = injectHotkeyRecorder({
32
- * onRecord: (hotkey) => this.shortcut.set(hotkey),
33
- * onCancel: () => console.log('Recording cancelled'),
34
- * })
35
- *
36
- * constructor() {
37
- * injectHotkey(
38
- * () => this.shortcut(),
39
- * () => this.handleSave(),
40
- * () => ({ enabled: !this.recorder.isRecording() }),
41
- * )
42
- * }
43
- * }
44
- * ```
45
- */
46
- declare function injectHotkeyRecorder(options: HotkeyRecorderOptions | (() => HotkeyRecorderOptions)): AngularHotkeyRecorder;
47
- //#endregion
48
- export { AngularHotkeyRecorder, injectHotkeyRecorder };
49
- //# sourceMappingURL=injectHotkeyRecorder.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkeyRecorder.js","names":[],"sources":["../src/injectHotkeyRecorder.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n linkedSignal,\n untracked,\n} from '@angular/core'\nimport { HotkeyRecorder } from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type { Atom, ReadonlyAtom } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\nimport type { Hotkey, HotkeyRecorderOptions } from '@tanstack/hotkeys'\n\nexport interface AngularHotkeyRecorder {\n /** Whether recording is currently active */\n readonly isRecording: () => boolean\n /** The currently recorded hotkey (for live preview) */\n readonly recordedHotkey: () => Hotkey | null\n /** Start recording a new hotkey */\n readonly startRecording: () => void\n /** Stop recording (same as cancel) */\n readonly stopRecording: () => void\n /** Cancel recording without saving */\n readonly cancelRecording: () => void\n}\n\n/**\n * Angular inject-based API for recording keyboard shortcuts.\n *\n * Thin wrapper around the framework-agnostic HotkeyRecorder class: captures\n * keyboard events, converts them to hotkey strings, and handles Escape to\n * cancel or Backspace/Delete to clear.\n *\n * @param options - Configuration options for the recorder (or getter)\n * @returns Object with recording state signals and control functions\n *\n * @example\n * ```ts\n * @Component({ ... })\n * export class ShortcutSettingsComponent {\n * shortcut = signal<Hotkey>('Mod+S')\n * recorder = injectHotkeyRecorder({\n * onRecord: (hotkey) => this.shortcut.set(hotkey),\n * onCancel: () => console.log('Recording cancelled'),\n * })\n *\n * constructor() {\n * injectHotkey(\n * () => this.shortcut(),\n * () => this.handleSave(),\n * () => ({ enabled: !this.recorder.isRecording() }),\n * )\n * }\n * }\n * ```\n */\nexport function injectHotkeyRecorder(\n options: HotkeyRecorderOptions | (() => HotkeyRecorderOptions),\n): AngularHotkeyRecorder {\n const defaultOptions = injectDefaultHotkeysOptions()\n const destroyRef = inject(DestroyRef)\n\n // Stable signal to lazy initialize the recorder\n const recorderSignal = computed(() =>\n untracked(() => {\n const resolvedOptions =\n typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkeyRecorder,\n ...resolvedOptions,\n } as HotkeyRecorderOptions\n\n return new HotkeyRecorder(mergedOptions)\n }),\n )\n\n // Subscribe to recorder state\n const recorderStore = computed(() => untracked(() => recorderSignal().store))\n const isRecording = injectLazyStore(\n recorderStore,\n (state) => state.isRecording,\n )\n const recordedHotkey = injectLazyStore(\n recorderStore,\n (state) => state.recordedHotkey,\n )\n\n // Sync options on every effect run (matches React's sync on render)\n effect(() => {\n const resolved = typeof options === 'function' ? options() : options\n recorderSignal().setOptions({\n ...defaultOptions.hotkeyRecorder,\n ...resolved,\n } as HotkeyRecorderOptions)\n })\n\n destroyRef.onDestroy(() => {\n recorderSignal().destroy()\n })\n\n return {\n isRecording,\n recordedHotkey,\n startRecording: () => recorderSignal().start(),\n stopRecording: () => recorderSignal().stop(),\n cancelRecording: () => recorderSignal().cancel(),\n }\n}\n\nfunction injectLazyStore<TState, TSelected = NoInfer<TState>>(\n storeSignal: Signal<Atom<TState> | ReadonlyAtom<TState>>,\n selector: (state: NoInfer<TState>) => TSelected,\n): Signal<TSelected> {\n const slice = linkedSignal(() => selector(storeSignal().get()))\n\n effect((onCleanup) => {\n const currentStore = storeSignal()\n slice.set(selector(currentStore.get()))\n const { unsubscribe } = currentStore.subscribe((s) => {\n slice.set(selector(s))\n })\n onCleanup(() => unsubscribe())\n })\n\n return slice.asReadonly()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,SAAgB,qBACd,SACuB;CACvB,MAAM,iBAAiB,6BAA6B;CACpD,MAAM,aAAa,OAAO,WAAW;CAGrC,MAAM,iBAAiB,eACrB,gBAAgB;EACd,MAAM,kBACJ,OAAO,YAAY,aAAa,SAAS,GAAG;AAO9C,SAAO,IAAI,eALW;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ,CAEuC;GACxC,CACH;CAGD,MAAM,gBAAgB,eAAe,gBAAgB,gBAAgB,CAAC,MAAM,CAAC;CAC7E,MAAM,cAAc,gBAClB,gBACC,UAAU,MAAM,YAClB;CACD,MAAM,iBAAiB,gBACrB,gBACC,UAAU,MAAM,eAClB;AAGD,cAAa;EACX,MAAM,WAAW,OAAO,YAAY,aAAa,SAAS,GAAG;AAC7D,kBAAgB,CAAC,WAAW;GAC1B,GAAG,eAAe;GAClB,GAAG;GACJ,CAA0B;GAC3B;AAEF,YAAW,gBAAgB;AACzB,kBAAgB,CAAC,SAAS;GAC1B;AAEF,QAAO;EACL;EACA;EACA,sBAAsB,gBAAgB,CAAC,OAAO;EAC9C,qBAAqB,gBAAgB,CAAC,MAAM;EAC5C,uBAAuB,gBAAgB,CAAC,QAAQ;EACjD;;AAGH,SAAS,gBACP,aACA,UACmB;CACnB,MAAM,QAAQ,mBAAmB,SAAS,aAAa,CAAC,KAAK,CAAC,CAAC;AAE/D,SAAQ,cAAc;EACpB,MAAM,eAAe,aAAa;AAClC,QAAM,IAAI,SAAS,aAAa,KAAK,CAAC,CAAC;EACvC,MAAM,EAAE,gBAAgB,aAAa,WAAW,MAAM;AACpD,SAAM,IAAI,SAAS,EAAE,CAAC;IACtB;AACF,kBAAgB,aAAa,CAAC;GAC9B;AAEF,QAAO,MAAM,YAAY"}
@@ -1,28 +0,0 @@
1
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
2
- let _tanstack_angular_store = require("@tanstack/angular-store");
3
-
4
- //#region src/injectHotkeyRegistrations.ts
5
- /**
6
- * Angular injectable that reactively reads all hotkey and sequence registrations
7
- * from the singleton managers.
8
- *
9
- * This is a standalone injectable that does NOT require the HotkeysProvider.
10
- * It subscribes to both HotkeyManager and SequenceManager stores and
11
- * triggers change detection when registrations change.
12
- *
13
- * Must be called in an injection context (constructor, factory, or `inject()`).
14
- *
15
- * @returns Object with `hotkeys` and `sequences` signals
16
- */
17
- function injectHotkeyRegistrations() {
18
- const hotkeyManager = (0, _tanstack_hotkeys.getHotkeyManager)();
19
- const sequenceManager = (0, _tanstack_hotkeys.getSequenceManager)();
20
- return {
21
- hotkeys: (0, _tanstack_angular_store.injectSelector)(hotkeyManager.registrations, (state) => Array.from(state.values()).map(_tanstack_hotkeys.toHotkeyRegistrationView)),
22
- sequences: (0, _tanstack_angular_store.injectSelector)(sequenceManager.registrations, (state) => Array.from(state.values()))
23
- };
24
- }
25
-
26
- //#endregion
27
- exports.injectHotkeyRegistrations = injectHotkeyRegistrations;
28
- //# sourceMappingURL=injectHotkeyRegistrations.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkeyRegistrations.cjs","names":["toHotkeyRegistrationView"],"sources":["../src/injectHotkeyRegistrations.ts"],"sourcesContent":["import { injectSelector } from '@tanstack/angular-store'\nimport {\n getHotkeyManager,\n getSequenceManager,\n toHotkeyRegistrationView,\n} from '@tanstack/hotkeys'\nimport type {\n HotkeyRegistrationView,\n SequenceRegistrationView,\n} from '@tanstack/hotkeys'\nimport type { Signal } from '@angular/core'\n\n/**\n * Return type for injectHotkeyRegistrations.\n */\nexport interface HotkeyRegistrationsResult {\n /** Signal for all registered hotkeys (public view, no callbacks) */\n hotkeys: Signal<Array<HotkeyRegistrationView>>\n /** Signal for all registered sequences */\n sequences: Signal<Array<SequenceRegistrationView>>\n}\n\n/**\n * Angular injectable that reactively reads all hotkey and sequence registrations\n * from the singleton managers.\n *\n * This is a standalone injectable that does NOT require the HotkeysProvider.\n * It subscribes to both HotkeyManager and SequenceManager stores and\n * triggers change detection when registrations change.\n *\n * Must be called in an injection context (constructor, factory, or `inject()`).\n *\n * @returns Object with `hotkeys` and `sequences` signals\n */\nexport function injectHotkeyRegistrations(): HotkeyRegistrationsResult {\n const hotkeyManager = getHotkeyManager()\n const sequenceManager = getSequenceManager()\n\n const hotkeys = injectSelector(hotkeyManager.registrations, (state) =>\n Array.from(state.values()).map(toHotkeyRegistrationView),\n )\n\n const sequences = injectSelector(sequenceManager.registrations, (state) =>\n Array.from(state.values()),\n )\n\n return { hotkeys, sequences }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,SAAgB,4BAAuD;CACrE,MAAM,yDAAkC;CACxC,MAAM,6DAAsC;AAU5C,QAAO;EAAE,qDARsB,cAAc,gBAAgB,UAC3D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,IAAIA,2CAAyB,CACzD;EAMiB,uDAJe,gBAAgB,gBAAgB,UAC/D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAC3B;EAE4B"}
@@ -1,29 +0,0 @@
1
- import { HotkeyRegistrationView, SequenceRegistrationView } from "@tanstack/hotkeys";
2
- import { Signal } from "@angular/core";
3
-
4
- //#region src/injectHotkeyRegistrations.d.ts
5
- /**
6
- * Return type for injectHotkeyRegistrations.
7
- */
8
- interface HotkeyRegistrationsResult {
9
- /** Signal for all registered hotkeys (public view, no callbacks) */
10
- hotkeys: Signal<Array<HotkeyRegistrationView>>;
11
- /** Signal for all registered sequences */
12
- sequences: Signal<Array<SequenceRegistrationView>>;
13
- }
14
- /**
15
- * Angular injectable that reactively reads all hotkey and sequence registrations
16
- * from the singleton managers.
17
- *
18
- * This is a standalone injectable that does NOT require the HotkeysProvider.
19
- * It subscribes to both HotkeyManager and SequenceManager stores and
20
- * triggers change detection when registrations change.
21
- *
22
- * Must be called in an injection context (constructor, factory, or `inject()`).
23
- *
24
- * @returns Object with `hotkeys` and `sequences` signals
25
- */
26
- declare function injectHotkeyRegistrations(): HotkeyRegistrationsResult;
27
- //#endregion
28
- export { HotkeyRegistrationsResult, injectHotkeyRegistrations };
29
- //# sourceMappingURL=injectHotkeyRegistrations.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"injectHotkeyRegistrations.js","names":[],"sources":["../src/injectHotkeyRegistrations.ts"],"sourcesContent":["import { injectSelector } from '@tanstack/angular-store'\nimport {\n getHotkeyManager,\n getSequenceManager,\n toHotkeyRegistrationView,\n} from '@tanstack/hotkeys'\nimport type {\n HotkeyRegistrationView,\n SequenceRegistrationView,\n} from '@tanstack/hotkeys'\nimport type { Signal } from '@angular/core'\n\n/**\n * Return type for injectHotkeyRegistrations.\n */\nexport interface HotkeyRegistrationsResult {\n /** Signal for all registered hotkeys (public view, no callbacks) */\n hotkeys: Signal<Array<HotkeyRegistrationView>>\n /** Signal for all registered sequences */\n sequences: Signal<Array<SequenceRegistrationView>>\n}\n\n/**\n * Angular injectable that reactively reads all hotkey and sequence registrations\n * from the singleton managers.\n *\n * This is a standalone injectable that does NOT require the HotkeysProvider.\n * It subscribes to both HotkeyManager and SequenceManager stores and\n * triggers change detection when registrations change.\n *\n * Must be called in an injection context (constructor, factory, or `inject()`).\n *\n * @returns Object with `hotkeys` and `sequences` signals\n */\nexport function injectHotkeyRegistrations(): HotkeyRegistrationsResult {\n const hotkeyManager = getHotkeyManager()\n const sequenceManager = getSequenceManager()\n\n const hotkeys = injectSelector(hotkeyManager.registrations, (state) =>\n Array.from(state.values()).map(toHotkeyRegistrationView),\n )\n\n const sequences = injectSelector(sequenceManager.registrations, (state) =>\n Array.from(state.values()),\n )\n\n return { hotkeys, sequences }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,SAAgB,4BAAuD;CACrE,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,kBAAkB,oBAAoB;AAU5C,QAAO;EAAE,SARO,eAAe,cAAc,gBAAgB,UAC3D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,IAAI,yBAAyB,CACzD;EAMiB,WAJA,eAAe,gBAAgB,gBAAgB,UAC/D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAC3B;EAE4B"}