@tanstack/vue-hotkeys 0.10.0 → 0.12.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 +15 -1
- package/dist/HotkeysProvider.d.ts +5 -9
- package/dist/HotkeysProvider.js +1 -2
- package/dist/HotkeysProviderContext.d.ts +5 -8
- package/dist/HotkeysProviderContext.js +1 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/useHeldKeyCodes.d.ts +2 -5
- package/dist/useHeldKeyCodes.js +3 -3
- package/dist/useHeldKeys.d.ts +2 -5
- package/dist/useHeldKeys.js +3 -3
- package/dist/useHotkey.d.ts +3 -6
- package/dist/useHotkey.js +3 -3
- package/dist/useHotkeyHint.d.ts +12 -0
- package/dist/useHotkeyHint.js +19 -0
- package/dist/useHotkeyRecorder.d.ts +3 -6
- package/dist/useHotkeyRecorder.js +1 -2
- package/dist/useHotkeyRegistrations.d.ts +3 -6
- package/dist/useHotkeyRegistrations.js +1 -2
- package/dist/useHotkeySequence.d.ts +3 -6
- package/dist/useHotkeySequence.js +1 -2
- package/dist/useHotkeySequenceRecorder.d.ts +3 -6
- package/dist/useHotkeySequenceRecorder.js +1 -2
- package/dist/useHotkeySequences.d.ts +3 -6
- package/dist/useHotkeySequences.js +1 -2
- package/dist/useHotkeys.d.ts +3 -6
- package/dist/useHotkeys.js +3 -3
- package/dist/useKeyHold.d.ts +2 -5
- package/dist/useKeyHold.js +3 -3
- package/package.json +12 -17
- package/dist/HotkeysProvider.cjs +0 -31
- package/dist/HotkeysProvider.cjs.map +0 -1
- package/dist/HotkeysProvider.d.cts +0 -34
- package/dist/HotkeysProvider.js.map +0 -1
- package/dist/HotkeysProviderContext.cjs +0 -20
- package/dist/HotkeysProviderContext.cjs.map +0 -1
- package/dist/HotkeysProviderContext.d.cts +0 -20
- package/dist/HotkeysProviderContext.js.map +0 -1
- package/dist/index.cjs +0 -35
- package/dist/index.d.cts +0 -14
- package/dist/useHeldKeyCodes.cjs +0 -37
- package/dist/useHeldKeyCodes.cjs.map +0 -1
- package/dist/useHeldKeyCodes.d.cts +0 -33
- package/dist/useHeldKeyCodes.js.map +0 -1
- package/dist/useHeldKeys.cjs +0 -35
- package/dist/useHeldKeys.cjs.map +0 -1
- package/dist/useHeldKeys.d.cts +0 -31
- package/dist/useHeldKeys.js.map +0 -1
- package/dist/useHotkey.cjs +0 -140
- package/dist/useHotkey.cjs.map +0 -1
- package/dist/useHotkey.d.cts +0 -86
- package/dist/useHotkey.js.map +0 -1
- package/dist/useHotkeyRecorder.cjs +0 -80
- package/dist/useHotkeyRecorder.cjs.map +0 -1
- package/dist/useHotkeyRecorder.d.cts +0 -61
- package/dist/useHotkeyRecorder.js.map +0 -1
- package/dist/useHotkeyRegistrations.cjs +0 -26
- package/dist/useHotkeyRegistrations.cjs.map +0 -1
- package/dist/useHotkeyRegistrations.d.cts +0 -27
- package/dist/useHotkeyRegistrations.js.map +0 -1
- package/dist/useHotkeySequence.cjs +0 -122
- package/dist/useHotkeySequence.cjs.map +0 -1
- package/dist/useHotkeySequence.d.cts +0 -68
- package/dist/useHotkeySequence.js.map +0 -1
- package/dist/useHotkeySequenceRecorder.cjs +0 -45
- package/dist/useHotkeySequenceRecorder.cjs.map +0 -1
- package/dist/useHotkeySequenceRecorder.d.cts +0 -20
- package/dist/useHotkeySequenceRecorder.js.map +0 -1
- package/dist/useHotkeySequences.cjs +0 -140
- package/dist/useHotkeySequences.cjs.map +0 -1
- package/dist/useHotkeySequences.d.cts +0 -64
- package/dist/useHotkeySequences.js.map +0 -1
- package/dist/useHotkeys.cjs +0 -139
- package/dist/useHotkeys.cjs.map +0 -1
- package/dist/useHotkeys.d.cts +0 -65
- package/dist/useHotkeys.js.map +0 -1
- package/dist/useKeyHold.cjs +0 -60
- package/dist/useKeyHold.cjs.map +0 -1
- package/dist/useKeyHold.d.cts +0 -52
- package/dist/useKeyHold.js.map +0 -1
- package/src/HotkeysProvider.tsx +0 -29
- package/src/HotkeysProviderContext.ts +0 -41
- package/src/index.ts +0 -18
- package/src/useHeldKeyCodes.ts +0 -34
- package/src/useHeldKeys.ts +0 -32
- package/src/useHotkey.ts +0 -213
- package/src/useHotkeyRecorder.ts +0 -112
- package/src/useHotkeyRegistrations.ts +0 -46
- package/src/useHotkeySequence.ts +0 -187
- package/src/useHotkeySequenceRecorder.ts +0 -75
- package/src/useHotkeySequences.ts +0 -221
- package/src/useHotkeys.ts +0 -221
- package/src/useKeyHold.ts +0 -65
- package/src/vue.d.ts +0 -6
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { Hotkey, HotkeyRecorderOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { MaybeRefOrGetter, Ref } from "vue";
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeyRecorder.d.ts
|
|
5
|
-
interface VueHotkeyRecorder {
|
|
6
|
-
/** Whether recording is currently active */
|
|
7
|
-
isRecording: Ref<boolean>;
|
|
8
|
-
/** The currently recorded hotkey (for live preview) */
|
|
9
|
-
recordedHotkey: Ref<Hotkey | null>;
|
|
10
|
-
/** Start recording a new hotkey */
|
|
11
|
-
startRecording: () => void;
|
|
12
|
-
/** Stop recording (same as cancel) */
|
|
13
|
-
stopRecording: () => void;
|
|
14
|
-
/** Cancel recording without saving */
|
|
15
|
-
cancelRecording: () => void;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Vue composable for recording keyboard shortcuts.
|
|
19
|
-
*
|
|
20
|
-
* This composable provides a thin wrapper around the framework-agnostic `HotkeyRecorder`
|
|
21
|
-
* class, managing all the complexity of capturing keyboard events, converting them
|
|
22
|
-
* to hotkey strings, and handling edge cases like Escape to cancel or Backspace/Delete
|
|
23
|
-
* to clear.
|
|
24
|
-
*
|
|
25
|
-
* @param options - Configuration options for the recorder
|
|
26
|
-
* @returns An object with recording state and control functions
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```vue
|
|
30
|
-
* <script setup>
|
|
31
|
-
* import { ref } from 'vue'
|
|
32
|
-
* import { useHotkeyRecorder } from '@tanstack/vue-hotkeys'
|
|
33
|
-
*
|
|
34
|
-
* const shortcut = ref<Hotkey>('Mod+S')
|
|
35
|
-
*
|
|
36
|
-
* const recorder = useHotkeyRecorder({
|
|
37
|
-
* onRecord: (hotkey) => {
|
|
38
|
-
* shortcut.value = hotkey
|
|
39
|
-
* },
|
|
40
|
-
* onCancel: () => {
|
|
41
|
-
* console.log('Recording cancelled')
|
|
42
|
-
* },
|
|
43
|
-
* })
|
|
44
|
-
* </script>
|
|
45
|
-
*
|
|
46
|
-
* <template>
|
|
47
|
-
* <div>
|
|
48
|
-
* <button @click="recorder.startRecording()">
|
|
49
|
-
* {{ recorder.isRecording ? 'Recording...' : 'Edit Shortcut' }}
|
|
50
|
-
* </button>
|
|
51
|
-
* <div v-if="recorder.recordedHotkey">
|
|
52
|
-
* Recording: {{ recorder.recordedHotkey }}
|
|
53
|
-
* </div>
|
|
54
|
-
* </div>
|
|
55
|
-
* </template>
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
declare function useHotkeyRecorder(options: MaybeRefOrGetter<HotkeyRecorderOptions>): VueHotkeyRecorder;
|
|
59
|
-
//#endregion
|
|
60
|
-
export { VueHotkeyRecorder, useHotkeyRecorder };
|
|
61
|
-
//# sourceMappingURL=useHotkeyRecorder.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeyRecorder.js","names":[],"sources":["../src/useHotkeyRecorder.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { useSelector } 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 useSelector\n const isRecording = useSelector(recorder.store, (state) => state.isRecording)\n const recordedHotkey = useSelector(\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,iBAAiB,0BAA0B;CACjD,MAAM,WAAW,IAAI,eACnB,uBAAuB,SAAS,eAAe,CAChD;CAGD,MAAM,cAAc,YAAY,SAAS,QAAQ,UAAU,MAAM,YAAY;CAC7E,MAAM,iBAAiB,YACrB,SAAS,QACR,UAAU,MAAM,eAClB;CAED,MAAM,cAAc,YACZ,uBAAuB,SAAS,eAAe,GACpD,oBAAoB;AACnB,WAAS,WAAW,gBAAgB;IAEtC,EAAE,WAAW,MAAM,CACpB;AAGD,mBAAkB;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,GAAG,MAAM,MAAM"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
let _tanstack_hotkeys = require("@tanstack/hotkeys");
|
|
2
|
-
let _tanstack_vue_store = require("@tanstack/vue-store");
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeyRegistrations.ts
|
|
5
|
-
/**
|
|
6
|
-
* Vue composable that reactively reads all hotkey and sequence registrations
|
|
7
|
-
* from the singleton managers.
|
|
8
|
-
*
|
|
9
|
-
* This is a standalone composable that does NOT require the HotkeysProvider.
|
|
10
|
-
* It subscribes to both HotkeyManager and SequenceManager stores and
|
|
11
|
-
* triggers reactivity when registrations change.
|
|
12
|
-
*
|
|
13
|
-
* @returns Object with `hotkeys` and `sequences` refs
|
|
14
|
-
*/
|
|
15
|
-
function useHotkeyRegistrations() {
|
|
16
|
-
const hotkeyManager = (0, _tanstack_hotkeys.getHotkeyManager)();
|
|
17
|
-
const sequenceManager = (0, _tanstack_hotkeys.getSequenceManager)();
|
|
18
|
-
return {
|
|
19
|
-
hotkeys: (0, _tanstack_vue_store.useSelector)(hotkeyManager.registrations, (state) => Array.from(state.values()).map(_tanstack_hotkeys.toHotkeyRegistrationView)),
|
|
20
|
-
sequences: (0, _tanstack_vue_store.useSelector)(sequenceManager.registrations, (state) => Array.from(state.values()))
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
exports.useHotkeyRegistrations = useHotkeyRegistrations;
|
|
26
|
-
//# sourceMappingURL=useHotkeyRegistrations.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeyRegistrations.cjs","names":["toHotkeyRegistrationView"],"sources":["../src/useHotkeyRegistrations.ts"],"sourcesContent":["import { useSelector } from '@tanstack/vue-store'\nimport {\n getHotkeyManager,\n getSequenceManager,\n toHotkeyRegistrationView,\n} from '@tanstack/hotkeys'\nimport type {\n HotkeyRegistrationView,\n SequenceRegistrationView,\n} from '@tanstack/hotkeys'\nimport type { Ref } from 'vue'\n\n/**\n * Return type for useHotkeyRegistrations.\n */\nexport interface HotkeyRegistrationsResult {\n /** All registered hotkeys (public view, no callbacks) */\n hotkeys: Ref<Array<HotkeyRegistrationView>>\n /** All registered sequences */\n sequences: Ref<Array<SequenceRegistrationView>>\n}\n\n/**\n * Vue composable that reactively reads all hotkey and sequence registrations\n * from the singleton managers.\n *\n * This is a standalone composable that does NOT require the HotkeysProvider.\n * It subscribes to both HotkeyManager and SequenceManager stores and\n * triggers reactivity when registrations change.\n *\n * @returns Object with `hotkeys` and `sequences` refs\n */\nexport function useHotkeyRegistrations(): HotkeyRegistrationsResult {\n const hotkeyManager = getHotkeyManager()\n const sequenceManager = getSequenceManager()\n\n const hotkeys = useSelector(hotkeyManager.registrations, (state) =>\n Array.from(state.values()).map(toHotkeyRegistrationView),\n )\n\n const sequences = useSelector(sequenceManager.registrations, (state) =>\n Array.from(state.values()),\n )\n\n return { hotkeys, sequences }\n}\n"],"mappings":";;;;;;;;;;;;;;AAgCA,SAAgB,yBAAoD;CAClE,MAAM,yDAAkC;CACxC,MAAM,6DAAsC;AAU5C,QAAO;EAAE,8CARmB,cAAc,gBAAgB,UACxD,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,IAAIA,2CAAyB,CACzD;EAMiB,gDAJY,gBAAgB,gBAAgB,UAC5D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAC3B;EAE4B"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { HotkeyRegistrationView, SequenceRegistrationView } from "@tanstack/hotkeys";
|
|
2
|
-
import { Ref } from "vue";
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeyRegistrations.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Return type for useHotkeyRegistrations.
|
|
7
|
-
*/
|
|
8
|
-
interface HotkeyRegistrationsResult {
|
|
9
|
-
/** All registered hotkeys (public view, no callbacks) */
|
|
10
|
-
hotkeys: Ref<Array<HotkeyRegistrationView>>;
|
|
11
|
-
/** All registered sequences */
|
|
12
|
-
sequences: Ref<Array<SequenceRegistrationView>>;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Vue composable that reactively reads all hotkey and sequence registrations
|
|
16
|
-
* from the singleton managers.
|
|
17
|
-
*
|
|
18
|
-
* This is a standalone composable that does NOT require the HotkeysProvider.
|
|
19
|
-
* It subscribes to both HotkeyManager and SequenceManager stores and
|
|
20
|
-
* triggers reactivity when registrations change.
|
|
21
|
-
*
|
|
22
|
-
* @returns Object with `hotkeys` and `sequences` refs
|
|
23
|
-
*/
|
|
24
|
-
declare function useHotkeyRegistrations(): HotkeyRegistrationsResult;
|
|
25
|
-
//#endregion
|
|
26
|
-
export { HotkeyRegistrationsResult, useHotkeyRegistrations };
|
|
27
|
-
//# sourceMappingURL=useHotkeyRegistrations.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeyRegistrations.js","names":[],"sources":["../src/useHotkeyRegistrations.ts"],"sourcesContent":["import { useSelector } from '@tanstack/vue-store'\nimport {\n getHotkeyManager,\n getSequenceManager,\n toHotkeyRegistrationView,\n} from '@tanstack/hotkeys'\nimport type {\n HotkeyRegistrationView,\n SequenceRegistrationView,\n} from '@tanstack/hotkeys'\nimport type { Ref } from 'vue'\n\n/**\n * Return type for useHotkeyRegistrations.\n */\nexport interface HotkeyRegistrationsResult {\n /** All registered hotkeys (public view, no callbacks) */\n hotkeys: Ref<Array<HotkeyRegistrationView>>\n /** All registered sequences */\n sequences: Ref<Array<SequenceRegistrationView>>\n}\n\n/**\n * Vue composable that reactively reads all hotkey and sequence registrations\n * from the singleton managers.\n *\n * This is a standalone composable that does NOT require the HotkeysProvider.\n * It subscribes to both HotkeyManager and SequenceManager stores and\n * triggers reactivity when registrations change.\n *\n * @returns Object with `hotkeys` and `sequences` refs\n */\nexport function useHotkeyRegistrations(): HotkeyRegistrationsResult {\n const hotkeyManager = getHotkeyManager()\n const sequenceManager = getSequenceManager()\n\n const hotkeys = useSelector(hotkeyManager.registrations, (state) =>\n Array.from(state.values()).map(toHotkeyRegistrationView),\n )\n\n const sequences = useSelector(sequenceManager.registrations, (state) =>\n Array.from(state.values()),\n )\n\n return { hotkeys, sequences }\n}\n"],"mappings":";;;;;;;;;;;;;;AAgCA,SAAgB,yBAAoD;CAClE,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,kBAAkB,oBAAoB;AAU5C,QAAO;EAAE,SARO,YAAY,cAAc,gBAAgB,UACxD,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,IAAI,yBAAyB,CACzD;EAMiB,WAJA,YAAY,gBAAgB,gBAAgB,UAC5D,MAAM,KAAK,MAAM,QAAQ,CAAC,CAC3B;EAE4B"}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
const require_HotkeysProviderContext = require('./HotkeysProviderContext.cjs');
|
|
2
|
-
let _tanstack_hotkeys = require("@tanstack/hotkeys");
|
|
3
|
-
let vue = require("vue");
|
|
4
|
-
|
|
5
|
-
//#region src/useHotkeySequence.ts
|
|
6
|
-
/**
|
|
7
|
-
* Vue composable for registering a keyboard shortcut sequence (Vim-style).
|
|
8
|
-
*
|
|
9
|
-
* This composable allows you to register multi-key sequences like 'g g' or 'd d'
|
|
10
|
-
* that trigger when the full sequence is pressed within a timeout.
|
|
11
|
-
*
|
|
12
|
-
* Each step may include modifiers. You can chain the same modifier across
|
|
13
|
-
* steps (e.g. `Shift+R` then `Shift+T`). Modifier-only keydown events (Shift,
|
|
14
|
-
* Control, Alt, or Meta pressed alone) are ignored while matching—they do not
|
|
15
|
-
* advance the sequence or reset progress.
|
|
16
|
-
*
|
|
17
|
-
* @param sequence - Array of hotkey strings that form the sequence
|
|
18
|
-
* @param callback - Function to call when the sequence is completed
|
|
19
|
-
* @param options - Options for the sequence behavior
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```vue
|
|
23
|
-
* <script setup>
|
|
24
|
-
* import { useHotkeySequence } from '@tanstack/vue-hotkeys'
|
|
25
|
-
*
|
|
26
|
-
* // 'g g' to go to top
|
|
27
|
-
* useHotkeySequence(['G', 'G'], () => {
|
|
28
|
-
* scrollToTop()
|
|
29
|
-
* })
|
|
30
|
-
*
|
|
31
|
-
* // 'd d' to delete line
|
|
32
|
-
* useHotkeySequence(['D', 'D'], () => {
|
|
33
|
-
* deleteLine()
|
|
34
|
-
* })
|
|
35
|
-
*
|
|
36
|
-
* // 'd i w' to delete inner word
|
|
37
|
-
* useHotkeySequence(['D', 'I', 'W'], () => {
|
|
38
|
-
* deleteInnerWord()
|
|
39
|
-
* }, { timeout: 500 })
|
|
40
|
-
*
|
|
41
|
-
* // Same modifier on consecutive steps (bare Shift between chords is ignored)
|
|
42
|
-
* useHotkeySequence(['Shift+R', 'Shift+T'], () => {
|
|
43
|
-
* nextAction()
|
|
44
|
-
* })
|
|
45
|
-
* <\/script>
|
|
46
|
-
*
|
|
47
|
-
* <template>
|
|
48
|
-
* <div>...</div>
|
|
49
|
-
* </template>
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
function useHotkeySequence(sequence, callback, options = {}) {
|
|
53
|
-
const defaultOptions = require_HotkeysProviderContext.useDefaultHotkeysOptions();
|
|
54
|
-
const manager = (0, _tanstack_hotkeys.getSequenceManager)();
|
|
55
|
-
let registration = null;
|
|
56
|
-
let lastSequenceKey = null;
|
|
57
|
-
let lastTarget = null;
|
|
58
|
-
const stopWatcher = (0, vue.watch)(() => {
|
|
59
|
-
const resolvedSequence = resolveMaybeRefOrGetter(sequence);
|
|
60
|
-
const resolvedOptions = resolveMaybeRefOrGetter(options);
|
|
61
|
-
const mergedOptions = {
|
|
62
|
-
...defaultOptions.hotkeySequence,
|
|
63
|
-
...resolvedOptions
|
|
64
|
-
};
|
|
65
|
-
return {
|
|
66
|
-
resolvedSequence,
|
|
67
|
-
mergedOptions,
|
|
68
|
-
resolvedEnabled: mergedOptions.enabled === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.enabled),
|
|
69
|
-
resolvedTarget: mergedOptions.target === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.target)
|
|
70
|
-
};
|
|
71
|
-
}, ({ resolvedSequence, mergedOptions, resolvedEnabled, resolvedTarget }) => {
|
|
72
|
-
const finalTarget = resolvedTarget === void 0 ? typeof document !== "undefined" ? document : null : resolvedTarget;
|
|
73
|
-
if (resolvedSequence.length === 0 || !finalTarget) {
|
|
74
|
-
if (registration?.isActive) {
|
|
75
|
-
registration.unregister();
|
|
76
|
-
registration = null;
|
|
77
|
-
}
|
|
78
|
-
lastSequenceKey = null;
|
|
79
|
-
lastTarget = null;
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
const sequenceKey = (0, _tanstack_hotkeys.formatHotkeySequence)(resolvedSequence);
|
|
83
|
-
const { target: _target, enabled: _enabled, ...restOptions } = mergedOptions;
|
|
84
|
-
const optionsWithoutTarget = {
|
|
85
|
-
...restOptions,
|
|
86
|
-
...resolvedEnabled === void 0 ? {} : { enabled: resolvedEnabled }
|
|
87
|
-
};
|
|
88
|
-
if (registration?.isActive && lastSequenceKey === sequenceKey && lastTarget === finalTarget) {
|
|
89
|
-
registration.callback = callback;
|
|
90
|
-
registration.setOptions(optionsWithoutTarget);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (registration?.isActive) {
|
|
94
|
-
registration.unregister();
|
|
95
|
-
registration = null;
|
|
96
|
-
}
|
|
97
|
-
registration = manager.register(resolvedSequence, callback, {
|
|
98
|
-
...optionsWithoutTarget,
|
|
99
|
-
target: finalTarget
|
|
100
|
-
});
|
|
101
|
-
if (registration.isActive) {
|
|
102
|
-
registration.callback = callback;
|
|
103
|
-
registration.setOptions(optionsWithoutTarget);
|
|
104
|
-
}
|
|
105
|
-
lastSequenceKey = sequenceKey;
|
|
106
|
-
lastTarget = finalTarget;
|
|
107
|
-
}, { immediate: true });
|
|
108
|
-
(0, vue.onUnmounted)(() => {
|
|
109
|
-
stopWatcher();
|
|
110
|
-
if (registration?.isActive) {
|
|
111
|
-
registration.unregister();
|
|
112
|
-
registration = null;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
function resolveMaybeRefOrGetter(value) {
|
|
117
|
-
return typeof value === "function" ? value() : (0, vue.unref)(value);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
//#endregion
|
|
121
|
-
exports.useHotkeySequence = useHotkeySequence;
|
|
122
|
-
//# sourceMappingURL=useHotkeySequence.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeySequence.cjs","names":["useDefaultHotkeysOptions"],"sources":["../src/useHotkeySequence.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { formatHotkeySequence, getSequenceManager } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { MaybeRefOrGetter } from 'vue'\nimport type {\n HotkeyCallback,\n HotkeySequence,\n SequenceOptions,\n SequenceRegistrationHandle,\n} from '@tanstack/hotkeys'\n\nexport interface UseHotkeySequenceOptions extends Omit<\n SequenceOptions,\n 'enabled' | 'target'\n> {\n /**\n * Whether the sequence 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 shortcut sequence (Vim-style).\n *\n * This composable allows you to register multi-key sequences like 'g g' or 'd d'\n * that trigger when the full sequence is pressed within a timeout.\n *\n * Each step may include modifiers. You can chain the same modifier across\n * steps (e.g. `Shift+R` then `Shift+T`). Modifier-only keydown events (Shift,\n * Control, Alt, or Meta pressed alone) are ignored while matching—they do not\n * advance the sequence or reset progress.\n *\n * @param sequence - Array of hotkey strings that form the sequence\n * @param callback - Function to call when the sequence is completed\n * @param options - Options for the sequence behavior\n *\n * @example\n * ```vue\n * <script setup>\n * import { useHotkeySequence } from '@tanstack/vue-hotkeys'\n *\n * // 'g g' to go to top\n * useHotkeySequence(['G', 'G'], () => {\n * scrollToTop()\n * })\n *\n * // 'd d' to delete line\n * useHotkeySequence(['D', 'D'], () => {\n * deleteLine()\n * })\n *\n * // 'd i w' to delete inner word\n * useHotkeySequence(['D', 'I', 'W'], () => {\n * deleteInnerWord()\n * }, { timeout: 500 })\n *\n * // Same modifier on consecutive steps (bare Shift between chords is ignored)\n * useHotkeySequence(['Shift+R', 'Shift+T'], () => {\n * nextAction()\n * })\n * </script>\n *\n * <template>\n * <div>...</div>\n * </template>\n * ```\n */\nexport function useHotkeySequence(\n sequence: MaybeRefOrGetter<HotkeySequence>,\n callback: HotkeyCallback,\n options: MaybeRefOrGetter<UseHotkeySequenceOptions> = {},\n): void {\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getSequenceManager()\n\n let registration: SequenceRegistrationHandle | null = null\n let lastSequenceKey: string | null = null\n let lastTarget: HTMLElement | Document | Window | null = null\n\n // Watch for changes to reactive dependencies\n const stopWatcher = watch(\n () => {\n const resolvedSequence = resolveMaybeRefOrGetter(sequence)\n const resolvedOptions = resolveMaybeRefOrGetter(options)\n const mergedOptions = {\n ...defaultOptions.hotkeySequence,\n ...resolvedOptions,\n } as UseHotkeySequenceOptions\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 resolvedSequence,\n mergedOptions,\n resolvedEnabled,\n resolvedTarget,\n }\n },\n ({ resolvedSequence, mergedOptions, resolvedEnabled, resolvedTarget }) => {\n const finalTarget =\n resolvedTarget === undefined\n ? typeof document !== 'undefined'\n ? document\n : null\n : resolvedTarget\n\n if (resolvedSequence.length === 0 || !finalTarget) {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastSequenceKey = null\n lastTarget = null\n return\n }\n\n const sequenceKey = formatHotkeySequence(resolvedSequence)\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 if (\n registration?.isActive &&\n lastSequenceKey === sequenceKey &&\n lastTarget === finalTarget\n ) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n return\n }\n\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n registration = manager.register(resolvedSequence, callback, {\n ...optionsWithoutTarget,\n target: finalTarget,\n })\n\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n\n lastSequenceKey = sequenceKey\n lastTarget = finalTarget\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2EA,SAAgB,kBACd,UACA,UACA,UAAsD,EAAE,EAClD;CACN,MAAM,iBAAiBA,yDAA0B;CACjD,MAAM,qDAA8B;CAEpC,IAAI,eAAkD;CACtD,IAAI,kBAAiC;CACrC,IAAI,aAAqD;CAGzD,MAAM,mCACE;EACJ,MAAM,mBAAmB,wBAAwB,SAAS;EAC1D,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,kBAAkB,eAAe,iBAAiB,qBAAqB;EACxE,MAAM,cACJ,mBAAmB,SACf,OAAO,aAAa,cAClB,WACA,OACF;AAEN,MAAI,iBAAiB,WAAW,KAAK,CAAC,aAAa;AACjD,OAAI,cAAc,UAAU;AAC1B,iBAAa,YAAY;AACzB,mBAAe;;AAEjB,qBAAkB;AAClB,gBAAa;AACb;;EAGF,MAAM,0DAAmC,iBAAiB;EAG1D,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD;EACJ,MAAM,uBAAuB;GAC3B,GAAG;GACH,GAAI,oBAAoB,SAAY,EAAE,GAAG,EAAE,SAAS,iBAAiB;GACtE;AAED,MACE,cAAc,YACd,oBAAoB,eACpB,eAAe,aACf;AACA,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;AAC7C;;AAGF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAGjB,iBAAe,QAAQ,SAAS,kBAAkB,UAAU;GAC1D,GAAG;GACH,QAAQ;GACT,CAAC;AAEF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;AAG/C,oBAAkB;AAClB,eAAa;IAEf,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"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { HotkeyCallback, HotkeySequence, SequenceOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { MaybeRefOrGetter } from "vue";
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeySequence.d.ts
|
|
5
|
-
interface UseHotkeySequenceOptions extends Omit<SequenceOptions, 'enabled' | 'target'> {
|
|
6
|
-
/**
|
|
7
|
-
* Whether the sequence 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 shortcut sequence (Vim-style).
|
|
21
|
-
*
|
|
22
|
-
* This composable allows you to register multi-key sequences like 'g g' or 'd d'
|
|
23
|
-
* that trigger when the full sequence is pressed within a timeout.
|
|
24
|
-
*
|
|
25
|
-
* Each step may include modifiers. You can chain the same modifier across
|
|
26
|
-
* steps (e.g. `Shift+R` then `Shift+T`). Modifier-only keydown events (Shift,
|
|
27
|
-
* Control, Alt, or Meta pressed alone) are ignored while matching—they do not
|
|
28
|
-
* advance the sequence or reset progress.
|
|
29
|
-
*
|
|
30
|
-
* @param sequence - Array of hotkey strings that form the sequence
|
|
31
|
-
* @param callback - Function to call when the sequence is completed
|
|
32
|
-
* @param options - Options for the sequence behavior
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```vue
|
|
36
|
-
* <script setup>
|
|
37
|
-
* import { useHotkeySequence } from '@tanstack/vue-hotkeys'
|
|
38
|
-
*
|
|
39
|
-
* // 'g g' to go to top
|
|
40
|
-
* useHotkeySequence(['G', 'G'], () => {
|
|
41
|
-
* scrollToTop()
|
|
42
|
-
* })
|
|
43
|
-
*
|
|
44
|
-
* // 'd d' to delete line
|
|
45
|
-
* useHotkeySequence(['D', 'D'], () => {
|
|
46
|
-
* deleteLine()
|
|
47
|
-
* })
|
|
48
|
-
*
|
|
49
|
-
* // 'd i w' to delete inner word
|
|
50
|
-
* useHotkeySequence(['D', 'I', 'W'], () => {
|
|
51
|
-
* deleteInnerWord()
|
|
52
|
-
* }, { timeout: 500 })
|
|
53
|
-
*
|
|
54
|
-
* // Same modifier on consecutive steps (bare Shift between chords is ignored)
|
|
55
|
-
* useHotkeySequence(['Shift+R', 'Shift+T'], () => {
|
|
56
|
-
* nextAction()
|
|
57
|
-
* })
|
|
58
|
-
* </script>
|
|
59
|
-
*
|
|
60
|
-
* <template>
|
|
61
|
-
* <div>...</div>
|
|
62
|
-
* </template>
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
declare function useHotkeySequence(sequence: MaybeRefOrGetter<HotkeySequence>, callback: HotkeyCallback, options?: MaybeRefOrGetter<UseHotkeySequenceOptions>): void;
|
|
66
|
-
//#endregion
|
|
67
|
-
export { UseHotkeySequenceOptions, useHotkeySequence };
|
|
68
|
-
//# sourceMappingURL=useHotkeySequence.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeySequence.js","names":[],"sources":["../src/useHotkeySequence.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { formatHotkeySequence, getSequenceManager } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { MaybeRefOrGetter } from 'vue'\nimport type {\n HotkeyCallback,\n HotkeySequence,\n SequenceOptions,\n SequenceRegistrationHandle,\n} from '@tanstack/hotkeys'\n\nexport interface UseHotkeySequenceOptions extends Omit<\n SequenceOptions,\n 'enabled' | 'target'\n> {\n /**\n * Whether the sequence 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 shortcut sequence (Vim-style).\n *\n * This composable allows you to register multi-key sequences like 'g g' or 'd d'\n * that trigger when the full sequence is pressed within a timeout.\n *\n * Each step may include modifiers. You can chain the same modifier across\n * steps (e.g. `Shift+R` then `Shift+T`). Modifier-only keydown events (Shift,\n * Control, Alt, or Meta pressed alone) are ignored while matching—they do not\n * advance the sequence or reset progress.\n *\n * @param sequence - Array of hotkey strings that form the sequence\n * @param callback - Function to call when the sequence is completed\n * @param options - Options for the sequence behavior\n *\n * @example\n * ```vue\n * <script setup>\n * import { useHotkeySequence } from '@tanstack/vue-hotkeys'\n *\n * // 'g g' to go to top\n * useHotkeySequence(['G', 'G'], () => {\n * scrollToTop()\n * })\n *\n * // 'd d' to delete line\n * useHotkeySequence(['D', 'D'], () => {\n * deleteLine()\n * })\n *\n * // 'd i w' to delete inner word\n * useHotkeySequence(['D', 'I', 'W'], () => {\n * deleteInnerWord()\n * }, { timeout: 500 })\n *\n * // Same modifier on consecutive steps (bare Shift between chords is ignored)\n * useHotkeySequence(['Shift+R', 'Shift+T'], () => {\n * nextAction()\n * })\n * </script>\n *\n * <template>\n * <div>...</div>\n * </template>\n * ```\n */\nexport function useHotkeySequence(\n sequence: MaybeRefOrGetter<HotkeySequence>,\n callback: HotkeyCallback,\n options: MaybeRefOrGetter<UseHotkeySequenceOptions> = {},\n): void {\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getSequenceManager()\n\n let registration: SequenceRegistrationHandle | null = null\n let lastSequenceKey: string | null = null\n let lastTarget: HTMLElement | Document | Window | null = null\n\n // Watch for changes to reactive dependencies\n const stopWatcher = watch(\n () => {\n const resolvedSequence = resolveMaybeRefOrGetter(sequence)\n const resolvedOptions = resolveMaybeRefOrGetter(options)\n const mergedOptions = {\n ...defaultOptions.hotkeySequence,\n ...resolvedOptions,\n } as UseHotkeySequenceOptions\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 resolvedSequence,\n mergedOptions,\n resolvedEnabled,\n resolvedTarget,\n }\n },\n ({ resolvedSequence, mergedOptions, resolvedEnabled, resolvedTarget }) => {\n const finalTarget =\n resolvedTarget === undefined\n ? typeof document !== 'undefined'\n ? document\n : null\n : resolvedTarget\n\n if (resolvedSequence.length === 0 || !finalTarget) {\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n lastSequenceKey = null\n lastTarget = null\n return\n }\n\n const sequenceKey = formatHotkeySequence(resolvedSequence)\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 if (\n registration?.isActive &&\n lastSequenceKey === sequenceKey &&\n lastTarget === finalTarget\n ) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n return\n }\n\n if (registration?.isActive) {\n registration.unregister()\n registration = null\n }\n\n registration = manager.register(resolvedSequence, callback, {\n ...optionsWithoutTarget,\n target: finalTarget,\n })\n\n if (registration.isActive) {\n registration.callback = callback\n registration.setOptions(optionsWithoutTarget)\n }\n\n lastSequenceKey = sequenceKey\n lastTarget = finalTarget\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2EA,SAAgB,kBACd,UACA,UACA,UAAsD,EAAE,EAClD;CACN,MAAM,iBAAiB,0BAA0B;CACjD,MAAM,UAAU,oBAAoB;CAEpC,IAAI,eAAkD;CACtD,IAAI,kBAAiC;CACrC,IAAI,aAAqD;CAGzD,MAAM,cAAc,YACZ;EACJ,MAAM,mBAAmB,wBAAwB,SAAS;EAC1D,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,kBAAkB,eAAe,iBAAiB,qBAAqB;EACxE,MAAM,cACJ,mBAAmB,SACf,OAAO,aAAa,cAClB,WACA,OACF;AAEN,MAAI,iBAAiB,WAAW,KAAK,CAAC,aAAa;AACjD,OAAI,cAAc,UAAU;AAC1B,iBAAa,YAAY;AACzB,mBAAe;;AAEjB,qBAAkB;AAClB,gBAAa;AACb;;EAGF,MAAM,cAAc,qBAAqB,iBAAiB;EAG1D,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD;EACJ,MAAM,uBAAuB;GAC3B,GAAG;GACH,GAAI,oBAAoB,SAAY,EAAE,GAAG,EAAE,SAAS,iBAAiB;GACtE;AAED,MACE,cAAc,YACd,oBAAoB,eACpB,eAAe,aACf;AACA,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;AAC7C;;AAGF,MAAI,cAAc,UAAU;AAC1B,gBAAa,YAAY;AACzB,kBAAe;;AAGjB,iBAAe,QAAQ,SAAS,kBAAkB,UAAU;GAC1D,GAAG;GACH,QAAQ;GACT,CAAC;AAEF,MAAI,aAAa,UAAU;AACzB,gBAAa,WAAW;AACxB,gBAAa,WAAW,qBAAqB;;AAG/C,oBAAkB;AAClB,eAAa;IAEf,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"}
|
|
@@ -1,45 +0,0 @@
|
|
|
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/useHotkeySequenceRecorder.ts
|
|
7
|
-
/**
|
|
8
|
-
* Vue composable for recording multi-chord sequences (Vim-style shortcuts).
|
|
9
|
-
*/
|
|
10
|
-
function useHotkeySequenceRecorder(options) {
|
|
11
|
-
const defaultOptions = require_HotkeysProviderContext.useDefaultHotkeysOptions();
|
|
12
|
-
const recorder = new _tanstack_hotkeys.HotkeySequenceRecorder(resolveHotkeySequenceRecorderOptions(options, defaultOptions));
|
|
13
|
-
const isRecording = (0, _tanstack_vue_store.useSelector)(recorder.store, (state) => state.isRecording);
|
|
14
|
-
const steps = (0, _tanstack_vue_store.useSelector)(recorder.store, (state) => state.steps);
|
|
15
|
-
const recordedSequence = (0, _tanstack_vue_store.useSelector)(recorder.store, (state) => state.recordedSequence);
|
|
16
|
-
const stopWatcher = (0, vue.watch)(() => resolveHotkeySequenceRecorderOptions(options, defaultOptions), (resolvedOptions) => {
|
|
17
|
-
recorder.setOptions(resolvedOptions);
|
|
18
|
-
}, { immediate: true });
|
|
19
|
-
(0, vue.onUnmounted)(() => {
|
|
20
|
-
stopWatcher();
|
|
21
|
-
recorder.destroy();
|
|
22
|
-
});
|
|
23
|
-
return {
|
|
24
|
-
isRecording,
|
|
25
|
-
steps,
|
|
26
|
-
recordedSequence,
|
|
27
|
-
startRecording: () => recorder.start(),
|
|
28
|
-
stopRecording: () => recorder.stop(),
|
|
29
|
-
cancelRecording: () => recorder.cancel(),
|
|
30
|
-
commitRecording: () => recorder.commit()
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function resolveHotkeySequenceRecorderOptions(options, defaultOptions) {
|
|
34
|
-
return {
|
|
35
|
-
...defaultOptions.hotkeySequenceRecorder,
|
|
36
|
-
...resolveMaybeRefOrGetter(options)
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function resolveMaybeRefOrGetter(value) {
|
|
40
|
-
return typeof value === "function" ? value() : (0, vue.unref)(value);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
44
|
-
exports.useHotkeySequenceRecorder = useHotkeySequenceRecorder;
|
|
45
|
-
//# sourceMappingURL=useHotkeySequenceRecorder.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeySequenceRecorder.cjs","names":["useDefaultHotkeysOptions","HotkeySequenceRecorder"],"sources":["../src/useHotkeySequenceRecorder.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { useSelector } from '@tanstack/vue-store'\nimport { HotkeySequenceRecorder } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { MaybeRefOrGetter, Ref } from 'vue'\nimport type {\n HotkeySequence,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\n\nexport interface VueHotkeySequenceRecorder {\n isRecording: Ref<boolean>\n steps: Ref<HotkeySequence>\n recordedSequence: Ref<HotkeySequence | null>\n startRecording: () => void\n stopRecording: () => void\n cancelRecording: () => void\n commitRecording: () => void\n}\n\n/**\n * Vue composable for recording multi-chord sequences (Vim-style shortcuts).\n */\nexport function useHotkeySequenceRecorder(\n options: MaybeRefOrGetter<HotkeySequenceRecorderOptions>,\n): VueHotkeySequenceRecorder {\n const defaultOptions = useDefaultHotkeysOptions()\n const recorder = new HotkeySequenceRecorder(\n resolveHotkeySequenceRecorderOptions(options, defaultOptions),\n )\n\n const isRecording = useSelector(recorder.store, (state) => state.isRecording)\n const steps = useSelector(recorder.store, (state) => state.steps)\n const recordedSequence = useSelector(\n recorder.store,\n (state) => state.recordedSequence,\n )\n\n const stopWatcher = watch(\n () => resolveHotkeySequenceRecorderOptions(options, defaultOptions),\n (resolvedOptions) => {\n recorder.setOptions(resolvedOptions)\n },\n { immediate: true },\n )\n\n onUnmounted(() => {\n stopWatcher()\n recorder.destroy()\n })\n\n return {\n isRecording: isRecording as Ref<boolean>,\n steps: steps as Ref<HotkeySequence>,\n recordedSequence: recordedSequence as Ref<HotkeySequence | null>,\n startRecording: () => recorder.start(),\n stopRecording: () => recorder.stop(),\n cancelRecording: () => recorder.cancel(),\n commitRecording: () => recorder.commit(),\n }\n}\n\nfunction resolveHotkeySequenceRecorderOptions(\n options: MaybeRefOrGetter<HotkeySequenceRecorderOptions>,\n defaultOptions: ReturnType<typeof useDefaultHotkeysOptions>,\n): HotkeySequenceRecorderOptions {\n return {\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolveMaybeRefOrGetter(options),\n } as HotkeySequenceRecorderOptions\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;AAuBA,SAAgB,0BACd,SAC2B;CAC3B,MAAM,iBAAiBA,yDAA0B;CACjD,MAAM,WAAW,IAAIC,yCACnB,qCAAqC,SAAS,eAAe,CAC9D;CAED,MAAM,mDAA0B,SAAS,QAAQ,UAAU,MAAM,YAAY;CAC7E,MAAM,6CAAoB,SAAS,QAAQ,UAAU,MAAM,MAAM;CACjE,MAAM,wDACJ,SAAS,QACR,UAAU,MAAM,iBAClB;CAED,MAAM,mCACE,qCAAqC,SAAS,eAAe,GAClE,oBAAoB;AACnB,WAAS,WAAW,gBAAgB;IAEtC,EAAE,WAAW,MAAM,CACpB;AAED,4BAAkB;AAChB,eAAa;AACb,WAAS,SAAS;GAClB;AAEF,QAAO;EACQ;EACN;EACW;EAClB,sBAAsB,SAAS,OAAO;EACtC,qBAAqB,SAAS,MAAM;EACpC,uBAAuB,SAAS,QAAQ;EACxC,uBAAuB,SAAS,QAAQ;EACzC;;AAGH,SAAS,qCACP,SACA,gBAC+B;AAC/B,QAAO;EACL,GAAG,eAAe;EAClB,GAAG,wBAAwB,QAAQ;EACpC;;AAGH,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,kBAAS,MAAM"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { HotkeySequence, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { MaybeRefOrGetter, Ref } from "vue";
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeySequenceRecorder.d.ts
|
|
5
|
-
interface VueHotkeySequenceRecorder {
|
|
6
|
-
isRecording: Ref<boolean>;
|
|
7
|
-
steps: Ref<HotkeySequence>;
|
|
8
|
-
recordedSequence: Ref<HotkeySequence | null>;
|
|
9
|
-
startRecording: () => void;
|
|
10
|
-
stopRecording: () => void;
|
|
11
|
-
cancelRecording: () => void;
|
|
12
|
-
commitRecording: () => void;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Vue composable for recording multi-chord sequences (Vim-style shortcuts).
|
|
16
|
-
*/
|
|
17
|
-
declare function useHotkeySequenceRecorder(options: MaybeRefOrGetter<HotkeySequenceRecorderOptions>): VueHotkeySequenceRecorder;
|
|
18
|
-
//#endregion
|
|
19
|
-
export { VueHotkeySequenceRecorder, useHotkeySequenceRecorder };
|
|
20
|
-
//# sourceMappingURL=useHotkeySequenceRecorder.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeySequenceRecorder.js","names":[],"sources":["../src/useHotkeySequenceRecorder.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { useSelector } from '@tanstack/vue-store'\nimport { HotkeySequenceRecorder } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { MaybeRefOrGetter, Ref } from 'vue'\nimport type {\n HotkeySequence,\n HotkeySequenceRecorderOptions,\n} from '@tanstack/hotkeys'\n\nexport interface VueHotkeySequenceRecorder {\n isRecording: Ref<boolean>\n steps: Ref<HotkeySequence>\n recordedSequence: Ref<HotkeySequence | null>\n startRecording: () => void\n stopRecording: () => void\n cancelRecording: () => void\n commitRecording: () => void\n}\n\n/**\n * Vue composable for recording multi-chord sequences (Vim-style shortcuts).\n */\nexport function useHotkeySequenceRecorder(\n options: MaybeRefOrGetter<HotkeySequenceRecorderOptions>,\n): VueHotkeySequenceRecorder {\n const defaultOptions = useDefaultHotkeysOptions()\n const recorder = new HotkeySequenceRecorder(\n resolveHotkeySequenceRecorderOptions(options, defaultOptions),\n )\n\n const isRecording = useSelector(recorder.store, (state) => state.isRecording)\n const steps = useSelector(recorder.store, (state) => state.steps)\n const recordedSequence = useSelector(\n recorder.store,\n (state) => state.recordedSequence,\n )\n\n const stopWatcher = watch(\n () => resolveHotkeySequenceRecorderOptions(options, defaultOptions),\n (resolvedOptions) => {\n recorder.setOptions(resolvedOptions)\n },\n { immediate: true },\n )\n\n onUnmounted(() => {\n stopWatcher()\n recorder.destroy()\n })\n\n return {\n isRecording: isRecording as Ref<boolean>,\n steps: steps as Ref<HotkeySequence>,\n recordedSequence: recordedSequence as Ref<HotkeySequence | null>,\n startRecording: () => recorder.start(),\n stopRecording: () => recorder.stop(),\n cancelRecording: () => recorder.cancel(),\n commitRecording: () => recorder.commit(),\n }\n}\n\nfunction resolveHotkeySequenceRecorderOptions(\n options: MaybeRefOrGetter<HotkeySequenceRecorderOptions>,\n defaultOptions: ReturnType<typeof useDefaultHotkeysOptions>,\n): HotkeySequenceRecorderOptions {\n return {\n ...defaultOptions.hotkeySequenceRecorder,\n ...resolveMaybeRefOrGetter(options),\n } as HotkeySequenceRecorderOptions\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;AAuBA,SAAgB,0BACd,SAC2B;CAC3B,MAAM,iBAAiB,0BAA0B;CACjD,MAAM,WAAW,IAAI,uBACnB,qCAAqC,SAAS,eAAe,CAC9D;CAED,MAAM,cAAc,YAAY,SAAS,QAAQ,UAAU,MAAM,YAAY;CAC7E,MAAM,QAAQ,YAAY,SAAS,QAAQ,UAAU,MAAM,MAAM;CACjE,MAAM,mBAAmB,YACvB,SAAS,QACR,UAAU,MAAM,iBAClB;CAED,MAAM,cAAc,YACZ,qCAAqC,SAAS,eAAe,GAClE,oBAAoB;AACnB,WAAS,WAAW,gBAAgB;IAEtC,EAAE,WAAW,MAAM,CACpB;AAED,mBAAkB;AAChB,eAAa;AACb,WAAS,SAAS;GAClB;AAEF,QAAO;EACQ;EACN;EACW;EAClB,sBAAsB,SAAS,OAAO;EACtC,qBAAqB,SAAS,MAAM;EACpC,uBAAuB,SAAS,QAAQ;EACxC,uBAAuB,SAAS,QAAQ;EACzC;;AAGH,SAAS,qCACP,SACA,gBAC+B;AAC/B,QAAO;EACL,GAAG,eAAe;EAClB,GAAG,wBAAwB,QAAQ;EACpC;;AAGH,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,GAAG,MAAM,MAAM"}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
const require_HotkeysProviderContext = require('./HotkeysProviderContext.cjs');
|
|
2
|
-
let _tanstack_hotkeys = require("@tanstack/hotkeys");
|
|
3
|
-
let vue = require("vue");
|
|
4
|
-
|
|
5
|
-
//#region src/useHotkeySequences.ts
|
|
6
|
-
/**
|
|
7
|
-
* Vue composable for registering multiple keyboard shortcut sequences at once (Vim-style).
|
|
8
|
-
*
|
|
9
|
-
* Uses the singleton SequenceManager. Accepts a dynamic array of definitions, or a getter/ref
|
|
10
|
-
* that returns one, so you can register variable-length lists safely.
|
|
11
|
-
*
|
|
12
|
-
* Options are merged in this order:
|
|
13
|
-
* HotkeysProvider defaults < commonOptions < per-definition options
|
|
14
|
-
*
|
|
15
|
-
* Definitions with an empty `sequence` are skipped (no registration).
|
|
16
|
-
*
|
|
17
|
-
* @param definitions - Array of sequence definitions, or a getter/ref
|
|
18
|
-
* @param commonOptions - Shared options applied to all sequences (overridden by per-definition options)
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```vue
|
|
22
|
-
* <script setup>
|
|
23
|
-
* import { useHotkeySequences } from '@tanstack/vue-hotkeys'
|
|
24
|
-
*
|
|
25
|
-
* useHotkeySequences([
|
|
26
|
-
* { sequence: ['G', 'G'], callback: () => scrollToTop() },
|
|
27
|
-
* { sequence: ['D', 'D'], callback: () => deleteLine() },
|
|
28
|
-
* ])
|
|
29
|
-
* <\/script>
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```vue
|
|
34
|
-
* <script setup>
|
|
35
|
-
* import { computed } from 'vue'
|
|
36
|
-
* import { useHotkeySequences } from '@tanstack/vue-hotkeys'
|
|
37
|
-
*
|
|
38
|
-
* const items = computed(() => [...])
|
|
39
|
-
* useHotkeySequences(
|
|
40
|
-
* () => items.value.map((item) => ({
|
|
41
|
-
* sequence: item.chords,
|
|
42
|
-
* callback: item.action,
|
|
43
|
-
* options: { enabled: item.enabled },
|
|
44
|
-
* })),
|
|
45
|
-
* { preventDefault: true },
|
|
46
|
-
* )
|
|
47
|
-
* <\/script>
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
function useHotkeySequences(definitions, commonOptions = {}) {
|
|
51
|
-
const defaultOptions = require_HotkeysProviderContext.useDefaultHotkeysOptions();
|
|
52
|
-
const manager = (0, _tanstack_hotkeys.getSequenceManager)();
|
|
53
|
-
const registrations = /* @__PURE__ */ new Map();
|
|
54
|
-
const stopWatcher = (0, vue.watch)(() => {
|
|
55
|
-
const resolvedDefinitions = resolveMaybeRefOrGetter(definitions);
|
|
56
|
-
const resolvedCommonOptions = resolveMaybeRefOrGetter(commonOptions);
|
|
57
|
-
return resolvedDefinitions.map((def, i) => {
|
|
58
|
-
const resolvedSequence = resolveMaybeRefOrGetter(def.sequence);
|
|
59
|
-
const resolvedDefOptions = def.options ? resolveMaybeRefOrGetter(def.options) : {};
|
|
60
|
-
const mergedOptions = {
|
|
61
|
-
...defaultOptions.hotkeySequence,
|
|
62
|
-
...resolvedCommonOptions,
|
|
63
|
-
...resolvedDefOptions
|
|
64
|
-
};
|
|
65
|
-
const sequenceString = (0, _tanstack_hotkeys.formatHotkeySequence)(resolvedSequence);
|
|
66
|
-
const resolvedEnabled = mergedOptions.enabled === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.enabled);
|
|
67
|
-
const resolvedTarget = mergedOptions.target === void 0 ? void 0 : resolveMaybeRefOrGetter(mergedOptions.target);
|
|
68
|
-
return {
|
|
69
|
-
index: i,
|
|
70
|
-
resolvedSequence,
|
|
71
|
-
sequenceString,
|
|
72
|
-
callback: def.callback,
|
|
73
|
-
mergedOptions,
|
|
74
|
-
resolvedEnabled,
|
|
75
|
-
resolvedTarget
|
|
76
|
-
};
|
|
77
|
-
});
|
|
78
|
-
}, (resolved) => {
|
|
79
|
-
const nextKeys = /* @__PURE__ */ new Set();
|
|
80
|
-
const prepared = [];
|
|
81
|
-
for (const entry of resolved) {
|
|
82
|
-
if (entry.resolvedSequence.length === 0) continue;
|
|
83
|
-
const finalTarget = entry.resolvedTarget ?? (typeof document !== "undefined" ? document : null);
|
|
84
|
-
if (!finalTarget) continue;
|
|
85
|
-
const registrationKey = `${entry.index}:${entry.sequenceString}`;
|
|
86
|
-
nextKeys.add(registrationKey);
|
|
87
|
-
prepared.push({
|
|
88
|
-
registrationKey,
|
|
89
|
-
entry,
|
|
90
|
-
finalTarget
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
for (const [key, record] of [...registrations.entries()]) if (!nextKeys.has(key)) {
|
|
94
|
-
if (record.handle.isActive) record.handle.unregister();
|
|
95
|
-
registrations.delete(key);
|
|
96
|
-
}
|
|
97
|
-
for (const { registrationKey, entry, finalTarget } of prepared) {
|
|
98
|
-
const existing = registrations.get(registrationKey);
|
|
99
|
-
if (existing?.handle.isActive && existing.target === finalTarget) {
|
|
100
|
-
existing.handle.callback = entry.callback;
|
|
101
|
-
const { target: _target, enabled: _enabled, ...restOptions } = entry.mergedOptions;
|
|
102
|
-
const optionsWithoutTarget = {
|
|
103
|
-
...restOptions,
|
|
104
|
-
...entry.resolvedEnabled === void 0 ? {} : { enabled: entry.resolvedEnabled }
|
|
105
|
-
};
|
|
106
|
-
existing.handle.setOptions(optionsWithoutTarget);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (existing) {
|
|
110
|
-
if (existing.handle.isActive) existing.handle.unregister();
|
|
111
|
-
registrations.delete(registrationKey);
|
|
112
|
-
}
|
|
113
|
-
const { target: _target, enabled: _enabled, ...restOptions } = entry.mergedOptions;
|
|
114
|
-
const optionsWithoutTarget = {
|
|
115
|
-
...restOptions,
|
|
116
|
-
...entry.resolvedEnabled === void 0 ? {} : { enabled: entry.resolvedEnabled }
|
|
117
|
-
};
|
|
118
|
-
const handle = manager.register(entry.resolvedSequence, entry.callback, {
|
|
119
|
-
...optionsWithoutTarget,
|
|
120
|
-
target: finalTarget
|
|
121
|
-
});
|
|
122
|
-
registrations.set(registrationKey, {
|
|
123
|
-
handle,
|
|
124
|
-
target: finalTarget
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}, { immediate: true });
|
|
128
|
-
(0, vue.onUnmounted)(() => {
|
|
129
|
-
stopWatcher();
|
|
130
|
-
for (const { handle } of registrations.values()) if (handle.isActive) handle.unregister();
|
|
131
|
-
registrations.clear();
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
function resolveMaybeRefOrGetter(value) {
|
|
135
|
-
return typeof value === "function" ? value() : (0, vue.unref)(value);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
//#endregion
|
|
139
|
-
exports.useHotkeySequences = useHotkeySequences;
|
|
140
|
-
//# sourceMappingURL=useHotkeySequences.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHotkeySequences.cjs","names":["useDefaultHotkeysOptions"],"sources":["../src/useHotkeySequences.ts"],"sourcesContent":["import { onUnmounted, unref, watch } from 'vue'\nimport { formatHotkeySequence, getSequenceManager } from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProviderContext'\nimport type { UseHotkeySequenceOptions } from './useHotkeySequence'\nimport type {\n HotkeyCallback,\n HotkeySequence,\n SequenceRegistrationHandle,\n} from '@tanstack/hotkeys'\nimport type { MaybeRefOrGetter } from 'vue'\n\n/**\n * A single sequence definition for use with `useHotkeySequences`.\n */\nexport interface UseHotkeySequenceDefinition {\n /** Array of hotkey strings that form the sequence */\n sequence: MaybeRefOrGetter<HotkeySequence>\n /** The function to call when the sequence is completed */\n callback: HotkeyCallback\n /** Per-sequence options (merged on top of commonOptions) */\n options?: MaybeRefOrGetter<UseHotkeySequenceOptions>\n}\n\n/**\n * Vue composable for registering multiple keyboard shortcut sequences at once (Vim-style).\n *\n * Uses the singleton SequenceManager. Accepts a dynamic array of definitions, or a getter/ref\n * that returns one, so you can register variable-length lists safely.\n *\n * Options are merged in this order:\n * HotkeysProvider defaults < commonOptions < per-definition options\n *\n * Definitions with an empty `sequence` are skipped (no registration).\n *\n * @param definitions - Array of sequence definitions, or a getter/ref\n * @param commonOptions - Shared options applied to all sequences (overridden by per-definition options)\n *\n * @example\n * ```vue\n * <script setup>\n * import { useHotkeySequences } from '@tanstack/vue-hotkeys'\n *\n * useHotkeySequences([\n * { sequence: ['G', 'G'], callback: () => scrollToTop() },\n * { sequence: ['D', 'D'], callback: () => deleteLine() },\n * ])\n * </script>\n * ```\n *\n * @example\n * ```vue\n * <script setup>\n * import { computed } from 'vue'\n * import { useHotkeySequences } from '@tanstack/vue-hotkeys'\n *\n * const items = computed(() => [...])\n * useHotkeySequences(\n * () => items.value.map((item) => ({\n * sequence: item.chords,\n * callback: item.action,\n * options: { enabled: item.enabled },\n * })),\n * { preventDefault: true },\n * )\n * </script>\n * ```\n */\nexport function useHotkeySequences(\n definitions: MaybeRefOrGetter<Array<UseHotkeySequenceDefinition>>,\n commonOptions: MaybeRefOrGetter<UseHotkeySequenceOptions> = {},\n): void {\n type RegistrationRecord = {\n handle: SequenceRegistrationHandle\n target: Document | HTMLElement | Window\n }\n\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getSequenceManager()\n\n const registrations = new Map<string, RegistrationRecord>()\n\n const stopWatcher = watch(\n () => {\n const resolvedDefinitions = resolveMaybeRefOrGetter(definitions)\n const resolvedCommonOptions = resolveMaybeRefOrGetter(commonOptions)\n\n return resolvedDefinitions.map((def, i) => {\n const resolvedSequence = resolveMaybeRefOrGetter(def.sequence)\n const resolvedDefOptions = def.options\n ? resolveMaybeRefOrGetter(def.options)\n : {}\n\n const mergedOptions = {\n ...defaultOptions.hotkeySequence,\n ...resolvedCommonOptions,\n ...resolvedDefOptions,\n } as UseHotkeySequenceOptions\n\n const sequenceString = formatHotkeySequence(resolvedSequence)\n\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 as any)\n\n return {\n index: i,\n resolvedSequence,\n sequenceString,\n callback: def.callback,\n mergedOptions,\n resolvedEnabled,\n resolvedTarget,\n }\n })\n },\n (resolved) => {\n const nextKeys = new Set<string>()\n const prepared: Array<{\n registrationKey: string\n entry: (typeof resolved)[number]\n finalTarget: Document | HTMLElement | Window\n }> = []\n\n for (const entry of resolved) {\n if (entry.resolvedSequence.length === 0) {\n continue\n }\n\n const finalTarget =\n entry.resolvedTarget ??\n (typeof document !== 'undefined' ? document : null)\n\n if (!finalTarget) {\n continue\n }\n\n const registrationKey = `${entry.index}:${entry.sequenceString}`\n nextKeys.add(registrationKey)\n prepared.push({ registrationKey, entry, finalTarget })\n }\n\n for (const [key, record] of [...registrations.entries()]) {\n if (!nextKeys.has(key)) {\n if (record.handle.isActive) {\n record.handle.unregister()\n }\n registrations.delete(key)\n }\n }\n\n for (const { registrationKey, entry, finalTarget } of prepared) {\n const existing = registrations.get(registrationKey)\n if (existing?.handle.isActive && existing.target === finalTarget) {\n existing.handle.callback = entry.callback\n const {\n target: _target,\n enabled: _enabled,\n ...restOptions\n } = entry.mergedOptions\n const optionsWithoutTarget = {\n ...restOptions,\n ...(entry.resolvedEnabled === undefined\n ? {}\n : { enabled: entry.resolvedEnabled }),\n }\n existing.handle.setOptions(optionsWithoutTarget)\n continue\n }\n\n if (existing) {\n if (existing.handle.isActive) {\n existing.handle.unregister()\n }\n registrations.delete(registrationKey)\n }\n\n const {\n target: _target,\n enabled: _enabled,\n ...restOptions\n } = entry.mergedOptions\n const optionsWithoutTarget = {\n ...restOptions,\n ...(entry.resolvedEnabled === undefined\n ? {}\n : { enabled: entry.resolvedEnabled }),\n }\n\n const handle = manager.register(\n entry.resolvedSequence,\n entry.callback,\n {\n ...optionsWithoutTarget,\n target: finalTarget,\n },\n )\n registrations.set(registrationKey, { handle, target: finalTarget })\n }\n },\n { immediate: true },\n )\n\n onUnmounted(() => {\n stopWatcher()\n for (const { handle } of registrations.values()) {\n if (handle.isActive) {\n handle.unregister()\n }\n }\n registrations.clear()\n })\n}\n\nfunction resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {\n return typeof value === 'function' ? (value as () => T)() : unref(value)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,SAAgB,mBACd,aACA,gBAA4D,EAAE,EACxD;CAMN,MAAM,iBAAiBA,yDAA0B;CACjD,MAAM,qDAA8B;CAEpC,MAAM,gCAAgB,IAAI,KAAiC;CAE3D,MAAM,mCACE;EACJ,MAAM,sBAAsB,wBAAwB,YAAY;EAChE,MAAM,wBAAwB,wBAAwB,cAAc;AAEpE,SAAO,oBAAoB,KAAK,KAAK,MAAM;GACzC,MAAM,mBAAmB,wBAAwB,IAAI,SAAS;GAC9D,MAAM,qBAAqB,IAAI,UAC3B,wBAAwB,IAAI,QAAQ,GACpC,EAAE;GAEN,MAAM,gBAAgB;IACpB,GAAG,eAAe;IAClB,GAAG;IACH,GAAG;IACJ;GAED,MAAM,6DAAsC,iBAAiB;GAE7D,MAAM,kBACJ,cAAc,YAAY,SACtB,SACA,wBAAwB,cAAc,QAAQ;GACpD,MAAM,iBACJ,cAAc,WAAW,SACrB,SACA,wBAAwB,cAAc,OAAc;AAE1D,UAAO;IACL,OAAO;IACP;IACA;IACA,UAAU,IAAI;IACd;IACA;IACA;IACD;IACD;KAEH,aAAa;EACZ,MAAM,2BAAW,IAAI,KAAa;EAClC,MAAM,WAID,EAAE;AAEP,OAAK,MAAM,SAAS,UAAU;AAC5B,OAAI,MAAM,iBAAiB,WAAW,EACpC;GAGF,MAAM,cACJ,MAAM,mBACL,OAAO,aAAa,cAAc,WAAW;AAEhD,OAAI,CAAC,YACH;GAGF,MAAM,kBAAkB,GAAG,MAAM,MAAM,GAAG,MAAM;AAChD,YAAS,IAAI,gBAAgB;AAC7B,YAAS,KAAK;IAAE;IAAiB;IAAO;IAAa,CAAC;;AAGxD,OAAK,MAAM,CAAC,KAAK,WAAW,CAAC,GAAG,cAAc,SAAS,CAAC,CACtD,KAAI,CAAC,SAAS,IAAI,IAAI,EAAE;AACtB,OAAI,OAAO,OAAO,SAChB,QAAO,OAAO,YAAY;AAE5B,iBAAc,OAAO,IAAI;;AAI7B,OAAK,MAAM,EAAE,iBAAiB,OAAO,iBAAiB,UAAU;GAC9D,MAAM,WAAW,cAAc,IAAI,gBAAgB;AACnD,OAAI,UAAU,OAAO,YAAY,SAAS,WAAW,aAAa;AAChE,aAAS,OAAO,WAAW,MAAM;IACjC,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD,MAAM;IACV,MAAM,uBAAuB;KAC3B,GAAG;KACH,GAAI,MAAM,oBAAoB,SAC1B,EAAE,GACF,EAAE,SAAS,MAAM,iBAAiB;KACvC;AACD,aAAS,OAAO,WAAW,qBAAqB;AAChD;;AAGF,OAAI,UAAU;AACZ,QAAI,SAAS,OAAO,SAClB,UAAS,OAAO,YAAY;AAE9B,kBAAc,OAAO,gBAAgB;;GAGvC,MAAM,EACJ,QAAQ,SACR,SAAS,UACT,GAAG,gBACD,MAAM;GACV,MAAM,uBAAuB;IAC3B,GAAG;IACH,GAAI,MAAM,oBAAoB,SAC1B,EAAE,GACF,EAAE,SAAS,MAAM,iBAAiB;IACvC;GAED,MAAM,SAAS,QAAQ,SACrB,MAAM,kBACN,MAAM,UACN;IACE,GAAG;IACH,QAAQ;IACT,CACF;AACD,iBAAc,IAAI,iBAAiB;IAAE;IAAQ,QAAQ;IAAa,CAAC;;IAGvE,EAAE,WAAW,MAAM,CACpB;AAED,4BAAkB;AAChB,eAAa;AACb,OAAK,MAAM,EAAE,YAAY,cAAc,QAAQ,CAC7C,KAAI,OAAO,SACT,QAAO,YAAY;AAGvB,gBAAc,OAAO;GACrB;;AAGJ,SAAS,wBAA2B,OAA+B;AACjE,QAAO,OAAO,UAAU,aAAc,OAAmB,kBAAS,MAAM"}
|