Skip to content

Commit

Permalink
Add support for keyDownEvents and keyUpEvents
Browse files Browse the repository at this point in the history
  • Loading branch information
Saadnajmi committed Jan 2, 2023
1 parent 71e7ccf commit 4f6c4eb
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 80 deletions.
42 changes: 34 additions & 8 deletions Libraries/Components/Pressable/Pressable.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,50 @@ type Props = $ReadOnly<{|
onBlur?: ?(event: BlurEvent) => mixed,

/**
* Called after a key down event is detected.
* Fired when a key is pressed. If validKeysDown is set, only those keys will fire this event.
*
* @platform macos
*/
onKeyDown?: ?(event: KeyEvent) => mixed,
onKeyDown?: ?(e: KeyEvent) => void,

/**
* Called after a key up event is detected.
* Array of keyboard events whose natiev handling should be supressed. Use with `onKeyDown`
* to handle a keyboard event purely in JS.
*
* @platform macos
*/
onKeyUp?: ?(event: KeyEvent) => mixed,
keyDownEvents?: ?$ReadOnlyArray<HandledKeyboardEvent>,

/**
* Array of keys to receive key down events for
* For arrow keys, add "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown",
* @deprecated use `keyDownEvents` instead.
* Array of keys to receive key down events for.
* If undefined, all keyboard events will fire `onKeyUp`.
*
* @platform macos
*/
validKeysDown?: ?Array<string>,

/**
* Array of keys to receive key up events for
* For arrow keys, add "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown",
* Fired when a key is pressed. If validKeysDown is set, only those keys will fire this event.
*
* @platform macos
*/
onKeyUp?: ?(e: KeyEvent) => void,

/**
* Array of keyboard events whose natiev handling should be supressed. Use with `onUp`
* to handle a keyboard event purely in JS.
*
* @platform macos
*/
keyUpEvents?: ?$ReadOnlyArray<HandledKeyboardEvent>,

/**
* @deprecated use `keyUpEvents` instead.
* Array of keys to receive key up events for.
* If undefined, all keyboard events will fire `onKeyUp`
*
* @platform macos
*/
validKeysUp?: ?Array<string>,
// ]TODO(macOS GH#774)
Expand Down
16 changes: 0 additions & 16 deletions Libraries/Components/View/PlatformViewPropTypes.macos.js

This file was deleted.

2 changes: 2 additions & 0 deletions Libraries/Components/View/ReactNativeViewAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const UIView = {
onKeyUp: true,
validKeysDown: true,
validKeysUp: true,
keyDownEvents: true,
keyUpEvents: true,
draggedTypes: true,
nextKeyViewTag: true,
// ]TODO(macOS GH#774)
Expand Down
7 changes: 1 addition & 6 deletions Libraries/Components/View/ReactNativeViewViewConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ReactNativeViewConfig: ViewConfig = {
Constants: {},
bubblingEventTypes: {
...ReactNativeViewViewConfigAndroid.bubblingEventTypes,
...ReactNativeViewViewConfigMacOS.bubblingEventTypes, // [macOS]
topBlur: {
phasedRegistrationNames: {
bubbled: 'onBlur',
Expand Down Expand Up @@ -106,12 +107,6 @@ const ReactNativeViewConfig: ViewConfig = {
topMagicTap: {
registrationName: 'onMagicTap',
},
topKeyUp: {
registrationName: 'onKeyUp',
},
topKeyDown: {
registrationName: 'onKeyDown',
},
topPointerEnter: {
registrationName: 'pointerenter',
},
Expand Down
21 changes: 10 additions & 11 deletions Libraries/Components/View/ReactNativeViewViewConfigMacOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@

const ReactNativeViewViewConfigMacOS = {
uiViewClassName: 'RCTView',
bubblingEventTypes: {
topKeyUp: {
registrationName: 'onKeyUp',
},
topKeyDown: {
registrationName: 'onKeyDown',
},
},
directEventTypes: {
topDoubleClick: {
registrationName: 'onDoubleClick',
Expand All @@ -40,20 +48,11 @@ const ReactNativeViewViewConfigMacOS = {
draggedTypes: true,
enableFocusRing: true,
nextKeyViewTag: true,
onBlur: true,
onClick: true,
onDoubleClick: true,
onDragEnter: true,
onDragLeave: true,
onDrop: true,
onFocus: true,
onKeyDown: true,
onKeyUp: true,
onMouseEnter: true,
onMouseLeave: true,
tooltip: true,
validKeysDown: true,
validKeysUp: true,
keyDownEvents: true,
keyUpEvents: true
},
};

Expand Down
44 changes: 42 additions & 2 deletions Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import type {ViewProps} from './ViewPropTypes';
import ViewNativeComponent from './ViewNativeComponent';
import TextAncestor from '../../Text/TextAncestor';
import * as React from 'react';
import invariant from 'invariant'; // TODO(macOS GH#774)
import invariant from 'invariant'; // [macOS]
import type {KeyEvent} from '../../Types/CoreEventTypes'; // [macOS]

export type Props = ViewProps;

Expand All @@ -28,9 +29,48 @@ const View: React.AbstractComponent<
ViewProps,
React.ElementRef<typeof ViewNativeComponent>,
> = React.forwardRef((props: ViewProps, forwardedRef) => {
// [macOS
const {onKeyDown, onKeyUp, validKeysDown, validKeysUp} = props;

invariant(
// $FlowFixMe Wanting to catch untyped usages
validKeysDown === undefined,
'Support for the "acceptsKeyboardFocus" property has been deprecated in favor of "keyDownEvents"',
);

invariant(
// $FlowFixMe Wanting to catch untyped usages
validKeysUp === undefined,
'Support for the "acceptsKeyboardFocus" property has been removed in favor of "keyUpEvents"',
);

// To support the deprecated validKeysDown prop, suppress bubbling if it is defined
const onKeyDownWithLegacyBehavior = (e: KeyEvent) => {
if (validKeysDown) {
e.stopPropogation();
}
onKeyDown?.();
};

// To support the deprecated validKeysUp prop, suppress bubbling if it is defined
const onKeyUpWithLegacyBehavior = (e: KeyEvent) => {
if (validKeysUp) {
e.stopPropogation();
}
onKeyUp?.();
};
// macOS]

return (
<TextAncestor.Provider value={false}>
<ViewNativeComponent {...props} ref={forwardedRef} />
{/* [macOS */}
<ViewNativeComponent
{...props}
ref={forwardedRef}
{...(onKeyDown && {keyDown: onKeyDownWithLegacyBehavior})}
{...(onKeyUp && {keyUp: onKeyUpWithLegacyBehavior})}
/>
{/* macOS] */}
</TextAncestor.Provider>
);
});
Expand Down
73 changes: 57 additions & 16 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ export type ViewLayoutEvent = LayoutEvent;
type BubblingEventProps = $ReadOnly<{|
onBlur?: ?(event: BlurEvent) => mixed,
onFocus?: ?(event: FocusEvent) => mixed,
onKeyDown?: ?(event: KeyEvent) => mixed, // TODO(macOS GH#774)
onKeyUp?: ?(event: KeyEvent) => mixed, // TODO(macOS GH#774)
|}>;

type DirectEventProps = $ReadOnly<{|
Expand Down Expand Up @@ -405,7 +403,64 @@ type IOSViewProps = $ReadOnly<{|
|}>;

// [TODO(macOS GH#774)
type HandledKeyboardEvent = $ReadOnly<{|
altKey?: ?boolean,
ctrlKey?: ?boolean,
metaKey?: ?boolean,
shiftKey?: ?boolean,
code: string,
handledEventPhase?: number,
|}>;

type MacOSViewProps = $ReadOnly<{|
/**
* Fired when a key is pressed. If validKeysDown is set, only those keys will fire this event.
*
* @platform macos
*/
onKeyDown?: ?(e: KeyEvent) => void,

/**
* Array of keyboard events whose natiev handling should be supressed. Use with `onKeyDown`
* to handle a keyboard event purely in JS.
*
* @platform macos
*/
keyDownEvents?: ?$ReadOnlyArray<HandledKeyboardEvent>,

/**
* @deprecated use `keyDownEvents` instead.
* Array of keys to receive key down events for.
* If undefined, all keyboard events will fire `onKeyUp`.
*
* @platform macos
*/
validKeysDown?: ?Array<string>,

/**
* Fired when a key is pressed. If validKeysDown is set, only those keys will fire this event.
*
* @platform macos
*/
onKeyUp?: ?(e: KeyEvent) => void,

/**
* Array of keyboard events whose natiev handling should be supressed. Use with `onUp`
* to handle a keyboard event purely in JS.
*
* @platform macos
*/
keyUpEvents?: ?$ReadOnlyArray<HandledKeyboardEvent>,

/**
* @deprecated use `keyUpEvents` instead.
* Array of keys to receive key up events for.
* If undefined, all keyboard events will fire `onKeyUp`
*
* @platform macos
*/
validKeysUp?: ?Array<string>,

/**
* Fired when a dragged element enters a valid drop target
*
Expand Down Expand Up @@ -455,20 +510,6 @@ type MacOSViewProps = $ReadOnly<{|
*/
enableFocusRing?: ?boolean,

/**
* Array of keys to receive key down events for
*
* @platform macos
*/
validKeysDown?: ?Array<string>,

/**
* Array of keys to receive key up events for
*
* @platform macos
*/
validKeysUp?: ?Array<string>,

/**
* Enables Drag'n'Drop Support for certain types of dragged types
*
Expand Down
19 changes: 7 additions & 12 deletions Libraries/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -1334,22 +1334,17 @@ class VirtualizedList extends React.PureComponent<Props, State> {
this.props.onPreferredScrollerStyleDidChange;
const invertedDidChange = this.props.onInvertedDidChange;

const isFirstRowSelected = this.state.selectedRowIndex === this.state.first;
const isLastRowSelected = this.state.selectedRowIndex === this.state.last;

// Don't pass in ArrowUp/ArrowDown at the top/bottom of the list so that keyboard event can bubble
let _validKeysDown = ['Home', 'End'];
if (!isFirstRowSelected) {
_validKeysDown.push('ArrowUp');
}
if (!isLastRowSelected) {
_validKeysDown.push('ArrowDown');
}
let _keyDownEvents = [
{key: 'Home'},
{key: 'End'},
{key: 'ArrowDown'},
{key: 'ArrowUp'},
];

const keyboardNavigationProps = {
focusable: true,
validKeysDown: _validKeysDown,
onKeyDown: this._handleKeyDown,
keyDownEvents: __keyDownEvents,
};
// ]TODO(macOS GH#774)
const onRefresh = props.onRefresh;
Expand Down
2 changes: 0 additions & 2 deletions Libraries/Renderer/shims/ReactNativeTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ export type PartialViewConfig = $ReadOnly<{
export type NativeMethods = $ReadOnly<{|
blur(): void,
focus(): void,
onKeyDown(): void,
onKeyUp(): void,
measure(callback: MeasureOnSuccessCallback): void,
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void,
measureLayout(
Expand Down
10 changes: 6 additions & 4 deletions React/Views/RCTView.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,12 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
@property (nonatomic, copy) RCTDirectEventBlock onDrop;

// Keyboarding events
@property (nonatomic, copy) RCTDirectEventBlock onKeyDown;
@property (nonatomic, copy) RCTDirectEventBlock onKeyUp;
@property (nonatomic, copy) NSArray<NSString*> *validKeysDown;
@property (nonatomic, copy) NSArray<NSString*> *validKeysUp;
@property (nonatomic, copy) RCTBubblingEventBlock onKeyDown;
@property (nonatomic, copy) RCTBubblingEventBlock onKeyUp;
@property (nonatomic, copy) NSArray<NSString *> *validKeysDown;
@property (nonatomic, copy) NSArray<NSString *> *validKeysUp;
@property (nonatomic, copy) NSArray<RCTHandledKeyboardEvent> *keyDownEvents;
@property (nonatomic, copy) NSArray<RCTHandledKeyboardEvent> *keyUpEvents;

// Shadow Properties
@property (nonatomic, strong) NSColor *shadowColor;
Expand Down
Loading

0 comments on commit 4f6c4eb

Please sign in to comment.