@legendapp/list 3.0.4 → 3.0.5

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-native.mjs CHANGED
@@ -122,6 +122,7 @@ function StateProvider({ children }) {
122
122
  const [value] = React2.useState(() => ({
123
123
  animatedScrollY: createAnimatedValue(0),
124
124
  columnWrapperStyle: void 0,
125
+ containerLayoutTriggers: /* @__PURE__ */ new Map(),
125
126
  contextNum: contextNum++,
126
127
  listeners: /* @__PURE__ */ new Map(),
127
128
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -540,9 +541,6 @@ function roundSize(size) {
540
541
  function isNullOrUndefined(value) {
541
542
  return value === null || value === void 0;
542
543
  }
543
- function comparatorDefault(a, b) {
544
- return a - b;
545
- }
546
544
  function getPadding(s, type) {
547
545
  var _a3, _b, _c;
548
546
  const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
@@ -895,18 +893,6 @@ var Container = typedMemo(function Container2({
895
893
  [itemKey, data, extraData]
896
894
  );
897
895
  const { index, renderedItem } = renderedItemInfo || {};
898
- const contextValue = useMemo(() => {
899
- ctx.viewRefs.set(id, ref);
900
- return {
901
- containerId: id,
902
- index,
903
- itemKey,
904
- triggerLayout: () => {
905
- forceLayoutRender((v) => v + 1);
906
- },
907
- value: data
908
- };
909
- }, [id, itemKey, index, data]);
910
896
  const onLayoutChange = useCallback((rectangle) => {
911
897
  var _a3, _b;
912
898
  const {
@@ -956,6 +942,27 @@ var Container = typedMemo(function Container2({
956
942
  });
957
943
  }
958
944
  }, []);
945
+ const triggerLayout = useCallback(() => {
946
+ forceLayoutRender((v) => v + 1);
947
+ }, []);
948
+ const contextValue = useMemo(() => {
949
+ ctx.viewRefs.set(id, ref);
950
+ return {
951
+ containerId: id,
952
+ index,
953
+ itemKey,
954
+ triggerLayout,
955
+ value: data
956
+ };
957
+ }, [id, itemKey, index, data, triggerLayout]);
958
+ useLayoutEffect(() => {
959
+ ctx.containerLayoutTriggers.set(id, triggerLayout);
960
+ return () => {
961
+ if (ctx.containerLayoutTriggers.get(id) === triggerLayout) {
962
+ ctx.containerLayoutTriggers.delete(id);
963
+ }
964
+ };
965
+ }, [ctx, id, triggerLayout]);
959
966
  const { onLayout } = useOnLayoutSync(
960
967
  {
961
968
  onLayoutChange,
@@ -1810,14 +1817,14 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
1810
1817
  }
1811
1818
 
1812
1819
  // src/utils/getItemSize.ts
1813
- function getKnownOrFixedSize(ctx, key, index, data) {
1814
- var _a3;
1820
+ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
1821
+ var _a3, _b;
1815
1822
  const state = ctx.state;
1816
1823
  const { getFixedItemSize, getItemType } = state.props;
1817
1824
  let size = key ? state.sizesKnown.get(key) : void 0;
1818
1825
  if (size === void 0 && key && getFixedItemSize) {
1819
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1820
- size = getFixedItemSize(data, index, itemType);
1826
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1827
+ size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
1821
1828
  if (size !== void 0) {
1822
1829
  state.sizesKnown.set(key, size);
1823
1830
  }
@@ -1836,8 +1843,8 @@ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
1836
1843
  }
1837
1844
  return true;
1838
1845
  }
1839
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
1840
- var _a3, _b, _c;
1846
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize, resolved) {
1847
+ var _a3, _b, _c, _d;
1841
1848
  const state = ctx.state;
1842
1849
  const {
1843
1850
  sizes,
@@ -1856,14 +1863,14 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1856
1863
  return renderedSize;
1857
1864
  }
1858
1865
  }
1859
- size = getKnownOrFixedSize(ctx, key, index, data);
1866
+ size = getKnownOrFixedSize(ctx, key, index, data, resolved);
1860
1867
  if (size !== void 0) {
1861
1868
  setSize(ctx, key, size, notifyTotalSize);
1862
1869
  return size;
1863
1870
  }
1864
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1871
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1865
1872
  if (useAverageSize && !scrollingTo) {
1866
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1873
+ const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
1867
1874
  if (averageSizeForType !== void 0) {
1868
1875
  size = roundSize(averageSizeForType);
1869
1876
  }
@@ -1872,7 +1879,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1872
1879
  return renderedSize;
1873
1880
  }
1874
1881
  if (size === void 0 && useAverageSize && scrollingTo) {
1875
- const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
1882
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
1876
1883
  if (averageSizeForType !== void 0) {
1877
1884
  size = roundSize(averageSizeForType);
1878
1885
  }
@@ -2579,8 +2586,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2579
2586
  if ((options == null ? void 0 : options.markHasScrolled) !== false) {
2580
2587
  state.hasScrolled = true;
2581
2588
  }
2582
- state.lastBatchingAction = Date.now();
2583
2589
  const currentTime = Date.now();
2590
+ state.lastBatchingAction = currentTime;
2584
2591
  const adjust = scrollAdjustHandler.getAdjust();
2585
2592
  const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
2586
2593
  if (adjustChanged) {
@@ -2889,26 +2896,22 @@ function advanceCurrentInitialScrollSession(ctx, options) {
2889
2896
  }
2890
2897
 
2891
2898
  // src/utils/checkAllSizesKnown.ts
2892
- function isNullOrUndefined2(value) {
2893
- return value === null || value === void 0;
2894
- }
2895
- function getMountedIndicesInRange(state, start, end) {
2896
- if (!isNullOrUndefined2(end) && !isNullOrUndefined2(start) && start >= 0 && end >= 0) {
2897
- return Array.from(state.containerItemKeys.keys()).map((key) => state.indexByKey.get(key)).filter((index) => index !== void 0 && index >= start && index <= end).sort((a, b) => a - b);
2899
+ function checkAllSizesKnown(state, start, end) {
2900
+ if (start == null || end == null || start < 0 || end < start) {
2901
+ return false;
2898
2902
  }
2899
- return [];
2900
- }
2901
- function getMountedBufferedIndices(state) {
2902
- return getMountedIndicesInRange(state, state.startBuffered, state.endBuffered);
2903
- }
2904
- function getMountedNoBufferIndices(state) {
2905
- return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2906
- }
2907
- function checkAllSizesKnown(state, indices) {
2908
- return indices.length > 0 && indices.every((index) => {
2909
- const key = getId(state, index);
2910
- return key !== void 0 && state.sizesKnown.has(key);
2911
- });
2903
+ let hasMountedIndex = false;
2904
+ for (const key of state.containerItemKeys.keys()) {
2905
+ const index = state.indexByKey.get(key);
2906
+ if (index !== void 0 && index >= start && index <= end) {
2907
+ hasMountedIndex = true;
2908
+ const id = getId(state, index);
2909
+ if (id === void 0 || !state.sizesKnown.has(id)) {
2910
+ return false;
2911
+ }
2912
+ }
2913
+ }
2914
+ return hasMountedIndex;
2912
2915
  }
2913
2916
 
2914
2917
  // src/core/bootstrapInitialScroll.ts
@@ -3409,8 +3412,7 @@ function evaluateBootstrapInitialScroll(ctx) {
3409
3412
  bootstrapInitialScroll.targetIndexSeed = void 0;
3410
3413
  }
3411
3414
  const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
3412
- const mountedBufferedIndices = getMountedBufferedIndices(state);
3413
- const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
3415
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
3414
3416
  const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
3415
3417
  const { data } = state.props;
3416
3418
  const visibleIndices = getBootstrapRevealVisibleIndices({
@@ -3841,7 +3843,14 @@ function updateSnapToOffsets(ctx) {
3841
3843
  }
3842
3844
 
3843
3845
  // src/core/updateItemPositions.ts
3844
- function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP, optimizeForVisibleWindow = false } = {
3846
+ function updateItemPositions(ctx, dataChanged, {
3847
+ doMVCP,
3848
+ forceFullUpdate = false,
3849
+ optimizeForVisibleWindow = false,
3850
+ scrollBottomBuffered,
3851
+ scrollVelocity,
3852
+ startIndex
3853
+ } = {
3845
3854
  doMVCP: false,
3846
3855
  forceFullUpdate: false,
3847
3856
  optimizeForVisibleWindow: false,
@@ -3868,7 +3877,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3868
3877
  const extraData = peek$(ctx, "extraData");
3869
3878
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
3870
3879
  const lastScrollDelta = state.lastScrollDelta;
3871
- const velocity = getScrollVelocity(state);
3880
+ const velocity = scrollVelocity != null ? scrollVelocity : getScrollVelocity(state);
3872
3881
  const shouldOptimize = !forceFullUpdate && !dataChanged && (optimizeForVisibleWindow || Math.abs(velocity) > 0 || Platform.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
3873
3882
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3874
3883
  const useAverageSize = true;
@@ -4048,25 +4057,28 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4048
4057
  const configId = viewabilityConfig.id;
4049
4058
  const viewabilityState = ensureViewabilityState(ctx, configId);
4050
4059
  const { viewableItems: previousViewableItems, start, end, startBuffered, endBuffered } = viewabilityState;
4051
- const viewabilityTokens = /* @__PURE__ */ new Map();
4060
+ let staleViewabilityAmountIds;
4052
4061
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4053
- viewabilityTokens.set(
4062
+ const nextValue = computeViewability(
4063
+ state,
4064
+ ctx,
4065
+ viewabilityConfig,
4054
4066
  containerId,
4055
- computeViewability(
4056
- state,
4057
- ctx,
4058
- viewabilityConfig,
4059
- containerId,
4060
- value.key,
4061
- scrollSize,
4062
- value.item,
4063
- value.index
4064
- )
4067
+ value.key,
4068
+ scrollSize,
4069
+ value.item,
4070
+ value.index
4065
4071
  );
4072
+ if (nextValue.sizeVisible < 0) {
4073
+ staleViewabilityAmountIds != null ? staleViewabilityAmountIds : staleViewabilityAmountIds = [];
4074
+ staleViewabilityAmountIds.push(containerId);
4075
+ }
4066
4076
  }
4067
4077
  const changed = [];
4078
+ const previousViewableKeys = /* @__PURE__ */ new Set();
4068
4079
  if (previousViewableItems) {
4069
4080
  for (const viewToken of previousViewableItems) {
4081
+ previousViewableKeys.add(viewToken.key);
4070
4082
  const containerId = findContainerId(ctx, viewToken.key);
4071
4083
  if (!checkIsViewable(
4072
4084
  state,
@@ -4098,7 +4110,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4098
4110
  key
4099
4111
  };
4100
4112
  viewableItems.push(viewToken);
4101
- if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
4113
+ if (!previousViewableKeys.has(viewToken.key)) {
4102
4114
  changed.push(viewToken);
4103
4115
  }
4104
4116
  }
@@ -4119,20 +4131,17 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4119
4131
  onViewableItemsChanged({ changed, end, endBuffered, start, startBuffered, viewableItems });
4120
4132
  }
4121
4133
  }
4122
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4123
- if (value.sizeVisible < 0) {
4124
- ctx.mapViewabilityAmountValues.delete(containerId);
4134
+ if (staleViewabilityAmountIds) {
4135
+ for (const containerId of staleViewabilityAmountIds) {
4136
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
4137
+ if (value && value.sizeVisible < 0) {
4138
+ ctx.mapViewabilityAmountValues.delete(containerId);
4139
+ }
4125
4140
  }
4126
4141
  }
4127
4142
  }
4128
- function shallowEqual(prev, next) {
4129
- if (!prev) return false;
4130
- const keys = Object.keys(next);
4131
- for (let i = 0; i < keys.length; i++) {
4132
- const k = keys[i];
4133
- if (prev[k] !== next[k]) return false;
4134
- }
4135
- return true;
4143
+ function areViewabilityAmountTokensEqual(prev, next) {
4144
+ return !!prev && prev.containerId === next.containerId && prev.index === next.index && prev.isViewable === next.isViewable && prev.item === next.item && prev.key === next.key && prev.percentOfScroller === next.percentOfScroller && prev.percentVisible === next.percentVisible && prev.scrollSize === next.scrollSize && prev.size === next.size && prev.sizeVisible === next.sizeVisible;
4136
4145
  }
4137
4146
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4138
4147
  const { sizes, scroll: scrollState } = state;
@@ -4157,7 +4166,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4157
4166
  sizeVisible: -1
4158
4167
  };
4159
4168
  const prev2 = ctx.mapViewabilityAmountValues.get(containerId);
4160
- if (!shallowEqual(prev2, value2)) {
4169
+ if (!areViewabilityAmountTokensEqual(prev2, value2)) {
4161
4170
  ctx.mapViewabilityAmountValues.set(containerId, value2);
4162
4171
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4163
4172
  if (cb) {
@@ -4187,7 +4196,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4187
4196
  sizeVisible
4188
4197
  };
4189
4198
  const prev = ctx.mapViewabilityAmountValues.get(containerId);
4190
- if (!shallowEqual(prev, value)) {
4199
+ if (!areViewabilityAmountTokensEqual(prev, value)) {
4191
4200
  ctx.mapViewabilityAmountValues.set(containerId, value);
4192
4201
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4193
4202
  if (cb) {
@@ -4238,126 +4247,152 @@ function getExpandedContainerPoolSize(dataLength, numContainers) {
4238
4247
  }
4239
4248
 
4240
4249
  // src/utils/findAvailableContainers.ts
4241
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4250
+ function findAvailableContainers(ctx, needNewContainers, startBuffered, endBuffered, pendingRemoval, getRequiredItemType, protectedKeys) {
4251
+ const numNeeded = needNewContainers.length;
4252
+ if (numNeeded === 0) {
4253
+ return [];
4254
+ }
4242
4255
  const numContainers = peek$(ctx, "numContainers");
4243
4256
  const state = ctx.state;
4244
4257
  const { stickyContainerPool, containerItemTypes } = state;
4245
4258
  const shouldAvoidAssignedContainerReuse = state.props.recycleItems && !!state.props.positionComponentInternal;
4246
- const result = [];
4247
- const availableContainers = [];
4248
- const pendingRemovalSet = new Set(pendingRemoval);
4259
+ const allocations = [];
4260
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4249
4261
  let pendingRemovalChanged = false;
4262
+ let nextNewContainerIndex = numContainers;
4263
+ const usedContainers = /* @__PURE__ */ new Set();
4264
+ let availableContainers;
4250
4265
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet;
4251
- const stickyHeaderItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyHeaderIndicesSet.has(index))) || [];
4252
4266
  const canReuseContainer = (containerIndex, requiredType) => {
4253
4267
  if (!requiredType) return true;
4254
4268
  const existingType = containerItemTypes.get(containerIndex);
4255
4269
  if (!existingType) return true;
4256
4270
  return existingType === requiredType;
4257
4271
  };
4258
- const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
4259
- let typeIndex = 0;
4260
- for (let i = 0; i < stickyHeaderItemIndices.length; i++) {
4261
- const requiredType = neededTypes[typeIndex];
4262
- let foundContainer = false;
4263
- for (const containerIndex of stickyContainerPool) {
4264
- const key = peek$(ctx, `containerItemKey${containerIndex}`);
4265
- const isPendingRemoval = pendingRemovalSet.has(containerIndex);
4266
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
4267
- result.push(containerIndex);
4268
- if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
4269
- pendingRemovalChanged = true;
4270
- }
4271
- foundContainer = true;
4272
- if (requiredItemTypes) typeIndex++;
4273
- break;
4274
- }
4272
+ const pushAllocation = (itemIndex, itemType, containerIndex) => {
4273
+ allocations.push({
4274
+ containerIndex,
4275
+ itemIndex,
4276
+ itemType
4277
+ });
4278
+ usedContainers.add(containerIndex);
4279
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.delete(containerIndex)) {
4280
+ pendingRemovalChanged = true;
4275
4281
  }
4276
- if (!foundContainer) {
4277
- const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
4278
- result.push(newContainerIndex);
4282
+ };
4283
+ const pushNewContainer = (itemIndex, itemType, isSticky) => {
4284
+ const newContainerIndex = nextNewContainerIndex++;
4285
+ pushAllocation(itemIndex, itemType, newContainerIndex);
4286
+ if (isSticky) {
4279
4287
  stickyContainerPool.add(newContainerIndex);
4280
- if (requiredItemTypes) typeIndex++;
4281
- }
4282
- }
4283
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4284
- if (stickyContainerPool.has(u)) {
4285
- continue;
4286
4288
  }
4287
- const key = peek$(ctx, `containerItemKey${u}`);
4288
- const requiredType = neededTypes[typeIndex];
4289
- const isPending = key !== void 0 && pendingRemovalSet.has(u);
4290
- const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
4291
- if (canUse) {
4292
- if (isPending) {
4293
- pendingRemovalSet.delete(u);
4294
- pendingRemovalChanged = true;
4295
- }
4296
- result.push(u);
4297
- if (requiredItemTypes) {
4298
- typeIndex++;
4299
- }
4289
+ return newContainerIndex;
4290
+ };
4291
+ const canUseContainer = (containerIndex, itemType) => {
4292
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4293
+ return false;
4300
4294
  }
4301
- }
4302
- if (!shouldAvoidAssignedContainerReuse) {
4303
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4304
- if (stickyContainerPool.has(u)) {
4305
- continue;
4306
- }
4307
- const key = peek$(ctx, `containerItemKey${u}`);
4308
- if (key === void 0) continue;
4309
- if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4310
- const index = state.indexByKey.get(key);
4311
- const isOutOfView = index < startBuffered || index > endBuffered;
4312
- if (isOutOfView) {
4313
- const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4314
- if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
4315
- availableContainers.push({ distance, index: u });
4295
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4296
+ const isPending = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4297
+ return (key === void 0 || isPending) && canReuseContainer(containerIndex, itemType);
4298
+ };
4299
+ const findStickyContainer = (itemType) => {
4300
+ let foundContainer;
4301
+ for (const containerIndex of stickyContainerPool) {
4302
+ if (!usedContainers.has(containerIndex)) {
4303
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4304
+ const isPendingRemoval = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4305
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, itemType)) {
4306
+ foundContainer = containerIndex;
4307
+ break;
4316
4308
  }
4317
4309
  }
4318
4310
  }
4319
- }
4320
- const remaining = numNeeded - result.length;
4321
- if (remaining > 0) {
4322
- if (availableContainers.length > 0) {
4323
- if (availableContainers.length > remaining) {
4324
- availableContainers.sort(comparatorByDistance);
4325
- availableContainers.length = remaining;
4311
+ return foundContainer;
4312
+ };
4313
+ const findUnassignedOrPendingContainer = (itemType) => {
4314
+ let foundContainer;
4315
+ for (let containerIndex = 0; containerIndex < numContainers && foundContainer === void 0; containerIndex++) {
4316
+ if (canUseContainer(containerIndex, itemType)) {
4317
+ foundContainer = containerIndex;
4326
4318
  }
4327
- for (const container of availableContainers) {
4328
- result.push(container.index);
4329
- if (requiredItemTypes) {
4330
- typeIndex++;
4319
+ }
4320
+ return foundContainer;
4321
+ };
4322
+ const getAvailableContainers = () => {
4323
+ if (!availableContainers) {
4324
+ availableContainers = [];
4325
+ if (!shouldAvoidAssignedContainerReuse) {
4326
+ for (let containerIndex = 0; containerIndex < numContainers; containerIndex++) {
4327
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4328
+ continue;
4329
+ }
4330
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4331
+ if (key === void 0) continue;
4332
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4333
+ const index = state.indexByKey.get(key);
4334
+ const isOutOfView = index < startBuffered || index > endBuffered;
4335
+ if (isOutOfView) {
4336
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4337
+ availableContainers.push({ distance, index: containerIndex });
4338
+ }
4331
4339
  }
4340
+ availableContainers.sort(comparatorByDistance);
4332
4341
  }
4333
4342
  }
4334
- const stillNeeded = numNeeded - result.length;
4335
- if (stillNeeded > 0) {
4336
- for (let i = 0; i < stillNeeded; i++) {
4337
- result.push(numContainers + i);
4343
+ return availableContainers;
4344
+ };
4345
+ const findAvailableContainer = (itemType) => {
4346
+ const containers = getAvailableContainers();
4347
+ let matchIndex = -1;
4348
+ for (let i = 0; i < containers.length && matchIndex === -1; i++) {
4349
+ const containerIndex = containers[i].index;
4350
+ if (!usedContainers.has(containerIndex) && canReuseContainer(containerIndex, itemType)) {
4351
+ matchIndex = i;
4338
4352
  }
4339
- if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
4340
- console.warn(
4341
- "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize.",
4342
- {
4343
- debugInfo: {
4344
- numContainers,
4345
- numContainersPooled: peek$(ctx, "numContainersPooled"),
4346
- numNeeded,
4347
- stillNeeded
4348
- }
4349
- }
4350
- );
4353
+ }
4354
+ return matchIndex === -1 ? void 0 : containers.splice(matchIndex, 1)[0].index;
4355
+ };
4356
+ for (const itemIndex of needNewContainers) {
4357
+ const itemType = getRequiredItemType == null ? void 0 : getRequiredItemType(itemIndex);
4358
+ const isSticky = stickyHeaderIndicesSet.has(itemIndex);
4359
+ let containerIndex;
4360
+ if (isSticky) {
4361
+ containerIndex = findStickyContainer(itemType);
4362
+ } else {
4363
+ containerIndex = findUnassignedOrPendingContainer(itemType);
4364
+ if (containerIndex === void 0) {
4365
+ containerIndex = findAvailableContainer(itemType);
4351
4366
  }
4352
4367
  }
4368
+ if (containerIndex !== void 0) {
4369
+ pushAllocation(itemIndex, itemType, containerIndex);
4370
+ } else {
4371
+ pushNewContainer(itemIndex, itemType, isSticky);
4372
+ }
4353
4373
  }
4354
4374
  if (pendingRemovalChanged) {
4355
4375
  pendingRemoval.length = 0;
4356
- for (const value of pendingRemovalSet) {
4357
- pendingRemoval.push(value);
4376
+ if (pendingRemovalSet) {
4377
+ for (const value of pendingRemovalSet) {
4378
+ pendingRemoval.push(value);
4379
+ }
4358
4380
  }
4359
4381
  }
4360
- return result.sort(comparatorDefault);
4382
+ if (IS_DEV && nextNewContainerIndex > peek$(ctx, "numContainersPooled")) {
4383
+ console.warn(
4384
+ "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize.",
4385
+ {
4386
+ debugInfo: {
4387
+ numContainers,
4388
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
4389
+ numNeeded,
4390
+ stillNeeded: nextNewContainerIndex - numContainers
4391
+ }
4392
+ }
4393
+ );
4394
+ }
4395
+ return allocations;
4361
4396
  }
4362
4397
  function comparatorByDistance(a, b) {
4363
4398
  return b.distance - a.distance;
@@ -4383,21 +4418,28 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
4383
4418
  }
4384
4419
  return -1;
4385
4420
  }
4386
- function getActiveStickyIndices(ctx, stickyHeaderIndices) {
4421
+ function isStickyIndexActive(ctx, targetIndex) {
4387
4422
  const state = ctx.state;
4388
- return new Set(
4389
- Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
4390
- );
4423
+ let isActive = false;
4424
+ for (const containerIndex of state.stickyContainerPool) {
4425
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4426
+ const itemIndex = key ? state.indexByKey.get(key) : void 0;
4427
+ if (itemIndex === targetIndex) {
4428
+ isActive = true;
4429
+ break;
4430
+ }
4431
+ }
4432
+ return isActive;
4391
4433
  }
4392
- function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4434
+ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4393
4435
  var _a3;
4394
4436
  const state = ctx.state;
4395
- const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
4396
4437
  set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
4397
4438
  for (let offset = 0; offset <= 1; offset++) {
4398
4439
  const idx = currentStickyIdx - offset;
4399
- if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
4440
+ if (idx < 0) continue;
4400
4441
  const stickyIndex = stickyArray[idx];
4442
+ if (isStickyIndexActive(ctx, stickyIndex)) continue;
4401
4443
  const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
4402
4444
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered) && !needNewContainersSet.has(stickyIndex)) {
4403
4445
  needNewContainersSet.add(stickyIndex);
@@ -4439,10 +4481,86 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4439
4481
  }
4440
4482
  }
4441
4483
  }
4484
+ function trackVisibleRange(range, i, top, size, scroll, scrollBottom) {
4485
+ let didPassVisibleEnd = false;
4486
+ if (range.startNoBuffer === null && top + size > scroll) {
4487
+ range.startNoBuffer = i;
4488
+ }
4489
+ if (range.firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4490
+ range.firstFullyOnScreenIndex = i;
4491
+ }
4492
+ if (range.startNoBuffer !== null) {
4493
+ if (top <= scrollBottom) {
4494
+ range.endNoBuffer = i;
4495
+ } else {
4496
+ didPassVisibleEnd = true;
4497
+ }
4498
+ }
4499
+ return didPassVisibleEnd;
4500
+ }
4501
+ function getIdsInVisibleRange(state, range) {
4502
+ var _a3, _b;
4503
+ const idsInView = [];
4504
+ const firstVisibleAnchorIndex = (_a3 = range.firstFullyOnScreenIndex) != null ? _a3 : range.startNoBuffer;
4505
+ if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && range.endNoBuffer !== null) {
4506
+ for (let i = firstVisibleAnchorIndex; i <= range.endNoBuffer; i++) {
4507
+ const id = (_b = state.idCache[i]) != null ? _b : getId(state, i);
4508
+ idsInView.push(id);
4509
+ }
4510
+ }
4511
+ return idsInView;
4512
+ }
4513
+ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4514
+ var _a3, _b;
4515
+ const state = ctx.state;
4516
+ const {
4517
+ endBuffered,
4518
+ idCache,
4519
+ positions,
4520
+ props: { data },
4521
+ sizes,
4522
+ startBuffered
4523
+ } = state;
4524
+ if (startBuffered === null || endBuffered === null || startBuffered < 0 || endBuffered < startBuffered) {
4525
+ return;
4526
+ }
4527
+ const visibleRange = {
4528
+ endNoBuffer: null,
4529
+ firstFullyOnScreenIndex: void 0,
4530
+ startNoBuffer: null
4531
+ };
4532
+ for (let i = startBuffered; i <= endBuffered && i < data.length; i++) {
4533
+ const id = (_a3 = idCache[i]) != null ? _a3 : getId(state, i);
4534
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(ctx, id, i, data[i]);
4535
+ const top = positions[i];
4536
+ const didPassVisibleEnd = trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4537
+ if (didPassVisibleEnd) {
4538
+ break;
4539
+ }
4540
+ }
4541
+ Object.assign(state, {
4542
+ endNoBuffer: visibleRange.endNoBuffer,
4543
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4544
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4545
+ startNoBuffer: visibleRange.startNoBuffer
4546
+ });
4547
+ if (visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4548
+ updateViewableItems(
4549
+ state,
4550
+ ctx,
4551
+ viewabilityConfigCallbackPairs,
4552
+ scrollLength,
4553
+ visibleRange.startNoBuffer,
4554
+ visibleRange.endNoBuffer,
4555
+ startBuffered,
4556
+ endBuffered
4557
+ );
4558
+ }
4559
+ }
4442
4560
  function calculateItemsInView(ctx, params = {}) {
4443
4561
  const state = ctx.state;
4444
4562
  batchedUpdates(() => {
4445
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
4563
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
4446
4564
  const {
4447
4565
  columns,
4448
4566
  containerItemKeys,
@@ -4543,6 +4661,15 @@ function calculateItemsInView(ctx, params = {}) {
4543
4661
  state.scrollForNextCalculateItemsInView = void 0;
4544
4662
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
4545
4663
  if (Platform.OS !== "web" || !isInMVCPActiveMode(state)) {
4664
+ if (viewabilityConfigCallbackPairs) {
4665
+ updateViewabilityForCachedRange(
4666
+ ctx,
4667
+ viewabilityConfigCallbackPairs,
4668
+ scrollLength,
4669
+ scroll,
4670
+ scrollBottom
4671
+ );
4672
+ }
4546
4673
  finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
4547
4674
  return;
4548
4675
  }
@@ -4559,6 +4686,7 @@ function calculateItemsInView(ctx, params = {}) {
4559
4686
  forceFullUpdate: !!forceFullItemPositions,
4560
4687
  optimizeForVisibleWindow,
4561
4688
  scrollBottomBuffered,
4689
+ scrollVelocity: speed,
4562
4690
  startIndex
4563
4691
  });
4564
4692
  totalSize = getContentSize(ctx);
@@ -4584,10 +4712,8 @@ function calculateItemsInView(ctx, params = {}) {
4584
4712
  updateScroll2(state.scroll);
4585
4713
  updateScrollRange();
4586
4714
  }
4587
- let startNoBuffer = null;
4588
4715
  let startBuffered = null;
4589
4716
  let startBufferedId = null;
4590
- let endNoBuffer = null;
4591
4717
  let endBuffered = null;
4592
4718
  let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4593
4719
  for (let i = loopStart; i >= 0; i--) {
@@ -4621,19 +4747,18 @@ function calculateItemsInView(ctx, params = {}) {
4621
4747
  maxIndexRendered = Math.max(maxIndexRendered, index);
4622
4748
  }
4623
4749
  }
4624
- let firstFullyOnScreenIndex;
4750
+ const visibleRange = {
4751
+ endNoBuffer: null,
4752
+ firstFullyOnScreenIndex: void 0,
4753
+ startNoBuffer: null
4754
+ };
4625
4755
  const dataLength = data.length;
4626
4756
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4627
4757
  const id = (_i = idCache[i]) != null ? _i : getId(state, i);
4628
4758
  const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
4629
4759
  const top = positions[i];
4630
4760
  if (!foundEnd) {
4631
- if (startNoBuffer === null && top + size > scroll) {
4632
- startNoBuffer = i;
4633
- }
4634
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4635
- firstFullyOnScreenIndex = i;
4636
- }
4761
+ trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4637
4762
  if (startBuffered === null && top + size > scrollTopBuffered) {
4638
4763
  startBuffered = i;
4639
4764
  startBufferedId = id;
@@ -4643,10 +4768,7 @@ function calculateItemsInView(ctx, params = {}) {
4643
4768
  nextTop = top;
4644
4769
  }
4645
4770
  }
4646
- if (startNoBuffer !== null) {
4647
- if (top <= scrollBottom) {
4648
- endNoBuffer = i;
4649
- }
4771
+ if (visibleRange.startNoBuffer !== null) {
4650
4772
  if (top <= scrollBottomBuffered) {
4651
4773
  endBuffered = i;
4652
4774
  if (scrollBottomBuffered > totalSize) {
@@ -4660,22 +4782,14 @@ function calculateItemsInView(ctx, params = {}) {
4660
4782
  }
4661
4783
  }
4662
4784
  }
4663
- const idsInView = [];
4664
- const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4665
- if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4666
- for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4667
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4668
- idsInView.push(id);
4669
- }
4670
- }
4671
4785
  Object.assign(state, {
4672
4786
  endBuffered,
4673
- endNoBuffer,
4674
- firstFullyOnScreenIndex,
4675
- idsInView,
4787
+ endNoBuffer: visibleRange.endNoBuffer,
4788
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4789
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4676
4790
  startBuffered,
4677
4791
  startBufferedId,
4678
- startNoBuffer
4792
+ startNoBuffer: visibleRange.startNoBuffer
4679
4793
  });
4680
4794
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
4681
4795
  state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
@@ -4697,7 +4811,7 @@ function calculateItemsInView(ctx, params = {}) {
4697
4811
  const needNewContainers = [];
4698
4812
  const needNewContainersSet = /* @__PURE__ */ new Set();
4699
4813
  for (let i = startBuffered; i <= endBuffered; i++) {
4700
- const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4814
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4701
4815
  if (!containerItemKeys.has(id)) {
4702
4816
  needNewContainersSet.add(i);
4703
4817
  needNewContainers.push(i);
@@ -4706,7 +4820,7 @@ function calculateItemsInView(ctx, params = {}) {
4706
4820
  if (alwaysRenderArr.length > 0) {
4707
4821
  for (const index of alwaysRenderArr) {
4708
4822
  if (index < 0 || index >= dataLength) continue;
4709
- const id = (_m = idCache[index]) != null ? _m : getId(state, index);
4823
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
4710
4824
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4711
4825
  needNewContainersSet.add(index);
4712
4826
  needNewContainers.push(index);
@@ -4716,7 +4830,6 @@ function calculateItemsInView(ctx, params = {}) {
4716
4830
  if (stickyHeaderIndicesArr.length > 0) {
4717
4831
  handleStickyActivation(
4718
4832
  ctx,
4719
- stickyHeaderIndicesSet,
4720
4833
  stickyHeaderIndicesArr,
4721
4834
  currentStickyIdx,
4722
4835
  needNewContainers,
@@ -4728,35 +4841,34 @@ function calculateItemsInView(ctx, params = {}) {
4728
4841
  set$(ctx, "activeStickyIndex", -1);
4729
4842
  }
4730
4843
  if (needNewContainers.length > 0) {
4731
- const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
4844
+ const getRequiredItemType = getItemType ? (i) => {
4732
4845
  const itemType = getItemType(data[i], i);
4733
4846
  return itemType !== void 0 ? String(itemType) : "";
4734
- }) : void 0;
4735
- const availableContainers = findAvailableContainers(
4847
+ } : void 0;
4848
+ const availableContainerAllocations = findAvailableContainers(
4736
4849
  ctx,
4737
- needNewContainers.length,
4850
+ needNewContainers,
4738
4851
  startBuffered,
4739
4852
  endBuffered,
4740
4853
  pendingRemoval,
4741
- requiredItemTypes,
4742
- needNewContainers,
4854
+ getRequiredItemType,
4743
4855
  protectedContainerKeys
4744
4856
  );
4745
- for (let idx = 0; idx < needNewContainers.length; idx++) {
4746
- const i = needNewContainers[idx];
4747
- const containerIndex = availableContainers[idx];
4748
- const id = (_n = idCache[i]) != null ? _n : getId(state, i);
4857
+ for (const allocation of availableContainerAllocations) {
4858
+ const i = allocation.itemIndex;
4859
+ const containerIndex = allocation.containerIndex;
4860
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4749
4861
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4750
4862
  if (oldKey && oldKey !== id) {
4751
4863
  containerItemKeys.delete(oldKey);
4752
4864
  }
4753
4865
  set$(ctx, `containerItemKey${containerIndex}`, id);
4754
4866
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
4755
- if (requiredItemTypes) {
4756
- state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4867
+ if (allocation.itemType !== void 0) {
4868
+ state.containerItemTypes.set(containerIndex, allocation.itemType);
4757
4869
  }
4758
4870
  containerItemKeys.set(id, containerIndex);
4759
- (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
4871
+ (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
4760
4872
  const containerSticky = `containerSticky${containerIndex}`;
4761
4873
  const isSticky = stickyHeaderIndicesSet.has(i);
4762
4874
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4794,7 +4906,7 @@ function calculateItemsInView(ctx, params = {}) {
4794
4906
  if (alwaysRenderArr.length > 0) {
4795
4907
  for (const index of alwaysRenderArr) {
4796
4908
  if (index < 0 || index >= dataLength) continue;
4797
- const id = (_p = idCache[index]) != null ? _p : getId(state, index);
4909
+ const id = (_o = idCache[index]) != null ? _o : getId(state, index);
4798
4910
  const containerIndex = containerItemKeys.get(id);
4799
4911
  if (containerIndex !== void 0) {
4800
4912
  state.stickyContainerPool.add(containerIndex);
@@ -4813,10 +4925,11 @@ function calculateItemsInView(ctx, params = {}) {
4813
4925
  alwaysRenderSet
4814
4926
  );
4815
4927
  }
4928
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4816
4929
  let didChangePositions = false;
4817
4930
  for (let i = 0; i < numContainers; i++) {
4818
4931
  const itemKey = peek$(ctx, `containerItemKey${i}`);
4819
- if (pendingRemoval.includes(i)) {
4932
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(i)) {
4820
4933
  if (itemKey !== void 0) {
4821
4934
  containerItemKeys.delete(itemKey);
4822
4935
  }
@@ -4847,24 +4960,24 @@ function calculateItemsInView(ctx, params = {}) {
4847
4960
  evaluateBootstrapInitialScroll(ctx);
4848
4961
  return;
4849
4962
  }
4850
- const mountedBufferedIndices = getMountedBufferedIndices(state);
4851
- const mountedNoBufferIndices = getMountedNoBufferIndices(state);
4852
- const readinessIndices = hasActiveInitialScroll(state) ? mountedBufferedIndices : mountedNoBufferIndices.length > 0 ? mountedNoBufferIndices : mountedBufferedIndices;
4853
- if (!queuedInitialLayout && readinessIndices.length > 0 && checkAllSizesKnown(state, readinessIndices)) {
4854
- setDidLayout(ctx);
4855
- handleInitialScrollLayoutReady(ctx);
4963
+ if (!queuedInitialLayout && !state.didContainersLayout) {
4964
+ const isInitialLayoutReady = hasActiveInitialScroll(state) ? checkAllSizesKnown(state, state.startBuffered, state.endBuffered) : checkAllSizesKnown(state, state.startNoBuffer, state.endNoBuffer) || checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
4965
+ if (isInitialLayoutReady) {
4966
+ setDidLayout(ctx);
4967
+ handleInitialScrollLayoutReady(ctx);
4968
+ }
4856
4969
  }
4857
- if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
4970
+ if (viewabilityConfigCallbackPairs && visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4858
4971
  if (!didMVCPAdjustScroll) {
4859
4972
  updateViewableItems(
4860
4973
  ctx.state,
4861
4974
  ctx,
4862
4975
  viewabilityConfigCallbackPairs,
4863
4976
  scrollLength,
4864
- startNoBuffer,
4865
- endNoBuffer,
4866
- startBuffered != null ? startBuffered : startNoBuffer,
4867
- endBuffered != null ? endBuffered : endNoBuffer
4977
+ visibleRange.startNoBuffer,
4978
+ visibleRange.endNoBuffer,
4979
+ startBuffered != null ? startBuffered : visibleRange.startNoBuffer,
4980
+ endBuffered != null ? endBuffered : visibleRange.endNoBuffer
4868
4981
  );
4869
4982
  }
4870
4983
  }
@@ -5325,6 +5438,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5325
5438
  } = state;
5326
5439
  if (!data) return;
5327
5440
  const index = state.indexByKey.get(itemKey);
5441
+ let resolvedMeasurementItem;
5328
5442
  if (getFixedItemSize) {
5329
5443
  if (index === void 0) {
5330
5444
  return;
@@ -5335,6 +5449,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5335
5449
  }
5336
5450
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5337
5451
  const size2 = getFixedItemSize(itemData, index, type);
5452
+ resolvedMeasurementItem = {
5453
+ didResolveFixedItemSize: true,
5454
+ fixedItemSize: size2,
5455
+ itemData,
5456
+ itemType: type
5457
+ };
5338
5458
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
5339
5459
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5340
5460
  return;
@@ -5344,7 +5464,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5344
5464
  let shouldMaintainScrollAtEnd = false;
5345
5465
  let minIndexSizeChanged;
5346
5466
  const prevSizeKnown = state.sizesKnown.get(itemKey);
5347
- const diff = updateOneItemSize(ctx, itemKey, sizeObj);
5467
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem);
5348
5468
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
5349
5469
  if (diff !== 0) {
5350
5470
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -5369,7 +5489,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5369
5489
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
5370
5490
  }
5371
5491
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5372
- if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5492
+ if (didContainersLayout || checkAllSizesKnown(state, state.startBuffered, state.endBuffered)) {
5373
5493
  if (needsRecalculate) {
5374
5494
  state.scrollForNextCalculateItemsInView = void 0;
5375
5495
  runOrScheduleMVCPRecalculate(ctx);
@@ -5383,8 +5503,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5383
5503
  }
5384
5504
  }
5385
5505
  }
5386
- function updateOneItemSize(ctx, itemKey, sizeObj) {
5387
- var _a3, _b;
5506
+ function updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem) {
5507
+ var _a3, _b, _c;
5388
5508
  const state = ctx.state;
5389
5509
  const {
5390
5510
  indexByKey,
@@ -5394,14 +5514,19 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5394
5514
  } = state;
5395
5515
  if (!data) return 0;
5396
5516
  const index = indexByKey.get(itemKey);
5397
- const itemData = data[index];
5398
- let itemType;
5399
- let fixedItemSize;
5400
- if (getFixedItemSize) {
5401
- itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5517
+ const itemData = (_a3 = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemData) != null ? _a3 : data[index];
5518
+ let itemType = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemType;
5519
+ let fixedItemSize = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.fixedItemSize;
5520
+ if (getFixedItemSize && !(resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize)) {
5521
+ itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5402
5522
  fixedItemSize = getFixedItemSize(itemData, index, itemType);
5403
5523
  }
5404
- const prevSize = getItemSize(ctx, itemKey, index, itemData);
5524
+ const resolvedItemSize = (resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize) || itemType !== void 0 || fixedItemSize !== void 0 ? {
5525
+ didResolveFixedItemSize: resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize,
5526
+ fixedItemSize,
5527
+ itemType
5528
+ } : void 0;
5529
+ const prevSize = getItemSize(ctx, itemKey, index, itemData, void 0, void 0, void 0, resolvedItemSize);
5405
5530
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5406
5531
  const prevSizeKnown = sizesKnown.get(itemKey);
5407
5532
  if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
@@ -5410,7 +5535,7 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5410
5535
  const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5411
5536
  sizesKnown.set(itemKey, size);
5412
5537
  if (fixedItemSize === void 0 && size > 0) {
5413
- itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5538
+ itemType != null ? itemType : itemType = getItemType ? (_c = getItemType(itemData, index)) != null ? _c : "" : "";
5414
5539
  let averages = averageSizes[itemType];
5415
5540
  if (!averages) {
5416
5541
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -5525,6 +5650,11 @@ function getAverageItemSizes(state) {
5525
5650
  }
5526
5651
  return averageItemSizes;
5527
5652
  }
5653
+ function triggerMountedContainerLayouts(ctx) {
5654
+ for (const triggerLayout of ctx.containerLayoutTriggers.values()) {
5655
+ triggerLayout();
5656
+ }
5657
+ }
5528
5658
  function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5529
5659
  const state = ctx.state;
5530
5660
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
@@ -5650,6 +5780,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5650
5780
  state.columns.length = 0;
5651
5781
  state.columnSpans.length = 0;
5652
5782
  }
5783
+ triggerMountedContainerLayouts(ctx);
5653
5784
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
5654
5785
  };
5655
5786
  return {
@@ -6457,7 +6588,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6457
6588
  viewabilityConfigCallbackPairs
6458
6589
  });
6459
6590
  state.viewabilityConfigCallbackPairs = viewability;
6460
- state.enableScrollForNextCalculateItemsInView = !viewability;
6591
+ state.enableScrollForNextCalculateItemsInView = true;
6461
6592
  if (viewability) {
6462
6593
  state.scrollForNextCalculateItemsInView = void 0;
6463
6594
  }