@legendapp/list 2.1.0-beta.7 → 2.1.0-beta.8

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,5 +1,5 @@
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
 
@@ -102,6 +102,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
102
102
  * Extra data to trigger re-rendering when changed.
103
103
  */
104
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;
105
110
  /**
106
111
  * In case you have distinct item sizes, you can provide a function to get the size of an item.
107
112
  * Use instead of FlatList's getItemLayout or FlashList overrideItemLayout if you want to have accurate initialScrollOffset, you should provide this function
@@ -250,6 +255,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
250
255
  refreshing?: boolean;
251
256
  /**
252
257
  * Render custom ScrollView component.
258
+ * Note: When using `stickyHeaderIndices`, you must provide an Animated ScrollView component.
253
259
  * @default (props) => <ScrollView {...props} />
254
260
  */
255
261
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
@@ -312,6 +318,7 @@ interface ScrollTarget {
312
318
  viewPosition?: number;
313
319
  animated?: boolean;
314
320
  isInitialScroll?: boolean;
321
+ precomputedWithViewOffset?: boolean;
315
322
  }
316
323
  interface InternalState {
317
324
  positions: Map<string, number>;
@@ -339,6 +346,11 @@ interface InternalState {
339
346
  scrollPrev: number;
340
347
  scrollPrevTime: number;
341
348
  scrollAdjustHandler: ScrollAdjustHandler;
349
+ triggerCalculateItemsInView?: (params?: {
350
+ doMVCP?: boolean;
351
+ dataChanged?: boolean;
352
+ forceFullItemPositions?: boolean;
353
+ }) => void;
342
354
  maintainingScrollAtEnd?: boolean;
343
355
  totalSize: number;
344
356
  otherAxisSize?: number;
@@ -382,17 +394,17 @@ interface InternalState {
382
394
  }>;
383
395
  refScroller: React.RefObject<ScrollView>;
384
396
  loadStartTime: number;
385
- initialScroll: ScrollIndexWithOffset | undefined;
397
+ initialScroll: ScrollIndexWithOffsetAndContentOffset | undefined;
386
398
  lastLayout: LayoutRectangle | undefined;
387
399
  timeoutSetPaddingTop?: any;
388
400
  activeStickyIndex: number | undefined;
389
401
  stickyContainers: Map<number, number>;
390
402
  stickyContainerPool: Set<number>;
391
403
  scrollProcessingEnabled: boolean;
392
- isOptimizingItemPositions: boolean;
393
404
  props: {
394
405
  alignItemsAtEnd: boolean;
395
406
  data: readonly any[];
407
+ dataVersion: Key | undefined;
396
408
  estimatedItemSize: number | undefined;
397
409
  getEstimatedItemSize: LegendListProps["getEstimatedItemSize"];
398
410
  getFixedItemSize: LegendListProps["getFixedItemSize"];
@@ -630,6 +642,9 @@ interface ScrollIndexWithOffset {
630
642
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
631
643
  viewPosition: number;
632
644
  }
645
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
646
+ contentOffset?: number;
647
+ }
633
648
  type GetRenderedItemResult<ItemT> = {
634
649
  index: number;
635
650
  item: ItemT;
@@ -652,4 +667,4 @@ declare function useListScrollSize(): {
652
667
  };
653
668
  declare function useSyncLayout(): () => void;
654
669
 
655
- 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 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 };
670
+ 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,5 +1,5 @@
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
 
@@ -102,6 +102,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
102
102
  * Extra data to trigger re-rendering when changed.
103
103
  */
104
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;
105
110
  /**
106
111
  * In case you have distinct item sizes, you can provide a function to get the size of an item.
107
112
  * Use instead of FlatList's getItemLayout or FlashList overrideItemLayout if you want to have accurate initialScrollOffset, you should provide this function
@@ -250,6 +255,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
250
255
  refreshing?: boolean;
251
256
  /**
252
257
  * Render custom ScrollView component.
258
+ * Note: When using `stickyHeaderIndices`, you must provide an Animated ScrollView component.
253
259
  * @default (props) => <ScrollView {...props} />
254
260
  */
255
261
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
@@ -312,6 +318,7 @@ interface ScrollTarget {
312
318
  viewPosition?: number;
313
319
  animated?: boolean;
314
320
  isInitialScroll?: boolean;
321
+ precomputedWithViewOffset?: boolean;
315
322
  }
316
323
  interface InternalState {
317
324
  positions: Map<string, number>;
@@ -339,6 +346,11 @@ interface InternalState {
339
346
  scrollPrev: number;
340
347
  scrollPrevTime: number;
341
348
  scrollAdjustHandler: ScrollAdjustHandler;
349
+ triggerCalculateItemsInView?: (params?: {
350
+ doMVCP?: boolean;
351
+ dataChanged?: boolean;
352
+ forceFullItemPositions?: boolean;
353
+ }) => void;
342
354
  maintainingScrollAtEnd?: boolean;
343
355
  totalSize: number;
344
356
  otherAxisSize?: number;
@@ -382,17 +394,17 @@ interface InternalState {
382
394
  }>;
383
395
  refScroller: React.RefObject<ScrollView>;
384
396
  loadStartTime: number;
385
- initialScroll: ScrollIndexWithOffset | undefined;
397
+ initialScroll: ScrollIndexWithOffsetAndContentOffset | undefined;
386
398
  lastLayout: LayoutRectangle | undefined;
387
399
  timeoutSetPaddingTop?: any;
388
400
  activeStickyIndex: number | undefined;
389
401
  stickyContainers: Map<number, number>;
390
402
  stickyContainerPool: Set<number>;
391
403
  scrollProcessingEnabled: boolean;
392
- isOptimizingItemPositions: boolean;
393
404
  props: {
394
405
  alignItemsAtEnd: boolean;
395
406
  data: readonly any[];
407
+ dataVersion: Key | undefined;
396
408
  estimatedItemSize: number | undefined;
397
409
  getEstimatedItemSize: LegendListProps["getEstimatedItemSize"];
398
410
  getFixedItemSize: LegendListProps["getFixedItemSize"];
@@ -630,6 +642,9 @@ interface ScrollIndexWithOffset {
630
642
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
631
643
  viewPosition: number;
632
644
  }
645
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
646
+ contentOffset?: number;
647
+ }
633
648
  type GetRenderedItemResult<ItemT> = {
634
649
  index: number;
635
650
  item: ItemT;
@@ -652,4 +667,4 @@ declare function useListScrollSize(): {
652
667
  };
653
668
  declare function useSyncLayout(): () => void;
654
669
 
655
- 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 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 };
670
+ 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.js CHANGED
@@ -1196,26 +1196,6 @@ function calculateOffsetForIndex(ctx, state, index) {
1196
1196
  return position;
1197
1197
  }
1198
1198
 
1199
- // src/core/checkActualChange.ts
1200
- function checkActualChange(state, dataProp, previousData) {
1201
- if (!previousData || !dataProp || dataProp.length !== previousData.length) {
1202
- return true;
1203
- }
1204
- const {
1205
- idCache,
1206
- props: { keyExtractor }
1207
- } = state;
1208
- for (let i = 0; i < dataProp.length; i++) {
1209
- if (dataProp[i] !== previousData[i]) {
1210
- return true;
1211
- }
1212
- if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
1213
- return true;
1214
- }
1215
- }
1216
- return false;
1217
- }
1218
-
1219
1199
  // src/utils/setPaddingTop.ts
1220
1200
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1221
1201
  if (stylePaddingTop !== void 0) {
@@ -1305,7 +1285,7 @@ function setSize(ctx, state, itemKey, size) {
1305
1285
  }
1306
1286
 
1307
1287
  // src/utils/getItemSize.ts
1308
- function getItemSize(ctx, state, key, index, data, useAverageSize) {
1288
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1309
1289
  var _a3, _b;
1310
1290
  const {
1311
1291
  sizesKnown,
@@ -1320,6 +1300,12 @@ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1320
1300
  let size;
1321
1301
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1322
1302
  const scrollingTo = peek$(ctx, "scrollingTo");
1303
+ if (preferCachedSize) {
1304
+ const cachedSize = sizes.get(key);
1305
+ if (cachedSize !== void 0) {
1306
+ return cachedSize;
1307
+ }
1308
+ }
1323
1309
  if (getFixedItemSize) {
1324
1310
  size = getFixedItemSize(index, data, itemType);
1325
1311
  if (size !== void 0) {
@@ -1529,14 +1515,13 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1529
1515
 
1530
1516
  // src/core/finishScrollTo.ts
1531
1517
  function finishScrollTo(ctx, state) {
1532
- var _a3;
1518
+ var _a3, _b;
1533
1519
  if (state) {
1534
1520
  state.scrollHistory.length = 0;
1535
1521
  state.initialScroll = void 0;
1536
- state.isOptimizingItemPositions = false;
1537
1522
  set$(ctx, "scrollingTo", void 0);
1538
1523
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1539
- calculateItemsInView(ctx, state, { forceFullItemPositions: true });
1524
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1540
1525
  }
1541
1526
  }
1542
1527
  }
@@ -1545,14 +1530,14 @@ function finishScrollTo(ctx, state) {
1545
1530
  function scrollTo(ctx, state, params) {
1546
1531
  var _a3;
1547
1532
  const { noScrollingTo, ...scrollTarget } = params;
1548
- const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1533
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1549
1534
  const {
1550
1535
  refScroller,
1551
1536
  props: { horizontal }
1552
1537
  } = state;
1553
- let offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1538
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1554
1539
  if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1555
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
1540
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1556
1541
  offset = Math.min(offset, maxOffset);
1557
1542
  }
1558
1543
  state.scrollHistory.length = 0;
@@ -1784,14 +1769,14 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1784
1769
  scrollBottomBuffered: -1,
1785
1770
  startIndex: 0
1786
1771
  }) {
1787
- var _a3, _b, _c, _d;
1772
+ var _a3, _b, _c, _d, _e;
1788
1773
  const {
1789
1774
  columns,
1790
1775
  indexByKey,
1791
1776
  positions,
1792
1777
  idCache,
1793
1778
  sizesKnown,
1794
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1779
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1795
1780
  } = state;
1796
1781
  const data = state.props.data;
1797
1782
  const dataLength = data.length;
@@ -1800,9 +1785,9 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1800
1785
  const hasColumns = numColumns > 1;
1801
1786
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1802
1787
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1803
- state.isOptimizingItemPositions = shouldOptimize;
1804
1788
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1805
1789
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1790
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1806
1791
  let currentRowTop = 0;
1807
1792
  let column = 1;
1808
1793
  let maxSizeInRow = 0;
@@ -1819,8 +1804,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1819
1804
  } else if (startIndex < dataLength) {
1820
1805
  const prevIndex = startIndex - 1;
1821
1806
  const prevId = getId(state, prevIndex);
1822
- const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1823
- const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1807
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1808
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1824
1809
  currentRowTop = prevPosition + prevSize;
1825
1810
  }
1826
1811
  }
@@ -1836,8 +1821,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1836
1821
  const itemsPerRow = hasColumns ? numColumns : 1;
1837
1822
  breakAt = i + itemsPerRow + 10;
1838
1823
  }
1839
- const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1840
- const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1824
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1825
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1841
1826
  if (IS_DEV && needsIndexByKey) {
1842
1827
  if (indexByKeyForChecking.has(id)) {
1843
1828
  console.error(
@@ -2647,6 +2632,26 @@ function calculateItemsInView(ctx, state, params = {}) {
2647
2632
  });
2648
2633
  }
2649
2634
 
2635
+ // src/core/checkActualChange.ts
2636
+ function checkActualChange(state, dataProp, previousData) {
2637
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2638
+ return true;
2639
+ }
2640
+ const {
2641
+ idCache,
2642
+ props: { keyExtractor }
2643
+ } = state;
2644
+ for (let i = 0; i < dataProp.length; i++) {
2645
+ if (dataProp[i] !== previousData[i]) {
2646
+ return true;
2647
+ }
2648
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2649
+ return true;
2650
+ }
2651
+ }
2652
+ return false;
2653
+ }
2654
+
2650
2655
  // src/core/doMaintainScrollAtEnd.ts
2651
2656
  function doMaintainScrollAtEnd(ctx, state, animated) {
2652
2657
  const {
@@ -3162,6 +3167,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3162
3167
  columnWrapperStyle,
3163
3168
  contentContainerStyle: contentContainerStyleProp,
3164
3169
  data: dataProp = [],
3170
+ dataVersion,
3165
3171
  drawDistance = 250,
3166
3172
  enableAverages = true,
3167
3173
  estimatedItemSize: estimatedItemSizeProp,
@@ -3211,13 +3217,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3211
3217
  waitForInitialLayout = true,
3212
3218
  ...rest
3213
3219
  } = props;
3214
- const [renderNum, setRenderNum] = React3.useState(0);
3215
- const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: 0 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3216
- const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
3217
3220
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3218
3221
  const style = { ...StyleSheet.flatten(styleProp) };
3219
3222
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
3220
3223
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3224
+ const [renderNum, setRenderNum] = React3.useState(0);
3225
+ const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3226
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
3221
3227
  const ctx = useStateContext();
3222
3228
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
3223
3229
  const refScroller = React3.useRef(null);
@@ -3251,7 +3257,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3251
3257
  isAtStart: false,
3252
3258
  isEndReached: false,
3253
3259
  isFirst: true,
3254
- isOptimizingItemPositions: false,
3255
3260
  isStartReached: false,
3256
3261
  lastBatchingAction: Date.now(),
3257
3262
  lastLayout: void 0,
@@ -3284,6 +3289,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3284
3289
  totalSize: 0,
3285
3290
  viewabilityConfigCallbackPairs: void 0
3286
3291
  };
3292
+ const internalState = ctx.internalState;
3293
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3287
3294
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3288
3295
  set$(ctx, "extraData", extraData);
3289
3296
  }
@@ -3292,7 +3299,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3292
3299
  const state = refState.current;
3293
3300
  const isFirstLocal = state.isFirst;
3294
3301
  state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3295
- const didDataChangeLocal = state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3302
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3296
3303
  if (didDataChangeLocal) {
3297
3304
  state.dataChangeNeedsScrollUpdate = true;
3298
3305
  state.didDataChange = true;
@@ -3302,6 +3309,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3302
3309
  state.props = {
3303
3310
  alignItemsAtEnd,
3304
3311
  data: dataProp,
3312
+ dataVersion,
3305
3313
  enableAverages,
3306
3314
  estimatedItemSize,
3307
3315
  getEstimatedItemSize,
@@ -3340,7 +3348,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3340
3348
  { length: Math.min(numColumnsProp, dataProp.length) },
3341
3349
  (_, i) => getId(state, dataProp.length - 1 - i)
3342
3350
  );
3343
- }, [dataProp, numColumnsProp]);
3351
+ }, [dataProp, dataVersion, numColumnsProp]);
3344
3352
  const initializeStateVars = () => {
3345
3353
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3346
3354
  set$(ctx, "numColumns", numColumnsProp);
@@ -3366,17 +3374,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3366
3374
  }
3367
3375
  const initialContentOffset = React3.useMemo(() => {
3368
3376
  const { initialScroll } = refState.current;
3369
- if (initialScroll) {
3370
- const { index, viewOffset } = initialScroll;
3371
- let initialContentOffset2 = viewOffset || 0;
3372
- if (index !== void 0) {
3373
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3374
- }
3375
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3376
- return initialContentOffset2;
3377
- }
3378
- return 0;
3379
- }, [renderNum]);
3377
+ if (!initialScroll) {
3378
+ return 0;
3379
+ }
3380
+ if (initialScroll.contentOffset !== void 0) {
3381
+ return initialScroll.contentOffset;
3382
+ }
3383
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3384
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3385
+ let clampedOffset = resolvedOffset;
3386
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3387
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3388
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3389
+ }
3390
+ clampedOffset = Math.max(0, clampedOffset);
3391
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3392
+ refState.current.initialScroll = updatedInitialScroll;
3393
+ state.initialScroll = updatedInitialScroll;
3394
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3395
+ return clampedOffset;
3396
+ }, [renderNum, state.initialScroll]);
3380
3397
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3381
3398
  refState.current.lastBatchingAction = Date.now();
3382
3399
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
@@ -3403,9 +3420,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3403
3420
  }
3404
3421
  }, []);
3405
3422
  const doInitialScroll = React3.useCallback(() => {
3423
+ var _a4;
3406
3424
  const initialScroll = state.initialScroll;
3407
3425
  if (initialScroll) {
3408
- scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...state.initialScroll || {} });
3426
+ scrollTo(ctx, state, {
3427
+ animated: false,
3428
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3429
+ offset: initialContentOffset,
3430
+ precomputedWithViewOffset: true
3431
+ });
3409
3432
  }
3410
3433
  }, [initialContentOffset, state.initialScroll]);
3411
3434
  const onLayoutChange = React3.useCallback((layout) => {
@@ -3437,15 +3460,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3437
3460
  state.didColumnsChange = false;
3438
3461
  state.didDataChange = false;
3439
3462
  state.isFirst = false;
3440
- }, [dataProp, numColumnsProp]);
3463
+ }, [dataProp, dataVersion, numColumnsProp]);
3441
3464
  React3.useLayoutEffect(() => {
3442
3465
  set$(ctx, "extraData", extraData);
3443
3466
  }, [extraData]);
3444
3467
  React3.useLayoutEffect(initializeStateVars, [
3468
+ dataVersion,
3445
3469
  memoizedLastItemKeys.join(","),
3446
3470
  numColumnsProp,
3447
- stylePaddingTopState,
3448
- stylePaddingBottomState
3471
+ stylePaddingBottomState,
3472
+ stylePaddingTopState
3449
3473
  ]);
3450
3474
  React3.useEffect(() => {
3451
3475
  const viewability = setupViewability({