All Versions
10
Latest Version
Avg Release Cycle
20 days
Latest Release
1743 days ago

Changelog History

  • v2.0.0 Changes

    July 12, 2019

    ๐Ÿš€ This release represents a complete re-write of the internals and much of the interface of react-hotkeys. Mousetrap has been removed as a dependency, and instead react-hotkeys works on the top of the React SyntheticEvent events system.

    โฌ†๏ธ > Upgrading from v1.*?

    ๐Ÿš€ > This release is the same as the v2.0.0-pre9 and these release notes contain a summary of the changes moving from v1.* to v2.0.0.

    โฌ†๏ธ > Upgrading from v2.0.0-pre*?

    ๐Ÿš€ > Ignore this set of release notes, and follow the notes for each each pre-release starting from the version you are using, up to v2.0.0-pre9.

    ๐Ÿ’ฅ Breaking Changes

    __mousetrap__ is no longer available

    โšก๏ธ Rather unsurprisingly, with the removal of Mousetrap, it's no longer possible to access the private Mousetrap instance to configure it. Many of the use-cases for needing to do so have been covered by API updates described below. If your use-case is not covered, however, please create a new issue.

    ๐Ÿšš HotKeyMapMixin has been removed

    This was an internal part of react-hotkeys and is no longer used, and so it does not makes sense to continue to provide it.

    ๐Ÿšš FocusTrap has been removed

    Similar to HotKeyMapMixin, this was an internal part of react-hotkeys and is no longer used, and so it does not makes sense to continue to provide it.

    withHotKeys has been replaced

    ๐Ÿšš The old withHotKeys function has been repurposed and should not be used in the same way the old one was (more on this later). The old implementation is still available as deprecatedWithHotKeys, but it is no longer officially supported and will be removed in future versions.

    Before:

    import {withHotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };withHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    After (suggested):

    You can write your own function or HoC that supplies the same keyMap to a component passed to it.

    import {HotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };function withActions(keyMap, Component) { return function(props) { return( \<HotKeys keyMap={keyMap}\>\<Component {...props} /\>\</HotKeys\> ); } }deprecatedWithHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    โช After (to restore old behaviour):

    import {deprecatedWithHotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };deprecatedWithHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    ๐Ÿšš focused and attach props hav been removed

    The focused and attach props were introduced as a way to bind keymaps that were either always active, or available outside of the React application. They are no longer needed with the introduction of GlobalHotkeys.

    Before:

    import {HotKeys} from 'react-hotkeys';\<HotKeys focused={true} attach={document} keyMap={keyMap} handlers={handlers}\>\<div\> My content \</div\>\</HotKeys\>
    

    After:

    import {GlobalHotKeys} from 'react-hotkeys';\<GlobalHotKeys keyMap={keyMap} handlers={handlers} /\>\<div\> My content\</div\>
    

    ๐Ÿ—„ Hard sequences are deprecated and turned off by default

    ๐ŸŽ Hard sequences (handlers associated to actions with names that are valid key sequence strings that implicitly define actions that are matched by the corresponding key sequence) are now deprecated and turned off by default. They can be re-enabled (at a performance penalty) using the enableHardSequences configuration option:

    import {configure} from 'react-hotkeys';configure({ enableHardSequences: true});
    

    0๏ธโƒฃ Default key event is now always keydown

    0๏ธโƒฃ react-hotkeys used to rely on the implicit behaviour of Mousetrap to guess the best key event based on the keys involved (this was, roughly speaking, keydown for non-modifier keys and keypress for modifier keys). Now by default, react-hotkeys will match hotkey sequences on the keydown event (or, more precisely: on the keydown event of the last key to complete the last combination in a sequence).

    If you want to trigger a single action on a different key event, you can use the object syntax and the action attribute to explicitly set which key event you wish to bind to:

    const keyMap = { CONTRACT: 'alt+down', COMMAND\_DOWN: {sequence: 'command', action: 'keydown'}, };
    

    ๐Ÿ”ง If you want to change the default key event for all hotkeys, you can use the defaultKeyEvent option of the configuration API.

    Keypress events are now simulated for modifier keys

    ๐Ÿ’ป Before, you had to rely on Mousetrap guessing the best key event for your key combination (unless you explicitly defined an event) and if you bound to a key combination to a keypress event, it did not work (the browser does not emit these events for modifier keys).

    react-hotkeys now simulates these events internally (they aren't emitted to the rest of your React components) so you do not have to worry about if your key combination includes a modifier key when binding to keypress.

    This shouldn't affect most library consumers, but is listed as a breaking change as it can conceivably cause different behaviour for the same application code.

    stopPropagation() is now observed

    Because react-hotkeys now uses the React event system, event.stopPropagation() now works as expected. If you have event listeners in your React application that call event.stopPropagation() before the event reaches a <HotKeys /> or <GlobalHotkeys /> component that has a keyMap prop, react-hotkeys never sees it.

    If you want to hide that a key has been pressed at all, you will need to capture all 3 of the keydown, keypress and keyup events.

    0๏ธโƒฃ Key events from input, select and textarea tags are ignored by default

    If you were ignoring key events from certain inputs by overriding the stopCallback function on mousetrap as has been previously suggested, you no longer need to.

    0๏ธโƒฃ By default, all key events that originate from <input>, <select> or <textarea>, or have a isContentEditable attribute of true are ignored by react-hotkeys.

    ๐Ÿ”ง If this is not what you want for your application, you can modify the list of tags using the ignoreTags configuration option or if you need additional control, you can specify a brand new function using the ignoreEventsCondition configuration option.

    Before:

    const mousetrap = this.hotKeys.\_\_mousetrap\_\_;mousetrap.\_\_proto\_\_.stopCallback = (e, element) =\> { // Your custom logic here};
    

    After:

    ๐Ÿ”ง (After you've confirmed the default function does not match your use-case):

    import {configure} from 'react-hotkeys';configure({ ignoreEventsCondition: function(event) { const { target: element } = event; // Your custom logic here } });
    

    stopPropagation() is called on events that are ignored

    0๏ธโƒฃ By default, react-hotkeys calls stopPropagation() on keyboard events that it ignores, at the first <HotKeys> component with a non-empty keyMap prop (or a hard sequence defined in the handlers prop, if hard sequences are enabled). This makes react-hotkeys more efficient, but may be hiding keyboard events from other key listeners you have in place in your React app.

    ๐Ÿ”ง You can disable this behaviour using the stopEventPropagationAfterIgnoring configuration option:

    import {configure} from 'react-hotkeys';configure({ stopEventPropagationAfterIgnoring: false});
    

    โšก๏ธ Updates to keyMaps and handlers after focus are ignored by default

    ๐ŸŽ For performance reasons, by default react-hotkeys takes the keyMap and handlers prop values when <HotKeys> components are focused and when <GlobalHotKeys> components are mounted. It ignores all subsequent updates to their values when these props change.

    If you need the ability to change them while a <HotKeys> component is still in focus, or while <GlobalHotKeys> is still mounted, then you can pass the allowChanges prop, permitting this behaviour for the particular component.

    import {HotKeys} from 'react-hotkeys';class MyComponent extends React.Component { render() { return ( \<HotKeys keyMap={keyMapThatChanges} handler={handlersThatChange} allowChanges\>\</HotKeys\> ); } }
    

    ๐ŸŽ If you need to do this for all your <HotKeys> and <GlobalHotKeys> components, you can use the ignoreKeymapAndHandlerChangesByDefault option for the Configuration API. This should normally never be done, as it can have significant performance implications.

    import {configure} from 'react-hotkeys';configure({ ignoreKeymapAndHandlerChangesByDefault: false});
    

    ๐Ÿ†• New features

    ๐Ÿ’ป Browser keynames are now supported in key sequence definitions

    ๐Ÿ’ป You can now use browser key names when defining your sequences, in addition to Mousetrap's name for the keys.

    ๐Ÿ†• New withHotKeys HoC - a way to avoid rendering a wrapping div

    If wrapping your component in a DOM-mountable node is not acceptable, or you need more control over how the react-hotkeys props are applied, then the new withHotKeys() HoC is available.

    Simple use-case

    The simplest use-case of withHotKeys() is to simply pass it your component class as the first argument. What is returned is a new component that will accept all of the same props as a <HotKey> component, so you can specify key maps and handlers at render time, for example.

    The component you wrap must take responsibility for passing the hotKeys props to a DOM-mountable element. If you fail to do this, key events will not be detected when a descendant of the component is in focus.

    import {withHotKeys} from 'react-hotkeys';class MyComponent extends Component { render() { /\*\* \* Must unwrap hotKeys prop and pass its values to a DOM-mountable \* element (like the div below).\*/const {hotKeys, ...remainingProps} = this.props; return ( \<div { ... { ...hotKeys, ...remainingProps } } \>\<span\>My HotKeys are effective here\</span\> { this.props.children } \</div\> ) } }const MyHotKeysComponent = withHotKeys(MyComponent);const keyMap = { TEST: 't'};const handlers = { TEST: ()=\> console.log('Test') };\<MyHotKeysComponent keyMap={ keyMap } handlers={ handlers }\>\<div\> You can press 't' to log to the console. \</div\>\</MyHotKeysComponent\>
    

    0๏ธโƒฃ Pre-defining default prop values

    0๏ธโƒฃ You can use the second argument of withHotKeys to specify default values for any props you would normally pass to <HotKeys />. This means you do not have to specify them at render-time.

    ๐Ÿ”€ > If you do provide prop values when you render the component, these will be merged with (and override) those defined in the second argument of withHotKeys.

    import {withHotKeys} from 'react-hotkeys';class MyComponent extends Component { render() { /\*\* \* Must unwrap hotKeys prop and pass its values to a DOM-mountable \* element (like the div below).\*/const {hotKeys, ...remainingProps} = this.props; return ( \<div { ... { ...hotKeys, ...remainingProps } } \>\<span\>My HotKeys are effective here\</span\> { this.props.children } \</div\> ) } }const keyMap = { TEST: 't'};const handlers = { TEST: ()=\> console.log('Test') };const MyHotKeysComponent = withHotKeys(MyComponent, {keyMap, handlers});/\*\* \* Render without having to specify prop values \*/\<MyHotKeysComponent\>\<div\> You can press 't' to log to the console. \</div\>\</MyHotKeysComponent\>
    

    ๐Ÿ†• New GlobalHotKeys component

    <GlobalHotKeys> components match key events that occur anywhere in the document (even when no part of your React application is in focus). They replace the need for the focused and attach prop.

    const keyMap = { SHOW\_ALL\_HOTKEYS: 'shift+?' };const handlers = { SHOW\_ALL\_HOTKEYS: this.showHotKeysDialog };\<GlobalHotKeys keyMap={ keyMap } handlers={ handlers } /\>
    

    ๐Ÿ‘ป <GlobalHotKeys> generally have no need for children, so should use a self-closing tag (as shown above). The only exception is when you are nesting other <GlobalHotKeys> components somewhere in the descendants (these are mounted before their parents, and so are generally matched first).

    ๐Ÿ†• New IgnoreKeys component

    If you want react-hotkeys to ignore key events coming from a particular area of your app when it is in focus, you can use the new <IgnoreKeys/> component:

    import {IgnoreKeys} from 'react-hotkeys';\<IgnoreKeys\>/\*\* \* Children that, when in focus, should have its key events ignored by \* react hotkeys\*/\</IgnoreKeys\>
    

    ๐Ÿ†• New ObserveKeys component

    0๏ธโƒฃ The <ObserveKeys /> component (and corresponding withObserveKeys method to avoid wrapper div) are for defining white-list exceptions to the the default ignoreEventsCondition

    <ObserveKeys only={'Escape'}>
      <input
        autoFocus
        onChange={({target: {value}}) => this.setState({ filter: value })}
        value={filter}
        placeholder='Filter'
      />
    </ObserveKeys>
    

    How actions and handlers are resolved

    Regardless of where <GlobalHotKeys> components appear in the render tree, they are matched with key events after the event has finished propagating through the React app (if the event originated in the React at all). This means if your React app is in focus and it handles a key event, it will be ignored by the <GlobalHotKeys> components.

    ๐Ÿšš The order used for resolving actions and handlers amongst <GlobalHotKeys> components, is the order in which they mounted (those mounted first, are given the chance to handle an action first). When a <GlobalHotKeys> component is unmounted, it is removed from consideration. This can get less deterministic over the course of a long session using a React app as components mount and unmount, so it is best to define actions and handlers that are globally unique.

    ๐ŸŽ It is recommended to use <HotKeys> components whenever possible for better performance and reliability.

    You can use the autofocus attributes or programmatically manage focus to automatically focus your React app so the user doesn't have to select it in order for hot keys to take effect. It is common practice to place a <HotKeys> component towards the top of your application to match hot keys across your entire React application.

    Can now generate an application key map

    It's now possible to generate a list of hotkeys for the application to display to the user.

    ๐Ÿ†• New innerRef prop

    Thanks to #124, <ReactHotkeys /> now accepts an innerRef prop:

    class MyComponent extends Component { componentDidMount() { this.\_container.focus(); } render() { return ( \<HotKeys innerRef={ (c) =\> this.\_container = c } \> My focusable content \</div\> ) } }
    

    Key map name, description and groups

    You can now specify name, description and groups for key maps #154 (More info)

    SHOW\_DIALOG: { name: 'Display keyboard shortcuts', sequence: 'shift+?', action: 'keyup' }
    

    Custom key codes

    You can now define custom key codes for WebOS and other environments (#156) (More info)

    import {configure} from 'react-hotkeys';configure({ customKeyCodes: { 10009: 'BackTV' } })
    

    Dynamic key maps at runtime

    You can now set dynamic key maps at runtime (#158) (More info)

    Small changes

    • โœ‚ Removed upper limit on React peer dependency version.
    • cmd is now an accepted alias for Command/Meta key

    ๐Ÿ†• New Configuration configuration API for global settings

    ๐Ÿ”ง The default behaviour across all <HotKeys> and <GlobalHotkeys> components is configured using the configure method.

    ๐Ÿ”ง > configure() should be called as your app is initialising and before the first time you mount a <HotKeys> component anywhere in your app.

    ๐Ÿ†• New comprehensive logging

    ๐ŸŒฒ react-hotkeys now provides comprehensive logging of all of its internal behaviour and allows setting one of 6 log levels.

    ๐Ÿ‘€ The default level is warn, which provides warnings and errors only, and is generally sufficient for most usage. However, if you are troubleshooting an issue or reporting a bug, you should increase the log level to debug or verbose to see what is going on, and be able to communicate it concisely.

    Optimisations

    ๐Ÿš€ Some improved and additional optimisations have been implemented as part of this release.

    ๐Ÿ›  Bugfixes

    • Possible wrong typescript definition #129
    • โš  Warnings in react-hotkeys when using React's strict mode #128
    • Pass handlers to withHotKeys #127
    • export all typescipt types #120
    • ๐Ÿš€ Child handler doesn't stopPropagation since 1.1.4 release #106
  • v2.0.0-pre9 Changes

    July 11, 2019

    Potentially Breaking Changes

    • ๐Ÿ”ง The configuration option allowCombinationSubmatches is now ignored when the Cmd key is pressed down (submatches are always allowed when Cmd is pressed). This is to fix the following bug.

    ๐Ÿ›  Bugfixes

    • ๐Ÿ›  Fix moving between actions bound to the Cmd (Meta) key (e.g.cmd+1 -> cmd+2 without releasing Cmd) #201
  • v2.0.0-pre8 Changes

    June 17, 2019

    Potentially breaking changes

    • ๐Ÿ”ง Repeated keydown events that occur when a key is held down are now ignored by default (#177). If you want the old behaviour, you can use the ignoreRepeatedEventsWhenKeyHeldDown configuration option.

    ๐Ÿ†• New features

    • You can now specify name, description and groups for key maps #154 (More info)

      SHOW_DIALOG: { name: 'Display keyboard shortcuts', sequence: 'shift+?', action: 'keyup' }

    • You can now define custom key codes for WebOS and other environments (#156) (More info)

      import {configure} from 'react-hotkeys';configure({ customKeyCodes: { 10009: 'BackTV' } })

    • You can now set dynamic key maps at runtime (#158) (More info)

    ๐Ÿ› Bug fixes

    • Action handlers that use useState now work correctly (#182, #196)
    • ๐Ÿ›  Fix some key combinations involving cmd acting as if those keys were still pressed down after they've been released (#183)
    • ๐Ÿ›  Fix some keys being incorrectly declared as invalid when used with the except or only options of ObserveKeys and IgnoreKeys (#198)
  • v2.0.0-pre7 Changes

    June 02, 2019

    Potentially breaking changes

    0๏ธโƒฃ react-hotkeys now ignores key combination submatches #186 by default.

    This resolves the issue of when an application has a context-dependent action, bound to a short key combination (e.g.?) and a longer global action bound to a longer key combination (e.g. shift+?), and the longer key combination is hidden behind the shorter one and never triggered whenever a child of the component that defines the shorter combination is in focus (#161, #181, #175).

    ๐Ÿ”ง If you would like the old behaviour, you can re-enable submatches with the allowCombinationSubmatches configuration option:

    configure({
      allowCombinationSubmatches: true,
    })
    

    ๐Ÿ‘€ For a full description of what this change means, and the tradeoffs, see the How combinations and sequences are matched section of the Readme.

    ๐Ÿ›  Bugfixes

    • ๐Ÿ›  Fix bug that prevented binding to keydown and key for the same key combination #166

    ๐Ÿ†• New features

    HotKeys root prop

    A new root prop is now available for HotKeys that allows placing HotKeys components at the root of the app without actually defining any key maps or handlers, to ensure all key events are recorded (#188):

    <HotKeys root>
      //... application
    </HotKeys>
    

    ๐Ÿš€ For details of when you may want to use this, see the React Hotkeys thinks I'm holding down a key I've released section of the readme.

    GlobalHotKeys report missed keyboard events

    GlobalHotKeys components now report key events that may have been missed by HotKeys, to avoid hanging key combinations when an action handler changes focus outside of the part of the React app below the highest HotKeys component.

    ๐Ÿš€ Again, you can see the React Hotkeys thinks I'm holding down a key I've released section of the readme for more details.

  • v2.0.0-pre6 Changes

    May 29, 2019

    ๐Ÿš€ This release still has a number of known issues, but hopefully it will go some way to addressing some of the issues people are experiencing.

    ๐Ÿ›  Bugfixes

    • Legacy context API has been detected within a strict-mode tree: in StrictMode #151
    • ref prop now has correct TypeScript type (Thanks @natew!) #168
    • ignoreEventsCondition now has correct argument TypeScript definition (Thanks @taromurao!) #170
    • Global hotkeys throwing errors after dom changes (Thanks @mrlubos & @StephenHaney!) #150
    • IgnoreKeys can't handle Backspace #172
    • Duplicate focus tree IDs cause keypresses to be ignored #173

    ๐Ÿ‘Œ Improvements

  • v2.0.0-pre5 Changes

    April 18, 2019

    ๐Ÿ’ฅ Breaking changes

    • Delete and Backspace (and the variant del) are no longer treated as aliases for one another. You will need to bind handlers to both, if you want to maintain backwards compatibility. #145, #159

    ๐Ÿ›  Bugfixes (that may be breaking changes if you depended on them)

    • ๐Ÿ›  When resetting key history, the mapping of key aliases for the keys that had already been pressed was being lost. This has now been fixed.
    • ๐Ÿš€ When the window loses focus, all keys that are currently pressed down are automatically released. This resolves the issue people were experiencing where React Hotkeys was prematurely triggering handlers for key combinations that caused the window to lose focus (e.g. displaying an alert), after that handler had been already called once #143

    ๐Ÿ›  Bugfixes

    • โž• Add the configure function to index.d.ts
    • โž• Add the withObserveKeys function to index.d.ts
    • ๐Ÿ›  Miscellaneous other fixes to index.d.ts (Thanks @shripadk and @Huvik!) #153 #163
    • ๐Ÿ›  Fix Github's ability to detect the correct license type
  • v2.0.0-pre4 Changes

    January 27, 2019

    ๐Ÿ’ฅ Breaking Changes

    ๐Ÿ›  Bugfixes

    • HotKeys not working for form fields/inputs #138
    • ๐Ÿ›  Fix a number of issues with the TypeScript definitions in index.d.ts
    • ๐Ÿ›  Fix Escape not being treated as a "special key" (non single char key name)
    • ๐Ÿ›  Fix incorrect JSDoc @private annotations
    • ๐Ÿ›  Fix incorrect object JSDoc @typedefs

    ๐Ÿ†• New Features

    • cmd is now an accepted alias for Command/Meta key
    • โž• Added a way of filtering key maps to the example app
    • โž• Add an <ObserveKeys /> component (and corresponding withObserveKeys method to avoid wrapper div) for defining white-list exceptions to the the default ignoreEventsCondition

      this.setState({ filter: value })} value={filter} placeholder='Filter' />

    ๐Ÿ‘Œ Improvements

    • ๐Ÿ‘Œ Improvements to the way the test suite is run #135 #139 #142
    • Readme improvements #139
    • ๐ŸŒฒ Standardise and improve logging statements
    • ๐Ÿ›  Fix various minor typos and static analysis suggestions
    • โœ‚ Remove internal concepts no longer used
  • v2.0.0-pre3 Changes

    January 17, 2019

    ๐Ÿ›  Bugfixes

    • ๐Ÿ›  Fixed some logging messages
    • ๐Ÿ›  Fixed <HotKeys> passing the component prop down to its children
    • ๐Ÿ›  Fixed blurred components unnecessarily holding on to their focus tree ids when a key event has yet to occur

    ๐Ÿ‘Œ Improvements

    • ๐Ÿš€ Make warning about Readme relating to pre-release more obvious
  • v2.0.0-pre2 Changes

    January 13, 2019

    Potentially breaking changes

    • โœ‚ Removed upper limit on React peer dependency version.

    ๐Ÿ†• New features

    Can now generate an application key map

    It's now possible to generate a list of hotkeys for the application to display to the user.

    ๐Ÿ†• New innerRef prop

    Thanks to #124, <ReactHotkeys /> now accepts an innerRef prop:

    class MyComponent extends Component { componentDidMount() { this.\_container.focus(); } render() { return ( \<HotKeys innerRef={ (c) =\> this.\_container = c } \> My focusable content \</div\> ) } }
    
  • v2.0.0-pre1 Changes

    January 10, 2019

    ๐Ÿš€ This release represents a complete re-write of the internals and much of the interface of react-hotkeys. Mousetrap has been removed as a dependency, and instead react-hotkeys works on the top of the React SyntheticEvent events system.

    ๐Ÿš€ This is a pre-release, so it not yet ready for use in production applications, but it does represent the future direction of the library.

    ๐Ÿ’ฅ Breaking Changes

    __mousetrap__ is no longer available

    โšก๏ธ Rather unsurprisingly, with the removal of Mousetrap, it's no longer possible to access the private Mousetrap instance to configure it. Many of the use-cases for needing to do so have been covered by API updates described below. If your use-case is not covered, however, please create a new issue.

    ๐Ÿšš HotKeyMapMixin has been removed

    This was an internal part of react-hotkeys and is no longer used, and so it does not makes sense to continue to supply.

    ๐Ÿšš FocusTrap has been removed

    Similar to HotKeyMapMixin, this was an internal part of react-hotkeys and is no longer used, and so it does not makes sense to continue to supply.

    withHotKeys has been replaced

    ๐Ÿšš The old withHotKeys function has been repurposed and should not be used in the same way the old one was (more on this later). The old implementation is still available as deprecatedWithHotKeys, but it is no longer officially supported and will be removed in future versions.

    Before:

    import {withHotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };withHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    After (suggested):

    You can write your own function or HoC that supplies the same keyMap to a component passed to it.

    import {HotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };function withActions(keyMap, Component) { return function(props) { return( \<HotKeys keyMap={keyMap}\>\<Component {...props} /\>\</HotKeys\> ); } }deprecatedWithHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    โช After (to restore old behaviour):

    import {deprecatedWithHotKeys} from 'react-hotkeys';const ACTION\_KEY\_MAP = { 'changeColor': 'alt+c', };deprecatedWithHotKeys(ACTION\_KEY\_MAP)(HOCWrappedNode);
    

    ๐Ÿšš focused and attach props hav been removed

    The focused and attach props were introduced as a way to bind keymaps that were either always active, or available outside of the React application. They are no longer needed with the introduction of GlobalHotkeys.

    Before:

    import {HotKeys} from 'react-hotkeys';\<HotKeys focused={true} attach={document} keyMap={keyMap} handlers={handlers}\>\<div\> My content \</div\>\</HotKeys\>
    

    After:

    import {GlobalHotKeys} from 'react-hotkeys';\<GlobalHotKeys keyMap={keyMap} handlers={handlers} /\>\<div\> My content\</div\>
    

    ๐Ÿ—„ Hard sequences are deprecated and turned off by default

    ๐ŸŽ Hard sequences (handlers associated to actions with names that are valid key sequence strings that implicitly define actions that are matched by the corresponding key sequence) are now deprecated and turned off by default. They can be re-enabled (at a performance penalty) using the enableHardSequences configuration option:

    import {configure} from 'react-hotkeys';configure({ enableHardSequences: true});
    

    0๏ธโƒฃ Default key event is now always keydown

    0๏ธโƒฃ react-hotkeys used to rely on the implicit behaviour of Mousetrap to guess the best key event based on the keys involved (this was, roughly speaking, keydown for non-modifier keys and keypress for modifier keys). Now by default, react-hotkeys will match hotkey sequences on the keydown event (or, more precisely: on the keydown event of the last key to complete the last combination in a sequence).

    If you want to trigger a single action on a different key event, you can use the object syntax and the action attribute to explicitly set which key event you wish to bind to:

    const keyMap = { CONTRACT: 'alt+down', COMMAND\_DOWN: {sequence: 'command', action: 'keydown'}, };
    

    ๐Ÿ”ง If you want to change the default key event for all hotkeys, you can use the defaultKeyEvent option of the configuration API.

    Keypress events are now simulated for modifier keys

    ๐Ÿ’ป Before, you had to rely on Mousetrap guessing the best key event for your key combination (unless you explicitly defined an event) and if you bound to a key combination to a keypress event, it did not work (the browser does not emit these events for modifier keys).

    react-hotkeys now simulates these events internally (they aren't emitted to the rest of your React components) so you do not have to worry about if your key combination includes a modifier key when binding to keypress.

    This shouldn't affect most library consumers, but is listed as a breaking change as it can conceivably cause different behaviour for the same application code.

    stopPropagation() is now observed

    Because react-hotkeys now uses the React event system, event.stopPropagation() now works as expected. If you have event listeners in your React application that call event.stopPropagation() before the event reaches a <HotKeys /> or <GlobalHotkeys /> component that has a keyMap prop, react-hotkeys never sees it.

    If you want to hide that a key has been pressed at all, you will need to capture all 3 of the keydown, keypress and keyup events.

    0๏ธโƒฃ Key events from input, select and textarea tags are ignored by default

    If you were ignoring key events from certain inputs by overriding the stopCallback function on mousetrap as has been previously suggested, you no longer need to.

    0๏ธโƒฃ By default, all key events that originate from <input>, <select> or <textarea>, or have a isContentEditable attribute of true are ignored by react-hotkeys.

    ๐Ÿ”ง If this is not what you want for your application, you can modify the list of tags using the ignoreTags configuration option or if you need additional control, you can specify a brand new function using the ignoreEventsCondition configuration option.

    Before:

    const mousetrap = this.hotKeys.\_\_mousetrap\_\_;mousetrap.\_\_proto\_\_.stopCallback = (e, element) =\> { // Your custom logic here};
    

    After:

    ๐Ÿ”ง (After you've confirmed the default function does not match your use-case):

    import {configure} from 'react-hotkeys';configure({ ignoreEventsCondition: function(event) { const { target: element } = event; // Your custom logic here } });
    

    stopPropagation() is called on events that are ignored

    0๏ธโƒฃ By default, react-hotkeys calls stopPropagation() on keyboard events that it ignores, at the first <HotKeys> component with a non-empty keyMap prop (or a hard sequence defined in the handlers prop, if hard sequences are enabled). This makes react-hotkeys more efficient, but may be hiding keyboard events from other key listeners you have in place in your React app.

    ๐Ÿ”ง You can disable this behaviour using the stopEventPropagationAfterIgnoring configuration option:

    import {configure} from 'react-hotkeys';configure({ stopEventPropagationAfterIgnoring: false});
    

    โšก๏ธ Updates to keyMaps and handlers after focus are ignored by default

    ๐ŸŽ For performance reasons, by default react-hotkeys takes the keyMap and handlers prop values when <HotKeys> components are focused and when <GlobalHotKeys> components are mounted. It ignores all subsequent updates
    to their values when these props change.

    If you need the ability to change them while a <HotKeys> component is still in focus, or while <GlobalHotKeys> is still mounted, then you can pass the allowChanges prop, permitting this behaviour for the particular component.

    import {HotKeys} from 'react-hotkeys';class MyComponent extends React.Component { render() { return ( \<HotKeys keyMap={keyMapThatChanges} handler={handlersThatChange} allowChanges\>\</HotKeys\> ); } }
    

    ๐ŸŽ If you need to do this for all your <HotKeys> and <GlobalHotKeys> components, you can use the ignoreKeymapAndHandlerChangesByDefault option for the Configuration API. This should normally never be done, as it can have significant performance implications.

    import {configure} from 'react-hotkeys';configure({ ignoreKeymapAndHandlerChangesByDefault: false});
    

    ๐Ÿ†• New features

    ๐Ÿ’ป Browser keynames are now supported in key sequence definitions

    ๐Ÿ’ป You can now use browser key names when defining your sequences, in addition to Mousetrap's name for the keys.

    ๐Ÿ†• New withHotKeys HoC - a way to avoid rendering a wrapping div

    If wrapping your component in a DOM-mountable node is not acceptable, or you need more control over how the react-hotkeys props are applied, then the new withHotKeys() HoC is available.

    Simple use-case

    The simplest use-case of withHotKeys() is to simply pass it your component class as the first argument. What is returned is a new component that will accept all of the same props as a <HotKey> component, so you can specify key maps and handlers at render time, for example.

    The component you wrap must take responsibility for passing the hotKeys props to a DOM-mountable element. If you fail to do this, key events will not be detected when a descendant of the component is in focus.

    import {withHotKeys} from 'react-hotkeys';class MyComponent extends Component { render() { /\*\* \* Must unwrap hotKeys prop and pass its values to a DOM-mountable \* element (like the div below).\*/const {hotKeys, ...remainingProps} = this.props; return ( \<div { ... { ...hotKeys, ...remainingProps } } \>\<span\>My HotKeys are effective here\</span\> { this.props.children } \</div\> ) } }const MyHotKeysComponent = withHotKeys(MyComponent);const keyMap = { TEST: 't'};const handlers = { TEST: ()=\> console.log('Test') };\<MyHotKeysComponent keyMap={ keyMap } handlers={ handlers }\>\<div\> You can press 't' to log to the console. \</div\>\</MyHotKeysComponent\>
    

    0๏ธโƒฃ Pre-defining default prop values

    0๏ธโƒฃ You can use the second argument of withHotKeys to specify default values for any props you would normally pass to <HotKeys />. This means you do not have to specify them at render-time.

    ๐Ÿ”€ > If you do provide prop values when you render the component, these will be merged with (and override) those defined in the second argument of withHotKeys.

    import {withHotKeys} from 'react-hotkeys';class MyComponent extends Component { render() { /\*\* \* Must unwrap hotKeys prop and pass its values to a DOM-mountable \* element (like the div below).\*/const {hotKeys, ...remainingProps} = this.props; return ( \<div { ... { ...hotKeys, ...remainingProps } } \>\<span\>My HotKeys are effective here\</span\> { this.props.children } \</div\> ) } }const keyMap = { TEST: 't'};const handlers = { TEST: ()=\> console.log('Test') };const MyHotKeysComponent = withHotKeys(MyComponent, {keyMap, handlers});/\*\* \* Render without having to specify prop values \*/\<MyHotKeysComponent\>\<div\> You can press 't' to log to the console. \</div\>\</MyHotKeysComponent\>
    

    ๐Ÿ†• New GlobalHotKeys component

    <GlobalHotKeys> components match key events that occur anywhere in the document (even when no part of your React application is in focus). They replace the need for the focused and attach prop.

    const keyMap = { SHOW\_ALL\_HOTKEYS: 'shift+?' };const handlers = { SHOW\_ALL\_HOTKEYS: this.showHotKeysDialog };\<GlobalHotKeys keyMap={ keyMap } handlers={ handlers } /\>
    

    ๐Ÿ‘ป <GlobalHotKeys> generally have no need for children, so should use a self-closing tag (as shown above). The only exception is when you are nesting other <GlobalHotKeys> components somewhere in the descendants (these are mounted before their parents, and so are generally matched first).

    ๐Ÿ†• New HotKeysIgnore component

    If you want react-hotkeys to ignore key events coming from a particular area of your app when it is in focus, you can use the new <HotKeysIgnore/> component:

    import {HotKeysIgnore} from 'react-hotkeys';\<HotKeysIgnore\>/\*\* \* Children that, when in focus, should have its key events ignored by \* react hotkeys\*/\</HotKeysIgnore\>
    

    How actions and handlers are resolved

    Regardless of where <GlobalHotKeys> components appear in the render tree, they are matched with key events after the event has finished propagating through the React app (if the event originated in the React at all). This means if your React app is in focus and it handles a key event, it will be ignored by the <GlobalHotKeys> components.

    ๐Ÿšš The order used for resolving actions and handlers amongst <GlobalHotKeys> components, is the order in which they mounted (those mounted first, are given the chance to handle an action first). When a <GlobalHotKeys> component is unmounted, it is removed from consideration. This can get less deterministic over the course of a long session using a React app as components mount and unmount, so it is best to define actions and handlers that are globally unique.

    ๐ŸŽ It is recommended to use <HotKeys> components whenever possible for better performance and reliability.

    You can use the autofocus attributes or programmatically manage focus to automatically focus your React app so the user doesn't have to select it in order for hot keys to take effect. It is common practice to place a <HotKeys> component towards the top of your application to match hot keys across your entire React application.

    ๐Ÿ†• New Configuration configuration API for global settings

    ๐Ÿ”ง The default behaviour across all <HotKeys> and <GlobalHotkeys> components is configured using the configure method.

    ๐Ÿ”ง > configure() should be called as your app is initialising and before the first time you mount a <HotKeys> component anywhere your app.

    ๐Ÿ†• New comprehensive logging

    ๐ŸŒฒ react-hotkeys now provides comprehensive logging of all of its internal behaviour and allows setting one of 6 log levels.

    ๐Ÿ‘€ The default level is warn, which provides warnings and errors only, and is generally sufficient for most usage. However, if you are troubleshooting an issue or reporting a bug, you should increase the log level to debug or verbose to see what is going on, and be able to communicate it concisely.

    Optimizations

    ๐Ÿš€ Some improved and additional optimisations have been implemented as part of this release.

    ๐Ÿ›  Bugfixes

    • Possible wrong typescript definition #129
    • โš  Warnings in react-hotkeys when using React's strict mode #128
    • Pass handlers to withHotKeys #127
    • export all typescipt types #120
    • ๐Ÿš€ Child handler doesn't stopPropagation since 1.1.4 release #106