@legendapp/list 3.0.0-beta.53 → 3.0.0-beta.54

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.js CHANGED
@@ -722,6 +722,7 @@ function getContainerPositionStyle({
722
722
  }
723
723
  var Container = typedMemo(function Container2({
724
724
  id,
725
+ itemKey,
725
726
  recycleItems,
726
727
  horizontal,
727
728
  getRenderedItem: getRenderedItem2,
@@ -733,11 +734,10 @@ var Container = typedMemo(function Container2({
733
734
  const { columnWrapperStyle, animatedScrollY } = ctx;
734
735
  const positionComponentInternal = ctx.state.props.positionComponentInternal;
735
736
  const stickyPositionComponentInternal = ctx.state.props.stickyPositionComponentInternal;
736
- const [column = 0, span = 1, data, itemKey, numColumns = 1, extraData, isSticky] = useArr$([
737
+ const [column = 0, span = 1, data, numColumns = 1, extraData, isSticky] = useArr$([
737
738
  `containerColumn${id}`,
738
739
  `containerSpan${id}`,
739
740
  `containerItemData${id}`,
740
- `containerItemKey${id}`,
741
741
  "numColumns",
742
742
  "extraData",
743
743
  `containerSticky${id}`
@@ -882,6 +882,39 @@ var Container = typedMemo(function Container2({
882
882
  );
883
883
  });
884
884
 
885
+ // src/components/ContainerSlot.tsx
886
+ function ContainerSlotBase({
887
+ id,
888
+ horizontal,
889
+ recycleItems,
890
+ ItemSeparatorComponent,
891
+ updateItemSize: updateItemSize2,
892
+ getRenderedItem: getRenderedItem2,
893
+ stickyHeaderConfig,
894
+ ContainerComponent = Container
895
+ }) {
896
+ const [itemKey] = useArr$([`containerItemKey${id}`]);
897
+ if (itemKey === void 0) {
898
+ return null;
899
+ }
900
+ return /* @__PURE__ */ React2__namespace.createElement(
901
+ ContainerComponent,
902
+ {
903
+ getRenderedItem: getRenderedItem2,
904
+ horizontal,
905
+ ItemSeparatorComponent,
906
+ id,
907
+ itemKey,
908
+ recycleItems,
909
+ stickyHeaderConfig,
910
+ updateItemSize: updateItemSize2
911
+ }
912
+ );
913
+ }
914
+ var ContainerSlot = typedMemo(function ContainerSlot2(props) {
915
+ return /* @__PURE__ */ React2__namespace.createElement(ContainerSlotBase, { ...props });
916
+ });
917
+
885
918
  // src/components/Containers.native.tsx
886
919
  var ContainersLayer = typedMemo(function ContainersLayer2({ children, horizontal }) {
887
920
  const ctx = useStateContext();
@@ -920,12 +953,12 @@ var Containers = typedMemo(function Containers2({
920
953
  updateItemSize: updateItemSize2,
921
954
  getRenderedItem: getRenderedItem2
922
955
  }) {
923
- const [numContainers] = useArr$(["numContainersPooled"]);
956
+ const [numContainersPooled] = useArr$(["numContainersPooled"]);
924
957
  const containers = [];
925
- for (let i = 0; i < numContainers; i++) {
958
+ for (let i = 0; i < numContainersPooled; i++) {
926
959
  containers.push(
927
960
  /* @__PURE__ */ React2__namespace.createElement(
928
- Container,
961
+ ContainerSlot,
929
962
  {
930
963
  getRenderedItem: getRenderedItem2,
931
964
  horizontal,
@@ -1252,10 +1285,9 @@ var initialScrollWatchdog = {
1252
1285
  clear(state) {
1253
1286
  initialScrollWatchdog.set(state, void 0);
1254
1287
  },
1255
- didObserveProgress(newScroll, watchdog) {
1256
- const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
1288
+ didReachTarget(newScroll, watchdog) {
1257
1289
  const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
1258
- return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET || nextDistance + INITIAL_SCROLL_MIN_TARGET_OFFSET < previousDistance;
1290
+ return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET;
1259
1291
  },
1260
1292
  get(state) {
1261
1293
  var _a3, _b;
@@ -1280,19 +1312,19 @@ var initialScrollWatchdog = {
1280
1312
  }
1281
1313
  };
1282
1314
  function setInitialScrollSession(state, options = {}) {
1283
- var _a3, _b, _c;
1315
+ var _a3, _b, _c, _d;
1284
1316
  const existingSession = state.initialScrollSession;
1285
1317
  const kind = (_a3 = options.kind) != null ? _a3 : existingSession == null ? void 0 : existingSession.kind;
1286
1318
  const completion = existingSession == null ? void 0 : existingSession.completion;
1287
- const hasBootstrapOverride = Object.hasOwn(options, "bootstrap");
1288
- const bootstrap = kind === "bootstrap" ? hasBootstrapOverride ? options.bootstrap : (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0 : void 0;
1319
+ const existingBootstrap = (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0;
1320
+ const bootstrap = kind === "bootstrap" ? options.bootstrap === null ? void 0 : (_b = options.bootstrap) != null ? _b : existingBootstrap : void 0;
1289
1321
  if (!kind) {
1290
1322
  return clearInitialScrollSession(state);
1291
1323
  }
1292
1324
  if (!state.initialScroll && !bootstrap && !hasInitialScrollSessionCompletion(completion)) {
1293
1325
  return clearInitialScrollSession(state);
1294
1326
  }
1295
- const previousDataLength = (_c = (_b = options.previousDataLength) != null ? _b : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _c : 0;
1327
+ const previousDataLength = (_d = (_c = options.previousDataLength) != null ? _c : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _d : 0;
1296
1328
  state.initialScrollSession = createInitialScrollSession({
1297
1329
  bootstrap,
1298
1330
  completion,
@@ -1874,7 +1906,7 @@ function checkFinishedScrollFallback(ctx) {
1874
1906
  state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, delay);
1875
1907
  };
1876
1908
  const checkHasScrolled = () => {
1877
- var _a3, _b, _c;
1909
+ var _a3, _b, _c, _d;
1878
1910
  state.timeoutCheckFinishedScrollFallback = void 0;
1879
1911
  const isStillScrollingTo = state.scrollingTo;
1880
1912
  if (isStillScrollingTo) {
@@ -1887,8 +1919,10 @@ function checkFinishedScrollFallback(ctx) {
1887
1919
  isStillScrollingTo
1888
1920
  );
1889
1921
  const completionState = getResolvedScrollCompletionState(ctx, isStillScrollingTo);
1890
- const canFinishAfterSilentNativeDispatch = silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
1922
+ const canFinishAfterSilentNativeDispatch = Platform.OS === "android" && silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
1891
1923
  const shouldRetrySilentInitialNativeScroll = Platform.OS === "android" && canFinishAfterSilentNativeDispatch && !initialScrollCompletion.didRetrySilentInitialScroll(state);
1924
+ const shouldFinishAfterObservedScroll = state.hasScrolled && (!isStillScrollingTo.isInitialScroll || completionState.isAtResolvedTarget);
1925
+ const shouldRetryUnalignedInitialScroll = isStillScrollingTo.isInitialScroll && !completionState.isAtResolvedTarget && numChecks <= maxChecks;
1892
1926
  if (shouldRetrySilentInitialNativeScroll) {
1893
1927
  const targetOffset = (_b = (_a3 = getInitialScrollWatchdogTargetOffset(state)) != null ? _a3 : isStillScrollingTo.targetOffset) != null ? _b : 0;
1894
1928
  const jiggleOffset = targetOffset >= SILENT_INITIAL_SCROLL_TARGET_EPSILON ? targetOffset - SILENT_INITIAL_SCROLL_TARGET_EPSILON : targetOffset + SILENT_INITIAL_SCROLL_TARGET_EPSILON;
@@ -1898,10 +1932,10 @@ function checkFinishedScrollFallback(ctx) {
1898
1932
  scrollToFallbackOffset(ctx, targetOffset);
1899
1933
  });
1900
1934
  scheduleFallbackCheck(SILENT_INITIAL_SCROLL_RETRY_DELAY_MS);
1901
- } else if (shouldFinishZeroTarget || state.hasScrolled || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
1935
+ } else if (shouldFinishZeroTarget || shouldFinishAfterObservedScroll || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
1902
1936
  finishScrollTo(ctx);
1903
- } else if (isNativeInitialPending && numChecks <= maxChecks) {
1904
- const targetOffset = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : state.scrollPending;
1937
+ } else if ((isNativeInitialPending || shouldRetryUnalignedInitialScroll) && numChecks <= maxChecks) {
1938
+ const targetOffset = (_d = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : isStillScrollingTo.targetOffset) != null ? _d : state.scrollPending;
1905
1939
  scrollToFallbackOffset(ctx, targetOffset);
1906
1940
  scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
1907
1941
  } else {
@@ -2130,7 +2164,7 @@ function advanceMeasuredInitialScroll(ctx, options) {
2130
2164
  const activeInitialTargetOffset = scrollingTo ? (_a3 = scrollingTo.targetOffset) != null ? _a3 : scrollingTo.offset : void 0;
2131
2165
  const didOffsetChange = initialScroll.contentOffset === void 0 || Math.abs(initialScroll.contentOffset - resolvedOffset) > 1;
2132
2166
  const didActiveInitialTargetChange = activeInitialTargetOffset !== void 0 && Math.abs(activeInitialTargetOffset - resolvedOffset) > 1;
2133
- const isAlreadyAtDesiredInitialTarget = activeInitialTargetOffset !== void 0 && Math.abs(state.scroll - activeInitialTargetOffset) <= 1 && Math.abs(state.scrollPending - activeInitialTargetOffset) <= 1;
2167
+ const isAlreadyAtDesiredInitialTarget = activeInitialTargetOffset !== void 0 && Math.abs(state.scroll - resolvedOffset) <= 1 && Math.abs(state.scrollPending - resolvedOffset) <= 1;
2134
2168
  if (!(options == null ? void 0 : options.forceScroll) && !didOffsetChange && isInitialScrollInProgress && !didActiveInitialTargetChange) {
2135
2169
  return false;
2136
2170
  }
@@ -2202,6 +2236,61 @@ function checkAllSizesKnown(state, indices) {
2202
2236
  });
2203
2237
  }
2204
2238
 
2239
+ // src/utils/requestAdjust.ts
2240
+ function requestAdjust(ctx, positionDiff, dataChanged) {
2241
+ const state = ctx.state;
2242
+ if (Math.abs(positionDiff) > 0.1) {
2243
+ const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2244
+ const doit = () => {
2245
+ if (needsScrollWorkaround) {
2246
+ scrollTo(ctx, {
2247
+ noScrollingTo: true,
2248
+ offset: state.scroll
2249
+ });
2250
+ } else {
2251
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
2252
+ if (state.adjustingFromInitialMount) {
2253
+ state.adjustingFromInitialMount--;
2254
+ }
2255
+ }
2256
+ };
2257
+ state.scroll += positionDiff;
2258
+ state.scrollForNextCalculateItemsInView = void 0;
2259
+ const readyToRender = peek$(ctx, "readyToRender");
2260
+ if (readyToRender) {
2261
+ doit();
2262
+ if (Platform.OS !== "web") {
2263
+ const threshold = state.scroll - positionDiff / 2;
2264
+ if (!state.ignoreScrollFromMVCP) {
2265
+ state.ignoreScrollFromMVCP = {};
2266
+ }
2267
+ if (positionDiff > 0) {
2268
+ state.ignoreScrollFromMVCP.lt = threshold;
2269
+ } else {
2270
+ state.ignoreScrollFromMVCP.gt = threshold;
2271
+ }
2272
+ if (state.ignoreScrollFromMVCPTimeout) {
2273
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
2274
+ }
2275
+ const delay = needsScrollWorkaround ? 250 : 100;
2276
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
2277
+ var _a3;
2278
+ state.ignoreScrollFromMVCP = void 0;
2279
+ const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
2280
+ if (shouldForceUpdate) {
2281
+ state.ignoreScrollFromMVCPIgnored = false;
2282
+ state.scrollPending = state.scroll;
2283
+ (_a3 = state.reprocessCurrentScroll) == null ? void 0 : _a3.call(state);
2284
+ }
2285
+ }, delay);
2286
+ }
2287
+ } else {
2288
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2289
+ requestAnimationFrame(doit);
2290
+ }
2291
+ }
2292
+ }
2293
+
2205
2294
  // src/core/bootstrapInitialScroll.ts
2206
2295
  var DEFAULT_BOOTSTRAP_REVEAL_EPSILON = 1;
2207
2296
  var DEFAULT_BOOTSTRAP_REVEAL_MAX_FRAMES = 8;
@@ -2295,7 +2384,7 @@ function clearBootstrapInitialScrollSession(state) {
2295
2384
  bootstrapInitialScroll.frameHandle = void 0;
2296
2385
  }
2297
2386
  setInitialScrollSession(state, {
2298
- bootstrap: void 0,
2387
+ bootstrap: null,
2299
2388
  kind: (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind
2300
2389
  });
2301
2390
  }
@@ -2451,15 +2540,18 @@ function clearFinishedBootstrapInitialScrollTargetIfMovedAway(ctx) {
2451
2540
  return;
2452
2541
  }
2453
2542
  if (didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2454
- if (shouldPreserveInitialScrollForFooterLayout(initialScroll)) {
2455
- clearPendingInitialScrollFooterLayout(ctx, {
2456
- dataLength: state.props.data.length,
2457
- stylePaddingBottom: (_b = state.props.stylePaddingBottom) != null ? _b : 0,
2458
- target: initialScroll
2459
- });
2460
- return;
2543
+ const shouldKeepEndTargetAlive = isRetargetableBottomAlignedInitialScrollTarget(initialScroll) && peek$(ctx, "isAtEnd");
2544
+ if (!shouldKeepEndTargetAlive) {
2545
+ if (shouldPreserveInitialScrollForFooterLayout(initialScroll)) {
2546
+ clearPendingInitialScrollFooterLayout(ctx, {
2547
+ dataLength: state.props.data.length,
2548
+ stylePaddingBottom: (_b = state.props.stylePaddingBottom) != null ? _b : 0,
2549
+ target: initialScroll
2550
+ });
2551
+ } else {
2552
+ clearFinishedViewportRetargetableInitialScroll(state);
2553
+ }
2461
2554
  }
2462
- clearFinishedViewportRetargetableInitialScroll(state);
2463
2555
  }
2464
2556
  }
2465
2557
  function startBootstrapInitialScrollOnMount(ctx, options) {
@@ -2498,7 +2590,7 @@ function handleBootstrapInitialScrollDataChange(ctx, options) {
2498
2590
  }
2499
2591
  const shouldResetDidFinish = !!(state.didFinishInitialScroll && previousDataLength === 0 && dataLength > 0 && initialScroll.index !== void 0);
2500
2592
  const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2501
- const shouldClearFinishedResizePreservation = didDataChange && dataLength > 0 && state.didFinishInitialScroll && !bootstrapInitialScroll && !shouldResetDidFinish;
2593
+ const shouldClearFinishedResizePreservation = !initialScrollAtEnd && didDataChange && dataLength > 0 && state.didFinishInitialScroll && !bootstrapInitialScroll && !shouldResetDidFinish;
2502
2594
  if (shouldClearFinishedResizePreservation) {
2503
2595
  clearPreservedInitialScrollTarget(state);
2504
2596
  return;
@@ -2601,27 +2693,46 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2601
2693
  }
2602
2694
  }
2603
2695
  function handleBootstrapInitialScrollLayoutChange(ctx) {
2696
+ var _a3, _b, _c, _d;
2604
2697
  const state = ctx.state;
2605
2698
  const initialScroll = state.initialScroll;
2606
- if (isOffsetInitialScrollSession(state) || state.props.data.length === 0 || !initialScroll) {
2607
- return;
2608
- }
2609
2699
  const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2610
- if (!bootstrapInitialScroll && initialScroll.viewPosition !== 1) {
2611
- return;
2612
- }
2613
- const didFinishInitialScroll = state.didFinishInitialScroll;
2614
- if (didFinishInitialScroll) {
2615
- setInitialScrollTarget(state, initialScroll, {
2616
- resetDidFinish: true
2617
- });
2618
- state.clearPreservedInitialScrollOnNextFinish = true;
2700
+ if (initialScroll && state.props.data.length > 0 && !isOffsetInitialScrollSession(state) && (bootstrapInitialScroll || initialScroll.viewPosition === 1)) {
2701
+ const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
2702
+ const scrollingTo = ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) ? state.scrollingTo : void 0;
2703
+ if (!bootstrapInitialScroll && (scrollingTo || state.didFinishInitialScroll)) {
2704
+ const currentOffset = scrollingTo ? (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset : getObservedBootstrapInitialScrollOffset(state);
2705
+ const offsetDiff = resolvedOffset - currentOffset;
2706
+ if (Math.abs(offsetDiff) > DEFAULT_BOOTSTRAP_REVEAL_EPSILON) {
2707
+ if (scrollingTo) {
2708
+ const existingWatchdog = initialScrollWatchdog.get(state);
2709
+ scrollingTo.offset = resolvedOffset;
2710
+ scrollingTo.targetOffset = resolvedOffset;
2711
+ state.initialScroll = {
2712
+ ...initialScroll,
2713
+ contentOffset: resolvedOffset
2714
+ };
2715
+ state.hasScrolled = false;
2716
+ initialScrollWatchdog.set(state, {
2717
+ startScroll: (_c = existingWatchdog == null ? void 0 : existingWatchdog.startScroll) != null ? _c : state.scroll,
2718
+ targetOffset: resolvedOffset
2719
+ });
2720
+ }
2721
+ requestAdjust(ctx, offsetDiff);
2722
+ if (state.didFinishInitialScroll) {
2723
+ (_d = state.triggerCalculateItemsInView) == null ? void 0 : _d.call(state, { forceFullItemPositions: true });
2724
+ }
2725
+ }
2726
+ if (state.didFinishInitialScroll) {
2727
+ clearFinishedViewportRetargetableInitialScroll(state);
2728
+ }
2729
+ } else {
2730
+ rearmBootstrapInitialScroll(ctx, {
2731
+ scroll: resolvedOffset,
2732
+ targetIndexSeed: initialScroll.index
2733
+ });
2734
+ }
2619
2735
  }
2620
- rearmBootstrapInitialScroll(ctx, {
2621
- scroll: resolveInitialScrollOffset(ctx, initialScroll),
2622
- seedContentOffset: didFinishInitialScroll && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2623
- targetIndexSeed: initialScroll.index
2624
- });
2625
2736
  }
2626
2737
  function evaluateBootstrapInitialScroll(ctx) {
2627
2738
  var _a3, _b;
@@ -2808,61 +2919,6 @@ function handleInitialScrollDataChange(ctx, options) {
2808
2919
  advanceCurrentInitialScrollSession(ctx);
2809
2920
  }
2810
2921
 
2811
- // src/utils/requestAdjust.ts
2812
- function requestAdjust(ctx, positionDiff, dataChanged) {
2813
- const state = ctx.state;
2814
- if (Math.abs(positionDiff) > 0.1) {
2815
- const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2816
- const doit = () => {
2817
- if (needsScrollWorkaround) {
2818
- scrollTo(ctx, {
2819
- noScrollingTo: true,
2820
- offset: state.scroll
2821
- });
2822
- } else {
2823
- state.scrollAdjustHandler.requestAdjust(positionDiff);
2824
- if (state.adjustingFromInitialMount) {
2825
- state.adjustingFromInitialMount--;
2826
- }
2827
- }
2828
- };
2829
- state.scroll += positionDiff;
2830
- state.scrollForNextCalculateItemsInView = void 0;
2831
- const readyToRender = peek$(ctx, "readyToRender");
2832
- if (readyToRender) {
2833
- doit();
2834
- if (Platform.OS !== "web") {
2835
- const threshold = state.scroll - positionDiff / 2;
2836
- if (!state.ignoreScrollFromMVCP) {
2837
- state.ignoreScrollFromMVCP = {};
2838
- }
2839
- if (positionDiff > 0) {
2840
- state.ignoreScrollFromMVCP.lt = threshold;
2841
- } else {
2842
- state.ignoreScrollFromMVCP.gt = threshold;
2843
- }
2844
- if (state.ignoreScrollFromMVCPTimeout) {
2845
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
2846
- }
2847
- const delay = needsScrollWorkaround ? 250 : 100;
2848
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
2849
- var _a3;
2850
- state.ignoreScrollFromMVCP = void 0;
2851
- const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
2852
- if (shouldForceUpdate) {
2853
- state.ignoreScrollFromMVCPIgnored = false;
2854
- state.scrollPending = state.scroll;
2855
- (_a3 = state.reprocessCurrentScroll) == null ? void 0 : _a3.call(state);
2856
- }
2857
- }, delay);
2858
- }
2859
- } else {
2860
- state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2861
- requestAnimationFrame(doit);
2862
- }
2863
- }
2864
- }
2865
-
2866
2922
  // src/core/mvcp.ts
2867
2923
  var MVCP_POSITION_EPSILON = 0.1;
2868
2924
  var MVCP_ANCHOR_LOCK_TTL_MS = 300;
@@ -3146,7 +3202,10 @@ function prepareMVCP(ctx, dataChanged) {
3146
3202
  return;
3147
3203
  }
3148
3204
  if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
3149
- requestAdjust(ctx, positionDiff, dataChanged && mvcpData);
3205
+ const shouldSkipAdjustForMaintainedEnd = state.maintainingScrollAtEnd && peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
3206
+ if (!shouldSkipAdjustForMaintainedEnd) {
3207
+ requestAdjust(ctx, positionDiff, dataChanged && mvcpData);
3208
+ }
3150
3209
  }
3151
3210
  };
3152
3211
  }
@@ -3765,6 +3824,30 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
3765
3824
  var unstableBatchedUpdates = ReactNative__namespace.unstable_batchedUpdates;
3766
3825
  var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
3767
3826
 
3827
+ // src/utils/containerPool.ts
3828
+ var MIN_INITIAL_CONTAINER_POOL_SIZE = 32;
3829
+ var MAX_INITIAL_SPARE_CONTAINERS = 64;
3830
+ function getInitialContainerPoolSize(dataLength, numContainers, initialContainerPoolRatio) {
3831
+ if (dataLength <= 0 || numContainers <= 0) {
3832
+ return 0;
3833
+ }
3834
+ const ratioPoolSize = Math.ceil(numContainers * initialContainerPoolRatio);
3835
+ const cappedSparePoolSize = numContainers + MAX_INITIAL_SPARE_CONTAINERS;
3836
+ const targetPoolSize = Math.max(
3837
+ numContainers,
3838
+ Math.min(ratioPoolSize, cappedSparePoolSize),
3839
+ Math.min(dataLength, MIN_INITIAL_CONTAINER_POOL_SIZE)
3840
+ );
3841
+ const maxUsefulPoolSize = Math.max(dataLength, numContainers);
3842
+ return Math.min(maxUsefulPoolSize, targetPoolSize);
3843
+ }
3844
+ function getExpandedContainerPoolSize(dataLength, numContainers) {
3845
+ if (dataLength <= 0 || numContainers <= 0) {
3846
+ return 0;
3847
+ }
3848
+ return Math.min(Math.max(dataLength, numContainers), Math.max(numContainers, Math.ceil(numContainers * 1.5)));
3849
+ }
3850
+
3768
3851
  // src/utils/findAvailableContainers.ts
3769
3852
  function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
3770
3853
  const numContainers = peek$(ctx, "numContainers");
@@ -3970,7 +4053,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
3970
4053
  function calculateItemsInView(ctx, params = {}) {
3971
4054
  const state = ctx.state;
3972
4055
  batchedUpdates(() => {
3973
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
4056
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
3974
4057
  const {
3975
4058
  columns,
3976
4059
  columnSpans,
@@ -4017,12 +4100,22 @@ function calculateItemsInView(ctx, params = {}) {
4017
4100
  // current initial-scroll target instead of transient native adjustments.
4018
4101
  resolveInitialScrollOffset(ctx, initialScroll)
4019
4102
  ) : state.scroll;
4020
- const scrollAdjustPending = (_c = peek$(ctx, "scrollAdjustPending")) != null ? _c : 0;
4021
- const scrollAdjustPad = scrollAdjustPending - topPad;
4022
- let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
4023
- if (scroll + scrollLength > totalSize) {
4024
- scroll = Math.max(0, totalSize - scrollLength);
4025
- }
4103
+ let scrollAdjustPending = 0;
4104
+ let scrollAdjustPad = 0;
4105
+ let scroll = 0;
4106
+ let scrollTopBuffered = 0;
4107
+ let scrollBottom = 0;
4108
+ let scrollBottomBuffered = 0;
4109
+ const updateScroll2 = (nextScrollState) => {
4110
+ var _a4;
4111
+ scrollAdjustPending = (_a4 = peek$(ctx, "scrollAdjustPending")) != null ? _a4 : 0;
4112
+ scrollAdjustPad = scrollAdjustPending - topPad;
4113
+ scroll = Math.round(nextScrollState + scrollExtra + scrollAdjustPad);
4114
+ if (scroll + scrollLength > totalSize) {
4115
+ scroll = Math.max(0, totalSize - scrollLength);
4116
+ }
4117
+ };
4118
+ updateScroll2(scrollState);
4026
4119
  const previousStickyIndex = peek$(ctx, "activeStickyIndex");
4027
4120
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
4028
4121
  const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
@@ -4038,9 +4131,12 @@ function calculateItemsInView(ctx, params = {}) {
4038
4131
  scrollBufferTop = drawDistance * 1.5;
4039
4132
  scrollBufferBottom = drawDistance * 0.5;
4040
4133
  }
4041
- const scrollTopBuffered = scroll - scrollBufferTop;
4042
- const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
4043
- const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4134
+ const updateScrollRange = () => {
4135
+ scrollTopBuffered = scroll - scrollBufferTop;
4136
+ scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
4137
+ scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4138
+ };
4139
+ updateScrollRange();
4044
4140
  if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4045
4141
  const { top, bottom } = scrollForNextCalculateItemsInView;
4046
4142
  if (top === null && bottom === null) {
@@ -4059,7 +4155,7 @@ function calculateItemsInView(ctx, params = {}) {
4059
4155
  columns.length = 0;
4060
4156
  columnSpans.length = 0;
4061
4157
  }
4062
- const startIndex = forceFullItemPositions || dataChanged ? 0 : (_d = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _d : 0;
4158
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
4063
4159
  const optimizeForVisibleWindow = !forceFullItemPositions && !dataChanged && numColumns > 1 && minIndexSizeChanged !== void 0;
4064
4160
  updateItemPositions(ctx, dataChanged, {
4065
4161
  doMVCP,
@@ -4084,21 +4180,25 @@ function calculateItemsInView(ctx, params = {}) {
4084
4180
  }
4085
4181
  }
4086
4182
  const scrollBeforeMVCP = state.scroll;
4087
- const scrollAdjustPendingBeforeMVCP = (_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0;
4183
+ const scrollAdjustPendingBeforeMVCP = (_d = peek$(ctx, "scrollAdjustPending")) != null ? _d : 0;
4088
4184
  checkMVCP == null ? void 0 : checkMVCP();
4089
- const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_f = peek$(ctx, "scrollAdjustPending")) != null ? _f : 0) !== scrollAdjustPendingBeforeMVCP);
4185
+ const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0) !== scrollAdjustPendingBeforeMVCP);
4186
+ if (didMVCPAdjustScroll && initialScroll) {
4187
+ updateScroll2(state.scroll);
4188
+ updateScrollRange();
4189
+ }
4090
4190
  let startNoBuffer = null;
4091
4191
  let startBuffered = null;
4092
4192
  let startBufferedId = null;
4093
4193
  let endNoBuffer = null;
4094
4194
  let endBuffered = null;
4095
- let loopStart = (_g = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _g : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4195
+ let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4096
4196
  for (let i = loopStart; i >= 0; i--) {
4097
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
4197
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
4098
4198
  const top = positions[i];
4099
- const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
4199
+ const size = (_h = sizes.get(id)) != null ? _h : getItemSize(ctx, id, i, data[i]);
4100
4200
  const bottom = top + size;
4101
- if (bottom > scroll - scrollBufferTop) {
4201
+ if (bottom > scrollTopBuffered) {
4102
4202
  loopStart = i;
4103
4203
  } else {
4104
4204
  break;
@@ -4127,8 +4227,8 @@ function calculateItemsInView(ctx, params = {}) {
4127
4227
  let firstFullyOnScreenIndex;
4128
4228
  const dataLength = data.length;
4129
4229
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4130
- const id = (_j = idCache[i]) != null ? _j : getId(state, i);
4131
- const size = (_k = sizes.get(id)) != null ? _k : getItemSize(ctx, id, i, data[i]);
4230
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
4231
+ const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
4132
4232
  const top = positions[i];
4133
4233
  if (!foundEnd) {
4134
4234
  if (startNoBuffer === null && top + size > scroll) {
@@ -4167,7 +4267,7 @@ function calculateItemsInView(ctx, params = {}) {
4167
4267
  const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4168
4268
  if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4169
4269
  for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4170
- const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4270
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4171
4271
  idsInView.push(id);
4172
4272
  }
4173
4273
  }
@@ -4200,7 +4300,7 @@ function calculateItemsInView(ctx, params = {}) {
4200
4300
  const needNewContainers = [];
4201
4301
  const needNewContainersSet = /* @__PURE__ */ new Set();
4202
4302
  for (let i = startBuffered; i <= endBuffered; i++) {
4203
- const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4303
+ const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4204
4304
  if (!containerItemKeys.has(id)) {
4205
4305
  needNewContainersSet.add(i);
4206
4306
  needNewContainers.push(i);
@@ -4209,7 +4309,7 @@ function calculateItemsInView(ctx, params = {}) {
4209
4309
  if (alwaysRenderArr.length > 0) {
4210
4310
  for (const index of alwaysRenderArr) {
4211
4311
  if (index < 0 || index >= dataLength) continue;
4212
- const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4312
+ const id = (_m = idCache[index]) != null ? _m : getId(state, index);
4213
4313
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4214
4314
  needNewContainersSet.add(index);
4215
4315
  needNewContainers.push(index);
@@ -4248,7 +4348,7 @@ function calculateItemsInView(ctx, params = {}) {
4248
4348
  for (let idx = 0; idx < needNewContainers.length; idx++) {
4249
4349
  const i = needNewContainers[idx];
4250
4350
  const containerIndex = availableContainers[idx];
4251
- const id = (_o = idCache[i]) != null ? _o : getId(state, i);
4351
+ const id = (_n = idCache[i]) != null ? _n : getId(state, i);
4252
4352
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4253
4353
  if (oldKey && oldKey !== id) {
4254
4354
  containerItemKeys.delete(oldKey);
@@ -4259,7 +4359,7 @@ function calculateItemsInView(ctx, params = {}) {
4259
4359
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4260
4360
  }
4261
4361
  containerItemKeys.set(id, containerIndex);
4262
- (_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.add(id);
4362
+ (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
4263
4363
  const containerSticky = `containerSticky${containerIndex}`;
4264
4364
  const isSticky = stickyIndicesSet.has(i);
4265
4365
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4283,17 +4383,17 @@ function calculateItemsInView(ctx, params = {}) {
4283
4383
  if (numContainers !== prevNumContainers) {
4284
4384
  set$(ctx, "numContainers", numContainers);
4285
4385
  if (numContainers > peek$(ctx, "numContainersPooled")) {
4286
- set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
4386
+ set$(ctx, "numContainersPooled", getExpandedContainerPoolSize(dataLength, numContainers));
4287
4387
  }
4288
4388
  }
4289
4389
  }
4290
- if (((_q = state.userScrollAnchorResetKeys) == null ? void 0 : _q.size) === 0) {
4390
+ if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
4291
4391
  state.userScrollAnchorResetKeys = void 0;
4292
4392
  }
4293
4393
  if (alwaysRenderArr.length > 0) {
4294
4394
  for (const index of alwaysRenderArr) {
4295
4395
  if (index < 0 || index >= dataLength) continue;
4296
- const id = (_r = idCache[index]) != null ? _r : getId(state, index);
4396
+ const id = (_q = idCache[index]) != null ? _q : getId(state, index);
4297
4397
  const containerIndex = containerItemKeys.get(id);
4298
4398
  if (containerIndex !== void 0) {
4299
4399
  state.stickyContainerPool.add(containerIndex);
@@ -4397,21 +4497,25 @@ function doMaintainScrollAtEnd(ctx) {
4397
4497
  if (contentSize < state.scrollLength) {
4398
4498
  state.scroll = 0;
4399
4499
  }
4400
- requestAnimationFrame(() => {
4401
- var _a3;
4402
- if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
4403
- state.maintainingScrollAtEnd = true;
4404
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
4405
- animated: maintainScrollAtEnd.animated
4406
- });
4407
- setTimeout(
4408
- () => {
4409
- state.maintainingScrollAtEnd = false;
4410
- },
4411
- maintainScrollAtEnd.animated ? 500 : 0
4412
- );
4413
- }
4414
- });
4500
+ if (!state.maintainingScrollAtEnd) {
4501
+ state.maintainingScrollAtEnd = true;
4502
+ requestAnimationFrame(() => {
4503
+ var _a3;
4504
+ if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
4505
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
4506
+ animated: maintainScrollAtEnd.animated
4507
+ });
4508
+ setTimeout(
4509
+ () => {
4510
+ state.maintainingScrollAtEnd = false;
4511
+ },
4512
+ maintainScrollAtEnd.animated ? 500 : 0
4513
+ );
4514
+ } else {
4515
+ state.maintainingScrollAtEnd = false;
4516
+ }
4517
+ });
4518
+ }
4415
4519
  return true;
4416
4520
  }
4417
4521
  return false;
@@ -4523,14 +4627,21 @@ function doInitialAllocateContainers(ctx) {
4523
4627
  } else {
4524
4628
  averageItemSize = estimatedItemSize;
4525
4629
  }
4526
- const numContainers = Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns);
4630
+ const numContainers = Math.max(
4631
+ 1,
4632
+ Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns)
4633
+ );
4527
4634
  for (let i = 0; i < numContainers; i++) {
4528
4635
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
4529
4636
  set$(ctx, `containerColumn${i}`, -1);
4530
4637
  set$(ctx, `containerSpan${i}`, 1);
4531
4638
  }
4532
4639
  set$(ctx, "numContainers", numContainers);
4533
- set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
4640
+ set$(
4641
+ ctx,
4642
+ "numContainersPooled",
4643
+ getInitialContainerPoolSize(data.length, numContainers, state.props.initialContainerPoolRatio)
4644
+ );
4534
4645
  if (!IsNewArchitecture || state.lastLayout) {
4535
4646
  if (state.initialScroll) {
4536
4647
  requestAnimationFrame(() => {
@@ -4682,8 +4793,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
4682
4793
  // src/core/onScroll.ts
4683
4794
  function trackInitialScrollNativeProgress(state, newScroll) {
4684
4795
  const initialNativeScrollWatchdog = initialScrollWatchdog.get(state);
4685
- const didInitialScrollProgress = !!initialNativeScrollWatchdog && initialScrollWatchdog.didObserveProgress(newScroll, initialNativeScrollWatchdog);
4686
- if (didInitialScrollProgress) {
4796
+ const didInitialScrollReachTarget = !!initialNativeScrollWatchdog && initialScrollWatchdog.didReachTarget(newScroll, initialNativeScrollWatchdog);
4797
+ if (didInitialScrollReachTarget) {
4687
4798
  initialScrollWatchdog.clear(state);
4688
4799
  return;
4689
4800
  }
@@ -4821,16 +4932,20 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4821
4932
  let contentBelowAnchor = 0;
4822
4933
  const footerSize = ctx.values.get("footerSize") || 0;
4823
4934
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
4935
+ let hasUnknownTailSize = false;
4824
4936
  for (let index = anchorIndex; index < data.length; index++) {
4825
4937
  const itemKey = getId(state, index);
4826
4938
  const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
4827
4939
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
4940
+ if (size === void 0) {
4941
+ hasUnknownTailSize = true;
4942
+ }
4828
4943
  if (effectiveSize !== null && effectiveSize !== void 0 && effectiveSize > 0) {
4829
4944
  contentBelowAnchor += effectiveSize;
4830
4945
  }
4831
4946
  }
4832
4947
  contentBelowAnchor += footerSize + stylePaddingBottom;
4833
- nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4948
+ nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4834
4949
  }
4835
4950
  }
4836
4951
  if (previousSize !== nextSize) {
@@ -4904,15 +5019,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
4904
5019
  const {
4905
5020
  didContainersLayout,
4906
5021
  sizesKnown,
4907
- props: {
4908
- getFixedItemSize,
4909
- getItemType,
4910
- horizontal,
4911
- suggestEstimatedItemSize,
4912
- onItemSizeChanged,
4913
- data,
4914
- maintainScrollAtEnd
4915
- }
5022
+ props: { getFixedItemSize, getItemType, horizontal, onItemSizeChanged, data, maintainScrollAtEnd }
4916
5023
  } = state;
4917
5024
  if (!data) return;
4918
5025
  const index = state.indexByKey.get(itemKey);
@@ -4963,18 +5070,6 @@ function updateItemSize(ctx, itemKey, sizeObj) {
4963
5070
  if (minIndexSizeChanged !== void 0) {
4964
5071
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
4965
5072
  }
4966
- if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
4967
- if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
4968
- state.timeoutSizeMessage = setTimeout(() => {
4969
- var _a4;
4970
- state.timeoutSizeMessage = void 0;
4971
- const num = state.sizesKnown.size;
4972
- const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
4973
- console.warn(
4974
- `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
4975
- );
4976
- }, 1e3);
4977
- }
4978
5073
  const cur = peek$(ctx, "otherAxisSize");
4979
5074
  if (!cur || maxOtherAxisSize > cur) {
4980
5075
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
@@ -5092,12 +5187,47 @@ function createColumnWrapperStyle(contentContainerStyle) {
5092
5187
  }
5093
5188
 
5094
5189
  // src/utils/createImperativeHandle.ts
5190
+ var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
5191
+ function getAverageItemSizes(state) {
5192
+ const averageItemSizes = {};
5193
+ for (const itemType in state.averageSizes) {
5194
+ const averageSize = state.averageSizes[itemType];
5195
+ if (averageSize) {
5196
+ averageItemSizes[itemType || DEFAULT_AVERAGE_ITEM_SIZE_TYPE] = {
5197
+ average: averageSize.avg,
5198
+ count: averageSize.num
5199
+ };
5200
+ }
5201
+ }
5202
+ return averageItemSizes;
5203
+ }
5095
5204
  function createImperativeHandle(ctx) {
5096
5205
  const state = ctx.state;
5097
5206
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
5098
5207
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5099
5208
  let imperativeScrollToken = 0;
5100
5209
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5210
+ const isScrollToIndexReady = (targetIndex, allowEmpty = false) => {
5211
+ var _a3;
5212
+ const props = state.props;
5213
+ const dataLength = props.data.length;
5214
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5215
+ if (targetIndex < 0) {
5216
+ return allowEmpty;
5217
+ }
5218
+ if (targetIndex >= dataLength) {
5219
+ return false;
5220
+ }
5221
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
5222
+ return true;
5223
+ }
5224
+ for (let index = anchorIndex; index < dataLength; index++) {
5225
+ if (!state.sizesKnown.has(getId(state, index))) {
5226
+ return false;
5227
+ }
5228
+ }
5229
+ return true;
5230
+ };
5101
5231
  const runWhenReady = (token, run, isReady) => {
5102
5232
  const startedAt = Date.now();
5103
5233
  let stableFrames = 0;
@@ -5119,11 +5249,10 @@ function createImperativeHandle(ctx) {
5119
5249
  };
5120
5250
  requestAnimationFrame(check);
5121
5251
  };
5122
- const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5123
- var _a3, _b;
5252
+ const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
5253
+ var _a3;
5124
5254
  const token = ++imperativeScrollToken;
5125
- const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5126
- (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5255
+ (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5127
5256
  state.pendingScrollResolve = resolve;
5128
5257
  const runNow = () => {
5129
5258
  if (token !== imperativeScrollToken) {
@@ -5198,6 +5327,7 @@ function createImperativeHandle(ctx) {
5198
5327
  },
5199
5328
  end: state.endNoBuffer,
5200
5329
  endBuffered: state.endBuffered,
5330
+ getAverageItemSizes: () => getAverageItemSizes(state),
5201
5331
  isAtEnd: peek$(ctx, "isAtEnd"),
5202
5332
  isAtStart: peek$(ctx, "isAtStart"),
5203
5333
  isEndReached: state.isEndReached,
@@ -5240,40 +5370,34 @@ function createImperativeHandle(ctx) {
5240
5370
  }
5241
5371
  return false;
5242
5372
  }),
5243
- scrollToEnd: (options) => runScrollWithPromise(() => {
5244
- const data = state.props.data;
5245
- const stylePaddingBottom = state.props.stylePaddingBottom;
5246
- const index = data.length - 1;
5247
- if (index !== -1) {
5248
- const paddingBottom = stylePaddingBottom || 0;
5249
- const footerSize = peek$(ctx, "footerSize") || 0;
5250
- scrollToIndex(ctx, {
5251
- ...options,
5252
- index,
5253
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
5254
- viewPosition: 1
5255
- });
5256
- return true;
5257
- }
5258
- return false;
5259
- }),
5260
- scrollToIndex: (params) => {
5261
- const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5262
- const options = shouldWaitForOutOfRangeTarget ? {
5263
- isReady: () => {
5264
- var _a3;
5265
- const props = state.props;
5266
- const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5267
- const lastIndex = props.data.length - 1;
5268
- const isInRange = params.index < props.data.length;
5269
- const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5270
- return isInRange && !shouldWaitForAnchorSize;
5373
+ scrollToEnd: (options) => runScrollWithPromise(
5374
+ () => {
5375
+ const data = state.props.data;
5376
+ const stylePaddingBottom = state.props.stylePaddingBottom;
5377
+ const index = data.length - 1;
5378
+ if (index !== -1) {
5379
+ const paddingBottom = stylePaddingBottom || 0;
5380
+ const footerSize = peek$(ctx, "footerSize") || 0;
5381
+ scrollToIndex(ctx, {
5382
+ ...options,
5383
+ index,
5384
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
5385
+ viewPosition: 1
5386
+ });
5387
+ return true;
5271
5388
  }
5272
- } : void 0;
5273
- return runScrollWithPromise(() => {
5274
- scrollToIndex(ctx, params);
5275
- return true;
5276
- }, options);
5389
+ return false;
5390
+ },
5391
+ () => isScrollToIndexReady(state.props.data.length - 1, true)
5392
+ ),
5393
+ scrollToIndex: (params) => {
5394
+ return runScrollWithPromise(
5395
+ () => {
5396
+ scrollToIndex(ctx, params);
5397
+ return true;
5398
+ },
5399
+ params.index >= 0 ? () => isScrollToIndexReady(params.index) : void 0
5400
+ );
5277
5401
  },
5278
5402
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5279
5403
  const data = state.props.data;
@@ -5537,7 +5661,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5537
5661
  getFixedItemSize,
5538
5662
  getItemType,
5539
5663
  horizontal,
5540
- initialContainerPoolRatio = 2,
5664
+ initialContainerPoolRatio = 3,
5541
5665
  initialScrollAtEnd = false,
5542
5666
  initialScrollIndex: initialScrollIndexProp,
5543
5667
  initialScrollOffset: initialScrollOffsetProp,
@@ -5578,7 +5702,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5578
5702
  stickyIndices: stickyIndicesDeprecated,
5579
5703
  // TODOV3: Remove from v3 release
5580
5704
  style: styleProp,
5581
- suggestEstimatedItemSize,
5582
5705
  useWindowScroll = false,
5583
5706
  viewabilityConfig,
5584
5707
  viewabilityConfigCallbackPairs,
@@ -5719,7 +5842,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5719
5842
  startReachedSnapshotDataChangeEpoch: void 0,
5720
5843
  stickyContainerPool: /* @__PURE__ */ new Set(),
5721
5844
  stickyContainers: /* @__PURE__ */ new Map(),
5722
- timeoutSizeMessage: 0,
5723
5845
  timeouts: /* @__PURE__ */ new Set(),
5724
5846
  totalSize: 0,
5725
5847
  viewabilityConfigCallbackPairs: void 0
@@ -5739,7 +5861,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5739
5861
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
5740
5862
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
5741
5863
  const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
5742
- if (didDataChangeLocal && state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.props.data.length > 0) {
5864
+ if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.props.data.length > 0) {
5743
5865
  clearPreservedInitialScrollTarget(state);
5744
5866
  }
5745
5867
  if (didDataChangeLocal) {
@@ -5794,7 +5916,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5794
5916
  stickyPositionComponentInternal,
5795
5917
  stylePaddingBottom: stylePaddingBottomState,
5796
5918
  stylePaddingTop: stylePaddingTopState,
5797
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
5798
5919
  useWindowScroll: useWindowScrollResolved
5799
5920
  };
5800
5921
  state.refScroller = refScroller;