@shopify/flash-list 2.0.0-alpha.2 → 2.0.0-alpha.21

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