@shopify/flash-list 2.0.0-alpha.8 → 2.0.0-rc.1

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.
Files changed (197) hide show
  1. package/README.md +38 -98
  2. package/dist/AnimatedFlashList.d.ts.map +1 -1
  3. package/dist/AnimatedFlashList.js +3 -3
  4. package/dist/AnimatedFlashList.js.map +1 -1
  5. package/dist/FlashList.d.ts +9 -0
  6. package/dist/FlashList.d.ts.map +1 -1
  7. package/dist/FlashList.js +20 -0
  8. package/dist/FlashList.js.map +1 -1
  9. package/dist/FlashListProps.d.ts +15 -8
  10. package/dist/FlashListProps.d.ts.map +1 -1
  11. package/dist/FlashListProps.js.map +1 -1
  12. package/dist/FlashListRef.d.ts +305 -0
  13. package/dist/FlashListRef.d.ts.map +1 -0
  14. package/dist/FlashListRef.js +3 -0
  15. package/dist/FlashListRef.js.map +1 -0
  16. package/dist/MasonryFlashList.js.map +1 -1
  17. package/dist/__tests__/RecyclerView.test.js +63 -28
  18. package/dist/__tests__/RecyclerView.test.js.map +1 -1
  19. package/dist/__tests__/RenderStackManager.test.d.ts +2 -0
  20. package/dist/__tests__/RenderStackManager.test.d.ts.map +1 -0
  21. package/dist/__tests__/RenderStackManager.test.js +486 -0
  22. package/dist/__tests__/RenderStackManager.test.js.map +1 -0
  23. package/dist/__tests__/helpers/createLayoutManager.d.ts.map +1 -1
  24. package/dist/__tests__/helpers/createLayoutManager.js +3 -4
  25. package/dist/__tests__/helpers/createLayoutManager.js.map +1 -1
  26. package/dist/__tests__/useUnmountAwareCallbacks.test.js +1 -1
  27. package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +1 -1
  28. package/dist/benchmark/useFlatListBenchmark.js +8 -7
  29. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  30. package/dist/enableNewCore.d.ts.map +1 -1
  31. package/dist/enableNewCore.js +2 -1
  32. package/dist/enableNewCore.js.map +1 -1
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/native/config/PlatformHelper.android.d.ts +2 -0
  37. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
  38. package/dist/native/config/PlatformHelper.android.js +2 -0
  39. package/dist/native/config/PlatformHelper.android.js.map +1 -1
  40. package/dist/native/config/PlatformHelper.d.ts +2 -0
  41. package/dist/native/config/PlatformHelper.d.ts.map +1 -1
  42. package/dist/native/config/PlatformHelper.ios.d.ts +2 -0
  43. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
  44. package/dist/native/config/PlatformHelper.ios.js +2 -0
  45. package/dist/native/config/PlatformHelper.ios.js.map +1 -1
  46. package/dist/native/config/PlatformHelper.js +2 -0
  47. package/dist/native/config/PlatformHelper.js.map +1 -1
  48. package/dist/native/config/PlatformHelper.web.d.ts +2 -0
  49. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
  50. package/dist/native/config/PlatformHelper.web.js +3 -1
  51. package/dist/native/config/PlatformHelper.web.js.map +1 -1
  52. package/dist/recyclerview/RecyclerView.d.ts +2 -1
  53. package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
  54. package/dist/recyclerview/RecyclerView.js +64 -37
  55. package/dist/recyclerview/RecyclerView.js.map +1 -1
  56. package/dist/recyclerview/RecyclerViewContextProvider.d.ts +6 -5
  57. package/dist/recyclerview/RecyclerViewContextProvider.d.ts.map +1 -1
  58. package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
  59. package/dist/recyclerview/RecyclerViewManager.d.ts +21 -7
  60. package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
  61. package/dist/recyclerview/RecyclerViewManager.js +105 -113
  62. package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
  63. package/dist/recyclerview/RenderStackManager.d.ts +85 -0
  64. package/dist/recyclerview/RenderStackManager.d.ts.map +1 -0
  65. package/dist/recyclerview/RenderStackManager.js +324 -0
  66. package/dist/recyclerview/RenderStackManager.js.map +1 -0
  67. package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
  68. package/dist/recyclerview/ViewHolder.js +5 -3
  69. package/dist/recyclerview/ViewHolder.js.map +1 -1
  70. package/dist/recyclerview/ViewHolderCollection.d.ts +3 -1
  71. package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
  72. package/dist/recyclerview/ViewHolderCollection.js +23 -8
  73. package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
  74. package/dist/recyclerview/components/ScrollAnchor.d.ts +2 -1
  75. package/dist/recyclerview/components/ScrollAnchor.d.ts.map +1 -1
  76. package/dist/recyclerview/components/ScrollAnchor.js +9 -4
  77. package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
  78. package/dist/recyclerview/components/StickyHeaders.d.ts +1 -1
  79. package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
  80. package/dist/recyclerview/components/StickyHeaders.js +40 -32
  81. package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
  82. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts +45 -1
  83. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts.map +1 -1
  84. package/dist/recyclerview/helpers/EngagedIndicesTracker.js +79 -20
  85. package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
  86. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +10 -0
  87. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -0
  88. package/dist/recyclerview/helpers/RenderTimeTracker.js +39 -0
  89. package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -0
  90. package/dist/recyclerview/helpers/VelocityTracker.d.ts +29 -0
  91. package/dist/recyclerview/helpers/VelocityTracker.d.ts.map +1 -0
  92. package/dist/recyclerview/helpers/VelocityTracker.js +70 -0
  93. package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -0
  94. package/dist/recyclerview/hooks/useBoundDetection.d.ts +1 -2
  95. package/dist/recyclerview/hooks/useBoundDetection.d.ts.map +1 -1
  96. package/dist/recyclerview/hooks/useBoundDetection.js +19 -16
  97. package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
  98. package/dist/recyclerview/hooks/useMappingHelper.d.ts +1 -1
  99. package/dist/recyclerview/hooks/useMappingHelper.d.ts.map +1 -1
  100. package/dist/recyclerview/hooks/useMappingHelper.js +1 -1
  101. package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
  102. package/dist/recyclerview/hooks/useOnLoad.d.ts.map +1 -1
  103. package/dist/recyclerview/hooks/useOnLoad.js +4 -6
  104. package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
  105. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts +3 -48
  106. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
  107. package/dist/recyclerview/hooks/useRecyclerViewController.js +179 -119
  108. package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
  109. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts +2 -0
  110. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts.map +1 -1
  111. package/dist/recyclerview/hooks/useRecyclerViewManager.js +10 -1
  112. package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
  113. package/dist/recyclerview/hooks/useSecondaryProps.js +1 -1
  114. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts +10 -3
  115. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts.map +1 -1
  116. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +33 -4
  117. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
  118. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts +6 -0
  119. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts.map +1 -1
  120. package/dist/recyclerview/layout-managers/GridLayoutManager.js +27 -5
  121. package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
  122. package/dist/recyclerview/layout-managers/LayoutManager.d.ts +10 -16
  123. package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
  124. package/dist/recyclerview/layout-managers/LayoutManager.js +4 -14
  125. package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
  126. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +2 -2
  127. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
  128. package/dist/recyclerview/utils/measureLayout.d.ts +1 -29
  129. package/dist/recyclerview/utils/measureLayout.d.ts.map +1 -1
  130. package/dist/recyclerview/utils/measureLayout.js +2 -4
  131. package/dist/recyclerview/utils/measureLayout.js.map +1 -1
  132. package/dist/recyclerview/utils/measureLayout.web.d.ts +29 -0
  133. package/dist/recyclerview/utils/measureLayout.web.d.ts.map +1 -0
  134. package/dist/recyclerview/utils/measureLayout.web.js +89 -0
  135. package/dist/recyclerview/utils/measureLayout.web.js.map +1 -0
  136. package/dist/tsconfig.tsbuildinfo +1 -1
  137. package/dist/viewability/ViewToken.d.ts +2 -2
  138. package/dist/viewability/ViewToken.d.ts.map +1 -1
  139. package/dist/viewability/ViewabilityHelper.js +1 -1
  140. package/dist/viewability/ViewabilityHelper.js.map +1 -1
  141. package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
  142. package/dist/viewability/ViewabilityManager.js +1 -2
  143. package/dist/viewability/ViewabilityManager.js.map +1 -1
  144. package/jestSetup.js +30 -11
  145. package/package.json +2 -1
  146. package/src/AnimatedFlashList.ts +3 -2
  147. package/src/FlashList.tsx +24 -0
  148. package/src/FlashListProps.ts +20 -8
  149. package/src/FlashListRef.ts +320 -0
  150. package/src/MasonryFlashList.tsx +2 -2
  151. package/src/__tests__/RecyclerView.test.tsx +84 -30
  152. package/src/__tests__/RenderStackManager.test.ts +575 -0
  153. package/src/__tests__/helpers/createLayoutManager.ts +2 -3
  154. package/src/__tests__/useUnmountAwareCallbacks.test.tsx +12 -12
  155. package/src/benchmark/useFlatListBenchmark.ts +2 -2
  156. package/src/enableNewCore.ts +3 -1
  157. package/src/index.ts +1 -0
  158. package/src/native/config/PlatformHelper.android.ts +2 -0
  159. package/src/native/config/PlatformHelper.ios.ts +2 -0
  160. package/src/native/config/PlatformHelper.ts +2 -0
  161. package/src/native/config/PlatformHelper.web.ts +3 -1
  162. package/src/recyclerview/RecyclerView.tsx +85 -43
  163. package/src/recyclerview/RecyclerViewContextProvider.ts +12 -6
  164. package/src/recyclerview/RecyclerViewManager.ts +123 -98
  165. package/src/recyclerview/RenderStackManager.ts +291 -0
  166. package/src/recyclerview/ViewHolder.tsx +5 -3
  167. package/src/recyclerview/ViewHolderCollection.tsx +33 -12
  168. package/src/recyclerview/components/ScrollAnchor.tsx +21 -8
  169. package/src/recyclerview/components/StickyHeaders.tsx +63 -44
  170. package/src/recyclerview/helpers/EngagedIndicesTracker.ts +120 -23
  171. package/src/recyclerview/helpers/RenderTimeTracker.ts +38 -0
  172. package/src/recyclerview/helpers/VelocityTracker.ts +77 -0
  173. package/src/recyclerview/hooks/useBoundDetection.ts +25 -18
  174. package/src/recyclerview/hooks/useMappingHelper.ts +1 -1
  175. package/src/recyclerview/hooks/useOnLoad.ts +4 -6
  176. package/src/recyclerview/hooks/useRecyclerViewController.tsx +204 -173
  177. package/src/recyclerview/hooks/useRecyclerViewManager.ts +11 -1
  178. package/src/recyclerview/hooks/useSecondaryProps.tsx +1 -1
  179. package/src/recyclerview/hooks/useUnmountAwareCallbacks.ts +39 -3
  180. package/src/recyclerview/layout-managers/GridLayoutManager.ts +30 -7
  181. package/src/recyclerview/layout-managers/LayoutManager.ts +12 -21
  182. package/src/recyclerview/layout-managers/MasonryLayoutManager.ts +1 -1
  183. package/src/recyclerview/utils/measureLayout.ts +3 -3
  184. package/src/recyclerview/utils/measureLayout.web.ts +104 -0
  185. package/src/viewability/ViewToken.ts +2 -2
  186. package/src/viewability/ViewabilityHelper.ts +1 -1
  187. package/src/viewability/ViewabilityManager.ts +6 -3
  188. package/dist/__tests__/RecycleKeyManager.test.d.ts +0 -2
  189. package/dist/__tests__/RecycleKeyManager.test.d.ts.map +0 -1
  190. package/dist/__tests__/RecycleKeyManager.test.js +0 -210
  191. package/dist/__tests__/RecycleKeyManager.test.js.map +0 -1
  192. package/dist/recyclerview/RecycleKeyManager.d.ts +0 -82
  193. package/dist/recyclerview/RecycleKeyManager.d.ts.map +0 -1
  194. package/dist/recyclerview/RecycleKeyManager.js +0 -135
  195. package/dist/recyclerview/RecycleKeyManager.js.map +0 -1
  196. package/src/__tests__/RecycleKeyManager.test.ts +0 -254
  197. package/src/recyclerview/RecycleKeyManager.ts +0 -185
@@ -1,9 +1,10 @@
1
1
  import { useCallback, useEffect, useMemo, useRef } from "react";
2
2
 
3
3
  import { RecyclerViewManager } from "../RecyclerViewManager";
4
- import { RecyclerViewProps } from "../RecyclerViewProps";
5
4
  import { CompatScroller } from "../components/CompatScroller";
6
5
 
6
+ import { useUnmountAwareAnimationFrame } from "./useUnmountAwareCallbacks";
7
+
7
8
  /**
8
9
  * Hook to detect when the scroll position reaches near the start or end of the list
9
10
  * and trigger the appropriate callbacks. This hook is responsible for:
@@ -17,7 +18,6 @@ import { CompatScroller } from "../components/CompatScroller";
17
18
  */
18
19
  export function useBoundDetection<T>(
19
20
  recyclerViewManager: RecyclerViewManager<T>,
20
- props: RecyclerViewProps<T>,
21
21
  scrollViewRef: React.RefObject<CompatScroller>
22
22
  ) {
23
23
  // Track whether we've already triggered the end reached callback to prevent duplicate calls
@@ -26,22 +26,27 @@ export function useBoundDetection<T>(
26
26
  const pendingStartReached = useRef(false);
27
27
  // Track whether we should auto-scroll to bottom when new content is added
28
28
  const pendingAutoscrollToBottom = useRef(false);
29
- const { horizontal, data, maintainVisibleContentPosition } = props;
29
+ const { data } = recyclerViewManager.props;
30
+ const { requestAnimationFrame } = useUnmountAwareAnimationFrame();
30
31
 
31
32
  /**
32
33
  * Checks if the scroll position is near the start or end of the list
33
34
  * and triggers appropriate callbacks if configured.
34
35
  */
35
36
  const checkBounds = useCallback(() => {
37
+ const {
38
+ onEndReached,
39
+ onStartReached,
40
+ maintainVisibleContentPosition,
41
+ horizontal,
42
+ onEndReachedThreshold: onEndReachedThresholdProp,
43
+ onStartReachedThreshold: onStartReachedThresholdProp,
44
+ } = recyclerViewManager.props;
36
45
  // Skip all calculations if neither callback is provided and autoscroll is disabled
37
46
  const autoscrollToBottomThreshold =
38
47
  maintainVisibleContentPosition?.autoscrollToBottomThreshold ?? -1;
39
48
 
40
- if (
41
- !props.onEndReached &&
42
- !props.onStartReached &&
43
- autoscrollToBottomThreshold < 0
44
- ) {
49
+ if (!onEndReached && !onStartReached && autoscrollToBottomThreshold < 0) {
45
50
  return;
46
51
  }
47
52
 
@@ -50,7 +55,7 @@ export function useBoundDetection<T>(
50
55
  recyclerViewManager.getAbsoluteLastScrollOffset();
51
56
  const contentSize = recyclerViewManager.getChildContainerDimensions();
52
57
  const windowSize = recyclerViewManager.getWindowSize();
53
- const isHorizontal = props.horizontal === true;
58
+ const isHorizontal = horizontal === true;
54
59
 
55
60
  // Calculate dimensions based on scroll direction
56
61
  const visibleLength = isHorizontal ? windowSize.width : windowSize.height;
@@ -59,8 +64,8 @@ export function useBoundDetection<T>(
59
64
  recyclerViewManager.firstItemOffset;
60
65
 
61
66
  // Check if we're near the end of the list
62
- if (props.onEndReached) {
63
- const onEndReachedThreshold = props.onEndReachedThreshold ?? 0.5;
67
+ if (onEndReached) {
68
+ const onEndReachedThreshold = onEndReachedThresholdProp ?? 0.5;
64
69
  const endThresholdDistance = onEndReachedThreshold * visibleLength;
65
70
 
66
71
  const isNearEnd =
@@ -69,27 +74,27 @@ export function useBoundDetection<T>(
69
74
 
70
75
  if (isNearEnd && !pendingEndReached.current) {
71
76
  pendingEndReached.current = true;
72
- props.onEndReached();
77
+ onEndReached();
73
78
  }
74
79
  pendingEndReached.current = isNearEnd;
75
80
  }
76
81
 
77
82
  // Check if we're near the start of the list
78
- if (props.onStartReached) {
79
- const onStartReachedThreshold = props.onStartReachedThreshold ?? 0.2;
83
+ if (onStartReached) {
84
+ const onStartReachedThreshold = onStartReachedThresholdProp ?? 0.2;
80
85
  const startThresholdDistance = onStartReachedThreshold * visibleLength;
81
86
 
82
87
  const isNearStart = lastScrollOffset <= startThresholdDistance;
83
88
 
84
89
  if (isNearStart && !pendingStartReached.current) {
85
90
  pendingStartReached.current = true;
86
- props.onStartReached();
91
+ onStartReached();
87
92
  }
88
93
  pendingStartReached.current = isNearStart;
89
94
  }
90
95
 
91
96
  // Handle auto-scrolling to bottom for vertical lists
92
- if (!horizontal) {
97
+ if (!isHorizontal) {
93
98
  const autoscrollToBottomThresholdDistance =
94
99
  autoscrollToBottomThreshold * visibleLength;
95
100
 
@@ -104,11 +109,13 @@ export function useBoundDetection<T>(
104
109
  }
105
110
  }
106
111
  }
107
- }, [recyclerViewManager, props]);
112
+ }, [recyclerViewManager]);
108
113
 
109
114
  // Reset end reached state when data changes
110
115
  useMemo(() => {
111
116
  pendingEndReached.current = false;
117
+ // needs to run only when data changes
118
+ // eslint-disable-next-line react-hooks/exhaustive-deps
112
119
  }, [data]);
113
120
 
114
121
  // Auto-scroll to bottom when new content is added and we're near the bottom
@@ -119,7 +126,7 @@ export function useBoundDetection<T>(
119
126
  pendingAutoscrollToBottom.current = false;
120
127
  });
121
128
  }
122
- }, [data]);
129
+ }, [data, requestAnimationFrame, scrollViewRef]);
123
130
 
124
131
  return {
125
132
  checkBounds,
@@ -10,7 +10,7 @@ import { useRecyclerViewContext } from "../RecyclerViewContextProvider";
10
10
  export const useMappingHelper = () => {
11
11
  const recyclerViewContext = useRecyclerViewContext();
12
12
  const getMappingKey = useCallback(
13
- (index: number, itemKey: string | number | bigint) => {
13
+ (itemKey: string | number | bigint, index: number) => {
14
14
  return recyclerViewContext ? index : itemKey;
15
15
  },
16
16
  [recyclerViewContext]
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
2
2
 
3
3
  import { RecyclerViewManager } from "../RecyclerViewManager";
4
4
 
5
- import { useUnmountFlag } from "./useUnmountFlag";
5
+ import { useUnmountAwareAnimationFrame } from "./useUnmountAwareCallbacks";
6
6
  // import { ToastAndroid } from "react-native";
7
7
 
8
8
  /**
@@ -22,7 +22,7 @@ export const useOnListLoad = <T>(
22
22
  const [isLoaded, setIsLoaded] = useState<boolean>(false);
23
23
  const dataLength = recyclerViewManager.getDataLength();
24
24
  // const dataCollector = useRef<number[]>([]);
25
- const isUnmounted = useUnmountFlag();
25
+ const { requestAnimationFrame } = useUnmountAwareAnimationFrame();
26
26
  // Track render cycles by collecting elapsed time on each render
27
27
  // useEffect(() => {
28
28
  // const elapsedTimeInMs = Date.now() - loadStartTimeRef.current;
@@ -48,10 +48,8 @@ export const useOnListLoad = <T>(
48
48
  // console.log("----------> dataCollector", dataCollectorString);
49
49
  // console.log("----------> FlashList v2 load in", `${elapsedTimeInMs} ms`);
50
50
  requestAnimationFrame(() => {
51
- if (!isUnmounted.current) {
52
- onLoad?.({ elapsedTimeInMs });
53
- setIsLoaded(true);
54
- }
51
+ onLoad?.({ elapsedTimeInMs });
52
+ setIsLoaded(true);
55
53
  });
56
54
  });
57
55