import { useEffect , useRef } from 'react' ; export function KeyHandlerReact < ET extends Element > ( ) { const keys = new Set < number > ( ) ; const bindObject = { onKeyDown : ( e ) => { e . stopPropagation ( ) ; keys . add ( e . keyCode ) ; console . log ( 'onKeyDown' , keys ) ; } , onKeyUp : ( e ) => { e . stopPropagation ( ) ; keys . delete ( e . keyCode ) ; console . log ( 'onKeyUp' , keys ) ; } , onBlur : ( ) => { keys . clear ( ) ; console . log ( 'onBlur' , keys ) ; } , } ; return bindObject ; } type KeyHandlerPlain_OnTimer = ( keys : Set < string > ) => boolean ; class KeyHandlerPlainState { timerId ? : number ; event ? : KeyboardEvent ; keys = new Set < string > ( ) ; timerAgain = false ; } export function KeyHandlerPlain ( onTimer , interval ? , preventList ? , stopList ? , enabled ? ) { const state = useRef < KeyHandlerPlainState > ( new KeyHandlerPlainState ( ) ) . current ; if ( ! interval ) { interval = 33 ; } function timerFunc ( ) { if ( state . timerAgain || state . keys . size ) { if ( state . timerAgain || state . event ?. target === document . body ) { state . timerAgain = onTimer ( state . keys ) ; } } else { if ( state . timerId ) { clearInterval ( state . timerId ) ; state . timerId = undefined ; } } } const onKeyDown = ( e ) => { if ( enabled && ! enabled ( ) ) { return ; } if ( ! preventList || preventList ?. has ( e . code ) ) { e . preventDefault ( ) ; } if ( ! stopList || stopList ?. has ( e . code ) ) { e . stopPropagation ( ) ; } state . event = e ; state . keys . add ( e . code ) ; if ( ! state . timerId && state . event . target === document . body ) { state . timerId = setInterval ( timerFunc , interval ) ; } } ; const onKeyUp = ( e ) => { if ( enabled && ! enabled ( ) ) { return ; } if ( ! preventList || preventList ?. has ( e . code ) ) { e . preventDefault ( ) ; } if ( ! stopList || stopList ?. has ( e . code ) ) { e . stopPropagation ( ) ; } state . event = e ; state . keys . delete ( e . code ) ; } ; const onBlur = ( ) => { state . keys . clear ( ) ; } ; useEffect ( ( ) => { window . addEventListener ( 'keydown' , onKeyDown ) ; window . addEventListener ( 'keyup' , onKeyUp ) ; window . addEventListener ( 'blur' , onBlur ) ; return ( ) => { window . removeEventListener ( 'keydown' , onKeyDown ) ; window . removeEventListener ( 'keyup' , onKeyUp ) ; window . removeEventListener ( 'blur' , onBlur ) ; } ; } , [ ] ) ; }