diff --git a/packages/react-native/Libraries/Components/Button.js b/packages/react-native/Libraries/Components/Button.js index b7237065f31759..1fd928195fe73a 100644 --- a/packages/react-native/Libraries/Components/Button.js +++ b/packages/react-native/Libraries/Components/Button.js @@ -12,12 +12,7 @@ import type {TextStyleProp, ViewStyleProp} from '../StyleSheet/StyleSheet'; import type {PressEvent} from '../Types/CoreEventTypes'; -import type { - BlurEvent, - FocusEvent, - HandledKeyEvent, - KeyEvent, -} from '../Types/CoreEventTypes'; // [macOS] +import type {BlurEvent, FocusEvent} from '../Types/CoreEventTypes'; // [macOS] import type { AccessibilityActionEvent, AccessibilityActionInfo, @@ -171,56 +166,6 @@ type ButtonProps = $ReadOnly<{| */ onFocus?: ?(e: FocusEvent) => void, - /** - * Handler to be called when a key down press is detected - */ - onKeyDown?: ?(e: KeyEvent) => void, - - /** - * Handler to be called when a key up press is detected - */ - onKeyUp?: ?(e: KeyEvent) => void, - - /* - * @deprecated use `keyDownEvents` or `keyUpEvents` instead - * Array of keys to receive key down events for - * For arrow keys, add "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", - */ - validKeysDown?: ?Array<string>, - - /* - * @deprecated use `keyDownEvents` or `keyUpEvents` instead - * Array of keys to receive key up events for - * For arrow keys, add "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", - */ - validKeysUp?: ?Array<string>, - - /** - * @deprecated use `keyDownEvents` or `keyUpEvents` instead - * When `true`, allows `onKeyDown` and `onKeyUp` to receive events not specified in - * `validKeysDown` and `validKeysUp`, respectively. Events matching `validKeysDown` and `validKeysUp` - * are still removed from the event queue, but the others are not. - * - * @platform macos - */ - passthroughAllKeyEvents?: ?boolean, - - /** - * Array of keys to receive key down events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` - * - * @platform macos - */ - keyDownEvents?: ?Array<HandledKeyEvent>, - - /** - * Array of keys to receive key up events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` - * - * @platform macos - */ - keyUpEvents?: ?Array<HandledKeyEvent>, - /* * Specifies the Tooltip for the view */ @@ -402,8 +347,6 @@ const Button: React.AbstractComponent< // [macOS onFocus, onBlur, - onKeyDown, - onKeyUp, tooltip, // macOS] } = props; diff --git a/packages/react-native/Libraries/Components/Pressable/Pressable.js b/packages/react-native/Libraries/Components/Pressable/Pressable.js index c046c57d7adea2..d1c9433ebc83b7 100644 --- a/packages/react-native/Libraries/Components/Pressable/Pressable.js +++ b/packages/react-native/Libraries/Components/Pressable/Pressable.js @@ -191,36 +191,10 @@ type Props = $ReadOnly<{| * * @platform macos */ - validKeysDown?: ?Array<string | HandledKeyEvent>, - - /** - * Array of keys to receive key up events for. These events have their default native behavior prevented. - * - * @platform macos - */ - validKeysUp?: ?Array<string | HandledKeyEvent>, - - /** - * @deprecated use `keyDownEvents` or `keyUpEvents` instead - * When `true`, allows `onKeyDown` and `onKeyUp` to receive events not specified in - * `validKeysDown` and `validKeysUp`, respectively. Events matching `validKeysDown` and `validKeysUp` - * are still removed from the event queue, but the others are not. - * - * @platform macos - */ - passthroughAllKeyEvents?: ?boolean, - - /** - * Array of keys to receive key down events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` - * - * @platform macos - */ keyDownEvents?: ?Array<HandledKeyEvent>, /** * Array of keys to receive key up events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` * * @platform macos */ @@ -377,7 +351,6 @@ function Pressable( onBlur, onKeyDown, onKeyUp, - passthroughAllKeyEvents, keyDownEvents, keyUpEvents, acceptsFirstMouse, diff --git a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js index 55b73378732bc9..7c33b48c95180c 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js @@ -51,9 +51,6 @@ const UIView = { onDrop: true, onKeyDown: true, onKeyUp: true, - validKeysDown: true, - validKeysUp: true, - passthroughAllKeyEvents: true, keyDownEvents: true, keyUpEvents: true, draggedTypes: true, diff --git a/packages/react-native/Libraries/Components/View/View.js b/packages/react-native/Libraries/Components/View/View.js index b6d1a58202cebd..ff32a275841bb0 100644 --- a/packages/react-native/Libraries/Components/View/View.js +++ b/packages/react-native/Libraries/Components/View/View.js @@ -54,9 +54,6 @@ const View: React.AbstractComponent< nativeID, tabIndex, // [macOS - passthroughAllKeyEvents, - validKeysDown, - validKeysUp, keyDownEvents, keyUpEvents, // macOS] @@ -101,19 +98,6 @@ const View: React.AbstractComponent< }; } - // [macOS - let _passthroughAllKeyEvents = passthroughAllKeyEvents; - let _validKeysDown = validKeysDown; - let _validKeysUp = validKeysUp; - if (keyDownEvents || keyUpEvents) { - _passthroughAllKeyEvents = true; - // $FlowFixMe[incompatible-type] - _validKeysDown = keyDownEvents; - // $FlowFixMe[incompatible-type] - _validKeysUp = keyUpEvents; - } - // macOS] - const actualView = ( <ViewNativeComponent {...otherProps} @@ -132,11 +116,6 @@ const View: React.AbstractComponent< : importantForAccessibility } nativeID={id ?? nativeID} - // [macOS - passthroughAllKeyEvents={_passthroughAllKeyEvents} - validKeysDown={_validKeysDown} - validKeysUp={_validKeysUp} - // macOS] ref={forwardedRef} /> ); diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts b/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts index 46fdf3ad71d662..bee9199b0fcab9 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts @@ -137,11 +137,8 @@ export interface ViewPropsMacOS { onDrop?: ((event: MouseEvent) => void) | undefined; onKeyDown?: ((event: KeyEvent) => void) | undefined; onKeyUp?: ((event: KeyEvent) => void) | undefined; - validKeysDown?: Array<HandledKeyEvent | string> | undefined; - validKeysUp?: Array<HandledKeyEvent | string> | undefined; - passthroughAllKeyEvents?: boolean | undefined; - keyDownEvents?: Array<HandledKeyEvent> | undefined; - keyUpEvents?: Array<HandledKeyEvent> | undefined; + keyDownEvents?: HandledKeyEvent[] | undefined; + keyUpEvents?: HandledKeyEvent[] | undefined; draggedTypes?: DraggedTypesType | undefined; } diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index 2fdb51f840eaee..b10219ceb1884d 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -116,36 +116,10 @@ export type KeyboardEventProps = $ReadOnly<{| * * @platform macos */ - validKeysDown?: ?Array<string | HandledKeyEvent>, - - /** - * Array of keys to receive key up events for. These events have their default native behavior prevented. - * - * @platform macos - */ - validKeysUp?: ?Array<string | HandledKeyEvent>, - - /** - * @deprecated use `keyDownEvents` or `keyUpEvents` instead - * When `true`, allows `onKeyDown` and `onKeyUp` to receive events not specified in - * `validKeysDown` and `validKeysUp`, respectively. Events matching `validKeysDown` and `validKeysUp` - * are still removed from the event queue, but the others are not. - * - * @platform macos - */ - passthroughAllKeyEvents?: ?boolean, - - /** - * Array of keys to receive key down events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` - * - * @platform macos - */ keyDownEvents?: ?Array<HandledKeyEvent>, /** * Array of keys to receive key up events for. These events have their default native behavior prevented. - * Overrides the props `validKeysDown`, `validKeysUp` and `passthroughAllKeyEvents` * * @platform macos */ diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.macos.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.macos.js index 2cd32a5532fc46..cd4007a16af4fe 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.macos.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.macos.js @@ -53,9 +53,6 @@ const validAttributesForNonEventProps = { draggedTypes: true, enableFocusRing: true, tooltip: true, - validKeysDown: true, - validKeysUp: true, - passthroughAllKeyEvents: true, keyDownEvents: true, keyUpEvents: true, mouseDownCanMoveWindow: true, diff --git a/packages/react-native/Libraries/Pressability/Pressability.js b/packages/react-native/Libraries/Pressability/Pressability.js index 11c951fd26979f..8102198cc21d2e 100644 --- a/packages/react-native/Libraries/Pressability/Pressability.js +++ b/packages/react-native/Libraries/Pressability/Pressability.js @@ -101,11 +101,15 @@ export type PressabilityConfig = $ReadOnly<{| // [macOS /* * Called after a key down event is detected. + * + * @platform macos */ onKeyDown?: ?(event: KeyEvent) => void, /* * Called after a key up event is detected. + * + * @platform macos */ onKeyUp?: ?(event: KeyEvent) => void, // macOS] diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h index 5b49265d808306..6414206dfabb84 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h +++ b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegate.h @@ -48,7 +48,7 @@ NS_ASSUME_NONNULL_BEGIN #if TARGET_OS_OSX // [macOS - (BOOL)textInputShouldHandleDeleteForward:(id<RCTBackedTextInputViewProtocol>)sender; // Return `YES` to have the deleteForward event handled normally. Return `NO` to disallow it and handle it yourself. - (BOOL)textInputShouldHandleKeyEvent:(NSEvent *)event; // Return `YES` to have the key event handled normally. Return `NO` to disallow it and handle it yourself. -- (BOOL)hasValidKeyDownOrValidKeyUp:(NSString *)key; +- (BOOL)hasKeyDownEventOrKeyUpEvent:(NSString *)key; - (NSDragOperation)textInputDraggingEntered:(id<NSDraggingInfo>)draggingInfo; - (void)textInputDraggingExited:(id<NSDraggingInfo>)draggingInfo; - (BOOL)textInputShouldHandleDragOperation:(id<NSDraggingInfo>)draggingInfo; diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.mm b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.mm index 54befd8bd84ca4..7fe50d5b24d67a 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.mm +++ b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.mm @@ -228,7 +228,7 @@ - (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doComman //escape } else if (commandSelector == @selector(cancelOperation:)) { [textInputDelegate textInputDidCancel]; - if (![textInputDelegate hasValidKeyDownOrValidKeyUp:@"Escape"]) { + if (![textInputDelegate hasKeyDownEventOrKeyUpEvent:@"Escape"]) { [[_backedTextInputView window] makeFirstResponder:nil]; } commandHandled = YES; @@ -457,7 +457,7 @@ - (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector //escape } else if (commandSelector == @selector(cancelOperation:)) { [textInputDelegate textInputDidCancel]; - if (![textInputDelegate hasValidKeyDownOrValidKeyUp:@"Escape"]) { + if (![textInputDelegate hasKeyDownEventOrKeyUpEvent:@"Escape"]) { [[_backedTextInputView window] makeFirstResponder:nil]; } commandHandled = YES; diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm index 0fc88ae0a8bc32..dd0e88178c7fe4 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm @@ -730,9 +730,9 @@ - (BOOL)textInputShouldHandleDeleteForward:(__unused id)sender { return YES; } -- (BOOL)hasValidKeyDownOrValidKeyUp:(NSString *)key { - return [RCTHandledKey key:key matchesFilter:self.validKeysDown] - || [RCTHandledKey key:key matchesFilter:self.validKeysUp]; +- (BOOL)hasKeyDownEventOrKeyUpEvent:(NSString *)key { + return [RCTHandledKey key:key matchesFilter:self.keyDownEvents] + || [RCTHandledKey key:key matchesFilter:self.keyUpEvents]; } - (NSDragOperation)textInputDraggingEntered:(id<NSDraggingInfo>)draggingInfo diff --git a/packages/react-native/Libraries/Types/CoreEventTypes.d.ts b/packages/react-native/Libraries/Types/CoreEventTypes.d.ts index 88d32463272586..66ba5ecb85b8f1 100644 --- a/packages/react-native/Libraries/Types/CoreEventTypes.d.ts +++ b/packages/react-native/Libraries/Types/CoreEventTypes.d.ts @@ -285,7 +285,7 @@ export interface NativeKeyEvent { } /** - * Represents a key that could be passed to `validKeysDown` and `validKeysUp`. + * Represents a key that could be passed to `keyDownEvents` and `keyUpEvents`. * * `key` is the actual key, such as "a", or one of the special values: * "Tab", "Escape", "Enter", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", diff --git a/packages/react-native/Libraries/Types/CoreEventTypes.js b/packages/react-native/Libraries/Types/CoreEventTypes.js index c8f1b917baf105..f506cb4ac7c3c3 100644 --- a/packages/react-native/Libraries/Types/CoreEventTypes.js +++ b/packages/react-native/Libraries/Types/CoreEventTypes.js @@ -310,7 +310,7 @@ export type KeyEvent = SyntheticEvent< >; /** - * Represents a key that could be passed to `validKeysDown` and `validKeysUp`. + * Represents a key that could be passed to `KeyDownEvents` and `KeyUpEvents`. * * `key` is the actual key, such as "a", or one of the special values: * "Tab", "Escape", "Enter", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 8c2910be4b7db8..c322e5629c2c54 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -1664,13 +1664,6 @@ exports[`public API should not change unintentionally Libraries/Components/Butto onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(e: BlurEvent) => void, onFocus?: ?(e: FocusEvent) => void, - onKeyDown?: ?(e: KeyEvent) => void, - onKeyUp?: ?(e: KeyEvent) => void, - validKeysDown?: ?Array<string>, - validKeysUp?: ?Array<string>, - passthroughAllKeyEvents?: ?boolean, - keyDownEvents?: ?Array<HandledKeyEvent>, - keyUpEvents?: ?Array<HandledKeyEvent>, tooltip?: string, accessible?: ?boolean, accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>, @@ -1866,9 +1859,6 @@ type Props = $ReadOnly<{| onBlur?: ?(event: BlurEvent) => void, onKeyDown?: ?(event: KeyEvent) => void, onKeyUp?: ?(event: KeyEvent) => void, - validKeysDown?: ?Array<string | HandledKeyEvent>, - validKeysUp?: ?Array<string | HandledKeyEvent>, - passthroughAllKeyEvents?: ?boolean, keyDownEvents?: ?Array<HandledKeyEvent>, keyUpEvents?: ?Array<HandledKeyEvent>, acceptsFirstMouse?: ?boolean, @@ -4031,9 +4021,6 @@ exports[`public API should not change unintentionally Libraries/Components/View/ onDrop: true, onKeyDown: true, onKeyUp: true, - validKeysDown: true, - validKeysUp: true, - passthroughAllKeyEvents: true, keyDownEvents: true, keyUpEvents: true, draggedTypes: true, @@ -4223,9 +4210,6 @@ type DirectEventProps = $ReadOnly<{| export type KeyboardEventProps = $ReadOnly<{| onKeyDown?: ?(event: KeyEvent) => void, onKeyUp?: ?(event: KeyEvent) => void, - validKeysDown?: ?Array<string | HandledKeyEvent>, - validKeysUp?: ?Array<string | HandledKeyEvent>, - passthroughAllKeyEvents?: ?boolean, keyDownEvents?: ?Array<HandledKeyEvent>, keyUpEvents?: ?Array<HandledKeyEvent>, |}>; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index af42831ab582c2..a9b58ed96267b5 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -504,7 +504,7 @@ - (void)grammarCheckingDidChange:(BOOL)enabled } } -- (BOOL)hasValidKeyDownOrValidKeyUp:(nonnull NSString *)key { +- (BOOL)hasKeyDownEventOrKeyUpEvent:(nonnull NSString *)key { return YES; } diff --git a/packages/react-native/React/Views/RCTHandledKey.h b/packages/react-native/React/Views/RCTHandledKey.h index f0d2562d46c9df..d23a3494b0754e 100644 --- a/packages/react-native/React/Views/RCTHandledKey.h +++ b/packages/react-native/React/Views/RCTHandledKey.h @@ -10,7 +10,7 @@ #if TARGET_OS_OSX #import <React/RCTConvert.h> -// This class is used for specifying key filtering e.g. for -[RCTView validKeysDown] and -[RCTView validKeysUp] +// This class is used for specifying key filtering e.g. for -[RCTView keyDownEvents] and -[RCTView keyUpEvents] // Also see RCTViewKeyboardEvent, which is a React representation of an actual NSEvent that is dispatched to JS. @interface RCTHandledKey : NSObject diff --git a/packages/react-native/React/Views/RCTHandledKey.m b/packages/react-native/React/Views/RCTHandledKey.m index aa685c3b999044..a7c61d7a2e6c2b 100644 --- a/packages/react-native/React/Views/RCTHandledKey.m +++ b/packages/react-native/React/Views/RCTHandledKey.m @@ -103,12 +103,6 @@ @implementation RCTConvert (RCTHandledKey) + (RCTHandledKey *)RCTHandledKey:(id)json { - // legacy way of specifying validKeysDown and validKeysUp -- here we ignore the modifiers when comparing to the NSEvent - if ([json isKindOfClass:[NSString class]]) { - return [[RCTHandledKey alloc] initWithKey:(NSString *)json]; - } - - // modern way of specifying validKeys and validKeysUp -- here we assume missing modifiers to mean false\NO if ([json isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)json; NSString *key = dict[@"key"]; @@ -122,7 +116,7 @@ + (RCTHandledKey *)RCTHandledKey:(id)json for (NSString *key in modifiers) { id value = dict[key]; if (value == nil) { - value = @NO; // assume NO -- instead of nil i.e. "don't care" unlike the string case above. + value = @(NO); // assume NO -- instead of nil i.e. "don't care" unlike the string case above. } if (![value isKindOfClass:[NSNumber class]]) { diff --git a/packages/react-native/React/Views/RCTView.h b/packages/react-native/React/Views/RCTView.h index 8947d0d16ab562..f314a05f31fb0a 100644 --- a/packages/react-native/React/Views/RCTView.h +++ b/packages/react-native/React/Views/RCTView.h @@ -170,11 +170,10 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait; // NOTE does not properly work with single line text inputs (most key downs). This is because those are // presumably handled by the window's field editor. To make it work, we'd need to look into providing // a custom field editor for NSTextField controls. -@property (nonatomic, assign) BOOL passthroughAllKeyEvents; @property (nonatomic, copy) RCTDirectEventBlock onKeyDown; @property (nonatomic, copy) RCTDirectEventBlock onKeyUp; -@property (nonatomic, copy) NSArray<RCTHandledKey*> *validKeysDown; -@property (nonatomic, copy) NSArray<RCTHandledKey*> *validKeysUp; +@property (nonatomic, copy) NSArray<RCTHandledKey*> *keyDownEvents; +@property (nonatomic, copy) NSArray<RCTHandledKey*> *keyUpEvents; // Shadow Properties @property (nonatomic, strong) NSColor *shadowColor; diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index 533b12b0f5b4bf..ba2cc6f24a8da3 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -1598,23 +1598,23 @@ - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event shouldBlock:(BOOL *)shouldBlock { BOOL keyDown = event.type == NSEventTypeKeyDown; - NSArray<RCTHandledKey *> *validKeys = keyDown ? self.validKeysDown : self.validKeysUp; + NSArray<RCTHandledKey *> *keyEvents = keyDown ? self.keyDownEvents : self.keyUpEvents; - // If the view is focusable and the component didn't explicity set the validKeysDown or validKeysUp, + // If the view is focusable and the component didn't explicity set the keyDownEvents or keyUpEvents, // allow enter/return and spacebar key events to mimic the behavior of native controls. - if (self.focusable && validKeys == nil) { - validKeys = @[ + if (self.focusable && keyEvents == nil) { + keyEvents = @[ [[RCTHandledKey alloc] initWithKey:@"Enter"], [[RCTHandledKey alloc] initWithKey:@" "] ]; } // If a view specifies a key, it will always be removed from the responder chain (i.e. "handled") - *shouldBlock = [RCTHandledKey event:event matchesFilter:validKeys]; + *shouldBlock = [RCTHandledKey event:event matchesFilter:keyEvents]; - // If an event isn't being removed from the queue, but was requested to "passthrough" by a view, - // we want to be sure we dispatch it only once for that view. See note for GetEventDispatchStateDictionary. - if ([self passthroughAllKeyEvents] && !*shouldBlock) { + // If an event isn't being removed from the queue, we want to be sure we dispatch it + // only once for that view. See note for GetEventDispatchStateDictionary. + if (!*shouldBlock) { NSNumber *tag = [self reactTag]; NSMutableDictionary<NSNumber *, NSNumber *> *dict = GetEventDispatchStateDictionary(event); @@ -1625,11 +1625,6 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event shouldBlock:(BOOL *)shoul dict[tag] = @YES; } - // Don't pass events we don't care about - if (![self passthroughAllKeyEvents] && !*shouldBlock) { - return nil; - } - return [RCTViewKeyboardEvent keyEventFromEvent:event reactTag:self.reactTag]; } diff --git a/packages/react-native/React/Views/RCTViewManager.m b/packages/react-native/React/Views/RCTViewManager.m index 1e29fe98279003..54232dac07f278 100644 --- a/packages/react-native/React/Views/RCTViewManager.m +++ b/packages/react-native/React/Views/RCTViewManager.m @@ -654,11 +654,10 @@ - (void) updateAccessibilityRole:(RCTView *)view withDefaultView:(RCTView *)defa RCT_EXPORT_VIEW_PROPERTY(onDragEnter, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDragLeave, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDrop, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(passthroughAllKeyEvents, BOOL) -RCT_EXPORT_VIEW_PROPERTY(onKeyDown, RCTDirectEventBlock) // macOS keyboard events -RCT_EXPORT_VIEW_PROPERTY(onKeyUp, RCTDirectEventBlock) // macOS keyboard events -RCT_EXPORT_VIEW_PROPERTY(validKeysDown, NSArray<RCTHandledKey *>) -RCT_EXPORT_VIEW_PROPERTY(validKeysUp, NSArray<RCTHandledKey *>) +RCT_EXPORT_VIEW_PROPERTY(onKeyDown, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onKeyUp, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(keyDownEvents, NSArray<RCTHandledKey *>) +RCT_EXPORT_VIEW_PROPERTY(keyUpEvents, NSArray<RCTHandledKey *>) #endif // macOS] diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollView.m b/packages/react-native/React/Views/ScrollView/RCTScrollView.m index 8102496efa9910..8a729defeb5f4d 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollView.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollView.m @@ -1332,10 +1332,10 @@ - (void)uiManagerWillPerformMounting:(RCTUIManager *)manager #if TARGET_OS_OSX - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event { BOOL keyDown = event.type == NSEventTypeKeyDown; - NSArray<RCTHandledKey *> *validKeys = keyDown ? self.validKeysDown : self.validKeysUp; + NSArray<RCTHandledKey *> *keyEvents = keyDown ? self.keyDownEvents : self.keyUpEvents; // Only post events for keys we care about - if (![RCTHandledKey event:event matchesFilter:validKeys]) { + if (![RCTHandledKey event:event matchesFilter:keyEvents]) { return nil; } diff --git a/packages/rn-tester/js/examples/KeyboardEventsExample/KeyboardEventsExample.js b/packages/rn-tester/js/examples/KeyboardEventsExample/KeyboardEventsExample.js index 302442a5ed22ff..bb708b7fa471b1 100644 --- a/packages/rn-tester/js/examples/KeyboardEventsExample/KeyboardEventsExample.js +++ b/packages/rn-tester/js/examples/KeyboardEventsExample/KeyboardEventsExample.js @@ -18,13 +18,6 @@ const ReactNative = require('react-native'); const {Button, ScrollView, StyleSheet, Switch, Text, TextInput, View} = ReactNative; -const switchStyle = { - alignItems: 'center', - padding: 10, - flexDirection: 'row', - justifyContent: 'space-between', -}; - function KeyEventExample(): React.Node { // $FlowFixMe[missing-empty-array-annot] const [log, setLog] = React.useState([]); @@ -57,195 +50,86 @@ function KeyEventExample(): React.Node { [appendLog], ); - const [showView, setShowView] = React.useState(true); - const toggleShowView = React.useCallback( - (value: boolean) => { - setShowView(value); - }, - [setShowView], - ); - - const [showTextInput, setShowTextInput] = React.useState(true); - const toggleShowTextInput = React.useCallback( - (value: boolean) => { - setShowTextInput(value); - }, - [setShowTextInput], - ); - - const [showTextInput2, setShowTextInput2] = React.useState(true); - const toggleShowTextInput2 = React.useCallback( - (value: boolean) => { - setShowTextInput2(value); - }, - [setShowTextInput2], - ); - - const [passthroughAllKeyEvents, setPassthroughAllKeyEvents] = - React.useState(false); - const togglePassthroughAllKeyEvents = React.useCallback( - (value: boolean) => { - setPassthroughAllKeyEvents(value); - }, - [setPassthroughAllKeyEvents], - ); - - const [useKeyDownOrUpEvents, setUseKeyDownOrUpEvents] = React.useState(false); - const toggleKeyDownOrUpEvents = React.useCallback( - (value: boolean) => { - setUseKeyDownOrUpEvents(value); - }, - [setUseKeyDownOrUpEvents], - ); - - const ViewText = useKeyDownOrUpEvents - ? "keyDownEvents: [{key: 'g'}, {key: 'Escape'}, {key: 'Enter'}, {key: 'ArrowLeft'}] \nkeyUpEvents: [{key: 'c'}, {key: 'd'}]" - : 'validKeysDown: [g, Escape, Enter, ArrowLeft] \nvalidKeysUp: [c, d]'; - const viewKeyboardProps = useKeyDownOrUpEvents - ? { - keyDownEvents: [ - {key: 'g'}, - {key: 'Escape'}, - {key: 'Enter'}, - {key: 'ArrowLeft'}, - ], - keyUpEvents: [{key: 'c'}, {key: 'd'}], - } - : { - validKeysDown: ['g', 'Escape', 'Enter', 'ArrowLeft'], - validKeysUp: ['c ', 'd'], - }; - - const TextInputText = useKeyDownOrUpEvents - ? "keyDownEvents: [{key: 'ArrowRight'}, {key: 'ArrowDown'}, {key: 'Enter', ctrlKey: true}, \nkeyUpEvents: [{key: 'Escape'}, {key: 'Enter'}]" - : "validKeysDown: ['ArrowRight', 'ArrowDown', 'Enter'] \nvalidKeysUp: ['Escape ', {key: 'Enter', ctrlKey: true}]"; - const textInputKeyboardProps = useKeyDownOrUpEvents - ? { - keyDownEvents: [ - {key: 'ArrowRight'}, - {key: 'ArrowDown'}, - {key: 'Enter', ctrlKey: true}, - ], - keyUpEvents: [{key: 'Escape'}, {key: 'Enter'}], - } - : { - validKeysDown: ['ArrowRight', 'ArrowDown', 'Enter'], - validKeysUp: ['Escape ', {key: 'Enter', ctrlKey: true}], - }; + const viewText = + "keyDownEvents: [{key: 'g'}, {key: 'Escape'}, {key: 'Enter'}, {key: 'ArrowLeft'}] \nkeyUpEvents: [{key: 'c'}, {key: 'd'}]"; + const viewKeyboardProps = { + onKeyDown: handleKeyDown, + keyDownEvents: [ + {key: 'g'}, + {key: 'Escape'}, + {key: 'Enter'}, + {key: 'ArrowLeft'}, + ], + onKeyUp: handleKeyUp, + keyUpEvents: [{key: 'c'}, {key: 'd'}], + }; + + const textInputText = + "keyDownEvents: [{key: 'ArrowRight'}, {key: 'ArrowDown'}, {key: 'Enter', ctrlKey: true}, \nkeyUpEvents: [{key: 'Escape'}, {key: 'Enter'}]"; + const textInputKeyboardProps = { + onKeyDown: handleKeyDown, + keyDownEvents: [ + {key: 'ArrowRight'}, + {key: 'ArrowDown'}, + {key: 'Enter', ctrlKey: true}, + ], + onKeyUp: handleKeyUp, + keyUpEvents: [{key: 'Escape'}, {key: 'Enter'}], + }; + + const textInputUnhandledText = + "keyDownEvents: [{key: 'ArrowRight'}, {key: 'ArrowDown'}, {key: 'Enter', ctrlKey: true}, \nkeyUpEvents: [{key: 'Escape'}, {key: 'Enter'}]"; + const textInputunHandledKeyboardProps = { + onKeyDown: handleKeyDown, + onKeyUp: handleKeyUp, + }; return ( <ScrollView> - <View style={{padding: 10}}> + <View + style={{ + padding: 10, + }}> <Text> Key events are called when a component detects a key press.To tab between views on macOS: Enable System Preferences / Keyboard / Shortcuts > Use keyboard navigation to move focus between controls. </Text> <View> - <View style={switchStyle}> - <Text style={styles.title}>View</Text> - <Switch value={showView} onValueChange={toggleShowView} /> - </View> - {showView && ( - <> - <Text style={styles.text}>{ViewText}</Text> - <View - focusable={true} - style={styles.row} - onKeyDown={handleKeyDown} - onKeyUp={handleKeyUp} - passthroughAllKeyEvents={passthroughAllKeyEvents} - {...viewKeyboardProps} - /> - </> - )} - <View style={switchStyle}> - <Text style={styles.title}>TextInput</Text> - <Switch value={showTextInput} onValueChange={toggleShowTextInput} /> - </View> - {showTextInput && ( - <> - <Text style={styles.text}>{TextInputText}</Text> - <TextInput - blurOnSubmit={false} - placeholder={'Singleline textInput'} - multiline={false} - focusable={true} - style={styles.row} - onKeyDown={handleKeyDown} - onKeyUp={handleKeyUp} - passthroughAllKeyEvents={passthroughAllKeyEvents} - {...textInputKeyboardProps} - /> - <TextInput - placeholder={'Multiline textInput'} - multiline={true} - focusable={true} - style={styles.row} - passthroughAllKeyEvents={passthroughAllKeyEvents} - validKeysDown={[ - 'ArrowRight', - 'ArrowDown', - {key: 'Enter', ctrlKey: true}, - ]} - onKeyDown={handleKeyDown} - validKeysUp={['Escape', 'Enter']} - onKeyUp={handleKeyUp} - /> - </> - )} - <View style={switchStyle}> - <Text style={styles.title}>TextInput with no handled keys</Text> - <Switch - value={showTextInput2} - onValueChange={toggleShowTextInput2} - /> - </View> - {showTextInput2 && ( - <> - <Text style={styles.text}> - validKeysDown: []{'\n'} - validKeysUp: [] - </Text> - <TextInput - blurOnSubmit={false} - placeholder={'Singleline textInput'} - multiline={false} - focusable={true} - style={styles.row} - passthroughAllKeyEvents={passthroughAllKeyEvents} - validKeysDown={[]} - onKeyDown={handleKeyDown} - validKeysUp={[]} - onKeyUp={handleKeyUp} - /> - <TextInput - placeholder={'Multiline textInput'} - multiline={true} - focusable={true} - style={styles.row} - passthroughAllKeyEvents={passthroughAllKeyEvents} - validKeysDown={[]} - onKeyDown={handleKeyDown} - validKeysUp={[]} - onKeyUp={handleKeyUp} - /> - </> - )} - <View style={switchStyle}> - <Text>{'Pass through all key events'}</Text> - <Switch - value={passthroughAllKeyEvents} - onValueChange={togglePassthroughAllKeyEvents} - /> - </View> - <View style={switchStyle}> - <Text>{'Use keyDownEvents / keyUpEvents'}</Text> - <Switch - value={useKeyDownOrUpEvents} - onValueChange={toggleKeyDownOrUpEvents} - /> - </View> + <Text style={styles.text}>{viewText}</Text> + <View focusable={true} style={styles.row} {...viewKeyboardProps} /> + <Text style={styles.text}>{textInputText}</Text> + <TextInput + blurOnSubmit={false} + placeholder={'Singleline textInput'} + multiline={false} + focusable={true} + style={styles.row} + {...textInputKeyboardProps} + /> + <TextInput + placeholder={'Multiline textInput'} + multiline={true} + focusable={true} + style={styles.row} + {...textInputKeyboardProps} + /> + <Text style={styles.text}>{textInputUnhandledText}</Text> + <TextInput + blurOnSubmit={false} + placeholder={'Singleline textInput'} + multiline={false} + focusable={true} + style={styles.row} + {...textInputunHandledKeyboardProps} + /> + <TextInput + placeholder={'Multiline textInput'} + multiline={true} + focusable={true} + style={styles.row} + {...textInputunHandledKeyboardProps} + /> <Button testID="event_clear_button" onPress={clearLog} diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index df93bfc2ba7c3c..147bbf2f4992aa 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -26,7 +26,6 @@ import { TextInput, View, } from 'react-native'; -import {Switch} from 'react-native'; // [macOS] const styles = StyleSheet.create({ multiline: { @@ -69,14 +68,6 @@ const styles = StyleSheet.create({ focusedUncontrolled: { margin: -2, }, - // [macOS - passthroughAllKeyEvents: { - alignItems: 'center', - padding: 10, - flexDirection: 'row', - justifyContent: 'space-between', - }, - // macOS] screenshotArea: { position: 'absolute', top: -5, @@ -370,8 +361,6 @@ class SubmitBehaviorExample extends React.Component<{...}> { } } -let counter = 0; // [macOS] - class TextEventsExample extends React.Component<{...}, $FlowFixMeState> { state: | any @@ -379,65 +368,25 @@ class TextEventsExample extends React.Component<{...}, $FlowFixMeState> { curText: string, prev2Text: string, prev3Text: string, - // [macOS - prev4Text: string, - prev5Text: string, - prev6Text: string, - // macOS] prevText: string, - passthroughAllKeyEvents: boolean, // [macOS] } = { curText: '<No Event>', prevText: '<No Event>', prev2Text: '<No Event>', prev3Text: '<No Event>', - // [macOS - prev4Text: '<No Event>', - prev5Text: '<No Event>', - prev6Text: '<No Event>', - passthroughAllKeyEvents: false, - // macOS] }; updateText = (text: string) => { - counter++; // [macOS] this.setState(state => { return { - curText: text + ' [' + counter + ']', // [macOS] + curText: text, prevText: state.curText, prev2Text: state.prevText, prev3Text: state.prev2Text, - // [macOS - prev4Text: state.prev3Text, - prev5Text: state.prev4Text, - prev6Text: state.prev5Text, - // macOS] - }; - }); - }; - - // [macOS - clearLog = () => { - this.setState(() => { - return { - curText: '<No Event>', - prevText: '<No Event>', - prev2Text: '<No Event>', - prev3Text: '<No Event>', - prev4Text: '<No Event>', - prev5Text: '<No Event>', - prev6Text: '<No Event>', }; }); }; - toggleSwitch = (value: boolean) => { - this.setState(() => { - return {passthroughAllKeyEvents: value}; - }); - }; - // macOS] - render(): React.Node { return ( <View> @@ -473,7 +422,6 @@ class TextEventsExample extends React.Component<{...}, $FlowFixMeState> { onKeyUp={event => this.updateText('onKeyUp key: ' + event.nativeEvent.key) } - passthroughAllKeyEvents={this.state.passthroughAllKeyEvents} // macOS] style={styles.singleLine} /> @@ -482,25 +430,7 @@ class TextEventsExample extends React.Component<{...}, $FlowFixMeState> { {'\n'} (prev: {this.state.prevText}){'\n'} (prev2: {this.state.prev2Text}){'\n'} - (prev3: {this.state.prev3Text}){'\n'} - (prev4: {this.state.prev4Text}){'\n'} - (prev5: {this.state.prev5Text}){'\n'} - (prev6: {this.state.prev6Text}) </Text> - {/* [macOS */} - <Button - testID="event_clear_button" - onPress={this.clearLog} - title="Clear event log" - /> - <View style={styles.passthroughAllKeyEvents}> - <Text>{'Pass through all key events'}</Text> - <Switch - value={this.state.passthroughAllKeyEvents} - onValueChange={this.toggleSwitch} - /> - </View> - {/* macOS] */} </View> ); }