@shopify/flash-list 2.0.4-alpha.1 → 2.2.0

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 (203) hide show
  1. package/dist/AnimatedFlashList.js +4 -6
  2. package/dist/AnimatedFlashList.js.map +1 -1
  3. package/dist/FlashList.js +1 -5
  4. package/dist/FlashList.js.map +1 -1
  5. package/dist/FlashListProps.d.ts +41 -1
  6. package/dist/FlashListProps.d.ts.map +1 -1
  7. package/dist/FlashListProps.js +1 -4
  8. package/dist/FlashListProps.js.map +1 -1
  9. package/dist/FlashListRef.js +1 -2
  10. package/dist/benchmark/AutoScrollHelper.js +22 -30
  11. package/dist/benchmark/AutoScrollHelper.js.map +1 -1
  12. package/dist/benchmark/JSFPSMonitor.js +27 -33
  13. package/dist/benchmark/JSFPSMonitor.js.map +1 -1
  14. package/dist/benchmark/roundToDecimalPlaces.js +2 -5
  15. package/dist/benchmark/roundToDecimalPlaces.js.map +1 -1
  16. package/dist/benchmark/useBenchmark.d.ts +9 -1
  17. package/dist/benchmark/useBenchmark.d.ts.map +1 -1
  18. package/dist/benchmark/useBenchmark.js +86 -95
  19. package/dist/benchmark/useBenchmark.js.map +1 -1
  20. package/dist/benchmark/useDataMultiplier.js +6 -10
  21. package/dist/benchmark/useDataMultiplier.js.map +1 -1
  22. package/dist/benchmark/useFlatListBenchmark.d.ts +4 -1
  23. package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
  24. package/dist/benchmark/useFlatListBenchmark.js +73 -81
  25. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  26. package/dist/errors/ErrorMessages.js +1 -4
  27. package/dist/errors/ErrorMessages.js.map +1 -1
  28. package/dist/errors/WarningMessages.js +1 -4
  29. package/dist/errors/WarningMessages.js.map +1 -1
  30. package/dist/index.js +17 -35
  31. package/dist/index.js.map +1 -1
  32. package/dist/isNewArch.js +6 -9
  33. package/dist/isNewArch.js.map +1 -1
  34. package/dist/native/config/PlatformHelper.android.js +2 -5
  35. package/dist/native/config/PlatformHelper.android.js.map +1 -1
  36. package/dist/native/config/PlatformHelper.ios.js +2 -5
  37. package/dist/native/config/PlatformHelper.ios.js.map +1 -1
  38. package/dist/native/config/PlatformHelper.js +2 -5
  39. package/dist/native/config/PlatformHelper.js.map +1 -1
  40. package/dist/native/config/PlatformHelper.web.js +2 -5
  41. package/dist/native/config/PlatformHelper.web.js.map +1 -1
  42. package/dist/recyclerview/LayoutCommitObserver.js +20 -24
  43. package/dist/recyclerview/LayoutCommitObserver.js.map +1 -1
  44. package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
  45. package/dist/recyclerview/RecyclerView.js +134 -111
  46. package/dist/recyclerview/RecyclerView.js.map +1 -1
  47. package/dist/recyclerview/RecyclerViewContextProvider.js +7 -12
  48. package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
  49. package/dist/recyclerview/RecyclerViewManager.js +138 -167
  50. package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
  51. package/dist/recyclerview/RecyclerViewProps.js +1 -2
  52. package/dist/recyclerview/RenderStackManager.js +97 -188
  53. package/dist/recyclerview/RenderStackManager.js.map +1 -1
  54. package/dist/recyclerview/ViewHolder.d.ts +2 -0
  55. package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
  56. package/dist/recyclerview/ViewHolder.js +19 -21
  57. package/dist/recyclerview/ViewHolder.js.map +1 -1
  58. package/dist/recyclerview/ViewHolderCollection.d.ts +4 -0
  59. package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
  60. package/dist/recyclerview/ViewHolderCollection.js +26 -30
  61. package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
  62. package/dist/recyclerview/components/CompatScroller.js +6 -7
  63. package/dist/recyclerview/components/CompatScroller.js.map +1 -1
  64. package/dist/recyclerview/components/CompatView.js +6 -7
  65. package/dist/recyclerview/components/CompatView.js.map +1 -1
  66. package/dist/recyclerview/components/ScrollAnchor.js +10 -15
  67. package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
  68. package/dist/recyclerview/components/StickyHeaders.d.ts +5 -1
  69. package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
  70. package/dist/recyclerview/components/StickyHeaders.js +77 -51
  71. package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
  72. package/dist/recyclerview/helpers/ConsecutiveNumbers.js +39 -66
  73. package/dist/recyclerview/helpers/ConsecutiveNumbers.js.map +1 -1
  74. package/dist/recyclerview/helpers/EngagedIndicesTracker.js +57 -63
  75. package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
  76. package/dist/recyclerview/helpers/RenderTimeTracker.js +19 -24
  77. package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
  78. package/dist/recyclerview/helpers/VelocityTracker.js +16 -22
  79. package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -1
  80. package/dist/recyclerview/hooks/useBoundDetection.js +37 -40
  81. package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
  82. package/dist/recyclerview/hooks/useLayoutState.js +9 -15
  83. package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
  84. package/dist/recyclerview/hooks/useMappingHelper.js +6 -10
  85. package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
  86. package/dist/recyclerview/hooks/useOnLoad.js +16 -22
  87. package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
  88. package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
  89. package/dist/recyclerview/hooks/useRecyclerViewController.js +169 -188
  90. package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
  91. package/dist/recyclerview/hooks/useRecyclerViewManager.js +12 -17
  92. package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
  93. package/dist/recyclerview/hooks/useRecyclingState.js +10 -14
  94. package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
  95. package/dist/recyclerview/hooks/useSecondaryProps.d.ts +2 -0
  96. package/dist/recyclerview/hooks/useSecondaryProps.d.ts.map +1 -1
  97. package/dist/recyclerview/hooks/useSecondaryProps.js +39 -30
  98. package/dist/recyclerview/hooks/useSecondaryProps.js.map +1 -1
  99. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +17 -22
  100. package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
  101. package/dist/recyclerview/hooks/useUnmountFlag.js +5 -9
  102. package/dist/recyclerview/hooks/useUnmountFlag.js.map +1 -1
  103. package/dist/recyclerview/layout-managers/GridLayoutManager.js +61 -80
  104. package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
  105. package/dist/recyclerview/layout-managers/LayoutManager.js +83 -123
  106. package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
  107. package/dist/recyclerview/layout-managers/LinearLayoutManager.js +51 -91
  108. package/dist/recyclerview/layout-managers/LinearLayoutManager.js.map +1 -1
  109. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +77 -96
  110. package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
  111. package/dist/recyclerview/utils/adjustOffsetForRTL.js +1 -4
  112. package/dist/recyclerview/utils/adjustOffsetForRTL.js.map +1 -1
  113. package/dist/recyclerview/utils/componentUtils.js +4 -9
  114. package/dist/recyclerview/utils/componentUtils.js.map +1 -1
  115. package/dist/recyclerview/utils/findVisibleIndex.js +9 -13
  116. package/dist/recyclerview/utils/findVisibleIndex.js.map +1 -1
  117. package/dist/recyclerview/utils/measureLayout.js +12 -20
  118. package/dist/recyclerview/utils/measureLayout.js.map +1 -1
  119. package/dist/recyclerview/utils/measureLayout.web.js +15 -23
  120. package/dist/recyclerview/utils/measureLayout.web.js.map +1 -1
  121. package/dist/recyclerview/viewability/ViewToken.js +1 -2
  122. package/dist/recyclerview/viewability/ViewabilityHelper.js +34 -41
  123. package/dist/recyclerview/viewability/ViewabilityHelper.js.map +1 -1
  124. package/dist/recyclerview/viewability/ViewabilityManager.js +48 -61
  125. package/dist/recyclerview/viewability/ViewabilityManager.js.map +1 -1
  126. package/dist/tsconfig.tsbuildinfo +1 -1
  127. package/dist/utils/AverageWindow.js +28 -39
  128. package/dist/utils/AverageWindow.js.map +1 -1
  129. package/package.json +4 -6
  130. package/src/FlashListProps.ts +51 -1
  131. package/src/benchmark/useBenchmark.ts +47 -4
  132. package/src/benchmark/useFlatListBenchmark.ts +38 -5
  133. package/src/recyclerview/RecyclerView.tsx +42 -8
  134. package/src/recyclerview/ViewHolder.tsx +6 -1
  135. package/src/recyclerview/ViewHolderCollection.tsx +10 -0
  136. package/src/recyclerview/components/StickyHeaders.tsx +54 -13
  137. package/src/recyclerview/hooks/useRecyclerViewController.tsx +7 -4
  138. package/src/recyclerview/hooks/useSecondaryProps.tsx +23 -0
  139. package/dist/__tests__/AverageWindow.test.d.ts +0 -2
  140. package/dist/__tests__/AverageWindow.test.d.ts.map +0 -1
  141. package/dist/__tests__/AverageWindow.test.js +0 -104
  142. package/dist/__tests__/AverageWindow.test.js.map +0 -1
  143. package/dist/__tests__/ConsecutiveNumbers.test.d.ts +0 -2
  144. package/dist/__tests__/ConsecutiveNumbers.test.d.ts.map +0 -1
  145. package/dist/__tests__/ConsecutiveNumbers.test.js +0 -224
  146. package/dist/__tests__/ConsecutiveNumbers.test.js.map +0 -1
  147. package/dist/__tests__/GridLayoutManager.test.d.ts +0 -2
  148. package/dist/__tests__/GridLayoutManager.test.d.ts.map +0 -1
  149. package/dist/__tests__/GridLayoutManager.test.js +0 -69
  150. package/dist/__tests__/GridLayoutManager.test.js.map +0 -1
  151. package/dist/__tests__/LayoutCommitObserver.test.d.ts +0 -2
  152. package/dist/__tests__/LayoutCommitObserver.test.d.ts.map +0 -1
  153. package/dist/__tests__/LayoutCommitObserver.test.js +0 -37
  154. package/dist/__tests__/LayoutCommitObserver.test.js.map +0 -1
  155. package/dist/__tests__/LinearLayoutManager.test.d.ts +0 -2
  156. package/dist/__tests__/LinearLayoutManager.test.d.ts.map +0 -1
  157. package/dist/__tests__/LinearLayoutManager.test.js +0 -140
  158. package/dist/__tests__/LinearLayoutManager.test.js.map +0 -1
  159. package/dist/__tests__/MasonryLayoutManager.test.d.ts +0 -2
  160. package/dist/__tests__/MasonryLayoutManager.test.d.ts.map +0 -1
  161. package/dist/__tests__/MasonryLayoutManager.test.js +0 -148
  162. package/dist/__tests__/MasonryLayoutManager.test.js.map +0 -1
  163. package/dist/__tests__/RecyclerView.test.d.ts +0 -2
  164. package/dist/__tests__/RecyclerView.test.d.ts.map +0 -1
  165. package/dist/__tests__/RecyclerView.test.js +0 -103
  166. package/dist/__tests__/RecyclerView.test.js.map +0 -1
  167. package/dist/__tests__/RecyclerViewManager.test.d.ts +0 -2
  168. package/dist/__tests__/RecyclerViewManager.test.d.ts.map +0 -1
  169. package/dist/__tests__/RecyclerViewManager.test.js +0 -56
  170. package/dist/__tests__/RecyclerViewManager.test.js.map +0 -1
  171. package/dist/__tests__/RenderStackManager.test.d.ts +0 -2
  172. package/dist/__tests__/RenderStackManager.test.d.ts.map +0 -1
  173. package/dist/__tests__/RenderStackManager.test.js +0 -485
  174. package/dist/__tests__/RenderStackManager.test.js.map +0 -1
  175. package/dist/__tests__/ViewabilityHelper.test.d.ts +0 -2
  176. package/dist/__tests__/ViewabilityHelper.test.d.ts.map +0 -1
  177. package/dist/__tests__/ViewabilityHelper.test.js +0 -186
  178. package/dist/__tests__/ViewabilityHelper.test.js.map +0 -1
  179. package/dist/__tests__/findVisibleIndex.test.d.ts +0 -2
  180. package/dist/__tests__/findVisibleIndex.test.d.ts.map +0 -1
  181. package/dist/__tests__/findVisibleIndex.test.js +0 -259
  182. package/dist/__tests__/findVisibleIndex.test.js.map +0 -1
  183. package/dist/__tests__/helpers/createLayoutManager.d.ts +0 -34
  184. package/dist/__tests__/helpers/createLayoutManager.d.ts.map +0 -1
  185. package/dist/__tests__/helpers/createLayoutManager.js +0 -110
  186. package/dist/__tests__/helpers/createLayoutManager.js.map +0 -1
  187. package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts +0 -2
  188. package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts.map +0 -1
  189. package/dist/__tests__/useUnmountAwareCallbacks.test.js +0 -185
  190. package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +0 -1
  191. package/src/__tests__/AverageWindow.test.ts +0 -128
  192. package/src/__tests__/ConsecutiveNumbers.test.ts +0 -232
  193. package/src/__tests__/GridLayoutManager.test.ts +0 -113
  194. package/src/__tests__/LayoutCommitObserver.test.tsx +0 -63
  195. package/src/__tests__/LinearLayoutManager.test.ts +0 -227
  196. package/src/__tests__/MasonryLayoutManager.test.ts +0 -202
  197. package/src/__tests__/RecyclerView.test.tsx +0 -144
  198. package/src/__tests__/RecyclerViewManager.test.ts +0 -74
  199. package/src/__tests__/RenderStackManager.test.ts +0 -574
  200. package/src/__tests__/ViewabilityHelper.test.ts +0 -282
  201. package/src/__tests__/findVisibleIndex.test.ts +0 -369
  202. package/src/__tests__/helpers/createLayoutManager.ts +0 -141
  203. package/src/__tests__/useUnmountAwareCallbacks.test.tsx +0 -285
@@ -1,113 +0,0 @@
1
- import {
2
- createPopulatedLayoutManager,
3
- getAllLayouts,
4
- LayoutManagerType,
5
- createLayoutParams,
6
- } from "./helpers/createLayoutManager";
7
-
8
- describe("GridLayoutManager", () => {
9
- const windowSize = { width: 400, height: 900 };
10
- const defaultParams = { windowSize, maxColumns: 2 };
11
-
12
- describe("Basic grid layout", () => {
13
- it("should arrange items in rows with equal widths", () => {
14
- const manager = createPopulatedLayoutManager(
15
- LayoutManagerType.GRID,
16
- 4,
17
- defaultParams
18
- );
19
- const layouts = getAllLayouts(manager);
20
-
21
- expect(layouts[0].x).toBe(0);
22
- expect(layouts[0].width).toBe(200);
23
- expect(layouts[1].x).toBe(200);
24
-
25
- expect(layouts[2].y).toBe(layouts[0].height);
26
- expect(layouts[3].x).toBe(200);
27
- });
28
-
29
- it("should respect maxColumns configuration", () => {
30
- const manager = createPopulatedLayoutManager(LayoutManagerType.GRID, 6, {
31
- ...defaultParams,
32
- maxColumns: 3,
33
- });
34
- const layouts = getAllLayouts(manager);
35
-
36
- expect(layouts[0].width).toBeCloseTo(400 / 3);
37
- expect(layouts[3].x).toBe(0);
38
- expect(layouts[3].y).toBe(layouts[0].height);
39
- });
40
- });
41
-
42
- describe("Multi-column items", () => {
43
- it("should handle items spanning multiple columns", () => {
44
- const manager = createPopulatedLayoutManager(LayoutManagerType.GRID, 3, {
45
- ...defaultParams,
46
- maxColumns: 3,
47
- overrideItemLayout: (index, layout) => {
48
- layout.span = index === 0 ? 2 : undefined;
49
- },
50
- });
51
- const layouts = getAllLayouts(manager);
52
-
53
- // First item spans 2 columns
54
- expect(layouts[0].width).toBeCloseTo((400 / 3) * 2);
55
- // Next item starts in third column
56
- expect(layouts[1].x).toBeCloseTo((400 / 3) * 2);
57
- });
58
-
59
- it("should wrap items that exceed column count", () => {
60
- const manager = createPopulatedLayoutManager(LayoutManagerType.GRID, 4, {
61
- ...defaultParams,
62
- overrideItemLayout: (index, layout) => {
63
- layout.span = index % 2 === 0 ? 2 : 1;
64
- },
65
- });
66
- const layouts = getAllLayouts(manager);
67
-
68
- // Row 1: 2 columns (span 2 + span 2 would exceed 2 columns)
69
- expect(layouts[0].width).toBe(400);
70
- expect(layouts[1].x).toBe(0);
71
- expect(layouts[1].y).toBe(layouts[0].height);
72
- expect(layouts[2].x).toBe(0);
73
- expect(layouts[2].y).toBe(layouts[1].height + layouts[0].height);
74
- });
75
- });
76
-
77
- describe("Layout recalculations", () => {
78
- it("should adjust layout when window size changes", () => {
79
- const manager = createPopulatedLayoutManager(
80
- LayoutManagerType.GRID,
81
- 4,
82
- defaultParams
83
- );
84
-
85
- // Update window size
86
- manager.updateLayoutParams(
87
- createLayoutParams({
88
- ...defaultParams,
89
- windowSize: { width: 600, height: 900 },
90
- })
91
- );
92
-
93
- const updatedWidth = getAllLayouts(manager)[0].width;
94
- expect(updatedWidth).toBe(300); // 600 / 2 columns
95
- });
96
-
97
- it("should maintain positions when adding new items", () => {
98
- const manager = createPopulatedLayoutManager(
99
- LayoutManagerType.GRID,
100
- 2,
101
- defaultParams
102
- );
103
- const initialLayouts = getAllLayouts(manager);
104
-
105
- // Add two more items
106
- manager.modifyLayout([], 4);
107
-
108
- const updatedLayouts = getAllLayouts(manager);
109
- expect(updatedLayouts[0]).toEqual(initialLayouts[0]);
110
- expect(updatedLayouts[3].y).toBe(initialLayouts[0].height);
111
- });
112
- });
113
- });
@@ -1,63 +0,0 @@
1
- import React from "react";
2
- import { render } from "@quilted/react-testing";
3
-
4
- import { useFlashListContext } from "../recyclerview/RecyclerViewContextProvider";
5
- import { LayoutCommitObserver } from "../recyclerview/LayoutCommitObserver";
6
- import { FlashList } from "..";
7
-
8
- describe("LayoutCommitObserver", () => {
9
- it("should not alter ref captured by child", () => {
10
- const ChildComponent = () => {
11
- const context = useFlashListContext();
12
- expect(context?.getRef()?.props.testID).toBe("child");
13
- expect(context?.getParentRef()?.props.testID).toBe("parent");
14
- expect(context?.getScrollViewRef()?.props.testID).toBe("child");
15
- expect(context?.getParentScrollViewRef()?.props.testID).toBe("parent");
16
-
17
- return null;
18
- };
19
-
20
- let commitLayoutEffectCount = 0;
21
-
22
- const content = (
23
- <FlashList
24
- testID="parent"
25
- data={[1]}
26
- renderItem={() => (
27
- <LayoutCommitObserver
28
- onCommitLayoutEffect={() => {
29
- commitLayoutEffectCount++;
30
- }}
31
- >
32
- <FlashList
33
- testID="child"
34
- data={[1]}
35
- renderItem={() => (
36
- <LayoutCommitObserver
37
- onCommitLayoutEffect={() => {
38
- commitLayoutEffectCount++;
39
- }}
40
- >
41
- <LayoutCommitObserver
42
- onCommitLayoutEffect={() => {
43
- commitLayoutEffectCount++;
44
- }}
45
- >
46
- <ChildComponent />
47
- </LayoutCommitObserver>
48
- </LayoutCommitObserver>
49
- )}
50
- />
51
- </LayoutCommitObserver>
52
- )}
53
- />
54
- );
55
-
56
- const renderResult = render(content);
57
-
58
- expect(commitLayoutEffectCount).toBe(3);
59
-
60
- // Force unmount to trigger cleanup of async operations
61
- renderResult.unmount();
62
- });
63
- });
@@ -1,227 +0,0 @@
1
- import {
2
- createPopulatedLayoutManager,
3
- getAllLayouts,
4
- LayoutManagerType,
5
- createLayoutParams,
6
- createLayoutManager,
7
- createMockLayoutInfo,
8
- } from "./helpers/createLayoutManager";
9
-
10
- describe("LinearLayoutManager", () => {
11
- const windowSize = { width: 400, height: 900 };
12
- const defaultParams = { windowSize, horizontal: false };
13
- const horizontalParams = { windowSize, horizontal: true };
14
-
15
- describe("Vertical layout", () => {
16
- it("should stack items vertically", () => {
17
- const manager = createPopulatedLayoutManager(
18
- LayoutManagerType.LINEAR,
19
- 3,
20
- defaultParams,
21
- 100, // itemWidth
22
- 100 // itemHeight
23
- );
24
- const layouts = getAllLayouts(manager);
25
-
26
- expect(layouts.length).toBe(3);
27
- expect(layouts[0].y).toBe(0);
28
- expect(layouts[1].y).toBe(100);
29
- expect(layouts[2].y).toBe(200);
30
- expect(layouts[0].x).toBe(0);
31
- expect(layouts[0].width).toBe(400); // Should take full width
32
- });
33
-
34
- it("should handle variable item heights", () => {
35
- const manager = createLayoutManager(
36
- LayoutManagerType.LINEAR,
37
- defaultParams
38
- );
39
- const layoutInfos = [
40
- createMockLayoutInfo(0, 400, 100),
41
- createMockLayoutInfo(1, 400, 150),
42
- createMockLayoutInfo(2, 400, 50),
43
- ];
44
- manager.modifyLayout(layoutInfos, 3);
45
- const layouts = getAllLayouts(manager);
46
-
47
- expect(layouts[0].height).toBe(100);
48
- expect(layouts[1].height).toBe(150);
49
- expect(layouts[2].height).toBe(50);
50
-
51
- expect(layouts[0].y).toBe(0);
52
- expect(layouts[1].y).toBe(100); // 0 + 100
53
- expect(layouts[2].y).toBe(250); // 100 + 150
54
- });
55
-
56
- it("should calculate total layout size correctly", () => {
57
- const manager = createPopulatedLayoutManager(
58
- LayoutManagerType.LINEAR,
59
- 3,
60
- defaultParams,
61
- 100,
62
- 100
63
- );
64
- const layoutSize = manager.getLayoutSize();
65
- expect(layoutSize.width).toBe(400);
66
- expect(layoutSize.height).toBe(300); // 3 items * 100 height
67
- });
68
- });
69
-
70
- describe("Horizontal layout", () => {
71
- it("should stack items horizontally", () => {
72
- const manager = createPopulatedLayoutManager(
73
- LayoutManagerType.LINEAR,
74
- 3,
75
- horizontalParams,
76
- 100, // itemWidth
77
- 100 // itemHeight - should take full height
78
- );
79
- const layouts = getAllLayouts(manager);
80
-
81
- expect(layouts.length).toBe(3);
82
- expect(layouts[0].x).toBe(0);
83
- expect(layouts[1].x).toBe(100);
84
- expect(layouts[2].x).toBe(200);
85
- expect(layouts[0].y).toBe(0);
86
- expect(layouts[0].minHeight).toBe(900); // Should take full height
87
- });
88
-
89
- it("should handle variable item widths", () => {
90
- const manager = createLayoutManager(
91
- LayoutManagerType.LINEAR,
92
- horizontalParams
93
- );
94
- const layoutInfos = [
95
- createMockLayoutInfo(0, 100, 900),
96
- createMockLayoutInfo(1, 150, 900),
97
- createMockLayoutInfo(2, 50, 900),
98
- ];
99
- manager.modifyLayout(layoutInfos, 3);
100
- const layouts = getAllLayouts(manager);
101
-
102
- expect(layouts[0].width).toBe(100);
103
- expect(layouts[1].width).toBe(150);
104
- expect(layouts[2].width).toBe(50);
105
-
106
- expect(layouts[0].x).toBe(0);
107
- expect(layouts[1].x).toBe(100); // 0 + 100
108
- expect(layouts[2].x).toBe(250); // 100 + 150
109
- });
110
-
111
- it("should calculate total layout size correctly in horizontal mode", () => {
112
- const manager = createPopulatedLayoutManager(
113
- LayoutManagerType.LINEAR,
114
- 3,
115
- horizontalParams,
116
- 100,
117
- 100
118
- );
119
- const layoutSize = manager.getLayoutSize();
120
- expect(layoutSize.width).toBe(300); // 3 items * 100 width
121
- expect(layoutSize.height).toBe(900);
122
- });
123
- });
124
-
125
- describe("Layout modifications", () => {
126
- it("should update layout when items are added", () => {
127
- const manager = createPopulatedLayoutManager(
128
- LayoutManagerType.LINEAR,
129
- 2,
130
- defaultParams,
131
- 100,
132
- 100
133
- );
134
- const initialLayouts = getAllLayouts(manager);
135
- expect(initialLayouts.length).toBe(2);
136
-
137
- // Add one more item
138
- const newLayoutInfo = [createMockLayoutInfo(2, 400, 120)];
139
- manager.modifyLayout(newLayoutInfo, 3);
140
-
141
- const updatedLayouts = getAllLayouts(manager);
142
- expect(updatedLayouts.length).toBe(3);
143
- expect(updatedLayouts[2].y).toBe(200); // 100 + 100
144
- expect(updatedLayouts[2].height).toBe(120);
145
- expect(manager.getLayoutSize().height).toBe(320); // 100 + 100 + 120
146
- });
147
-
148
- it("should update layout when items are removed", () => {
149
- const manager = createPopulatedLayoutManager(
150
- LayoutManagerType.LINEAR,
151
- 3,
152
- defaultParams,
153
- 100,
154
- 100
155
- );
156
- expect(getAllLayouts(manager).length).toBe(3);
157
- expect(manager.getLayoutSize().height).toBe(300);
158
-
159
- // Remove the last item
160
- manager.modifyLayout([], 2);
161
-
162
- const updatedLayouts = getAllLayouts(manager);
163
- expect(updatedLayouts.length).toBe(2);
164
- expect(manager.getLayoutSize().height).toBe(200);
165
- });
166
-
167
- it("should handle replacing all items", () => {
168
- const manager = createPopulatedLayoutManager(
169
- LayoutManagerType.LINEAR,
170
- 3,
171
- defaultParams,
172
- 100,
173
- 100
174
- );
175
-
176
- const newLayoutInfos = [
177
- createMockLayoutInfo(0, 400, 50),
178
- createMockLayoutInfo(1, 400, 60),
179
- ];
180
- manager.modifyLayout(newLayoutInfos, 2);
181
-
182
- const layouts = getAllLayouts(manager);
183
- expect(layouts.length).toBe(2);
184
- expect(layouts[0].height).toBe(50);
185
- expect(layouts[1].height).toBe(60);
186
- expect(layouts[1].y).toBe(50);
187
- expect(manager.getLayoutSize().height).toBe(110); // 50 + 60
188
- });
189
-
190
- it("should recalculate layout when window size changes", () => {
191
- const manager = createPopulatedLayoutManager(
192
- LayoutManagerType.LINEAR,
193
- 3,
194
- defaultParams,
195
- 100,
196
- 100
197
- );
198
- const initialLayouts = getAllLayouts(manager);
199
- expect(initialLayouts[0].width).toBe(400);
200
-
201
- manager.updateLayoutParams(
202
- createLayoutParams({
203
- ...defaultParams,
204
- windowSize: { width: 600, height: 900 },
205
- })
206
- );
207
-
208
- const updatedLayouts = getAllLayouts(manager);
209
- expect(updatedLayouts[0].width).toBe(600); // Width should adapt
210
- expect(updatedLayouts[1].y).toBe(initialLayouts[1].y); // Vertical position shouldn't change
211
- });
212
- });
213
-
214
- describe("Empty layout", () => {
215
- it("should return zero size for empty layout", () => {
216
- const manager = createLayoutManager(
217
- LayoutManagerType.LINEAR,
218
- defaultParams
219
- );
220
- manager.modifyLayout([], 0);
221
- const layoutSize = manager.getLayoutSize();
222
- expect(layoutSize.width).toBe(0);
223
- expect(layoutSize.height).toBe(0);
224
- expect(getAllLayouts(manager).length).toBe(0);
225
- });
226
- });
227
- });
@@ -1,202 +0,0 @@
1
- import { RVLayoutManager } from "../recyclerview/layout-managers/LayoutManager";
2
- import { RVMasonryLayoutManagerImpl } from "../recyclerview/layout-managers/MasonryLayoutManager";
3
-
4
- import {
5
- getAllLayouts,
6
- LayoutManagerType,
7
- createLayoutParams,
8
- createLayoutManager,
9
- createMockLayoutInfo,
10
- } from "./helpers/createLayoutManager";
11
-
12
- describe("MasonryLayoutManager", () => {
13
- const windowSize = { width: 400, height: 900 };
14
- const defaultParams = {
15
- windowSize,
16
- maxColumns: 2,
17
- optimizeItemArrangement: true,
18
- };
19
-
20
- // Helper to get column heights
21
- const getColumnHeights = (manager: RVLayoutManager): number[] => {
22
- return (manager as RVMasonryLayoutManagerImpl)["columnHeights"];
23
- };
24
-
25
- describe("Vertical Masonry Layout", () => {
26
- it("should distribute items into columns based on height", () => {
27
- const manager = createLayoutManager(
28
- LayoutManagerType.MASONRY,
29
- defaultParams
30
- );
31
- const layoutInfos = [
32
- createMockLayoutInfo(0, 200, 100), // Col 0
33
- createMockLayoutInfo(1, 200, 150), // Col 1
34
- createMockLayoutInfo(2, 200, 120), // Col 0 (shorter)
35
- createMockLayoutInfo(3, 200, 80), // Col 1 (shorter)
36
- createMockLayoutInfo(4, 200, 200), // Col 0 (shorter)
37
- ];
38
- manager.modifyLayout(layoutInfos, 5);
39
- const layouts = getAllLayouts(manager);
40
-
41
- expect(layouts[0].x).toBe(0);
42
- expect(layouts[0].y).toBe(0);
43
-
44
- expect(layouts[1].x).toBe(200); // Second column
45
- expect(layouts[1].y).toBe(0);
46
-
47
- expect(layouts[2].x).toBe(0); // Back to first column
48
- expect(layouts[2].y).toBe(100); // Below item 0
49
-
50
- expect(layouts[3].x).toBe(200); // Still first column
51
- expect(layouts[3].y).toBe(150); // Below item 2 (100 + 120)
52
-
53
- expect(layouts[4].x).toBe(0); // Second column
54
- expect(layouts[4].y).toBe(220); // Below item 1
55
- });
56
-
57
- it("should respect maxColumns configuration", () => {
58
- const manager = createLayoutManager(LayoutManagerType.MASONRY, {
59
- ...defaultParams,
60
- maxColumns: 3,
61
- });
62
- const layoutInfos = [
63
- createMockLayoutInfo(0, 133, 100), // Col 0
64
- createMockLayoutInfo(1, 133, 150), // Col 1
65
- createMockLayoutInfo(2, 133, 120), // Col 2
66
- createMockLayoutInfo(3, 133, 80), // Col 0
67
- ];
68
- manager.modifyLayout(layoutInfos, 4);
69
- const layouts = getAllLayouts(manager);
70
- const colWidth = windowSize.width / 3;
71
-
72
- expect(layouts[0].x).toBeCloseTo(0);
73
- expect(layouts[1].x).toBeCloseTo(colWidth);
74
- expect(layouts[2].x).toBeCloseTo(colWidth * 2);
75
- expect(layouts[3].x).toBeCloseTo(0); // Placed in the shortest column (Col 0)
76
- expect(layouts[3].y).toBeCloseTo(100); // Below item 0
77
- });
78
-
79
- it("should calculate total layout size correctly", () => {
80
- const manager = createLayoutManager(
81
- LayoutManagerType.MASONRY,
82
- defaultParams
83
- );
84
- const layoutInfos = [
85
- createMockLayoutInfo(0, 200, 100), // Col 0
86
- createMockLayoutInfo(1, 200, 150), // Col 1
87
- createMockLayoutInfo(2, 200, 120), // Col 0
88
- ];
89
- manager.modifyLayout(layoutInfos, 3);
90
- const layoutSize = manager.getLayoutSize();
91
-
92
- expect(layoutSize.width).toBe(400);
93
- // Height is the tallest column height
94
- const heights = getColumnHeights(manager);
95
- expect(layoutSize.height).toBeCloseTo(Math.max(...heights)); // Max of [220, 150]
96
- expect(layoutSize.height).toBeCloseTo(220);
97
- });
98
- });
99
-
100
- describe("Layout Modifications", () => {
101
- it("should update layout when items are added", () => {
102
- const manager = createLayoutManager(
103
- LayoutManagerType.MASONRY,
104
- defaultParams
105
- );
106
- const initialInfos = [
107
- createMockLayoutInfo(0, 200, 100), // Col 0 H=100
108
- createMockLayoutInfo(1, 200, 150), // Col 1 H=150
109
- ];
110
- manager.modifyLayout(initialInfos, 2);
111
- expect(getAllLayouts(manager).length).toBe(2);
112
- expect(getColumnHeights(manager)).toEqual([100, 150]);
113
-
114
- // Add item, should go to Col 0
115
- const newLayoutInfos = [createMockLayoutInfo(2, 200, 120)];
116
- manager.modifyLayout(newLayoutInfos, 3);
117
-
118
- const layouts = getAllLayouts(manager);
119
- expect(layouts.length).toBe(3);
120
- expect(layouts[2].x).toBe(0); // Col 0
121
- expect(layouts[2].y).toBe(100); // Below item 0
122
- expect(getColumnHeights(manager)).toEqual([220, 150]); // 100+120, 150
123
- });
124
-
125
- it("should handle removing items (requires full recalculation)", () => {
126
- const manager = createLayoutManager(
127
- LayoutManagerType.MASONRY,
128
- defaultParams
129
- );
130
- const initialInfos = [
131
- createMockLayoutInfo(0, 200, 100), // Col 0 H=100
132
- createMockLayoutInfo(1, 200, 150), // Col 1 H=150
133
- createMockLayoutInfo(2, 200, 120), // Col 0 H=220
134
- ];
135
- manager.modifyLayout(initialInfos, 3);
136
- expect(getColumnHeights(manager)).toEqual([220, 150]);
137
-
138
- // Remove item 2 (from Col 0) - Masonry usually recalculates fully
139
- // We simulate this by passing the remaining items
140
- const remainingInfos = [
141
- createMockLayoutInfo(0, 200, 100),
142
- createMockLayoutInfo(1, 200, 150),
143
- ];
144
- manager.modifyLayout(remainingInfos, 2);
145
-
146
- const layouts = getAllLayouts(manager);
147
- expect(layouts.length).toBe(2);
148
- expect(getColumnHeights(manager)).toEqual([100, 150]); // Back to original state
149
- });
150
-
151
- it("should recalculate layout when window size changes", () => {
152
- const manager = createLayoutManager(
153
- LayoutManagerType.MASONRY,
154
- defaultParams
155
- );
156
- const initialInfos = [
157
- createMockLayoutInfo(0, 200, 100), // Col 0
158
- createMockLayoutInfo(1, 200, 150), // Col 1
159
- createMockLayoutInfo(2, 200, 120), // Col 0
160
- ];
161
- manager.modifyLayout(initialInfos, 3);
162
- const initialLayouts = getAllLayouts(manager);
163
- expect(initialLayouts[1].x).toBe(200);
164
-
165
- // Change window size and columns
166
- manager.updateLayoutParams(
167
- createLayoutParams({
168
- ...defaultParams,
169
- maxColumns: 3,
170
- windowSize: { width: 600, height: 900 },
171
- })
172
- );
173
- // modifyLayout needs to be called again as dimensions depend on width
174
- const updatedInfos = [
175
- createMockLayoutInfo(0, 200, 100), // New width = 600/3 = 200
176
- createMockLayoutInfo(1, 200, 150),
177
- createMockLayoutInfo(2, 200, 120),
178
- ];
179
- manager.modifyLayout(updatedInfos, 3);
180
-
181
- const updatedLayouts = getAllLayouts(manager);
182
- expect(updatedLayouts[0].width).toBe(200);
183
- expect(updatedLayouts[1].x).toBe(200); // Col 1 starts at 200
184
- expect(updatedLayouts[2].x).toBe(400); // Col 2 starts at 400
185
- expect(getColumnHeights(manager)).toEqual([100, 150, 120]);
186
- });
187
- });
188
-
189
- describe("Empty Layout", () => {
190
- it("should return zero size for empty layout", () => {
191
- const manager = createLayoutManager(
192
- LayoutManagerType.MASONRY,
193
- defaultParams
194
- );
195
- manager.modifyLayout([], 0);
196
- const layoutSize = manager.getLayoutSize();
197
- expect(layoutSize.width).toBe(0);
198
- expect(layoutSize.height).toBe(0);
199
- expect(getAllLayouts(manager).length).toBe(0);
200
- });
201
- });
202
- });