@@ -3,6 +3,9 @@ import { onMounted, ref, toRef, toValue, watch } from 'vue'
3
3
import type { KeyFilter , KeyPredicate } from '@vueuse/core'
4
4
import { onKeyStroke , useEventListener } from '@vueuse/core'
5
5
6
+ type PressedKeys = Set < string >
7
+ type KeyOrCode = 'key' | 'code'
8
+
6
9
export interface UseKeyPressOptions {
7
10
actInsideInputWithModifier ?: MaybeRefOrGetter < boolean >
8
11
target ?: MaybeRefOrGetter < EventTarget | null | undefined >
@@ -35,43 +38,41 @@ function isKeyMatch(pressedKey: string, keyToMatch: string, pressedKeys: Set<str
35
38
return pressedKey . toLowerCase ( ) === keyToMatch . toLowerCase ( )
36
39
}
37
40
38
- if ( isKeyUp ) {
39
- pressedKeys . delete ( pressedKey . toLowerCase ( ) )
40
- } else {
41
+ // we need to remove the key *after* checking for a match otherwise a combination like 'shift+a' would never get unmatched/reset
42
+ if ( ! isKeyUp ) {
41
43
pressedKeys . add ( pressedKey . toLowerCase ( ) )
42
44
}
43
45
44
- return keyCombination . every (
46
+ const isMatch = keyCombination . every (
45
47
( key , index ) => pressedKeys . has ( key ) && Array . from ( pressedKeys . values ( ) ) [ index ] === keyCombination [ index ] ,
46
48
)
49
+
50
+ if ( isKeyUp ) {
51
+ pressedKeys . delete ( pressedKey . toLowerCase ( ) )
52
+ }
53
+
54
+ return isMatch
47
55
}
48
56
49
- function createKeyPredicate ( keyFilter : string | string [ ] , pressedKeys : Set < string > ) : KeyPredicate {
57
+ function createKeyPredicate ( keyFilter : string | string [ ] , pressedKeys : PressedKeys ) : KeyPredicate {
50
58
return ( event : KeyboardEvent ) => {
51
59
if ( ! event . code && ! event . key ) {
52
60
return false
53
61
}
54
62
55
63
const keyOrCode = useKeyOrCode ( event . code , keyFilter )
56
64
57
- const isKeyUp = event . type === 'keyup'
58
- const pressedKey = event [ keyOrCode ]
59
-
60
65
// if the keyFilter is an array of multiple keys, we need to check each possible key combination
61
66
if ( Array . isArray ( keyFilter ) ) {
62
- return keyFilter . some ( ( key ) => isKeyMatch ( pressedKey , key , pressedKeys , isKeyUp ) )
67
+ return keyFilter . some ( ( key ) => isKeyMatch ( event [ keyOrCode ] , key , pressedKeys , event . type === 'keyup' ) )
63
68
}
64
69
65
70
// if the keyFilter is a string, we need to check if the key matches the string
66
- return isKeyMatch ( pressedKey , keyFilter , pressedKeys , isKeyUp )
71
+ return isKeyMatch ( event [ keyOrCode ] , keyFilter , pressedKeys , event . type === 'keyup' )
67
72
}
68
73
}
69
74
70
- function useKeyOrCode ( code : string , keysToWatch : string | string [ ] ) {
71
- if ( typeof keysToWatch === 'string' ) {
72
- return code === keysToWatch ? 'code' : 'key'
73
- }
74
-
75
+ function useKeyOrCode ( code : string , keysToWatch : string | string [ ] ) : KeyOrCode {
75
76
return keysToWatch . includes ( code ) ? 'code' : 'key'
76
77
}
77
78
@@ -133,9 +134,7 @@ export function useKeyPress(keyFilter: MaybeRefOrGetter<KeyFilter | boolean | nu
133
134
)
134
135
135
136
onKeyStroke (
136
- ( ...args ) => {
137
- return currentFilter ( ...args )
138
- } ,
137
+ ( ...args ) => currentFilter ( ...args ) ,
139
138
( e ) => {
140
139
if ( isPressed . value ) {
141
140
const preventAction = ( ! modifierPressed || ( modifierPressed && ! actInsideInputWithModifier . value ) ) && isInputDOMNode ( e )
@@ -144,7 +143,8 @@ export function useKeyPress(keyFilter: MaybeRefOrGetter<KeyFilter | boolean | nu
144
143
return
145
144
}
146
145
147
- reset ( )
146
+ modifierPressed = false
147
+ isPressed . value = false
148
148
}
149
149
} ,
150
150
{ eventName : 'keyup' , target } ,
0 commit comments