@tanstack/vue-hotkeys 0.13.0 → 0.14.1
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/HotkeysProvider.d.ts +36 -6
- package/dist/HotkeysProvider.js +30 -8
- package/dist/HotkeysProviderContext.d.ts +43 -9
- package/dist/HotkeysProviderContext.js +36 -6
- package/dist/defaultOptions.js +14 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.js +3 -5
- package/dist/useAppHotkeys.d.ts +43 -0
- package/dist/useAppHotkeys.js +64 -0
- package/dist/useHotkey.d.ts +36 -73
- package/dist/useHotkey.js +6 -133
- package/dist/useHotkeyHint.d.ts +6 -6
- package/dist/useHotkeyHint.js +13 -6
- package/dist/useHotkeyRecorder.d.ts +25 -44
- package/dist/useHotkeyRecorder.js +12 -57
- package/dist/useHotkeyRegistrations.d.ts +18 -17
- package/dist/useHotkeyRegistrations.js +18 -13
- package/dist/useHotkeys.d.ts +33 -44
- package/dist/useHotkeys.js +36 -118
- package/package.json +2 -2
- package/dist/useHotkeySequence.d.ts +0 -65
- package/dist/useHotkeySequence.js +0 -121
- package/dist/useHotkeySequenceRecorder.d.ts +0 -17
- package/dist/useHotkeySequenceRecorder.js +0 -44
- package/dist/useHotkeySequences.d.ts +0 -61
- package/dist/useHotkeySequences.js +0 -139
package/dist/useHotkey.js
CHANGED
|
@@ -1,139 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { detectPlatform, getHotkeyManager, normalizeRegisterableHotkey } from "@tanstack/hotkeys";
|
|
3
|
-
import { onUnmounted, unref, watch } from "vue";
|
|
1
|
+
import { useHotkeys } from "./useHotkeys.js";
|
|
4
2
|
|
|
5
3
|
//#region src/useHotkey.ts
|
|
6
|
-
/**
|
|
7
|
-
* Vue composable for registering a keyboard hotkey.
|
|
8
|
-
*
|
|
9
|
-
* Uses the singleton HotkeyManager for efficient event handling.
|
|
10
|
-
* The callback receives both the keyboard event and a context object
|
|
11
|
-
* containing the hotkey string and parsed hotkey.
|
|
12
|
-
*
|
|
13
|
-
* This composable automatically tracks reactive dependencies and updates
|
|
14
|
-
* the registration when options or the callback change.
|
|
15
|
-
*
|
|
16
|
-
* @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)
|
|
17
|
-
* @param callback - The function to call when the hotkey is pressed
|
|
18
|
-
* @param options - Options for the hotkey behavior
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```vue
|
|
22
|
-
* <script setup>
|
|
23
|
-
* import { ref } from 'vue'
|
|
24
|
-
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
25
|
-
*
|
|
26
|
-
* const count = ref(0)
|
|
27
|
-
*
|
|
28
|
-
* // Callback always has access to latest count value
|
|
29
|
-
* useHotkey('Mod+S', (event, { hotkey }) => {
|
|
30
|
-
* console.log(`Save triggered, count is ${count.value}`)
|
|
31
|
-
* handleSave()
|
|
32
|
-
* })
|
|
33
|
-
* <\/script>
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```vue
|
|
38
|
-
* <script setup>
|
|
39
|
-
* import { ref } from 'vue'
|
|
40
|
-
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
41
|
-
*
|
|
42
|
-
* const isOpen = ref(false)
|
|
43
|
-
*
|
|
44
|
-
* // enabled option is reactive
|
|
45
|
-
* useHotkey('Escape', () => {
|
|
46
|
-
* isOpen.value = false
|
|
47
|
-
* }, { enabled: isOpen })
|
|
48
|
-
* <\/script>
|
|
49
|
-
* ```
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```vue
|
|
53
|
-
* <script setup>
|
|
54
|
-
* import { ref } from 'vue'
|
|
55
|
-
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
56
|
-
*
|
|
57
|
-
* const editorRef = ref<HTMLDivElement | null>(null)
|
|
58
|
-
*
|
|
59
|
-
* // Scoped to a specific element
|
|
60
|
-
* useHotkey('Mod+S', () => {
|
|
61
|
-
* save()
|
|
62
|
-
* }, { target: editorRef })
|
|
63
|
-
* <\/script>
|
|
64
|
-
*
|
|
65
|
-
* <template>
|
|
66
|
-
* <div ref="editorRef">...</div>
|
|
67
|
-
* </template>
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
4
|
function useHotkey(hotkey, callback, options = {}) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const stopWatcher = watch(() => {
|
|
77
|
-
const resolvedHotkey = resolveMaybeRefOrGetter(hotkey);
|
|
78
|
-
const resolvedOptions = resolveMaybeRefOrGetter(options);
|
|
79
|
-
const mergedOptions = {
|
|
80
|
-
...defaultOptions().hotkey,
|
|
81
|
-
...resolvedOptions
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
resolvedHotkey,
|
|
85
|
-
mergedOptions,
|
|
86
|
-
resolvedEnabled: mergedOptions.enabled === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.enabled),
|
|
87
|
-
resolvedTarget: mergedOptions.target === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.target)
|
|
88
|
-
};
|
|
89
|
-
}, ({ resolvedHotkey, mergedOptions, resolvedEnabled, resolvedTarget }) => {
|
|
90
|
-
const platform = mergedOptions.platform ?? detectPlatform();
|
|
91
|
-
const hotkeyString = normalizeRegisterableHotkey(resolvedHotkey, platform);
|
|
92
|
-
const finalTarget = resolvedTarget === void 0 ? typeof document !== "undefined" ? document : null : resolvedTarget;
|
|
93
|
-
if (!finalTarget) {
|
|
94
|
-
if (registration?.isActive) {
|
|
95
|
-
registration.unregister();
|
|
96
|
-
registration = null;
|
|
97
|
-
}
|
|
98
|
-
lastHotkeyString = null;
|
|
99
|
-
lastTarget = null;
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const { target: _target, enabled: _enabled, ...restOptions } = mergedOptions;
|
|
103
|
-
const optionsWithoutTarget = {
|
|
104
|
-
...restOptions,
|
|
105
|
-
...resolvedEnabled === void 0 ? {} : { enabled: resolvedEnabled }
|
|
106
|
-
};
|
|
107
|
-
if (registration?.isActive && lastHotkeyString === hotkeyString && lastTarget === finalTarget) {
|
|
108
|
-
registration.callback = callback;
|
|
109
|
-
registration.setOptions(optionsWithoutTarget);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (registration?.isActive) {
|
|
113
|
-
registration.unregister();
|
|
114
|
-
registration = null;
|
|
115
|
-
}
|
|
116
|
-
registration = manager.register(hotkeyString, callback, {
|
|
117
|
-
...optionsWithoutTarget,
|
|
118
|
-
target: finalTarget
|
|
119
|
-
});
|
|
120
|
-
if (registration.isActive) {
|
|
121
|
-
registration.callback = callback;
|
|
122
|
-
registration.setOptions(optionsWithoutTarget);
|
|
123
|
-
}
|
|
124
|
-
lastHotkeyString = hotkeyString;
|
|
125
|
-
lastTarget = finalTarget;
|
|
126
|
-
}, { immediate: true });
|
|
127
|
-
onUnmounted(() => {
|
|
128
|
-
stopWatcher();
|
|
129
|
-
if (registration?.isActive) {
|
|
130
|
-
registration.unregister();
|
|
131
|
-
registration = null;
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
function resolveMaybeRefOrGetter(value) {
|
|
136
|
-
return typeof value === "function" ? value() : unref(value);
|
|
5
|
+
useHotkeys([{
|
|
6
|
+
hotkey,
|
|
7
|
+
callback,
|
|
8
|
+
options
|
|
9
|
+
}]);
|
|
137
10
|
}
|
|
138
11
|
|
|
139
12
|
//#endregion
|
package/dist/useHotkeyHint.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { HeldModifierOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
1
|
+
import { AppHotkey, HeldModifierOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
2
|
import { ComputedRef, MaybeRefOrGetter } from "vue";
|
|
3
3
|
//#region src/useHotkeyHint.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Returns a computed ref indicating whether held modifiers reveal this shortcut.
|
|
6
|
-
* Pass refs or getters to track changing
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Pass refs or getters to track changing hotkeys and options. A sequence
|
|
7
|
+
* reveals its hint from its first step, and an app hotkey uses its effective
|
|
8
|
+
* hotkey (false while unbound). This helper does not register a shortcut or
|
|
9
|
+
* check whether its target is focused.
|
|
10
10
|
*/
|
|
11
|
-
export declare function useHotkeyHint(hotkey: MaybeRefOrGetter<RegisterableHotkey>, options?: MaybeRefOrGetter<HeldModifierOptions>): ComputedRef<boolean>;
|
|
11
|
+
export declare function useHotkeyHint(hotkey: MaybeRefOrGetter<RegisterableHotkey | AppHotkey>, options?: MaybeRefOrGetter<HeldModifierOptions>): ComputedRef<boolean>;
|
|
12
12
|
//#endregion
|
package/dist/useHotkeyHint.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useAppHotkeysStoreSource } from "./defaultOptions.js";
|
|
2
|
+
import { getKeyStateTracker, isAppHotkey, matchesHeldModifiers, resolveAppHotkey } from "@tanstack/hotkeys";
|
|
2
3
|
import { computed, toValue } from "vue";
|
|
3
4
|
import { useSelector } from "@tanstack/vue-store";
|
|
4
5
|
|
|
5
6
|
//#region src/useHotkeyHint.ts
|
|
6
7
|
/**
|
|
7
8
|
* Returns a computed ref indicating whether held modifiers reveal this shortcut.
|
|
8
|
-
* Pass refs or getters to track changing
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Pass refs or getters to track changing hotkeys and options. A sequence
|
|
10
|
+
* reveals its hint from its first step, and an app hotkey uses its effective
|
|
11
|
+
* hotkey (false while unbound). This helper does not register a shortcut or
|
|
12
|
+
* check whether its target is focused.
|
|
12
13
|
*/
|
|
13
14
|
function useHotkeyHint(hotkey, options = {}) {
|
|
15
|
+
const appHotkeys = useAppHotkeysStoreSource();
|
|
14
16
|
const held = useSelector(getKeyStateTracker().store, (state) => state.heldKeys);
|
|
15
|
-
return computed(() =>
|
|
17
|
+
return computed(() => {
|
|
18
|
+
appHotkeys.state.value;
|
|
19
|
+
const value = toValue(hotkey);
|
|
20
|
+
const resolved = isAppHotkey(value) ? resolveAppHotkey(value, appHotkeys.store).hotkey : value;
|
|
21
|
+
return resolved !== null && matchesHeldModifiers(resolved, held.value, toValue(options));
|
|
22
|
+
});
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
//#endregion
|
|
@@ -1,58 +1,39 @@
|
|
|
1
|
-
import { Hotkey, HotkeyRecorderOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import {
|
|
1
|
+
import { Hotkey, HotkeyChord, HotkeyChordRecorderOptions, HotkeyRecorderOptions, HotkeySequence, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
2
|
+
import { Ref } from "vue";
|
|
3
3
|
//#region src/useHotkeyRecorder.d.ts
|
|
4
|
-
export interface VueHotkeyRecorder {
|
|
4
|
+
export interface VueHotkeyRecorder<THotkey extends Hotkey = Hotkey> {
|
|
5
5
|
/** Whether recording is currently active */
|
|
6
|
-
isRecording: Ref<boolean
|
|
7
|
-
/**
|
|
8
|
-
|
|
6
|
+
isRecording: Readonly<Ref<boolean>>;
|
|
7
|
+
/** Chords recorded so far in a multi-step recording (for live preview) */
|
|
8
|
+
steps: Readonly<Ref<HotkeySequence>>;
|
|
9
|
+
/** The last committed hotkey */
|
|
10
|
+
recordedHotkey: Readonly<Ref<THotkey | null>>;
|
|
9
11
|
/** Start recording a new hotkey */
|
|
10
12
|
startRecording: () => void;
|
|
11
|
-
/** Stop recording
|
|
13
|
+
/** Stop recording without calling onCancel */
|
|
12
14
|
stopRecording: () => void;
|
|
13
|
-
/** Cancel recording
|
|
15
|
+
/** Cancel recording and call onCancel */
|
|
14
16
|
cancelRecording: () => void;
|
|
17
|
+
/** Commit the recorded steps now (multi-step recordings) */
|
|
18
|
+
commitRecording: () => void;
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
|
-
* Vue composable for recording keyboard shortcuts.
|
|
21
|
+
* Vue composable for recording keyboard shortcuts. Options may be a ref or getter.
|
|
18
22
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @param options - Configuration options for the recorder
|
|
25
|
-
* @returns An object with recording state and control functions
|
|
23
|
+
* With the default `maxSteps: 1`, the first valid chord is recorded. With a
|
|
24
|
+
* larger `maxSteps`, each chord adds a step; the recording commits on Enter
|
|
25
|
+
* (unless `commitKeys: 'none'`), after `idleTimeoutMs`, or at `maxSteps`, and
|
|
26
|
+
* `onRecord` receives a chord (one step) or a sequence.
|
|
26
27
|
*
|
|
27
28
|
* @example
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* import { useHotkeyRecorder } from '@tanstack/vue-hotkeys'
|
|
32
|
-
*
|
|
33
|
-
* const shortcut = ref<Hotkey>('Mod+S')
|
|
34
|
-
*
|
|
35
|
-
* const recorder = useHotkeyRecorder({
|
|
36
|
-
* onRecord: (hotkey) => {
|
|
37
|
-
* shortcut.value = hotkey
|
|
38
|
-
* },
|
|
39
|
-
* onCancel: () => {
|
|
40
|
-
* console.log('Recording cancelled')
|
|
41
|
-
* },
|
|
42
|
-
* })
|
|
43
|
-
* </script>
|
|
44
|
-
*
|
|
45
|
-
* <template>
|
|
46
|
-
* <div>
|
|
47
|
-
* <button @click="recorder.startRecording()">
|
|
48
|
-
* {{ recorder.isRecording ? 'Recording...' : 'Edit Shortcut' }}
|
|
49
|
-
* </button>
|
|
50
|
-
* <div v-if="recorder.recordedHotkey">
|
|
51
|
-
* Recording: {{ recorder.recordedHotkey }}
|
|
52
|
-
* </div>
|
|
53
|
-
* </div>
|
|
54
|
-
* </template>
|
|
29
|
+
* ```ts
|
|
30
|
+
* const recorder = useHotkeyRecorder({ onRecord: (hotkey) => (shortcut.value = hotkey) })
|
|
31
|
+
* const sequenceRecorder = useHotkeyRecorder({ maxSteps: 3, onRecord: save })
|
|
55
32
|
* ```
|
|
56
33
|
*/
|
|
57
|
-
export declare function useHotkeyRecorder(options:
|
|
34
|
+
export declare function useHotkeyRecorder(options: HotkeyChordRecorderOptions): VueHotkeyRecorder<HotkeyChord>;
|
|
35
|
+
export declare function useHotkeyRecorder(options: HotkeySequenceRecorderOptions): VueHotkeyRecorder;
|
|
36
|
+
export declare function useHotkeyRecorder(options: () => HotkeySequenceRecorderOptions): VueHotkeyRecorder;
|
|
37
|
+
export declare function useHotkeyRecorder(options: () => HotkeyChordRecorderOptions): VueHotkeyRecorder<HotkeyChord>;
|
|
38
|
+
export declare function useHotkeyRecorder(options: Ref<HotkeyRecorderOptions>): VueHotkeyRecorder;
|
|
58
39
|
//#endregion
|
|
@@ -1,79 +1,34 @@
|
|
|
1
1
|
import { useDefaultHotkeysOptionsSource } from "./defaultOptions.js";
|
|
2
2
|
import { HotkeyRecorder } from "@tanstack/hotkeys";
|
|
3
|
-
import {
|
|
3
|
+
import { onScopeDispose, toValue, watch } from "vue";
|
|
4
4
|
import { useSelector } from "@tanstack/vue-store";
|
|
5
5
|
|
|
6
6
|
//#region src/useHotkeyRecorder.ts
|
|
7
|
-
/**
|
|
8
|
-
* Vue composable for recording keyboard shortcuts.
|
|
9
|
-
*
|
|
10
|
-
* This composable provides a thin wrapper around the framework-agnostic `HotkeyRecorder`
|
|
11
|
-
* class, managing all the complexity of capturing keyboard events, converting them
|
|
12
|
-
* to hotkey strings, and handling edge cases like Escape to cancel or Backspace/Delete
|
|
13
|
-
* to clear.
|
|
14
|
-
*
|
|
15
|
-
* @param options - Configuration options for the recorder
|
|
16
|
-
* @returns An object with recording state and control functions
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```vue
|
|
20
|
-
* <script setup>
|
|
21
|
-
* import { ref } from 'vue'
|
|
22
|
-
* import { useHotkeyRecorder } from '@tanstack/vue-hotkeys'
|
|
23
|
-
*
|
|
24
|
-
* const shortcut = ref<Hotkey>('Mod+S')
|
|
25
|
-
*
|
|
26
|
-
* const recorder = useHotkeyRecorder({
|
|
27
|
-
* onRecord: (hotkey) => {
|
|
28
|
-
* shortcut.value = hotkey
|
|
29
|
-
* },
|
|
30
|
-
* onCancel: () => {
|
|
31
|
-
* console.log('Recording cancelled')
|
|
32
|
-
* },
|
|
33
|
-
* })
|
|
34
|
-
* <\/script>
|
|
35
|
-
*
|
|
36
|
-
* <template>
|
|
37
|
-
* <div>
|
|
38
|
-
* <button @click="recorder.startRecording()">
|
|
39
|
-
* {{ recorder.isRecording ? 'Recording...' : 'Edit Shortcut' }}
|
|
40
|
-
* </button>
|
|
41
|
-
* <div v-if="recorder.recordedHotkey">
|
|
42
|
-
* Recording: {{ recorder.recordedHotkey }}
|
|
43
|
-
* </div>
|
|
44
|
-
* </div>
|
|
45
|
-
* </template>
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
7
|
function useHotkeyRecorder(options) {
|
|
49
8
|
const defaultOptions = useDefaultHotkeysOptionsSource();
|
|
50
|
-
const
|
|
9
|
+
const resolve = () => ({
|
|
10
|
+
...defaultOptions().hotkeyRecorder,
|
|
11
|
+
...toValue(options)
|
|
12
|
+
});
|
|
13
|
+
const recorder = new HotkeyRecorder(resolve());
|
|
51
14
|
const isRecording = useSelector(recorder.store, (state) => state.isRecording);
|
|
15
|
+
const steps = useSelector(recorder.store, (state) => state.steps);
|
|
52
16
|
const recordedHotkey = useSelector(recorder.store, (state) => state.recordedHotkey);
|
|
53
|
-
const stopWatcher = watch(() =>
|
|
54
|
-
|
|
55
|
-
}, { immediate: true });
|
|
56
|
-
onUnmounted(() => {
|
|
17
|
+
const stopWatcher = watch(resolve, (resolved) => recorder.setOptions(resolved));
|
|
18
|
+
onScopeDispose(() => {
|
|
57
19
|
stopWatcher();
|
|
58
20
|
recorder.destroy();
|
|
59
21
|
});
|
|
60
22
|
return {
|
|
61
23
|
isRecording,
|
|
24
|
+
steps,
|
|
62
25
|
recordedHotkey,
|
|
63
26
|
startRecording: () => recorder.start(),
|
|
64
27
|
stopRecording: () => recorder.stop(),
|
|
65
|
-
cancelRecording: () => recorder.cancel()
|
|
28
|
+
cancelRecording: () => recorder.cancel(),
|
|
29
|
+
commitRecording: () => recorder.commit()
|
|
66
30
|
};
|
|
67
31
|
}
|
|
68
|
-
function resolveRecorderOptions(options, defaultOptions) {
|
|
69
|
-
return {
|
|
70
|
-
...defaultOptions().hotkeyRecorder,
|
|
71
|
-
...resolveMaybeRefOrGetter(options)
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function resolveMaybeRefOrGetter(value) {
|
|
75
|
-
return typeof value === "function" ? value() : unref(value);
|
|
76
|
-
}
|
|
77
32
|
|
|
78
33
|
//#endregion
|
|
79
34
|
export { useHotkeyRecorder };
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { HotkeyRegistrationView
|
|
1
|
+
import { HotkeyRegistrationView } from "@tanstack/hotkeys";
|
|
2
2
|
import { Ref } from "vue";
|
|
3
3
|
//#region src/useHotkeyRegistrations.d.ts
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
hotkeys: Ref<Array<HotkeyRegistrationView>>;
|
|
10
|
-
/** All registered sequences */
|
|
11
|
-
sequences: Ref<Array<SequenceRegistrationView>>;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Vue composable that reactively reads all hotkey and sequence registrations
|
|
15
|
-
* from the singleton managers.
|
|
5
|
+
* Vue composable that reactively reads every hotkey registration, chords and
|
|
6
|
+
* sequences, from the singleton HotkeyManager. Narrow each view with `kind`.
|
|
7
|
+
*
|
|
8
|
+
* This composable does NOT require the HotkeysProvider.
|
|
16
9
|
*
|
|
17
|
-
*
|
|
18
|
-
* It subscribes to both HotkeyManager and SequenceManager stores and
|
|
19
|
-
* triggers reactivity when registrations change.
|
|
10
|
+
* @returns A ref of all registrations, without callbacks
|
|
20
11
|
*
|
|
21
|
-
* @
|
|
12
|
+
* @example
|
|
13
|
+
* ```vue
|
|
14
|
+
* <script setup>
|
|
15
|
+
* const registrations = useHotkeyRegistrations()
|
|
16
|
+
* </script>
|
|
17
|
+
* <template>
|
|
18
|
+
* <li v-for="reg in registrations" :key="reg.id">
|
|
19
|
+
* {{ reg.options.meta?.name }}: {{ formatForDisplay(reg.hotkey) }}
|
|
20
|
+
* </li>
|
|
21
|
+
* </template>
|
|
22
|
+
* ```
|
|
22
23
|
*/
|
|
23
|
-
export declare function useHotkeyRegistrations():
|
|
24
|
+
export declare function useHotkeyRegistrations(): Readonly<Ref<Array<HotkeyRegistrationView>>>;
|
|
24
25
|
//#endregion
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import { getHotkeyManager,
|
|
1
|
+
import { getHotkeyManager, toHotkeyRegistrationView } from "@tanstack/hotkeys";
|
|
2
2
|
import { useSelector } from "@tanstack/vue-store";
|
|
3
3
|
|
|
4
4
|
//#region src/useHotkeyRegistrations.ts
|
|
5
5
|
/**
|
|
6
|
-
* Vue composable that reactively reads
|
|
7
|
-
* from the singleton
|
|
6
|
+
* Vue composable that reactively reads every hotkey registration, chords and
|
|
7
|
+
* sequences, from the singleton HotkeyManager. Narrow each view with `kind`.
|
|
8
8
|
*
|
|
9
|
-
* This
|
|
10
|
-
* It subscribes to both HotkeyManager and SequenceManager stores and
|
|
11
|
-
* triggers reactivity when registrations change.
|
|
9
|
+
* This composable does NOT require the HotkeysProvider.
|
|
12
10
|
*
|
|
13
|
-
* @returns
|
|
11
|
+
* @returns A ref of all registrations, without callbacks
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```vue
|
|
15
|
+
* <script setup>
|
|
16
|
+
* const registrations = useHotkeyRegistrations()
|
|
17
|
+
* <\/script>
|
|
18
|
+
* <template>
|
|
19
|
+
* <li v-for="reg in registrations" :key="reg.id">
|
|
20
|
+
* {{ reg.options.meta?.name }}: {{ formatForDisplay(reg.hotkey) }}
|
|
21
|
+
* </li>
|
|
22
|
+
* </template>
|
|
23
|
+
* ```
|
|
14
24
|
*/
|
|
15
25
|
function useHotkeyRegistrations() {
|
|
16
|
-
|
|
17
|
-
const sequenceManager = getSequenceManager();
|
|
18
|
-
return {
|
|
19
|
-
hotkeys: useSelector(hotkeyManager.registrations, (state) => Array.from(state.values()).map(toHotkeyRegistrationView)),
|
|
20
|
-
sequences: useSelector(sequenceManager.registrations, (state) => Array.from(state.values()))
|
|
21
|
-
};
|
|
26
|
+
return useSelector(getHotkeyManager().registrations, (state) => Array.from(state.values()).map(toHotkeyRegistrationView));
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
//#endregion
|
package/dist/useHotkeys.d.ts
CHANGED
|
@@ -1,62 +1,51 @@
|
|
|
1
|
-
import { UseHotkeyOptions } from "./useHotkey.js";
|
|
2
|
-
import { HotkeyCallback, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
1
|
+
import { UseAppHotkeyOptions, UseHotkeyChordOptions, UseHotkeyCommonOptions, UseHotkeyOptions, UseHotkeySequenceOptions } from "./useHotkey.js";
|
|
2
|
+
import { AppHotkey, HotkeyCallback, HotkeySequence, RegisterableHotkey, RegisterableHotkeyChord } from "@tanstack/hotkeys";
|
|
3
3
|
import { MaybeRefOrGetter } from "vue";
|
|
4
4
|
//#region src/useHotkeys.d.ts
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* One hotkey for `useHotkeys`. The hotkey and options may be refs or getters.
|
|
7
|
+
* Chords accept `requireReset`; sequences accept `timeout`; hotkeys of unknown
|
|
8
|
+
* kind accept only shared options.
|
|
7
9
|
*/
|
|
8
|
-
export
|
|
9
|
-
/**
|
|
10
|
-
hotkey: MaybeRefOrGetter<
|
|
10
|
+
export type UseHotkeyDefinition = {
|
|
11
|
+
/** A chord string such as `'Mod+S'`, or a RawHotkey object */
|
|
12
|
+
hotkey: MaybeRefOrGetter<RegisterableHotkeyChord>;
|
|
11
13
|
/** The function to call when the hotkey is pressed */
|
|
12
14
|
callback: HotkeyCallback;
|
|
13
15
|
/** Per-hotkey options (merged on top of commonOptions) */
|
|
16
|
+
options?: MaybeRefOrGetter<UseHotkeyChordOptions>;
|
|
17
|
+
} | {
|
|
18
|
+
/** A sequence such as `['G', 'G']` */
|
|
19
|
+
hotkey: MaybeRefOrGetter<HotkeySequence>;
|
|
20
|
+
callback: HotkeyCallback;
|
|
21
|
+
options?: MaybeRefOrGetter<UseHotkeySequenceOptions>;
|
|
22
|
+
} | {
|
|
23
|
+
/** An app hotkey from `defineAppHotkeys` */
|
|
24
|
+
hotkey: MaybeRefOrGetter<AppHotkey>;
|
|
25
|
+
callback: HotkeyCallback;
|
|
26
|
+
options?: MaybeRefOrGetter<UseAppHotkeyOptions>;
|
|
27
|
+
} | {
|
|
28
|
+
/** A hotkey whose kind is not known statically. Accepts only shared options. */
|
|
29
|
+
hotkey: MaybeRefOrGetter<RegisterableHotkey>;
|
|
30
|
+
callback: HotkeyCallback;
|
|
14
31
|
options?: MaybeRefOrGetter<UseHotkeyOptions>;
|
|
15
|
-
}
|
|
32
|
+
};
|
|
16
33
|
/**
|
|
17
|
-
* Vue composable for registering
|
|
18
|
-
*
|
|
19
|
-
* Uses the singleton HotkeyManager for efficient event handling.
|
|
20
|
-
* Accepts a dynamic array of hotkey definitions, making it safe to use
|
|
21
|
-
* with variable-length lists.
|
|
34
|
+
* Vue composable for registering several hotkeys at once: chords, sequences,
|
|
35
|
+
* and app hotkeys. The list, each hotkey, and options may be refs or getters.
|
|
22
36
|
*
|
|
23
|
-
* Options
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* @param commonOptions - Shared options applied to all hotkeys (overridden by per-definition options)
|
|
37
|
+
* Options merge in this order: provider defaults, app hotkey declaration,
|
|
38
|
+
* commonOptions, per-hotkey options. Each option applies only to the kinds
|
|
39
|
+
* that support it. Unbound app hotkeys and empty sequences register nothing.
|
|
40
|
+
* A target that resolves to `null` skips registration until it is set.
|
|
28
41
|
*
|
|
29
42
|
* @example
|
|
30
|
-
* ```
|
|
31
|
-
* <script setup>
|
|
32
|
-
* import { useHotkeys } from '@tanstack/vue-hotkeys'
|
|
33
|
-
*
|
|
43
|
+
* ```ts
|
|
34
44
|
* useHotkeys([
|
|
35
45
|
* { hotkey: 'Mod+S', callback: () => save() },
|
|
36
|
-
* { hotkey: '
|
|
37
|
-
* { hotkey: 'Escape', callback: () => close() },
|
|
46
|
+
* { hotkey: ['G', 'G'], callback: () => scrollToTop(), options: { timeout: 500 } },
|
|
38
47
|
* ])
|
|
39
|
-
* </script>
|
|
40
|
-
* ```
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```vue
|
|
44
|
-
* <script setup>
|
|
45
|
-
* import { computed } from 'vue'
|
|
46
|
-
* import { useHotkeys } from '@tanstack/vue-hotkeys'
|
|
47
|
-
*
|
|
48
|
-
* const items = computed(() => [...])
|
|
49
|
-
* // Dynamic hotkeys from reactive data
|
|
50
|
-
* useHotkeys(
|
|
51
|
-
* () => items.value.map((item) => ({
|
|
52
|
-
* hotkey: item.shortcut,
|
|
53
|
-
* callback: item.action,
|
|
54
|
-
* options: { enabled: item.enabled },
|
|
55
|
-
* })),
|
|
56
|
-
* { preventDefault: true },
|
|
57
|
-
* )
|
|
58
|
-
* </script>
|
|
59
48
|
* ```
|
|
60
49
|
*/
|
|
61
|
-
export declare function useHotkeys(hotkeys: MaybeRefOrGetter<
|
|
50
|
+
export declare function useHotkeys(hotkeys: MaybeRefOrGetter<ReadonlyArray<UseHotkeyDefinition>>, commonOptions?: MaybeRefOrGetter<UseHotkeyCommonOptions>): void;
|
|
62
51
|
//#endregion
|