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.
Files changed (224) hide show
  1. package/README.md +186 -32
  2. package/ReactNativeList.podspec +39 -0
  3. package/android/CMakeLists.txt +48 -0
  4. package/android/build.gradle +151 -0
  5. package/android/fix-prefab.gradle +51 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/cpp/JHybridUiListModule.cpp +192 -0
  9. package/android/src/main/cpp/JHybridUiListModule.h +50 -0
  10. package/android/src/main/cpp/cpp-adapter.cpp +12 -0
  11. package/android/src/main/java/com/hannojg/reactnativelist/ReactNativeListPackage.kt +27 -0
  12. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListDataSource.kt +146 -0
  13. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListLayout.kt +86 -0
  14. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListModule.kt +116 -0
  15. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListView.kt +410 -0
  16. package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridViewHolder.kt +9 -0
  17. package/android/src/main/java/com/margelo/nitro/reactnativelist/NativeListAdapter.kt +217 -0
  18. package/ios/DataSource/HybridNativeListDataSource.swift +213 -0
  19. package/ios/HybridObjects/HybridUiListModule.swift +49 -0
  20. package/ios/HybridObjects/HybridViewHolder.swift +16 -0
  21. package/ios/Layout/HybridNativeListLayout.swift +128 -0
  22. package/ios/Utils/ErrorUtils.h +26 -0
  23. package/ios/Utils/HybridIOSWorkletsModuleProxyHolder.swift +10 -0
  24. package/ios/Utils/SurfaceHelper.h +20 -0
  25. package/ios/Utils/SurfaceHelper.mm +144 -0
  26. package/ios/Utils/SurfacePresenterRegistry.h +17 -0
  27. package/ios/Utils/SurfacePresenterRegistry.m +31 -0
  28. package/ios/Utils/TurboModuleInstaller.h +18 -0
  29. package/ios/Utils/TurboModuleInstaller.mm +267 -0
  30. package/ios/Views/HostCell.swift +216 -0
  31. package/ios/Views/HybridUiListView.swift +695 -0
  32. package/lib/ReactFabricMirror.d.ts +4 -0
  33. package/lib/ReactFabricMirror.js +515 -0
  34. package/lib/UiListModule.d.ts +2 -0
  35. package/lib/UiListModule.js +2 -0
  36. package/lib/index.d.ts +8 -0
  37. package/lib/index.js +21 -0
  38. package/lib/privateGlobals.d.ts +14 -0
  39. package/lib/privateGlobals.js +2 -0
  40. package/lib/renderer/RenderHelper.d.ts +2 -0
  41. package/lib/renderer/RenderHelper.js +11 -0
  42. package/lib/renderer/UiManagerHelper.d.ts +2 -0
  43. package/lib/renderer/UiManagerHelper.js +2 -0
  44. package/lib/renderer/fabric/RenderHelper.d.ts +2 -0
  45. package/lib/renderer/fabric/RenderHelper.js +11 -0
  46. package/lib/renderer/fabric/UiManagerHelper.d.ts +2 -0
  47. package/lib/renderer/fabric/UiManagerHelper.js +2 -0
  48. package/lib/renderer/react/ReactFabricMirror.d.ts +4 -0
  49. package/lib/renderer/react/ReactFabricMirror.js +515 -0
  50. package/lib/renderer/react/ReactFabricRenderer.d.ts +3 -0
  51. package/lib/renderer/react/ReactFabricRenderer.js +9 -0
  52. package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.d.ts +6 -0
  53. package/lib/specs/IOSWorkletsModuleProxyHolder.nitro.js +1 -0
  54. package/lib/specs/UIListModule.nitro.d.ts +9 -0
  55. package/lib/specs/UIListModule.nitro.js +1 -0
  56. package/lib/specs/UIManagerHelper.nitro.d.ts +13 -0
  57. package/lib/specs/UIManagerHelper.nitro.js +1 -0
  58. package/lib/specs/UiListView.nitro.d.ts +20 -0
  59. package/lib/specs/UiListView.nitro.js +1 -0
  60. package/lib/specs/ViewHolder.nitro.d.ts +6 -0
  61. package/lib/specs/ViewHolder.nitro.js +1 -0
  62. package/lib/views/List.d.ts +35 -0
  63. package/lib/views/List.js +225 -0
  64. package/lib/views/UiListHostComponent.d.ts +2 -0
  65. package/lib/views/UiListHostComponent.js +3 -0
  66. package/metro/RendererProxyThreadSwitch.js +66 -0
  67. package/metro-config.d.ts +1 -0
  68. package/metro-config.js +124 -0
  69. package/nitro.json +47 -0
  70. package/nitrogen/generated/.gitattributes +1 -0
  71. package/nitrogen/generated/android/ReactNativeList+autolinking.cmake +99 -0
  72. package/nitrogen/generated/android/ReactNativeList+autolinking.gradle +27 -0
  73. package/nitrogen/generated/android/ReactNativeListOnLoad.cpp +156 -0
  74. package/nitrogen/generated/android/ReactNativeListOnLoad.hpp +34 -0
  75. package/nitrogen/generated/android/c++/JFunc_bool_NativeListItem_NativeListItem.hpp +83 -0
  76. package/nitrogen/generated/android/c++/JFunc_bool_double_NativeListItem_double.hpp +83 -0
  77. package/nitrogen/generated/android/c++/JFunc_double_std__string.hpp +78 -0
  78. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp +49 -0
  79. package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.hpp +63 -0
  80. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp +63 -0
  81. package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.hpp +65 -0
  82. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp +101 -0
  83. package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.hpp +70 -0
  84. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp +49 -0
  85. package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.hpp +63 -0
  86. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp +65 -0
  87. package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.hpp +64 -0
  88. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp +92 -0
  89. package/nitrogen/generated/android/c++/JHybridUiListViewSpec.hpp +67 -0
  90. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp +49 -0
  91. package/nitrogen/generated/android/c++/JHybridViewHolderSpec.hpp +63 -0
  92. package/nitrogen/generated/android/c++/JNativeItemSizeEstimate.hpp +61 -0
  93. package/nitrogen/generated/android/c++/JNativeLinearListLayoutConfig.hpp +81 -0
  94. package/nitrogen/generated/android/c++/JNativeLinearListLayoutIOSConfig.hpp +59 -0
  95. package/nitrogen/generated/android/c++/JNativeListItem.hpp +76 -0
  96. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp +26 -0
  97. package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.hpp +72 -0
  98. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp +53 -0
  99. package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.hpp +49 -0
  100. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp +53 -0
  101. package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.hpp +49 -0
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_NativeListItem_NativeListItem.kt +80 -0
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_double_NativeListItem_double.kt +80 -0
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_double_std__string.kt +80 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridIOSWorkletsModuleProxyHolderSpec.kt +52 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeLinearListLayoutSpec.kt +54 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListDataSourceSpec.kt +87 -0
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListLayoutSpec.kt +52 -0
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListModuleSpec.kt +59 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListViewSpec.kt +76 -0
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridViewHolderSpec.kt +53 -0
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeItemSizeEstimate.kt +56 -0
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutConfig.kt +76 -0
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutIOSConfig.kt +51 -0
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeListItem.kt +71 -0
  116. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/ReactNativeListOnLoad.kt +35 -0
  117. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.kt +62 -0
  118. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewManager.kt +80 -0
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewStateUpdater.kt +23 -0
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderManager.kt +80 -0
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderStateUpdater.kt +23 -0
  122. package/nitrogen/generated/ios/ReactNativeList+autolinking.rb +62 -0
  123. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.cpp +162 -0
  124. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.hpp +368 -0
  125. package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Umbrella.hpp +92 -0
  126. package/nitrogen/generated/ios/ReactNativeListAutolinking.mm +83 -0
  127. package/nitrogen/generated/ios/ReactNativeListAutolinking.swift +86 -0
  128. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.cpp +11 -0
  129. package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.hpp +75 -0
  130. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.cpp +11 -0
  131. package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.hpp +92 -0
  132. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.cpp +11 -0
  133. package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.hpp +132 -0
  134. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.cpp +11 -0
  135. package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.hpp +75 -0
  136. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.cpp +11 -0
  137. package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.hpp +93 -0
  138. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.cpp +11 -0
  139. package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.hpp +121 -0
  140. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.cpp +11 -0
  141. package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.hpp +75 -0
  142. package/nitrogen/generated/ios/c++/views/HybridUiListViewComponent.mm +118 -0
  143. package/nitrogen/generated/ios/c++/views/HybridViewHolderComponent.mm +118 -0
  144. package/nitrogen/generated/ios/swift/Func_bool_NativeListItem_NativeListItem.swift +47 -0
  145. package/nitrogen/generated/ios/swift/Func_bool_double_NativeListItem_double.swift +47 -0
  146. package/nitrogen/generated/ios/swift/Func_double_std__string.swift +47 -0
  147. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec.swift +55 -0
  148. package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec_cxx.swift +128 -0
  149. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec.swift +55 -0
  150. package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec_cxx.swift +140 -0
  151. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec.swift +62 -0
  152. package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec_cxx.swift +222 -0
  153. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec.swift +55 -0
  154. package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec_cxx.swift +128 -0
  155. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec.swift +56 -0
  156. package/nitrogen/generated/ios/swift/HybridUiListModuleSpec_cxx.swift +175 -0
  157. package/nitrogen/generated/ios/swift/HybridUiListViewSpec.swift +59 -0
  158. package/nitrogen/generated/ios/swift/HybridUiListViewSpec_cxx.swift +227 -0
  159. package/nitrogen/generated/ios/swift/HybridViewHolderSpec.swift +55 -0
  160. package/nitrogen/generated/ios/swift/HybridViewHolderSpec_cxx.swift +147 -0
  161. package/nitrogen/generated/ios/swift/NativeItemSizeEstimate.swift +60 -0
  162. package/nitrogen/generated/ios/swift/NativeLinearListLayoutConfig.swift +60 -0
  163. package/nitrogen/generated/ios/swift/NativeLinearListLayoutIOSConfig.swift +35 -0
  164. package/nitrogen/generated/ios/swift/NativeListItem.swift +75 -0
  165. package/nitrogen/generated/ios/swift/Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_.swift +30 -0
  166. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp +21 -0
  167. package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.hpp +62 -0
  168. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp +22 -0
  169. package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.hpp +67 -0
  170. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp +28 -0
  171. package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.hpp +72 -0
  172. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp +21 -0
  173. package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.hpp +62 -0
  174. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp +22 -0
  175. package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.hpp +68 -0
  176. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp +25 -0
  177. package/nitrogen/generated/shared/c++/HybridUiListViewSpec.hpp +79 -0
  178. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp +23 -0
  179. package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.hpp +65 -0
  180. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp +21 -0
  181. package/nitrogen/generated/shared/c++/HybridViewHolderSpec.hpp +62 -0
  182. package/nitrogen/generated/shared/c++/NativeItemSizeEstimate.hpp +87 -0
  183. package/nitrogen/generated/shared/c++/NativeLinearListLayoutConfig.hpp +105 -0
  184. package/nitrogen/generated/shared/c++/NativeLinearListLayoutIOSConfig.hpp +85 -0
  185. package/nitrogen/generated/shared/c++/NativeListItem.hpp +101 -0
  186. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp +72 -0
  187. package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.hpp +109 -0
  188. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp +72 -0
  189. package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.hpp +109 -0
  190. package/nitrogen/generated/shared/json/UiListViewConfig.json +9 -0
  191. package/nitrogen/generated/shared/json/ViewHolderConfig.json +9 -0
  192. package/package.json +152 -5
  193. package/react-native.config.js +16 -0
  194. package/src/ListDataSource.ts +232 -0
  195. package/src/ListLayout.ts +95 -0
  196. package/src/UiListModule.ts +5 -0
  197. package/src/hooks/useChangeEffect.ts +50 -0
  198. package/src/index.tsx +49 -0
  199. package/src/privateGlobals.ts +20 -0
  200. package/src/renderer/fabric/RenderHelper.ts +29 -0
  201. package/src/renderer/fabric/UiManagerHelper.ts +5 -0
  202. package/src/renderer/react/ReactFabricMirror.bundle.js +1984 -0
  203. package/src/renderer/react/ReactFabricMirror.ts +766 -0
  204. package/src/renderer/react/ReactFabricRenderer.ts +11 -0
  205. package/src/specs/IOSWorkletsModuleProxyHolder.nitro.ts +6 -0
  206. package/src/specs/NativeLinearListLayout.nitro.ts +23 -0
  207. package/src/specs/NativeListDataSource.nitro.ts +28 -0
  208. package/src/specs/NativeListLayout.nitro.ts +6 -0
  209. package/src/specs/UIListModule.nitro.ts +13 -0
  210. package/src/specs/UIManagerHelper.nitro.ts +34 -0
  211. package/src/specs/UiListView.nitro.ts +31 -0
  212. package/src/specs/ViewHolder.nitro.ts +11 -0
  213. package/src/views/List.tsx +525 -0
  214. package/src/views/UiListHostComponent.ts +8 -0
  215. package/FillRateHelper.js +0 -179
  216. package/FlatList.js +0 -494
  217. package/LICENSE.md +0 -31
  218. package/MetroListView.js +0 -166
  219. package/SectionList.js +0 -291
  220. package/ViewabilityHelper.js +0 -260
  221. package/VirtualizeUtils.js +0 -163
  222. package/VirtualizedList.js +0 -861
  223. package/VirtualizedSectionList.js +0 -397
  224. package/index.js +0 -5
@@ -0,0 +1,225 @@
1
+ import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
2
+ import { UiListHostComponent } from './UiListHostComponent';
3
+ import { callback } from 'react-native-nitro-modules';
4
+ import { scheduleOnUI } from 'react-native-worklets';
5
+ import { renderSyncWorklet, uiListModuleBoxed, } from '../renderer/fabric/RenderHelper';
6
+ import { View } from 'react-native';
7
+ import { getReactFabricRenderer } from '../renderer/react/ReactFabricRenderer';
8
+ function assertValidSize(size, index) {
9
+ const width = size.width;
10
+ const height = size.height;
11
+ if (width != null && (!Number.isFinite(width) || width <= 0)) {
12
+ throw new Error(`List item at index ${index} has an invalid width.`);
13
+ }
14
+ if (height != null && (!Number.isFinite(height) || height <= 0)) {
15
+ throw new Error(`List item at index ${index} has an invalid height.`);
16
+ }
17
+ }
18
+ function stringifyKey(key, index) {
19
+ if (typeof key === 'string') {
20
+ return key;
21
+ }
22
+ if (typeof key === 'number') {
23
+ return String(key);
24
+ }
25
+ throw new Error(`List item at index ${index} returned an invalid key.`);
26
+ }
27
+ function createNativeItem(item, index, props) {
28
+ const rawKey = props.keyExtractor(item, index);
29
+ const key = stringifyKey(rawKey, index);
30
+ const type = props.getItemType(item, index);
31
+ const renderer = props.renderers[type];
32
+ if (renderer == null) {
33
+ throw new Error(`List item at index ${index} uses unknown type "${type}".`);
34
+ }
35
+ const size = props.getItemSize?.(item, index) ?? {};
36
+ assertValidSize(size, index);
37
+ return {
38
+ key: key,
39
+ type: type,
40
+ width: size.width,
41
+ height: size.height,
42
+ data: item,
43
+ };
44
+ }
45
+ function createNativeItems(data, props) {
46
+ const seenIdentities = new Set();
47
+ const items = [];
48
+ for (let index = 0; index < data.length; index++) {
49
+ const item = data[index];
50
+ if (item == null) {
51
+ throw new Error(`List item at index ${index} is undefined.`);
52
+ }
53
+ const nativeItem = createNativeItem(item, index, props);
54
+ const identity = nativeItem.type + ':' + nativeItem.key;
55
+ if (seenIdentities.has(identity)) {
56
+ throw new Error(`List contains duplicate item identity "${identity}".`);
57
+ }
58
+ seenIdentities.add(identity);
59
+ items.push(nativeItem);
60
+ }
61
+ return items;
62
+ }
63
+ function ListInner(props, forwardedRef) {
64
+ const { data, getItemSize, getItemType, keyExtractor, renderers, style } = props;
65
+ const isSetup = useRef(false);
66
+ const nativeListRef = useRef(null);
67
+ const [isNativeReady, setIsNativeReady] = useState(false);
68
+ const nativeItems = useMemo(() => {
69
+ const normalizationProps = {
70
+ data,
71
+ keyExtractor,
72
+ getItemType,
73
+ getItemSize,
74
+ renderers,
75
+ };
76
+ return createNativeItems(data, normalizationProps);
77
+ }, [data, getItemSize, getItemType, keyExtractor, renderers]);
78
+ useImperativeHandle(forwardedRef, () => {
79
+ return {
80
+ replaceData(nextData, animated = true) {
81
+ const ref = nativeListRef.current;
82
+ if (ref == null)
83
+ return;
84
+ const nextItems = createNativeItems(nextData, props);
85
+ ref.setData(nextItems, animated);
86
+ },
87
+ insertItem(index, item) {
88
+ const ref = nativeListRef.current;
89
+ if (ref == null)
90
+ return;
91
+ const nativeItem = createNativeItem(item, index, props);
92
+ ref.insertItem(index, nativeItem);
93
+ },
94
+ updateItem(index, item) {
95
+ const ref = nativeListRef.current;
96
+ if (ref == null)
97
+ return;
98
+ const nativeItem = createNativeItem(item, index, props);
99
+ ref.updateItem(index, nativeItem);
100
+ },
101
+ removeItem(index) {
102
+ const ref = nativeListRef.current;
103
+ if (ref == null)
104
+ return;
105
+ ref.removeItem(index);
106
+ },
107
+ moveItem(fromIndex, toIndex) {
108
+ const ref = nativeListRef.current;
109
+ if (ref == null)
110
+ return;
111
+ ref.moveItem(fromIndex, toIndex);
112
+ },
113
+ };
114
+ }, [props]);
115
+ useEffect(() => {
116
+ const ref = nativeListRef.current;
117
+ if (ref == null || !isNativeReady)
118
+ return;
119
+ ref.setData(nativeItems, true);
120
+ }, [isNativeReady, nativeItems]);
121
+ return (React.createElement(UiListHostComponent, { style: style, hybridRef: callback((ref) => {
122
+ nativeListRef.current = ref;
123
+ if (isSetup.current)
124
+ return;
125
+ isSetup.current = true;
126
+ scheduleOnUI(() => {
127
+ 'worklet';
128
+ const { nativeLog, reactRender } = getReactFabricRenderer();
129
+ const tagToArrayPosition = {};
130
+ const tagToItemId = {};
131
+ let nextItemId = 0;
132
+ const elementsRendered = [];
133
+ const uiListModuleUnboxed = uiListModuleBoxed.unbox();
134
+ ref.setListCallbacks(uiListModuleUnboxed, (type) => {
135
+ const nativeRef = globalThis.React.createRef();
136
+ const itemId = nextItemId++;
137
+ const typedType = type;
138
+ const renderer = renderers[typedType];
139
+ if (renderer == null) {
140
+ throw new Error('No renderer for list item type ' + type);
141
+ }
142
+ const newElement = renderer.renderItemWorklet({
143
+ type: typedType,
144
+ });
145
+ const newProps = {
146
+ key: 'itemid-' + itemId,
147
+ ref: nativeRef,
148
+ collapsable: false,
149
+ };
150
+ const newElementWithKey = globalThis.React.cloneElement(newElement, newProps);
151
+ const newLength = elementsRendered.push(newElementWithKey);
152
+ const currentIndex = newLength - 1;
153
+ const parentContainer = React.createElement(View, null, elementsRendered);
154
+ reactRender(parentContainer, () => {
155
+ nativeLog('Render complete');
156
+ });
157
+ if (nativeRef.current == null) {
158
+ throw new Error('Ref is null after render');
159
+ }
160
+ const tag = nativeRef.current.__nativeTag;
161
+ tagToArrayPosition[tag] = currentIndex;
162
+ tagToItemId[tag] = itemId;
163
+ const start = globalThis.performance.now();
164
+ renderSyncWorklet();
165
+ const end = globalThis.performance.now();
166
+ nativeLog('renderSync took ', end - start, 'ms');
167
+ return tag;
168
+ }, (reactTag, item, index) => {
169
+ const typedType = item.type;
170
+ const renderer = renderers[typedType];
171
+ if (renderer == null) {
172
+ throw new Error('No renderer for list item type ' + item.type);
173
+ }
174
+ const itemId = tagToItemId[reactTag];
175
+ if (itemId == null) {
176
+ throw new Error('No itemId for tag ' + reactTag);
177
+ }
178
+ const newElement = renderer.renderItemWorklet({
179
+ item: item.data,
180
+ index,
181
+ key: item.key,
182
+ type: typedType,
183
+ });
184
+ const newProps = {
185
+ key: 'itemid-' + itemId,
186
+ collapsable: false,
187
+ };
188
+ const newElementWithKey = globalThis.React.cloneElement(newElement, newProps);
189
+ const position = tagToArrayPosition[reactTag];
190
+ if (position == null) {
191
+ throw new Error('No position for tag ' + reactTag);
192
+ }
193
+ elementsRendered[position] = newElementWithKey;
194
+ const parentContainer = React.createElement(View, null, elementsRendered);
195
+ reactRender(parentContainer, () => {
196
+ nativeLog('Update Render complete');
197
+ });
198
+ const start = globalThis.performance.now();
199
+ renderSyncWorklet();
200
+ const end = globalThis.performance.now();
201
+ nativeLog('Update renderSync took ', end - start, 'ms');
202
+ return true;
203
+ }, (oldItem, newItem) => {
204
+ if (oldItem.type !== newItem.type) {
205
+ return false;
206
+ }
207
+ if (oldItem.width !== newItem.width) {
208
+ return false;
209
+ }
210
+ if (oldItem.height !== newItem.height) {
211
+ return false;
212
+ }
213
+ const typedType = newItem.type;
214
+ const renderer = renderers[typedType];
215
+ if (renderer == null) {
216
+ throw new Error('No renderer for list item type ' + newItem.type);
217
+ }
218
+ return renderer.isContentEqualWorklet(oldItem.data, newItem.data);
219
+ });
220
+ ref.setData(nativeItems, false);
221
+ });
222
+ setIsNativeReady(true);
223
+ }) }));
224
+ }
225
+ export const List = forwardRef(ListInner);
@@ -0,0 +1,2 @@
1
+ import { UiListViewMethods, UiListViewProps } from '../specs/UiListView.nitro';
2
+ export declare const UiListHostComponent: import("react-native-nitro-modules").ReactNativeView<UiListViewProps, UiListViewMethods>;
@@ -0,0 +1,3 @@
1
+ import { getHostComponent } from 'react-native-nitro-modules';
2
+ import UiListViewConfig from '../../nitrogen/generated/shared/json/UiListViewConfig.json';
3
+ export const UiListHostComponent = getHostComponent('UiListView', () => UiListViewConfig);
@@ -0,0 +1,66 @@
1
+ 'use strict'
2
+
3
+ function isReactNativeRuntime() {
4
+ return global.__RUNTIME_KIND === 1
5
+ }
6
+
7
+ let cachedReactNativeRendererProxy
8
+ function getReactNativeRendererProxy() {
9
+ if (cachedReactNativeRendererProxy == null) {
10
+ // Intentionally lazy: avoid loading the default RN renderer in non-RN runtimes.
11
+ // eslint-disable-next-line @react-native/no-deep-imports
12
+ cachedReactNativeRendererProxy = require('react-native/Libraries/ReactNative/RendererProxy')
13
+ }
14
+ return cachedReactNativeRendererProxy
15
+ }
16
+
17
+ function getNodeFromInternalInstanceHandle(internalInstanceHandle) {
18
+ if (isReactNativeRuntime()) {
19
+ return getReactNativeRendererProxy().getNodeFromInternalInstanceHandle(
20
+ internalInstanceHandle
21
+ )
22
+ }
23
+
24
+ const stateNode = internalInstanceHandle?.stateNode
25
+ if (stateNode == null) {
26
+ return null
27
+ }
28
+ return stateNode.node ?? stateNode
29
+ }
30
+
31
+ function getPublicInstanceFromInternalInstanceHandle(internalInstanceHandle) {
32
+ if (isReactNativeRuntime()) {
33
+ return getReactNativeRendererProxy().getPublicInstanceFromInternalInstanceHandle(
34
+ internalInstanceHandle
35
+ )
36
+ }
37
+
38
+ const stateNode = internalInstanceHandle?.stateNode
39
+ if (stateNode == null) {
40
+ return null
41
+ }
42
+
43
+ if (stateNode.canonical?.publicInstance != null) {
44
+ return stateNode.canonical.publicInstance
45
+ }
46
+
47
+ return stateNode.node ?? stateNode
48
+ }
49
+
50
+ function getPublicInstanceFromRootTag(rootTag) {
51
+ if (isReactNativeRuntime()) {
52
+ return getReactNativeRendererProxy().getPublicInstanceFromRootTag(rootTag)
53
+ }
54
+
55
+ if (global.rootInstance?.containerTag === Number(rootTag)) {
56
+ return global.rootInstance.publicInstance ?? null
57
+ }
58
+
59
+ return null
60
+ }
61
+
62
+ module.exports = {
63
+ getNodeFromInternalInstanceHandle,
64
+ getPublicInstanceFromInternalInstanceHandle,
65
+ getPublicInstanceFromRootTag,
66
+ }
@@ -0,0 +1 @@
1
+ export function getReactNativeListMetroConfig<TConfig>(config: TConfig): TConfig
@@ -0,0 +1,124 @@
1
+ 'use strict'
2
+
3
+ const path = require('path')
4
+
5
+ const rendererProxyThreadSwitchPath = path.resolve(
6
+ __dirname,
7
+ 'metro/RendererProxyThreadSwitch.js'
8
+ )
9
+
10
+ function isRendererProxyImport(moduleName) {
11
+ return /(?:^|\/)RendererProxy(?:\.js)?$/.test(moduleName)
12
+ }
13
+
14
+ //#region Turbo module handling
15
+ // react-native-worklets installs a shim preventing the usage of TurboModules on other runtimes:
16
+ // - https://github.com/software-mansion/react-native-reanimated/blob/9c2e3b05216b22d3c1ed4be67719876d1fa9115d/packages/react-native-worklets/bundleMode/shims/turboModuleRegistryShim.js#L36
17
+ // As we properly handle turbo modules we want to allow for it.
18
+ // So we basically redirect all imports of the shim back to the original TurboModuleRegistry.js file:
19
+ const turboModuleRegistryModuleName =
20
+ 'react-native/Libraries/TurboModule/TurboModuleRegistry'
21
+ const turboModuleRegistryPath = require.resolve(turboModuleRegistryModuleName)
22
+ const turboModuleRegistryFileSuffix = path.join(
23
+ 'react-native',
24
+ 'Libraries',
25
+ 'TurboModule',
26
+ 'TurboModuleRegistry.js'
27
+ )
28
+ const workletsTurboModuleRegistryShimSuffix = path.join(
29
+ 'react-native-worklets',
30
+ 'bundleMode',
31
+ 'shims',
32
+ 'turboModuleRegistryShim.js'
33
+ )
34
+
35
+ function isTurboModuleRegistryImport(moduleName) {
36
+ return moduleName === turboModuleRegistryModuleName
37
+ }
38
+
39
+ function isSourceFileResolution(result) {
40
+ if (result == null) {
41
+ return false
42
+ }
43
+
44
+ if (result.type !== 'sourceFile') {
45
+ return false
46
+ }
47
+
48
+ return typeof result.filePath === 'string'
49
+ }
50
+
51
+ function isTurboModuleRegistryResolution(result) {
52
+ if (!isSourceFileResolution(result)) {
53
+ return false
54
+ }
55
+
56
+ return result.filePath.endsWith(turboModuleRegistryFileSuffix)
57
+ }
58
+
59
+ function isWorkletsTurboModuleRegistryShimResolution(result) {
60
+ if (!isSourceFileResolution(result)) {
61
+ return false
62
+ }
63
+
64
+ return result.filePath.endsWith(workletsTurboModuleRegistryShimSuffix)
65
+ }
66
+
67
+ function createTurboModuleRegistryResolution() {
68
+ return {
69
+ type: 'sourceFile',
70
+ filePath: turboModuleRegistryPath,
71
+ }
72
+ }
73
+ //#endregion
74
+
75
+ function isReactNativeDomInternalsImporter(originModulePath) {
76
+ if (typeof originModulePath !== 'string') {
77
+ return false
78
+ }
79
+
80
+ return originModulePath.includes(
81
+ `${path.sep}node_modules${path.sep}react-native${path.sep}src${path.sep}private${path.sep}webapis${path.sep}dom${path.sep}nodes${path.sep}internals${path.sep}`
82
+ )
83
+ }
84
+
85
+ function getReactNativeListMetroConfig(config) {
86
+ config.resolver = config.resolver || {}
87
+ const currentResolveRequest = config.resolver.resolveRequest
88
+
89
+ config.resolver.resolveRequest = (context, moduleName, platform) => {
90
+ if (isTurboModuleRegistryImport(moduleName)) {
91
+ return createTurboModuleRegistryResolution()
92
+ }
93
+
94
+ // Redirect only React Native DOM internals to a runtime-switching proxy.
95
+ if (
96
+ isRendererProxyImport(moduleName) &&
97
+ isReactNativeDomInternalsImporter(context.originModulePath)
98
+ ) {
99
+ return {
100
+ type: 'sourceFile',
101
+ filePath: rendererProxyThreadSwitchPath,
102
+ }
103
+ }
104
+
105
+ const resolveRequest = currentResolveRequest || context.resolveRequest
106
+ const resolved = resolveRequest(context, moduleName, platform)
107
+
108
+ if (isTurboModuleRegistryResolution(resolved)) {
109
+ return createTurboModuleRegistryResolution()
110
+ }
111
+
112
+ if (isWorkletsTurboModuleRegistryShimResolution(resolved)) {
113
+ return createTurboModuleRegistryResolution()
114
+ }
115
+
116
+ return resolved
117
+ }
118
+
119
+ return config
120
+ }
121
+
122
+ module.exports = {
123
+ getReactNativeListMetroConfig,
124
+ }
package/nitro.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://nitro.margelo.com/nitro.schema.json",
3
+ "cxxNamespace": [
4
+ "reactnativelist"
5
+ ],
6
+ "ios": {
7
+ "iosModuleName": "ReactNativeList"
8
+ },
9
+ "android": {
10
+ "androidNamespace": [
11
+ "reactnativelist"
12
+ ],
13
+ "androidCxxLibName": "ReactNativeList"
14
+ },
15
+ "autolinking": {
16
+ "ViewHolder": {
17
+ "kotlin": "HybridViewHolder",
18
+ "swift": "HybridViewHolder"
19
+ },
20
+ "UiListView": {
21
+ "kotlin": "HybridUiListView",
22
+ "swift": "HybridUiListView"
23
+ },
24
+ "NativeListDataSource": {
25
+ "kotlin": "HybridNativeListDataSource",
26
+ "swift": "HybridNativeListDataSource"
27
+ },
28
+ "NativeListLayout": {
29
+ "kotlin": "HybridNativeListLayout",
30
+ "swift": "HybridNativeListLayout"
31
+ },
32
+ "NativeLinearListLayout": {
33
+ "kotlin": "HybridNativeLinearListLayout",
34
+ "swift": "HybridNativeLinearListLayout"
35
+ },
36
+ "UiListModule": {
37
+ "kotlin": "HybridUiListModule",
38
+ "swift": "HybridUiListModule"
39
+ },
40
+ "UiManagerHelper": {
41
+ "cpp": "HybridUiManagerHelper"
42
+ }
43
+ },
44
+ "ignorePaths": [
45
+ "**/node_modules"
46
+ ]
47
+ }
@@ -0,0 +1 @@
1
+ ** linguist-generated=true
@@ -0,0 +1,99 @@
1
+ #
2
+ # ReactNativeList+autolinking.cmake
3
+ # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ # https://github.com/mrousavy/nitro
5
+ # Copyright © Marc Rousavy @ Margelo
6
+ #
7
+
8
+ # This is a CMake file that adds all files generated by Nitrogen
9
+ # to the current CMake project.
10
+ #
11
+ # To use it, add this to your CMakeLists.txt:
12
+ # ```cmake
13
+ # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeList+autolinking.cmake)
14
+ # ```
15
+
16
+ # Define a flag to check if we are building properly
17
+ add_definitions(-DBUILDING_REACTNATIVELIST_WITH_GENERATED_CMAKE_PROJECT)
18
+
19
+ # Enable Raw Props parsing in react-native (for Nitro Views)
20
+ add_definitions(-DRN_SERIALIZABLE_STATE)
21
+
22
+ # Add all headers that were generated by Nitrogen
23
+ include_directories(
24
+ "../nitrogen/generated/shared/c++"
25
+ "../nitrogen/generated/android/c++"
26
+ "../nitrogen/generated/android/"
27
+ )
28
+
29
+ # Add all .cpp sources that were generated by Nitrogen
30
+ target_sources(
31
+ # CMake project name (Android C++ library name)
32
+ ReactNativeList PRIVATE
33
+ # Autolinking Setup
34
+ ../nitrogen/generated/android/ReactNativeListOnLoad.cpp
35
+ # Shared Nitrogen C++ sources
36
+ ../nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp
37
+ ../nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp
38
+ ../nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp
39
+ ../nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp
40
+ ../nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp
41
+ ../nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp
42
+ ../nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp
43
+ ../nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp
44
+ ../nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp
45
+ ../nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp
46
+ # Android-specific Nitrogen C++ sources
47
+ ../nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp
48
+ ../nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp
49
+ ../nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp
50
+ ../nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp
51
+ ../nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp
52
+ ../nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp
53
+ ../nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp
54
+ ../nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp
55
+ ../nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp
56
+ ../nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp
57
+ )
58
+
59
+ # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake
60
+ # Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake
61
+ target_compile_definitions(
62
+ ReactNativeList PRIVATE
63
+ -DFOLLY_NO_CONFIG=1
64
+ -DFOLLY_HAVE_CLOCK_GETTIME=1
65
+ -DFOLLY_USE_LIBCPP=1
66
+ -DFOLLY_CFG_NO_COROUTINES=1
67
+ -DFOLLY_MOBILE=1
68
+ -DFOLLY_HAVE_RECVMMSG=1
69
+ -DFOLLY_HAVE_PTHREAD=1
70
+ # Once we target android-23 above, we can comment
71
+ # the following line. NDK uses GNU style stderror_r() after API 23.
72
+ -DFOLLY_HAVE_XSI_STRERROR_R=1
73
+ )
74
+
75
+ # Add all libraries required by the generated specs
76
+ find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++
77
+ find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)
78
+ find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library
79
+
80
+ # Link all libraries together
81
+ target_link_libraries(
82
+ ReactNativeList
83
+ fbjni::fbjni # <-- Facebook C++ JNI helpers
84
+ ReactAndroid::jsi # <-- RN: JSI
85
+ react-native-nitro-modules::NitroModules # <-- NitroModules Core :)
86
+ )
87
+
88
+ # Link react-native (different prefab between RN 0.75 and RN 0.76)
89
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
90
+ target_link_libraries(
91
+ ReactNativeList
92
+ ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab
93
+ )
94
+ else()
95
+ target_link_libraries(
96
+ ReactNativeList
97
+ ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core
98
+ )
99
+ endif()
@@ -0,0 +1,27 @@
1
+ ///
2
+ /// ReactNativeList+autolinking.gradle
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ /// This is a Gradle file that adds all files generated by Nitrogen
9
+ /// to the current Gradle project.
10
+ ///
11
+ /// To use it, add this to your build.gradle:
12
+ /// ```gradle
13
+ /// apply from: '../nitrogen/generated/android/ReactNativeList+autolinking.gradle'
14
+ /// ```
15
+
16
+ logger.warn("[NitroModules] 🔥 ReactNativeList is boosted by nitro!")
17
+
18
+ android {
19
+ sourceSets {
20
+ main {
21
+ java.srcDirs += [
22
+ // Nitrogen files
23
+ "${project.projectDir}/../nitrogen/generated/android/kotlin"
24
+ ]
25
+ }
26
+ }
27
+ }