mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-07 20:21:25 +00:00
[fix] PressResponder keyboard edge-case
Fixes the state-machine logic for the press responder when focus is moved away from the target element during a 'keydown' event.
This commit is contained in:
@@ -45,7 +45,6 @@ export type EventHandlers = $ReadOnly<{|
|
|||||||
onClick: (event: ClickEvent) => void,
|
onClick: (event: ClickEvent) => void,
|
||||||
onContextMenu: (event: ClickEvent) => void,
|
onContextMenu: (event: ClickEvent) => void,
|
||||||
onKeyDown: (event: KeyboardEvent) => void,
|
onKeyDown: (event: KeyboardEvent) => void,
|
||||||
onKeyUp: (event: KeyboardEvent) => void,
|
|
||||||
onResponderGrant: (event: ResponderEvent) => void,
|
onResponderGrant: (event: ResponderEvent) => void,
|
||||||
onResponderMove: (event: ResponderEvent) => void,
|
onResponderMove: (event: ResponderEvent) => void,
|
||||||
onResponderRelease: (event: ResponderEvent) => void,
|
onResponderRelease: (event: ResponderEvent) => void,
|
||||||
@@ -132,7 +131,9 @@ const isValidKeyPress = event => {
|
|||||||
const target = event.currentTarget;
|
const target = event.currentTarget;
|
||||||
const role = target.getAttribute('role');
|
const role = target.getAttribute('role');
|
||||||
const isSpacebar = key === ' ' || key === 'Spacebar';
|
const isSpacebar = key === ' ' || key === 'Spacebar';
|
||||||
return key === 'Enter' || (isSpacebar && (role === 'button' || role === 'menuitem'));
|
return (
|
||||||
|
!event.repeat && (key === 'Enter' || (isSpacebar && (role === 'button' || role === 'menuitem')))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_LONG_PRESS_DELAY_MS = 450; // 500 - 50
|
const DEFAULT_LONG_PRESS_DELAY_MS = 450; // 500 - 50
|
||||||
@@ -297,6 +298,13 @@ export default class PressResponder {
|
|||||||
this._receiveSignal(RESPONDER_RELEASE, event);
|
this._receiveSignal(RESPONDER_RELEASE, event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const keyupHandler = (event: KeyboardEvent) => {
|
||||||
|
if (this._touchState !== NOT_RESPONDER) {
|
||||||
|
end(event);
|
||||||
|
document.removeEventListener('keyup', keyupHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onStartShouldSetResponder: (): boolean => {
|
onStartShouldSetResponder: (): boolean => {
|
||||||
const { disabled } = this._config;
|
const { disabled } = this._config;
|
||||||
@@ -310,15 +318,9 @@ export default class PressResponder {
|
|||||||
if (isValidKeyPress(event)) {
|
if (isValidKeyPress(event)) {
|
||||||
if (this._touchState === NOT_RESPONDER) {
|
if (this._touchState === NOT_RESPONDER) {
|
||||||
start(event, false);
|
start(event, false);
|
||||||
}
|
// Listen to 'keyup' on document to account for situations where
|
||||||
event.stopPropagation();
|
// focus is moved to another element during 'keydown'.
|
||||||
}
|
document.addEventListener('keyup', keyupHandler);
|
||||||
},
|
|
||||||
|
|
||||||
onKeyUp: event => {
|
|
||||||
if (isValidKeyPress(event)) {
|
|
||||||
if (this._touchState !== NOT_RESPONDER) {
|
|
||||||
end(event);
|
|
||||||
}
|
}
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,16 +235,18 @@ const createDOMProps = (component, props) => {
|
|||||||
// for keyboards.
|
// for keyboards.
|
||||||
const onKeyDown = domProps.onKeyDown;
|
const onKeyDown = domProps.onKeyDown;
|
||||||
domProps.onKeyDown = function(e) {
|
domProps.onKeyDown = function(e) {
|
||||||
const key = e.key;
|
const { key, repeat } = e;
|
||||||
const isSpacebarKey = key === ' ' || key === 'Spacebar';
|
const isSpacebarKey = key === ' ' || key === 'Spacebar';
|
||||||
const isButtonRole = role === 'button' || role === 'menuitem';
|
const isButtonRole = role === 'button' || role === 'menuitem';
|
||||||
if (onKeyDown != null) {
|
if (onKeyDown != null) {
|
||||||
onKeyDown(e);
|
onKeyDown(e);
|
||||||
}
|
}
|
||||||
if (key === 'Enter') {
|
if (!repeat && key === 'Enter') {
|
||||||
onClick(e);
|
onClick(e);
|
||||||
} else if (isSpacebarKey && isButtonRole) {
|
} else if (isSpacebarKey && isButtonRole) {
|
||||||
onClick(e);
|
if (!repeat) {
|
||||||
|
onClick(e);
|
||||||
|
}
|
||||||
// Prevent spacebar scrolling the window
|
// Prevent spacebar scrolling the window
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user