@legendapp/list 3.0.0-beta.47 → 3.0.0-beta.49

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/react.js CHANGED
@@ -2083,7 +2083,7 @@ function getId(state, index) {
2083
2083
  }
2084
2084
 
2085
2085
  // src/core/addTotalSize.ts
2086
- function addTotalSize(ctx, key, add) {
2086
+ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2087
2087
  const state = ctx.state;
2088
2088
  const prevTotalSize = state.totalSize;
2089
2089
  let totalSize = state.totalSize;
@@ -2100,25 +2100,29 @@ function addTotalSize(ctx, key, add) {
2100
2100
  {
2101
2101
  state.pendingTotalSize = void 0;
2102
2102
  state.totalSize = totalSize;
2103
- set$(ctx, "totalSize", totalSize);
2103
+ if (notifyTotalSize) {
2104
+ set$(ctx, "totalSize", totalSize);
2105
+ }
2104
2106
  }
2107
+ } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2108
+ set$(ctx, "totalSize", totalSize);
2105
2109
  }
2106
2110
  }
2107
2111
 
2108
2112
  // src/core/setSize.ts
2109
- function setSize(ctx, itemKey, size) {
2113
+ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2110
2114
  const state = ctx.state;
2111
2115
  const { sizes } = state;
2112
2116
  const previousSize = sizes.get(itemKey);
2113
2117
  const diff = previousSize !== void 0 ? size - previousSize : size;
2114
2118
  if (diff !== 0) {
2115
- addTotalSize(ctx, itemKey, diff);
2119
+ addTotalSize(ctx, itemKey, diff, notifyTotalSize);
2116
2120
  }
2117
2121
  sizes.set(itemKey, size);
2118
2122
  }
2119
2123
 
2120
2124
  // src/utils/getItemSize.ts
2121
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
2125
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2122
2126
  var _a3, _b, _c;
2123
2127
  const state = ctx.state;
2124
2128
  const {
@@ -2164,7 +2168,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
2164
2168
  if (size === void 0) {
2165
2169
  size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
2166
2170
  }
2167
- setSize(ctx, key, size);
2171
+ setSize(ctx, key, size, notifyTotalSize);
2168
2172
  return size;
2169
2173
  }
2170
2174
  function getItemSizeAtIndex(ctx, index) {
@@ -2603,10 +2607,10 @@ function getMountedBufferedIndices(state) {
2603
2607
  function getMountedNoBufferIndices(state) {
2604
2608
  return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2605
2609
  }
2606
- function checkAllSizesKnown(state, indices = getMountedBufferedIndices(state)) {
2610
+ function checkAllSizesKnown(state, indices) {
2607
2611
  return indices.length > 0 && indices.every((index) => {
2608
2612
  const key = getId(state, index);
2609
- return state.sizesKnown.has(key);
2613
+ return key !== void 0 && state.sizesKnown.has(key);
2610
2614
  });
2611
2615
  }
2612
2616
 
@@ -3916,6 +3920,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3916
3920
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3917
3921
  const useAverageSize = !getEstimatedItemSize;
3918
3922
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0) !== 0;
3923
+ const notifyTotalSizeWhileCachingSizes = false;
3919
3924
  let currentRowTop = 0;
3920
3925
  let column = 1;
3921
3926
  let maxSizeInRow = 0;
@@ -3943,7 +3948,15 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3943
3948
  const prevIndex = startIndex - 1;
3944
3949
  const prevId = getId(state, prevIndex);
3945
3950
  const prevPosition = (_c = positions[prevIndex]) != null ? _c : 0;
3946
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
3951
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(
3952
+ ctx,
3953
+ prevId,
3954
+ prevIndex,
3955
+ data[prevIndex],
3956
+ useAverageSize,
3957
+ preferCachedSize,
3958
+ notifyTotalSizeWhileCachingSizes
3959
+ );
3947
3960
  currentRowTop = prevPosition + prevSize;
3948
3961
  }
3949
3962
  }
@@ -3976,7 +3989,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3976
3989
  maxSizeInRow = 0;
3977
3990
  }
3978
3991
  const knownSize = sizesKnown.get(id);
3979
- const size = knownSize !== void 0 ? knownSize : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
3992
+ const size = knownSize !== void 0 ? knownSize : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize, notifyTotalSizeWhileCachingSizes);
3980
3993
  if (IS_DEV && needsIndexByKey) {
3981
3994
  if (indexByKeyForChecking.has(id)) {
3982
3995
  console.error(
@@ -4232,7 +4245,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4232
4245
  }
4233
4246
  function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4234
4247
  let value = ctx.mapViewabilityAmountValues.get(containerId);
4235
- if (!value || value.key !== key) {
4248
+ if (!value || value.key !== key || value.index !== index) {
4236
4249
  value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
4237
4250
  }
4238
4251
  return value.isViewable;
@@ -4247,7 +4260,7 @@ var unstableBatchedUpdates = ReactDOM__namespace.unstable_batchedUpdates;
4247
4260
  var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
4248
4261
 
4249
4262
  // src/utils/findAvailableContainers.ts
4250
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
4263
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4251
4264
  const numContainers = peek$(ctx, "numContainers");
4252
4265
  const state = ctx.state;
4253
4266
  const { stickyContainerPool, containerItemTypes } = state;
@@ -4315,6 +4328,7 @@ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pen
4315
4328
  }
4316
4329
  const key = peek$(ctx, `containerItemKey${u}`);
4317
4330
  if (key === void 0) continue;
4331
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4318
4332
  const index = state.indexByKey.get(key);
4319
4333
  const isOutOfView = index < startBuffered || index > endBuffered;
4320
4334
  if (isOutOfView) {
@@ -4450,7 +4464,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4450
4464
  function calculateItemsInView(ctx, params = {}) {
4451
4465
  const state = ctx.state;
4452
4466
  batchedUpdates(() => {
4453
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
4467
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
4454
4468
  const {
4455
4469
  columns,
4456
4470
  columnSpans,
@@ -4552,17 +4566,31 @@ function calculateItemsInView(ctx, params = {}) {
4552
4566
  if (minIndexSizeChanged !== void 0) {
4553
4567
  state.minIndexSizeChanged = void 0;
4554
4568
  }
4569
+ let protectedContainerKeys;
4570
+ if (dataChanged && doMVCP && state.props.maintainVisibleContentPosition.data && state.didContainersLayout && state.idsInView.length > 0) {
4571
+ const shouldRestorePosition = state.props.maintainVisibleContentPosition.shouldRestorePosition;
4572
+ protectedContainerKeys = /* @__PURE__ */ new Set();
4573
+ for (const id of state.idsInView) {
4574
+ const index = indexByKey.get(id);
4575
+ if (index === void 0) continue;
4576
+ if (shouldRestorePosition && !shouldRestorePosition(data[index], index, data)) continue;
4577
+ protectedContainerKeys.add(id);
4578
+ }
4579
+ }
4580
+ const scrollBeforeMVCP = state.scroll;
4581
+ const scrollAdjustPendingBeforeMVCP = (_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0;
4555
4582
  checkMVCP == null ? void 0 : checkMVCP();
4583
+ const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_f = peek$(ctx, "scrollAdjustPending")) != null ? _f : 0) !== scrollAdjustPendingBeforeMVCP);
4556
4584
  let startNoBuffer = null;
4557
4585
  let startBuffered = null;
4558
4586
  let startBufferedId = null;
4559
4587
  let endNoBuffer = null;
4560
4588
  let endBuffered = null;
4561
- let loopStart = (_e = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _e : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4589
+ let loopStart = (_g = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _g : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4562
4590
  for (let i = loopStart; i >= 0; i--) {
4563
- const id = (_f = idCache[i]) != null ? _f : getId(state, i);
4591
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
4564
4592
  const top = positions[i];
4565
- const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
4593
+ const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
4566
4594
  const bottom = top + size;
4567
4595
  if (bottom > scroll - scrollBufferTop) {
4568
4596
  loopStart = i;
@@ -4593,8 +4621,8 @@ function calculateItemsInView(ctx, params = {}) {
4593
4621
  let firstFullyOnScreenIndex;
4594
4622
  const dataLength = data.length;
4595
4623
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4596
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
4597
- const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
4624
+ const id = (_j = idCache[i]) != null ? _j : getId(state, i);
4625
+ const size = (_k = sizes.get(id)) != null ? _k : getItemSize(ctx, id, i, data[i]);
4598
4626
  const top = positions[i];
4599
4627
  if (!foundEnd) {
4600
4628
  if (startNoBuffer === null && top + size > scroll) {
@@ -4633,7 +4661,7 @@ function calculateItemsInView(ctx, params = {}) {
4633
4661
  const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4634
4662
  if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4635
4663
  for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4636
- const id = (_j = idCache[i]) != null ? _j : getId(state, i);
4664
+ const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4637
4665
  idsInView.push(id);
4638
4666
  }
4639
4667
  }
@@ -4666,7 +4694,7 @@ function calculateItemsInView(ctx, params = {}) {
4666
4694
  const needNewContainers = [];
4667
4695
  const needNewContainersSet = /* @__PURE__ */ new Set();
4668
4696
  for (let i = startBuffered; i <= endBuffered; i++) {
4669
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4697
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4670
4698
  if (!containerItemKeys.has(id)) {
4671
4699
  needNewContainersSet.add(i);
4672
4700
  needNewContainers.push(i);
@@ -4675,7 +4703,7 @@ function calculateItemsInView(ctx, params = {}) {
4675
4703
  if (alwaysRenderArr.length > 0) {
4676
4704
  for (const index of alwaysRenderArr) {
4677
4705
  if (index < 0 || index >= dataLength) continue;
4678
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
4706
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4679
4707
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4680
4708
  needNewContainersSet.add(index);
4681
4709
  needNewContainers.push(index);
@@ -4708,12 +4736,13 @@ function calculateItemsInView(ctx, params = {}) {
4708
4736
  endBuffered,
4709
4737
  pendingRemoval,
4710
4738
  requiredItemTypes,
4711
- needNewContainers
4739
+ needNewContainers,
4740
+ protectedContainerKeys
4712
4741
  );
4713
4742
  for (let idx = 0; idx < needNewContainers.length; idx++) {
4714
4743
  const i = needNewContainers[idx];
4715
4744
  const containerIndex = availableContainers[idx];
4716
- const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4745
+ const id = (_o = idCache[i]) != null ? _o : getId(state, i);
4717
4746
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4718
4747
  if (oldKey && oldKey !== id) {
4719
4748
  containerItemKeys.delete(oldKey);
@@ -4724,6 +4753,7 @@ function calculateItemsInView(ctx, params = {}) {
4724
4753
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4725
4754
  }
4726
4755
  containerItemKeys.set(id, containerIndex);
4756
+ (_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.add(id);
4727
4757
  const containerSticky = `containerSticky${containerIndex}`;
4728
4758
  const isSticky = stickyIndicesSet.has(i);
4729
4759
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4751,10 +4781,13 @@ function calculateItemsInView(ctx, params = {}) {
4751
4781
  }
4752
4782
  }
4753
4783
  }
4784
+ if (((_q = state.userScrollAnchorResetKeys) == null ? void 0 : _q.size) === 0) {
4785
+ state.userScrollAnchorResetKeys = void 0;
4786
+ }
4754
4787
  if (alwaysRenderArr.length > 0) {
4755
4788
  for (const index of alwaysRenderArr) {
4756
4789
  if (index < 0 || index >= dataLength) continue;
4757
- const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4790
+ const id = (_r = idCache[index]) != null ? _r : getId(state, index);
4758
4791
  const containerIndex = containerItemKeys.get(id);
4759
4792
  if (containerIndex !== void 0) {
4760
4793
  state.stickyContainerPool.add(containerIndex);
@@ -4815,16 +4848,18 @@ function calculateItemsInView(ctx, params = {}) {
4815
4848
  handleInitialScrollLayoutReady(ctx);
4816
4849
  }
4817
4850
  if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
4818
- updateViewableItems(
4819
- ctx.state,
4820
- ctx,
4821
- viewabilityConfigCallbackPairs,
4822
- scrollLength,
4823
- startNoBuffer,
4824
- endNoBuffer,
4825
- startBuffered != null ? startBuffered : startNoBuffer,
4826
- endBuffered != null ? endBuffered : endNoBuffer
4827
- );
4851
+ if (!didMVCPAdjustScroll) {
4852
+ updateViewableItems(
4853
+ ctx.state,
4854
+ ctx,
4855
+ viewabilityConfigCallbackPairs,
4856
+ scrollLength,
4857
+ startNoBuffer,
4858
+ endNoBuffer,
4859
+ startBuffered != null ? startBuffered : startNoBuffer,
4860
+ endBuffered != null ? endBuffered : endNoBuffer
4861
+ );
4862
+ }
4828
4863
  }
4829
4864
  if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
4830
4865
  const item = data[nextActiveStickyIndex];
@@ -5113,7 +5148,14 @@ function updateScroll(ctx, newScroll, forceUpdate) {
5113
5148
  (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
5114
5149
  checkThresholds(ctx);
5115
5150
  };
5116
- if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
5151
+ if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
5152
+ state.mvcpAnchorLock = void 0;
5153
+ state.pendingNativeMVCPAdjust = void 0;
5154
+ state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
5155
+ if (state.queuedMVCPRecalculate !== void 0) {
5156
+ cancelAnimationFrame(state.queuedMVCPRecalculate);
5157
+ state.queuedMVCPRecalculate = void 0;
5158
+ }
5117
5159
  ReactDOM.flushSync(runCalculateItems);
5118
5160
  } else {
5119
5161
  runCalculateItems();
@@ -5296,6 +5338,20 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5296
5338
  // src/core/updateItemSize.ts
5297
5339
  function runOrScheduleMVCPRecalculate(ctx) {
5298
5340
  const state = ctx.state;
5341
+ if (state.userScrollAnchorResetKeys !== void 0) {
5342
+ if (state.queuedMVCPRecalculate !== void 0) {
5343
+ return;
5344
+ }
5345
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5346
+ var _a3;
5347
+ state.queuedMVCPRecalculate = void 0;
5348
+ calculateItemsInView(ctx);
5349
+ if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5350
+ state.userScrollAnchorResetKeys = void 0;
5351
+ }
5352
+ });
5353
+ return;
5354
+ }
5299
5355
  {
5300
5356
  if (!state.mvcpAnchorLock) {
5301
5357
  if (state.queuedMVCPRecalculate !== void 0) {
@@ -5317,6 +5373,8 @@ function runOrScheduleMVCPRecalculate(ctx) {
5317
5373
  function updateItemSize(ctx, itemKey, sizeObj) {
5318
5374
  var _a3;
5319
5375
  const state = ctx.state;
5376
+ const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5377
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5320
5378
  const {
5321
5379
  didContainersLayout,
5322
5380
  sizesKnown,
@@ -5395,10 +5453,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5395
5453
  if (!cur || maxOtherAxisSize > cur) {
5396
5454
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
5397
5455
  }
5398
- if (didContainersLayout || checkAllSizesKnown(state)) {
5456
+ if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5399
5457
  if (needsRecalculate) {
5400
5458
  state.scrollForNextCalculateItemsInView = void 0;
5401
5459
  runOrScheduleMVCPRecalculate(ctx);
5460
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5461
+ state.userScrollAnchorResetKeys = void 0;
5402
5462
  }
5403
5463
  if (shouldMaintainScrollAtEnd) {
5404
5464
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
package/react.mjs CHANGED
@@ -2062,7 +2062,7 @@ function getId(state, index) {
2062
2062
  }
2063
2063
 
2064
2064
  // src/core/addTotalSize.ts
2065
- function addTotalSize(ctx, key, add) {
2065
+ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2066
2066
  const state = ctx.state;
2067
2067
  const prevTotalSize = state.totalSize;
2068
2068
  let totalSize = state.totalSize;
@@ -2079,25 +2079,29 @@ function addTotalSize(ctx, key, add) {
2079
2079
  {
2080
2080
  state.pendingTotalSize = void 0;
2081
2081
  state.totalSize = totalSize;
2082
- set$(ctx, "totalSize", totalSize);
2082
+ if (notifyTotalSize) {
2083
+ set$(ctx, "totalSize", totalSize);
2084
+ }
2083
2085
  }
2086
+ } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2087
+ set$(ctx, "totalSize", totalSize);
2084
2088
  }
2085
2089
  }
2086
2090
 
2087
2091
  // src/core/setSize.ts
2088
- function setSize(ctx, itemKey, size) {
2092
+ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2089
2093
  const state = ctx.state;
2090
2094
  const { sizes } = state;
2091
2095
  const previousSize = sizes.get(itemKey);
2092
2096
  const diff = previousSize !== void 0 ? size - previousSize : size;
2093
2097
  if (diff !== 0) {
2094
- addTotalSize(ctx, itemKey, diff);
2098
+ addTotalSize(ctx, itemKey, diff, notifyTotalSize);
2095
2099
  }
2096
2100
  sizes.set(itemKey, size);
2097
2101
  }
2098
2102
 
2099
2103
  // src/utils/getItemSize.ts
2100
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
2104
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2101
2105
  var _a3, _b, _c;
2102
2106
  const state = ctx.state;
2103
2107
  const {
@@ -2143,7 +2147,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
2143
2147
  if (size === void 0) {
2144
2148
  size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
2145
2149
  }
2146
- setSize(ctx, key, size);
2150
+ setSize(ctx, key, size, notifyTotalSize);
2147
2151
  return size;
2148
2152
  }
2149
2153
  function getItemSizeAtIndex(ctx, index) {
@@ -2582,10 +2586,10 @@ function getMountedBufferedIndices(state) {
2582
2586
  function getMountedNoBufferIndices(state) {
2583
2587
  return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2584
2588
  }
2585
- function checkAllSizesKnown(state, indices = getMountedBufferedIndices(state)) {
2589
+ function checkAllSizesKnown(state, indices) {
2586
2590
  return indices.length > 0 && indices.every((index) => {
2587
2591
  const key = getId(state, index);
2588
- return state.sizesKnown.has(key);
2592
+ return key !== void 0 && state.sizesKnown.has(key);
2589
2593
  });
2590
2594
  }
2591
2595
 
@@ -3895,6 +3899,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3895
3899
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3896
3900
  const useAverageSize = !getEstimatedItemSize;
3897
3901
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0) !== 0;
3902
+ const notifyTotalSizeWhileCachingSizes = false;
3898
3903
  let currentRowTop = 0;
3899
3904
  let column = 1;
3900
3905
  let maxSizeInRow = 0;
@@ -3922,7 +3927,15 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3922
3927
  const prevIndex = startIndex - 1;
3923
3928
  const prevId = getId(state, prevIndex);
3924
3929
  const prevPosition = (_c = positions[prevIndex]) != null ? _c : 0;
3925
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
3930
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(
3931
+ ctx,
3932
+ prevId,
3933
+ prevIndex,
3934
+ data[prevIndex],
3935
+ useAverageSize,
3936
+ preferCachedSize,
3937
+ notifyTotalSizeWhileCachingSizes
3938
+ );
3926
3939
  currentRowTop = prevPosition + prevSize;
3927
3940
  }
3928
3941
  }
@@ -3955,7 +3968,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3955
3968
  maxSizeInRow = 0;
3956
3969
  }
3957
3970
  const knownSize = sizesKnown.get(id);
3958
- const size = knownSize !== void 0 ? knownSize : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
3971
+ const size = knownSize !== void 0 ? knownSize : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize, notifyTotalSizeWhileCachingSizes);
3959
3972
  if (IS_DEV && needsIndexByKey) {
3960
3973
  if (indexByKeyForChecking.has(id)) {
3961
3974
  console.error(
@@ -4211,7 +4224,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4211
4224
  }
4212
4225
  function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4213
4226
  let value = ctx.mapViewabilityAmountValues.get(containerId);
4214
- if (!value || value.key !== key) {
4227
+ if (!value || value.key !== key || value.index !== index) {
4215
4228
  value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
4216
4229
  }
4217
4230
  return value.isViewable;
@@ -4226,7 +4239,7 @@ var unstableBatchedUpdates = ReactDOM.unstable_batchedUpdates;
4226
4239
  var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
4227
4240
 
4228
4241
  // src/utils/findAvailableContainers.ts
4229
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
4242
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4230
4243
  const numContainers = peek$(ctx, "numContainers");
4231
4244
  const state = ctx.state;
4232
4245
  const { stickyContainerPool, containerItemTypes } = state;
@@ -4294,6 +4307,7 @@ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pen
4294
4307
  }
4295
4308
  const key = peek$(ctx, `containerItemKey${u}`);
4296
4309
  if (key === void 0) continue;
4310
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4297
4311
  const index = state.indexByKey.get(key);
4298
4312
  const isOutOfView = index < startBuffered || index > endBuffered;
4299
4313
  if (isOutOfView) {
@@ -4429,7 +4443,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4429
4443
  function calculateItemsInView(ctx, params = {}) {
4430
4444
  const state = ctx.state;
4431
4445
  batchedUpdates(() => {
4432
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
4446
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
4433
4447
  const {
4434
4448
  columns,
4435
4449
  columnSpans,
@@ -4531,17 +4545,31 @@ function calculateItemsInView(ctx, params = {}) {
4531
4545
  if (minIndexSizeChanged !== void 0) {
4532
4546
  state.minIndexSizeChanged = void 0;
4533
4547
  }
4548
+ let protectedContainerKeys;
4549
+ if (dataChanged && doMVCP && state.props.maintainVisibleContentPosition.data && state.didContainersLayout && state.idsInView.length > 0) {
4550
+ const shouldRestorePosition = state.props.maintainVisibleContentPosition.shouldRestorePosition;
4551
+ protectedContainerKeys = /* @__PURE__ */ new Set();
4552
+ for (const id of state.idsInView) {
4553
+ const index = indexByKey.get(id);
4554
+ if (index === void 0) continue;
4555
+ if (shouldRestorePosition && !shouldRestorePosition(data[index], index, data)) continue;
4556
+ protectedContainerKeys.add(id);
4557
+ }
4558
+ }
4559
+ const scrollBeforeMVCP = state.scroll;
4560
+ const scrollAdjustPendingBeforeMVCP = (_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0;
4534
4561
  checkMVCP == null ? void 0 : checkMVCP();
4562
+ const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_f = peek$(ctx, "scrollAdjustPending")) != null ? _f : 0) !== scrollAdjustPendingBeforeMVCP);
4535
4563
  let startNoBuffer = null;
4536
4564
  let startBuffered = null;
4537
4565
  let startBufferedId = null;
4538
4566
  let endNoBuffer = null;
4539
4567
  let endBuffered = null;
4540
- let loopStart = (_e = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _e : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4568
+ let loopStart = (_g = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _g : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4541
4569
  for (let i = loopStart; i >= 0; i--) {
4542
- const id = (_f = idCache[i]) != null ? _f : getId(state, i);
4570
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
4543
4571
  const top = positions[i];
4544
- const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
4572
+ const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
4545
4573
  const bottom = top + size;
4546
4574
  if (bottom > scroll - scrollBufferTop) {
4547
4575
  loopStart = i;
@@ -4572,8 +4600,8 @@ function calculateItemsInView(ctx, params = {}) {
4572
4600
  let firstFullyOnScreenIndex;
4573
4601
  const dataLength = data.length;
4574
4602
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4575
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
4576
- const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
4603
+ const id = (_j = idCache[i]) != null ? _j : getId(state, i);
4604
+ const size = (_k = sizes.get(id)) != null ? _k : getItemSize(ctx, id, i, data[i]);
4577
4605
  const top = positions[i];
4578
4606
  if (!foundEnd) {
4579
4607
  if (startNoBuffer === null && top + size > scroll) {
@@ -4612,7 +4640,7 @@ function calculateItemsInView(ctx, params = {}) {
4612
4640
  const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4613
4641
  if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4614
4642
  for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4615
- const id = (_j = idCache[i]) != null ? _j : getId(state, i);
4643
+ const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4616
4644
  idsInView.push(id);
4617
4645
  }
4618
4646
  }
@@ -4645,7 +4673,7 @@ function calculateItemsInView(ctx, params = {}) {
4645
4673
  const needNewContainers = [];
4646
4674
  const needNewContainersSet = /* @__PURE__ */ new Set();
4647
4675
  for (let i = startBuffered; i <= endBuffered; i++) {
4648
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4676
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4649
4677
  if (!containerItemKeys.has(id)) {
4650
4678
  needNewContainersSet.add(i);
4651
4679
  needNewContainers.push(i);
@@ -4654,7 +4682,7 @@ function calculateItemsInView(ctx, params = {}) {
4654
4682
  if (alwaysRenderArr.length > 0) {
4655
4683
  for (const index of alwaysRenderArr) {
4656
4684
  if (index < 0 || index >= dataLength) continue;
4657
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
4685
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4658
4686
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4659
4687
  needNewContainersSet.add(index);
4660
4688
  needNewContainers.push(index);
@@ -4687,12 +4715,13 @@ function calculateItemsInView(ctx, params = {}) {
4687
4715
  endBuffered,
4688
4716
  pendingRemoval,
4689
4717
  requiredItemTypes,
4690
- needNewContainers
4718
+ needNewContainers,
4719
+ protectedContainerKeys
4691
4720
  );
4692
4721
  for (let idx = 0; idx < needNewContainers.length; idx++) {
4693
4722
  const i = needNewContainers[idx];
4694
4723
  const containerIndex = availableContainers[idx];
4695
- const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4724
+ const id = (_o = idCache[i]) != null ? _o : getId(state, i);
4696
4725
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4697
4726
  if (oldKey && oldKey !== id) {
4698
4727
  containerItemKeys.delete(oldKey);
@@ -4703,6 +4732,7 @@ function calculateItemsInView(ctx, params = {}) {
4703
4732
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4704
4733
  }
4705
4734
  containerItemKeys.set(id, containerIndex);
4735
+ (_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.add(id);
4706
4736
  const containerSticky = `containerSticky${containerIndex}`;
4707
4737
  const isSticky = stickyIndicesSet.has(i);
4708
4738
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4730,10 +4760,13 @@ function calculateItemsInView(ctx, params = {}) {
4730
4760
  }
4731
4761
  }
4732
4762
  }
4763
+ if (((_q = state.userScrollAnchorResetKeys) == null ? void 0 : _q.size) === 0) {
4764
+ state.userScrollAnchorResetKeys = void 0;
4765
+ }
4733
4766
  if (alwaysRenderArr.length > 0) {
4734
4767
  for (const index of alwaysRenderArr) {
4735
4768
  if (index < 0 || index >= dataLength) continue;
4736
- const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4769
+ const id = (_r = idCache[index]) != null ? _r : getId(state, index);
4737
4770
  const containerIndex = containerItemKeys.get(id);
4738
4771
  if (containerIndex !== void 0) {
4739
4772
  state.stickyContainerPool.add(containerIndex);
@@ -4794,16 +4827,18 @@ function calculateItemsInView(ctx, params = {}) {
4794
4827
  handleInitialScrollLayoutReady(ctx);
4795
4828
  }
4796
4829
  if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
4797
- updateViewableItems(
4798
- ctx.state,
4799
- ctx,
4800
- viewabilityConfigCallbackPairs,
4801
- scrollLength,
4802
- startNoBuffer,
4803
- endNoBuffer,
4804
- startBuffered != null ? startBuffered : startNoBuffer,
4805
- endBuffered != null ? endBuffered : endNoBuffer
4806
- );
4830
+ if (!didMVCPAdjustScroll) {
4831
+ updateViewableItems(
4832
+ ctx.state,
4833
+ ctx,
4834
+ viewabilityConfigCallbackPairs,
4835
+ scrollLength,
4836
+ startNoBuffer,
4837
+ endNoBuffer,
4838
+ startBuffered != null ? startBuffered : startNoBuffer,
4839
+ endBuffered != null ? endBuffered : endNoBuffer
4840
+ );
4841
+ }
4807
4842
  }
4808
4843
  if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
4809
4844
  const item = data[nextActiveStickyIndex];
@@ -5092,7 +5127,14 @@ function updateScroll(ctx, newScroll, forceUpdate) {
5092
5127
  (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
5093
5128
  checkThresholds(ctx);
5094
5129
  };
5095
- if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
5130
+ if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
5131
+ state.mvcpAnchorLock = void 0;
5132
+ state.pendingNativeMVCPAdjust = void 0;
5133
+ state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
5134
+ if (state.queuedMVCPRecalculate !== void 0) {
5135
+ cancelAnimationFrame(state.queuedMVCPRecalculate);
5136
+ state.queuedMVCPRecalculate = void 0;
5137
+ }
5096
5138
  flushSync(runCalculateItems);
5097
5139
  } else {
5098
5140
  runCalculateItems();
@@ -5275,6 +5317,20 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5275
5317
  // src/core/updateItemSize.ts
5276
5318
  function runOrScheduleMVCPRecalculate(ctx) {
5277
5319
  const state = ctx.state;
5320
+ if (state.userScrollAnchorResetKeys !== void 0) {
5321
+ if (state.queuedMVCPRecalculate !== void 0) {
5322
+ return;
5323
+ }
5324
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5325
+ var _a3;
5326
+ state.queuedMVCPRecalculate = void 0;
5327
+ calculateItemsInView(ctx);
5328
+ if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5329
+ state.userScrollAnchorResetKeys = void 0;
5330
+ }
5331
+ });
5332
+ return;
5333
+ }
5278
5334
  {
5279
5335
  if (!state.mvcpAnchorLock) {
5280
5336
  if (state.queuedMVCPRecalculate !== void 0) {
@@ -5296,6 +5352,8 @@ function runOrScheduleMVCPRecalculate(ctx) {
5296
5352
  function updateItemSize(ctx, itemKey, sizeObj) {
5297
5353
  var _a3;
5298
5354
  const state = ctx.state;
5355
+ const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5356
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5299
5357
  const {
5300
5358
  didContainersLayout,
5301
5359
  sizesKnown,
@@ -5374,10 +5432,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5374
5432
  if (!cur || maxOtherAxisSize > cur) {
5375
5433
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
5376
5434
  }
5377
- if (didContainersLayout || checkAllSizesKnown(state)) {
5435
+ if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5378
5436
  if (needsRecalculate) {
5379
5437
  state.scrollForNextCalculateItemsInView = void 0;
5380
5438
  runOrScheduleMVCPRecalculate(ctx);
5439
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5440
+ state.userScrollAnchorResetKeys = void 0;
5381
5441
  }
5382
5442
  if (shouldMaintainScrollAtEnd) {
5383
5443
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {