react-native-nitro-list 0.1.1 → 0.1.3

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 (376) hide show
  1. package/README.md +16 -44
  2. package/ios/HybridNitroList.swift +12 -14
  3. package/lib/commonjs/cell/CellKeyGenerator.js +21 -0
  4. package/lib/commonjs/cell/CellKeyGenerator.js.map +1 -0
  5. package/lib/commonjs/cell/CellRecycler.js +48 -40
  6. package/lib/commonjs/cell/CellRecycler.js.map +1 -1
  7. package/lib/commonjs/cell/createCell.js +21 -0
  8. package/lib/commonjs/cell/createCell.js.map +1 -0
  9. package/lib/commonjs/cell/index.js +20 -0
  10. package/lib/commonjs/cell/index.js.map +1 -0
  11. package/lib/commonjs/getVisibleIndices.js.map +1 -1
  12. package/lib/commonjs/hooks/usePersistentCallback.js +36 -0
  13. package/lib/commonjs/hooks/usePersistentCallback.js.map +1 -0
  14. package/lib/commonjs/index.js +31 -3
  15. package/lib/commonjs/index.js.map +1 -1
  16. package/lib/commonjs/layout/MutableLinearLayout.js +78 -39
  17. package/lib/commonjs/layout/MutableLinearLayout.js.map +1 -1
  18. package/lib/commonjs/layout/constants/layoutDefaults.js +19 -0
  19. package/lib/commonjs/layout/constants/layoutDefaults.js.map +1 -0
  20. package/lib/commonjs/layout/index.js +0 -18
  21. package/lib/commonjs/layout/index.js.map +1 -1
  22. package/lib/commonjs/native/NitroListView.js +20 -0
  23. package/lib/commonjs/native/NitroListView.js.map +1 -0
  24. package/lib/commonjs/recycler/CellPool.js +33 -0
  25. package/lib/commonjs/recycler/CellPool.js.map +1 -0
  26. package/lib/commonjs/recycler/NitroList.js +223 -0
  27. package/lib/commonjs/recycler/NitroList.js.map +1 -0
  28. package/lib/commonjs/scroll/useScrollVelocity.js +20 -0
  29. package/lib/commonjs/scroll/useScrollVelocity.js.map +1 -0
  30. package/lib/commonjs/{native/NitroList.types.js → specs/NitroList.nitro.js} +1 -1
  31. package/lib/commonjs/{layout/LayoutProvider.js.map → specs/NitroList.nitro.js.map} +1 -1
  32. package/lib/commonjs/types/Axis.js +2 -0
  33. package/lib/{module/layout/LayoutProvider.js.map → commonjs/types/Axis.js.map} +1 -1
  34. package/lib/commonjs/types/CellKey.js +2 -0
  35. package/lib/commonjs/{layout/LayoutRectangle.js.map → types/CellKey.js.map} +1 -1
  36. package/lib/commonjs/types/CellType.js +27 -0
  37. package/lib/commonjs/types/CellType.js.map +1 -0
  38. package/lib/commonjs/types/VisibleRange.js +2 -0
  39. package/lib/commonjs/{native/NitroList.types.js.map → types/VisibleRange.js.map} +1 -1
  40. package/lib/commonjs/{RecyclerList.types.js → types/VisibleRangeInput.js} +1 -1
  41. package/lib/commonjs/types/VisibleRangeInput.js.map +1 -0
  42. package/lib/commonjs/types/index.js +13 -0
  43. package/lib/commonjs/types/index.js.map +1 -0
  44. package/lib/commonjs/types/layout/LayoutRect.js +2 -0
  45. package/lib/commonjs/types/layout/LayoutRect.js.map +1 -0
  46. package/lib/commonjs/{specs/nitro-layout-engine.nitro.js → types/layout/LinearLayoutInput.js} +1 -1
  47. package/lib/commonjs/types/layout/LinearLayoutInput.js.map +1 -0
  48. package/lib/commonjs/types/layout/MainAxisPadding.js +26 -0
  49. package/lib/commonjs/types/layout/MainAxisPadding.js.map +1 -0
  50. package/lib/commonjs/types/layout/index.js +2 -0
  51. package/lib/commonjs/types/layout/index.js.map +1 -0
  52. package/lib/commonjs/types/recycler/CellPool.js +42 -0
  53. package/lib/commonjs/types/recycler/CellPool.js.map +1 -0
  54. package/lib/commonjs/{layout/LayoutProvider.js → types/recycler/NitroListProps.js} +1 -1
  55. package/lib/commonjs/types/recycler/NitroListProps.js.map +1 -0
  56. package/lib/commonjs/types/recycler/RecyclerCell.js +6 -0
  57. package/lib/commonjs/types/recycler/RecyclerCell.js.map +1 -0
  58. package/lib/commonjs/types/recycler/RecyclerItemRenderer.js +6 -0
  59. package/lib/commonjs/types/recycler/RecyclerItemRenderer.js.map +1 -0
  60. package/lib/commonjs/types/recycler/index.js +2 -0
  61. package/lib/commonjs/types/recycler/index.js.map +1 -0
  62. package/lib/commonjs/types/scroll/ScrollMetrics.js +6 -0
  63. package/lib/commonjs/types/scroll/ScrollMetrics.js.map +1 -0
  64. package/lib/commonjs/types/scroll/index.js +2 -0
  65. package/lib/commonjs/types/scroll/index.js.map +1 -0
  66. package/lib/commonjs/windowing/computeVisibleItemRange.js +61 -0
  67. package/lib/commonjs/windowing/computeVisibleItemRange.js.map +1 -0
  68. package/lib/commonjs/windowing/index.js +3 -3
  69. package/lib/commonjs/windowing/index.js.map +1 -1
  70. package/lib/module/cell/CellKeyGenerator.js +16 -0
  71. package/lib/module/cell/CellKeyGenerator.js.map +1 -0
  72. package/lib/module/cell/CellRecycler.js +48 -39
  73. package/lib/module/cell/CellRecycler.js.map +1 -1
  74. package/lib/module/cell/createCell.js +17 -0
  75. package/lib/module/cell/createCell.js.map +1 -0
  76. package/lib/module/cell/index.js +7 -0
  77. package/lib/module/cell/index.js.map +1 -0
  78. package/lib/module/getVisibleIndices.js.map +1 -1
  79. package/lib/module/hooks/usePersistentCallback.js +33 -0
  80. package/lib/module/hooks/usePersistentCallback.js.map +1 -0
  81. package/lib/module/index.js +5 -1
  82. package/lib/module/index.js.map +1 -1
  83. package/lib/module/layout/MutableLinearLayout.js +78 -38
  84. package/lib/module/layout/MutableLinearLayout.js.map +1 -1
  85. package/lib/module/layout/constants/layoutDefaults.js +15 -0
  86. package/lib/module/layout/constants/layoutDefaults.js.map +1 -0
  87. package/lib/module/layout/index.js +0 -3
  88. package/lib/module/layout/index.js.map +1 -1
  89. package/lib/module/native/NitroListView.js +17 -0
  90. package/lib/module/native/NitroListView.js.map +1 -0
  91. package/lib/module/recycler/CellPool.js +28 -0
  92. package/lib/module/recycler/CellPool.js.map +1 -0
  93. package/lib/module/recycler/NitroList.js +220 -0
  94. package/lib/module/recycler/NitroList.js.map +1 -0
  95. package/lib/module/scroll/useScrollVelocity.js +16 -0
  96. package/lib/module/scroll/useScrollVelocity.js.map +1 -0
  97. package/lib/module/specs/NitroList.nitro.js +4 -0
  98. package/lib/module/specs/NitroList.nitro.js.map +1 -0
  99. package/lib/module/types/Axis.js +2 -0
  100. package/lib/module/types/Axis.js.map +1 -0
  101. package/lib/module/types/CellKey.js +2 -0
  102. package/lib/module/types/CellKey.js.map +1 -0
  103. package/lib/module/types/CellType.js +22 -0
  104. package/lib/module/types/CellType.js.map +1 -0
  105. package/lib/module/types/VisibleRange.js +2 -0
  106. package/lib/module/types/VisibleRange.js.map +1 -0
  107. package/lib/module/types/VisibleRangeInput.js +4 -0
  108. package/lib/module/types/VisibleRangeInput.js.map +1 -0
  109. package/lib/module/types/index.js +4 -0
  110. package/lib/module/types/index.js.map +1 -0
  111. package/lib/module/types/layout/LayoutRect.js +2 -0
  112. package/lib/module/types/layout/LayoutRect.js.map +1 -0
  113. package/lib/module/types/layout/LinearLayoutInput.js +4 -0
  114. package/lib/module/types/layout/LinearLayoutInput.js.map +1 -0
  115. package/lib/module/types/layout/MainAxisPadding.js +22 -0
  116. package/lib/module/types/layout/MainAxisPadding.js.map +1 -0
  117. package/lib/module/types/layout/index.js +2 -0
  118. package/lib/module/types/layout/index.js.map +1 -0
  119. package/lib/module/types/recycler/CellPool.js +37 -0
  120. package/lib/module/types/recycler/CellPool.js.map +1 -0
  121. package/lib/module/types/recycler/NitroListProps.js +4 -0
  122. package/lib/module/types/recycler/NitroListProps.js.map +1 -0
  123. package/lib/module/types/recycler/RecyclerCell.js +4 -0
  124. package/lib/module/types/recycler/RecyclerCell.js.map +1 -0
  125. package/lib/module/types/recycler/RecyclerItemRenderer.js +4 -0
  126. package/lib/module/types/recycler/RecyclerItemRenderer.js.map +1 -0
  127. package/lib/module/types/recycler/index.js +2 -0
  128. package/lib/module/types/recycler/index.js.map +1 -0
  129. package/lib/module/types/scroll/ScrollMetrics.js +4 -0
  130. package/lib/module/types/scroll/ScrollMetrics.js.map +1 -0
  131. package/lib/module/types/scroll/index.js +2 -0
  132. package/lib/module/types/scroll/index.js.map +1 -0
  133. package/lib/module/windowing/computeVisibleItemRange.js +57 -0
  134. package/lib/module/windowing/computeVisibleItemRange.js.map +1 -0
  135. package/lib/module/windowing/index.js +1 -1
  136. package/lib/module/windowing/index.js.map +1 -1
  137. package/lib/typescript/src/cell/Cell.d.ts +13 -4
  138. package/lib/typescript/src/cell/Cell.d.ts.map +1 -1
  139. package/lib/typescript/src/cell/CellKeyGenerator.d.ts +11 -0
  140. package/lib/typescript/src/cell/CellKeyGenerator.d.ts.map +1 -0
  141. package/lib/typescript/src/cell/CellRecycler.d.ts +19 -11
  142. package/lib/typescript/src/cell/CellRecycler.d.ts.map +1 -1
  143. package/lib/typescript/src/cell/createCell.d.ts +7 -0
  144. package/lib/typescript/src/cell/createCell.d.ts.map +1 -0
  145. package/lib/typescript/src/cell/index.d.ts +4 -0
  146. package/lib/typescript/src/cell/index.d.ts.map +1 -0
  147. package/lib/typescript/src/getVisibleIndices.d.ts +2 -2
  148. package/lib/typescript/src/getVisibleIndices.d.ts.map +1 -1
  149. package/lib/typescript/src/hooks/usePersistentCallback.d.ts +16 -0
  150. package/lib/typescript/src/hooks/usePersistentCallback.d.ts.map +1 -0
  151. package/lib/typescript/src/index.d.ts +3 -2
  152. package/lib/typescript/src/index.d.ts.map +1 -1
  153. package/lib/typescript/src/layout/MutableLinearLayout.d.ts +45 -13
  154. package/lib/typescript/src/layout/MutableLinearLayout.d.ts.map +1 -1
  155. package/lib/typescript/src/layout/constants/layoutDefaults.d.ts +13 -0
  156. package/lib/typescript/src/layout/constants/layoutDefaults.d.ts.map +1 -0
  157. package/lib/typescript/src/layout/index.d.ts +1 -4
  158. package/lib/typescript/src/layout/index.d.ts.map +1 -1
  159. package/lib/typescript/src/native/NitroListView.d.ts +20 -0
  160. package/lib/typescript/src/native/NitroListView.d.ts.map +1 -0
  161. package/lib/typescript/src/recycler/CellPool.d.ts +11 -0
  162. package/lib/typescript/src/recycler/CellPool.d.ts.map +1 -0
  163. package/lib/typescript/src/recycler/NitroList.d.ts +4 -0
  164. package/lib/typescript/src/recycler/NitroList.d.ts.map +1 -0
  165. package/lib/typescript/src/scroll/useScrollVelocity.d.ts +2 -0
  166. package/lib/typescript/src/scroll/useScrollVelocity.d.ts.map +1 -0
  167. package/lib/typescript/src/specs/NitroList.nitro.d.ts +26 -0
  168. package/lib/typescript/src/specs/NitroList.nitro.d.ts.map +1 -0
  169. package/lib/typescript/src/types/Axis.d.ts +11 -0
  170. package/lib/typescript/src/types/Axis.d.ts.map +1 -0
  171. package/lib/typescript/src/types/CellKey.d.ts +2 -0
  172. package/lib/typescript/src/types/CellKey.d.ts.map +1 -0
  173. package/lib/typescript/src/types/CellType.d.ts +22 -0
  174. package/lib/typescript/src/types/CellType.d.ts.map +1 -0
  175. package/lib/typescript/src/types/VisibleRange.d.ts +10 -0
  176. package/lib/typescript/src/types/VisibleRange.d.ts.map +1 -0
  177. package/lib/typescript/src/types/VisibleRangeInput.d.ts +35 -0
  178. package/lib/typescript/src/types/VisibleRangeInput.d.ts.map +1 -0
  179. package/lib/typescript/src/types/index.d.ts +8 -0
  180. package/lib/typescript/src/types/index.d.ts.map +1 -0
  181. package/lib/typescript/src/types/layout/LayoutRect.d.ts +15 -0
  182. package/lib/typescript/src/types/layout/LayoutRect.d.ts.map +1 -0
  183. package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts +10 -0
  184. package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts.map +1 -0
  185. package/lib/typescript/src/types/layout/MainAxisPadding.d.ts +20 -0
  186. package/lib/typescript/src/types/layout/MainAxisPadding.d.ts.map +1 -0
  187. package/lib/typescript/src/types/layout/index.d.ts +4 -0
  188. package/lib/typescript/src/types/layout/index.d.ts.map +1 -0
  189. package/lib/typescript/src/types/recycler/CellPool.d.ts +16 -0
  190. package/lib/typescript/src/types/recycler/CellPool.d.ts.map +1 -0
  191. package/lib/typescript/src/types/recycler/NitroListProps.d.ts +66 -0
  192. package/lib/typescript/src/types/recycler/NitroListProps.d.ts.map +1 -0
  193. package/lib/typescript/src/types/recycler/RecyclerCell.d.ts +12 -0
  194. package/lib/typescript/src/types/recycler/RecyclerCell.d.ts.map +1 -0
  195. package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts +12 -0
  196. package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts.map +1 -0
  197. package/lib/typescript/src/types/recycler/index.d.ts +4 -0
  198. package/lib/typescript/src/types/recycler/index.d.ts.map +1 -0
  199. package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts +15 -0
  200. package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts.map +1 -0
  201. package/lib/typescript/src/types/scroll/index.d.ts +2 -0
  202. package/lib/typescript/src/types/scroll/index.d.ts.map +1 -0
  203. package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts +19 -0
  204. package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts.map +1 -0
  205. package/lib/typescript/src/windowing/index.d.ts +1 -1
  206. package/lib/typescript/src/windowing/index.d.ts.map +1 -1
  207. package/nitro.json +5 -5
  208. package/nitrogen/generated/android/NitroList+autolinking.cmake +2 -2
  209. package/nitrogen/generated/android/NitroListOnLoad.cpp +2 -2
  210. package/nitrogen/generated/android/c++/{JHybridNitroLayoutEngineSpec.cpp → JHybridNitroListSpec.cpp} +15 -15
  211. package/nitrogen/generated/android/c++/{JHybridNitroLayoutEngineSpec.hpp → JHybridNitroListSpec.hpp} +11 -11
  212. package/nitrogen/generated/android/c++/{JLayoutRectangle.hpp → JItemLayout.hpp} +10 -10
  213. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/{HybridNitroLayoutEngineSpec.kt → HybridNitroListSpec.kt} +7 -7
  214. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/{LayoutRectangle.kt → ItemLayout.kt} +5 -5
  215. package/nitrogen/generated/ios/NitroList-Swift-Cxx-Bridge.cpp +9 -9
  216. package/nitrogen/generated/ios/NitroList-Swift-Cxx-Bridge.hpp +27 -27
  217. package/nitrogen/generated/ios/NitroList-Swift-Cxx-Umbrella.hpp +8 -8
  218. package/nitrogen/generated/ios/c++/{HybridNitroLayoutEngineSpecSwift.cpp → HybridNitroListSpecSwift.cpp} +2 -2
  219. package/nitrogen/generated/ios/c++/{HybridNitroLayoutEngineSpecSwift.hpp → HybridNitroListSpecSwift.hpp} +16 -16
  220. package/nitrogen/generated/ios/swift/HybridNitroListSpec.swift +56 -0
  221. package/nitrogen/generated/ios/swift/{HybridNitroLayoutEngineSpec_cxx.swift → HybridNitroListSpec_cxx.swift} +23 -23
  222. package/nitrogen/generated/ios/swift/{LayoutRectangle.swift → ItemLayout.swift} +5 -5
  223. package/nitrogen/generated/shared/c++/{HybridNitroLayoutEngineSpec.cpp → HybridNitroListSpec.cpp} +4 -4
  224. package/nitrogen/generated/shared/c++/{HybridNitroLayoutEngineSpec.hpp → HybridNitroListSpec.hpp} +13 -13
  225. package/nitrogen/generated/shared/c++/{LayoutRectangle.hpp → ItemLayout.hpp} +11 -11
  226. package/package.json +5 -5
  227. package/src/cell/Cell.ts +13 -4
  228. package/src/cell/CellKeyGenerator.ts +17 -0
  229. package/src/cell/CellRecycler.ts +53 -43
  230. package/src/cell/createCell.ts +15 -0
  231. package/src/cell/index.ts +5 -0
  232. package/src/getVisibleIndices.ts +4 -2
  233. package/src/hooks/usePersistentCallback.ts +37 -0
  234. package/src/index.ts +7 -2
  235. package/src/layout/MutableLinearLayout.ts +91 -58
  236. package/src/layout/constants/layoutDefaults.ts +12 -0
  237. package/src/layout/index.ts +1 -4
  238. package/src/native/NitroListView.ts +22 -0
  239. package/src/recycler/CellPool.ts +33 -0
  240. package/src/recycler/NitroList.tsx +317 -0
  241. package/src/scroll/useScrollVelocity.ts +16 -0
  242. package/src/specs/NitroList.nitro.ts +29 -0
  243. package/src/types/Axis.ts +10 -0
  244. package/src/types/CellKey.ts +2 -0
  245. package/src/types/CellType.ts +9 -0
  246. package/src/types/VisibleRange.ts +9 -0
  247. package/src/types/VisibleRangeInput.ts +39 -0
  248. package/src/types/index.ts +15 -0
  249. package/src/types/layout/LayoutRect.ts +14 -0
  250. package/src/types/layout/LinearLayoutInput.ts +12 -0
  251. package/src/types/layout/MainAxisPadding.ts +23 -0
  252. package/src/types/layout/index.ts +3 -0
  253. package/src/types/recycler/CellPool.ts +45 -0
  254. package/src/types/recycler/NitroListProps.ts +74 -0
  255. package/src/types/recycler/RecyclerCell.ts +12 -0
  256. package/src/types/recycler/RecyclerItemRenderer.ts +12 -0
  257. package/src/types/recycler/index.ts +3 -0
  258. package/src/types/scroll/ScrollMetrics.ts +18 -0
  259. package/src/types/scroll/index.ts +1 -0
  260. package/src/windowing/computeVisibleItemRange.ts +82 -0
  261. package/src/windowing/index.ts +1 -1
  262. package/lib/commonjs/NitroList.js +0 -9
  263. package/lib/commonjs/NitroList.js.map +0 -1
  264. package/lib/commonjs/RecyclerList.internal.js +0 -25
  265. package/lib/commonjs/RecyclerList.internal.js.map +0 -1
  266. package/lib/commonjs/RecyclerList.js +0 -171
  267. package/lib/commonjs/RecyclerList.js.map +0 -1
  268. package/lib/commonjs/RecyclerList.types.js.map +0 -1
  269. package/lib/commonjs/cell/StableKey.js +0 -10
  270. package/lib/commonjs/cell/StableKey.js.map +0 -1
  271. package/lib/commonjs/hooks/useCellRenderer.js +0 -62
  272. package/lib/commonjs/hooks/useCellRenderer.js.map +0 -1
  273. package/lib/commonjs/hooks/useStableCallback.js +0 -13
  274. package/lib/commonjs/hooks/useStableCallback.js.map +0 -1
  275. package/lib/commonjs/layout/EstimatedLayoutProvider.js +0 -30
  276. package/lib/commonjs/layout/EstimatedLayoutProvider.js.map +0 -1
  277. package/lib/commonjs/layout/LayoutEngine.js +0 -21
  278. package/lib/commonjs/layout/LayoutEngine.js.map +0 -1
  279. package/lib/commonjs/layout/LayoutRectangle.js +0 -2
  280. package/lib/commonjs/native/NitroLayoutEngine.js +0 -9
  281. package/lib/commonjs/native/NitroLayoutEngine.js.map +0 -1
  282. package/lib/commonjs/native/NitroRecyclerView.js +0 -9
  283. package/lib/commonjs/native/NitroRecyclerView.js.map +0 -1
  284. package/lib/commonjs/specs/nitro-layout-engine.nitro.js.map +0 -1
  285. package/lib/commonjs/viewability/ViewabilityHelper.js +0 -121
  286. package/lib/commonjs/viewability/ViewabilityHelper.js.map +0 -1
  287. package/lib/commonjs/windowing/findVisibleIndexRange.js +0 -48
  288. package/lib/commonjs/windowing/findVisibleIndexRange.js.map +0 -1
  289. package/lib/module/NitroList.js +0 -5
  290. package/lib/module/NitroList.js.map +0 -1
  291. package/lib/module/RecyclerList.internal.js +0 -22
  292. package/lib/module/RecyclerList.internal.js.map +0 -1
  293. package/lib/module/RecyclerList.js +0 -166
  294. package/lib/module/RecyclerList.js.map +0 -1
  295. package/lib/module/RecyclerList.types.js +0 -4
  296. package/lib/module/RecyclerList.types.js.map +0 -1
  297. package/lib/module/cell/StableKey.js +0 -6
  298. package/lib/module/cell/StableKey.js.map +0 -1
  299. package/lib/module/hooks/useCellRenderer.js +0 -58
  300. package/lib/module/hooks/useCellRenderer.js.map +0 -1
  301. package/lib/module/hooks/useStableCallback.js +0 -9
  302. package/lib/module/hooks/useStableCallback.js.map +0 -1
  303. package/lib/module/layout/EstimatedLayoutProvider.js +0 -25
  304. package/lib/module/layout/EstimatedLayoutProvider.js.map +0 -1
  305. package/lib/module/layout/LayoutEngine.js +0 -17
  306. package/lib/module/layout/LayoutEngine.js.map +0 -1
  307. package/lib/module/layout/LayoutProvider.js +0 -4
  308. package/lib/module/layout/LayoutRectangle.js +0 -2
  309. package/lib/module/layout/LayoutRectangle.js.map +0 -1
  310. package/lib/module/native/NitroLayoutEngine.js +0 -5
  311. package/lib/module/native/NitroLayoutEngine.js.map +0 -1
  312. package/lib/module/native/NitroList.types.js +0 -4
  313. package/lib/module/native/NitroList.types.js.map +0 -1
  314. package/lib/module/native/NitroRecyclerView.js +0 -5
  315. package/lib/module/native/NitroRecyclerView.js.map +0 -1
  316. package/lib/module/specs/nitro-layout-engine.nitro.js +0 -4
  317. package/lib/module/specs/nitro-layout-engine.nitro.js.map +0 -1
  318. package/lib/module/viewability/ViewabilityHelper.js +0 -116
  319. package/lib/module/viewability/ViewabilityHelper.js.map +0 -1
  320. package/lib/module/windowing/findVisibleIndexRange.js +0 -44
  321. package/lib/module/windowing/findVisibleIndexRange.js.map +0 -1
  322. package/lib/typescript/src/NitroList.d.ts +0 -5
  323. package/lib/typescript/src/NitroList.d.ts.map +0 -1
  324. package/lib/typescript/src/RecyclerList.d.ts +0 -26
  325. package/lib/typescript/src/RecyclerList.d.ts.map +0 -1
  326. package/lib/typescript/src/RecyclerList.internal.d.ts +0 -9
  327. package/lib/typescript/src/RecyclerList.internal.d.ts.map +0 -1
  328. package/lib/typescript/src/RecyclerList.types.d.ts +0 -18
  329. package/lib/typescript/src/RecyclerList.types.d.ts.map +0 -1
  330. package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts +0 -2
  331. package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts.map +0 -1
  332. package/lib/typescript/src/cell/StableKey.d.ts +0 -2
  333. package/lib/typescript/src/cell/StableKey.d.ts.map +0 -1
  334. package/lib/typescript/src/hooks/useCellRenderer.d.ts +0 -19
  335. package/lib/typescript/src/hooks/useCellRenderer.d.ts.map +0 -1
  336. package/lib/typescript/src/hooks/useStableCallback.d.ts +0 -2
  337. package/lib/typescript/src/hooks/useStableCallback.d.ts.map +0 -1
  338. package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts +0 -15
  339. package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts.map +0 -1
  340. package/lib/typescript/src/layout/LayoutEngine.d.ts +0 -10
  341. package/lib/typescript/src/layout/LayoutEngine.d.ts.map +0 -1
  342. package/lib/typescript/src/layout/LayoutProvider.d.ts +0 -16
  343. package/lib/typescript/src/layout/LayoutProvider.d.ts.map +0 -1
  344. package/lib/typescript/src/layout/LayoutRectangle.d.ts +0 -11
  345. package/lib/typescript/src/layout/LayoutRectangle.d.ts.map +0 -1
  346. package/lib/typescript/src/native/NitroLayoutEngine.d.ts +0 -3
  347. package/lib/typescript/src/native/NitroLayoutEngine.d.ts.map +0 -1
  348. package/lib/typescript/src/native/NitroList.types.d.ts +0 -9
  349. package/lib/typescript/src/native/NitroList.types.d.ts.map +0 -1
  350. package/lib/typescript/src/native/NitroRecyclerView.d.ts +0 -5
  351. package/lib/typescript/src/native/NitroRecyclerView.d.ts.map +0 -1
  352. package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts +0 -14
  353. package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts.map +0 -1
  354. package/lib/typescript/src/viewability/ViewabilityHelper.d.ts +0 -50
  355. package/lib/typescript/src/viewability/ViewabilityHelper.d.ts.map +0 -1
  356. package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts +0 -11
  357. package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts.map +0 -1
  358. package/nitrogen/generated/ios/swift/HybridNitroLayoutEngineSpec.swift +0 -56
  359. package/src/NitroList.ts +0 -8
  360. package/src/RecyclerList.internal.ts +0 -38
  361. package/src/RecyclerList.tsx +0 -252
  362. package/src/RecyclerList.types.ts +0 -24
  363. package/src/__tests__/windowing/findVisibleIndexRange.test.ts +0 -55
  364. package/src/cell/StableKey.ts +0 -6
  365. package/src/hooks/useCellRenderer.ts +0 -86
  366. package/src/hooks/useStableCallback.ts +0 -13
  367. package/src/layout/EstimatedLayoutProvider.ts +0 -35
  368. package/src/layout/LayoutEngine.ts +0 -21
  369. package/src/layout/LayoutProvider.ts +0 -17
  370. package/src/layout/LayoutRectangle.ts +0 -10
  371. package/src/native/NitroLayoutEngine.ts +0 -7
  372. package/src/native/NitroList.types.ts +0 -12
  373. package/src/native/NitroRecyclerView.ts +0 -8
  374. package/src/specs/nitro-layout-engine.nitro.ts +0 -17
  375. package/src/viewability/ViewabilityHelper.ts +0 -130
  376. package/src/windowing/findVisibleIndexRange.ts +0 -60
@@ -1,4 +1,6 @@
1
- import type { LayoutRectangle } from './layout/LayoutRectangle'
1
+
2
+
3
+ import type { LayoutRect } from './types/layout'
2
4
  import type { ScrollMetrics } from './windowing/ScrollMetrics'
3
5
 
4
6
  /**
@@ -6,7 +8,7 @@ import type { ScrollMetrics } from './windowing/ScrollMetrics'
6
8
  * Returns indices intersecting viewport ± buffer.
7
9
  */
8
10
  export function getVisibleRange(
9
- layouts: readonly LayoutRectangle[],
11
+ layouts: readonly LayoutRect[],
10
12
  metrics: ScrollMetrics,
11
13
  bufferPx: number
12
14
  ): readonly number[] {
@@ -0,0 +1,37 @@
1
+ import { useRef, useCallback } from 'react'
2
+
3
+ /**
4
+ * Returns a function whose identity is stable across renders,
5
+ * but always invokes the latest provided implementation.
6
+ *
7
+ * Invariants:
8
+ * - Function reference NEVER changes
9
+ * - Logic is ALWAYS up to date
10
+ *
11
+ * This is critical for long-lived systems such as:
12
+ * - Recyclers
13
+ * - Effects
14
+ * - Native bridges
15
+ * - Event pipelines
16
+ */
17
+ export function usePersistentCallback<
18
+ T extends (...args: never[]) => unknown
19
+ >(fn: T): T {
20
+
21
+ /**
22
+ * Holds the latest implementation.
23
+ * Updating this does NOT trigger re-renders.
24
+ */
25
+ const fnRef = useRef(fn)
26
+ fnRef.current = fn
27
+
28
+ /**
29
+ * Stable wrapper that forwards calls
30
+ * to the latest implementation.
31
+ */
32
+ return useCallback(
33
+ ((...args: never[]) =>
34
+ fnRef.current(...args)) as T,
35
+ []
36
+ )
37
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,7 @@
1
- export { RecyclerList } from './RecyclerList'
2
- export type { RecyclerListProps } from './RecyclerList.types'
1
+
2
+ // Export the Native View
3
+ export * from './native/NitroListView';
4
+ // Export the JSI Specs
5
+ export * from './specs/NitroList.nitro';
6
+
7
+ export { default as NitroList } from './recycler/NitroList';
@@ -1,79 +1,112 @@
1
- import type { LayoutRectangle } from './LayoutRectangle'
1
+ import type { Axis } from '../types/Axis'
2
+ import type { LinearLayoutInput } from '../types/layout'
3
+ import type { LayoutRect } from '../types/layout/LayoutRect'
4
+ import { DEFAULT_ITEM_SPACING } from './constants/layoutDefaults'
2
5
 
3
- /**
4
- * INTERNAL mutable layout record.
5
- * This is intentionally mutable and never exposed publicly.
6
- */
7
- type MutableLayoutRectangle = {
8
- x: number
9
- y: number
10
- width: number
11
- height: number
12
- }
13
6
 
14
7
  /**
15
- * Mutable linear layout store.
16
- * FlashList-style incremental relayout.
8
+ * Mutable, deterministic linear layout engine.
9
+ *
10
+ * Responsibilities:
11
+ * - Compute absolute item geometry
12
+ * - Own layout truth (no React, no scroll state)
13
+ * - Guarantee monotonic ordering along the main axis
14
+ *
15
+ * Cross-platform equivalents:
16
+ * - Flutter: RenderSliver / SliverList
17
+ * - Android: LinearLayoutManager
18
+ * - iOS: UICollectionViewFlowLayout (linear)
17
19
  */
18
20
  export class MutableLinearLayout {
19
- private readonly layouts: MutableLayoutRectangle[]
20
- private totalHeight: number
21
+ private readonly isVertical: boolean
21
22
 
22
- constructor(
23
- initialHeights: readonly number[],
24
- width: number
25
- ) {
26
- this.layouts = []
27
- let y = 0
28
-
29
- for (const height of initialHeights) {
30
- this.layouts.push({
31
- x: 0,
32
- y,
33
- width,
34
- height,
35
- })
36
- y += height
23
+ /** Absolute item layouts in index order */
24
+ private layouts: LayoutRect[] = []
25
+
26
+ /** Total scrollable size along main axis */
27
+ private contentSize = 0
28
+
29
+ constructor(axis: Axis) {
30
+ this.isVertical = axis === 'vertical'
31
+ }
32
+
33
+ /**
34
+ * Computes layout synchronously from input.
35
+ *
36
+ * This method is intentionally parameter-object based
37
+ * to allow future extension without breaking API.
38
+ *
39
+ * Invariants:
40
+ * - Layouts are monotonic along main axis
41
+ * - No gaps except explicit spacing
42
+ * - Deterministic for identical inputs
43
+ */
44
+ compute(input: LinearLayoutInput): void {
45
+ const {
46
+ crossAxisSize,
47
+ itemMainAxisSizes,
48
+ padding,
49
+ itemSpacing = DEFAULT_ITEM_SPACING,
50
+ } = input
51
+
52
+ const itemCount = itemMainAxisSizes.length
53
+ const layouts: LayoutRect[] = new Array(itemCount)
54
+
55
+ let cursor = padding.start
56
+
57
+ for (let i = 0; i < itemCount; i++) {
58
+ const mainAxisSize = itemMainAxisSizes[i]!
59
+
60
+ layouts[i] = this.isVertical
61
+ ? {
62
+ x: 0,
63
+ y: cursor,
64
+ width: crossAxisSize,
65
+ height: mainAxisSize,
66
+ }
67
+ : {
68
+ x: cursor,
69
+ y: 0,
70
+ width: mainAxisSize,
71
+ height: crossAxisSize,
72
+ }
73
+
74
+ cursor += mainAxisSize
75
+
76
+ // Space BETWEEN items, not after the last
77
+ if (i < itemCount - 1) {
78
+ cursor += itemSpacing
79
+ }
37
80
  }
38
81
 
39
- this.totalHeight = y
82
+ this.layouts = layouts
83
+ this.contentSize = cursor + padding.end
40
84
  }
41
85
 
42
86
  /**
43
- * Read-only snapshot for consumers.
44
- * Returned type is immutable.
87
+ * Returns computed item layouts.
88
+ *
89
+ * Order is guaranteed monotonic along the main axis,
90
+ * which is required for binary-search-based windowing.
45
91
  */
46
- getLayouts(): readonly LayoutRectangle[] {
92
+ getLayouts(): readonly LayoutRect[] {
47
93
  return this.layouts
48
94
  }
49
95
 
50
- getContentHeight(): number {
51
- return this.totalHeight
96
+ /**
97
+ * Returns total scrollable size along the main axis,
98
+ * including padding and inter-item spacing.
99
+ */
100
+ getContentSize(): number {
101
+ return this.contentSize
52
102
  }
53
103
 
54
104
  /**
55
- * Update height of one item and shift following items.
56
- * Returns true if layout changed.
105
+ * Clears internal layout state.
106
+ * Call on severe invalidation or teardown.
57
107
  */
58
- updateItemHeight(
59
- index: number,
60
- newHeight: number
61
- ): boolean {
62
- const layout = this.layouts[index]
63
- if (!layout) return false
64
-
65
- const delta = newHeight - layout.height
66
- if (delta === 0) return false
67
-
68
- // Update this item
69
- layout.height = newHeight
70
-
71
- // Shift all items after this index
72
- for (let i = index + 1; i < this.layouts.length; i++) {
73
- this.layouts[i]!.y += delta
74
- }
75
-
76
- this.totalHeight += delta
77
- return true
108
+ reset(): void {
109
+ this.layouts = []
110
+ this.contentSize = 0
78
111
  }
79
112
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Default spacing between items along the main axis.
3
+ *
4
+ * This value is used by layout engines when no explicit
5
+ * itemSpacing is provided.
6
+ *
7
+ * Mirrors:
8
+ * - Android RecyclerView ItemDecoration (typical 8–16dp)
9
+ * - iOS UICollectionViewFlowLayout minimumLineSpacing
10
+ * - Flutter SliverList spacing conventions
11
+ */
12
+ export const DEFAULT_ITEM_SPACING = 12
@@ -1,4 +1 @@
1
- export type { LayoutRectangle } from './LayoutRectangle'
2
- export type { LayoutProvider } from './LayoutProvider'
3
- export { EstimatedLayoutProvider } from './EstimatedLayoutProvider'
4
- export { computeLayouts } from './LayoutEngine'
1
+ export type { MutableLinearLayout } from './MutableLinearLayout'
@@ -0,0 +1,22 @@
1
+ import { requireNativeComponent, type ViewProps } from 'react-native'
2
+
3
+ /**
4
+ * Props for the NitroListView.
5
+ * * We extend ViewProps so that developers can use standard styles
6
+ * like 'flex: 1' or 'backgroundColor' on the list.
7
+ */
8
+ export type NitroListViewProps = ViewProps & {
9
+ /**
10
+ * The total number of items to be displayed in the list.
11
+ * This is passed to the native side (Swift/Kotlin) for layout math.
12
+ */
13
+ itemCount: number
14
+ }
15
+
16
+ /**
17
+ * The Native Component that maps to the physical view in Swift/Kotlin.
18
+ * * 'NitroListView' is the "Secret Handshake" name. It must match
19
+ * the name exported by your Native ViewManagers.
20
+ */
21
+ export const NitroListView =
22
+ requireNativeComponent<NitroListViewProps>('NitroListView')
@@ -0,0 +1,33 @@
1
+ import type { RecyclerCell } from '../types/recycler/RecyclerCell'
2
+ import type { CellType } from '../types/CellType'
3
+
4
+ export class CellPool<T extends RecyclerCell<any>> {
5
+ private readonly pools = new Map<CellType, T[]>()
6
+ private readonly maxPerType = new Map<CellType, number>()
7
+
8
+ hasType(type: CellType): boolean {
9
+ return this.pools.has(type)
10
+ }
11
+
12
+ registerType(type: CellType, maxCount: number): void {
13
+ if (this.pools.has(type)) return
14
+ this.pools.set(type, [])
15
+ this.maxPerType.set(type, maxCount)
16
+ }
17
+
18
+ acquire(type: CellType): T | null {
19
+ const bucket = this.pools.get(type)
20
+ if (!bucket || bucket.length === 0) return null
21
+ return bucket.pop() ?? null
22
+ }
23
+
24
+ release(cell: T): void {
25
+ const bucket = this.pools.get(cell.type)
26
+ const max = this.maxPerType.get(cell.type)
27
+ if (!bucket || max === undefined) return
28
+
29
+ cell.index = -1
30
+ if (bucket.length >= max) return
31
+ bucket.push(cell)
32
+ }
33
+ }
@@ -0,0 +1,317 @@
1
+ import React, { useRef, useEffect, useState } from 'react'
2
+ import {
3
+ ScrollView,
4
+ View,
5
+ StyleSheet,
6
+ type NativeSyntheticEvent,
7
+ type NativeScrollEvent,
8
+ type LayoutChangeEvent,
9
+ } from 'react-native'
10
+
11
+ import type { LayoutRect, VisibleRange } from '../types'
12
+ import type { RecyclerCell, NitroListProps } from '../types/recycler'
13
+ import type { CellType } from '../types/CellType'
14
+ import type { CellKey } from '../types/CellKey'
15
+
16
+ import { MutableLinearLayout } from '../layout/MutableLinearLayout'
17
+ import { computeVisibleItemRange } from '../windowing'
18
+ import { CellPool } from './CellPool'
19
+
20
+ /* ========================================================= */
21
+
22
+ const DEFAULT_VIEWPORT_SIZE = 800
23
+ const DEFAULT_ITEM_SIZE = 60
24
+ const SCROLL_EVENT_THROTTLE = 16
25
+
26
+ /* ========================================================= */
27
+ /* Internal (mutable) cell */
28
+ /* ========================================================= */
29
+
30
+ interface InternalRecyclerCell extends RecyclerCell<CellKey> {
31
+ active: boolean
32
+ }
33
+
34
+ /* ========================================================= */
35
+ /* NitroList */
36
+ /* ========================================================= */
37
+
38
+ export default function NitroList<T>(
39
+ props: NitroListProps<T>
40
+ ): React.ReactElement {
41
+ const {
42
+ data,
43
+ renderItem,
44
+ getCellType,
45
+ scrollDirection = 'vertical',
46
+ bufferRatio = 1.3,
47
+ containerCrossAxisSize,
48
+ itemMainAxisSizes,
49
+ padding = { start: 0, end: 0 },
50
+ itemSpacing,
51
+ } = props
52
+
53
+ const isVertical = scrollDirection === 'vertical'
54
+ const [, forceRender] = useState(0)
55
+
56
+ const DEBUG = true
57
+
58
+
59
+ /* ======================================================= */
60
+ /* Layout engine (recomputed when signature changes) */
61
+ /* ======================================================= */
62
+
63
+ const layoutEngineRef = useRef<MutableLinearLayout | null>(null)
64
+ const layoutSignatureRef = useRef<string>('')
65
+
66
+ const layoutSignature = [
67
+ scrollDirection,
68
+ containerCrossAxisSize,
69
+ data.length,
70
+ itemMainAxisSizes,
71
+ padding.start,
72
+ padding.end,
73
+ itemSpacing ?? 'none',
74
+ ].join('|')
75
+
76
+ if (
77
+ layoutEngineRef.current === null ||
78
+ layoutSignatureRef.current !== layoutSignature
79
+ ) {
80
+ const engine = new MutableLinearLayout(scrollDirection)
81
+ engine.compute({
82
+ crossAxisSize: containerCrossAxisSize,
83
+ itemMainAxisSizes,
84
+ padding,
85
+ itemSpacing,
86
+ })
87
+
88
+ layoutEngineRef.current = engine
89
+ layoutSignatureRef.current = layoutSignature
90
+ }
91
+
92
+ const layouts: readonly LayoutRect[] =
93
+ layoutEngineRef.current.getLayouts()
94
+
95
+ const contentSize: number =
96
+ layoutEngineRef.current.getContentSize()
97
+
98
+ /* ======================================================= */
99
+ /* Scroll metrics */
100
+ /* ======================================================= */
101
+
102
+ const scrollOffsetRef = useRef<number>(0)
103
+ const viewportSizeRef = useRef<number>(DEFAULT_VIEWPORT_SIZE)
104
+
105
+ /* ======================================================= */
106
+ /* Cell pool */
107
+ /* ======================================================= */
108
+
109
+ const cellPoolRef = useRef<CellPool<InternalRecyclerCell>>(
110
+ new CellPool<InternalRecyclerCell>()
111
+ )
112
+
113
+ const activeCellsRef = useRef<InternalRecyclerCell[]>([])
114
+ const nextKeyRef = useRef<number>(0)
115
+
116
+ const createCell = (type: CellType): InternalRecyclerCell => ({
117
+ key: nextKeyRef.current++,
118
+ type,
119
+ index: -1,
120
+ active: false,
121
+ })
122
+
123
+ /* ======================================================= */
124
+ /* Visible window coordination */
125
+ /* ======================================================= */
126
+
127
+ const updateVisibleCells = (): void => {
128
+ const range: VisibleRange | null =
129
+ computeVisibleItemRange({
130
+ layouts,
131
+ offset: scrollOffsetRef.current,
132
+ viewportSize: viewportSizeRef.current,
133
+ buffer: viewportSizeRef.current * bufferRatio,
134
+ isVertical,
135
+ })
136
+
137
+
138
+
139
+ if (range === null) return
140
+
141
+ if (DEBUG) {
142
+ console.log(
143
+ '[NitroList] range:',
144
+ range.startIndex,
145
+ range.endIndex
146
+ )
147
+ }
148
+
149
+
150
+ const active = activeCellsRef.current
151
+
152
+ // 1. Mark all inactive
153
+ for (const cell of active) {
154
+ cell.active = false
155
+ }
156
+
157
+ let writeIndex = 0
158
+
159
+ // 2. Activate visible range
160
+ for (
161
+ let index = range.startIndex;
162
+ index <= range.endIndex;
163
+ index++
164
+ ) {
165
+ const item = data[index]
166
+ if (item === undefined) continue
167
+
168
+ const type = getCellType(item, index)
169
+
170
+ // Seed pool once per type
171
+ if (!cellPoolRef.current.hasType(type)) {
172
+ const maxCells =
173
+ Math.ceil(
174
+ (viewportSizeRef.current / DEFAULT_ITEM_SIZE) *
175
+ bufferRatio
176
+ ) + 2
177
+
178
+ cellPoolRef.current.registerType(type, maxCells)
179
+ for (let i = 0; i < maxCells; i++) {
180
+ cellPoolRef.current.release(createCell(type))
181
+ }
182
+ }
183
+
184
+ let cell: InternalRecyclerCell | null =
185
+ cellPoolRef.current.acquire(type)
186
+
187
+ if (cell === null) {
188
+ const reusable = active.find(
189
+ c => !c.active && c.type === type
190
+ )
191
+
192
+ cell = reusable ?? createCell(type)
193
+ }
194
+
195
+
196
+ cell.index = index
197
+ cell.active = true
198
+ active[writeIndex++] = cell
199
+ }
200
+
201
+ // 3. Recycle unused cells
202
+ for (let i = writeIndex; i < active.length; i++) {
203
+ const cell = active[i]
204
+ if (cell === undefined) continue
205
+
206
+ cell.index = -1
207
+ cell.active = false
208
+ cellPoolRef.current.release(cell)
209
+ }
210
+
211
+ // 4. Compact once
212
+ if (active.length !== writeIndex) {
213
+ active.length = writeIndex
214
+ forceRender(v => v + 1)
215
+ }
216
+ }
217
+
218
+ /* ======================================================= */
219
+ /* Handlers */
220
+ /* ======================================================= */
221
+
222
+ const onScroll = (
223
+ e: NativeSyntheticEvent<NativeScrollEvent>
224
+ ): void => {
225
+ scrollOffsetRef.current = isVertical
226
+ ? e.nativeEvent.contentOffset.y
227
+ : e.nativeEvent.contentOffset.x
228
+
229
+ updateVisibleCells()
230
+ }
231
+
232
+ const onLayout = (e: LayoutChangeEvent): void => {
233
+ viewportSizeRef.current = isVertical
234
+ ? e.nativeEvent.layout.height
235
+ : e.nativeEvent.layout.width
236
+
237
+ updateVisibleCells()
238
+ }
239
+
240
+ useEffect(() => {
241
+ updateVisibleCells()
242
+ // eslint-disable-next-line react-hooks/exhaustive-deps
243
+ }, [])
244
+
245
+
246
+ if (DEBUG) {
247
+ console.log('[NitroList] layouts:', layouts.length)
248
+ console.log('[NitroList] contentSize:', contentSize)
249
+ console.log('[NitroList] data.length:', data.length)
250
+ }
251
+
252
+ /* ======================================================= */
253
+ /* Render */
254
+ /* ======================================================= */
255
+
256
+ return (
257
+ <ScrollView
258
+ onScroll={onScroll}
259
+ onLayout={onLayout}
260
+ horizontal={!isVertical}
261
+ scrollEventThrottle={SCROLL_EVENT_THROTTLE}
262
+ removeClippedSubviews
263
+ >
264
+ {/* REQUIRED positioning container */}
265
+ <View
266
+ style={
267
+ isVertical
268
+ ? { height: contentSize }
269
+ : { width: contentSize }
270
+ }
271
+ >
272
+ {activeCellsRef.current.map(cell => {
273
+ const layout = layouts[cell.index]
274
+ const item = data[cell.index]
275
+
276
+ if (layout === undefined || item === undefined) {
277
+ return null
278
+ }
279
+
280
+ return (
281
+ <View
282
+ key={cell.key}
283
+ style={[
284
+ styles.cell,
285
+ isVertical
286
+ ? {
287
+ top: layout.y,
288
+ height: layout.height,
289
+ width: layout.width,
290
+ }
291
+ : {
292
+ left: layout.x,
293
+ width: layout.width,
294
+ height: layout.height,
295
+ },
296
+ ]}
297
+ >
298
+ {renderItem({
299
+ item,
300
+ index: cell.index,
301
+ cell,
302
+ })}
303
+ </View>
304
+ )
305
+ })}
306
+ </View>
307
+ </ScrollView>
308
+ )
309
+ }
310
+
311
+ /* ========================================================= */
312
+
313
+ const styles = StyleSheet.create({
314
+ cell: {
315
+ position: 'absolute',
316
+ },
317
+ })
@@ -0,0 +1,16 @@
1
+ export function createScrollVelocityTracker() {
2
+ let lastOffset = 0
3
+ let lastTime = Date.now()
4
+
5
+ return function getVelocity(offset: number): number {
6
+ const now = Date.now()
7
+ const dt = now - lastTime
8
+ const dy = Math.abs(offset - lastOffset)
9
+
10
+ lastOffset = offset
11
+ lastTime = now
12
+
13
+ if (dt === 0) return 0
14
+ return dy / dt // px per ms
15
+ }
16
+ }
@@ -0,0 +1,29 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules'
2
+
3
+ /**
4
+ * Represents the physical area an item occupies on the screen.
5
+ * Standard: 'Layout' suffix tells the user this is a data object, not a logic object.
6
+ */
7
+ export interface ItemLayout {
8
+ readonly x: number
9
+ readonly y: number
10
+ readonly width: number
11
+ readonly height: number
12
+ }
13
+
14
+ /**
15
+ * The high-performance layout engine for NitroList.
16
+ * This interface will be used by Nitro to generate your Swift and Kotlin code.
17
+ */
18
+ export interface NitroList
19
+ extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
20
+
21
+ /**
22
+ * Calculates exactly where every item should sit on the screen.
23
+ * Standard: Use descriptive parameter names so developers know what to provide.
24
+ */
25
+ computeLayout(
26
+ containerWidth: number,
27
+ itemHeights: readonly number[]
28
+ ): readonly ItemLayout[]
29
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Axis along which scrolling and layout occur.
3
+ *
4
+ * Matches Flutter's Axis:
5
+ * - vertical → Y axis
6
+ * - horizontal → X axis
7
+ *
8
+ * This is NOT gesture direction.
9
+ */
10
+ export type Axis = 'vertical' | 'horizontal'
@@ -0,0 +1,2 @@
1
+ // CellKey.ts
2
+ export type CellKey = number