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.
- package/README.md +16 -44
- package/ios/HybridNitroList.swift +12 -14
- package/lib/commonjs/cell/CellKeyGenerator.js +21 -0
- package/lib/commonjs/cell/CellKeyGenerator.js.map +1 -0
- package/lib/commonjs/cell/CellRecycler.js +48 -40
- package/lib/commonjs/cell/CellRecycler.js.map +1 -1
- package/lib/commonjs/cell/createCell.js +21 -0
- package/lib/commonjs/cell/createCell.js.map +1 -0
- package/lib/commonjs/cell/index.js +20 -0
- package/lib/commonjs/cell/index.js.map +1 -0
- package/lib/commonjs/getVisibleIndices.js.map +1 -1
- package/lib/commonjs/hooks/usePersistentCallback.js +36 -0
- package/lib/commonjs/hooks/usePersistentCallback.js.map +1 -0
- package/lib/commonjs/index.js +31 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/layout/MutableLinearLayout.js +78 -39
- package/lib/commonjs/layout/MutableLinearLayout.js.map +1 -1
- package/lib/commonjs/layout/constants/layoutDefaults.js +19 -0
- package/lib/commonjs/layout/constants/layoutDefaults.js.map +1 -0
- package/lib/commonjs/layout/index.js +0 -18
- package/lib/commonjs/layout/index.js.map +1 -1
- package/lib/commonjs/native/NitroListView.js +20 -0
- package/lib/commonjs/native/NitroListView.js.map +1 -0
- package/lib/commonjs/recycler/CellPool.js +33 -0
- package/lib/commonjs/recycler/CellPool.js.map +1 -0
- package/lib/commonjs/recycler/NitroList.js +223 -0
- package/lib/commonjs/recycler/NitroList.js.map +1 -0
- package/lib/commonjs/scroll/useScrollVelocity.js +20 -0
- package/lib/commonjs/scroll/useScrollVelocity.js.map +1 -0
- package/lib/commonjs/{native/NitroList.types.js → specs/NitroList.nitro.js} +1 -1
- package/lib/commonjs/{layout/LayoutProvider.js.map → specs/NitroList.nitro.js.map} +1 -1
- package/lib/commonjs/types/Axis.js +2 -0
- package/lib/{module/layout/LayoutProvider.js.map → commonjs/types/Axis.js.map} +1 -1
- package/lib/commonjs/types/CellKey.js +2 -0
- package/lib/commonjs/{layout/LayoutRectangle.js.map → types/CellKey.js.map} +1 -1
- package/lib/commonjs/types/CellType.js +27 -0
- package/lib/commonjs/types/CellType.js.map +1 -0
- package/lib/commonjs/types/VisibleRange.js +2 -0
- package/lib/commonjs/{native/NitroList.types.js.map → types/VisibleRange.js.map} +1 -1
- package/lib/commonjs/{RecyclerList.types.js → types/VisibleRangeInput.js} +1 -1
- package/lib/commonjs/types/VisibleRangeInput.js.map +1 -0
- package/lib/commonjs/types/index.js +13 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/types/layout/LayoutRect.js +2 -0
- package/lib/commonjs/types/layout/LayoutRect.js.map +1 -0
- package/lib/commonjs/{specs/nitro-layout-engine.nitro.js → types/layout/LinearLayoutInput.js} +1 -1
- package/lib/commonjs/types/layout/LinearLayoutInput.js.map +1 -0
- package/lib/commonjs/types/layout/MainAxisPadding.js +26 -0
- package/lib/commonjs/types/layout/MainAxisPadding.js.map +1 -0
- package/lib/commonjs/types/layout/index.js +2 -0
- package/lib/commonjs/types/layout/index.js.map +1 -0
- package/lib/commonjs/types/recycler/CellPool.js +42 -0
- package/lib/commonjs/types/recycler/CellPool.js.map +1 -0
- package/lib/commonjs/{layout/LayoutProvider.js → types/recycler/NitroListProps.js} +1 -1
- package/lib/commonjs/types/recycler/NitroListProps.js.map +1 -0
- package/lib/commonjs/types/recycler/RecyclerCell.js +6 -0
- package/lib/commonjs/types/recycler/RecyclerCell.js.map +1 -0
- package/lib/commonjs/types/recycler/RecyclerItemRenderer.js +6 -0
- package/lib/commonjs/types/recycler/RecyclerItemRenderer.js.map +1 -0
- package/lib/commonjs/types/recycler/index.js +2 -0
- package/lib/commonjs/types/recycler/index.js.map +1 -0
- package/lib/commonjs/types/scroll/ScrollMetrics.js +6 -0
- package/lib/commonjs/types/scroll/ScrollMetrics.js.map +1 -0
- package/lib/commonjs/types/scroll/index.js +2 -0
- package/lib/commonjs/types/scroll/index.js.map +1 -0
- package/lib/commonjs/windowing/computeVisibleItemRange.js +61 -0
- package/lib/commonjs/windowing/computeVisibleItemRange.js.map +1 -0
- package/lib/commonjs/windowing/index.js +3 -3
- package/lib/commonjs/windowing/index.js.map +1 -1
- package/lib/module/cell/CellKeyGenerator.js +16 -0
- package/lib/module/cell/CellKeyGenerator.js.map +1 -0
- package/lib/module/cell/CellRecycler.js +48 -39
- package/lib/module/cell/CellRecycler.js.map +1 -1
- package/lib/module/cell/createCell.js +17 -0
- package/lib/module/cell/createCell.js.map +1 -0
- package/lib/module/cell/index.js +7 -0
- package/lib/module/cell/index.js.map +1 -0
- package/lib/module/getVisibleIndices.js.map +1 -1
- package/lib/module/hooks/usePersistentCallback.js +33 -0
- package/lib/module/hooks/usePersistentCallback.js.map +1 -0
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/layout/MutableLinearLayout.js +78 -38
- package/lib/module/layout/MutableLinearLayout.js.map +1 -1
- package/lib/module/layout/constants/layoutDefaults.js +15 -0
- package/lib/module/layout/constants/layoutDefaults.js.map +1 -0
- package/lib/module/layout/index.js +0 -3
- package/lib/module/layout/index.js.map +1 -1
- package/lib/module/native/NitroListView.js +17 -0
- package/lib/module/native/NitroListView.js.map +1 -0
- package/lib/module/recycler/CellPool.js +28 -0
- package/lib/module/recycler/CellPool.js.map +1 -0
- package/lib/module/recycler/NitroList.js +220 -0
- package/lib/module/recycler/NitroList.js.map +1 -0
- package/lib/module/scroll/useScrollVelocity.js +16 -0
- package/lib/module/scroll/useScrollVelocity.js.map +1 -0
- package/lib/module/specs/NitroList.nitro.js +4 -0
- package/lib/module/specs/NitroList.nitro.js.map +1 -0
- package/lib/module/types/Axis.js +2 -0
- package/lib/module/types/Axis.js.map +1 -0
- package/lib/module/types/CellKey.js +2 -0
- package/lib/module/types/CellKey.js.map +1 -0
- package/lib/module/types/CellType.js +22 -0
- package/lib/module/types/CellType.js.map +1 -0
- package/lib/module/types/VisibleRange.js +2 -0
- package/lib/module/types/VisibleRange.js.map +1 -0
- package/lib/module/types/VisibleRangeInput.js +4 -0
- package/lib/module/types/VisibleRangeInput.js.map +1 -0
- package/lib/module/types/index.js +4 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/types/layout/LayoutRect.js +2 -0
- package/lib/module/types/layout/LayoutRect.js.map +1 -0
- package/lib/module/types/layout/LinearLayoutInput.js +4 -0
- package/lib/module/types/layout/LinearLayoutInput.js.map +1 -0
- package/lib/module/types/layout/MainAxisPadding.js +22 -0
- package/lib/module/types/layout/MainAxisPadding.js.map +1 -0
- package/lib/module/types/layout/index.js +2 -0
- package/lib/module/types/layout/index.js.map +1 -0
- package/lib/module/types/recycler/CellPool.js +37 -0
- package/lib/module/types/recycler/CellPool.js.map +1 -0
- package/lib/module/types/recycler/NitroListProps.js +4 -0
- package/lib/module/types/recycler/NitroListProps.js.map +1 -0
- package/lib/module/types/recycler/RecyclerCell.js +4 -0
- package/lib/module/types/recycler/RecyclerCell.js.map +1 -0
- package/lib/module/types/recycler/RecyclerItemRenderer.js +4 -0
- package/lib/module/types/recycler/RecyclerItemRenderer.js.map +1 -0
- package/lib/module/types/recycler/index.js +2 -0
- package/lib/module/types/recycler/index.js.map +1 -0
- package/lib/module/types/scroll/ScrollMetrics.js +4 -0
- package/lib/module/types/scroll/ScrollMetrics.js.map +1 -0
- package/lib/module/types/scroll/index.js +2 -0
- package/lib/module/types/scroll/index.js.map +1 -0
- package/lib/module/windowing/computeVisibleItemRange.js +57 -0
- package/lib/module/windowing/computeVisibleItemRange.js.map +1 -0
- package/lib/module/windowing/index.js +1 -1
- package/lib/module/windowing/index.js.map +1 -1
- package/lib/typescript/src/cell/Cell.d.ts +13 -4
- package/lib/typescript/src/cell/Cell.d.ts.map +1 -1
- package/lib/typescript/src/cell/CellKeyGenerator.d.ts +11 -0
- package/lib/typescript/src/cell/CellKeyGenerator.d.ts.map +1 -0
- package/lib/typescript/src/cell/CellRecycler.d.ts +19 -11
- package/lib/typescript/src/cell/CellRecycler.d.ts.map +1 -1
- package/lib/typescript/src/cell/createCell.d.ts +7 -0
- package/lib/typescript/src/cell/createCell.d.ts.map +1 -0
- package/lib/typescript/src/cell/index.d.ts +4 -0
- package/lib/typescript/src/cell/index.d.ts.map +1 -0
- package/lib/typescript/src/getVisibleIndices.d.ts +2 -2
- package/lib/typescript/src/getVisibleIndices.d.ts.map +1 -1
- package/lib/typescript/src/hooks/usePersistentCallback.d.ts +16 -0
- package/lib/typescript/src/hooks/usePersistentCallback.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/layout/MutableLinearLayout.d.ts +45 -13
- package/lib/typescript/src/layout/MutableLinearLayout.d.ts.map +1 -1
- package/lib/typescript/src/layout/constants/layoutDefaults.d.ts +13 -0
- package/lib/typescript/src/layout/constants/layoutDefaults.d.ts.map +1 -0
- package/lib/typescript/src/layout/index.d.ts +1 -4
- package/lib/typescript/src/layout/index.d.ts.map +1 -1
- package/lib/typescript/src/native/NitroListView.d.ts +20 -0
- package/lib/typescript/src/native/NitroListView.d.ts.map +1 -0
- package/lib/typescript/src/recycler/CellPool.d.ts +11 -0
- package/lib/typescript/src/recycler/CellPool.d.ts.map +1 -0
- package/lib/typescript/src/recycler/NitroList.d.ts +4 -0
- package/lib/typescript/src/recycler/NitroList.d.ts.map +1 -0
- package/lib/typescript/src/scroll/useScrollVelocity.d.ts +2 -0
- package/lib/typescript/src/scroll/useScrollVelocity.d.ts.map +1 -0
- package/lib/typescript/src/specs/NitroList.nitro.d.ts +26 -0
- package/lib/typescript/src/specs/NitroList.nitro.d.ts.map +1 -0
- package/lib/typescript/src/types/Axis.d.ts +11 -0
- package/lib/typescript/src/types/Axis.d.ts.map +1 -0
- package/lib/typescript/src/types/CellKey.d.ts +2 -0
- package/lib/typescript/src/types/CellKey.d.ts.map +1 -0
- package/lib/typescript/src/types/CellType.d.ts +22 -0
- package/lib/typescript/src/types/CellType.d.ts.map +1 -0
- package/lib/typescript/src/types/VisibleRange.d.ts +10 -0
- package/lib/typescript/src/types/VisibleRange.d.ts.map +1 -0
- package/lib/typescript/src/types/VisibleRangeInput.d.ts +35 -0
- package/lib/typescript/src/types/VisibleRangeInput.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +8 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -0
- package/lib/typescript/src/types/layout/LayoutRect.d.ts +15 -0
- package/lib/typescript/src/types/layout/LayoutRect.d.ts.map +1 -0
- package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts +10 -0
- package/lib/typescript/src/types/layout/LinearLayoutInput.d.ts.map +1 -0
- package/lib/typescript/src/types/layout/MainAxisPadding.d.ts +20 -0
- package/lib/typescript/src/types/layout/MainAxisPadding.d.ts.map +1 -0
- package/lib/typescript/src/types/layout/index.d.ts +4 -0
- package/lib/typescript/src/types/layout/index.d.ts.map +1 -0
- package/lib/typescript/src/types/recycler/CellPool.d.ts +16 -0
- package/lib/typescript/src/types/recycler/CellPool.d.ts.map +1 -0
- package/lib/typescript/src/types/recycler/NitroListProps.d.ts +66 -0
- package/lib/typescript/src/types/recycler/NitroListProps.d.ts.map +1 -0
- package/lib/typescript/src/types/recycler/RecyclerCell.d.ts +12 -0
- package/lib/typescript/src/types/recycler/RecyclerCell.d.ts.map +1 -0
- package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts +12 -0
- package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts.map +1 -0
- package/lib/typescript/src/types/recycler/index.d.ts +4 -0
- package/lib/typescript/src/types/recycler/index.d.ts.map +1 -0
- package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts +15 -0
- package/lib/typescript/src/types/scroll/ScrollMetrics.d.ts.map +1 -0
- package/lib/typescript/src/types/scroll/index.d.ts +2 -0
- package/lib/typescript/src/types/scroll/index.d.ts.map +1 -0
- package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts +19 -0
- package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts.map +1 -0
- package/lib/typescript/src/windowing/index.d.ts +1 -1
- package/lib/typescript/src/windowing/index.d.ts.map +1 -1
- package/nitro.json +5 -5
- package/nitrogen/generated/android/NitroList+autolinking.cmake +2 -2
- package/nitrogen/generated/android/NitroListOnLoad.cpp +2 -2
- package/nitrogen/generated/android/c++/{JHybridNitroLayoutEngineSpec.cpp → JHybridNitroListSpec.cpp} +15 -15
- package/nitrogen/generated/android/c++/{JHybridNitroLayoutEngineSpec.hpp → JHybridNitroListSpec.hpp} +11 -11
- package/nitrogen/generated/android/c++/{JLayoutRectangle.hpp → JItemLayout.hpp} +10 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/{HybridNitroLayoutEngineSpec.kt → HybridNitroListSpec.kt} +7 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolist/{LayoutRectangle.kt → ItemLayout.kt} +5 -5
- package/nitrogen/generated/ios/NitroList-Swift-Cxx-Bridge.cpp +9 -9
- package/nitrogen/generated/ios/NitroList-Swift-Cxx-Bridge.hpp +27 -27
- package/nitrogen/generated/ios/NitroList-Swift-Cxx-Umbrella.hpp +8 -8
- package/nitrogen/generated/ios/c++/{HybridNitroLayoutEngineSpecSwift.cpp → HybridNitroListSpecSwift.cpp} +2 -2
- package/nitrogen/generated/ios/c++/{HybridNitroLayoutEngineSpecSwift.hpp → HybridNitroListSpecSwift.hpp} +16 -16
- package/nitrogen/generated/ios/swift/HybridNitroListSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/{HybridNitroLayoutEngineSpec_cxx.swift → HybridNitroListSpec_cxx.swift} +23 -23
- package/nitrogen/generated/ios/swift/{LayoutRectangle.swift → ItemLayout.swift} +5 -5
- package/nitrogen/generated/shared/c++/{HybridNitroLayoutEngineSpec.cpp → HybridNitroListSpec.cpp} +4 -4
- package/nitrogen/generated/shared/c++/{HybridNitroLayoutEngineSpec.hpp → HybridNitroListSpec.hpp} +13 -13
- package/nitrogen/generated/shared/c++/{LayoutRectangle.hpp → ItemLayout.hpp} +11 -11
- package/package.json +5 -5
- package/src/cell/Cell.ts +13 -4
- package/src/cell/CellKeyGenerator.ts +17 -0
- package/src/cell/CellRecycler.ts +53 -43
- package/src/cell/createCell.ts +15 -0
- package/src/cell/index.ts +5 -0
- package/src/getVisibleIndices.ts +4 -2
- package/src/hooks/usePersistentCallback.ts +37 -0
- package/src/index.ts +7 -2
- package/src/layout/MutableLinearLayout.ts +91 -58
- package/src/layout/constants/layoutDefaults.ts +12 -0
- package/src/layout/index.ts +1 -4
- package/src/native/NitroListView.ts +22 -0
- package/src/recycler/CellPool.ts +33 -0
- package/src/recycler/NitroList.tsx +317 -0
- package/src/scroll/useScrollVelocity.ts +16 -0
- package/src/specs/NitroList.nitro.ts +29 -0
- package/src/types/Axis.ts +10 -0
- package/src/types/CellKey.ts +2 -0
- package/src/types/CellType.ts +9 -0
- package/src/types/VisibleRange.ts +9 -0
- package/src/types/VisibleRangeInput.ts +39 -0
- package/src/types/index.ts +15 -0
- package/src/types/layout/LayoutRect.ts +14 -0
- package/src/types/layout/LinearLayoutInput.ts +12 -0
- package/src/types/layout/MainAxisPadding.ts +23 -0
- package/src/types/layout/index.ts +3 -0
- package/src/types/recycler/CellPool.ts +45 -0
- package/src/types/recycler/NitroListProps.ts +74 -0
- package/src/types/recycler/RecyclerCell.ts +12 -0
- package/src/types/recycler/RecyclerItemRenderer.ts +12 -0
- package/src/types/recycler/index.ts +3 -0
- package/src/types/scroll/ScrollMetrics.ts +18 -0
- package/src/types/scroll/index.ts +1 -0
- package/src/windowing/computeVisibleItemRange.ts +82 -0
- package/src/windowing/index.ts +1 -1
- package/lib/commonjs/NitroList.js +0 -9
- package/lib/commonjs/NitroList.js.map +0 -1
- package/lib/commonjs/RecyclerList.internal.js +0 -25
- package/lib/commonjs/RecyclerList.internal.js.map +0 -1
- package/lib/commonjs/RecyclerList.js +0 -171
- package/lib/commonjs/RecyclerList.js.map +0 -1
- package/lib/commonjs/RecyclerList.types.js.map +0 -1
- package/lib/commonjs/cell/StableKey.js +0 -10
- package/lib/commonjs/cell/StableKey.js.map +0 -1
- package/lib/commonjs/hooks/useCellRenderer.js +0 -62
- package/lib/commonjs/hooks/useCellRenderer.js.map +0 -1
- package/lib/commonjs/hooks/useStableCallback.js +0 -13
- package/lib/commonjs/hooks/useStableCallback.js.map +0 -1
- package/lib/commonjs/layout/EstimatedLayoutProvider.js +0 -30
- package/lib/commonjs/layout/EstimatedLayoutProvider.js.map +0 -1
- package/lib/commonjs/layout/LayoutEngine.js +0 -21
- package/lib/commonjs/layout/LayoutEngine.js.map +0 -1
- package/lib/commonjs/layout/LayoutRectangle.js +0 -2
- package/lib/commonjs/native/NitroLayoutEngine.js +0 -9
- package/lib/commonjs/native/NitroLayoutEngine.js.map +0 -1
- package/lib/commonjs/native/NitroRecyclerView.js +0 -9
- package/lib/commonjs/native/NitroRecyclerView.js.map +0 -1
- package/lib/commonjs/specs/nitro-layout-engine.nitro.js.map +0 -1
- package/lib/commonjs/viewability/ViewabilityHelper.js +0 -121
- package/lib/commonjs/viewability/ViewabilityHelper.js.map +0 -1
- package/lib/commonjs/windowing/findVisibleIndexRange.js +0 -48
- package/lib/commonjs/windowing/findVisibleIndexRange.js.map +0 -1
- package/lib/module/NitroList.js +0 -5
- package/lib/module/NitroList.js.map +0 -1
- package/lib/module/RecyclerList.internal.js +0 -22
- package/lib/module/RecyclerList.internal.js.map +0 -1
- package/lib/module/RecyclerList.js +0 -166
- package/lib/module/RecyclerList.js.map +0 -1
- package/lib/module/RecyclerList.types.js +0 -4
- package/lib/module/RecyclerList.types.js.map +0 -1
- package/lib/module/cell/StableKey.js +0 -6
- package/lib/module/cell/StableKey.js.map +0 -1
- package/lib/module/hooks/useCellRenderer.js +0 -58
- package/lib/module/hooks/useCellRenderer.js.map +0 -1
- package/lib/module/hooks/useStableCallback.js +0 -9
- package/lib/module/hooks/useStableCallback.js.map +0 -1
- package/lib/module/layout/EstimatedLayoutProvider.js +0 -25
- package/lib/module/layout/EstimatedLayoutProvider.js.map +0 -1
- package/lib/module/layout/LayoutEngine.js +0 -17
- package/lib/module/layout/LayoutEngine.js.map +0 -1
- package/lib/module/layout/LayoutProvider.js +0 -4
- package/lib/module/layout/LayoutRectangle.js +0 -2
- package/lib/module/layout/LayoutRectangle.js.map +0 -1
- package/lib/module/native/NitroLayoutEngine.js +0 -5
- package/lib/module/native/NitroLayoutEngine.js.map +0 -1
- package/lib/module/native/NitroList.types.js +0 -4
- package/lib/module/native/NitroList.types.js.map +0 -1
- package/lib/module/native/NitroRecyclerView.js +0 -5
- package/lib/module/native/NitroRecyclerView.js.map +0 -1
- package/lib/module/specs/nitro-layout-engine.nitro.js +0 -4
- package/lib/module/specs/nitro-layout-engine.nitro.js.map +0 -1
- package/lib/module/viewability/ViewabilityHelper.js +0 -116
- package/lib/module/viewability/ViewabilityHelper.js.map +0 -1
- package/lib/module/windowing/findVisibleIndexRange.js +0 -44
- package/lib/module/windowing/findVisibleIndexRange.js.map +0 -1
- package/lib/typescript/src/NitroList.d.ts +0 -5
- package/lib/typescript/src/NitroList.d.ts.map +0 -1
- package/lib/typescript/src/RecyclerList.d.ts +0 -26
- package/lib/typescript/src/RecyclerList.d.ts.map +0 -1
- package/lib/typescript/src/RecyclerList.internal.d.ts +0 -9
- package/lib/typescript/src/RecyclerList.internal.d.ts.map +0 -1
- package/lib/typescript/src/RecyclerList.types.d.ts +0 -18
- package/lib/typescript/src/RecyclerList.types.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts +0 -2
- package/lib/typescript/src/__tests__/windowing/findVisibleIndexRange.test.d.ts.map +0 -1
- package/lib/typescript/src/cell/StableKey.d.ts +0 -2
- package/lib/typescript/src/cell/StableKey.d.ts.map +0 -1
- package/lib/typescript/src/hooks/useCellRenderer.d.ts +0 -19
- package/lib/typescript/src/hooks/useCellRenderer.d.ts.map +0 -1
- package/lib/typescript/src/hooks/useStableCallback.d.ts +0 -2
- package/lib/typescript/src/hooks/useStableCallback.d.ts.map +0 -1
- package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts +0 -15
- package/lib/typescript/src/layout/EstimatedLayoutProvider.d.ts.map +0 -1
- package/lib/typescript/src/layout/LayoutEngine.d.ts +0 -10
- package/lib/typescript/src/layout/LayoutEngine.d.ts.map +0 -1
- package/lib/typescript/src/layout/LayoutProvider.d.ts +0 -16
- package/lib/typescript/src/layout/LayoutProvider.d.ts.map +0 -1
- package/lib/typescript/src/layout/LayoutRectangle.d.ts +0 -11
- package/lib/typescript/src/layout/LayoutRectangle.d.ts.map +0 -1
- package/lib/typescript/src/native/NitroLayoutEngine.d.ts +0 -3
- package/lib/typescript/src/native/NitroLayoutEngine.d.ts.map +0 -1
- package/lib/typescript/src/native/NitroList.types.d.ts +0 -9
- package/lib/typescript/src/native/NitroList.types.d.ts.map +0 -1
- package/lib/typescript/src/native/NitroRecyclerView.d.ts +0 -5
- package/lib/typescript/src/native/NitroRecyclerView.d.ts.map +0 -1
- package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts +0 -14
- package/lib/typescript/src/specs/nitro-layout-engine.nitro.d.ts.map +0 -1
- package/lib/typescript/src/viewability/ViewabilityHelper.d.ts +0 -50
- package/lib/typescript/src/viewability/ViewabilityHelper.d.ts.map +0 -1
- package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts +0 -11
- package/lib/typescript/src/windowing/findVisibleIndexRange.d.ts.map +0 -1
- package/nitrogen/generated/ios/swift/HybridNitroLayoutEngineSpec.swift +0 -56
- package/src/NitroList.ts +0 -8
- package/src/RecyclerList.internal.ts +0 -38
- package/src/RecyclerList.tsx +0 -252
- package/src/RecyclerList.types.ts +0 -24
- package/src/__tests__/windowing/findVisibleIndexRange.test.ts +0 -55
- package/src/cell/StableKey.ts +0 -6
- package/src/hooks/useCellRenderer.ts +0 -86
- package/src/hooks/useStableCallback.ts +0 -13
- package/src/layout/EstimatedLayoutProvider.ts +0 -35
- package/src/layout/LayoutEngine.ts +0 -21
- package/src/layout/LayoutProvider.ts +0 -17
- package/src/layout/LayoutRectangle.ts +0 -10
- package/src/native/NitroLayoutEngine.ts +0 -7
- package/src/native/NitroList.types.ts +0 -12
- package/src/native/NitroRecyclerView.ts +0 -8
- package/src/specs/nitro-layout-engine.nitro.ts +0 -17
- package/src/viewability/ViewabilityHelper.ts +0 -130
- package/src/windowing/findVisibleIndexRange.ts +0 -60
package/src/getVisibleIndices.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
-
|
|
2
|
-
|
|
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 {
|
|
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
|
|
16
|
-
*
|
|
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
|
|
20
|
-
private totalHeight: number
|
|
21
|
+
private readonly isVertical: boolean
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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.
|
|
82
|
+
this.layouts = layouts
|
|
83
|
+
this.contentSize = cursor + padding.end
|
|
40
84
|
}
|
|
41
85
|
|
|
42
86
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
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
|
|
92
|
+
getLayouts(): readonly LayoutRect[] {
|
|
47
93
|
return this.layouts
|
|
48
94
|
}
|
|
49
95
|
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
*
|
|
56
|
-
*
|
|
105
|
+
* Clears internal layout state.
|
|
106
|
+
* Call on severe invalidation or teardown.
|
|
57
107
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
package/src/layout/index.ts
CHANGED
|
@@ -1,4 +1 @@
|
|
|
1
|
-
export type {
|
|
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
|
+
}
|