@legendapp/list 2.1.0-beta.0 → 2.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,81 @@
1
+ ## 2.0.13
2
+ - Feat: Allow returning undefined in getFixedItemSize to fall back to estimated size
3
+ - Fix: scrollToIndex viewOffset was being subtracted twice, causing incorrect scroll positioning
4
+ - Fix: Initial container allocation was not applying maintainVisibleContentPosition calculations
5
+ - Fix: updateItemSize was providing full data array to getEstimatedItemSize and getFixedItemSize instead of individual item
6
+
7
+ ## 2.0.12
8
+ - Fix: Scroll velocity calculation was sometimes incorrect when item sizes were very different from estimate
9
+ - Fix: onScroll while scrolling was updating positions without maintainVisibleContentPosition calculations, which was breaking scroll position maintenance
10
+
11
+ ## 2.0.11
12
+ - Fix: Missing React import in a file
13
+
14
+ ## 2.0.10
15
+ - Feat: Add onStickyHeaderChange callback for sticky headers
16
+ - Fix: Items with a falsy value like 0 were not rendering
17
+ - Fix: Column positions sometimes not calculating correctly
18
+ - Perf: updateItemsPositions was not breaking early sometimes
19
+ - Perf: Changed idCache to be an array instead of a Map for better performance
20
+ - Perf: Speed up container reuse lookups
21
+
22
+ ## 2.0.9
23
+ - Fix: Improve initialScrollIndex accuracy and reliability
24
+
25
+ ## 2.0.8
26
+ - Fix: Data changing sometimes left blank spaces because it was ignoring scroll
27
+ - Fix: Toggling between empty and non-empty causing maintainVisibleContentPosition issues
28
+
29
+ ## 2.0.7
30
+ - Fix: Layout not working on react-native-macos because of transform instead of position
31
+
32
+ ## 2.0.6
33
+ - Fix: updateItemPositions edge case with items multiple screen heights long was breaking the loop too early
34
+
35
+ ## 2.0.5
36
+ - Perf: Change updateAllPositions to constrain processing to the scroll range
37
+ - Fix: Crash when using snapTo in some environments
38
+ - Perf: Change Separator to use useIsLastItem which should reduce the number of times it runs
39
+
40
+ ## 2.0.4
41
+ - Fix: Possible crash if refScroller is undefined
42
+
43
+ ## 2.0.3
44
+ - Feat: Set activeStickyIndex for usage in getState()
45
+ - Revert changes from 2.0.1 and 2.0.2 which were buggy in an edge case
46
+
47
+ ## 2.0.2
48
+ - Fix: Performance improvement in 2.0.1 caused a bug in an edge case
49
+
50
+ ## 2.0.1
51
+ - Perf: Improve performance in very long lists (bad release)
52
+
53
+ ## 2.0.0
54
+ Major version release with significant performance improvements and architectural changes:
55
+ - Feat: Complete rewrite of virtualization algorithm for better performance
56
+ - Feat: Add sticky headers support via stickyIndices prop
57
+ - Feat: Add snapToIndices prop for snap-to behavior
58
+ - Feat: Add getItemType prop for better item type handling
59
+ - Feat: Add getFixedItemSize prop for items with known fixed sizes
60
+ - Feat: Add itemsAreEqual prop to reduce re-rendering when data changes
61
+ - Feat: Expose positions in getState()
62
+ - Feat: Add enableAverages prop to control average size calculations
63
+ - Feat: Add viewOffset option to scrollToEnd
64
+ - Feat: Improve maintainScrollAtEnd with more granular options
65
+ - Feat: Add ref function to enable/disable scroll processing
66
+ - Feat: Support lazy rendering directly in LegendList component
67
+ - Perf: Optimize container positioning using transform instead of absolute positioning
68
+ - Perf: Improve scroll buffering algorithm with directional bias
69
+ - Perf: Enable batched updates for better rendering performance
70
+ - Perf: Optimize container allocation and reuse algorithms
71
+ - Perf: Improve average item size calculations
72
+ - Fix: Improve maintainVisibleContentPosition reliability
73
+ - Fix: Better handling of data changes and scroll position maintenance
74
+ - Fix: Improve initial scroll positioning accuracy
75
+ - Fix: Better handling of padding changes
76
+ - Fix: Resolve various edge cases with container recycling
77
+ - Fix: Improve viewability calculations
78
+
1
79
  ## 1.1.4
2
80
  - Feat: Add sizes to getState()
3
81
 
package/animated.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import * as React$1 from 'react';
2
1
  import * as _legendapp_list from '@legendapp/list';
2
+ import * as React from 'react';
3
3
  import { Animated } from 'react-native';
4
4
 
5
- declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: _legendapp_list.LegendListProps<T> & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode) & {
5
+ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: _legendapp_list.LegendListProps<T> & React.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode) & {
6
6
  displayName?: string;
7
7
  }>;
8
8
 
package/animated.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import * as React$1 from 'react';
2
1
  import * as _legendapp_list from '@legendapp/list';
2
+ import * as React from 'react';
3
3
  import { Animated } from 'react-native';
4
4
 
5
- declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: _legendapp_list.LegendListProps<T> & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode) & {
5
+ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: _legendapp_list.LegendListProps<T> & React.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode) & {
6
6
  displayName?: string;
7
7
  }>;
8
8
 
package/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import Animated$1 from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
7
7
 
8
- type ListenerType = "numContainers" | "numContainersPooled" | `containerItemKey${number}` | `containerItemData${number}` | `containerPosition${number}` | `containerColumn${number}` | `containerSticky${number}` | `containerStickyOffset${number}` | "containersDidLayout" | "extraData" | "numColumns" | "lastItemKeys" | "totalSize" | "alignItemsPaddingTop" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize" | "lastPositionUpdate";
8
+ type ListenerType = "numContainers" | "numContainersPooled" | `containerItemKey${number}` | `containerItemData${number}` | `containerPosition${number}` | `containerColumn${number}` | `containerSticky${number}` | `containerStickyOffset${number}` | "containersDidLayout" | "extraData" | "numColumns" | "lastItemKeys" | "totalSize" | "alignItemsPaddingTop" | "lastPositionUpdate" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize";
9
9
  interface StateContext {
10
10
  internalState: InternalState | undefined;
11
11
  listeners: Map<ListenerType, Set<(value: any) => void>>;
@@ -211,6 +211,13 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
211
211
  * @default 0.5
212
212
  */
213
213
  onStartReachedThreshold?: number | null | undefined;
214
+ /**
215
+ * Called when the sticky header changes.
216
+ */
217
+ onStickyHeaderChange?: (info: {
218
+ index: number;
219
+ item: any;
220
+ }) => void;
214
221
  /**
215
222
  * Called when the viewability of items changes.
216
223
  */
@@ -270,7 +277,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
270
277
  */
271
278
  stickyIndices?: number[];
272
279
  getItemType?: (item: ItemT, index: number) => TItemType;
273
- getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number;
280
+ getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number | undefined;
274
281
  itemsAreEqual?: (itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean;
275
282
  }
276
283
  type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof ScrollView> | ComponentProps<typeof Animated.ScrollView> | ComponentProps<typeof Animated$1.ScrollView>, TItemType extends string | undefined = string | undefined> = BaseScrollViewProps<TScrollView> & LegendListSpecificProps<ItemT, TItemType> & (DataModeProps<ItemT, TItemType> | ChildrenModeProps);
@@ -285,6 +292,12 @@ interface ColumnWrapperStyle {
285
292
  columnGap?: number;
286
293
  }
287
294
  type LegendListProps<ItemT = any> = LegendListPropsBase<ItemT, ComponentProps<typeof ScrollView>>;
295
+ interface ThresholdSnapshot {
296
+ scrollPosition: number;
297
+ contentSize?: number;
298
+ dataLength?: number;
299
+ atThreshold: boolean;
300
+ }
288
301
  interface InternalState {
289
302
  positions: Map<string, number>;
290
303
  columns: Map<string, number>;
@@ -318,14 +331,15 @@ interface InternalState {
318
331
  timeoutSizeMessage: any;
319
332
  nativeMarginTop: number;
320
333
  indexByKey: Map<string, number>;
321
- idCache: Map<number, string>;
334
+ idCache: string[];
322
335
  viewabilityConfigCallbackPairs: ViewabilityConfigCallbackPairs<any> | undefined;
323
336
  scrollHistory: Array<{
324
337
  scroll: number;
325
338
  time: number;
326
339
  }>;
327
- startReachedBlockedByTimer: boolean;
328
- endReachedBlockedByTimer: boolean;
340
+ lastScrollAdjustForHistory?: number;
341
+ startReachedSnapshot: ThresholdSnapshot | undefined;
342
+ endReachedSnapshot: ThresholdSnapshot | undefined;
329
343
  scrollForNextCalculateItemsInView: {
330
344
  top: number;
331
345
  bottom: number;
@@ -334,6 +348,7 @@ interface InternalState {
334
348
  minIndexSizeChanged: number | undefined;
335
349
  queuedInitialLayout?: boolean | undefined;
336
350
  queuedCalculateItemsInView: number | undefined;
351
+ dataChangeNeedsScrollUpdate: boolean;
337
352
  lastBatchingAction: number;
338
353
  ignoreScrollFromMVCP?: {
339
354
  lt?: number;
@@ -346,6 +361,7 @@ interface InternalState {
346
361
  viewOffset?: number;
347
362
  viewPosition?: number;
348
363
  animated?: boolean;
364
+ isInitialScroll?: boolean;
349
365
  } | undefined;
350
366
  needsOtherAxisSize?: boolean;
351
367
  averageSizes: Record<string, {
@@ -361,7 +377,6 @@ interface InternalState {
361
377
  stickyContainers: Map<number, number>;
362
378
  stickyContainerPool: Set<number>;
363
379
  scrollProcessingEnabled: boolean;
364
- onScrollRafScheduled?: boolean;
365
380
  props: {
366
381
  alignItemsAtEnd: boolean;
367
382
  data: readonly any[];
@@ -381,6 +396,7 @@ interface InternalState {
381
396
  onScroll: LegendListProps["onScroll"];
382
397
  onStartReached: LegendListProps["onStartReached"];
383
398
  onStartReachedThreshold: number | null | undefined;
399
+ onStickyHeaderChange: LegendListProps["onStickyHeaderChange"];
384
400
  recycleItems: boolean;
385
401
  suggestEstimatedItemSize: boolean;
386
402
  stylePaddingBottom: number | undefined;
@@ -412,6 +428,7 @@ interface LegendListRenderItemProps<ItemT, TItemType extends string | number | u
412
428
  extraData: any;
413
429
  }
414
430
  type ScrollState = {
431
+ activeStickyIndex: number | undefined;
415
432
  contentLength: number;
416
433
  data: readonly any[];
417
434
  end: number;
@@ -542,7 +559,7 @@ interface ViewAmountToken<ItemT = any> extends ViewToken<ItemT> {
542
559
  percentOfScroller: number;
543
560
  scrollSize: number;
544
561
  }
545
- interface ViewabilityConfigCallbackPair<ItemT> {
562
+ interface ViewabilityConfigCallbackPair<ItemT = any> {
546
563
  viewabilityConfig: ViewabilityConfig;
547
564
  onViewableItemsChanged?: OnViewableItemsChanged<ItemT>;
548
565
  }
@@ -623,4 +640,4 @@ declare function useListScrollSize(): {
623
640
  };
624
641
  declare function useSyncLayout(): () => void;
625
642
 
626
- export { type ColumnWrapperStyle, type GetRenderedItem, type GetRenderedItemResult, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type MaintainScrollAtEndOptions, type OnViewableItemsChanged, type ScrollIndexWithOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
643
+ export { type ColumnWrapperStyle, type GetRenderedItem, type GetRenderedItemResult, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type MaintainScrollAtEndOptions, type OnViewableItemsChanged, type ScrollIndexWithOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type ThresholdSnapshot, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
package/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import Animated$1 from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
7
7
 
8
- type ListenerType = "numContainers" | "numContainersPooled" | `containerItemKey${number}` | `containerItemData${number}` | `containerPosition${number}` | `containerColumn${number}` | `containerSticky${number}` | `containerStickyOffset${number}` | "containersDidLayout" | "extraData" | "numColumns" | "lastItemKeys" | "totalSize" | "alignItemsPaddingTop" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize" | "lastPositionUpdate";
8
+ type ListenerType = "numContainers" | "numContainersPooled" | `containerItemKey${number}` | `containerItemData${number}` | `containerPosition${number}` | `containerColumn${number}` | `containerSticky${number}` | `containerStickyOffset${number}` | "containersDidLayout" | "extraData" | "numColumns" | "lastItemKeys" | "totalSize" | "alignItemsPaddingTop" | "lastPositionUpdate" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize";
9
9
  interface StateContext {
10
10
  internalState: InternalState | undefined;
11
11
  listeners: Map<ListenerType, Set<(value: any) => void>>;
@@ -211,6 +211,13 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
211
211
  * @default 0.5
212
212
  */
213
213
  onStartReachedThreshold?: number | null | undefined;
214
+ /**
215
+ * Called when the sticky header changes.
216
+ */
217
+ onStickyHeaderChange?: (info: {
218
+ index: number;
219
+ item: any;
220
+ }) => void;
214
221
  /**
215
222
  * Called when the viewability of items changes.
216
223
  */
@@ -270,7 +277,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
270
277
  */
271
278
  stickyIndices?: number[];
272
279
  getItemType?: (item: ItemT, index: number) => TItemType;
273
- getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number;
280
+ getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number | undefined;
274
281
  itemsAreEqual?: (itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean;
275
282
  }
276
283
  type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof ScrollView> | ComponentProps<typeof Animated.ScrollView> | ComponentProps<typeof Animated$1.ScrollView>, TItemType extends string | undefined = string | undefined> = BaseScrollViewProps<TScrollView> & LegendListSpecificProps<ItemT, TItemType> & (DataModeProps<ItemT, TItemType> | ChildrenModeProps);
@@ -285,6 +292,12 @@ interface ColumnWrapperStyle {
285
292
  columnGap?: number;
286
293
  }
287
294
  type LegendListProps<ItemT = any> = LegendListPropsBase<ItemT, ComponentProps<typeof ScrollView>>;
295
+ interface ThresholdSnapshot {
296
+ scrollPosition: number;
297
+ contentSize?: number;
298
+ dataLength?: number;
299
+ atThreshold: boolean;
300
+ }
288
301
  interface InternalState {
289
302
  positions: Map<string, number>;
290
303
  columns: Map<string, number>;
@@ -318,14 +331,15 @@ interface InternalState {
318
331
  timeoutSizeMessage: any;
319
332
  nativeMarginTop: number;
320
333
  indexByKey: Map<string, number>;
321
- idCache: Map<number, string>;
334
+ idCache: string[];
322
335
  viewabilityConfigCallbackPairs: ViewabilityConfigCallbackPairs<any> | undefined;
323
336
  scrollHistory: Array<{
324
337
  scroll: number;
325
338
  time: number;
326
339
  }>;
327
- startReachedBlockedByTimer: boolean;
328
- endReachedBlockedByTimer: boolean;
340
+ lastScrollAdjustForHistory?: number;
341
+ startReachedSnapshot: ThresholdSnapshot | undefined;
342
+ endReachedSnapshot: ThresholdSnapshot | undefined;
329
343
  scrollForNextCalculateItemsInView: {
330
344
  top: number;
331
345
  bottom: number;
@@ -334,6 +348,7 @@ interface InternalState {
334
348
  minIndexSizeChanged: number | undefined;
335
349
  queuedInitialLayout?: boolean | undefined;
336
350
  queuedCalculateItemsInView: number | undefined;
351
+ dataChangeNeedsScrollUpdate: boolean;
337
352
  lastBatchingAction: number;
338
353
  ignoreScrollFromMVCP?: {
339
354
  lt?: number;
@@ -346,6 +361,7 @@ interface InternalState {
346
361
  viewOffset?: number;
347
362
  viewPosition?: number;
348
363
  animated?: boolean;
364
+ isInitialScroll?: boolean;
349
365
  } | undefined;
350
366
  needsOtherAxisSize?: boolean;
351
367
  averageSizes: Record<string, {
@@ -361,7 +377,6 @@ interface InternalState {
361
377
  stickyContainers: Map<number, number>;
362
378
  stickyContainerPool: Set<number>;
363
379
  scrollProcessingEnabled: boolean;
364
- onScrollRafScheduled?: boolean;
365
380
  props: {
366
381
  alignItemsAtEnd: boolean;
367
382
  data: readonly any[];
@@ -381,6 +396,7 @@ interface InternalState {
381
396
  onScroll: LegendListProps["onScroll"];
382
397
  onStartReached: LegendListProps["onStartReached"];
383
398
  onStartReachedThreshold: number | null | undefined;
399
+ onStickyHeaderChange: LegendListProps["onStickyHeaderChange"];
384
400
  recycleItems: boolean;
385
401
  suggestEstimatedItemSize: boolean;
386
402
  stylePaddingBottom: number | undefined;
@@ -412,6 +428,7 @@ interface LegendListRenderItemProps<ItemT, TItemType extends string | number | u
412
428
  extraData: any;
413
429
  }
414
430
  type ScrollState = {
431
+ activeStickyIndex: number | undefined;
415
432
  contentLength: number;
416
433
  data: readonly any[];
417
434
  end: number;
@@ -542,7 +559,7 @@ interface ViewAmountToken<ItemT = any> extends ViewToken<ItemT> {
542
559
  percentOfScroller: number;
543
560
  scrollSize: number;
544
561
  }
545
- interface ViewabilityConfigCallbackPair<ItemT> {
562
+ interface ViewabilityConfigCallbackPair<ItemT = any> {
546
563
  viewabilityConfig: ViewabilityConfig;
547
564
  onViewableItemsChanged?: OnViewableItemsChanged<ItemT>;
548
565
  }
@@ -623,4 +640,4 @@ declare function useListScrollSize(): {
623
640
  };
624
641
  declare function useSyncLayout(): () => void;
625
642
 
626
- export { type ColumnWrapperStyle, type GetRenderedItem, type GetRenderedItemResult, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type MaintainScrollAtEndOptions, type OnViewableItemsChanged, type ScrollIndexWithOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
643
+ export { type ColumnWrapperStyle, type GetRenderedItem, type GetRenderedItemResult, type InternalState, LegendList, type LegendListProps, type LegendListPropsBase, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type MaintainScrollAtEndOptions, type OnViewableItemsChanged, type ScrollIndexWithOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type ThresholdSnapshot, type TypedForwardRef, type TypedMemo, type ViewAmountToken, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, type ViewableRange, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };