@shopify/flash-list 1.3.0 → 1.4.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.
- package/CHANGELOG.md +12 -0
- package/dist/FlashList.d.ts +0 -1
- package/dist/FlashList.d.ts.map +1 -1
- package/dist/FlashList.js +17 -41
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +0 -1
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/GridLayoutProviderWithProps.d.ts +9 -1
- package/dist/GridLayoutProviderWithProps.d.ts.map +1 -1
- package/dist/GridLayoutProviderWithProps.js +30 -1
- package/dist/GridLayoutProviderWithProps.js.map +1 -1
- package/dist/MasonryFlashList.d.ts +14 -2
- package/dist/MasonryFlashList.d.ts.map +1 -1
- package/dist/MasonryFlashList.js +14 -5
- package/dist/MasonryFlashList.js.map +1 -1
- package/dist/__tests__/ContentContainerUtils.test.d.ts +2 -0
- package/dist/__tests__/ContentContainerUtils.test.d.ts.map +1 -0
- package/dist/__tests__/ContentContainerUtils.test.js +85 -0
- package/dist/__tests__/ContentContainerUtils.test.js.map +1 -0
- package/dist/__tests__/FlashList.test.js +32 -0
- package/dist/__tests__/FlashList.test.js.map +1 -1
- package/dist/__tests__/GridLayoutProviderWithProps.test.js +10 -0
- package/dist/__tests__/GridLayoutProviderWithProps.test.js.map +1 -1
- package/dist/__tests__/MasonryFlashList.test.js +49 -0
- package/dist/__tests__/MasonryFlashList.test.js.map +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +1 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.js +7 -2
- package/dist/__tests__/helpers/mountMasonryFlashList.js.map +1 -1
- package/dist/errors/Warnings.d.ts +0 -1
- package/dist/errors/Warnings.d.ts.map +1 -1
- package/dist/errors/Warnings.js +1 -3
- package/dist/errors/Warnings.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/ContentContainerUtils.d.ts +27 -0
- package/dist/utils/ContentContainerUtils.d.ts.map +1 -0
- package/dist/utils/ContentContainerUtils.js +48 -0
- package/dist/utils/ContentContainerUtils.js.map +1 -0
- package/package.json +3 -3
- package/src/FlashList.tsx +29 -50
- package/src/FlashListProps.ts +0 -1
- package/src/GridLayoutProviderWithProps.ts +39 -3
- package/src/MasonryFlashList.tsx +39 -5
- package/src/__tests__/ContentContainerUtils.test.ts +130 -0
- package/src/__tests__/FlashList.test.tsx +32 -0
- package/src/__tests__/GridLayoutProviderWithProps.test.ts +29 -0
- package/src/__tests__/MasonryFlashList.test.ts +57 -0
- package/src/__tests__/helpers/mountMasonryFlashList.tsx +6 -1
- package/src/errors/Warnings.ts +1 -4
- package/src/index.ts +2 -0
- package/src/utils/ContentContainerUtils.ts +92 -0
package/src/MasonryFlashList.tsx
CHANGED
|
@@ -11,9 +11,20 @@ import {
|
|
|
11
11
|
import CustomError from "./errors/CustomError";
|
|
12
12
|
import ExceptionList from "./errors/ExceptionList";
|
|
13
13
|
import FlashList from "./FlashList";
|
|
14
|
-
import { FlashListProps } from "./FlashListProps";
|
|
14
|
+
import { FlashListProps, ListRenderItemInfo } from "./FlashListProps";
|
|
15
|
+
import { applyContentContainerInsetForLayoutManager } from "./utils/ContentContainerUtils";
|
|
15
16
|
import ViewToken from "./viewability/ViewToken";
|
|
16
17
|
|
|
18
|
+
export interface MasonryListRenderItemInfo<TItem>
|
|
19
|
+
extends ListRenderItemInfo<TItem> {
|
|
20
|
+
columnSpan: number;
|
|
21
|
+
columnIndex: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type MasonryListRenderItem<TItem> = (
|
|
25
|
+
info: MasonryListRenderItemInfo<TItem>
|
|
26
|
+
) => React.ReactElement | null;
|
|
27
|
+
|
|
17
28
|
export interface MasonryFlashListProps<T>
|
|
18
29
|
extends Omit<
|
|
19
30
|
FlashListProps<T>,
|
|
@@ -21,6 +32,7 @@ export interface MasonryFlashListProps<T>
|
|
|
21
32
|
| "initialScrollIndex"
|
|
22
33
|
| "inverted"
|
|
23
34
|
| "onBlankArea"
|
|
35
|
+
| "renderItem"
|
|
24
36
|
| "viewabilityConfigCallbackPairs"
|
|
25
37
|
> {
|
|
26
38
|
/**
|
|
@@ -39,6 +51,14 @@ export interface MasonryFlashListProps<T>
|
|
|
39
51
|
* `overrideItemLayout` is required to make this work.
|
|
40
52
|
*/
|
|
41
53
|
optimizeItemArrangement?: boolean;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Extends typical `renderItem` to include `columnIndex` and `columnSpan` (number of columns the item spans).
|
|
57
|
+
* `columnIndex` gives the consumer column information in case they might need to treat items differently based on column.
|
|
58
|
+
* This information may not otherwise be derived if using the `optimizeItemArrangement` feature, as the items will no
|
|
59
|
+
* longer be linearly distributed across the columns; instead they are allocated to the column with the least estimated height.
|
|
60
|
+
*/
|
|
61
|
+
renderItem: MasonryListRenderItem<T> | null | undefined;
|
|
42
62
|
}
|
|
43
63
|
|
|
44
64
|
type OnScrollCallback = ScrollViewProps["onScroll"];
|
|
@@ -157,6 +177,12 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
157
177
|
(dataSet[0]?.length ?? 0) *
|
|
158
178
|
(props.estimatedItemSize ?? defaultEstimatedItemSize);
|
|
159
179
|
|
|
180
|
+
const insetForLayoutManager = applyContentContainerInsetForLayoutManager(
|
|
181
|
+
{ height: 0, width: 0 },
|
|
182
|
+
props.contentContainerStyle,
|
|
183
|
+
false
|
|
184
|
+
);
|
|
185
|
+
|
|
160
186
|
return (
|
|
161
187
|
<FlashList
|
|
162
188
|
ref={getFlashList}
|
|
@@ -179,6 +205,8 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
179
205
|
...innerArgs,
|
|
180
206
|
item: innerArgs.item.originalItem,
|
|
181
207
|
index: innerArgs.item.originalIndex,
|
|
208
|
+
columnSpan: 1,
|
|
209
|
+
columnIndex: args.index,
|
|
182
210
|
}) ?? null
|
|
183
211
|
);
|
|
184
212
|
}}
|
|
@@ -207,8 +235,9 @@ const MasonryFlashListComponent = React.forwardRef(
|
|
|
207
235
|
estimatedListSize={{
|
|
208
236
|
height: estimatedListSize.height,
|
|
209
237
|
width:
|
|
210
|
-
((getListRenderedSize(parentFlashList)?.width ||
|
|
211
|
-
estimatedListSize.width)
|
|
238
|
+
(((getListRenderedSize(parentFlashList)?.width ||
|
|
239
|
+
estimatedListSize.width) +
|
|
240
|
+
insetForLayoutManager.width) /
|
|
212
241
|
totalColumnFlex) *
|
|
213
242
|
(getColumnFlex?.(
|
|
214
243
|
args.item,
|
|
@@ -410,8 +439,13 @@ const updateViewTokens = (tokens: ViewToken[]) => {
|
|
|
410
439
|
for (let i = 0; i < length; i++) {
|
|
411
440
|
const token = tokens[i];
|
|
412
441
|
if (token.index !== null && token.index !== undefined) {
|
|
413
|
-
|
|
414
|
-
|
|
442
|
+
if (token.item) {
|
|
443
|
+
token.index = token.item.originalIndex;
|
|
444
|
+
token.item = token.item.originalItem;
|
|
445
|
+
} else {
|
|
446
|
+
token.index = null;
|
|
447
|
+
token.item = undefined;
|
|
448
|
+
}
|
|
415
449
|
}
|
|
416
450
|
}
|
|
417
451
|
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyContentContainerInsetForLayoutManager,
|
|
3
|
+
getContentContainerPadding,
|
|
4
|
+
hasUnsupportedKeysInContentContainerStyle,
|
|
5
|
+
updateContentStyle,
|
|
6
|
+
} from "../utils/ContentContainerUtils";
|
|
7
|
+
|
|
8
|
+
describe("ContentContainerUtils", () => {
|
|
9
|
+
it("detects unsupported keys in style", () => {
|
|
10
|
+
expect(hasUnsupportedKeysInContentContainerStyle({ flex: 1 })).toBe(true);
|
|
11
|
+
expect(hasUnsupportedKeysInContentContainerStyle({ paddingTop: 0 })).toBe(
|
|
12
|
+
false
|
|
13
|
+
);
|
|
14
|
+
expect(
|
|
15
|
+
hasUnsupportedKeysInContentContainerStyle({
|
|
16
|
+
paddingTop: 1,
|
|
17
|
+
paddingVertical: 1,
|
|
18
|
+
})
|
|
19
|
+
).toBe(false);
|
|
20
|
+
expect(
|
|
21
|
+
hasUnsupportedKeysInContentContainerStyle({
|
|
22
|
+
paddingTop: 1,
|
|
23
|
+
paddingVertical: 1,
|
|
24
|
+
padding: 1,
|
|
25
|
+
paddingLeft: 1,
|
|
26
|
+
paddingRight: 1,
|
|
27
|
+
paddingBottom: 1,
|
|
28
|
+
backgroundColor: "red",
|
|
29
|
+
paddingHorizontal: 1,
|
|
30
|
+
})
|
|
31
|
+
).toBe(false);
|
|
32
|
+
expect(hasUnsupportedKeysInContentContainerStyle({ margin: 1 })).toBe(true);
|
|
33
|
+
expect(hasUnsupportedKeysInContentContainerStyle({ padding: 1 })).toBe(
|
|
34
|
+
false
|
|
35
|
+
);
|
|
36
|
+
expect(
|
|
37
|
+
hasUnsupportedKeysInContentContainerStyle({ backgroundColor: "red" })
|
|
38
|
+
).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
it("updated content style to have all supported styles defined", () => {
|
|
41
|
+
expect(
|
|
42
|
+
updateContentStyle({}, { padding: 1, backgroundColor: "red" })
|
|
43
|
+
).toEqual({
|
|
44
|
+
paddingTop: 1,
|
|
45
|
+
paddingBottom: 1,
|
|
46
|
+
paddingLeft: 1,
|
|
47
|
+
paddingRight: 1,
|
|
48
|
+
backgroundColor: "red",
|
|
49
|
+
});
|
|
50
|
+
expect(updateContentStyle({}, { paddingHorizontal: 1 })).toEqual({
|
|
51
|
+
paddingTop: 0,
|
|
52
|
+
paddingBottom: 0,
|
|
53
|
+
paddingLeft: 1,
|
|
54
|
+
paddingRight: 1,
|
|
55
|
+
});
|
|
56
|
+
expect(updateContentStyle({}, { paddingVertical: 1 })).toEqual({
|
|
57
|
+
paddingTop: 1,
|
|
58
|
+
paddingBottom: 1,
|
|
59
|
+
paddingLeft: 0,
|
|
60
|
+
paddingRight: 0,
|
|
61
|
+
});
|
|
62
|
+
expect(
|
|
63
|
+
updateContentStyle({}, { paddingLeft: "1", paddingVertical: "1" })
|
|
64
|
+
).toEqual({
|
|
65
|
+
paddingTop: 1,
|
|
66
|
+
paddingBottom: 1,
|
|
67
|
+
paddingLeft: 1,
|
|
68
|
+
paddingRight: 0,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
it("computes correct layout manager insets", () => {
|
|
72
|
+
expect(
|
|
73
|
+
applyContentContainerInsetForLayoutManager(
|
|
74
|
+
{ height: 0, width: 0 },
|
|
75
|
+
{ padding: 1 },
|
|
76
|
+
false
|
|
77
|
+
)
|
|
78
|
+
).toEqual({ height: 0, width: -2 });
|
|
79
|
+
expect(
|
|
80
|
+
applyContentContainerInsetForLayoutManager(
|
|
81
|
+
{ height: 0, width: 0 },
|
|
82
|
+
{ padding: 1 },
|
|
83
|
+
true
|
|
84
|
+
)
|
|
85
|
+
).toEqual({ height: -2, width: 0 });
|
|
86
|
+
expect(
|
|
87
|
+
applyContentContainerInsetForLayoutManager(
|
|
88
|
+
{ height: 0, width: 0 },
|
|
89
|
+
{ paddingVertical: 1 },
|
|
90
|
+
true
|
|
91
|
+
)
|
|
92
|
+
).toEqual({ height: -2, width: 0 });
|
|
93
|
+
});
|
|
94
|
+
it("calculated correct padding for scrollview content", () => {
|
|
95
|
+
expect(
|
|
96
|
+
getContentContainerPadding(
|
|
97
|
+
{
|
|
98
|
+
paddingLeft: 1,
|
|
99
|
+
paddingTop: 1,
|
|
100
|
+
paddingBottom: 1,
|
|
101
|
+
paddingRight: 1,
|
|
102
|
+
backgroundColor: "red",
|
|
103
|
+
},
|
|
104
|
+
true
|
|
105
|
+
)
|
|
106
|
+
).toEqual({
|
|
107
|
+
paddingTop: 1,
|
|
108
|
+
paddingBottom: 1,
|
|
109
|
+
paddingLeft: undefined,
|
|
110
|
+
paddingRight: undefined,
|
|
111
|
+
});
|
|
112
|
+
expect(
|
|
113
|
+
getContentContainerPadding(
|
|
114
|
+
{
|
|
115
|
+
paddingLeft: 1,
|
|
116
|
+
paddingTop: 1,
|
|
117
|
+
paddingBottom: 1,
|
|
118
|
+
paddingRight: 1,
|
|
119
|
+
backgroundColor: "red",
|
|
120
|
+
},
|
|
121
|
+
false
|
|
122
|
+
)
|
|
123
|
+
).toEqual({
|
|
124
|
+
paddingTop: undefined,
|
|
125
|
+
paddingBottom: undefined,
|
|
126
|
+
paddingLeft: 1,
|
|
127
|
+
paddingRight: 1,
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -824,4 +824,36 @@ describe("FlashList", () => {
|
|
|
824
824
|
expect(scrollToOffset).toBeCalledWith(1800, 1800, false, true);
|
|
825
825
|
flashList.unmount();
|
|
826
826
|
});
|
|
827
|
+
it("applies horizontal content container padding for vertical list", () => {
|
|
828
|
+
const flashList = mountFlashList({
|
|
829
|
+
numColumns: 4,
|
|
830
|
+
contentContainerStyle: { paddingHorizontal: 10 },
|
|
831
|
+
});
|
|
832
|
+
let hasLayoutItems = false;
|
|
833
|
+
flashList.instance.state.layoutProvider
|
|
834
|
+
.getLayoutManager()!
|
|
835
|
+
.getLayouts()
|
|
836
|
+
.forEach((layout) => {
|
|
837
|
+
hasLayoutItems = true;
|
|
838
|
+
expect(layout.width).toBe(95);
|
|
839
|
+
});
|
|
840
|
+
expect(hasLayoutItems).toBe(true);
|
|
841
|
+
flashList.unmount();
|
|
842
|
+
});
|
|
843
|
+
it("applies vertical content container padding for horizontal list", () => {
|
|
844
|
+
const flashList = mountFlashList({
|
|
845
|
+
horizontal: true,
|
|
846
|
+
contentContainerStyle: { paddingVertical: 10 },
|
|
847
|
+
});
|
|
848
|
+
let hasLayoutItems = false;
|
|
849
|
+
flashList.instance.state.layoutProvider
|
|
850
|
+
.getLayoutManager()!
|
|
851
|
+
.getLayouts()
|
|
852
|
+
.forEach((layout) => {
|
|
853
|
+
hasLayoutItems = true;
|
|
854
|
+
expect(layout.height).toBe(880);
|
|
855
|
+
});
|
|
856
|
+
expect(hasLayoutItems).toBe(true);
|
|
857
|
+
flashList.unmount();
|
|
858
|
+
});
|
|
827
859
|
});
|
|
@@ -147,4 +147,33 @@ describe("GridLayoutProviderWithProps", () => {
|
|
|
147
147
|
// horizontal list
|
|
148
148
|
runCacheUpdateTest(true);
|
|
149
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
|
+
});
|
|
150
179
|
});
|
|
@@ -26,6 +26,35 @@ describe("MasonryFlashList", () => {
|
|
|
26
26
|
});
|
|
27
27
|
masonryFlashList.unmount();
|
|
28
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
|
+
});
|
|
29
58
|
it("raised onLoad event only when first internal child mounts", () => {
|
|
30
59
|
const onLoadMock = jest.fn();
|
|
31
60
|
const ref = React.createRef<MasonryFlashListRef<string>>();
|
|
@@ -232,4 +261,32 @@ describe("MasonryFlashList", () => {
|
|
|
232
261
|
)
|
|
233
262
|
).toBe(35339);
|
|
234
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
|
+
});
|
|
235
292
|
});
|
|
@@ -16,7 +16,12 @@ jest.mock("../../FlashList", () => {
|
|
|
16
16
|
componentDidMount() {
|
|
17
17
|
super.componentDidMount();
|
|
18
18
|
this.rlvRef?._scrollComponent?._scrollViewRef?.props.onLayout({
|
|
19
|
-
nativeEvent: {
|
|
19
|
+
nativeEvent: {
|
|
20
|
+
layout: {
|
|
21
|
+
height: this.props.estimatedListSize?.height ?? 900,
|
|
22
|
+
width: this.props.estimatedListSize?.width ?? 400,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
20
25
|
});
|
|
21
26
|
}
|
|
22
27
|
}
|
package/src/errors/Warnings.ts
CHANGED
|
@@ -2,10 +2,7 @@ const WarningList = {
|
|
|
2
2
|
styleUnsupported:
|
|
3
3
|
"You have passed a style to FlashList. This list doesn't support styling, use contentContainerStyle or wrap the list in a parent and apply style to it instead.",
|
|
4
4
|
styleContentContainerUnsupported:
|
|
5
|
-
"FlashList only supports padding related props and backgroundColor in contentContainerStyle."
|
|
6
|
-
" Please remove other values as they're not used. In case of vertical lists horizontal padding is ignored and vice versa, if you need it apply padding to your items instead.",
|
|
7
|
-
styleUnsupportedPaddingType:
|
|
8
|
-
"FlashList will ignore horizontal padding in case of vertical lists and vertical padding if the list is horizontal. If you need to have it apply relevant padding to your items instead.",
|
|
5
|
+
"FlashList only supports padding related props and backgroundColor in contentContainerStyle. Please remove other values as they're not used.",
|
|
9
6
|
unusableRenderedSize:
|
|
10
7
|
"FlashList's rendered size is not usable. Either the height or width is too small (<2px). " +
|
|
11
8
|
"Please make sure that the parent view of the list has a valid size. FlashList will match the size of the parent.",
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,8 @@ export {
|
|
|
34
34
|
MasonryFlashListScrollEvent,
|
|
35
35
|
MasonryFlashListRef,
|
|
36
36
|
MasonryListItem,
|
|
37
|
+
MasonryListRenderItem,
|
|
38
|
+
MasonryListRenderItemInfo,
|
|
37
39
|
} from "./MasonryFlashList";
|
|
38
40
|
export { JSFPSMonitor, JSFPSResult } from "./benchmark/JSFPSMonitor";
|
|
39
41
|
export { autoScroll, Cancellable } from "./benchmark/AutoScrollHelper";
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ViewStyle } from "react-native";
|
|
2
|
+
import { Dimension } from "recyclerlistview";
|
|
3
|
+
|
|
4
|
+
import { ContentStyle } from "../FlashListProps";
|
|
5
|
+
|
|
6
|
+
export interface ContentStyleExplicit {
|
|
7
|
+
paddingTop: number;
|
|
8
|
+
paddingBottom: number;
|
|
9
|
+
paddingLeft: number;
|
|
10
|
+
paddingRight: number;
|
|
11
|
+
backgroundColor?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const updateContentStyle = (
|
|
15
|
+
contentStyle: ContentStyle,
|
|
16
|
+
contentContainerStyleSource: ContentStyle | undefined
|
|
17
|
+
): ContentStyleExplicit => {
|
|
18
|
+
const {
|
|
19
|
+
paddingTop,
|
|
20
|
+
paddingRight,
|
|
21
|
+
paddingBottom,
|
|
22
|
+
paddingLeft,
|
|
23
|
+
padding,
|
|
24
|
+
paddingVertical,
|
|
25
|
+
paddingHorizontal,
|
|
26
|
+
backgroundColor,
|
|
27
|
+
} = (contentContainerStyleSource ?? {}) as ViewStyle;
|
|
28
|
+
contentStyle.paddingLeft = Number(
|
|
29
|
+
paddingLeft || paddingHorizontal || padding || 0
|
|
30
|
+
);
|
|
31
|
+
contentStyle.paddingRight = Number(
|
|
32
|
+
paddingRight || paddingHorizontal || padding || 0
|
|
33
|
+
);
|
|
34
|
+
contentStyle.paddingTop = Number(
|
|
35
|
+
paddingTop || paddingVertical || padding || 0
|
|
36
|
+
);
|
|
37
|
+
contentStyle.paddingBottom = Number(
|
|
38
|
+
paddingBottom || paddingVertical || padding || 0
|
|
39
|
+
);
|
|
40
|
+
contentStyle.backgroundColor = backgroundColor;
|
|
41
|
+
return contentStyle as ContentStyleExplicit;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const hasUnsupportedKeysInContentContainerStyle = (
|
|
45
|
+
contentContainerStyleSource: ViewStyle | undefined
|
|
46
|
+
) => {
|
|
47
|
+
const {
|
|
48
|
+
paddingTop,
|
|
49
|
+
paddingRight,
|
|
50
|
+
paddingBottom,
|
|
51
|
+
paddingLeft,
|
|
52
|
+
padding,
|
|
53
|
+
paddingVertical,
|
|
54
|
+
paddingHorizontal,
|
|
55
|
+
backgroundColor,
|
|
56
|
+
...rest
|
|
57
|
+
} = (contentContainerStyleSource ?? {}) as ViewStyle;
|
|
58
|
+
return Object.keys(rest).length > 0;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** Applies padding corrections to given dimension. Mutates the dim object that was passed and returns it. */
|
|
62
|
+
export const applyContentContainerInsetForLayoutManager = (
|
|
63
|
+
dim: Dimension,
|
|
64
|
+
contentContainerStyle: ViewStyle | undefined,
|
|
65
|
+
horizontal: boolean | undefined | null
|
|
66
|
+
) => {
|
|
67
|
+
const contentStyle = updateContentStyle({}, contentContainerStyle);
|
|
68
|
+
if (horizontal) {
|
|
69
|
+
dim.height -= contentStyle.paddingTop + contentStyle.paddingBottom;
|
|
70
|
+
} else {
|
|
71
|
+
dim.width -= contentStyle.paddingLeft + contentStyle.paddingRight;
|
|
72
|
+
}
|
|
73
|
+
return dim;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** Returns padding to be applied on content container and will ignore paddings that have already been handled. */
|
|
77
|
+
export const getContentContainerPadding = (
|
|
78
|
+
contentStyle: ContentStyleExplicit,
|
|
79
|
+
horizontal: boolean | undefined | null
|
|
80
|
+
) => {
|
|
81
|
+
if (horizontal) {
|
|
82
|
+
return {
|
|
83
|
+
paddingTop: contentStyle.paddingTop,
|
|
84
|
+
paddingBottom: contentStyle.paddingBottom,
|
|
85
|
+
};
|
|
86
|
+
} else {
|
|
87
|
+
return {
|
|
88
|
+
paddingLeft: contentStyle.paddingLeft,
|
|
89
|
+
paddingRight: contentStyle.paddingRight,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|