mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-30 09:19:21 +00:00
Adjust keyboard onClick shim
This commit is contained in:
@@ -153,7 +153,6 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|||||||
<View
|
<View
|
||||||
{...rest}
|
{...rest}
|
||||||
{...pressEventHandlers}
|
{...pressEventHandlers}
|
||||||
accessibilityRole={props.accessibilityRole ?? 'button'}
|
|
||||||
accessibilityState={accessibilityState}
|
accessibilityState={accessibilityState}
|
||||||
accessible={accessible !== false}
|
accessible={accessible !== false}
|
||||||
focusable={focusable !== false}
|
focusable={focusable !== false}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import invariant from 'fbjs/lib/invariant';
|
import invariant from 'fbjs/lib/invariant';
|
||||||
import isLink from '../../modules/isLink';
|
|
||||||
import isSelectionValid from '../../modules/isSelectionValid';
|
import isSelectionValid from '../../modules/isSelectionValid';
|
||||||
|
|
||||||
type ClickEvent = any;
|
type ClickEvent = any;
|
||||||
@@ -131,9 +130,12 @@ const isPressStartSignal = signal =>
|
|||||||
|
|
||||||
const isTerminalSignal = signal => signal === RESPONDER_TERMINATED || signal === RESPONDER_RELEASE;
|
const isTerminalSignal = signal => signal === RESPONDER_TERMINATED || signal === RESPONDER_RELEASE;
|
||||||
|
|
||||||
const isKeyPress = event => {
|
const isValidKeyPress = event => {
|
||||||
|
const key = event.key;
|
||||||
const target = event.currentTarget;
|
const target = event.currentTarget;
|
||||||
return (!isLink(target) && event.key === ' ') || event.key === 'Enter';
|
const role = target.getAttribute('role');
|
||||||
|
const isSpacebar = key === ' ' || key === 'Spacebar';
|
||||||
|
return 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
|
||||||
@@ -306,7 +308,7 @@ export default class PressResponder {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onKeyDown: event => {
|
onKeyDown: event => {
|
||||||
if (isKeyPress(event)) {
|
if (isValidKeyPress(event)) {
|
||||||
if (this._touchState === NOT_RESPONDER) {
|
if (this._touchState === NOT_RESPONDER) {
|
||||||
start(event, false);
|
start(event, false);
|
||||||
}
|
}
|
||||||
@@ -315,7 +317,7 @@ export default class PressResponder {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onKeyUp: event => {
|
onKeyUp: event => {
|
||||||
if (isKeyPress(event)) {
|
if (isValidKeyPress(event)) {
|
||||||
end(event);
|
end(event);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-16
@@ -86,6 +86,14 @@ const createDOMProps = (component, props, styleResolver) => {
|
|||||||
const disabled =
|
const disabled =
|
||||||
(accessibilityState != null && accessibilityState.disabled === true) || providedDisabled;
|
(accessibilityState != null && accessibilityState.disabled === true) || providedDisabled;
|
||||||
const role = AccessibilityUtil.propsToAriaRole(props);
|
const role = AccessibilityUtil.propsToAriaRole(props);
|
||||||
|
const isNativeInteractiveElement =
|
||||||
|
role === 'link' ||
|
||||||
|
component === 'a' ||
|
||||||
|
component === 'button' ||
|
||||||
|
component === 'input' ||
|
||||||
|
component === 'select' ||
|
||||||
|
component === 'textarea' ||
|
||||||
|
domProps.contentEditable != null;
|
||||||
|
|
||||||
// unstable_ariaSet
|
// unstable_ariaSet
|
||||||
if (unstable_ariaSet != null) {
|
if (unstable_ariaSet != null) {
|
||||||
@@ -176,24 +184,17 @@ const createDOMProps = (component, props, styleResolver) => {
|
|||||||
// FOCUS
|
// FOCUS
|
||||||
// Assume that 'link' is focusable by default (uses <a>).
|
// Assume that 'link' is focusable by default (uses <a>).
|
||||||
// Assume that 'button' is not (uses <div role='button'>) but must be treated as such.
|
// Assume that 'button' is not (uses <div role='button'>) but must be treated as such.
|
||||||
const isInteractiveElement =
|
|
||||||
role === 'link' ||
|
|
||||||
component === 'a' ||
|
|
||||||
component === 'button' ||
|
|
||||||
component === 'input' ||
|
|
||||||
component === 'select' ||
|
|
||||||
component === 'textarea';
|
|
||||||
const focusable =
|
const focusable =
|
||||||
!disabled &&
|
!disabled &&
|
||||||
importantForAccessibility !== 'no' &&
|
importantForAccessibility !== 'no' &&
|
||||||
importantForAccessibility !== 'no-hide-descendants';
|
importantForAccessibility !== 'no-hide-descendants';
|
||||||
if (isInteractiveElement) {
|
if (isNativeInteractiveElement) {
|
||||||
if (accessible === false || !focusable) {
|
if (accessible === false || !focusable) {
|
||||||
domProps.tabIndex = '-1';
|
domProps.tabIndex = '-1';
|
||||||
} else {
|
} else {
|
||||||
domProps['data-focusable'] = true;
|
domProps['data-focusable'] = true;
|
||||||
}
|
}
|
||||||
} else if (AccessibilityUtil.buttonLikeRoles[role] || role === 'textbox') {
|
} else if (role === 'button' || role === 'menuitem' || role === 'textbox') {
|
||||||
if (accessible !== false && focusable) {
|
if (accessible !== false && focusable) {
|
||||||
domProps['data-focusable'] = true;
|
domProps['data-focusable'] = true;
|
||||||
domProps.tabIndex = '0';
|
domProps.tabIndex = '0';
|
||||||
@@ -252,22 +253,30 @@ const createDOMProps = (component, props, styleResolver) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keyboard accessibility
|
// Keyboard accessibility
|
||||||
// Button-like roles should trigger 'onClick' if SPACE or ENTER keys are pressed.
|
// Button-like roles should trigger 'onClick' if SPACE key is pressed.
|
||||||
// Button-like roles should not trigger 'onClick' if they are disabled.
|
// Button-like roles should not trigger 'onClick' if they are disabled.
|
||||||
if (domProps['data-focusable']) {
|
if (domProps['data-focusable']) {
|
||||||
const onClick = domProps.onClick;
|
const onClick = domProps.onClick;
|
||||||
if (onClick != null) {
|
if (onClick != null) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
domProps.onClick = undefined;
|
domProps.onClick = undefined;
|
||||||
} else if (!isInteractiveElement) {
|
} else if (!isNativeInteractiveElement) {
|
||||||
|
// For native elements that are focusable but don't dispatch 'click' events
|
||||||
|
// for keyboards.
|
||||||
const onKeyDown = domProps.onKeyDown;
|
const onKeyDown = domProps.onKeyDown;
|
||||||
domProps.onKeyDown = function(e) {
|
domProps.onKeyDown = function(e) {
|
||||||
if (!e.isDefaultPrevented() && (e.key === 'Enter' || e.key === ' ')) {
|
const key = e.key;
|
||||||
e.preventDefault();
|
const isSpacebarKey = key === ' ' || key === 'Spacebar';
|
||||||
if (onKeyDown != null) {
|
const isButtonRole = role === 'button' || role === 'menuitem';
|
||||||
onKeyDown(e);
|
if (onKeyDown != null) {
|
||||||
}
|
onKeyDown(e);
|
||||||
|
}
|
||||||
|
if (key === 'Enter') {
|
||||||
onClick(e);
|
onClick(e);
|
||||||
|
} else if (isSpacebarKey && isButtonRole) {
|
||||||
|
onClick(e);
|
||||||
|
// Prevent spacebar scrolling the window
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) Nicolas Gallagher
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default function isLink(node: HTMLElement) {
|
|
||||||
return (
|
|
||||||
(node.nodeName === 'A' && node.getAttribute('href') != null) ||
|
|
||||||
node.getAttribute('role') === 'link'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user