@legendapp/list 3.0.3 → 3.0.4

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.
@@ -2441,17 +2441,42 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2441
2441
  }
2442
2442
 
2443
2443
  // src/utils/getItemSize.ts
2444
+ function getKnownOrFixedSize(ctx, key, index, data) {
2445
+ var _a3;
2446
+ const state = ctx.state;
2447
+ const { getFixedItemSize, getItemType } = state.props;
2448
+ let size = key ? state.sizesKnown.get(key) : void 0;
2449
+ if (size === void 0 && key && getFixedItemSize) {
2450
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2451
+ size = getFixedItemSize(data, index, itemType);
2452
+ if (size !== void 0) {
2453
+ state.sizesKnown.set(key, size);
2454
+ }
2455
+ }
2456
+ return size;
2457
+ }
2458
+ function getKnownOrFixedItemSize(ctx, index) {
2459
+ const key = getId(ctx.state, index);
2460
+ return getKnownOrFixedSize(ctx, key, index, ctx.state.props.data[index]);
2461
+ }
2462
+ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
2463
+ for (let index = startIndex; index <= endIndex; index++) {
2464
+ if (getKnownOrFixedItemSize(ctx, index) === void 0) {
2465
+ return false;
2466
+ }
2467
+ }
2468
+ return true;
2469
+ }
2444
2470
  function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2445
2471
  var _a3, _b, _c;
2446
2472
  const state = ctx.state;
2447
2473
  const {
2448
- sizesKnown,
2449
2474
  sizes,
2450
2475
  averageSizes,
2451
- props: { estimatedItemSize, getFixedItemSize, getItemType },
2476
+ props: { estimatedItemSize, getItemType },
2452
2477
  scrollingTo
2453
2478
  } = state;
2454
- const sizeKnown = sizesKnown.get(key);
2479
+ const sizeKnown = state.sizesKnown.get(key);
2455
2480
  if (sizeKnown !== void 0) {
2456
2481
  return sizeKnown;
2457
2482
  }
@@ -2462,14 +2487,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2462
2487
  return renderedSize;
2463
2488
  }
2464
2489
  }
2465
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2466
- if (getFixedItemSize) {
2467
- size = getFixedItemSize(data, index, itemType);
2468
- if (size !== void 0) {
2469
- sizesKnown.set(key, size);
2470
- }
2490
+ size = getKnownOrFixedSize(ctx, key, index, data);
2491
+ if (size !== void 0) {
2492
+ setSize(ctx, key, size, notifyTotalSize);
2493
+ return size;
2471
2494
  }
2472
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
2495
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2496
+ if (useAverageSize && !scrollingTo) {
2473
2497
  const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
2474
2498
  if (averageSizeForType !== void 0) {
2475
2499
  size = roundSize(averageSizeForType);
@@ -2478,7 +2502,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2478
2502
  if (size === void 0 && renderedSize !== void 0) {
2479
2503
  return renderedSize;
2480
2504
  }
2481
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && scrollingTo) {
2505
+ if (size === void 0 && useAverageSize && scrollingTo) {
2482
2506
  const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
2483
2507
  if (averageSizeForType !== void 0) {
2484
2508
  size = roundSize(averageSizeForType);
@@ -5798,22 +5822,27 @@ var ScrollAdjustHandler = class {
5798
5822
 
5799
5823
  // src/core/updateAnchoredEndSpace.ts
5800
5824
  function maybeUpdateAnchoredEndSpace(ctx) {
5801
- var _a3;
5825
+ var _a3, _b;
5802
5826
  const state = ctx.state;
5803
5827
  const anchoredEndSpace = state.props.anchoredEndSpace;
5804
5828
  const previousSize = peek$(ctx, "anchoredEndSpaceSize");
5829
+ const previousReadyAnchorIndex = state.anchoredEndSpaceReadyAnchorIndex;
5830
+ const previousReadyAnchorKey = state.anchoredEndSpaceReadyAnchorKey;
5831
+ const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
5832
+ let nextAnchorKey;
5833
+ let isReady = true;
5805
5834
  let nextSize = 0;
5806
5835
  if (anchoredEndSpace) {
5807
5836
  const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
5808
5837
  const { data } = state.props;
5809
5838
  if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
5839
+ nextAnchorKey = getId(state, anchorIndex);
5810
5840
  let contentBelowAnchor = 0;
5811
5841
  const footerSize = ctx.values.get("footerSize") || 0;
5812
5842
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
5813
5843
  let hasUnknownTailSize = false;
5814
5844
  for (let index = anchorIndex; index < data.length; index++) {
5815
- const itemKey = getId(state, index);
5816
- const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
5845
+ const size = getKnownOrFixedItemSize(ctx, index);
5817
5846
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
5818
5847
  if (size === void 0) {
5819
5848
  hasUnknownTailSize = true;
@@ -5823,15 +5852,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5823
5852
  }
5824
5853
  }
5825
5854
  contentBelowAnchor += footerSize + stylePaddingBottom;
5855
+ isReady = !hasUnknownTailSize;
5826
5856
  nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5857
+ } else if (anchorIndex >= 0) {
5858
+ isReady = false;
5827
5859
  }
5828
5860
  }
5829
- if (previousSize !== nextSize) {
5830
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5831
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5832
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5861
+ const didSizeChange = previousSize !== nextSize;
5862
+ const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
5863
+ if (isReady && (didSizeChange || didReadyAnchorChange)) {
5864
+ state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
5865
+ state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
5866
+ if (didSizeChange) {
5867
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5868
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5869
+ }
5870
+ if (didSizeChange && (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset)) {
5833
5871
  updateScroll(ctx, state.scroll, true);
5834
5872
  }
5873
+ (_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
5835
5874
  }
5836
5875
  return nextSize;
5837
5876
  }
@@ -6064,6 +6103,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
6064
6103
  }
6065
6104
  }
6066
6105
 
6106
+ // src/core/scrollToEnd.ts
6107
+ function scrollToEnd(ctx, options) {
6108
+ const state = ctx.state;
6109
+ const data = state.props.data;
6110
+ const index = data.length - 1;
6111
+ if (index === -1) {
6112
+ return false;
6113
+ }
6114
+ const paddingBottom = state.props.stylePaddingBottom || 0;
6115
+ const footerSize = peek$(ctx, "footerSize") || 0;
6116
+ scrollToIndex(ctx, {
6117
+ ...options,
6118
+ index,
6119
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6120
+ viewPosition: 1
6121
+ });
6122
+ return true;
6123
+ }
6124
+
6067
6125
  // src/utils/createImperativeHandle.ts
6068
6126
  var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
6069
6127
  function getAverageItemSizes(state) {
@@ -6079,7 +6137,7 @@ function getAverageItemSizes(state) {
6079
6137
  }
6080
6138
  return averageItemSizes;
6081
6139
  }
6082
- function createImperativeHandle(ctx) {
6140
+ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6083
6141
  const state = ctx.state;
6084
6142
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
6085
6143
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
@@ -6096,15 +6154,10 @@ function createImperativeHandle(ctx) {
6096
6154
  if (targetIndex >= dataLength) {
6097
6155
  return false;
6098
6156
  }
6099
- if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
6157
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
6100
6158
  return true;
6101
6159
  }
6102
- for (let index = anchorIndex; index < dataLength; index++) {
6103
- if (!state.sizesKnown.has(getId(state, index))) {
6104
- return false;
6105
- }
6106
- }
6107
- return true;
6160
+ return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
6108
6161
  };
6109
6162
  const runWhenReady = (token, run, isReady) => {
6110
6163
  const startedAt = Date.now();
@@ -6127,11 +6180,7 @@ function createImperativeHandle(ctx) {
6127
6180
  };
6128
6181
  requestAnimationFrame(check);
6129
6182
  };
6130
- const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6131
- var _a3;
6132
- const token = ++imperativeScrollToken;
6133
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6134
- state.pendingScrollResolve = resolve;
6183
+ const runScrollRequest = (token, resolve, run, isReady = () => true) => {
6135
6184
  const runNow = () => {
6136
6185
  if (token !== imperativeScrollToken) {
6137
6186
  return;
@@ -6149,7 +6198,33 @@ function createImperativeHandle(ctx) {
6149
6198
  } else {
6150
6199
  runNow();
6151
6200
  }
6201
+ };
6202
+ const startImperativeScroll = (resolve) => {
6203
+ var _a3;
6204
+ const token = ++imperativeScrollToken;
6205
+ state.pendingScrollToEnd = void 0;
6206
+ (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6207
+ state.pendingScrollResolve = resolve;
6208
+ return token;
6209
+ };
6210
+ const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6211
+ const token = startImperativeScroll(resolve);
6212
+ runScrollRequest(token, resolve, run, isReady);
6152
6213
  });
6214
+ state.runPendingScrollToEnd = () => {
6215
+ const pendingScroll = state.pendingScrollToEnd;
6216
+ if (pendingScroll) {
6217
+ state.pendingScrollToEnd = void 0;
6218
+ if (pendingScroll.token === imperativeScrollToken) {
6219
+ runScrollRequest(
6220
+ pendingScroll.token,
6221
+ pendingScroll.resolve,
6222
+ () => scrollToEnd(ctx, pendingScroll.options),
6223
+ () => isScrollToIndexReady(state.props.data.length - 1, true)
6224
+ );
6225
+ }
6226
+ }
6227
+ };
6153
6228
  const scrollIndexIntoView = (options) => {
6154
6229
  if (state) {
6155
6230
  const { index, ...rest } = options;
@@ -6248,26 +6323,20 @@ function createImperativeHandle(ctx) {
6248
6323
  }
6249
6324
  return false;
6250
6325
  }),
6251
- scrollToEnd: (options) => runScrollWithPromise(
6252
- () => {
6253
- const data = state.props.data;
6254
- const stylePaddingBottom = state.props.stylePaddingBottom;
6255
- const index = data.length - 1;
6256
- if (index !== -1) {
6257
- const paddingBottom = stylePaddingBottom || 0;
6258
- const footerSize = peek$(ctx, "footerSize") || 0;
6259
- scrollToIndex(ctx, {
6260
- ...options,
6261
- index,
6262
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6263
- viewPosition: 1
6264
- });
6265
- return true;
6266
- }
6267
- return false;
6268
- },
6269
- () => isScrollToIndexReady(state.props.data.length - 1, true)
6270
- ),
6326
+ scrollToEnd: (options) => new Promise((resolve) => {
6327
+ var _a3;
6328
+ const token = startImperativeScroll(resolve);
6329
+ state.pendingScrollToEnd = {
6330
+ options,
6331
+ resolve,
6332
+ token
6333
+ };
6334
+ if (scheduleImperativeScrollCommit) {
6335
+ scheduleImperativeScrollCommit();
6336
+ } else {
6337
+ (_a3 = state.runPendingScrollToEnd) == null ? void 0 : _a3.call(state);
6338
+ }
6339
+ }),
6271
6340
  scrollToIndex: (params) => {
6272
6341
  return runScrollWithPromise(
6273
6342
  () => {
@@ -6637,6 +6706,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6637
6706
  viewOffset: 0
6638
6707
  } : void 0;
6639
6708
  const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
6709
+ const [, scheduleImperativeScrollCommit] = React3.useReducer((value) => value + 1, 0);
6640
6710
  const ctx = useStateContext();
6641
6711
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
6642
6712
  const refScroller = useRef(null);
@@ -7001,7 +7071,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7001
7071
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
7002
7072
  useInit(() => {
7003
7073
  });
7004
- useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
7074
+ useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7075
+ useLayoutEffect(() => {
7076
+ var _a4;
7077
+ (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
7078
+ });
7005
7079
  useEffect(() => {
7006
7080
  if (usesBootstrapInitialScroll) {
7007
7081
  return;
package/react.d.ts CHANGED
@@ -417,12 +417,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
417
417
  size?: boolean;
418
418
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
419
419
  }
420
+ interface AnchoredEndSpaceReadyInfo {
421
+ anchorIndex: number | undefined;
422
+ anchorKey: string | undefined;
423
+ size: number;
424
+ }
425
+ interface ScrollToEndOptions {
426
+ animated?: boolean;
427
+ viewOffset?: number;
428
+ }
420
429
  interface AnchoredEndSpaceConfig$1 {
421
430
  anchorIndex: number;
422
431
  anchorOffset?: number;
423
432
  anchorMaxSize?: number;
424
433
  includeInEndInset?: boolean;
425
434
  onSizeChanged?: (size: number) => void;
435
+ onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
426
436
  }
427
437
  interface StickyHeaderConfig {
428
438
  /**
@@ -554,10 +564,7 @@ type LegendListRef$1 = {
554
564
  * @param options.animated - If true, animates the scroll. Default: true.
555
565
  * @param options.viewOffset - Offset from the target position.
556
566
  */
557
- scrollToEnd(options?: {
558
- animated?: boolean | undefined;
559
- viewOffset?: number | undefined;
560
- }): Promise<void>;
567
+ scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
561
568
  /**
562
569
  * Scrolls to a specific index in the list.
563
570
  * @param params - Parameters for scrolling.
package/react.js CHANGED
@@ -2462,17 +2462,42 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2462
2462
  }
2463
2463
 
2464
2464
  // src/utils/getItemSize.ts
2465
+ function getKnownOrFixedSize(ctx, key, index, data) {
2466
+ var _a3;
2467
+ const state = ctx.state;
2468
+ const { getFixedItemSize, getItemType } = state.props;
2469
+ let size = key ? state.sizesKnown.get(key) : void 0;
2470
+ if (size === void 0 && key && getFixedItemSize) {
2471
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2472
+ size = getFixedItemSize(data, index, itemType);
2473
+ if (size !== void 0) {
2474
+ state.sizesKnown.set(key, size);
2475
+ }
2476
+ }
2477
+ return size;
2478
+ }
2479
+ function getKnownOrFixedItemSize(ctx, index) {
2480
+ const key = getId(ctx.state, index);
2481
+ return getKnownOrFixedSize(ctx, key, index, ctx.state.props.data[index]);
2482
+ }
2483
+ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
2484
+ for (let index = startIndex; index <= endIndex; index++) {
2485
+ if (getKnownOrFixedItemSize(ctx, index) === void 0) {
2486
+ return false;
2487
+ }
2488
+ }
2489
+ return true;
2490
+ }
2465
2491
  function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2466
2492
  var _a3, _b, _c;
2467
2493
  const state = ctx.state;
2468
2494
  const {
2469
- sizesKnown,
2470
2495
  sizes,
2471
2496
  averageSizes,
2472
- props: { estimatedItemSize, getFixedItemSize, getItemType },
2497
+ props: { estimatedItemSize, getItemType },
2473
2498
  scrollingTo
2474
2499
  } = state;
2475
- const sizeKnown = sizesKnown.get(key);
2500
+ const sizeKnown = state.sizesKnown.get(key);
2476
2501
  if (sizeKnown !== void 0) {
2477
2502
  return sizeKnown;
2478
2503
  }
@@ -2483,14 +2508,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2483
2508
  return renderedSize;
2484
2509
  }
2485
2510
  }
2486
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2487
- if (getFixedItemSize) {
2488
- size = getFixedItemSize(data, index, itemType);
2489
- if (size !== void 0) {
2490
- sizesKnown.set(key, size);
2491
- }
2511
+ size = getKnownOrFixedSize(ctx, key, index, data);
2512
+ if (size !== void 0) {
2513
+ setSize(ctx, key, size, notifyTotalSize);
2514
+ return size;
2492
2515
  }
2493
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
2516
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2517
+ if (useAverageSize && !scrollingTo) {
2494
2518
  const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
2495
2519
  if (averageSizeForType !== void 0) {
2496
2520
  size = roundSize(averageSizeForType);
@@ -2499,7 +2523,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2499
2523
  if (size === void 0 && renderedSize !== void 0) {
2500
2524
  return renderedSize;
2501
2525
  }
2502
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && scrollingTo) {
2526
+ if (size === void 0 && useAverageSize && scrollingTo) {
2503
2527
  const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
2504
2528
  if (averageSizeForType !== void 0) {
2505
2529
  size = roundSize(averageSizeForType);
@@ -5819,22 +5843,27 @@ var ScrollAdjustHandler = class {
5819
5843
 
5820
5844
  // src/core/updateAnchoredEndSpace.ts
5821
5845
  function maybeUpdateAnchoredEndSpace(ctx) {
5822
- var _a3;
5846
+ var _a3, _b;
5823
5847
  const state = ctx.state;
5824
5848
  const anchoredEndSpace = state.props.anchoredEndSpace;
5825
5849
  const previousSize = peek$(ctx, "anchoredEndSpaceSize");
5850
+ const previousReadyAnchorIndex = state.anchoredEndSpaceReadyAnchorIndex;
5851
+ const previousReadyAnchorKey = state.anchoredEndSpaceReadyAnchorKey;
5852
+ const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
5853
+ let nextAnchorKey;
5854
+ let isReady = true;
5826
5855
  let nextSize = 0;
5827
5856
  if (anchoredEndSpace) {
5828
5857
  const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
5829
5858
  const { data } = state.props;
5830
5859
  if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
5860
+ nextAnchorKey = getId(state, anchorIndex);
5831
5861
  let contentBelowAnchor = 0;
5832
5862
  const footerSize = ctx.values.get("footerSize") || 0;
5833
5863
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
5834
5864
  let hasUnknownTailSize = false;
5835
5865
  for (let index = anchorIndex; index < data.length; index++) {
5836
- const itemKey = getId(state, index);
5837
- const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
5866
+ const size = getKnownOrFixedItemSize(ctx, index);
5838
5867
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
5839
5868
  if (size === void 0) {
5840
5869
  hasUnknownTailSize = true;
@@ -5844,15 +5873,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5844
5873
  }
5845
5874
  }
5846
5875
  contentBelowAnchor += footerSize + stylePaddingBottom;
5876
+ isReady = !hasUnknownTailSize;
5847
5877
  nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5878
+ } else if (anchorIndex >= 0) {
5879
+ isReady = false;
5848
5880
  }
5849
5881
  }
5850
- if (previousSize !== nextSize) {
5851
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5852
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5853
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5882
+ const didSizeChange = previousSize !== nextSize;
5883
+ const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
5884
+ if (isReady && (didSizeChange || didReadyAnchorChange)) {
5885
+ state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
5886
+ state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
5887
+ if (didSizeChange) {
5888
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5889
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5890
+ }
5891
+ if (didSizeChange && (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset)) {
5854
5892
  updateScroll(ctx, state.scroll, true);
5855
5893
  }
5894
+ (_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
5856
5895
  }
5857
5896
  return nextSize;
5858
5897
  }
@@ -6085,6 +6124,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
6085
6124
  }
6086
6125
  }
6087
6126
 
6127
+ // src/core/scrollToEnd.ts
6128
+ function scrollToEnd(ctx, options) {
6129
+ const state = ctx.state;
6130
+ const data = state.props.data;
6131
+ const index = data.length - 1;
6132
+ if (index === -1) {
6133
+ return false;
6134
+ }
6135
+ const paddingBottom = state.props.stylePaddingBottom || 0;
6136
+ const footerSize = peek$(ctx, "footerSize") || 0;
6137
+ scrollToIndex(ctx, {
6138
+ ...options,
6139
+ index,
6140
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6141
+ viewPosition: 1
6142
+ });
6143
+ return true;
6144
+ }
6145
+
6088
6146
  // src/utils/createImperativeHandle.ts
6089
6147
  var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
6090
6148
  function getAverageItemSizes(state) {
@@ -6100,7 +6158,7 @@ function getAverageItemSizes(state) {
6100
6158
  }
6101
6159
  return averageItemSizes;
6102
6160
  }
6103
- function createImperativeHandle(ctx) {
6161
+ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6104
6162
  const state = ctx.state;
6105
6163
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
6106
6164
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
@@ -6117,15 +6175,10 @@ function createImperativeHandle(ctx) {
6117
6175
  if (targetIndex >= dataLength) {
6118
6176
  return false;
6119
6177
  }
6120
- if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
6178
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
6121
6179
  return true;
6122
6180
  }
6123
- for (let index = anchorIndex; index < dataLength; index++) {
6124
- if (!state.sizesKnown.has(getId(state, index))) {
6125
- return false;
6126
- }
6127
- }
6128
- return true;
6181
+ return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
6129
6182
  };
6130
6183
  const runWhenReady = (token, run, isReady) => {
6131
6184
  const startedAt = Date.now();
@@ -6148,11 +6201,7 @@ function createImperativeHandle(ctx) {
6148
6201
  };
6149
6202
  requestAnimationFrame(check);
6150
6203
  };
6151
- const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6152
- var _a3;
6153
- const token = ++imperativeScrollToken;
6154
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6155
- state.pendingScrollResolve = resolve;
6204
+ const runScrollRequest = (token, resolve, run, isReady = () => true) => {
6156
6205
  const runNow = () => {
6157
6206
  if (token !== imperativeScrollToken) {
6158
6207
  return;
@@ -6170,7 +6219,33 @@ function createImperativeHandle(ctx) {
6170
6219
  } else {
6171
6220
  runNow();
6172
6221
  }
6222
+ };
6223
+ const startImperativeScroll = (resolve) => {
6224
+ var _a3;
6225
+ const token = ++imperativeScrollToken;
6226
+ state.pendingScrollToEnd = void 0;
6227
+ (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6228
+ state.pendingScrollResolve = resolve;
6229
+ return token;
6230
+ };
6231
+ const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6232
+ const token = startImperativeScroll(resolve);
6233
+ runScrollRequest(token, resolve, run, isReady);
6173
6234
  });
6235
+ state.runPendingScrollToEnd = () => {
6236
+ const pendingScroll = state.pendingScrollToEnd;
6237
+ if (pendingScroll) {
6238
+ state.pendingScrollToEnd = void 0;
6239
+ if (pendingScroll.token === imperativeScrollToken) {
6240
+ runScrollRequest(
6241
+ pendingScroll.token,
6242
+ pendingScroll.resolve,
6243
+ () => scrollToEnd(ctx, pendingScroll.options),
6244
+ () => isScrollToIndexReady(state.props.data.length - 1, true)
6245
+ );
6246
+ }
6247
+ }
6248
+ };
6174
6249
  const scrollIndexIntoView = (options) => {
6175
6250
  if (state) {
6176
6251
  const { index, ...rest } = options;
@@ -6269,26 +6344,20 @@ function createImperativeHandle(ctx) {
6269
6344
  }
6270
6345
  return false;
6271
6346
  }),
6272
- scrollToEnd: (options) => runScrollWithPromise(
6273
- () => {
6274
- const data = state.props.data;
6275
- const stylePaddingBottom = state.props.stylePaddingBottom;
6276
- const index = data.length - 1;
6277
- if (index !== -1) {
6278
- const paddingBottom = stylePaddingBottom || 0;
6279
- const footerSize = peek$(ctx, "footerSize") || 0;
6280
- scrollToIndex(ctx, {
6281
- ...options,
6282
- index,
6283
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6284
- viewPosition: 1
6285
- });
6286
- return true;
6287
- }
6288
- return false;
6289
- },
6290
- () => isScrollToIndexReady(state.props.data.length - 1, true)
6291
- ),
6347
+ scrollToEnd: (options) => new Promise((resolve) => {
6348
+ var _a3;
6349
+ const token = startImperativeScroll(resolve);
6350
+ state.pendingScrollToEnd = {
6351
+ options,
6352
+ resolve,
6353
+ token
6354
+ };
6355
+ if (scheduleImperativeScrollCommit) {
6356
+ scheduleImperativeScrollCommit();
6357
+ } else {
6358
+ (_a3 = state.runPendingScrollToEnd) == null ? void 0 : _a3.call(state);
6359
+ }
6360
+ }),
6292
6361
  scrollToIndex: (params) => {
6293
6362
  return runScrollWithPromise(
6294
6363
  () => {
@@ -6658,6 +6727,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6658
6727
  viewOffset: 0
6659
6728
  } : void 0;
6660
6729
  const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
6730
+ const [, scheduleImperativeScrollCommit] = React3__namespace.useReducer((value) => value + 1, 0);
6661
6731
  const ctx = useStateContext();
6662
6732
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
6663
6733
  const refScroller = React3.useRef(null);
@@ -7022,7 +7092,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7022
7092
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
7023
7093
  useInit(() => {
7024
7094
  });
7025
- React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
7095
+ React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7096
+ React3.useLayoutEffect(() => {
7097
+ var _a4;
7098
+ (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
7099
+ });
7026
7100
  React3.useEffect(() => {
7027
7101
  if (usesBootstrapInitialScroll) {
7028
7102
  return;