@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.
@@ -1,5 +1,5 @@
1
1
  import * as React3 from 'react';
2
- import { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useImperativeHandle, useLayoutEffect, useContext } from 'react';
2
+ import { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle, useContext } from 'react';
3
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
4
4
  import * as ReactDOM from 'react-dom';
5
5
  import { flushSync } from 'react-dom';
@@ -132,6 +132,7 @@ function StateProvider({ children }) {
132
132
  const [value] = React3.useState(() => ({
133
133
  animatedScrollY: createAnimatedValue(0),
134
134
  columnWrapperStyle: void 0,
135
+ containerLayoutTriggers: /* @__PURE__ */ new Map(),
135
136
  contextNum: contextNum++,
136
137
  listeners: /* @__PURE__ */ new Map(),
137
138
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -399,9 +400,6 @@ function roundSize(size) {
399
400
  function isNullOrUndefined(value) {
400
401
  return value === null || value === void 0;
401
402
  }
402
- function comparatorDefault(a, b) {
403
- return a - b;
404
- }
405
403
  function getPadding(s, type) {
406
404
  var _a3, _b, _c;
407
405
  const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
@@ -909,18 +907,6 @@ var Container = typedMemo(function Container2({
909
907
  [itemKey, data, extraData]
910
908
  );
911
909
  const { index, renderedItem } = renderedItemInfo || {};
912
- const contextValue = useMemo(() => {
913
- ctx.viewRefs.set(id, ref);
914
- return {
915
- containerId: id,
916
- index,
917
- itemKey,
918
- triggerLayout: () => {
919
- forceLayoutRender((v) => v + 1);
920
- },
921
- value: data
922
- };
923
- }, [id, itemKey, index, data]);
924
910
  const onLayoutChange = useCallback((rectangle) => {
925
911
  const {
926
912
  horizontal: currentHorizontal,
@@ -964,6 +950,27 @@ var Container = typedMemo(function Container2({
964
950
  doUpdate();
965
951
  }
966
952
  }, []);
953
+ const triggerLayout = useCallback(() => {
954
+ forceLayoutRender((v) => v + 1);
955
+ }, []);
956
+ const contextValue = useMemo(() => {
957
+ ctx.viewRefs.set(id, ref);
958
+ return {
959
+ containerId: id,
960
+ index,
961
+ itemKey,
962
+ triggerLayout,
963
+ value: data
964
+ };
965
+ }, [id, itemKey, index, data, triggerLayout]);
966
+ useLayoutEffect(() => {
967
+ ctx.containerLayoutTriggers.set(id, triggerLayout);
968
+ return () => {
969
+ if (ctx.containerLayoutTriggers.get(id) === triggerLayout) {
970
+ ctx.containerLayoutTriggers.delete(id);
971
+ }
972
+ };
973
+ }, [ctx, id, triggerLayout]);
967
974
  const { onLayout } = useOnLayoutSync(
968
975
  {
969
976
  onLayoutChange,
@@ -2441,14 +2448,14 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2441
2448
  }
2442
2449
 
2443
2450
  // src/utils/getItemSize.ts
2444
- function getKnownOrFixedSize(ctx, key, index, data) {
2445
- var _a3;
2451
+ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
2452
+ var _a3, _b;
2446
2453
  const state = ctx.state;
2447
2454
  const { getFixedItemSize, getItemType } = state.props;
2448
2455
  let size = key ? state.sizesKnown.get(key) : void 0;
2449
2456
  if (size === void 0 && key && getFixedItemSize) {
2450
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2451
- size = getFixedItemSize(data, index, itemType);
2457
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2458
+ size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
2452
2459
  if (size !== void 0) {
2453
2460
  state.sizesKnown.set(key, size);
2454
2461
  }
@@ -2467,8 +2474,8 @@ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
2467
2474
  }
2468
2475
  return true;
2469
2476
  }
2470
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2471
- var _a3, _b, _c;
2477
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize, resolved) {
2478
+ var _a3, _b, _c, _d;
2472
2479
  const state = ctx.state;
2473
2480
  const {
2474
2481
  sizes,
@@ -2487,14 +2494,14 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2487
2494
  return renderedSize;
2488
2495
  }
2489
2496
  }
2490
- size = getKnownOrFixedSize(ctx, key, index, data);
2497
+ size = getKnownOrFixedSize(ctx, key, index, data, resolved);
2491
2498
  if (size !== void 0) {
2492
2499
  setSize(ctx, key, size, notifyTotalSize);
2493
2500
  return size;
2494
2501
  }
2495
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2502
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2496
2503
  if (useAverageSize && !scrollingTo) {
2497
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
2504
+ const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
2498
2505
  if (averageSizeForType !== void 0) {
2499
2506
  size = roundSize(averageSizeForType);
2500
2507
  }
@@ -2503,7 +2510,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2503
2510
  return renderedSize;
2504
2511
  }
2505
2512
  if (size === void 0 && useAverageSize && scrollingTo) {
2506
- const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
2513
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
2507
2514
  if (averageSizeForType !== void 0) {
2508
2515
  size = roundSize(averageSizeForType);
2509
2516
  }
@@ -3064,8 +3071,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3064
3071
  if ((options == null ? void 0 : options.markHasScrolled) !== false) {
3065
3072
  state.hasScrolled = true;
3066
3073
  }
3067
- state.lastBatchingAction = Date.now();
3068
3074
  const currentTime = Date.now();
3075
+ state.lastBatchingAction = currentTime;
3069
3076
  const adjust = scrollAdjustHandler.getAdjust();
3070
3077
  const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
3071
3078
  if (adjustChanged) {
@@ -3374,26 +3381,22 @@ function advanceCurrentInitialScrollSession(ctx, options) {
3374
3381
  }
3375
3382
 
3376
3383
  // src/utils/checkAllSizesKnown.ts
3377
- function isNullOrUndefined2(value) {
3378
- return value === null || value === void 0;
3379
- }
3380
- function getMountedIndicesInRange(state, start, end) {
3381
- if (!isNullOrUndefined2(end) && !isNullOrUndefined2(start) && start >= 0 && end >= 0) {
3382
- 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);
3384
+ function checkAllSizesKnown(state, start, end) {
3385
+ if (start == null || end == null || start < 0 || end < start) {
3386
+ return false;
3383
3387
  }
3384
- return [];
3385
- }
3386
- function getMountedBufferedIndices(state) {
3387
- return getMountedIndicesInRange(state, state.startBuffered, state.endBuffered);
3388
- }
3389
- function getMountedNoBufferIndices(state) {
3390
- return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
3391
- }
3392
- function checkAllSizesKnown(state, indices) {
3393
- return indices.length > 0 && indices.every((index) => {
3394
- const key = getId(state, index);
3395
- return key !== void 0 && state.sizesKnown.has(key);
3396
- });
3388
+ let hasMountedIndex = false;
3389
+ for (const key of state.containerItemKeys.keys()) {
3390
+ const index = state.indexByKey.get(key);
3391
+ if (index !== void 0 && index >= start && index <= end) {
3392
+ hasMountedIndex = true;
3393
+ const id = getId(state, index);
3394
+ if (id === void 0 || !state.sizesKnown.has(id)) {
3395
+ return false;
3396
+ }
3397
+ }
3398
+ }
3399
+ return hasMountedIndex;
3397
3400
  }
3398
3401
 
3399
3402
  // src/core/bootstrapInitialScroll.ts
@@ -3894,8 +3897,7 @@ function evaluateBootstrapInitialScroll(ctx) {
3894
3897
  bootstrapInitialScroll.targetIndexSeed = void 0;
3895
3898
  }
3896
3899
  const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
3897
- const mountedBufferedIndices = getMountedBufferedIndices(state);
3898
- const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
3900
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
3899
3901
  const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
3900
3902
  const { data } = state.props;
3901
3903
  const visibleIndices = getBootstrapRevealVisibleIndices({
@@ -4471,7 +4473,14 @@ function updateSnapToOffsets(ctx) {
4471
4473
  }
4472
4474
 
4473
4475
  // src/core/updateItemPositions.ts
4474
- function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP, optimizeForVisibleWindow = false } = {
4476
+ function updateItemPositions(ctx, dataChanged, {
4477
+ doMVCP,
4478
+ forceFullUpdate = false,
4479
+ optimizeForVisibleWindow = false,
4480
+ scrollBottomBuffered,
4481
+ scrollVelocity,
4482
+ startIndex
4483
+ } = {
4475
4484
  doMVCP: false,
4476
4485
  forceFullUpdate: false,
4477
4486
  optimizeForVisibleWindow: false,
@@ -4498,7 +4507,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
4498
4507
  const extraData = peek$(ctx, "extraData");
4499
4508
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
4500
4509
  const lastScrollDelta = state.lastScrollDelta;
4501
- const velocity = getScrollVelocity(state);
4510
+ const velocity = scrollVelocity != null ? scrollVelocity : getScrollVelocity(state);
4502
4511
  const shouldOptimize = !forceFullUpdate && !dataChanged && (optimizeForVisibleWindow || Math.abs(velocity) > 0 || state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
4503
4512
  const maxVisibleArea = scrollBottomBuffered + 1e3;
4504
4513
  const useAverageSize = true;
@@ -4678,25 +4687,28 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4678
4687
  const configId = viewabilityConfig.id;
4679
4688
  const viewabilityState = ensureViewabilityState(ctx, configId);
4680
4689
  const { viewableItems: previousViewableItems, start, end, startBuffered, endBuffered } = viewabilityState;
4681
- const viewabilityTokens = /* @__PURE__ */ new Map();
4690
+ let staleViewabilityAmountIds;
4682
4691
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4683
- viewabilityTokens.set(
4692
+ const nextValue = computeViewability(
4693
+ state,
4694
+ ctx,
4695
+ viewabilityConfig,
4684
4696
  containerId,
4685
- computeViewability(
4686
- state,
4687
- ctx,
4688
- viewabilityConfig,
4689
- containerId,
4690
- value.key,
4691
- scrollSize,
4692
- value.item,
4693
- value.index
4694
- )
4697
+ value.key,
4698
+ scrollSize,
4699
+ value.item,
4700
+ value.index
4695
4701
  );
4702
+ if (nextValue.sizeVisible < 0) {
4703
+ staleViewabilityAmountIds != null ? staleViewabilityAmountIds : staleViewabilityAmountIds = [];
4704
+ staleViewabilityAmountIds.push(containerId);
4705
+ }
4696
4706
  }
4697
4707
  const changed = [];
4708
+ const previousViewableKeys = /* @__PURE__ */ new Set();
4698
4709
  if (previousViewableItems) {
4699
4710
  for (const viewToken of previousViewableItems) {
4711
+ previousViewableKeys.add(viewToken.key);
4700
4712
  const containerId = findContainerId(ctx, viewToken.key);
4701
4713
  if (!checkIsViewable(
4702
4714
  state,
@@ -4728,7 +4740,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4728
4740
  key
4729
4741
  };
4730
4742
  viewableItems.push(viewToken);
4731
- if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
4743
+ if (!previousViewableKeys.has(viewToken.key)) {
4732
4744
  changed.push(viewToken);
4733
4745
  }
4734
4746
  }
@@ -4749,20 +4761,17 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4749
4761
  onViewableItemsChanged({ changed, end, endBuffered, start, startBuffered, viewableItems });
4750
4762
  }
4751
4763
  }
4752
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4753
- if (value.sizeVisible < 0) {
4754
- ctx.mapViewabilityAmountValues.delete(containerId);
4764
+ if (staleViewabilityAmountIds) {
4765
+ for (const containerId of staleViewabilityAmountIds) {
4766
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
4767
+ if (value && value.sizeVisible < 0) {
4768
+ ctx.mapViewabilityAmountValues.delete(containerId);
4769
+ }
4755
4770
  }
4756
4771
  }
4757
4772
  }
4758
- function shallowEqual(prev, next) {
4759
- if (!prev) return false;
4760
- const keys = Object.keys(next);
4761
- for (let i = 0; i < keys.length; i++) {
4762
- const k = keys[i];
4763
- if (prev[k] !== next[k]) return false;
4764
- }
4765
- return true;
4773
+ function areViewabilityAmountTokensEqual(prev, next) {
4774
+ 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;
4766
4775
  }
4767
4776
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4768
4777
  const { sizes, scroll: scrollState } = state;
@@ -4787,7 +4796,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4787
4796
  sizeVisible: -1
4788
4797
  };
4789
4798
  const prev2 = ctx.mapViewabilityAmountValues.get(containerId);
4790
- if (!shallowEqual(prev2, value2)) {
4799
+ if (!areViewabilityAmountTokensEqual(prev2, value2)) {
4791
4800
  ctx.mapViewabilityAmountValues.set(containerId, value2);
4792
4801
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4793
4802
  if (cb) {
@@ -4817,7 +4826,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4817
4826
  sizeVisible
4818
4827
  };
4819
4828
  const prev = ctx.mapViewabilityAmountValues.get(containerId);
4820
- if (!shallowEqual(prev, value)) {
4829
+ if (!areViewabilityAmountTokensEqual(prev, value)) {
4821
4830
  ctx.mapViewabilityAmountValues.set(containerId, value);
4822
4831
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4823
4832
  if (cb) {
@@ -4868,126 +4877,152 @@ function getExpandedContainerPoolSize(dataLength, numContainers) {
4868
4877
  }
4869
4878
 
4870
4879
  // src/utils/findAvailableContainers.ts
4871
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4880
+ function findAvailableContainers(ctx, needNewContainers, startBuffered, endBuffered, pendingRemoval, getRequiredItemType, protectedKeys) {
4881
+ const numNeeded = needNewContainers.length;
4882
+ if (numNeeded === 0) {
4883
+ return [];
4884
+ }
4872
4885
  const numContainers = peek$(ctx, "numContainers");
4873
4886
  const state = ctx.state;
4874
4887
  const { stickyContainerPool, containerItemTypes } = state;
4875
4888
  const shouldAvoidAssignedContainerReuse = state.props.recycleItems && !!state.props.positionComponentInternal;
4876
- const result = [];
4877
- const availableContainers = [];
4878
- const pendingRemovalSet = new Set(pendingRemoval);
4889
+ const allocations = [];
4890
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4879
4891
  let pendingRemovalChanged = false;
4892
+ let nextNewContainerIndex = numContainers;
4893
+ const usedContainers = /* @__PURE__ */ new Set();
4894
+ let availableContainers;
4880
4895
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet;
4881
- const stickyHeaderItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyHeaderIndicesSet.has(index))) || [];
4882
4896
  const canReuseContainer = (containerIndex, requiredType) => {
4883
4897
  if (!requiredType) return true;
4884
4898
  const existingType = containerItemTypes.get(containerIndex);
4885
4899
  if (!existingType) return true;
4886
4900
  return existingType === requiredType;
4887
4901
  };
4888
- const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
4889
- let typeIndex = 0;
4890
- for (let i = 0; i < stickyHeaderItemIndices.length; i++) {
4891
- const requiredType = neededTypes[typeIndex];
4892
- let foundContainer = false;
4893
- for (const containerIndex of stickyContainerPool) {
4894
- const key = peek$(ctx, `containerItemKey${containerIndex}`);
4895
- const isPendingRemoval = pendingRemovalSet.has(containerIndex);
4896
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
4897
- result.push(containerIndex);
4898
- if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
4899
- pendingRemovalChanged = true;
4900
- }
4901
- foundContainer = true;
4902
- if (requiredItemTypes) typeIndex++;
4903
- break;
4904
- }
4902
+ const pushAllocation = (itemIndex, itemType, containerIndex) => {
4903
+ allocations.push({
4904
+ containerIndex,
4905
+ itemIndex,
4906
+ itemType
4907
+ });
4908
+ usedContainers.add(containerIndex);
4909
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.delete(containerIndex)) {
4910
+ pendingRemovalChanged = true;
4905
4911
  }
4906
- if (!foundContainer) {
4907
- const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
4908
- result.push(newContainerIndex);
4912
+ };
4913
+ const pushNewContainer = (itemIndex, itemType, isSticky) => {
4914
+ const newContainerIndex = nextNewContainerIndex++;
4915
+ pushAllocation(itemIndex, itemType, newContainerIndex);
4916
+ if (isSticky) {
4909
4917
  stickyContainerPool.add(newContainerIndex);
4910
- if (requiredItemTypes) typeIndex++;
4911
4918
  }
4912
- }
4913
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4914
- if (stickyContainerPool.has(u)) {
4915
- continue;
4916
- }
4917
- const key = peek$(ctx, `containerItemKey${u}`);
4918
- const requiredType = neededTypes[typeIndex];
4919
- const isPending = key !== void 0 && pendingRemovalSet.has(u);
4920
- const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
4921
- if (canUse) {
4922
- if (isPending) {
4923
- pendingRemovalSet.delete(u);
4924
- pendingRemovalChanged = true;
4925
- }
4926
- result.push(u);
4927
- if (requiredItemTypes) {
4928
- typeIndex++;
4929
- }
4919
+ return newContainerIndex;
4920
+ };
4921
+ const canUseContainer = (containerIndex, itemType) => {
4922
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4923
+ return false;
4930
4924
  }
4931
- }
4932
- if (!shouldAvoidAssignedContainerReuse) {
4933
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4934
- if (stickyContainerPool.has(u)) {
4935
- continue;
4936
- }
4937
- const key = peek$(ctx, `containerItemKey${u}`);
4938
- if (key === void 0) continue;
4939
- if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4940
- const index = state.indexByKey.get(key);
4941
- const isOutOfView = index < startBuffered || index > endBuffered;
4942
- if (isOutOfView) {
4943
- const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4944
- if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
4945
- availableContainers.push({ distance, index: u });
4925
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4926
+ const isPending = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4927
+ return (key === void 0 || isPending) && canReuseContainer(containerIndex, itemType);
4928
+ };
4929
+ const findStickyContainer = (itemType) => {
4930
+ let foundContainer;
4931
+ for (const containerIndex of stickyContainerPool) {
4932
+ if (!usedContainers.has(containerIndex)) {
4933
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4934
+ const isPendingRemoval = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4935
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, itemType)) {
4936
+ foundContainer = containerIndex;
4937
+ break;
4946
4938
  }
4947
4939
  }
4948
4940
  }
4949
- }
4950
- const remaining = numNeeded - result.length;
4951
- if (remaining > 0) {
4952
- if (availableContainers.length > 0) {
4953
- if (availableContainers.length > remaining) {
4954
- availableContainers.sort(comparatorByDistance);
4955
- availableContainers.length = remaining;
4941
+ return foundContainer;
4942
+ };
4943
+ const findUnassignedOrPendingContainer = (itemType) => {
4944
+ let foundContainer;
4945
+ for (let containerIndex = 0; containerIndex < numContainers && foundContainer === void 0; containerIndex++) {
4946
+ if (canUseContainer(containerIndex, itemType)) {
4947
+ foundContainer = containerIndex;
4956
4948
  }
4957
- for (const container of availableContainers) {
4958
- result.push(container.index);
4959
- if (requiredItemTypes) {
4960
- typeIndex++;
4949
+ }
4950
+ return foundContainer;
4951
+ };
4952
+ const getAvailableContainers = () => {
4953
+ if (!availableContainers) {
4954
+ availableContainers = [];
4955
+ if (!shouldAvoidAssignedContainerReuse) {
4956
+ for (let containerIndex = 0; containerIndex < numContainers; containerIndex++) {
4957
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4958
+ continue;
4959
+ }
4960
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4961
+ if (key === void 0) continue;
4962
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4963
+ const index = state.indexByKey.get(key);
4964
+ const isOutOfView = index < startBuffered || index > endBuffered;
4965
+ if (isOutOfView) {
4966
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4967
+ availableContainers.push({ distance, index: containerIndex });
4968
+ }
4961
4969
  }
4970
+ availableContainers.sort(comparatorByDistance);
4962
4971
  }
4963
4972
  }
4964
- const stillNeeded = numNeeded - result.length;
4965
- if (stillNeeded > 0) {
4966
- for (let i = 0; i < stillNeeded; i++) {
4967
- result.push(numContainers + i);
4973
+ return availableContainers;
4974
+ };
4975
+ const findAvailableContainer = (itemType) => {
4976
+ const containers = getAvailableContainers();
4977
+ let matchIndex = -1;
4978
+ for (let i = 0; i < containers.length && matchIndex === -1; i++) {
4979
+ const containerIndex = containers[i].index;
4980
+ if (!usedContainers.has(containerIndex) && canReuseContainer(containerIndex, itemType)) {
4981
+ matchIndex = i;
4968
4982
  }
4969
- if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
4970
- console.warn(
4971
- "[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.",
4972
- {
4973
- debugInfo: {
4974
- numContainers,
4975
- numContainersPooled: peek$(ctx, "numContainersPooled"),
4976
- numNeeded,
4977
- stillNeeded
4978
- }
4979
- }
4980
- );
4983
+ }
4984
+ return matchIndex === -1 ? void 0 : containers.splice(matchIndex, 1)[0].index;
4985
+ };
4986
+ for (const itemIndex of needNewContainers) {
4987
+ const itemType = getRequiredItemType == null ? void 0 : getRequiredItemType(itemIndex);
4988
+ const isSticky = stickyHeaderIndicesSet.has(itemIndex);
4989
+ let containerIndex;
4990
+ if (isSticky) {
4991
+ containerIndex = findStickyContainer(itemType);
4992
+ } else {
4993
+ containerIndex = findUnassignedOrPendingContainer(itemType);
4994
+ if (containerIndex === void 0) {
4995
+ containerIndex = findAvailableContainer(itemType);
4981
4996
  }
4982
4997
  }
4998
+ if (containerIndex !== void 0) {
4999
+ pushAllocation(itemIndex, itemType, containerIndex);
5000
+ } else {
5001
+ pushNewContainer(itemIndex, itemType, isSticky);
5002
+ }
4983
5003
  }
4984
5004
  if (pendingRemovalChanged) {
4985
5005
  pendingRemoval.length = 0;
4986
- for (const value of pendingRemovalSet) {
4987
- pendingRemoval.push(value);
5006
+ if (pendingRemovalSet) {
5007
+ for (const value of pendingRemovalSet) {
5008
+ pendingRemoval.push(value);
5009
+ }
4988
5010
  }
4989
5011
  }
4990
- return result.sort(comparatorDefault);
5012
+ if (IS_DEV && nextNewContainerIndex > peek$(ctx, "numContainersPooled")) {
5013
+ console.warn(
5014
+ "[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.",
5015
+ {
5016
+ debugInfo: {
5017
+ numContainers,
5018
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
5019
+ numNeeded,
5020
+ stillNeeded: nextNewContainerIndex - numContainers
5021
+ }
5022
+ }
5023
+ );
5024
+ }
5025
+ return allocations;
4991
5026
  }
4992
5027
  function comparatorByDistance(a, b) {
4993
5028
  return b.distance - a.distance;
@@ -5013,21 +5048,28 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
5013
5048
  }
5014
5049
  return -1;
5015
5050
  }
5016
- function getActiveStickyIndices(ctx, stickyHeaderIndices) {
5051
+ function isStickyIndexActive(ctx, targetIndex) {
5017
5052
  const state = ctx.state;
5018
- return new Set(
5019
- 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))
5020
- );
5053
+ let isActive = false;
5054
+ for (const containerIndex of state.stickyContainerPool) {
5055
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
5056
+ const itemIndex = key ? state.indexByKey.get(key) : void 0;
5057
+ if (itemIndex === targetIndex) {
5058
+ isActive = true;
5059
+ break;
5060
+ }
5061
+ }
5062
+ return isActive;
5021
5063
  }
5022
- function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
5064
+ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
5023
5065
  var _a3;
5024
5066
  const state = ctx.state;
5025
- const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
5026
5067
  set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
5027
5068
  for (let offset = 0; offset <= 1; offset++) {
5028
5069
  const idx = currentStickyIdx - offset;
5029
- if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
5070
+ if (idx < 0) continue;
5030
5071
  const stickyIndex = stickyArray[idx];
5072
+ if (isStickyIndexActive(ctx, stickyIndex)) continue;
5031
5073
  const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
5032
5074
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered) && !needNewContainersSet.has(stickyIndex)) {
5033
5075
  needNewContainersSet.add(stickyIndex);
@@ -5069,10 +5111,86 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5069
5111
  }
5070
5112
  }
5071
5113
  }
5114
+ function trackVisibleRange(range, i, top, size, scroll, scrollBottom) {
5115
+ let didPassVisibleEnd = false;
5116
+ if (range.startNoBuffer === null && top + size > scroll) {
5117
+ range.startNoBuffer = i;
5118
+ }
5119
+ if (range.firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
5120
+ range.firstFullyOnScreenIndex = i;
5121
+ }
5122
+ if (range.startNoBuffer !== null) {
5123
+ if (top <= scrollBottom) {
5124
+ range.endNoBuffer = i;
5125
+ } else {
5126
+ didPassVisibleEnd = true;
5127
+ }
5128
+ }
5129
+ return didPassVisibleEnd;
5130
+ }
5131
+ function getIdsInVisibleRange(state, range) {
5132
+ var _a3, _b;
5133
+ const idsInView = [];
5134
+ const firstVisibleAnchorIndex = (_a3 = range.firstFullyOnScreenIndex) != null ? _a3 : range.startNoBuffer;
5135
+ if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && range.endNoBuffer !== null) {
5136
+ for (let i = firstVisibleAnchorIndex; i <= range.endNoBuffer; i++) {
5137
+ const id = (_b = state.idCache[i]) != null ? _b : getId(state, i);
5138
+ idsInView.push(id);
5139
+ }
5140
+ }
5141
+ return idsInView;
5142
+ }
5143
+ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
5144
+ var _a3, _b;
5145
+ const state = ctx.state;
5146
+ const {
5147
+ endBuffered,
5148
+ idCache,
5149
+ positions,
5150
+ props: { data },
5151
+ sizes,
5152
+ startBuffered
5153
+ } = state;
5154
+ if (startBuffered === null || endBuffered === null || startBuffered < 0 || endBuffered < startBuffered) {
5155
+ return;
5156
+ }
5157
+ const visibleRange = {
5158
+ endNoBuffer: null,
5159
+ firstFullyOnScreenIndex: void 0,
5160
+ startNoBuffer: null
5161
+ };
5162
+ for (let i = startBuffered; i <= endBuffered && i < data.length; i++) {
5163
+ const id = (_a3 = idCache[i]) != null ? _a3 : getId(state, i);
5164
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(ctx, id, i, data[i]);
5165
+ const top = positions[i];
5166
+ const didPassVisibleEnd = trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
5167
+ if (didPassVisibleEnd) {
5168
+ break;
5169
+ }
5170
+ }
5171
+ Object.assign(state, {
5172
+ endNoBuffer: visibleRange.endNoBuffer,
5173
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
5174
+ idsInView: getIdsInVisibleRange(state, visibleRange),
5175
+ startNoBuffer: visibleRange.startNoBuffer
5176
+ });
5177
+ if (visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
5178
+ updateViewableItems(
5179
+ state,
5180
+ ctx,
5181
+ viewabilityConfigCallbackPairs,
5182
+ scrollLength,
5183
+ visibleRange.startNoBuffer,
5184
+ visibleRange.endNoBuffer,
5185
+ startBuffered,
5186
+ endBuffered
5187
+ );
5188
+ }
5189
+ }
5072
5190
  function calculateItemsInView(ctx, params = {}) {
5073
5191
  const state = ctx.state;
5074
5192
  batchedUpdates(() => {
5075
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5193
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
5076
5194
  const {
5077
5195
  columns,
5078
5196
  containerItemKeys,
@@ -5173,6 +5291,15 @@ function calculateItemsInView(ctx, params = {}) {
5173
5291
  state.scrollForNextCalculateItemsInView = void 0;
5174
5292
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
5175
5293
  if (!isInMVCPActiveMode(state)) {
5294
+ if (viewabilityConfigCallbackPairs) {
5295
+ updateViewabilityForCachedRange(
5296
+ ctx,
5297
+ viewabilityConfigCallbackPairs,
5298
+ scrollLength,
5299
+ scroll,
5300
+ scrollBottom
5301
+ );
5302
+ }
5176
5303
  finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
5177
5304
  return;
5178
5305
  }
@@ -5189,6 +5316,7 @@ function calculateItemsInView(ctx, params = {}) {
5189
5316
  forceFullUpdate: !!forceFullItemPositions,
5190
5317
  optimizeForVisibleWindow,
5191
5318
  scrollBottomBuffered,
5319
+ scrollVelocity: speed,
5192
5320
  startIndex
5193
5321
  });
5194
5322
  totalSize = getContentSize(ctx);
@@ -5214,10 +5342,8 @@ function calculateItemsInView(ctx, params = {}) {
5214
5342
  updateScroll2(state.scroll);
5215
5343
  updateScrollRange();
5216
5344
  }
5217
- let startNoBuffer = null;
5218
5345
  let startBuffered = null;
5219
5346
  let startBufferedId = null;
5220
- let endNoBuffer = null;
5221
5347
  let endBuffered = null;
5222
5348
  let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
5223
5349
  for (let i = loopStart; i >= 0; i--) {
@@ -5251,19 +5377,18 @@ function calculateItemsInView(ctx, params = {}) {
5251
5377
  maxIndexRendered = Math.max(maxIndexRendered, index);
5252
5378
  }
5253
5379
  }
5254
- let firstFullyOnScreenIndex;
5380
+ const visibleRange = {
5381
+ endNoBuffer: null,
5382
+ firstFullyOnScreenIndex: void 0,
5383
+ startNoBuffer: null
5384
+ };
5255
5385
  const dataLength = data.length;
5256
5386
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
5257
5387
  const id = (_i = idCache[i]) != null ? _i : getId(state, i);
5258
5388
  const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
5259
5389
  const top = positions[i];
5260
5390
  if (!foundEnd) {
5261
- if (startNoBuffer === null && top + size > scroll) {
5262
- startNoBuffer = i;
5263
- }
5264
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
5265
- firstFullyOnScreenIndex = i;
5266
- }
5391
+ trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
5267
5392
  if (startBuffered === null && top + size > scrollTopBuffered) {
5268
5393
  startBuffered = i;
5269
5394
  startBufferedId = id;
@@ -5273,10 +5398,7 @@ function calculateItemsInView(ctx, params = {}) {
5273
5398
  nextTop = top;
5274
5399
  }
5275
5400
  }
5276
- if (startNoBuffer !== null) {
5277
- if (top <= scrollBottom) {
5278
- endNoBuffer = i;
5279
- }
5401
+ if (visibleRange.startNoBuffer !== null) {
5280
5402
  if (top <= scrollBottomBuffered) {
5281
5403
  endBuffered = i;
5282
5404
  if (scrollBottomBuffered > totalSize) {
@@ -5290,22 +5412,14 @@ function calculateItemsInView(ctx, params = {}) {
5290
5412
  }
5291
5413
  }
5292
5414
  }
5293
- const idsInView = [];
5294
- const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
5295
- if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
5296
- for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
5297
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5298
- idsInView.push(id);
5299
- }
5300
- }
5301
5415
  Object.assign(state, {
5302
5416
  endBuffered,
5303
- endNoBuffer,
5304
- firstFullyOnScreenIndex,
5305
- idsInView,
5417
+ endNoBuffer: visibleRange.endNoBuffer,
5418
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
5419
+ idsInView: getIdsInVisibleRange(state, visibleRange),
5306
5420
  startBuffered,
5307
5421
  startBufferedId,
5308
- startNoBuffer
5422
+ startNoBuffer: visibleRange.startNoBuffer
5309
5423
  });
5310
5424
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
5311
5425
  state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
@@ -5327,7 +5441,7 @@ function calculateItemsInView(ctx, params = {}) {
5327
5441
  const needNewContainers = [];
5328
5442
  const needNewContainersSet = /* @__PURE__ */ new Set();
5329
5443
  for (let i = startBuffered; i <= endBuffered; i++) {
5330
- const id = (_l = idCache[i]) != null ? _l : getId(state, i);
5444
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5331
5445
  if (!containerItemKeys.has(id)) {
5332
5446
  needNewContainersSet.add(i);
5333
5447
  needNewContainers.push(i);
@@ -5336,7 +5450,7 @@ function calculateItemsInView(ctx, params = {}) {
5336
5450
  if (alwaysRenderArr.length > 0) {
5337
5451
  for (const index of alwaysRenderArr) {
5338
5452
  if (index < 0 || index >= dataLength) continue;
5339
- const id = (_m = idCache[index]) != null ? _m : getId(state, index);
5453
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
5340
5454
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
5341
5455
  needNewContainersSet.add(index);
5342
5456
  needNewContainers.push(index);
@@ -5346,7 +5460,6 @@ function calculateItemsInView(ctx, params = {}) {
5346
5460
  if (stickyHeaderIndicesArr.length > 0) {
5347
5461
  handleStickyActivation(
5348
5462
  ctx,
5349
- stickyHeaderIndicesSet,
5350
5463
  stickyHeaderIndicesArr,
5351
5464
  currentStickyIdx,
5352
5465
  needNewContainers,
@@ -5358,35 +5471,34 @@ function calculateItemsInView(ctx, params = {}) {
5358
5471
  set$(ctx, "activeStickyIndex", -1);
5359
5472
  }
5360
5473
  if (needNewContainers.length > 0) {
5361
- const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
5474
+ const getRequiredItemType = getItemType ? (i) => {
5362
5475
  const itemType = getItemType(data[i], i);
5363
5476
  return itemType !== void 0 ? String(itemType) : "";
5364
- }) : void 0;
5365
- const availableContainers = findAvailableContainers(
5477
+ } : void 0;
5478
+ const availableContainerAllocations = findAvailableContainers(
5366
5479
  ctx,
5367
- needNewContainers.length,
5480
+ needNewContainers,
5368
5481
  startBuffered,
5369
5482
  endBuffered,
5370
5483
  pendingRemoval,
5371
- requiredItemTypes,
5372
- needNewContainers,
5484
+ getRequiredItemType,
5373
5485
  protectedContainerKeys
5374
5486
  );
5375
- for (let idx = 0; idx < needNewContainers.length; idx++) {
5376
- const i = needNewContainers[idx];
5377
- const containerIndex = availableContainers[idx];
5378
- const id = (_n = idCache[i]) != null ? _n : getId(state, i);
5487
+ for (const allocation of availableContainerAllocations) {
5488
+ const i = allocation.itemIndex;
5489
+ const containerIndex = allocation.containerIndex;
5490
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
5379
5491
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
5380
5492
  if (oldKey && oldKey !== id) {
5381
5493
  containerItemKeys.delete(oldKey);
5382
5494
  }
5383
5495
  set$(ctx, `containerItemKey${containerIndex}`, id);
5384
5496
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
5385
- if (requiredItemTypes) {
5386
- state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5497
+ if (allocation.itemType !== void 0) {
5498
+ state.containerItemTypes.set(containerIndex, allocation.itemType);
5387
5499
  }
5388
5500
  containerItemKeys.set(id, containerIndex);
5389
- (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5501
+ (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
5390
5502
  const containerSticky = `containerSticky${containerIndex}`;
5391
5503
  const isSticky = stickyHeaderIndicesSet.has(i);
5392
5504
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5424,7 +5536,7 @@ function calculateItemsInView(ctx, params = {}) {
5424
5536
  if (alwaysRenderArr.length > 0) {
5425
5537
  for (const index of alwaysRenderArr) {
5426
5538
  if (index < 0 || index >= dataLength) continue;
5427
- const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5539
+ const id = (_o = idCache[index]) != null ? _o : getId(state, index);
5428
5540
  const containerIndex = containerItemKeys.get(id);
5429
5541
  if (containerIndex !== void 0) {
5430
5542
  state.stickyContainerPool.add(containerIndex);
@@ -5443,10 +5555,11 @@ function calculateItemsInView(ctx, params = {}) {
5443
5555
  alwaysRenderSet
5444
5556
  );
5445
5557
  }
5558
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
5446
5559
  let didChangePositions = false;
5447
5560
  for (let i = 0; i < numContainers; i++) {
5448
5561
  const itemKey = peek$(ctx, `containerItemKey${i}`);
5449
- if (pendingRemoval.includes(i)) {
5562
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(i)) {
5450
5563
  if (itemKey !== void 0) {
5451
5564
  containerItemKeys.delete(itemKey);
5452
5565
  }
@@ -5477,24 +5590,24 @@ function calculateItemsInView(ctx, params = {}) {
5477
5590
  evaluateBootstrapInitialScroll(ctx);
5478
5591
  return;
5479
5592
  }
5480
- const mountedBufferedIndices = getMountedBufferedIndices(state);
5481
- const mountedNoBufferIndices = getMountedNoBufferIndices(state);
5482
- const readinessIndices = hasActiveInitialScroll(state) ? mountedBufferedIndices : mountedNoBufferIndices.length > 0 ? mountedNoBufferIndices : mountedBufferedIndices;
5483
- if (!queuedInitialLayout && readinessIndices.length > 0 && checkAllSizesKnown(state, readinessIndices)) {
5484
- setDidLayout(ctx);
5485
- handleInitialScrollLayoutReady(ctx);
5593
+ if (!queuedInitialLayout && !state.didContainersLayout) {
5594
+ const isInitialLayoutReady = hasActiveInitialScroll(state) ? checkAllSizesKnown(state, state.startBuffered, state.endBuffered) : checkAllSizesKnown(state, state.startNoBuffer, state.endNoBuffer) || checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
5595
+ if (isInitialLayoutReady) {
5596
+ setDidLayout(ctx);
5597
+ handleInitialScrollLayoutReady(ctx);
5598
+ }
5486
5599
  }
5487
- if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
5600
+ if (viewabilityConfigCallbackPairs && visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
5488
5601
  if (!didMVCPAdjustScroll) {
5489
5602
  updateViewableItems(
5490
5603
  ctx.state,
5491
5604
  ctx,
5492
5605
  viewabilityConfigCallbackPairs,
5493
5606
  scrollLength,
5494
- startNoBuffer,
5495
- endNoBuffer,
5496
- startBuffered != null ? startBuffered : startNoBuffer,
5497
- endBuffered != null ? endBuffered : endNoBuffer
5607
+ visibleRange.startNoBuffer,
5608
+ visibleRange.endNoBuffer,
5609
+ startBuffered != null ? startBuffered : visibleRange.startNoBuffer,
5610
+ endBuffered != null ? endBuffered : visibleRange.endNoBuffer
5498
5611
  );
5499
5612
  }
5500
5613
  }
@@ -5953,6 +6066,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5953
6066
  } = state;
5954
6067
  if (!data) return;
5955
6068
  const index = state.indexByKey.get(itemKey);
6069
+ let resolvedMeasurementItem;
5956
6070
  if (getFixedItemSize) {
5957
6071
  if (index === void 0) {
5958
6072
  return;
@@ -5963,6 +6077,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5963
6077
  }
5964
6078
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5965
6079
  const size2 = getFixedItemSize(itemData, index, type);
6080
+ resolvedMeasurementItem = {
6081
+ didResolveFixedItemSize: true,
6082
+ fixedItemSize: size2,
6083
+ itemData,
6084
+ itemType: type
6085
+ };
5966
6086
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
5967
6087
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5968
6088
  return;
@@ -5972,7 +6092,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5972
6092
  let shouldMaintainScrollAtEnd = false;
5973
6093
  let minIndexSizeChanged;
5974
6094
  const prevSizeKnown = state.sizesKnown.get(itemKey);
5975
- const diff = updateOneItemSize(ctx, itemKey, sizeObj);
6095
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem);
5976
6096
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
5977
6097
  if (diff !== 0) {
5978
6098
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -5997,7 +6117,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5997
6117
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
5998
6118
  }
5999
6119
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
6000
- if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
6120
+ if (didContainersLayout || checkAllSizesKnown(state, state.startBuffered, state.endBuffered)) {
6001
6121
  if (needsRecalculate) {
6002
6122
  state.scrollForNextCalculateItemsInView = void 0;
6003
6123
  runOrScheduleMVCPRecalculate(ctx);
@@ -6011,8 +6131,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
6011
6131
  }
6012
6132
  }
6013
6133
  }
6014
- function updateOneItemSize(ctx, itemKey, sizeObj) {
6015
- var _a3, _b;
6134
+ function updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem) {
6135
+ var _a3, _b, _c;
6016
6136
  const state = ctx.state;
6017
6137
  const {
6018
6138
  indexByKey,
@@ -6022,20 +6142,25 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
6022
6142
  } = state;
6023
6143
  if (!data) return 0;
6024
6144
  const index = indexByKey.get(itemKey);
6025
- const itemData = data[index];
6026
- let itemType;
6027
- let fixedItemSize;
6028
- if (getFixedItemSize) {
6029
- itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
6145
+ const itemData = (_a3 = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemData) != null ? _a3 : data[index];
6146
+ let itemType = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemType;
6147
+ let fixedItemSize = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.fixedItemSize;
6148
+ if (getFixedItemSize && !(resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize)) {
6149
+ itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
6030
6150
  fixedItemSize = getFixedItemSize(itemData, index, itemType);
6031
6151
  }
6032
- const prevSize = getItemSize(ctx, itemKey, index, itemData);
6152
+ const resolvedItemSize = (resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize) || itemType !== void 0 || fixedItemSize !== void 0 ? {
6153
+ didResolveFixedItemSize: resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize,
6154
+ fixedItemSize,
6155
+ itemType
6156
+ } : void 0;
6157
+ const prevSize = getItemSize(ctx, itemKey, index, itemData, void 0, void 0, void 0, resolvedItemSize);
6033
6158
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
6034
6159
  const prevSizeKnown = sizesKnown.get(itemKey);
6035
6160
  const size = Math.round(rawSize) ;
6036
6161
  sizesKnown.set(itemKey, size);
6037
6162
  if (fixedItemSize === void 0 && size > 0) {
6038
- itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
6163
+ itemType != null ? itemType : itemType = getItemType ? (_c = getItemType(itemData, index)) != null ? _c : "" : "";
6039
6164
  let averages = averageSizes[itemType];
6040
6165
  if (!averages) {
6041
6166
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6137,6 +6262,11 @@ function getAverageItemSizes(state) {
6137
6262
  }
6138
6263
  return averageItemSizes;
6139
6264
  }
6265
+ function triggerMountedContainerLayouts(ctx) {
6266
+ for (const triggerLayout of ctx.containerLayoutTriggers.values()) {
6267
+ triggerLayout();
6268
+ }
6269
+ }
6140
6270
  function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6141
6271
  const state = ctx.state;
6142
6272
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
@@ -6262,6 +6392,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6262
6392
  state.columns.length = 0;
6263
6393
  state.columnSpans.length = 0;
6264
6394
  }
6395
+ triggerMountedContainerLayouts(ctx);
6265
6396
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
6266
6397
  };
6267
6398
  return {
@@ -7064,7 +7195,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7064
7195
  viewabilityConfigCallbackPairs
7065
7196
  });
7066
7197
  state.viewabilityConfigCallbackPairs = viewability;
7067
- state.enableScrollForNextCalculateItemsInView = !viewability;
7198
+ state.enableScrollForNextCalculateItemsInView = true;
7068
7199
  if (viewability) {
7069
7200
  state.scrollForNextCalculateItemsInView = void 0;
7070
7201
  }