@react-native-tvos/virtualized-lists 0.78.0-0rc4 → 0.79.0-0rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Lists/FillRateHelper.js +1 -1
- package/Lists/ListMetricsAggregator.js +7 -4
- package/Lists/StateSafePureComponent.js +2 -2
- package/Lists/ViewabilityHelper.js +6 -3
- package/Lists/VirtualizedList.js +57 -46
- package/Lists/VirtualizedListCellRenderer.js +16 -12
- package/Lists/VirtualizedListProps.js +18 -41
- package/Lists/VirtualizedSectionList.js +16 -16
- package/Utilities/clamp.js +1 -1
- package/Utilities/infoLog.js +1 -1
- package/index.js +9 -8
- package/package.json +1 -1
- package/Interaction/Batchinator.js +0 -85
package/Lists/FillRateHelper.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {
|
|
12
|
-
import type {
|
|
11
|
+
import type {VirtualizedListProps} from './VirtualizedListProps';
|
|
12
|
+
import type {LayoutRectangle} from 'react-native/Libraries/Types/CoreEventTypes';
|
|
13
13
|
|
|
14
14
|
import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils';
|
|
15
15
|
import invariant from 'invariant';
|
|
@@ -82,7 +82,7 @@ export default class ListMetricsAggregator {
|
|
|
82
82
|
cellIndex: number,
|
|
83
83
|
cellKey: string,
|
|
84
84
|
orientation: ListOrientation,
|
|
85
|
-
layout:
|
|
85
|
+
layout: LayoutRectangle,
|
|
86
86
|
}): boolean {
|
|
87
87
|
this._invalidateIfOrientationChanged(orientation);
|
|
88
88
|
|
|
@@ -264,7 +264,10 @@ export default class ListMetricsAggregator {
|
|
|
264
264
|
* Finds the flow-relative offset (e.g. starting from the left in LTR, but
|
|
265
265
|
* right in RTL) from a layout box.
|
|
266
266
|
*/
|
|
267
|
-
flowRelativeOffset(
|
|
267
|
+
flowRelativeOffset(
|
|
268
|
+
layout: LayoutRectangle,
|
|
269
|
+
referenceContentLength?: ?number,
|
|
270
|
+
): number {
|
|
268
271
|
const {horizontal, rtl} = this._orientation;
|
|
269
272
|
|
|
270
273
|
if (horizontal && rtl) {
|
|
@@ -31,8 +31,8 @@ export default class StateSafePureComponent<
|
|
|
31
31
|
this._installSetStateHooks();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
setState(
|
|
35
|
-
partialState: ?(
|
|
34
|
+
setState<K: $Keys<State>>(
|
|
35
|
+
partialState: ?(Pick<State, K> | ((State, Props) => ?Pick<State, K>)),
|
|
36
36
|
callback?: () => mixed,
|
|
37
37
|
): void {
|
|
38
38
|
if (typeof partialState === 'function') {
|
|
@@ -35,7 +35,10 @@ export type ViewabilityConfigCallbackPair = {
|
|
|
35
35
|
...
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export type
|
|
38
|
+
export type ViewabilityConfigCallbackPairs =
|
|
39
|
+
Array<ViewabilityConfigCallbackPair>;
|
|
40
|
+
|
|
41
|
+
export type ViewabilityConfig = $ReadOnly<{
|
|
39
42
|
/**
|
|
40
43
|
* Minimum amount of time (in milliseconds) that an item must be physically viewable before the
|
|
41
44
|
* viewability callback will be fired. A high number means that scrolling through content without
|
|
@@ -62,7 +65,7 @@ export type ViewabilityConfig = $ReadOnly<{|
|
|
|
62
65
|
* render.
|
|
63
66
|
*/
|
|
64
67
|
waitForInteraction?: boolean,
|
|
65
|
-
|
|
68
|
+
}>;
|
|
66
69
|
|
|
67
70
|
/**
|
|
68
71
|
* A Utility class for calculating viewable items based on current metrics like scroll position and
|
|
@@ -346,4 +349,4 @@ function _isEntirelyVisible(
|
|
|
346
349
|
return top >= 0 && bottom <= viewportHeight && bottom > top;
|
|
347
350
|
}
|
|
348
351
|
|
|
349
|
-
|
|
352
|
+
export default ViewabilityHelper;
|
package/Lists/VirtualizedList.js
CHANGED
|
@@ -12,19 +12,18 @@ import type {CellMetricProps, ListOrientation} from './ListMetricsAggregator';
|
|
|
12
12
|
import type {ViewToken} from './ViewabilityHelper';
|
|
13
13
|
import type {
|
|
14
14
|
Item,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
RenderItemType,
|
|
15
|
+
ListRenderItem,
|
|
16
|
+
ListRenderItemInfo,
|
|
18
17
|
Separators,
|
|
18
|
+
VirtualizedListProps,
|
|
19
19
|
} from './VirtualizedListProps';
|
|
20
20
|
import type {ScrollResponderType} from 'react-native/Libraries/Components/ScrollView/ScrollView';
|
|
21
21
|
import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
|
22
22
|
import type {
|
|
23
|
-
|
|
23
|
+
LayoutChangeEvent,
|
|
24
24
|
ScrollEvent,
|
|
25
25
|
} from 'react-native/Libraries/Types/CoreEventTypes';
|
|
26
26
|
|
|
27
|
-
import Batchinator from '../Interaction/Batchinator';
|
|
28
27
|
import clamp from '../Utilities/clamp';
|
|
29
28
|
import infoLog from '../Utilities/infoLog';
|
|
30
29
|
import {CellRenderMask} from './CellRenderMask';
|
|
@@ -65,7 +64,7 @@ import {
|
|
|
65
64
|
findNodeHandle,
|
|
66
65
|
} from 'react-native';
|
|
67
66
|
|
|
68
|
-
export type {
|
|
67
|
+
export type {ListRenderItemInfo, ListRenderItem, Separators};
|
|
69
68
|
|
|
70
69
|
const ON_EDGE_REACHED_EPSILON = 0.001;
|
|
71
70
|
|
|
@@ -124,7 +123,10 @@ function getScrollingThreshold(threshold: number, visibleLength: number) {
|
|
|
124
123
|
* - As an effort to remove defaultProps, use helper functions when referencing certain props
|
|
125
124
|
*
|
|
126
125
|
*/
|
|
127
|
-
class VirtualizedList extends StateSafePureComponent<
|
|
126
|
+
class VirtualizedList extends StateSafePureComponent<
|
|
127
|
+
VirtualizedListProps,
|
|
128
|
+
State,
|
|
129
|
+
> {
|
|
128
130
|
static contextType: typeof VirtualizedListContext = VirtualizedListContext;
|
|
129
131
|
|
|
130
132
|
// scrollToEnd may be janky without getItemLayout prop
|
|
@@ -261,6 +263,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
261
263
|
return;
|
|
262
264
|
}
|
|
263
265
|
|
|
266
|
+
// $FlowFixMe[incompatible-call]
|
|
264
267
|
scrollRef.scrollTo({
|
|
265
268
|
animated,
|
|
266
269
|
...this._scrollToParamsFromOffset(offset),
|
|
@@ -317,10 +320,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
317
320
|
}
|
|
318
321
|
}
|
|
319
322
|
|
|
320
|
-
getScrollRef():
|
|
321
|
-
|
|
322
|
-
| ?React.ElementRef<typeof View> {
|
|
323
|
+
getScrollRef(): ?React.ElementRef<typeof ScrollView> {
|
|
324
|
+
// $FlowFixMe[prop-missing]
|
|
323
325
|
if (this._scrollRef && this._scrollRef.getScrollRef) {
|
|
326
|
+
// $FlowFixMe[not-a-function]
|
|
324
327
|
return this._scrollRef.getScrollRef();
|
|
325
328
|
} else {
|
|
326
329
|
return this._scrollRef;
|
|
@@ -371,15 +374,11 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
371
374
|
|
|
372
375
|
state: State;
|
|
373
376
|
|
|
374
|
-
constructor(props:
|
|
377
|
+
constructor(props: VirtualizedListProps) {
|
|
375
378
|
super(props);
|
|
376
379
|
this._checkProps(props);
|
|
377
380
|
|
|
378
381
|
this._fillRateHelper = new FillRateHelper(this._listMetrics);
|
|
379
|
-
this._updateCellsToRenderBatcher = new Batchinator(
|
|
380
|
-
this._updateCellsToRender,
|
|
381
|
-
this.props.updateCellsBatchingPeriod ?? 50,
|
|
382
|
-
);
|
|
383
382
|
|
|
384
383
|
if (this.props.viewabilityConfigCallbackPairs) {
|
|
385
384
|
this._viewabilityTuples = this.props.viewabilityConfigCallbackPairs.map(
|
|
@@ -421,7 +420,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
421
420
|
};
|
|
422
421
|
}
|
|
423
422
|
|
|
424
|
-
_checkProps(props:
|
|
423
|
+
_checkProps(props: VirtualizedListProps) {
|
|
425
424
|
const {onScroll, windowSize, getItemCount, data, initialScrollIndex} =
|
|
426
425
|
props;
|
|
427
426
|
|
|
@@ -470,7 +469,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
470
469
|
}
|
|
471
470
|
|
|
472
471
|
static _findItemIndexWithKey(
|
|
473
|
-
props:
|
|
472
|
+
props: VirtualizedListProps,
|
|
474
473
|
key: string,
|
|
475
474
|
hint: ?number,
|
|
476
475
|
): ?number {
|
|
@@ -492,9 +491,9 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
492
491
|
|
|
493
492
|
static _getItemKey(
|
|
494
493
|
props: {
|
|
495
|
-
data:
|
|
496
|
-
getItem:
|
|
497
|
-
keyExtractor:
|
|
494
|
+
data: VirtualizedListProps['data'],
|
|
495
|
+
getItem: VirtualizedListProps['getItem'],
|
|
496
|
+
keyExtractor: VirtualizedListProps['keyExtractor'],
|
|
498
497
|
...
|
|
499
498
|
},
|
|
500
499
|
index: number,
|
|
@@ -504,7 +503,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
504
503
|
}
|
|
505
504
|
|
|
506
505
|
static _createRenderMask(
|
|
507
|
-
props:
|
|
506
|
+
props: VirtualizedListProps,
|
|
508
507
|
cellsAroundViewport: {first: number, last: number},
|
|
509
508
|
additionalRegions?: ?$ReadOnlyArray<{first: number, last: number}>,
|
|
510
509
|
): CellRenderMask {
|
|
@@ -547,7 +546,10 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
547
546
|
return renderMask;
|
|
548
547
|
}
|
|
549
548
|
|
|
550
|
-
static _initialRenderRegion(props:
|
|
549
|
+
static _initialRenderRegion(props: VirtualizedListProps): {
|
|
550
|
+
first: number,
|
|
551
|
+
last: number,
|
|
552
|
+
} {
|
|
551
553
|
const itemCount = props.getItemCount(props.data);
|
|
552
554
|
|
|
553
555
|
const firstCellIndex = Math.max(
|
|
@@ -568,7 +570,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
568
570
|
}
|
|
569
571
|
|
|
570
572
|
static _ensureClosestStickyHeader(
|
|
571
|
-
props:
|
|
573
|
+
props: VirtualizedListProps,
|
|
572
574
|
stickyIndicesSet: Set<number>,
|
|
573
575
|
renderMask: CellRenderMask,
|
|
574
576
|
cellIdx: number,
|
|
@@ -584,7 +586,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
584
586
|
}
|
|
585
587
|
|
|
586
588
|
_adjustCellsAroundViewport(
|
|
587
|
-
props:
|
|
589
|
+
props: VirtualizedListProps,
|
|
588
590
|
cellsAroundViewport: {first: number, last: number},
|
|
589
591
|
pendingScrollUpdateCount: number,
|
|
590
592
|
): {first: number, last: number} {
|
|
@@ -688,14 +690,17 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
688
690
|
if (this._isNestedWithSameOrientation()) {
|
|
689
691
|
this.context.unregisterAsNestedChild({ref: this});
|
|
690
692
|
}
|
|
691
|
-
this.
|
|
693
|
+
clearTimeout(this._updateCellsToRenderTimeoutID);
|
|
692
694
|
this._viewabilityTuples.forEach(tuple => {
|
|
693
695
|
tuple.viewabilityHelper.dispose();
|
|
694
696
|
});
|
|
695
697
|
this._fillRateHelper.deactivateAndFlush();
|
|
696
698
|
}
|
|
697
699
|
|
|
698
|
-
static getDerivedStateFromProps(
|
|
700
|
+
static getDerivedStateFromProps(
|
|
701
|
+
newProps: VirtualizedListProps,
|
|
702
|
+
prevState: State,
|
|
703
|
+
): State {
|
|
699
704
|
// first and last could be stale (e.g. if a new, shorter items props is passed in), so we make
|
|
700
705
|
// sure we're rendering a reasonable range here.
|
|
701
706
|
const itemCount = newProps.getItemCount(newProps.data);
|
|
@@ -827,7 +832,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
827
832
|
|
|
828
833
|
static _constrainToItemCount(
|
|
829
834
|
cells: {first: number, last: number},
|
|
830
|
-
props:
|
|
835
|
+
props: VirtualizedListProps,
|
|
831
836
|
): {first: number, last: number} {
|
|
832
837
|
const itemCount = props.getItemCount(props.data);
|
|
833
838
|
const lastPossibleCellIndex = itemCount - 1;
|
|
@@ -952,7 +957,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
952
957
|
cellKey={this._getCellKey() + '-empty'}
|
|
953
958
|
key="$empty">
|
|
954
959
|
{React.cloneElement(element, {
|
|
955
|
-
onLayout: (event:
|
|
960
|
+
onLayout: (event: LayoutChangeEvent) => {
|
|
956
961
|
this._onLayoutEmpty(event);
|
|
957
962
|
// $FlowFixMe[prop-missing] React.Element internal inspection
|
|
958
963
|
if (element.props.onLayout) {
|
|
@@ -1140,7 +1145,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1140
1145
|
(
|
|
1141
1146
|
this.props.renderScrollComponent ||
|
|
1142
1147
|
this._defaultRenderScrollComponent
|
|
1143
|
-
)(scrollProps)
|
|
1148
|
+
)(scrollProps) as ExactReactElement_DEPRECATED<any>,
|
|
1144
1149
|
{
|
|
1145
1150
|
ref: this._captureScrollRef,
|
|
1146
1151
|
},
|
|
@@ -1152,7 +1157,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1152
1157
|
(
|
|
1153
1158
|
this.props.renderScrollComponent ||
|
|
1154
1159
|
this._defaultRenderScrollComponent
|
|
1155
|
-
)(scrollProps)
|
|
1160
|
+
)(scrollProps) as ExactReactElement_DEPRECATED<any>,
|
|
1156
1161
|
{
|
|
1157
1162
|
ref: this._captureScrollRef,
|
|
1158
1163
|
},
|
|
@@ -1198,7 +1203,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1198
1203
|
}
|
|
1199
1204
|
}
|
|
1200
1205
|
|
|
1201
|
-
componentDidUpdate(prevProps:
|
|
1206
|
+
componentDidUpdate(prevProps: VirtualizedListProps) {
|
|
1202
1207
|
const {data, extraData, getItemLayout} = this.props;
|
|
1203
1208
|
if (data !== prevProps.data || extraData !== prevProps.extraData) {
|
|
1204
1209
|
// clear the viewableIndices cache to also trigger
|
|
@@ -1265,15 +1270,13 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1265
1270
|
visibleLength: 0,
|
|
1266
1271
|
zoomScale: 1,
|
|
1267
1272
|
};
|
|
1268
|
-
_scrollRef: ?React.ElementRef<
|
|
1273
|
+
_scrollRef: ?React.ElementRef<typeof ScrollView> = null;
|
|
1269
1274
|
_sentStartForContentLength = 0;
|
|
1270
1275
|
_sentEndForContentLength = 0;
|
|
1271
|
-
|
|
1276
|
+
_updateCellsToRenderTimeoutID: ?TimeoutID = null;
|
|
1272
1277
|
_viewabilityTuples: Array<ViewabilityHelperCallbackTuple> = [];
|
|
1273
1278
|
|
|
1274
|
-
|
|
1275
|
-
* LTI update could not be added via codemod */
|
|
1276
|
-
_captureScrollRef = ref => {
|
|
1279
|
+
_captureScrollRef = (ref: ?React.ElementRef<typeof ScrollView>) => {
|
|
1277
1280
|
this._scrollRef = ref;
|
|
1278
1281
|
};
|
|
1279
1282
|
|
|
@@ -1328,7 +1331,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1328
1331
|
};
|
|
1329
1332
|
|
|
1330
1333
|
_onCellLayout = (
|
|
1331
|
-
e:
|
|
1334
|
+
e: LayoutChangeEvent,
|
|
1332
1335
|
cellKey: string,
|
|
1333
1336
|
cellIndex: number,
|
|
1334
1337
|
): void => {
|
|
@@ -1415,7 +1418,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1415
1418
|
}
|
|
1416
1419
|
}
|
|
1417
1420
|
|
|
1418
|
-
_onLayout = (e:
|
|
1421
|
+
_onLayout = (e: LayoutChangeEvent) => {
|
|
1419
1422
|
if (this._isNestedWithSameOrientation()) {
|
|
1420
1423
|
// Need to adjust our scroll metrics to be relative to our containing
|
|
1421
1424
|
// VirtualizedList before we can make claims about list item viewability
|
|
@@ -1430,7 +1433,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1430
1433
|
this._maybeCallOnEdgeReached();
|
|
1431
1434
|
};
|
|
1432
1435
|
|
|
1433
|
-
_onLayoutEmpty = (e:
|
|
1436
|
+
_onLayoutEmpty = (e: LayoutChangeEvent) => {
|
|
1434
1437
|
this.props.onLayout && this.props.onLayout(e);
|
|
1435
1438
|
};
|
|
1436
1439
|
|
|
@@ -1438,12 +1441,12 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1438
1441
|
return this._getCellKey() + '-footer';
|
|
1439
1442
|
}
|
|
1440
1443
|
|
|
1441
|
-
_onLayoutFooter = (e:
|
|
1444
|
+
_onLayoutFooter = (e: LayoutChangeEvent) => {
|
|
1442
1445
|
this._triggerRemeasureForChildListsInCell(this._getFooterCellKey());
|
|
1443
1446
|
this._footerLength = this._selectLength(e.nativeEvent.layout);
|
|
1444
1447
|
};
|
|
1445
1448
|
|
|
1446
|
-
_onLayoutHeader = (e:
|
|
1449
|
+
_onLayoutHeader = (e: LayoutChangeEvent) => {
|
|
1447
1450
|
this._headerLength = this._selectLength(e.nativeEvent.layout);
|
|
1448
1451
|
};
|
|
1449
1452
|
|
|
@@ -1756,7 +1759,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1756
1759
|
zoomScale,
|
|
1757
1760
|
};
|
|
1758
1761
|
if (this.state.pendingScrollUpdateCount > 0) {
|
|
1759
|
-
this.setState(state => ({
|
|
1762
|
+
this.setState<'pendingScrollUpdateCount'>(state => ({
|
|
1760
1763
|
pendingScrollUpdateCount: state.pendingScrollUpdateCount - 1,
|
|
1761
1764
|
}));
|
|
1762
1765
|
}
|
|
@@ -1803,11 +1806,19 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1803
1806
|
this._hiPriInProgress = true;
|
|
1804
1807
|
// Don't worry about interactions when scrolling quickly; focus on filling content as fast
|
|
1805
1808
|
// as possible.
|
|
1806
|
-
this.
|
|
1809
|
+
if (this._updateCellsToRenderTimeoutID != null) {
|
|
1810
|
+
clearTimeout(this._updateCellsToRenderTimeoutID);
|
|
1811
|
+
this._updateCellsToRenderTimeoutID = null;
|
|
1812
|
+
}
|
|
1807
1813
|
this._updateCellsToRender();
|
|
1808
1814
|
return;
|
|
1809
1815
|
} else {
|
|
1810
|
-
this.
|
|
1816
|
+
if (this._updateCellsToRenderTimeoutID == null) {
|
|
1817
|
+
this._updateCellsToRenderTimeoutID = setTimeout(() => {
|
|
1818
|
+
this._updateCellsToRenderTimeoutID = null;
|
|
1819
|
+
this._updateCellsToRender();
|
|
1820
|
+
}, this.props.updateCellsBatchingPeriod ?? 50);
|
|
1821
|
+
}
|
|
1811
1822
|
}
|
|
1812
1823
|
}
|
|
1813
1824
|
|
|
@@ -1908,7 +1919,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
|
|
|
1908
1919
|
_updateCellsToRender = () => {
|
|
1909
1920
|
this._updateViewableItems(this.props, this.state.cellsAroundViewport);
|
|
1910
1921
|
|
|
1911
|
-
this.setState((state, props
|
|
1922
|
+
this.setState<'cellsAroundViewport' | 'renderMask'>((state, props) => {
|
|
1912
1923
|
const cellsAroundViewport = this._adjustCellsAroundViewport(
|
|
1913
1924
|
props,
|
|
1914
1925
|
state.cellsAroundViewport,
|
|
@@ -2082,4 +2093,4 @@ const styles = StyleSheet.create({
|
|
|
2082
2093
|
},
|
|
2083
2094
|
});
|
|
2084
2095
|
|
|
2085
|
-
|
|
2096
|
+
export default VirtualizedList;
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {CellRendererProps,
|
|
11
|
+
import type {CellRendererProps, ListRenderItem} from './VirtualizedListProps';
|
|
12
12
|
import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
|
13
13
|
import type {
|
|
14
14
|
FocusEvent,
|
|
15
|
-
|
|
15
|
+
LayoutChangeEvent,
|
|
16
16
|
} from 'react-native/Libraries/Types/CoreEventTypes';
|
|
17
17
|
|
|
18
18
|
import {VirtualizedListCellContextProvider} from './VirtualizedListContext.js';
|
|
@@ -31,7 +31,11 @@ export type Props<ItemT> = {
|
|
|
31
31
|
index: number,
|
|
32
32
|
inversionStyle: ViewStyleProp,
|
|
33
33
|
item: ItemT,
|
|
34
|
-
onCellLayout?: (
|
|
34
|
+
onCellLayout?: (
|
|
35
|
+
event: LayoutChangeEvent,
|
|
36
|
+
cellKey: string,
|
|
37
|
+
index: number,
|
|
38
|
+
) => void,
|
|
35
39
|
onCellFocusCapture?: (cellKey: string) => void,
|
|
36
40
|
onUnmount: (cellKey: string) => void,
|
|
37
41
|
onUpdateSeparators: (
|
|
@@ -39,14 +43,14 @@ export type Props<ItemT> = {
|
|
|
39
43
|
props: Partial<SeparatorProps<ItemT>>,
|
|
40
44
|
) => void,
|
|
41
45
|
prevCellKey: ?string,
|
|
42
|
-
renderItem?: ?
|
|
46
|
+
renderItem?: ?ListRenderItem<ItemT>,
|
|
43
47
|
...
|
|
44
48
|
};
|
|
45
49
|
|
|
46
|
-
type SeparatorProps<ItemT> = $ReadOnly<{
|
|
50
|
+
type SeparatorProps<ItemT> = $ReadOnly<{
|
|
47
51
|
highlighted: boolean,
|
|
48
52
|
leadingItem: ?ItemT,
|
|
49
|
-
|
|
53
|
+
}>;
|
|
50
54
|
|
|
51
55
|
type State<ItemT> = {
|
|
52
56
|
separatorProps: SeparatorProps<ItemT>,
|
|
@@ -64,10 +68,10 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
|
|
|
64
68
|
},
|
|
65
69
|
};
|
|
66
70
|
|
|
67
|
-
static getDerivedStateFromProps(
|
|
68
|
-
props: Props<
|
|
69
|
-
prevState: State<
|
|
70
|
-
): ?State<
|
|
71
|
+
static getDerivedStateFromProps<StaticItemT>(
|
|
72
|
+
props: Props<StaticItemT>,
|
|
73
|
+
prevState: State<StaticItemT>,
|
|
74
|
+
): ?State<StaticItemT> {
|
|
71
75
|
if (props.item !== prevState.separatorProps.leadingItem) {
|
|
72
76
|
return {
|
|
73
77
|
separatorProps: {
|
|
@@ -117,7 +121,7 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
|
|
|
117
121
|
this.props.onUnmount(this.props.cellKey);
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
_onLayout = (nativeEvent:
|
|
124
|
+
_onLayout = (nativeEvent: LayoutChangeEvent): void => {
|
|
121
125
|
this.props.onCellLayout?.(
|
|
122
126
|
nativeEvent,
|
|
123
127
|
this.props.cellKey,
|
|
@@ -130,7 +134,7 @@ export default class CellRenderer<ItemT> extends React.PureComponent<
|
|
|
130
134
|
};
|
|
131
135
|
|
|
132
136
|
_renderElement(
|
|
133
|
-
renderItem: ?
|
|
137
|
+
renderItem: ?ListRenderItem<ItemT>,
|
|
134
138
|
ListItemComponent: any,
|
|
135
139
|
item: ItemT,
|
|
136
140
|
index: number,
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
|
17
17
|
import type {
|
|
18
18
|
FocusEvent,
|
|
19
|
-
|
|
19
|
+
LayoutChangeEvent,
|
|
20
20
|
} from 'react-native/Libraries/Types/CoreEventTypes';
|
|
21
21
|
|
|
22
22
|
import * as React from 'react';
|
|
@@ -31,7 +31,7 @@ export type Separators = {
|
|
|
31
31
|
...
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
export type
|
|
34
|
+
export type ListRenderItemInfo<ItemT> = {
|
|
35
35
|
item: ItemT,
|
|
36
36
|
index: number,
|
|
37
37
|
separators: Separators,
|
|
@@ -44,15 +44,15 @@ export type CellRendererProps<ItemT> = $ReadOnly<{
|
|
|
44
44
|
index: number,
|
|
45
45
|
item: ItemT,
|
|
46
46
|
onFocusCapture?: (event: FocusEvent) => void,
|
|
47
|
-
onLayout?: (event:
|
|
47
|
+
onLayout?: (event: LayoutChangeEvent) => void,
|
|
48
48
|
style: ViewStyleProp,
|
|
49
49
|
}>;
|
|
50
50
|
|
|
51
|
-
export type
|
|
52
|
-
info:
|
|
51
|
+
export type ListRenderItem<ItemT> = (
|
|
52
|
+
info: ListRenderItemInfo<ItemT>,
|
|
53
53
|
) => React.Node;
|
|
54
54
|
|
|
55
|
-
type RequiredProps = {
|
|
55
|
+
type RequiredProps = {
|
|
56
56
|
/**
|
|
57
57
|
* The default accessor functions assume this is an Array<{key: string} | {id: string}> but you can override
|
|
58
58
|
* getItem, getItemCount, and keyExtractor to handle any type of index-based data.
|
|
@@ -66,9 +66,9 @@ type RequiredProps = {|
|
|
|
66
66
|
* Determines how many items are in the data blob.
|
|
67
67
|
*/
|
|
68
68
|
getItemCount: (data: any) => number,
|
|
69
|
-
|
|
70
|
-
type OptionalProps = {
|
|
71
|
-
renderItem?: ?
|
|
69
|
+
};
|
|
70
|
+
type OptionalProps = {
|
|
71
|
+
renderItem?: ?ListRenderItem<Item>,
|
|
72
72
|
/**
|
|
73
73
|
* `debug` will turn on extra logging and visual overlays to aid with debugging both usage and
|
|
74
74
|
* implementation, but with a significant perf hit.
|
|
@@ -155,26 +155,17 @@ type OptionalProps = {|
|
|
|
155
155
|
* `highlight` and `unhighlight` (which set the `highlighted: boolean` prop) are insufficient for
|
|
156
156
|
* your use-case.
|
|
157
157
|
*/
|
|
158
|
-
ListItemComponent?: ?(
|
|
159
|
-
| React.ComponentType<any>
|
|
160
|
-
| ExactReactElement_DEPRECATED<any>
|
|
161
|
-
),
|
|
158
|
+
ListItemComponent?: ?(React.ComponentType<any> | React.MixedElement),
|
|
162
159
|
/**
|
|
163
160
|
* Rendered when the list is empty. Can be a React Component Class, a render function, or
|
|
164
161
|
* a rendered element.
|
|
165
162
|
*/
|
|
166
|
-
ListEmptyComponent?: ?(
|
|
167
|
-
| React.ComponentType<any>
|
|
168
|
-
| ExactReactElement_DEPRECATED<any>
|
|
169
|
-
),
|
|
163
|
+
ListEmptyComponent?: ?(React.ComponentType<any> | React.MixedElement),
|
|
170
164
|
/**
|
|
171
165
|
* Rendered at the bottom of all the items. Can be a React Component Class, a render function, or
|
|
172
166
|
* a rendered element.
|
|
173
167
|
*/
|
|
174
|
-
ListFooterComponent?: ?(
|
|
175
|
-
| React.ComponentType<any>
|
|
176
|
-
| ExactReactElement_DEPRECATED<any>
|
|
177
|
-
),
|
|
168
|
+
ListFooterComponent?: ?(React.ComponentType<any> | React.MixedElement),
|
|
178
169
|
/**
|
|
179
170
|
* Styling for internal View for ListFooterComponent
|
|
180
171
|
*/
|
|
@@ -183,10 +174,7 @@ type OptionalProps = {|
|
|
|
183
174
|
* Rendered at the top of all the items. Can be a React Component Class, a render function, or
|
|
184
175
|
* a rendered element.
|
|
185
176
|
*/
|
|
186
|
-
ListHeaderComponent?: ?(
|
|
187
|
-
| React.ComponentType<any>
|
|
188
|
-
| ExactReactElement_DEPRECATED<any>
|
|
189
|
-
),
|
|
177
|
+
ListHeaderComponent?: ?(React.ComponentType<any> | React.MixedElement),
|
|
190
178
|
/**
|
|
191
179
|
* Styling for internal View for ListHeaderComponent
|
|
192
180
|
*/
|
|
@@ -256,7 +244,7 @@ type OptionalProps = {|
|
|
|
256
244
|
* <RefreshControl> component built internally. The onRefresh and refreshing
|
|
257
245
|
* props are also ignored. Only works for vertical VirtualizedList.
|
|
258
246
|
*/
|
|
259
|
-
refreshControl?: ?
|
|
247
|
+
refreshControl?: ?React.MixedElement,
|
|
260
248
|
/**
|
|
261
249
|
* Set this true while waiting for new data from a refresh.
|
|
262
250
|
*/
|
|
@@ -270,7 +258,7 @@ type OptionalProps = {|
|
|
|
270
258
|
/**
|
|
271
259
|
* Render a custom scroll component, e.g. with a differently styled `RefreshControl`.
|
|
272
260
|
*/
|
|
273
|
-
renderScrollComponent?: (props: Object) =>
|
|
261
|
+
renderScrollComponent?: (props: Object) => React.MixedElement,
|
|
274
262
|
/**
|
|
275
263
|
* Amount of time between low-pri item render batches, e.g. for rendering items quite a ways off
|
|
276
264
|
* screen. Similar fill rate/responsiveness tradeoff as `maxToRenderPerBatch`.
|
|
@@ -293,24 +281,13 @@ type OptionalProps = {|
|
|
|
293
281
|
* chance that fast scrolling may reveal momentary blank areas of unrendered content.
|
|
294
282
|
*/
|
|
295
283
|
windowSize?: ?number,
|
|
296
|
-
|
|
297
|
-
* The legacy implementation is no longer supported.
|
|
298
|
-
*/
|
|
299
|
-
legacyImplementation?: empty,
|
|
300
|
-
/**
|
|
301
|
-
* Defines regions within the list that are exempt from virtualization,
|
|
302
|
-
* ensuring they remain rendered at all times. Useful for cases where
|
|
303
|
-
* users can't afford blank areas in certain parts of the list.
|
|
304
|
-
* The specified regions are lazily rendered after the initial render.
|
|
305
|
-
*/
|
|
306
|
-
additionalRenderRegions?: Array<{first: number, last: number}>,
|
|
307
|
-
|};
|
|
284
|
+
};
|
|
308
285
|
|
|
309
|
-
export type
|
|
286
|
+
export type VirtualizedListProps = {
|
|
310
287
|
...React.ElementConfig<ScrollView>,
|
|
311
288
|
...RequiredProps,
|
|
312
289
|
...OptionalProps,
|
|
313
|
-
|
|
290
|
+
};
|
|
314
291
|
|
|
315
292
|
/**
|
|
316
293
|
* Default Props Helper Functions
|
|
@@ -44,11 +44,11 @@ export type SectionBase<SectionItemT> = {
|
|
|
44
44
|
...
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
type RequiredProps<SectionT: SectionBase<any>> = {
|
|
47
|
+
type RequiredProps<SectionT: SectionBase<any>> = {
|
|
48
48
|
sections: $ReadOnlyArray<SectionT>,
|
|
49
|
-
|
|
49
|
+
};
|
|
50
50
|
|
|
51
|
-
type OptionalProps<SectionT: SectionBase<any>> = {
|
|
51
|
+
type OptionalProps<SectionT: SectionBase<any>> = {
|
|
52
52
|
/**
|
|
53
53
|
* Default renderer for every item in every section.
|
|
54
54
|
*/
|
|
@@ -87,11 +87,11 @@ type OptionalProps<SectionT: SectionBase<any>> = {|
|
|
|
87
87
|
*/
|
|
88
88
|
stickySectionHeadersEnabled?: boolean,
|
|
89
89
|
onEndReached?: ?({distanceFromEnd: number, ...}) => void,
|
|
90
|
-
|
|
90
|
+
};
|
|
91
91
|
|
|
92
92
|
type VirtualizedListProps = React.ElementConfig<typeof VirtualizedList>;
|
|
93
93
|
|
|
94
|
-
export type
|
|
94
|
+
export type VirtualizedSectionListProps<SectionT: SectionBase<any>> = {
|
|
95
95
|
...RequiredProps<SectionT>,
|
|
96
96
|
...OptionalProps<SectionT>,
|
|
97
97
|
...$Diff<
|
|
@@ -102,14 +102,14 @@ export type Props<SectionT> = {|
|
|
|
102
102
|
...
|
|
103
103
|
},
|
|
104
104
|
>,
|
|
105
|
-
|
|
106
|
-
export type ScrollToLocationParamsType = {
|
|
105
|
+
};
|
|
106
|
+
export type ScrollToLocationParamsType = {
|
|
107
107
|
animated?: ?boolean,
|
|
108
108
|
itemIndex: number,
|
|
109
109
|
sectionIndex: number,
|
|
110
110
|
viewOffset?: number,
|
|
111
111
|
viewPosition?: number,
|
|
112
|
-
|
|
112
|
+
};
|
|
113
113
|
|
|
114
114
|
type State = {childProps: VirtualizedListProps, ...};
|
|
115
115
|
|
|
@@ -120,7 +120,7 @@ type State = {childProps: VirtualizedListProps, ...};
|
|
|
120
120
|
*/
|
|
121
121
|
class VirtualizedSectionList<
|
|
122
122
|
SectionT: SectionBase<any>,
|
|
123
|
-
> extends React.PureComponent<
|
|
123
|
+
> extends React.PureComponent<VirtualizedSectionListProps<SectionT>, State> {
|
|
124
124
|
scrollToLocation(params: ScrollToLocationParamsType) {
|
|
125
125
|
let index = params.itemIndex;
|
|
126
126
|
for (let i = 0; i < params.sectionIndex; i++) {
|
|
@@ -203,7 +203,7 @@ class VirtualizedSectionList<
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
_getItem(
|
|
206
|
-
props:
|
|
206
|
+
props: VirtualizedSectionListProps<SectionT>,
|
|
207
207
|
sections: ?$ReadOnlyArray<Item>,
|
|
208
208
|
index: number,
|
|
209
209
|
): ?Item {
|
|
@@ -453,15 +453,15 @@ class VirtualizedSectionList<
|
|
|
453
453
|
};
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
-
type ItemWithSeparatorCommonProps = $ReadOnly<{
|
|
456
|
+
type ItemWithSeparatorCommonProps = $ReadOnly<{
|
|
457
457
|
leadingItem: ?Item,
|
|
458
458
|
leadingSection: ?Object,
|
|
459
459
|
section: Object,
|
|
460
460
|
trailingItem: ?Item,
|
|
461
461
|
trailingSection: ?Object,
|
|
462
|
-
|
|
462
|
+
}>;
|
|
463
463
|
|
|
464
|
-
type ItemWithSeparatorProps = $ReadOnly<{
|
|
464
|
+
type ItemWithSeparatorProps = $ReadOnly<{
|
|
465
465
|
...ItemWithSeparatorCommonProps,
|
|
466
466
|
LeadingSeparatorComponent: ?React.ComponentType<any>,
|
|
467
467
|
SeparatorComponent: ?React.ComponentType<any>,
|
|
@@ -481,7 +481,7 @@ type ItemWithSeparatorProps = $ReadOnly<{|
|
|
|
481
481
|
updatePropsFor: (prevCellKey: string, value: Object) => void,
|
|
482
482
|
renderItem: Function,
|
|
483
483
|
inverted: boolean,
|
|
484
|
-
|
|
484
|
+
}>;
|
|
485
485
|
|
|
486
486
|
function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node {
|
|
487
487
|
const {
|
|
@@ -598,12 +598,12 @@ function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node {
|
|
|
598
598
|
);
|
|
599
599
|
}
|
|
600
600
|
|
|
601
|
-
|
|
601
|
+
export default VirtualizedSectionList as component(
|
|
602
602
|
ref: React.RefSetter<
|
|
603
603
|
interface {
|
|
604
604
|
getListRef(): ?VirtualizedList,
|
|
605
605
|
scrollToLocation(params: ScrollToLocationParamsType): void,
|
|
606
606
|
},
|
|
607
607
|
>,
|
|
608
|
-
...
|
|
608
|
+
...VirtualizedSectionListProps<SectionBase<any>>
|
|
609
609
|
);
|
package/Utilities/clamp.js
CHANGED
package/Utilities/infoLog.js
CHANGED
package/index.js
CHANGED
|
@@ -22,37 +22,38 @@ export type {
|
|
|
22
22
|
ViewToken,
|
|
23
23
|
ViewabilityConfig,
|
|
24
24
|
ViewabilityConfigCallbackPair,
|
|
25
|
+
ViewabilityConfigCallbackPairs,
|
|
25
26
|
} from './Lists/ViewabilityHelper';
|
|
26
27
|
export type {
|
|
27
28
|
CellRendererProps,
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
ListRenderItemInfo,
|
|
30
|
+
ListRenderItem,
|
|
30
31
|
Separators,
|
|
31
32
|
} from './Lists/VirtualizedListProps';
|
|
32
33
|
export type {
|
|
33
|
-
|
|
34
|
+
VirtualizedSectionListProps,
|
|
34
35
|
ScrollToLocationParamsType,
|
|
35
36
|
SectionBase,
|
|
36
37
|
} from './Lists/VirtualizedSectionList';
|
|
37
38
|
export type {FillRateInfo} from './Lists/FillRateHelper';
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
export default {
|
|
40
41
|
keyExtractor,
|
|
41
42
|
|
|
42
43
|
get VirtualizedList(): VirtualizedList {
|
|
43
|
-
return require('./Lists/VirtualizedList');
|
|
44
|
+
return require('./Lists/VirtualizedList').default;
|
|
44
45
|
},
|
|
45
46
|
get VirtualizedSectionList(): VirtualizedSectionList {
|
|
46
|
-
return require('./Lists/VirtualizedSectionList');
|
|
47
|
+
return require('./Lists/VirtualizedSectionList').default;
|
|
47
48
|
},
|
|
48
49
|
get VirtualizedListContextResetter(): VirtualizedListContextResetter {
|
|
49
50
|
const VirtualizedListContext = require('./Lists/VirtualizedListContext');
|
|
50
51
|
return VirtualizedListContext.VirtualizedListContextResetter;
|
|
51
52
|
},
|
|
52
53
|
get ViewabilityHelper(): ViewabilityHelper {
|
|
53
|
-
return require('./Lists/ViewabilityHelper');
|
|
54
|
+
return require('./Lists/ViewabilityHelper').default;
|
|
54
55
|
},
|
|
55
56
|
get FillRateHelper(): FillRateHelper {
|
|
56
|
-
return require('./Lists/FillRateHelper');
|
|
57
|
+
return require('./Lists/FillRateHelper').default;
|
|
57
58
|
},
|
|
58
59
|
};
|
package/package.json
CHANGED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {InteractionManager} from 'react-native';
|
|
12
|
-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A simple class for batching up invocations of a low-pri callback. A timeout is set to run the
|
|
16
|
-
* callback once after a delay, no matter how many times it's scheduled. Once the delay is reached,
|
|
17
|
-
* InteractionManager.runAfterInteractions is used to invoke the callback after any hi-pri
|
|
18
|
-
* interactions are done running.
|
|
19
|
-
*
|
|
20
|
-
* Make sure to cleanup with dispose(). Example:
|
|
21
|
-
*
|
|
22
|
-
* class Widget extends React.Component {
|
|
23
|
-
* _batchedSave: new Batchinator(() => this._saveState, 1000);
|
|
24
|
-
* _saveSate() {
|
|
25
|
-
* // save this.state to disk
|
|
26
|
-
* }
|
|
27
|
-
* componentDidUpdate() {
|
|
28
|
-
* this._batchedSave.schedule();
|
|
29
|
-
* }
|
|
30
|
-
* componentWillUnmount() {
|
|
31
|
-
* this._batchedSave.dispose();
|
|
32
|
-
* }
|
|
33
|
-
* ...
|
|
34
|
-
* }
|
|
35
|
-
*/
|
|
36
|
-
class Batchinator {
|
|
37
|
-
_callback: () => void;
|
|
38
|
-
_delay: number;
|
|
39
|
-
_taskHandle: ?{cancel: () => void, ...};
|
|
40
|
-
|
|
41
|
-
constructor(callback: () => void, delay: number) {
|
|
42
|
-
this._delay = delay;
|
|
43
|
-
this._callback = callback;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/*
|
|
47
|
-
* Cleanup any pending tasks.
|
|
48
|
-
*
|
|
49
|
-
* By default, if there is a pending task the callback is run immediately. Set the option abort to
|
|
50
|
-
* true to not call the callback if it was pending.
|
|
51
|
-
*/
|
|
52
|
-
dispose(): void {
|
|
53
|
-
if (this._taskHandle) {
|
|
54
|
-
this._taskHandle.cancel();
|
|
55
|
-
this._taskHandle = null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
schedule(): void {
|
|
60
|
-
if (this._taskHandle) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const invokeCallback = () => {
|
|
64
|
-
// Note that we clear the handle before invoking the callback so that if the callback calls
|
|
65
|
-
// schedule again, it will actually schedule another task.
|
|
66
|
-
this._taskHandle = null;
|
|
67
|
-
this._callback();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const timeoutHandle = setTimeout(
|
|
71
|
-
// NOTE: When shipping this, delete `Batchinator` instead of only these
|
|
72
|
-
// lines of code. Without `InteractionManager`, it's just a `setTimeout`.
|
|
73
|
-
ReactNativeFeatureFlags.disableInteractionManagerInBatchinator()
|
|
74
|
-
? invokeCallback
|
|
75
|
-
: () => {
|
|
76
|
-
this._taskHandle =
|
|
77
|
-
InteractionManager.runAfterInteractions(invokeCallback);
|
|
78
|
-
},
|
|
79
|
-
this._delay,
|
|
80
|
-
);
|
|
81
|
-
this._taskHandle = {cancel: () => clearTimeout(timeoutHandle)};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = Batchinator;
|