@legendapp/list 1.0.0-beta.50 → 1.0.0-beta.52
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 +11 -12
- package/animated.d.mts +2 -1
- package/animated.d.ts +2 -1
- package/index.d.mts +18 -8
- package/index.d.ts +18 -8
- package/index.js +120 -53
- package/index.mjs +120 -53
- package/keyboard-controller.d.mts +134 -130
- package/keyboard-controller.d.ts +134 -130
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Legend List
|
|
1
|
+
# Legend List
|
|
2
2
|
|
|
3
3
|
**Legend List** is a high-performance list component for **React Native**, written purely in Javascript / Typescript (no native dependencies). It aims to be a drop-in replacement for `FlatList` and/or `FlashList` with better performance, especially when handling dynamically sized items.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## ⚠️ Caution: Experimental ⚠️
|
|
7
|
+
## ⚠️ Caution: Experimental ⚠️
|
|
8
8
|
|
|
9
9
|
This is an early release to test and gather feedback. It's not used in production yet and needs more work to reach parity with FlatList (and FlashList) features.
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ This is an early release to test and gather feedback. It's not used in productio
|
|
|
13
13
|
## 🤔 Why Legend List?
|
|
14
14
|
|
|
15
15
|
* **Performance:** Designed from the ground up for speed, aiming to outperform `FlatList` in common scenarios.
|
|
16
|
-
* **Dynamic Item Sizes:** Natively supports items with varying heights without performance hits.
|
|
16
|
+
* **Dynamic Item Sizes:** Natively supports items with varying heights without performance hits.
|
|
17
17
|
* **Drop-in Potential:** Aims for API compatibility with `FlatList` for easier migration.
|
|
18
18
|
* **Pure JS/TS:** No native module linking required, ensuring easier integration and compatibility across platforms.
|
|
19
19
|
* **Lightweight:** Our goal is to keep LegendList as small of a dependency as possible. For more advanced use cases, we plan on supporting optional plugins. This ensures that we keep the package size as small as possible.
|
|
@@ -21,7 +21,7 @@ This is an early release to test and gather feedback. It's not used in productio
|
|
|
21
21
|
For more information, listen to the podcast we had on [React Native Radio](https://infinite.red/react-native-radio/rnr-325-legend-list-with-jay-meistrich)!
|
|
22
22
|
|
|
23
23
|
---
|
|
24
|
-
## ✨ Additional Features
|
|
24
|
+
## ✨ Additional Features
|
|
25
25
|
|
|
26
26
|
Beyond standard `FlatList` capabilities:
|
|
27
27
|
|
|
@@ -57,7 +57,7 @@ yarn add @legendapp/list
|
|
|
57
57
|
|
|
58
58
|
### Example
|
|
59
59
|
```ts
|
|
60
|
-
import React, { useRef } from "react";
|
|
60
|
+
import React, { useRef } from "react";
|
|
61
61
|
import { View, Image, Text, StyleSheet } from "react-native";
|
|
62
62
|
import { LegendList, LegendListRef, LegendListRenderItemProps } from "@legendapp/list";
|
|
63
63
|
import { userData } from "../userData"; // Assuming userData is defined elsewhere
|
|
@@ -87,17 +87,16 @@ const LegendListExample = () => {
|
|
|
87
87
|
<LegendList<UserData>
|
|
88
88
|
// Required Props
|
|
89
89
|
data={data}
|
|
90
|
-
renderItem={renderItem}
|
|
91
|
-
estimatedItemSize={70}
|
|
90
|
+
renderItem={renderItem}
|
|
92
91
|
|
|
93
92
|
// Strongly Recommended Prop (Improves performance)
|
|
94
|
-
keyExtractor={(item) => item.id}
|
|
93
|
+
keyExtractor={(item) => item.id}
|
|
95
94
|
|
|
96
95
|
// Optional Props
|
|
97
|
-
ref={listRef}
|
|
98
|
-
recycleItems={true}
|
|
99
|
-
maintainScrollAtEnd={false}
|
|
100
|
-
maintainScrollAtEndThreshold={1}
|
|
96
|
+
ref={listRef}
|
|
97
|
+
recycleItems={true}
|
|
98
|
+
maintainScrollAtEnd={false}
|
|
99
|
+
maintainScrollAtEndThreshold={1}
|
|
101
100
|
|
|
102
101
|
// See docs for all available props!
|
|
103
102
|
/>
|
package/animated.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import * as _legendapp_list from '@legendapp/list';
|
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { Animated } from 'react-native';
|
|
5
5
|
|
|
6
|
-
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
6
|
+
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
7
7
|
alignItemsAtEnd?: boolean;
|
|
8
8
|
columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
|
|
9
9
|
data: readonly T[];
|
|
@@ -50,6 +50,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<re
|
|
|
50
50
|
refreshing?: boolean;
|
|
51
51
|
renderItem?: ((props: _legendapp_list.LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
52
52
|
renderScrollComponent?: (props: react_native.ScrollViewProps) => React.ReactElement<react_native.ScrollViewProps>;
|
|
53
|
+
suggestEstimatedItemSize?: boolean;
|
|
53
54
|
viewabilityConfig?: _legendapp_list.ViewabilityConfig;
|
|
54
55
|
viewabilityConfigCallbackPairs?: _legendapp_list.ViewabilityConfigCallbackPairs | undefined;
|
|
55
56
|
waitForInitialLayout?: boolean;
|
package/animated.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as _legendapp_list from '@legendapp/list';
|
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { Animated } from 'react-native';
|
|
5
5
|
|
|
6
|
-
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
6
|
+
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
7
7
|
alignItemsAtEnd?: boolean;
|
|
8
8
|
columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
|
|
9
9
|
data: readonly T[];
|
|
@@ -50,6 +50,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<re
|
|
|
50
50
|
refreshing?: boolean;
|
|
51
51
|
renderItem?: ((props: _legendapp_list.LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
52
52
|
renderScrollComponent?: (props: react_native.ScrollViewProps) => React.ReactElement<react_native.ScrollViewProps>;
|
|
53
|
+
suggestEstimatedItemSize?: boolean;
|
|
53
54
|
viewabilityConfig?: _legendapp_list.ViewabilityConfig;
|
|
54
55
|
viewabilityConfigCallbackPairs?: _legendapp_list.ViewabilityConfigCallbackPairs | undefined;
|
|
55
56
|
waitForInitialLayout?: boolean;
|
package/index.d.mts
CHANGED
|
@@ -41,10 +41,8 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
|
|
|
41
41
|
*/
|
|
42
42
|
drawDistance?: number;
|
|
43
43
|
/**
|
|
44
|
-
* Estimated size of each item in pixels
|
|
45
|
-
*
|
|
46
|
-
* a suggested size.
|
|
47
|
-
* @required
|
|
44
|
+
* Estimated size of each item in pixels, a hint for the first render. After some
|
|
45
|
+
* items are rendered, the average size of rendered items will be used instead.
|
|
48
46
|
* @default undefined
|
|
49
47
|
*/
|
|
50
48
|
estimatedItemSize?: number;
|
|
@@ -191,6 +189,12 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
|
|
|
191
189
|
* @default (props) => <ScrollView {...props} />
|
|
192
190
|
*/
|
|
193
191
|
renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
|
|
192
|
+
/**
|
|
193
|
+
* This will log a suggested estimatedItemSize.
|
|
194
|
+
* @required
|
|
195
|
+
* @default false
|
|
196
|
+
*/
|
|
197
|
+
suggestEstimatedItemSize?: boolean;
|
|
194
198
|
/**
|
|
195
199
|
* Configuration for determining item viewability.
|
|
196
200
|
*/
|
|
@@ -215,7 +219,7 @@ type AnchoredPosition = {
|
|
|
215
219
|
relativeCoordinate: number;
|
|
216
220
|
top: number;
|
|
217
221
|
};
|
|
218
|
-
type LegendListProps<ItemT> = LegendListPropsBase<ItemT, ComponentProps<typeof ScrollView>>;
|
|
222
|
+
type LegendListProps<ItemT> = LegendListPropsBase<ItemT, Omit<ComponentProps<typeof ScrollView>, "scrollEventThrottle">>;
|
|
219
223
|
interface InternalState {
|
|
220
224
|
anchorElement?: {
|
|
221
225
|
id: string;
|
|
@@ -226,7 +230,7 @@ interface InternalState {
|
|
|
226
230
|
positions: Map<string, number>;
|
|
227
231
|
columns: Map<string, number>;
|
|
228
232
|
sizes: Map<string, number>;
|
|
229
|
-
sizesKnown: Map<string, number
|
|
233
|
+
sizesKnown: Map<string, number>;
|
|
230
234
|
pendingAdjust: number;
|
|
231
235
|
isStartReached: boolean;
|
|
232
236
|
isEndReached: boolean;
|
|
@@ -246,6 +250,7 @@ interface InternalState {
|
|
|
246
250
|
scrollPrevTime: number;
|
|
247
251
|
scrollVelocity: number;
|
|
248
252
|
scrollAdjustHandler: ScrollAdjustHandler;
|
|
253
|
+
maintainingScrollAtEnd?: boolean;
|
|
249
254
|
totalSize: number;
|
|
250
255
|
totalSizeBelowAnchor: number;
|
|
251
256
|
timeouts: Set<number>;
|
|
@@ -273,6 +278,10 @@ interface InternalState {
|
|
|
273
278
|
lastBatchingAction: number;
|
|
274
279
|
ignoreScrollFromCalcTotal?: boolean;
|
|
275
280
|
scrollingToOffset?: number | undefined;
|
|
281
|
+
averageSizes: Record<string, {
|
|
282
|
+
num: number;
|
|
283
|
+
avg: number;
|
|
284
|
+
}>;
|
|
276
285
|
onScroll: ((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined;
|
|
277
286
|
}
|
|
278
287
|
interface ViewableRange<T> {
|
|
@@ -453,7 +462,7 @@ type TypedMemo = <T extends React.ComponentType<any>>(Component: T, propsAreEqua
|
|
|
453
462
|
};
|
|
454
463
|
declare const typedMemo: TypedMemo;
|
|
455
464
|
|
|
456
|
-
declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
465
|
+
declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
457
466
|
alignItemsAtEnd?: boolean;
|
|
458
467
|
columnWrapperStyle?: ColumnWrapperStyle;
|
|
459
468
|
data: readonly T[];
|
|
@@ -500,6 +509,7 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
|
|
|
500
509
|
refreshing?: boolean;
|
|
501
510
|
renderItem?: ((props: LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
502
511
|
renderScrollComponent?: (props: react_native.ScrollViewProps) => React$1.ReactElement<react_native.ScrollViewProps>;
|
|
512
|
+
suggestEstimatedItemSize?: boolean;
|
|
503
513
|
viewabilityConfig?: ViewabilityConfig;
|
|
504
514
|
viewabilityConfigCallbackPairs?: ViewabilityConfigCallbackPairs | undefined;
|
|
505
515
|
waitForInitialLayout?: boolean;
|
|
@@ -508,6 +518,6 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
|
|
|
508
518
|
declare function useViewability(callback: ViewabilityCallback, configId?: string): void;
|
|
509
519
|
declare function useViewabilityAmount(callback: ViewabilityAmountCallback): void;
|
|
510
520
|
declare function useRecyclingEffect(effect: (info: LegendListRecyclingState<unknown>) => void | (() => void)): void;
|
|
511
|
-
declare function useRecyclingState<ItemT>(valueOrFun: ((info: LegendListRecyclingState<ItemT>) => ItemT) | ItemT):
|
|
521
|
+
declare function useRecyclingState<ItemT>(valueOrFun: ((info: LegendListRecyclingState<ItemT>) => ItemT) | ItemT): readonly [ItemT | null, Dispatch<SetStateAction<ItemT>>];
|
|
512
522
|
|
|
513
523
|
export { type AnchoredPosition, type ColumnWrapperStyle, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type ScrollState, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
|
package/index.d.ts
CHANGED
|
@@ -41,10 +41,8 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
|
|
|
41
41
|
*/
|
|
42
42
|
drawDistance?: number;
|
|
43
43
|
/**
|
|
44
|
-
* Estimated size of each item in pixels
|
|
45
|
-
*
|
|
46
|
-
* a suggested size.
|
|
47
|
-
* @required
|
|
44
|
+
* Estimated size of each item in pixels, a hint for the first render. After some
|
|
45
|
+
* items are rendered, the average size of rendered items will be used instead.
|
|
48
46
|
* @default undefined
|
|
49
47
|
*/
|
|
50
48
|
estimatedItemSize?: number;
|
|
@@ -191,6 +189,12 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
|
|
|
191
189
|
* @default (props) => <ScrollView {...props} />
|
|
192
190
|
*/
|
|
193
191
|
renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
|
|
192
|
+
/**
|
|
193
|
+
* This will log a suggested estimatedItemSize.
|
|
194
|
+
* @required
|
|
195
|
+
* @default false
|
|
196
|
+
*/
|
|
197
|
+
suggestEstimatedItemSize?: boolean;
|
|
194
198
|
/**
|
|
195
199
|
* Configuration for determining item viewability.
|
|
196
200
|
*/
|
|
@@ -215,7 +219,7 @@ type AnchoredPosition = {
|
|
|
215
219
|
relativeCoordinate: number;
|
|
216
220
|
top: number;
|
|
217
221
|
};
|
|
218
|
-
type LegendListProps<ItemT> = LegendListPropsBase<ItemT, ComponentProps<typeof ScrollView>>;
|
|
222
|
+
type LegendListProps<ItemT> = LegendListPropsBase<ItemT, Omit<ComponentProps<typeof ScrollView>, "scrollEventThrottle">>;
|
|
219
223
|
interface InternalState {
|
|
220
224
|
anchorElement?: {
|
|
221
225
|
id: string;
|
|
@@ -226,7 +230,7 @@ interface InternalState {
|
|
|
226
230
|
positions: Map<string, number>;
|
|
227
231
|
columns: Map<string, number>;
|
|
228
232
|
sizes: Map<string, number>;
|
|
229
|
-
sizesKnown: Map<string, number
|
|
233
|
+
sizesKnown: Map<string, number>;
|
|
230
234
|
pendingAdjust: number;
|
|
231
235
|
isStartReached: boolean;
|
|
232
236
|
isEndReached: boolean;
|
|
@@ -246,6 +250,7 @@ interface InternalState {
|
|
|
246
250
|
scrollPrevTime: number;
|
|
247
251
|
scrollVelocity: number;
|
|
248
252
|
scrollAdjustHandler: ScrollAdjustHandler;
|
|
253
|
+
maintainingScrollAtEnd?: boolean;
|
|
249
254
|
totalSize: number;
|
|
250
255
|
totalSizeBelowAnchor: number;
|
|
251
256
|
timeouts: Set<number>;
|
|
@@ -273,6 +278,10 @@ interface InternalState {
|
|
|
273
278
|
lastBatchingAction: number;
|
|
274
279
|
ignoreScrollFromCalcTotal?: boolean;
|
|
275
280
|
scrollingToOffset?: number | undefined;
|
|
281
|
+
averageSizes: Record<string, {
|
|
282
|
+
num: number;
|
|
283
|
+
avg: number;
|
|
284
|
+
}>;
|
|
276
285
|
onScroll: ((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined;
|
|
277
286
|
}
|
|
278
287
|
interface ViewableRange<T> {
|
|
@@ -453,7 +462,7 @@ type TypedMemo = <T extends React.ComponentType<any>>(Component: T, propsAreEqua
|
|
|
453
462
|
};
|
|
454
463
|
declare const typedMemo: TypedMemo;
|
|
455
464
|
|
|
456
|
-
declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
465
|
+
declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
457
466
|
alignItemsAtEnd?: boolean;
|
|
458
467
|
columnWrapperStyle?: ColumnWrapperStyle;
|
|
459
468
|
data: readonly T[];
|
|
@@ -500,6 +509,7 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
|
|
|
500
509
|
refreshing?: boolean;
|
|
501
510
|
renderItem?: ((props: LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
502
511
|
renderScrollComponent?: (props: react_native.ScrollViewProps) => React$1.ReactElement<react_native.ScrollViewProps>;
|
|
512
|
+
suggestEstimatedItemSize?: boolean;
|
|
503
513
|
viewabilityConfig?: ViewabilityConfig;
|
|
504
514
|
viewabilityConfigCallbackPairs?: ViewabilityConfigCallbackPairs | undefined;
|
|
505
515
|
waitForInitialLayout?: boolean;
|
|
@@ -508,6 +518,6 @@ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "content
|
|
|
508
518
|
declare function useViewability(callback: ViewabilityCallback, configId?: string): void;
|
|
509
519
|
declare function useViewabilityAmount(callback: ViewabilityAmountCallback): void;
|
|
510
520
|
declare function useRecyclingEffect(effect: (info: LegendListRecyclingState<unknown>) => void | (() => void)): void;
|
|
511
|
-
declare function useRecyclingState<ItemT>(valueOrFun: ((info: LegendListRecyclingState<ItemT>) => ItemT) | ItemT):
|
|
521
|
+
declare function useRecyclingState<ItemT>(valueOrFun: ((info: LegendListRecyclingState<ItemT>) => ItemT) | ItemT): readonly [ItemT | null, Dispatch<SetStateAction<ItemT>>];
|
|
512
522
|
|
|
513
523
|
export { type AnchoredPosition, type ColumnWrapperStyle, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type OnViewableItemsChanged, type ScrollState, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
|
package/index.js
CHANGED
|
@@ -149,6 +149,16 @@ function useInterval(callback, delay) {
|
|
|
149
149
|
function isFunction(obj) {
|
|
150
150
|
return typeof obj === "function";
|
|
151
151
|
}
|
|
152
|
+
var warned = /* @__PURE__ */ new Set();
|
|
153
|
+
function warnDevOnce(id, text) {
|
|
154
|
+
if (__DEV__ && !warned.has(id)) {
|
|
155
|
+
warned.add(id);
|
|
156
|
+
console.warn(`[legend-list] ${text}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function roundSize(size) {
|
|
160
|
+
return Math.floor(size * 8) / 8;
|
|
161
|
+
}
|
|
152
162
|
var symbolFirst = Symbol();
|
|
153
163
|
function useInit(cb) {
|
|
154
164
|
const refValue = React6.useRef(symbolFirst);
|
|
@@ -327,7 +337,7 @@ var Container = ({
|
|
|
327
337
|
const onLayout = (event) => {
|
|
328
338
|
if (itemKey !== void 0) {
|
|
329
339
|
const layout = event.nativeEvent.layout;
|
|
330
|
-
const size =
|
|
340
|
+
const size = roundSize(layout[horizontal ? "width" : "height"]);
|
|
331
341
|
refLastSize.current = size;
|
|
332
342
|
updateItemSize(itemKey, size);
|
|
333
343
|
}
|
|
@@ -897,9 +907,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
897
907
|
renderItem,
|
|
898
908
|
estimatedItemSize,
|
|
899
909
|
getEstimatedItemSize,
|
|
910
|
+
suggestEstimatedItemSize,
|
|
900
911
|
ListEmptyComponent,
|
|
901
912
|
onItemSizeChanged,
|
|
902
|
-
scrollEventThrottle,
|
|
903
913
|
refScrollView,
|
|
904
914
|
waitForInitialLayout = true,
|
|
905
915
|
extraData,
|
|
@@ -947,14 +957,31 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
947
957
|
const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
|
|
948
958
|
return `${ret}`;
|
|
949
959
|
};
|
|
950
|
-
const getItemSize = (key, index, data) => {
|
|
951
|
-
|
|
952
|
-
const sizeKnown =
|
|
960
|
+
const getItemSize = (key, index, data, useAverageSize = false) => {
|
|
961
|
+
const state = refState.current;
|
|
962
|
+
const sizeKnown = state.sizesKnown.get(key);
|
|
953
963
|
if (sizeKnown !== void 0) {
|
|
954
964
|
return sizeKnown;
|
|
955
965
|
}
|
|
956
|
-
|
|
957
|
-
|
|
966
|
+
let size;
|
|
967
|
+
if (getEstimatedItemSize) {
|
|
968
|
+
size = getEstimatedItemSize(index, data);
|
|
969
|
+
}
|
|
970
|
+
if (size === void 0 && useAverageSize) {
|
|
971
|
+
const itemType = "";
|
|
972
|
+
const average = state.averageSizes[itemType];
|
|
973
|
+
if (average) {
|
|
974
|
+
size = roundSize(average.avg);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
const sizePrevious = state.sizesKnown.get(key);
|
|
978
|
+
if (sizePrevious !== void 0) {
|
|
979
|
+
return sizePrevious;
|
|
980
|
+
}
|
|
981
|
+
if (size === void 0) {
|
|
982
|
+
size = estimatedItemSize != null ? estimatedItemSize : DEFAULT_ITEM_SIZE;
|
|
983
|
+
}
|
|
984
|
+
state.sizes.set(key, size);
|
|
958
985
|
return size;
|
|
959
986
|
};
|
|
960
987
|
const calculateOffsetForIndex = (index = initialScrollIndex) => {
|
|
@@ -1025,6 +1052,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1025
1052
|
numPendingInitialLayout: 0,
|
|
1026
1053
|
queuedCalculateItemsInView: 0,
|
|
1027
1054
|
lastBatchingAction: Date.now(),
|
|
1055
|
+
averageSizes: {},
|
|
1028
1056
|
onScroll: onScrollProp
|
|
1029
1057
|
};
|
|
1030
1058
|
const dataLength = dataProp.length;
|
|
@@ -1040,7 +1068,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1040
1068
|
id: getId(0)
|
|
1041
1069
|
};
|
|
1042
1070
|
} else {
|
|
1043
|
-
|
|
1071
|
+
__DEV__ && warnDevOnce(
|
|
1072
|
+
"maintainVisibleContentPosition",
|
|
1073
|
+
"[legend-list] maintainVisibleContentPosition was not able to find an anchor element"
|
|
1074
|
+
);
|
|
1044
1075
|
}
|
|
1045
1076
|
}
|
|
1046
1077
|
set$(ctx, "scrollAdjust", 0);
|
|
@@ -1202,14 +1233,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1202
1233
|
var _a;
|
|
1203
1234
|
const state = refState.current;
|
|
1204
1235
|
const { data, scrollLength, positions, startBuffered, endBuffered } = state;
|
|
1205
|
-
|
|
1236
|
+
const numColumns = peek$(ctx, "numColumns");
|
|
1237
|
+
if (!data || scrollLength === 0 || numColumns > 1) {
|
|
1206
1238
|
return;
|
|
1207
1239
|
}
|
|
1208
1240
|
const numContainers = ctx.values.get("numContainers");
|
|
1209
1241
|
let numMeasurements = 0;
|
|
1210
1242
|
for (let i = 0; i < numContainers; i++) {
|
|
1211
1243
|
const itemKey = peek$(ctx, `containerItemKey${i}`);
|
|
1212
|
-
const isSizeKnown =
|
|
1244
|
+
const isSizeKnown = state.sizesKnown.get(itemKey);
|
|
1213
1245
|
if (itemKey && !isSizeKnown) {
|
|
1214
1246
|
const containerRef = ctx.viewRefs.get(i);
|
|
1215
1247
|
if (containerRef) {
|
|
@@ -1334,7 +1366,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1334
1366
|
}
|
|
1335
1367
|
const top2 = newPosition || positions.get(id);
|
|
1336
1368
|
if (top2 !== void 0) {
|
|
1337
|
-
const size = getItemSize(
|
|
1369
|
+
const size = getItemSize(
|
|
1370
|
+
id,
|
|
1371
|
+
i,
|
|
1372
|
+
data[i],
|
|
1373
|
+
/*useAverageSize*/
|
|
1374
|
+
true
|
|
1375
|
+
);
|
|
1338
1376
|
const bottom = top2 + size;
|
|
1339
1377
|
if (bottom > scroll - scrollBuffer) {
|
|
1340
1378
|
loopStart = i;
|
|
@@ -1364,7 +1402,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1364
1402
|
};
|
|
1365
1403
|
for (let i = Math.max(0, loopStart); i < data.length; i++) {
|
|
1366
1404
|
const id = getId(i);
|
|
1367
|
-
const size = getItemSize(
|
|
1405
|
+
const size = getItemSize(
|
|
1406
|
+
id,
|
|
1407
|
+
i,
|
|
1408
|
+
data[i],
|
|
1409
|
+
/*useAverageSize*/
|
|
1410
|
+
true
|
|
1411
|
+
);
|
|
1368
1412
|
maxSizeInRow = Math.max(maxSizeInRow, size);
|
|
1369
1413
|
if (top === void 0 || id === ((_a = state.anchorElement) == null ? void 0 : _a.id)) {
|
|
1370
1414
|
top = getInitialTop(i);
|
|
@@ -1588,9 +1632,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1588
1632
|
}
|
|
1589
1633
|
requestAnimationFrame(() => {
|
|
1590
1634
|
var _a;
|
|
1635
|
+
state.maintainingScrollAtEnd = true;
|
|
1591
1636
|
(_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
|
|
1592
1637
|
animated
|
|
1593
1638
|
});
|
|
1639
|
+
setTimeout(
|
|
1640
|
+
() => {
|
|
1641
|
+
state.maintainingScrollAtEnd = false;
|
|
1642
|
+
},
|
|
1643
|
+
0
|
|
1644
|
+
);
|
|
1594
1645
|
});
|
|
1595
1646
|
return true;
|
|
1596
1647
|
}
|
|
@@ -1618,9 +1669,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1618
1669
|
if (!refState.current) {
|
|
1619
1670
|
return;
|
|
1620
1671
|
}
|
|
1621
|
-
const { queuedInitialLayout, scrollLength, scroll } = refState.current;
|
|
1672
|
+
const { queuedInitialLayout, scrollLength, scroll, maintainingScrollAtEnd } = refState.current;
|
|
1622
1673
|
const contentSize = getContentSize(ctx);
|
|
1623
|
-
if (contentSize > 0 && queuedInitialLayout) {
|
|
1674
|
+
if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
|
|
1624
1675
|
const distanceFromEnd = contentSize - scroll - scrollLength;
|
|
1625
1676
|
const distanceFromEndAbs = Math.abs(distanceFromEnd);
|
|
1626
1677
|
const isContentLess = contentSize < scrollLength;
|
|
@@ -1688,13 +1739,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1688
1739
|
if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
|
|
1689
1740
|
state.isEndReached = false;
|
|
1690
1741
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1742
|
+
if (!didMaintainScrollAtEnd) {
|
|
1743
|
+
checkAtTop();
|
|
1744
|
+
checkAtBottom();
|
|
1745
|
+
}
|
|
1693
1746
|
}
|
|
1694
1747
|
}
|
|
1695
1748
|
};
|
|
1696
1749
|
const calcTotalSizesAndPositions = ({ forgetPositions = false }) => {
|
|
1697
1750
|
var _a, _b;
|
|
1751
|
+
const state = refState.current;
|
|
1698
1752
|
let totalSize = 0;
|
|
1699
1753
|
let totalSizeBelowIndex = 0;
|
|
1700
1754
|
const indexByKey = /* @__PURE__ */ new Map();
|
|
@@ -1702,7 +1756,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1702
1756
|
let column = 1;
|
|
1703
1757
|
let maxSizeInRow = 0;
|
|
1704
1758
|
const numColumns = (_a = peek$(ctx, "numColumns")) != null ? _a : numColumnsProp;
|
|
1705
|
-
if (!
|
|
1759
|
+
if (!state) {
|
|
1706
1760
|
return;
|
|
1707
1761
|
}
|
|
1708
1762
|
for (let i = 0; i < dataProp.length; i++) {
|
|
@@ -1715,36 +1769,36 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1715
1769
|
}
|
|
1716
1770
|
}
|
|
1717
1771
|
indexByKey.set(key, i);
|
|
1718
|
-
if (!forgetPositions &&
|
|
1719
|
-
newPositions.set(key,
|
|
1772
|
+
if (!forgetPositions && state.positions.get(key) != null && state.indexByKey.get(key) === i) {
|
|
1773
|
+
newPositions.set(key, state.positions.get(key));
|
|
1720
1774
|
}
|
|
1721
1775
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1776
|
+
state.indexByKey = indexByKey;
|
|
1777
|
+
state.positions = newPositions;
|
|
1724
1778
|
if (!forgetPositions && !isFirst) {
|
|
1725
1779
|
if (maintainVisibleContentPosition) {
|
|
1726
|
-
if (
|
|
1780
|
+
if (state.anchorElement == null || indexByKey.get(state.anchorElement.id) == null) {
|
|
1727
1781
|
if (dataProp.length) {
|
|
1728
1782
|
const newAnchorElement = {
|
|
1729
1783
|
coordinate: 0,
|
|
1730
1784
|
id: getId(0)
|
|
1731
1785
|
};
|
|
1732
|
-
|
|
1733
|
-
(_b =
|
|
1786
|
+
state.anchorElement = newAnchorElement;
|
|
1787
|
+
(_b = state.belowAnchorElementPositions) == null ? void 0 : _b.clear();
|
|
1734
1788
|
scrollTo(0, false);
|
|
1735
1789
|
setTimeout(() => {
|
|
1736
1790
|
calculateItemsInView();
|
|
1737
1791
|
}, 0);
|
|
1738
1792
|
} else {
|
|
1739
|
-
|
|
1793
|
+
state.startBufferedId = void 0;
|
|
1740
1794
|
}
|
|
1741
1795
|
}
|
|
1742
1796
|
} else {
|
|
1743
|
-
if (
|
|
1797
|
+
if (state.startBufferedId != null && newPositions.get(state.startBufferedId) == null) {
|
|
1744
1798
|
if (dataProp.length) {
|
|
1745
|
-
|
|
1799
|
+
state.startBufferedId = getId(0);
|
|
1746
1800
|
} else {
|
|
1747
|
-
|
|
1801
|
+
state.startBufferedId = void 0;
|
|
1748
1802
|
}
|
|
1749
1803
|
scrollTo(0, false);
|
|
1750
1804
|
setTimeout(() => {
|
|
@@ -1771,7 +1825,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1771
1825
|
if (maxSizeInRow > 0) {
|
|
1772
1826
|
totalSize += maxSizeInRow;
|
|
1773
1827
|
}
|
|
1774
|
-
const state = refState.current;
|
|
1775
1828
|
state.ignoreScrollFromCalcTotal = true;
|
|
1776
1829
|
requestAnimationFrame(() => {
|
|
1777
1830
|
state.ignoreScrollFromCalcTotal = false;
|
|
@@ -1804,6 +1857,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1804
1857
|
if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
|
|
1805
1858
|
refState.current.lastBatchingAction = Date.now();
|
|
1806
1859
|
if (!keyExtractorProp && !isFirst && didDataChange) {
|
|
1860
|
+
__DEV__ && warnDevOnce(
|
|
1861
|
+
"keyExtractor",
|
|
1862
|
+
"Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
|
|
1863
|
+
);
|
|
1807
1864
|
refState.current.sizes.clear();
|
|
1808
1865
|
refState.current.positions.clear();
|
|
1809
1866
|
}
|
|
@@ -1834,24 +1891,28 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1834
1891
|
if (index === void 0) {
|
|
1835
1892
|
return null;
|
|
1836
1893
|
}
|
|
1837
|
-
const useViewability2 = __DEV__ ? (
|
|
1838
|
-
|
|
1839
|
-
|
|
1894
|
+
const useViewability2 = __DEV__ ? () => {
|
|
1895
|
+
warnDevOnce(
|
|
1896
|
+
"useViewability",
|
|
1897
|
+
`useViewability has been moved from a render prop to a regular import: import { useViewability } from "@legendapp/list";`
|
|
1840
1898
|
);
|
|
1841
1899
|
} : void 0;
|
|
1842
|
-
const useViewabilityAmount2 = __DEV__ ? (
|
|
1843
|
-
|
|
1844
|
-
|
|
1900
|
+
const useViewabilityAmount2 = __DEV__ ? () => {
|
|
1901
|
+
warnDevOnce(
|
|
1902
|
+
"useViewabilityAmount",
|
|
1903
|
+
`useViewabilityAmount has been moved from a render prop to a regular import: import { useViewabilityAmount } from "@legendapp/list";`
|
|
1845
1904
|
);
|
|
1846
1905
|
} : void 0;
|
|
1847
|
-
const useRecyclingEffect2 = __DEV__ ? (
|
|
1848
|
-
|
|
1849
|
-
|
|
1906
|
+
const useRecyclingEffect2 = __DEV__ ? () => {
|
|
1907
|
+
warnDevOnce(
|
|
1908
|
+
"useRecyclingEffect",
|
|
1909
|
+
`useRecyclingEffect has been moved from a render prop to a regular import: import { useRecyclingEffect } from "@legendapp/list";`
|
|
1850
1910
|
);
|
|
1851
1911
|
} : void 0;
|
|
1852
|
-
const useRecyclingState2 = __DEV__ ? (
|
|
1853
|
-
|
|
1854
|
-
|
|
1912
|
+
const useRecyclingState2 = __DEV__ ? () => {
|
|
1913
|
+
warnDevOnce(
|
|
1914
|
+
"useRecyclingState",
|
|
1915
|
+
`useRecyclingState has been moved from a render prop to a regular import: import { useRecyclingState } from "@legendapp/list";`
|
|
1855
1916
|
);
|
|
1856
1917
|
} : void 0;
|
|
1857
1918
|
const renderedItem = (_b = (_a = refState.current).renderItem) == null ? void 0 : _b.call(_a, {
|
|
@@ -1904,7 +1965,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1904
1965
|
});
|
|
1905
1966
|
const updateItemSize = React6.useCallback((itemKey, size, fromFixGaps) => {
|
|
1906
1967
|
const state = refState.current;
|
|
1907
|
-
const { sizes, indexByKey, sizesKnown, data, rowHeights, startBuffered, endBuffered } = state;
|
|
1968
|
+
const { sizes, indexByKey, sizesKnown, data, rowHeights, startBuffered, endBuffered, averageSizes } = state;
|
|
1908
1969
|
if (!data) {
|
|
1909
1970
|
return;
|
|
1910
1971
|
}
|
|
@@ -1922,7 +1983,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1922
1983
|
needsUpdateContainersDidLayout = true;
|
|
1923
1984
|
}
|
|
1924
1985
|
}
|
|
1925
|
-
sizesKnown
|
|
1986
|
+
sizesKnown.set(itemKey, size);
|
|
1987
|
+
const itemType = "";
|
|
1988
|
+
let averages = averageSizes[itemType];
|
|
1989
|
+
if (!averages) {
|
|
1990
|
+
averages = averageSizes[itemType] = {
|
|
1991
|
+
num: 0,
|
|
1992
|
+
avg: 0
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
|
|
1996
|
+
averages.num++;
|
|
1926
1997
|
if (!prevSize || Math.abs(prevSize - size) > 0.5) {
|
|
1927
1998
|
let diff;
|
|
1928
1999
|
needsCalculate = true;
|
|
@@ -1937,19 +2008,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1937
2008
|
sizes.set(itemKey, size);
|
|
1938
2009
|
diff = size - prevSize;
|
|
1939
2010
|
}
|
|
1940
|
-
if (__DEV__ &&
|
|
2011
|
+
if (__DEV__ && suggestEstimatedItemSize) {
|
|
1941
2012
|
if (state.timeoutSizeMessage) {
|
|
1942
2013
|
clearTimeout(state.timeoutSizeMessage);
|
|
1943
2014
|
}
|
|
1944
2015
|
state.timeoutSizeMessage = setTimeout(() => {
|
|
1945
2016
|
state.timeoutSizeMessage = void 0;
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
for (const [_, size2] of sizesKnown) {
|
|
1949
|
-
num++;
|
|
1950
|
-
total += size2;
|
|
1951
|
-
}
|
|
1952
|
-
const avg = Math.round(total / num);
|
|
2017
|
+
const num = sizesKnown.size;
|
|
2018
|
+
const avg = state.averageSizes[""].avg;
|
|
1953
2019
|
console.warn(
|
|
1954
2020
|
`[legend-list] estimatedItemSize or getEstimatedItemSize are not defined. Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
|
|
1955
2021
|
);
|
|
@@ -2009,7 +2075,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
2009
2075
|
const isWidthZero = event.nativeEvent.layout.width === 0;
|
|
2010
2076
|
const isHeightZero = event.nativeEvent.layout.height === 0;
|
|
2011
2077
|
if (isWidthZero || isHeightZero) {
|
|
2012
|
-
|
|
2078
|
+
warnDevOnce(
|
|
2079
|
+
"height0",
|
|
2013
2080
|
`[legend-list] List ${isWidthZero ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
|
|
2014
2081
|
);
|
|
2015
2082
|
}
|
|
@@ -2176,7 +2243,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
2176
2243
|
alignItemsAtEnd,
|
|
2177
2244
|
ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
|
|
2178
2245
|
maintainVisibleContentPosition,
|
|
2179
|
-
scrollEventThrottle:
|
|
2246
|
+
scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
|
|
2180
2247
|
waitForInitialLayout,
|
|
2181
2248
|
refreshControl: refreshControl != null ? refreshControl : onRefresh && /* @__PURE__ */ React6__namespace.createElement(
|
|
2182
2249
|
reactNative.RefreshControl,
|