@tanstack/vue-hotkeys 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HotkeysProvider.d.ts +5 -9
- package/dist/HotkeysProvider.js +1 -2
- package/dist/HotkeysProviderContext.d.ts +5 -8
- package/dist/HotkeysProviderContext.js +1 -2
- 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 +2 -5
- package/dist/useHotkeyHint.js +1 -2
- 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 -37
- package/dist/index.d.cts +0 -15
- 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/useHotkeyHint.cjs +0 -20
- package/dist/useHotkeyHint.cjs.map +0 -1
- package/dist/useHotkeyHint.d.cts +0 -15
- package/dist/useHotkeyHint.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 -19
- package/src/useHeldKeyCodes.ts +0 -34
- package/src/useHeldKeys.ts +0 -32
- package/src/useHotkey.ts +0 -213
- package/src/useHotkeyHint.ts +0 -25
- 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,221 +0,0 @@
|
|
|
1
|
-
import { onUnmounted, unref, watch } from 'vue'
|
|
2
|
-
import { formatHotkeySequence, getSequenceManager } from '@tanstack/hotkeys'
|
|
3
|
-
import { useDefaultHotkeysOptions } from './HotkeysProviderContext'
|
|
4
|
-
import type { UseHotkeySequenceOptions } from './useHotkeySequence'
|
|
5
|
-
import type {
|
|
6
|
-
HotkeyCallback,
|
|
7
|
-
HotkeySequence,
|
|
8
|
-
SequenceRegistrationHandle,
|
|
9
|
-
} from '@tanstack/hotkeys'
|
|
10
|
-
import type { MaybeRefOrGetter } from 'vue'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A single sequence definition for use with `useHotkeySequences`.
|
|
14
|
-
*/
|
|
15
|
-
export interface UseHotkeySequenceDefinition {
|
|
16
|
-
/** Array of hotkey strings that form the sequence */
|
|
17
|
-
sequence: MaybeRefOrGetter<HotkeySequence>
|
|
18
|
-
/** The function to call when the sequence is completed */
|
|
19
|
-
callback: HotkeyCallback
|
|
20
|
-
/** Per-sequence options (merged on top of commonOptions) */
|
|
21
|
-
options?: MaybeRefOrGetter<UseHotkeySequenceOptions>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Vue composable for registering multiple keyboard shortcut sequences at once (Vim-style).
|
|
26
|
-
*
|
|
27
|
-
* Uses the singleton SequenceManager. Accepts a dynamic array of definitions, or a getter/ref
|
|
28
|
-
* that returns one, so you can register variable-length lists safely.
|
|
29
|
-
*
|
|
30
|
-
* Options are merged in this order:
|
|
31
|
-
* HotkeysProvider defaults < commonOptions < per-definition options
|
|
32
|
-
*
|
|
33
|
-
* Definitions with an empty `sequence` are skipped (no registration).
|
|
34
|
-
*
|
|
35
|
-
* @param definitions - Array of sequence definitions, or a getter/ref
|
|
36
|
-
* @param commonOptions - Shared options applied to all sequences (overridden by per-definition options)
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```vue
|
|
40
|
-
* <script setup>
|
|
41
|
-
* import { useHotkeySequences } from '@tanstack/vue-hotkeys'
|
|
42
|
-
*
|
|
43
|
-
* useHotkeySequences([
|
|
44
|
-
* { sequence: ['G', 'G'], callback: () => scrollToTop() },
|
|
45
|
-
* { sequence: ['D', 'D'], callback: () => deleteLine() },
|
|
46
|
-
* ])
|
|
47
|
-
* </script>
|
|
48
|
-
* ```
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```vue
|
|
52
|
-
* <script setup>
|
|
53
|
-
* import { computed } from 'vue'
|
|
54
|
-
* import { useHotkeySequences } from '@tanstack/vue-hotkeys'
|
|
55
|
-
*
|
|
56
|
-
* const items = computed(() => [...])
|
|
57
|
-
* useHotkeySequences(
|
|
58
|
-
* () => items.value.map((item) => ({
|
|
59
|
-
* sequence: item.chords,
|
|
60
|
-
* callback: item.action,
|
|
61
|
-
* options: { enabled: item.enabled },
|
|
62
|
-
* })),
|
|
63
|
-
* { preventDefault: true },
|
|
64
|
-
* )
|
|
65
|
-
* </script>
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
export function useHotkeySequences(
|
|
69
|
-
definitions: MaybeRefOrGetter<Array<UseHotkeySequenceDefinition>>,
|
|
70
|
-
commonOptions: MaybeRefOrGetter<UseHotkeySequenceOptions> = {},
|
|
71
|
-
): void {
|
|
72
|
-
type RegistrationRecord = {
|
|
73
|
-
handle: SequenceRegistrationHandle
|
|
74
|
-
target: Document | HTMLElement | Window
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const defaultOptions = useDefaultHotkeysOptions()
|
|
78
|
-
const manager = getSequenceManager()
|
|
79
|
-
|
|
80
|
-
const registrations = new Map<string, RegistrationRecord>()
|
|
81
|
-
|
|
82
|
-
const stopWatcher = watch(
|
|
83
|
-
() => {
|
|
84
|
-
const resolvedDefinitions = resolveMaybeRefOrGetter(definitions)
|
|
85
|
-
const resolvedCommonOptions = resolveMaybeRefOrGetter(commonOptions)
|
|
86
|
-
|
|
87
|
-
return resolvedDefinitions.map((def, i) => {
|
|
88
|
-
const resolvedSequence = resolveMaybeRefOrGetter(def.sequence)
|
|
89
|
-
const resolvedDefOptions = def.options
|
|
90
|
-
? resolveMaybeRefOrGetter(def.options)
|
|
91
|
-
: {}
|
|
92
|
-
|
|
93
|
-
const mergedOptions = {
|
|
94
|
-
...defaultOptions.hotkeySequence,
|
|
95
|
-
...resolvedCommonOptions,
|
|
96
|
-
...resolvedDefOptions,
|
|
97
|
-
} as UseHotkeySequenceOptions
|
|
98
|
-
|
|
99
|
-
const sequenceString = formatHotkeySequence(resolvedSequence)
|
|
100
|
-
|
|
101
|
-
const resolvedEnabled =
|
|
102
|
-
mergedOptions.enabled === undefined
|
|
103
|
-
? undefined
|
|
104
|
-
: resolveMaybeRefOrGetter(mergedOptions.enabled)
|
|
105
|
-
const resolvedTarget =
|
|
106
|
-
mergedOptions.target === undefined
|
|
107
|
-
? undefined
|
|
108
|
-
: resolveMaybeRefOrGetter(mergedOptions.target as any)
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
index: i,
|
|
112
|
-
resolvedSequence,
|
|
113
|
-
sequenceString,
|
|
114
|
-
callback: def.callback,
|
|
115
|
-
mergedOptions,
|
|
116
|
-
resolvedEnabled,
|
|
117
|
-
resolvedTarget,
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
},
|
|
121
|
-
(resolved) => {
|
|
122
|
-
const nextKeys = new Set<string>()
|
|
123
|
-
const prepared: Array<{
|
|
124
|
-
registrationKey: string
|
|
125
|
-
entry: (typeof resolved)[number]
|
|
126
|
-
finalTarget: Document | HTMLElement | Window
|
|
127
|
-
}> = []
|
|
128
|
-
|
|
129
|
-
for (const entry of resolved) {
|
|
130
|
-
if (entry.resolvedSequence.length === 0) {
|
|
131
|
-
continue
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const finalTarget =
|
|
135
|
-
entry.resolvedTarget ??
|
|
136
|
-
(typeof document !== 'undefined' ? document : null)
|
|
137
|
-
|
|
138
|
-
if (!finalTarget) {
|
|
139
|
-
continue
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const registrationKey = `${entry.index}:${entry.sequenceString}`
|
|
143
|
-
nextKeys.add(registrationKey)
|
|
144
|
-
prepared.push({ registrationKey, entry, finalTarget })
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
for (const [key, record] of [...registrations.entries()]) {
|
|
148
|
-
if (!nextKeys.has(key)) {
|
|
149
|
-
if (record.handle.isActive) {
|
|
150
|
-
record.handle.unregister()
|
|
151
|
-
}
|
|
152
|
-
registrations.delete(key)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
for (const { registrationKey, entry, finalTarget } of prepared) {
|
|
157
|
-
const existing = registrations.get(registrationKey)
|
|
158
|
-
if (existing?.handle.isActive && existing.target === finalTarget) {
|
|
159
|
-
existing.handle.callback = entry.callback
|
|
160
|
-
const {
|
|
161
|
-
target: _target,
|
|
162
|
-
enabled: _enabled,
|
|
163
|
-
...restOptions
|
|
164
|
-
} = entry.mergedOptions
|
|
165
|
-
const optionsWithoutTarget = {
|
|
166
|
-
...restOptions,
|
|
167
|
-
...(entry.resolvedEnabled === undefined
|
|
168
|
-
? {}
|
|
169
|
-
: { enabled: entry.resolvedEnabled }),
|
|
170
|
-
}
|
|
171
|
-
existing.handle.setOptions(optionsWithoutTarget)
|
|
172
|
-
continue
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (existing) {
|
|
176
|
-
if (existing.handle.isActive) {
|
|
177
|
-
existing.handle.unregister()
|
|
178
|
-
}
|
|
179
|
-
registrations.delete(registrationKey)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const {
|
|
183
|
-
target: _target,
|
|
184
|
-
enabled: _enabled,
|
|
185
|
-
...restOptions
|
|
186
|
-
} = entry.mergedOptions
|
|
187
|
-
const optionsWithoutTarget = {
|
|
188
|
-
...restOptions,
|
|
189
|
-
...(entry.resolvedEnabled === undefined
|
|
190
|
-
? {}
|
|
191
|
-
: { enabled: entry.resolvedEnabled }),
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const handle = manager.register(
|
|
195
|
-
entry.resolvedSequence,
|
|
196
|
-
entry.callback,
|
|
197
|
-
{
|
|
198
|
-
...optionsWithoutTarget,
|
|
199
|
-
target: finalTarget,
|
|
200
|
-
},
|
|
201
|
-
)
|
|
202
|
-
registrations.set(registrationKey, { handle, target: finalTarget })
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
{ immediate: true },
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
onUnmounted(() => {
|
|
209
|
-
stopWatcher()
|
|
210
|
-
for (const { handle } of registrations.values()) {
|
|
211
|
-
if (handle.isActive) {
|
|
212
|
-
handle.unregister()
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
registrations.clear()
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {
|
|
220
|
-
return typeof value === 'function' ? (value as () => T)() : unref(value)
|
|
221
|
-
}
|
package/src/useHotkeys.ts
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { onUnmounted, unref, watch } from 'vue'
|
|
2
|
-
import {
|
|
3
|
-
detectPlatform,
|
|
4
|
-
getHotkeyManager,
|
|
5
|
-
normalizeRegisterableHotkey,
|
|
6
|
-
} from '@tanstack/hotkeys'
|
|
7
|
-
import { useDefaultHotkeysOptions } from './HotkeysProviderContext'
|
|
8
|
-
import type { UseHotkeyOptions } from './useHotkey'
|
|
9
|
-
import type {
|
|
10
|
-
HotkeyCallback,
|
|
11
|
-
HotkeyRegistrationHandle,
|
|
12
|
-
RegisterableHotkey,
|
|
13
|
-
} from '@tanstack/hotkeys'
|
|
14
|
-
import type { MaybeRefOrGetter } from 'vue'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* A single hotkey definition for use with `useHotkeys`.
|
|
18
|
-
*/
|
|
19
|
-
export interface UseHotkeyDefinition {
|
|
20
|
-
/** The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object */
|
|
21
|
-
hotkey: MaybeRefOrGetter<RegisterableHotkey>
|
|
22
|
-
/** The function to call when the hotkey is pressed */
|
|
23
|
-
callback: HotkeyCallback
|
|
24
|
-
/** Per-hotkey options (merged on top of commonOptions) */
|
|
25
|
-
options?: MaybeRefOrGetter<UseHotkeyOptions>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Vue composable for registering multiple keyboard hotkeys at once.
|
|
30
|
-
*
|
|
31
|
-
* Uses the singleton HotkeyManager for efficient event handling.
|
|
32
|
-
* Accepts a dynamic array of hotkey definitions, making it safe to use
|
|
33
|
-
* with variable-length lists.
|
|
34
|
-
*
|
|
35
|
-
* Options are merged in this order:
|
|
36
|
-
* HotkeysProvider defaults < commonOptions < per-definition options
|
|
37
|
-
*
|
|
38
|
-
* @param hotkeys - Array of hotkey definitions to register, or a getter/ref
|
|
39
|
-
* @param commonOptions - Shared options applied to all hotkeys (overridden by per-definition options)
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```vue
|
|
43
|
-
* <script setup>
|
|
44
|
-
* import { useHotkeys } from '@tanstack/vue-hotkeys'
|
|
45
|
-
*
|
|
46
|
-
* useHotkeys([
|
|
47
|
-
* { hotkey: 'Mod+S', callback: () => save() },
|
|
48
|
-
* { hotkey: 'Mod+Z', callback: () => undo() },
|
|
49
|
-
* { hotkey: 'Escape', callback: () => close() },
|
|
50
|
-
* ])
|
|
51
|
-
* </script>
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```vue
|
|
56
|
-
* <script setup>
|
|
57
|
-
* import { computed } from 'vue'
|
|
58
|
-
* import { useHotkeys } from '@tanstack/vue-hotkeys'
|
|
59
|
-
*
|
|
60
|
-
* const items = computed(() => [...])
|
|
61
|
-
* // Dynamic hotkeys from reactive data
|
|
62
|
-
* useHotkeys(
|
|
63
|
-
* () => items.value.map((item) => ({
|
|
64
|
-
* hotkey: item.shortcut,
|
|
65
|
-
* callback: item.action,
|
|
66
|
-
* options: { enabled: item.enabled },
|
|
67
|
-
* })),
|
|
68
|
-
* { preventDefault: true },
|
|
69
|
-
* )
|
|
70
|
-
* </script>
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
export function useHotkeys(
|
|
74
|
-
hotkeys: MaybeRefOrGetter<Array<UseHotkeyDefinition>>,
|
|
75
|
-
commonOptions: MaybeRefOrGetter<UseHotkeyOptions> = {},
|
|
76
|
-
): void {
|
|
77
|
-
type RegistrationRecord = {
|
|
78
|
-
handle: HotkeyRegistrationHandle
|
|
79
|
-
target: Document | HTMLElement | Window
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const defaultOptions = useDefaultHotkeysOptions()
|
|
83
|
-
const manager = getHotkeyManager()
|
|
84
|
-
|
|
85
|
-
const registrations = new Map<string, RegistrationRecord>()
|
|
86
|
-
|
|
87
|
-
const stopWatcher = watch(
|
|
88
|
-
() => {
|
|
89
|
-
const resolvedHotkeys = resolveMaybeRefOrGetter(hotkeys)
|
|
90
|
-
const resolvedCommonOptions = resolveMaybeRefOrGetter(commonOptions)
|
|
91
|
-
|
|
92
|
-
return resolvedHotkeys.map((def, i) => {
|
|
93
|
-
const resolvedHotkey = resolveMaybeRefOrGetter(def.hotkey)
|
|
94
|
-
const resolvedDefOptions = def.options
|
|
95
|
-
? resolveMaybeRefOrGetter(def.options)
|
|
96
|
-
: {}
|
|
97
|
-
|
|
98
|
-
const mergedOptions = {
|
|
99
|
-
...defaultOptions.hotkey,
|
|
100
|
-
...resolvedCommonOptions,
|
|
101
|
-
...resolvedDefOptions,
|
|
102
|
-
} as UseHotkeyOptions
|
|
103
|
-
|
|
104
|
-
const platform = mergedOptions.platform ?? detectPlatform()
|
|
105
|
-
const hotkeyString = normalizeRegisterableHotkey(
|
|
106
|
-
resolvedHotkey,
|
|
107
|
-
platform,
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
const resolvedEnabled =
|
|
111
|
-
mergedOptions.enabled === undefined
|
|
112
|
-
? undefined
|
|
113
|
-
: resolveMaybeRefOrGetter(mergedOptions.enabled)
|
|
114
|
-
const resolvedTarget =
|
|
115
|
-
mergedOptions.target === undefined
|
|
116
|
-
? undefined
|
|
117
|
-
: resolveMaybeRefOrGetter(mergedOptions.target as any)
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
index: i,
|
|
121
|
-
hotkeyString,
|
|
122
|
-
callback: def.callback,
|
|
123
|
-
mergedOptions,
|
|
124
|
-
resolvedEnabled,
|
|
125
|
-
resolvedTarget,
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
},
|
|
129
|
-
(resolved) => {
|
|
130
|
-
const nextKeys = new Set<string>()
|
|
131
|
-
const prepared: Array<{
|
|
132
|
-
registrationKey: string
|
|
133
|
-
entry: (typeof resolved)[number]
|
|
134
|
-
finalTarget: Document | HTMLElement | Window
|
|
135
|
-
}> = []
|
|
136
|
-
|
|
137
|
-
for (const entry of resolved) {
|
|
138
|
-
const finalTarget =
|
|
139
|
-
entry.resolvedTarget ??
|
|
140
|
-
(typeof document !== 'undefined' ? document : null)
|
|
141
|
-
|
|
142
|
-
if (!finalTarget) {
|
|
143
|
-
continue
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const registrationKey = `${entry.index}:${entry.hotkeyString}`
|
|
147
|
-
nextKeys.add(registrationKey)
|
|
148
|
-
prepared.push({ registrationKey, entry, finalTarget })
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
for (const [key, record] of [...registrations.entries()]) {
|
|
152
|
-
if (!nextKeys.has(key)) {
|
|
153
|
-
if (record.handle.isActive) {
|
|
154
|
-
record.handle.unregister()
|
|
155
|
-
}
|
|
156
|
-
registrations.delete(key)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
for (const { registrationKey, entry, finalTarget } of prepared) {
|
|
161
|
-
const existing = registrations.get(registrationKey)
|
|
162
|
-
if (existing?.handle.isActive && existing.target === finalTarget) {
|
|
163
|
-
existing.handle.callback = entry.callback
|
|
164
|
-
const {
|
|
165
|
-
target: _target,
|
|
166
|
-
enabled: _enabled,
|
|
167
|
-
...restOptions
|
|
168
|
-
} = entry.mergedOptions
|
|
169
|
-
const optionsWithoutTarget = {
|
|
170
|
-
...restOptions,
|
|
171
|
-
...(entry.resolvedEnabled === undefined
|
|
172
|
-
? {}
|
|
173
|
-
: { enabled: entry.resolvedEnabled }),
|
|
174
|
-
}
|
|
175
|
-
existing.handle.setOptions(optionsWithoutTarget)
|
|
176
|
-
continue
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (existing) {
|
|
180
|
-
if (existing.handle.isActive) {
|
|
181
|
-
existing.handle.unregister()
|
|
182
|
-
}
|
|
183
|
-
registrations.delete(registrationKey)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const {
|
|
187
|
-
target: _target,
|
|
188
|
-
enabled: _enabled,
|
|
189
|
-
...restOptions
|
|
190
|
-
} = entry.mergedOptions
|
|
191
|
-
const optionsWithoutTarget = {
|
|
192
|
-
...restOptions,
|
|
193
|
-
...(entry.resolvedEnabled === undefined
|
|
194
|
-
? {}
|
|
195
|
-
: { enabled: entry.resolvedEnabled }),
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const handle = manager.register(entry.hotkeyString, entry.callback, {
|
|
199
|
-
...optionsWithoutTarget,
|
|
200
|
-
target: finalTarget,
|
|
201
|
-
})
|
|
202
|
-
registrations.set(registrationKey, { handle, target: finalTarget })
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
{ immediate: true },
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
onUnmounted(() => {
|
|
209
|
-
stopWatcher()
|
|
210
|
-
for (const { handle } of registrations.values()) {
|
|
211
|
-
if (handle.isActive) {
|
|
212
|
-
handle.unregister()
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
registrations.clear()
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function resolveMaybeRefOrGetter<T>(value: MaybeRefOrGetter<T>): T {
|
|
220
|
-
return typeof value === 'function' ? (value as () => T)() : unref(value)
|
|
221
|
-
}
|
package/src/useKeyHold.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { useSelector } from '@tanstack/vue-store'
|
|
2
|
-
import { getKeyStateTracker } from '@tanstack/hotkeys'
|
|
3
|
-
import { unref } from 'vue'
|
|
4
|
-
import type { MaybeRefOrGetter, Ref } from 'vue'
|
|
5
|
-
import type { IndividualKey } from '@tanstack/hotkeys'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Vue composable that returns a reactive ref indicating whether a specific key is currently being held.
|
|
9
|
-
*
|
|
10
|
-
* This composable uses `useSelector` from `@tanstack/vue-store` to subscribe
|
|
11
|
-
* to the global KeyStateTracker and uses a selector to determine if
|
|
12
|
-
* the specified key is held.
|
|
13
|
-
*
|
|
14
|
-
* @param key - The key to check (e.g., 'Shift', 'Control', 'A')
|
|
15
|
-
* @returns Reactive ref that is true if the key is currently held down
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```vue
|
|
19
|
-
* <script setup>
|
|
20
|
-
* import { useKeyHold } from '@tanstack/vue-hotkeys'
|
|
21
|
-
*
|
|
22
|
-
* const isShiftHeld = useKeyHold('Shift')
|
|
23
|
-
* </script>
|
|
24
|
-
*
|
|
25
|
-
* <template>
|
|
26
|
-
* <div :style="{ opacity: isShiftHeld ? 1 : 0.5 }">
|
|
27
|
-
* {{ isShiftHeld ? 'Shift is pressed!' : 'Press Shift' }}
|
|
28
|
-
* </div>
|
|
29
|
-
* </template>
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```vue
|
|
34
|
-
* <script setup>
|
|
35
|
-
* import { useKeyHold } from '@tanstack/vue-hotkeys'
|
|
36
|
-
*
|
|
37
|
-
* const ctrl = useKeyHold('Control')
|
|
38
|
-
* const shift = useKeyHold('Shift')
|
|
39
|
-
* const alt = useKeyHold('Alt')
|
|
40
|
-
* </script>
|
|
41
|
-
*
|
|
42
|
-
* <template>
|
|
43
|
-
* <div>
|
|
44
|
-
* <span :style="{ opacity: ctrl ? 1 : 0.3 }">Ctrl</span>
|
|
45
|
-
* <span :style="{ opacity: shift ? 1 : 0.3 }">Shift</span>
|
|
46
|
-
* <span :style="{ opacity: alt ? 1 : 0.3 }">Alt</span>
|
|
47
|
-
* </div>
|
|
48
|
-
* </template>
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export function useKeyHold(key: MaybeRefOrGetter<IndividualKey>): Ref<boolean> {
|
|
52
|
-
const tracker = getKeyStateTracker()
|
|
53
|
-
|
|
54
|
-
const isHeld = useSelector(tracker.store, (state) => {
|
|
55
|
-
const keyValue = unref(key)
|
|
56
|
-
const normalizedKey = (
|
|
57
|
-
typeof keyValue === 'string' ? keyValue : String(keyValue)
|
|
58
|
-
).toLowerCase()
|
|
59
|
-
return state.heldKeys.some(
|
|
60
|
-
(heldKey) => heldKey.toLowerCase() === normalizedKey,
|
|
61
|
-
)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
return isHeld as Ref<boolean>
|
|
65
|
-
}
|