react-native-nitro-list 0.1.1 → 0.1.2

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 (312) hide show
  1. package/ios/HybridNitroList.swift +10 -14
  2. package/lib/commonjs/cell/CellKeyGenerator.js +21 -0
  3. package/lib/commonjs/cell/CellKeyGenerator.js.map +1 -0
  4. package/lib/commonjs/cell/CellRecycler.js +48 -40
  5. package/lib/commonjs/cell/CellRecycler.js.map +1 -1
  6. package/lib/commonjs/cell/createCell.js +21 -0
  7. package/lib/commonjs/cell/createCell.js.map +1 -0
  8. package/lib/commonjs/cell/index.js +20 -0
  9. package/lib/commonjs/cell/index.js.map +1 -0
  10. package/lib/commonjs/getVisibleIndices.js.map +1 -1
  11. package/lib/commonjs/hooks/usePersistentCallback.js +36 -0
  12. package/lib/commonjs/hooks/usePersistentCallback.js.map +1 -0
  13. package/lib/commonjs/index.js +1 -1
  14. package/lib/commonjs/layout/MutableLinearLayout.js +78 -39
  15. package/lib/commonjs/layout/MutableLinearLayout.js.map +1 -1
  16. package/lib/commonjs/layout/constants/layoutDefaults.js +19 -0
  17. package/lib/commonjs/layout/constants/layoutDefaults.js.map +1 -0
  18. package/lib/commonjs/layout/index.js +0 -18
  19. package/lib/commonjs/layout/index.js.map +1 -1
  20. package/lib/commonjs/recycler/CellPool.js +46 -0
  21. package/lib/commonjs/recycler/CellPool.js.map +1 -0
  22. package/lib/commonjs/recycler/RecyclerList.js +224 -0
  23. package/lib/commonjs/recycler/RecyclerList.js.map +1 -0
  24. package/lib/commonjs/types/Axis.js +2 -0
  25. package/lib/commonjs/{layout/LayoutProvider.js.map → types/Axis.js.map} +1 -1
  26. package/lib/commonjs/types/CellKey.js +2 -0
  27. package/lib/{module/layout/LayoutProvider.js.map → commonjs/types/CellKey.js.map} +1 -1
  28. package/lib/commonjs/types/CellType.js +2 -0
  29. package/lib/commonjs/{layout/LayoutRectangle.js.map → types/CellType.js.map} +1 -1
  30. package/lib/commonjs/types/VisibleRange.js +2 -0
  31. package/lib/{module/layout/LayoutRectangle.js.map → commonjs/types/VisibleRange.js.map} +1 -1
  32. package/lib/commonjs/{RecyclerList.types.js → types/VisibleRangeInput.js} +1 -1
  33. package/lib/commonjs/types/VisibleRangeInput.js.map +1 -0
  34. package/lib/commonjs/types/index.js +13 -0
  35. package/lib/commonjs/types/index.js.map +1 -0
  36. package/lib/commonjs/types/layout/LayoutRect.js +2 -0
  37. package/lib/commonjs/types/layout/LayoutRect.js.map +1 -0
  38. package/lib/commonjs/types/layout/LinearLayoutInput.js +6 -0
  39. package/lib/commonjs/types/layout/LinearLayoutInput.js.map +1 -0
  40. package/lib/commonjs/types/layout/MainAxisPadding.js +26 -0
  41. package/lib/commonjs/types/layout/MainAxisPadding.js.map +1 -0
  42. package/lib/commonjs/types/layout/index.js +2 -0
  43. package/lib/commonjs/types/layout/index.js.map +1 -0
  44. package/lib/commonjs/types/recycler/RecyclerCellInstance.js +6 -0
  45. package/lib/commonjs/types/recycler/RecyclerCellInstance.js.map +1 -0
  46. package/lib/commonjs/types/recycler/RecyclerItemRenderer.js +6 -0
  47. package/lib/commonjs/types/recycler/RecyclerItemRenderer.js.map +1 -0
  48. package/lib/commonjs/types/recycler/RecyclerListProps.js +6 -0
  49. package/lib/commonjs/types/recycler/RecyclerListProps.js.map +1 -0
  50. package/lib/commonjs/types/recycler/index.js +2 -0
  51. package/lib/commonjs/types/recycler/index.js.map +1 -0
  52. package/lib/commonjs/{layout/LayoutProvider.js → types/scroll/ScrollMetrics.js} +1 -1
  53. package/lib/commonjs/types/scroll/ScrollMetrics.js.map +1 -0
  54. package/lib/commonjs/types/scroll/index.js +2 -0
  55. package/lib/commonjs/types/scroll/index.js.map +1 -0
  56. package/lib/commonjs/windowing/computeVisibleItemRange.js +71 -0
  57. package/lib/commonjs/windowing/computeVisibleItemRange.js.map +1 -0
  58. package/lib/commonjs/windowing/index.js +3 -3
  59. package/lib/commonjs/windowing/index.js.map +1 -1
  60. package/lib/module/cell/CellKeyGenerator.js +16 -0
  61. package/lib/module/cell/CellKeyGenerator.js.map +1 -0
  62. package/lib/module/cell/CellRecycler.js +48 -39
  63. package/lib/module/cell/CellRecycler.js.map +1 -1
  64. package/lib/module/cell/createCell.js +17 -0
  65. package/lib/module/cell/createCell.js.map +1 -0
  66. package/lib/module/cell/index.js +7 -0
  67. package/lib/module/cell/index.js.map +1 -0
  68. package/lib/module/getVisibleIndices.js.map +1 -1
  69. package/lib/module/hooks/usePersistentCallback.js +33 -0
  70. package/lib/module/hooks/usePersistentCallback.js.map +1 -0
  71. package/lib/module/index.js +1 -1
  72. package/lib/module/index.js.map +1 -1
  73. package/lib/module/layout/MutableLinearLayout.js +78 -38
  74. package/lib/module/layout/MutableLinearLayout.js.map +1 -1
  75. package/lib/module/layout/constants/layoutDefaults.js +15 -0
  76. package/lib/module/layout/constants/layoutDefaults.js.map +1 -0
  77. package/lib/module/layout/index.js +0 -3
  78. package/lib/module/layout/index.js.map +1 -1
  79. package/lib/module/recycler/CellPool.js +41 -0
  80. package/lib/module/recycler/CellPool.js.map +1 -0
  81. package/lib/module/recycler/RecyclerList.js +221 -0
  82. package/lib/module/recycler/RecyclerList.js.map +1 -0
  83. package/lib/module/types/Axis.js +2 -0
  84. package/lib/module/types/Axis.js.map +1 -0
  85. package/lib/module/types/CellKey.js +2 -0
  86. package/lib/module/types/CellKey.js.map +1 -0
  87. package/lib/module/types/CellType.js +2 -0
  88. package/lib/module/types/CellType.js.map +1 -0
  89. package/lib/module/types/VisibleRange.js +2 -0
  90. package/lib/module/types/VisibleRange.js.map +1 -0
  91. package/lib/module/types/VisibleRangeInput.js +4 -0
  92. package/lib/module/types/VisibleRangeInput.js.map +1 -0
  93. package/lib/module/types/index.js +4 -0
  94. package/lib/module/types/index.js.map +1 -0
  95. package/lib/module/types/layout/LayoutRect.js +2 -0
  96. package/lib/module/types/layout/LayoutRect.js.map +1 -0
  97. package/lib/module/types/layout/LinearLayoutInput.js +4 -0
  98. package/lib/module/types/layout/LinearLayoutInput.js.map +1 -0
  99. package/lib/module/types/layout/MainAxisPadding.js +22 -0
  100. package/lib/module/types/layout/MainAxisPadding.js.map +1 -0
  101. package/lib/module/types/layout/index.js +2 -0
  102. package/lib/module/types/layout/index.js.map +1 -0
  103. package/lib/module/types/recycler/RecyclerCellInstance.js +4 -0
  104. package/lib/module/types/recycler/RecyclerCellInstance.js.map +1 -0
  105. package/lib/module/types/recycler/RecyclerItemRenderer.js +4 -0
  106. package/lib/module/types/recycler/RecyclerItemRenderer.js.map +1 -0
  107. package/lib/module/types/recycler/RecyclerListProps.js +4 -0
  108. package/lib/module/types/recycler/RecyclerListProps.js.map +1 -0
  109. package/lib/module/types/recycler/index.js +2 -0
  110. package/lib/module/types/recycler/index.js.map +1 -0
  111. package/lib/module/types/scroll/ScrollMetrics.js +4 -0
  112. package/lib/module/types/scroll/ScrollMetrics.js.map +1 -0
  113. package/lib/module/types/scroll/index.js +2 -0
  114. package/lib/module/types/scroll/index.js.map +1 -0
  115. package/lib/module/windowing/computeVisibleItemRange.js +67 -0
  116. package/lib/module/windowing/computeVisibleItemRange.js.map +1 -0
  117. package/lib/module/windowing/index.js +1 -1
  118. package/lib/module/windowing/index.js.map +1 -1
  119. package/lib/typescript/src/cell/Cell.d.ts +13 -4
  120. package/lib/typescript/src/cell/Cell.d.ts.map +1 -1
  121. package/lib/typescript/src/cell/CellKeyGenerator.d.ts +11 -0
  122. package/lib/typescript/src/cell/CellKeyGenerator.d.ts.map +1 -0
  123. package/lib/typescript/src/cell/CellRecycler.d.ts +19 -11
  124. package/lib/typescript/src/cell/CellRecycler.d.ts.map +1 -1
  125. package/lib/typescript/src/cell/createCell.d.ts +7 -0
  126. package/lib/typescript/src/cell/createCell.d.ts.map +1 -0
  127. package/lib/typescript/src/cell/index.d.ts +4 -0
  128. package/lib/typescript/src/cell/index.d.ts.map +1 -0
  129. package/lib/typescript/src/getVisibleIndices.d.ts +2 -2
  130. package/lib/typescript/src/getVisibleIndices.d.ts.map +1 -1
  131. package/lib/typescript/src/hooks/usePersistentCallback.d.ts +16 -0
  132. package/lib/typescript/src/hooks/usePersistentCallback.d.ts.map +1 -0
  133. package/lib/typescript/src/index.d.ts +1 -2
  134. package/lib/typescript/src/index.d.ts.map +1 -1
  135. package/lib/typescript/src/layout/MutableLinearLayout.d.ts +45 -13
  136. package/lib/typescript/src/layout/MutableLinearLayout.d.ts.map +1 -1
  137. package/lib/typescript/src/layout/constants/layoutDefaults.d.ts +13 -0
  138. package/lib/typescript/src/layout/constants/layoutDefaults.d.ts.map +1 -0
  139. package/lib/typescript/src/layout/index.d.ts +1 -4
  140. package/lib/typescript/src/layout/index.d.ts.map +1 -1
  141. package/lib/typescript/src/native/NitroList.types.d.ts +2 -2
  142. package/lib/typescript/src/native/NitroList.types.d.ts.map +1 -1
  143. package/lib/typescript/src/recycler/CellPool.d.ts +14 -0
  144. package/lib/typescript/src/recycler/CellPool.d.ts.map +1 -0
  145. package/lib/typescript/src/recycler/RecyclerList.d.ts +4 -0
  146. package/lib/typescript/src/recycler/RecyclerList.d.ts.map +1 -0
  147. package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts +2 -2
  148. package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts.map +1 -1
  149. package/lib/typescript/src/types/Axis.d.ts +11 -0
  150. package/lib/typescript/src/types/Axis.d.ts.map +1 -0
  151. package/lib/typescript/src/types/CellKey.d.ts +10 -0
  152. package/lib/typescript/src/types/CellKey.d.ts.map +1 -0
  153. package/lib/typescript/src/types/CellType.d.ts +11 -0
  154. package/lib/typescript/src/types/CellType.d.ts.map +1 -0
  155. package/lib/typescript/src/types/VisibleRange.d.ts +10 -0
  156. package/lib/typescript/src/types/VisibleRange.d.ts.map +1 -0
  157. package/lib/typescript/src/types/VisibleRangeInput.d.ts +35 -0
  158. package/lib/typescript/src/types/VisibleRangeInput.d.ts.map +1 -0
  159. package/lib/typescript/src/types/index.d.ts +8 -0
  160. package/lib/typescript/src/types/index.d.ts.map +1 -0
  161. package/lib/typescript/src/types/layout/LayoutRect.d.ts +15 -0
  162. package/lib/typescript/src/types/layout/LayoutRect.d.ts.map +1 -0
  163. package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts +10 -0
  164. package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts.map +1 -0
  165. package/lib/typescript/src/types/layout/MainAxisPadding.d.ts +20 -0
  166. package/lib/typescript/src/types/layout/MainAxisPadding.d.ts.map +1 -0
  167. package/lib/typescript/src/types/layout/index.d.ts +4 -0
  168. package/lib/typescript/src/types/layout/index.d.ts.map +1 -0
  169. package/lib/typescript/src/types/recycler/RecyclerCellInstance.d.ts +37 -0
  170. package/lib/typescript/src/types/recycler/RecyclerCellInstance.d.ts.map +1 -0
  171. package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts +8 -0
  172. package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts.map +1 -0
  173. package/lib/typescript/src/types/recycler/RecyclerListProps.d.ts +66 -0
  174. package/lib/typescript/src/types/recycler/RecyclerListProps.d.ts.map +1 -0
  175. package/lib/typescript/src/types/recycler/index.d.ts +4 -0
  176. package/lib/typescript/src/types/recycler/index.d.ts.map +1 -0
  177. package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts +15 -0
  178. package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts.map +1 -0
  179. package/lib/typescript/src/types/scroll/index.d.ts +2 -0
  180. package/lib/typescript/src/types/scroll/index.d.ts.map +1 -0
  181. package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts +15 -0
  182. package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts.map +1 -0
  183. package/lib/typescript/src/windowing/index.d.ts +1 -1
  184. package/lib/typescript/src/windowing/index.d.ts.map +1 -1
  185. package/nitrogen/generated/android/c++/JHybridNitroLayoutEngineSpec.cpp +7 -7
  186. package/nitrogen/generated/android/c++/JHybridNitroLayoutEngineSpec.hpp +1 -1
  187. package/nitrogen/generated/android/c++/{JLayoutRectangle.hpp → JLayoutRect.hpp} +10 -10
  188. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/HybridNitroLayoutEngineSpec.kt +1 -1
  189. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/{LayoutRectangle.kt → LayoutRect.kt} +5 -5
  190. package/nitrogen/generated/ios/NitroList-Swift-Cxx-Bridge.hpp +14 -14
  191. package/nitrogen/generated/ios/NitroList-Swift-Cxx-Umbrella.hpp +3 -3
  192. package/nitrogen/generated/ios/c++/HybridNitroLayoutEngineSpecSwift.hpp +4 -4
  193. package/nitrogen/generated/ios/swift/HybridNitroLayoutEngineSpec.swift +1 -1
  194. package/nitrogen/generated/ios/swift/HybridNitroLayoutEngineSpec_cxx.swift +5 -5
  195. package/nitrogen/generated/ios/swift/{LayoutRectangle.swift → LayoutRect.swift} +5 -5
  196. package/nitrogen/generated/shared/c++/HybridNitroLayoutEngineSpec.hpp +4 -4
  197. package/nitrogen/generated/shared/c++/{LayoutRectangle.hpp → LayoutRect.hpp} +11 -11
  198. package/package.json +1 -1
  199. package/src/cell/Cell.ts +13 -4
  200. package/src/cell/CellKeyGenerator.ts +17 -0
  201. package/src/cell/CellRecycler.ts +53 -43
  202. package/src/cell/createCell.ts +15 -0
  203. package/src/cell/index.ts +5 -0
  204. package/src/getVisibleIndices.ts +4 -2
  205. package/src/hooks/usePersistentCallback.ts +37 -0
  206. package/src/index.ts +1 -2
  207. package/src/layout/MutableLinearLayout.ts +91 -58
  208. package/src/layout/constants/layoutDefaults.ts +12 -0
  209. package/src/layout/index.ts +1 -4
  210. package/src/native/NitroList.types.ts +3 -2
  211. package/src/recycler/CellPool.ts +47 -0
  212. package/src/recycler/RecyclerList.tsx +304 -0
  213. package/src/specs/nitro-layout-engine.nitro.ts +2 -2
  214. package/src/types/Axis.ts +10 -0
  215. package/src/types/CellKey.ts +9 -0
  216. package/src/types/CellType.ts +10 -0
  217. package/src/types/VisibleRange.ts +9 -0
  218. package/src/types/VisibleRangeInput.ts +39 -0
  219. package/src/types/index.ts +15 -0
  220. package/src/types/layout/LayoutRect.ts +14 -0
  221. package/src/types/layout/LinearLayoutInput.ts +12 -0
  222. package/src/types/layout/MainAxisPadding.ts +23 -0
  223. package/src/types/layout/index.ts +3 -0
  224. package/src/types/recycler/RecyclerCellInstance.ts +40 -0
  225. package/src/types/recycler/RecyclerItemRenderer.ts +8 -0
  226. package/src/types/recycler/RecyclerListProps.ts +74 -0
  227. package/src/types/recycler/index.ts +3 -0
  228. package/src/types/scroll/ScrollMetrics.ts +18 -0
  229. package/src/types/scroll/index.ts +1 -0
  230. package/src/windowing/computeVisibleItemRange.ts +78 -0
  231. package/src/windowing/index.ts +1 -1
  232. package/lib/commonjs/RecyclerList.internal.js +0 -25
  233. package/lib/commonjs/RecyclerList.internal.js.map +0 -1
  234. package/lib/commonjs/RecyclerList.js +0 -171
  235. package/lib/commonjs/RecyclerList.js.map +0 -1
  236. package/lib/commonjs/RecyclerList.types.js.map +0 -1
  237. package/lib/commonjs/cell/StableKey.js +0 -10
  238. package/lib/commonjs/cell/StableKey.js.map +0 -1
  239. package/lib/commonjs/hooks/useCellRenderer.js +0 -62
  240. package/lib/commonjs/hooks/useCellRenderer.js.map +0 -1
  241. package/lib/commonjs/hooks/useStableCallback.js +0 -13
  242. package/lib/commonjs/hooks/useStableCallback.js.map +0 -1
  243. package/lib/commonjs/layout/EstimatedLayoutProvider.js +0 -30
  244. package/lib/commonjs/layout/EstimatedLayoutProvider.js.map +0 -1
  245. package/lib/commonjs/layout/LayoutEngine.js +0 -21
  246. package/lib/commonjs/layout/LayoutEngine.js.map +0 -1
  247. package/lib/commonjs/layout/LayoutRectangle.js +0 -2
  248. package/lib/commonjs/viewability/ViewabilityHelper.js +0 -121
  249. package/lib/commonjs/viewability/ViewabilityHelper.js.map +0 -1
  250. package/lib/commonjs/windowing/findVisibleIndexRange.js +0 -48
  251. package/lib/commonjs/windowing/findVisibleIndexRange.js.map +0 -1
  252. package/lib/module/RecyclerList.internal.js +0 -22
  253. package/lib/module/RecyclerList.internal.js.map +0 -1
  254. package/lib/module/RecyclerList.js +0 -166
  255. package/lib/module/RecyclerList.js.map +0 -1
  256. package/lib/module/RecyclerList.types.js +0 -4
  257. package/lib/module/RecyclerList.types.js.map +0 -1
  258. package/lib/module/cell/StableKey.js +0 -6
  259. package/lib/module/cell/StableKey.js.map +0 -1
  260. package/lib/module/hooks/useCellRenderer.js +0 -58
  261. package/lib/module/hooks/useCellRenderer.js.map +0 -1
  262. package/lib/module/hooks/useStableCallback.js +0 -9
  263. package/lib/module/hooks/useStableCallback.js.map +0 -1
  264. package/lib/module/layout/EstimatedLayoutProvider.js +0 -25
  265. package/lib/module/layout/EstimatedLayoutProvider.js.map +0 -1
  266. package/lib/module/layout/LayoutEngine.js +0 -17
  267. package/lib/module/layout/LayoutEngine.js.map +0 -1
  268. package/lib/module/layout/LayoutProvider.js +0 -4
  269. package/lib/module/layout/LayoutRectangle.js +0 -2
  270. package/lib/module/viewability/ViewabilityHelper.js +0 -116
  271. package/lib/module/viewability/ViewabilityHelper.js.map +0 -1
  272. package/lib/module/windowing/findVisibleIndexRange.js +0 -44
  273. package/lib/module/windowing/findVisibleIndexRange.js.map +0 -1
  274. package/lib/typescript/src/RecyclerList.d.ts +0 -26
  275. package/lib/typescript/src/RecyclerList.d.ts.map +0 -1
  276. package/lib/typescript/src/RecyclerList.internal.d.ts +0 -9
  277. package/lib/typescript/src/RecyclerList.internal.d.ts.map +0 -1
  278. package/lib/typescript/src/RecyclerList.types.d.ts +0 -18
  279. package/lib/typescript/src/RecyclerList.types.d.ts.map +0 -1
  280. package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts +0 -2
  281. package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts.map +0 -1
  282. package/lib/typescript/src/cell/StableKey.d.ts +0 -2
  283. package/lib/typescript/src/cell/StableKey.d.ts.map +0 -1
  284. package/lib/typescript/src/hooks/useCellRenderer.d.ts +0 -19
  285. package/lib/typescript/src/hooks/useCellRenderer.d.ts.map +0 -1
  286. package/lib/typescript/src/hooks/useStableCallback.d.ts +0 -2
  287. package/lib/typescript/src/hooks/useStableCallback.d.ts.map +0 -1
  288. package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts +0 -15
  289. package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts.map +0 -1
  290. package/lib/typescript/src/layout/LayoutEngine.d.ts +0 -10
  291. package/lib/typescript/src/layout/LayoutEngine.d.ts.map +0 -1
  292. package/lib/typescript/src/layout/LayoutProvider.d.ts +0 -16
  293. package/lib/typescript/src/layout/LayoutProvider.d.ts.map +0 -1
  294. package/lib/typescript/src/layout/LayoutRectangle.d.ts +0 -11
  295. package/lib/typescript/src/layout/LayoutRectangle.d.ts.map +0 -1
  296. package/lib/typescript/src/viewability/ViewabilityHelper.d.ts +0 -50
  297. package/lib/typescript/src/viewability/ViewabilityHelper.d.ts.map +0 -1
  298. package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts +0 -11
  299. package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts.map +0 -1
  300. package/src/RecyclerList.internal.ts +0 -38
  301. package/src/RecyclerList.tsx +0 -252
  302. package/src/RecyclerList.types.ts +0 -24
  303. package/src/__tests__/windowing/findVisibleIndexRange.test.ts +0 -55
  304. package/src/cell/StableKey.ts +0 -6
  305. package/src/hooks/useCellRenderer.ts +0 -86
  306. package/src/hooks/useStableCallback.ts +0 -13
  307. package/src/layout/EstimatedLayoutProvider.ts +0 -35
  308. package/src/layout/LayoutEngine.ts +0 -21
  309. package/src/layout/LayoutProvider.ts +0 -17
  310. package/src/layout/LayoutRectangle.ts +0 -10
  311. package/src/viewability/ViewabilityHelper.ts +0 -130
  312. package/src/windowing/findVisibleIndexRange.ts +0 -60
@@ -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'
2
4
 
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
- }
5
+ import { DEFAULT_ITEM_SPACING } from './constants/layoutDefaults'
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'
@@ -1,4 +1,5 @@
1
- import type { LayoutRectangle } from '../layout/LayoutRectangle'
1
+ import type { LayoutRect } from "../types/layout";
2
+
2
3
 
3
4
  /**
4
5
  * JS runtime interface backed by Nitro (JSI).
@@ -8,5 +9,5 @@ export interface NitroList {
8
9
  computeLayout(
9
10
  containerWidth: number,
10
11
  itemHeights: readonly number[]
11
- ): readonly LayoutRectangle[]
12
+ ): readonly LayoutRect[]
12
13
  }
@@ -0,0 +1,47 @@
1
+ import type { CellType } from '../types/CellType'
2
+ import type { RecyclerCellInstance } from '../types/recycler'
3
+
4
+ export class CellPool {
5
+ private readonly pools = new Map<CellType, RecyclerCellInstance[]>()
6
+ private readonly maxPerType = new Map<CellType, number>()
7
+
8
+ /** ✅ NEW: check if a type is registered */
9
+ hasType(type: CellType): boolean {
10
+ return this.pools.has(type)
11
+ }
12
+
13
+ registerType(type: CellType, maxCount: number): void {
14
+ if (this.maxPerType.has(type)) return
15
+ this.maxPerType.set(type, maxCount)
16
+ this.pools.set(type, [])
17
+ }
18
+
19
+ acquire(type: CellType): RecyclerCellInstance | null {
20
+ const bucket = this.pools.get(type)
21
+ if (!bucket || bucket.length === 0) return null
22
+ return bucket.pop()!
23
+ }
24
+
25
+ release(cell: RecyclerCellInstance): void {
26
+ const { type } = cell
27
+ const bucket = this.pools.get(type)
28
+ const max = this.maxPerType.get(type)
29
+
30
+ if (!bucket || max === undefined) return
31
+
32
+ cell.index = -1
33
+
34
+ if (bucket.length >= max) return
35
+ bucket.push(cell)
36
+ }
37
+
38
+ clear(): void {
39
+ for (const bucket of this.pools.values()) {
40
+ bucket.length = 0
41
+ }
42
+ }
43
+
44
+ getPoolSize(type: CellType): number {
45
+ return this.pools.get(type)?.length ?? 0
46
+ }
47
+ }
@@ -0,0 +1,304 @@
1
+ import React, { useRef, useEffect, useState } from 'react'
2
+ import {
3
+ ScrollView,
4
+ View,
5
+ StyleSheet,
6
+ type NativeSyntheticEvent,
7
+ type NativeScrollEvent,
8
+ } from 'react-native'
9
+
10
+ import type { LayoutRect, VisibleRange } from '../types'
11
+ import type {
12
+ RecyclerCellInstance,
13
+ RecyclerListProps,
14
+ } from '../types/recycler'
15
+ import type { CellType } from '../types/CellType'
16
+
17
+ import { MutableLinearLayout } from '../layout/MutableLinearLayout'
18
+ import { computeVisibleItemRange } from '../windowing'
19
+ import { CellPool } from './CellPool'
20
+
21
+ /* =========================================================
22
+ * Constants
23
+ * =======================================================*/
24
+
25
+ const DEFAULT_VIEWPORT_SIZE = 800
26
+ const DEFAULT_ITEM_SIZE = 60
27
+ const SCROLL_EVENT_THROTTLE = 16
28
+
29
+ /* =========================================================
30
+ * RecyclerList
31
+ * =======================================================*/
32
+
33
+ export function RecyclerList<T>(
34
+ props: RecyclerListProps<T>
35
+ ): React.ReactElement {
36
+ const {
37
+ scrollDirection = 'vertical',
38
+ containerCrossAxisSize,
39
+ data,
40
+ itemMainAxisSizes,
41
+ padding = { start: 0, end: 0 },
42
+ itemSpacing,
43
+ bufferRatio = 1.3,
44
+ getCellType,
45
+ renderItem,
46
+ } = props
47
+
48
+ const isVertical = scrollDirection === 'vertical'
49
+ const itemCount = data.length
50
+
51
+ /* -------------------------------------------------------
52
+ * Controlled render
53
+ * -----------------------------------------------------*/
54
+
55
+ const [, forceRender] = useState(0)
56
+
57
+ /* -------------------------------------------------------
58
+ * Layout engine
59
+ * -----------------------------------------------------*/
60
+
61
+ const layoutEngineRef = useRef<MutableLinearLayout | null>(null)
62
+ const layoutSignatureRef = useRef('')
63
+
64
+ const layoutSignature = [
65
+ scrollDirection,
66
+ containerCrossAxisSize,
67
+ itemCount,
68
+ itemMainAxisSizes,
69
+ padding.start,
70
+ padding.end,
71
+ itemSpacing ?? 'default',
72
+ ].join('|')
73
+
74
+ if (
75
+ !layoutEngineRef.current ||
76
+ layoutSignatureRef.current !== layoutSignature
77
+ ) {
78
+ const engine = new MutableLinearLayout(scrollDirection)
79
+ engine.compute({
80
+ crossAxisSize: containerCrossAxisSize,
81
+ itemMainAxisSizes,
82
+ padding,
83
+ itemSpacing,
84
+ })
85
+ layoutEngineRef.current = engine
86
+ layoutSignatureRef.current = layoutSignature
87
+ }
88
+
89
+ const layouts: readonly LayoutRect[] =
90
+ layoutEngineRef.current.getLayouts()
91
+
92
+ const contentSize =
93
+ layoutEngineRef.current.getContentSize()
94
+
95
+ /* -------------------------------------------------------
96
+ * Scroll metrics
97
+ * -----------------------------------------------------*/
98
+
99
+ const scrollOffsetRef = useRef(0)
100
+ const viewportSizeRef = useRef(DEFAULT_VIEWPORT_SIZE)
101
+
102
+ /* -------------------------------------------------------
103
+ * Cell pool + physical cells
104
+ * -----------------------------------------------------*/
105
+
106
+ const cellPoolRef = useRef(new CellPool())
107
+ const activeCellsRef = useRef<RecyclerCellInstance[]>([])
108
+ const nextCellKeyRef = useRef(0)
109
+
110
+ const createCell = (type: CellType): RecyclerCellInstance => ({
111
+ key: nextCellKeyRef.current++,
112
+ index: -1,
113
+ type,
114
+ })
115
+
116
+ const MAX_CELLS = Math.ceil(
117
+ (viewportSizeRef.current / DEFAULT_ITEM_SIZE) *
118
+ bufferRatio
119
+ ) + 2
120
+
121
+ /* -------------------------------------------------------
122
+ * Visible cell coordinator
123
+ * -----------------------------------------------------*/
124
+
125
+ const updateVisibleCells = (): void => {
126
+ const offset = scrollOffsetRef.current
127
+ const viewportSize = viewportSizeRef.current
128
+ const buffer = viewportSize * bufferRatio
129
+
130
+ const range: VisibleRange | null =
131
+ computeVisibleItemRange({
132
+ layouts,
133
+ offset,
134
+ viewportSize,
135
+ buffer,
136
+ isVertical,
137
+ })
138
+
139
+ if (!range) return
140
+
141
+ const nextCells: RecyclerCellInstance[] = []
142
+ const used = new Set<RecyclerCellInstance>()
143
+
144
+ for (
145
+ let index = range.startIndex;
146
+ index <= range.endIndex;
147
+ index++
148
+ ) {
149
+ const item = data[index]
150
+ if (item === undefined) continue
151
+
152
+ const type = getCellType(item, index)
153
+
154
+ // Register type once, with hard cap
155
+ if (!cellPoolRef.current.hasType(type)) {
156
+ cellPoolRef.current.registerType(type, MAX_CELLS)
157
+ for (let i = 0; i < MAX_CELLS; i++) {
158
+ cellPoolRef.current.release(createCell(type))
159
+ }
160
+ }
161
+
162
+ let cell = cellPoolRef.current.acquire(type)
163
+
164
+ if (!cell) {
165
+ const reuseIndex =
166
+ activeCellsRef.current.findIndex(
167
+ c => c.type === type
168
+ )
169
+
170
+ if (reuseIndex === -1) continue
171
+
172
+ cell =
173
+ activeCellsRef.current.splice(
174
+ reuseIndex,
175
+ 1
176
+ )[0]!
177
+ }
178
+
179
+ cell.index = index
180
+ nextCells.push(cell)
181
+ used.add(cell)
182
+ }
183
+
184
+ for (const cell of activeCellsRef.current) {
185
+ if (!used.has(cell)) {
186
+ cellPoolRef.current.release(cell)
187
+ }
188
+ }
189
+
190
+ let changed =
191
+ nextCells.length !== activeCellsRef.current.length
192
+
193
+ if (!changed) {
194
+ for (let i = 0; i < nextCells.length; i++) {
195
+ if (nextCells[i] !== activeCellsRef.current[i]) {
196
+ changed = true
197
+ break
198
+ }
199
+ }
200
+ }
201
+
202
+ if (changed) {
203
+ activeCellsRef.current = nextCells
204
+ forceRender(v => v + 1)
205
+ }
206
+ }
207
+
208
+ /* -------------------------------------------------------
209
+ * Scroll handlers
210
+ * -----------------------------------------------------*/
211
+
212
+ const frameScheduledRef = useRef(false)
213
+
214
+ const onScroll = (
215
+ e: NativeSyntheticEvent<NativeScrollEvent>
216
+ ): void => {
217
+ scrollOffsetRef.current = isVertical
218
+ ? e.nativeEvent.contentOffset.y
219
+ : e.nativeEvent.contentOffset.x
220
+
221
+ if (frameScheduledRef.current) return
222
+ frameScheduledRef.current = true
223
+
224
+ requestAnimationFrame(() => {
225
+ frameScheduledRef.current = false
226
+ updateVisibleCells()
227
+ })
228
+ }
229
+
230
+ const onLayout = (e: any): void => {
231
+ viewportSizeRef.current = isVertical
232
+ ? e.nativeEvent.layout.height
233
+ : e.nativeEvent.layout.width
234
+
235
+ updateVisibleCells()
236
+ }
237
+
238
+ useEffect(() => {
239
+ updateVisibleCells()
240
+ // eslint-disable-next-line react-hooks/exhaustive-deps
241
+ }, [])
242
+
243
+ /* -------------------------------------------------------
244
+ * Render
245
+ * -----------------------------------------------------*/
246
+
247
+ return (
248
+ <ScrollView
249
+ onScroll={onScroll}
250
+ onLayout={onLayout}
251
+ horizontal={!isVertical}
252
+ scrollEventThrottle={SCROLL_EVENT_THROTTLE}
253
+ removeClippedSubviews
254
+ >
255
+ <View
256
+ style={
257
+ isVertical
258
+ ? { height: contentSize }
259
+ : { width: contentSize }
260
+ }
261
+ >
262
+ {activeCellsRef.current.map(cell => {
263
+ const index = cell.index
264
+ const layout = layouts[index]
265
+ const item = data[index]
266
+
267
+ if (!layout || item === undefined) return null
268
+
269
+ return (
270
+ <View
271
+ key={cell.key}
272
+ style={[
273
+ styles.cell,
274
+ isVertical
275
+ ? {
276
+ top: layout.y,
277
+ height: layout.height,
278
+ width: layout.width,
279
+ }
280
+ : {
281
+ left: layout.x,
282
+ width: layout.width,
283
+ height: layout.height,
284
+ },
285
+ ]}
286
+ >
287
+ {renderItem({ item, index, cell })}
288
+ </View>
289
+ )
290
+ })}
291
+ </View>
292
+ </ScrollView>
293
+ )
294
+ }
295
+
296
+ /* =========================================================
297
+ * Styles
298
+ * =======================================================*/
299
+
300
+ const styles = StyleSheet.create({
301
+ cell: {
302
+ position: 'absolute',
303
+ },
304
+ })
@@ -1,6 +1,6 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules'
2
2
 
3
- export interface LayoutRectangle {
3
+ export interface LayoutRect {
4
4
  readonly x: number
5
5
  readonly y: number
6
6
  readonly width: number
@@ -13,5 +13,5 @@ export interface NitroLayoutEngine
13
13
  computeLayout(
14
14
  containerWidth: number,
15
15
  itemHeights: readonly number[]
16
- ): readonly LayoutRectangle[]
16
+ ): readonly LayoutRect[]
17
17
  }
@@ -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,9 @@
1
+ /**
2
+ * Stable identifier for a cell.
3
+ *
4
+ * Cross-platform equivalent:
5
+ * - Flutter: Key
6
+ * - Android: stableId
7
+ * - iOS: reuseIdentifier (logical)
8
+ */
9
+ export type CellKey = string | number
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Logical cell type.
3
+ *
4
+ * Used to group compatible cells for recycling.
5
+ *
6
+ * Cross-platform equivalent:
7
+ * - Android: viewType
8
+ * - iOS: reuseIdentifier
9
+ */
10
+ export type CellType = string | number
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Visible item index range.
3
+ *
4
+ * Indices are inclusive.
5
+ */
6
+ export interface VisibleRange {
7
+ readonly startIndex: number
8
+ readonly endIndex: number
9
+ }
@@ -0,0 +1,39 @@
1
+ import type { LayoutRect } from './layout/LayoutRect'
2
+
3
+ /**
4
+ * Input required to compute the visible item range.
5
+ *
6
+ * Pure contract:
7
+ * - No logic
8
+ * - No platform assumptions
9
+ * - Safe to share with native / tests
10
+ */
11
+ export interface VisibleRangeInput {
12
+ /**
13
+ * Ordered, monotonic layouts along the main axis.
14
+ * Required for binary search correctness.
15
+ */
16
+ readonly layouts: readonly LayoutRect[]
17
+
18
+ /**
19
+ * Scroll offset along the main axis.
20
+ */
21
+ readonly offset: number
22
+
23
+ /**
24
+ * Viewport size along the main axis.
25
+ */
26
+ readonly viewportSize: number
27
+
28
+ /**
29
+ * Extra buffer before and after the viewport.
30
+ */
31
+ readonly buffer: number
32
+
33
+ /**
34
+ * Axis selector.
35
+ * true → vertical
36
+ * false → horizontal
37
+ */
38
+ readonly isVertical: boolean
39
+ }
@@ -0,0 +1,15 @@
1
+ export type { Axis } from './Axis'
2
+
3
+ export type {
4
+ MainAxisPadding,
5
+ } from './layout/MainAxisPadding'
6
+ export {
7
+ ZERO_MAIN_AXIS_PADDING,
8
+ } from './layout/MainAxisPadding'
9
+
10
+ export type { LayoutRect } from './layout/LayoutRect'
11
+ export type { VisibleRange } from './VisibleRange'
12
+ export type { CellKey } from './CellKey'
13
+ export type { CellType } from './CellType'
14
+
15
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Absolute layout rectangle.
3
+ *
4
+ * Cross-platform equivalent of:
5
+ * - Flutter: Rect
6
+ * - Android: Rect
7
+ * - iOS: CGRect
8
+ */
9
+ export interface LayoutRect {
10
+ readonly x: number
11
+ readonly y: number
12
+ readonly width: number
13
+ readonly height: number
14
+ }
@@ -0,0 +1,12 @@
1
+ import type { MainAxisPadding } from './MainAxisPadding'
2
+
3
+ export interface LinearLayoutInput {
4
+ readonly crossAxisSize: number
5
+ readonly itemMainAxisSizes: readonly number[]
6
+
7
+ /** Padding before/after content (main axis) */
8
+ readonly padding: MainAxisPadding
9
+
10
+ /** Space BETWEEN items (main axis) */
11
+ readonly itemSpacing?: number
12
+ }