@legendapp/list 3.3.6 → 3.3.8

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
@@ -380,6 +380,7 @@ var IsNewArchitecture = f !== void 0 && f != null;
380
380
  // src/core/containerItemMetadata.ts
381
381
  function createContainerItemMetadata(state, itemIndex, itemData, itemType) {
382
382
  return {
383
+ data: state.props.data,
383
384
  dataChangeEpoch: state.dataChangeEpoch,
384
385
  getFixedItemSize: state.props.getFixedItemSize,
385
386
  getItemType: state.props.getItemType,
@@ -388,25 +389,29 @@ function createContainerItemMetadata(state, itemIndex, itemData, itemType) {
388
389
  itemType
389
390
  };
390
391
  }
391
- function resolveContainerItemMetadata(state, containerId, itemIndex, itemData) {
392
- var _a3, _b;
393
- const { getFixedItemSize, getItemType } = state.props;
392
+ function updateContainerItemMetadata(state, containerId, itemIndex, itemData, itemType) {
393
+ var _a3;
394
+ const { getItemType } = state.props;
394
395
  const previousMetadata = state.containerItemMetadata.get(containerId);
395
- let metadata;
396
396
  if ((previousMetadata == null ? void 0 : previousMetadata.dataChangeEpoch) === state.dataChangeEpoch && previousMetadata.getItemType === getItemType && previousMetadata.itemData === itemData && previousMetadata.itemIndex === itemIndex) {
397
- metadata = previousMetadata;
398
- } else {
399
- const itemType = getItemType ? (_a3 = getItemType(itemData, itemIndex)) != null ? _a3 : "" : void 0;
400
- metadata = createContainerItemMetadata(state, itemIndex, itemData, itemType);
401
- state.containerItemMetadata.set(containerId, metadata);
397
+ return previousMetadata;
402
398
  }
399
+ const resolvedItemType = getItemType ? (_a3 = getItemType(itemData, itemIndex)) != null ? _a3 : "" : void 0;
400
+ const metadata = createContainerItemMetadata(state, itemIndex, itemData, resolvedItemType);
401
+ state.containerItemMetadata.set(containerId, metadata);
402
+ return metadata;
403
+ }
404
+ function resolveContainerItemMetadata(state, containerId, itemIndex, itemData) {
405
+ var _a3;
406
+ const { getFixedItemSize } = state.props;
407
+ const metadata = updateContainerItemMetadata(state, containerId, itemIndex, itemData);
403
408
  if (metadata.getFixedItemSize !== getFixedItemSize) {
404
409
  metadata.didResolveFixedItemSize = false;
405
410
  metadata.fixedItemSize = void 0;
406
411
  metadata.getFixedItemSize = getFixedItemSize;
407
412
  }
408
413
  if (getFixedItemSize && !metadata.didResolveFixedItemSize) {
409
- metadata.fixedItemSize = getFixedItemSize(itemData, itemIndex, (_b = metadata.itemType) != null ? _b : "");
414
+ metadata.fixedItemSize = getFixedItemSize(itemData, itemIndex, (_a3 = metadata.itemType) != null ? _a3 : "");
410
415
  metadata.didResolveFixedItemSize = true;
411
416
  }
412
417
  return metadata;
@@ -3273,6 +3278,7 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3273
3278
  return { didChangePosition: false, didRefreshData: false };
3274
3279
  }
3275
3280
  const itemKey = (_a3 = state.idCache[itemIndex]) != null ? _a3 : getId(state, itemIndex);
3281
+ const metadata = updateContainerItemMetadata(state, containerIndex, itemIndex, item);
3276
3282
  const updateLayout = (_b = options == null ? void 0 : options.updateLayout) != null ? _b : true;
3277
3283
  let didChangePosition = false;
3278
3284
  let didRefreshData = false;
@@ -3283,7 +3289,7 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3283
3289
  return { didChangePosition: false, didRefreshData: false };
3284
3290
  }
3285
3291
  const logicalPosition = (positionValue || 0) - ((_c = options == null ? void 0 : options.scrollAdjustPending) != null ? _c : 0);
3286
- const itemSize = (_d = state.sizes.get(itemKey)) != null ? _d : getItemSize(ctx, itemKey, itemIndex, item);
3292
+ const itemSize = (_d = state.sizes.get(itemKey)) != null ? _d : getItemSize(ctx, itemKey, itemIndex, item, void 0, void 0, void 0, metadata);
3287
3293
  const position = toPhysicalHorizontalItemPosition(state, logicalPosition, itemSize, peek$(ctx, "totalSize"));
3288
3294
  const column = columns[itemIndex] || 1;
3289
3295
  const span = columnSpans[itemIndex] || 1;
@@ -4569,18 +4575,22 @@ function calculateItemsInView(ctx, params = {}) {
4569
4575
  if (oldKey && oldKey !== id) {
4570
4576
  containerItemKeys.delete(oldKey);
4571
4577
  }
4578
+ state.containerItemMetadata.set(
4579
+ containerIndex,
4580
+ createContainerItemMetadata(state, i, data[i], allocation.itemType)
4581
+ );
4572
4582
  if (oldKey !== id) {
4573
4583
  changedContainerIds != null ? changedContainerIds : changedContainerIds = /* @__PURE__ */ new Set();
4574
4584
  changedContainerIds.add(containerIndex);
4575
4585
  state.containerItemGenerations[containerIndex] = ((_p = state.containerItemGenerations[containerIndex]) != null ? _p : 0) + 1;
4586
+ if (state.props.hideItemsUntilMeasured) {
4587
+ const isLayoutReady = state.sizesKnown.has(id) || resolveContainerItemMetadata(state, containerIndex, i, data[i]).fixedItemSize !== void 0;
4588
+ set$(ctx, `containerLayoutReady${containerIndex}`, isLayoutReady);
4589
+ }
4576
4590
  }
4577
4591
  set$(ctx, `containerItemKey${containerIndex}`, id);
4578
4592
  set$(ctx, `containerItemIndex${containerIndex}`, i);
4579
4593
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
4580
- state.containerItemMetadata.set(
4581
- containerIndex,
4582
- createContainerItemMetadata(state, i, data[i], allocation.itemType)
4583
- );
4584
4594
  containerItemKeys.set(id, containerIndex);
4585
4595
  (_q = state.userScrollAnchorReset) == null ? void 0 : _q.keys.add(id);
4586
4596
  const containerSticky = `containerSticky${containerIndex}`;
@@ -5009,24 +5019,39 @@ function resolveSkippedAnchorReset(ctx, itemKey) {
5009
5019
  state.userScrollAnchorReset = void 0;
5010
5020
  }
5011
5021
  }
5022
+ function revealMeasuredGeneration(ctx, containerId, itemKey, generation) {
5023
+ var _a3;
5024
+ if (!ctx.state.props.hideItemsUntilMeasured) {
5025
+ return;
5026
+ }
5027
+ const isCurrentGeneration = ((_a3 = ctx.state.containerItemGenerations[containerId]) != null ? _a3 : 0) === generation;
5028
+ const isCurrentAssignment = peek$(ctx, `containerItemKey${containerId}`) === itemKey;
5029
+ if (isCurrentGeneration && isCurrentAssignment) {
5030
+ set$(ctx, `containerLayoutReady${containerId}`, true);
5031
+ }
5032
+ }
5012
5033
  function measureContainersInLayoutEffect(ctx, targetContainerIds = null) {
5013
- var _a3, _b, _c;
5034
+ var _a3, _b;
5014
5035
  const state = ctx.state;
5015
5036
  const measurements = [];
5037
+ const measuredGenerations = state.props.hideItemsUntilMeasured ? [] : void 0;
5016
5038
  let isCollectingSynchronousMeasurements = true;
5017
5039
  const containerIds = targetContainerIds != null ? targetContainerIds : ctx.viewRefs.keys();
5018
5040
  for (const containerId of containerIds) {
5019
- const viewRef = ctx.viewRefs.get(containerId);
5041
+ const view = (_a3 = ctx.viewRefs.get(containerId)) == null ? void 0 : _a3.current;
5020
5042
  const itemKey = peek$(ctx, `containerItemKey${containerId}`);
5021
5043
  if (itemKey !== void 0) {
5022
- const generation = ((_a3 = state.containerItemGenerations[containerId]) != null ? _a3 : 0) + 1;
5044
+ const generation = ((_b = state.containerItemGenerations[containerId]) != null ? _b : 0) + 1;
5023
5045
  state.containerItemGenerations[containerId] = generation;
5024
5046
  const fixedItemSize = resolveFixedItemSize(ctx, containerId, itemKey);
5025
5047
  const canSkipMeasurement = !state.needsOtherAxisSize && fixedItemSize !== void 0 && state.sizesKnown.get(itemKey) === fixedItemSize + ctx.scrollAxisGap;
5026
5048
  if (canSkipMeasurement) {
5027
5049
  resolveSkippedAnchorReset(ctx, itemKey);
5028
- } else if (viewRef) {
5029
- (_c = (_b = viewRef.current) == null ? void 0 : _b.measure) == null ? void 0 : _c.call(_b, (_x, _y, width, height) => {
5050
+ if (measuredGenerations) {
5051
+ revealMeasuredGeneration(ctx, containerId, itemKey, generation);
5052
+ }
5053
+ } else if (view == null ? void 0 : view.measure) {
5054
+ view.measure((_x, _y, width, height) => {
5030
5055
  var _a4;
5031
5056
  const isCurrentGeneration = ((_a4 = ctx.state.containerItemGenerations[containerId]) != null ? _a4 : 0) === generation;
5032
5057
  if (isCurrentGeneration) {
@@ -5037,17 +5062,28 @@ function measureContainersInLayoutEffect(ctx, targetContainerIds = null) {
5037
5062
  };
5038
5063
  if (isCollectingSynchronousMeasurements) {
5039
5064
  measurements.push(measurement);
5065
+ measuredGenerations == null ? void 0 : measuredGenerations.push({ containerId, generation, itemKey });
5040
5066
  } else {
5041
5067
  updateItemSizes(ctx, measurement);
5068
+ if (measuredGenerations) {
5069
+ revealMeasuredGeneration(ctx, containerId, itemKey, generation);
5070
+ }
5042
5071
  }
5043
5072
  }
5044
5073
  });
5074
+ } else if (measuredGenerations) {
5075
+ revealMeasuredGeneration(ctx, containerId, itemKey, generation);
5045
5076
  }
5046
5077
  }
5047
5078
  }
5048
5079
  isCollectingSynchronousMeasurements = false;
5049
5080
  if (measurements.length > 0) {
5050
5081
  updateItemSizesBatch(ctx, measurements);
5082
+ if (measuredGenerations) {
5083
+ for (const { containerId, generation, itemKey } of measuredGenerations) {
5084
+ revealMeasuredGeneration(ctx, containerId, itemKey, generation);
5085
+ }
5086
+ }
5051
5087
  }
5052
5088
  }
5053
5089
  var typedForwardRef = React2.forwardRef;
@@ -5135,8 +5171,20 @@ var PositionViewState = typedMemo(function PositionViewState2({
5135
5171
  refView,
5136
5172
  ...rest
5137
5173
  }) {
5138
- const [position = POSITION_OUT_OF_VIEW, _itemKey] = useArr$([`containerPosition${id}`, `containerItemKey${id}`]);
5139
- return /* @__PURE__ */ React2.createElement(View$1, { ref: refView, style: [style, horizontal ? { left: position } : { top: position }], ...rest });
5174
+ const [position = POSITION_OUT_OF_VIEW, _itemKey, layoutReady = true] = useArr$([
5175
+ `containerPosition${id}`,
5176
+ `containerItemKey${id}`,
5177
+ `containerLayoutReady${id}`
5178
+ ]);
5179
+ return /* @__PURE__ */ React2.createElement(
5180
+ View$1,
5181
+ {
5182
+ ref: refView,
5183
+ style: [style, horizontal ? { left: position } : { top: position }, !layoutReady && { opacity: 0 }],
5184
+ ...rest,
5185
+ pointerEvents: layoutReady ? void 0 : "none"
5186
+ }
5187
+ );
5140
5188
  });
5141
5189
  var PositionViewAnimated = typedMemo(function PositionViewAnimated2({
5142
5190
  id,
@@ -5723,7 +5771,7 @@ var Container = typedMemo(function Container2({
5723
5771
  ]
5724
5772
  );
5725
5773
  const renderedItemInfo = useMemo(
5726
- () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
5774
+ () => itemKey !== void 0 ? getRenderedItem2(itemKey, id) : null,
5727
5775
  [itemKey, data, extraData]
5728
5776
  );
5729
5777
  const { renderedItem } = renderedItemInfo || {};
@@ -6264,6 +6312,16 @@ function checkStructuralDataChange(state, dataProp, previousData) {
6264
6312
  return false;
6265
6313
  }
6266
6314
 
6315
+ // src/core/containerLayoutReady.ts
6316
+ var CONTAINER_LAYOUT_READY_PREFIX = "containerLayoutReady";
6317
+ function resetContainerLayoutReady(ctx) {
6318
+ for (const signalName of ctx.values.keys()) {
6319
+ if (signalName.startsWith(CONTAINER_LAYOUT_READY_PREFIX)) {
6320
+ set$(ctx, signalName, void 0);
6321
+ }
6322
+ }
6323
+ }
6324
+
6267
6325
  // src/core/doInitialAllocateContainers.ts
6268
6326
  function doInitialAllocateContainers(ctx) {
6269
6327
  var _a3, _b;
@@ -6974,34 +7032,37 @@ function getAlwaysRenderIndices(config, data, keyExtractor, anchoredEndSpaceAnch
6974
7032
  }
6975
7033
 
6976
7034
  // src/utils/getRenderedItem.ts
6977
- function getRenderedItem(ctx, key) {
6978
- var _a3;
7035
+ function getRenderedItem(ctx, key, containerId) {
7036
+ var _a3, _b, _c;
6979
7037
  const state = ctx.state;
6980
7038
  if (!state) {
6981
7039
  return null;
6982
7040
  }
7041
+ const metadata = state.containerItemMetadata.get(containerId);
7042
+ const useAssignedGeneration = metadata && metadata.dataChangeEpoch !== state.dataChangeEpoch;
6983
7043
  const {
6984
7044
  indexByKey,
6985
- props: { data, getItemType, renderItem }
7045
+ props: { data: currentData, getItemType, renderItem }
6986
7046
  } = state;
6987
- const index = indexByKey.get(key);
7047
+ const data = useAssignedGeneration ? metadata.data : currentData;
7048
+ const index = (_a3 = metadata == null ? void 0 : metadata.itemIndex) != null ? _a3 : indexByKey.get(key);
6988
7049
  if (index === void 0) {
6989
7050
  return null;
6990
7051
  }
6991
7052
  let renderedItem = null;
6992
7053
  const extraData = peek$(ctx, "extraData");
6993
- const item = data[index];
7054
+ const item = useAssignedGeneration ? metadata.itemData : data[index];
6994
7055
  if (renderItem && !isNullOrUndefined(item)) {
6995
7056
  const itemProps = {
6996
7057
  data,
6997
7058
  extraData,
6998
7059
  index,
6999
7060
  item,
7000
- type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
7061
+ type: useAssignedGeneration ? (_b = metadata.itemType) != null ? _b : "" : getItemType ? (_c = getItemType(item, index)) != null ? _c : "" : ""
7001
7062
  };
7002
7063
  renderedItem = renderItem(itemProps);
7003
7064
  }
7004
- return { index, item: data[index], renderedItem };
7065
+ return { index, item, renderedItem };
7005
7066
  }
7006
7067
 
7007
7068
  // src/utils/normalizeMaintainScrollAtEnd.ts
@@ -7167,6 +7228,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7167
7228
  initialScrollIndex: initialScrollIndexProp,
7168
7229
  initialScrollOffset: initialScrollOffsetProp,
7169
7230
  experimental_adaptiveRender,
7231
+ experimental_hideItemsUntilMeasured,
7170
7232
  itemsAreEqual,
7171
7233
  keyExtractor: keyExtractorProp,
7172
7234
  ListEmptyComponent,
@@ -7387,6 +7449,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7387
7449
  const state = refState.current;
7388
7450
  const isFirstLocal = state.isFirst;
7389
7451
  const previousAdaptiveRender = state.props.adaptiveRender;
7452
+ const previousHideItemsUntilMeasured = state.props.hideItemsUntilMeasured;
7390
7453
  const previousNumColumnsProp = state.props.numColumns;
7391
7454
  const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
7392
7455
  ctx.scrollAxisGap = nextScrollAxisGap;
@@ -7432,6 +7495,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7432
7495
  estimatedItemSize,
7433
7496
  getFixedItemSize: useWrapIfItem(getFixedItemSize),
7434
7497
  getItemType: useWrapIfItem(getItemType),
7498
+ hideItemsUntilMeasured: experimental_hideItemsUntilMeasured,
7435
7499
  horizontal: !!horizontal,
7436
7500
  itemsAreEqual,
7437
7501
  keyExtractor: useWrapIfItem(keyExtractor),
@@ -7469,6 +7533,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7469
7533
  if (!isFirstLocal && previousAdaptiveRender && !experimental_adaptiveRender) {
7470
7534
  resetAdaptiveRender(ctx);
7471
7535
  }
7536
+ if (!isFirstLocal && previousHideItemsUntilMeasured && !experimental_hideItemsUntilMeasured) {
7537
+ resetContainerLayoutReady(ctx);
7538
+ }
7472
7539
  const memoizedLastItemKeys = useMemo(() => {
7473
7540
  if (!dataProp.length) return [];
7474
7541
  return Array.from(
@@ -7725,7 +7792,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7725
7792
  }, [ctx, usesBootstrapInitialScroll]);
7726
7793
  const fns = useMemo(
7727
7794
  () => ({
7728
- getRenderedItem: (key) => getRenderedItem(ctx, key),
7795
+ getRenderedItem: (key, containerId) => getRenderedItem(ctx, key, containerId),
7729
7796
  onMomentumScrollEnd: (event) => {
7730
7797
  checkFinishedScrollFallback(ctx);
7731
7798
  if (state.props.onMomentumScrollEnd) {
@@ -31,7 +31,7 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
31
31
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
32
32
  }
33
33
 
34
- type ListenerType = "activeStickyIndex" | "alignItemsAtEndPadding" | "anchoredEndSpaceSize" | "containerLayoutEpoch" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "adaptiveRender" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemIndex${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
34
+ type ListenerType = "activeStickyIndex" | "alignItemsAtEndPadding" | "anchoredEndSpaceSize" | "containerLayoutEpoch" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "adaptiveRender" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemIndex${number}` | `containerItemKey${number}` | `containerLayoutReady${number}` | `containerPosition${number}` | `containerSticky${number}`;
35
35
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "adaptiveRender" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
36
36
  type ListenerTypeValueMap = {
37
37
  activeStickyIndex: number;
@@ -70,6 +70,8 @@ type ListenerTypeValueMap = {
70
70
  adaptiveRender: "normal" | "light";
71
71
  } & {
72
72
  [K in ListenerType as K extends `containerItemKey${number}` ? K : never]: string;
73
+ } & {
74
+ [K in ListenerType as K extends `containerLayoutReady${number}` ? K : never]: boolean;
73
75
  } & {
74
76
  [K in ListenerType as K extends `containerItemData${number}` ? K : never]: any;
75
77
  } & {
@@ -371,6 +373,20 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
371
373
  * Configures the adaptive render signal. Items can use this to render a lighter version while scrolling quickly.
372
374
  */
373
375
  experimental_adaptiveRender?: AdaptiveRenderConfig;
376
+ /**
377
+ * Keeps a newly recycled item laid out but invisible until its size has been measured, so it is never painted at
378
+ * the estimated position it was recycled to. Only applies on the new architecture.
379
+ *
380
+ * This trades a possible flash at the wrong position for an extra render and native commit per recycled row, so it
381
+ * is worth enabling only for lists with dynamically sized items whose estimates are visibly wrong. Items with a
382
+ * size from `getFixedItemSize`, or with an already measured size, are exact and render immediately either way.
383
+ *
384
+ * Sticky headers are intentionally excluded. They are painted from a scroll-driven interpolation rather than the
385
+ * committed position, so hiding them would blink a header out mid-scroll without preventing a flash.
386
+ *
387
+ * @default false
388
+ */
389
+ experimental_hideItemsUntilMeasured?: boolean;
374
390
  /**
375
391
  * Function to call when the user pulls to refresh.
376
392
  */
@@ -2952,6 +2952,7 @@ function abortBootstrapInitialScroll(ctx) {
2952
2952
  // src/core/containerItemMetadata.ts
2953
2953
  function createContainerItemMetadata(state, itemIndex, itemData, itemType) {
2954
2954
  return {
2955
+ data: state.props.data,
2955
2956
  dataChangeEpoch: state.dataChangeEpoch,
2956
2957
  getFixedItemSize: state.props.getFixedItemSize,
2957
2958
  getItemType: state.props.getItemType,
@@ -2960,25 +2961,29 @@ function createContainerItemMetadata(state, itemIndex, itemData, itemType) {
2960
2961
  itemType
2961
2962
  };
2962
2963
  }
2963
- function resolveContainerItemMetadata(state, containerId, itemIndex, itemData) {
2964
- var _a3, _b;
2965
- const { getFixedItemSize, getItemType } = state.props;
2964
+ function updateContainerItemMetadata(state, containerId, itemIndex, itemData, itemType) {
2965
+ var _a3;
2966
+ const { getItemType } = state.props;
2966
2967
  const previousMetadata = state.containerItemMetadata.get(containerId);
2967
- let metadata;
2968
2968
  if ((previousMetadata == null ? void 0 : previousMetadata.dataChangeEpoch) === state.dataChangeEpoch && previousMetadata.getItemType === getItemType && previousMetadata.itemData === itemData && previousMetadata.itemIndex === itemIndex) {
2969
- metadata = previousMetadata;
2970
- } else {
2971
- const itemType = getItemType ? (_a3 = getItemType(itemData, itemIndex)) != null ? _a3 : "" : void 0;
2972
- metadata = createContainerItemMetadata(state, itemIndex, itemData, itemType);
2973
- state.containerItemMetadata.set(containerId, metadata);
2969
+ return previousMetadata;
2974
2970
  }
2971
+ const resolvedItemType = getItemType ? (_a3 = getItemType(itemData, itemIndex)) != null ? _a3 : "" : void 0;
2972
+ const metadata = createContainerItemMetadata(state, itemIndex, itemData, resolvedItemType);
2973
+ state.containerItemMetadata.set(containerId, metadata);
2974
+ return metadata;
2975
+ }
2976
+ function resolveContainerItemMetadata(state, containerId, itemIndex, itemData) {
2977
+ var _a3;
2978
+ const { getFixedItemSize } = state.props;
2979
+ const metadata = updateContainerItemMetadata(state, containerId, itemIndex, itemData);
2975
2980
  if (metadata.getFixedItemSize !== getFixedItemSize) {
2976
2981
  metadata.didResolveFixedItemSize = false;
2977
2982
  metadata.fixedItemSize = void 0;
2978
2983
  metadata.getFixedItemSize = getFixedItemSize;
2979
2984
  }
2980
2985
  if (getFixedItemSize && !metadata.didResolveFixedItemSize) {
2981
- metadata.fixedItemSize = getFixedItemSize(itemData, itemIndex, (_b = metadata.itemType) != null ? _b : "");
2986
+ metadata.fixedItemSize = getFixedItemSize(itemData, itemIndex, (_a3 = metadata.itemType) != null ? _a3 : "");
2982
2987
  metadata.didResolveFixedItemSize = true;
2983
2988
  }
2984
2989
  return metadata;
@@ -3323,6 +3328,7 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3323
3328
  return { didChangePosition: false, didRefreshData: false };
3324
3329
  }
3325
3330
  const itemKey = (_a3 = state.idCache[itemIndex]) != null ? _a3 : getId(state, itemIndex);
3331
+ const metadata = updateContainerItemMetadata(state, containerIndex, itemIndex, item);
3326
3332
  const updateLayout = (_b = options == null ? void 0 : options.updateLayout) != null ? _b : true;
3327
3333
  let didChangePosition = false;
3328
3334
  let didRefreshData = false;
@@ -3333,7 +3339,7 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3333
3339
  return { didChangePosition: false, didRefreshData: false };
3334
3340
  }
3335
3341
  const logicalPosition = (positionValue || 0) - ((_c = options == null ? void 0 : options.scrollAdjustPending) != null ? _c : 0);
3336
- const itemSize = (_d = state.sizes.get(itemKey)) != null ? _d : getItemSize(ctx, itemKey, itemIndex, item);
3342
+ const itemSize = (_d = state.sizes.get(itemKey)) != null ? _d : getItemSize(ctx, itemKey, itemIndex, item, void 0, void 0, void 0, metadata);
3337
3343
  const position = toPhysicalHorizontalItemPosition(state, logicalPosition, itemSize, peek$(ctx, "totalSize"));
3338
3344
  const column = columns[itemIndex] || 1;
3339
3345
  const span = columnSpans[itemIndex] || 1;
@@ -4619,18 +4625,22 @@ function calculateItemsInView(ctx, params = {}) {
4619
4625
  if (oldKey && oldKey !== id) {
4620
4626
  containerItemKeys.delete(oldKey);
4621
4627
  }
4628
+ state.containerItemMetadata.set(
4629
+ containerIndex,
4630
+ createContainerItemMetadata(state, i, data[i], allocation.itemType)
4631
+ );
4622
4632
  if (oldKey !== id) {
4623
4633
  changedContainerIds != null ? changedContainerIds : changedContainerIds = /* @__PURE__ */ new Set();
4624
4634
  changedContainerIds.add(containerIndex);
4625
4635
  state.containerItemGenerations[containerIndex] = ((_p = state.containerItemGenerations[containerIndex]) != null ? _p : 0) + 1;
4636
+ if (state.props.hideItemsUntilMeasured) {
4637
+ const isLayoutReady = state.sizesKnown.has(id) || resolveContainerItemMetadata(state, containerIndex, i, data[i]).fixedItemSize !== void 0;
4638
+ set$(ctx, `containerLayoutReady${containerIndex}`, isLayoutReady);
4639
+ }
4626
4640
  }
4627
4641
  set$(ctx, `containerItemKey${containerIndex}`, id);
4628
4642
  set$(ctx, `containerItemIndex${containerIndex}`, i);
4629
4643
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
4630
- state.containerItemMetadata.set(
4631
- containerIndex,
4632
- createContainerItemMetadata(state, i, data[i], allocation.itemType)
4633
- );
4634
4644
  containerItemKeys.set(id, containerIndex);
4635
4645
  (_q = state.userScrollAnchorReset) == null ? void 0 : _q.keys.add(id);
4636
4646
  const containerSticky = `containerSticky${containerIndex}`;
@@ -5693,7 +5703,7 @@ var Container = typedMemo(function Container2({
5693
5703
  ]
5694
5704
  );
5695
5705
  const renderedItemInfo = React3.useMemo(
5696
- () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
5706
+ () => itemKey !== void 0 ? getRenderedItem2(itemKey, id) : null,
5697
5707
  [itemKey, data, extraData]
5698
5708
  );
5699
5709
  const { renderedItem } = renderedItemInfo || {};
@@ -6944,6 +6954,16 @@ function checkStructuralDataChange(state, dataProp, previousData) {
6944
6954
  return false;
6945
6955
  }
6946
6956
 
6957
+ // src/core/containerLayoutReady.ts
6958
+ var CONTAINER_LAYOUT_READY_PREFIX = "containerLayoutReady";
6959
+ function resetContainerLayoutReady(ctx) {
6960
+ for (const signalName of ctx.values.keys()) {
6961
+ if (signalName.startsWith(CONTAINER_LAYOUT_READY_PREFIX)) {
6962
+ set$(ctx, signalName, void 0);
6963
+ }
6964
+ }
6965
+ }
6966
+
6947
6967
  // src/core/doInitialAllocateContainers.ts
6948
6968
  function doInitialAllocateContainers(ctx) {
6949
6969
  var _a3, _b;
@@ -7638,34 +7658,37 @@ function getAlwaysRenderIndices(config, data, keyExtractor, anchoredEndSpaceAnch
7638
7658
  }
7639
7659
 
7640
7660
  // src/utils/getRenderedItem.ts
7641
- function getRenderedItem(ctx, key) {
7642
- var _a3;
7661
+ function getRenderedItem(ctx, key, containerId) {
7662
+ var _a3, _b, _c;
7643
7663
  const state = ctx.state;
7644
7664
  if (!state) {
7645
7665
  return null;
7646
7666
  }
7667
+ const metadata = state.containerItemMetadata.get(containerId);
7668
+ const useAssignedGeneration = metadata && metadata.dataChangeEpoch !== state.dataChangeEpoch;
7647
7669
  const {
7648
7670
  indexByKey,
7649
- props: { data, getItemType, renderItem }
7671
+ props: { data: currentData, getItemType, renderItem }
7650
7672
  } = state;
7651
- const index = indexByKey.get(key);
7673
+ const data = useAssignedGeneration ? metadata.data : currentData;
7674
+ const index = (_a3 = metadata == null ? void 0 : metadata.itemIndex) != null ? _a3 : indexByKey.get(key);
7652
7675
  if (index === void 0) {
7653
7676
  return null;
7654
7677
  }
7655
7678
  let renderedItem = null;
7656
7679
  const extraData = peek$(ctx, "extraData");
7657
- const item = data[index];
7680
+ const item = useAssignedGeneration ? metadata.itemData : data[index];
7658
7681
  if (renderItem && !isNullOrUndefined(item)) {
7659
7682
  const itemProps = {
7660
7683
  data,
7661
7684
  extraData,
7662
7685
  index,
7663
7686
  item,
7664
- type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
7687
+ type: useAssignedGeneration ? (_b = metadata.itemType) != null ? _b : "" : getItemType ? (_c = getItemType(item, index)) != null ? _c : "" : ""
7665
7688
  };
7666
7689
  renderedItem = renderItem(itemProps);
7667
7690
  }
7668
- return { index, item: data[index], renderedItem };
7691
+ return { index, item, renderedItem };
7669
7692
  }
7670
7693
 
7671
7694
  // src/utils/normalizeMaintainScrollAtEnd.ts
@@ -7831,6 +7854,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7831
7854
  initialScrollIndex: initialScrollIndexProp,
7832
7855
  initialScrollOffset: initialScrollOffsetProp,
7833
7856
  experimental_adaptiveRender,
7857
+ experimental_hideItemsUntilMeasured,
7834
7858
  itemsAreEqual,
7835
7859
  keyExtractor: keyExtractorProp,
7836
7860
  ListEmptyComponent,
@@ -8051,6 +8075,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8051
8075
  const state = refState.current;
8052
8076
  const isFirstLocal = state.isFirst;
8053
8077
  const previousAdaptiveRender = state.props.adaptiveRender;
8078
+ const previousHideItemsUntilMeasured = state.props.hideItemsUntilMeasured;
8054
8079
  const previousNumColumnsProp = state.props.numColumns;
8055
8080
  const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
8056
8081
  ctx.scrollAxisGap = nextScrollAxisGap;
@@ -8096,6 +8121,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8096
8121
  estimatedItemSize,
8097
8122
  getFixedItemSize: useWrapIfItem(getFixedItemSize),
8098
8123
  getItemType: useWrapIfItem(getItemType),
8124
+ hideItemsUntilMeasured: experimental_hideItemsUntilMeasured,
8099
8125
  horizontal: !!horizontal,
8100
8126
  itemsAreEqual,
8101
8127
  keyExtractor: useWrapIfItem(keyExtractor),
@@ -8133,6 +8159,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8133
8159
  if (!isFirstLocal && previousAdaptiveRender && !experimental_adaptiveRender) {
8134
8160
  resetAdaptiveRender(ctx);
8135
8161
  }
8162
+ if (!isFirstLocal && previousHideItemsUntilMeasured && !experimental_hideItemsUntilMeasured) {
8163
+ resetContainerLayoutReady(ctx);
8164
+ }
8136
8165
  const memoizedLastItemKeys = React3.useMemo(() => {
8137
8166
  if (!dataProp.length) return [];
8138
8167
  return Array.from(
@@ -8381,7 +8410,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8381
8410
  }, [ctx, usesBootstrapInitialScroll]);
8382
8411
  const fns = React3.useMemo(
8383
8412
  () => ({
8384
- getRenderedItem: (key) => getRenderedItem(ctx, key),
8413
+ getRenderedItem: (key, containerId) => getRenderedItem(ctx, key, containerId),
8385
8414
  onMomentumScrollEnd: (event) => {
8386
8415
  checkFinishedScrollFallback(ctx);
8387
8416
  if (state.props.onMomentumScrollEnd) {