@tanstack/vue-hotkeys 0.12.1 → 0.14.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/README.md CHANGED
@@ -67,6 +67,9 @@ Type-safe keyboard shortcuts for the web. Template-string bindings, parsed objec
67
67
  > [!NOTE]
68
68
  > You may know **TanStack Hotkeys** by our adapter names, too!
69
69
  >
70
+ > - [**Alpine Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/alpine/quick-start)
71
+ > - [**Ember Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/ember/quick-start)
72
+ > - [**Octane Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/octane/quick-start)
70
73
  > - [**React Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/react/react-hotkeys)
71
74
  > - [**Preact Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/preact/preact-hotkeys)
72
75
  > - [**Solid Hotkeys**](https://tanstack.com/hotkeys/latest/docs/framework/solid/reference)
@@ -1,12 +1,20 @@
1
1
  import { HotkeysProviderOptions } from "./HotkeysProviderContext.js";
2
+ import { AppHotkeys, CustomHotkeys } from "@tanstack/hotkeys";
3
+ import { PropType } from "vue";
2
4
  //#region src/HotkeysProvider.d.ts
3
5
  /**
4
- * Vue component that provides default options for hotkeys context.
6
+ * Vue component that provides default options, app hotkeys, and the user's
7
+ * custom hotkeys. `customHotkeys` is read once; listen to
8
+ * `custom-hotkeys-change` to save changes.
5
9
  *
6
10
  * @example
7
11
  * ```vue
8
12
  * <template>
9
- * <HotkeysProvider :defaultOptions="{ hotkey: { enabled: true } }">
13
+ * <HotkeysProvider
14
+ * :app-hotkeys="appHotkeys"
15
+ * :custom-hotkeys="saved"
16
+ * @custom-hotkeys-change="save"
17
+ * >
10
18
  * <App />
11
19
  * </HotkeysProvider>
12
20
  * </template>
@@ -14,17 +22,39 @@ import { HotkeysProviderOptions } from "./HotkeysProviderContext.js";
14
22
  */
15
23
  export declare const HotkeysProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
16
24
  defaultOptions: {
17
- type: () => HotkeysProviderOptions;
25
+ type: PropType<HotkeysProviderOptions>;
26
+ default: undefined;
27
+ };
28
+ appHotkeys: {
29
+ type: PropType<AppHotkeys>;
30
+ default: undefined;
31
+ };
32
+ customHotkeys: {
33
+ type: PropType<CustomHotkeys | null>;
18
34
  default: undefined;
19
35
  };
20
36
  }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
21
37
  [key: string]: any;
22
- }>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
38
+ }>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
39
+ customHotkeysChange: (_customHotkeys: CustomHotkeys) => true;
40
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
23
41
  defaultOptions: {
24
- type: () => HotkeysProviderOptions;
42
+ type: PropType<HotkeysProviderOptions>;
43
+ default: undefined;
44
+ };
45
+ appHotkeys: {
46
+ type: PropType<AppHotkeys>;
47
+ default: undefined;
48
+ };
49
+ customHotkeys: {
50
+ type: PropType<CustomHotkeys | null>;
25
51
  default: undefined;
26
52
  };
27
- }>> & Readonly<{}>, {
53
+ }>> & Readonly<{
54
+ onCustomHotkeysChange?: ((_customHotkeys: CustomHotkeys<Readonly<Record<string, import("@tanstack/hotkeys").AppHotkey<string, import("@tanstack/hotkeys").HotkeyChord | import("@tanstack/hotkeys").HotkeySequence | null>>>>) => any) | undefined;
55
+ }>, {
28
56
  defaultOptions: HotkeysProviderOptions;
57
+ appHotkeys: Readonly<Record<string, import("@tanstack/hotkeys").AppHotkey<string, import("@tanstack/hotkeys").HotkeyChord | import("@tanstack/hotkeys").HotkeySequence | null>>>;
58
+ customHotkeys: CustomHotkeys<Readonly<Record<string, import("@tanstack/hotkeys").AppHotkey<string, import("@tanstack/hotkeys").HotkeyChord | import("@tanstack/hotkeys").HotkeySequence | null>>>> | null;
29
59
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
30
60
  //#endregion
@@ -3,12 +3,18 @@ import { defineComponent } from "vue";
3
3
 
4
4
  //#region src/HotkeysProvider.tsx
5
5
  /**
6
- * Vue component that provides default options for hotkeys context.
6
+ * Vue component that provides default options, app hotkeys, and the user's
7
+ * custom hotkeys. `customHotkeys` is read once; listen to
8
+ * `custom-hotkeys-change` to save changes.
7
9
  *
8
10
  * @example
9
11
  * ```vue
10
12
  * <template>
11
- * <HotkeysProvider :defaultOptions="{ hotkey: { enabled: true } }">
13
+ * <HotkeysProvider
14
+ * :app-hotkeys="appHotkeys"
15
+ * :custom-hotkeys="saved"
16
+ * @custom-hotkeys-change="save"
17
+ * >
12
18
  * <App />
13
19
  * </HotkeysProvider>
14
20
  * </template>
@@ -16,12 +22,28 @@ import { defineComponent } from "vue";
16
22
  */
17
23
  const HotkeysProvider = defineComponent({
18
24
  name: "HotkeysProvider",
19
- props: { defaultOptions: {
20
- type: Object,
21
- default: void 0
22
- } },
23
- setup(props, { slots }) {
24
- provideHotkeysContext(props.defaultOptions);
25
+ props: {
26
+ defaultOptions: {
27
+ type: Object,
28
+ default: void 0
29
+ },
30
+ appHotkeys: {
31
+ type: Object,
32
+ default: void 0
33
+ },
34
+ customHotkeys: {
35
+ type: Object,
36
+ default: void 0
37
+ }
38
+ },
39
+ emits: { customHotkeysChange: (_customHotkeys) => true },
40
+ setup(props, { slots, emit }) {
41
+ provideHotkeysContext({
42
+ defaultOptions: () => props.defaultOptions,
43
+ appHotkeys: () => props.appHotkeys,
44
+ customHotkeys: props.customHotkeys,
45
+ onCustomHotkeysChange: (custom) => emit("customHotkeysChange", custom)
46
+ });
25
47
  return () => slots.default?.();
26
48
  }
27
49
  });
@@ -1,17 +1,52 @@
1
- import { UseHotkeyOptions } from "./useHotkey.js";
2
- import { UseHotkeySequenceOptions } from "./useHotkeySequence.js";
3
- import { HotkeyRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
1
+ import { UseHotkeyCommonOptions } from "./useHotkey.js";
2
+ import { AppHotkeys, AppHotkeysStore, CustomHotkeys, HotkeyChordRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
3
+ import { MaybeRefOrGetter } from "vue";
4
4
  //#region src/HotkeysProviderContext.d.ts
5
5
  export interface HotkeysProviderOptions {
6
- hotkey?: Partial<UseHotkeyOptions>;
7
- hotkeyRecorder?: Partial<HotkeyRecorderOptions>;
8
- hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>;
9
- hotkeySequence?: Partial<UseHotkeySequenceOptions>;
6
+ /**
7
+ * Defaults for every hotkey registered by `useHotkey` and `useHotkeys`.
8
+ * `requireReset` applies to chords and `timeout` applies to sequences.
9
+ */
10
+ hotkey?: UseHotkeyCommonOptions;
11
+ /** Defaults for every `useHotkeyRecorder`. */
12
+ hotkeyRecorder?: Partial<Omit<HotkeyChordRecorderOptions & HotkeySequenceRecorderOptions, 'maxSteps' | 'onRecord' | 'validate'>>;
10
13
  }
11
14
  interface HotkeysContextValue {
12
- defaultOptions: HotkeysProviderOptions;
15
+ readonly appHotkeysStore: AppHotkeysStore | null;
16
+ readonly defaultOptions: HotkeysProviderOptions;
13
17
  }
14
- export declare function provideHotkeysContext(defaultOptions?: HotkeysProviderOptions): void;
18
+ /** Options for `provideHotkeysContext`. */
19
+ export interface ProvideHotkeysContextOptions {
20
+ defaultOptions?: MaybeRefOrGetter<HotkeysProviderOptions | undefined>;
21
+ /**
22
+ * Every app hotkey, from `defineAppHotkeys`. Read when the context is
23
+ * provided; later changes update the declarations.
24
+ */
25
+ appHotkeys?: MaybeRefOrGetter<AppHotkeys | undefined>;
26
+ /**
27
+ * Starting custom hotkeys, such as saved data. Read once; the context owns
28
+ * the state afterwards. Invalid entries are ignored with a warning.
29
+ */
30
+ customHotkeys?: CustomHotkeys | null;
31
+ /** Called with the custom hotkeys after every change, ready to save. */
32
+ onCustomHotkeysChange?: (customHotkeys: CustomHotkeys) => void;
33
+ }
34
+ /**
35
+ * Provides default options, app hotkeys, and the user's custom hotkeys to
36
+ * descendants. `HotkeysProvider` calls this; call it directly in a root
37
+ * component's setup instead of rendering the provider.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * provideHotkeysContext({
42
+ * appHotkeys,
43
+ * customHotkeys: JSON.parse(localStorage.getItem('hotkeys') ?? '{}'),
44
+ * onCustomHotkeysChange: (custom) =>
45
+ * localStorage.setItem('hotkeys', JSON.stringify(custom)),
46
+ * })
47
+ * ```
48
+ */
49
+ export declare function provideHotkeysContext(options?: ProvideHotkeysContextOptions): void;
15
50
  export declare function useHotkeysContext(): HotkeysContextValue | null;
16
51
  export declare function useDefaultHotkeysOptions(): HotkeysProviderOptions;
17
52
  //#endregion
@@ -1,16 +1,48 @@
1
- import { inject, provide } from "vue";
1
+ import { AppHotkeysStore, publishAppHotkeysStore } from "@tanstack/hotkeys";
2
+ import { inject, onScopeDispose, provide, toValue, watch } from "vue";
2
3
 
3
4
  //#region src/HotkeysProviderContext.ts
4
5
  const HotkeysContext = Symbol("HotkeysContext");
5
6
  const DEFAULT_OPTIONS = {};
6
- function provideHotkeysContext(defaultOptions) {
7
- provide(HotkeysContext, { defaultOptions: defaultOptions ?? DEFAULT_OPTIONS });
7
+ /**
8
+ * Provides default options, app hotkeys, and the user's custom hotkeys to
9
+ * descendants. `HotkeysProvider` calls this; call it directly in a root
10
+ * component's setup instead of rendering the provider.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * provideHotkeysContext({
15
+ * appHotkeys,
16
+ * customHotkeys: JSON.parse(localStorage.getItem('hotkeys') ?? '{}'),
17
+ * onCustomHotkeysChange: (custom) =>
18
+ * localStorage.setItem('hotkeys', JSON.stringify(custom)),
19
+ * })
20
+ * ```
21
+ */
22
+ function provideHotkeysContext(options = {}) {
23
+ const appHotkeys = toValue(options.appHotkeys);
24
+ const store = appHotkeys ? new AppHotkeysStore(appHotkeys, {
25
+ customHotkeys: options.customHotkeys,
26
+ onCustomHotkeysChange: (custom) => options.onCustomHotkeysChange?.(custom)
27
+ }) : null;
28
+ if (store) {
29
+ watch(() => toValue(options.appHotkeys), (next) => {
30
+ if (next) store.setAppHotkeys(next);
31
+ });
32
+ if (typeof document !== "undefined") onScopeDispose(publishAppHotkeysStore(store));
33
+ }
34
+ provide(HotkeysContext, {
35
+ appHotkeysStore: store,
36
+ get defaultOptions() {
37
+ return toValue(options.defaultOptions) ?? DEFAULT_OPTIONS;
38
+ }
39
+ });
8
40
  }
9
41
  function useHotkeysContext() {
10
42
  return inject(HotkeysContext, null);
11
43
  }
12
44
  function useDefaultHotkeysOptions() {
13
- return inject(HotkeysContext, null)?.defaultOptions ?? {};
45
+ return inject(HotkeysContext, null)?.defaultOptions ?? DEFAULT_OPTIONS;
14
46
  }
15
47
 
16
48
  //#endregion
@@ -0,0 +1,24 @@
1
+ import { useHotkeysContext } from "./HotkeysProviderContext.js";
2
+ import { Store, useSelector } from "@tanstack/vue-store";
3
+
4
+ //#region src/defaultOptions.ts
5
+ /** Captures the context once and reads current defaults inside reactive computations. */
6
+ function useDefaultHotkeysOptionsSource() {
7
+ const context = useHotkeysContext();
8
+ return () => context?.defaultOptions ?? {};
9
+ }
10
+ const NO_APP_HOTKEYS = new Store(null);
11
+ /**
12
+ * The provider's app hotkeys store and a ref that tracks its state, so
13
+ * watchers re-run when app hotkeys or custom hotkeys change.
14
+ */
15
+ function useAppHotkeysStoreSource() {
16
+ const store = useHotkeysContext()?.appHotkeysStore ?? null;
17
+ return {
18
+ store,
19
+ state: useSelector(store?.store ?? NO_APP_HOTKEYS, (value) => value)
20
+ };
21
+ }
22
+
23
+ //#endregion
24
+ export { useAppHotkeysStoreSource, useDefaultHotkeysOptionsSource };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,13 @@
1
- import { UseHotkeyOptions, useHotkey } from "./useHotkey.js";
2
- import { UseHotkeySequenceOptions, useHotkeySequence } from "./useHotkeySequence.js";
3
- import { HotkeysProviderOptions, provideHotkeysContext, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProviderContext.js";
1
+ import { UseAppHotkeyOptions, UseHotkeyChordOptions, UseHotkeyCommonOptions, UseHotkeyOptions, UseHotkeyOptionsFor, UseHotkeySequenceOptions, UseHotkeyTarget, useHotkey } from "./useHotkey.js";
2
+ import { HotkeysProviderOptions, ProvideHotkeysContextOptions, provideHotkeysContext, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProviderContext.js";
4
3
  import { HotkeysProvider } from "./HotkeysProvider.js";
5
4
  import { UseHotkeyDefinition, useHotkeys } from "./useHotkeys.js";
6
5
  import { useHeldKeys } from "./useHeldKeys.js";
7
6
  import { useHeldKeyCodes } from "./useHeldKeyCodes.js";
8
7
  import { useKeyHold } from "./useKeyHold.js";
9
- import { UseHotkeySequenceDefinition, useHotkeySequences } from "./useHotkeySequences.js";
10
8
  import { VueHotkeyRecorder, useHotkeyRecorder } from "./useHotkeyRecorder.js";
11
- import { HotkeyRegistrationsResult, useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
12
- import { VueHotkeySequenceRecorder, useHotkeySequenceRecorder } from "./useHotkeySequenceRecorder.js";
9
+ import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
13
10
  import { useHotkeyHint } from "./useHotkeyHint.js";
11
+ import { UseCustomHotkeysResult, useAppHotkeyList, useAppHotkeys, useCustomHotkeys } from "./useAppHotkeys.js";
14
12
  export * from "@tanstack/hotkeys";
15
- export { HotkeyRegistrationsResult, HotkeysProvider, HotkeysProviderOptions, UseHotkeyDefinition, UseHotkeyOptions, UseHotkeySequenceDefinition, UseHotkeySequenceOptions, VueHotkeyRecorder, VueHotkeySequenceRecorder, provideHotkeysContext, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeySequence, useHotkeySequenceRecorder, useHotkeySequences, useHotkeys, useHotkeysContext, useKeyHold };
13
+ export { HotkeysProvider, HotkeysProviderOptions, ProvideHotkeysContextOptions, UseAppHotkeyOptions, UseCustomHotkeysResult, UseHotkeyChordOptions, UseHotkeyCommonOptions, UseHotkeyDefinition, UseHotkeyOptions, UseHotkeyOptionsFor, UseHotkeySequenceOptions, UseHotkeyTarget, VueHotkeyRecorder, provideHotkeysContext, useAppHotkeyList, useAppHotkeys, useCustomHotkeys, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeys, useHotkeysContext, useKeyHold };
package/dist/index.js CHANGED
@@ -1,17 +1,15 @@
1
1
  import { provideHotkeysContext, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProviderContext.js";
2
2
  import { HotkeysProvider } from "./HotkeysProvider.js";
3
- import { useHotkey } from "./useHotkey.js";
4
3
  import { useHotkeys } from "./useHotkeys.js";
4
+ import { useHotkey } from "./useHotkey.js";
5
5
  import { useHeldKeys } from "./useHeldKeys.js";
6
6
  import { useHeldKeyCodes } from "./useHeldKeyCodes.js";
7
7
  import { useKeyHold } from "./useKeyHold.js";
8
- import { useHotkeySequence } from "./useHotkeySequence.js";
9
- import { useHotkeySequences } from "./useHotkeySequences.js";
10
8
  import { useHotkeyRecorder } from "./useHotkeyRecorder.js";
11
9
  import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
12
- import { useHotkeySequenceRecorder } from "./useHotkeySequenceRecorder.js";
13
10
  import { useHotkeyHint } from "./useHotkeyHint.js";
11
+ import { useAppHotkeyList, useAppHotkeys, useCustomHotkeys } from "./useAppHotkeys.js";
14
12
 
15
13
  export * from "@tanstack/hotkeys"
16
14
 
17
- export { HotkeysProvider, provideHotkeysContext, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeySequence, useHotkeySequenceRecorder, useHotkeySequences, useHotkeys, useHotkeysContext, useKeyHold };
15
+ export { HotkeysProvider, provideHotkeysContext, useAppHotkeyList, useAppHotkeys, useCustomHotkeys, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeys, useHotkeysContext, useKeyHold };
@@ -0,0 +1,43 @@
1
+ import { AppHotkey, AppHotkeyListItem, CustomHotkeys, Hotkey, RegisteredAppHotkeys } from "@tanstack/hotkeys";
2
+ import { ComputedRef } from "vue";
3
+ //#region src/useAppHotkeys.d.ts
4
+ /**
5
+ * Returns a computed ref of the effective app hotkeys from `HotkeysProvider`,
6
+ * typed by `Register`: each declaration with the user's custom hotkey applied.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const hotkeys = useAppHotkeys()
11
+ * useHotkey(() => hotkeys.value['doc.save'], () => save())
12
+ * ```
13
+ */
14
+ export declare function useAppHotkeys(): ComputedRef<RegisteredAppHotkeys>;
15
+ /**
16
+ * Lists every app hotkey with its live status, in declaration order, for
17
+ * cheat sheets and settings screens. App hotkeys whose components have not
18
+ * mounted are `'inactive'`; those without a hotkey are `'unbound'`.
19
+ */
20
+ export declare function useAppHotkeyList(): ComputedRef<Array<AppHotkeyListItem<RegisteredAppHotkeys[keyof RegisteredAppHotkeys]>>>;
21
+ /** Custom hotkey state and actions returned by `useCustomHotkeys`. */
22
+ export interface UseCustomHotkeysResult {
23
+ /** The user's hotkeys that differ from the defaults. */
24
+ customHotkeys: ComputedRef<CustomHotkeys>;
25
+ /**
26
+ * Sets the user's hotkey for an app hotkey. `null` unbinds it.
27
+ * Returns conflicting app hotkeys; when any exist, nothing changes.
28
+ */
29
+ setCustomHotkey: (id: keyof RegisteredAppHotkeys & string, hotkey: Hotkey | null) => Array<AppHotkey>;
30
+ /** Restores the default hotkey for an app hotkey. */
31
+ resetCustomHotkey: (id: keyof RegisteredAppHotkeys & string) => void;
32
+ /** Restores every default hotkey. */
33
+ resetCustomHotkeys: () => void;
34
+ /** Other app hotkeys that would collide if `id` used `hotkey`. */
35
+ findConflicts: (id: keyof RegisteredAppHotkeys & string, hotkey: Hotkey) => Array<AppHotkey>;
36
+ }
37
+ /**
38
+ * Reads and changes the user's custom hotkeys. Changes apply to every
39
+ * registered app hotkey immediately and are emitted by the provider as
40
+ * `custom-hotkeys-change`, ready to save.
41
+ */
42
+ export declare function useCustomHotkeys(): UseCustomHotkeysResult;
43
+ //#endregion
@@ -0,0 +1,64 @@
1
+ import { useAppHotkeysStoreSource } from "./defaultOptions.js";
2
+ import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
3
+ import { computed } from "vue";
4
+
5
+ //#region src/useAppHotkeys.ts
6
+ function useRequiredStore(name) {
7
+ const source = useAppHotkeysStoreSource();
8
+ if (!source.store) throw new Error(`${name} requires a HotkeysProvider with app hotkeys`);
9
+ return {
10
+ store: source.store,
11
+ state: source.state
12
+ };
13
+ }
14
+ /**
15
+ * Returns a computed ref of the effective app hotkeys from `HotkeysProvider`,
16
+ * typed by `Register`: each declaration with the user's custom hotkey applied.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const hotkeys = useAppHotkeys()
21
+ * useHotkey(() => hotkeys.value['doc.save'], () => save())
22
+ * ```
23
+ */
24
+ function useAppHotkeys() {
25
+ const { store, state } = useRequiredStore("useAppHotkeys");
26
+ return computed(() => {
27
+ state.value;
28
+ return store.appHotkeys;
29
+ });
30
+ }
31
+ /**
32
+ * Lists every app hotkey with its live status, in declaration order, for
33
+ * cheat sheets and settings screens. App hotkeys whose components have not
34
+ * mounted are `'inactive'`; those without a hotkey are `'unbound'`.
35
+ */
36
+ function useAppHotkeyList() {
37
+ const { store, state } = useRequiredStore("useAppHotkeyList");
38
+ const registrations = useHotkeyRegistrations();
39
+ return computed(() => {
40
+ state.value;
41
+ return store.getList(registrations.value);
42
+ });
43
+ }
44
+ /**
45
+ * Reads and changes the user's custom hotkeys. Changes apply to every
46
+ * registered app hotkey immediately and are emitted by the provider as
47
+ * `custom-hotkeys-change`, ready to save.
48
+ */
49
+ function useCustomHotkeys() {
50
+ const { store, state } = useRequiredStore("useCustomHotkeys");
51
+ return {
52
+ customHotkeys: computed(() => {
53
+ state.value;
54
+ return store.customHotkeys;
55
+ }),
56
+ setCustomHotkey: (id, hotkey) => store.setCustomHotkey(id, hotkey),
57
+ resetCustomHotkey: (id) => store.resetCustomHotkey(id),
58
+ resetCustomHotkeys: () => store.resetCustomHotkeys(),
59
+ findConflicts: (id, hotkey) => store.findConflicts(id, hotkey)
60
+ };
61
+ }
62
+
63
+ //#endregion
64
+ export { useAppHotkeyList, useAppHotkeys, useCustomHotkeys };
@@ -1,83 +1,46 @@
1
- import { HotkeyCallback, HotkeyOptions, RegisterableHotkey } from "@tanstack/hotkeys";
1
+ import { AppHotkey, HotkeyCallback, RegisterableHotkey, Target } from "@tanstack/hotkeys";
2
2
  import { MaybeRefOrGetter } from "vue";
3
+ import { AdapterAppHotkeyOptions, AdapterChordOptions, AdapterCommonOptions, AdapterHotkeyOptions, AdapterOptionsFor, AdapterSequenceOptions } from "@tanstack/hotkeys/adapter";
3
4
  //#region src/useHotkey.d.ts
4
- export interface UseHotkeyOptions extends Omit<HotkeyOptions, 'enabled' | 'target'> {
5
- /**
6
- * Whether the hotkey is active.
7
- * Can be a Ref, a getter function, or a boolean value.
8
- * Defaults to true.
9
- */
5
+ /**
6
+ * The element to listen on: a ref, getter, element, or null. A target that
7
+ * resolves to `null` skips registration until it is set. Defaults to document.
8
+ */
9
+ export type UseHotkeyTarget = MaybeRefOrGetter<Target | null>;
10
+ /** Lets `enabled` be a ref or getter. */
11
+ type WithReactiveEnabled<TOptions> = Omit<TOptions, 'enabled'> & {
12
+ /** Whether the hotkey is active. Can be a ref, getter, or boolean. Defaults to true. */
10
13
  enabled?: MaybeRefOrGetter<boolean>;
11
- /**
12
- * The DOM element to attach the event listener to.
13
- * Can be a Ref, a getter function, direct DOM element, or null.
14
- * Defaults to document.
15
- */
16
- target?: MaybeRefOrGetter<HTMLElement | Document | Window | null>;
17
- }
14
+ };
15
+ /** Options shared by chords and sequences. */
16
+ export type UseHotkeyOptions = WithReactiveEnabled<AdapterHotkeyOptions<UseHotkeyTarget>>;
17
+ /** Options for a chord such as `'Mod+S'`. */
18
+ export type UseHotkeyChordOptions = WithReactiveEnabled<AdapterChordOptions<UseHotkeyTarget>>;
19
+ /** Options for a sequence such as `['G', 'G']`. */
20
+ export type UseHotkeySequenceOptions = WithReactiveEnabled<AdapterSequenceOptions<UseHotkeyTarget>>;
21
+ /** Options applied to every hotkey, such as provider defaults. Each applies to the kinds that support it. */
22
+ export type UseHotkeyCommonOptions = WithReactiveEnabled<AdapterCommonOptions<UseHotkeyTarget>>;
23
+ /** The options type for a hotkey: chord options for chords, sequence options for sequences. */
24
+ export type UseHotkeyOptionsFor<T extends RegisterableHotkey> = WithReactiveEnabled<AdapterOptionsFor<T, UseHotkeyTarget>>;
25
+ /** Call-site options for an app hotkey, typed by its declared default kind. */
26
+ export type UseAppHotkeyOptions<T extends AppHotkey = AppHotkey> = WithReactiveEnabled<AdapterAppHotkeyOptions<T, UseHotkeyTarget>>;
18
27
  /**
19
- * Vue composable for registering a keyboard hotkey.
20
- *
21
- * Uses the singleton HotkeyManager for efficient event handling.
22
- * The callback receives both the keyboard event and a context object
23
- * containing the hotkey string and parsed hotkey.
24
- *
25
- * This composable automatically tracks reactive dependencies and updates
26
- * the registration when options or the callback change.
27
- *
28
- * @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)
29
- * @param callback - The function to call when the hotkey is pressed
30
- * @param options - Options for the hotkey behavior
28
+ * Vue composable for registering a hotkey: a chord such as `'Mod+S'`, a
29
+ * sequence such as `['G', 'G']`, or an app hotkey from `defineAppHotkeys`.
30
+ * The hotkey and options may be refs or getters.
31
31
  *
32
- * @example
33
- * ```vue
34
- * <script setup>
35
- * import { ref } from 'vue'
36
- * import { useHotkey } from '@tanstack/vue-hotkeys'
37
- *
38
- * const count = ref(0)
39
- *
40
- * // Callback always has access to latest count value
41
- * useHotkey('Mod+S', (event, { hotkey }) => {
42
- * console.log(`Save triggered, count is ${count.value}`)
43
- * handleSave()
44
- * })
45
- * </script>
46
- * ```
32
+ * Chords accept `requireReset`; sequences accept `timeout`. A one-step
33
+ * sequence registers as its chord. An app hotkey uses its effective hotkey
34
+ * from `HotkeysProvider` (including the user's custom hotkey) and its
35
+ * declared meta and options, and registers nothing while unbound.
47
36
  *
48
37
  * @example
49
- * ```vue
50
- * <script setup>
51
- * import { ref } from 'vue'
52
- * import { useHotkey } from '@tanstack/vue-hotkeys'
53
- *
54
- * const isOpen = ref(false)
55
- *
56
- * // enabled option is reactive
57
- * useHotkey('Escape', () => {
58
- * isOpen.value = false
59
- * }, { enabled: isOpen })
60
- * </script>
61
- * ```
62
- *
63
- * @example
64
- * ```vue
65
- * <script setup>
66
- * import { ref } from 'vue'
67
- * import { useHotkey } from '@tanstack/vue-hotkeys'
68
- *
69
- * const editorRef = ref<HTMLDivElement | null>(null)
70
- *
71
- * // Scoped to a specific element
72
- * useHotkey('Mod+S', () => {
73
- * save()
74
- * }, { target: editorRef })
75
- * </script>
76
- *
77
- * <template>
78
- * <div ref="editorRef">...</div>
79
- * </template>
38
+ * ```ts
39
+ * useHotkey('Mod+S', () => save())
40
+ * useHotkey(['G', 'G'], () => scrollToTop(), { timeout: 500 })
41
+ * useHotkey('Escape', () => close(), { enabled: isOpen })
80
42
  * ```
81
43
  */
82
- export declare function useHotkey(hotkey: MaybeRefOrGetter<RegisterableHotkey>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseHotkeyOptions>): void;
44
+ export declare function useHotkey<T extends AppHotkey>(hotkey: MaybeRefOrGetter<T>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseAppHotkeyOptions<T>>): void;
45
+ export declare function useHotkey<T extends RegisterableHotkey>(hotkey: MaybeRefOrGetter<T>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseHotkeyOptionsFor<T>>): void;
83
46
  //#endregion