@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.
- package/dist/hotkeys-provider.cjs.map +1 -1
- package/dist/hotkeys-provider.d.cts +2 -1
- package/dist/hotkeys-provider.d.ts +2 -1
- package/dist/hotkeys-provider.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/injectHotkeySequenceRecorder.cjs +58 -0
- package/dist/injectHotkeySequenceRecorder.cjs.map +1 -0
- package/dist/injectHotkeySequenceRecorder.d.cts +19 -0
- package/dist/injectHotkeySequenceRecorder.d.ts +19 -0
- package/dist/injectHotkeySequenceRecorder.js +58 -0
- package/dist/injectHotkeySequenceRecorder.js.map +1 -0
- package/package.json +2 -2
- package/src/hotkeys-provider.ts +5 -1
- package/src/index.ts +1 -0
- package/src/injectHotkeySequenceRecorder.ts +103 -0
|
@@ -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 {
|
|
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 {
|
|
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.
|
|
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.
|
|
45
|
+
"@tanstack/hotkeys": "0.5.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@angular/common": ">=19.0.0",
|
package/src/hotkeys-provider.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { InjectionToken, inject } from '@angular/core'
|
|
2
|
-
import type {
|
|
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
|
@@ -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
|
+
}
|