Skip to content

Commit be3a7e9

Browse files
committed
refactor(VHotkey): remove duplicate and redundant code
1 parent df5f40f commit be3a7e9

File tree

3 files changed

+152
-231
lines changed

3 files changed

+152
-231
lines changed

packages/vuetify/src/composables/hotkey/hotkey.ts

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
import { splitKeyCombination, splitKeySequence } from '@/composables/hotkey/hotkey-parsing'
33

44
// Utilities
5-
import { onBeforeUnmount, toValue, watch } from 'vue'
5+
import { onScopeDispose, toValue, watch } from 'vue'
66
import { IN_BROWSER } from '@/util'
7-
import { getCurrentInstance } from '@/util/getCurrentInstance'
87

98
// Types
109
import type { MaybeRef } from '@/util'
@@ -36,13 +35,6 @@ export function useHotkey (
3635
let isSequence = false
3736
let groupIndex = 0
3837

39-
function clearTimer () {
40-
if (!timeout) return
41-
42-
clearTimeout(timeout)
43-
timeout = 0
44-
}
45-
4638
function isInputFocused () {
4739
if (toValue(inputs)) return false
4840

@@ -58,15 +50,15 @@ export function useHotkey (
5850

5951
function resetSequence () {
6052
groupIndex = 0
61-
clearTimer()
53+
clearTimeout(timeout)
6254
}
6355

6456
function handler (e: KeyboardEvent) {
6557
const group = keyGroups[groupIndex]
6658

6759
if (!group || isInputFocused()) return
6860

69-
if (!matchesKeyGroup(e, group)) {
61+
if (!matchesKeyGroup(e, group, isMac)) {
7062
if (isSequence) resetSequence()
7163
return
7264
}
@@ -78,7 +70,7 @@ export function useHotkey (
7870
return
7971
}
8072

81-
clearTimer()
73+
clearTimeout(timeout)
8274
groupIndex++
8375

8476
if (groupIndex === keyGroups.length) {
@@ -92,14 +84,14 @@ export function useHotkey (
9284

9385
function cleanup () {
9486
window.removeEventListener(toValue(event), handler)
95-
clearTimer()
87+
clearTimeout(timeout)
9688
}
9789

98-
watch(() => toValue(keys), function (unrefKeys) {
90+
watch(() => toValue(keys), newKeys => {
9991
cleanup()
10092

101-
if (unrefKeys) {
102-
const groups = splitKeySequence(unrefKeys.toLowerCase())
93+
if (newKeys) {
94+
const groups = splitKeySequence(newKeys.toLowerCase())
10395
isSequence = groups.length > 1
10496
keyGroups = groups
10597
resetSequence()
@@ -108,59 +100,54 @@ export function useHotkey (
108100
}, { immediate: true })
109101

110102
// Watch for changes in the event type to re-register the listener
111-
watch(() => toValue(event), function (newEvent, oldEvent) {
103+
watch(() => toValue(event), (newEvent, oldEvent) => {
112104
if (oldEvent && keyGroups && keyGroups.length > 0) {
113105
window.removeEventListener(oldEvent, handler)
114106
window.addEventListener(newEvent, handler)
115107
}
116108
})
117109

118-
try {
119-
getCurrentInstance('useHotkey')
120-
onBeforeUnmount(cleanup)
121-
} catch {
122-
// Not in Vue setup context
123-
}
110+
onScopeDispose(cleanup, true)
111+
112+
return cleanup
113+
}
124114

125-
function parseKeyGroup (group: string) {
126-
const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd']
115+
function matchesKeyGroup (e: KeyboardEvent, group: string, isMac: boolean) {
116+
const { modifiers, actualKey } = parseKeyGroup(group)
127117

128-
// Use the shared combination splitting logic
129-
const parts = splitKeyCombination(group.toLowerCase())
118+
const expectCtrl = modifiers.ctrl || (!isMac && (modifiers.cmd || modifiers.meta))
119+
const expectMeta = isMac && (modifiers.cmd || modifiers.meta)
130120

131-
// If the combination is invalid, return empty result
132-
if (parts.length === 0) {
133-
return { modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])), actualKey: undefined }
134-
}
121+
return (
122+
e.ctrlKey === expectCtrl &&
123+
e.metaKey === expectMeta &&
124+
e.shiftKey === modifiers.shift &&
125+
e.altKey === modifiers.alt &&
126+
e.key.toLowerCase() === actualKey?.toLowerCase()
127+
)
128+
}
135129

136-
const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false])) as Record<string, boolean>
137-
let actualKey: string | undefined
130+
function parseKeyGroup (group: string) {
131+
const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd']
138132

139-
for (const part of parts) {
140-
if (MODIFIERS.includes(part)) {
141-
modifiers[part] = true
142-
} else {
143-
actualKey = part
144-
}
145-
}
133+
// Use the shared combination splitting logic
134+
const parts = splitKeyCombination(group.toLowerCase())
146135

147-
return { modifiers, actualKey }
136+
// If the combination is invalid, return empty result
137+
if (parts.length === 0) {
138+
return { modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])), actualKey: undefined }
148139
}
149140

150-
function matchesKeyGroup (e: KeyboardEvent, group: string) {
151-
const { modifiers, actualKey } = parseKeyGroup(group)
141+
const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false])) as Record<string, boolean>
142+
let actualKey: string | undefined
152143

153-
const expectCtrl = modifiers.ctrl || (!isMac && (modifiers.cmd || modifiers.meta))
154-
const expectMeta = isMac && (modifiers.cmd || modifiers.meta)
155-
156-
return (
157-
e.ctrlKey === expectCtrl &&
158-
e.metaKey === expectMeta &&
159-
e.shiftKey === modifiers.shift &&
160-
e.altKey === modifiers.alt &&
161-
e.key.toLowerCase() === actualKey?.toLowerCase()
162-
)
144+
for (const part of parts) {
145+
if (MODIFIERS.includes(part)) {
146+
modifiers[part] = true
147+
} else {
148+
actualKey = part
149+
}
163150
}
164151

165-
return cleanup
152+
return { modifiers, actualKey }
166153
}

packages/vuetify/src/labs/VHotkey/VHotkey.scss

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@
147147
gap: $hotkey-combination-gap;
148148
}
149149

150-
151-
152150
&--inline &__key {
153151
&-symbol.v-kbd,
154152
&-text.v-kbd {
@@ -209,22 +207,20 @@
209207
}
210208

211209
&--variant-outlined &__key.v-kbd {
210+
background: none;
211+
212212
@include tools.elevation(0);
213-
& {
214-
background: none;
215-
}
216213
}
217214

218215
&--variant-text {
219216
.v-hotkey__key.v-kbd {
217+
background: transparent !important;
218+
border: none !important;
219+
padding-left: 0;
220+
padding-right: 0;
221+
min-width: auto;
222+
220223
@include tools.elevation(0);
221-
& {
222-
background: transparent !important;
223-
border: none !important;
224-
padding-left: 0;
225-
padding-right: 0;
226-
min-width: auto;
227-
}
228224
}
229225

230226
.v-hotkey__combination {
@@ -237,17 +233,4 @@
237233
box-shadow: unset;
238234
}
239235
}
240-
241-
// Screen reader only content
242-
.sr-only {
243-
position: absolute;
244-
width: 1px;
245-
height: 1px;
246-
padding: 0;
247-
margin: -1px;
248-
overflow: hidden;
249-
clip: rect(0, 0, 0, 0);
250-
white-space: nowrap;
251-
border: 0;
252-
}
253236
}

0 commit comments

Comments
 (0)