@legendapp/list 2.0.0-next.15 → 2.0.0-next.17

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/animated.d.mts CHANGED
@@ -69,6 +69,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Om
69
69
  stickyIndices?: number[];
70
70
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
71
71
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
72
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
72
73
  } & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode)>;
73
74
 
74
75
  export { AnimatedLegendList };
package/animated.d.ts CHANGED
@@ -69,6 +69,7 @@ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Om
69
69
  stickyIndices?: number[];
70
70
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
71
71
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
72
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
72
73
  } & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode)>;
73
74
 
74
75
  export { AnimatedLegendList };
package/index.d.mts CHANGED
@@ -243,6 +243,7 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
243
243
  stickyIndices?: number[];
244
244
  getItemType?: (item: ItemT, index: number) => TItemType;
245
245
  getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number;
246
+ itemsAreEqual?: (itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean;
246
247
  };
247
248
  interface MaintainScrollAtEndOptions {
248
249
  onLayout?: boolean;
@@ -339,6 +340,7 @@ interface InternalState {
339
340
  activeStickyIndex: number | undefined;
340
341
  stickyContainers: Map<number, number>;
341
342
  stickyContainerPool: Set<number>;
343
+ scrollProcessingEnabled: boolean;
342
344
  props: {
343
345
  alignItemsAtEnd: boolean;
344
346
  data: readonly any[];
@@ -374,6 +376,7 @@ interface InternalState {
374
376
  snapToIndices: number[] | undefined;
375
377
  stickyIndicesSet: Set<number>;
376
378
  stickyIndicesArr: number[];
379
+ itemsAreEqual: LegendListProps["itemsAreEqual"];
377
380
  };
378
381
  }
379
382
  interface ViewableRange<T> {
@@ -500,6 +503,11 @@ type LegendListRef = {
500
503
  * @param animated - If true, uses Animated to animate the change.
501
504
  */
502
505
  setVisibleContentAnchorOffset(value: number | ((value: number) => number)): void;
506
+ /**
507
+ * Sets whether scroll processing is enabled.
508
+ * @param enabled - If true, scroll processing is enabled.
509
+ */
510
+ setScrollProcessingEnabled(enabled: boolean): void;
503
511
  };
504
512
  interface ViewToken<ItemT = any> {
505
513
  item: ItemT;
@@ -649,6 +657,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
649
657
  stickyIndices?: number[];
650
658
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
651
659
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
660
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
652
661
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode) | react_native.Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
653
662
  alignItemsAtEnd?: boolean;
654
663
  columnWrapperStyle?: ColumnWrapperStyle;
@@ -715,6 +724,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
715
724
  stickyIndices?: number[];
716
725
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
717
726
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
727
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
718
728
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode)> | (<ItemT_1>(props: _legendapp_list_reanimated.AnimatedLegendListProps<ItemT_1> & {
719
729
  ref?: React$1.Ref<LegendListRef>;
720
730
  }) => React$1.ReactElement | null) = <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -783,6 +793,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
783
793
  stickyIndices?: number[];
784
794
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
785
795
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
796
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
786
797
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode>(props: LazyLegendListProps<ItemT, ListT> & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode;
787
798
 
788
799
  declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -851,6 +862,7 @@ declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "sc
851
862
  stickyIndices?: number[];
852
863
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
853
864
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
865
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
854
866
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode;
855
867
 
856
868
  declare function useViewability(callback: ViewabilityCallback, configId?: string): void;
package/index.d.ts CHANGED
@@ -243,6 +243,7 @@ type LegendListPropsBase<ItemT, TScrollView extends ComponentProps<typeof Scroll
243
243
  stickyIndices?: number[];
244
244
  getItemType?: (item: ItemT, index: number) => TItemType;
245
245
  getFixedItemSize?: (index: number, item: ItemT, type: TItemType) => number;
246
+ itemsAreEqual?: (itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean;
246
247
  };
247
248
  interface MaintainScrollAtEndOptions {
248
249
  onLayout?: boolean;
@@ -339,6 +340,7 @@ interface InternalState {
339
340
  activeStickyIndex: number | undefined;
340
341
  stickyContainers: Map<number, number>;
341
342
  stickyContainerPool: Set<number>;
343
+ scrollProcessingEnabled: boolean;
342
344
  props: {
343
345
  alignItemsAtEnd: boolean;
344
346
  data: readonly any[];
@@ -374,6 +376,7 @@ interface InternalState {
374
376
  snapToIndices: number[] | undefined;
375
377
  stickyIndicesSet: Set<number>;
376
378
  stickyIndicesArr: number[];
379
+ itemsAreEqual: LegendListProps["itemsAreEqual"];
377
380
  };
378
381
  }
379
382
  interface ViewableRange<T> {
@@ -500,6 +503,11 @@ type LegendListRef = {
500
503
  * @param animated - If true, uses Animated to animate the change.
501
504
  */
502
505
  setVisibleContentAnchorOffset(value: number | ((value: number) => number)): void;
506
+ /**
507
+ * Sets whether scroll processing is enabled.
508
+ * @param enabled - If true, scroll processing is enabled.
509
+ */
510
+ setScrollProcessingEnabled(enabled: boolean): void;
503
511
  };
504
512
  interface ViewToken<ItemT = any> {
505
513
  item: ItemT;
@@ -649,6 +657,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
649
657
  stickyIndices?: number[];
650
658
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
651
659
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
660
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
652
661
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode) | react_native.Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
653
662
  alignItemsAtEnd?: boolean;
654
663
  columnWrapperStyle?: ColumnWrapperStyle;
@@ -715,6 +724,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
715
724
  stickyIndices?: number[];
716
725
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
717
726
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
727
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
718
728
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode)> | (<ItemT_1>(props: _legendapp_list_reanimated.AnimatedLegendListProps<ItemT_1> & {
719
729
  ref?: React$1.Ref<LegendListRef>;
720
730
  }) => React$1.ReactElement | null) = <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -783,6 +793,7 @@ declare const LazyLegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_
783
793
  stickyIndices?: number[];
784
794
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
785
795
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
796
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
786
797
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode>(props: LazyLegendListProps<ItemT, ListT> & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode;
787
798
 
788
799
  declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -851,6 +862,7 @@ declare const LegendList: <T>(props: Omit<Omit<react_native.ScrollViewProps, "sc
851
862
  stickyIndices?: number[];
852
863
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
853
864
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
865
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
854
866
  } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode;
855
867
 
856
868
  declare function useViewability(callback: ViewabilityCallback, configId?: string): void;
package/index.js CHANGED
@@ -298,7 +298,6 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
298
298
  return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
299
299
  }
300
300
  }, [position, horizontal, animatedScrollY, stickyOffset]);
301
- console.log("index", index, position, transform);
302
301
  const viewStyle = React3__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
303
302
  return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
304
303
  });
@@ -1188,11 +1187,6 @@ function updateAllPositions(ctx, state, dataChanged) {
1188
1187
  const numColumns = peek$(ctx, "numColumns");
1189
1188
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1190
1189
  const scrollVelocity = getScrollVelocity(state);
1191
- if (dataChanged) {
1192
- indexByKey.clear();
1193
- idCache.clear();
1194
- positions.clear();
1195
- }
1196
1190
  const useAverageSize = false;
1197
1191
  const itemType = "";
1198
1192
  let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
@@ -1708,9 +1702,11 @@ function setDidLayout(ctx, state) {
1708
1702
  // src/core/calculateItemsInView.ts
1709
1703
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1710
1704
  var _a;
1705
+ const idCache = state.idCache;
1706
+ const positions = state.positions;
1711
1707
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1712
- const stickyId = (_a = state.idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1713
- const stickyPos = stickyId ? state.positions.get(stickyId) : void 0;
1708
+ const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1709
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1714
1710
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1715
1711
  return i;
1716
1712
  }
@@ -1770,17 +1766,19 @@ function calculateItemsInView(ctx, state, params = {}) {
1770
1766
  reactNative.unstable_batchedUpdates(() => {
1771
1767
  var _a, _b, _c, _d, _e, _f, _g, _h;
1772
1768
  const {
1773
- scrollLength,
1774
- startBufferedId: startBufferedIdOrig,
1775
- positions,
1776
1769
  columns,
1777
1770
  containerItemKeys,
1771
+ enableScrollForNextCalculateItemsInView,
1778
1772
  idCache,
1779
- sizes,
1780
1773
  indexByKey,
1774
+ minIndexSizeChanged,
1775
+ positions,
1781
1776
  scrollForNextCalculateItemsInView,
1782
- enableScrollForNextCalculateItemsInView,
1783
- minIndexSizeChanged
1777
+ scrollLength,
1778
+ sizes,
1779
+ startBufferedId: startBufferedIdOrig,
1780
+ viewabilityConfigCallbackPairs,
1781
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1784
1782
  } = state;
1785
1783
  const { data, stickyIndicesArr, stickyIndicesSet } = state.props;
1786
1784
  const prevNumContainers = peek$(ctx, "numContainers");
@@ -1795,13 +1793,17 @@ function calculateItemsInView(ctx, state, params = {}) {
1795
1793
  const speed = getScrollVelocity(state);
1796
1794
  if (doMVCP || dataChanged) {
1797
1795
  const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1796
+ if (dataChanged) {
1797
+ indexByKey.clear();
1798
+ idCache.clear();
1799
+ positions.clear();
1800
+ }
1798
1801
  updateAllPositions(ctx, state, dataChanged);
1799
1802
  checkMVCP == null ? void 0 : checkMVCP();
1800
1803
  }
1801
1804
  const scrollExtra = 0;
1802
1805
  const { queuedInitialLayout } = state;
1803
1806
  let { scroll: scrollState } = state;
1804
- const initialScroll = state.props.initialScroll;
1805
1807
  if (!queuedInitialLayout && initialScroll) {
1806
1808
  const updatedOffset = calculateOffsetWithOffsetPosition(
1807
1809
  state,
@@ -1813,13 +1815,12 @@ function calculateItemsInView(ctx, state, params = {}) {
1813
1815
  const scrollAdjustPad = -previousScrollAdjust - topPad;
1814
1816
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
1815
1817
  if (scroll + scrollLength > totalSize) {
1816
- scroll = totalSize - scrollLength;
1818
+ scroll = Math.max(0, totalSize - scrollLength);
1817
1819
  }
1818
1820
  if (ENABLE_DEBUG_VIEW) {
1819
1821
  set$(ctx, "debugRawScroll", scrollState);
1820
1822
  set$(ctx, "debugComputedScroll", scroll);
1821
1823
  }
1822
- const scrollBuffer = state.props.scrollBuffer;
1823
1824
  let scrollBufferTop = scrollBuffer;
1824
1825
  let scrollBufferBottom = scrollBuffer;
1825
1826
  if (speed > 0) {
@@ -1830,7 +1831,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1830
1831
  scrollBufferBottom = scrollBuffer * 0.5;
1831
1832
  }
1832
1833
  const scrollTopBuffered = scroll - scrollBufferTop;
1833
- const scrollBottom = scroll + scrollLength;
1834
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
1834
1835
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1835
1836
  if (scrollForNextCalculateItemsInView) {
1836
1837
  const { top, bottom } = scrollForNextCalculateItemsInView;
@@ -1930,7 +1931,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1930
1931
  if (dataChanged) {
1931
1932
  for (let i = 0; i < numContainers; i++) {
1932
1933
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1933
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1934
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1934
1935
  pendingRemoval.push(i);
1935
1936
  }
1936
1937
  }
@@ -1945,11 +1946,20 @@ function calculateItemsInView(ctx, state, params = {}) {
1945
1946
  }
1946
1947
  }
1947
1948
  if (stickyIndicesArr.length > 0) {
1948
- handleStickyActivation(ctx, state, stickyIndicesSet, stickyIndicesArr, scroll, needNewContainers, startBuffered, endBuffered);
1949
+ handleStickyActivation(
1950
+ ctx,
1951
+ state,
1952
+ stickyIndicesSet,
1953
+ stickyIndicesArr,
1954
+ scroll,
1955
+ needNewContainers,
1956
+ startBuffered,
1957
+ endBuffered
1958
+ );
1949
1959
  }
1950
1960
  if (needNewContainers.length > 0) {
1951
- const requiredItemTypes = state.props.getItemType ? needNewContainers.map((i) => {
1952
- const itemType = state.props.getItemType(data[i], i);
1961
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
1962
+ const itemType = getItemType(data[i], i);
1953
1963
  return itemType ? String(itemType) : "";
1954
1964
  }) : void 0;
1955
1965
  const availableContainers = findAvailableContainers(
@@ -2034,7 +2044,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2034
2044
  if (column >= 0 && column !== prevColumn) {
2035
2045
  set$(ctx, `containerColumn${i}`, column);
2036
2046
  }
2037
- if (prevData !== item) {
2047
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2038
2048
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
2039
2049
  }
2040
2050
  }
@@ -2046,15 +2056,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2046
2056
  setDidLayout(ctx, state);
2047
2057
  }
2048
2058
  }
2049
- if (state.viewabilityConfigCallbackPairs) {
2050
- updateViewableItems(
2051
- state,
2052
- ctx,
2053
- state.viewabilityConfigCallbackPairs,
2054
- scrollLength,
2055
- startNoBuffer,
2056
- endNoBuffer
2057
- );
2059
+ if (viewabilityConfigCallbackPairs) {
2060
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2058
2061
  }
2059
2062
  });
2060
2063
  }
@@ -2191,6 +2194,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2191
2194
  // src/core/onScroll.ts
2192
2195
  function onScroll(ctx, state, event) {
2193
2196
  var _a, _b, _c, _d, _e;
2197
+ if (!state.scrollProcessingEnabled) {
2198
+ return;
2199
+ }
2194
2200
  if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2195
2201
  return;
2196
2202
  }
@@ -2359,7 +2365,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2359
2365
  }
2360
2366
  }
2361
2367
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2362
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2368
+ const speed = getScrollVelocity(state);
2369
+ if (!containersDidLayout || !queuedItemSizeUpdatesWaiting || Math.abs(speed) < 1) {
2363
2370
  updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2364
2371
  if (containersDidLayout) {
2365
2372
  state.queuedItemSizeUpdatesWaiting = true;
@@ -2453,11 +2460,63 @@ function getRenderedItem(ctx, state, key) {
2453
2460
  item: data[index],
2454
2461
  type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2455
2462
  };
2456
- renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
2463
+ renderedItem = isFunction(renderItem2) ? renderItem2(itemProps) : React3__namespace.default.createElement(renderItem2, itemProps);
2457
2464
  }
2458
2465
  return { index, item: data[index], renderedItem };
2459
2466
  }
2460
2467
 
2468
+ // src/utils/updateAveragesOnDataChange.ts
2469
+ function updateAveragesOnDataChange(state, oldData, newData) {
2470
+ var _a;
2471
+ const {
2472
+ averageSizes,
2473
+ sizesKnown,
2474
+ indexByKey,
2475
+ props: { itemsAreEqual, getItemType, keyExtractor }
2476
+ } = state;
2477
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2478
+ for (const key in averageSizes) {
2479
+ delete averageSizes[key];
2480
+ }
2481
+ return;
2482
+ }
2483
+ const itemTypesToPreserve = {};
2484
+ const newDataLength = newData.length;
2485
+ const oldDataLength = oldData.length;
2486
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2487
+ const newItem = newData[newIndex];
2488
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2489
+ const oldIndex = indexByKey.get(id);
2490
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2491
+ const knownSize = sizesKnown.get(id);
2492
+ if (knownSize === void 0) continue;
2493
+ const oldItem = oldData[oldIndex];
2494
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2495
+ if (areEqual) {
2496
+ const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2497
+ let typeData = itemTypesToPreserve[itemType];
2498
+ if (!typeData) {
2499
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2500
+ }
2501
+ typeData.totalSize += knownSize;
2502
+ typeData.count++;
2503
+ }
2504
+ }
2505
+ }
2506
+ for (const key in averageSizes) {
2507
+ delete averageSizes[key];
2508
+ }
2509
+ for (const itemType in itemTypesToPreserve) {
2510
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2511
+ if (count > 0) {
2512
+ averageSizes[itemType] = {
2513
+ avg: totalSize / count,
2514
+ num: count
2515
+ };
2516
+ }
2517
+ }
2518
+ }
2519
+
2461
2520
  // src/components/LegendList.tsx
2462
2521
  var DEFAULT_DRAW_DISTANCE = 250;
2463
2522
  var DEFAULT_ITEM_SIZE = 100;
@@ -2482,6 +2541,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2482
2541
  initialContainerPoolRatio = 2,
2483
2542
  initialScrollIndex: initialScrollIndexProp,
2484
2543
  initialScrollOffset,
2544
+ itemsAreEqual,
2485
2545
  keyExtractor: keyExtractorProp,
2486
2546
  ListEmptyComponent,
2487
2547
  ListHeaderComponent,
@@ -2571,6 +2631,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2571
2631
  scrollPending: 0,
2572
2632
  scrollPrev: 0,
2573
2633
  scrollPrevTime: 0,
2634
+ scrollProcessingEnabled: true,
2574
2635
  scrollTime: 0,
2575
2636
  sizes: /* @__PURE__ */ new Map(),
2576
2637
  sizesKnown: /* @__PURE__ */ new Map(),
@@ -2600,6 +2661,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2600
2661
  horizontal: !!horizontal,
2601
2662
  initialContainerPoolRatio,
2602
2663
  initialScroll,
2664
+ itemsAreEqual,
2603
2665
  keyExtractor,
2604
2666
  maintainScrollAtEnd,
2605
2667
  maintainScrollAtEndThreshold,
@@ -2626,6 +2688,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2626
2688
  const checkResetContainers = (isFirst2) => {
2627
2689
  const state2 = refState.current;
2628
2690
  if (state2) {
2691
+ if (!isFirst2 && state2.props.data !== dataProp) {
2692
+ updateAveragesOnDataChange(state2, state2.props.data, dataProp);
2693
+ }
2629
2694
  state2.props.data = dataProp;
2630
2695
  if (!isFirst2) {
2631
2696
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
@@ -2833,6 +2898,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2833
2898
  }
2834
2899
  },
2835
2900
  scrollToOffset: (params) => scrollTo(state, params),
2901
+ setScrollProcessingEnabled: (enabled) => {
2902
+ refState.current.scrollProcessingEnabled = enabled;
2903
+ },
2836
2904
  setVisibleContentAnchorOffset: (value) => {
2837
2905
  const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2838
2906
  set$(ctx, "scrollAdjustUserOffset", val);
package/index.mjs CHANGED
@@ -277,7 +277,6 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
277
277
  return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
278
278
  }
279
279
  }, [position, horizontal, animatedScrollY, stickyOffset]);
280
- console.log("index", index, position, transform);
281
280
  const viewStyle = React3.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
282
281
  return /* @__PURE__ */ React3.createElement(Animated.View, { ref: refView, style: viewStyle, ...rest });
283
282
  });
@@ -1167,11 +1166,6 @@ function updateAllPositions(ctx, state, dataChanged) {
1167
1166
  const numColumns = peek$(ctx, "numColumns");
1168
1167
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1169
1168
  const scrollVelocity = getScrollVelocity(state);
1170
- if (dataChanged) {
1171
- indexByKey.clear();
1172
- idCache.clear();
1173
- positions.clear();
1174
- }
1175
1169
  const useAverageSize = false;
1176
1170
  const itemType = "";
1177
1171
  let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
@@ -1687,9 +1681,11 @@ function setDidLayout(ctx, state) {
1687
1681
  // src/core/calculateItemsInView.ts
1688
1682
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1689
1683
  var _a;
1684
+ const idCache = state.idCache;
1685
+ const positions = state.positions;
1690
1686
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1691
- const stickyId = (_a = state.idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1692
- const stickyPos = stickyId ? state.positions.get(stickyId) : void 0;
1687
+ const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1688
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1693
1689
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1694
1690
  return i;
1695
1691
  }
@@ -1749,17 +1745,19 @@ function calculateItemsInView(ctx, state, params = {}) {
1749
1745
  unstable_batchedUpdates(() => {
1750
1746
  var _a, _b, _c, _d, _e, _f, _g, _h;
1751
1747
  const {
1752
- scrollLength,
1753
- startBufferedId: startBufferedIdOrig,
1754
- positions,
1755
1748
  columns,
1756
1749
  containerItemKeys,
1750
+ enableScrollForNextCalculateItemsInView,
1757
1751
  idCache,
1758
- sizes,
1759
1752
  indexByKey,
1753
+ minIndexSizeChanged,
1754
+ positions,
1760
1755
  scrollForNextCalculateItemsInView,
1761
- enableScrollForNextCalculateItemsInView,
1762
- minIndexSizeChanged
1756
+ scrollLength,
1757
+ sizes,
1758
+ startBufferedId: startBufferedIdOrig,
1759
+ viewabilityConfigCallbackPairs,
1760
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1763
1761
  } = state;
1764
1762
  const { data, stickyIndicesArr, stickyIndicesSet } = state.props;
1765
1763
  const prevNumContainers = peek$(ctx, "numContainers");
@@ -1774,13 +1772,17 @@ function calculateItemsInView(ctx, state, params = {}) {
1774
1772
  const speed = getScrollVelocity(state);
1775
1773
  if (doMVCP || dataChanged) {
1776
1774
  const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1775
+ if (dataChanged) {
1776
+ indexByKey.clear();
1777
+ idCache.clear();
1778
+ positions.clear();
1779
+ }
1777
1780
  updateAllPositions(ctx, state, dataChanged);
1778
1781
  checkMVCP == null ? void 0 : checkMVCP();
1779
1782
  }
1780
1783
  const scrollExtra = 0;
1781
1784
  const { queuedInitialLayout } = state;
1782
1785
  let { scroll: scrollState } = state;
1783
- const initialScroll = state.props.initialScroll;
1784
1786
  if (!queuedInitialLayout && initialScroll) {
1785
1787
  const updatedOffset = calculateOffsetWithOffsetPosition(
1786
1788
  state,
@@ -1792,13 +1794,12 @@ function calculateItemsInView(ctx, state, params = {}) {
1792
1794
  const scrollAdjustPad = -previousScrollAdjust - topPad;
1793
1795
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
1794
1796
  if (scroll + scrollLength > totalSize) {
1795
- scroll = totalSize - scrollLength;
1797
+ scroll = Math.max(0, totalSize - scrollLength);
1796
1798
  }
1797
1799
  if (ENABLE_DEBUG_VIEW) {
1798
1800
  set$(ctx, "debugRawScroll", scrollState);
1799
1801
  set$(ctx, "debugComputedScroll", scroll);
1800
1802
  }
1801
- const scrollBuffer = state.props.scrollBuffer;
1802
1803
  let scrollBufferTop = scrollBuffer;
1803
1804
  let scrollBufferBottom = scrollBuffer;
1804
1805
  if (speed > 0) {
@@ -1809,7 +1810,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1809
1810
  scrollBufferBottom = scrollBuffer * 0.5;
1810
1811
  }
1811
1812
  const scrollTopBuffered = scroll - scrollBufferTop;
1812
- const scrollBottom = scroll + scrollLength;
1813
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
1813
1814
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1814
1815
  if (scrollForNextCalculateItemsInView) {
1815
1816
  const { top, bottom } = scrollForNextCalculateItemsInView;
@@ -1909,7 +1910,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1909
1910
  if (dataChanged) {
1910
1911
  for (let i = 0; i < numContainers; i++) {
1911
1912
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1912
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1913
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1913
1914
  pendingRemoval.push(i);
1914
1915
  }
1915
1916
  }
@@ -1924,11 +1925,20 @@ function calculateItemsInView(ctx, state, params = {}) {
1924
1925
  }
1925
1926
  }
1926
1927
  if (stickyIndicesArr.length > 0) {
1927
- handleStickyActivation(ctx, state, stickyIndicesSet, stickyIndicesArr, scroll, needNewContainers, startBuffered, endBuffered);
1928
+ handleStickyActivation(
1929
+ ctx,
1930
+ state,
1931
+ stickyIndicesSet,
1932
+ stickyIndicesArr,
1933
+ scroll,
1934
+ needNewContainers,
1935
+ startBuffered,
1936
+ endBuffered
1937
+ );
1928
1938
  }
1929
1939
  if (needNewContainers.length > 0) {
1930
- const requiredItemTypes = state.props.getItemType ? needNewContainers.map((i) => {
1931
- const itemType = state.props.getItemType(data[i], i);
1940
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
1941
+ const itemType = getItemType(data[i], i);
1932
1942
  return itemType ? String(itemType) : "";
1933
1943
  }) : void 0;
1934
1944
  const availableContainers = findAvailableContainers(
@@ -2013,7 +2023,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2013
2023
  if (column >= 0 && column !== prevColumn) {
2014
2024
  set$(ctx, `containerColumn${i}`, column);
2015
2025
  }
2016
- if (prevData !== item) {
2026
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2017
2027
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
2018
2028
  }
2019
2029
  }
@@ -2025,15 +2035,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2025
2035
  setDidLayout(ctx, state);
2026
2036
  }
2027
2037
  }
2028
- if (state.viewabilityConfigCallbackPairs) {
2029
- updateViewableItems(
2030
- state,
2031
- ctx,
2032
- state.viewabilityConfigCallbackPairs,
2033
- scrollLength,
2034
- startNoBuffer,
2035
- endNoBuffer
2036
- );
2038
+ if (viewabilityConfigCallbackPairs) {
2039
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2037
2040
  }
2038
2041
  });
2039
2042
  }
@@ -2170,6 +2173,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2170
2173
  // src/core/onScroll.ts
2171
2174
  function onScroll(ctx, state, event) {
2172
2175
  var _a, _b, _c, _d, _e;
2176
+ if (!state.scrollProcessingEnabled) {
2177
+ return;
2178
+ }
2173
2179
  if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2174
2180
  return;
2175
2181
  }
@@ -2338,7 +2344,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2338
2344
  }
2339
2345
  }
2340
2346
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2341
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2347
+ const speed = getScrollVelocity(state);
2348
+ if (!containersDidLayout || !queuedItemSizeUpdatesWaiting || Math.abs(speed) < 1) {
2342
2349
  updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2343
2350
  if (containersDidLayout) {
2344
2351
  state.queuedItemSizeUpdatesWaiting = true;
@@ -2432,11 +2439,63 @@ function getRenderedItem(ctx, state, key) {
2432
2439
  item: data[index],
2433
2440
  type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2434
2441
  };
2435
- renderedItem = React3__default.createElement(renderItem2, itemProps);
2442
+ renderedItem = isFunction(renderItem2) ? renderItem2(itemProps) : React3__default.createElement(renderItem2, itemProps);
2436
2443
  }
2437
2444
  return { index, item: data[index], renderedItem };
2438
2445
  }
2439
2446
 
2447
+ // src/utils/updateAveragesOnDataChange.ts
2448
+ function updateAveragesOnDataChange(state, oldData, newData) {
2449
+ var _a;
2450
+ const {
2451
+ averageSizes,
2452
+ sizesKnown,
2453
+ indexByKey,
2454
+ props: { itemsAreEqual, getItemType, keyExtractor }
2455
+ } = state;
2456
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2457
+ for (const key in averageSizes) {
2458
+ delete averageSizes[key];
2459
+ }
2460
+ return;
2461
+ }
2462
+ const itemTypesToPreserve = {};
2463
+ const newDataLength = newData.length;
2464
+ const oldDataLength = oldData.length;
2465
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2466
+ const newItem = newData[newIndex];
2467
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2468
+ const oldIndex = indexByKey.get(id);
2469
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2470
+ const knownSize = sizesKnown.get(id);
2471
+ if (knownSize === void 0) continue;
2472
+ const oldItem = oldData[oldIndex];
2473
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2474
+ if (areEqual) {
2475
+ const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2476
+ let typeData = itemTypesToPreserve[itemType];
2477
+ if (!typeData) {
2478
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2479
+ }
2480
+ typeData.totalSize += knownSize;
2481
+ typeData.count++;
2482
+ }
2483
+ }
2484
+ }
2485
+ for (const key in averageSizes) {
2486
+ delete averageSizes[key];
2487
+ }
2488
+ for (const itemType in itemTypesToPreserve) {
2489
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2490
+ if (count > 0) {
2491
+ averageSizes[itemType] = {
2492
+ avg: totalSize / count,
2493
+ num: count
2494
+ };
2495
+ }
2496
+ }
2497
+ }
2498
+
2440
2499
  // src/components/LegendList.tsx
2441
2500
  var DEFAULT_DRAW_DISTANCE = 250;
2442
2501
  var DEFAULT_ITEM_SIZE = 100;
@@ -2461,6 +2520,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2461
2520
  initialContainerPoolRatio = 2,
2462
2521
  initialScrollIndex: initialScrollIndexProp,
2463
2522
  initialScrollOffset,
2523
+ itemsAreEqual,
2464
2524
  keyExtractor: keyExtractorProp,
2465
2525
  ListEmptyComponent,
2466
2526
  ListHeaderComponent,
@@ -2550,6 +2610,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2550
2610
  scrollPending: 0,
2551
2611
  scrollPrev: 0,
2552
2612
  scrollPrevTime: 0,
2613
+ scrollProcessingEnabled: true,
2553
2614
  scrollTime: 0,
2554
2615
  sizes: /* @__PURE__ */ new Map(),
2555
2616
  sizesKnown: /* @__PURE__ */ new Map(),
@@ -2579,6 +2640,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2579
2640
  horizontal: !!horizontal,
2580
2641
  initialContainerPoolRatio,
2581
2642
  initialScroll,
2643
+ itemsAreEqual,
2582
2644
  keyExtractor,
2583
2645
  maintainScrollAtEnd,
2584
2646
  maintainScrollAtEndThreshold,
@@ -2605,6 +2667,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2605
2667
  const checkResetContainers = (isFirst2) => {
2606
2668
  const state2 = refState.current;
2607
2669
  if (state2) {
2670
+ if (!isFirst2 && state2.props.data !== dataProp) {
2671
+ updateAveragesOnDataChange(state2, state2.props.data, dataProp);
2672
+ }
2608
2673
  state2.props.data = dataProp;
2609
2674
  if (!isFirst2) {
2610
2675
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
@@ -2812,6 +2877,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2812
2877
  }
2813
2878
  },
2814
2879
  scrollToOffset: (params) => scrollTo(state, params),
2880
+ setScrollProcessingEnabled: (enabled) => {
2881
+ refState.current.scrollProcessingEnabled = enabled;
2882
+ },
2815
2883
  setVisibleContentAnchorOffset: (value) => {
2816
2884
  const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2817
2885
  set$(ctx, "scrollAdjustUserOffset", val);
@@ -70,6 +70,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
70
70
  stickyIndices?: number[];
71
71
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
72
72
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
73
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
73
74
  } & React.RefAttributes<LegendListRef>) => React.ReactNode) | react_native.Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
74
75
  alignItemsAtEnd?: boolean;
75
76
  columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
@@ -136,6 +137,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
136
137
  stickyIndices?: number[];
137
138
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
138
139
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
140
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
139
141
  } & React.RefAttributes<LegendListRef>) => React.ReactNode)> | (<ItemT_1>(props: _legendapp_list_reanimated.AnimatedLegendListProps<ItemT_1> & {
140
142
  ref?: React.Ref<LegendListRef>;
141
143
  }) => React.ReactElement | null) = <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -204,6 +206,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
204
206
  stickyIndices?: number[];
205
207
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
206
208
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
209
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
207
210
  } & React.RefAttributes<LegendListRef>) => React.ReactNode>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
208
211
  alignItemsAtEnd?: boolean;
209
212
  columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
@@ -270,6 +273,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
270
273
  stickyIndices?: number[];
271
274
  getItemType?: ((item: ItemT, index: number) => string | undefined) | undefined;
272
275
  getFixedItemSize?: ((index: number, item: ItemT, type: string | undefined) => number) | undefined;
276
+ itemsAreEqual?: ((itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean) | undefined;
273
277
  } & {
274
278
  LegendList?: ListT;
275
279
  } & React.RefAttributes<LegendListRef>) => React.ReactNode;
@@ -70,6 +70,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
70
70
  stickyIndices?: number[];
71
71
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
72
72
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
73
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
73
74
  } & React.RefAttributes<LegendListRef>) => React.ReactNode) | react_native.Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
74
75
  alignItemsAtEnd?: boolean;
75
76
  columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
@@ -136,6 +137,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
136
137
  stickyIndices?: number[];
137
138
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
138
139
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
140
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
139
141
  } & React.RefAttributes<LegendListRef>) => React.ReactNode)> | (<ItemT_1>(props: _legendapp_list_reanimated.AnimatedLegendListProps<ItemT_1> & {
140
142
  ref?: React.Ref<LegendListRef>;
141
143
  }) => React.ReactElement | null) = <T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
@@ -204,6 +206,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
204
206
  stickyIndices?: number[];
205
207
  getItemType?: ((item: T, index: number) => string | undefined) | undefined;
206
208
  getFixedItemSize?: ((index: number, item: T, type: string | undefined) => number) | undefined;
209
+ itemsAreEqual?: ((itemPrevious: T, item: T, index: number, data: readonly T[]) => boolean) | undefined;
207
210
  } & React.RefAttributes<LegendListRef>) => React.ReactNode>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children"> & {
208
211
  alignItemsAtEnd?: boolean;
209
212
  columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
@@ -270,6 +273,7 @@ declare const LegendList: <ItemT, ListT extends (<T>(props: Omit<Omit<react_nati
270
273
  stickyIndices?: number[];
271
274
  getItemType?: ((item: ItemT, index: number) => string | undefined) | undefined;
272
275
  getFixedItemSize?: ((index: number, item: ItemT, type: string | undefined) => number) | undefined;
276
+ itemsAreEqual?: ((itemPrevious: ItemT, item: ItemT, index: number, data: readonly ItemT[]) => boolean) | undefined;
273
277
  } & {
274
278
  LegendList?: ListT;
275
279
  } & React.RefAttributes<LegendListRef>) => React.ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.0.0-next.15",
3
+ "version": "2.0.0-next.17",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,
package/reanimated.d.mts CHANGED
@@ -2,7 +2,7 @@ import React__default, { ComponentProps } from 'react';
2
2
  import Animated from 'react-native-reanimated';
3
3
  import { LegendListPropsBase, LegendListRef } from '@legendapp/list';
4
4
 
5
- type KeysToOmit = "getEstimatedItemSize" | "getFixedItemSize" | "getItemType" | "keyExtractor" | "animatedProps" | "renderItem" | "onItemSizeChanged" | "ItemSeparatorComponent";
5
+ type KeysToOmit = "getEstimatedItemSize" | "getFixedItemSize" | "getItemType" | "keyExtractor" | "animatedProps" | "renderItem" | "onItemSizeChanged" | "itemsAreEqual" | "ItemSeparatorComponent";
6
6
  type PropsBase<ItemT> = LegendListPropsBase<ItemT, ComponentProps<typeof Animated.ScrollView>>;
7
7
  interface AnimatedLegendListPropsBase<ItemT> extends Omit<PropsBase<ItemT>, KeysToOmit> {
8
8
  refScrollView?: React__default.Ref<Animated.ScrollView>;
package/reanimated.d.ts CHANGED
@@ -2,7 +2,7 @@ import React__default, { ComponentProps } from 'react';
2
2
  import Animated from 'react-native-reanimated';
3
3
  import { LegendListPropsBase, LegendListRef } from '@legendapp/list';
4
4
 
5
- type KeysToOmit = "getEstimatedItemSize" | "getFixedItemSize" | "getItemType" | "keyExtractor" | "animatedProps" | "renderItem" | "onItemSizeChanged" | "ItemSeparatorComponent";
5
+ type KeysToOmit = "getEstimatedItemSize" | "getFixedItemSize" | "getItemType" | "keyExtractor" | "animatedProps" | "renderItem" | "onItemSizeChanged" | "itemsAreEqual" | "ItemSeparatorComponent";
6
6
  type PropsBase<ItemT> = LegendListPropsBase<ItemT, ComponentProps<typeof Animated.ScrollView>>;
7
7
  interface AnimatedLegendListPropsBase<ItemT> extends Omit<PropsBase<ItemT>, KeysToOmit> {
8
8
  refScrollView?: React__default.Ref<Animated.ScrollView>;
package/.DS_Store DELETED
Binary file