@react-native-ohos/flash-list 1.6.4-rc.1

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 (298) hide show
  1. package/LICENSE +7 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +9 -0
  4. package/dist/AnimatedFlashList.d.ts +6 -0
  5. package/dist/AnimatedFlashList.d.ts.map +1 -0
  6. package/dist/AnimatedFlashList.js +8 -0
  7. package/dist/AnimatedFlashList.js.map +1 -0
  8. package/dist/FlashList.d.ts +126 -0
  9. package/dist/FlashList.d.ts.map +1 -0
  10. package/dist/FlashList.js +524 -0
  11. package/dist/FlashList.js.map +1 -0
  12. package/dist/FlashListProps.d.ts +256 -0
  13. package/dist/FlashListProps.d.ts.map +1 -0
  14. package/dist/FlashListProps.js +9 -0
  15. package/dist/FlashListProps.js.map +1 -0
  16. package/dist/GridLayoutProviderWithProps.d.ts +42 -0
  17. package/dist/GridLayoutProviderWithProps.d.ts.map +1 -0
  18. package/dist/GridLayoutProviderWithProps.js +115 -0
  19. package/dist/GridLayoutProviderWithProps.js.map +1 -0
  20. package/dist/MasonryFlashList.d.ts +51 -0
  21. package/dist/MasonryFlashList.d.ts.map +1 -0
  22. package/dist/MasonryFlashList.js +252 -0
  23. package/dist/MasonryFlashList.js.map +1 -0
  24. package/dist/PureComponentWrapper.d.ts +22 -0
  25. package/dist/PureComponentWrapper.d.ts.map +1 -0
  26. package/dist/PureComponentWrapper.js +37 -0
  27. package/dist/PureComponentWrapper.js.map +1 -0
  28. package/dist/__tests__/AverageWindow.test.d.ts +2 -0
  29. package/dist/__tests__/AverageWindow.test.d.ts.map +1 -0
  30. package/dist/__tests__/AverageWindow.test.js +69 -0
  31. package/dist/__tests__/AverageWindow.test.js.map +1 -0
  32. package/dist/__tests__/ContentContainerUtils.test.d.ts +2 -0
  33. package/dist/__tests__/ContentContainerUtils.test.d.ts.map +1 -0
  34. package/dist/__tests__/ContentContainerUtils.test.js +85 -0
  35. package/dist/__tests__/ContentContainerUtils.test.js.map +1 -0
  36. package/dist/__tests__/FlashList.test.d.ts +2 -0
  37. package/dist/__tests__/FlashList.test.d.ts.map +1 -0
  38. package/dist/__tests__/FlashList.test.js +792 -0
  39. package/dist/__tests__/FlashList.test.js.map +1 -0
  40. package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts +2 -0
  41. package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts.map +1 -0
  42. package/dist/__tests__/GridLayoutProviderWithProps.test.js +143 -0
  43. package/dist/__tests__/GridLayoutProviderWithProps.test.js.map +1 -0
  44. package/dist/__tests__/MasonryFlashList.test.d.ts +2 -0
  45. package/dist/__tests__/MasonryFlashList.test.d.ts.map +1 -0
  46. package/dist/__tests__/MasonryFlashList.test.js +254 -0
  47. package/dist/__tests__/MasonryFlashList.test.js.map +1 -0
  48. package/dist/__tests__/PlatformHelper.web.test.d.ts +2 -0
  49. package/dist/__tests__/PlatformHelper.web.test.d.ts.map +1 -0
  50. package/dist/__tests__/PlatformHelper.web.test.js +33 -0
  51. package/dist/__tests__/PlatformHelper.web.test.js.map +1 -0
  52. package/dist/__tests__/ViewabilityHelper.test.d.ts +2 -0
  53. package/dist/__tests__/ViewabilityHelper.test.d.ts.map +1 -0
  54. package/dist/__tests__/ViewabilityHelper.test.js +187 -0
  55. package/dist/__tests__/ViewabilityHelper.test.js.map +1 -0
  56. package/dist/__tests__/helpers/mountFlashList.d.ts +19 -0
  57. package/dist/__tests__/helpers/mountFlashList.d.ts.map +1 -0
  58. package/dist/__tests__/helpers/mountFlashList.js +44 -0
  59. package/dist/__tests__/helpers/mountFlashList.js.map +1 -0
  60. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +18 -0
  61. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -0
  62. package/dist/__tests__/helpers/mountMasonryFlashList.js +49 -0
  63. package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -0
  64. package/dist/__tests__/useBlankAreaTracker.test.d.ts +2 -0
  65. package/dist/__tests__/useBlankAreaTracker.test.d.ts.map +1 -0
  66. package/dist/__tests__/useBlankAreaTracker.test.js +177 -0
  67. package/dist/__tests__/useBlankAreaTracker.test.js.map +1 -0
  68. package/dist/benchmark/AutoScrollHelper.d.ts +18 -0
  69. package/dist/benchmark/AutoScrollHelper.d.ts.map +1 -0
  70. package/dist/benchmark/AutoScrollHelper.js +68 -0
  71. package/dist/benchmark/AutoScrollHelper.js.map +1 -0
  72. package/dist/benchmark/JSFPSMonitor.d.ts +23 -0
  73. package/dist/benchmark/JSFPSMonitor.d.ts.map +1 -0
  74. package/dist/benchmark/JSFPSMonitor.js +65 -0
  75. package/dist/benchmark/JSFPSMonitor.js.map +1 -0
  76. package/dist/benchmark/roundToDecimalPlaces.d.ts +2 -0
  77. package/dist/benchmark/roundToDecimalPlaces.d.ts.map +1 -0
  78. package/dist/benchmark/roundToDecimalPlaces.js +9 -0
  79. package/dist/benchmark/roundToDecimalPlaces.js.map +1 -0
  80. package/dist/benchmark/useBenchmark.d.ts +35 -0
  81. package/dist/benchmark/useBenchmark.d.ts.map +1 -0
  82. package/dist/benchmark/useBenchmark.js +167 -0
  83. package/dist/benchmark/useBenchmark.js.map +1 -0
  84. package/dist/benchmark/useBlankAreaTracker.d.ts +34 -0
  85. package/dist/benchmark/useBlankAreaTracker.d.ts.map +1 -0
  86. package/dist/benchmark/useBlankAreaTracker.js +67 -0
  87. package/dist/benchmark/useBlankAreaTracker.js.map +1 -0
  88. package/dist/benchmark/useDataMultiplier.d.ts +9 -0
  89. package/dist/benchmark/useDataMultiplier.d.ts.map +1 -0
  90. package/dist/benchmark/useDataMultiplier.js +25 -0
  91. package/dist/benchmark/useDataMultiplier.js.map +1 -0
  92. package/dist/benchmark/useFlatListBenchmark.d.ts +13 -0
  93. package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -0
  94. package/dist/benchmark/useFlatListBenchmark.js +100 -0
  95. package/dist/benchmark/useFlatListBenchmark.js.map +1 -0
  96. package/dist/errors/CustomError.d.ts +8 -0
  97. package/dist/errors/CustomError.d.ts.map +1 -0
  98. package/dist/errors/CustomError.js +14 -0
  99. package/dist/errors/CustomError.js.map +1 -0
  100. package/dist/errors/ExceptionList.d.ts +24 -0
  101. package/dist/errors/ExceptionList.d.ts.map +1 -0
  102. package/dist/errors/ExceptionList.js +26 -0
  103. package/dist/errors/ExceptionList.js.map +1 -0
  104. package/dist/errors/Warnings.d.ts +9 -0
  105. package/dist/errors/Warnings.d.ts.map +1 -0
  106. package/dist/errors/Warnings.js +13 -0
  107. package/dist/errors/Warnings.js.map +1 -0
  108. package/dist/fabric/AutoLayoutNativeComponent.d.ts +19 -0
  109. package/dist/fabric/AutoLayoutNativeComponent.d.ts.map +1 -0
  110. package/dist/fabric/AutoLayoutNativeComponent.js +29 -0
  111. package/dist/fabric/AutoLayoutNativeComponent.js.map +1 -0
  112. package/dist/fabric/CellContainerNativeComponent.d.ts +8 -0
  113. package/dist/fabric/CellContainerNativeComponent.d.ts.map +1 -0
  114. package/dist/fabric/CellContainerNativeComponent.js +29 -0
  115. package/dist/fabric/CellContainerNativeComponent.js.map +1 -0
  116. package/dist/index.d.ts +14 -0
  117. package/dist/index.d.ts.map +1 -0
  118. package/dist/index.js +32 -0
  119. package/dist/index.js.map +1 -0
  120. package/dist/native/auto-layout/AutoLayoutView.d.ts +22 -0
  121. package/dist/native/auto-layout/AutoLayoutView.d.ts.map +1 -0
  122. package/dist/native/auto-layout/AutoLayoutView.js +48 -0
  123. package/dist/native/auto-layout/AutoLayoutView.js.map +1 -0
  124. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts +4 -0
  125. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts.map +1 -0
  126. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js +6 -0
  127. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js.map +1 -0
  128. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts +5 -0
  129. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts.map +1 -0
  130. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.d.ts +4 -0
  131. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.d.ts.map +1 -0
  132. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.js +29 -0
  133. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.js.map +1 -0
  134. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts +4 -0
  135. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts.map +1 -0
  136. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js +6 -0
  137. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js.map +1 -0
  138. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js +6 -0
  139. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js.map +1 -0
  140. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts +16 -0
  141. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts.map +1 -0
  142. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js +3 -0
  143. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js.map +1 -0
  144. package/dist/native/cell-container/CellContainer.android.d.ts +6 -0
  145. package/dist/native/cell-container/CellContainer.android.d.ts.map +1 -0
  146. package/dist/native/cell-container/CellContainer.android.js +9 -0
  147. package/dist/native/cell-container/CellContainer.android.js.map +1 -0
  148. package/dist/native/cell-container/CellContainer.d.ts +8 -0
  149. package/dist/native/cell-container/CellContainer.d.ts.map +1 -0
  150. package/dist/native/cell-container/CellContainer.harmony.d.ts +6 -0
  151. package/dist/native/cell-container/CellContainer.harmony.d.ts.map +1 -0
  152. package/dist/native/cell-container/CellContainer.harmony.js +32 -0
  153. package/dist/native/cell-container/CellContainer.harmony.js.map +1 -0
  154. package/dist/native/cell-container/CellContainer.ios.d.ts +6 -0
  155. package/dist/native/cell-container/CellContainer.ios.d.ts.map +1 -0
  156. package/dist/native/cell-container/CellContainer.ios.js +9 -0
  157. package/dist/native/cell-container/CellContainer.ios.js.map +1 -0
  158. package/dist/native/cell-container/CellContainer.js +11 -0
  159. package/dist/native/cell-container/CellContainer.js.map +1 -0
  160. package/dist/native/cell-container/CellContainer.web.d.ts +7 -0
  161. package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -0
  162. package/dist/native/cell-container/CellContainer.web.js +13 -0
  163. package/dist/native/cell-container/CellContainer.web.js.map +1 -0
  164. package/dist/native/config/PlatformHelper.android.d.ts +26 -0
  165. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -0
  166. package/dist/native/config/PlatformHelper.android.js +23 -0
  167. package/dist/native/config/PlatformHelper.android.js.map +1 -0
  168. package/dist/native/config/PlatformHelper.d.ts +26 -0
  169. package/dist/native/config/PlatformHelper.d.ts.map +1 -0
  170. package/dist/native/config/PlatformHelper.harmony.d.ts +26 -0
  171. package/dist/native/config/PlatformHelper.harmony.d.ts.map +1 -0
  172. package/dist/native/config/PlatformHelper.harmony.js +22 -0
  173. package/dist/native/config/PlatformHelper.harmony.js.map +1 -0
  174. package/dist/native/config/PlatformHelper.ios.d.ts +26 -0
  175. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -0
  176. package/dist/native/config/PlatformHelper.ios.js +22 -0
  177. package/dist/native/config/PlatformHelper.ios.js.map +1 -0
  178. package/dist/native/config/PlatformHelper.js +23 -0
  179. package/dist/native/config/PlatformHelper.js.map +1 -0
  180. package/dist/native/config/PlatformHelper.web.d.ts +27 -0
  181. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -0
  182. package/dist/native/config/PlatformHelper.web.js +25 -0
  183. package/dist/native/config/PlatformHelper.web.js.map +1 -0
  184. package/dist/tsconfig.tsbuildinfo +1 -0
  185. package/dist/utils/AverageWindow.d.ts +21 -0
  186. package/dist/utils/AverageWindow.d.ts.map +1 -0
  187. package/dist/utils/AverageWindow.js +49 -0
  188. package/dist/utils/AverageWindow.js.map +1 -0
  189. package/dist/utils/ContentContainerUtils.d.ts +27 -0
  190. package/dist/utils/ContentContainerUtils.d.ts.map +1 -0
  191. package/dist/utils/ContentContainerUtils.js +48 -0
  192. package/dist/utils/ContentContainerUtils.js.map +1 -0
  193. package/dist/viewability/ViewToken.d.ts +8 -0
  194. package/dist/viewability/ViewToken.d.ts.map +1 -0
  195. package/dist/viewability/ViewToken.js +3 -0
  196. package/dist/viewability/ViewToken.js.map +1 -0
  197. package/dist/viewability/ViewabilityHelper.d.ts +25 -0
  198. package/dist/viewability/ViewabilityHelper.d.ts.map +1 -0
  199. package/dist/viewability/ViewabilityHelper.js +104 -0
  200. package/dist/viewability/ViewabilityHelper.js.map +1 -0
  201. package/dist/viewability/ViewabilityManager.d.ts +24 -0
  202. package/dist/viewability/ViewabilityManager.d.ts.map +1 -0
  203. package/dist/viewability/ViewabilityManager.js +94 -0
  204. package/dist/viewability/ViewabilityManager.js.map +1 -0
  205. package/harmony/flash_list/BuildProfile.ets +5 -0
  206. package/harmony/flash_list/LICENSE +7 -0
  207. package/harmony/flash_list/build-profile.json5 +8 -0
  208. package/harmony/flash_list/hvigorfile.ts +1 -0
  209. package/harmony/flash_list/index.ets +29 -0
  210. package/harmony/flash_list/obfuscation-rules.txt +18 -0
  211. package/harmony/flash_list/oh-package-lock.json5 +17 -0
  212. package/harmony/flash_list/oh-package.json5 +13 -0
  213. package/harmony/flash_list/src/main/cpp/AutoLayoutNode.cpp +63 -0
  214. package/harmony/flash_list/src/main/cpp/AutoLayoutNode.h +57 -0
  215. package/harmony/flash_list/src/main/cpp/AutoLayoutShadow.cpp +140 -0
  216. package/harmony/flash_list/src/main/cpp/AutoLayoutShadow.h +66 -0
  217. package/harmony/flash_list/src/main/cpp/AutoLayoutViewComponentInstance.cpp +208 -0
  218. package/harmony/flash_list/src/main/cpp/AutoLayoutViewComponentInstance.h +78 -0
  219. package/harmony/flash_list/src/main/cpp/AutoLayoutViewEventEmitRequestHandler.h +53 -0
  220. package/harmony/flash_list/src/main/cpp/AutoLayoutViewJSIBinder.h +50 -0
  221. package/harmony/flash_list/src/main/cpp/CMakeLists.txt +7 -0
  222. package/harmony/flash_list/src/main/cpp/CellContainerComponentInstance.cpp +80 -0
  223. package/harmony/flash_list/src/main/cpp/CellContainerComponentInstance.h +67 -0
  224. package/harmony/flash_list/src/main/cpp/CellContainerJSIBinder.h +39 -0
  225. package/harmony/flash_list/src/main/cpp/ComponentDescriptors.h +40 -0
  226. package/harmony/flash_list/src/main/cpp/EventEmitters.cpp +40 -0
  227. package/harmony/flash_list/src/main/cpp/EventEmitters.h +48 -0
  228. package/harmony/flash_list/src/main/cpp/FlashListPackage.h +78 -0
  229. package/harmony/flash_list/src/main/cpp/FlashListStackNode.cpp +89 -0
  230. package/harmony/flash_list/src/main/cpp/FlashListStackNode.h +59 -0
  231. package/harmony/flash_list/src/main/cpp/Props.cpp +52 -0
  232. package/harmony/flash_list/src/main/cpp/Props.h +64 -0
  233. package/harmony/flash_list/src/main/cpp/ShadowNodes.cpp +34 -0
  234. package/harmony/flash_list/src/main/cpp/ShadowNodes.h +48 -0
  235. package/harmony/flash_list/src/main/ets/Logger.ets +64 -0
  236. package/harmony/flash_list/src/main/ets/RNAutoLayoutShadow.ets +154 -0
  237. package/harmony/flash_list/src/main/ets/RNAutoLayoutView.ets +252 -0
  238. package/harmony/flash_list/src/main/ets/RNCellContainer.ets +113 -0
  239. package/harmony/flash_list/src/main/module.json5 +7 -0
  240. package/harmony/flash_list/src/main/resources/base/element/color.json +8 -0
  241. package/harmony/flash_list/src/main/resources/base/element/string.json +16 -0
  242. package/harmony/flash_list/src/main/resources/base/media/icon.png +0 -0
  243. package/harmony/flash_list/src/main/resources/base/profile/main_pages.json +5 -0
  244. package/harmony/flash_list/src/main/resources/en_US/element/string.json +16 -0
  245. package/harmony/flash_list/src/main/resources/zh_CN/element/string.json +16 -0
  246. package/harmony/flash_list.har +0 -0
  247. package/jestSetup.js +16 -0
  248. package/package.json +88 -0
  249. package/src/AnimatedFlashList.ts +11 -0
  250. package/src/FlashList.tsx +870 -0
  251. package/src/FlashListProps.ts +335 -0
  252. package/src/GridLayoutProviderWithProps.ts +180 -0
  253. package/src/MasonryFlashList.tsx +476 -0
  254. package/src/PureComponentWrapper.tsx +42 -0
  255. package/src/__tests__/AverageWindow.test.ts +80 -0
  256. package/src/__tests__/ContentContainerUtils.test.ts +130 -0
  257. package/src/__tests__/FlashList.test.tsx +886 -0
  258. package/src/__tests__/GridLayoutProviderWithProps.test.ts +179 -0
  259. package/src/__tests__/MasonryFlashList.test.ts +292 -0
  260. package/src/__tests__/PlatformHelper.web.test.ts +45 -0
  261. package/src/__tests__/ViewabilityHelper.test.ts +283 -0
  262. package/src/__tests__/helpers/mountFlashList.tsx +62 -0
  263. package/src/__tests__/helpers/mountMasonryFlashList.tsx +70 -0
  264. package/src/__tests__/useBlankAreaTracker.test.tsx +204 -0
  265. package/src/benchmark/AutoScrollHelper.ts +70 -0
  266. package/src/benchmark/JSFPSMonitor.ts +74 -0
  267. package/src/benchmark/roundToDecimalPlaces.ts +4 -0
  268. package/src/benchmark/useBenchmark.ts +240 -0
  269. package/src/benchmark/useBlankAreaTracker.ts +117 -0
  270. package/src/benchmark/useDataMultiplier.ts +19 -0
  271. package/src/benchmark/useFlatListBenchmark.ts +107 -0
  272. package/src/errors/CustomError.ts +10 -0
  273. package/src/errors/ExceptionList.ts +28 -0
  274. package/src/errors/Warnings.ts +15 -0
  275. package/src/fabric/AutoLayoutNativeComponent.ts +51 -0
  276. package/src/fabric/CellContainerNativeComponent.ts +34 -0
  277. package/src/index.ts +43 -0
  278. package/src/native/auto-layout/AutoLayoutView.tsx +73 -0
  279. package/src/native/auto-layout/AutoLayoutViewNativeComponent.android.ts +7 -0
  280. package/src/native/auto-layout/AutoLayoutViewNativeComponent.harmony.ts +30 -0
  281. package/src/native/auto-layout/AutoLayoutViewNativeComponent.ios.ts +7 -0
  282. package/src/native/auto-layout/AutoLayoutViewNativeComponent.ts +7 -0
  283. package/src/native/auto-layout/AutoLayoutViewNativeComponentProps.ts +17 -0
  284. package/src/native/cell-container/CellContainer.android.ts +7 -0
  285. package/src/native/cell-container/CellContainer.harmony.ts +30 -0
  286. package/src/native/cell-container/CellContainer.ios.ts +6 -0
  287. package/src/native/cell-container/CellContainer.tsx +14 -0
  288. package/src/native/cell-container/CellContainer.web.tsx +9 -0
  289. package/src/native/config/PlatformHelper.android.ts +29 -0
  290. package/src/native/config/PlatformHelper.harmony.ts +51 -0
  291. package/src/native/config/PlatformHelper.ios.ts +28 -0
  292. package/src/native/config/PlatformHelper.ts +29 -0
  293. package/src/native/config/PlatformHelper.web.ts +34 -0
  294. package/src/utils/AverageWindow.ts +49 -0
  295. package/src/utils/ContentContainerUtils.ts +92 -0
  296. package/src/viewability/ViewToken.ts +7 -0
  297. package/src/viewability/ViewabilityHelper.ts +162 -0
  298. package/src/viewability/ViewabilityManager.ts +134 -0
@@ -0,0 +1,179 @@
1
+ import { ScrollView } from "react-native";
2
+ import { ProgressiveListView } from "recyclerlistview";
3
+
4
+ import FlashList from "../FlashList";
5
+
6
+ import { mountFlashList } from "./helpers/mountFlashList";
7
+
8
+ describe("GridLayoutProviderWithProps", () => {
9
+ it("updates average window on layout manager change", () => {
10
+ const flashList = mountFlashList();
11
+ const oldAverageWindow = (flashList.instance as FlashList<any>).state
12
+ .layoutProvider["averageWindow"];
13
+
14
+ // width change from default 400 to 600 will force layout manager to change
15
+ flashList.find(ScrollView)?.trigger("onLayout", {
16
+ nativeEvent: { layout: { height: 900, width: 600 } },
17
+ });
18
+
19
+ const newAverageWindow =
20
+ flashList.instance.state.layoutProvider["averageWindow"];
21
+
22
+ expect(newAverageWindow).not.toBe(oldAverageWindow);
23
+ flashList.unmount();
24
+ });
25
+ it("average window's size is two times the number of items that will fill the screen", () => {
26
+ const flashList = mountFlashList({ numColumns: 2 });
27
+ expect(
28
+ flashList.instance.state.layoutProvider["averageWindow"]["inputValues"]
29
+ .length
30
+ ).toBe(20);
31
+ flashList.find(ScrollView)?.trigger("onLayout", {
32
+ nativeEvent: { layout: { height: 2000, width: 600 } },
33
+ });
34
+ expect(
35
+ flashList.instance.state.layoutProvider["averageWindow"]["inputValues"]
36
+ .length
37
+ ).toBe(40);
38
+ flashList.setProps({ numColumns: 1 });
39
+ expect(
40
+ flashList.instance.state.layoutProvider["averageWindow"]["inputValues"]
41
+ .length
42
+ ).toBe(20);
43
+ flashList.unmount();
44
+ });
45
+ it("average window should not be less than 6 in size", () => {
46
+ const flashList = mountFlashList();
47
+ flashList.find(ScrollView)?.trigger("onLayout", {
48
+ nativeEvent: { layout: { height: 100, width: 100 } },
49
+ });
50
+ expect(
51
+ flashList.instance.state.layoutProvider["averageWindow"]["inputValues"]
52
+ .length
53
+ ).toBe(6);
54
+ flashList.unmount();
55
+ });
56
+ it("vertical list: average should not update when widths change", () => {
57
+ const flashList = mountFlashList();
58
+ const layoutProvider = flashList.instance.state.layoutProvider;
59
+ const oldAverage = layoutProvider.averageItemSize;
60
+
61
+ layoutProvider.getLayoutManager()!.getLayouts()[0].width = 500;
62
+ flashList.find(ProgressiveListView)?.instance.onItemLayout(0);
63
+
64
+ expect(oldAverage).toBe(layoutProvider.averageItemSize);
65
+ flashList.unmount();
66
+ });
67
+ it("horizontal list: average should not update when heights change", () => {
68
+ const flashList = mountFlashList({ horizontal: true });
69
+ const layoutProvider = flashList.instance.state.layoutProvider;
70
+ const oldAverage = layoutProvider.averageItemSize;
71
+
72
+ layoutProvider.getLayoutManager()!.getLayouts()[0].height = 600;
73
+
74
+ // Can throw a no op set state warning. Should be handled in PLV.
75
+ flashList.find(ProgressiveListView)?.instance.onItemLayout(0);
76
+
77
+ expect(oldAverage).toBe(layoutProvider.averageItemSize);
78
+ flashList.unmount();
79
+ });
80
+ it("computes correct average", () => {
81
+ const flashList = mountFlashList();
82
+ const layoutProvider = flashList.instance.state.layoutProvider;
83
+ expect(layoutProvider.averageItemSize).toBe(200);
84
+
85
+ const layouts = layoutProvider.getLayoutManager()!.getLayouts();
86
+ const progressiveListView = flashList.find(ProgressiveListView);
87
+ layouts[0].height = 100;
88
+ layouts[1].height = 200;
89
+ layouts[2].height = 300;
90
+ layouts[3].height = 400;
91
+ progressiveListView?.instance.onItemLayout(0);
92
+ progressiveListView?.instance.onItemLayout(1);
93
+ progressiveListView?.instance.onItemLayout(2);
94
+ progressiveListView?.instance.onItemLayout(3);
95
+
96
+ // estimatedItemSize is treated as one of the values. That's why 240.
97
+ expect(layoutProvider.averageItemSize).toBe(240);
98
+ flashList.unmount();
99
+ });
100
+ it("updates all cached widths for vertical list and heights for horizontal list when orientation changes", () => {
101
+ const runCacheUpdateTest = (horizontal: boolean) => {
102
+ const flashList = mountFlashList({
103
+ data: new Array(20).fill("1"),
104
+ horizontal,
105
+ });
106
+ const progressiveListView = flashList.find(ProgressiveListView);
107
+ const layoutProvider = flashList.instance.state.layoutProvider;
108
+
109
+ layoutProvider
110
+ .getLayoutManager()!
111
+ .getLayouts()
112
+ .forEach((layout, index) => {
113
+ // marking layouts as if they're actual rendered sizes
114
+ progressiveListView?.instance.onItemLayout(index);
115
+
116
+ // checking size
117
+ if (horizontal) {
118
+ expect(layout.height).toBe(900);
119
+ } else {
120
+ expect(layout.width).toBe(400);
121
+ }
122
+ });
123
+
124
+ // simulates orientation change
125
+ flashList.find(ScrollView)?.trigger("onLayout", {
126
+ nativeEvent: { layout: { height: 400, width: 900 } },
127
+ });
128
+
129
+ layoutProvider
130
+ .getLayoutManager()!
131
+ .getLayouts()
132
+ .forEach((layout) => {
133
+ // making sure all widths or heights are updated
134
+ if (horizontal) {
135
+ expect(layout.height).toBe(400);
136
+ } else {
137
+ expect(layout.width).toBe(900);
138
+ }
139
+
140
+ // making sure extra keys don't make their way to layout unnecessarily
141
+ expect(Object.keys(layout).length).toBe(6);
142
+ });
143
+ flashList.unmount();
144
+ };
145
+ // vertical list
146
+ runCacheUpdateTest(false);
147
+ // horizontal list
148
+ runCacheUpdateTest(true);
149
+ });
150
+ it("expires if column count or padding changes", () => {
151
+ const flashList = mountFlashList();
152
+ const baseProps = flashList.instance.props;
153
+ expect(
154
+ flashList.instance.state.layoutProvider.updateProps({
155
+ ...baseProps,
156
+ contentContainerStyle: { paddingTop: 10 },
157
+ }).hasExpired
158
+ ).toBe(false);
159
+ expect(
160
+ flashList.instance.state.layoutProvider.updateProps({
161
+ ...baseProps,
162
+ contentContainerStyle: { paddingBottom: 10 },
163
+ }).hasExpired
164
+ ).toBe(false);
165
+ expect(
166
+ flashList.instance.state.layoutProvider.updateProps({
167
+ ...baseProps,
168
+ contentContainerStyle: { paddingLeft: 10 },
169
+ }).hasExpired
170
+ ).toBe(true);
171
+ flashList.instance.state.layoutProvider["_hasExpired"] = false;
172
+ expect(
173
+ flashList.instance.state.layoutProvider.updateProps({
174
+ ...baseProps,
175
+ numColumns: 2,
176
+ }).hasExpired
177
+ ).toBe(true);
178
+ });
179
+ });
@@ -0,0 +1,292 @@
1
+ import { ScrollView, Text, View } from "react-native";
2
+ import "@quilted/react-testing/matchers";
3
+ import { ProgressiveListView } from "recyclerlistview";
4
+ import React from "react";
5
+
6
+ import {
7
+ MasonryFlashListProps,
8
+ MasonryFlashListRef,
9
+ } from "../MasonryFlashList";
10
+ import FlashList from "../FlashList";
11
+
12
+ import { mountMasonryFlashList } from "./helpers/mountMasonryFlashList";
13
+
14
+ describe("MasonryFlashList", () => {
15
+ beforeEach(() => {
16
+ jest.clearAllMocks();
17
+ jest.useFakeTimers();
18
+ });
19
+
20
+ it("renders items and has 3 internal lists", () => {
21
+ const masonryFlashList = mountMasonryFlashList();
22
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(3);
23
+ expect(masonryFlashList).toContainReactComponent(Text, { children: "One" });
24
+ expect(masonryFlashList).toContainReactComponent(ProgressiveListView, {
25
+ isHorizontal: false,
26
+ });
27
+ masonryFlashList.unmount();
28
+ });
29
+ it("invokes renderItem with columnIndex and columnSpan", () => {
30
+ const mockRenderItem = jest.fn(() => null);
31
+ const masonryFlashList = mountMasonryFlashList({
32
+ renderItem: mockRenderItem,
33
+ data: ["One", "Two", "Three"],
34
+ numColumns: 3,
35
+ });
36
+ expect(mockRenderItem).toHaveBeenCalledWith(
37
+ expect.objectContaining({
38
+ columnIndex: 0,
39
+ columnSpan: 1,
40
+ })
41
+ );
42
+
43
+ expect(mockRenderItem).toHaveBeenCalledWith(
44
+ expect.objectContaining({
45
+ columnIndex: 1,
46
+ columnSpan: 1,
47
+ })
48
+ );
49
+
50
+ expect(mockRenderItem).toHaveBeenCalledWith(
51
+ expect.objectContaining({
52
+ columnSpan: 1,
53
+ columnIndex: 2,
54
+ })
55
+ );
56
+ masonryFlashList.unmount();
57
+ });
58
+ it("raised onLoad event only when first internal child mounts", () => {
59
+ const onLoadMock = jest.fn();
60
+ const ref = React.createRef<MasonryFlashListRef<string>>();
61
+ const masonryFlashList = mountMasonryFlashList(
62
+ {
63
+ onLoad: onLoadMock,
64
+ },
65
+ ref
66
+ );
67
+ expect(onLoadMock).not.toHaveBeenCalled();
68
+ masonryFlashList.findAll(ProgressiveListView)[1]?.instance.onItemLayout(0);
69
+ expect(onLoadMock).toHaveBeenCalledTimes(1);
70
+
71
+ // on load shouldn't be passed to wrapper list
72
+ expect((ref.current as FlashList<string>).props.onLoad).toBeUndefined();
73
+ masonryFlashList.unmount();
74
+ });
75
+ it("can resize columns using getColumnFlex", () => {
76
+ const masonryFlashList = mountMasonryFlashList({
77
+ getColumnFlex: (_, column) => (column === 0 ? 1 : 3),
78
+ });
79
+ const progressiveListView =
80
+ masonryFlashList.find(ProgressiveListView)!.instance;
81
+ expect(progressiveListView.getLayout(0).width).toBe(100);
82
+ expect(progressiveListView.getLayout(1).width).toBe(300);
83
+
84
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(3);
85
+ masonryFlashList.findAll(ProgressiveListView).forEach((plv, index) => {
86
+ if (index === 1) {
87
+ expect(plv.instance.props.layoutSize.width).toBe(100);
88
+ }
89
+ if (index === 2) {
90
+ expect(plv.instance.props.layoutSize.width).toBe(300);
91
+ }
92
+ });
93
+ masonryFlashList.unmount();
94
+ });
95
+ it("mounts a single ScrollView", () => {
96
+ const masonryFlashList = mountMasonryFlashList();
97
+ expect(masonryFlashList.findAll(ScrollView)).toHaveLength(1);
98
+ masonryFlashList.unmount();
99
+ });
100
+ it("forwards single onScroll event to external listener", () => {
101
+ const onScrollMock = jest.fn();
102
+ const masonryFlashList = mountMasonryFlashList({
103
+ onScroll: onScrollMock,
104
+ });
105
+ masonryFlashList.find(ScrollView)?.instance.props.onScroll({
106
+ nativeEvent: { contentOffset: { x: 0, y: 0 } },
107
+ });
108
+ expect(onScrollMock).toHaveBeenCalledTimes(1);
109
+ masonryFlashList.unmount();
110
+ });
111
+ it("updates scroll offset of all internal lists", () => {
112
+ const onScrollMock = jest.fn();
113
+ const masonryFlashList = mountMasonryFlashList({
114
+ onScroll: onScrollMock,
115
+ });
116
+ masonryFlashList.find(ScrollView)?.instance.props.onScroll({
117
+ nativeEvent: { contentOffset: { x: 0, y: 100 } },
118
+ });
119
+ masonryFlashList.findAll(ProgressiveListView).forEach((list) => {
120
+ expect(list.instance.getCurrentScrollOffset()).toBe(100);
121
+ });
122
+ masonryFlashList.unmount();
123
+ });
124
+ it("has a valid ref object", () => {
125
+ const ref = React.createRef<MasonryFlashListRef<string>>();
126
+ const masonryFlashList = mountMasonryFlashList({}, ref);
127
+ expect(ref.current).toBeDefined();
128
+ masonryFlashList.unmount();
129
+ });
130
+ it("forwards overrideItemLayout to internal lists", () => {
131
+ const overrideItemLayout = jest.fn((layout) => {
132
+ layout.size = 300;
133
+ });
134
+ const masonryFlashList = mountMasonryFlashList({
135
+ overrideItemLayout,
136
+ });
137
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(3);
138
+ masonryFlashList.findAll(ProgressiveListView).forEach((list, index) => {
139
+ if (index !== 0) {
140
+ expect(list.instance.getLayout(0).height).toBe(300);
141
+ }
142
+ });
143
+ masonryFlashList.unmount();
144
+ });
145
+ it("forwards keyExtractor to internal list", () => {
146
+ const keyExtractor = (_: string, index: number) => (index + 1).toString();
147
+ const masonryFlashList = mountMasonryFlashList({
148
+ keyExtractor,
149
+ });
150
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(3);
151
+ expect(
152
+ masonryFlashList
153
+ .findAll(ProgressiveListView)[0]
154
+ .instance.props.dataProvider.getStableId(0)
155
+ ).toBe("0");
156
+ expect(
157
+ masonryFlashList
158
+ .findAll(ProgressiveListView)[1]
159
+ .instance.props.dataProvider.getStableId(0)
160
+ ).toBe("1");
161
+ expect(
162
+ masonryFlashList
163
+ .findAll(ProgressiveListView)[2]
164
+ .instance.props.dataProvider.getStableId(0)
165
+ ).toBe("2");
166
+ masonryFlashList.unmount();
167
+ });
168
+ it("correctly maps list indices to actual indices", () => {
169
+ const data = new Array(20).fill(0).map((_, index) => index.toString());
170
+ const getItemType = (item: string, index: number) => {
171
+ expect(index.toString()).toBe(item);
172
+ return 0;
173
+ };
174
+ const renderItem: MasonryFlashListProps<string>["renderItem"] = ({
175
+ item,
176
+ index,
177
+ }) => {
178
+ expect(index.toString()).toBe(item);
179
+ return null;
180
+ };
181
+ const overrideItemLayout: MasonryFlashListProps<string>["overrideItemLayout"] =
182
+ (layout, item: string, index: number) => {
183
+ expect(index.toString()).toBe(item);
184
+ };
185
+ const keyExtractor = (item: string, index: number) => {
186
+ expect(index.toString()).toBe(item);
187
+ return index.toString();
188
+ };
189
+ const onViewableItemsChanged: MasonryFlashListProps<string>["onViewableItemsChanged"] =
190
+ (info) => {
191
+ info.viewableItems.forEach((viewToken) => {
192
+ expect(viewToken.index?.toString()).toBe(viewToken.item);
193
+ });
194
+ };
195
+
196
+ const masonryFlashList = mountMasonryFlashList({
197
+ data,
198
+ renderItem,
199
+ getItemType,
200
+ overrideItemLayout,
201
+ keyExtractor,
202
+ onViewableItemsChanged,
203
+ });
204
+ jest.advanceTimersByTime(1000);
205
+ masonryFlashList.unmount();
206
+ });
207
+ it("internal list height should be derived from the parent and width from itself", () => {
208
+ const masonryFlashList = mountMasonryFlashList({
209
+ testID: "MasonryProxyScrollView",
210
+ });
211
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(3);
212
+ masonryFlashList.findAll(View).forEach((view: any) => {
213
+ view.props?.onLayout?.({
214
+ nativeEvent: { layout: { width: 500, height: 500 } },
215
+ });
216
+ });
217
+ masonryFlashList.findAll(ProgressiveListView).forEach((list, index) => {
218
+ if (index !== 0) {
219
+ expect(list.instance.getRenderedSize().width).toBe(500);
220
+ expect(list.instance.getRenderedSize().height).toBe(900);
221
+ }
222
+ });
223
+ masonryFlashList.unmount();
224
+ });
225
+ it("can optimize item arrangement", () => {
226
+ const columnCount = 3;
227
+ const data = new Array(999).fill(null).map((_, index) => {
228
+ return "1";
229
+ });
230
+ const masonryFlashList = mountMasonryFlashList({
231
+ data,
232
+ optimizeItemArrangement: true,
233
+ numColumns: columnCount,
234
+ overrideItemLayout(layout, _, index, __, ___?) {
235
+ layout.size = ((index * 10) % 100) + 100 / ((index % columnCount) + 1);
236
+ },
237
+ });
238
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(4);
239
+
240
+ // I've verified that the following values are correct by observing the algorithm in action
241
+ // Captured values will help prevent regression in the future
242
+ expect(
243
+ Math.floor(
244
+ masonryFlashList
245
+ .findAll(ProgressiveListView)[1]
246
+ .instance.getContentDimension().height
247
+ )
248
+ ).toBe(35306);
249
+ expect(
250
+ Math.floor(
251
+ masonryFlashList
252
+ .findAll(ProgressiveListView)[2]
253
+ .instance.getContentDimension().height
254
+ )
255
+ ).toBe(35313);
256
+ expect(
257
+ Math.floor(
258
+ masonryFlashList
259
+ .findAll(ProgressiveListView)[3]
260
+ .instance.getContentDimension().height
261
+ )
262
+ ).toBe(35339);
263
+ });
264
+ it("applies horizontal content container padding to the list", () => {
265
+ const masonryFlashList = mountMasonryFlashList({
266
+ numColumns: 4,
267
+ contentContainerStyle: { paddingHorizontal: 10 },
268
+ });
269
+ expect(masonryFlashList.findAll(ProgressiveListView).length).toBe(5);
270
+ masonryFlashList.findAll(ProgressiveListView).forEach((list, index) => {
271
+ if (index === 0) {
272
+ expect(list.instance.getRenderedSize().width).toBe(400);
273
+ expect(list.instance.getRenderedSize().height).toBe(900);
274
+ } else {
275
+ expect(list.instance.getRenderedSize().width).toBe(95);
276
+ expect(list.instance.getRenderedSize().height).toBe(900);
277
+ }
278
+ });
279
+ masonryFlashList.unmount();
280
+ });
281
+ it("divides columns equally if no getColumnFlex is passed", () => {
282
+ const masonryFlashList = mountMasonryFlashList({
283
+ numColumns: 4,
284
+ });
285
+ const progressiveListView =
286
+ masonryFlashList.find(ProgressiveListView)!.instance;
287
+ expect(progressiveListView.getLayout(0).width).toBe(100);
288
+ expect(progressiveListView.getLayout(1).width).toBe(100);
289
+ expect(progressiveListView.getLayout(2).width).toBe(100);
290
+ expect(progressiveListView.getLayout(3).width).toBe(100);
291
+ });
292
+ });
@@ -0,0 +1,45 @@
1
+ import {
2
+ getCellContainerPlatformStyles,
3
+ getItemAnimator,
4
+ } from "../native/config/PlatformHelper.web";
5
+
6
+ describe("Platform Helper Web", () => {
7
+ it("can compute right transform for web", () => {
8
+ const transformStyle = getCellContainerPlatformStyles(false, {
9
+ x: 20,
10
+ y: 70,
11
+ });
12
+ const transformInvertedStyle = getCellContainerPlatformStyles(true, {
13
+ x: 30,
14
+ y: 30,
15
+ });
16
+ const transformHorizontalInvertedStyle = getCellContainerPlatformStyles(
17
+ true,
18
+ {
19
+ x: 30,
20
+ y: 30,
21
+ isHorizontal: true,
22
+ }
23
+ );
24
+ const expectedTransform = "translate(20px,70px)";
25
+ const expectedTransformInverted = "translate(30px,30px) scaleY(-1)";
26
+ const expectedTransformHorizontalInverted =
27
+ "translate(30px,30px) scaleX(-1)";
28
+
29
+ expect(transformStyle?.transform).toBe(expectedTransform);
30
+ expect(transformStyle?.WebkitTransform).toBe(expectedTransform);
31
+ expect(transformInvertedStyle?.transform).toBe(expectedTransformInverted);
32
+ expect(transformInvertedStyle?.WebkitTransform).toBe(
33
+ expectedTransformInverted
34
+ );
35
+ expect(transformHorizontalInvertedStyle?.transform).toBe(
36
+ expectedTransformHorizontalInverted
37
+ );
38
+ expect(transformHorizontalInvertedStyle?.WebkitTransform).toBe(
39
+ expectedTransformHorizontalInverted
40
+ );
41
+ });
42
+ it("can return an animator", () => {
43
+ expect(getItemAnimator()!["animateWillMount"]).toBeDefined();
44
+ });
45
+ });