@legendapp/list 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/index.d.mts +8 -29
- package/index.d.ts +8 -29
- package/index.js +15 -10
- package/index.mjs +15 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ This is an early release to test and gather feedback. It's not used in productio
|
|
|
11
11
|
In addition to normal FlatList features:
|
|
12
12
|
|
|
13
13
|
- Dynamic layouts supported. Just use the `estimatedItemLength` prop to give a close estimate so that layouts aren't too far off, and positions will adjust while rendering.
|
|
14
|
-
- `
|
|
14
|
+
- `maintainScrollAtEnd`: If true and scroll is within `maintainScrollAtEndThreshold * screen height` then changing items or heights will scroll to the bottom. This can be useful for chat interfaces.
|
|
15
15
|
- `recycleItems` prop enables toggling recycling of list items. If enabled it will reuse item components for improved performance, but it will reuse any local state in items. So if you have local state in items you likely want this disabled.
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
@@ -40,8 +40,8 @@ interface PropsOptional {
|
|
|
40
40
|
initialContainers?: number;
|
|
41
41
|
recycleItems?: boolean;
|
|
42
42
|
onEndReachedThreshold?: number | null | undefined;
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
maintainScrollAtEnd?: boolean;
|
|
44
|
+
maintainScrollAtEndThreshold?: number;
|
|
45
45
|
onEndReached?: ((info: { distanceFromEnd: number }) => void) | null | undefined;
|
|
46
46
|
keyExtractor?: (item: T, index: number) => string;
|
|
47
47
|
onViewableRangeChanged?: (range: ViewableRange<T>) => void;
|
package/index.d.mts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
-
import * as react_native from 'react-native';
|
|
1
|
+
import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
|
|
4
2
|
import { ScrollView, StyleProp, ViewStyle } from 'react-native';
|
|
5
3
|
|
|
6
4
|
type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
|
|
@@ -11,9 +9,9 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
|
|
|
11
9
|
initialContainers?: number;
|
|
12
10
|
recycleItems?: boolean;
|
|
13
11
|
onEndReachedThreshold?: number | null | undefined;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
maintainScrollAtEnd?: boolean;
|
|
13
|
+
maintainScrollAtEndThreshold?: number;
|
|
14
|
+
alignItemsAtEnd?: boolean;
|
|
17
15
|
estimatedItemLength: (index: number) => number;
|
|
18
16
|
onEndReached?: ((info: {
|
|
19
17
|
distanceFromEnd: number;
|
|
@@ -25,6 +23,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
|
|
|
25
23
|
ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
26
24
|
ListFooterComponent?: ReactNode;
|
|
27
25
|
ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
26
|
+
ItemSeparatorComponent?: ReactNode;
|
|
28
27
|
};
|
|
29
28
|
interface ViewableRange<T> {
|
|
30
29
|
startBuffered: number;
|
|
@@ -38,28 +37,8 @@ interface LegendListRenderItemInfo<ItemT> {
|
|
|
38
37
|
index: number;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
declare const LegendList:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
initialScrollIndex?: number;
|
|
45
|
-
drawDistance?: number;
|
|
46
|
-
initialContainers?: number;
|
|
47
|
-
recycleItems?: boolean;
|
|
48
|
-
onEndReachedThreshold?: number | null | undefined;
|
|
49
|
-
autoScrollToBottom?: boolean;
|
|
50
|
-
autoScrollToBottomThreshold?: number;
|
|
51
|
-
startAtBottom?: boolean;
|
|
52
|
-
estimatedItemLength: (index: number) => number;
|
|
53
|
-
onEndReached?: ((info: {
|
|
54
|
-
distanceFromEnd: number;
|
|
55
|
-
}) => void) | null | undefined;
|
|
56
|
-
keyExtractor?: ((item: unknown, index: number) => string) | undefined;
|
|
57
|
-
renderItem?: ((props: LegendListRenderItemInfo<unknown>) => React.ReactNode) | undefined;
|
|
58
|
-
onViewableRangeChanged?: ((range: ViewableRange<unknown>) => void) | undefined;
|
|
59
|
-
ListHeaderComponent?: React.ReactNode;
|
|
60
|
-
ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
61
|
-
ListFooterComponent?: React.ReactNode;
|
|
62
|
-
ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
63
|
-
} & React.RefAttributes<ScrollView>>;
|
|
40
|
+
declare const LegendList: <T>(props: LegendListProps<T> & {
|
|
41
|
+
ref?: ForwardedRef<ScrollView>;
|
|
42
|
+
}) => ReactElement;
|
|
64
43
|
|
|
65
44
|
export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
-
import * as react_native from 'react-native';
|
|
1
|
+
import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
|
|
4
2
|
import { ScrollView, StyleProp, ViewStyle } from 'react-native';
|
|
5
3
|
|
|
6
4
|
type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
|
|
@@ -11,9 +9,9 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
|
|
|
11
9
|
initialContainers?: number;
|
|
12
10
|
recycleItems?: boolean;
|
|
13
11
|
onEndReachedThreshold?: number | null | undefined;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
maintainScrollAtEnd?: boolean;
|
|
13
|
+
maintainScrollAtEndThreshold?: number;
|
|
14
|
+
alignItemsAtEnd?: boolean;
|
|
17
15
|
estimatedItemLength: (index: number) => number;
|
|
18
16
|
onEndReached?: ((info: {
|
|
19
17
|
distanceFromEnd: number;
|
|
@@ -25,6 +23,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
|
|
|
25
23
|
ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
26
24
|
ListFooterComponent?: ReactNode;
|
|
27
25
|
ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
26
|
+
ItemSeparatorComponent?: ReactNode;
|
|
28
27
|
};
|
|
29
28
|
interface ViewableRange<T> {
|
|
30
29
|
startBuffered: number;
|
|
@@ -38,28 +37,8 @@ interface LegendListRenderItemInfo<ItemT> {
|
|
|
38
37
|
index: number;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
declare const LegendList:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
initialScrollIndex?: number;
|
|
45
|
-
drawDistance?: number;
|
|
46
|
-
initialContainers?: number;
|
|
47
|
-
recycleItems?: boolean;
|
|
48
|
-
onEndReachedThreshold?: number | null | undefined;
|
|
49
|
-
autoScrollToBottom?: boolean;
|
|
50
|
-
autoScrollToBottomThreshold?: number;
|
|
51
|
-
startAtBottom?: boolean;
|
|
52
|
-
estimatedItemLength: (index: number) => number;
|
|
53
|
-
onEndReached?: ((info: {
|
|
54
|
-
distanceFromEnd: number;
|
|
55
|
-
}) => void) | null | undefined;
|
|
56
|
-
keyExtractor?: ((item: unknown, index: number) => string) | undefined;
|
|
57
|
-
renderItem?: ((props: LegendListRenderItemInfo<unknown>) => React.ReactNode) | undefined;
|
|
58
|
-
onViewableRangeChanged?: ((range: ViewableRange<unknown>) => void) | undefined;
|
|
59
|
-
ListHeaderComponent?: React.ReactNode;
|
|
60
|
-
ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
61
|
-
ListFooterComponent?: React.ReactNode;
|
|
62
|
-
ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
|
|
63
|
-
} & React.RefAttributes<ScrollView>>;
|
|
40
|
+
declare const LegendList: <T>(props: LegendListProps<T> & {
|
|
41
|
+
ref?: ForwardedRef<ScrollView>;
|
|
42
|
+
}) => ReactElement;
|
|
64
43
|
|
|
65
44
|
export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
|
package/index.js
CHANGED
|
@@ -33,13 +33,15 @@ var Container = ({
|
|
|
33
33
|
recycleItems,
|
|
34
34
|
listProps,
|
|
35
35
|
getRenderedItem,
|
|
36
|
-
onLayout
|
|
36
|
+
onLayout,
|
|
37
|
+
ItemSeparatorComponent
|
|
37
38
|
}) => {
|
|
38
39
|
const { horizontal } = listProps;
|
|
39
40
|
const { id } = $container.peek();
|
|
40
41
|
const itemIndex = react.use$($container.itemIndex);
|
|
41
42
|
const key = recycleItems ? void 0 : itemIndex;
|
|
42
43
|
const createStyle = () => horizontal ? {
|
|
44
|
+
flexDirection: "row",
|
|
43
45
|
position: "absolute",
|
|
44
46
|
top: 0,
|
|
45
47
|
bottom: 0,
|
|
@@ -63,7 +65,8 @@ var Container = ({
|
|
|
63
65
|
onLayout(index, length);
|
|
64
66
|
}
|
|
65
67
|
},
|
|
66
|
-
/* @__PURE__ */ React2__namespace.createElement(reactNative.View, { key }, getRenderedItem(itemIndex))
|
|
68
|
+
/* @__PURE__ */ React2__namespace.createElement(reactNative.View, { key }, getRenderedItem(itemIndex)),
|
|
69
|
+
ItemSeparatorComponent && itemIndex !== listProps.data.length - 1 && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, null, ItemSeparatorComponent)
|
|
67
70
|
);
|
|
68
71
|
};
|
|
69
72
|
|
|
@@ -83,9 +86,9 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
83
86
|
drawDistance,
|
|
84
87
|
recycleItems = true,
|
|
85
88
|
onEndReachedThreshold,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
maintainScrollAtEnd = false,
|
|
90
|
+
maintainScrollAtEndThreshold = 0.1,
|
|
91
|
+
alignItemsAtEnd = false,
|
|
89
92
|
keyExtractor,
|
|
90
93
|
renderItem,
|
|
91
94
|
estimatedItemLength,
|
|
@@ -95,6 +98,7 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
95
98
|
ListHeaderComponentStyle,
|
|
96
99
|
ListFooterComponent,
|
|
97
100
|
ListFooterComponentStyle,
|
|
101
|
+
ItemSeparatorComponent,
|
|
98
102
|
...rest
|
|
99
103
|
} = props;
|
|
100
104
|
const internalRef = React2.useRef(null);
|
|
@@ -140,7 +144,7 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
140
144
|
const setTotalLength = (length) => {
|
|
141
145
|
visibleRange$.totalLength.set(length);
|
|
142
146
|
const screenLength = refPositions.current.scrollLength;
|
|
143
|
-
if (
|
|
147
|
+
if (alignItemsAtEnd) {
|
|
144
148
|
const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
|
|
145
149
|
paddingTop$.set(Math.max(0, screenLength - length - listPaddingTop));
|
|
146
150
|
}
|
|
@@ -301,7 +305,7 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
301
305
|
const newScroll = visibleRange$.scroll.peek();
|
|
302
306
|
const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - scrollLength;
|
|
303
307
|
if (refPositions.current) {
|
|
304
|
-
refPositions.current.isAtBottom = distanceFromEnd < scrollLength *
|
|
308
|
+
refPositions.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
|
|
305
309
|
}
|
|
306
310
|
if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
|
|
307
311
|
if (distanceFromEnd < (onEndReachedThreshold || 0.5) * scrollLength) {
|
|
@@ -337,7 +341,7 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
337
341
|
state.beginBatch();
|
|
338
342
|
lengths.set(id, length);
|
|
339
343
|
setTotalLength(visibleRange$.totalLength.peek() + (length - prevLength));
|
|
340
|
-
if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) &&
|
|
344
|
+
if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
|
|
341
345
|
requestAnimationFrame(() => {
|
|
342
346
|
var _a2;
|
|
343
347
|
(_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
|
|
@@ -396,7 +400,7 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
396
400
|
...rest,
|
|
397
401
|
ref: refScroller
|
|
398
402
|
},
|
|
399
|
-
|
|
403
|
+
alignItemsAtEnd && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: () => ({ height: paddingTop$.get() }) }),
|
|
400
404
|
ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
|
|
401
405
|
/* @__PURE__ */ React2__namespace.createElement(
|
|
402
406
|
react.Reactive.View,
|
|
@@ -415,7 +419,8 @@ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
415
419
|
$container: containers$[i],
|
|
416
420
|
listProps: props,
|
|
417
421
|
getRenderedItem,
|
|
418
|
-
onLayout: updateItemLength
|
|
422
|
+
onLayout: updateItemLength,
|
|
423
|
+
ItemSeparatorComponent
|
|
419
424
|
}
|
|
420
425
|
))
|
|
421
426
|
),
|
package/index.mjs
CHANGED
|
@@ -12,13 +12,15 @@ var Container = ({
|
|
|
12
12
|
recycleItems,
|
|
13
13
|
listProps,
|
|
14
14
|
getRenderedItem,
|
|
15
|
-
onLayout
|
|
15
|
+
onLayout,
|
|
16
|
+
ItemSeparatorComponent
|
|
16
17
|
}) => {
|
|
17
18
|
const { horizontal } = listProps;
|
|
18
19
|
const { id } = $container.peek();
|
|
19
20
|
const itemIndex = use$($container.itemIndex);
|
|
20
21
|
const key = recycleItems ? void 0 : itemIndex;
|
|
21
22
|
const createStyle = () => horizontal ? {
|
|
23
|
+
flexDirection: "row",
|
|
22
24
|
position: "absolute",
|
|
23
25
|
top: 0,
|
|
24
26
|
bottom: 0,
|
|
@@ -42,7 +44,8 @@ var Container = ({
|
|
|
42
44
|
onLayout(index, length);
|
|
43
45
|
}
|
|
44
46
|
},
|
|
45
|
-
/* @__PURE__ */ React2.createElement(View, { key }, getRenderedItem(itemIndex))
|
|
47
|
+
/* @__PURE__ */ React2.createElement(View, { key }, getRenderedItem(itemIndex)),
|
|
48
|
+
ItemSeparatorComponent && itemIndex !== listProps.data.length - 1 && /* @__PURE__ */ React2.createElement(Reactive.View, null, ItemSeparatorComponent)
|
|
46
49
|
);
|
|
47
50
|
};
|
|
48
51
|
|
|
@@ -62,9 +65,9 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
62
65
|
drawDistance,
|
|
63
66
|
recycleItems = true,
|
|
64
67
|
onEndReachedThreshold,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
maintainScrollAtEnd = false,
|
|
69
|
+
maintainScrollAtEndThreshold = 0.1,
|
|
70
|
+
alignItemsAtEnd = false,
|
|
68
71
|
keyExtractor,
|
|
69
72
|
renderItem,
|
|
70
73
|
estimatedItemLength,
|
|
@@ -74,6 +77,7 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
74
77
|
ListHeaderComponentStyle,
|
|
75
78
|
ListFooterComponent,
|
|
76
79
|
ListFooterComponentStyle,
|
|
80
|
+
ItemSeparatorComponent,
|
|
77
81
|
...rest
|
|
78
82
|
} = props;
|
|
79
83
|
const internalRef = useRef(null);
|
|
@@ -119,7 +123,7 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
119
123
|
const setTotalLength = (length) => {
|
|
120
124
|
visibleRange$.totalLength.set(length);
|
|
121
125
|
const screenLength = refPositions.current.scrollLength;
|
|
122
|
-
if (
|
|
126
|
+
if (alignItemsAtEnd) {
|
|
123
127
|
const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
|
|
124
128
|
paddingTop$.set(Math.max(0, screenLength - length - listPaddingTop));
|
|
125
129
|
}
|
|
@@ -280,7 +284,7 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
280
284
|
const newScroll = visibleRange$.scroll.peek();
|
|
281
285
|
const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - scrollLength;
|
|
282
286
|
if (refPositions.current) {
|
|
283
|
-
refPositions.current.isAtBottom = distanceFromEnd < scrollLength *
|
|
287
|
+
refPositions.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
|
|
284
288
|
}
|
|
285
289
|
if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
|
|
286
290
|
if (distanceFromEnd < (onEndReachedThreshold || 0.5) * scrollLength) {
|
|
@@ -316,7 +320,7 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
316
320
|
beginBatch();
|
|
317
321
|
lengths.set(id, length);
|
|
318
322
|
setTotalLength(visibleRange$.totalLength.peek() + (length - prevLength));
|
|
319
|
-
if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) &&
|
|
323
|
+
if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
|
|
320
324
|
requestAnimationFrame(() => {
|
|
321
325
|
var _a2;
|
|
322
326
|
(_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
|
|
@@ -375,7 +379,7 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
375
379
|
...rest,
|
|
376
380
|
ref: refScroller
|
|
377
381
|
},
|
|
378
|
-
|
|
382
|
+
alignItemsAtEnd && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: () => ({ height: paddingTop$.get() }) }),
|
|
379
383
|
ListHeaderComponent && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
|
|
380
384
|
/* @__PURE__ */ React2.createElement(
|
|
381
385
|
Reactive.View,
|
|
@@ -394,7 +398,8 @@ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
|
|
|
394
398
|
$container: containers$[i],
|
|
395
399
|
listProps: props,
|
|
396
400
|
getRenderedItem,
|
|
397
|
-
onLayout: updateItemLength
|
|
401
|
+
onLayout: updateItemLength,
|
|
402
|
+
ItemSeparatorComponent
|
|
398
403
|
}
|
|
399
404
|
))
|
|
400
405
|
),
|