@tanstack/angular-hotkeys 0.5.1 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"file":"hotkeys-provider.cjs","names":["InjectionToken"],"sources":["../src/hotkeys-provider.ts"],"sourcesContent":["import { InjectionToken, inject } from '@angular/core'\nimport type { HotkeyRecorderOptions } from '@tanstack/hotkeys'\nimport type { InjectHotkeyOptions } from './injectHotkey'\nimport type { InjectHotkeySequenceOptions } from './injectHotkeySequence'\nimport type { StaticProvider } from '@angular/core'\n\nexport interface HotkeysProviderOptions {\n hotkey?: Partial<InjectHotkeyOptions>\n hotkeyRecorder?: Partial<HotkeyRecorderOptions>\n hotkeySequence?: Partial<InjectHotkeySequenceOptions>\n}\n\nexport interface HotkeysContextValue {\n readonly defaultOptions: HotkeysProviderOptions\n}\n\nexport const HOTKEYS_INJECTION_TOKEN = new InjectionToken<HotkeysContextValue>(\n 'HOTKEYS_INJECTION_TOKEN',\n {\n providedIn: 'root',\n factory: () => ({ defaultOptions: {} }),\n },\n)\n\nexport function provideHotkeys(\n defaultOptions: HotkeysProviderOptions,\n): StaticProvider {\n return {\n provide: HOTKEYS_INJECTION_TOKEN,\n useValue: { defaultOptions },\n }\n}\n\nexport function injectHotkeysContext(): HotkeysContextValue {\n return inject(HOTKEYS_INJECTION_TOKEN)\n}\n\nexport function injectDefaultHotkeysOptions(): HotkeysProviderOptions {\n return injectHotkeysContext().defaultOptions\n}\n"],"mappings":";;;AAgBA,MAAa,0BAA0B,IAAIA,6BACzC,2BACA;CACE,YAAY;CACZ,gBAAgB,EAAE,gBAAgB,EAAE,EAAE;CACvC,CACF;AAED,SAAgB,eACd,gBACgB;AAChB,QAAO;EACL,SAAS;EACT,UAAU,EAAE,gBAAgB;EAC7B;;AAGH,SAAgB,uBAA4C;AAC1D,kCAAc,wBAAwB;;AAGxC,SAAgB,8BAAsD;AACpE,QAAO,sBAAsB,CAAC"}
1
+ {"version":3,"file":"hotkeys-provider.cjs","names":["InjectionToken"],"sources":["../src/hotkeys-provider.ts"],"sourcesContent":["import { InjectionToken, inject } from '@angular/core'\nimport type {\n HotkeyRecorderOptions,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\nimport type { InjectHotkeyOptions } from './injectHotkey'\nimport type { InjectHotkeySequenceOptions } from './injectHotkeySequence'\nimport type { StaticProvider } from '@angular/core'\n\nexport interface HotkeysProviderOptions {\n hotkey?: Partial<InjectHotkeyOptions>\n hotkeyRecorder?: Partial<HotkeyRecorderOptions>\n hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>\n hotkeySequence?: Partial<InjectHotkeySequenceOptions>\n}\n\nexport interface HotkeysContextValue {\n readonly defaultOptions: HotkeysProviderOptions\n}\n\nexport const HOTKEYS_INJECTION_TOKEN = new InjectionToken<HotkeysContextValue>(\n 'HOTKEYS_INJECTION_TOKEN',\n {\n providedIn: 'root',\n factory: () => ({ defaultOptions: {} }),\n },\n)\n\nexport function provideHotkeys(\n defaultOptions: HotkeysProviderOptions,\n): StaticProvider {\n return {\n provide: HOTKEYS_INJECTION_TOKEN,\n useValue: { defaultOptions },\n }\n}\n\nexport function injectHotkeysContext(): HotkeysContextValue {\n return inject(HOTKEYS_INJECTION_TOKEN)\n}\n\nexport function injectDefaultHotkeysOptions(): HotkeysProviderOptions {\n return injectHotkeysContext().defaultOptions\n}\n"],"mappings":";;;AAoBA,MAAa,0BAA0B,IAAIA,6BACzC,2BACA;CACE,YAAY;CACZ,gBAAgB,EAAE,gBAAgB,EAAE,EAAE;CACvC,CACF;AAED,SAAgB,eACd,gBACgB;AAChB,QAAO;EACL,SAAS;EACT,UAAU,EAAE,gBAAgB;EAC7B;;AAGH,SAAgB,uBAA4C;AAC1D,kCAAc,wBAAwB;;AAGxC,SAAgB,8BAAsD;AACpE,QAAO,sBAAsB,CAAC"}
@@ -1,12 +1,13 @@
1
1
  import { InjectHotkeyOptions } from "./injectHotkey.cjs";
2
2
  import { InjectHotkeySequenceOptions } from "./injectHotkeySequence.cjs";
3
- import { HotkeyRecorderOptions } from "@tanstack/hotkeys";
3
+ import { HotkeyRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
4
4
  import { InjectionToken, StaticProvider } from "@angular/core";
5
5
 
6
6
  //#region src/hotkeys-provider.d.ts
7
7
  interface HotkeysProviderOptions {
8
8
  hotkey?: Partial<InjectHotkeyOptions>;
9
9
  hotkeyRecorder?: Partial<HotkeyRecorderOptions>;
10
+ hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>;
10
11
  hotkeySequence?: Partial<InjectHotkeySequenceOptions>;
11
12
  }
12
13
  interface HotkeysContextValue {
@@ -1,12 +1,13 @@
1
1
  import { InjectHotkeyOptions } from "./injectHotkey.js";
2
2
  import { InjectHotkeySequenceOptions } from "./injectHotkeySequence.js";
3
- import { HotkeyRecorderOptions } from "@tanstack/hotkeys";
3
+ import { HotkeyRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
4
4
  import { InjectionToken, StaticProvider } from "@angular/core";
5
5
 
6
6
  //#region src/hotkeys-provider.d.ts
7
7
  interface HotkeysProviderOptions {
8
8
  hotkey?: Partial<InjectHotkeyOptions>;
9
9
  hotkeyRecorder?: Partial<HotkeyRecorderOptions>;
10
+ hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>;
10
11
  hotkeySequence?: Partial<InjectHotkeySequenceOptions>;
11
12
  }
12
13
  interface HotkeysContextValue {
@@ -1 +1 @@
1
- {"version":3,"file":"hotkeys-provider.js","names":[],"sources":["../src/hotkeys-provider.ts"],"sourcesContent":["import { InjectionToken, inject } from '@angular/core'\nimport type { HotkeyRecorderOptions } from '@tanstack/hotkeys'\nimport type { InjectHotkeyOptions } from './injectHotkey'\nimport type { InjectHotkeySequenceOptions } from './injectHotkeySequence'\nimport type { StaticProvider } from '@angular/core'\n\nexport interface HotkeysProviderOptions {\n hotkey?: Partial<InjectHotkeyOptions>\n hotkeyRecorder?: Partial<HotkeyRecorderOptions>\n hotkeySequence?: Partial<InjectHotkeySequenceOptions>\n}\n\nexport interface HotkeysContextValue {\n readonly defaultOptions: HotkeysProviderOptions\n}\n\nexport const HOTKEYS_INJECTION_TOKEN = new InjectionToken<HotkeysContextValue>(\n 'HOTKEYS_INJECTION_TOKEN',\n {\n providedIn: 'root',\n factory: () => ({ defaultOptions: {} }),\n },\n)\n\nexport function provideHotkeys(\n defaultOptions: HotkeysProviderOptions,\n): StaticProvider {\n return {\n provide: HOTKEYS_INJECTION_TOKEN,\n useValue: { defaultOptions },\n }\n}\n\nexport function injectHotkeysContext(): HotkeysContextValue {\n return inject(HOTKEYS_INJECTION_TOKEN)\n}\n\nexport function injectDefaultHotkeysOptions(): HotkeysProviderOptions {\n return injectHotkeysContext().defaultOptions\n}\n"],"mappings":";;;AAgBA,MAAa,0BAA0B,IAAI,eACzC,2BACA;CACE,YAAY;CACZ,gBAAgB,EAAE,gBAAgB,EAAE,EAAE;CACvC,CACF;AAED,SAAgB,eACd,gBACgB;AAChB,QAAO;EACL,SAAS;EACT,UAAU,EAAE,gBAAgB;EAC7B;;AAGH,SAAgB,uBAA4C;AAC1D,QAAO,OAAO,wBAAwB;;AAGxC,SAAgB,8BAAsD;AACpE,QAAO,sBAAsB,CAAC"}
1
+ {"version":3,"file":"hotkeys-provider.js","names":[],"sources":["../src/hotkeys-provider.ts"],"sourcesContent":["import { InjectionToken, inject } from '@angular/core'\nimport type {\n HotkeyRecorderOptions,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\nimport type { InjectHotkeyOptions } from './injectHotkey'\nimport type { InjectHotkeySequenceOptions } from './injectHotkeySequence'\nimport type { StaticProvider } from '@angular/core'\n\nexport interface HotkeysProviderOptions {\n hotkey?: Partial<InjectHotkeyOptions>\n hotkeyRecorder?: Partial<HotkeyRecorderOptions>\n hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>\n hotkeySequence?: Partial<InjectHotkeySequenceOptions>\n}\n\nexport interface HotkeysContextValue {\n readonly defaultOptions: HotkeysProviderOptions\n}\n\nexport const HOTKEYS_INJECTION_TOKEN = new InjectionToken<HotkeysContextValue>(\n 'HOTKEYS_INJECTION_TOKEN',\n {\n providedIn: 'root',\n factory: () => ({ defaultOptions: {} }),\n },\n)\n\nexport function provideHotkeys(\n defaultOptions: HotkeysProviderOptions,\n): StaticProvider {\n return {\n provide: HOTKEYS_INJECTION_TOKEN,\n useValue: { defaultOptions },\n }\n}\n\nexport function injectHotkeysContext(): HotkeysContextValue {\n return inject(HOTKEYS_INJECTION_TOKEN)\n}\n\nexport function injectDefaultHotkeysOptions(): HotkeysProviderOptions {\n return injectHotkeysContext().defaultOptions\n}\n"],"mappings":";;;AAoBA,MAAa,0BAA0B,IAAI,eACzC,2BACA;CACE,YAAY;CACZ,gBAAgB,EAAE,gBAAgB,EAAE,EAAE;CACvC,CACF;AAED,SAAgB,eACd,gBACgB;AAChB,QAAO;EACL,SAAS;EACT,UAAU,EAAE,gBAAgB;EAC7B;;AAGH,SAAgB,uBAA4C;AAC1D,QAAO,OAAO,wBAAwB;;AAGxC,SAAgB,8BAAsD;AACpE,QAAO,sBAAsB,CAAC"}
package/dist/index.cjs CHANGED
@@ -7,6 +7,7 @@ const require_injectHeldKeys = require('./injectHeldKeys.cjs');
7
7
  const require_injectHeldKeyCodes = require('./injectHeldKeyCodes.cjs');
8
8
  const require_injectKeyHold = require('./injectKeyHold.cjs');
9
9
  const require_injectHotkeyRecorder = require('./injectHotkeyRecorder.cjs');
10
+ const require_injectHotkeySequenceRecorder = require('./injectHotkeySequenceRecorder.cjs');
10
11
 
11
12
  exports.HOTKEYS_INJECTION_TOKEN = require_hotkeys_provider.HOTKEYS_INJECTION_TOKEN;
12
13
  exports.injectDefaultHotkeysOptions = require_hotkeys_provider.injectDefaultHotkeysOptions;
@@ -15,6 +16,7 @@ exports.injectHeldKeys = require_injectHeldKeys.injectHeldKeys;
15
16
  exports.injectHotkey = require_injectHotkey.injectHotkey;
16
17
  exports.injectHotkeyRecorder = require_injectHotkeyRecorder.injectHotkeyRecorder;
17
18
  exports.injectHotkeySequence = require_injectHotkeySequence.injectHotkeySequence;
19
+ exports.injectHotkeySequenceRecorder = require_injectHotkeySequenceRecorder.injectHotkeySequenceRecorder;
18
20
  exports.injectHotkeys = require_injectHotkeys.injectHotkeys;
19
21
  exports.injectHotkeysContext = require_hotkeys_provider.injectHotkeysContext;
20
22
  exports.injectKeyHold = require_injectKeyHold.injectKeyHold;
package/dist/index.d.cts CHANGED
@@ -6,5 +6,6 @@ import { injectHeldKeys } from "./injectHeldKeys.cjs";
6
6
  import { injectHeldKeyCodes } from "./injectHeldKeyCodes.cjs";
7
7
  import { injectKeyHold } from "./injectKeyHold.cjs";
8
8
  import { AngularHotkeyRecorder, injectHotkeyRecorder } from "./injectHotkeyRecorder.cjs";
9
+ import { AngularHotkeySequenceRecorder, injectHotkeySequenceRecorder } from "./injectHotkeySequenceRecorder.cjs";
9
10
  export * from "@tanstack/hotkeys";
10
- export { AngularHotkeyRecorder, HOTKEYS_INJECTION_TOKEN, HotkeysContextValue, HotkeysProviderOptions, InjectHotkeyDefinition, InjectHotkeyOptions, InjectHotkeySequenceOptions, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
11
+ export { AngularHotkeyRecorder, AngularHotkeySequenceRecorder, HOTKEYS_INJECTION_TOKEN, HotkeysContextValue, HotkeysProviderOptions, InjectHotkeyDefinition, InjectHotkeyOptions, InjectHotkeySequenceOptions, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeySequenceRecorder, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
package/dist/index.d.ts CHANGED
@@ -6,5 +6,6 @@ import { injectHeldKeys } from "./injectHeldKeys.js";
6
6
  import { injectHeldKeyCodes } from "./injectHeldKeyCodes.js";
7
7
  import { injectKeyHold } from "./injectKeyHold.js";
8
8
  import { AngularHotkeyRecorder, injectHotkeyRecorder } from "./injectHotkeyRecorder.js";
9
+ import { AngularHotkeySequenceRecorder, injectHotkeySequenceRecorder } from "./injectHotkeySequenceRecorder.js";
9
10
  export * from "@tanstack/hotkeys";
10
- export { AngularHotkeyRecorder, HOTKEYS_INJECTION_TOKEN, HotkeysContextValue, HotkeysProviderOptions, InjectHotkeyDefinition, InjectHotkeyOptions, InjectHotkeySequenceOptions, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
11
+ export { AngularHotkeyRecorder, AngularHotkeySequenceRecorder, HOTKEYS_INJECTION_TOKEN, HotkeysContextValue, HotkeysProviderOptions, InjectHotkeyDefinition, InjectHotkeyOptions, InjectHotkeySequenceOptions, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeySequenceRecorder, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
package/dist/index.js CHANGED
@@ -6,7 +6,8 @@ import { injectHeldKeys } from "./injectHeldKeys.js";
6
6
  import { injectHeldKeyCodes } from "./injectHeldKeyCodes.js";
7
7
  import { injectKeyHold } from "./injectKeyHold.js";
8
8
  import { injectHotkeyRecorder } from "./injectHotkeyRecorder.js";
9
+ import { injectHotkeySequenceRecorder } from "./injectHotkeySequenceRecorder.js";
9
10
 
10
11
  export * from "@tanstack/hotkeys"
11
12
 
12
- export { HOTKEYS_INJECTION_TOKEN, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
13
+ export { HOTKEYS_INJECTION_TOKEN, injectDefaultHotkeysOptions, injectHeldKeyCodes, injectHeldKeys, injectHotkey, injectHotkeyRecorder, injectHotkeySequence, injectHotkeySequenceRecorder, injectHotkeys, injectHotkeysContext, injectKeyHold, provideHotkeys };
@@ -0,0 +1,58 @@
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/injectHotkeySequenceRecorder.ts
6
+ /**
7
+ * Angular inject-based API for recording multi-chord sequences.
8
+ */
9
+ function injectHotkeySequenceRecorder(options) {
10
+ const defaultOptions = require_hotkeys_provider.injectDefaultHotkeysOptions();
11
+ const destroyRef = (0, _angular_core.inject)(_angular_core.DestroyRef);
12
+ const recorderSignal = (0, _angular_core.computed)(() => (0, _angular_core.untracked)(() => {
13
+ const resolvedOptions = typeof options === "function" ? options() : options;
14
+ return new _tanstack_hotkeys.HotkeySequenceRecorder({
15
+ ...defaultOptions.hotkeySequenceRecorder,
16
+ ...resolvedOptions
17
+ });
18
+ }));
19
+ const recorderStore = (0, _angular_core.computed)(() => (0, _angular_core.untracked)(() => recorderSignal().store));
20
+ const isRecording = injectLazyStore(recorderStore, (state) => state.isRecording);
21
+ const steps = injectLazyStore(recorderStore, (state) => state.steps);
22
+ const recordedSequence = injectLazyStore(recorderStore, (state) => state.recordedSequence);
23
+ (0, _angular_core.effect)(() => {
24
+ const resolved = typeof options === "function" ? options() : options;
25
+ recorderSignal().setOptions({
26
+ ...defaultOptions.hotkeySequenceRecorder,
27
+ ...resolved
28
+ });
29
+ });
30
+ destroyRef.onDestroy(() => {
31
+ recorderSignal().destroy();
32
+ });
33
+ return {
34
+ isRecording,
35
+ steps,
36
+ recordedSequence,
37
+ startRecording: () => recorderSignal().start(),
38
+ stopRecording: () => recorderSignal().stop(),
39
+ cancelRecording: () => recorderSignal().cancel(),
40
+ commitRecording: () => recorderSignal().commit()
41
+ };
42
+ }
43
+ function injectLazyStore(storeSignal, selector) {
44
+ const slice = (0, _angular_core.linkedSignal)(() => selector(storeSignal().get()));
45
+ (0, _angular_core.effect)((onCleanup) => {
46
+ const currentStore = storeSignal();
47
+ slice.set(selector(currentStore.get()));
48
+ const { unsubscribe } = currentStore.subscribe((s) => {
49
+ slice.set(selector(s));
50
+ });
51
+ onCleanup(() => unsubscribe());
52
+ });
53
+ return slice.asReadonly();
54
+ }
55
+
56
+ //#endregion
57
+ exports.injectHotkeySequenceRecorder = injectHotkeySequenceRecorder;
58
+ //# sourceMappingURL=injectHotkeySequenceRecorder.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injectHotkeySequenceRecorder.cjs","names":["injectDefaultHotkeysOptions","DestroyRef","HotkeySequenceRecorder"],"sources":["../src/injectHotkeySequenceRecorder.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n linkedSignal,\n untracked,\n} from '@angular/core'\nimport { HotkeySequenceRecorder } from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type { Atom, ReadonlyAtom } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\nimport type {\n HotkeySequence,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\n\nexport interface AngularHotkeySequenceRecorder {\n readonly isRecording: () => boolean\n readonly steps: () => HotkeySequence\n readonly recordedSequence: () => HotkeySequence | null\n readonly startRecording: () => void\n readonly stopRecording: () => void\n readonly cancelRecording: () => void\n readonly commitRecording: () => void\n}\n\n/**\n * Angular inject-based API for recording multi-chord sequences.\n */\nexport function injectHotkeySequenceRecorder(\n options:\n | HotkeySequenceRecorderOptions\n | (() => HotkeySequenceRecorderOptions),\n): AngularHotkeySequenceRecorder {\n const defaultOptions = injectDefaultHotkeysOptions()\n const destroyRef = inject(DestroyRef)\n\n const recorderSignal = computed(() =>\n untracked(() => {\n const resolvedOptions =\n typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolvedOptions,\n } as HotkeySequenceRecorderOptions\n\n return new HotkeySequenceRecorder(mergedOptions)\n }),\n )\n\n const recorderStore = computed(() => untracked(() => recorderSignal().store))\n const isRecording = injectLazyStore(\n recorderStore,\n (state) => state.isRecording,\n )\n const steps = injectLazyStore(recorderStore, (state) => state.steps)\n const recordedSequence = injectLazyStore(\n recorderStore,\n (state) => state.recordedSequence,\n )\n\n effect(() => {\n const resolved = typeof options === 'function' ? options() : options\n recorderSignal().setOptions({\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolved,\n } as HotkeySequenceRecorderOptions)\n })\n\n destroyRef.onDestroy(() => {\n recorderSignal().destroy()\n })\n\n return {\n isRecording,\n steps,\n recordedSequence,\n startRecording: () => recorderSignal().start(),\n stopRecording: () => recorderSignal().stop(),\n cancelRecording: () => recorderSignal().cancel(),\n commitRecording: () => recorderSignal().commit(),\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":";;;;;;;;AA8BA,SAAgB,6BACd,SAG+B;CAC/B,MAAM,iBAAiBA,sDAA6B;CACpD,MAAM,uCAAoBC,yBAAW;CAErC,MAAM,sFACY;EACd,MAAM,kBACJ,OAAO,YAAY,aAAa,SAAS,GAAG;AAO9C,SAAO,IAAIC,yCALW;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ,CAE+C;GAChD,CACH;CAED,MAAM,qFAA+C,gBAAgB,CAAC,MAAM,CAAC;CAC7E,MAAM,cAAc,gBAClB,gBACC,UAAU,MAAM,YAClB;CACD,MAAM,QAAQ,gBAAgB,gBAAgB,UAAU,MAAM,MAAM;CACpE,MAAM,mBAAmB,gBACvB,gBACC,UAAU,MAAM,iBAClB;AAED,iCAAa;EACX,MAAM,WAAW,OAAO,YAAY,aAAa,SAAS,GAAG;AAC7D,kBAAgB,CAAC,WAAW;GAC1B,GAAG,eAAe;GAClB,GAAG;GACJ,CAAkC;GACnC;AAEF,YAAW,gBAAgB;AACzB,kBAAgB,CAAC,SAAS;GAC1B;AAEF,QAAO;EACL;EACA;EACA;EACA,sBAAsB,gBAAgB,CAAC,OAAO;EAC9C,qBAAqB,gBAAgB,CAAC,MAAM;EAC5C,uBAAuB,gBAAgB,CAAC,QAAQ;EAChD,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"}
@@ -0,0 +1,19 @@
1
+ import { HotkeySequence, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
2
+
3
+ //#region src/injectHotkeySequenceRecorder.d.ts
4
+ interface AngularHotkeySequenceRecorder {
5
+ readonly isRecording: () => boolean;
6
+ readonly steps: () => HotkeySequence;
7
+ readonly recordedSequence: () => HotkeySequence | null;
8
+ readonly startRecording: () => void;
9
+ readonly stopRecording: () => void;
10
+ readonly cancelRecording: () => void;
11
+ readonly commitRecording: () => void;
12
+ }
13
+ /**
14
+ * Angular inject-based API for recording multi-chord sequences.
15
+ */
16
+ declare function injectHotkeySequenceRecorder(options: HotkeySequenceRecorderOptions | (() => HotkeySequenceRecorderOptions)): AngularHotkeySequenceRecorder;
17
+ //#endregion
18
+ export { AngularHotkeySequenceRecorder, injectHotkeySequenceRecorder };
19
+ //# sourceMappingURL=injectHotkeySequenceRecorder.d.cts.map
@@ -0,0 +1,19 @@
1
+ import { HotkeySequence, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
2
+
3
+ //#region src/injectHotkeySequenceRecorder.d.ts
4
+ interface AngularHotkeySequenceRecorder {
5
+ readonly isRecording: () => boolean;
6
+ readonly steps: () => HotkeySequence;
7
+ readonly recordedSequence: () => HotkeySequence | null;
8
+ readonly startRecording: () => void;
9
+ readonly stopRecording: () => void;
10
+ readonly cancelRecording: () => void;
11
+ readonly commitRecording: () => void;
12
+ }
13
+ /**
14
+ * Angular inject-based API for recording multi-chord sequences.
15
+ */
16
+ declare function injectHotkeySequenceRecorder(options: HotkeySequenceRecorderOptions | (() => HotkeySequenceRecorderOptions)): AngularHotkeySequenceRecorder;
17
+ //#endregion
18
+ export { AngularHotkeySequenceRecorder, injectHotkeySequenceRecorder };
19
+ //# sourceMappingURL=injectHotkeySequenceRecorder.d.ts.map
@@ -0,0 +1,58 @@
1
+ import { injectDefaultHotkeysOptions } from "./hotkeys-provider.js";
2
+ import { HotkeySequenceRecorder } from "@tanstack/hotkeys";
3
+ import { DestroyRef, computed, effect, inject, linkedSignal, untracked } from "@angular/core";
4
+
5
+ //#region src/injectHotkeySequenceRecorder.ts
6
+ /**
7
+ * Angular inject-based API for recording multi-chord sequences.
8
+ */
9
+ function injectHotkeySequenceRecorder(options) {
10
+ const defaultOptions = injectDefaultHotkeysOptions();
11
+ const destroyRef = inject(DestroyRef);
12
+ const recorderSignal = computed(() => untracked(() => {
13
+ const resolvedOptions = typeof options === "function" ? options() : options;
14
+ return new HotkeySequenceRecorder({
15
+ ...defaultOptions.hotkeySequenceRecorder,
16
+ ...resolvedOptions
17
+ });
18
+ }));
19
+ const recorderStore = computed(() => untracked(() => recorderSignal().store));
20
+ const isRecording = injectLazyStore(recorderStore, (state) => state.isRecording);
21
+ const steps = injectLazyStore(recorderStore, (state) => state.steps);
22
+ const recordedSequence = injectLazyStore(recorderStore, (state) => state.recordedSequence);
23
+ effect(() => {
24
+ const resolved = typeof options === "function" ? options() : options;
25
+ recorderSignal().setOptions({
26
+ ...defaultOptions.hotkeySequenceRecorder,
27
+ ...resolved
28
+ });
29
+ });
30
+ destroyRef.onDestroy(() => {
31
+ recorderSignal().destroy();
32
+ });
33
+ return {
34
+ isRecording,
35
+ steps,
36
+ recordedSequence,
37
+ startRecording: () => recorderSignal().start(),
38
+ stopRecording: () => recorderSignal().stop(),
39
+ cancelRecording: () => recorderSignal().cancel(),
40
+ commitRecording: () => recorderSignal().commit()
41
+ };
42
+ }
43
+ function injectLazyStore(storeSignal, selector) {
44
+ const slice = linkedSignal(() => selector(storeSignal().get()));
45
+ effect((onCleanup) => {
46
+ const currentStore = storeSignal();
47
+ slice.set(selector(currentStore.get()));
48
+ const { unsubscribe } = currentStore.subscribe((s) => {
49
+ slice.set(selector(s));
50
+ });
51
+ onCleanup(() => unsubscribe());
52
+ });
53
+ return slice.asReadonly();
54
+ }
55
+
56
+ //#endregion
57
+ export { injectHotkeySequenceRecorder };
58
+ //# sourceMappingURL=injectHotkeySequenceRecorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injectHotkeySequenceRecorder.js","names":[],"sources":["../src/injectHotkeySequenceRecorder.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n linkedSignal,\n untracked,\n} from '@angular/core'\nimport { HotkeySequenceRecorder } from '@tanstack/hotkeys'\nimport { injectDefaultHotkeysOptions } from './hotkeys-provider'\nimport type { Atom, ReadonlyAtom } from '@tanstack/angular-store'\nimport type { Signal } from '@angular/core'\nimport type {\n HotkeySequence,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\n\nexport interface AngularHotkeySequenceRecorder {\n readonly isRecording: () => boolean\n readonly steps: () => HotkeySequence\n readonly recordedSequence: () => HotkeySequence | null\n readonly startRecording: () => void\n readonly stopRecording: () => void\n readonly cancelRecording: () => void\n readonly commitRecording: () => void\n}\n\n/**\n * Angular inject-based API for recording multi-chord sequences.\n */\nexport function injectHotkeySequenceRecorder(\n options:\n | HotkeySequenceRecorderOptions\n | (() => HotkeySequenceRecorderOptions),\n): AngularHotkeySequenceRecorder {\n const defaultOptions = injectDefaultHotkeysOptions()\n const destroyRef = inject(DestroyRef)\n\n const recorderSignal = computed(() =>\n untracked(() => {\n const resolvedOptions =\n typeof options === 'function' ? options() : options\n\n const mergedOptions = {\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolvedOptions,\n } as HotkeySequenceRecorderOptions\n\n return new HotkeySequenceRecorder(mergedOptions)\n }),\n )\n\n const recorderStore = computed(() => untracked(() => recorderSignal().store))\n const isRecording = injectLazyStore(\n recorderStore,\n (state) => state.isRecording,\n )\n const steps = injectLazyStore(recorderStore, (state) => state.steps)\n const recordedSequence = injectLazyStore(\n recorderStore,\n (state) => state.recordedSequence,\n )\n\n effect(() => {\n const resolved = typeof options === 'function' ? options() : options\n recorderSignal().setOptions({\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolved,\n } as HotkeySequenceRecorderOptions)\n })\n\n destroyRef.onDestroy(() => {\n recorderSignal().destroy()\n })\n\n return {\n isRecording,\n steps,\n recordedSequence,\n startRecording: () => recorderSignal().start(),\n stopRecording: () => recorderSignal().stop(),\n cancelRecording: () => recorderSignal().cancel(),\n commitRecording: () => recorderSignal().commit(),\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":";;;;;;;;AA8BA,SAAgB,6BACd,SAG+B;CAC/B,MAAM,iBAAiB,6BAA6B;CACpD,MAAM,aAAa,OAAO,WAAW;CAErC,MAAM,iBAAiB,eACrB,gBAAgB;EACd,MAAM,kBACJ,OAAO,YAAY,aAAa,SAAS,GAAG;AAO9C,SAAO,IAAI,uBALW;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ,CAE+C;GAChD,CACH;CAED,MAAM,gBAAgB,eAAe,gBAAgB,gBAAgB,CAAC,MAAM,CAAC;CAC7E,MAAM,cAAc,gBAClB,gBACC,UAAU,MAAM,YAClB;CACD,MAAM,QAAQ,gBAAgB,gBAAgB,UAAU,MAAM,MAAM;CACpE,MAAM,mBAAmB,gBACvB,gBACC,UAAU,MAAM,iBAClB;AAED,cAAa;EACX,MAAM,WAAW,OAAO,YAAY,aAAa,SAAS,GAAG;AAC7D,kBAAgB,CAAC,WAAW;GAC1B,GAAG,eAAe;GAClB,GAAG;GACJ,CAAkC;GACnC;AAEF,YAAW,gBAAgB;AACzB,kBAAgB,CAAC,SAAS;GAC1B;AAEF,QAAO;EACL;EACA;EACA;EACA,sBAAsB,gBAAgB,CAAC,OAAO;EAC9C,qBAAqB,gBAAgB,CAAC,MAAM;EAC5C,uBAAuB,gBAAgB,CAAC,QAAQ;EAChD,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/angular-hotkeys",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Angular adapter for TanStack Hotkeys",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "@tanstack/angular-store": "^0.9.2",
45
- "@tanstack/hotkeys": "0.4.3"
45
+ "@tanstack/hotkeys": "0.5.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@angular/common": ">=19.0.0",
@@ -1,5 +1,8 @@
1
1
  import { InjectionToken, inject } from '@angular/core'
2
- import type { HotkeyRecorderOptions } from '@tanstack/hotkeys'
2
+ import type {
3
+ HotkeyRecorderOptions,
4
+ HotkeySequenceRecorderOptions,
5
+ } from '@tanstack/hotkeys'
3
6
  import type { InjectHotkeyOptions } from './injectHotkey'
4
7
  import type { InjectHotkeySequenceOptions } from './injectHotkeySequence'
5
8
  import type { StaticProvider } from '@angular/core'
@@ -7,6 +10,7 @@ import type { StaticProvider } from '@angular/core'
7
10
  export interface HotkeysProviderOptions {
8
11
  hotkey?: Partial<InjectHotkeyOptions>
9
12
  hotkeyRecorder?: Partial<HotkeyRecorderOptions>
13
+ hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>
10
14
  hotkeySequence?: Partial<InjectHotkeySequenceOptions>
11
15
  }
12
16
 
package/src/index.ts CHANGED
@@ -12,3 +12,4 @@ export * from './injectHeldKeys'
12
12
  export * from './injectHeldKeyCodes'
13
13
  export * from './injectKeyHold'
14
14
  export * from './injectHotkeyRecorder'
15
+ export * from './injectHotkeySequenceRecorder'
@@ -0,0 +1,103 @@
1
+ import {
2
+ DestroyRef,
3
+ computed,
4
+ effect,
5
+ inject,
6
+ linkedSignal,
7
+ untracked,
8
+ } from '@angular/core'
9
+ import { HotkeySequenceRecorder } from '@tanstack/hotkeys'
10
+ import { injectDefaultHotkeysOptions } from './hotkeys-provider'
11
+ import type { Atom, ReadonlyAtom } from '@tanstack/angular-store'
12
+ import type { Signal } from '@angular/core'
13
+ import type {
14
+ HotkeySequence,
15
+ HotkeySequenceRecorderOptions,
16
+ } from '@tanstack/hotkeys'
17
+
18
+ export interface AngularHotkeySequenceRecorder {
19
+ readonly isRecording: () => boolean
20
+ readonly steps: () => HotkeySequence
21
+ readonly recordedSequence: () => HotkeySequence | null
22
+ readonly startRecording: () => void
23
+ readonly stopRecording: () => void
24
+ readonly cancelRecording: () => void
25
+ readonly commitRecording: () => void
26
+ }
27
+
28
+ /**
29
+ * Angular inject-based API for recording multi-chord sequences.
30
+ */
31
+ export function injectHotkeySequenceRecorder(
32
+ options:
33
+ | HotkeySequenceRecorderOptions
34
+ | (() => HotkeySequenceRecorderOptions),
35
+ ): AngularHotkeySequenceRecorder {
36
+ const defaultOptions = injectDefaultHotkeysOptions()
37
+ const destroyRef = inject(DestroyRef)
38
+
39
+ const recorderSignal = computed(() =>
40
+ untracked(() => {
41
+ const resolvedOptions =
42
+ typeof options === 'function' ? options() : options
43
+
44
+ const mergedOptions = {
45
+ ...defaultOptions.hotkeySequenceRecorder,
46
+ ...resolvedOptions,
47
+ } as HotkeySequenceRecorderOptions
48
+
49
+ return new HotkeySequenceRecorder(mergedOptions)
50
+ }),
51
+ )
52
+
53
+ const recorderStore = computed(() => untracked(() => recorderSignal().store))
54
+ const isRecording = injectLazyStore(
55
+ recorderStore,
56
+ (state) => state.isRecording,
57
+ )
58
+ const steps = injectLazyStore(recorderStore, (state) => state.steps)
59
+ const recordedSequence = injectLazyStore(
60
+ recorderStore,
61
+ (state) => state.recordedSequence,
62
+ )
63
+
64
+ effect(() => {
65
+ const resolved = typeof options === 'function' ? options() : options
66
+ recorderSignal().setOptions({
67
+ ...defaultOptions.hotkeySequenceRecorder,
68
+ ...resolved,
69
+ } as HotkeySequenceRecorderOptions)
70
+ })
71
+
72
+ destroyRef.onDestroy(() => {
73
+ recorderSignal().destroy()
74
+ })
75
+
76
+ return {
77
+ isRecording,
78
+ steps,
79
+ recordedSequence,
80
+ startRecording: () => recorderSignal().start(),
81
+ stopRecording: () => recorderSignal().stop(),
82
+ cancelRecording: () => recorderSignal().cancel(),
83
+ commitRecording: () => recorderSignal().commit(),
84
+ }
85
+ }
86
+
87
+ function injectLazyStore<TState, TSelected = NoInfer<TState>>(
88
+ storeSignal: Signal<Atom<TState> | ReadonlyAtom<TState>>,
89
+ selector: (state: NoInfer<TState>) => TSelected,
90
+ ): Signal<TSelected> {
91
+ const slice = linkedSignal(() => selector(storeSignal().get()))
92
+
93
+ effect((onCleanup) => {
94
+ const currentStore = storeSignal()
95
+ slice.set(selector(currentStore.get()))
96
+ const { unsubscribe } = currentStore.subscribe((s) => {
97
+ slice.set(selector(s))
98
+ })
99
+ onCleanup(() => unsubscribe())
100
+ })
101
+
102
+ return slice.asReadonly()
103
+ }