@shopify/flash-list 2.0.0-alpha.9 → 2.0.0-rc.10

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 (209) hide show
  1. package/README.md +37 -97
  2. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +2 -2
  3. package/dist/AnimatedFlashList.d.ts.map +1 -1
  4. package/dist/AnimatedFlashList.js +3 -3
  5. package/dist/AnimatedFlashList.js.map +1 -1
  6. package/dist/FlashList.d.ts +9 -0
  7. package/dist/FlashList.d.ts.map +1 -1
  8. package/dist/FlashList.js +20 -0
  9. package/dist/FlashList.js.map +1 -1
  10. package/dist/FlashListProps.d.ts +30 -10
  11. package/dist/FlashListProps.d.ts.map +1 -1
  12. package/dist/FlashListProps.js.map +1 -1
  13. package/dist/FlashListRef.d.ts +305 -0
  14. package/dist/FlashListRef.d.ts.map +1 -0
  15. package/dist/FlashListRef.js +3 -0
  16. package/dist/FlashListRef.js.map +1 -0
  17. package/dist/MasonryFlashList.js.map +1 -1
  18. package/dist/__tests__/RecyclerView.test.js +72 -28
  19. package/dist/__tests__/RecyclerView.test.js.map +1 -1
  20. package/dist/__tests__/RenderStackManager.test.d.ts +2 -0
  21. package/dist/__tests__/RenderStackManager.test.d.ts.map +1 -0
  22. package/dist/__tests__/RenderStackManager.test.js +485 -0
  23. package/dist/__tests__/RenderStackManager.test.js.map +1 -0
  24. package/dist/__tests__/helpers/createLayoutManager.d.ts.map +1 -1
  25. package/dist/__tests__/helpers/createLayoutManager.js +3 -4
  26. package/dist/__tests__/helpers/createLayoutManager.js.map +1 -1
  27. package/dist/__tests__/useUnmountAwareCallbacks.test.js +1 -1
  28. package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +1 -1
  29. package/dist/benchmark/useBenchmark.js +0 -25
  30. package/dist/benchmark/useBenchmark.js.map +1 -1
  31. package/dist/benchmark/useFlatListBenchmark.js +8 -7
  32. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/native/config/PlatformHelper.android.d.ts +1 -0
  38. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
  39. package/dist/native/config/PlatformHelper.android.js +1 -0
  40. package/dist/native/config/PlatformHelper.android.js.map +1 -1
  41. package/dist/native/config/PlatformHelper.d.ts +1 -0
  42. package/dist/native/config/PlatformHelper.d.ts.map +1 -1
  43. package/dist/native/config/PlatformHelper.ios.d.ts +1 -0
  44. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
  45. package/dist/native/config/PlatformHelper.ios.js +1 -0
  46. package/dist/native/config/PlatformHelper.ios.js.map +1 -1
  47. package/dist/native/config/PlatformHelper.js +1 -0
  48. package/dist/native/config/PlatformHelper.js.map +1 -1
  49. package/dist/native/config/PlatformHelper.web.d.ts +1 -0
  50. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
  51. package/dist/native/config/PlatformHelper.web.js +1 -0
  52. package/dist/native/config/PlatformHelper.web.js.map +1 -1
  53. package/dist/recyclerview/RecyclerView.d.ts +2 -1
  54. package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
  55. package/dist/recyclerview/RecyclerView.js +104 -57
  56. package/dist/recyclerview/RecyclerView.js.map +1 -1
  57. package/dist/recyclerview/RecyclerViewContextProvider.d.ts +41 -6
  58. package/dist/recyclerview/RecyclerViewContextProvider.d.ts.map +1 -1
  59. package/dist/recyclerview/RecyclerViewContextProvider.js +4 -0
  60. package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
  61. package/dist/recyclerview/RecyclerViewManager.d.ts +24 -7
  62. package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
  63. package/dist/recyclerview/RecyclerViewManager.js +119 -113
  64. package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
  65. package/dist/recyclerview/RenderStackManager.d.ts +86 -0
  66. package/dist/recyclerview/RenderStackManager.d.ts.map +1 -0
  67. package/dist/recyclerview/RenderStackManager.js +343 -0
  68. package/dist/recyclerview/RenderStackManager.js.map +1 -0
  69. package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
  70. package/dist/recyclerview/ViewHolder.js +5 -3
  71. package/dist/recyclerview/ViewHolder.js.map +1 -1
  72. package/dist/recyclerview/ViewHolderCollection.d.ts +9 -3
  73. package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
  74. package/dist/recyclerview/ViewHolderCollection.js +26 -9
  75. package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
  76. package/dist/recyclerview/components/ScrollAnchor.d.ts +2 -2
  77. package/dist/recyclerview/components/ScrollAnchor.d.ts.map +1 -1
  78. package/dist/recyclerview/components/ScrollAnchor.js +9 -5
  79. package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
  80. package/dist/recyclerview/components/StickyHeaders.d.ts +1 -1
  81. package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
  82. package/dist/recyclerview/components/StickyHeaders.js +40 -33
  83. package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
  84. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts +45 -1
  85. package/dist/recyclerview/helpers/EngagedIndicesTracker.d.ts.map +1 -1
  86. package/dist/recyclerview/helpers/EngagedIndicesTracker.js +77 -20
  87. package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
  88. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +11 -0
  89. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -0
  90. package/dist/recyclerview/helpers/RenderTimeTracker.js +42 -0
  91. package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -0
  92. package/dist/recyclerview/helpers/VelocityTracker.d.ts +29 -0
  93. package/dist/recyclerview/helpers/VelocityTracker.d.ts.map +1 -0
  94. package/dist/recyclerview/helpers/VelocityTracker.js +70 -0
  95. package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -0
  96. package/dist/recyclerview/hooks/useBoundDetection.d.ts +1 -2
  97. package/dist/recyclerview/hooks/useBoundDetection.d.ts.map +1 -1
  98. package/dist/recyclerview/hooks/useBoundDetection.js +56 -22
  99. package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
  100. package/dist/recyclerview/hooks/useLayoutState.d.ts +3 -1
  101. package/dist/recyclerview/hooks/useLayoutState.d.ts.map +1 -1
  102. package/dist/recyclerview/hooks/useLayoutState.js +5 -3
  103. package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
  104. package/dist/recyclerview/hooks/useMappingHelper.d.ts +1 -1
  105. package/dist/recyclerview/hooks/useMappingHelper.d.ts.map +1 -1
  106. package/dist/recyclerview/hooks/useMappingHelper.js +1 -1
  107. package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
  108. package/dist/recyclerview/hooks/useOnLoad.d.ts.map +1 -1
  109. package/dist/recyclerview/hooks/useOnLoad.js +4 -6
  110. package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
  111. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts +5 -49
  112. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
  113. package/dist/recyclerview/hooks/useRecyclerViewController.js +315 -204
  114. package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
  115. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts +2 -0
  116. package/dist/recyclerview/hooks/useRecyclerViewManager.d.ts.map +1 -1
  117. package/dist/recyclerview/hooks/useRecyclerViewManager.js +11 -1
  118. package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
  119. package/dist/recyclerview/hooks/useRecyclingState.d.ts +4 -2
  120. package/dist/recyclerview/hooks/useRecyclingState.d.ts.map +1 -1
  121. package/dist/recyclerview/hooks/useRecyclingState.js +2 -2
  122. package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
  123. package/dist/recyclerview/hooks/useSecondaryProps.js +1 -1
  124. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts +10 -3
  125. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.d.ts.map +1 -1
  126. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +33 -4
  127. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
  128. package/dist/recyclerview/hooks/useUnmountFlag.d.ts.map +1 -1
  129. package/dist/recyclerview/hooks/useUnmountFlag.js +1 -0
  130. package/dist/recyclerview/hooks/useUnmountFlag.js.map +1 -1
  131. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts +18 -4
  132. package/dist/recyclerview/layout-managers/GridLayoutManager.d.ts.map +1 -1
  133. package/dist/recyclerview/layout-managers/GridLayoutManager.js +60 -21
  134. package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
  135. package/dist/recyclerview/layout-managers/LayoutManager.d.ts +35 -21
  136. package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
  137. package/dist/recyclerview/layout-managers/LayoutManager.js +92 -28
  138. package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
  139. package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts +9 -1
  140. package/dist/recyclerview/layout-managers/MasonryLayoutManager.d.ts.map +1 -1
  141. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +28 -12
  142. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
  143. package/dist/recyclerview/utils/measureLayout.web.d.ts.map +1 -1
  144. package/dist/recyclerview/utils/measureLayout.web.js +1 -3
  145. package/dist/recyclerview/utils/measureLayout.web.js.map +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/dist/viewability/ViewToken.d.ts +2 -2
  148. package/dist/viewability/ViewToken.d.ts.map +1 -1
  149. package/dist/viewability/ViewabilityHelper.js +1 -1
  150. package/dist/viewability/ViewabilityHelper.js.map +1 -1
  151. package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
  152. package/dist/viewability/ViewabilityManager.js +11 -5
  153. package/dist/viewability/ViewabilityManager.js.map +1 -1
  154. package/jestSetup.js +30 -11
  155. package/package.json +2 -1
  156. package/src/AnimatedFlashList.ts +3 -2
  157. package/src/FlashList.tsx +24 -0
  158. package/src/FlashListProps.ts +41 -10
  159. package/src/FlashListRef.ts +320 -0
  160. package/src/MasonryFlashList.tsx +2 -2
  161. package/src/__tests__/RecyclerView.test.tsx +106 -31
  162. package/src/__tests__/RenderStackManager.test.ts +574 -0
  163. package/src/__tests__/helpers/createLayoutManager.ts +2 -3
  164. package/src/__tests__/useUnmountAwareCallbacks.test.tsx +12 -12
  165. package/src/benchmark/useBenchmark.ts +0 -37
  166. package/src/benchmark/useFlatListBenchmark.ts +2 -2
  167. package/src/index.ts +2 -1
  168. package/src/native/config/PlatformHelper.android.ts +1 -0
  169. package/src/native/config/PlatformHelper.ios.ts +1 -0
  170. package/src/native/config/PlatformHelper.ts +1 -0
  171. package/src/native/config/PlatformHelper.web.ts +1 -0
  172. package/src/recyclerview/RecyclerView.tsx +139 -75
  173. package/src/recyclerview/RecyclerViewContextProvider.ts +52 -7
  174. package/src/recyclerview/RecyclerViewManager.ts +135 -98
  175. package/src/recyclerview/RenderStackManager.ts +317 -0
  176. package/src/recyclerview/ViewHolder.tsx +5 -3
  177. package/src/recyclerview/ViewHolderCollection.tsx +42 -14
  178. package/src/recyclerview/components/ScrollAnchor.tsx +21 -9
  179. package/src/recyclerview/components/StickyHeaders.tsx +63 -45
  180. package/src/recyclerview/helpers/EngagedIndicesTracker.ts +118 -23
  181. package/src/recyclerview/helpers/RenderTimeTracker.ts +42 -0
  182. package/src/recyclerview/helpers/VelocityTracker.ts +77 -0
  183. package/src/recyclerview/hooks/useBoundDetection.ts +72 -23
  184. package/src/recyclerview/hooks/useLayoutState.ts +15 -6
  185. package/src/recyclerview/hooks/useMappingHelper.ts +1 -1
  186. package/src/recyclerview/hooks/useOnLoad.ts +4 -6
  187. package/src/recyclerview/hooks/useRecyclerViewController.tsx +364 -254
  188. package/src/recyclerview/hooks/useRecyclerViewManager.ts +13 -1
  189. package/src/recyclerview/hooks/useRecyclingState.ts +11 -7
  190. package/src/recyclerview/hooks/useSecondaryProps.tsx +1 -1
  191. package/src/recyclerview/hooks/useUnmountAwareCallbacks.ts +39 -3
  192. package/src/recyclerview/hooks/useUnmountFlag.ts +1 -0
  193. package/src/recyclerview/layout-managers/GridLayoutManager.ts +67 -23
  194. package/src/recyclerview/layout-managers/LayoutManager.ts +110 -41
  195. package/src/recyclerview/layout-managers/MasonryLayoutManager.ts +30 -8
  196. package/src/recyclerview/utils/measureLayout.web.ts +1 -3
  197. package/src/viewability/ViewToken.ts +2 -2
  198. package/src/viewability/ViewabilityHelper.ts +1 -1
  199. package/src/viewability/ViewabilityManager.ts +16 -9
  200. package/dist/__tests__/RecycleKeyManager.test.d.ts +0 -2
  201. package/dist/__tests__/RecycleKeyManager.test.d.ts.map +0 -1
  202. package/dist/__tests__/RecycleKeyManager.test.js +0 -210
  203. package/dist/__tests__/RecycleKeyManager.test.js.map +0 -1
  204. package/dist/recyclerview/RecycleKeyManager.d.ts +0 -82
  205. package/dist/recyclerview/RecycleKeyManager.d.ts.map +0 -1
  206. package/dist/recyclerview/RecycleKeyManager.js +0 -135
  207. package/dist/recyclerview/RecycleKeyManager.js.map +0 -1
  208. package/src/__tests__/RecycleKeyManager.test.ts +0 -254
  209. package/src/recyclerview/RecycleKeyManager.ts +0 -185
@@ -24,151 +24,150 @@ var useUnmountAwareCallbacks_1 = require("./useUnmountAwareCallbacks");
24
24
  * @param scrollAnchorRef - Reference to the scroll anchor component
25
25
  * @param props - The RecyclerViewProps containing configuration
26
26
  */
27
- function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scrollAnchorRef, props) {
27
+ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scrollAnchorRef) {
28
28
  var _this = this;
29
- var _a;
30
- var horizontal = props.horizontal, data = props.data;
31
29
  var isUnmounted = (0, useUnmountFlag_1.useUnmountFlag)();
32
- var _b = tslib_1.__read((0, react_1.useState)(0), 2), _ = _b[0], setRenderId = _b[1];
33
- var pauseAdjustRef = (0, react_1.useRef)(false);
30
+ var _a = tslib_1.__read((0, react_1.useState)(0), 2), _ = _a[0], setRenderId = _a[1];
31
+ var pauseOffsetCorrection = (0, react_1.useRef)(false);
34
32
  var initialScrollCompletedRef = (0, react_1.useRef)(false);
35
- var lastDataLengthRef = (0, react_1.useRef)((_a = data === null || data === void 0 ? void 0 : data.length) !== null && _a !== void 0 ? _a : 0);
36
- var setTimeout = (0, useUnmountAwareCallbacks_1.useUnmountAwareCallbacks)().setTimeout;
33
+ var lastDataLengthRef = (0, react_1.useRef)(recyclerViewManager.getDataLength());
34
+ var setTimeout = (0, useUnmountAwareCallbacks_1.useUnmountAwareTimeout)().setTimeout;
37
35
  // Track the first visible item for maintaining scroll position
38
36
  var firstVisibleItemKey = (0, react_1.useRef)(undefined);
39
37
  var firstVisibleItemLayout = (0, react_1.useRef)(undefined);
40
- var pendingScrollResolves = (0, react_1.useRef)([]);
41
- var applyInitialScrollIndex = (0, react_1.useCallback)(function () {
42
- var _a, _b, _c;
43
- var initialScrollIndex = (_a = recyclerViewManager.getInitialScrollIndex()) !== null && _a !== void 0 ? _a : -1;
44
- var dataLength = (_c = (_b = props.data) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
45
- if (initialScrollIndex >= 0 &&
46
- initialScrollIndex < dataLength &&
47
- !initialScrollCompletedRef.current &&
48
- recyclerViewManager.getIsFirstLayoutComplete()) {
49
- // Use setTimeout to ensure that we keep trying to scroll on first few renders
50
- setTimeout(function () {
51
- initialScrollCompletedRef.current = true;
52
- pauseAdjustRef.current = false;
53
- }, 100);
54
- pauseAdjustRef.current = true;
55
- var offset_1 = horizontal
56
- ? recyclerViewManager.getLayout(initialScrollIndex).x
57
- : recyclerViewManager.getLayout(initialScrollIndex).y;
58
- handlerMethods.scrollToOffset({
59
- offset: offset_1,
60
- animated: false,
61
- skipFirstItemOffset: false,
62
- });
63
- setTimeout(function () {
64
- handlerMethods.scrollToOffset({
65
- offset: offset_1,
66
- animated: false,
67
- skipFirstItemOffset: false,
68
- });
69
- }, 0);
70
- }
71
- }, [recyclerViewManager, props.data]);
38
+ // Queue to store callbacks that should be executed after scroll offset updates
39
+ var pendingScrollCallbacks = (0, react_1.useRef)([]);
72
40
  // Handle initial scroll position when the list first loads
73
41
  // useOnLoad(recyclerViewManager, () => {
74
42
  // });
75
43
  /**
76
- * Updates the scroll offset and returns a Promise that resolves
77
- * when the update has been applied.
44
+ * Updates the scroll offset and calls the provided callback
45
+ * after the update has been applied and the component has re-rendered.
46
+ *
47
+ * @param offset - The new scroll offset to apply
48
+ * @param callback - Optional callback to execute after the update is applied
78
49
  */
79
- var updateScrollOffsetAsync = (0, react_1.useCallback)(function (offset) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
80
- return tslib_1.__generator(this, function (_a) {
81
- return [2 /*return*/, new Promise(function (resolve) {
82
- // TODO: Make sure we don't scroll beyond content size
83
- if (recyclerViewManager.updateScrollOffset(offset) !== undefined) {
84
- // Add the resolve function to the queue
85
- pendingScrollResolves.current.push(resolve);
86
- setRenderId(function (prev) { return prev + 1; });
87
- }
88
- else {
89
- resolve();
90
- }
91
- })];
92
- });
93
- }); }, [recyclerViewManager]);
50
+ var updateScrollOffsetWithCallback = (0, react_1.useCallback)(function (offset, callback) {
51
+ // Attempt to update the scroll offset in the RecyclerViewManager
52
+ // This returns undefined if no update is needed
53
+ if (recyclerViewManager.updateScrollOffset(offset) !== undefined) {
54
+ // It will be executed after the next render
55
+ pendingScrollCallbacks.current.push(callback);
56
+ // Trigger a re-render to apply the scroll offset update
57
+ setRenderId(function (prev) { return prev + 1; });
58
+ }
59
+ else {
60
+ // No update needed, execute callback immediately
61
+ callback();
62
+ }
63
+ }, [recyclerViewManager]);
64
+ var computeFirstVisibleIndexForOffsetCorrection = (0, react_1.useCallback)(function () {
65
+ var _a = recyclerViewManager.props, data = _a.data, keyExtractor = _a.keyExtractor;
66
+ if (recyclerViewManager.getIsFirstLayoutComplete() &&
67
+ keyExtractor &&
68
+ recyclerViewManager.getDataLength() > 0 &&
69
+ recyclerViewManager.shouldMaintainVisibleContentPosition()) {
70
+ // Update the tracked first visible item
71
+ var firstVisibleIndex = Math.max(0, recyclerViewManager.computeVisibleIndices().startIndex);
72
+ if (firstVisibleIndex !== undefined && firstVisibleIndex >= 0) {
73
+ firstVisibleItemKey.current = keyExtractor(data[firstVisibleIndex], firstVisibleIndex);
74
+ firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(firstVisibleIndex));
75
+ }
76
+ }
77
+ }, [recyclerViewManager]);
94
78
  /**
95
79
  * Maintains the visible content position when the list updates.
96
80
  * This is particularly useful for chat applications where we want to keep
97
81
  * the user's current view position when new messages are added.
98
82
  */
99
- var applyContentOffset = (0, react_1.useCallback)(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
100
- var resolves, currentDataLength, hasDataChanged, currentIndexOfFirstVisibleItem, diff, firstVisibleIndex;
101
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
102
- return tslib_1.__generator(this, function (_k) {
103
- resolves = pendingScrollResolves.current;
104
- pendingScrollResolves.current = [];
105
- resolves.forEach(function (resolve) { return resolve(); });
106
- currentDataLength = (_b = (_a = props.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
107
- if (!props.horizontal &&
108
- recyclerViewManager.getIsFirstLayoutComplete() &&
109
- props.keyExtractor &&
110
- currentDataLength > 0 &&
111
- ((_c = props.maintainVisibleContentPosition) === null || _c === void 0 ? void 0 : _c.disabled) !== true) {
112
- hasDataChanged = currentDataLength !== lastDataLengthRef.current;
113
- // If we have a tracked first visible item, maintain its position
114
- if (firstVisibleItemKey.current) {
115
- currentIndexOfFirstVisibleItem = (_d = recyclerViewManager
116
- .getEngagedIndices()
117
- .findValue(function (index) {
118
- var _a;
119
- return ((_a = props.keyExtractor) === null || _a === void 0 ? void 0 : _a.call(props, props.data[index], index)) ===
120
- firstVisibleItemKey.current;
121
- })) !== null && _d !== void 0 ? _d : (hasDataChanged
122
- ? (_e = props.data) === null || _e === void 0 ? void 0 : _e.findIndex(function (item, index) {
123
- var _a;
124
- return ((_a = props.keyExtractor) === null || _a === void 0 ? void 0 : _a.call(props, item, index)) ===
125
- firstVisibleItemKey.current;
126
- })
127
- : undefined);
128
- if (currentIndexOfFirstVisibleItem !== undefined) {
129
- diff = recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem).y -
83
+ var applyOffsetCorrection = (0, react_1.useCallback)(function () {
84
+ var _a, _b, _c;
85
+ var _d = recyclerViewManager.props, horizontal = _d.horizontal, data = _d.data, keyExtractor = _d.keyExtractor;
86
+ // Execute all pending callbacks from previous scroll offset updates
87
+ // This ensures any scroll operations that were waiting for render are completed
88
+ var callbacks = pendingScrollCallbacks.current;
89
+ pendingScrollCallbacks.current = [];
90
+ callbacks.forEach(function (callback) { return callback(); });
91
+ var currentDataLength = recyclerViewManager.getDataLength();
92
+ if (recyclerViewManager.getIsFirstLayoutComplete() &&
93
+ keyExtractor &&
94
+ currentDataLength > 0 &&
95
+ recyclerViewManager.shouldMaintainVisibleContentPosition()) {
96
+ var hasDataChanged = currentDataLength !== lastDataLengthRef.current;
97
+ // If we have a tracked first visible item, maintain its position
98
+ if (firstVisibleItemKey.current) {
99
+ var currentIndexOfFirstVisibleItem = (_a = recyclerViewManager
100
+ .getEngagedIndices()
101
+ .findValue(function (index) {
102
+ return (keyExtractor === null || keyExtractor === void 0 ? void 0 : keyExtractor(data[index], index)) ===
103
+ firstVisibleItemKey.current;
104
+ })) !== null && _a !== void 0 ? _a : (hasDataChanged
105
+ ? data === null || data === void 0 ? void 0 : data.findIndex(function (item, index) {
106
+ return (keyExtractor === null || keyExtractor === void 0 ? void 0 : keyExtractor(item, index)) === firstVisibleItemKey.current;
107
+ })
108
+ : undefined);
109
+ if (currentIndexOfFirstVisibleItem !== undefined &&
110
+ currentIndexOfFirstVisibleItem >= 0) {
111
+ // Calculate the difference in position and apply the offset
112
+ var diff = horizontal
113
+ ? recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem).x -
114
+ firstVisibleItemLayout.current.x
115
+ : recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem).y -
130
116
  firstVisibleItemLayout.current.y;
131
- firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem));
132
- if (diff !== 0 && !pauseAdjustRef.current) {
133
- // console.log("diff", diff, firstVisibleItemKey.current);
134
- if (PlatformHelper_1.PlatformConfig.supportsOffsetCorrection) {
135
- (_f = scrollAnchorRef.current) === null || _f === void 0 ? void 0 : _f.scrollBy(diff);
136
- }
137
- else {
138
- (_g = scrollViewRef.current) === null || _g === void 0 ? void 0 : _g.scrollTo({
117
+ firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(currentIndexOfFirstVisibleItem));
118
+ if (diff !== 0 &&
119
+ !pauseOffsetCorrection.current &&
120
+ !recyclerViewManager.animationOptimizationsEnabled) {
121
+ // console.log("diff", diff, firstVisibleItemKey.current);
122
+ if (PlatformHelper_1.PlatformConfig.supportsOffsetCorrection) {
123
+ // console.log("scrollBy", diff);
124
+ (_b = scrollAnchorRef.current) === null || _b === void 0 ? void 0 : _b.scrollBy(diff);
125
+ }
126
+ else {
127
+ var scrollToParams = horizontal
128
+ ? {
129
+ x: recyclerViewManager.getAbsoluteLastScrollOffset() + diff,
130
+ animated: false,
131
+ }
132
+ : {
139
133
  y: recyclerViewManager.getAbsoluteLastScrollOffset() + diff,
140
134
  animated: false,
141
- });
142
- }
143
- if (hasDataChanged) {
144
- updateScrollOffsetAsync(recyclerViewManager.getAbsoluteLastScrollOffset() + diff);
145
- recyclerViewManager.ignoreScrollEvents = true;
146
- setTimeout(function () {
147
- recyclerViewManager.ignoreScrollEvents = false;
148
- }, 100);
149
- }
135
+ };
136
+ (_c = scrollViewRef.current) === null || _c === void 0 ? void 0 : _c.scrollTo(scrollToParams);
137
+ }
138
+ if (hasDataChanged) {
139
+ updateScrollOffsetWithCallback(recyclerViewManager.getAbsoluteLastScrollOffset() + diff, function () { });
140
+ recyclerViewManager.ignoreScrollEvents = true;
141
+ setTimeout(function () {
142
+ recyclerViewManager.ignoreScrollEvents = false;
143
+ }, 100);
150
144
  }
151
145
  }
152
146
  }
153
- firstVisibleIndex = Math.max(0, recyclerViewManager.getVisibleIndices().startIndex);
154
- if (firstVisibleIndex !== undefined && firstVisibleIndex >= 0) {
155
- firstVisibleItemKey.current = props.keyExtractor(props.data[firstVisibleIndex], firstVisibleIndex);
156
- firstVisibleItemLayout.current = tslib_1.__assign({}, recyclerViewManager.getLayout(firstVisibleIndex));
157
- }
158
147
  }
159
- lastDataLengthRef.current = (_j = (_h = props.data) === null || _h === void 0 ? void 0 : _h.length) !== null && _j !== void 0 ? _j : 0;
160
- return [2 /*return*/];
161
- });
162
- }); }, [props.data, props.keyExtractor, recyclerViewManager, setTimeout]);
148
+ computeFirstVisibleIndexForOffsetCorrection();
149
+ }
150
+ lastDataLengthRef.current = recyclerViewManager.getDataLength();
151
+ }, [
152
+ recyclerViewManager,
153
+ scrollAnchorRef,
154
+ scrollViewRef,
155
+ setTimeout,
156
+ updateScrollOffsetWithCallback,
157
+ computeFirstVisibleIndexForOffsetCorrection,
158
+ ]);
163
159
  var handlerMethods = (0, react_1.useMemo)(function () {
164
160
  return {
165
- props: props,
161
+ get props() {
162
+ return recyclerViewManager.props;
163
+ },
166
164
  /**
167
165
  * Scrolls the list to a specific offset position.
168
166
  * Handles RTL layouts and first item offset adjustments.
169
167
  */
170
168
  scrollToOffset: function (_a) {
171
169
  var offset = _a.offset, animated = _a.animated, _b = _a.skipFirstItemOffset, skipFirstItemOffset = _b === void 0 ? true : _b;
170
+ var horizontal = recyclerViewManager.props.horizontal;
172
171
  if (scrollViewRef.current) {
173
172
  // Adjust offset for RTL layouts in horizontal mode
174
173
  if (react_native_1.I18nManager.isRTL && horizontal) {
@@ -188,6 +187,9 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
188
187
  scrollViewRef.current.scrollTo(tslib_1.__assign(tslib_1.__assign({}, scrollTo_1), { animated: animated }));
189
188
  }
190
189
  },
190
+ clearLayoutCacheOnUpdate: function () {
191
+ recyclerViewManager.markLayoutManagerDirty();
192
+ },
191
193
  // Expose native scroll view methods
192
194
  flashScrollIndicators: function () {
193
195
  scrollViewRef.current.flashScrollIndicators();
@@ -210,10 +212,12 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
210
212
  args_1[_i] = arguments[_i];
211
213
  }
212
214
  return tslib_1.__awaiter(_this, tslib_1.__spreadArray([], tslib_1.__read(args_1), false), void 0, function (_a) {
215
+ var data;
213
216
  var _b = _a === void 0 ? {} : _a, animated = _b.animated;
214
217
  return tslib_1.__generator(this, function (_c) {
215
218
  switch (_c.label) {
216
219
  case 0:
220
+ data = recyclerViewManager.props.data;
217
221
  if (!(data && data.length > 0)) return [3 /*break*/, 2];
218
222
  return [4 /*yield*/, handlerMethods.scrollToIndex({
219
223
  index: data.length - 1,
@@ -223,7 +227,9 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
223
227
  _c.sent();
224
228
  _c.label = 2;
225
229
  case 2:
226
- scrollViewRef.current.scrollToEnd({ animated: animated });
230
+ setTimeout(function () {
231
+ scrollViewRef.current.scrollToEnd({ animated: animated });
232
+ }, 0);
227
233
  return [2 /*return*/];
228
234
  }
229
235
  });
@@ -242,117 +248,169 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
242
248
  /**
243
249
  * Scrolls to a specific index in the list.
244
250
  * Supports viewPosition and viewOffset for precise positioning.
251
+ * Returns a Promise that resolves when the scroll is complete.
245
252
  */
246
- scrollToIndex: function (_a) { return tslib_1.__awaiter(_this, [_a], void 0, function (_b) {
247
- var getFinalOffset, lastScrollOffset, finalOffset, bufferForScroll, bufferForCompute, i, i, maxOffset;
248
- var index = _b.index, animated = _b.animated, viewPosition = _b.viewPosition, viewOffset = _b.viewOffset;
249
- return tslib_1.__generator(this, function (_c) {
250
- switch (_c.label) {
251
- case 0:
252
- if (!(scrollViewRef.current && data && data.length > index)) return [3 /*break*/, 10];
253
- pauseAdjustRef.current = true;
254
- getFinalOffset = function () {
255
- var layout = recyclerViewManager.getLayout(index);
256
- var offset = horizontal ? layout.x : layout.y;
257
- var finalOffset = offset;
258
- // take viewPosition etc into account
259
- if (viewPosition !== undefined || viewOffset !== undefined) {
260
- var containerSize = horizontal
261
- ? recyclerViewManager.getWindowSize().width
262
- : recyclerViewManager.getWindowSize().height;
263
- var itemSize = horizontal ? layout.width : layout.height;
264
- if (viewPosition !== undefined) {
265
- // viewPosition: 0 = top, 0.5 = center, 1 = bottom
266
- finalOffset =
267
- offset - (containerSize - itemSize) * viewPosition;
268
- }
269
- if (viewOffset !== undefined) {
270
- finalOffset += viewOffset;
271
- }
253
+ scrollToIndex: function (_a) {
254
+ var index = _a.index, animated = _a.animated, viewPosition = _a.viewPosition, viewOffset = _a.viewOffset;
255
+ return new Promise(function (resolve) {
256
+ var horizontal = recyclerViewManager.props.horizontal;
257
+ if (scrollViewRef.current &&
258
+ index >= 0 &&
259
+ index < recyclerViewManager.getDataLength()) {
260
+ // Pause the scroll offset adjustments
261
+ pauseOffsetCorrection.current = true;
262
+ recyclerViewManager.setOffsetProjectionEnabled(false);
263
+ var getFinalOffset_1 = function () {
264
+ var layout = recyclerViewManager.getLayout(index);
265
+ var offset = horizontal ? layout.x : layout.y;
266
+ var finalOffset = offset;
267
+ // take viewPosition etc into account
268
+ if (viewPosition !== undefined || viewOffset !== undefined) {
269
+ var containerSize = horizontal
270
+ ? recyclerViewManager.getWindowSize().width
271
+ : recyclerViewManager.getWindowSize().height;
272
+ var itemSize = horizontal ? layout.width : layout.height;
273
+ if (viewPosition !== undefined) {
274
+ // viewPosition: 0 = top, 0.5 = center, 1 = bottom
275
+ finalOffset =
276
+ offset - (containerSize - itemSize) * viewPosition;
272
277
  }
273
- return finalOffset;
274
- };
275
- lastScrollOffset = recyclerViewManager.getLastScrollOffset();
276
- finalOffset = getFinalOffset();
277
- bufferForScroll = horizontal
278
- ? recyclerViewManager.getWindowSize().width
279
- : recyclerViewManager.getWindowSize().height;
280
- bufferForCompute = bufferForScroll * 2;
278
+ if (viewOffset !== undefined) {
279
+ finalOffset += viewOffset;
280
+ }
281
+ }
282
+ return finalOffset + recyclerViewManager.firstItemOffset;
283
+ };
284
+ var lastAbsoluteScrollOffset_1 = recyclerViewManager.getAbsoluteLastScrollOffset();
285
+ var bufferForScroll = horizontal
286
+ ? recyclerViewManager.getWindowSize().width
287
+ : recyclerViewManager.getWindowSize().height;
288
+ var bufferForCompute_1 = bufferForScroll * 2;
289
+ var getStartScrollOffset_1 = function () {
290
+ var lastScrollOffset = lastAbsoluteScrollOffset_1;
291
+ var finalOffset = getFinalOffset_1();
281
292
  if (finalOffset > lastScrollOffset) {
282
- lastScrollOffset = Math.max(finalOffset - bufferForCompute, lastScrollOffset);
293
+ lastScrollOffset = Math.max(finalOffset - bufferForCompute_1, lastScrollOffset);
283
294
  recyclerViewManager.setScrollDirection("forward");
284
295
  }
285
296
  else {
286
- lastScrollOffset = Math.min(finalOffset + bufferForCompute, lastScrollOffset);
297
+ lastScrollOffset = Math.min(finalOffset + bufferForCompute_1, lastScrollOffset);
287
298
  recyclerViewManager.setScrollDirection("backward");
288
299
  }
289
- if (!animated) return [3 /*break*/, 5];
290
- i = 0;
291
- _c.label = 1;
292
- case 1:
293
- if (!(i < 5)) return [3 /*break*/, 4];
300
+ return lastScrollOffset;
301
+ };
302
+ var initialTargetOffset_1 = getFinalOffset_1();
303
+ var initialStartScrollOffset_1 = getStartScrollOffset_1();
304
+ var finalOffset_1 = initialTargetOffset_1;
305
+ var startScrollOffset_1 = initialStartScrollOffset_1;
306
+ var steps_1 = 5;
307
+ /**
308
+ * Recursively performs the scroll animation steps.
309
+ * This function replaces the async/await loop with callback-based execution.
310
+ *
311
+ * @param currentStep - The current step in the animation (0 to steps-1)
312
+ */
313
+ var performScrollStep_1 = function (currentStep) {
314
+ // Check if component is unmounted or we've completed all steps
294
315
  if (isUnmounted.current) {
295
- return [2 /*return*/];
316
+ resolve();
317
+ return;
296
318
  }
297
- return [4 /*yield*/, updateScrollOffsetAsync(finalOffset + (lastScrollOffset - finalOffset) * (i / 4))];
298
- case 2:
299
- _c.sent();
300
- _c.label = 3;
301
- case 3:
302
- i++;
303
- return [3 /*break*/, 1];
304
- case 4: return [3 /*break*/, 9];
305
- case 5:
306
- i = 0;
307
- _c.label = 6;
308
- case 6:
309
- if (!(i < 5)) return [3 /*break*/, 9];
310
- if (isUnmounted.current) {
311
- return [2 /*return*/];
319
+ else if (currentStep >= steps_1) {
320
+ // All steps completed, perform final scroll
321
+ finishScrollToIndex_1();
322
+ return;
312
323
  }
313
- return [4 /*yield*/, updateScrollOffsetAsync(lastScrollOffset + (finalOffset - lastScrollOffset) * (i / 4))];
314
- case 7:
315
- _c.sent();
316
- _c.label = 8;
317
- case 8:
318
- i++;
319
- return [3 /*break*/, 6];
320
- case 9:
321
- finalOffset = getFinalOffset();
322
- maxOffset = recyclerViewManager.getMaxScrollOffset();
323
- if (finalOffset > maxOffset) {
324
- finalOffset = maxOffset;
324
+ // Calculate the offset for this step
325
+ // For animated scrolls: interpolate from finalOffset to startScrollOffset
326
+ // For non-animated: interpolate from startScrollOffset to finalOffset
327
+ var nextOffset = animated
328
+ ? finalOffset_1 +
329
+ (startScrollOffset_1 - finalOffset_1) *
330
+ (currentStep / (steps_1 - 1))
331
+ : startScrollOffset_1 +
332
+ (finalOffset_1 - startScrollOffset_1) *
333
+ (currentStep / (steps_1 - 1));
334
+ // Update scroll offset with a callback to continue to the next step
335
+ updateScrollOffsetWithCallback(nextOffset, function () {
336
+ // Check if the index is still valid after the update
337
+ if (index >= recyclerViewManager.getDataLength()) {
338
+ // Index out of bounds, scroll to end instead
339
+ handlerMethods.scrollToEnd({ animated: animated });
340
+ resolve(); // Resolve the promise as we're done
341
+ return;
342
+ }
343
+ // Check if the target position has changed significantly
344
+ var newFinalOffset = getFinalOffset_1();
345
+ if ((newFinalOffset < initialTargetOffset_1 &&
346
+ newFinalOffset < initialStartScrollOffset_1) ||
347
+ (newFinalOffset > initialTargetOffset_1 &&
348
+ newFinalOffset > initialStartScrollOffset_1)) {
349
+ // Target has moved, recalculate and restart from beginning
350
+ finalOffset_1 = newFinalOffset;
351
+ startScrollOffset_1 = getStartScrollOffset_1();
352
+ initialTargetOffset_1 = newFinalOffset;
353
+ initialStartScrollOffset_1 = startScrollOffset_1;
354
+ performScrollStep_1(0); // Restart from step 0
355
+ }
356
+ else {
357
+ // Continue to next step
358
+ performScrollStep_1(currentStep + 1);
359
+ }
360
+ });
361
+ };
362
+ /**
363
+ * Completes the scroll to index operation by performing the final scroll
364
+ * and re-enabling offset correction after a delay.
365
+ */
366
+ var finishScrollToIndex_1 = function () {
367
+ finalOffset_1 = getFinalOffset_1();
368
+ var maxOffset = recyclerViewManager.getMaxScrollOffset();
369
+ if (finalOffset_1 > maxOffset) {
370
+ finalOffset_1 = maxOffset;
325
371
  }
326
372
  if (animated) {
327
- // We don't need to add firstItemOffset here as it will be added in scrollToOffset
373
+ // For animated scrolls, first jump to the start position
374
+ // We don't need to add firstItemOffset here as it's already added
328
375
  handlerMethods.scrollToOffset({
329
- offset: lastScrollOffset,
376
+ offset: startScrollOffset_1,
330
377
  animated: false,
331
- skipFirstItemOffset: false,
378
+ skipFirstItemOffset: true,
332
379
  });
333
380
  }
381
+ // Perform the final scroll to the target position
334
382
  handlerMethods.scrollToOffset({
335
- offset: finalOffset,
383
+ offset: finalOffset_1,
336
384
  animated: animated,
337
- skipFirstItemOffset: false,
385
+ skipFirstItemOffset: true,
338
386
  });
387
+ // Re-enable offset correction after a delay
388
+ // Longer delay for animated scrolls to allow animation to complete
339
389
  setTimeout(function () {
340
- pauseAdjustRef.current = false;
341
- }, 200);
342
- _c.label = 10;
343
- case 10: return [2 /*return*/];
390
+ pauseOffsetCorrection.current = false;
391
+ recyclerViewManager.setOffsetProjectionEnabled(true);
392
+ resolve(); // Resolve the promise after re-enabling corrections
393
+ }, animated ? 300 : 200);
394
+ };
395
+ // Start the scroll animation process
396
+ performScrollStep_1(0);
397
+ }
398
+ else {
399
+ // Invalid parameters, resolve immediately
400
+ resolve();
344
401
  }
345
402
  });
346
- }); },
403
+ },
347
404
  /**
348
405
  * Scrolls to a specific item in the list.
349
406
  * Finds the item's index and uses scrollToIndex internally.
350
407
  */
351
408
  scrollToItem: function (_a) {
352
409
  var item = _a.item, animated = _a.animated, viewPosition = _a.viewPosition, viewOffset = _a.viewOffset;
410
+ var data = recyclerViewManager.props.data;
353
411
  if (scrollViewRef.current && data) {
354
412
  // Find the index of the item in the data array
355
- var index = Array.from(data).findIndex(function (dataItem) { return dataItem === item; });
413
+ var index = data.findIndex(function (dataItem) { return dataItem === item; });
356
414
  if (index >= 0) {
357
415
  handlerMethods.scrollToIndex({
358
416
  index: index,
@@ -371,7 +429,7 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
371
429
  return recyclerViewManager.getWindowSize();
372
430
  },
373
431
  getLayout: function (index) {
374
- return recyclerViewManager.getLayout(index);
432
+ return recyclerViewManager.tryGetLayout(index);
375
433
  },
376
434
  getAbsoluteLastScrollOffset: function () {
377
435
  return recyclerViewManager.getAbsoluteLastScrollOffset();
@@ -382,11 +440,11 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
382
440
  recordInteraction: function () {
383
441
  recyclerViewManager.recordInteraction();
384
442
  },
385
- getVisibleIndices: function () {
386
- return recyclerViewManager.getVisibleIndices();
443
+ computeVisibleIndices: function () {
444
+ return recyclerViewManager.computeVisibleIndices();
387
445
  },
388
446
  getFirstVisibleIndex: function () {
389
- return recyclerViewManager.getVisibleIndices().startIndex;
447
+ return recyclerViewManager.computeVisibleIndices().startIndex;
390
448
  },
391
449
  recomputeViewableItems: function () {
392
450
  recyclerViewManager.recomputeViewableItems();
@@ -395,14 +453,67 @@ function useRecyclerViewController(recyclerViewManager, ref, scrollViewRef, scro
395
453
  * Disables item recycling in preparation for layout animations.
396
454
  */
397
455
  prepareForLayoutAnimationRender: function () {
398
- recyclerViewManager.disableRecycling = true;
456
+ recyclerViewManager.animationOptimizationsEnabled = true;
399
457
  },
400
458
  };
401
- }, [horizontal, data, recyclerViewManager]);
459
+ }, [
460
+ recyclerViewManager,
461
+ scrollViewRef,
462
+ setTimeout,
463
+ isUnmounted,
464
+ updateScrollOffsetWithCallback,
465
+ ]);
466
+ var applyInitialScrollIndex = (0, react_1.useCallback)(function () {
467
+ var _a, _b;
468
+ var _c = recyclerViewManager.props, horizontal = _c.horizontal, data = _c.data;
469
+ var initialScrollIndex = (_a = recyclerViewManager.getInitialScrollIndex()) !== null && _a !== void 0 ? _a : -1;
470
+ var dataLength = (_b = data === null || data === void 0 ? void 0 : data.length) !== null && _b !== void 0 ? _b : 0;
471
+ if (initialScrollIndex >= 0 &&
472
+ initialScrollIndex < dataLength &&
473
+ !initialScrollCompletedRef.current &&
474
+ recyclerViewManager.getIsFirstLayoutComplete()) {
475
+ // Use setTimeout to ensure that we keep trying to scroll on first few renders
476
+ setTimeout(function () {
477
+ initialScrollCompletedRef.current = true;
478
+ pauseOffsetCorrection.current = false;
479
+ }, 100);
480
+ pauseOffsetCorrection.current = true;
481
+ var offset_1 = horizontal
482
+ ? recyclerViewManager.getLayout(initialScrollIndex).x
483
+ : recyclerViewManager.getLayout(initialScrollIndex).y;
484
+ handlerMethods.scrollToOffset({
485
+ offset: offset_1,
486
+ animated: false,
487
+ skipFirstItemOffset: false,
488
+ });
489
+ setTimeout(function () {
490
+ handlerMethods.scrollToOffset({
491
+ offset: offset_1,
492
+ animated: false,
493
+ skipFirstItemOffset: false,
494
+ });
495
+ }, 0);
496
+ }
497
+ }, [handlerMethods, recyclerViewManager, setTimeout]);
402
498
  // Expose imperative methods through the ref
403
499
  (0, react_1.useImperativeHandle)(ref, function () {
404
- return tslib_1.__assign(tslib_1.__assign({}, scrollViewRef.current), handlerMethods);
405
- }, [handlerMethods]);
406
- return { applyContentOffset: applyContentOffset, applyInitialScrollIndex: applyInitialScrollIndex };
500
+ var imperativeApi = tslib_1.__assign(tslib_1.__assign({}, scrollViewRef.current), handlerMethods);
501
+ // Without this the props getter from handlerMethods is evaluated during spread and
502
+ // future updates to props are not reflected in the ref
503
+ Object.defineProperty(imperativeApi, "props", {
504
+ get: function () {
505
+ return recyclerViewManager.props;
506
+ },
507
+ enumerable: true,
508
+ configurable: true,
509
+ });
510
+ return imperativeApi;
511
+ }, [handlerMethods, scrollViewRef, recyclerViewManager]);
512
+ return {
513
+ applyOffsetCorrection: applyOffsetCorrection,
514
+ computeFirstVisibleIndexForOffsetCorrection: computeFirstVisibleIndexForOffsetCorrection,
515
+ applyInitialScrollIndex: applyInitialScrollIndex,
516
+ handlerMethods: handlerMethods,
517
+ };
407
518
  }
408
519
  //# sourceMappingURL=useRecyclerViewController.js.map