Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix nonprintable keys #199

Merged
merged 3 commits into from
Jun 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions src/const/KeysWithoutPressEventDictionary.js

This file was deleted.

10 changes: 10 additions & 0 deletions src/const/NonPrintableKeysDictionary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐥 New dictionary of non-printable keys, that takes its values from the same list that the React normalization algorithm uses.

* Dictionary of keys whose name is not a single symbol or character
*/
import dictionaryFrom from '../utils/object/dictionaryFrom';
import translateToKey from '../vendor/react-dom/translateToKey';

const NonPrintableKeysDictionary =
dictionaryFrom(Object.values(translateToKey), true);

export default NonPrintableKeysDictionary;
16 changes: 0 additions & 16 deletions src/const/SpecialKeysDictionary.js

This file was deleted.

12 changes: 12 additions & 0 deletions src/helpers/parsing-key-maps/isCustomKeyName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Configuration from '../../lib/Configuration';

/**
* Whether the specified key name is among those defined as custom key codes
* @param {ReactKeyName} keyName Name of the key
* @return {Boolean} true if keyName matches a custom key name
*/
function isCustomKeyName(keyName) {
return Configuration.option('_customKeyNamesDict')[keyName];
}

export default isCustomKeyName;
13 changes: 13 additions & 0 deletions src/helpers/parsing-key-maps/isNonPrintableKeyName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import NonPrintableKeysDictionary from '../../const/NonPrintableKeysDictionary';

/**
* Whether the specified key is a valid key name that is not a single character or
* symbol
* @param {ReactKeyName} keyName Name of the key
* @returns {boolean} Whether the key is a valid special key
*/
function isNonPrintableKeyName(keyName) {
return !!NonPrintableKeysDictionary[keyName];
}

export default isNonPrintableKeyName;
13 changes: 0 additions & 13 deletions src/helpers/parsing-key-maps/isSpecialKey.js

This file was deleted.

7 changes: 5 additions & 2 deletions src/helpers/parsing-key-maps/isValidKey.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import isSpecialKey from './isSpecialKey';
import isNonPrintableKeyName from './isNonPrintableKeyName';
import isCustomKeyName from './isCustomKeyName';

function isValidKey(keyName) {
return isSpecialKey(keyName) || String.fromCharCode(keyName.charCodeAt(0)) === keyName;
return isNonPrintableKeyName(keyName) ||
String.fromCharCode(keyName.charCodeAt(0)) === keyName ||
isCustomKeyName(keyName)
}

export class InvalidKeyNameError extends Error {
Expand Down
4 changes: 2 additions & 2 deletions src/helpers/resolving-handlers/hasKeyPressEvent.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import KeysWithoutPressEventDictionary from '../../const/KeysWithoutPressEventDictionary';
import isNonPrintableKeyName from '../parsing-key-maps/isNonPrintableKeyName';

/**
* Whether the specified key name is for a key that has a native keypress event
* @param {NormalizedKeyName} keyName Name of the key
* @returns {Boolean} Whether the key has a native keypress event
*/
function hasKeyPressEvent(keyName) {
return !KeysWithoutPressEventDictionary[keyName];
return !isNonPrintableKeyName(keyName);
}

export default hasKeyPressEvent;
6 changes: 5 additions & 1 deletion src/lib/Configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,16 @@ class Configuration {
* @see _configuration
*/
static init(configuration) {
const {ignoreTags} = configuration;
const {ignoreTags, customKeyCodes } = configuration;

if (ignoreTags) {
configuration._ignoreTagsDict = dictionaryFrom(configuration.ignoreTags);
}

if (customKeyCodes) {
configuration._customKeyNamesDict = dictionaryFrom(Object.values(configuration.customKeyCodes));
}

if (process.env.NODE_ENV === 'production') {
if (['verbose', 'debug', 'info'].indexOf(configuration.logLevel) !== -1) {
console.warn(
Expand Down
4 changes: 2 additions & 2 deletions src/lib/strategies/FocusOnlyKeyEventStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ class FocusOnlyKeyEventStrategy extends AbstractKeyEventStrategy {
this._callHandlerIfActionNotHandled(event, _key, KeyEventRecordIndex.keydown, componentId, focusTreeId);
}

this._simulateKeyPressesMissingFromBrowser(event, _key, focusTreeId, componentId, options);
this._simulateKeypressForNonPrintableKeys(event, _key, focusTreeId, componentId, options);

this._updateEventPropagationHistory(componentId, componentPosition);

Expand Down Expand Up @@ -619,7 +619,7 @@ class FocusOnlyKeyEventStrategy extends AbstractKeyEventStrategy {
}
}

_simulateKeyPressesMissingFromBrowser(event, key, focusTreeId, componentId, options){
_simulateKeypressForNonPrintableKeys(event, key, focusTreeId, componentId, options){
this._handleEventSimulation(
'keypressEventsToSimulate',
'simulatePendingKeyPressEvents',
Expand Down
4 changes: 2 additions & 2 deletions src/lib/strategies/GlobalKeyEventStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ class GlobalKeyEventStrategy extends AbstractKeyEventStrategy {
this._callHandlerIfExists(event, _key, KeyEventRecordIndex.keydown);
}

this._simulateKeyPressesMissingFromBrowser(event, _key);
this._simulateKeypressForNonPrintableKeys(event, _key);
}

_howReactAppRespondedTo(event, key, eventRecordIndex) {
Expand Down Expand Up @@ -534,7 +534,7 @@ class GlobalKeyEventStrategy extends AbstractKeyEventStrategy {
}
}

_simulateKeyPressesMissingFromBrowser(event, key) {
_simulateKeypressForNonPrintableKeys(event, key) {
this.keyEventManager.simulatePendingKeyPressEvents();

this._handleEventSimulation(
Expand Down
46 changes: 2 additions & 44 deletions src/vendor/react-dom/reactsGetEventKey.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import getEventCharCode from './getEventCharCode';
import translateToKey from './translateToKey';

/**
* Normalization of deprecated HTML5 `key` values
Expand All @@ -28,50 +29,6 @@ const normalizeKey = {
MozPrintableKey: 'Unidentified',
};

/**
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐥☂️Abstract React's list of non-printable keys into a separate file, so it can be re-used by react-hotkeys.

* Translation from legacy `keyCode` to HTML5 `key`
* Only special keys supported, all others depend on keyboard layout or browser
* @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
*/
const translateToKey = {
'8': 'Backspace',
'9': 'Tab',
'12': 'Clear',
'13': 'Enter',
'16': 'Shift',
'17': 'Control',
'18': 'Alt',
'19': 'Pause',
'20': 'CapsLock',
'27': 'Escape',
'32': ' ',
'33': 'PageUp',
'34': 'PageDown',
'35': 'End',
'36': 'Home',
'37': 'ArrowLeft',
'38': 'ArrowUp',
'39': 'ArrowRight',
'40': 'ArrowDown',
'45': 'Insert',
'46': 'Delete',
'112': 'F1',
'113': 'F2',
'114': 'F3',
'115': 'F4',
'116': 'F5',
'117': 'F6',
'118': 'F7',
'119': 'F8',
'120': 'F9',
'121': 'F10',
'122': 'F11',
'123': 'F12',
'144': 'NumLock',
'145': 'ScrollLock',
'224': 'Meta',
};

/**
* @param {object} nativeEvent Native browser event.
* @return {string} Normalized `key` property.
Expand All @@ -97,6 +54,7 @@ function reactsGetEventKey(nativeEvent) {
// thus be captured by `keypress`, no other non-printable key should.
return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
}

if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
// While user keyboard layout determines the actual meaning of each
// `keyCode` value, almost all function keys have a universal value.
Expand Down
45 changes: 45 additions & 0 deletions src/vendor/react-dom/translateToKey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Translation from legacy `keyCode` to HTML5 `key`
* Only special keys supported, all others depend on keyboard layout or browser
* @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
*/
const translateToKey = {
'8': 'Backspace',
'9': 'Tab',
'12': 'Clear',
'13': 'Enter',
'16': 'Shift',
'17': 'Control',
'18': 'Alt',
'19': 'Pause',
'20': 'CapsLock',
'27': 'Escape',
'32': ' ',
'33': 'PageUp',
'34': 'PageDown',
'35': 'End',
'36': 'Home',
'37': 'ArrowLeft',
'38': 'ArrowUp',
'39': 'ArrowRight',
'40': 'ArrowDown',
'45': 'Insert',
'46': 'Delete',
'112': 'F1',
'113': 'F2',
'114': 'F3',
'115': 'F4',
'116': 'F5',
'117': 'F6',
'118': 'F7',
'119': 'F8',
'120': 'F9',
'121': 'F10',
'122': 'F11',
'123': 'F12',
'144': 'NumLock',
'145': 'ScrollLock',
'224': 'Meta',
};

export default translateToKey;
Loading