@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.native.js CHANGED
@@ -286,6 +286,11 @@ function extractPadding(style, contentContainerStyle, type) {
286
286
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
287
287
  }
288
288
  function findContainerId(ctx, key) {
289
+ var _a3, _b;
290
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
291
+ if (directMatch !== void 0) {
292
+ return directMatch;
293
+ }
289
294
  const numContainers = peek$(ctx, "numContainers");
290
295
  for (let i = 0; i < numContainers; i++) {
291
296
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -1134,7 +1139,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1134
1139
  }
1135
1140
  }
1136
1141
  if (getFixedItemSize) {
1137
- size = getFixedItemSize(index, data, itemType);
1142
+ size = getFixedItemSize(data, index, itemType);
1138
1143
  if (size !== void 0) {
1139
1144
  sizesKnown.set(key, size);
1140
1145
  }
@@ -1152,7 +1157,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1152
1157
  }
1153
1158
  }
1154
1159
  if (size === void 0) {
1155
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1160
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1156
1161
  }
1157
1162
  setSize(ctx, key, size);
1158
1163
  return size;
@@ -1320,9 +1325,14 @@ function scrollTo(ctx, params) {
1320
1325
  }
1321
1326
  }
1322
1327
 
1328
+ // src/platform/flushSync.native.ts
1329
+ var flushSync = (fn) => {
1330
+ fn();
1331
+ };
1332
+
1323
1333
  // src/utils/checkThreshold.ts
1324
1334
  var HYSTERESIS_MULTIPLIER = 1.3;
1325
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1335
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1326
1336
  const absDistance = Math.abs(distance);
1327
1337
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1328
1338
  if (wasReached === null) {
@@ -1332,7 +1342,7 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1332
1342
  return null;
1333
1343
  }
1334
1344
  const updateSnapshot = () => {
1335
- setSnapshot == null ? void 0 : setSnapshot({
1345
+ setSnapshot({
1336
1346
  atThreshold,
1337
1347
  contentSize: context.contentSize,
1338
1348
  dataLength: context.dataLength,
@@ -1343,19 +1353,21 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1343
1353
  if (!within) {
1344
1354
  return false;
1345
1355
  }
1346
- onReached == null ? void 0 : onReached(distance);
1356
+ onReached(distance);
1347
1357
  updateSnapshot();
1348
1358
  return true;
1349
1359
  }
1350
1360
  const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1351
1361
  if (reset) {
1352
- setSnapshot == null ? void 0 : setSnapshot(void 0);
1362
+ setSnapshot(void 0);
1353
1363
  return false;
1354
1364
  }
1355
1365
  if (within) {
1356
1366
  const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1357
1367
  if (changed) {
1358
- onReached == null ? void 0 : onReached(distance);
1368
+ if (allowReentryOnChange) {
1369
+ onReached(distance);
1370
+ }
1359
1371
  updateSnapshot();
1360
1372
  }
1361
1373
  }
@@ -1398,7 +1410,8 @@ function checkAtBottom(ctx) {
1398
1410
  },
1399
1411
  (snapshot) => {
1400
1412
  state.endReachedSnapshot = snapshot;
1401
- }
1413
+ },
1414
+ true
1402
1415
  );
1403
1416
  }
1404
1417
  }
@@ -1433,15 +1446,16 @@ function checkAtTop(state) {
1433
1446
  },
1434
1447
  (snapshot) => {
1435
1448
  state.startReachedSnapshot = snapshot;
1436
- }
1449
+ },
1450
+ false
1437
1451
  );
1438
1452
  }
1439
1453
 
1440
1454
  // src/core/updateScroll.ts
1441
1455
  function updateScroll(ctx, newScroll, forceUpdate) {
1442
- var _a3;
1443
1456
  const state = ctx.state;
1444
1457
  const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1458
+ const prevScroll = state.scroll;
1445
1459
  state.hasScrolled = true;
1446
1460
  state.lastBatchingAction = Date.now();
1447
1461
  const currentTime = Date.now();
@@ -1459,7 +1473,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1459
1473
  if (state.scrollHistory.length > 5) {
1460
1474
  state.scrollHistory.shift();
1461
1475
  }
1462
- state.scrollPrev = state.scroll;
1476
+ state.scrollPrev = prevScroll;
1463
1477
  state.scrollPrevTime = state.scrollTime;
1464
1478
  state.scroll = newScroll;
1465
1479
  state.scrollTime = currentTime;
@@ -1471,15 +1485,27 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1471
1485
  return;
1472
1486
  }
1473
1487
  }
1488
+ const scrollDelta = Math.abs(newScroll - prevScroll);
1489
+ const scrollLength = state.scrollLength;
1474
1490
  const lastCalculated = state.scrollLastCalculate;
1475
1491
  const shouldUpdate = forceUpdate || state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1476
1492
  if (shouldUpdate) {
1477
1493
  state.scrollLastCalculate = state.scroll;
1478
1494
  state.ignoreScrollFromMVCPIgnored = false;
1479
- (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1480
- checkAtBottom(ctx);
1481
- checkAtTop(state);
1495
+ state.lastScrollDelta = scrollDelta;
1496
+ const runCalculateItems = () => {
1497
+ var _a3;
1498
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1499
+ checkAtBottom(ctx);
1500
+ checkAtTop(state);
1501
+ };
1502
+ if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1503
+ flushSync(runCalculateItems);
1504
+ } else {
1505
+ runCalculateItems();
1506
+ }
1482
1507
  state.dataChangeNeedsScrollUpdate = false;
1508
+ state.lastScrollDelta = 0;
1483
1509
  }
1484
1510
  }
1485
1511
 
@@ -1594,7 +1620,7 @@ function prepareMVCP(ctx, dataChanged) {
1594
1620
  const state = ctx.state;
1595
1621
  const { idsInView, positions, props } = state;
1596
1622
  const {
1597
- maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll }
1623
+ maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
1598
1624
  } = props;
1599
1625
  const scrollingTo = state.scrollingTo;
1600
1626
  let prevPosition;
@@ -1629,8 +1655,16 @@ function prepareMVCP(ctx, dataChanged) {
1629
1655
  return () => {
1630
1656
  let positionDiff = 0;
1631
1657
  if (dataChanged && targetId === void 0 && mvcpData) {
1658
+ const data = state.props.data;
1632
1659
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1633
1660
  const { id, position } = idsInViewWithPositions[i];
1661
+ const index = indexByKey.get(id);
1662
+ if (index !== void 0 && shouldRestorePosition) {
1663
+ const item = data[index];
1664
+ if (item === void 0 || !shouldRestorePosition(item, index, data)) {
1665
+ continue;
1666
+ }
1667
+ }
1634
1668
  const newPosition = positions.get(id);
1635
1669
  if (newPosition !== void 0) {
1636
1670
  positionDiff = newPosition - position;
@@ -1836,7 +1870,9 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
1836
1870
  const numColumns = peek$(ctx, "numColumns");
1837
1871
  const hasColumns = numColumns > 1;
1838
1872
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1839
- const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1873
+ const lastScrollDelta = state.lastScrollDelta;
1874
+ const velocity = getScrollVelocity(state);
1875
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || Platform2.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
1840
1876
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1841
1877
  const useAverageSize = !getEstimatedItemSize;
1842
1878
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
@@ -2615,7 +2651,7 @@ function calculateItemsInView(ctx, params = {}) {
2615
2651
  if (requiredItemTypes) {
2616
2652
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2617
2653
  }
2618
- containerItemKeys.add(id);
2654
+ containerItemKeys.set(id, containerIndex);
2619
2655
  const containerSticky = `containerSticky${containerIndex}`;
2620
2656
  if (stickyIndicesSet.has(i)) {
2621
2657
  set$(ctx, containerSticky, true);
@@ -2862,7 +2898,7 @@ function doInitialAllocateContainers(ctx) {
2862
2898
  const item = data[i];
2863
2899
  if (item !== void 0) {
2864
2900
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
2865
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2901
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(item, i, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(item, i, itemType)) != null ? _c : estimatedItemSize;
2866
2902
  }
2867
2903
  }
2868
2904
  averageItemSize = totalSize / num;
@@ -3049,7 +3085,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3049
3085
  return;
3050
3086
  }
3051
3087
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3052
- const size2 = getFixedItemSize(index, itemData, type);
3088
+ const size2 = getFixedItemSize(itemData, index, type);
3053
3089
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
3054
3090
  return;
3055
3091
  }
@@ -3065,14 +3101,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3065
3101
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
3066
3102
  const { startBuffered, endBuffered } = state;
3067
3103
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
3068
- if (!needsRecalculate) {
3069
- const numContainers = ctx.values.get("numContainers");
3070
- for (let i = 0; i < numContainers; i++) {
3071
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
3072
- needsRecalculate = true;
3073
- break;
3074
- }
3075
- }
3104
+ if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
3105
+ needsRecalculate = true;
3076
3106
  }
3077
3107
  if (state.needsOtherAxisSize) {
3078
3108
  const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
@@ -3347,7 +3377,8 @@ function normalizeMaintainVisibleContentPosition(value) {
3347
3377
  if (value && typeof value === "object") {
3348
3378
  return {
3349
3379
  data: (_a3 = value.data) != null ? _a3 : false,
3350
- size: (_b = value.size) != null ? _b : true
3380
+ size: (_b = value.size) != null ? _b : true,
3381
+ shouldRestorePosition: value.shouldRestorePosition
3351
3382
  };
3352
3383
  }
3353
3384
  if (value === false) {
@@ -3516,7 +3547,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3516
3547
  activeStickyIndex: -1,
3517
3548
  averageSizes: {},
3518
3549
  columns: /* @__PURE__ */ new Map(),
3519
- containerItemKeys: /* @__PURE__ */ new Set(),
3550
+ containerItemKeys: /* @__PURE__ */ new Map(),
3520
3551
  containerItemTypes: /* @__PURE__ */ new Map(),
3521
3552
  dataChangeNeedsScrollUpdate: false,
3522
3553
  didColumnsChange: false,
@@ -3544,6 +3575,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3544
3575
  isStartReached: null,
3545
3576
  lastBatchingAction: Date.now(),
3546
3577
  lastLayout: void 0,
3578
+ lastScrollDelta: 0,
3547
3579
  loadStartTime: Date.now(),
3548
3580
  minIndexSizeChanged: 0,
3549
3581
  nativeMarginTop: 0,
@@ -3844,6 +3876,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3844
3876
  });
3845
3877
 
3846
3878
  exports.LegendList = LegendList;
3879
+ exports.typedForwardRef = typedForwardRef;
3880
+ exports.typedMemo = typedMemo;
3847
3881
  exports.useIsLastItem = useIsLastItem;
3848
3882
  exports.useListScrollSize = useListScrollSize;
3849
3883
  exports.useRecyclingEffect = useRecyclingEffect;
package/index.native.mjs CHANGED
@@ -265,6 +265,11 @@ function extractPadding(style, contentContainerStyle, type) {
265
265
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
266
266
  }
267
267
  function findContainerId(ctx, key) {
268
+ var _a3, _b;
269
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
270
+ if (directMatch !== void 0) {
271
+ return directMatch;
272
+ }
268
273
  const numContainers = peek$(ctx, "numContainers");
269
274
  for (let i = 0; i < numContainers; i++) {
270
275
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -1113,7 +1118,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1113
1118
  }
1114
1119
  }
1115
1120
  if (getFixedItemSize) {
1116
- size = getFixedItemSize(index, data, itemType);
1121
+ size = getFixedItemSize(data, index, itemType);
1117
1122
  if (size !== void 0) {
1118
1123
  sizesKnown.set(key, size);
1119
1124
  }
@@ -1131,7 +1136,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1131
1136
  }
1132
1137
  }
1133
1138
  if (size === void 0) {
1134
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1139
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1135
1140
  }
1136
1141
  setSize(ctx, key, size);
1137
1142
  return size;
@@ -1299,9 +1304,14 @@ function scrollTo(ctx, params) {
1299
1304
  }
1300
1305
  }
1301
1306
 
1307
+ // src/platform/flushSync.native.ts
1308
+ var flushSync = (fn) => {
1309
+ fn();
1310
+ };
1311
+
1302
1312
  // src/utils/checkThreshold.ts
1303
1313
  var HYSTERESIS_MULTIPLIER = 1.3;
1304
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1314
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1305
1315
  const absDistance = Math.abs(distance);
1306
1316
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1307
1317
  if (wasReached === null) {
@@ -1311,7 +1321,7 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1311
1321
  return null;
1312
1322
  }
1313
1323
  const updateSnapshot = () => {
1314
- setSnapshot == null ? void 0 : setSnapshot({
1324
+ setSnapshot({
1315
1325
  atThreshold,
1316
1326
  contentSize: context.contentSize,
1317
1327
  dataLength: context.dataLength,
@@ -1322,19 +1332,21 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1322
1332
  if (!within) {
1323
1333
  return false;
1324
1334
  }
1325
- onReached == null ? void 0 : onReached(distance);
1335
+ onReached(distance);
1326
1336
  updateSnapshot();
1327
1337
  return true;
1328
1338
  }
1329
1339
  const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1330
1340
  if (reset) {
1331
- setSnapshot == null ? void 0 : setSnapshot(void 0);
1341
+ setSnapshot(void 0);
1332
1342
  return false;
1333
1343
  }
1334
1344
  if (within) {
1335
1345
  const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1336
1346
  if (changed) {
1337
- onReached == null ? void 0 : onReached(distance);
1347
+ if (allowReentryOnChange) {
1348
+ onReached(distance);
1349
+ }
1338
1350
  updateSnapshot();
1339
1351
  }
1340
1352
  }
@@ -1377,7 +1389,8 @@ function checkAtBottom(ctx) {
1377
1389
  },
1378
1390
  (snapshot) => {
1379
1391
  state.endReachedSnapshot = snapshot;
1380
- }
1392
+ },
1393
+ true
1381
1394
  );
1382
1395
  }
1383
1396
  }
@@ -1412,15 +1425,16 @@ function checkAtTop(state) {
1412
1425
  },
1413
1426
  (snapshot) => {
1414
1427
  state.startReachedSnapshot = snapshot;
1415
- }
1428
+ },
1429
+ false
1416
1430
  );
1417
1431
  }
1418
1432
 
1419
1433
  // src/core/updateScroll.ts
1420
1434
  function updateScroll(ctx, newScroll, forceUpdate) {
1421
- var _a3;
1422
1435
  const state = ctx.state;
1423
1436
  const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1437
+ const prevScroll = state.scroll;
1424
1438
  state.hasScrolled = true;
1425
1439
  state.lastBatchingAction = Date.now();
1426
1440
  const currentTime = Date.now();
@@ -1438,7 +1452,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1438
1452
  if (state.scrollHistory.length > 5) {
1439
1453
  state.scrollHistory.shift();
1440
1454
  }
1441
- state.scrollPrev = state.scroll;
1455
+ state.scrollPrev = prevScroll;
1442
1456
  state.scrollPrevTime = state.scrollTime;
1443
1457
  state.scroll = newScroll;
1444
1458
  state.scrollTime = currentTime;
@@ -1450,15 +1464,27 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1450
1464
  return;
1451
1465
  }
1452
1466
  }
1467
+ const scrollDelta = Math.abs(newScroll - prevScroll);
1468
+ const scrollLength = state.scrollLength;
1453
1469
  const lastCalculated = state.scrollLastCalculate;
1454
1470
  const shouldUpdate = forceUpdate || state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1455
1471
  if (shouldUpdate) {
1456
1472
  state.scrollLastCalculate = state.scroll;
1457
1473
  state.ignoreScrollFromMVCPIgnored = false;
1458
- (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1459
- checkAtBottom(ctx);
1460
- checkAtTop(state);
1474
+ state.lastScrollDelta = scrollDelta;
1475
+ const runCalculateItems = () => {
1476
+ var _a3;
1477
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1478
+ checkAtBottom(ctx);
1479
+ checkAtTop(state);
1480
+ };
1481
+ if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1482
+ flushSync(runCalculateItems);
1483
+ } else {
1484
+ runCalculateItems();
1485
+ }
1461
1486
  state.dataChangeNeedsScrollUpdate = false;
1487
+ state.lastScrollDelta = 0;
1462
1488
  }
1463
1489
  }
1464
1490
 
@@ -1573,7 +1599,7 @@ function prepareMVCP(ctx, dataChanged) {
1573
1599
  const state = ctx.state;
1574
1600
  const { idsInView, positions, props } = state;
1575
1601
  const {
1576
- maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll }
1602
+ maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
1577
1603
  } = props;
1578
1604
  const scrollingTo = state.scrollingTo;
1579
1605
  let prevPosition;
@@ -1608,8 +1634,16 @@ function prepareMVCP(ctx, dataChanged) {
1608
1634
  return () => {
1609
1635
  let positionDiff = 0;
1610
1636
  if (dataChanged && targetId === void 0 && mvcpData) {
1637
+ const data = state.props.data;
1611
1638
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1612
1639
  const { id, position } = idsInViewWithPositions[i];
1640
+ const index = indexByKey.get(id);
1641
+ if (index !== void 0 && shouldRestorePosition) {
1642
+ const item = data[index];
1643
+ if (item === void 0 || !shouldRestorePosition(item, index, data)) {
1644
+ continue;
1645
+ }
1646
+ }
1613
1647
  const newPosition = positions.get(id);
1614
1648
  if (newPosition !== void 0) {
1615
1649
  positionDiff = newPosition - position;
@@ -1815,7 +1849,9 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
1815
1849
  const numColumns = peek$(ctx, "numColumns");
1816
1850
  const hasColumns = numColumns > 1;
1817
1851
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1818
- const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1852
+ const lastScrollDelta = state.lastScrollDelta;
1853
+ const velocity = getScrollVelocity(state);
1854
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || Platform2.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
1819
1855
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1820
1856
  const useAverageSize = !getEstimatedItemSize;
1821
1857
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
@@ -2594,7 +2630,7 @@ function calculateItemsInView(ctx, params = {}) {
2594
2630
  if (requiredItemTypes) {
2595
2631
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2596
2632
  }
2597
- containerItemKeys.add(id);
2633
+ containerItemKeys.set(id, containerIndex);
2598
2634
  const containerSticky = `containerSticky${containerIndex}`;
2599
2635
  if (stickyIndicesSet.has(i)) {
2600
2636
  set$(ctx, containerSticky, true);
@@ -2841,7 +2877,7 @@ function doInitialAllocateContainers(ctx) {
2841
2877
  const item = data[i];
2842
2878
  if (item !== void 0) {
2843
2879
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
2844
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2880
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(item, i, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(item, i, itemType)) != null ? _c : estimatedItemSize;
2845
2881
  }
2846
2882
  }
2847
2883
  averageItemSize = totalSize / num;
@@ -3028,7 +3064,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3028
3064
  return;
3029
3065
  }
3030
3066
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3031
- const size2 = getFixedItemSize(index, itemData, type);
3067
+ const size2 = getFixedItemSize(itemData, index, type);
3032
3068
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
3033
3069
  return;
3034
3070
  }
@@ -3044,14 +3080,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
3044
3080
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
3045
3081
  const { startBuffered, endBuffered } = state;
3046
3082
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
3047
- if (!needsRecalculate) {
3048
- const numContainers = ctx.values.get("numContainers");
3049
- for (let i = 0; i < numContainers; i++) {
3050
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
3051
- needsRecalculate = true;
3052
- break;
3053
- }
3054
- }
3083
+ if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
3084
+ needsRecalculate = true;
3055
3085
  }
3056
3086
  if (state.needsOtherAxisSize) {
3057
3087
  const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
@@ -3326,7 +3356,8 @@ function normalizeMaintainVisibleContentPosition(value) {
3326
3356
  if (value && typeof value === "object") {
3327
3357
  return {
3328
3358
  data: (_a3 = value.data) != null ? _a3 : false,
3329
- size: (_b = value.size) != null ? _b : true
3359
+ size: (_b = value.size) != null ? _b : true,
3360
+ shouldRestorePosition: value.shouldRestorePosition
3330
3361
  };
3331
3362
  }
3332
3363
  if (value === false) {
@@ -3495,7 +3526,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3495
3526
  activeStickyIndex: -1,
3496
3527
  averageSizes: {},
3497
3528
  columns: /* @__PURE__ */ new Map(),
3498
- containerItemKeys: /* @__PURE__ */ new Set(),
3529
+ containerItemKeys: /* @__PURE__ */ new Map(),
3499
3530
  containerItemTypes: /* @__PURE__ */ new Map(),
3500
3531
  dataChangeNeedsScrollUpdate: false,
3501
3532
  didColumnsChange: false,
@@ -3523,6 +3554,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3523
3554
  isStartReached: null,
3524
3555
  lastBatchingAction: Date.now(),
3525
3556
  lastLayout: void 0,
3557
+ lastScrollDelta: 0,
3526
3558
  loadStartTime: Date.now(),
3527
3559
  minIndexSizeChanged: 0,
3528
3560
  nativeMarginTop: 0,
@@ -3822,4 +3854,4 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3822
3854
  ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React2.createElement(DebugView, { state: refState.current }));
3823
3855
  });
3824
3856
 
3825
- export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
3857
+ export { LegendList, typedForwardRef, typedMemo, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.0.0-beta.17",
3
+ "version": "3.0.0-beta.19",
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,
@@ -1,8 +1,7 @@
1
1
  import * as react_native from 'react-native';
2
2
  import { SectionListData, SectionBase, SectionListRenderItemInfo, SectionListScrollParams } from 'react-native';
3
3
  import * as React from 'react';
4
- import { a as LegendListRef, L as LegendListProps } from './types-Dj2MEm9V.mjs';
5
- import 'react-native-reanimated';
4
+ import { LegendListRef, LegendListProps } from '@legendapp/list';
6
5
 
7
6
  type SectionListSeparatorProps<ItemT, SectionT> = {
8
7
  leadingItem?: ItemT;
package/section-list.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import * as react_native from 'react-native';
2
2
  import { SectionListData, SectionBase, SectionListRenderItemInfo, SectionListScrollParams } from 'react-native';
3
3
  import * as React from 'react';
4
- import { a as LegendListRef, L as LegendListProps } from './types-Dj2MEm9V.js';
5
- import 'react-native-reanimated';
4
+ import { LegendListRef, LegendListProps } from '@legendapp/list';
6
5
 
7
6
  type SectionListSeparatorProps<ItemT, SectionT> = {
8
7
  leadingItem?: ItemT;