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

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,6 @@
1
+ ## 2.0.14
2
+ - Feat: Add dataVersion prop to trigger re-render when mutating the data array in place
3
+
1
4
  ## 2.0.13
2
5
  - Feat: Allow returning undefined in getFixedItemSize to fall back to estimated size
3
6
  - Fix: scrollToIndex viewOffset was being subtracted twice, causing incorrect scroll positioning
package/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as React$1 from 'react';
2
- import { ComponentProps, ReactNode, Dispatch, SetStateAction } from 'react';
2
+ import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
3
  import { View, ScrollView, Animated, LayoutRectangle, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent, ScrollViewProps } from 'react-native';
4
4
  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" | "lastPositionUpdate" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize";
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" | "scrollAdjustPending" | "scrollingTo" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize" | "activeStickyIndex";
9
9
  interface StateContext {
10
10
  internalState: InternalState | undefined;
11
11
  listeners: Map<ListenerType, Set<(value: any) => void>>;
@@ -28,6 +28,7 @@ interface StateContext {
28
28
 
29
29
  declare class ScrollAdjustHandler {
30
30
  private appliedAdjust;
31
+ private pendingAdjust;
31
32
  private context;
32
33
  private mounted;
33
34
  constructor(ctx: StateContext);
@@ -36,7 +37,7 @@ declare class ScrollAdjustHandler {
36
37
  getAdjust(): number;
37
38
  }
38
39
 
39
- type BaseScrollViewProps<TScrollView> = Omit<TScrollView, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children" | "onScroll">;
40
+ type BaseScrollViewProps<TScrollView> = Omit<TScrollView, "contentOffset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children" | "onScroll">;
40
41
  interface DataModeProps<ItemT, TItemType extends string | undefined> {
41
42
  /**
42
43
  * Array of items to render in the list.
@@ -101,6 +102,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
101
102
  * Extra data to trigger re-rendering when changed.
102
103
  */
103
104
  extraData?: any;
105
+ /**
106
+ * Version token that forces the list to treat data as updated even when the array reference is stable.
107
+ * Increment or change this when mutating the data array in place.
108
+ */
109
+ dataVersion?: Key;
104
110
  /**
105
111
  * In case you have distinct item sizes, you can provide a function to get the size of an item.
106
112
  * Use instead of FlatList's getItemLayout or FlashList overrideItemLayout if you want to have accurate initialScrollOffset, you should provide this function
@@ -124,6 +130,12 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
124
130
  index: number;
125
131
  viewOffset?: number | undefined;
126
132
  };
133
+ /**
134
+ * When true, the list initializes scrolled to the last item.
135
+ * Overrides `initialScrollIndex` and `initialScrollOffset` when data is available.
136
+ * @default false
137
+ */
138
+ initialScrollAtEnd?: boolean;
127
139
  /**
128
140
  * Component to render between items, receiving the leading item as prop.
129
141
  */
@@ -213,7 +225,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
213
225
  onStartReachedThreshold?: number | null | undefined;
214
226
  /**
215
227
  * Called when the sticky header changes.
216
- */
228
+ */
217
229
  onStickyHeaderChange?: (info: {
218
230
  index: number;
219
231
  item: any;
@@ -243,6 +255,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
243
255
  refreshing?: boolean;
244
256
  /**
245
257
  * Render custom ScrollView component.
258
+ * Note: When using `stickyHeaderIndices`, you must provide an Animated ScrollView component.
246
259
  * @default (props) => <ScrollView {...props} />
247
260
  */
248
261
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
@@ -298,6 +311,15 @@ interface ThresholdSnapshot {
298
311
  dataLength?: number;
299
312
  atThreshold: boolean;
300
313
  }
314
+ interface ScrollTarget {
315
+ offset: number;
316
+ index?: number;
317
+ viewOffset?: number;
318
+ viewPosition?: number;
319
+ animated?: boolean;
320
+ isInitialScroll?: boolean;
321
+ precomputedWithViewOffset?: boolean;
322
+ }
301
323
  interface InternalState {
302
324
  positions: Map<string, number>;
303
325
  columns: Map<string, number>;
@@ -324,6 +346,11 @@ interface InternalState {
324
346
  scrollPrev: number;
325
347
  scrollPrevTime: number;
326
348
  scrollAdjustHandler: ScrollAdjustHandler;
349
+ triggerCalculateItemsInView?: (params?: {
350
+ doMVCP?: boolean;
351
+ dataChanged?: boolean;
352
+ forceFullItemPositions?: boolean;
353
+ }) => void;
327
354
  maintainingScrollAtEnd?: boolean;
328
355
  totalSize: number;
329
356
  otherAxisSize?: number;
@@ -349,20 +376,17 @@ interface InternalState {
349
376
  queuedInitialLayout?: boolean | undefined;
350
377
  queuedCalculateItemsInView: number | undefined;
351
378
  dataChangeNeedsScrollUpdate: boolean;
379
+ previousData?: readonly unknown[];
380
+ didColumnsChange?: boolean;
381
+ didDataChange?: boolean;
382
+ isFirst?: boolean;
352
383
  lastBatchingAction: number;
353
384
  ignoreScrollFromMVCP?: {
354
385
  lt?: number;
355
386
  gt?: number;
356
387
  };
388
+ ignoreScrollFromMVCPIgnored?: boolean;
357
389
  ignoreScrollFromMVCPTimeout?: any;
358
- scrollingTo?: {
359
- offset: number;
360
- index?: number;
361
- viewOffset?: number;
362
- viewPosition?: number;
363
- animated?: boolean;
364
- isInitialScroll?: boolean;
365
- } | undefined;
366
390
  needsOtherAxisSize?: boolean;
367
391
  averageSizes: Record<string, {
368
392
  num: number;
@@ -370,7 +394,7 @@ interface InternalState {
370
394
  }>;
371
395
  refScroller: React.RefObject<ScrollView>;
372
396
  loadStartTime: number;
373
- initialScroll: ScrollIndexWithOffset | undefined;
397
+ initialScroll: ScrollIndexWithOffsetAndContentOffset | undefined;
374
398
  lastLayout: LayoutRectangle | undefined;
375
399
  timeoutSetPaddingTop?: any;
376
400
  activeStickyIndex: number | undefined;
@@ -380,6 +404,7 @@ interface InternalState {
380
404
  props: {
381
405
  alignItemsAtEnd: boolean;
382
406
  data: readonly any[];
407
+ dataVersion: Key | undefined;
383
408
  estimatedItemSize: number | undefined;
384
409
  getEstimatedItemSize: LegendListProps["getEstimatedItemSize"];
385
410
  getFixedItemSize: LegendListProps["getFixedItemSize"];
@@ -401,7 +426,6 @@ interface InternalState {
401
426
  suggestEstimatedItemSize: boolean;
402
427
  stylePaddingBottom: number | undefined;
403
428
  renderItem: LegendListProps["renderItem"];
404
- initialScroll: ScrollIndexWithOffset | undefined;
405
429
  scrollBuffer: number;
406
430
  numColumns: number;
407
431
  initialContainerPoolRatio: number;
@@ -431,6 +455,7 @@ type ScrollState = {
431
455
  activeStickyIndex: number | undefined;
432
456
  contentLength: number;
433
457
  data: readonly any[];
458
+ elementAtIndex: (index: number) => View | null | undefined;
434
459
  end: number;
435
460
  endBuffered: number;
436
461
  isAtEnd: boolean;
@@ -618,6 +643,9 @@ interface ScrollIndexWithOffset {
618
643
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
619
644
  viewPosition: number;
620
645
  }
646
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
647
+ contentOffset?: number;
648
+ }
621
649
  type GetRenderedItemResult<ItemT> = {
622
650
  index: number;
623
651
  item: ItemT;
@@ -640,4 +668,4 @@ declare function useListScrollSize(): {
640
668
  };
641
669
  declare function useSyncLayout(): () => void;
642
670
 
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 };
671
+ 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 ScrollIndexWithOffsetAndContentOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type ScrollTarget, 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
@@ -1,11 +1,11 @@
1
1
  import * as React$1 from 'react';
2
- import { ComponentProps, ReactNode, Dispatch, SetStateAction } from 'react';
2
+ import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
3
  import { View, ScrollView, Animated, LayoutRectangle, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent, ScrollViewProps } from 'react-native';
4
4
  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" | "lastPositionUpdate" | "stylePaddingTop" | "scrollAdjust" | "scrollAdjustUserOffset" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize";
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" | "scrollAdjustPending" | "scrollingTo" | "headerSize" | "footerSize" | "maintainVisibleContentPosition" | "debugRawScroll" | "debugComputedScroll" | "otherAxisSize" | "snapToOffsets" | "scrollSize" | "activeStickyIndex";
9
9
  interface StateContext {
10
10
  internalState: InternalState | undefined;
11
11
  listeners: Map<ListenerType, Set<(value: any) => void>>;
@@ -28,6 +28,7 @@ interface StateContext {
28
28
 
29
29
  declare class ScrollAdjustHandler {
30
30
  private appliedAdjust;
31
+ private pendingAdjust;
31
32
  private context;
32
33
  private mounted;
33
34
  constructor(ctx: StateContext);
@@ -36,7 +37,7 @@ declare class ScrollAdjustHandler {
36
37
  getAdjust(): number;
37
38
  }
38
39
 
39
- type BaseScrollViewProps<TScrollView> = Omit<TScrollView, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children" | "onScroll">;
40
+ type BaseScrollViewProps<TScrollView> = Omit<TScrollView, "contentOffset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children" | "onScroll">;
40
41
  interface DataModeProps<ItemT, TItemType extends string | undefined> {
41
42
  /**
42
43
  * Array of items to render in the list.
@@ -101,6 +102,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
101
102
  * Extra data to trigger re-rendering when changed.
102
103
  */
103
104
  extraData?: any;
105
+ /**
106
+ * Version token that forces the list to treat data as updated even when the array reference is stable.
107
+ * Increment or change this when mutating the data array in place.
108
+ */
109
+ dataVersion?: Key;
104
110
  /**
105
111
  * In case you have distinct item sizes, you can provide a function to get the size of an item.
106
112
  * Use instead of FlatList's getItemLayout or FlashList overrideItemLayout if you want to have accurate initialScrollOffset, you should provide this function
@@ -124,6 +130,12 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
124
130
  index: number;
125
131
  viewOffset?: number | undefined;
126
132
  };
133
+ /**
134
+ * When true, the list initializes scrolled to the last item.
135
+ * Overrides `initialScrollIndex` and `initialScrollOffset` when data is available.
136
+ * @default false
137
+ */
138
+ initialScrollAtEnd?: boolean;
127
139
  /**
128
140
  * Component to render between items, receiving the leading item as prop.
129
141
  */
@@ -213,7 +225,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
213
225
  onStartReachedThreshold?: number | null | undefined;
214
226
  /**
215
227
  * Called when the sticky header changes.
216
- */
228
+ */
217
229
  onStickyHeaderChange?: (info: {
218
230
  index: number;
219
231
  item: any;
@@ -243,6 +255,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
243
255
  refreshing?: boolean;
244
256
  /**
245
257
  * Render custom ScrollView component.
258
+ * Note: When using `stickyHeaderIndices`, you must provide an Animated ScrollView component.
246
259
  * @default (props) => <ScrollView {...props} />
247
260
  */
248
261
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
@@ -298,6 +311,15 @@ interface ThresholdSnapshot {
298
311
  dataLength?: number;
299
312
  atThreshold: boolean;
300
313
  }
314
+ interface ScrollTarget {
315
+ offset: number;
316
+ index?: number;
317
+ viewOffset?: number;
318
+ viewPosition?: number;
319
+ animated?: boolean;
320
+ isInitialScroll?: boolean;
321
+ precomputedWithViewOffset?: boolean;
322
+ }
301
323
  interface InternalState {
302
324
  positions: Map<string, number>;
303
325
  columns: Map<string, number>;
@@ -324,6 +346,11 @@ interface InternalState {
324
346
  scrollPrev: number;
325
347
  scrollPrevTime: number;
326
348
  scrollAdjustHandler: ScrollAdjustHandler;
349
+ triggerCalculateItemsInView?: (params?: {
350
+ doMVCP?: boolean;
351
+ dataChanged?: boolean;
352
+ forceFullItemPositions?: boolean;
353
+ }) => void;
327
354
  maintainingScrollAtEnd?: boolean;
328
355
  totalSize: number;
329
356
  otherAxisSize?: number;
@@ -349,20 +376,17 @@ interface InternalState {
349
376
  queuedInitialLayout?: boolean | undefined;
350
377
  queuedCalculateItemsInView: number | undefined;
351
378
  dataChangeNeedsScrollUpdate: boolean;
379
+ previousData?: readonly unknown[];
380
+ didColumnsChange?: boolean;
381
+ didDataChange?: boolean;
382
+ isFirst?: boolean;
352
383
  lastBatchingAction: number;
353
384
  ignoreScrollFromMVCP?: {
354
385
  lt?: number;
355
386
  gt?: number;
356
387
  };
388
+ ignoreScrollFromMVCPIgnored?: boolean;
357
389
  ignoreScrollFromMVCPTimeout?: any;
358
- scrollingTo?: {
359
- offset: number;
360
- index?: number;
361
- viewOffset?: number;
362
- viewPosition?: number;
363
- animated?: boolean;
364
- isInitialScroll?: boolean;
365
- } | undefined;
366
390
  needsOtherAxisSize?: boolean;
367
391
  averageSizes: Record<string, {
368
392
  num: number;
@@ -370,7 +394,7 @@ interface InternalState {
370
394
  }>;
371
395
  refScroller: React.RefObject<ScrollView>;
372
396
  loadStartTime: number;
373
- initialScroll: ScrollIndexWithOffset | undefined;
397
+ initialScroll: ScrollIndexWithOffsetAndContentOffset | undefined;
374
398
  lastLayout: LayoutRectangle | undefined;
375
399
  timeoutSetPaddingTop?: any;
376
400
  activeStickyIndex: number | undefined;
@@ -380,6 +404,7 @@ interface InternalState {
380
404
  props: {
381
405
  alignItemsAtEnd: boolean;
382
406
  data: readonly any[];
407
+ dataVersion: Key | undefined;
383
408
  estimatedItemSize: number | undefined;
384
409
  getEstimatedItemSize: LegendListProps["getEstimatedItemSize"];
385
410
  getFixedItemSize: LegendListProps["getFixedItemSize"];
@@ -401,7 +426,6 @@ interface InternalState {
401
426
  suggestEstimatedItemSize: boolean;
402
427
  stylePaddingBottom: number | undefined;
403
428
  renderItem: LegendListProps["renderItem"];
404
- initialScroll: ScrollIndexWithOffset | undefined;
405
429
  scrollBuffer: number;
406
430
  numColumns: number;
407
431
  initialContainerPoolRatio: number;
@@ -431,6 +455,7 @@ type ScrollState = {
431
455
  activeStickyIndex: number | undefined;
432
456
  contentLength: number;
433
457
  data: readonly any[];
458
+ elementAtIndex: (index: number) => View | null | undefined;
434
459
  end: number;
435
460
  endBuffered: number;
436
461
  isAtEnd: boolean;
@@ -618,6 +643,9 @@ interface ScrollIndexWithOffset {
618
643
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
619
644
  viewPosition: number;
620
645
  }
646
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
647
+ contentOffset?: number;
648
+ }
621
649
  type GetRenderedItemResult<ItemT> = {
622
650
  index: number;
623
651
  item: ItemT;
@@ -640,4 +668,4 @@ declare function useListScrollSize(): {
640
668
  };
641
669
  declare function useSyncLayout(): () => void;
642
670
 
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 };
671
+ 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 ScrollIndexWithOffsetAndContentOffset, type ScrollIndexWithOffsetPosition, type ScrollState, type ScrollTarget, 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 };