@@ -44,6 +44,10 @@ const MODIFIER_KEYS = ['ctrl', 'alt', 'shift'];
44
44
const IGNORE_ELEMENTS = [ 'input' , 'textarea' ] ;
45
45
//#endregion
46
46
47
+ //#region store
48
+ let latestHotkey : Pattern & { callback : CallbackFunction } | null = null ;
49
+ //#endregion
50
+
47
51
//#region impl
48
52
export const makeHotkey = ( keymap : Keymap ) => {
49
53
const actions = parseKeymap ( keymap ) ;
@@ -53,11 +57,12 @@ export const makeHotkey = (keymap: Keymap) => {
53
57
if ( IGNORE_ELEMENTS . includes ( document . activeElement . tagName . toLowerCase ( ) ) ) return ;
54
58
if ( ( document . activeElement as HTMLElement ) . isContentEditable ) return ;
55
59
}
56
- for ( const { patterns , callback , options } of actions ) {
57
- if ( matchPatterns ( ev , patterns , options ) ) {
60
+ for ( const action of actions ) {
61
+ if ( matchPatterns ( ev , action ) ) {
58
62
ev . preventDefault ( ) ;
59
63
ev . stopPropagation ( ) ;
60
- callback ( ev ) ;
64
+ action . callback ( ev ) ;
65
+ storePattern ( ev , action . callback ) ;
61
66
}
62
67
}
63
68
} ;
@@ -102,10 +107,21 @@ const parseOptions = (rawCallback: Keymap[keyof Keymap]) => {
102
107
return { ...defaultOptions } as const satisfies Action [ 'options' ] ;
103
108
} ;
104
109
105
- const matchPatterns = ( ev : KeyboardEvent , patterns : Action [ 'patterns' ] , options : Action [ 'options' ] ) => {
110
+ const matchPatterns = ( ev : KeyboardEvent , action : Action ) => {
111
+ const { patterns, options, callback } = action ;
106
112
if ( ev . repeat && ! options . allowRepeat ) return false ;
107
113
const key = ev . key . toLowerCase ( ) ;
108
114
return patterns . some ( ( { which, ctrl, shift, alt } ) => {
115
+ if (
116
+ latestHotkey != null &&
117
+ latestHotkey . which . includes ( key ) &&
118
+ latestHotkey . ctrl === ctrl &&
119
+ latestHotkey . alt === alt &&
120
+ latestHotkey . shift === shift &&
121
+ latestHotkey . callback === callback
122
+ ) {
123
+ return false ;
124
+ }
109
125
if ( ! which . includes ( key ) ) return false ;
110
126
if ( ctrl !== ( ev . ctrlKey || ev . metaKey ) ) return false ;
111
127
if ( alt !== ev . altKey ) return false ;
@@ -114,6 +130,16 @@ const matchPatterns = (ev: KeyboardEvent, patterns: Action['patterns'], options:
114
130
} ) ;
115
131
} ;
116
132
133
+ const storePattern = ( ev : KeyboardEvent , callback : CallbackFunction ) => {
134
+ latestHotkey = {
135
+ which : [ ev . key . toLowerCase ( ) ] ,
136
+ ctrl : ev . ctrlKey || ev . metaKey ,
137
+ alt : ev . altKey ,
138
+ shift : ev . shiftKey ,
139
+ callback,
140
+ } ;
141
+ } ;
142
+
117
143
const parseKeyCode = ( input ?: string | null ) => {
118
144
if ( input == null ) return [ ] ;
119
145
const raw = getValueByKey ( KEY_ALIASES , input ) ;
0 commit comments