@legendapp/list 3.0.1 → 3.0.3

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/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 3.0.3
2
+
3
+ - Fix: MVCP was getting batched to improve big jumps, but was making scroll worse
4
+ - Fix: On native, ignore one-physical-pixel layout measurement noise, preventing unnecessary item size updates from Fabric and native onLayout rounding differences.
5
+ - Fix: Average item sizes update correctly when getFixedItemSize returns undefined for only some item types.
6
+
7
+ ## 3.0.2
8
+
9
+ - Fix: Using viewability was causing scrolling to end to sometimes not update items in view if the JS thread was slammed
10
+
1
11
  ## 3.0.1
2
12
 
3
13
  - Feat: SectionList now supports getFixedItemSize for items, headers, footers, and separators.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
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/react-native.js CHANGED
@@ -743,6 +743,22 @@ function Separator({ ItemSeparatorComponent, leadingItem }) {
743
743
  const isLastItem = useIsLastItem();
744
744
  return isLastItem ? null : /* @__PURE__ */ React2__namespace.createElement(ItemSeparatorComponent, { leadingItem });
745
745
  }
746
+ var PixelRatio = ReactNative.PixelRatio;
747
+
748
+ // src/utils/layoutMeasurement.ts
749
+ var FLOATING_POINT_SLACK = 0.01;
750
+ var NATIVE_LAYOUT_MEASUREMENT_EPSILON = 1 / PixelRatio.get() + FLOATING_POINT_SLACK;
751
+ function isWithinEpsilon(delta) {
752
+ return Math.abs(delta) <= NATIVE_LAYOUT_MEASUREMENT_EPSILON;
753
+ }
754
+ function isNativeLayoutNoise(delta) {
755
+ return isWithinEpsilon(delta);
756
+ }
757
+ function isNativeLayoutSizeNoise(heightDelta, widthDelta) {
758
+ return isWithinEpsilon(heightDelta) && isWithinEpsilon(widthDelta);
759
+ }
760
+
761
+ // src/hooks/useOnLayoutSync.native.tsx
746
762
  function useOnLayoutSync({
747
763
  ref,
748
764
  onLayoutProp,
@@ -751,11 +767,21 @@ function useOnLayoutSync({
751
767
  const lastLayoutRef = React2.useRef(null);
752
768
  const onLayout = React2.useCallback(
753
769
  (event) => {
754
- var _a3, _b;
755
770
  const { layout } = event.nativeEvent;
756
- if (layout.height !== ((_a3 = lastLayoutRef.current) == null ? void 0 : _a3.height) || layout.width !== ((_b = lastLayoutRef.current) == null ? void 0 : _b.width)) {
771
+ const lastLayout = lastLayoutRef.current;
772
+ const didLayoutSizeChange = lastLayout && (layout.height !== lastLayout.height || layout.width !== lastLayout.width);
773
+ const isMeasuredLayoutNoise = !!didLayoutSizeChange && !!lastLayout.measuredLayout && isNativeLayoutSizeNoise(
774
+ layout.height - lastLayout.measuredLayout.height,
775
+ layout.width - lastLayout.measuredLayout.width
776
+ );
777
+ if (!lastLayout || didLayoutSizeChange && !isMeasuredLayoutNoise) {
757
778
  onLayoutChange(layout, false);
758
- lastLayoutRef.current = layout;
779
+ }
780
+ if (!lastLayout || didLayoutSizeChange) {
781
+ lastLayoutRef.current = {
782
+ ...layout,
783
+ measuredLayout: isMeasuredLayoutNoise ? lastLayout == null ? void 0 : lastLayout.measuredLayout : void 0
784
+ };
759
785
  }
760
786
  onLayoutProp == null ? void 0 : onLayoutProp(event);
761
787
  },
@@ -766,7 +792,7 @@ function useOnLayoutSync({
766
792
  if (ref.current) {
767
793
  ref.current.measure((x, y, width, height) => {
768
794
  const layout = { height, width, x, y };
769
- lastLayoutRef.current = layout;
795
+ lastLayoutRef.current = { ...layout, measuredLayout: layout };
770
796
  onLayoutChange(layout, true);
771
797
  });
772
798
  }
@@ -2199,10 +2225,7 @@ function requestAdjust(ctx, positionDiff, dataChanged) {
2199
2225
  const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2200
2226
  const doit = () => {
2201
2227
  if (needsScrollWorkaround) {
2202
- scrollTo(ctx, {
2203
- noScrollingTo: true,
2204
- offset: state.scroll
2205
- });
2228
+ doScrollTo(ctx, { horizontal: state.props.horizontal, offset: state.scroll });
2206
2229
  } else {
2207
2230
  state.scrollAdjustHandler.requestAdjust(positionDiff);
2208
2231
  if (state.adjustingFromInitialMount) {
@@ -2598,7 +2621,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2598
2621
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
2599
2622
  state.mvcpAnchorLock = void 0;
2600
2623
  state.pendingNativeMVCPAdjust = void 0;
2601
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
2624
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
2602
2625
  if (state.queuedMVCPRecalculate !== void 0) {
2603
2626
  cancelAnimationFrame(state.queuedMVCPRecalculate);
2604
2627
  state.queuedMVCPRecalculate = void 0;
@@ -4416,7 +4439,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4416
4439
  function calculateItemsInView(ctx, params = {}) {
4417
4440
  const state = ctx.state;
4418
4441
  batchedUpdates(() => {
4419
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
4442
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
4420
4443
  const {
4421
4444
  columns,
4422
4445
  containerItemKeys,
@@ -4511,7 +4534,7 @@ function calculateItemsInView(ctx, params = {}) {
4511
4534
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4512
4535
  };
4513
4536
  updateScrollRange();
4514
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4537
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4515
4538
  const { top, bottom } = scrollForNextCalculateItemsInView;
4516
4539
  if (top === null && bottom === null) {
4517
4540
  state.scrollForNextCalculateItemsInView = void 0;
@@ -4730,7 +4753,7 @@ function calculateItemsInView(ctx, params = {}) {
4730
4753
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4731
4754
  }
4732
4755
  containerItemKeys.set(id, containerIndex);
4733
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
4756
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
4734
4757
  const containerSticky = `containerSticky${containerIndex}`;
4735
4758
  const isSticky = stickyHeaderIndicesSet.has(i);
4736
4759
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4758,13 +4781,17 @@ function calculateItemsInView(ctx, params = {}) {
4758
4781
  }
4759
4782
  }
4760
4783
  }
4761
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
4762
- state.userScrollAnchorResetKeys = void 0;
4784
+ if (state.userScrollAnchorReset) {
4785
+ if (state.userScrollAnchorReset.keys.size === 0) {
4786
+ state.userScrollAnchorReset = void 0;
4787
+ } else {
4788
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
4789
+ }
4763
4790
  }
4764
4791
  if (alwaysRenderArr.length > 0) {
4765
4792
  for (const index of alwaysRenderArr) {
4766
4793
  if (index < 0 || index >= dataLength) continue;
4767
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
4794
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
4768
4795
  const containerIndex = containerItemKeys.get(id);
4769
4796
  if (containerIndex !== void 0) {
4770
4797
  state.stickyContainerPool.add(containerIndex);
@@ -5218,37 +5245,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5218
5245
 
5219
5246
  // src/core/updateItemSize.ts
5220
5247
  function runOrScheduleMVCPRecalculate(ctx) {
5248
+ var _a3, _b;
5221
5249
  const state = ctx.state;
5222
- if (state.userScrollAnchorResetKeys !== void 0) {
5223
- if (state.queuedMVCPRecalculate !== void 0) {
5224
- return;
5225
- }
5226
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5227
- var _a3;
5228
- state.queuedMVCPRecalculate = void 0;
5250
+ if (state.userScrollAnchorReset !== void 0) {
5251
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5252
+ const replacementMeasurementBatchThreshold = 3;
5253
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5254
+ if (shouldBatchReplacementMeasurements) {
5255
+ if (state.queuedMVCPRecalculate === void 0) {
5256
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5257
+ var _a4;
5258
+ state.queuedMVCPRecalculate = void 0;
5259
+ calculateItemsInView(ctx);
5260
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5261
+ state.userScrollAnchorReset = void 0;
5262
+ }
5263
+ });
5264
+ }
5265
+ } else {
5229
5266
  calculateItemsInView(ctx);
5230
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5231
- state.userScrollAnchorResetKeys = void 0;
5267
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5268
+ state.userScrollAnchorReset = void 0;
5232
5269
  }
5233
- });
5234
- return;
5235
- }
5236
- if (Platform.OS === "web") {
5270
+ }
5271
+ } else if (Platform.OS === "web") {
5237
5272
  if (!state.mvcpAnchorLock) {
5238
5273
  if (state.queuedMVCPRecalculate !== void 0) {
5239
5274
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5240
5275
  state.queuedMVCPRecalculate = void 0;
5241
5276
  }
5242
5277
  calculateItemsInView(ctx, { doMVCP: true });
5243
- return;
5244
- }
5245
- if (state.queuedMVCPRecalculate !== void 0) {
5246
- return;
5278
+ } else if (state.queuedMVCPRecalculate === void 0) {
5279
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5280
+ state.queuedMVCPRecalculate = void 0;
5281
+ calculateItemsInView(ctx, { doMVCP: true });
5282
+ });
5247
5283
  }
5248
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5249
- state.queuedMVCPRecalculate = void 0;
5250
- calculateItemsInView(ctx, { doMVCP: true });
5251
- });
5252
5284
  } else {
5253
5285
  calculateItemsInView(ctx, { doMVCP: true });
5254
5286
  }
@@ -5266,8 +5298,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5266
5298
  function updateItemSize(ctx, itemKey, sizeObj) {
5267
5299
  var _a3;
5268
5300
  const state = ctx.state;
5269
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5270
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5301
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5302
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5271
5303
  const {
5272
5304
  didContainersLayout,
5273
5305
  sizesKnown,
@@ -5323,8 +5355,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5323
5355
  if (needsRecalculate) {
5324
5356
  state.scrollForNextCalculateItemsInView = void 0;
5325
5357
  runOrScheduleMVCPRecalculate(ctx);
5326
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5327
- state.userScrollAnchorResetKeys = void 0;
5358
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5359
+ state.userScrollAnchorReset = void 0;
5328
5360
  }
5329
5361
  if (shouldMaintainScrollAtEnd) {
5330
5362
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5334,7 +5366,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5334
5366
  }
5335
5367
  }
5336
5368
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5337
- var _a3;
5369
+ var _a3, _b;
5338
5370
  const state = ctx.state;
5339
5371
  const {
5340
5372
  indexByKey,
@@ -5344,13 +5376,23 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5344
5376
  } = state;
5345
5377
  if (!data) return 0;
5346
5378
  const index = indexByKey.get(itemKey);
5347
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
5379
+ const itemData = data[index];
5380
+ let itemType;
5381
+ let fixedItemSize;
5382
+ if (getFixedItemSize) {
5383
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5384
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
5385
+ }
5386
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5348
5387
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5349
- const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5350
5388
  const prevSizeKnown = sizesKnown.get(itemKey);
5389
+ if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
5390
+ return 0;
5391
+ }
5392
+ const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5351
5393
  sizesKnown.set(itemKey, size);
5352
- if (!getFixedItemSize && size > 0) {
5353
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
5394
+ if (fixedItemSize === void 0 && size > 0) {
5395
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5354
5396
  let averages = averageSizes[itemType];
5355
5397
  if (!averages) {
5356
5398
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6367,6 +6409,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6367
6409
  });
6368
6410
  state.viewabilityConfigCallbackPairs = viewability;
6369
6411
  state.enableScrollForNextCalculateItemsInView = !viewability;
6412
+ if (viewability) {
6413
+ state.scrollForNextCalculateItemsInView = void 0;
6414
+ }
6370
6415
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
6371
6416
  useInit(() => {
6372
6417
  if (!IsNewArchitecture) {
package/react-native.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React2 from 'react';
2
2
  import { useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle, useContext } from 'react';
3
3
  import * as ReactNative from 'react-native';
4
- import { Animated, Platform as Platform$1, View as View$1, Text as Text$1, StyleSheet as StyleSheet$1, RefreshControl, Dimensions, I18nManager } from 'react-native';
4
+ import { Animated, Platform as Platform$1, View as View$1, Text as Text$1, PixelRatio as PixelRatio$1, StyleSheet as StyleSheet$1, RefreshControl, Dimensions, I18nManager } from 'react-native';
5
5
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
6
6
 
7
7
  // src/components/LegendList.tsx
@@ -722,6 +722,22 @@ function Separator({ ItemSeparatorComponent, leadingItem }) {
722
722
  const isLastItem = useIsLastItem();
723
723
  return isLastItem ? null : /* @__PURE__ */ React2.createElement(ItemSeparatorComponent, { leadingItem });
724
724
  }
725
+ var PixelRatio = PixelRatio$1;
726
+
727
+ // src/utils/layoutMeasurement.ts
728
+ var FLOATING_POINT_SLACK = 0.01;
729
+ var NATIVE_LAYOUT_MEASUREMENT_EPSILON = 1 / PixelRatio.get() + FLOATING_POINT_SLACK;
730
+ function isWithinEpsilon(delta) {
731
+ return Math.abs(delta) <= NATIVE_LAYOUT_MEASUREMENT_EPSILON;
732
+ }
733
+ function isNativeLayoutNoise(delta) {
734
+ return isWithinEpsilon(delta);
735
+ }
736
+ function isNativeLayoutSizeNoise(heightDelta, widthDelta) {
737
+ return isWithinEpsilon(heightDelta) && isWithinEpsilon(widthDelta);
738
+ }
739
+
740
+ // src/hooks/useOnLayoutSync.native.tsx
725
741
  function useOnLayoutSync({
726
742
  ref,
727
743
  onLayoutProp,
@@ -730,11 +746,21 @@ function useOnLayoutSync({
730
746
  const lastLayoutRef = useRef(null);
731
747
  const onLayout = useCallback(
732
748
  (event) => {
733
- var _a3, _b;
734
749
  const { layout } = event.nativeEvent;
735
- if (layout.height !== ((_a3 = lastLayoutRef.current) == null ? void 0 : _a3.height) || layout.width !== ((_b = lastLayoutRef.current) == null ? void 0 : _b.width)) {
750
+ const lastLayout = lastLayoutRef.current;
751
+ const didLayoutSizeChange = lastLayout && (layout.height !== lastLayout.height || layout.width !== lastLayout.width);
752
+ const isMeasuredLayoutNoise = !!didLayoutSizeChange && !!lastLayout.measuredLayout && isNativeLayoutSizeNoise(
753
+ layout.height - lastLayout.measuredLayout.height,
754
+ layout.width - lastLayout.measuredLayout.width
755
+ );
756
+ if (!lastLayout || didLayoutSizeChange && !isMeasuredLayoutNoise) {
736
757
  onLayoutChange(layout, false);
737
- lastLayoutRef.current = layout;
758
+ }
759
+ if (!lastLayout || didLayoutSizeChange) {
760
+ lastLayoutRef.current = {
761
+ ...layout,
762
+ measuredLayout: isMeasuredLayoutNoise ? lastLayout == null ? void 0 : lastLayout.measuredLayout : void 0
763
+ };
738
764
  }
739
765
  onLayoutProp == null ? void 0 : onLayoutProp(event);
740
766
  },
@@ -745,7 +771,7 @@ function useOnLayoutSync({
745
771
  if (ref.current) {
746
772
  ref.current.measure((x, y, width, height) => {
747
773
  const layout = { height, width, x, y };
748
- lastLayoutRef.current = layout;
774
+ lastLayoutRef.current = { ...layout, measuredLayout: layout };
749
775
  onLayoutChange(layout, true);
750
776
  });
751
777
  }
@@ -2178,10 +2204,7 @@ function requestAdjust(ctx, positionDiff, dataChanged) {
2178
2204
  const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2179
2205
  const doit = () => {
2180
2206
  if (needsScrollWorkaround) {
2181
- scrollTo(ctx, {
2182
- noScrollingTo: true,
2183
- offset: state.scroll
2184
- });
2207
+ doScrollTo(ctx, { horizontal: state.props.horizontal, offset: state.scroll });
2185
2208
  } else {
2186
2209
  state.scrollAdjustHandler.requestAdjust(positionDiff);
2187
2210
  if (state.adjustingFromInitialMount) {
@@ -2577,7 +2600,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2577
2600
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
2578
2601
  state.mvcpAnchorLock = void 0;
2579
2602
  state.pendingNativeMVCPAdjust = void 0;
2580
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
2603
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
2581
2604
  if (state.queuedMVCPRecalculate !== void 0) {
2582
2605
  cancelAnimationFrame(state.queuedMVCPRecalculate);
2583
2606
  state.queuedMVCPRecalculate = void 0;
@@ -4395,7 +4418,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4395
4418
  function calculateItemsInView(ctx, params = {}) {
4396
4419
  const state = ctx.state;
4397
4420
  batchedUpdates(() => {
4398
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
4421
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
4399
4422
  const {
4400
4423
  columns,
4401
4424
  containerItemKeys,
@@ -4490,7 +4513,7 @@ function calculateItemsInView(ctx, params = {}) {
4490
4513
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4491
4514
  };
4492
4515
  updateScrollRange();
4493
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4516
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4494
4517
  const { top, bottom } = scrollForNextCalculateItemsInView;
4495
4518
  if (top === null && bottom === null) {
4496
4519
  state.scrollForNextCalculateItemsInView = void 0;
@@ -4709,7 +4732,7 @@ function calculateItemsInView(ctx, params = {}) {
4709
4732
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4710
4733
  }
4711
4734
  containerItemKeys.set(id, containerIndex);
4712
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
4735
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
4713
4736
  const containerSticky = `containerSticky${containerIndex}`;
4714
4737
  const isSticky = stickyHeaderIndicesSet.has(i);
4715
4738
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4737,13 +4760,17 @@ function calculateItemsInView(ctx, params = {}) {
4737
4760
  }
4738
4761
  }
4739
4762
  }
4740
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
4741
- state.userScrollAnchorResetKeys = void 0;
4763
+ if (state.userScrollAnchorReset) {
4764
+ if (state.userScrollAnchorReset.keys.size === 0) {
4765
+ state.userScrollAnchorReset = void 0;
4766
+ } else {
4767
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
4768
+ }
4742
4769
  }
4743
4770
  if (alwaysRenderArr.length > 0) {
4744
4771
  for (const index of alwaysRenderArr) {
4745
4772
  if (index < 0 || index >= dataLength) continue;
4746
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
4773
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
4747
4774
  const containerIndex = containerItemKeys.get(id);
4748
4775
  if (containerIndex !== void 0) {
4749
4776
  state.stickyContainerPool.add(containerIndex);
@@ -5197,37 +5224,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5197
5224
 
5198
5225
  // src/core/updateItemSize.ts
5199
5226
  function runOrScheduleMVCPRecalculate(ctx) {
5227
+ var _a3, _b;
5200
5228
  const state = ctx.state;
5201
- if (state.userScrollAnchorResetKeys !== void 0) {
5202
- if (state.queuedMVCPRecalculate !== void 0) {
5203
- return;
5204
- }
5205
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5206
- var _a3;
5207
- state.queuedMVCPRecalculate = void 0;
5229
+ if (state.userScrollAnchorReset !== void 0) {
5230
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5231
+ const replacementMeasurementBatchThreshold = 3;
5232
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5233
+ if (shouldBatchReplacementMeasurements) {
5234
+ if (state.queuedMVCPRecalculate === void 0) {
5235
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5236
+ var _a4;
5237
+ state.queuedMVCPRecalculate = void 0;
5238
+ calculateItemsInView(ctx);
5239
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5240
+ state.userScrollAnchorReset = void 0;
5241
+ }
5242
+ });
5243
+ }
5244
+ } else {
5208
5245
  calculateItemsInView(ctx);
5209
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5210
- state.userScrollAnchorResetKeys = void 0;
5246
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5247
+ state.userScrollAnchorReset = void 0;
5211
5248
  }
5212
- });
5213
- return;
5214
- }
5215
- if (Platform.OS === "web") {
5249
+ }
5250
+ } else if (Platform.OS === "web") {
5216
5251
  if (!state.mvcpAnchorLock) {
5217
5252
  if (state.queuedMVCPRecalculate !== void 0) {
5218
5253
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5219
5254
  state.queuedMVCPRecalculate = void 0;
5220
5255
  }
5221
5256
  calculateItemsInView(ctx, { doMVCP: true });
5222
- return;
5223
- }
5224
- if (state.queuedMVCPRecalculate !== void 0) {
5225
- return;
5257
+ } else if (state.queuedMVCPRecalculate === void 0) {
5258
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5259
+ state.queuedMVCPRecalculate = void 0;
5260
+ calculateItemsInView(ctx, { doMVCP: true });
5261
+ });
5226
5262
  }
5227
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5228
- state.queuedMVCPRecalculate = void 0;
5229
- calculateItemsInView(ctx, { doMVCP: true });
5230
- });
5231
5263
  } else {
5232
5264
  calculateItemsInView(ctx, { doMVCP: true });
5233
5265
  }
@@ -5245,8 +5277,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5245
5277
  function updateItemSize(ctx, itemKey, sizeObj) {
5246
5278
  var _a3;
5247
5279
  const state = ctx.state;
5248
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5249
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5280
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5281
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5250
5282
  const {
5251
5283
  didContainersLayout,
5252
5284
  sizesKnown,
@@ -5302,8 +5334,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5302
5334
  if (needsRecalculate) {
5303
5335
  state.scrollForNextCalculateItemsInView = void 0;
5304
5336
  runOrScheduleMVCPRecalculate(ctx);
5305
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5306
- state.userScrollAnchorResetKeys = void 0;
5337
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5338
+ state.userScrollAnchorReset = void 0;
5307
5339
  }
5308
5340
  if (shouldMaintainScrollAtEnd) {
5309
5341
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5313,7 +5345,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5313
5345
  }
5314
5346
  }
5315
5347
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5316
- var _a3;
5348
+ var _a3, _b;
5317
5349
  const state = ctx.state;
5318
5350
  const {
5319
5351
  indexByKey,
@@ -5323,13 +5355,23 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5323
5355
  } = state;
5324
5356
  if (!data) return 0;
5325
5357
  const index = indexByKey.get(itemKey);
5326
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
5358
+ const itemData = data[index];
5359
+ let itemType;
5360
+ let fixedItemSize;
5361
+ if (getFixedItemSize) {
5362
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5363
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
5364
+ }
5365
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5327
5366
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5328
- const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5329
5367
  const prevSizeKnown = sizesKnown.get(itemKey);
5368
+ if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
5369
+ return 0;
5370
+ }
5371
+ const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5330
5372
  sizesKnown.set(itemKey, size);
5331
- if (!getFixedItemSize && size > 0) {
5332
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
5373
+ if (fixedItemSize === void 0 && size > 0) {
5374
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5333
5375
  let averages = averageSizes[itemType];
5334
5376
  if (!averages) {
5335
5377
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6346,6 +6388,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6346
6388
  });
6347
6389
  state.viewabilityConfigCallbackPairs = viewability;
6348
6390
  state.enableScrollForNextCalculateItemsInView = !viewability;
6391
+ if (viewability) {
6392
+ state.scrollForNextCalculateItemsInView = void 0;
6393
+ }
6349
6394
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
6350
6395
  useInit(() => {
6351
6396
  if (!IsNewArchitecture) {
@@ -3106,7 +3106,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3106
3106
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
3107
3107
  state.mvcpAnchorLock = void 0;
3108
3108
  state.pendingNativeMVCPAdjust = void 0;
3109
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
3109
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
3110
3110
  if (state.queuedMVCPRecalculate !== void 0) {
3111
3111
  cancelAnimationFrame(state.queuedMVCPRecalculate);
3112
3112
  state.queuedMVCPRecalculate = void 0;
@@ -5069,7 +5069,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5069
5069
  function calculateItemsInView(ctx, params = {}) {
5070
5070
  const state = ctx.state;
5071
5071
  batchedUpdates(() => {
5072
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5072
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5073
5073
  const {
5074
5074
  columns,
5075
5075
  containerItemKeys,
@@ -5164,7 +5164,7 @@ function calculateItemsInView(ctx, params = {}) {
5164
5164
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
5165
5165
  };
5166
5166
  updateScrollRange();
5167
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5167
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5168
5168
  const { top, bottom } = scrollForNextCalculateItemsInView;
5169
5169
  if (top === null && bottom === null) {
5170
5170
  state.scrollForNextCalculateItemsInView = void 0;
@@ -5383,7 +5383,7 @@ function calculateItemsInView(ctx, params = {}) {
5383
5383
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5384
5384
  }
5385
5385
  containerItemKeys.set(id, containerIndex);
5386
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
5386
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5387
5387
  const containerSticky = `containerSticky${containerIndex}`;
5388
5388
  const isSticky = stickyHeaderIndicesSet.has(i);
5389
5389
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5411,13 +5411,17 @@ function calculateItemsInView(ctx, params = {}) {
5411
5411
  }
5412
5412
  }
5413
5413
  }
5414
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
5415
- state.userScrollAnchorResetKeys = void 0;
5414
+ if (state.userScrollAnchorReset) {
5415
+ if (state.userScrollAnchorReset.keys.size === 0) {
5416
+ state.userScrollAnchorReset = void 0;
5417
+ } else {
5418
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5419
+ }
5416
5420
  }
5417
5421
  if (alwaysRenderArr.length > 0) {
5418
5422
  for (const index of alwaysRenderArr) {
5419
5423
  if (index < 0 || index >= dataLength) continue;
5420
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
5424
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5421
5425
  const containerIndex = containerItemKeys.get(id);
5422
5426
  if (containerIndex !== void 0) {
5423
5427
  state.stickyContainerPool.add(containerIndex);
@@ -5871,37 +5875,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5871
5875
 
5872
5876
  // src/core/updateItemSize.ts
5873
5877
  function runOrScheduleMVCPRecalculate(ctx) {
5878
+ var _a3, _b;
5874
5879
  const state = ctx.state;
5875
- if (state.userScrollAnchorResetKeys !== void 0) {
5876
- if (state.queuedMVCPRecalculate !== void 0) {
5877
- return;
5878
- }
5879
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5880
- var _a3;
5881
- state.queuedMVCPRecalculate = void 0;
5880
+ if (state.userScrollAnchorReset !== void 0) {
5881
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5882
+ const replacementMeasurementBatchThreshold = 3;
5883
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5884
+ if (shouldBatchReplacementMeasurements) {
5885
+ if (state.queuedMVCPRecalculate === void 0) {
5886
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5887
+ var _a4;
5888
+ state.queuedMVCPRecalculate = void 0;
5889
+ calculateItemsInView(ctx);
5890
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5891
+ state.userScrollAnchorReset = void 0;
5892
+ }
5893
+ });
5894
+ }
5895
+ } else {
5882
5896
  calculateItemsInView(ctx);
5883
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5884
- state.userScrollAnchorResetKeys = void 0;
5897
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5898
+ state.userScrollAnchorReset = void 0;
5885
5899
  }
5886
- });
5887
- return;
5888
- }
5889
- {
5900
+ }
5901
+ } else {
5890
5902
  if (!state.mvcpAnchorLock) {
5891
5903
  if (state.queuedMVCPRecalculate !== void 0) {
5892
5904
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5893
5905
  state.queuedMVCPRecalculate = void 0;
5894
5906
  }
5895
5907
  calculateItemsInView(ctx, { doMVCP: true });
5896
- return;
5897
- }
5898
- if (state.queuedMVCPRecalculate !== void 0) {
5899
- return;
5908
+ } else if (state.queuedMVCPRecalculate === void 0) {
5909
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5910
+ state.queuedMVCPRecalculate = void 0;
5911
+ calculateItemsInView(ctx, { doMVCP: true });
5912
+ });
5900
5913
  }
5901
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5902
- state.queuedMVCPRecalculate = void 0;
5903
- calculateItemsInView(ctx, { doMVCP: true });
5904
- });
5905
5914
  }
5906
5915
  }
5907
5916
  function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
@@ -5917,8 +5926,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5917
5926
  function updateItemSize(ctx, itemKey, sizeObj) {
5918
5927
  var _a3;
5919
5928
  const state = ctx.state;
5920
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5921
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5929
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5930
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5922
5931
  const {
5923
5932
  didContainersLayout,
5924
5933
  sizesKnown,
@@ -5974,8 +5983,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5974
5983
  if (needsRecalculate) {
5975
5984
  state.scrollForNextCalculateItemsInView = void 0;
5976
5985
  runOrScheduleMVCPRecalculate(ctx);
5977
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5978
- state.userScrollAnchorResetKeys = void 0;
5986
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5987
+ state.userScrollAnchorReset = void 0;
5979
5988
  }
5980
5989
  if (shouldMaintainScrollAtEnd) {
5981
5990
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5985,7 +5994,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5985
5994
  }
5986
5995
  }
5987
5996
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5988
- var _a3;
5997
+ var _a3, _b;
5989
5998
  const state = ctx.state;
5990
5999
  const {
5991
6000
  indexByKey,
@@ -5995,13 +6004,20 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5995
6004
  } = state;
5996
6005
  if (!data) return 0;
5997
6006
  const index = indexByKey.get(itemKey);
5998
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
6007
+ const itemData = data[index];
6008
+ let itemType;
6009
+ let fixedItemSize;
6010
+ if (getFixedItemSize) {
6011
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
6012
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
6013
+ }
6014
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5999
6015
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
6000
- const size = Math.round(rawSize) ;
6001
6016
  const prevSizeKnown = sizesKnown.get(itemKey);
6017
+ const size = Math.round(rawSize) ;
6002
6018
  sizesKnown.set(itemKey, size);
6003
- if (!getFixedItemSize && size > 0) {
6004
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
6019
+ if (fixedItemSize === void 0 && size > 0) {
6020
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
6005
6021
  let averages = averageSizes[itemType];
6006
6022
  if (!averages) {
6007
6023
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -7000,6 +7016,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7000
7016
  });
7001
7017
  state.viewabilityConfigCallbackPairs = viewability;
7002
7018
  state.enableScrollForNextCalculateItemsInView = !viewability;
7019
+ if (viewability) {
7020
+ state.scrollForNextCalculateItemsInView = void 0;
7021
+ }
7003
7022
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
7004
7023
  useInit(() => {
7005
7024
  });
@@ -3085,7 +3085,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3085
3085
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
3086
3086
  state.mvcpAnchorLock = void 0;
3087
3087
  state.pendingNativeMVCPAdjust = void 0;
3088
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
3088
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
3089
3089
  if (state.queuedMVCPRecalculate !== void 0) {
3090
3090
  cancelAnimationFrame(state.queuedMVCPRecalculate);
3091
3091
  state.queuedMVCPRecalculate = void 0;
@@ -5048,7 +5048,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5048
5048
  function calculateItemsInView(ctx, params = {}) {
5049
5049
  const state = ctx.state;
5050
5050
  batchedUpdates(() => {
5051
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5051
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5052
5052
  const {
5053
5053
  columns,
5054
5054
  containerItemKeys,
@@ -5143,7 +5143,7 @@ function calculateItemsInView(ctx, params = {}) {
5143
5143
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
5144
5144
  };
5145
5145
  updateScrollRange();
5146
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5146
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5147
5147
  const { top, bottom } = scrollForNextCalculateItemsInView;
5148
5148
  if (top === null && bottom === null) {
5149
5149
  state.scrollForNextCalculateItemsInView = void 0;
@@ -5362,7 +5362,7 @@ function calculateItemsInView(ctx, params = {}) {
5362
5362
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5363
5363
  }
5364
5364
  containerItemKeys.set(id, containerIndex);
5365
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
5365
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5366
5366
  const containerSticky = `containerSticky${containerIndex}`;
5367
5367
  const isSticky = stickyHeaderIndicesSet.has(i);
5368
5368
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5390,13 +5390,17 @@ function calculateItemsInView(ctx, params = {}) {
5390
5390
  }
5391
5391
  }
5392
5392
  }
5393
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
5394
- state.userScrollAnchorResetKeys = void 0;
5393
+ if (state.userScrollAnchorReset) {
5394
+ if (state.userScrollAnchorReset.keys.size === 0) {
5395
+ state.userScrollAnchorReset = void 0;
5396
+ } else {
5397
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5398
+ }
5395
5399
  }
5396
5400
  if (alwaysRenderArr.length > 0) {
5397
5401
  for (const index of alwaysRenderArr) {
5398
5402
  if (index < 0 || index >= dataLength) continue;
5399
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
5403
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5400
5404
  const containerIndex = containerItemKeys.get(id);
5401
5405
  if (containerIndex !== void 0) {
5402
5406
  state.stickyContainerPool.add(containerIndex);
@@ -5850,37 +5854,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5850
5854
 
5851
5855
  // src/core/updateItemSize.ts
5852
5856
  function runOrScheduleMVCPRecalculate(ctx) {
5857
+ var _a3, _b;
5853
5858
  const state = ctx.state;
5854
- if (state.userScrollAnchorResetKeys !== void 0) {
5855
- if (state.queuedMVCPRecalculate !== void 0) {
5856
- return;
5857
- }
5858
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5859
- var _a3;
5860
- state.queuedMVCPRecalculate = void 0;
5859
+ if (state.userScrollAnchorReset !== void 0) {
5860
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5861
+ const replacementMeasurementBatchThreshold = 3;
5862
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5863
+ if (shouldBatchReplacementMeasurements) {
5864
+ if (state.queuedMVCPRecalculate === void 0) {
5865
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5866
+ var _a4;
5867
+ state.queuedMVCPRecalculate = void 0;
5868
+ calculateItemsInView(ctx);
5869
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5870
+ state.userScrollAnchorReset = void 0;
5871
+ }
5872
+ });
5873
+ }
5874
+ } else {
5861
5875
  calculateItemsInView(ctx);
5862
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5863
- state.userScrollAnchorResetKeys = void 0;
5876
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5877
+ state.userScrollAnchorReset = void 0;
5864
5878
  }
5865
- });
5866
- return;
5867
- }
5868
- {
5879
+ }
5880
+ } else {
5869
5881
  if (!state.mvcpAnchorLock) {
5870
5882
  if (state.queuedMVCPRecalculate !== void 0) {
5871
5883
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5872
5884
  state.queuedMVCPRecalculate = void 0;
5873
5885
  }
5874
5886
  calculateItemsInView(ctx, { doMVCP: true });
5875
- return;
5876
- }
5877
- if (state.queuedMVCPRecalculate !== void 0) {
5878
- return;
5887
+ } else if (state.queuedMVCPRecalculate === void 0) {
5888
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5889
+ state.queuedMVCPRecalculate = void 0;
5890
+ calculateItemsInView(ctx, { doMVCP: true });
5891
+ });
5879
5892
  }
5880
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5881
- state.queuedMVCPRecalculate = void 0;
5882
- calculateItemsInView(ctx, { doMVCP: true });
5883
- });
5884
5893
  }
5885
5894
  }
5886
5895
  function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
@@ -5896,8 +5905,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5896
5905
  function updateItemSize(ctx, itemKey, sizeObj) {
5897
5906
  var _a3;
5898
5907
  const state = ctx.state;
5899
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5900
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5908
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5909
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5901
5910
  const {
5902
5911
  didContainersLayout,
5903
5912
  sizesKnown,
@@ -5953,8 +5962,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5953
5962
  if (needsRecalculate) {
5954
5963
  state.scrollForNextCalculateItemsInView = void 0;
5955
5964
  runOrScheduleMVCPRecalculate(ctx);
5956
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5957
- state.userScrollAnchorResetKeys = void 0;
5965
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5966
+ state.userScrollAnchorReset = void 0;
5958
5967
  }
5959
5968
  if (shouldMaintainScrollAtEnd) {
5960
5969
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5964,7 +5973,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5964
5973
  }
5965
5974
  }
5966
5975
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5967
- var _a3;
5976
+ var _a3, _b;
5968
5977
  const state = ctx.state;
5969
5978
  const {
5970
5979
  indexByKey,
@@ -5974,13 +5983,20 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5974
5983
  } = state;
5975
5984
  if (!data) return 0;
5976
5985
  const index = indexByKey.get(itemKey);
5977
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
5986
+ const itemData = data[index];
5987
+ let itemType;
5988
+ let fixedItemSize;
5989
+ if (getFixedItemSize) {
5990
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5991
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
5992
+ }
5993
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5978
5994
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5979
- const size = Math.round(rawSize) ;
5980
5995
  const prevSizeKnown = sizesKnown.get(itemKey);
5996
+ const size = Math.round(rawSize) ;
5981
5997
  sizesKnown.set(itemKey, size);
5982
- if (!getFixedItemSize && size > 0) {
5983
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
5998
+ if (fixedItemSize === void 0 && size > 0) {
5999
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5984
6000
  let averages = averageSizes[itemType];
5985
6001
  if (!averages) {
5986
6002
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6979,6 +6995,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6979
6995
  });
6980
6996
  state.viewabilityConfigCallbackPairs = viewability;
6981
6997
  state.enableScrollForNextCalculateItemsInView = !viewability;
6998
+ if (viewability) {
6999
+ state.scrollForNextCalculateItemsInView = void 0;
7000
+ }
6982
7001
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
6983
7002
  useInit(() => {
6984
7003
  });
package/react.js CHANGED
@@ -3106,7 +3106,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3106
3106
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
3107
3107
  state.mvcpAnchorLock = void 0;
3108
3108
  state.pendingNativeMVCPAdjust = void 0;
3109
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
3109
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
3110
3110
  if (state.queuedMVCPRecalculate !== void 0) {
3111
3111
  cancelAnimationFrame(state.queuedMVCPRecalculate);
3112
3112
  state.queuedMVCPRecalculate = void 0;
@@ -5069,7 +5069,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5069
5069
  function calculateItemsInView(ctx, params = {}) {
5070
5070
  const state = ctx.state;
5071
5071
  batchedUpdates(() => {
5072
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5072
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5073
5073
  const {
5074
5074
  columns,
5075
5075
  containerItemKeys,
@@ -5164,7 +5164,7 @@ function calculateItemsInView(ctx, params = {}) {
5164
5164
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
5165
5165
  };
5166
5166
  updateScrollRange();
5167
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5167
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5168
5168
  const { top, bottom } = scrollForNextCalculateItemsInView;
5169
5169
  if (top === null && bottom === null) {
5170
5170
  state.scrollForNextCalculateItemsInView = void 0;
@@ -5383,7 +5383,7 @@ function calculateItemsInView(ctx, params = {}) {
5383
5383
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5384
5384
  }
5385
5385
  containerItemKeys.set(id, containerIndex);
5386
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
5386
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5387
5387
  const containerSticky = `containerSticky${containerIndex}`;
5388
5388
  const isSticky = stickyHeaderIndicesSet.has(i);
5389
5389
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5411,13 +5411,17 @@ function calculateItemsInView(ctx, params = {}) {
5411
5411
  }
5412
5412
  }
5413
5413
  }
5414
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
5415
- state.userScrollAnchorResetKeys = void 0;
5414
+ if (state.userScrollAnchorReset) {
5415
+ if (state.userScrollAnchorReset.keys.size === 0) {
5416
+ state.userScrollAnchorReset = void 0;
5417
+ } else {
5418
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5419
+ }
5416
5420
  }
5417
5421
  if (alwaysRenderArr.length > 0) {
5418
5422
  for (const index of alwaysRenderArr) {
5419
5423
  if (index < 0 || index >= dataLength) continue;
5420
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
5424
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5421
5425
  const containerIndex = containerItemKeys.get(id);
5422
5426
  if (containerIndex !== void 0) {
5423
5427
  state.stickyContainerPool.add(containerIndex);
@@ -5871,37 +5875,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5871
5875
 
5872
5876
  // src/core/updateItemSize.ts
5873
5877
  function runOrScheduleMVCPRecalculate(ctx) {
5878
+ var _a3, _b;
5874
5879
  const state = ctx.state;
5875
- if (state.userScrollAnchorResetKeys !== void 0) {
5876
- if (state.queuedMVCPRecalculate !== void 0) {
5877
- return;
5878
- }
5879
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5880
- var _a3;
5881
- state.queuedMVCPRecalculate = void 0;
5880
+ if (state.userScrollAnchorReset !== void 0) {
5881
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5882
+ const replacementMeasurementBatchThreshold = 3;
5883
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5884
+ if (shouldBatchReplacementMeasurements) {
5885
+ if (state.queuedMVCPRecalculate === void 0) {
5886
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5887
+ var _a4;
5888
+ state.queuedMVCPRecalculate = void 0;
5889
+ calculateItemsInView(ctx);
5890
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5891
+ state.userScrollAnchorReset = void 0;
5892
+ }
5893
+ });
5894
+ }
5895
+ } else {
5882
5896
  calculateItemsInView(ctx);
5883
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5884
- state.userScrollAnchorResetKeys = void 0;
5897
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5898
+ state.userScrollAnchorReset = void 0;
5885
5899
  }
5886
- });
5887
- return;
5888
- }
5889
- {
5900
+ }
5901
+ } else {
5890
5902
  if (!state.mvcpAnchorLock) {
5891
5903
  if (state.queuedMVCPRecalculate !== void 0) {
5892
5904
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5893
5905
  state.queuedMVCPRecalculate = void 0;
5894
5906
  }
5895
5907
  calculateItemsInView(ctx, { doMVCP: true });
5896
- return;
5897
- }
5898
- if (state.queuedMVCPRecalculate !== void 0) {
5899
- return;
5908
+ } else if (state.queuedMVCPRecalculate === void 0) {
5909
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5910
+ state.queuedMVCPRecalculate = void 0;
5911
+ calculateItemsInView(ctx, { doMVCP: true });
5912
+ });
5900
5913
  }
5901
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5902
- state.queuedMVCPRecalculate = void 0;
5903
- calculateItemsInView(ctx, { doMVCP: true });
5904
- });
5905
5914
  }
5906
5915
  }
5907
5916
  function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
@@ -5917,8 +5926,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5917
5926
  function updateItemSize(ctx, itemKey, sizeObj) {
5918
5927
  var _a3;
5919
5928
  const state = ctx.state;
5920
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5921
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5929
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5930
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5922
5931
  const {
5923
5932
  didContainersLayout,
5924
5933
  sizesKnown,
@@ -5974,8 +5983,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5974
5983
  if (needsRecalculate) {
5975
5984
  state.scrollForNextCalculateItemsInView = void 0;
5976
5985
  runOrScheduleMVCPRecalculate(ctx);
5977
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5978
- state.userScrollAnchorResetKeys = void 0;
5986
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5987
+ state.userScrollAnchorReset = void 0;
5979
5988
  }
5980
5989
  if (shouldMaintainScrollAtEnd) {
5981
5990
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5985,7 +5994,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5985
5994
  }
5986
5995
  }
5987
5996
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5988
- var _a3;
5997
+ var _a3, _b;
5989
5998
  const state = ctx.state;
5990
5999
  const {
5991
6000
  indexByKey,
@@ -5995,13 +6004,20 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5995
6004
  } = state;
5996
6005
  if (!data) return 0;
5997
6006
  const index = indexByKey.get(itemKey);
5998
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
6007
+ const itemData = data[index];
6008
+ let itemType;
6009
+ let fixedItemSize;
6010
+ if (getFixedItemSize) {
6011
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
6012
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
6013
+ }
6014
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5999
6015
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
6000
- const size = Math.round(rawSize) ;
6001
6016
  const prevSizeKnown = sizesKnown.get(itemKey);
6017
+ const size = Math.round(rawSize) ;
6002
6018
  sizesKnown.set(itemKey, size);
6003
- if (!getFixedItemSize && size > 0) {
6004
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
6019
+ if (fixedItemSize === void 0 && size > 0) {
6020
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
6005
6021
  let averages = averageSizes[itemType];
6006
6022
  if (!averages) {
6007
6023
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -7000,6 +7016,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7000
7016
  });
7001
7017
  state.viewabilityConfigCallbackPairs = viewability;
7002
7018
  state.enableScrollForNextCalculateItemsInView = !viewability;
7019
+ if (viewability) {
7020
+ state.scrollForNextCalculateItemsInView = void 0;
7021
+ }
7003
7022
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
7004
7023
  useInit(() => {
7005
7024
  });
package/react.mjs CHANGED
@@ -3085,7 +3085,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3085
3085
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
3086
3086
  state.mvcpAnchorLock = void 0;
3087
3087
  state.pendingNativeMVCPAdjust = void 0;
3088
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
3088
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
3089
3089
  if (state.queuedMVCPRecalculate !== void 0) {
3090
3090
  cancelAnimationFrame(state.queuedMVCPRecalculate);
3091
3091
  state.queuedMVCPRecalculate = void 0;
@@ -5048,7 +5048,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5048
5048
  function calculateItemsInView(ctx, params = {}) {
5049
5049
  const state = ctx.state;
5050
5050
  batchedUpdates(() => {
5051
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5051
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5052
5052
  const {
5053
5053
  columns,
5054
5054
  containerItemKeys,
@@ -5143,7 +5143,7 @@ function calculateItemsInView(ctx, params = {}) {
5143
5143
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
5144
5144
  };
5145
5145
  updateScrollRange();
5146
- if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5146
+ if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
5147
5147
  const { top, bottom } = scrollForNextCalculateItemsInView;
5148
5148
  if (top === null && bottom === null) {
5149
5149
  state.scrollForNextCalculateItemsInView = void 0;
@@ -5362,7 +5362,7 @@ function calculateItemsInView(ctx, params = {}) {
5362
5362
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5363
5363
  }
5364
5364
  containerItemKeys.set(id, containerIndex);
5365
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
5365
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5366
5366
  const containerSticky = `containerSticky${containerIndex}`;
5367
5367
  const isSticky = stickyHeaderIndicesSet.has(i);
5368
5368
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5390,13 +5390,17 @@ function calculateItemsInView(ctx, params = {}) {
5390
5390
  }
5391
5391
  }
5392
5392
  }
5393
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
5394
- state.userScrollAnchorResetKeys = void 0;
5393
+ if (state.userScrollAnchorReset) {
5394
+ if (state.userScrollAnchorReset.keys.size === 0) {
5395
+ state.userScrollAnchorReset = void 0;
5396
+ } else {
5397
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5398
+ }
5395
5399
  }
5396
5400
  if (alwaysRenderArr.length > 0) {
5397
5401
  for (const index of alwaysRenderArr) {
5398
5402
  if (index < 0 || index >= dataLength) continue;
5399
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
5403
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5400
5404
  const containerIndex = containerItemKeys.get(id);
5401
5405
  if (containerIndex !== void 0) {
5402
5406
  state.stickyContainerPool.add(containerIndex);
@@ -5850,37 +5854,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5850
5854
 
5851
5855
  // src/core/updateItemSize.ts
5852
5856
  function runOrScheduleMVCPRecalculate(ctx) {
5857
+ var _a3, _b;
5853
5858
  const state = ctx.state;
5854
- if (state.userScrollAnchorResetKeys !== void 0) {
5855
- if (state.queuedMVCPRecalculate !== void 0) {
5856
- return;
5857
- }
5858
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5859
- var _a3;
5860
- state.queuedMVCPRecalculate = void 0;
5859
+ if (state.userScrollAnchorReset !== void 0) {
5860
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5861
+ const replacementMeasurementBatchThreshold = 3;
5862
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5863
+ if (shouldBatchReplacementMeasurements) {
5864
+ if (state.queuedMVCPRecalculate === void 0) {
5865
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5866
+ var _a4;
5867
+ state.queuedMVCPRecalculate = void 0;
5868
+ calculateItemsInView(ctx);
5869
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5870
+ state.userScrollAnchorReset = void 0;
5871
+ }
5872
+ });
5873
+ }
5874
+ } else {
5861
5875
  calculateItemsInView(ctx);
5862
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5863
- state.userScrollAnchorResetKeys = void 0;
5876
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5877
+ state.userScrollAnchorReset = void 0;
5864
5878
  }
5865
- });
5866
- return;
5867
- }
5868
- {
5879
+ }
5880
+ } else {
5869
5881
  if (!state.mvcpAnchorLock) {
5870
5882
  if (state.queuedMVCPRecalculate !== void 0) {
5871
5883
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5872
5884
  state.queuedMVCPRecalculate = void 0;
5873
5885
  }
5874
5886
  calculateItemsInView(ctx, { doMVCP: true });
5875
- return;
5876
- }
5877
- if (state.queuedMVCPRecalculate !== void 0) {
5878
- return;
5887
+ } else if (state.queuedMVCPRecalculate === void 0) {
5888
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5889
+ state.queuedMVCPRecalculate = void 0;
5890
+ calculateItemsInView(ctx, { doMVCP: true });
5891
+ });
5879
5892
  }
5880
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5881
- state.queuedMVCPRecalculate = void 0;
5882
- calculateItemsInView(ctx, { doMVCP: true });
5883
- });
5884
5893
  }
5885
5894
  }
5886
5895
  function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
@@ -5896,8 +5905,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5896
5905
  function updateItemSize(ctx, itemKey, sizeObj) {
5897
5906
  var _a3;
5898
5907
  const state = ctx.state;
5899
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5900
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5908
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5909
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5901
5910
  const {
5902
5911
  didContainersLayout,
5903
5912
  sizesKnown,
@@ -5953,8 +5962,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5953
5962
  if (needsRecalculate) {
5954
5963
  state.scrollForNextCalculateItemsInView = void 0;
5955
5964
  runOrScheduleMVCPRecalculate(ctx);
5956
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5957
- state.userScrollAnchorResetKeys = void 0;
5965
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
5966
+ state.userScrollAnchorReset = void 0;
5958
5967
  }
5959
5968
  if (shouldMaintainScrollAtEnd) {
5960
5969
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5964,7 +5973,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5964
5973
  }
5965
5974
  }
5966
5975
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5967
- var _a3;
5976
+ var _a3, _b;
5968
5977
  const state = ctx.state;
5969
5978
  const {
5970
5979
  indexByKey,
@@ -5974,13 +5983,20 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5974
5983
  } = state;
5975
5984
  if (!data) return 0;
5976
5985
  const index = indexByKey.get(itemKey);
5977
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
5986
+ const itemData = data[index];
5987
+ let itemType;
5988
+ let fixedItemSize;
5989
+ if (getFixedItemSize) {
5990
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5991
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
5992
+ }
5993
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5978
5994
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5979
- const size = Math.round(rawSize) ;
5980
5995
  const prevSizeKnown = sizesKnown.get(itemKey);
5996
+ const size = Math.round(rawSize) ;
5981
5997
  sizesKnown.set(itemKey, size);
5982
- if (!getFixedItemSize && size > 0) {
5983
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
5998
+ if (fixedItemSize === void 0 && size > 0) {
5999
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5984
6000
  let averages = averageSizes[itemType];
5985
6001
  if (!averages) {
5986
6002
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6979,6 +6995,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6979
6995
  });
6980
6996
  state.viewabilityConfigCallbackPairs = viewability;
6981
6997
  state.enableScrollForNextCalculateItemsInView = !viewability;
6998
+ if (viewability) {
6999
+ state.scrollForNextCalculateItemsInView = void 0;
7000
+ }
6982
7001
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
6983
7002
  useInit(() => {
6984
7003
  });