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

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/index.mjs CHANGED
@@ -292,6 +292,16 @@ function getPadding(s, type) {
292
292
  function extractPadding(style, contentContainerStyle, type) {
293
293
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
294
294
  }
295
+ function findContainerId(ctx, key) {
296
+ const numContainers = peek$(ctx, "numContainers");
297
+ for (let i = 0; i < numContainers; i++) {
298
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
299
+ if (itemKey === key) {
300
+ return i;
301
+ }
302
+ }
303
+ return -1;
304
+ }
295
305
 
296
306
  // src/state/ContextContainer.ts
297
307
  var ContextContainer = createContext(null);
@@ -1175,26 +1185,6 @@ function calculateOffsetForIndex(ctx, state, index) {
1175
1185
  return position;
1176
1186
  }
1177
1187
 
1178
- // src/core/checkActualChange.ts
1179
- function checkActualChange(state, dataProp, previousData) {
1180
- if (!previousData || !dataProp || dataProp.length !== previousData.length) {
1181
- return true;
1182
- }
1183
- const {
1184
- idCache,
1185
- props: { keyExtractor }
1186
- } = state;
1187
- for (let i = 0; i < dataProp.length; i++) {
1188
- if (dataProp[i] !== previousData[i]) {
1189
- return true;
1190
- }
1191
- if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
1192
- return true;
1193
- }
1194
- }
1195
- return false;
1196
- }
1197
-
1198
1188
  // src/utils/setPaddingTop.ts
1199
1189
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1200
1190
  if (stylePaddingTop !== void 0) {
@@ -1284,7 +1274,7 @@ function setSize(ctx, state, itemKey, size) {
1284
1274
  }
1285
1275
 
1286
1276
  // src/utils/getItemSize.ts
1287
- function getItemSize(ctx, state, key, index, data, useAverageSize) {
1277
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1288
1278
  var _a3, _b;
1289
1279
  const {
1290
1280
  sizesKnown,
@@ -1299,6 +1289,12 @@ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1299
1289
  let size;
1300
1290
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1301
1291
  const scrollingTo = peek$(ctx, "scrollingTo");
1292
+ if (preferCachedSize) {
1293
+ const cachedSize = sizes.get(key);
1294
+ if (cachedSize !== void 0) {
1295
+ return cachedSize;
1296
+ }
1297
+ }
1302
1298
  if (getFixedItemSize) {
1303
1299
  size = getFixedItemSize(index, data, itemType);
1304
1300
  if (size !== void 0) {
@@ -1508,14 +1504,13 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1508
1504
 
1509
1505
  // src/core/finishScrollTo.ts
1510
1506
  function finishScrollTo(ctx, state) {
1511
- var _a3;
1507
+ var _a3, _b;
1512
1508
  if (state) {
1513
1509
  state.scrollHistory.length = 0;
1514
1510
  state.initialScroll = void 0;
1515
- state.isOptimizingItemPositions = false;
1516
1511
  set$(ctx, "scrollingTo", void 0);
1517
1512
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1518
- calculateItemsInView(ctx, state, { forceFullItemPositions: true });
1513
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1519
1514
  }
1520
1515
  }
1521
1516
  }
@@ -1524,14 +1519,14 @@ function finishScrollTo(ctx, state) {
1524
1519
  function scrollTo(ctx, state, params) {
1525
1520
  var _a3;
1526
1521
  const { noScrollingTo, ...scrollTarget } = params;
1527
- const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1522
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1528
1523
  const {
1529
1524
  refScroller,
1530
1525
  props: { horizontal }
1531
1526
  } = state;
1532
- let offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1527
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1533
1528
  if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1534
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
1529
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1535
1530
  offset = Math.min(offset, maxOffset);
1536
1531
  }
1537
1532
  state.scrollHistory.length = 0;
@@ -1763,14 +1758,14 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1763
1758
  scrollBottomBuffered: -1,
1764
1759
  startIndex: 0
1765
1760
  }) {
1766
- var _a3, _b, _c, _d;
1761
+ var _a3, _b, _c, _d, _e;
1767
1762
  const {
1768
1763
  columns,
1769
1764
  indexByKey,
1770
1765
  positions,
1771
1766
  idCache,
1772
1767
  sizesKnown,
1773
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1768
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1774
1769
  } = state;
1775
1770
  const data = state.props.data;
1776
1771
  const dataLength = data.length;
@@ -1779,9 +1774,9 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1779
1774
  const hasColumns = numColumns > 1;
1780
1775
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1781
1776
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1782
- state.isOptimizingItemPositions = shouldOptimize;
1783
1777
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1784
1778
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1779
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1785
1780
  let currentRowTop = 0;
1786
1781
  let column = 1;
1787
1782
  let maxSizeInRow = 0;
@@ -1798,8 +1793,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1798
1793
  } else if (startIndex < dataLength) {
1799
1794
  const prevIndex = startIndex - 1;
1800
1795
  const prevId = getId(state, prevIndex);
1801
- const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1802
- const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1796
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1797
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1803
1798
  currentRowTop = prevPosition + prevSize;
1804
1799
  }
1805
1800
  }
@@ -1815,8 +1810,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1815
1810
  const itemsPerRow = hasColumns ? numColumns : 1;
1816
1811
  breakAt = i + itemsPerRow + 10;
1817
1812
  }
1818
- const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1819
- const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1813
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1814
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1820
1815
  if (IS_DEV && needsIndexByKey) {
1821
1816
  if (indexByKeyForChecking.has(id)) {
1822
1817
  console.error(
@@ -2034,16 +2029,6 @@ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize,
2034
2029
  const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2035
2030
  return value.isViewable;
2036
2031
  }
2037
- function findContainerId(ctx, key) {
2038
- const numContainers = peek$(ctx, "numContainers");
2039
- for (let i = 0; i < numContainers; i++) {
2040
- const itemKey = peek$(ctx, `containerItemKey${i}`);
2041
- if (itemKey === key) {
2042
- return i;
2043
- }
2044
- }
2045
- return -1;
2046
- }
2047
2032
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2048
2033
  const key = containerId + configId;
2049
2034
  ctx.mapViewabilityValues.set(key, viewToken);
@@ -2565,7 +2550,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2565
2550
  for (let i = 0; i < numContainers; i++) {
2566
2551
  const itemKey = peek$(ctx, `containerItemKey${i}`);
2567
2552
  if (pendingRemoval.includes(i)) {
2568
- if (itemKey) {
2553
+ if (itemKey !== void 0) {
2569
2554
  containerItemKeys.delete(itemKey);
2570
2555
  }
2571
2556
  state.containerItemTypes.delete(i);
@@ -2626,6 +2611,26 @@ function calculateItemsInView(ctx, state, params = {}) {
2626
2611
  });
2627
2612
  }
2628
2613
 
2614
+ // src/core/checkActualChange.ts
2615
+ function checkActualChange(state, dataProp, previousData) {
2616
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2617
+ return true;
2618
+ }
2619
+ const {
2620
+ idCache,
2621
+ props: { keyExtractor }
2622
+ } = state;
2623
+ for (let i = 0; i < dataProp.length; i++) {
2624
+ if (dataProp[i] !== previousData[i]) {
2625
+ return true;
2626
+ }
2627
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2628
+ return true;
2629
+ }
2630
+ }
2631
+ return false;
2632
+ }
2633
+
2629
2634
  // src/core/doMaintainScrollAtEnd.ts
2630
2635
  function doMaintainScrollAtEnd(ctx, state, animated) {
2631
2636
  const {
@@ -3141,6 +3146,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3141
3146
  columnWrapperStyle,
3142
3147
  contentContainerStyle: contentContainerStyleProp,
3143
3148
  data: dataProp = [],
3149
+ dataVersion,
3144
3150
  drawDistance = 250,
3145
3151
  enableAverages = true,
3146
3152
  estimatedItemSize: estimatedItemSizeProp,
@@ -3190,13 +3196,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3190
3196
  waitForInitialLayout = true,
3191
3197
  ...rest
3192
3198
  } = props;
3193
- const [renderNum, setRenderNum] = useState(0);
3194
- 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;
3195
- const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
3196
3199
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3197
3200
  const style = { ...StyleSheet.flatten(styleProp) };
3198
3201
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
3199
3202
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3203
+ const [renderNum, setRenderNum] = useState(0);
3204
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, 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;
3205
+ const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
3200
3206
  const ctx = useStateContext();
3201
3207
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
3202
3208
  const refScroller = useRef(null);
@@ -3230,7 +3236,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3230
3236
  isAtStart: false,
3231
3237
  isEndReached: false,
3232
3238
  isFirst: true,
3233
- isOptimizingItemPositions: false,
3234
3239
  isStartReached: false,
3235
3240
  lastBatchingAction: Date.now(),
3236
3241
  lastLayout: void 0,
@@ -3263,6 +3268,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3263
3268
  totalSize: 0,
3264
3269
  viewabilityConfigCallbackPairs: void 0
3265
3270
  };
3271
+ const internalState = ctx.internalState;
3272
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3266
3273
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3267
3274
  set$(ctx, "extraData", extraData);
3268
3275
  }
@@ -3271,7 +3278,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3271
3278
  const state = refState.current;
3272
3279
  const isFirstLocal = state.isFirst;
3273
3280
  state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3274
- const didDataChangeLocal = state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3281
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3275
3282
  if (didDataChangeLocal) {
3276
3283
  state.dataChangeNeedsScrollUpdate = true;
3277
3284
  state.didDataChange = true;
@@ -3281,6 +3288,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3281
3288
  state.props = {
3282
3289
  alignItemsAtEnd,
3283
3290
  data: dataProp,
3291
+ dataVersion,
3284
3292
  enableAverages,
3285
3293
  estimatedItemSize,
3286
3294
  getEstimatedItemSize,
@@ -3319,7 +3327,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3319
3327
  { length: Math.min(numColumnsProp, dataProp.length) },
3320
3328
  (_, i) => getId(state, dataProp.length - 1 - i)
3321
3329
  );
3322
- }, [dataProp, numColumnsProp]);
3330
+ }, [dataProp, dataVersion, numColumnsProp]);
3323
3331
  const initializeStateVars = () => {
3324
3332
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3325
3333
  set$(ctx, "numColumns", numColumnsProp);
@@ -3345,17 +3353,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3345
3353
  }
3346
3354
  const initialContentOffset = useMemo(() => {
3347
3355
  const { initialScroll } = refState.current;
3348
- if (initialScroll) {
3349
- const { index, viewOffset } = initialScroll;
3350
- let initialContentOffset2 = viewOffset || 0;
3351
- if (index !== void 0) {
3352
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3353
- }
3354
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3355
- return initialContentOffset2;
3356
- }
3357
- return 0;
3358
- }, [renderNum]);
3356
+ if (!initialScroll) {
3357
+ return 0;
3358
+ }
3359
+ if (initialScroll.contentOffset !== void 0) {
3360
+ return initialScroll.contentOffset;
3361
+ }
3362
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3363
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3364
+ let clampedOffset = resolvedOffset;
3365
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3366
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3367
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3368
+ }
3369
+ clampedOffset = Math.max(0, clampedOffset);
3370
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3371
+ refState.current.initialScroll = updatedInitialScroll;
3372
+ state.initialScroll = updatedInitialScroll;
3373
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3374
+ return clampedOffset;
3375
+ }, [renderNum, state.initialScroll]);
3359
3376
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3360
3377
  refState.current.lastBatchingAction = Date.now();
3361
3378
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
@@ -3382,9 +3399,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3382
3399
  }
3383
3400
  }, []);
3384
3401
  const doInitialScroll = useCallback(() => {
3402
+ var _a4;
3385
3403
  const initialScroll = state.initialScroll;
3386
3404
  if (initialScroll) {
3387
- scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...state.initialScroll || {} });
3405
+ scrollTo(ctx, state, {
3406
+ animated: false,
3407
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3408
+ offset: initialContentOffset,
3409
+ precomputedWithViewOffset: true
3410
+ });
3388
3411
  }
3389
3412
  }, [initialContentOffset, state.initialScroll]);
3390
3413
  const onLayoutChange = useCallback((layout) => {
@@ -3416,15 +3439,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3416
3439
  state.didColumnsChange = false;
3417
3440
  state.didDataChange = false;
3418
3441
  state.isFirst = false;
3419
- }, [dataProp, numColumnsProp]);
3442
+ }, [dataProp, dataVersion, numColumnsProp]);
3420
3443
  useLayoutEffect(() => {
3421
3444
  set$(ctx, "extraData", extraData);
3422
3445
  }, [extraData]);
3423
3446
  useLayoutEffect(initializeStateVars, [
3447
+ dataVersion,
3424
3448
  memoizedLastItemKeys.join(","),
3425
3449
  numColumnsProp,
3426
- stylePaddingTopState,
3427
- stylePaddingBottomState
3450
+ stylePaddingBottomState,
3451
+ stylePaddingTopState
3428
3452
  ]);
3429
3453
  useEffect(() => {
3430
3454
  const viewability = setupViewability({
@@ -3462,6 +3486,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3462
3486
  activeStickyIndex: state2.activeStickyIndex,
3463
3487
  contentLength: state2.totalSize,
3464
3488
  data: state2.props.data,
3489
+ elementAtIndex: (index) => {
3490
+ var _a4;
3491
+ return (_a4 = ctx.viewRefs.get(findContainerId(ctx, getId(state2, index)))) == null ? void 0 : _a4.current;
3492
+ },
3465
3493
  end: state2.endNoBuffer,
3466
3494
  endBuffered: state2.endBuffered,
3467
3495
  isAtEnd: state2.isAtEnd,
@@ -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 Reanimated 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"];
@@ -443,6 +455,7 @@ type ScrollState = {
443
455
  activeStickyIndex: number | undefined;
444
456
  contentLength: number;
445
457
  data: readonly any[];
458
+ elementAtIndex: (index: number) => View | null | undefined;
446
459
  end: number;
447
460
  endBuffered: number;
448
461
  isAtEnd: boolean;
@@ -630,6 +643,9 @@ interface ScrollIndexWithOffset {
630
643
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
631
644
  viewPosition: number;
632
645
  }
646
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
647
+ contentOffset?: number;
648
+ }
633
649
  type GetRenderedItemResult<ItemT> = {
634
650
  index: number;
635
651
  item: ItemT;
@@ -652,4 +668,4 @@ declare function useListScrollSize(): {
652
668
  };
653
669
  declare function useSyncLayout(): () => void;
654
670
 
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 };
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.native.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 Reanimated 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"];
@@ -443,6 +455,7 @@ type ScrollState = {
443
455
  activeStickyIndex: number | undefined;
444
456
  contentLength: number;
445
457
  data: readonly any[];
458
+ elementAtIndex: (index: number) => View | null | undefined;
446
459
  end: number;
447
460
  endBuffered: number;
448
461
  isAtEnd: boolean;
@@ -630,6 +643,9 @@ interface ScrollIndexWithOffset {
630
643
  interface ScrollIndexWithOffsetPosition extends ScrollIndexWithOffset {
631
644
  viewPosition: number;
632
645
  }
646
+ interface ScrollIndexWithOffsetAndContentOffset extends ScrollIndexWithOffset {
647
+ contentOffset?: number;
648
+ }
633
649
  type GetRenderedItemResult<ItemT> = {
634
650
  index: number;
635
651
  item: ItemT;
@@ -652,4 +668,4 @@ declare function useListScrollSize(): {
652
668
  };
653
669
  declare function useSyncLayout(): () => void;
654
670
 
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 };
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 };