import * as React from "react" ; import { IConstructor } from "../../common/constructor" ; import { HOTKEYS_WARN_DECORATOR_NEEDS_REACT_ELEMENT , HOTKEYS_WARN_DECORATOR_NO_METHOD } from "../../common/errors" ; import { getDisplayName , isFunction } from "../../common/utils" ; import { HotkeyScope , HotkeysEvents } from "./hotkeysEvents" ; import { IHotkeysProps } from "./hotkeysTypes" ; export interface IHotkeysTargetComponent extends React . Component { /** Components decorated with the `@HotkeysTarget` decorator must implement React's component `render` function. */ render ( ) : React . ReactElement < any > | null | undefined ; /**
     * Components decorated with the `@HotkeysTarget` decorator must implement
     * this method, and it must return a `Hotkeys` React element.
     */ renderHotkeys : ( ) => React . ReactElement < IHotkeysProps > ; } deprecated export function HotkeysTarget < T extends IConstructor < IHotkeysTargetComponent > > ( WrappedComponent ) { if ( ! isFunction ( WrappedComponent . prototype . renderHotkeys ) ) { console . warn ( HOTKEYS_WARN_DECORATOR_NO_METHOD ) ; } return class HotkeysTargetClass extends WrappedComponent { public static displayName = `HotkeysTarget(${ getDisplayName ( WrappedComponent ) })` ; internal public globalHotkeysEvents : HotkeysEvents = new HotkeysEvents ( HotkeyScope . GLOBAL ) ; internal public localHotkeysEvents : HotkeysEvents = new HotkeysEvents ( HotkeyScope . LOCAL ) ; public componentDidMount ( ) { if ( super . componentDidMount != null ) { super . componentDidMount ( ) ; } document . addEventListener ( "keydown" , this . globalHotkeysEvents . handleKeyDown ) ; document . addEventListener ( "keyup" , this . globalHotkeysEvents . handleKeyUp ) ; } public componentWillUnmount ( ) { super . componentWillUnmount ?. ( ) ; document . removeEventListener ( "keydown" , this . globalHotkeysEvents . handleKeyDown ) ; document . removeEventListener ( "keyup" , this . globalHotkeysEvents . handleKeyUp ) ; this . globalHotkeysEvents . clear ( ) ; this . localHotkeysEvents . clear ( ) ; } public render ( ) { const element = super . render ( ) as JSX . Element ; if ( element == null ) { return element ; } if ( ! React . isValidElement < any > ( element ) ) { console . warn ( HOTKEYS_WARN_DECORATOR_NEEDS_REACT_ELEMENT ) ; return element ; } if ( isFunction ( this . renderHotkeys ) ) { const hotkeys = this . renderHotkeys ( ) ; if ( this . localHotkeysEvents ) { this . localHotkeysEvents . setHotkeys ( hotkeys . props ) ; } if ( this . globalHotkeysEvents ) { this . globalHotkeysEvents . setHotkeys ( hotkeys . props ) ; } if ( this . localHotkeysEvents . count ( ) > 0 ) { const tabIndex = hotkeys . props . tabIndex === undefined ? 0 : hotkeys . props . tabIndex ; const { onKeyDown : existingKeyDown , onKeyUp : existingKeyUp } = element . props ; const handleKeyDownWrapper = ( e ) => { this . localHotkeysEvents . handleKeyDown ( e . nativeEvent as KeyboardEvent ) ; existingKeyDown ?. ( e ) ; } ; const handleKeyUpWrapper = ( e ) => { this . localHotkeysEvents . handleKeyUp ( e . nativeEvent as KeyboardEvent ) ; existingKeyUp ?. ( e ) ; } ; return React . cloneElement ( element , { onKeyDown : handleKeyDownWrapper , onKeyUp : handleKeyUpWrapper , tabIndex , } ) ; } } return element ; } } ; }