react-native-nitro-list 0.1.2 → 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 +7 -5
- package/lib/commonjs/index.js +31 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/layout/MutableLinearLayout.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 +5 -18
- package/lib/commonjs/recycler/CellPool.js.map +1 -1
- package/lib/commonjs/recycler/{RecyclerList.js → NitroList.js} +91 -92
- 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/{native/NitroList.types.js.map → specs/NitroList.nitro.js.map} +1 -1
- package/lib/commonjs/types/CellType.js +25 -0
- package/lib/commonjs/types/CellType.js.map +1 -1
- package/lib/commonjs/types/recycler/CellPool.js +42 -0
- package/lib/commonjs/types/recycler/CellPool.js.map +1 -0
- package/lib/commonjs/types/recycler/{RecyclerListProps.js → NitroListProps.js} +1 -1
- package/lib/commonjs/types/recycler/NitroListProps.js.map +1 -0
- package/lib/commonjs/types/recycler/{RecyclerCellInstance.js → RecyclerCell.js} +1 -1
- package/lib/commonjs/types/recycler/RecyclerCell.js.map +1 -0
- package/lib/commonjs/windowing/computeVisibleItemRange.js +22 -32
- package/lib/commonjs/windowing/computeVisibleItemRange.js.map +1 -1
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/layout/MutableLinearLayout.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 +5 -18
- package/lib/module/recycler/CellPool.js.map +1 -1
- 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/{native/NitroList.types.js.map → specs/NitroList.nitro.js.map} +1 -1
- package/lib/module/types/CellType.js +20 -0
- package/lib/module/types/CellType.js.map +1 -1
- 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/windowing/computeVisibleItemRange.js +22 -32
- package/lib/module/windowing/computeVisibleItemRange.js.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/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 +4 -7
- package/lib/typescript/src/recycler/CellPool.d.ts.map +1 -1
- 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/CellKey.d.ts +1 -9
- package/lib/typescript/src/types/CellKey.d.ts.map +1 -1
- package/lib/typescript/src/types/CellType.d.ts +12 -1
- package/lib/typescript/src/types/CellType.d.ts.map +1 -1
- 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/{RecyclerListProps.d.ts → NitroListProps.d.ts} +3 -3
- 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 +6 -2
- package/lib/typescript/src/types/recycler/RecyclerItemRenderer.d.ts.map +1 -1
- package/lib/typescript/src/types/recycler/index.d.ts +2 -2
- package/lib/typescript/src/types/recycler/index.d.ts.map +1 -1
- package/lib/typescript/src/windowing/computeVisibleItemRange.d.ts +16 -12
- package/lib/typescript/src/windowing/computeVisibleItemRange.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++/{JLayoutRect.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/{LayoutRect.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/{LayoutRect.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++/{LayoutRect.hpp → ItemLayout.hpp} +11 -11
- package/package.json +5 -5
- package/src/index.ts +7 -1
- package/src/layout/MutableLinearLayout.ts +1 -1
- package/src/native/NitroListView.ts +22 -0
- package/src/recycler/CellPool.ts +10 -24
- 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/CellKey.ts +2 -9
- package/src/types/CellType.ts +8 -9
- package/src/types/recycler/CellPool.ts +45 -0
- package/src/types/recycler/{RecyclerListProps.ts → NitroListProps.ts} +2 -2
- package/src/types/recycler/RecyclerCell.ts +12 -0
- package/src/types/recycler/RecyclerItemRenderer.ts +6 -2
- package/src/types/recycler/index.ts +2 -2
- package/src/windowing/computeVisibleItemRange.ts +42 -38
- package/lib/commonjs/NitroList.js +0 -9
- package/lib/commonjs/NitroList.js.map +0 -1
- 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/recycler/RecyclerList.js.map +0 -1
- package/lib/commonjs/specs/nitro-layout-engine.nitro.js +0 -6
- package/lib/commonjs/specs/nitro-layout-engine.nitro.js.map +0 -1
- package/lib/commonjs/types/recycler/RecyclerCellInstance.js.map +0 -1
- package/lib/commonjs/types/recycler/RecyclerListProps.js.map +0 -1
- package/lib/module/NitroList.js +0 -5
- package/lib/module/NitroList.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/NitroRecyclerView.js +0 -5
- package/lib/module/native/NitroRecyclerView.js.map +0 -1
- package/lib/module/recycler/RecyclerList.js +0 -221
- package/lib/module/recycler/RecyclerList.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/types/recycler/RecyclerCellInstance.js +0 -4
- package/lib/module/types/recycler/RecyclerCellInstance.js.map +0 -1
- package/lib/module/types/recycler/RecyclerListProps.js +0 -4
- package/lib/module/types/recycler/RecyclerListProps.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/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/recycler/RecyclerList.d.ts +0 -4
- package/lib/typescript/src/recycler/RecyclerList.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/types/recycler/RecyclerCellInstance.d.ts +0 -37
- package/lib/typescript/src/types/recycler/RecyclerCellInstance.d.ts.map +0 -1
- package/lib/typescript/src/types/recycler/RecyclerListProps.d.ts.map +0 -1
- package/nitrogen/generated/ios/swift/HybridNitroLayoutEngineSpec.swift +0 -56
- package/src/NitroList.ts +0 -8
- package/src/native/NitroLayoutEngine.ts +0 -7
- package/src/native/NitroList.types.ts +0 -13
- package/src/native/NitroRecyclerView.ts +0 -8
- package/src/recycler/RecyclerList.tsx +0 -304
- package/src/specs/nitro-layout-engine.nitro.ts +0 -17
- package/src/types/recycler/RecyclerCellInstance.ts +0 -40
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NitroRecyclerView.d.ts","sourceRoot":"","sources":["../../../../src/native/NitroRecyclerView.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,iBAAiB,8DACuC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RecyclerList.d.ts","sourceRoot":"","sources":["../../../../src/recycler/RecyclerList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAU1D,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,mBAAmB,CAAA;AAmB1B,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC1B,KAAK,CAAC,YAAY,CAmQpB"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
export interface LayoutRect {
|
|
3
|
-
readonly x: number;
|
|
4
|
-
readonly y: number;
|
|
5
|
-
readonly width: number;
|
|
6
|
-
readonly height: number;
|
|
7
|
-
}
|
|
8
|
-
export interface NitroLayoutEngine extends HybridObject<{
|
|
9
|
-
ios: 'swift';
|
|
10
|
-
android: 'kotlin';
|
|
11
|
-
}> {
|
|
12
|
-
computeLayout(containerWidth: number, itemHeights: readonly number[]): readonly LayoutRect[];
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=nitro-layout-engine.nitro.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nitro-layout-engine.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/nitro-layout-engine.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,iBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IAEzD,aAAa,CACX,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,SAAS,UAAU,EAAE,CAAA;CACzB"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { CellKey } from "../CellKey";
|
|
2
|
-
import type { CellType } from "../CellType";
|
|
3
|
-
/**
|
|
4
|
-
* Physical reusable cell instance.
|
|
5
|
-
*
|
|
6
|
-
* Represents a single mounted view that can be rebound
|
|
7
|
-
* to different data items as scrolling occurs.
|
|
8
|
-
*
|
|
9
|
-
* Cross-platform equivalent:
|
|
10
|
-
* - Flutter: Element / RenderObject
|
|
11
|
-
* - Android: ViewHolder
|
|
12
|
-
* - iOS: UICollectionViewCell
|
|
13
|
-
*/
|
|
14
|
-
export interface RecyclerCellInstance {
|
|
15
|
-
/**
|
|
16
|
-
* Stable physical identity.
|
|
17
|
-
*
|
|
18
|
-
* Used as React key.
|
|
19
|
-
* MUST remain constant for the lifetime of the instance.
|
|
20
|
-
*/
|
|
21
|
-
readonly key: CellKey;
|
|
22
|
-
/**
|
|
23
|
-
* Logical data index currently bound to this instance.
|
|
24
|
-
*
|
|
25
|
-
* This value changes as the cell is recycled.
|
|
26
|
-
* - -1 may be used to indicate "unbound".
|
|
27
|
-
*/
|
|
28
|
-
index: number;
|
|
29
|
-
/**
|
|
30
|
-
* Logical compatibility type.
|
|
31
|
-
*
|
|
32
|
-
* Determines which instances can be reused together.
|
|
33
|
-
* Instances with different types MUST NOT be reused.
|
|
34
|
-
*/
|
|
35
|
-
readonly type: CellType;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=RecyclerCellInstance.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RecyclerCellInstance.d.ts","sourceRoot":"","sources":["../../../../../src/types/recycler/RecyclerCellInstance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAG3C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IAErB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CACxB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RecyclerListProps.d.ts","sourceRoot":"","sources":["../../../../../src/types/recycler/RecyclerListProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;IAE/B;;;;;;OAMG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAA;IAEvC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAE3B;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IAE7C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAA;IAElC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAE7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAE7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,QAAQ,CAAA;IAE1D;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAA;CAC7C"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
///
|
|
2
|
-
/// HybridNitroLayoutEngineSpec.swift
|
|
3
|
-
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
-
/// https://github.com/mrousavy/nitro
|
|
5
|
-
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
import Foundation
|
|
9
|
-
import NitroModules
|
|
10
|
-
|
|
11
|
-
/// See ``HybridNitroLayoutEngineSpec``
|
|
12
|
-
public protocol HybridNitroLayoutEngineSpec_protocol: HybridObject {
|
|
13
|
-
// Properties
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// Methods
|
|
17
|
-
func computeLayout(containerWidth: Double, itemHeights: [Double]) throws -> [LayoutRect]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public extension HybridNitroLayoutEngineSpec_protocol {
|
|
21
|
-
/// Default implementation of ``HybridObject.toString``
|
|
22
|
-
func toString() -> String {
|
|
23
|
-
return "[HybridObject NitroLayoutEngine]"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/// See ``HybridNitroLayoutEngineSpec``
|
|
28
|
-
open class HybridNitroLayoutEngineSpec_base {
|
|
29
|
-
private weak var cxxWrapper: HybridNitroLayoutEngineSpec_cxx? = nil
|
|
30
|
-
public init() { }
|
|
31
|
-
public func getCxxWrapper() -> HybridNitroLayoutEngineSpec_cxx {
|
|
32
|
-
#if DEBUG
|
|
33
|
-
guard self is HybridNitroLayoutEngineSpec else {
|
|
34
|
-
fatalError("`self` is not a `HybridNitroLayoutEngineSpec`! Did you accidentally inherit from `HybridNitroLayoutEngineSpec_base` instead of `HybridNitroLayoutEngineSpec`?")
|
|
35
|
-
}
|
|
36
|
-
#endif
|
|
37
|
-
if let cxxWrapper = self.cxxWrapper {
|
|
38
|
-
return cxxWrapper
|
|
39
|
-
} else {
|
|
40
|
-
let cxxWrapper = HybridNitroLayoutEngineSpec_cxx(self as! HybridNitroLayoutEngineSpec)
|
|
41
|
-
self.cxxWrapper = cxxWrapper
|
|
42
|
-
return cxxWrapper
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* A Swift base-protocol representing the NitroLayoutEngine HybridObject.
|
|
49
|
-
* Implement this protocol to create Swift-based instances of NitroLayoutEngine.
|
|
50
|
-
* ```swift
|
|
51
|
-
* class HybridNitroLayoutEngine : HybridNitroLayoutEngineSpec {
|
|
52
|
-
* // ...
|
|
53
|
-
* }
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
public typealias HybridNitroLayoutEngineSpec = HybridNitroLayoutEngineSpec_protocol & HybridNitroLayoutEngineSpec_base
|
package/src/NitroList.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { NitroModules } from 'react-native-nitro-modules'
|
|
2
|
-
import type { NitroLayoutEngine as NitroLayoutEngineSpec } from '../specs/nitro-layout-engine.nitro'
|
|
3
|
-
|
|
4
|
-
export const NitroLayoutEngine =
|
|
5
|
-
NitroModules.createHybridObject<NitroLayoutEngineSpec>(
|
|
6
|
-
'NitroLayoutEngine'
|
|
7
|
-
)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { LayoutRect } from "../types/layout";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* JS runtime interface backed by Nitro (JSI).
|
|
6
|
-
* Must match native HybridNitroList exactly.
|
|
7
|
-
*/
|
|
8
|
-
export interface NitroList {
|
|
9
|
-
computeLayout(
|
|
10
|
-
containerWidth: number,
|
|
11
|
-
itemHeights: readonly number[]
|
|
12
|
-
): readonly LayoutRect[]
|
|
13
|
-
}
|
|
@@ -1,304 +0,0 @@
|
|
|
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,17 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from 'react-native-nitro-modules'
|
|
2
|
-
|
|
3
|
-
export interface LayoutRect {
|
|
4
|
-
readonly x: number
|
|
5
|
-
readonly y: number
|
|
6
|
-
readonly width: number
|
|
7
|
-
readonly height: number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface NitroLayoutEngine
|
|
11
|
-
extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
|
|
12
|
-
|
|
13
|
-
computeLayout(
|
|
14
|
-
containerWidth: number,
|
|
15
|
-
itemHeights: readonly number[]
|
|
16
|
-
): readonly LayoutRect[]
|
|
17
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { CellKey } from "../CellKey"
|
|
2
|
-
import type { CellType } from "../CellType"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Physical reusable cell instance.
|
|
7
|
-
*
|
|
8
|
-
* Represents a single mounted view that can be rebound
|
|
9
|
-
* to different data items as scrolling occurs.
|
|
10
|
-
*
|
|
11
|
-
* Cross-platform equivalent:
|
|
12
|
-
* - Flutter: Element / RenderObject
|
|
13
|
-
* - Android: ViewHolder
|
|
14
|
-
* - iOS: UICollectionViewCell
|
|
15
|
-
*/
|
|
16
|
-
export interface RecyclerCellInstance {
|
|
17
|
-
/**
|
|
18
|
-
* Stable physical identity.
|
|
19
|
-
*
|
|
20
|
-
* Used as React key.
|
|
21
|
-
* MUST remain constant for the lifetime of the instance.
|
|
22
|
-
*/
|
|
23
|
-
readonly key: CellKey
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Logical data index currently bound to this instance.
|
|
27
|
-
*
|
|
28
|
-
* This value changes as the cell is recycled.
|
|
29
|
-
* - -1 may be used to indicate "unbound".
|
|
30
|
-
*/
|
|
31
|
-
index: number
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Logical compatibility type.
|
|
35
|
-
*
|
|
36
|
-
* Determines which instances can be reused together.
|
|
37
|
-
* Instances with different types MUST NOT be reused.
|
|
38
|
-
*/
|
|
39
|
-
readonly type: CellType
|
|
40
|
-
}
|