@@ -3,6 +3,9 @@ import { onMounted, ref, toRef, toValue, watch } from 'vue'
33import type { KeyFilter , KeyPredicate } from '@vueuse/core'
44import { onKeyStroke , useEventListener } from '@vueuse/core'
55
6+ type PressedKeys = Set < string >
7+ type KeyOrCode = 'key' | 'code'
8+
69export interface UseKeyPressOptions {
710 actInsideInputWithModifier ?: MaybeRefOrGetter < boolean >
811 target ?: MaybeRefOrGetter < EventTarget | null | undefined >
@@ -35,43 +38,41 @@ function isKeyMatch(pressedKey: string, keyToMatch: string, pressedKeys: Set<str
3538 return pressedKey . toLowerCase ( ) === keyToMatch . toLowerCase ( )
3639 }
3740
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 ) {
4143 pressedKeys . add ( pressedKey . toLowerCase ( ) )
4244 }
4345
44- return keyCombination . every (
46+ const isMatch = keyCombination . every (
4547 ( key , index ) => pressedKeys . has ( key ) && Array . from ( pressedKeys . values ( ) ) [ index ] === keyCombination [ index ] ,
4648 )
49+
50+ if ( isKeyUp ) {
51+ pressedKeys . delete ( pressedKey . toLowerCase ( ) )
52+ }
53+
54+ return isMatch
4755}
4856
49- function createKeyPredicate ( keyFilter : string | string [ ] , pressedKeys : Set < string > ) : KeyPredicate {
57+ function createKeyPredicate ( keyFilter : string | string [ ] , pressedKeys : PressedKeys ) : KeyPredicate {
5058 return ( event : KeyboardEvent ) => {
5159 if ( ! event . code && ! event . key ) {
5260 return false
5361 }
5462
5563 const keyOrCode = useKeyOrCode ( event . code , keyFilter )
5664
57- const isKeyUp = event . type === 'keyup'
58- const pressedKey = event [ keyOrCode ]
59-
6065 // if the keyFilter is an array of multiple keys, we need to check each possible key combination
6166 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' ) )
6368 }
6469
6570 // 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' )
6772 }
6873}
6974
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 {
7576 return keysToWatch . includes ( code ) ? 'code' : 'key'
7677}
7778
@@ -133,9 +134,7 @@ export function useKeyPress(keyFilter: MaybeRefOrGetter<KeyFilter | boolean | nu
133134 )
134135
135136 onKeyStroke (
136- ( ...args ) => {
137- return currentFilter ( ...args )
138- } ,
137+ ( ...args ) => currentFilter ( ...args ) ,
139138 ( e ) => {
140139 if ( isPressed . value ) {
141140 const preventAction = ( ! modifierPressed || ( modifierPressed && ! actInsideInputWithModifier . value ) ) && isInputDOMNode ( e )
@@ -144,7 +143,8 @@ export function useKeyPress(keyFilter: MaybeRefOrGetter<KeyFilter | boolean | nu
144143 return
145144 }
146145
147- reset ( )
146+ modifierPressed = false
147+ isPressed . value = false
148148 }
149149 } ,
150150 { eventName : 'keyup' , target } ,
0 commit comments