@tanstack/vue-hotkeys 0.0.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/README.md +122 -0
- package/dist/HotkeysProvider.cjs +31 -0
- package/dist/HotkeysProvider.cjs.map +1 -0
- package/dist/HotkeysProvider.d.cts +34 -0
- package/dist/HotkeysProvider.d.ts +34 -0
- package/dist/HotkeysProvider.js +31 -0
- package/dist/HotkeysProvider.js.map +1 -0
- package/dist/HotkeysProviderContext.cjs +20 -0
- package/dist/HotkeysProviderContext.cjs.map +1 -0
- package/dist/HotkeysProviderContext.d.cts +19 -0
- package/dist/HotkeysProviderContext.d.ts +19 -0
- package/dist/HotkeysProviderContext.js +18 -0
- package/dist/HotkeysProviderContext.js.map +1 -0
- package/dist/index.cjs +27 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +12 -0
- package/dist/useHeldKeyCodes.cjs +37 -0
- package/dist/useHeldKeyCodes.cjs.map +1 -0
- package/dist/useHeldKeyCodes.d.cts +33 -0
- package/dist/useHeldKeyCodes.d.ts +33 -0
- package/dist/useHeldKeyCodes.js +37 -0
- package/dist/useHeldKeyCodes.js.map +1 -0
- package/dist/useHeldKeys.cjs +35 -0
- package/dist/useHeldKeys.cjs.map +1 -0
- package/dist/useHeldKeys.d.cts +31 -0
- package/dist/useHeldKeys.d.ts +31 -0
- package/dist/useHeldKeys.js +35 -0
- package/dist/useHeldKeys.js.map +1 -0
- package/dist/useHotkey.cjs +124 -0
- package/dist/useHotkey.cjs.map +1 -0
- package/dist/useHotkey.d.cts +86 -0
- package/dist/useHotkey.d.ts +86 -0
- package/dist/useHotkey.js +124 -0
- package/dist/useHotkey.js.map +1 -0
- package/dist/useHotkeyRecorder.cjs +80 -0
- package/dist/useHotkeyRecorder.cjs.map +1 -0
- package/dist/useHotkeyRecorder.d.cts +61 -0
- package/dist/useHotkeyRecorder.d.ts +61 -0
- package/dist/useHotkeyRecorder.js +80 -0
- package/dist/useHotkeyRecorder.js.map +1 -0
- package/dist/useHotkeySequence.cjs +95 -0
- package/dist/useHotkeySequence.cjs.map +1 -0
- package/dist/useHotkeySequence.d.cts +58 -0
- package/dist/useHotkeySequence.d.ts +58 -0
- package/dist/useHotkeySequence.js +95 -0
- package/dist/useHotkeySequence.js.map +1 -0
- package/dist/useKeyHold.cjs +60 -0
- package/dist/useKeyHold.cjs.map +1 -0
- package/dist/useKeyHold.d.cts +52 -0
- package/dist/useKeyHold.d.ts +52 -0
- package/dist/useKeyHold.js +60 -0
- package/dist/useKeyHold.js.map +1 -0
- package/package.json +66 -0
- package/src/HotkeysProvider.tsx +29 -0
- package/src/HotkeysProviderContext.ts +37 -0
- package/src/index.ts +14 -0
- package/src/useHeldKeyCodes.ts +34 -0
- package/src/useHeldKeys.ts +32 -0
- package/src/useHotkey.ts +197 -0
- package/src/useHotkeyRecorder.ts +112 -0
- package/src/useHotkeySequence.ts +158 -0
- package/src/useKeyHold.ts +65 -0
- package/src/vue.d.ts +6 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Ref } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/useHeldKeys.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Vue composable that returns a reactive ref of currently held keyboard keys.
|
|
6
|
+
*
|
|
7
|
+
* This composable uses `useStore` from `@tanstack/vue-store` to subscribe
|
|
8
|
+
* to the global KeyStateTracker and updates whenever keys are pressed
|
|
9
|
+
* or released.
|
|
10
|
+
*
|
|
11
|
+
* @returns Reactive ref containing array of currently held key names
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```vue
|
|
15
|
+
* <script setup>
|
|
16
|
+
* import { useHeldKeys } from '@tanstack/vue-hotkeys'
|
|
17
|
+
*
|
|
18
|
+
* const heldKeys = useHeldKeys()
|
|
19
|
+
* </script>
|
|
20
|
+
*
|
|
21
|
+
* <template>
|
|
22
|
+
* <div>
|
|
23
|
+
* Currently pressed: {{ heldKeys.join(' + ') || 'None' }}
|
|
24
|
+
* </div>
|
|
25
|
+
* </template>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare function useHeldKeys(): Ref<Array<string>>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { useHeldKeys };
|
|
31
|
+
//# sourceMappingURL=useHeldKeys.d.cts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Ref } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/useHeldKeys.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Vue composable that returns a reactive ref of currently held keyboard keys.
|
|
6
|
+
*
|
|
7
|
+
* This composable uses `useStore` from `@tanstack/vue-store` to subscribe
|
|
8
|
+
* to the global KeyStateTracker and updates whenever keys are pressed
|
|
9
|
+
* or released.
|
|
10
|
+
*
|
|
11
|
+
* @returns Reactive ref containing array of currently held key names
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```vue
|
|
15
|
+
* <script setup>
|
|
16
|
+
* import { useHeldKeys } from '@tanstack/vue-hotkeys'
|
|
17
|
+
*
|
|
18
|
+
* const heldKeys = useHeldKeys()
|
|
19
|
+
* </script>
|
|
20
|
+
*
|
|
21
|
+
* <template>
|
|
22
|
+
* <div>
|
|
23
|
+
* Currently pressed: {{ heldKeys.join(' + ') || 'None' }}
|
|
24
|
+
* </div>
|
|
25
|
+
* </template>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare function useHeldKeys(): Ref<Array<string>>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { useHeldKeys };
|
|
31
|
+
//# sourceMappingURL=useHeldKeys.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getKeyStateTracker } from "@tanstack/hotkeys";
|
|
2
|
+
import { useStore } from "@tanstack/vue-store";
|
|
3
|
+
|
|
4
|
+
//#region src/useHeldKeys.ts
|
|
5
|
+
/**
|
|
6
|
+
* Vue composable that returns a reactive ref of currently held keyboard keys.
|
|
7
|
+
*
|
|
8
|
+
* This composable uses `useStore` from `@tanstack/vue-store` to subscribe
|
|
9
|
+
* to the global KeyStateTracker and updates whenever keys are pressed
|
|
10
|
+
* or released.
|
|
11
|
+
*
|
|
12
|
+
* @returns Reactive ref containing array of currently held key names
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```vue
|
|
16
|
+
* <script setup>
|
|
17
|
+
* import { useHeldKeys } from '@tanstack/vue-hotkeys'
|
|
18
|
+
*
|
|
19
|
+
* const heldKeys = useHeldKeys()
|
|
20
|
+
* <\/script>
|
|
21
|
+
*
|
|
22
|
+
* <template>
|
|
23
|
+
* <div>
|
|
24
|
+
* Currently pressed: {{ heldKeys.join(' + ') || 'None' }}
|
|
25
|
+
* </div>
|
|
26
|
+
* </template>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
function useHeldKeys() {
|
|
30
|
+
return useStore(getKeyStateTracker().store, (state) => state.heldKeys);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { useHeldKeys };
|
|
35
|
+
//# sourceMappingURL=useHeldKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHeldKeys.js","names":[],"sources":["../src/useHeldKeys.ts"],"sourcesContent":["import { useStore } from '@tanstack/vue-store'\nimport { getKeyStateTracker } from '@tanstack/hotkeys'\nimport type { Ref } from 'vue'\n\n/**\n * Vue composable that returns a reactive ref of currently held keyboard keys.\n *\n * This composable uses `useStore` from `@tanstack/vue-store` to subscribe\n * to the global KeyStateTracker and updates whenever keys are pressed\n * or released.\n *\n * @returns Reactive ref containing array of currently held key names\n *\n * @example\n * ```vue\n * <script setup>\n * import { useHeldKeys } from '@tanstack/vue-hotkeys'\n *\n * const heldKeys = useHeldKeys()\n * </script>\n *\n * <template>\n * <div>\n * Currently pressed: {{ heldKeys.join(' + ') || 'None' }}\n * </div>\n * </template>\n * ```\n */\nexport function useHeldKeys(): Ref<Array<string>> {\n const tracker = getKeyStateTracker()\n return useStore(tracker.store, (state) => state.heldKeys)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,cAAkC;AAEhD,QAAO,SADS,oBAAoB,CACZ,QAAQ,UAAU,MAAM,SAAS"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const require_HotkeysProviderContext = require('./HotkeysProviderContext.cjs');
|
|
2
|
+
let _tanstack_hotkeys = require("@tanstack/hotkeys");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
|
|
5
|
+
//#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
|
+
function useHotkey(hotkey, callback, options = {}) {
|
|
71
|
+
const defaultOptions = require_HotkeysProviderContext.useDefaultHotkeysOptions();
|
|
72
|
+
const manager = (0, _tanstack_hotkeys.getHotkeyManager)();
|
|
73
|
+
let registration = null;
|
|
74
|
+
const stopWatcher = (0, vue.watch)(() => {
|
|
75
|
+
const resolvedHotkey = resolveMaybeRefOrGetter(hotkey);
|
|
76
|
+
const resolvedOptions = resolveMaybeRefOrGetter(options);
|
|
77
|
+
const mergedOptions = {
|
|
78
|
+
...defaultOptions.hotkey,
|
|
79
|
+
...resolvedOptions
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
resolvedHotkey,
|
|
83
|
+
mergedOptions,
|
|
84
|
+
resolvedEnabled: mergedOptions.enabled === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.enabled),
|
|
85
|
+
resolvedTarget: mergedOptions.target === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.target)
|
|
86
|
+
};
|
|
87
|
+
}, ({ resolvedHotkey, mergedOptions, resolvedEnabled, resolvedTarget }) => {
|
|
88
|
+
const platform = mergedOptions.platform ?? (0, _tanstack_hotkeys.detectPlatform)();
|
|
89
|
+
const hotkeyString = typeof resolvedHotkey === "string" ? resolvedHotkey : (0, _tanstack_hotkeys.formatHotkey)((0, _tanstack_hotkeys.rawHotkeyToParsedHotkey)(resolvedHotkey, platform));
|
|
90
|
+
const finalTarget = resolvedTarget ?? (typeof document !== "undefined" ? document : null);
|
|
91
|
+
if (!finalTarget) return;
|
|
92
|
+
if (registration?.isActive) {
|
|
93
|
+
registration.unregister();
|
|
94
|
+
registration = null;
|
|
95
|
+
}
|
|
96
|
+
const { target: _target, enabled: _enabled, ...restOptions } = mergedOptions;
|
|
97
|
+
const optionsWithoutTarget = {
|
|
98
|
+
...restOptions,
|
|
99
|
+
...resolvedEnabled === void 0 ? {} : { enabled: resolvedEnabled }
|
|
100
|
+
};
|
|
101
|
+
registration = manager.register(hotkeyString, callback, {
|
|
102
|
+
...optionsWithoutTarget,
|
|
103
|
+
target: finalTarget
|
|
104
|
+
});
|
|
105
|
+
if (registration.isActive) {
|
|
106
|
+
registration.callback = callback;
|
|
107
|
+
registration.setOptions(optionsWithoutTarget);
|
|
108
|
+
}
|
|
109
|
+
}, { immediate: true });
|
|
110
|
+
(0, vue.onUnmounted)(() => {
|
|
111
|
+
stopWatcher();
|
|
112
|
+
if (registration?.isActive) {
|
|
113
|
+
registration.unregister();
|
|
114
|
+
registration = null;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function resolveMaybeRefOrGetter(value) {
|
|
119
|
+
return typeof value === "function" ? value() : (0, vue.unref)(value);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
exports.useHotkey = useHotkey;
|
|
124
|
+
//# sourceMappingURL=useHotkey.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHotkey.cjs","names":["useDefaultHotkeysOptions"],"sources":["../src/useHotkey.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport {\n detectPlatform,\n formatHotkey,\n getHotkeyManager,\n rawHotkeyToParsedHotkey,\n} from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type {\n Hotkey,\n HotkeyCallback,\n HotkeyOptions,\n HotkeyRegistrationHandle,\n RegisterableHotkey,\n} from '@tanstack/hotkeys'\nimport type { MaybeRefOrGetter } from 'vue'\n\nexport interface UseHotkeyOptions extends Omit<\n HotkeyOptions,\n 'enabled' | 'target'\n> {\n /**\n * Whether the hotkey is active.\n * Can be a Ref, a getter function, or a boolean value.\n * Defaults to true.\n */\n enabled?: MaybeRefOrGetter<boolean>\n /**\n * The DOM element to attach the event listener to.\n * Can be a Ref, a getter function, direct DOM element, or null.\n * Defaults to document.\n */\n target?: MaybeRefOrGetter<HTMLElement | Document | Window | null>\n}\n\n/**\n * Vue composable for registering a keyboard hotkey.\n *\n * Uses the singleton HotkeyManager for efficient event handling.\n * The callback receives both the keyboard event and a context object\n * containing the hotkey string and parsed hotkey.\n *\n * This composable automatically tracks reactive dependencies and updates\n * the registration when options or the callback change.\n *\n * @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)\n * @param callback - The function to call when the hotkey is pressed\n * @param options - Options for the hotkey behavior\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const count = ref(0)\n *\n * // Callback always has access to latest count value\n * useHotkey('Mod+S', (event, { hotkey }) => {\n * console.log(`Save triggered, count is ${count.value}`)\n * handleSave()\n * })\n * </script>\n * ```\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const isOpen = ref(false)\n *\n * // enabled option is reactive\n * useHotkey('Escape', () => {\n * isOpen.value = false\n * }, { enabled: isOpen })\n * </script>\n * ```\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const editorRef = ref<HTMLDivElement | null>(null)\n *\n * // Scoped to a specific element\n * useHotkey('Mod+S', () => {\n * save()\n * }, { target: editorRef })\n * </script>\n *\n * <template>\n * <div ref=\"editorRef\">...</div>\n * </template>\n * ```\n */\nexport function useHotkey(\n hotkey: MaybeRefOrGetter<RegisterableHotkey>,\n callback: HotkeyCallback,\n options: MaybeRefOrGetter<UseHotkeyOptions> = {},\n): void {\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getHotkeyManager()\n\n let registration: HotkeyRegistrationHandle | null = null\n\n // Watch for changes to reactive dependencies\n const stopWatcher = watch(\n () => {\n const resolvedHotkey = resolveMaybeRefOrGetter(hotkey)\n const resolvedOptions = resolveMaybeRefOrGetter(options)\n const mergedOptions = {\n ...defaultOptions.hotkey,\n ...resolvedOptions,\n } as UseHotkeyOptions\n const resolvedEnabled =\n mergedOptions.enabled === undefined\n ? undefined\n : resolveMaybeRefOrGetter(mergedOptions.enabled)\n const resolvedTarget =\n mergedOptions.target === undefined\n ? undefined\n : resolveMaybeRefOrGetter(mergedOptions.target)\n\n return {\n resolvedHotkey,\n mergedOptions,\n resolvedEnabled,\n resolvedTarget,\n }\n },\n ({ resolvedHotkey, mergedOptions, resolvedEnabled, resolvedTarget }) => {\n // Normalize to hotkey string\n const platform = mergedOptions.platform ?? detectPlatform()\n const hotkeyString: Hotkey =\n typeof resolvedHotkey === 'string'\n ? resolvedHotkey\n : (formatHotkey(\n rawHotkeyToParsedHotkey(resolvedHotkey as any, platform),\n ) as Hotkey)\n\n // Resolve target\n const finalTarget =\n resolvedTarget ?? (typeof document !== 'undefined' ? document : null)\n\n if (!finalTarget) {\n return\n }\n\n // Unregister previous registration if it exists\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n // Extract options without target (target is handled separately)\n const {\n target: _target,\n enabled: _enabled,\n ...restOptions\n } = mergedOptions\n const optionsWithoutTarget = {\n ...restOptions,\n ...(resolvedEnabled === undefined ? {} : { enabled: resolvedEnabled }),\n }\n\n // Register the hotkey\n registration = manager.register(hotkeyString, callback, {\n ...optionsWithoutTarget,\n target: finalTarget,\n })\n\n // Update callback and options\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n },\n { immediate: true },\n )\n\n // Cleanup on unmount\n onUnmounted(() => {\n stopWatcher()\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n })\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,SAAgB,UACd,QACA,UACA,UAA8C,EAAE,EAC1C;CACN,MAAM,iBAAiBA,yDAA0B;CACjD,MAAM,mDAA4B;CAElC,IAAI,eAAgD;CAGpD,MAAM,mCACE;EACJ,MAAM,iBAAiB,wBAAwB,OAAO;EACtD,MAAM,kBAAkB,wBAAwB,QAAQ;EACxD,MAAM,gBAAgB;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ;AAUD,SAAO;GACL;GACA;GACA,iBAXA,cAAc,YAAY,SACtB,SACA,wBAAwB,cAAc,QAAQ;GAUlD,gBARA,cAAc,WAAW,SACrB,SACA,wBAAwB,cAAc,OAAO;GAOlD;KAEF,EAAE,gBAAgB,eAAe,iBAAiB,qBAAqB;EAEtE,MAAM,WAAW,cAAc,mDAA4B;EAC3D,MAAM,eACJ,OAAO,mBAAmB,WACtB,oGAE0B,gBAAuB,SAAS,CACzD;EAGP,MAAM,cACJ,mBAAmB,OAAO,aAAa,cAAc,WAAW;AAElE,MAAI,CAAC,YACH;AAIF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;EAIjB,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD;EACJ,MAAM,uBAAuB;GAC3B,GAAG;GACH,GAAI,oBAAoB,SAAY,EAAE,GAAG,EAAE,SAAS,iBAAiB;GACtE;AAGD,iBAAe,QAAQ,SAAS,cAAc,UAAU;GACtD,GAAG;GACH,QAAQ;GACT,CAAC;AAGF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;IAGjD,EAAE,WAAW,MAAM,CACpB;AAGD,4BAAkB;AAChB,eAAa;AACb,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;GAEjB;;AAGJ,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,kBAAS,MAAM"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { HotkeyCallback, HotkeyOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
|
+
import { MaybeRefOrGetter } from "vue";
|
|
3
|
+
|
|
4
|
+
//#region src/useHotkey.d.ts
|
|
5
|
+
interface UseHotkeyOptions extends Omit<HotkeyOptions, 'enabled' | 'target'> {
|
|
6
|
+
/**
|
|
7
|
+
* Whether the hotkey is active.
|
|
8
|
+
* Can be a Ref, a getter function, or a boolean value.
|
|
9
|
+
* Defaults to true.
|
|
10
|
+
*/
|
|
11
|
+
enabled?: MaybeRefOrGetter<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* The DOM element to attach the event listener to.
|
|
14
|
+
* Can be a Ref, a getter function, direct DOM element, or null.
|
|
15
|
+
* Defaults to document.
|
|
16
|
+
*/
|
|
17
|
+
target?: MaybeRefOrGetter<HTMLElement | Document | Window | null>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Vue composable for registering a keyboard hotkey.
|
|
21
|
+
*
|
|
22
|
+
* Uses the singleton HotkeyManager for efficient event handling.
|
|
23
|
+
* The callback receives both the keyboard event and a context object
|
|
24
|
+
* containing the hotkey string and parsed hotkey.
|
|
25
|
+
*
|
|
26
|
+
* This composable automatically tracks reactive dependencies and updates
|
|
27
|
+
* the registration when options or the callback change.
|
|
28
|
+
*
|
|
29
|
+
* @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)
|
|
30
|
+
* @param callback - The function to call when the hotkey is pressed
|
|
31
|
+
* @param options - Options for the hotkey behavior
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```vue
|
|
35
|
+
* <script setup>
|
|
36
|
+
* import { ref } from 'vue'
|
|
37
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
38
|
+
*
|
|
39
|
+
* const count = ref(0)
|
|
40
|
+
*
|
|
41
|
+
* // Callback always has access to latest count value
|
|
42
|
+
* useHotkey('Mod+S', (event, { hotkey }) => {
|
|
43
|
+
* console.log(`Save triggered, count is ${count.value}`)
|
|
44
|
+
* handleSave()
|
|
45
|
+
* })
|
|
46
|
+
* </script>
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```vue
|
|
51
|
+
* <script setup>
|
|
52
|
+
* import { ref } from 'vue'
|
|
53
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
54
|
+
*
|
|
55
|
+
* const isOpen = ref(false)
|
|
56
|
+
*
|
|
57
|
+
* // enabled option is reactive
|
|
58
|
+
* useHotkey('Escape', () => {
|
|
59
|
+
* isOpen.value = false
|
|
60
|
+
* }, { enabled: isOpen })
|
|
61
|
+
* </script>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```vue
|
|
66
|
+
* <script setup>
|
|
67
|
+
* import { ref } from 'vue'
|
|
68
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
69
|
+
*
|
|
70
|
+
* const editorRef = ref<HTMLDivElement | null>(null)
|
|
71
|
+
*
|
|
72
|
+
* // Scoped to a specific element
|
|
73
|
+
* useHotkey('Mod+S', () => {
|
|
74
|
+
* save()
|
|
75
|
+
* }, { target: editorRef })
|
|
76
|
+
* </script>
|
|
77
|
+
*
|
|
78
|
+
* <template>
|
|
79
|
+
* <div ref="editorRef">...</div>
|
|
80
|
+
* </template>
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function useHotkey(hotkey: MaybeRefOrGetter<RegisterableHotkey>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseHotkeyOptions>): void;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { UseHotkeyOptions, useHotkey };
|
|
86
|
+
//# sourceMappingURL=useHotkey.d.cts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { HotkeyCallback, HotkeyOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
|
+
import { MaybeRefOrGetter } from "vue";
|
|
3
|
+
|
|
4
|
+
//#region src/useHotkey.d.ts
|
|
5
|
+
interface UseHotkeyOptions extends Omit<HotkeyOptions, 'enabled' | 'target'> {
|
|
6
|
+
/**
|
|
7
|
+
* Whether the hotkey is active.
|
|
8
|
+
* Can be a Ref, a getter function, or a boolean value.
|
|
9
|
+
* Defaults to true.
|
|
10
|
+
*/
|
|
11
|
+
enabled?: MaybeRefOrGetter<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* The DOM element to attach the event listener to.
|
|
14
|
+
* Can be a Ref, a getter function, direct DOM element, or null.
|
|
15
|
+
* Defaults to document.
|
|
16
|
+
*/
|
|
17
|
+
target?: MaybeRefOrGetter<HTMLElement | Document | Window | null>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Vue composable for registering a keyboard hotkey.
|
|
21
|
+
*
|
|
22
|
+
* Uses the singleton HotkeyManager for efficient event handling.
|
|
23
|
+
* The callback receives both the keyboard event and a context object
|
|
24
|
+
* containing the hotkey string and parsed hotkey.
|
|
25
|
+
*
|
|
26
|
+
* This composable automatically tracks reactive dependencies and updates
|
|
27
|
+
* the registration when options or the callback change.
|
|
28
|
+
*
|
|
29
|
+
* @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)
|
|
30
|
+
* @param callback - The function to call when the hotkey is pressed
|
|
31
|
+
* @param options - Options for the hotkey behavior
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```vue
|
|
35
|
+
* <script setup>
|
|
36
|
+
* import { ref } from 'vue'
|
|
37
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
38
|
+
*
|
|
39
|
+
* const count = ref(0)
|
|
40
|
+
*
|
|
41
|
+
* // Callback always has access to latest count value
|
|
42
|
+
* useHotkey('Mod+S', (event, { hotkey }) => {
|
|
43
|
+
* console.log(`Save triggered, count is ${count.value}`)
|
|
44
|
+
* handleSave()
|
|
45
|
+
* })
|
|
46
|
+
* </script>
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```vue
|
|
51
|
+
* <script setup>
|
|
52
|
+
* import { ref } from 'vue'
|
|
53
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
54
|
+
*
|
|
55
|
+
* const isOpen = ref(false)
|
|
56
|
+
*
|
|
57
|
+
* // enabled option is reactive
|
|
58
|
+
* useHotkey('Escape', () => {
|
|
59
|
+
* isOpen.value = false
|
|
60
|
+
* }, { enabled: isOpen })
|
|
61
|
+
* </script>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```vue
|
|
66
|
+
* <script setup>
|
|
67
|
+
* import { ref } from 'vue'
|
|
68
|
+
* import { useHotkey } from '@tanstack/vue-hotkeys'
|
|
69
|
+
*
|
|
70
|
+
* const editorRef = ref<HTMLDivElement | null>(null)
|
|
71
|
+
*
|
|
72
|
+
* // Scoped to a specific element
|
|
73
|
+
* useHotkey('Mod+S', () => {
|
|
74
|
+
* save()
|
|
75
|
+
* }, { target: editorRef })
|
|
76
|
+
* </script>
|
|
77
|
+
*
|
|
78
|
+
* <template>
|
|
79
|
+
* <div ref="editorRef">...</div>
|
|
80
|
+
* </template>
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function useHotkey(hotkey: MaybeRefOrGetter<RegisterableHotkey>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseHotkeyOptions>): void;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { UseHotkeyOptions, useHotkey };
|
|
86
|
+
//# sourceMappingURL=useHotkey.d.ts.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { useDefaultHotkeysOptions } from "./HotkeysProviderContext.js";
|
|
2
|
+
import { detectPlatform, formatHotkey, getHotkeyManager, rawHotkeyToParsedHotkey } from "@tanstack/hotkeys";
|
|
3
|
+
import { onUnmounted, unref, watch } from "vue";
|
|
4
|
+
|
|
5
|
+
//#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
|
+
function useHotkey(hotkey, callback, options = {}) {
|
|
71
|
+
const defaultOptions = useDefaultHotkeysOptions();
|
|
72
|
+
const manager = getHotkeyManager();
|
|
73
|
+
let registration = null;
|
|
74
|
+
const stopWatcher = watch(() => {
|
|
75
|
+
const resolvedHotkey = resolveMaybeRefOrGetter(hotkey);
|
|
76
|
+
const resolvedOptions = resolveMaybeRefOrGetter(options);
|
|
77
|
+
const mergedOptions = {
|
|
78
|
+
...defaultOptions.hotkey,
|
|
79
|
+
...resolvedOptions
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
resolvedHotkey,
|
|
83
|
+
mergedOptions,
|
|
84
|
+
resolvedEnabled: mergedOptions.enabled === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.enabled),
|
|
85
|
+
resolvedTarget: mergedOptions.target === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.target)
|
|
86
|
+
};
|
|
87
|
+
}, ({ resolvedHotkey, mergedOptions, resolvedEnabled, resolvedTarget }) => {
|
|
88
|
+
const platform = mergedOptions.platform ?? detectPlatform();
|
|
89
|
+
const hotkeyString = typeof resolvedHotkey === "string" ? resolvedHotkey : formatHotkey(rawHotkeyToParsedHotkey(resolvedHotkey, platform));
|
|
90
|
+
const finalTarget = resolvedTarget ?? (typeof document !== "undefined" ? document : null);
|
|
91
|
+
if (!finalTarget) return;
|
|
92
|
+
if (registration?.isActive) {
|
|
93
|
+
registration.unregister();
|
|
94
|
+
registration = null;
|
|
95
|
+
}
|
|
96
|
+
const { target: _target, enabled: _enabled, ...restOptions } = mergedOptions;
|
|
97
|
+
const optionsWithoutTarget = {
|
|
98
|
+
...restOptions,
|
|
99
|
+
...resolvedEnabled === void 0 ? {} : { enabled: resolvedEnabled }
|
|
100
|
+
};
|
|
101
|
+
registration = manager.register(hotkeyString, callback, {
|
|
102
|
+
...optionsWithoutTarget,
|
|
103
|
+
target: finalTarget
|
|
104
|
+
});
|
|
105
|
+
if (registration.isActive) {
|
|
106
|
+
registration.callback = callback;
|
|
107
|
+
registration.setOptions(optionsWithoutTarget);
|
|
108
|
+
}
|
|
109
|
+
}, { immediate: true });
|
|
110
|
+
onUnmounted(() => {
|
|
111
|
+
stopWatcher();
|
|
112
|
+
if (registration?.isActive) {
|
|
113
|
+
registration.unregister();
|
|
114
|
+
registration = null;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function resolveMaybeRefOrGetter(value) {
|
|
119
|
+
return typeof value === "function" ? value() : unref(value);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
export { useHotkey };
|
|
124
|
+
//# sourceMappingURL=useHotkey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHotkey.js","names":[],"sources":["../src/useHotkey.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport {\n detectPlatform,\n formatHotkey,\n getHotkeyManager,\n rawHotkeyToParsedHotkey,\n} from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type {\n Hotkey,\n HotkeyCallback,\n HotkeyOptions,\n HotkeyRegistrationHandle,\n RegisterableHotkey,\n} from '@tanstack/hotkeys'\nimport type { MaybeRefOrGetter } from 'vue'\n\nexport interface UseHotkeyOptions extends Omit<\n HotkeyOptions,\n 'enabled' | 'target'\n> {\n /**\n * Whether the hotkey is active.\n * Can be a Ref, a getter function, or a boolean value.\n * Defaults to true.\n */\n enabled?: MaybeRefOrGetter<boolean>\n /**\n * The DOM element to attach the event listener to.\n * Can be a Ref, a getter function, direct DOM element, or null.\n * Defaults to document.\n */\n target?: MaybeRefOrGetter<HTMLElement | Document | Window | null>\n}\n\n/**\n * Vue composable for registering a keyboard hotkey.\n *\n * Uses the singleton HotkeyManager for efficient event handling.\n * The callback receives both the keyboard event and a context object\n * containing the hotkey string and parsed hotkey.\n *\n * This composable automatically tracks reactive dependencies and updates\n * the registration when options or the callback change.\n *\n * @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)\n * @param callback - The function to call when the hotkey is pressed\n * @param options - Options for the hotkey behavior\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const count = ref(0)\n *\n * // Callback always has access to latest count value\n * useHotkey('Mod+S', (event, { hotkey }) => {\n * console.log(`Save triggered, count is ${count.value}`)\n * handleSave()\n * })\n * </script>\n * ```\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const isOpen = ref(false)\n *\n * // enabled option is reactive\n * useHotkey('Escape', () => {\n * isOpen.value = false\n * }, { enabled: isOpen })\n * </script>\n * ```\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkey } from '@tanstack/vue-hotkeys'\n *\n * const editorRef = ref<HTMLDivElement | null>(null)\n *\n * // Scoped to a specific element\n * useHotkey('Mod+S', () => {\n * save()\n * }, { target: editorRef })\n * </script>\n *\n * <template>\n * <div ref=\"editorRef\">...</div>\n * </template>\n * ```\n */\nexport function useHotkey(\n hotkey: MaybeRefOrGetter<RegisterableHotkey>,\n callback: HotkeyCallback,\n options: MaybeRefOrGetter<UseHotkeyOptions> = {},\n): void {\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getHotkeyManager()\n\n let registration: HotkeyRegistrationHandle | null = null\n\n // Watch for changes to reactive dependencies\n const stopWatcher = watch(\n () => {\n const resolvedHotkey = resolveMaybeRefOrGetter(hotkey)\n const resolvedOptions = resolveMaybeRefOrGetter(options)\n const mergedOptions = {\n ...defaultOptions.hotkey,\n ...resolvedOptions,\n } as UseHotkeyOptions\n const resolvedEnabled =\n mergedOptions.enabled === undefined\n ? undefined\n : resolveMaybeRefOrGetter(mergedOptions.enabled)\n const resolvedTarget =\n mergedOptions.target === undefined\n ? undefined\n : resolveMaybeRefOrGetter(mergedOptions.target)\n\n return {\n resolvedHotkey,\n mergedOptions,\n resolvedEnabled,\n resolvedTarget,\n }\n },\n ({ resolvedHotkey, mergedOptions, resolvedEnabled, resolvedTarget }) => {\n // Normalize to hotkey string\n const platform = mergedOptions.platform ?? detectPlatform()\n const hotkeyString: Hotkey =\n typeof resolvedHotkey === 'string'\n ? resolvedHotkey\n : (formatHotkey(\n rawHotkeyToParsedHotkey(resolvedHotkey as any, platform),\n ) as Hotkey)\n\n // Resolve target\n const finalTarget =\n resolvedTarget ?? (typeof document !== 'undefined' ? document : null)\n\n if (!finalTarget) {\n return\n }\n\n // Unregister previous registration if it exists\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n // Extract options without target (target is handled separately)\n const {\n target: _target,\n enabled: _enabled,\n ...restOptions\n } = mergedOptions\n const optionsWithoutTarget = {\n ...restOptions,\n ...(resolvedEnabled === undefined ? {} : { enabled: resolvedEnabled }),\n }\n\n // Register the hotkey\n registration = manager.register(hotkeyString, callback, {\n ...optionsWithoutTarget,\n target: finalTarget,\n })\n\n // Update callback and options\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n },\n { immediate: true },\n )\n\n // Cleanup on unmount\n onUnmounted(() => {\n stopWatcher()\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n })\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,SAAgB,UACd,QACA,UACA,UAA8C,EAAE,EAC1C;CACN,MAAM,iBAAiB,0BAA0B;CACjD,MAAM,UAAU,kBAAkB;CAElC,IAAI,eAAgD;CAGpD,MAAM,cAAc,YACZ;EACJ,MAAM,iBAAiB,wBAAwB,OAAO;EACtD,MAAM,kBAAkB,wBAAwB,QAAQ;EACxD,MAAM,gBAAgB;GACpB,GAAG,eAAe;GAClB,GAAG;GACJ;AAUD,SAAO;GACL;GACA;GACA,iBAXA,cAAc,YAAY,SACtB,SACA,wBAAwB,cAAc,QAAQ;GAUlD,gBARA,cAAc,WAAW,SACrB,SACA,wBAAwB,cAAc,OAAO;GAOlD;KAEF,EAAE,gBAAgB,eAAe,iBAAiB,qBAAqB;EAEtE,MAAM,WAAW,cAAc,YAAY,gBAAgB;EAC3D,MAAM,eACJ,OAAO,mBAAmB,WACtB,iBACC,aACC,wBAAwB,gBAAuB,SAAS,CACzD;EAGP,MAAM,cACJ,mBAAmB,OAAO,aAAa,cAAc,WAAW;AAElE,MAAI,CAAC,YACH;AAIF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;EAIjB,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD;EACJ,MAAM,uBAAuB;GAC3B,GAAG;GACH,GAAI,oBAAoB,SAAY,EAAE,GAAG,EAAE,SAAS,iBAAiB;GACtE;AAGD,iBAAe,QAAQ,SAAS,cAAc,UAAU;GACtD,GAAG;GACH,QAAQ;GACT,CAAC;AAGF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;IAGjD,EAAE,WAAW,MAAM,CACpB;AAGD,mBAAkB;AAChB,eAAa;AACb,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;GAEjB;;AAGJ,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,GAAG,MAAM,MAAM"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const require_HotkeysProviderContext = require('./HotkeysProviderContext.cjs');
|
|
2
|
+
let _tanstack_hotkeys = require("@tanstack/hotkeys");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
let _tanstack_vue_store = require("@tanstack/vue-store");
|
|
5
|
+
|
|
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
|
+
function useHotkeyRecorder(options) {
|
|
49
|
+
const defaultOptions = require_HotkeysProviderContext.useDefaultHotkeysOptions();
|
|
50
|
+
const recorder = new _tanstack_hotkeys.HotkeyRecorder(resolveRecorderOptions(options, defaultOptions));
|
|
51
|
+
const isRecording = (0, _tanstack_vue_store.useStore)(recorder.store, (state) => state.isRecording);
|
|
52
|
+
const recordedHotkey = (0, _tanstack_vue_store.useStore)(recorder.store, (state) => state.recordedHotkey);
|
|
53
|
+
const stopWatcher = (0, vue.watch)(() => resolveRecorderOptions(options, defaultOptions), (resolvedOptions) => {
|
|
54
|
+
recorder.setOptions(resolvedOptions);
|
|
55
|
+
}, { immediate: true });
|
|
56
|
+
(0, vue.onUnmounted)(() => {
|
|
57
|
+
stopWatcher();
|
|
58
|
+
recorder.destroy();
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
isRecording,
|
|
62
|
+
recordedHotkey,
|
|
63
|
+
startRecording: () => recorder.start(),
|
|
64
|
+
stopRecording: () => recorder.stop(),
|
|
65
|
+
cancelRecording: () => recorder.cancel()
|
|
66
|
+
};
|
|
67
|
+
}
|
|
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() : (0, vue.unref)(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
exports.useHotkeyRecorder = useHotkeyRecorder;
|
|
80
|
+
//# sourceMappingURL=useHotkeyRecorder.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHotkeyRecorder.cjs","names":["useDefaultHotkeysOptions","HotkeyRecorder"],"sources":["../src/useHotkeyRecorder.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { useStore } from '@tanstack/vue-store'\nimport { HotkeyRecorder } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { MaybeRefOrGetter, Ref } from 'vue'\nimport type { Hotkey, HotkeyRecorderOptions } from '@tanstack/hotkeys'\n\nexport interface VueHotkeyRecorder {\n /** Whether recording is currently active */\n isRecording: Ref<boolean>\n /** The currently recorded hotkey (for live preview) */\n recordedHotkey: Ref<Hotkey | null>\n /** Start recording a new hotkey */\n startRecording: () => void\n /** Stop recording (same as cancel) */\n stopRecording: () => void\n /** Cancel recording without saving */\n cancelRecording: () => void\n}\n\n/**\n * Vue composable for recording keyboard shortcuts.\n *\n * This composable provides a thin wrapper around the framework-agnostic `HotkeyRecorder`\n * class, managing all the complexity of capturing keyboard events, converting them\n * to hotkey strings, and handling edge cases like Escape to cancel or Backspace/Delete\n * to clear.\n *\n * @param options - Configuration options for the recorder\n * @returns An object with recording state and control functions\n *\n * @example\n * ```vue\n * <script setup>\n * import { ref } from 'vue'\n * import { useHotkeyRecorder } from '@tanstack/vue-hotkeys'\n *\n * const shortcut = ref<Hotkey>('Mod+S')\n *\n * const recorder = useHotkeyRecorder({\n * onRecord: (hotkey) => {\n * shortcut.value = hotkey\n * },\n * onCancel: () => {\n * console.log('Recording cancelled')\n * },\n * })\n * </script>\n *\n * <template>\n * <div>\n * <button @click=\"recorder.startRecording()\">\n * {{ recorder.isRecording ? 'Recording...' : 'Edit Shortcut' }}\n * </button>\n * <div v-if=\"recorder.recordedHotkey\">\n * Recording: {{ recorder.recordedHotkey }}\n * </div>\n * </div>\n * </template>\n * ```\n */\nexport function useHotkeyRecorder(\n options: MaybeRefOrGetter<HotkeyRecorderOptions>,\n): VueHotkeyRecorder {\n const defaultOptions = useDefaultHotkeysOptions()\n const recorder = new HotkeyRecorder(\n resolveRecorderOptions(options, defaultOptions),\n )\n\n // Subscribe to recorder state using useStore\n const isRecording = useStore(recorder.store, (state) => state.isRecording)\n const recordedHotkey = useStore(\n recorder.store,\n (state) => state.recordedHotkey,\n )\n\n const stopWatcher = watch(\n () => resolveRecorderOptions(options, defaultOptions),\n (resolvedOptions) => {\n recorder.setOptions(resolvedOptions)\n },\n { immediate: true },\n )\n\n // Cleanup on unmount\n onUnmounted(() => {\n stopWatcher()\n recorder.destroy()\n })\n\n return {\n isRecording: isRecording as Ref<boolean>,\n recordedHotkey: recordedHotkey as Ref<Hotkey | null>,\n startRecording: () => recorder.start(),\n stopRecording: () => recorder.stop(),\n cancelRecording: () => recorder.cancel(),\n }\n}\n\nfunction resolveRecorderOptions(\n options: MaybeRefOrGetter<HotkeyRecorderOptions>,\n defaultOptions: ReturnType<typeof useDefaultHotkeysOptions>,\n): HotkeyRecorderOptions {\n return {\n ...defaultOptions.hotkeyRecorder,\n ...resolveMaybeRefOrGetter(options),\n } as HotkeyRecorderOptions\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,kBACd,SACmB;CACnB,MAAM,iBAAiBA,yDAA0B;CACjD,MAAM,WAAW,IAAIC,iCACnB,uBAAuB,SAAS,eAAe,CAChD;CAGD,MAAM,gDAAuB,SAAS,QAAQ,UAAU,MAAM,YAAY;CAC1E,MAAM,mDACJ,SAAS,QACR,UAAU,MAAM,eAClB;CAED,MAAM,mCACE,uBAAuB,SAAS,eAAe,GACpD,oBAAoB;AACnB,WAAS,WAAW,gBAAgB;IAEtC,EAAE,WAAW,MAAM,CACpB;AAGD,4BAAkB;AAChB,eAAa;AACb,WAAS,SAAS;GAClB;AAEF,QAAO;EACQ;EACG;EAChB,sBAAsB,SAAS,OAAO;EACtC,qBAAqB,SAAS,MAAM;EACpC,uBAAuB,SAAS,QAAQ;EACzC;;AAGH,SAAS,uBACP,SACA,gBACuB;AACvB,QAAO;EACL,GAAG,eAAe;EAClB,GAAG,wBAAwB,QAAQ;EACpC;;AAGH,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,kBAAS,MAAM"}
|