@shopify/flash-list 2.0.0 → 2.0.2-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 (289) hide show
  1. package/README.md +97 -27
  2. package/RNFlashList.podspec +37 -0
  3. package/android/build.gradle +89 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutShadow.kt +105 -0
  6. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt +158 -0
  7. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt +70 -0
  8. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +29 -0
  9. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainer.java +16 -0
  10. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerImpl.kt +16 -0
  11. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt +34 -0
  12. package/android/src/main/kotlin/com/shopify/reactnative/flash_list/FlashListPackage.kt +19 -0
  13. package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java +47 -0
  14. package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java +21 -0
  15. package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java +32 -0
  16. package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java +16 -0
  17. package/android/src/test/java/com/shopify/reactnative/flash_list/AutoLayoutShadowTest.kt +147 -0
  18. package/android/src/test/java/com/shopify/reactnative/flash_list/models/Rect.kt +61 -0
  19. package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestCollection.kt +6 -0
  20. package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestDataModel.kt +8 -0
  21. package/android/src/test/resources/LayoutTestData.json +788 -0
  22. package/dist/AnimatedFlashList.js +2 -2
  23. package/dist/AnimatedFlashList.js.map +1 -1
  24. package/dist/FlashList.d.ts +167 -1
  25. package/dist/FlashList.d.ts.map +1 -1
  26. package/dist/FlashList.js +595 -3
  27. package/dist/FlashList.js.map +1 -1
  28. package/dist/FlashListProps.d.ts +63 -2
  29. package/dist/FlashListProps.d.ts.map +1 -1
  30. package/dist/FlashListProps.js.map +1 -1
  31. package/dist/GridLayoutProviderWithProps.d.ts +42 -0
  32. package/dist/GridLayoutProviderWithProps.d.ts.map +1 -0
  33. package/dist/GridLayoutProviderWithProps.js +114 -0
  34. package/dist/GridLayoutProviderWithProps.js.map +1 -0
  35. package/dist/MasonryFlashList.d.ts +51 -0
  36. package/dist/MasonryFlashList.d.ts.map +1 -0
  37. package/dist/MasonryFlashList.js +252 -0
  38. package/dist/MasonryFlashList.js.map +1 -0
  39. package/dist/PureComponentWrapper.d.ts +22 -0
  40. package/dist/PureComponentWrapper.d.ts.map +1 -0
  41. package/dist/PureComponentWrapper.js +37 -0
  42. package/dist/PureComponentWrapper.js.map +1 -0
  43. package/dist/__tests__/ContentContainerUtils.test.d.ts +2 -0
  44. package/dist/__tests__/ContentContainerUtils.test.d.ts.map +1 -0
  45. package/dist/__tests__/ContentContainerUtils.test.js +85 -0
  46. package/dist/__tests__/ContentContainerUtils.test.js.map +1 -0
  47. package/dist/__tests__/FlashList.test.d.ts +2 -0
  48. package/dist/__tests__/FlashList.test.d.ts.map +1 -0
  49. package/dist/__tests__/FlashList.test.js +902 -0
  50. package/dist/__tests__/FlashList.test.js.map +1 -0
  51. package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts +2 -0
  52. package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts.map +1 -0
  53. package/dist/__tests__/GridLayoutProviderWithProps.test.js +143 -0
  54. package/dist/__tests__/GridLayoutProviderWithProps.test.js.map +1 -0
  55. package/dist/__tests__/MasonryFlashList.test.d.ts +2 -0
  56. package/dist/__tests__/MasonryFlashList.test.d.ts.map +1 -0
  57. package/dist/__tests__/MasonryFlashList.test.js +254 -0
  58. package/dist/__tests__/MasonryFlashList.test.js.map +1 -0
  59. package/dist/__tests__/PlatformHelper.web.test.d.ts +2 -0
  60. package/dist/__tests__/PlatformHelper.web.test.d.ts.map +1 -0
  61. package/dist/__tests__/PlatformHelper.web.test.js +33 -0
  62. package/dist/__tests__/PlatformHelper.web.test.js.map +1 -0
  63. package/dist/__tests__/ViewabilityHelper.test.js +4 -3
  64. package/dist/__tests__/ViewabilityHelper.test.js.map +1 -1
  65. package/dist/__tests__/helpers/mountFlashList.d.ts +19 -0
  66. package/dist/__tests__/helpers/mountFlashList.d.ts.map +1 -0
  67. package/dist/__tests__/helpers/mountFlashList.js +44 -0
  68. package/dist/__tests__/helpers/mountFlashList.js.map +1 -0
  69. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +18 -0
  70. package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -0
  71. package/dist/__tests__/helpers/mountMasonryFlashList.js +49 -0
  72. package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -0
  73. package/dist/__tests__/useBlankAreaTracker.test.d.ts +2 -0
  74. package/dist/__tests__/useBlankAreaTracker.test.d.ts.map +1 -0
  75. package/dist/__tests__/useBlankAreaTracker.test.js +179 -0
  76. package/dist/__tests__/useBlankAreaTracker.test.js.map +1 -0
  77. package/dist/benchmark/JSFPSMonitor.d.ts.map +1 -1
  78. package/dist/benchmark/JSFPSMonitor.js +1 -2
  79. package/dist/benchmark/JSFPSMonitor.js.map +1 -1
  80. package/dist/benchmark/useBenchmark.d.ts +4 -2
  81. package/dist/benchmark/useBenchmark.d.ts.map +1 -1
  82. package/dist/benchmark/useBenchmark.js +24 -12
  83. package/dist/benchmark/useBenchmark.js.map +1 -1
  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 +66 -0
  87. package/dist/benchmark/useBlankAreaTracker.js.map +1 -0
  88. package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
  89. package/dist/benchmark/useFlatListBenchmark.js +1 -2
  90. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  91. package/dist/enableNewCore.d.ts +3 -0
  92. package/dist/enableNewCore.d.ts.map +1 -0
  93. package/dist/enableNewCore.js +25 -0
  94. package/dist/enableNewCore.js.map +1 -0
  95. package/dist/errors/CustomError.d.ts +8 -0
  96. package/dist/errors/CustomError.d.ts.map +1 -0
  97. package/dist/errors/CustomError.js +14 -0
  98. package/dist/errors/CustomError.js.map +1 -0
  99. package/dist/errors/ExceptionList.d.ts +24 -0
  100. package/dist/errors/ExceptionList.d.ts.map +1 -0
  101. package/dist/errors/ExceptionList.js +26 -0
  102. package/dist/errors/ExceptionList.js.map +1 -0
  103. package/dist/errors/Warnings.d.ts +9 -0
  104. package/dist/errors/Warnings.d.ts.map +1 -0
  105. package/dist/errors/Warnings.js +13 -0
  106. package/dist/errors/Warnings.js.map +1 -0
  107. package/dist/index.d.ts +9 -3
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +29 -7
  110. package/dist/index.js.map +1 -1
  111. package/dist/native/auto-layout/AutoLayoutView.d.ts +22 -0
  112. package/dist/native/auto-layout/AutoLayoutView.d.ts.map +1 -0
  113. package/dist/native/auto-layout/AutoLayoutView.js +48 -0
  114. package/dist/native/auto-layout/AutoLayoutView.js.map +1 -0
  115. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts +4 -0
  116. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts.map +1 -0
  117. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js +6 -0
  118. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js.map +1 -0
  119. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts +5 -0
  120. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts.map +1 -0
  121. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts +4 -0
  122. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts.map +1 -0
  123. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js +6 -0
  124. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js.map +1 -0
  125. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js +6 -0
  126. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js.map +1 -0
  127. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts +16 -0
  128. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts.map +1 -0
  129. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js +3 -0
  130. package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js.map +1 -0
  131. package/dist/native/cell-container/CellContainer.android.d.ts +6 -0
  132. package/dist/native/cell-container/CellContainer.android.d.ts.map +1 -0
  133. package/dist/native/cell-container/CellContainer.android.js +9 -0
  134. package/dist/native/cell-container/CellContainer.android.js.map +1 -0
  135. package/dist/native/cell-container/CellContainer.d.ts +8 -0
  136. package/dist/native/cell-container/CellContainer.d.ts.map +1 -0
  137. package/dist/native/cell-container/CellContainer.ios.d.ts +6 -0
  138. package/dist/native/cell-container/CellContainer.ios.d.ts.map +1 -0
  139. package/dist/native/cell-container/CellContainer.ios.js +9 -0
  140. package/dist/native/cell-container/CellContainer.ios.js.map +1 -0
  141. package/dist/native/cell-container/CellContainer.js +11 -0
  142. package/dist/native/cell-container/CellContainer.js.map +1 -0
  143. package/dist/native/cell-container/CellContainer.web.d.ts +7 -0
  144. package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -0
  145. package/dist/native/cell-container/CellContainer.web.js +13 -0
  146. package/dist/native/cell-container/CellContainer.web.js.map +1 -0
  147. package/dist/native/config/PlatformHelper.android.d.ts +22 -1
  148. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
  149. package/dist/native/config/PlatformHelper.android.js +16 -1
  150. package/dist/native/config/PlatformHelper.android.js.map +1 -1
  151. package/dist/native/config/PlatformHelper.d.ts +22 -1
  152. package/dist/native/config/PlatformHelper.d.ts.map +1 -1
  153. package/dist/native/config/PlatformHelper.ios.d.ts +22 -1
  154. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
  155. package/dist/native/config/PlatformHelper.ios.js +15 -1
  156. package/dist/native/config/PlatformHelper.ios.js.map +1 -1
  157. package/dist/native/config/PlatformHelper.js +16 -1
  158. package/dist/native/config/PlatformHelper.js.map +1 -1
  159. package/dist/native/config/PlatformHelper.web.d.ts +23 -1
  160. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
  161. package/dist/native/config/PlatformHelper.web.js +18 -1
  162. package/dist/native/config/PlatformHelper.web.js.map +1 -1
  163. package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
  164. package/dist/recyclerview/RecyclerView.js +6 -6
  165. package/dist/recyclerview/RecyclerView.js.map +1 -1
  166. package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
  167. package/dist/recyclerview/RecyclerViewManager.js +8 -9
  168. package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
  169. package/dist/recyclerview/RecyclerViewProps.d.ts +8 -1
  170. package/dist/recyclerview/RecyclerViewProps.d.ts.map +1 -1
  171. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts +3 -0
  172. package/dist/recyclerview/helpers/RenderTimeTracker.d.ts.map +1 -1
  173. package/dist/recyclerview/helpers/RenderTimeTracker.js +7 -0
  174. package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
  175. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
  176. package/dist/recyclerview/hooks/useRecyclerViewController.js +0 -4
  177. package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
  178. package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
  179. package/dist/recyclerview/layout-managers/LayoutManager.js +1 -2
  180. package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
  181. package/dist/specs/AutoLayoutNativeComponent.d.ts +18 -0
  182. package/dist/specs/AutoLayoutNativeComponent.d.ts.map +1 -0
  183. package/dist/specs/AutoLayoutNativeComponent.js +6 -0
  184. package/dist/specs/AutoLayoutNativeComponent.js.map +1 -0
  185. package/dist/specs/CellContainerNativeComponent.d.ts +8 -0
  186. package/dist/specs/CellContainerNativeComponent.d.ts.map +1 -0
  187. package/dist/specs/CellContainerNativeComponent.js +6 -0
  188. package/dist/specs/CellContainerNativeComponent.js.map +1 -0
  189. package/dist/tsconfig.tsbuildinfo +1 -1
  190. package/dist/utils/ContentContainerUtils.d.ts +27 -0
  191. package/dist/utils/ContentContainerUtils.d.ts.map +1 -0
  192. package/dist/utils/ContentContainerUtils.js +48 -0
  193. package/dist/utils/ContentContainerUtils.js.map +1 -0
  194. package/dist/viewability/ViewToken.d.ts.map +1 -0
  195. package/dist/viewability/ViewToken.js.map +1 -0
  196. package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.d.ts +2 -2
  197. package/dist/viewability/ViewabilityHelper.d.ts.map +1 -0
  198. package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.js +4 -2
  199. package/dist/{recyclerview/viewability → viewability}/ViewabilityHelper.js.map +1 -1
  200. package/dist/{recyclerview/viewability → viewability}/ViewabilityManager.d.ts +3 -3
  201. package/dist/viewability/ViewabilityManager.d.ts.map +1 -0
  202. package/dist/{recyclerview/viewability → viewability}/ViewabilityManager.js +16 -16
  203. package/dist/viewability/ViewabilityManager.js.map +1 -0
  204. package/ios/RNFlashList.xcodeproj/project.pbxproj +3 -0
  205. package/ios/RNFlashList.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  206. package/ios/Sources/AutoLayoutView.swift +294 -0
  207. package/ios/Sources/AutoLayoutViewComponentView.h +16 -0
  208. package/ios/Sources/AutoLayoutViewComponentView.mm +90 -0
  209. package/ios/Sources/AutoLayoutViewManager.mm +14 -0
  210. package/ios/Sources/AutoLayoutViewManager.swift +12 -0
  211. package/ios/Sources/CellContainerComponentView.h +18 -0
  212. package/ios/Sources/CellContainerComponentView.mm +62 -0
  213. package/ios/Sources/CellContainerManager.mm +8 -0
  214. package/ios/Sources/CellContainerManager.swift +12 -0
  215. package/ios/Sources/FlatListPro-Bridging-Header.h +11 -0
  216. package/ios/Tests/AutoLayoutViewTests.swift +113 -0
  217. package/package.json +14 -3
  218. package/src/AnimatedFlashList.ts +2 -2
  219. package/src/FlashList.tsx +953 -0
  220. package/src/FlashListProps.ts +79 -3
  221. package/src/GridLayoutProviderWithProps.ts +180 -0
  222. package/src/MasonryFlashList.tsx +476 -0
  223. package/src/PureComponentWrapper.tsx +42 -0
  224. package/src/__tests__/ContentContainerUtils.test.ts +130 -0
  225. package/src/__tests__/FlashList.test.tsx +1001 -0
  226. package/src/__tests__/GridLayoutProviderWithProps.test.ts +179 -0
  227. package/src/__tests__/MasonryFlashList.test.ts +292 -0
  228. package/src/__tests__/PlatformHelper.web.test.ts +45 -0
  229. package/src/__tests__/ViewabilityHelper.test.ts +14 -13
  230. package/src/__tests__/helpers/mountFlashList.tsx +62 -0
  231. package/src/__tests__/helpers/mountMasonryFlashList.tsx +70 -0
  232. package/src/__tests__/useBlankAreaTracker.test.tsx +206 -0
  233. package/src/benchmark/JSFPSMonitor.ts +3 -3
  234. package/src/benchmark/useBenchmark.ts +40 -12
  235. package/src/benchmark/useBlankAreaTracker.ts +117 -0
  236. package/src/benchmark/useFlatListBenchmark.ts +1 -3
  237. package/src/enableNewCore.ts +24 -0
  238. package/src/errors/CustomError.ts +10 -0
  239. package/src/errors/ExceptionList.ts +28 -0
  240. package/src/errors/Warnings.ts +15 -0
  241. package/src/index.ts +43 -7
  242. package/src/native/auto-layout/AutoLayoutView.tsx +73 -0
  243. package/src/native/auto-layout/AutoLayoutViewNativeComponent.android.ts +7 -0
  244. package/src/native/auto-layout/AutoLayoutViewNativeComponent.ios.ts +7 -0
  245. package/src/native/auto-layout/AutoLayoutViewNativeComponent.ts +7 -0
  246. package/src/native/auto-layout/AutoLayoutViewNativeComponentProps.ts +17 -0
  247. package/src/native/cell-container/CellContainer.android.ts +7 -0
  248. package/src/native/cell-container/CellContainer.ios.ts +7 -0
  249. package/src/native/cell-container/CellContainer.tsx +14 -0
  250. package/src/native/cell-container/CellContainer.web.tsx +9 -0
  251. package/src/native/config/PlatformHelper.android.ts +25 -1
  252. package/src/native/config/PlatformHelper.ios.ts +24 -1
  253. package/src/native/config/PlatformHelper.ts +25 -1
  254. package/src/native/config/PlatformHelper.web.ts +30 -1
  255. package/src/recyclerview/RecyclerView.tsx +11 -6
  256. package/src/recyclerview/RecyclerViewManager.ts +18 -9
  257. package/src/recyclerview/RecyclerViewProps.ts +11 -1
  258. package/src/recyclerview/helpers/RenderTimeTracker.ts +8 -0
  259. package/src/recyclerview/hooks/useRecyclerViewController.tsx +0 -4
  260. package/src/recyclerview/layout-managers/LayoutManager.ts +1 -2
  261. package/src/specs/AutoLayoutNativeComponent.ts +24 -0
  262. package/src/specs/CellContainerNativeComponent.ts +9 -0
  263. package/src/utils/ContentContainerUtils.ts +92 -0
  264. package/src/{recyclerview/viewability → viewability}/ViewabilityHelper.ts +9 -8
  265. package/src/{recyclerview/viewability → viewability}/ViewabilityManager.ts +20 -18
  266. package/dist/errors/ErrorMessages.d.ts +0 -16
  267. package/dist/errors/ErrorMessages.d.ts.map +0 -1
  268. package/dist/errors/ErrorMessages.js +0 -19
  269. package/dist/errors/ErrorMessages.js.map +0 -1
  270. package/dist/errors/WarningMessages.d.ts +0 -4
  271. package/dist/errors/WarningMessages.d.ts.map +0 -1
  272. package/dist/errors/WarningMessages.js +0 -7
  273. package/dist/errors/WarningMessages.js.map +0 -1
  274. package/dist/isNewArch.d.ts +0 -2
  275. package/dist/isNewArch.d.ts.map +0 -1
  276. package/dist/isNewArch.js +0 -25
  277. package/dist/isNewArch.js.map +0 -1
  278. package/dist/recyclerview/viewability/ViewToken.d.ts.map +0 -1
  279. package/dist/recyclerview/viewability/ViewToken.js.map +0 -1
  280. package/dist/recyclerview/viewability/ViewabilityHelper.d.ts.map +0 -1
  281. package/dist/recyclerview/viewability/ViewabilityManager.d.ts.map +0 -1
  282. package/dist/recyclerview/viewability/ViewabilityManager.js.map +0 -1
  283. package/src/FlashList.ts +0 -1
  284. package/src/errors/ErrorMessages.ts +0 -26
  285. package/src/errors/WarningMessages.ts +0 -4
  286. package/src/isNewArch.ts +0 -25
  287. /package/dist/{recyclerview/viewability → viewability}/ViewToken.d.ts +0 -0
  288. /package/dist/{recyclerview/viewability → viewability}/ViewToken.js +0 -0
  289. /package/src/{recyclerview/viewability → viewability}/ViewToken.ts +0 -0
@@ -0,0 +1,902 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ var react_1 = tslib_1.__importStar(require("react"));
5
+ var react_native_1 = require("react-native");
6
+ require("@quilted/react-testing/matchers");
7
+ var recyclerlistview_1 = require("recyclerlistview");
8
+ var Warnings_1 = tslib_1.__importDefault(require("../errors/Warnings"));
9
+ var AutoLayoutView_1 = tslib_1.__importDefault(require("../native/auto-layout/AutoLayoutView"));
10
+ var CellContainer_1 = tslib_1.__importDefault(require("../native/cell-container/CellContainer"));
11
+ var FlashListProps_1 = require("../FlashListProps");
12
+ var mountFlashList_1 = require("./helpers/mountFlashList");
13
+ jest.mock("../native/cell-container/CellContainer", function () {
14
+ return jest.requireActual("../native/cell-container/CellContainer.ios.ts")
15
+ .default;
16
+ });
17
+ describe("FlashList", function () {
18
+ beforeEach(function () {
19
+ jest.clearAllMocks();
20
+ jest.useFakeTimers();
21
+ });
22
+ it("renders items", function () {
23
+ var flashList = (0, mountFlashList_1.mountFlashList)();
24
+ expect(flashList).toContainReactComponent(react_native_1.Text, { children: "One" });
25
+ expect(flashList).toContainReactComponent(recyclerlistview_1.ProgressiveListView, {
26
+ isHorizontal: false,
27
+ });
28
+ });
29
+ it("sets ProgressiveListView to horizontal", function () {
30
+ var flashList = (0, mountFlashList_1.mountFlashList)({ horizontal: true });
31
+ expect(flashList).toContainReactComponent(recyclerlistview_1.ProgressiveListView, {
32
+ isHorizontal: true,
33
+ });
34
+ });
35
+ it("calls prepareForLayoutAnimationRender", function () {
36
+ var flashList = (0, mountFlashList_1.mountFlashList)({
37
+ keyExtractor: function (item) { return item; },
38
+ });
39
+ var warn = jest.spyOn(console, "warn").mockReturnValue();
40
+ var prepareForLayoutAnimationRender = jest.spyOn(flashList.instance.recyclerlistview_unsafe, "prepareForLayoutAnimationRender");
41
+ flashList.instance.prepareForLayoutAnimationRender();
42
+ expect(prepareForLayoutAnimationRender).toHaveBeenCalledTimes(1);
43
+ expect(warn).not.toHaveBeenCalled();
44
+ });
45
+ it("sends a warning when prepareForLayoutAnimationRender without keyExtractor", function () {
46
+ var flashList = (0, mountFlashList_1.mountFlashList)();
47
+ var warn = jest.spyOn(console, "warn").mockReturnValue();
48
+ var prepareForLayoutAnimationRender = jest.spyOn(flashList.instance.recyclerlistview_unsafe, "prepareForLayoutAnimationRender");
49
+ flashList.instance.prepareForLayoutAnimationRender();
50
+ expect(prepareForLayoutAnimationRender).not.toHaveBeenCalled();
51
+ expect(warn).toHaveBeenCalledWith(Warnings_1.default.missingKeyExtractor);
52
+ });
53
+ it("disables initial scroll correction on recyclerlistview if initialScrollIndex is in first row", function () {
54
+ var flashList = (0, mountFlashList_1.mountFlashList)({ initialScrollIndex: 0, numColumns: 3 });
55
+ expect(flashList.instance["getUpdatedWindowCorrectionConfig"]()
56
+ .applyToInitialOffset).toBe(false);
57
+ flashList = (0, mountFlashList_1.mountFlashList)({ initialScrollIndex: 3, numColumns: 3 });
58
+ expect(flashList.instance["getUpdatedWindowCorrectionConfig"]()
59
+ .applyToInitialOffset).toBe(true);
60
+ flashList = (0, mountFlashList_1.mountFlashList)({ initialScrollIndex: 2, numColumns: 3 });
61
+ expect(flashList.instance["getUpdatedWindowCorrectionConfig"]()
62
+ .applyToInitialOffset).toBe(false);
63
+ });
64
+ it("assigns distance from window to window correction object", function () {
65
+ var flashList = (0, mountFlashList_1.mountFlashList)({ estimatedFirstItemOffset: 100 });
66
+ expect(flashList.instance["getUpdatedWindowCorrectionConfig"]().value.windowShift).toBe(-100);
67
+ });
68
+ it("only forwards onBlankArea prop to AutoLayout when needed", function () {
69
+ var _a;
70
+ var flashList = (0, mountFlashList_1.mountFlashList)();
71
+ var autoLayoutView = (_a = flashList.find(AutoLayoutView_1.default)) === null || _a === void 0 ? void 0 : _a.instance;
72
+ expect(autoLayoutView.props.onBlankAreaEvent).toBeUndefined();
73
+ flashList.setProps({ onBlankArea: function () { } });
74
+ expect(autoLayoutView.props.onBlankAreaEvent).not.toBeUndefined();
75
+ });
76
+ it("calls render item only when data of the items has changed", function () {
77
+ var renderItemMock = jest.fn(function (_a) {
78
+ var item = _a.item;
79
+ return react_1.default.createElement(react_native_1.Text, null, item);
80
+ });
81
+ var flashList = (0, mountFlashList_1.mountFlashList)({
82
+ renderItem: renderItemMock,
83
+ data: ["One", "Two", "Three", "Four"],
84
+ });
85
+ // because we have 4 data items
86
+ expect(renderItemMock).toHaveBeenCalledTimes(4);
87
+ // reset counter
88
+ renderItemMock.mockClear();
89
+ // changes layout of all four items
90
+ flashList.setProps({ numColumns: 2 });
91
+ // render item should be called 0 times because only layout of items would have changed
92
+ expect(renderItemMock).toHaveBeenCalledTimes(0);
93
+ flashList.unmount();
94
+ });
95
+ it("keeps component mounted based on prepareForLayoutAnimationRender being called", function () {
96
+ // Tracks components being unmounted
97
+ var unmountMock = jest.fn();
98
+ var Item = function (_a) {
99
+ var text = _a.text;
100
+ (0, react_1.useEffect)(function () {
101
+ return unmountMock;
102
+ }, []);
103
+ return react_1.default.createElement(react_native_1.Text, null, text);
104
+ };
105
+ var flashList = (0, mountFlashList_1.mountFlashList)({
106
+ keyExtractor: function (item) { return item; },
107
+ renderItem: function (_a) {
108
+ var item = _a.item;
109
+ return react_1.default.createElement(Item, { text: item });
110
+ },
111
+ data: ["One", "Two", "Three", "Four"],
112
+ });
113
+ // Change data without prepareForLayoutAnimationRender
114
+ flashList.setProps({ data: ["One", "Two", "Three", "Five"] });
115
+ expect(unmountMock).not.toHaveBeenCalled();
116
+ // Before changing data, we run prepareForLayoutAnimationRender.
117
+ // This ensures component gets unmounted instead of being recycled to ensure layout animations run as expected.
118
+ flashList.instance.prepareForLayoutAnimationRender();
119
+ flashList.setProps({ data: ["One", "Two", "Three", "Six"] });
120
+ expect(unmountMock).toHaveBeenCalledTimes(1);
121
+ });
122
+ it("fires onLoad event", function () {
123
+ var _a;
124
+ var onLoadMock = jest.fn();
125
+ // empty list
126
+ (0, mountFlashList_1.mountFlashList)({ data: [], onLoad: onLoadMock });
127
+ expect(onLoadMock).toHaveBeenCalledWith({
128
+ elapsedTimeInMs: expect.any(Number),
129
+ });
130
+ onLoadMock.mockClear();
131
+ // non-empty list
132
+ var flashList = (0, mountFlashList_1.mountFlashList)({ onLoad: onLoadMock });
133
+ (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance.onItemLayout(0);
134
+ expect(onLoadMock).toHaveBeenCalledWith({
135
+ elapsedTimeInMs: expect.any(Number),
136
+ });
137
+ });
138
+ it("loads an empty state", function () {
139
+ var EmptyComponent = function () {
140
+ return react_1.default.createElement(react_native_1.Text, null, "Empty");
141
+ };
142
+ var flashList = (0, mountFlashList_1.mountFlashList)({
143
+ data: [],
144
+ ListEmptyComponent: EmptyComponent,
145
+ });
146
+ expect(flashList).toContainReactComponent(EmptyComponent);
147
+ });
148
+ it("loads header and footer in empty state", function () {
149
+ var HeaderComponent = function () {
150
+ return react_1.default.createElement(react_native_1.Text, null, "Empty");
151
+ };
152
+ var FooterComponent = function () {
153
+ return react_1.default.createElement(react_native_1.Text, null, "Empty");
154
+ };
155
+ var flashList = (0, mountFlashList_1.mountFlashList)({
156
+ data: [],
157
+ ListHeaderComponent: HeaderComponent,
158
+ ListFooterComponent: FooterComponent,
159
+ });
160
+ expect(flashList).toContainReactComponent(HeaderComponent);
161
+ expect(flashList).toContainReactComponent(FooterComponent);
162
+ });
163
+ it("reports layout changes to the layout provider", function () {
164
+ var _a;
165
+ var flashList = (0, mountFlashList_1.mountFlashList)();
166
+ var reportItemLayoutMock = jest.spyOn(flashList.instance.state.layoutProvider, "reportItemLayout");
167
+ (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance.onItemLayout(0);
168
+ expect(reportItemLayoutMock).toHaveBeenCalledWith(0);
169
+ flashList.unmount();
170
+ });
171
+ it("should prefer overrideItemLayout over estimate and average", function () {
172
+ var flashList = (0, mountFlashList_1.mountFlashList)({
173
+ overrideItemLayout: function (layout) {
174
+ layout.size = 50;
175
+ },
176
+ });
177
+ expect(flashList.instance.state.layoutProvider.averageItemSize).toBe(200);
178
+ expect(flashList.instance.state
179
+ .layoutProvider.getLayoutManager()
180
+ .getLayouts()[0].height).toBe(50);
181
+ });
182
+ it("should override span with overrideItemLayout", function () {
183
+ var renderItemMock = jest.fn(function (_a) {
184
+ var item = _a.item;
185
+ return react_1.default.createElement(react_native_1.Text, null, item);
186
+ });
187
+ (0, mountFlashList_1.mountFlashList)({
188
+ overrideItemLayout: function (layout) {
189
+ layout.span = 2;
190
+ },
191
+ numColumns: 2,
192
+ estimatedItemSize: 300,
193
+ renderItem: renderItemMock,
194
+ });
195
+ expect(renderItemMock).toHaveBeenCalledTimes(3);
196
+ renderItemMock.mockClear();
197
+ (0, mountFlashList_1.mountFlashList)({
198
+ overrideItemLayout: function (layout, _, index) {
199
+ if (index > 2) {
200
+ layout.span = 2;
201
+ }
202
+ },
203
+ data: new Array(20).fill(""),
204
+ numColumns: 3,
205
+ estimatedItemSize: 100,
206
+ renderItem: renderItemMock,
207
+ });
208
+ expect(renderItemMock).toHaveBeenCalledTimes(11);
209
+ });
210
+ it("overrideItemLayout should consider 0 as a valid span", function () {
211
+ var renderItemMock = jest.fn(function (_a) {
212
+ var item = _a.item;
213
+ return react_1.default.createElement(react_native_1.Text, null, item);
214
+ });
215
+ (0, mountFlashList_1.mountFlashList)({
216
+ overrideItemLayout: function (layout, _, index) {
217
+ if (index < 4) {
218
+ layout.span = 0;
219
+ }
220
+ },
221
+ data: new Array(20).fill(""),
222
+ numColumns: 2,
223
+ renderItem: renderItemMock,
224
+ });
225
+ expect(renderItemMock).toHaveBeenCalledTimes(14);
226
+ });
227
+ it("reports onViewableItemsChanged for viewable items", function () {
228
+ var _a, _b, _c, _d;
229
+ var onViewableItemsChanged = jest.fn();
230
+ var onViewableItemsChangedForItemVisiblePercentThreshold = jest.fn();
231
+ var flashList = (0, mountFlashList_1.mountFlashList)({
232
+ estimatedItemSize: 300,
233
+ viewabilityConfig: {
234
+ minimumViewTime: 250,
235
+ },
236
+ viewabilityConfigCallbackPairs: [
237
+ {
238
+ onViewableItemsChanged: onViewableItemsChangedForItemVisiblePercentThreshold,
239
+ viewabilityConfig: {
240
+ itemVisiblePercentThreshold: 50,
241
+ waitForInteraction: true,
242
+ },
243
+ },
244
+ ],
245
+ onViewableItemsChanged: onViewableItemsChanged,
246
+ });
247
+ // onViewableItemsChanged is not called before 250 ms have elapsed
248
+ expect(onViewableItemsChanged).not.toHaveBeenCalled();
249
+ jest.advanceTimersByTime(250);
250
+ // Initial viewable items
251
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
252
+ changed: [
253
+ {
254
+ index: 0,
255
+ isViewable: true,
256
+ item: "One",
257
+ key: "0",
258
+ timestamp: expect.any(Number),
259
+ },
260
+ {
261
+ index: 1,
262
+ isViewable: true,
263
+ item: "Two",
264
+ key: "1",
265
+ timestamp: expect.any(Number),
266
+ },
267
+ {
268
+ index: 2,
269
+ isViewable: true,
270
+ item: "Three",
271
+ key: "2",
272
+ timestamp: expect.any(Number),
273
+ },
274
+ ],
275
+ viewableItems: [
276
+ {
277
+ index: 0,
278
+ isViewable: true,
279
+ item: "One",
280
+ key: "0",
281
+ timestamp: expect.any(Number),
282
+ },
283
+ {
284
+ index: 1,
285
+ isViewable: true,
286
+ item: "Two",
287
+ key: "1",
288
+ timestamp: expect.any(Number),
289
+ },
290
+ {
291
+ index: 2,
292
+ isViewable: true,
293
+ item: "Three",
294
+ key: "2",
295
+ timestamp: expect.any(Number),
296
+ },
297
+ ],
298
+ });
299
+ expect(onViewableItemsChangedForItemVisiblePercentThreshold).not.toHaveBeenCalled();
300
+ // onViewableItemsChangedForItemVisiblePercentThreshold waits for interaction before reporting viewable items
301
+ flashList.instance.recordInteraction();
302
+ jest.advanceTimersByTime(250);
303
+ expect(onViewableItemsChangedForItemVisiblePercentThreshold).toHaveBeenCalledWith({
304
+ changed: [
305
+ {
306
+ index: 0,
307
+ isViewable: true,
308
+ item: "One",
309
+ key: "0",
310
+ timestamp: expect.any(Number),
311
+ },
312
+ {
313
+ index: 1,
314
+ isViewable: true,
315
+ item: "Two",
316
+ key: "1",
317
+ timestamp: expect.any(Number),
318
+ },
319
+ {
320
+ index: 2,
321
+ isViewable: true,
322
+ item: "Three",
323
+ key: "2",
324
+ timestamp: expect.any(Number),
325
+ },
326
+ ],
327
+ viewableItems: [
328
+ {
329
+ index: 0,
330
+ isViewable: true,
331
+ item: "One",
332
+ key: "0",
333
+ timestamp: expect.any(Number),
334
+ },
335
+ {
336
+ index: 1,
337
+ isViewable: true,
338
+ item: "Two",
339
+ key: "1",
340
+ timestamp: expect.any(Number),
341
+ },
342
+ {
343
+ index: 2,
344
+ isViewable: true,
345
+ item: "Three",
346
+ key: "2",
347
+ timestamp: expect.any(Number),
348
+ },
349
+ ],
350
+ });
351
+ onViewableItemsChanged.mockReset();
352
+ onViewableItemsChangedForItemVisiblePercentThreshold.mockReset();
353
+ // Mocking a scroll that will make the first item not visible and the last item visible
354
+ jest
355
+ .spyOn(flashList.instance.recyclerlistview_unsafe, "getCurrentScrollOffset")
356
+ .mockReturnValue(200);
357
+ (_b = (_a = flashList.instance.recyclerlistview_unsafe.props).onVisibleIndicesChanged) === null || _b === void 0 ? void 0 : _b.call(_a, [0, 1, 2, 3], [], []);
358
+ (_d = (_c = flashList.instance.recyclerlistview_unsafe.props).onScroll) === null || _d === void 0 ? void 0 : _d.call(_c, { nativeEvent: { contentOffset: { x: 0, y: 200 } } }, 0, 200);
359
+ jest.advanceTimersByTime(250);
360
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
361
+ changed: [
362
+ {
363
+ index: 3,
364
+ isViewable: true,
365
+ item: "Four",
366
+ key: "3",
367
+ timestamp: expect.any(Number),
368
+ },
369
+ ],
370
+ viewableItems: [
371
+ {
372
+ index: 0,
373
+ isViewable: true,
374
+ item: "One",
375
+ key: "0",
376
+ timestamp: expect.any(Number),
377
+ },
378
+ {
379
+ index: 1,
380
+ isViewable: true,
381
+ item: "Two",
382
+ key: "1",
383
+ timestamp: expect.any(Number),
384
+ },
385
+ {
386
+ index: 2,
387
+ isViewable: true,
388
+ item: "Three",
389
+ key: "2",
390
+ timestamp: expect.any(Number),
391
+ },
392
+ {
393
+ index: 3,
394
+ isViewable: true,
395
+ item: "Four",
396
+ key: "3",
397
+ timestamp: expect.any(Number),
398
+ },
399
+ ],
400
+ });
401
+ expect(onViewableItemsChangedForItemVisiblePercentThreshold).toHaveBeenCalledWith({
402
+ changed: [
403
+ {
404
+ index: 3,
405
+ isViewable: true,
406
+ item: "Four",
407
+ key: "3",
408
+ timestamp: expect.any(Number),
409
+ },
410
+ {
411
+ index: 0,
412
+ isViewable: false,
413
+ item: "One",
414
+ key: "0",
415
+ timestamp: expect.any(Number),
416
+ },
417
+ ],
418
+ viewableItems: [
419
+ {
420
+ index: 1,
421
+ isViewable: true,
422
+ item: "Two",
423
+ key: "1",
424
+ timestamp: expect.any(Number),
425
+ },
426
+ {
427
+ index: 2,
428
+ isViewable: true,
429
+ item: "Three",
430
+ key: "2",
431
+ timestamp: expect.any(Number),
432
+ },
433
+ {
434
+ index: 3,
435
+ isViewable: true,
436
+ item: "Four",
437
+ key: "3",
438
+ timestamp: expect.any(Number),
439
+ },
440
+ ],
441
+ });
442
+ });
443
+ it("viewability reports take into account estimatedFirstItemOffset", function () {
444
+ var onViewableItemsChanged = jest.fn();
445
+ (0, mountFlashList_1.mountFlashList)({
446
+ estimatedFirstItemOffset: 200,
447
+ estimatedItemSize: 300,
448
+ onViewableItemsChanged: onViewableItemsChanged,
449
+ viewabilityConfig: { itemVisiblePercentThreshold: 50 },
450
+ });
451
+ // onViewableItemsChanged is not called before 250 ms have elapsed
452
+ expect(onViewableItemsChanged).not.toHaveBeenCalled();
453
+ jest.advanceTimersByTime(250);
454
+ // Initial viewable items
455
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
456
+ changed: [
457
+ {
458
+ index: 0,
459
+ isViewable: true,
460
+ item: "One",
461
+ key: "0",
462
+ timestamp: expect.any(Number),
463
+ },
464
+ {
465
+ index: 1,
466
+ isViewable: true,
467
+ item: "Two",
468
+ key: "1",
469
+ timestamp: expect.any(Number),
470
+ },
471
+ ],
472
+ viewableItems: [
473
+ {
474
+ index: 0,
475
+ isViewable: true,
476
+ item: "One",
477
+ key: "0",
478
+ timestamp: expect.any(Number),
479
+ },
480
+ {
481
+ index: 1,
482
+ isViewable: true,
483
+ item: "Two",
484
+ key: "1",
485
+ timestamp: expect.any(Number),
486
+ },
487
+ ],
488
+ });
489
+ });
490
+ it("retrigers viewability events when recomputeViewableItems is called", function () {
491
+ var onViewableItemsChanged = jest.fn();
492
+ var flashList = (0, mountFlashList_1.mountFlashList)({
493
+ estimatedItemSize: 300,
494
+ onViewableItemsChanged: onViewableItemsChanged,
495
+ viewabilityConfig: {
496
+ itemVisiblePercentThreshold: 50,
497
+ minimumViewTime: 0,
498
+ },
499
+ });
500
+ // Initial viewable items
501
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
502
+ changed: [
503
+ {
504
+ index: 0,
505
+ isViewable: true,
506
+ item: "One",
507
+ key: "0",
508
+ timestamp: expect.any(Number),
509
+ },
510
+ {
511
+ index: 1,
512
+ isViewable: true,
513
+ item: "Two",
514
+ key: "1",
515
+ timestamp: expect.any(Number),
516
+ },
517
+ {
518
+ index: 2,
519
+ isViewable: true,
520
+ item: "Three",
521
+ key: "2",
522
+ timestamp: expect.any(Number),
523
+ },
524
+ ],
525
+ viewableItems: [
526
+ {
527
+ index: 0,
528
+ isViewable: true,
529
+ item: "One",
530
+ key: "0",
531
+ timestamp: expect.any(Number),
532
+ },
533
+ {
534
+ index: 1,
535
+ isViewable: true,
536
+ item: "Two",
537
+ key: "1",
538
+ timestamp: expect.any(Number),
539
+ },
540
+ {
541
+ index: 2,
542
+ isViewable: true,
543
+ item: "Three",
544
+ key: "2",
545
+ timestamp: expect.any(Number),
546
+ },
547
+ ],
548
+ });
549
+ onViewableItemsChanged.mockClear();
550
+ flashList.instance.recomputeViewableItems();
551
+ expect(onViewableItemsChanged).toHaveBeenCalledWith({
552
+ changed: [
553
+ {
554
+ index: 0,
555
+ isViewable: true,
556
+ item: "One",
557
+ key: "0",
558
+ timestamp: expect.any(Number),
559
+ },
560
+ {
561
+ index: 1,
562
+ isViewable: true,
563
+ item: "Two",
564
+ key: "1",
565
+ timestamp: expect.any(Number),
566
+ },
567
+ {
568
+ index: 2,
569
+ isViewable: true,
570
+ item: "Three",
571
+ key: "2",
572
+ timestamp: expect.any(Number),
573
+ },
574
+ ],
575
+ viewableItems: [
576
+ {
577
+ index: 0,
578
+ isViewable: true,
579
+ item: "One",
580
+ key: "0",
581
+ timestamp: expect.any(Number),
582
+ },
583
+ {
584
+ index: 1,
585
+ isViewable: true,
586
+ item: "Two",
587
+ key: "1",
588
+ timestamp: expect.any(Number),
589
+ },
590
+ {
591
+ index: 2,
592
+ isViewable: true,
593
+ item: "Three",
594
+ key: "2",
595
+ timestamp: expect.any(Number),
596
+ },
597
+ ],
598
+ });
599
+ });
600
+ it("should not overlap header with sitcky index 0", function () {
601
+ var HeaderComponent = function () {
602
+ return react_1.default.createElement(react_native_1.Text, null, "Empty");
603
+ };
604
+ var flashList = (0, mountFlashList_1.mountFlashList)({
605
+ ListHeaderComponent: HeaderComponent,
606
+ stickyHeaderIndices: [0],
607
+ });
608
+ // If sticky renders there'll be 6
609
+ expect(flashList.findAll(react_native_1.Text).length).toBe(5);
610
+ });
611
+ it("rerenders all items when layout manager changes", function () {
612
+ var _a;
613
+ var countMounts = 0;
614
+ var currentId = 0;
615
+ // Effect will be triggered once per mount
616
+ var RenderComponent = function (_a) {
617
+ var id = _a.id;
618
+ (0, react_1.useEffect)(function () {
619
+ countMounts++;
620
+ }, [id]);
621
+ return react_1.default.createElement(react_native_1.Text, null, "Test");
622
+ };
623
+ var renderItem = function () {
624
+ return react_1.default.createElement(RenderComponent, { id: currentId });
625
+ };
626
+ var flashList = (0, mountFlashList_1.mountFlashList)({
627
+ data: new Array(100).fill("1"),
628
+ estimatedItemSize: 70,
629
+ renderItem: renderItem,
630
+ });
631
+ var scrollTo = function (y) {
632
+ var _a;
633
+ (_a = flashList.find(react_native_1.ScrollView)) === null || _a === void 0 ? void 0 : _a.trigger("onScroll", {
634
+ nativeEvent: { contentOffset: { x: 0, y: y } },
635
+ });
636
+ };
637
+ // Mocking some scrolls
638
+ scrollTo(200);
639
+ scrollTo(400);
640
+ scrollTo(600);
641
+ scrollTo(3000);
642
+ scrollTo(2000);
643
+ // changing id will trigger effects if components rerender
644
+ currentId = 1;
645
+ // capturing current component count to check later
646
+ var currentComponentCount = countMounts;
647
+ // resetting count
648
+ countMounts = 0;
649
+ // items widths before layout manager change should be 400
650
+ flashList.findAll(CellContainer_1.default).forEach(function (cell) {
651
+ if (cell.props.index !== -1) {
652
+ expect(cell.instance.props.style.width).toBe(400);
653
+ }
654
+ });
655
+ // This will cause a layout manager change
656
+ (_a = flashList.find(react_native_1.ScrollView)) === null || _a === void 0 ? void 0 : _a.trigger("onLayout", {
657
+ nativeEvent: { layout: { height: 400, width: 900 } },
658
+ });
659
+ // If counts match, then all components were updated
660
+ expect(countMounts).toBe(currentComponentCount);
661
+ // items widths after layout manager change should be 900
662
+ flashList.findAll(CellContainer_1.default).forEach(function (cell) {
663
+ if (cell.props.index !== -1) {
664
+ expect(cell.instance.props.style.width).toBe(900);
665
+ }
666
+ });
667
+ flashList.unmount();
668
+ });
669
+ it("sends a warning when estimatedItemSize is not set", function () {
670
+ var _a, _b, _c;
671
+ var warn = jest.spyOn(console, "warn").mockReturnValue();
672
+ var flashList = (0, mountFlashList_1.mountFlashList)({
673
+ disableDefaultEstimatedItemSize: true,
674
+ renderItem: function (_a) {
675
+ var item = _a.item;
676
+ return react_1.default.createElement(react_native_1.Text, { style: { height: 200 } }, item);
677
+ },
678
+ });
679
+ var layoutData = flashList.instance.state.layoutProvider
680
+ .getLayoutManager()
681
+ .getLayouts();
682
+ layoutData[0].height = 100;
683
+ layoutData[1].height = 200;
684
+ layoutData[2].height = 300;
685
+ (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance.onItemLayout(0);
686
+ expect(flashList.instance.state.layoutProvider.averageItemSize).toBe(100);
687
+ (_b = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _b === void 0 ? void 0 : _b.instance.onItemLayout(1);
688
+ (_c = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _c === void 0 ? void 0 : _c.instance.onItemLayout(2);
689
+ jest.advanceTimersByTime(1000);
690
+ var averageItemSize = flashList.instance.state.layoutProvider.averageItemSize;
691
+ expect(warn).toHaveBeenCalledWith(Warnings_1.default.estimatedItemSizeMissingWarning.replace("@size", averageItemSize.toString()));
692
+ expect(flashList.instance.state.layoutProvider.averageItemSize).toBe(175);
693
+ flashList.unmount();
694
+ });
695
+ it("clears size warning timeout on unmount", function () {
696
+ var _a;
697
+ var warn = jest.spyOn(console, "warn").mockReturnValue();
698
+ var flashList = (0, mountFlashList_1.mountFlashList)({
699
+ disableDefaultEstimatedItemSize: true,
700
+ });
701
+ (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance.onItemLayout(0);
702
+ flashList.unmount();
703
+ jest.advanceTimersByTime(1000);
704
+ expect(warn).toBeCalledTimes(0);
705
+ });
706
+ it("measure size of horizontal list when appropriate", function () {
707
+ var flashList = (0, mountFlashList_1.mountFlashList)({
708
+ data: new Array(1).fill("1"),
709
+ horizontal: true,
710
+ });
711
+ var forceUpdate = jest.spyOn(flashList.instance, "forceUpdate");
712
+ // should contain 1 actual text and 1 dummy on mount
713
+ expect(flashList.findAll(react_native_1.Text).length).toBe(2);
714
+ // Trigger onLoad
715
+ flashList.instance["onItemLayout"](0);
716
+ jest.advanceTimersByTime(600);
717
+ expect(forceUpdate).toBeCalledTimes(1);
718
+ // TODO: Investigate why forceUpdate isn't working in tests, forcing an update
719
+ flashList.setProps({ overrideItemLayout: function () { } });
720
+ // After update the dummy should get removed
721
+ expect(flashList.findAll(react_native_1.Text).length).toBe(1);
722
+ flashList.unmount();
723
+ flashList = (0, mountFlashList_1.mountFlashList)({
724
+ data: new Array(1).fill("1"),
725
+ horizontal: true,
726
+ disableHorizontalListHeightMeasurement: true,
727
+ });
728
+ // should contain 1 actual text as measurement is disabled
729
+ expect(flashList.findAll(react_native_1.Text).length).toBe(1);
730
+ flashList.unmount();
731
+ });
732
+ it("cancels post load setTimeout on unmount", function () {
733
+ var flashList = (0, mountFlashList_1.mountFlashList)({
734
+ data: new Array(1).fill("1"),
735
+ horizontal: true,
736
+ });
737
+ var forceUpdate = jest.spyOn(flashList.instance, "forceUpdate");
738
+ flashList.instance["onItemLayout"](0);
739
+ flashList.unmount();
740
+ jest.advanceTimersByTime(600);
741
+ expect(forceUpdate).toBeCalledTimes(0);
742
+ });
743
+ it("uses 250 as draw distance on Android/iOS", function () {
744
+ var _a, _b;
745
+ var flashList = (0, mountFlashList_1.mountFlashList)();
746
+ (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance.onItemLayout(0);
747
+ jest.advanceTimersByTime(1000);
748
+ expect((_b = flashList
749
+ .find(recyclerlistview_1.ProgressiveListView)) === null || _b === void 0 ? void 0 : _b.instance.getCurrentRenderAheadOffset()).toBe(250);
750
+ flashList.unmount();
751
+ });
752
+ it("forwards correct renderTarget", function () {
753
+ var _a, _b, _c, _d, _e;
754
+ var renderItem = function (_a) {
755
+ var target = _a.target;
756
+ return react_1.default.createElement(react_native_1.Text, null, target);
757
+ };
758
+ var flashList = (0, mountFlashList_1.mountFlashList)({
759
+ data: ["0"],
760
+ stickyHeaderIndices: [0],
761
+ renderItem: renderItem,
762
+ });
763
+ expect((_b = (_a = flashList.find(react_native_1.Animated.View)) === null || _a === void 0 ? void 0 : _a.find(react_native_1.Text)) === null || _b === void 0 ? void 0 : _b.props.children).toBe(FlashListProps_1.RenderTargetOptions.StickyHeader);
764
+ expect((_d = (_c = flashList.find(react_native_1.View)) === null || _c === void 0 ? void 0 : _c.find(react_native_1.Text)) === null || _d === void 0 ? void 0 : _d.props.children).toBe(FlashListProps_1.RenderTargetOptions.Cell);
765
+ var flashListHorizontal = (0, mountFlashList_1.mountFlashList)({
766
+ renderItem: renderItem,
767
+ horizontal: true,
768
+ });
769
+ expect((_e = flashListHorizontal
770
+ .findAllWhere(function (node) { var _a, _b; return ((_b = (_a = node === null || node === void 0 ? void 0 : node.props) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.opacity) === 0; })[0]
771
+ .find(react_native_1.Text)) === null || _e === void 0 ? void 0 : _e.props.children).toBe("Measurement");
772
+ });
773
+ it("force updates items only when renderItem change", function () {
774
+ var renderItem = jest.fn(function () { return react_1.default.createElement(react_native_1.Text, null, "Test"); });
775
+ var flashList = (0, mountFlashList_1.mountFlashList)({
776
+ data: new Array(1).fill("1"),
777
+ renderItem: renderItem,
778
+ });
779
+ flashList.setProps({ data: new Array(1).fill("1") });
780
+ expect(renderItem).toBeCalledTimes(1);
781
+ var newRenderItem = jest.fn(function () { return react_1.default.createElement(react_native_1.Text, null, "Test"); });
782
+ flashList.setProps({
783
+ data: new Array(1).fill("1"),
784
+ renderItem: newRenderItem,
785
+ });
786
+ expect(newRenderItem).toBeCalledTimes(1);
787
+ });
788
+ it("forwards disableAutoLayout prop correctly", function () {
789
+ var _a, _b;
790
+ var flashList = (0, mountFlashList_1.mountFlashList)();
791
+ expect((_a = flashList.find(AutoLayoutView_1.default)) === null || _a === void 0 ? void 0 : _a.props.disableAutoLayout).toBe(undefined);
792
+ flashList.setProps({ disableAutoLayout: true });
793
+ expect((_b = flashList.find(AutoLayoutView_1.default)) === null || _b === void 0 ? void 0 : _b.props.disableAutoLayout).toBe(true);
794
+ });
795
+ it("computes correct scrollTo offset when view position is specified", function () {
796
+ var _a;
797
+ var flashList = (0, mountFlashList_1.mountFlashList)({
798
+ data: new Array(40).fill(1).map(function (_, index) {
799
+ return index.toString();
800
+ }),
801
+ });
802
+ var plv = (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance;
803
+ var scrollToOffset = jest.spyOn(plv, "scrollToOffset");
804
+ flashList.instance.scrollToIndex({ index: 10, viewPosition: 0.5 });
805
+ // Each item is 200px in height and to position it in the middle of the window (900 x 400), its offset needs to be
806
+ // reduced by 350px. That gives us 1650. Other test cases follow the same logic.
807
+ expect(scrollToOffset).toBeCalledWith(1650, 1650, false, true);
808
+ flashList.instance.scrollToItem({
809
+ item: "10",
810
+ viewPosition: 0.5,
811
+ });
812
+ expect(scrollToOffset).toBeCalledWith(1650, 1650, false, true);
813
+ flashList.setProps({ horizontal: true });
814
+ flashList.instance.scrollToItem({
815
+ item: "10",
816
+ viewPosition: 0.5,
817
+ });
818
+ expect(scrollToOffset).toBeCalledWith(1900, 1900, false, true);
819
+ flashList.unmount();
820
+ });
821
+ it("computes correct scrollTo offset when view offset is specified", function () {
822
+ var _a;
823
+ var flashList = (0, mountFlashList_1.mountFlashList)({
824
+ data: new Array(40).fill(1).map(function (_, index) {
825
+ return index.toString();
826
+ }),
827
+ });
828
+ var plv = (_a = flashList.find(recyclerlistview_1.ProgressiveListView)) === null || _a === void 0 ? void 0 : _a.instance;
829
+ var scrollToOffset = jest.spyOn(plv, "scrollToOffset");
830
+ // Each item is 200px in height and to position it in the middle of the window (900 x 400), it's offset needs to be
831
+ // reduced by 350px + 100px offset. That gives us 1550. Other test cases follow the same logic.
832
+ flashList.instance.scrollToIndex({
833
+ index: 10,
834
+ viewPosition: 0.5,
835
+ viewOffset: 100,
836
+ });
837
+ expect(scrollToOffset).toBeCalledWith(1550, 1550, false, true);
838
+ flashList.setProps({ horizontal: true });
839
+ flashList.instance.scrollToItem({
840
+ item: "10",
841
+ viewPosition: 0.5,
842
+ viewOffset: 100,
843
+ });
844
+ expect(scrollToOffset).toBeCalledWith(1800, 1800, false, true);
845
+ flashList.unmount();
846
+ });
847
+ it("applies horizontal content container padding for vertical list", function () {
848
+ var flashList = (0, mountFlashList_1.mountFlashList)({
849
+ numColumns: 4,
850
+ contentContainerStyle: { paddingHorizontal: 10 },
851
+ });
852
+ var hasLayoutItems = false;
853
+ flashList.instance.state.layoutProvider
854
+ .getLayoutManager()
855
+ .getLayouts()
856
+ .forEach(function (layout) {
857
+ hasLayoutItems = true;
858
+ expect(layout.width).toBe(95);
859
+ });
860
+ expect(hasLayoutItems).toBe(true);
861
+ flashList.unmount();
862
+ });
863
+ it("applies vertical content container padding for horizontal list", function () {
864
+ var flashList = (0, mountFlashList_1.mountFlashList)({
865
+ horizontal: true,
866
+ contentContainerStyle: { paddingVertical: 10 },
867
+ });
868
+ var hasLayoutItems = false;
869
+ flashList.instance.state.layoutProvider
870
+ .getLayoutManager()
871
+ .getLayouts()
872
+ .forEach(function (layout) {
873
+ hasLayoutItems = true;
874
+ expect(layout.height).toBe(880);
875
+ });
876
+ expect(hasLayoutItems).toBe(true);
877
+ flashList.unmount();
878
+ });
879
+ it("warns if rendered size is too small but only when it remain small for a duration", function () {
880
+ var flashList = (0, mountFlashList_1.mountFlashList)({
881
+ data: new Array(1).fill("1"),
882
+ });
883
+ var warn = jest.spyOn(console, "warn").mockReturnValue();
884
+ var triggerLayout = function (height, time) {
885
+ var _a;
886
+ (_a = flashList.find(react_native_1.ScrollView)) === null || _a === void 0 ? void 0 : _a.trigger("onLayout", {
887
+ nativeEvent: { layout: { height: height, width: 900 } },
888
+ });
889
+ jest.advanceTimersByTime(time);
890
+ };
891
+ triggerLayout(0, 500);
892
+ triggerLayout(100, 1000);
893
+ triggerLayout(0, 1200);
894
+ expect(warn).toHaveBeenCalledTimes(1);
895
+ triggerLayout(100, 500);
896
+ triggerLayout(0, 500);
897
+ flashList.unmount();
898
+ jest.advanceTimersByTime(1200);
899
+ expect(warn).toHaveBeenCalledTimes(1);
900
+ });
901
+ });
902
+ //# sourceMappingURL=FlashList.test.js.map