@legendapp/list 3.0.0-beta.17 → 3.0.0-beta.19

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.js CHANGED
@@ -287,6 +287,11 @@ function extractPadding(style, contentContainerStyle, type) {
287
287
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
288
288
  }
289
289
  function findContainerId(ctx, key) {
290
+ var _a3, _b;
291
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
292
+ if (directMatch !== void 0) {
293
+ return directMatch;
294
+ }
290
295
  const numContainers = peek$(ctx, "numContainers");
291
296
  for (let i = 0; i < numContainers; i++) {
292
297
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -1403,7 +1408,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1403
1408
  }
1404
1409
  }
1405
1410
  if (getFixedItemSize) {
1406
- size = getFixedItemSize(index, data, itemType);
1411
+ size = getFixedItemSize(data, index, itemType);
1407
1412
  if (size !== void 0) {
1408
1413
  sizesKnown.set(key, size);
1409
1414
  }
@@ -1421,7 +1426,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1421
1426
  }
1422
1427
  }
1423
1428
  if (size === void 0) {
1424
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1429
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1425
1430
  }
1426
1431
  setSize(ctx, key, size);
1427
1432
  return size;
@@ -1592,7 +1597,7 @@ function scrollTo(ctx, params) {
1592
1597
 
1593
1598
  // src/utils/checkThreshold.ts
1594
1599
  var HYSTERESIS_MULTIPLIER = 1.3;
1595
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1600
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1596
1601
  const absDistance = Math.abs(distance);
1597
1602
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1598
1603
  if (wasReached === null) {
@@ -1602,7 +1607,7 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1602
1607
  return null;
1603
1608
  }
1604
1609
  const updateSnapshot = () => {
1605
- setSnapshot == null ? void 0 : setSnapshot({
1610
+ setSnapshot({
1606
1611
  atThreshold,
1607
1612
  contentSize: context.contentSize,
1608
1613
  dataLength: context.dataLength,
@@ -1613,19 +1618,21 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1613
1618
  if (!within) {
1614
1619
  return false;
1615
1620
  }
1616
- onReached == null ? void 0 : onReached(distance);
1621
+ onReached(distance);
1617
1622
  updateSnapshot();
1618
1623
  return true;
1619
1624
  }
1620
1625
  const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1621
1626
  if (reset) {
1622
- setSnapshot == null ? void 0 : setSnapshot(void 0);
1627
+ setSnapshot(void 0);
1623
1628
  return false;
1624
1629
  }
1625
1630
  if (within) {
1626
1631
  const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1627
1632
  if (changed) {
1628
- onReached == null ? void 0 : onReached(distance);
1633
+ if (allowReentryOnChange) {
1634
+ onReached(distance);
1635
+ }
1629
1636
  updateSnapshot();
1630
1637
  }
1631
1638
  }
@@ -1668,7 +1675,8 @@ function checkAtBottom(ctx) {
1668
1675
  },
1669
1676
  (snapshot) => {
1670
1677
  state.endReachedSnapshot = snapshot;
1671
- }
1678
+ },
1679
+ true
1672
1680
  );
1673
1681
  }
1674
1682
  }
@@ -1703,15 +1711,16 @@ function checkAtTop(state) {
1703
1711
  },
1704
1712
  (snapshot) => {
1705
1713
  state.startReachedSnapshot = snapshot;
1706
- }
1714
+ },
1715
+ false
1707
1716
  );
1708
1717
  }
1709
1718
 
1710
1719
  // src/core/updateScroll.ts
1711
1720
  function updateScroll(ctx, newScroll, forceUpdate) {
1712
- var _a3;
1713
1721
  const state = ctx.state;
1714
1722
  const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1723
+ const prevScroll = state.scroll;
1715
1724
  state.hasScrolled = true;
1716
1725
  state.lastBatchingAction = Date.now();
1717
1726
  const currentTime = Date.now();
@@ -1729,7 +1738,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1729
1738
  if (state.scrollHistory.length > 5) {
1730
1739
  state.scrollHistory.shift();
1731
1740
  }
1732
- state.scrollPrev = state.scroll;
1741
+ state.scrollPrev = prevScroll;
1733
1742
  state.scrollPrevTime = state.scrollTime;
1734
1743
  state.scroll = newScroll;
1735
1744
  state.scrollTime = currentTime;
@@ -1741,15 +1750,27 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1741
1750
  return;
1742
1751
  }
1743
1752
  }
1753
+ const scrollDelta = Math.abs(newScroll - prevScroll);
1754
+ const scrollLength = state.scrollLength;
1744
1755
  const lastCalculated = state.scrollLastCalculate;
1745
1756
  const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1746
1757
  if (shouldUpdate) {
1747
1758
  state.scrollLastCalculate = state.scroll;
1748
1759
  state.ignoreScrollFromMVCPIgnored = false;
1749
- (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1750
- checkAtBottom(ctx);
1751
- checkAtTop(state);
1760
+ state.lastScrollDelta = scrollDelta;
1761
+ const runCalculateItems = () => {
1762
+ var _a3;
1763
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1764
+ checkAtBottom(ctx);
1765
+ checkAtTop(state);
1766
+ };
1767
+ if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1768
+ reactDom.flushSync(runCalculateItems);
1769
+ } else {
1770
+ runCalculateItems();
1771
+ }
1752
1772
  state.dataChangeNeedsScrollUpdate = false;
1773
+ state.lastScrollDelta = 0;
1753
1774
  }
1754
1775
  }
1755
1776
 
@@ -1782,7 +1803,7 @@ function prepareMVCP(ctx, dataChanged) {
1782
1803
  const state = ctx.state;
1783
1804
  const { idsInView, positions, props } = state;
1784
1805
  const {
1785
- maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll }
1806
+ maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
1786
1807
  } = props;
1787
1808
  const scrollingTo = state.scrollingTo;
1788
1809
  let prevPosition;
@@ -1814,8 +1835,16 @@ function prepareMVCP(ctx, dataChanged) {
1814
1835
  return () => {
1815
1836
  let positionDiff = 0;
1816
1837
  if (dataChanged && targetId === void 0 && mvcpData) {
1838
+ const data = state.props.data;
1817
1839
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1818
1840
  const { id, position } = idsInViewWithPositions[i];
1841
+ const index = indexByKey.get(id);
1842
+ if (index !== void 0 && shouldRestorePosition) {
1843
+ const item = data[index];
1844
+ if (item === void 0 || !shouldRestorePosition(item, index, data)) {
1845
+ continue;
1846
+ }
1847
+ }
1819
1848
  const newPosition = positions.get(id);
1820
1849
  if (newPosition !== void 0) {
1821
1850
  positionDiff = newPosition - position;
@@ -2021,7 +2050,9 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
2021
2050
  const numColumns = peek$(ctx, "numColumns");
2022
2051
  const hasColumns = numColumns > 1;
2023
2052
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
2024
- const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
2053
+ const lastScrollDelta = state.lastScrollDelta;
2054
+ const velocity = getScrollVelocity(state);
2055
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
2025
2056
  const maxVisibleArea = scrollBottomBuffered + 1e3;
2026
2057
  const useAverageSize = !getEstimatedItemSize;
2027
2058
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
@@ -2794,7 +2825,7 @@ function calculateItemsInView(ctx, params = {}) {
2794
2825
  if (requiredItemTypes) {
2795
2826
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2796
2827
  }
2797
- containerItemKeys.add(id);
2828
+ containerItemKeys.set(id, containerIndex);
2798
2829
  const containerSticky = `containerSticky${containerIndex}`;
2799
2830
  if (stickyIndicesSet.has(i)) {
2800
2831
  set$(ctx, containerSticky, true);
@@ -3084,7 +3115,7 @@ function doInitialAllocateContainers(ctx) {
3084
3115
  const item = data[i];
3085
3116
  if (item !== void 0) {
3086
3117
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
3087
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
3118
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(item, i, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(item, i, itemType)) != null ? _c : estimatedItemSize;
3088
3119
  }
3089
3120
  }
3090
3121
  averageItemSize = totalSize / num;
@@ -3271,7 +3302,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3271
3302
  return;
3272
3303
  }
3273
3304
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3274
- const size2 = getFixedItemSize(index, itemData, type);
3305
+ const size2 = getFixedItemSize(itemData, index, type);
3275
3306
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
3276
3307
  return;
3277
3308
  }
@@ -3287,14 +3318,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3287
3318
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
3288
3319
  const { startBuffered, endBuffered } = state;
3289
3320
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
3290
- if (!needsRecalculate) {
3291
- const numContainers = ctx.values.get("numContainers");
3292
- for (let i = 0; i < numContainers; i++) {
3293
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
3294
- needsRecalculate = true;
3295
- break;
3296
- }
3297
- }
3321
+ if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
3322
+ needsRecalculate = true;
3298
3323
  }
3299
3324
  if (state.needsOtherAxisSize) {
3300
3325
  const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
@@ -3550,7 +3575,8 @@ function normalizeMaintainVisibleContentPosition(value) {
3550
3575
  if (value && typeof value === "object") {
3551
3576
  return {
3552
3577
  data: (_a3 = value.data) != null ? _a3 : false,
3553
- size: (_b = value.size) != null ? _b : true
3578
+ size: (_b = value.size) != null ? _b : true,
3579
+ shouldRestorePosition: value.shouldRestorePosition
3554
3580
  };
3555
3581
  }
3556
3582
  if (value === false) {
@@ -3719,7 +3745,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3719
3745
  activeStickyIndex: -1,
3720
3746
  averageSizes: {},
3721
3747
  columns: /* @__PURE__ */ new Map(),
3722
- containerItemKeys: /* @__PURE__ */ new Set(),
3748
+ containerItemKeys: /* @__PURE__ */ new Map(),
3723
3749
  containerItemTypes: /* @__PURE__ */ new Map(),
3724
3750
  dataChangeNeedsScrollUpdate: false,
3725
3751
  didColumnsChange: false,
@@ -3747,6 +3773,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3747
3773
  isStartReached: null,
3748
3774
  lastBatchingAction: Date.now(),
3749
3775
  lastLayout: void 0,
3776
+ lastScrollDelta: 0,
3750
3777
  loadStartTime: Date.now(),
3751
3778
  minIndexSizeChanged: 0,
3752
3779
  nativeMarginTop: 0,
@@ -4030,6 +4057,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4030
4057
  });
4031
4058
 
4032
4059
  exports.LegendList = LegendList;
4060
+ exports.typedForwardRef = typedForwardRef;
4061
+ exports.typedMemo = typedMemo;
4033
4062
  exports.useIsLastItem = useIsLastItem;
4034
4063
  exports.useListScrollSize = useListScrollSize;
4035
4064
  exports.useRecyclingEffect = useRecyclingEffect;
package/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React3 from 'react';
2
2
  import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useImperativeHandle, useLayoutEffect, memo, useContext } from 'react';
3
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
4
- import { unstable_batchedUpdates } from 'react-dom';
4
+ import { unstable_batchedUpdates, flushSync } from 'react-dom';
5
5
 
6
6
  // src/components/LegendList.tsx
7
7
  forwardRef(function AnimatedView2(props, ref) {
@@ -266,6 +266,11 @@ function extractPadding(style, contentContainerStyle, type) {
266
266
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
267
267
  }
268
268
  function findContainerId(ctx, key) {
269
+ var _a3, _b;
270
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
271
+ if (directMatch !== void 0) {
272
+ return directMatch;
273
+ }
269
274
  const numContainers = peek$(ctx, "numContainers");
270
275
  for (let i = 0; i < numContainers; i++) {
271
276
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -1382,7 +1387,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1382
1387
  }
1383
1388
  }
1384
1389
  if (getFixedItemSize) {
1385
- size = getFixedItemSize(index, data, itemType);
1390
+ size = getFixedItemSize(data, index, itemType);
1386
1391
  if (size !== void 0) {
1387
1392
  sizesKnown.set(key, size);
1388
1393
  }
@@ -1400,7 +1405,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1400
1405
  }
1401
1406
  }
1402
1407
  if (size === void 0) {
1403
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1408
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1404
1409
  }
1405
1410
  setSize(ctx, key, size);
1406
1411
  return size;
@@ -1571,7 +1576,7 @@ function scrollTo(ctx, params) {
1571
1576
 
1572
1577
  // src/utils/checkThreshold.ts
1573
1578
  var HYSTERESIS_MULTIPLIER = 1.3;
1574
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1579
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1575
1580
  const absDistance = Math.abs(distance);
1576
1581
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1577
1582
  if (wasReached === null) {
@@ -1581,7 +1586,7 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1581
1586
  return null;
1582
1587
  }
1583
1588
  const updateSnapshot = () => {
1584
- setSnapshot == null ? void 0 : setSnapshot({
1589
+ setSnapshot({
1585
1590
  atThreshold,
1586
1591
  contentSize: context.contentSize,
1587
1592
  dataLength: context.dataLength,
@@ -1592,19 +1597,21 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1592
1597
  if (!within) {
1593
1598
  return false;
1594
1599
  }
1595
- onReached == null ? void 0 : onReached(distance);
1600
+ onReached(distance);
1596
1601
  updateSnapshot();
1597
1602
  return true;
1598
1603
  }
1599
1604
  const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1600
1605
  if (reset) {
1601
- setSnapshot == null ? void 0 : setSnapshot(void 0);
1606
+ setSnapshot(void 0);
1602
1607
  return false;
1603
1608
  }
1604
1609
  if (within) {
1605
1610
  const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1606
1611
  if (changed) {
1607
- onReached == null ? void 0 : onReached(distance);
1612
+ if (allowReentryOnChange) {
1613
+ onReached(distance);
1614
+ }
1608
1615
  updateSnapshot();
1609
1616
  }
1610
1617
  }
@@ -1647,7 +1654,8 @@ function checkAtBottom(ctx) {
1647
1654
  },
1648
1655
  (snapshot) => {
1649
1656
  state.endReachedSnapshot = snapshot;
1650
- }
1657
+ },
1658
+ true
1651
1659
  );
1652
1660
  }
1653
1661
  }
@@ -1682,15 +1690,16 @@ function checkAtTop(state) {
1682
1690
  },
1683
1691
  (snapshot) => {
1684
1692
  state.startReachedSnapshot = snapshot;
1685
- }
1693
+ },
1694
+ false
1686
1695
  );
1687
1696
  }
1688
1697
 
1689
1698
  // src/core/updateScroll.ts
1690
1699
  function updateScroll(ctx, newScroll, forceUpdate) {
1691
- var _a3;
1692
1700
  const state = ctx.state;
1693
1701
  const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1702
+ const prevScroll = state.scroll;
1694
1703
  state.hasScrolled = true;
1695
1704
  state.lastBatchingAction = Date.now();
1696
1705
  const currentTime = Date.now();
@@ -1708,7 +1717,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1708
1717
  if (state.scrollHistory.length > 5) {
1709
1718
  state.scrollHistory.shift();
1710
1719
  }
1711
- state.scrollPrev = state.scroll;
1720
+ state.scrollPrev = prevScroll;
1712
1721
  state.scrollPrevTime = state.scrollTime;
1713
1722
  state.scroll = newScroll;
1714
1723
  state.scrollTime = currentTime;
@@ -1720,15 +1729,27 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1720
1729
  return;
1721
1730
  }
1722
1731
  }
1732
+ const scrollDelta = Math.abs(newScroll - prevScroll);
1733
+ const scrollLength = state.scrollLength;
1723
1734
  const lastCalculated = state.scrollLastCalculate;
1724
1735
  const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1725
1736
  if (shouldUpdate) {
1726
1737
  state.scrollLastCalculate = state.scroll;
1727
1738
  state.ignoreScrollFromMVCPIgnored = false;
1728
- (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1729
- checkAtBottom(ctx);
1730
- checkAtTop(state);
1739
+ state.lastScrollDelta = scrollDelta;
1740
+ const runCalculateItems = () => {
1741
+ var _a3;
1742
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1743
+ checkAtBottom(ctx);
1744
+ checkAtTop(state);
1745
+ };
1746
+ if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1747
+ flushSync(runCalculateItems);
1748
+ } else {
1749
+ runCalculateItems();
1750
+ }
1731
1751
  state.dataChangeNeedsScrollUpdate = false;
1752
+ state.lastScrollDelta = 0;
1732
1753
  }
1733
1754
  }
1734
1755
 
@@ -1761,7 +1782,7 @@ function prepareMVCP(ctx, dataChanged) {
1761
1782
  const state = ctx.state;
1762
1783
  const { idsInView, positions, props } = state;
1763
1784
  const {
1764
- maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll }
1785
+ maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
1765
1786
  } = props;
1766
1787
  const scrollingTo = state.scrollingTo;
1767
1788
  let prevPosition;
@@ -1793,8 +1814,16 @@ function prepareMVCP(ctx, dataChanged) {
1793
1814
  return () => {
1794
1815
  let positionDiff = 0;
1795
1816
  if (dataChanged && targetId === void 0 && mvcpData) {
1817
+ const data = state.props.data;
1796
1818
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1797
1819
  const { id, position } = idsInViewWithPositions[i];
1820
+ const index = indexByKey.get(id);
1821
+ if (index !== void 0 && shouldRestorePosition) {
1822
+ const item = data[index];
1823
+ if (item === void 0 || !shouldRestorePosition(item, index, data)) {
1824
+ continue;
1825
+ }
1826
+ }
1798
1827
  const newPosition = positions.get(id);
1799
1828
  if (newPosition !== void 0) {
1800
1829
  positionDiff = newPosition - position;
@@ -2000,7 +2029,9 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
2000
2029
  const numColumns = peek$(ctx, "numColumns");
2001
2030
  const hasColumns = numColumns > 1;
2002
2031
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
2003
- const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
2032
+ const lastScrollDelta = state.lastScrollDelta;
2033
+ const velocity = getScrollVelocity(state);
2034
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
2004
2035
  const maxVisibleArea = scrollBottomBuffered + 1e3;
2005
2036
  const useAverageSize = !getEstimatedItemSize;
2006
2037
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
@@ -2773,7 +2804,7 @@ function calculateItemsInView(ctx, params = {}) {
2773
2804
  if (requiredItemTypes) {
2774
2805
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2775
2806
  }
2776
- containerItemKeys.add(id);
2807
+ containerItemKeys.set(id, containerIndex);
2777
2808
  const containerSticky = `containerSticky${containerIndex}`;
2778
2809
  if (stickyIndicesSet.has(i)) {
2779
2810
  set$(ctx, containerSticky, true);
@@ -3063,7 +3094,7 @@ function doInitialAllocateContainers(ctx) {
3063
3094
  const item = data[i];
3064
3095
  if (item !== void 0) {
3065
3096
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
3066
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
3097
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(item, i, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(item, i, itemType)) != null ? _c : estimatedItemSize;
3067
3098
  }
3068
3099
  }
3069
3100
  averageItemSize = totalSize / num;
@@ -3250,7 +3281,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3250
3281
  return;
3251
3282
  }
3252
3283
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3253
- const size2 = getFixedItemSize(index, itemData, type);
3284
+ const size2 = getFixedItemSize(itemData, index, type);
3254
3285
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
3255
3286
  return;
3256
3287
  }
@@ -3266,14 +3297,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3266
3297
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
3267
3298
  const { startBuffered, endBuffered } = state;
3268
3299
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
3269
- if (!needsRecalculate) {
3270
- const numContainers = ctx.values.get("numContainers");
3271
- for (let i = 0; i < numContainers; i++) {
3272
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
3273
- needsRecalculate = true;
3274
- break;
3275
- }
3276
- }
3300
+ if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
3301
+ needsRecalculate = true;
3277
3302
  }
3278
3303
  if (state.needsOtherAxisSize) {
3279
3304
  const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
@@ -3529,7 +3554,8 @@ function normalizeMaintainVisibleContentPosition(value) {
3529
3554
  if (value && typeof value === "object") {
3530
3555
  return {
3531
3556
  data: (_a3 = value.data) != null ? _a3 : false,
3532
- size: (_b = value.size) != null ? _b : true
3557
+ size: (_b = value.size) != null ? _b : true,
3558
+ shouldRestorePosition: value.shouldRestorePosition
3533
3559
  };
3534
3560
  }
3535
3561
  if (value === false) {
@@ -3698,7 +3724,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3698
3724
  activeStickyIndex: -1,
3699
3725
  averageSizes: {},
3700
3726
  columns: /* @__PURE__ */ new Map(),
3701
- containerItemKeys: /* @__PURE__ */ new Set(),
3727
+ containerItemKeys: /* @__PURE__ */ new Map(),
3702
3728
  containerItemTypes: /* @__PURE__ */ new Map(),
3703
3729
  dataChangeNeedsScrollUpdate: false,
3704
3730
  didColumnsChange: false,
@@ -3726,6 +3752,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3726
3752
  isStartReached: null,
3727
3753
  lastBatchingAction: Date.now(),
3728
3754
  lastLayout: void 0,
3755
+ lastScrollDelta: 0,
3729
3756
  loadStartTime: Date.now(),
3730
3757
  minIndexSizeChanged: 0,
3731
3758
  nativeMarginTop: 0,
@@ -4008,4 +4035,4 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4008
4035
  ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
4009
4036
  });
4010
4037
 
4011
- export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
4038
+ export { LegendList, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };