@shopify/flash-list 2.0.3 → 2.1.0
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/dist/AnimatedFlashList.js +4 -6
- package/dist/AnimatedFlashList.js.map +1 -1
- package/dist/FlashList.js +1 -5
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +9 -1
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js +1 -4
- package/dist/FlashListProps.js.map +1 -1
- package/dist/FlashListRef.js +1 -2
- package/dist/benchmark/AutoScrollHelper.js +22 -30
- package/dist/benchmark/AutoScrollHelper.js.map +1 -1
- package/dist/benchmark/JSFPSMonitor.js +27 -33
- package/dist/benchmark/JSFPSMonitor.js.map +1 -1
- package/dist/benchmark/roundToDecimalPlaces.js +2 -5
- package/dist/benchmark/roundToDecimalPlaces.js.map +1 -1
- package/dist/benchmark/useBenchmark.d.ts +9 -1
- package/dist/benchmark/useBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useBenchmark.js +86 -95
- package/dist/benchmark/useBenchmark.js.map +1 -1
- package/dist/benchmark/useDataMultiplier.js +6 -10
- package/dist/benchmark/useDataMultiplier.js.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.d.ts +4 -1
- package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.js +73 -81
- package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
- package/dist/errors/ErrorMessages.js +1 -4
- package/dist/errors/ErrorMessages.js.map +1 -1
- package/dist/errors/WarningMessages.d.ts +1 -0
- package/dist/errors/WarningMessages.d.ts.map +1 -1
- package/dist/errors/WarningMessages.js +2 -4
- package/dist/errors/WarningMessages.js.map +1 -1
- package/dist/index.js +17 -35
- package/dist/index.js.map +1 -1
- package/dist/isNewArch.js +6 -9
- package/dist/isNewArch.js.map +1 -1
- package/dist/native/config/PlatformHelper.android.js +2 -5
- package/dist/native/config/PlatformHelper.android.js.map +1 -1
- package/dist/native/config/PlatformHelper.ios.js +2 -5
- package/dist/native/config/PlatformHelper.ios.js.map +1 -1
- package/dist/native/config/PlatformHelper.js +2 -5
- package/dist/native/config/PlatformHelper.js.map +1 -1
- package/dist/native/config/PlatformHelper.web.js +2 -5
- package/dist/native/config/PlatformHelper.web.js.map +1 -1
- package/dist/recyclerview/LayoutCommitObserver.js +20 -24
- package/dist/recyclerview/LayoutCommitObserver.js.map +1 -1
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +117 -107
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewContextProvider.js +7 -12
- package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts +2 -0
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +146 -164
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RecyclerViewProps.js +1 -2
- package/dist/recyclerview/RenderStackManager.js +97 -188
- package/dist/recyclerview/RenderStackManager.js.map +1 -1
- package/dist/recyclerview/ViewHolder.js +16 -20
- package/dist/recyclerview/ViewHolder.js.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.js +26 -30
- package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
- package/dist/recyclerview/components/CompatScroller.js +6 -7
- package/dist/recyclerview/components/CompatScroller.js.map +1 -1
- package/dist/recyclerview/components/CompatView.js +6 -7
- package/dist/recyclerview/components/CompatView.js.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.js +10 -15
- package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.js +34 -40
- package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
- package/dist/recyclerview/helpers/ConsecutiveNumbers.js +39 -66
- package/dist/recyclerview/helpers/ConsecutiveNumbers.js.map +1 -1
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js +57 -63
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.js +19 -24
- package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
- package/dist/recyclerview/helpers/VelocityTracker.js +16 -22
- package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -1
- package/dist/recyclerview/hooks/useBoundDetection.js +37 -40
- package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
- package/dist/recyclerview/hooks/useLayoutState.js +9 -15
- package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.js +6 -10
- package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
- package/dist/recyclerview/hooks/useOnLoad.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useOnLoad.js +17 -22
- package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +169 -188
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js +12 -17
- package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclingState.js +10 -14
- package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
- package/dist/recyclerview/hooks/useSecondaryProps.js +24 -30
- package/dist/recyclerview/hooks/useSecondaryProps.js.map +1 -1
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +17 -22
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
- package/dist/recyclerview/hooks/useUnmountFlag.js +5 -9
- package/dist/recyclerview/hooks/useUnmountFlag.js.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.js +61 -80
- package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +83 -123
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LinearLayoutManager.js +51 -91
- package/dist/recyclerview/layout-managers/LinearLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +77 -96
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
- package/dist/recyclerview/utils/adjustOffsetForRTL.js +1 -4
- package/dist/recyclerview/utils/adjustOffsetForRTL.js.map +1 -1
- package/dist/recyclerview/utils/componentUtils.js +4 -9
- package/dist/recyclerview/utils/componentUtils.js.map +1 -1
- package/dist/recyclerview/utils/findVisibleIndex.js +9 -13
- package/dist/recyclerview/utils/findVisibleIndex.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.js +12 -20
- package/dist/recyclerview/utils/measureLayout.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.web.js +15 -23
- package/dist/recyclerview/utils/measureLayout.web.js.map +1 -1
- package/dist/recyclerview/viewability/ViewToken.js +1 -2
- package/dist/recyclerview/viewability/ViewabilityHelper.js +34 -41
- package/dist/recyclerview/viewability/ViewabilityHelper.js.map +1 -1
- package/dist/recyclerview/viewability/ViewabilityManager.js +48 -61
- package/dist/recyclerview/viewability/ViewabilityManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/AverageWindow.js +28 -39
- package/dist/utils/AverageWindow.js.map +1 -1
- package/package.json +4 -6
- package/src/FlashListProps.ts +8 -1
- package/src/benchmark/useBenchmark.ts +47 -4
- package/src/benchmark/useFlatListBenchmark.ts +38 -5
- package/src/errors/WarningMessages.ts +2 -0
- package/src/recyclerview/RecyclerView.tsx +18 -5
- package/src/recyclerview/RecyclerViewManager.ts +12 -0
- package/src/recyclerview/hooks/useOnLoad.ts +1 -0
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +7 -4
- package/dist/__tests__/AverageWindow.test.d.ts +0 -2
- package/dist/__tests__/AverageWindow.test.d.ts.map +0 -1
- package/dist/__tests__/AverageWindow.test.js +0 -104
- package/dist/__tests__/AverageWindow.test.js.map +0 -1
- package/dist/__tests__/ConsecutiveNumbers.test.d.ts +0 -2
- package/dist/__tests__/ConsecutiveNumbers.test.d.ts.map +0 -1
- package/dist/__tests__/ConsecutiveNumbers.test.js +0 -224
- package/dist/__tests__/ConsecutiveNumbers.test.js.map +0 -1
- package/dist/__tests__/GridLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/GridLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/GridLayoutManager.test.js +0 -69
- package/dist/__tests__/GridLayoutManager.test.js.map +0 -1
- package/dist/__tests__/LayoutCommitObserver.test.d.ts +0 -2
- package/dist/__tests__/LayoutCommitObserver.test.d.ts.map +0 -1
- package/dist/__tests__/LayoutCommitObserver.test.js +0 -37
- package/dist/__tests__/LayoutCommitObserver.test.js.map +0 -1
- package/dist/__tests__/LinearLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/LinearLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/LinearLayoutManager.test.js +0 -140
- package/dist/__tests__/LinearLayoutManager.test.js.map +0 -1
- package/dist/__tests__/MasonryLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/MasonryLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/MasonryLayoutManager.test.js +0 -148
- package/dist/__tests__/MasonryLayoutManager.test.js.map +0 -1
- package/dist/__tests__/RecyclerView.test.d.ts +0 -2
- package/dist/__tests__/RecyclerView.test.d.ts.map +0 -1
- package/dist/__tests__/RecyclerView.test.js +0 -103
- package/dist/__tests__/RecyclerView.test.js.map +0 -1
- package/dist/__tests__/RenderStackManager.test.d.ts +0 -2
- package/dist/__tests__/RenderStackManager.test.d.ts.map +0 -1
- package/dist/__tests__/RenderStackManager.test.js +0 -485
- package/dist/__tests__/RenderStackManager.test.js.map +0 -1
- package/dist/__tests__/ViewabilityHelper.test.d.ts +0 -2
- package/dist/__tests__/ViewabilityHelper.test.d.ts.map +0 -1
- package/dist/__tests__/ViewabilityHelper.test.js +0 -186
- package/dist/__tests__/ViewabilityHelper.test.js.map +0 -1
- package/dist/__tests__/findVisibleIndex.test.d.ts +0 -2
- package/dist/__tests__/findVisibleIndex.test.d.ts.map +0 -1
- package/dist/__tests__/findVisibleIndex.test.js +0 -259
- package/dist/__tests__/findVisibleIndex.test.js.map +0 -1
- package/dist/__tests__/helpers/createLayoutManager.d.ts +0 -34
- package/dist/__tests__/helpers/createLayoutManager.d.ts.map +0 -1
- package/dist/__tests__/helpers/createLayoutManager.js +0 -110
- package/dist/__tests__/helpers/createLayoutManager.js.map +0 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts +0 -2
- package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts.map +0 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.js +0 -185
- package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +0 -1
- package/src/__tests__/AverageWindow.test.ts +0 -128
- package/src/__tests__/ConsecutiveNumbers.test.ts +0 -232
- package/src/__tests__/GridLayoutManager.test.ts +0 -113
- package/src/__tests__/LayoutCommitObserver.test.tsx +0 -63
- package/src/__tests__/LinearLayoutManager.test.ts +0 -227
- package/src/__tests__/MasonryLayoutManager.test.ts +0 -202
- package/src/__tests__/RecyclerView.test.tsx +0 -144
- package/src/__tests__/RenderStackManager.test.ts +0 -574
- package/src/__tests__/ViewabilityHelper.test.ts +0 -282
- package/src/__tests__/findVisibleIndex.test.ts +0 -369
- package/src/__tests__/helpers/createLayoutManager.ts +0 -141
- package/src/__tests__/useUnmountAwareCallbacks.test.tsx +0 -285
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { useEffect, useState, useCallback, useRef } from "react";
|
|
2
2
|
|
|
3
3
|
import { FlashListRef } from "../FlashListRef";
|
|
4
4
|
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
@@ -24,6 +24,12 @@ export interface BenchmarkParams {
|
|
|
24
24
|
* Blank area is negative when list is able to draw faster than the scroll speed.
|
|
25
25
|
*/
|
|
26
26
|
sumNegativeBlankAreaValues?: boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* When set to true, the benchmark will not start automatically.
|
|
30
|
+
* Use the returned startBenchmark function to trigger it manually.
|
|
31
|
+
*/
|
|
32
|
+
startManually?: boolean;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
export interface BenchmarkResult {
|
|
@@ -44,15 +50,27 @@ export function useBenchmark(
|
|
|
44
50
|
callback: (benchmarkResult: BenchmarkResult) => void,
|
|
45
51
|
params: BenchmarkParams = {}
|
|
46
52
|
) {
|
|
47
|
-
|
|
53
|
+
const [isBenchmarkRunning, setIsBenchmarkRunning] = useState(false);
|
|
54
|
+
const cancellableRef = useRef<Cancellable | null>(null);
|
|
55
|
+
|
|
56
|
+
const startBenchmark = useCallback(() => {
|
|
57
|
+
if (isBenchmarkRunning) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
const cancellable = new Cancellable();
|
|
62
|
+
cancellableRef.current = cancellable;
|
|
49
63
|
const suggestions: string[] = [];
|
|
64
|
+
|
|
50
65
|
if (flashListRef.current) {
|
|
51
66
|
if (!(Number(flashListRef.current.props.data?.length) > 0)) {
|
|
52
67
|
throw new Error(ErrorMessages.dataEmptyCannotRunBenchmark);
|
|
53
68
|
}
|
|
54
69
|
}
|
|
55
|
-
|
|
70
|
+
|
|
71
|
+
setIsBenchmarkRunning(true);
|
|
72
|
+
|
|
73
|
+
const runBenchmark = async () => {
|
|
56
74
|
const jsFPSMonitor = new JSFPSMonitor();
|
|
57
75
|
jsFPSMonitor.startTracking();
|
|
58
76
|
for (let i = 0; i < (params.repeatCount || 1); i++) {
|
|
@@ -78,13 +96,37 @@ export function useBenchmark(
|
|
|
78
96
|
result.formattedString = getFormattedString(result);
|
|
79
97
|
}
|
|
80
98
|
callback(result);
|
|
99
|
+
setIsBenchmarkRunning(false);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
runBenchmark();
|
|
103
|
+
}, [
|
|
104
|
+
callback,
|
|
105
|
+
flashListRef,
|
|
106
|
+
isBenchmarkRunning,
|
|
107
|
+
params.repeatCount,
|
|
108
|
+
params.speedMultiplier,
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (params.startManually) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const cancelTimeout = setTimeout(() => {
|
|
117
|
+
startBenchmark();
|
|
81
118
|
}, params.startDelayInMs || 3000);
|
|
119
|
+
|
|
82
120
|
return () => {
|
|
83
121
|
clearTimeout(cancelTimeout);
|
|
84
|
-
|
|
122
|
+
if (cancellableRef.current) {
|
|
123
|
+
cancellableRef.current.cancel();
|
|
124
|
+
}
|
|
85
125
|
};
|
|
86
126
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
127
|
}, []);
|
|
128
|
+
|
|
129
|
+
return { startBenchmark, isBenchmarkRunning } as const;
|
|
88
130
|
}
|
|
89
131
|
|
|
90
132
|
export function getFormattedString(res: BenchmarkResult) {
|
|
@@ -161,6 +203,7 @@ async function runScrollBenchmark(
|
|
|
161
203
|
}
|
|
162
204
|
}
|
|
163
205
|
}
|
|
206
|
+
|
|
164
207
|
function computeSuggestions(
|
|
165
208
|
flashListRef: React.RefObject<FlashListRef<any> | null | undefined>,
|
|
166
209
|
suggestions: string[]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { FlatList } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
@@ -25,14 +25,24 @@ export function useFlatListBenchmark(
|
|
|
25
25
|
callback: (benchmarkResult: BenchmarkResult) => void,
|
|
26
26
|
params: FlatListBenchmarkParams
|
|
27
27
|
) {
|
|
28
|
-
|
|
28
|
+
const [isBenchmarkRunning, setIsBenchmarkRunning] = useState(false);
|
|
29
|
+
const cancellableRef = useRef<Cancellable | null>(null);
|
|
30
|
+
|
|
31
|
+
const startBenchmark = useCallback(() => {
|
|
32
|
+
if (isBenchmarkRunning) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
29
35
|
const cancellable = new Cancellable();
|
|
36
|
+
cancellableRef.current = cancellable;
|
|
30
37
|
if (flatListRef.current && flatListRef.current.props) {
|
|
31
38
|
if (!(Number(flatListRef.current.props.data?.length) > 0)) {
|
|
32
39
|
throw new Error(ErrorMessages.dataEmptyCannotRunBenchmark);
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
|
-
|
|
42
|
+
|
|
43
|
+
setIsBenchmarkRunning(true);
|
|
44
|
+
|
|
45
|
+
const runBenchmark = async () => {
|
|
36
46
|
const jsFPSMonitor = new JSFPSMonitor();
|
|
37
47
|
jsFPSMonitor.startTracking();
|
|
38
48
|
for (let i = 0; i < (params.repeatCount || 1); i++) {
|
|
@@ -53,14 +63,37 @@ export function useFlatListBenchmark(
|
|
|
53
63
|
result.formattedString = getFormattedString(result);
|
|
54
64
|
}
|
|
55
65
|
callback(result);
|
|
66
|
+
setIsBenchmarkRunning(false);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
runBenchmark();
|
|
70
|
+
}, [
|
|
71
|
+
callback,
|
|
72
|
+
flatListRef,
|
|
73
|
+
isBenchmarkRunning,
|
|
74
|
+
params.repeatCount,
|
|
75
|
+
params.speedMultiplier,
|
|
76
|
+
params.targetOffset,
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (params.startManually) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const cancelTimeout = setTimeout(() => {
|
|
85
|
+
startBenchmark();
|
|
56
86
|
}, params.startDelayInMs || 3000);
|
|
87
|
+
|
|
57
88
|
return () => {
|
|
58
89
|
clearTimeout(cancelTimeout);
|
|
59
|
-
|
|
90
|
+
if (cancellableRef.current) {
|
|
91
|
+
cancellableRef.current.cancel();
|
|
92
|
+
}
|
|
60
93
|
};
|
|
61
94
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
95
|
}, []);
|
|
63
|
-
return
|
|
96
|
+
return { startBenchmark, isBenchmarkRunning };
|
|
64
97
|
}
|
|
65
98
|
|
|
66
99
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const WarningMessages = {
|
|
2
2
|
keyExtractorNotDefinedForAnimation:
|
|
3
3
|
"keyExtractor is not defined. This might cause the animations to not work as expected.",
|
|
4
|
+
keyExtractorNotDefinedForMVCP:
|
|
5
|
+
"keyExtractor is not defined, maintainVisibleContentPosition may not work as expected.",
|
|
4
6
|
exceededMaxRendersWithoutCommit:
|
|
5
7
|
"Exceeded max renders without commit. This might mean that you have duplicate keys in your keyExtractor output or your list is nested in a ScrollView causing a lot of items to render at once. " +
|
|
6
8
|
"If it's none of those and is causing a real issue or error, consider reporing this on FlashList Github",
|
|
@@ -227,6 +227,17 @@ const RecyclerViewComponent = <T,>(
|
|
|
227
227
|
viewHolderCollectionRef.current?.commitLayout();
|
|
228
228
|
applyOffsetCorrection();
|
|
229
229
|
}
|
|
230
|
+
|
|
231
|
+
if (
|
|
232
|
+
horizontal &&
|
|
233
|
+
recyclerViewManager.hasLayout() &&
|
|
234
|
+
recyclerViewManager.getWindowSize().height > 0
|
|
235
|
+
) {
|
|
236
|
+
// We want the parent FlashList to continue rendering the next batch of items as soon as height is available.
|
|
237
|
+
// Waiting for each horizontal list to finish might cause too many setState calls.
|
|
238
|
+
// This will help avoid "Maximum update depth exceeded" error.
|
|
239
|
+
parentRecyclerViewContext?.unmarkChildLayoutAsPending(recyclerViewId);
|
|
240
|
+
}
|
|
230
241
|
});
|
|
231
242
|
|
|
232
243
|
/**
|
|
@@ -479,11 +490,13 @@ const RecyclerViewComponent = <T,>(
|
|
|
479
490
|
return (
|
|
480
491
|
<RecyclerViewContextProvider value={recyclerViewContext}>
|
|
481
492
|
<CompatView
|
|
482
|
-
style={
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
493
|
+
style={[
|
|
494
|
+
{
|
|
495
|
+
flex: horizontal ? undefined : 1,
|
|
496
|
+
overflow: "hidden",
|
|
497
|
+
},
|
|
498
|
+
style,
|
|
499
|
+
]}
|
|
487
500
|
ref={internalViewRef}
|
|
488
501
|
collapsable={false}
|
|
489
502
|
onLayout={(event) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
2
|
+
import { WarningMessages } from "../errors/WarningMessages";
|
|
2
3
|
|
|
3
4
|
import ViewabilityManager from "./viewability/ViewabilityManager";
|
|
4
5
|
import { ConsecutiveNumbers } from "./helpers/ConsecutiveNumbers";
|
|
@@ -37,6 +38,7 @@ export class RecyclerViewManager<T> {
|
|
|
37
38
|
|
|
38
39
|
public firstItemOffset = 0;
|
|
39
40
|
public ignoreScrollEvents = false;
|
|
41
|
+
public isFirstPaintOnUiComplete = false;
|
|
40
42
|
|
|
41
43
|
public get animationOptimizationsEnabled() {
|
|
42
44
|
return this._animationOptimizationsEnabled;
|
|
@@ -69,6 +71,7 @@ export class RecyclerViewManager<T> {
|
|
|
69
71
|
props.maxItemsInRecyclePool
|
|
70
72
|
);
|
|
71
73
|
this.itemViewabilityManager = new ViewabilityManager<T>(this as any);
|
|
74
|
+
this.checkPropsAndWarn();
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
// updates render stack based on the engaged indices which are sorted. Recycles unused keys.
|
|
@@ -261,6 +264,9 @@ export class RecyclerViewManager<T> {
|
|
|
261
264
|
return true;
|
|
262
265
|
}
|
|
263
266
|
if (this.hasRenderedProgressively) {
|
|
267
|
+
if (!this.isFirstPaintOnUiComplete) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
264
270
|
return this.recomputeEngagedIndices() !== undefined;
|
|
265
271
|
} else {
|
|
266
272
|
this.renderProgressively();
|
|
@@ -446,4 +452,10 @@ export class RecyclerViewManager<T> {
|
|
|
446
452
|
this.propsRef.extraData
|
|
447
453
|
);
|
|
448
454
|
}
|
|
455
|
+
|
|
456
|
+
private checkPropsAndWarn() {
|
|
457
|
+
if (this.propsRef.onStartReached && !this.propsRef.keyExtractor) {
|
|
458
|
+
console.warn(WarningMessages.keyExtractorNotDefinedForMVCP);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
449
461
|
}
|
|
@@ -48,6 +48,7 @@ export const useOnListLoad = <T>(
|
|
|
48
48
|
// console.log("----------> dataCollector", dataCollectorString);
|
|
49
49
|
// console.log("----------> FlashList v2 load in", `${elapsedTimeInMs} ms`);
|
|
50
50
|
requestAnimationFrame(() => {
|
|
51
|
+
recyclerViewManager.isFirstPaintOnUiComplete = true;
|
|
51
52
|
onLoad?.({ elapsedTimeInMs });
|
|
52
53
|
setIsLoaded(true);
|
|
53
54
|
});
|
|
@@ -289,7 +289,7 @@ export function useRecyclerViewController<T>(
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
setTimeout(() => {
|
|
292
|
-
scrollViewRef.current
|
|
292
|
+
scrollViewRef.current?.scrollToEnd({ animated });
|
|
293
293
|
}, 0);
|
|
294
294
|
},
|
|
295
295
|
|
|
@@ -564,7 +564,8 @@ export function useRecyclerViewController<T>(
|
|
|
564
564
|
]);
|
|
565
565
|
|
|
566
566
|
const applyInitialScrollIndex = useCallback(() => {
|
|
567
|
-
const { horizontal, data } =
|
|
567
|
+
const { horizontal, data, initialScrollIndexParams } =
|
|
568
|
+
recyclerViewManager.props;
|
|
568
569
|
|
|
569
570
|
const initialScrollIndex =
|
|
570
571
|
recyclerViewManager.getInitialScrollIndex() ?? -1;
|
|
@@ -583,9 +584,11 @@ export function useRecyclerViewController<T>(
|
|
|
583
584
|
|
|
584
585
|
pauseOffsetCorrection.current = true;
|
|
585
586
|
|
|
587
|
+
const additionalOffset = initialScrollIndexParams?.viewOffset ?? 0;
|
|
586
588
|
const offset = horizontal
|
|
587
|
-
? recyclerViewManager.getLayout(initialScrollIndex).x
|
|
588
|
-
: recyclerViewManager.getLayout(initialScrollIndex).y
|
|
589
|
+
? recyclerViewManager.getLayout(initialScrollIndex).x + additionalOffset
|
|
590
|
+
: recyclerViewManager.getLayout(initialScrollIndex).y +
|
|
591
|
+
additionalOffset;
|
|
589
592
|
handlerMethods.scrollToOffset({
|
|
590
593
|
offset,
|
|
591
594
|
animated: false,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AverageWindow.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/AverageWindow.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var AverageWindow_1 = require("../utils/AverageWindow");
|
|
4
|
-
describe("AverageWindow", function () {
|
|
5
|
-
var fillAverageWindow = function (averageWindow, from, to) {
|
|
6
|
-
for (var i = from; i < to; i++) {
|
|
7
|
-
averageWindow.addValue(i);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
it("all input window values should be filled with correct values", function () {
|
|
11
|
-
var commonValue = 50;
|
|
12
|
-
var size = 100;
|
|
13
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size);
|
|
14
|
-
var inputValues = averageWindow["inputValues"];
|
|
15
|
-
for (var i = 0; i < size; i++) {
|
|
16
|
-
averageWindow.addValue(commonValue);
|
|
17
|
-
}
|
|
18
|
-
expect(Math.round(averageWindow.currentValue)).toBe(commonValue);
|
|
19
|
-
expect(inputValues.every(function (val) { return val === commonValue; })).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
it("computes correct average", function () {
|
|
22
|
-
// We're gonna check if average from internal array matches the current average value
|
|
23
|
-
var size = 100;
|
|
24
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size);
|
|
25
|
-
var inputValues = averageWindow["inputValues"];
|
|
26
|
-
fillAverageWindow(averageWindow, 0, 200);
|
|
27
|
-
// calculate average directly
|
|
28
|
-
var reduceObj = inputValues.reduce(function (obj, val) {
|
|
29
|
-
if (val !== undefined) {
|
|
30
|
-
obj.sum += val;
|
|
31
|
-
obj.count++;
|
|
32
|
-
}
|
|
33
|
-
return obj;
|
|
34
|
-
}, { sum: 0, count: 0 });
|
|
35
|
-
// running average could be different by few decimal points so floor is required
|
|
36
|
-
expect(Math.floor(averageWindow.currentValue)).toBe(Math.floor(reduceObj.sum / reduceObj.count));
|
|
37
|
-
});
|
|
38
|
-
it("should prioritize new values quickly", function () {
|
|
39
|
-
var size = 30;
|
|
40
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size);
|
|
41
|
-
fillAverageWindow(averageWindow, 0, 100);
|
|
42
|
-
expect(averageWindow.currentValue).toBeGreaterThan(70);
|
|
43
|
-
fillAverageWindow(averageWindow, 0, 30);
|
|
44
|
-
expect(averageWindow.currentValue).toBeLessThan(30);
|
|
45
|
-
});
|
|
46
|
-
it("reports initial average correctly", function () {
|
|
47
|
-
var size = 30;
|
|
48
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size, 25);
|
|
49
|
-
expect(averageWindow.currentValue).toBe(25);
|
|
50
|
-
});
|
|
51
|
-
it("updates initial average correctly", function () {
|
|
52
|
-
var size = 30;
|
|
53
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size, 10);
|
|
54
|
-
averageWindow.addValue(20);
|
|
55
|
-
expect(averageWindow.currentValue).toBe(15);
|
|
56
|
-
});
|
|
57
|
-
it("increments next index correctly", function () {
|
|
58
|
-
var size = 30;
|
|
59
|
-
var averageWindow = new AverageWindow_1.AverageWindow(size);
|
|
60
|
-
for (var i = 0; i < 300; i++) {
|
|
61
|
-
expect(averageWindow["getNextIndex"]()).toBe(i % size);
|
|
62
|
-
}
|
|
63
|
-
var averageWindow2 = new AverageWindow_1.AverageWindow(size, 1);
|
|
64
|
-
for (var i = 1; i < 300; i++) {
|
|
65
|
-
expect(averageWindow2["getNextIndex"]()).toBe(i % size);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
describe("MultiTypeAverageWindow", function () {
|
|
70
|
-
it("should maintain separate averages for different types", function () {
|
|
71
|
-
var windowSize = 10;
|
|
72
|
-
var multiTypeAverageWindow = new AverageWindow_1.MultiTypeAverageWindow(windowSize);
|
|
73
|
-
multiTypeAverageWindow.addValue(10, "type1");
|
|
74
|
-
multiTypeAverageWindow.addValue(20, "type2");
|
|
75
|
-
expect(multiTypeAverageWindow.getCurrentValue("type1")).toBe(10);
|
|
76
|
-
expect(multiTypeAverageWindow.getCurrentValue("type2")).toBe(20);
|
|
77
|
-
});
|
|
78
|
-
it("should update averages correctly for each type", function () {
|
|
79
|
-
var windowSize = 5;
|
|
80
|
-
var multiTypeAverageWindow = new AverageWindow_1.MultiTypeAverageWindow(windowSize);
|
|
81
|
-
multiTypeAverageWindow.addValue(10, "type1");
|
|
82
|
-
multiTypeAverageWindow.addValue(20, "type1");
|
|
83
|
-
multiTypeAverageWindow.addValue(30, "type1");
|
|
84
|
-
multiTypeAverageWindow.addValue(5, "type2");
|
|
85
|
-
multiTypeAverageWindow.addValue(15, "type2");
|
|
86
|
-
expect(multiTypeAverageWindow.getCurrentValue("type1")).toBe(20);
|
|
87
|
-
expect(multiTypeAverageWindow.getCurrentValue("type2")).toBe(10);
|
|
88
|
-
});
|
|
89
|
-
it("should return 0 for non-existent types", function () {
|
|
90
|
-
var windowSize = 5;
|
|
91
|
-
var multiTypeAverageWindow = new AverageWindow_1.MultiTypeAverageWindow(windowSize);
|
|
92
|
-
expect(multiTypeAverageWindow.getCurrentValue("nonExistentType")).toBe(0);
|
|
93
|
-
});
|
|
94
|
-
it("should reset all averages", function () {
|
|
95
|
-
var windowSize = 5;
|
|
96
|
-
var multiTypeAverageWindow = new AverageWindow_1.MultiTypeAverageWindow(windowSize);
|
|
97
|
-
multiTypeAverageWindow.addValue(10, "type1");
|
|
98
|
-
multiTypeAverageWindow.addValue(20, "type2");
|
|
99
|
-
multiTypeAverageWindow.reset();
|
|
100
|
-
expect(multiTypeAverageWindow.getCurrentValue("type1")).toBe(0);
|
|
101
|
-
expect(multiTypeAverageWindow.getCurrentValue("type2")).toBe(0);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
//# sourceMappingURL=AverageWindow.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AverageWindow.test.js","sourceRoot":"","sources":["../../src/__tests__/AverageWindow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ConsecutiveNumbers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ConsecutiveNumbers.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var tslib_1 = require("tslib");
|
|
4
|
-
/* eslint-disable id-length */
|
|
5
|
-
var ConsecutiveNumbers_1 = require("../recyclerview/helpers/ConsecutiveNumbers");
|
|
6
|
-
describe("ConsecutiveNumbers", function () {
|
|
7
|
-
describe("constructor", function () {
|
|
8
|
-
it("should initialize with start and end indices", function () {
|
|
9
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
10
|
-
expect(numbers.startIndex).toBe(5);
|
|
11
|
-
expect(numbers.endIndex).toBe(10);
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
describe("EMPTY", function () {
|
|
15
|
-
it("should have correct values for EMPTY constant", function () {
|
|
16
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.startIndex).toBe(-1);
|
|
17
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.endIndex).toBe(-2);
|
|
18
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.length).toBe(0);
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
describe("length", function () {
|
|
22
|
-
it("should return correct length for valid range", function () {
|
|
23
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10).length).toBe(6);
|
|
24
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(0, 0).length).toBe(1);
|
|
25
|
-
});
|
|
26
|
-
it("should return 0 for invalid range", function () {
|
|
27
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 4).length).toBe(0);
|
|
28
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(10, 5).length).toBe(0);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
describe("at", function () {
|
|
32
|
-
it("should return correct value at index", function () {
|
|
33
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
34
|
-
expect(numbers.at(0)).toBe(5);
|
|
35
|
-
expect(numbers.at(3)).toBe(8);
|
|
36
|
-
expect(numbers.at(5)).toBe(10);
|
|
37
|
-
});
|
|
38
|
-
it("should work with negative ranges", function () {
|
|
39
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(-3, 2);
|
|
40
|
-
expect(numbers.at(0)).toBe(-3);
|
|
41
|
-
expect(numbers.at(3)).toBe(0);
|
|
42
|
-
expect(numbers.at(5)).toBe(2);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
describe("equals", function () {
|
|
46
|
-
it("should return true for identical ranges", function () {
|
|
47
|
-
var a = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
48
|
-
var b = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
49
|
-
expect(a.equals(b)).toBe(true);
|
|
50
|
-
});
|
|
51
|
-
it("should return false for different ranges", function () {
|
|
52
|
-
var a = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
53
|
-
var b = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 11);
|
|
54
|
-
var c = new ConsecutiveNumbers_1.ConsecutiveNumbers(6, 10);
|
|
55
|
-
expect(a.equals(b)).toBe(false);
|
|
56
|
-
expect(a.equals(c)).toBe(false);
|
|
57
|
-
});
|
|
58
|
-
it("should handle empty ranges", function () {
|
|
59
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.equals(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY)).toBe(true);
|
|
60
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.equals(new ConsecutiveNumbers_1.ConsecutiveNumbers(1, 5))).toBe(false);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
describe("toArray", function () {
|
|
64
|
-
it("should return correct array for valid range", function () {
|
|
65
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 8).toArray()).toEqual([5, 6, 7, 8]);
|
|
66
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(0, 3).toArray()).toEqual([0, 1, 2, 3]);
|
|
67
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(-2, 1).toArray()).toEqual([-2, -1, 0, 1]);
|
|
68
|
-
});
|
|
69
|
-
it("should return empty array for invalid ranges", function () {
|
|
70
|
-
expect(new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 4).toArray()).toEqual([]);
|
|
71
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.toArray()).toEqual([]);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
describe("includes", function () {
|
|
75
|
-
it("should return true for values in range", function () {
|
|
76
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
77
|
-
expect(numbers.includes(5)).toBe(true);
|
|
78
|
-
expect(numbers.includes(7)).toBe(true);
|
|
79
|
-
expect(numbers.includes(10)).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it("should return false for values outside range", function () {
|
|
82
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
83
|
-
expect(numbers.includes(4)).toBe(false);
|
|
84
|
-
expect(numbers.includes(11)).toBe(false);
|
|
85
|
-
});
|
|
86
|
-
it("should handle empty ranges", function () {
|
|
87
|
-
expect(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY.includes(0)).toBe(false);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
describe("indexOf", function () {
|
|
91
|
-
it("should return correct index for values in range", function () {
|
|
92
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
93
|
-
expect(numbers.indexOf(5)).toBe(0);
|
|
94
|
-
expect(numbers.indexOf(7)).toBe(2);
|
|
95
|
-
expect(numbers.indexOf(10)).toBe(5);
|
|
96
|
-
});
|
|
97
|
-
it("should return -1 for values outside range", function () {
|
|
98
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
99
|
-
expect(numbers.indexOf(4)).toBe(-1);
|
|
100
|
-
expect(numbers.indexOf(11)).toBe(-1);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
describe("findValue", function () {
|
|
104
|
-
it("should find values matching predicate", function () {
|
|
105
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
106
|
-
expect(numbers.findValue(function (v) { return v % 2 === 0; })).toBe(6);
|
|
107
|
-
expect(numbers.findValue(function (v) { return v > 8; })).toBe(9);
|
|
108
|
-
});
|
|
109
|
-
it("should return undefined when no match found", function () {
|
|
110
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
111
|
-
expect(numbers.findValue(function (v) { return v > 100; })).toBe(undefined);
|
|
112
|
-
});
|
|
113
|
-
it("should provide index and array to predicate", function () {
|
|
114
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 7);
|
|
115
|
-
var mockFn = jest.fn().mockReturnValue(false);
|
|
116
|
-
numbers.findValue(mockFn);
|
|
117
|
-
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
118
|
-
expect(mockFn).toHaveBeenNthCalledWith(1, 5, 0, numbers);
|
|
119
|
-
expect(mockFn).toHaveBeenNthCalledWith(2, 6, 1, numbers);
|
|
120
|
-
expect(mockFn).toHaveBeenNthCalledWith(3, 7, 2, numbers);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
describe("every", function () {
|
|
124
|
-
it("should return true when all values match predicate", function () {
|
|
125
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
126
|
-
expect(numbers.every(function (v) { return v >= 5; })).toBe(true);
|
|
127
|
-
expect(numbers.every(function (v) { return v <= 10; })).toBe(true);
|
|
128
|
-
});
|
|
129
|
-
it("should return false when some values do not match predicate", function () {
|
|
130
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
131
|
-
expect(numbers.every(function (v) { return v % 2 === 0; })).toBe(false);
|
|
132
|
-
expect(numbers.every(function (v) { return v > 7; })).toBe(false);
|
|
133
|
-
});
|
|
134
|
-
it("should provide index and array to predicate", function () {
|
|
135
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 7);
|
|
136
|
-
var mockFn = jest.fn().mockReturnValue(true);
|
|
137
|
-
numbers.every(mockFn);
|
|
138
|
-
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
139
|
-
expect(mockFn).toHaveBeenNthCalledWith(1, 5, 0, numbers);
|
|
140
|
-
expect(mockFn).toHaveBeenNthCalledWith(2, 6, 1, numbers);
|
|
141
|
-
expect(mockFn).toHaveBeenNthCalledWith(3, 7, 2, numbers);
|
|
142
|
-
});
|
|
143
|
-
it("should short-circuit when predicate returns false", function () {
|
|
144
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
145
|
-
var mockFn = jest.fn().mockImplementation(function (v) { return v < 7; });
|
|
146
|
-
numbers.every(mockFn);
|
|
147
|
-
expect(mockFn).toHaveBeenCalledTimes(3); // Should stop after v=7
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
describe("slice", function () {
|
|
151
|
-
it("should slice with both start and end", function () {
|
|
152
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
153
|
-
var sliced = numbers.slice(1, 4);
|
|
154
|
-
expect(sliced.startIndex).toBe(6);
|
|
155
|
-
expect(sliced.endIndex).toBe(8);
|
|
156
|
-
expect(sliced.length).toBe(3);
|
|
157
|
-
});
|
|
158
|
-
it("should slice with only start", function () {
|
|
159
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
160
|
-
var sliced = numbers.slice(2);
|
|
161
|
-
expect(sliced.startIndex).toBe(7);
|
|
162
|
-
expect(sliced.endIndex).toBe(10);
|
|
163
|
-
expect(sliced.length).toBe(4);
|
|
164
|
-
});
|
|
165
|
-
it("should handle out of bounds slices", function () {
|
|
166
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
167
|
-
var sliced = numbers.slice(0, 100);
|
|
168
|
-
expect(sliced.length).toBe(6);
|
|
169
|
-
expect(sliced.startIndex).toBe(5);
|
|
170
|
-
expect(sliced.endIndex).toBe(10);
|
|
171
|
-
});
|
|
172
|
-
it("should handle invalid slices", function () {
|
|
173
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 10);
|
|
174
|
-
var sliced = numbers.slice(4, 3);
|
|
175
|
-
expect(sliced.length).toBe(0);
|
|
176
|
-
expect(sliced.startIndex).toBe(9);
|
|
177
|
-
expect(sliced.endIndex).toBe(8);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
describe("iterator", function () {
|
|
181
|
-
it("should iterate over all values", function () {
|
|
182
|
-
var e_1, _a;
|
|
183
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 8);
|
|
184
|
-
var result = [];
|
|
185
|
-
try {
|
|
186
|
-
for (var numbers_1 = tslib_1.__values(numbers), numbers_1_1 = numbers_1.next(); !numbers_1_1.done; numbers_1_1 = numbers_1.next()) {
|
|
187
|
-
var num = numbers_1_1.value;
|
|
188
|
-
result.push(num);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
192
|
-
finally {
|
|
193
|
-
try {
|
|
194
|
-
if (numbers_1_1 && !numbers_1_1.done && (_a = numbers_1.return)) _a.call(numbers_1);
|
|
195
|
-
}
|
|
196
|
-
finally { if (e_1) throw e_1.error; }
|
|
197
|
-
}
|
|
198
|
-
expect(result).toEqual([5, 6, 7, 8]);
|
|
199
|
-
});
|
|
200
|
-
it("should handle empty ranges", function () {
|
|
201
|
-
var e_2, _a;
|
|
202
|
-
var result = [];
|
|
203
|
-
try {
|
|
204
|
-
for (var _b = tslib_1.__values(ConsecutiveNumbers_1.ConsecutiveNumbers.EMPTY), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
205
|
-
var num = _c.value;
|
|
206
|
-
result.push(num);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
210
|
-
finally {
|
|
211
|
-
try {
|
|
212
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
213
|
-
}
|
|
214
|
-
finally { if (e_2) throw e_2.error; }
|
|
215
|
-
}
|
|
216
|
-
expect(result).toEqual([]);
|
|
217
|
-
});
|
|
218
|
-
it("should work with spread operator", function () {
|
|
219
|
-
var numbers = new ConsecutiveNumbers_1.ConsecutiveNumbers(5, 8);
|
|
220
|
-
expect(tslib_1.__spreadArray([], tslib_1.__read(numbers), false)).toEqual([5, 6, 7, 8]);
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
//# sourceMappingURL=ConsecutiveNumbers.test.js.map
|