@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.
package/react-native.mjs CHANGED
@@ -1810,17 +1810,42 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
1810
1810
  }
1811
1811
 
1812
1812
  // src/utils/getItemSize.ts
1813
+ function getKnownOrFixedSize(ctx, key, index, data) {
1814
+ var _a3;
1815
+ const state = ctx.state;
1816
+ const { getFixedItemSize, getItemType } = state.props;
1817
+ let size = key ? state.sizesKnown.get(key) : void 0;
1818
+ if (size === void 0 && key && getFixedItemSize) {
1819
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1820
+ size = getFixedItemSize(data, index, itemType);
1821
+ if (size !== void 0) {
1822
+ state.sizesKnown.set(key, size);
1823
+ }
1824
+ }
1825
+ return size;
1826
+ }
1827
+ function getKnownOrFixedItemSize(ctx, index) {
1828
+ const key = getId(ctx.state, index);
1829
+ return getKnownOrFixedSize(ctx, key, index, ctx.state.props.data[index]);
1830
+ }
1831
+ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
1832
+ for (let index = startIndex; index <= endIndex; index++) {
1833
+ if (getKnownOrFixedItemSize(ctx, index) === void 0) {
1834
+ return false;
1835
+ }
1836
+ }
1837
+ return true;
1838
+ }
1813
1839
  function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
1814
1840
  var _a3, _b, _c;
1815
1841
  const state = ctx.state;
1816
1842
  const {
1817
- sizesKnown,
1818
1843
  sizes,
1819
1844
  averageSizes,
1820
- props: { estimatedItemSize, getFixedItemSize, getItemType },
1845
+ props: { estimatedItemSize, getItemType },
1821
1846
  scrollingTo
1822
1847
  } = state;
1823
- const sizeKnown = sizesKnown.get(key);
1848
+ const sizeKnown = state.sizesKnown.get(key);
1824
1849
  if (sizeKnown !== void 0) {
1825
1850
  return sizeKnown;
1826
1851
  }
@@ -1831,14 +1856,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1831
1856
  return renderedSize;
1832
1857
  }
1833
1858
  }
1834
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1835
- if (getFixedItemSize) {
1836
- size = getFixedItemSize(data, index, itemType);
1837
- if (size !== void 0) {
1838
- sizesKnown.set(key, size);
1839
- }
1859
+ size = getKnownOrFixedSize(ctx, key, index, data);
1860
+ if (size !== void 0) {
1861
+ setSize(ctx, key, size, notifyTotalSize);
1862
+ return size;
1840
1863
  }
1841
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1864
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1865
+ if (useAverageSize && !scrollingTo) {
1842
1866
  const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1843
1867
  if (averageSizeForType !== void 0) {
1844
1868
  size = roundSize(averageSizeForType);
@@ -1847,7 +1871,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1847
1871
  if (size === void 0 && renderedSize !== void 0) {
1848
1872
  return renderedSize;
1849
1873
  }
1850
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && scrollingTo) {
1874
+ if (size === void 0 && useAverageSize && scrollingTo) {
1851
1875
  const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
1852
1876
  if (averageSizeForType !== void 0) {
1853
1877
  size = roundSize(averageSizeForType);
@@ -5168,22 +5192,27 @@ var ScrollAdjustHandler = class {
5168
5192
 
5169
5193
  // src/core/updateAnchoredEndSpace.ts
5170
5194
  function maybeUpdateAnchoredEndSpace(ctx) {
5171
- var _a3;
5195
+ var _a3, _b;
5172
5196
  const state = ctx.state;
5173
5197
  const anchoredEndSpace = state.props.anchoredEndSpace;
5174
5198
  const previousSize = peek$(ctx, "anchoredEndSpaceSize");
5199
+ const previousReadyAnchorIndex = state.anchoredEndSpaceReadyAnchorIndex;
5200
+ const previousReadyAnchorKey = state.anchoredEndSpaceReadyAnchorKey;
5201
+ const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
5202
+ let nextAnchorKey;
5203
+ let isReady = true;
5175
5204
  let nextSize = 0;
5176
5205
  if (anchoredEndSpace) {
5177
5206
  const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
5178
5207
  const { data } = state.props;
5179
5208
  if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
5209
+ nextAnchorKey = getId(state, anchorIndex);
5180
5210
  let contentBelowAnchor = 0;
5181
5211
  const footerSize = ctx.values.get("footerSize") || 0;
5182
5212
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
5183
5213
  let hasUnknownTailSize = false;
5184
5214
  for (let index = anchorIndex; index < data.length; index++) {
5185
- const itemKey = getId(state, index);
5186
- const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
5215
+ const size = getKnownOrFixedItemSize(ctx, index);
5187
5216
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
5188
5217
  if (size === void 0) {
5189
5218
  hasUnknownTailSize = true;
@@ -5193,15 +5222,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5193
5222
  }
5194
5223
  }
5195
5224
  contentBelowAnchor += footerSize + stylePaddingBottom;
5225
+ isReady = !hasUnknownTailSize;
5196
5226
  nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5227
+ } else if (anchorIndex >= 0) {
5228
+ isReady = false;
5197
5229
  }
5198
5230
  }
5199
- if (previousSize !== nextSize) {
5200
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5201
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5202
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5231
+ const didSizeChange = previousSize !== nextSize;
5232
+ const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
5233
+ if (isReady && (didSizeChange || didReadyAnchorChange)) {
5234
+ state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
5235
+ state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
5236
+ if (didSizeChange) {
5237
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5238
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5239
+ }
5240
+ if (didSizeChange && (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset)) {
5203
5241
  updateScroll(ctx, state.scroll, true);
5204
5242
  }
5243
+ (_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
5205
5244
  }
5206
5245
  return nextSize;
5207
5246
  }
@@ -5452,6 +5491,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
5452
5491
  }
5453
5492
  }
5454
5493
 
5494
+ // src/core/scrollToEnd.ts
5495
+ function scrollToEnd(ctx, options) {
5496
+ const state = ctx.state;
5497
+ const data = state.props.data;
5498
+ const index = data.length - 1;
5499
+ if (index === -1) {
5500
+ return false;
5501
+ }
5502
+ const paddingBottom = state.props.stylePaddingBottom || 0;
5503
+ const footerSize = peek$(ctx, "footerSize") || 0;
5504
+ scrollToIndex(ctx, {
5505
+ ...options,
5506
+ index,
5507
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
5508
+ viewPosition: 1
5509
+ });
5510
+ return true;
5511
+ }
5512
+
5455
5513
  // src/utils/createImperativeHandle.ts
5456
5514
  var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
5457
5515
  function getAverageItemSizes(state) {
@@ -5467,7 +5525,7 @@ function getAverageItemSizes(state) {
5467
5525
  }
5468
5526
  return averageItemSizes;
5469
5527
  }
5470
- function createImperativeHandle(ctx) {
5528
+ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5471
5529
  const state = ctx.state;
5472
5530
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
5473
5531
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
@@ -5484,15 +5542,10 @@ function createImperativeHandle(ctx) {
5484
5542
  if (targetIndex >= dataLength) {
5485
5543
  return false;
5486
5544
  }
5487
- if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
5545
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
5488
5546
  return true;
5489
5547
  }
5490
- for (let index = anchorIndex; index < dataLength; index++) {
5491
- if (!state.sizesKnown.has(getId(state, index))) {
5492
- return false;
5493
- }
5494
- }
5495
- return true;
5548
+ return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
5496
5549
  };
5497
5550
  const runWhenReady = (token, run, isReady) => {
5498
5551
  const startedAt = Date.now();
@@ -5515,11 +5568,7 @@ function createImperativeHandle(ctx) {
5515
5568
  };
5516
5569
  requestAnimationFrame(check);
5517
5570
  };
5518
- const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
5519
- var _a3;
5520
- const token = ++imperativeScrollToken;
5521
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5522
- state.pendingScrollResolve = resolve;
5571
+ const runScrollRequest = (token, resolve, run, isReady = () => true) => {
5523
5572
  const runNow = () => {
5524
5573
  if (token !== imperativeScrollToken) {
5525
5574
  return;
@@ -5537,7 +5586,33 @@ function createImperativeHandle(ctx) {
5537
5586
  } else {
5538
5587
  runNow();
5539
5588
  }
5589
+ };
5590
+ const startImperativeScroll = (resolve) => {
5591
+ var _a3;
5592
+ const token = ++imperativeScrollToken;
5593
+ state.pendingScrollToEnd = void 0;
5594
+ (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5595
+ state.pendingScrollResolve = resolve;
5596
+ return token;
5597
+ };
5598
+ const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
5599
+ const token = startImperativeScroll(resolve);
5600
+ runScrollRequest(token, resolve, run, isReady);
5540
5601
  });
5602
+ state.runPendingScrollToEnd = () => {
5603
+ const pendingScroll = state.pendingScrollToEnd;
5604
+ if (pendingScroll) {
5605
+ state.pendingScrollToEnd = void 0;
5606
+ if (pendingScroll.token === imperativeScrollToken) {
5607
+ runScrollRequest(
5608
+ pendingScroll.token,
5609
+ pendingScroll.resolve,
5610
+ () => scrollToEnd(ctx, pendingScroll.options),
5611
+ () => isScrollToIndexReady(state.props.data.length - 1, true)
5612
+ );
5613
+ }
5614
+ }
5615
+ };
5541
5616
  const scrollIndexIntoView = (options) => {
5542
5617
  if (state) {
5543
5618
  const { index, ...rest } = options;
@@ -5636,26 +5711,20 @@ function createImperativeHandle(ctx) {
5636
5711
  }
5637
5712
  return false;
5638
5713
  }),
5639
- scrollToEnd: (options) => runScrollWithPromise(
5640
- () => {
5641
- const data = state.props.data;
5642
- const stylePaddingBottom = state.props.stylePaddingBottom;
5643
- const index = data.length - 1;
5644
- if (index !== -1) {
5645
- const paddingBottom = stylePaddingBottom || 0;
5646
- const footerSize = peek$(ctx, "footerSize") || 0;
5647
- scrollToIndex(ctx, {
5648
- ...options,
5649
- index,
5650
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
5651
- viewPosition: 1
5652
- });
5653
- return true;
5654
- }
5655
- return false;
5656
- },
5657
- () => isScrollToIndexReady(state.props.data.length - 1, true)
5658
- ),
5714
+ scrollToEnd: (options) => new Promise((resolve) => {
5715
+ var _a3;
5716
+ const token = startImperativeScroll(resolve);
5717
+ state.pendingScrollToEnd = {
5718
+ options,
5719
+ resolve,
5720
+ token
5721
+ };
5722
+ if (scheduleImperativeScrollCommit) {
5723
+ scheduleImperativeScrollCommit();
5724
+ } else {
5725
+ (_a3 = state.runPendingScrollToEnd) == null ? void 0 : _a3.call(state);
5726
+ }
5727
+ }),
5659
5728
  scrollToIndex: (params) => {
5660
5729
  return runScrollWithPromise(
5661
5730
  () => {
@@ -6025,6 +6094,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6025
6094
  viewOffset: 0
6026
6095
  } : void 0;
6027
6096
  const [canRender, setCanRender] = React2.useState(!IsNewArchitecture);
6097
+ const [, scheduleImperativeScrollCommit] = React2.useReducer((value) => value + 1, 0);
6028
6098
  const ctx = useStateContext();
6029
6099
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
6030
6100
  const refScroller = useRef(null);
@@ -6397,7 +6467,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6397
6467
  doInitialAllocateContainers(ctx);
6398
6468
  }
6399
6469
  });
6400
- useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
6470
+ useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
6471
+ useLayoutEffect(() => {
6472
+ var _a4;
6473
+ (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
6474
+ });
6401
6475
  useEffect(() => {
6402
6476
  if (Platform.OS !== "web" || usesBootstrapInitialScroll) {
6403
6477
  return;
@@ -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.
@@ -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;