Skip to content

Commit 7e68079

Browse files
Saadnajmiclaude
andcommitted
fix: minimal additive diff for legacy validKeys compat layer
- Keep existing _onKeyDown/_onKeyUp handlers from main, just read from effectiveProps instead of props - Fix Flow errors: restore let actualView, use Array instead of $ReadOnlyArray in LegacyKeyResult type - Zero deleted lines from upstream — purely additive changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a9e9a98 commit 7e68079

3 files changed

Lines changed: 126 additions & 33 deletions

File tree

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

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import type {
1616
GestureResponderEvent,
1717
ScrollEvent,
1818
} from '../../Types/CoreEventTypes';
19-
// [macOS]
19+
// [macOS
20+
import type {HandledKeyEvent, KeyEvent} from '../../Types/CoreEventTypes';
21+
// macOS]
2022
import type {
2123
AutoCapitalize,
2224
EnterKeyHintType,
@@ -393,11 +395,19 @@ function InternalTextInput(props: TextInputProps): React.Node {
393395
// [macOS Legacy keyboard event compat — to remove, delete this block and its import
394396
const usingLegacyKeyboardProps = hasLegacyKeyProps(props);
395397
// $FlowFixMe[unclear-type]
396-
const propsWithoutLegacyKeyProps = usingLegacyKeyboardProps ? ({...props}: any) : props;
398+
const effectiveProps: any = usingLegacyKeyboardProps ? ({...props}: any) : props;
397399
if (usingLegacyKeyboardProps) {
398-
stripLegacyKeyProps(propsWithoutLegacyKeyProps);
400+
stripLegacyKeyProps(effectiveProps);
401+
const legacy = processLegacyKeyProps(props);
402+
effectiveProps.keyDownEvents = legacy.keyDownEvents;
403+
effectiveProps.keyUpEvents = legacy.keyUpEvents;
404+
if (legacy.onKeyDown != null) {
405+
effectiveProps.onKeyDown = legacy.onKeyDown;
406+
}
407+
if (legacy.onKeyUp != null) {
408+
effectiveProps.onKeyUp = legacy.onKeyUp;
409+
}
399410
}
400-
const legacy = usingLegacyKeyboardProps ? processLegacyKeyProps(props) : null;
401411
// macOS]
402412
const {
403413
'aria-busy': ariaBusy,
@@ -413,7 +423,7 @@ function InternalTextInput(props: TextInputProps): React.Node {
413423
selectionHandleColor,
414424
cursorColor,
415425
...otherProps
416-
} = propsWithoutLegacyKeyProps;
426+
} = effectiveProps;
417427

418428
const inputRef = useRef<null | TextInputInstance>(null);
419429

@@ -593,7 +603,49 @@ function InternalTextInput(props: TextInputProps): React.Node {
593603
props.onScroll && props.onScroll(event);
594604
};
595605

596-
// macOS] (legacy key handlers are in processLegacyKeyProps)
606+
// [macOS
607+
const _onKeyDown = (event: KeyEvent) => {
608+
const keyDownEvents = effectiveProps.keyDownEvents;
609+
if (keyDownEvents != null && !event.isPropagationStopped()) {
610+
const isHandled = keyDownEvents.some(
611+
({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
612+
return (
613+
event.nativeEvent.key === key &&
614+
Boolean(metaKey) === event.nativeEvent.metaKey &&
615+
Boolean(ctrlKey) === event.nativeEvent.ctrlKey &&
616+
Boolean(altKey) === event.nativeEvent.altKey &&
617+
Boolean(shiftKey) === event.nativeEvent.shiftKey
618+
);
619+
},
620+
);
621+
if (isHandled === true) {
622+
event.stopPropagation();
623+
}
624+
}
625+
effectiveProps.onKeyDown?.(event);
626+
};
627+
628+
const _onKeyUp = (event: KeyEvent) => {
629+
const keyUpEvents = effectiveProps.keyUpEvents;
630+
if (keyUpEvents != null && !event.isPropagationStopped()) {
631+
const isHandled = keyUpEvents.some(
632+
({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
633+
return (
634+
event.nativeEvent.key === key &&
635+
Boolean(metaKey) === event.nativeEvent.metaKey &&
636+
Boolean(ctrlKey) === event.nativeEvent.ctrlKey &&
637+
Boolean(altKey) === event.nativeEvent.altKey &&
638+
Boolean(shiftKey) === event.nativeEvent.shiftKey
639+
);
640+
},
641+
);
642+
if (isHandled === true) {
643+
event.stopPropagation();
644+
}
645+
}
646+
effectiveProps.onKeyUp?.(event);
647+
};
648+
// macOS]
597649

598650
let textInput = null;
599651

@@ -744,8 +796,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
744796
caretHidden={caretHidden}
745797
dataDetectorTypes={props.dataDetectorTypes}
746798
focusable={tabIndex !== undefined ? !tabIndex : focusable}
747-
{...(legacy != null && {keyDownEvents: legacy.keyDownEvents})}
748-
{...(legacy != null && {keyUpEvents: legacy.keyUpEvents})}
749799
mostRecentEventCount={mostRecentEventCount}
750800
nativeID={id ?? props.nativeID}
751801
numberOfLines={props.rows ?? props.numberOfLines}
@@ -754,8 +804,8 @@ function InternalTextInput(props: TextInputProps): React.Node {
754804
onContentSizeChange={props.onContentSizeChange}
755805
onFocus={_onFocus}
756806
// $FlowFixMe[exponential-spread]
757-
{...(legacy?.onKeyDown != null && {onKeyDown: legacy.onKeyDown})} // [macOS]
758-
{...(legacy?.onKeyUp != null && {onKeyUp: legacy.onKeyUp})} // [macOS]
807+
{...(otherProps.onKeyDown && {onKeyDown: _onKeyDown})} // [macOS]
808+
{...(otherProps.onKeyUp && {onKeyUp: _onKeyUp})} // [macOS]
759809
onScroll={_onScroll}
760810
onSelectionChange={_onSelectionChange}
761811
onSelectionChangeShouldSetResponder={emptyFunctionThatReturnsTrue}

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

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* @format
99
*/
1010

11+
import type {HandledKeyEvent, KeyEvent} from '../../Types/CoreEventTypes'; // [macOS]
1112
import type {ViewProps} from './ViewPropTypes';
1213

1314
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
@@ -34,14 +35,69 @@ export default component View(
3435
...props: ViewProps
3536
) {
3637
const hasTextAncestor = use(TextAncestorContext);
38+
3739
// [macOS Legacy keyboard event compat — to remove, delete this block and its import
3840
const usingLegacyKeyboardProps = hasLegacyKeyProps(props);
3941
// $FlowFixMe[unclear-type]
40-
const propsWithoutLegacyKeyProps = usingLegacyKeyboardProps ? ({...props}: any) : props;
42+
const effectiveProps: any = usingLegacyKeyboardProps ? ({...props}: any) : props;
4143
if (usingLegacyKeyboardProps) {
42-
stripLegacyKeyProps(propsWithoutLegacyKeyProps);
44+
stripLegacyKeyProps(effectiveProps);
45+
const legacy = processLegacyKeyProps(props);
46+
effectiveProps.keyDownEvents = legacy.keyDownEvents;
47+
effectiveProps.keyUpEvents = legacy.keyUpEvents;
48+
if (legacy.onKeyDown != null) {
49+
effectiveProps.onKeyDown = legacy.onKeyDown;
50+
}
51+
if (legacy.onKeyUp != null) {
52+
effectiveProps.onKeyUp = legacy.onKeyUp;
53+
}
4354
}
44-
const legacy = usingLegacyKeyboardProps ? processLegacyKeyProps(props) : null;
55+
// macOS]
56+
57+
let actualView;
58+
59+
// [macOS
60+
const _onKeyDown = (event: KeyEvent) => {
61+
const keyDownEvents = effectiveProps.keyDownEvents;
62+
if (keyDownEvents != null && !event.isPropagationStopped()) {
63+
const isHandled = keyDownEvents.some(
64+
({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
65+
return (
66+
event.nativeEvent.key === key &&
67+
Boolean(metaKey) === event.nativeEvent.metaKey &&
68+
Boolean(ctrlKey) === event.nativeEvent.ctrlKey &&
69+
Boolean(altKey) === event.nativeEvent.altKey &&
70+
Boolean(shiftKey) === event.nativeEvent.shiftKey
71+
);
72+
},
73+
);
74+
if (isHandled === true) {
75+
event.stopPropagation();
76+
}
77+
}
78+
effectiveProps.onKeyDown?.(event);
79+
};
80+
81+
const _onKeyUp = (event: KeyEvent) => {
82+
const keyUpEvents = effectiveProps.keyUpEvents;
83+
if (keyUpEvents != null && !event.isPropagationStopped()) {
84+
const isHandled = keyUpEvents.some(
85+
({key, metaKey, ctrlKey, altKey, shiftKey}: HandledKeyEvent) => {
86+
return (
87+
event.nativeEvent.key === key &&
88+
Boolean(metaKey) === event.nativeEvent.metaKey &&
89+
Boolean(ctrlKey) === event.nativeEvent.ctrlKey &&
90+
Boolean(altKey) === event.nativeEvent.altKey &&
91+
Boolean(shiftKey) === event.nativeEvent.shiftKey
92+
);
93+
},
94+
);
95+
if (isHandled === true) {
96+
event.stopPropagation();
97+
}
98+
}
99+
effectiveProps.onKeyUp?.(event);
100+
};
45101
// macOS]
46102

47103
if (ReactNativeFeatureFlags.reduceDefaultPropsInView()) {
@@ -64,22 +120,11 @@ export default component View(
64120
id,
65121
tabIndex,
66122
...otherProps
67-
} = propsWithoutLegacyKeyProps;
123+
} = effectiveProps;
68124

69125
// Since we destructured props, we can now treat it as mutable
70126
const processedProps = otherProps as {...ViewProps};
71127

72-
if (legacy != null) {
73-
processedProps.keyDownEvents = legacy.keyDownEvents;
74-
processedProps.keyUpEvents = legacy.keyUpEvents;
75-
if (legacy.onKeyDown != null) {
76-
processedProps.onKeyDown = legacy.onKeyDown;
77-
}
78-
if (legacy.onKeyUp != null) {
79-
processedProps.onKeyUp = legacy.onKeyUp;
80-
}
81-
}
82-
83128
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
84129
if (parsedAriaLabelledBy !== undefined) {
85130
processedProps.accessibilityLabelledBy = parsedAriaLabelledBy;
@@ -174,7 +219,7 @@ export default component View(
174219
nativeID,
175220
tabIndex,
176221
...otherProps
177-
} = propsWithoutLegacyKeyProps;
222+
} = effectiveProps;
178223
const _accessibilityLabelledBy =
179224
ariaLabelledBy?.split(/\s*,\s*/g) ?? accessibilityLabelledBy;
180225

@@ -226,11 +271,9 @@ export default component View(
226271
: importantForAccessibility
227272
}
228273
nativeID={id ?? nativeID}
229-
{...(legacy != null && {keyDownEvents: legacy.keyDownEvents})} // [macOS]
230-
{...(legacy != null && {keyUpEvents: legacy.keyUpEvents})} // [macOS]
231274
// $FlowFixMe[exponential-spread]
232-
{...(legacy?.onKeyDown != null && {onKeyDown: legacy.onKeyDown})} // [macOS]
233-
{...(legacy?.onKeyUp != null && {onKeyUp: legacy.onKeyUp})} // [macOS]
275+
{...(otherProps.onKeyDown && {onKeyDown: _onKeyDown})} // [macOS]
276+
{...(otherProps.onKeyUp && {onKeyUp: _onKeyUp})} // [macOS]
234277
ref={ref}
235278
/>
236279
);

packages/react-native/Libraries/Utilities/normalizeLegacyHandledKeyEvents.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function expandKey(entry: LegacyHandledKeyEvent): Array<HandledKeyEvent> {
3636

3737
function normalize(
3838
legacy: ?$ReadOnlyArray<LegacyHandledKeyEvent>,
39-
): void | $ReadOnlyArray<HandledKeyEvent> {
39+
): void | Array<HandledKeyEvent> {
4040
if (legacy == null) {
4141
return undefined;
4242
}
@@ -62,8 +62,8 @@ function matchesEvent(
6262
}
6363

6464
export type LegacyKeyResult = {
65-
keyDownEvents: void | $ReadOnlyArray<HandledKeyEvent>,
66-
keyUpEvents: void | $ReadOnlyArray<HandledKeyEvent>,
65+
keyDownEvents: void | Array<HandledKeyEvent>,
66+
keyUpEvents: void | Array<HandledKeyEvent>,
6767
onKeyDown: void | ((event: KeyEvent) => void),
6868
onKeyUp: void | ((event: KeyEvent) => void),
6969
};

0 commit comments

Comments
 (0)