Skip to content

Commit 065c195

Browse files
committed
Deprecate onScrollKeyDown
remove pressable diff Remove JS handling for PageUp/Down, fix flow errors Add back "autoscroll to focused view" behavior remove commented code remove change to pressable Update documentation fix flow error fix lint issue
1 parent 6b42baf commit 065c195

File tree

16 files changed

+162
-299
lines changed

16 files changed

+162
-299
lines changed

Libraries/Components/ScrollView/ScrollView.js

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,50 +1188,6 @@ class ScrollView extends React.Component<Props, State> {
11881188
}
11891189

11901190
// [TODO(macOS GH#774)
1191-
_handleKeyDown = (event: ScrollEvent) => {
1192-
if (this.props.onScrollKeyDown) {
1193-
this.props.onScrollKeyDown(event);
1194-
} else {
1195-
if (Platform.OS === 'macos') {
1196-
const nativeEvent = event.nativeEvent;
1197-
const key = nativeEvent.key;
1198-
const kMinScrollOffset = 10;
1199-
if (key === 'PAGE_UP') {
1200-
this._handleScrollByKeyDown(event, {
1201-
x: nativeEvent.contentOffset.x,
1202-
y:
1203-
nativeEvent.contentOffset.y +
1204-
-nativeEvent.layoutMeasurement.height,
1205-
});
1206-
} else if (key === 'PAGE_DOWN') {
1207-
this._handleScrollByKeyDown(event, {
1208-
x: nativeEvent.contentOffset.x,
1209-
y:
1210-
nativeEvent.contentOffset.y +
1211-
nativeEvent.layoutMeasurement.height,
1212-
});
1213-
} else if (key === 'HOME') {
1214-
this.scrollTo({x: 0, y: 0});
1215-
} else if (key === 'END') {
1216-
this.scrollToEnd({animated: true});
1217-
}
1218-
}
1219-
}
1220-
};
1221-
1222-
_handleScrollByKeyDown = (event: ScrollEvent, newOffset) => {
1223-
const maxX =
1224-
event.nativeEvent.contentSize.width -
1225-
event.nativeEvent.layoutMeasurement.width;
1226-
const maxY =
1227-
event.nativeEvent.contentSize.height -
1228-
event.nativeEvent.layoutMeasurement.height;
1229-
this.scrollTo({
1230-
x: Math.max(0, Math.min(maxX, newOffset.x)),
1231-
y: Math.max(0, Math.min(maxY, newOffset.y)),
1232-
});
1233-
};
1234-
12351191
_handlePreferredScrollerStyleDidChange = (event: ScrollEvent) => {
12361192
this.setState({contentKey: this.state.contentKey + 1});
12371193
}; // ]TODO(macOS GH#774)
@@ -1787,7 +1743,6 @@ class ScrollView extends React.Component<Props, State> {
17871743
// Override the onContentSizeChange from props, since this event can
17881744
// bubble up from TextInputs
17891745
onContentSizeChange: null,
1790-
onScrollKeyDown: this._handleKeyDown, // TODO(macOS GH#774)
17911746
onPreferredScrollerStyleDidChange:
17921747
this._handlePreferredScrollerStyleDidChange, // TODO(macOS GH#774)
17931748
onLayout: this._handleLayout,

Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ exports[`<ScrollView /> should render as expected: should deep render when not m
2727
onScroll={[Function]}
2828
onScrollBeginDrag={[Function]}
2929
onScrollEndDrag={[Function]}
30-
onScrollKeyDown={[Function]}
3130
onScrollShouldSetResponder={[Function]}
3231
onStartShouldSetResponder={[Function]}
3332
onStartShouldSetResponderCapture={[Function]}

Libraries/Components/View/ViewPropTypes.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@ type DirectEventProps = $ReadOnly<{|
7676
*/
7777
onPreferredScrollerStyleDidChange?: ?(event: ScrollEvent) => mixed, // TODO(macOS GH#774)
7878

79-
/**
80-
* When `focusable` is true, the system will try to invoke this function
81-
* when the user performs accessibility key down gesture.
82-
*/
83-
onScrollKeyDown?: ?(event: ScrollEvent) => mixed, // TODO(macOS GH#774)
84-
8579
/**
8680
* Invoked on mount and layout changes with:
8781
*

Libraries/Lists/VirtualizedList.js

Lines changed: 65 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import type {
3535
ViewToken,
3636
ViewabilityConfigCallbackPair,
3737
} from './ViewabilityHelper';
38-
import type {ScrollEvent} from '../Types/CoreEventTypes'; // TODO(macOS GH#774)
38+
import type {KeyEvent} from '../Types/CoreEventTypes'; // TODO(macOS GH#774)
3939
import {
4040
VirtualizedListCellContextProvider,
4141
VirtualizedListContext,
@@ -109,12 +109,24 @@ type OptionalProps = {|
109109
* this for debugging purposes. Defaults to false.
110110
*/
111111
disableVirtualization?: ?boolean,
112+
// [TODO(macOS GH#774)
112113
/**
113-
* Handles key down events and updates selection based on the key event
114+
* Allows you to 'select' a row using arrow keys. The selected row will have the prop `isSelected`
115+
* passed in as true to it's renderItem / ListItemComponent. You can also imperatively select a row
116+
* using the `selectRowAtIndex` method. You can set the initially selected row using the
117+
* `initialSelectedIndex` prop.
118+
* Keyboard Behavior:
119+
* - ArrowUp: Select row above current selected row
120+
* - ArrowDown: Select row below current selected row
121+
* - Option+ArrowUp: Select the first row
122+
* - Opton+ArrowDown: Select the last 'realized' row
123+
* - Home: Scroll to top of list
124+
* - End: Scroll to end of list
114125
*
115126
* @platform macos
116127
*/
117-
enableSelectionOnKeyPress?: ?boolean, // TODO(macOS GH#774)
128+
enableSelectionOnKeyPress?: ?boolean,
129+
// ]TODO(macOS GH#774)
118130
/**
119131
* A marker property for telling the list to re-render (since it implements `PureComponent`). If
120132
* any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the
@@ -1309,14 +1321,16 @@ class VirtualizedList extends React.PureComponent<Props, State> {
13091321
}
13101322

13111323
_defaultRenderScrollComponent = props => {
1312-
let keyEventHandler = this.props.onScrollKeyDown; // [TODO(macOS GH#774)
1313-
if (!keyEventHandler) {
1314-
keyEventHandler = this.props.enableSelectionOnKeyPress
1315-
? this._handleKeyDown
1316-
: null;
1317-
}
1324+
// [TODO(macOS GH#774)
13181325
const preferredScrollerStyleDidChangeHandler =
1319-
this.props.onPreferredScrollerStyleDidChange; // ]TODO(macOS GH#774)
1326+
this.props.onPreferredScrollerStyleDidChange;
1327+
1328+
const keyboardNavigationProps = {
1329+
focusable: true,
1330+
validKeysDown: ['ArrowUp', 'ArrowDown', 'Home', 'End'],
1331+
onKeyDown: this._handleKeyDown,
1332+
};
1333+
// ]TODO(macOS GH#774)
13201334
const onRefresh = props.onRefresh;
13211335
if (this._isNestedWithSameOrientation()) {
13221336
// $FlowFixMe[prop-missing] - Typing ReactNativeComponent revealed errors
@@ -1333,8 +1347,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
13331347
<ScrollView
13341348
{...props}
13351349
// [TODO(macOS GH#774)
1336-
{...(props.enableSelectionOnKeyPress && {focusable: true})}
1337-
onScrollKeyDown={keyEventHandler}
1350+
{...(props.enableSelectionOnKeyPress && keyboardNavigationProps)}
13381351
onPreferredScrollerStyleDidChange={
13391352
preferredScrollerStyleDidChangeHandler
13401353
} // TODO(macOS GH#774)]
@@ -1356,8 +1369,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
13561369
// $FlowFixMe Invalid prop usage
13571370
<ScrollView
13581371
{...props}
1359-
{...(props.enableSelectionOnKeyPress && {focusable: true})} // [TODO(macOS GH#774)
1360-
onScrollKeyDown={keyEventHandler}
1372+
// [TODO(macOS GH#774)
1373+
{...(props.enableSelectionOnKeyPress && keyboardNavigationProps)}
13611374
onPreferredScrollerStyleDidChange={
13621375
preferredScrollerStyleDidChangeHandler
13631376
} // TODO(macOS GH#774)]
@@ -1539,64 +1552,50 @@ class VirtualizedList extends React.PureComponent<Props, State> {
15391552
}
15401553
};
15411554

1542-
_handleKeyDown = (event: ScrollEvent) => {
1543-
if (this.props.onScrollKeyDown) {
1544-
this.props.onScrollKeyDown(event);
1545-
} else {
1546-
if (Platform.OS === 'macos') {
1547-
// $FlowFixMe Cannot get e.nativeEvent because property nativeEvent is missing in Event
1548-
const nativeEvent = event.nativeEvent;
1549-
const key = nativeEvent.key;
1550-
1551-
let prevIndex = -1;
1552-
let newIndex = -1;
1553-
if ('selectedRowIndex' in this.state) {
1554-
prevIndex = this.state.selectedRowIndex;
1555-
}
1555+
_handleKeyDown = (event: KeyEvent) => {
1556+
if (Platform.OS === 'macos') {
1557+
this.props.onKeyDown?.(event);
1558+
if (event.defaultPrevented) {
1559+
return;
1560+
}
1561+
1562+
const nativeEvent = event.nativeEvent;
1563+
const key = nativeEvent.key;
15561564

1557-
// const {data, getItem} = this.props;
1558-
if (key === 'UP_ARROW') {
1565+
let prevIndex = -1;
1566+
let newIndex = -1;
1567+
if ('selectedRowIndex' in this.state) {
1568+
prevIndex = this.state.selectedRowIndex;
1569+
}
1570+
1571+
// const {data, getItem} = this.props;
1572+
if (key === 'ArrowUp') {
1573+
if (nativeEvent.altKey) {
1574+
// Option+Up selects the first element
1575+
newIndex = this._selectRowAtIndex(0);
1576+
} else {
15591577
newIndex = this._selectRowAboveIndex(prevIndex);
1560-
this._handleSelectionChange(prevIndex, newIndex);
1561-
} else if (key === 'DOWN_ARROW') {
1578+
}
1579+
this._handleSelectionChange(prevIndex, newIndex);
1580+
} else if (key === 'ArrowDown') {
1581+
if (nativeEvent.altKey) {
1582+
// Option+Down selects the last element
1583+
newIndex = this._selectRowAtIndex(this.state.last);
1584+
} else {
15621585
newIndex = this._selectRowBelowIndex(prevIndex);
1563-
this._handleSelectionChange(prevIndex, newIndex);
1564-
} else if (key === 'ENTER') {
1586+
}
1587+
this._handleSelectionChange(prevIndex, newIndex);
1588+
} else if (key === 'Enter') {
1589+
if (this.props.onSelectionEntered) {
1590+
const item = this.props.getItem(this.props.data, prevIndex);
15651591
if (this.props.onSelectionEntered) {
1566-
const item = this.props.getItem(this.props.data, prevIndex);
1567-
if (this.props.onSelectionEntered) {
1568-
this.props.onSelectionEntered(item);
1569-
}
1592+
this.props.onSelectionEntered(item);
15701593
}
1571-
} else if (key === 'OPTION_UP') {
1572-
newIndex = this._selectRowAtIndex(0);
1573-
this._handleSelectionChange(prevIndex, newIndex);
1574-
} else if (key === 'OPTION_DOWN') {
1575-
newIndex = this._selectRowAtIndex(this.state.last);
1576-
this._handleSelectionChange(prevIndex, newIndex);
1577-
} else if (key === 'PAGE_UP') {
1578-
const maxY =
1579-
event.nativeEvent.contentSize.height -
1580-
event.nativeEvent.layoutMeasurement.height;
1581-
const newOffset = Math.min(
1582-
maxY,
1583-
nativeEvent.contentOffset.y + -nativeEvent.layoutMeasurement.height,
1584-
);
1585-
this.scrollToOffset({animated: true, offset: newOffset});
1586-
} else if (key === 'PAGE_DOWN') {
1587-
const maxY =
1588-
event.nativeEvent.contentSize.height -
1589-
event.nativeEvent.layoutMeasurement.height;
1590-
const newOffset = Math.min(
1591-
maxY,
1592-
nativeEvent.contentOffset.y + nativeEvent.layoutMeasurement.height,
1593-
);
1594-
this.scrollToOffset({animated: true, offset: newOffset});
1595-
} else if (key === 'HOME') {
1596-
this.scrollToOffset({animated: true, offset: 0});
1597-
} else if (key === 'END') {
1598-
this.scrollToEnd({animated: true});
15991594
}
1595+
} else if (key === 'Home') {
1596+
this.scrollToOffset({animated: true, offset: 0});
1597+
} else if (key === 'End') {
1598+
this.scrollToEnd({animated: true});
16001599
}
16011600
}
16021601
};

Libraries/Lists/VirtualizedSectionList.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const Platform = require('../Utilities/Platform'); // TODO(macOS GH#774)
1212
import invariant from 'invariant';
1313
import type {ViewToken} from './ViewabilityHelper';
1414
import type {SelectedRowIndexPathType} from './VirtualizedList'; // TODO(macOS GH#774)
15-
import type {ScrollEvent} from '../Types/CoreEventTypes'; // TODO(macOS GH#774)
15+
import type {KeyEvent} from '../Types/CoreEventTypes'; // TODO(macOS GH#774)
1616
import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils';
1717
import {View, VirtualizedList} from 'react-native';
1818
import * as React from 'react';
@@ -311,16 +311,20 @@ class VirtualizedSectionList<
311311
}
312312
};
313313

314-
_handleKeyDown = (e: ScrollEvent) => {
314+
_handleKeyDown = (e: KeyEvent) => {
315315
if (Platform.OS === 'macos') {
316+
if (e.defaultPrevented) {
317+
return;
318+
}
319+
316320
const event = e.nativeEvent;
317321
const key = event.key;
318322
let prevIndexPath = this.state.selectedRowIndexPath;
319323
let nextIndexPath = null;
320324
const sectionIndex = this.state.selectedRowIndexPath.sectionIndex;
321325
const rowIndex = this.state.selectedRowIndexPath.rowIndex;
322326

323-
if (key === 'DOWN_ARROW') {
327+
if (key === 'ArrowDown') {
324328
nextIndexPath = this._selectRowBelowIndexPath(prevIndexPath);
325329
this._ensureItemAtIndexPathIsVisible(nextIndexPath);
326330

@@ -332,7 +336,7 @@ class VirtualizedSectionList<
332336
item: item,
333337
});
334338
}
335-
} else if (key === 'UP_ARROW') {
339+
} else if (key === 'ArrowUp') {
336340
nextIndexPath = this._selectRowAboveIndexPath(prevIndexPath);
337341
this._ensureItemAtIndexPathIsVisible(nextIndexPath);
338342

@@ -344,7 +348,7 @@ class VirtualizedSectionList<
344348
item: item,
345349
});
346350
}
347-
} else if (key === 'ENTER') {
351+
} else if (key === 'Enter') {
348352
if (this.props.onSelectionEntered) {
349353
const item = this.props.sections[sectionIndex].data[rowIndex];
350354
this.props.onSelectionEntered(item);

Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ exports[`FlatList renders all the bells and whistles 1`] = `
3838
onScroll={[Function]}
3939
onScrollBeginDrag={[Function]}
4040
onScrollEndDrag={[Function]}
41-
onScrollKeyDown={null}
4241
refreshControl={
4342
<RefreshControlMock
4443
onRefresh={[MockFunction]}
@@ -135,7 +134,6 @@ exports[`FlatList renders empty list 1`] = `
135134
onScroll={[Function]}
136135
onScrollBeginDrag={[Function]}
137136
onScrollEndDrag={[Function]}
138-
onScrollKeyDown={null}
139137
removeClippedSubviews={false}
140138
renderItem={[Function]}
141139
scrollEventThrottle={50}
@@ -159,7 +157,6 @@ exports[`FlatList renders null list 1`] = `
159157
onScroll={[Function]}
160158
onScrollBeginDrag={[Function]}
161159
onScrollEndDrag={[Function]}
162-
onScrollKeyDown={null}
163160
removeClippedSubviews={false}
164161
renderItem={[Function]}
165162
scrollEventThrottle={50}
@@ -196,7 +193,6 @@ exports[`FlatList renders simple list (multiple columns) 1`] = `
196193
onScroll={[Function]}
197194
onScrollBeginDrag={[Function]}
198195
onScrollEndDrag={[Function]}
199-
onScrollKeyDown={null}
200196
removeClippedSubviews={false}
201197
renderItem={[Function]}
202198
scrollEventThrottle={50}
@@ -269,7 +265,6 @@ exports[`FlatList renders simple list 1`] = `
269265
onScroll={[Function]}
270266
onScrollBeginDrag={[Function]}
271267
onScrollEndDrag={[Function]}
272-
onScrollKeyDown={null}
273268
removeClippedSubviews={false}
274269
renderItem={[Function]}
275270
scrollEventThrottle={50}
@@ -332,7 +327,6 @@ exports[`FlatList renders simple list using ListItemComponent (multiple columns)
332327
onScroll={[Function]}
333328
onScrollBeginDrag={[Function]}
334329
onScrollEndDrag={[Function]}
335-
onScrollKeyDown={null}
336330
removeClippedSubviews={false}
337331
scrollEventThrottle={50}
338332
stickyHeaderIndices={Array []}
@@ -405,7 +399,6 @@ exports[`FlatList renders simple list using ListItemComponent 1`] = `
405399
onScroll={[Function]}
406400
onScrollBeginDrag={[Function]}
407401
onScrollEndDrag={[Function]}
408-
onScrollKeyDown={null}
409402
removeClippedSubviews={false}
410403
scrollEventThrottle={50}
411404
stickyHeaderIndices={Array []}

0 commit comments

Comments
 (0)