├── .babelrc ├── .eslintignore ├── .eslintrc.json ├── .flowconfig ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── demo ├── components │ ├── app.js │ └── examples │ │ ├── ExampleBox.js │ │ ├── component │ │ └── index.js │ │ ├── decorators │ │ ├── key-handler.js │ │ └── key-toggle-handler.js │ │ └── input │ │ ├── code-explore.js │ │ ├── default.js │ │ └── keypress.js ├── index.html └── main.js ├── lib ├── constants.js ├── index.js ├── key-handle-decorator.js ├── key-handler.js ├── types.js └── utils.js ├── package.json ├── rollup.config.js ├── test ├── components │ ├── helpers │ │ └── triggerKeyEvent.js │ └── key-handler.test.js ├── mocha.opts ├── support │ └── helper.js └── utils.test.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react", "stage-1"], 3 | "plugins": ["transform-class-properties"] 4 | } 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | demo/bundle.js 2 | dist 3 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "mocha": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:flowtype/recommended", 11 | "plugin:prettier/recommended", 12 | "plugin:react/recommended" 13 | ], 14 | "parser": "babel-eslint", 15 | "parserOptions": { 16 | "ecmaFeatures": { 17 | "experimentalObjectRestSpread": true, 18 | "jsx": true 19 | }, 20 | "ecmaVersion": 6, 21 | "sourceType": "module" 22 | }, 23 | "plugins": ["flowtype", "react"], 24 | "rules": { 25 | "comma-dangle": ["error", "always-multiline"], 26 | "flowtype/no-types-missing-file-annotation": "off", 27 | "indent": ["error", 2], 28 | "linebreak-style": ["error", "unix"], 29 | "quotes": ["error", "single"], 30 | "semi": ["error", "always"] 31 | }, 32 | "settings": { 33 | "react": { 34 | "flowVersion": "0.79", 35 | "version": "16.2" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/node_modules/config-chain/.* 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [lints] 9 | 10 | [options] 11 | 12 | [version] 13 | 0.79.1 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | .size-snapshot.json 3 | dist/ 4 | node_modules/ 5 | npm-debug.log 6 | package-lock.json 7 | yarn-error.log 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | demo/ 3 | lib/ 4 | test/ 5 | .babelrc 6 | .eslintignore 7 | .eslintrc.json 8 | .flowconfig 9 | .size-snapshot.json 10 | .travis.yml 11 | npm-debug.log 12 | rollup.config.js 13 | yarn-error.log 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | demo/index.html 2 | test/mocha.opts 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsxBracketSameLine": true, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '8' 4 | script: 5 | - npm test 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | This project adheres to [Semantic Versioning](http://semver.org/). 5 | 6 | ## [Unreleased] 7 | 8 | - [bugfix] 9 | - [feature] 10 | 11 | ## [1.2.0-beta.3] - 2018-08-30 12 | 13 | - [feature] Add `code` support by [@gforge](https://github.com/gforge) 14 | - [deprecate] `keyCode` prop in favour of `code` by [@gforge](https://github.com/gforge) 15 | - [feature] Allows for `keyValue`, `code` and `keyCode` to come in array format by [@gforge](https://github.com/gforge) 16 | - [breaking] No longer add a `
` wrapper around the `KeyHandler` component, but use `React.Fragment` instead 17 | 18 | ## [1.2.0-beta.2] - 2018-08-21 19 | 20 | - [bugfix] Pass original props to component we are decorating when using one of the decorators 21 | 22 | ## [1.2.0-beta.1] - 2018-08-21 23 | 24 | - [feature] Use rollup to bundle up the code 25 | 26 | ## [1.1.0] - 2018-07-31 27 | 28 | > There's two major bugs in 1.1.0, it is highly recommended to update to 1.2.0 or downgrade to 1.0.1 29 | 30 | - [feature] Add flow support by [@gforge](https://github.com/gforge) 31 | - [bugfix] Fallback from `event.keyCode` to `event.which` for browsers such as FireFox when using the `keypress` event name. [@gforge](https://github.com/gforge) 32 | 33 | ## [1.0.1] - 2017-10-26 34 | 35 | - [feature] Loosen react dependency to support React 16 36 | 37 | ## [1.0.0] - 2017-08-28 38 | 39 | - [breaking] Drop keyName support 40 | - [bugfix] Get rid of deprecation warnings 41 | 42 | ## [0.3.0] - 2016-09-13 43 | 44 | - [feature] Treat content editable elements as inputs by [@jamesfzhang](https://github.com/jamesfzhang). This means the key handle 45 | will be ignored for events triggered from these elements. (Draft.js support) 46 | 47 | ## [0.2.0] - 2016-04-17 48 | 49 | - [feature] Loosen react dependency for future react versions 50 | - [deprecate] `keyName` prop in favour of `keyValue` 51 | - [feature] Added prop types 52 | - [feature] Add support for W3C `KeyboardEvent.key` by [@leocavalcante](https://github.com/leocavalcante) 53 | 54 | ## [0.1.0] - 2016-03-02 55 | 56 | - [feature] Add decorators 57 | - [feature] Ignore key events from form elements 58 | - [feature] Key names 59 | 60 | ## [0.0.4] - 2016-02-27 61 | 62 | - [bugfix] Use right function to remove the event listener 63 | 64 | ## [0.0.2] & [0.0.3] - 2016-02-27 65 | 66 | - [bugfix] Protect from server side rendering errors 67 | 68 | ## [0.0.1] - 2016-02-27 69 | 70 | - Initial implementation 71 | 72 | [unreleased]: https://github.com/ayrton/react-key-handler/compare/v1.1.0...HEAD 73 | [1.2.0-beta.3]: https://github.com/ayrton/react-key-handler/compare/v1.2.0-beta.2...v1.2.0-beta.3 74 | [1.2.0-beta.2]: https://github.com/ayrton/react-key-handler/compare/v1.2.0-beta.1...v1.2.0-beta.2 75 | [1.2.0-beta.1]: https://github.com/ayrton/react-key-handler/compare/v1.1.0...v1.2.0-beta.1 76 | [1.1.0]: https://github.com/ayrton/react-key-handler/compare/v1.0.1...v1.1.0 77 | [1.0.1]: https://github.com/ayrton/react-key-handler/compare/v1.0.0...v1.0.1 78 | [1.0.0]: https://github.com/ayrton/react-key-handler/compare/v0.3.0...v1.0.0 79 | [0.3.0]: https://github.com/ayrton/react-key-handler/compare/v0.2.0...v0.3.0 80 | [0.2.0]: https://github.com/ayrton/react-key-handler/compare/v0.1.0...v0.2.0 81 | [0.1.0]: https://github.com/ayrton/react-key-handler/compare/v0.0.4...v0.1.0 82 | [0.0.4]: https://github.com/ayrton/react-key-handler/compare/v0.0.3...v0.0.4 83 | [0.0.3]: https://github.com/ayrton/react-key-handler/compare/v0.0.2...v0.0.3 84 | [0.0.2]: https://github.com/ayrton/react-key-handler/compare/v0.0.1...v0.0.2 85 | [0.0.1]: https://github.com/ayrton/react-key-handler/commit/8267e3dc7357bb7fb106f5148e6f9cb9f69ed3b5 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-key-handler 🔑 2 | 3 | [![npm version](https://img.shields.io/npm/v/react-key-handler.svg)](https://www.npmjs.com/package/react-key-handler) [![License](https://img.shields.io/npm/l/react-key-handler.svg)](https://www.npmjs.com/package/react-key-handler) [![Build Status](https://travis-ci.org/ayrton/react-key-handler.svg?branch=master)](https://travis-ci.org/ayrton/react-key-handler) 4 | 5 | React component to handle keyboard events (such as `keyup`, `keydown` & `keypress`). 6 | 7 | ## Testimonials 8 | 9 | >
“Happy to see that react-key-handler is SSR safe :+1:”
10 | > [Veselin Todorov](https://github.com/vesln), Chai.js core 11 | 12 | ## Table of Contents 13 | 14 | 1. [Installation](#installation) 15 | 2. [Usage](#usage) 16 | 1. [Higher-order Components](#higher-order-components) 17 | 2. [Component](#component) 18 | 3. [Form key handling](#form-key-handling) 19 | 3. [Key event names](#key-event-names) 20 | 4. [`keyValue`, `code` and `keyCode`](#keyvalue-code-and-keycode) 21 | 5. [Development](#development) 22 | 1. [Setup](#setup) 23 | 2. [Getting started](#getting-started) 24 | 3. [Tests](#tests) 25 | 6. [Contributing](#contributing) 26 | 7. [License](#license) 27 | 28 | ## Installation 29 | 30 | ```sh 31 | $ npm install react-key-handler --save 32 | ``` 33 | 34 | ## Usage 35 | 36 | You can use `react-key-handler` library in two flavours: 37 | 38 | - [higher-order components](#higher-order-components) 39 | - [component](#component) 40 | 41 | ### Higher-order Components 42 | 43 | This library includes two similar higher-order components, but with a different puprose: 44 | 45 | | Higher-order Component | Purpose | 46 | | ---------------------- | ------------------- | 47 | | `keyHandler` | Handles key changes | 48 | | `keyToggleHandler` | Handles key toggles | 49 | 50 | Both have the same API and will decorate the given component with a `keyValue`, `code` 51 | and `keyCode` property. 52 | 53 | Internally the `KeyHandler` component is used, for a full understanding be sure to 54 | check out [the implementation](lib/key-handler.js). 55 | 56 | ```jsx 57 | import React from 'react'; 58 | import { keyHandler, KEYPRESS } from 'react-key-handler'; 59 | 60 | function Demo({ keyValue }) { 61 | return ( 62 |
63 | {keyValue === 's' && ( 64 |
    65 |
  1. hello
  2. 66 |
  3. world
  4. 67 |
68 | )} 69 |
70 | ); 71 | } 72 | 73 | export default keyHandler({ keyEventName: KEYPRESS, keyValue: 's' })(Demo); 74 | ``` 75 | 76 | The prop types of the `KeyHandler` component are: 77 | 78 | | Name | Type | Required | Default | | 79 | | --------------- | ------ | ---------- | --------- | -------------------------------------- | 80 | | keyEventName | string | no | `'keyup'` | `'keydown'`, `'keypress'` or `'keyup'` | 81 | | keyValue | string | yes **\*** | | Any given [KeyboardEvent.key] | 82 | | code | string | yes **\*** | | Any given [KeyboardEvent.code] | 83 | | keyCode† | number | yes **\*** | | Any given [KeyboardEvent.keyCode] | 84 | 85 | **\*** You should pass at least one of these props. 86 | 87 | † _Note_ that the keyCode is frequently browser specific and has therefore be set as 88 | deprecated, see [MDN for details](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode). 89 | 90 | [Examples](demo/components/examples/decorators/) 91 | 92 | ### Component 93 | 94 | ```jsx 95 | import React from 'react'; 96 | import KeyHandler, { KEYPRESS } from 'react-key-handler'; 97 | 98 | export default class Demo extends React.Component { 99 | state = { showMenu: false }; 100 | 101 | render() { 102 | const { showMenu } = this.state; 103 | 104 | return ( 105 | 106 | 111 | 112 | {showMenu && ( 113 |
    114 |
  1. hello
  2. 115 |
  3. world
  4. 116 |
117 | )} 118 |
119 | ); 120 | }, 121 | 122 | toggleMenu = (event) => { 123 | event.preventDefault(); 124 | 125 | this.setState({ showMenu: !this.state.showMenu }); 126 | }; 127 | } 128 | ``` 129 | 130 | The prop types of the `KeyHandler` component are: 131 | 132 | | Name | Type | Required | Default | | 133 | | --------------- | -------- | ---------- | --------- | ------------------------------------------------ | 134 | | keyEventName | string | no | `'keyup'` | `'keydown'`, `'keypress'` or `'keyup'` | 135 | | keyValue | string | yes **\*** | | Any given [KeyboardEvent.key] | 136 | | code | string | yes **\*** | | Any given [KeyboardEvent.code] | 137 | | keyCode† | number | yes **\*** | | Any given [KeyboardEvent.keyCode] | 138 | | onKeyHandle | function | yes | | Function that is called when they key is handled | 139 | 140 | **\*** You should pass at least one of these props. 141 | 142 | † _Note_ that the keyCode is frequently browser specific and has therefore be set as 143 | deprecated, see [MDN for details](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode). 144 | 145 | [Example](demo/components/examples/component/index.js) 146 | 147 | ### Form key handling 148 | 149 | This library does not handle key events for form elements such as `` and `