Skip to content

Commit acac6dd

Browse files
committed
fix: keyDownEvents stops propogation, specify default events for Pressable
1 parent aef0241 commit acac6dd

File tree

3 files changed

+115
-5
lines changed

3 files changed

+115
-5
lines changed

packages/react-native/Libraries/Components/Pressable/Pressable.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,11 @@ function Pressable(
353353

354354
const accessibilityLabel = ariaLabel ?? props.accessibilityLabel;
355355

356+
const keyDownEvents = keyDownEvents ?? [{key: 'Space'}, {key: 'Enter'}];
357+
356358
const restPropsWithDefaults: React.ElementConfig<typeof View> = {
357359
...restProps,
358360
...android_rippleConfig?.viewProps,
359-
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled, // [macOS]
360-
mouseDownCanMoveWindow: false, // [macOS]
361-
enableFocusRing: enableFocusRing !== false && !disabled,
362361
accessible: accessible !== false,
363362
accessibilityViewIsModal:
364363
restProps['aria-modal'] ?? restProps.accessibilityViewIsModal,
@@ -368,6 +367,12 @@ function Pressable(
368367
focusable: focusable !== false && !disabled, // macOS]
369368
accessibilityValue,
370369
hitSlop,
370+
// [macOS
371+
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled,
372+
enableFocusRing: enableFocusRing !== false && !disabled,
373+
keyDownEvents,
374+
mouseDownCanMoveWindow: false,
375+
// macOS]
371376
};
372377

373378
const config = useMemo(

packages/react-native/Libraries/Components/TextInput/TextInput.js

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import type {HostInstance} from '../../../src/private/types/HostInstance';
1212
import type {____TextStyle_Internal as TextStyleInternal} from '../../StyleSheet/StyleSheetTypes';
1313
import type {
1414
GestureResponderEvent,
15+
KeyEvent,
16+
HandledKeyEvent,
1517
NativeSyntheticEvent,
1618
ScrollEvent,
1719
} from '../../Types/CoreEventTypes';
@@ -1134,6 +1136,34 @@ export type TextInputProps = $ReadOnly<{
11341136
* unwanted edits without flicker.
11351137
*/
11361138
value?: ?Stringish,
1139+
1140+
// [macOS
1141+
/**
1142+
* An array of key events that should be handled by the TextInput.
1143+
* When a key event matches one of these specifications, event propagation will be stopped.
1144+
* @platform macos
1145+
*/
1146+
keyDownEvents?: ?$ReadOnlyArray<HandledKeyEvent>,
1147+
1148+
/**
1149+
* An array of key events that should be handled by the TextInput.
1150+
* When a key event matches one of these specifications, event propagation will be stopped.
1151+
* @platform macos
1152+
*/
1153+
keyUpEvents?: ?$ReadOnlyArray<HandledKeyEvent>,
1154+
1155+
/**
1156+
* Callback that is called when a key is pressed down.
1157+
* @platform macos
1158+
*/
1159+
onKeyDown?: ?(e: KeyEvent) => mixed,
1160+
1161+
/**
1162+
* Callback that is called when a key is released.
1163+
* @platform macos
1164+
*/
1165+
onKeyUp?: ?(e: KeyEvent) => mixed,
1166+
// macOS]
11371167
}>;
11381168

11391169
type ViewCommands = $NonMaybeType<
@@ -1640,6 +1670,42 @@ function InternalTextInput(props: TextInputProps): React.Node {
16401670
props.onScroll && props.onScroll(event);
16411671
};
16421672

1673+
const _keyDown = (event: KeyEvent) => {
1674+
if (props.keyDownEvents && event.isPropagationStopped() !== true) {
1675+
const isHandled = props.keyDownEvents.some(({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
1676+
return (
1677+
event.nativeEvent.key === key &&
1678+
(metaKey ?? event.nativeEvent.metaKey) === event.nativeEvent.metaKey &&
1679+
(ctrlKey ?? event.nativeEvent.ctrlKey) === event.nativeEvent.ctrlKey &&
1680+
(altKey ?? event.nativeEvent.altKey) === event.nativeEvent.altKey &&
1681+
(shiftKey ?? event.nativeEvent.shiftKey) === event.nativeEvent.shiftKey
1682+
);
1683+
});
1684+
if (isHandled) {
1685+
event.stopPropagation();
1686+
}
1687+
}
1688+
props.onKeyDown && props.onKeyDown(event);
1689+
};
1690+
1691+
const _keyUp = (event: KeyEvent) => {
1692+
if (props.keyUpEvents && event.isPropagationStopped() !== true) {
1693+
const isHandled = props.keyUpEvents.some(({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
1694+
return (
1695+
event.nativeEvent.key === key &&
1696+
(metaKey ?? event.nativeEvent.metaKey) === event.nativeEvent.metaKey &&
1697+
(ctrlKey ?? event.nativeEvent.ctrlKey) === event.nativeEvent.ctrlKey &&
1698+
(altKey ?? event.nativeEvent.altKey) === event.nativeEvent.altKey &&
1699+
(shiftKey ?? event.nativeEvent.shiftKey) === event.nativeEvent.shiftKey
1700+
);
1701+
});
1702+
if (isHandled) {
1703+
event.stopPropagation();
1704+
}
1705+
}
1706+
props.onKeyUp && props.onKeyUp(event);
1707+
};
1708+
16431709
let textInput = null;
16441710

16451711
const multiline = props.multiline ?? false;
@@ -1795,8 +1861,8 @@ function InternalTextInput(props: TextInputProps): React.Node {
17951861
onChange={_onChange}
17961862
onContentSizeChange={props.onContentSizeChange}
17971863
onFocus={_onFocus}
1798-
onKeyDown={props.onKeyDown} // [macOS]
1799-
onKeyUp={props.onKeyUp} // [macOS]
1864+
onKeyDown={_keyDown} // [macOS]
1865+
onKeyUp={_keyUp} // [macOS]
18001866
onScroll={_onScroll}
18011867
onSelectionChange={_onSelectionChange}
18021868
onSelectionChangeShouldSetResponder={emptyFunctionThatReturnsTrue}

packages/react-native/Libraries/Components/View/View.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {ViewProps} from './ViewPropTypes';
1313
import TextAncestor from '../../Text/TextAncestor';
1414
import ViewNativeComponent from './ViewNativeComponent';
1515
import * as React from 'react';
16+
import type { KeyEvent, HandledKeyEvent } from '../../Types/CoreEventTypes';
1617

1718
export type Props = ViewProps;
1819

@@ -94,6 +95,42 @@ const View: component(
9495
};
9596
}
9697

98+
const _keyDown = (event: KeyEvent) => {
99+
if (otherProps.keyDownEvents && event.isPropagationStopped() !== true) {
100+
const isHandled = otherProps.keyDownEvents.some(({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
101+
return (
102+
event.nativeEvent.key === key &&
103+
(metaKey ?? event.nativeEvent.metaKey) === event.nativeEvent.metaKey &&
104+
(ctrlKey ?? event.nativeEvent.ctrlKey) === event.nativeEvent.ctrlKey &&
105+
(altKey ?? event.nativeEvent.altKey) === event.nativeEvent.altKey &&
106+
(shiftKey ?? event.nativeEvent.shiftKey) === event.nativeEvent.shiftKey
107+
);
108+
});
109+
if (isHandled) {
110+
event.stopPropagation();
111+
}
112+
}
113+
otherProps.onKeyDown && otherProps.onKeyDown(event);
114+
};
115+
116+
const _keyUp = (event: KeyEvent) => {
117+
if (otherProps.keyUpEvents && event.isPropagationStopped() !== true) {
118+
const isHandled = otherProps.keyUpEvents.some(({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
119+
return (
120+
event.nativeEvent.key === key &&
121+
(metaKey ?? event.nativeEvent.metaKey) === event.nativeEvent.metaKey &&
122+
(ctrlKey ?? event.nativeEvent.ctrlKey) === event.nativeEvent.ctrlKey &&
123+
(altKey ?? event.nativeEvent.altKey) === event.nativeEvent.altKey &&
124+
(shiftKey ?? event.nativeEvent.shiftKey) === event.nativeEvent.shiftKey
125+
);
126+
});
127+
if (isHandled) {
128+
event.stopPropagation();
129+
}
130+
}
131+
otherProps.onKeyUp && otherProps.onKeyUp(event);
132+
};
133+
97134
const actualView = (
98135
<ViewNativeComponent
99136
{...otherProps}
@@ -112,6 +149,8 @@ const View: component(
112149
: importantForAccessibility
113150
}
114151
nativeID={id ?? nativeID}
152+
onKeyDown={_keyDown}
153+
onKeyUp={_keyUp}
115154
ref={forwardedRef}
116155
/>
117156
);

0 commit comments

Comments
 (0)