@@ -292,6 +292,8 @@ class SpatialNavigation {
292292 this . nativeMode = false ;
293293 this . throttle = 0 ;
294294
295+ this . pressedKeys = { } ;
296+
295297 /**
296298 * Flag used to block key events from this service
297299 * @type {boolean }
@@ -374,6 +376,10 @@ class SpatialNavigation {
374376 }
375377 }
376378
379+ getEventType ( keyCode ) {
380+ return findKey ( this . getKeyMap ( ) , ( code ) => keyCode === code ) ;
381+ }
382+
377383 bindEventHandlers ( ) {
378384 if ( window ) {
379385 this . keyDownEventListener = ( event ) => {
@@ -385,22 +391,28 @@ class SpatialNavigation {
385391 this . logIndex += 1 ;
386392 }
387393
388- const eventType = findKey ( this . getKeyMap ( ) , ( code ) => event . keyCode === code ) ;
394+ const eventType = this . getEventType ( event . keyCode ) ;
389395
390396 if ( ! eventType ) {
391397 return ;
392398 }
393399
400+ this . pressedKeys [ eventType ] = this . pressedKeys [ eventType ] ? this . pressedKeys [ eventType ] + 1 : 1 ;
401+
394402 event . preventDefault ( ) ;
395403 event . stopPropagation ( ) ;
396404
405+ const details = {
406+ pressedKeys : this . pressedKeys
407+ } ;
408+
397409 if ( eventType === KEY_ENTER && this . focusKey ) {
398- this . onEnterPress ( ) ;
410+ this . onEnterPress ( details ) ;
399411
400412 return ;
401413 }
402414
403- const preventDefaultNavigation = this . onArrowPress ( eventType ) === false ;
415+ const preventDefaultNavigation = this . onArrowPress ( eventType , details ) === false ;
404416
405417 if ( preventDefaultNavigation ) {
406418 this . log ( 'keyDownEventListener' , 'default navigation prevented' ) ;
@@ -414,13 +426,20 @@ class SpatialNavigation {
414426 if ( this . throttle ) {
415427 this . keyDownEventListener =
416428 lodashThrottle ( this . keyDownEventListener . bind ( this ) , this . throttle , THROTTLE_OPTIONS ) ;
429+ }
417430
418- // When throttling then make sure to only throttle key down and cancel any queued functions in case of key up
419- this . keyUpEventListener = ( ) => this . keyDownEventListener . cancel ( ) ;
431+ // When throttling then make sure to only throttle key down and cancel any queued functions in case of key up
432+ this . keyUpEventListener = ( event ) => {
433+ const eventType = this . getEventType ( event . keyCode ) ;
420434
421- window . addEventListener ( 'keyup' , this . keyUpEventListener ) ;
422- }
435+ Reflect . deleteProperty ( this . pressedKeys , eventType ) ;
436+
437+ if ( this . throttle ) {
438+ this . keyDownEventListener . cancel ( ) ;
439+ }
440+ } ;
423441
442+ window . addEventListener ( 'keyup' , this . keyUpEventListener ) ;
424443 window . addEventListener ( 'keydown' , this . keyDownEventListener ) ;
425444 }
426445 }
@@ -437,7 +456,7 @@ class SpatialNavigation {
437456 }
438457 }
439458
440- onEnterPress ( ) {
459+ onEnterPress ( details ) {
441460 const component = this . focusableComponents [ this . focusKey ] ;
442461
443462 /* Guard against last-focused component being unmounted at time of onEnterPress (e.g due to UI fading out) */
@@ -454,7 +473,7 @@ class SpatialNavigation {
454473 return ;
455474 }
456475
457- component . onEnterPressHandler && component . onEnterPressHandler ( ) ;
476+ component . onEnterPressHandler && component . onEnterPressHandler ( details ) ;
458477 }
459478
460479 onArrowPress ( ...args ) {
0 commit comments