react-native-list 1.0.1 → 2.0.0-alpha.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.
- package/README.md +186 -32
- package/ReactNativeList.podspec +39 -0
- package/android/CMakeLists.txt +48 -0
- package/android/build.gradle +151 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/JHybridUiListModule.cpp +192 -0
- package/android/src/main/cpp/JHybridUiListModule.h +50 -0
- package/android/src/main/cpp/cpp-adapter.cpp +12 -0
- package/android/src/main/java/com/hannojg/reactnativelist/ReactNativeListPackage.kt +27 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListDataSource.kt +146 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListLayout.kt +86 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListModule.kt +116 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListView.kt +410 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridViewHolder.kt +9 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/NativeListAdapter.kt +217 -0
- package/ios/DataSource/HybridNativeListDataSource.swift +213 -0
- package/ios/HybridObjects/HybridUiListModule.swift +49 -0
- package/ios/HybridObjects/HybridViewHolder.swift +16 -0
- package/ios/Layout/HybridNativeListLayout.swift +128 -0
- package/ios/Utils/ErrorUtils.h +26 -0
- package/ios/Utils/HybridIOSWorkletsModuleProxyHolder.swift +10 -0
- package/ios/Utils/SurfaceHelper.h +20 -0
- package/ios/Utils/SurfaceHelper.mm +144 -0
- package/ios/Utils/SurfacePresenterRegistry.h +17 -0
- package/ios/Utils/SurfacePresenterRegistry.m +31 -0
- package/ios/Utils/TurboModuleInstaller.h +18 -0
- package/ios/Utils/TurboModuleInstaller.mm +267 -0
- package/ios/Views/HostCell.swift +216 -0
- package/ios/Views/HybridUiListView.swift +695 -0
- package/lib/ReactFabricMirror.d.ts +4 -0
- package/lib/ReactFabricMirror.js +515 -0
- package/lib/UiListModule.d.ts +2 -0
- package/lib/UiListModule.js +2 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +21 -0
- package/lib/privateGlobals.d.ts +14 -0
- package/lib/privateGlobals.js +2 -0
- package/lib/renderer/RenderHelper.d.ts +2 -0
- package/lib/renderer/RenderHelper.js +11 -0
- package/lib/renderer/UiManagerHelper.d.ts +2 -0
- package/lib/renderer/UiManagerHelper.js +2 -0
- package/lib/renderer/fabric/RenderHelper.d.ts +2 -0
- package/lib/renderer/fabric/RenderHelper.js +11 -0
- package/lib/renderer/fabric/UiManagerHelper.d.ts +2 -0
- package/lib/renderer/fabric/UiManagerHelper.js +2 -0
- package/lib/renderer/react/ReactFabricMirror.d.ts +4 -0
- package/lib/renderer/react/ReactFabricMirror.js +515 -0
- package/lib/renderer/react/ReactFabricRenderer.d.ts +3 -0
- package/lib/renderer/react/ReactFabricRenderer.js +9 -0
- package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.d.ts +6 -0
- package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.js +1 -0
- package/lib/specs/UIListModule.nitro.d.ts +9 -0
- package/lib/specs/UIListModule.nitro.js +1 -0
- package/lib/specs/UIManagerHelper.nitro.d.ts +13 -0
- package/lib/specs/UIManagerHelper.nitro.js +1 -0
- package/lib/specs/UiListView.nitro.d.ts +20 -0
- package/lib/specs/UiListView.nitro.js +1 -0
- package/lib/specs/ViewHolder.nitro.d.ts +6 -0
- package/lib/specs/ViewHolder.nitro.js +1 -0
- package/lib/views/List.d.ts +35 -0
- package/lib/views/List.js +225 -0
- package/lib/views/UiListHostComponent.d.ts +2 -0
- package/lib/views/UiListHostComponent.js +3 -0
- package/metro/RendererProxyThreadSwitch.js +66 -0
- package/metro-config.d.ts +1 -0
- package/metro-config.js +124 -0
- package/nitro.json +47 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/ReactNativeList+autolinking.cmake +99 -0
- package/nitrogen/generated/android/ReactNativeList+autolinking.gradle +27 -0
- package/nitrogen/generated/android/ReactNativeListOnLoad.cpp +156 -0
- package/nitrogen/generated/android/ReactNativeListOnLoad.hpp +34 -0
- package/nitrogen/generated/android/c++/JFunc_bool_NativeListItem_NativeListItem.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_bool_double_NativeListItem_double.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_double_std__string.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp +63 -0
- package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.hpp +65 -0
- package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp +101 -0
- package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.hpp +70 -0
- package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp +65 -0
- package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.hpp +64 -0
- package/nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp +92 -0
- package/nitrogen/generated/android/c++/JHybridUiListViewSpec.hpp +67 -0
- package/nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridViewHolderSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JNativeItemSizeEstimate.hpp +61 -0
- package/nitrogen/generated/android/c++/JNativeLinearListLayoutConfig.hpp +81 -0
- package/nitrogen/generated/android/c++/JNativeLinearListLayoutIOSConfig.hpp +59 -0
- package/nitrogen/generated/android/c++/JNativeListItem.hpp +76 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.hpp +72 -0
- package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp +53 -0
- package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp +53 -0
- package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_NativeListItem_NativeListItem.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_double_NativeListItem_double.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_double_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridIOSWorkletsModuleProxyHolderSpec.kt +52 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeLinearListLayoutSpec.kt +54 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListDataSourceSpec.kt +87 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListLayoutSpec.kt +52 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListModuleSpec.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListViewSpec.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridViewHolderSpec.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeItemSizeEstimate.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutConfig.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutIOSConfig.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeListItem.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/ReactNativeListOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewStateUpdater.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderStateUpdater.kt +23 -0
- package/nitrogen/generated/ios/ReactNativeList+autolinking.rb +62 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.cpp +162 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.hpp +368 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Umbrella.hpp +92 -0
- package/nitrogen/generated/ios/ReactNativeListAutolinking.mm +83 -0
- package/nitrogen/generated/ios/ReactNativeListAutolinking.swift +86 -0
- package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.hpp +92 -0
- package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.hpp +132 -0
- package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.hpp +93 -0
- package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.hpp +121 -0
- package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/views/HybridUiListViewComponent.mm +118 -0
- package/nitrogen/generated/ios/c++/views/HybridViewHolderComponent.mm +118 -0
- package/nitrogen/generated/ios/swift/Func_bool_NativeListItem_NativeListItem.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_bool_double_NativeListItem_double.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_double_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec_cxx.swift +128 -0
- package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec_cxx.swift +140 -0
- package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec.swift +62 -0
- package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec_cxx.swift +222 -0
- package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec_cxx.swift +128 -0
- package/nitrogen/generated/ios/swift/HybridUiListModuleSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/HybridUiListModuleSpec_cxx.swift +175 -0
- package/nitrogen/generated/ios/swift/HybridUiListViewSpec.swift +59 -0
- package/nitrogen/generated/ios/swift/HybridUiListViewSpec_cxx.swift +227 -0
- package/nitrogen/generated/ios/swift/HybridViewHolderSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridViewHolderSpec_cxx.swift +147 -0
- package/nitrogen/generated/ios/swift/NativeItemSizeEstimate.swift +60 -0
- package/nitrogen/generated/ios/swift/NativeLinearListLayoutConfig.swift +60 -0
- package/nitrogen/generated/ios/swift/NativeLinearListLayoutIOSConfig.swift +35 -0
- package/nitrogen/generated/ios/swift/NativeListItem.swift +75 -0
- package/nitrogen/generated/ios/swift/Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_.swift +30 -0
- package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.hpp +67 -0
- package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp +28 -0
- package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.hpp +72 -0
- package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridUiListViewSpec.hpp +79 -0
- package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridViewHolderSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/NativeItemSizeEstimate.hpp +87 -0
- package/nitrogen/generated/shared/c++/NativeLinearListLayoutConfig.hpp +105 -0
- package/nitrogen/generated/shared/c++/NativeLinearListLayoutIOSConfig.hpp +85 -0
- package/nitrogen/generated/shared/c++/NativeListItem.hpp +101 -0
- package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp +72 -0
- package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.hpp +109 -0
- package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp +72 -0
- package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.hpp +109 -0
- package/nitrogen/generated/shared/json/UiListViewConfig.json +9 -0
- package/nitrogen/generated/shared/json/ViewHolderConfig.json +9 -0
- package/package.json +152 -5
- package/react-native.config.js +16 -0
- package/src/ListDataSource.ts +232 -0
- package/src/ListLayout.ts +95 -0
- package/src/UiListModule.ts +5 -0
- package/src/hooks/useChangeEffect.ts +50 -0
- package/src/index.tsx +49 -0
- package/src/privateGlobals.ts +20 -0
- package/src/renderer/fabric/RenderHelper.ts +29 -0
- package/src/renderer/fabric/UiManagerHelper.ts +5 -0
- package/src/renderer/react/ReactFabricMirror.bundle.js +1984 -0
- package/src/renderer/react/ReactFabricMirror.ts +766 -0
- package/src/renderer/react/ReactFabricRenderer.ts +11 -0
- package/src/specs/IOSWorkletsModuleProxyHolder.nitro.ts +6 -0
- package/src/specs/NativeLinearListLayout.nitro.ts +23 -0
- package/src/specs/NativeListDataSource.nitro.ts +28 -0
- package/src/specs/NativeListLayout.nitro.ts +6 -0
- package/src/specs/UIListModule.nitro.ts +13 -0
- package/src/specs/UIManagerHelper.nitro.ts +34 -0
- package/src/specs/UiListView.nitro.ts +31 -0
- package/src/specs/ViewHolder.nitro.ts +11 -0
- package/src/views/List.tsx +525 -0
- package/src/views/UiListHostComponent.ts +8 -0
- package/FillRateHelper.js +0 -179
- package/FlatList.js +0 -494
- package/LICENSE.md +0 -31
- package/MetroListView.js +0 -166
- package/SectionList.js +0 -291
- package/ViewabilityHelper.js +0 -260
- package/VirtualizeUtils.js +0 -163
- package/VirtualizedList.js +0 -861
- package/VirtualizedSectionList.js +0 -397
- package/index.js +0 -5
package/README.md
CHANGED
|
@@ -1,49 +1,203 @@
|
|
|
1
|
-
|
|
2
|
-
--
|
|
1
|
+
# React Native List
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
High-performance list for React Native.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
- 📱 True native [`UICollectionView`](https://developer.apple.com/documentation/uikit/uicollectionview) on iOS
|
|
6
|
+
- 🤖 True native [`RecyclerView`](https://developer.android.com/develop/ui/views/layout/recyclerview) on android
|
|
7
|
+
- 🔄 Synchronous rendering of react components using "worklet" function components
|
|
8
|
+
- 🐎 Platform native animations out of the box for list item transitions
|
|
9
|
+
- 📉 Low memory usage due to true native view recycling
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
https://github.com/user-attachments/assets/4a2684bf-7337-45e0-bb17-ee7b8a382943
|
|
10
12
|
|
|
11
13
|
## Installation
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
> [!WARNING]
|
|
16
|
+
> Using this library requires you to use [react-native-worklets **bundle mode**](https://docs.swmansion.com/react-native-worklets/docs/bundleMode/setup).
|
|
17
|
+
>
|
|
18
|
+
> - Please follow [the setup instructions of it first](https://docs.swmansion.com/react-native-worklets/docs/bundleMode/setup), and make sure your app works before using react-native-list!
|
|
19
|
+
> - You need at least version 0.10.0!
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
yarn add react-native-list
|
|
17
|
-
```
|
|
18
|
-
or
|
|
19
|
-
```sh
|
|
20
|
-
npm add react-native --save
|
|
21
|
-
```
|
|
21
|
+
Once that's out of the way, you can start with the regular setup of the library:
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
```sh
|
|
24
|
+
bun add react-native-list@alpha
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Configuring Metro
|
|
28
|
+
|
|
29
|
+
Simply wrap your config with `getReactNativeListMetroConfig` in `metro.config.js`:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const { getDefaultConfig } = require("expo/metro-config");
|
|
33
|
+
const {
|
|
34
|
+
getBundleModeMetroConfig,
|
|
35
|
+
} = require("react-native-worklets/bundleMode");
|
|
36
|
+
|
|
37
|
+
let config = getDefaultConfig(__dirname);
|
|
38
|
+
config = getBundleModeMetroConfig(config);
|
|
39
|
+
// ⚠️ Make sure to apply this _after_ the bundle mode metro config:
|
|
40
|
+
config = getReactNativeListMetroConfig(config);
|
|
41
|
+
module.exports = config;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> [!NOTE]
|
|
45
|
+
> If you're using expo you need to make sure to enable inline requires in your metro config:
|
|
46
|
+
>
|
|
47
|
+
> ```js
|
|
48
|
+
> const config = {
|
|
49
|
+
> transformer: {
|
|
50
|
+
> getTransformOptions: async () => ({
|
|
51
|
+
> transform: {
|
|
52
|
+
> // Bundle mode only works with inline support
|
|
53
|
+
> // See: https://github.com/software-mansion/react-native-reanimated/issues/8904
|
|
54
|
+
> inlineRequires: true,
|
|
55
|
+
> },
|
|
56
|
+
> }),
|
|
57
|
+
> },
|
|
58
|
+
> };
|
|
59
|
+
> ```
|
|
60
|
+
>
|
|
61
|
+
> If you don't see a `metro.config.js` in your project, see [expo's documentation on modifying metro](https://docs.expo.dev/guides/customizing-metro/).
|
|
62
|
+
|
|
63
|
+
## Simple example
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { List, useLinearListLayout, useListDataSource } from "react-native-list";
|
|
67
|
+
import type { ListItem, ListRenderers } from "react-native-list";
|
|
24
68
|
|
|
25
|
-
|
|
69
|
+
type TextItem = ListItem<
|
|
70
|
+
// The type of your list item
|
|
71
|
+
"text",
|
|
72
|
+
// The data shape for that list item:
|
|
73
|
+
{
|
|
74
|
+
text: string;
|
|
75
|
+
}
|
|
76
|
+
>;
|
|
26
77
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
78
|
+
type ImageItem = ...
|
|
79
|
+
|
|
80
|
+
type Items = TextItem | ImageItem
|
|
81
|
+
|
|
82
|
+
// Provide render functions for your item types:
|
|
83
|
+
const renderers: ListRenderers<Items> = {
|
|
84
|
+
text: {
|
|
85
|
+
renderItemWorklet: ({ item }) => {
|
|
86
|
+
"worklet"; // 👀 Note: our render function is a worklet!
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
// Though being in a worklet, you can use any component you like in here
|
|
90
|
+
<View
|
|
91
|
+
style={{
|
|
92
|
+
justifyContent: "center",
|
|
93
|
+
paddingHorizontal: 16,
|
|
94
|
+
backgroundColor: "#f6f8fa",
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
// Note: there are two phases: 1. View creation (without data), 2. binding data to the views
|
|
98
|
+
// that's why item.data can be undefined because the native list is requesting to
|
|
99
|
+
// create the view hierarchy, but without any data yet.
|
|
100
|
+
<Text>{item.data?.text}</Text>
|
|
101
|
+
</View>
|
|
102
|
+
);
|
|
35
103
|
},
|
|
36
|
-
}
|
|
37
|
-
|
|
104
|
+
},
|
|
105
|
+
image: ...
|
|
106
|
+
};
|
|
38
107
|
|
|
39
|
-
|
|
108
|
+
export function ExampleList() {
|
|
109
|
+
const dataSource = useListDataSource<Items>({
|
|
110
|
+
data: [...],
|
|
111
|
+
});
|
|
112
|
+
const layout = useLinearListLayout({
|
|
113
|
+
itemSpacing: 8,
|
|
114
|
+
});
|
|
40
115
|
|
|
41
|
-
|
|
116
|
+
return (
|
|
117
|
+
<List
|
|
118
|
+
dataSource={dataSource}
|
|
119
|
+
layout={layout}
|
|
120
|
+
renderers={renderers}
|
|
121
|
+
style={{
|
|
122
|
+
flex: 1,
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
42
128
|
|
|
43
|
-
|
|
44
|
-
|
|
129
|
+
## API
|
|
130
|
+
|
|
131
|
+
XXXX TODO
|
|
132
|
+
|
|
133
|
+
## Benchmark
|
|
134
|
+
|
|
135
|
+
> Scrolling as fast as possible. Release build. iPhone 13 Pro.
|
|
136
|
+
|
|
137
|
+
https://github.com/user-attachments/assets/aa7c2c41-b7ac-4d8b-9eb1-fd8b2feda4de
|
|
45
138
|
|
|
46
|
-
|
|
139
|
+
| | Legend List | react-native-list |
|
|
140
|
+
| --------- | ----------- | ----------------- |
|
|
141
|
+
| FPS | 60 | 60 |
|
|
142
|
+
| Memory | 86.89mb | 86.88mb |
|
|
143
|
+
| Total CPU | 144.69% | 185.93% |
|
|
144
|
+
| Can blank | yes | no |
|
|
145
|
+
|
|
146
|
+
Performance difference is best described as this:
|
|
147
|
+
|
|
148
|
+
- With react-native-list you will never get a blank. However, instead, you could see UI thread drop frames if your item rendering is too heavy.
|
|
149
|
+
- With Legend List you may see blanks, however, its way less likely you will drop frames on the UI thread (instead your JS thread might be fully busy, but you won't really get to notice that on the UIs performance)
|
|
150
|
+
|
|
151
|
+
## Known performance pitfalls
|
|
152
|
+
|
|
153
|
+
- For iOS when using dynamically sized items, try to use `iosConfig.estimatedItemSize` to roughly specify how many items will be visible in the view port. This can help a lot with performance.
|
|
154
|
+
- When specifying sizes for items use `useLinearListLayout({})` inset configs. Avoid setting a width in the styles that exceed the actual available view port width.
|
|
155
|
+
- If you can, always provide item sizes upfront. With that the performance will be unbeatable.
|
|
156
|
+
- In your item render function, when you have no item data yet it is tempting to return early with `null` or just an empty `<View />`. However, this is super bad for performance. There are two phases for native lists. First is view creation, where you're expected to create the view hierarchy for your item - just not with any data yet (so that any data could be bind to it). The second phase is actually binding data to the view. This will result in a simple "update props" operation on the native side instead of needing to create a new view hierarchy. Example:
|
|
157
|
+
|
|
158
|
+
❌ **Bad**:
|
|
159
|
+
|
|
160
|
+
```jsx
|
|
161
|
+
renderItemWorklet: ({ item }) => {
|
|
162
|
+
"worklet";
|
|
163
|
+
if (item == null) return <View />
|
|
164
|
+
return (
|
|
165
|
+
<View>
|
|
166
|
+
<Image src={item.image}>
|
|
167
|
+
<Text>{item.userName}</Text>
|
|
168
|
+
</View>
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
✅ **Good**:
|
|
173
|
+
|
|
174
|
+
```jsx
|
|
175
|
+
renderItemWorklet: ({ item }) => {
|
|
176
|
+
"worklet";
|
|
177
|
+
return (
|
|
178
|
+
<View>
|
|
179
|
+
<Image src={item?.image}>
|
|
180
|
+
<Text>{item?.userName ?? ""}</Text>
|
|
181
|
+
</View>
|
|
182
|
+
)
|
|
47
183
|
```
|
|
48
184
|
|
|
49
|
-
|
|
185
|
+
## Development
|
|
186
|
+
|
|
187
|
+
First clone init the submodules:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
git submodule update --init --recursive
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Regenerate native Nitro specs after changing files in `src/specs` or `nitro.json`:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
bun specs
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Run TypeScript checks:
|
|
200
|
+
|
|
201
|
+
```sh
|
|
202
|
+
bun run typecheck
|
|
203
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "ReactNativeList"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
|
|
14
|
+
s.source = { :git => "https://github.com/hannojg/react-native-list.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = [
|
|
17
|
+
# Implementation (Swift)
|
|
18
|
+
"ios/**/*.{h,swift}",
|
|
19
|
+
# Autolinking/Registration (Objective-C++)
|
|
20
|
+
"ios/**/*.{m,mm}",
|
|
21
|
+
# Implementation (C++ objects)
|
|
22
|
+
"cpp/**/*.{hpp,cpp}",
|
|
23
|
+
]
|
|
24
|
+
s.public_header_files = "ios/**/*.h"
|
|
25
|
+
s.pod_target_xcconfig = {
|
|
26
|
+
"HEADER_SEARCH_PATHS" => [
|
|
27
|
+
'"$(PODS_TARGET_SRCROOT)/ReactCommon"',
|
|
28
|
+
].join(' ')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
load 'nitrogen/generated/ios/ReactNativeList+autolinking.rb'
|
|
32
|
+
add_nitrogen_files(s)
|
|
33
|
+
|
|
34
|
+
s.dependency 'React-jsi'
|
|
35
|
+
s.dependency 'React-callinvoker'
|
|
36
|
+
s.dependency 'DifferenceKit', '~> 1.3'
|
|
37
|
+
s.dependency "RNWorklets"
|
|
38
|
+
install_modules_dependencies(s)
|
|
39
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
project(ReactNativeList)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set (PACKAGE_NAME ReactNativeList)
|
|
5
|
+
set (CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set (CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
# Define C++ library and add all sources
|
|
9
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
10
|
+
../cpp/HybridUiManagerHelper.cpp
|
|
11
|
+
../cpp/WorkletsUiCallInvoker.cpp
|
|
12
|
+
src/main/cpp/cpp-adapter.cpp
|
|
13
|
+
src/main/cpp/JHybridUiListModule.cpp
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Add Nitrogen specs :)
|
|
17
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeList+autolinking.cmake)
|
|
18
|
+
|
|
19
|
+
# Set up local includes
|
|
20
|
+
include_directories(
|
|
21
|
+
"src/main/cpp"
|
|
22
|
+
"../cpp"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
find_library(LOG_LIB log)
|
|
27
|
+
find_package(react-native-worklets REQUIRED) # <-- for Worklets
|
|
28
|
+
|
|
29
|
+
# Worklets prefab headers transitively need these React Native internal headers
|
|
30
|
+
# (they are PRIVATE in the worklets CMakeLists.txt, so not propagated via prefab)
|
|
31
|
+
#TODO: THIS SHOULDN'T BE HARDCODED LIKE THIS!
|
|
32
|
+
set(REACT_NATIVE_DIR "${CMAKE_SOURCE_DIR}/../../node_modules/react-native")
|
|
33
|
+
target_include_directories(${PACKAGE_NAME} PRIVATE
|
|
34
|
+
"${REACT_NATIVE_DIR}/ReactCommon"
|
|
35
|
+
"${REACT_NATIVE_DIR}/ReactCommon/callinvoker"
|
|
36
|
+
"${REACT_NATIVE_DIR}/ReactCommon/runtimeexecutor"
|
|
37
|
+
"${REACT_NATIVE_DIR}/ReactCommon/jsiexecutor"
|
|
38
|
+
"${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule"
|
|
39
|
+
"${REACT_NATIVE_DIR}/ReactCommon/react/nativemodule/core/ReactCommon"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Link all libraries together
|
|
43
|
+
target_link_libraries(
|
|
44
|
+
${PACKAGE_NAME}
|
|
45
|
+
${LOG_LIB}
|
|
46
|
+
android # <-- Android core
|
|
47
|
+
react-native-worklets::worklets # <-- Worklets C++ library
|
|
48
|
+
)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.13.2"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def reactNativeArchitectures() {
|
|
13
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
14
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
|
+
apply from: '../nitrogen/generated/android/ReactNativeList+autolinking.gradle'
|
|
24
|
+
apply from: "./fix-prefab.gradle"
|
|
25
|
+
|
|
26
|
+
if (isNewArchitectureEnabled()) {
|
|
27
|
+
apply plugin: "com.facebook.react"
|
|
28
|
+
|
|
29
|
+
react {
|
|
30
|
+
libraryName = "ReactNativeList"
|
|
31
|
+
codegenJavaPackageName = "com.hannojg.reactnativelist"
|
|
32
|
+
jsRootDir = file("../src")
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def getExtOrDefault(name) {
|
|
37
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ReactNativeList_" + name]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def getExtOrIntegerDefault(name) {
|
|
41
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeList_" + name]).toInteger()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
android {
|
|
45
|
+
namespace "com.hannojg.reactnativelist"
|
|
46
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
47
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
48
|
+
|
|
49
|
+
defaultConfig {
|
|
50
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
51
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
52
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
53
|
+
|
|
54
|
+
externalNativeBuild {
|
|
55
|
+
cmake {
|
|
56
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
57
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
58
|
+
abiFilters (*reactNativeArchitectures())
|
|
59
|
+
|
|
60
|
+
buildTypes {
|
|
61
|
+
debug {
|
|
62
|
+
cppFlags "-O1 -g"
|
|
63
|
+
}
|
|
64
|
+
release {
|
|
65
|
+
cppFlags "-O2"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
externalNativeBuild {
|
|
73
|
+
cmake {
|
|
74
|
+
path "CMakeLists.txt"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
packagingOptions {
|
|
79
|
+
excludes = [
|
|
80
|
+
"META-INF",
|
|
81
|
+
"META-INF/**",
|
|
82
|
+
"**/libc++_shared.so",
|
|
83
|
+
"**/libNitroModules.so",
|
|
84
|
+
"**/libfbjni.so",
|
|
85
|
+
"**/libjsi.so",
|
|
86
|
+
"**/libfolly_json.so",
|
|
87
|
+
"**/libfolly_runtime.so",
|
|
88
|
+
"**/libglog.so",
|
|
89
|
+
"**/libhermes.so",
|
|
90
|
+
"**/libhermes-executor-debug.so",
|
|
91
|
+
"**/libhermes_executor.so",
|
|
92
|
+
"**/libreactnative.so",
|
|
93
|
+
"**/libreactnativejni.so",
|
|
94
|
+
"**/libturbomodulejsijni.so",
|
|
95
|
+
"**/libreact_nativemodule_core.so",
|
|
96
|
+
"**/libjscexecutor.so"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
buildFeatures {
|
|
101
|
+
buildConfig true
|
|
102
|
+
prefab true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
buildTypes {
|
|
106
|
+
release {
|
|
107
|
+
minifyEnabled false
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
lintOptions {
|
|
112
|
+
disable "GradleCompatible"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
sourceSets {
|
|
116
|
+
main {
|
|
117
|
+
if (isNewArchitectureEnabled()) {
|
|
118
|
+
java.srcDirs += [
|
|
119
|
+
// React Codegen files
|
|
120
|
+
"${project.buildDir}/generated/source/codegen/java"
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
compileOptions {
|
|
127
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
128
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
repositories {
|
|
134
|
+
mavenCentral()
|
|
135
|
+
google()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
dependencies {
|
|
140
|
+
// For < 0.71, this will be from the local maven repo
|
|
141
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
142
|
+
//noinspection GradleDynamicVersion
|
|
143
|
+
implementation "com.facebook.react:react-native:+"
|
|
144
|
+
|
|
145
|
+
// Add a dependency on NitroModules
|
|
146
|
+
implementation project(":react-native-nitro-modules")
|
|
147
|
+
implementation project(":react-native-worklets")
|
|
148
|
+
|
|
149
|
+
// RecyclerView
|
|
150
|
+
implementation "androidx.recyclerview:recyclerview:1.4.0"
|
|
151
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
tasks.configureEach { task ->
|
|
2
|
+
// Make sure that we generate our prefab publication file only after having built the native library
|
|
3
|
+
// so that not a header publication file, but a full configuration publication will be generated, which
|
|
4
|
+
// will include the .so file
|
|
5
|
+
|
|
6
|
+
def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
|
|
7
|
+
def matcher = task.name =~ prefabConfigurePattern
|
|
8
|
+
if (matcher.matches()) {
|
|
9
|
+
def variantName = matcher[0][1]
|
|
10
|
+
task.outputs.upToDateWhen { false }
|
|
11
|
+
task.dependsOn("externalNativeBuild${variantName}")
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
afterEvaluate {
|
|
16
|
+
def abis = reactNativeArchitectures()
|
|
17
|
+
rootProject.allprojects.each { proj ->
|
|
18
|
+
if (proj === rootProject) return
|
|
19
|
+
|
|
20
|
+
def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
|
|
21
|
+
config.dependencies.any { dep ->
|
|
22
|
+
dep.group == project.group && dep.name == project.name
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!dependsOnThisLib && proj != project) return
|
|
26
|
+
|
|
27
|
+
if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants
|
|
32
|
+
// Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to
|
|
33
|
+
// generate a libnameConfig.cmake file that will contain our native library (.so).
|
|
34
|
+
// See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue
|
|
35
|
+
variants.all { variant ->
|
|
36
|
+
def variantName = variant.name
|
|
37
|
+
abis.each { abi ->
|
|
38
|
+
def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
|
|
39
|
+
if (!searchDir.exists()) return
|
|
40
|
+
def matches = []
|
|
41
|
+
searchDir.eachDir { randomDir ->
|
|
42
|
+
def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
|
|
43
|
+
if (prefabFile.exists()) matches << prefabFile
|
|
44
|
+
}
|
|
45
|
+
matches.each { prefabConfig ->
|
|
46
|
+
prefabConfig.setLastModified(System.currentTimeMillis())
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|