@@ -18,6 +18,24 @@ export function useLastTriggerRef() {
1818 return useRef < LastTriggerData > ( { keyOrCode : '' , timestamp : 0 } ) ;
1919}
2020
21+ function parseEvent (
22+ event : KeyboardEvent | ReactKeyboardEvent < HTMLDivElement > ,
23+ combinedShortcuts : Record < string , KbsInternalShortcut > ,
24+ ) {
25+ const { key, code } = eventToKeyOrCode ( event ) ;
26+ let keyOrCode ;
27+ let shortcut ;
28+ if ( combinedShortcuts [ key ] ) {
29+ shortcut = combinedShortcuts [ key ] ;
30+ keyOrCode = key ;
31+ } else {
32+ shortcut = combinedShortcuts [ code ] ;
33+ keyOrCode = code ;
34+ }
35+
36+ return { key, code, keyOrCode, shortcut } ;
37+ }
38+
2139export function getKeyDownHandler (
2240 lastTrigger : MutableRefObject < LastTriggerData > ,
2341 combinedShortcuts : Record < string , KbsInternalShortcut > ,
@@ -28,33 +46,41 @@ export function getKeyDownHandler(
2846 if ( shouldIgnoreElement ( event . target as HTMLElement ) ) {
2947 return ;
3048 }
31- const { key, code } = eventToKeyOrCode ( event ) ;
32- let keyOrCode ;
33- let shortcut ;
34- if ( combinedShortcuts [ key ] ) {
35- shortcut = combinedShortcuts [ key ] ;
36- keyOrCode = key ;
37- } else {
38- shortcut = combinedShortcuts [ code ] ;
39- keyOrCode = code ;
40- }
41- if ( shortcut ) {
42- event . stopPropagation ( ) ;
43- event . preventDefault ( ) ;
44-
45- if ( shortcut . maxFrequency > 0 ) {
46- const now = performance . now ( ) ;
47- if (
48- event . repeat &&
49- lastTrigger . current . keyOrCode === keyOrCode &&
50- now - lastTrigger . current . timestamp < 1000 / shortcut . maxFrequency
51- ) {
52- return ;
53- }
54- lastTrigger . current = { keyOrCode, timestamp : now } ;
55- }
5649
57- shortcut . handler ( event ) ;
50+ const { key, keyOrCode, shortcut } = parseEvent ( event , combinedShortcuts ) ;
51+ if ( ! shortcut ) return ;
52+ const initialKeys = new Set ( key . split ( ']_' ) ) ;
53+
54+ event . stopPropagation ( ) ;
55+ event . preventDefault ( ) ;
56+
57+ if ( shortcut . maxFrequency > 0 ) {
58+ const now = performance . now ( ) ;
59+ if (
60+ event . repeat &&
61+ lastTrigger . current . keyOrCode === keyOrCode &&
62+ now - lastTrigger . current . timestamp < 1000 / shortcut . maxFrequency
63+ ) {
64+ return ;
65+ }
66+ lastTrigger . current = { keyOrCode, timestamp : now } ;
5867 }
68+
69+ const cleanup = shortcut . handler ( event ) ;
70+ if ( ! cleanup ) return ;
71+
72+ const handleKeyUp = (
73+ event : KeyboardEvent | ReactKeyboardEvent < HTMLDivElement > ,
74+ ) => {
75+ if ( shouldIgnoreElement ( event . target as HTMLElement ) ) return ;
76+ const { key } = parseEvent ( event , combinedShortcuts ) ;
77+ const releasedKeys = key . split ( ']_' ) ;
78+ if ( ! releasedKeys . some ( ( key ) => initialKeys . has ( key ) ) ) return ;
79+
80+ document . body . removeEventListener ( 'keyup' , handleKeyUp ) ;
81+ cleanup ( event ) ;
82+ } ;
83+
84+ document . body . addEventListener ( 'keyup' , handleKeyUp ) ;
5985 } ;
6086}
0 commit comments