@legendapp/list 3.0.2 → 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.mjs CHANGED
@@ -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);
@@ -3085,7 +3109,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3085
3109
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
3086
3110
  state.mvcpAnchorLock = void 0;
3087
3111
  state.pendingNativeMVCPAdjust = void 0;
3088
- state.userScrollAnchorResetKeys = /* @__PURE__ */ new Set();
3112
+ state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
3089
3113
  if (state.queuedMVCPRecalculate !== void 0) {
3090
3114
  cancelAnimationFrame(state.queuedMVCPRecalculate);
3091
3115
  state.queuedMVCPRecalculate = void 0;
@@ -5048,7 +5072,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
5048
5072
  function calculateItemsInView(ctx, params = {}) {
5049
5073
  const state = ctx.state;
5050
5074
  batchedUpdates(() => {
5051
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
5075
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
5052
5076
  const {
5053
5077
  columns,
5054
5078
  containerItemKeys,
@@ -5362,7 +5386,7 @@ function calculateItemsInView(ctx, params = {}) {
5362
5386
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
5363
5387
  }
5364
5388
  containerItemKeys.set(id, containerIndex);
5365
- (_o = state.userScrollAnchorResetKeys) == null ? void 0 : _o.add(id);
5389
+ (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
5366
5390
  const containerSticky = `containerSticky${containerIndex}`;
5367
5391
  const isSticky = stickyHeaderIndicesSet.has(i);
5368
5392
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5390,13 +5414,17 @@ function calculateItemsInView(ctx, params = {}) {
5390
5414
  }
5391
5415
  }
5392
5416
  }
5393
- if (((_p = state.userScrollAnchorResetKeys) == null ? void 0 : _p.size) === 0) {
5394
- state.userScrollAnchorResetKeys = void 0;
5417
+ if (state.userScrollAnchorReset) {
5418
+ if (state.userScrollAnchorReset.keys.size === 0) {
5419
+ state.userScrollAnchorReset = void 0;
5420
+ } else {
5421
+ state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5422
+ }
5395
5423
  }
5396
5424
  if (alwaysRenderArr.length > 0) {
5397
5425
  for (const index of alwaysRenderArr) {
5398
5426
  if (index < 0 || index >= dataLength) continue;
5399
- const id = (_q = idCache[index]) != null ? _q : getId(state, index);
5427
+ const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5400
5428
  const containerIndex = containerItemKeys.get(id);
5401
5429
  if (containerIndex !== void 0) {
5402
5430
  state.stickyContainerPool.add(containerIndex);
@@ -5794,22 +5822,27 @@ var ScrollAdjustHandler = class {
5794
5822
 
5795
5823
  // src/core/updateAnchoredEndSpace.ts
5796
5824
  function maybeUpdateAnchoredEndSpace(ctx) {
5797
- var _a3;
5825
+ var _a3, _b;
5798
5826
  const state = ctx.state;
5799
5827
  const anchoredEndSpace = state.props.anchoredEndSpace;
5800
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;
5801
5834
  let nextSize = 0;
5802
5835
  if (anchoredEndSpace) {
5803
5836
  const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
5804
5837
  const { data } = state.props;
5805
5838
  if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
5839
+ nextAnchorKey = getId(state, anchorIndex);
5806
5840
  let contentBelowAnchor = 0;
5807
5841
  const footerSize = ctx.values.get("footerSize") || 0;
5808
5842
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
5809
5843
  let hasUnknownTailSize = false;
5810
5844
  for (let index = anchorIndex; index < data.length; index++) {
5811
- const itemKey = getId(state, index);
5812
- const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
5845
+ const size = getKnownOrFixedItemSize(ctx, index);
5813
5846
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
5814
5847
  if (size === void 0) {
5815
5848
  hasUnknownTailSize = true;
@@ -5819,15 +5852,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5819
5852
  }
5820
5853
  }
5821
5854
  contentBelowAnchor += footerSize + stylePaddingBottom;
5855
+ isReady = !hasUnknownTailSize;
5822
5856
  nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5857
+ } else if (anchorIndex >= 0) {
5858
+ isReady = false;
5823
5859
  }
5824
5860
  }
5825
- if (previousSize !== nextSize) {
5826
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5827
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5828
- 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)) {
5829
5871
  updateScroll(ctx, state.scroll, true);
5830
5872
  }
5873
+ (_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
5831
5874
  }
5832
5875
  return nextSize;
5833
5876
  }
@@ -5850,37 +5893,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
5850
5893
 
5851
5894
  // src/core/updateItemSize.ts
5852
5895
  function runOrScheduleMVCPRecalculate(ctx) {
5896
+ var _a3, _b;
5853
5897
  const state = ctx.state;
5854
- if (state.userScrollAnchorResetKeys !== void 0) {
5855
- if (state.queuedMVCPRecalculate !== void 0) {
5856
- return;
5857
- }
5858
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5859
- var _a3;
5860
- state.queuedMVCPRecalculate = void 0;
5898
+ if (state.userScrollAnchorReset !== void 0) {
5899
+ const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
5900
+ const replacementMeasurementBatchThreshold = 3;
5901
+ const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
5902
+ if (shouldBatchReplacementMeasurements) {
5903
+ if (state.queuedMVCPRecalculate === void 0) {
5904
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5905
+ var _a4;
5906
+ state.queuedMVCPRecalculate = void 0;
5907
+ calculateItemsInView(ctx);
5908
+ if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
5909
+ state.userScrollAnchorReset = void 0;
5910
+ }
5911
+ });
5912
+ }
5913
+ } else {
5861
5914
  calculateItemsInView(ctx);
5862
- if (((_a3 = state.userScrollAnchorResetKeys) == null ? void 0 : _a3.size) === 0) {
5863
- state.userScrollAnchorResetKeys = void 0;
5915
+ if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
5916
+ state.userScrollAnchorReset = void 0;
5864
5917
  }
5865
- });
5866
- return;
5867
- }
5868
- {
5918
+ }
5919
+ } else {
5869
5920
  if (!state.mvcpAnchorLock) {
5870
5921
  if (state.queuedMVCPRecalculate !== void 0) {
5871
5922
  cancelAnimationFrame(state.queuedMVCPRecalculate);
5872
5923
  state.queuedMVCPRecalculate = void 0;
5873
5924
  }
5874
5925
  calculateItemsInView(ctx, { doMVCP: true });
5875
- return;
5876
- }
5877
- if (state.queuedMVCPRecalculate !== void 0) {
5878
- return;
5926
+ } else if (state.queuedMVCPRecalculate === void 0) {
5927
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5928
+ state.queuedMVCPRecalculate = void 0;
5929
+ calculateItemsInView(ctx, { doMVCP: true });
5930
+ });
5879
5931
  }
5880
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
5881
- state.queuedMVCPRecalculate = void 0;
5882
- calculateItemsInView(ctx, { doMVCP: true });
5883
- });
5884
5932
  }
5885
5933
  }
5886
5934
  function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
@@ -5896,8 +5944,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5896
5944
  function updateItemSize(ctx, itemKey, sizeObj) {
5897
5945
  var _a3;
5898
5946
  const state = ctx.state;
5899
- const userScrollAnchorResetKeys = state.userScrollAnchorResetKeys;
5900
- const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.delete(itemKey));
5947
+ const userScrollAnchorReset = state.userScrollAnchorReset;
5948
+ const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
5901
5949
  const {
5902
5950
  didContainersLayout,
5903
5951
  sizesKnown,
@@ -5953,8 +6001,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5953
6001
  if (needsRecalculate) {
5954
6002
  state.scrollForNextCalculateItemsInView = void 0;
5955
6003
  runOrScheduleMVCPRecalculate(ctx);
5956
- } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorResetKeys == null ? void 0 : userScrollAnchorResetKeys.size) === 0) {
5957
- state.userScrollAnchorResetKeys = void 0;
6004
+ } else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
6005
+ state.userScrollAnchorReset = void 0;
5958
6006
  }
5959
6007
  if (shouldMaintainScrollAtEnd) {
5960
6008
  if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
@@ -5964,7 +6012,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5964
6012
  }
5965
6013
  }
5966
6014
  function updateOneItemSize(ctx, itemKey, sizeObj) {
5967
- var _a3;
6015
+ var _a3, _b;
5968
6016
  const state = ctx.state;
5969
6017
  const {
5970
6018
  indexByKey,
@@ -5974,13 +6022,20 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5974
6022
  } = state;
5975
6023
  if (!data) return 0;
5976
6024
  const index = indexByKey.get(itemKey);
5977
- const prevSize = getItemSize(ctx, itemKey, index, data[index]);
6025
+ const itemData = data[index];
6026
+ let itemType;
6027
+ let fixedItemSize;
6028
+ if (getFixedItemSize) {
6029
+ itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
6030
+ fixedItemSize = getFixedItemSize(itemData, index, itemType);
6031
+ }
6032
+ const prevSize = getItemSize(ctx, itemKey, index, itemData);
5978
6033
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5979
- const size = Math.round(rawSize) ;
5980
6034
  const prevSizeKnown = sizesKnown.get(itemKey);
6035
+ const size = Math.round(rawSize) ;
5981
6036
  sizesKnown.set(itemKey, size);
5982
- if (!getFixedItemSize && size > 0) {
5983
- const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
6037
+ if (fixedItemSize === void 0 && size > 0) {
6038
+ itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5984
6039
  let averages = averageSizes[itemType];
5985
6040
  if (!averages) {
5986
6041
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -6048,6 +6103,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
6048
6103
  }
6049
6104
  }
6050
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
+
6051
6125
  // src/utils/createImperativeHandle.ts
6052
6126
  var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
6053
6127
  function getAverageItemSizes(state) {
@@ -6063,7 +6137,7 @@ function getAverageItemSizes(state) {
6063
6137
  }
6064
6138
  return averageItemSizes;
6065
6139
  }
6066
- function createImperativeHandle(ctx) {
6140
+ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6067
6141
  const state = ctx.state;
6068
6142
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
6069
6143
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
@@ -6080,15 +6154,10 @@ function createImperativeHandle(ctx) {
6080
6154
  if (targetIndex >= dataLength) {
6081
6155
  return false;
6082
6156
  }
6083
- if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
6157
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
6084
6158
  return true;
6085
6159
  }
6086
- for (let index = anchorIndex; index < dataLength; index++) {
6087
- if (!state.sizesKnown.has(getId(state, index))) {
6088
- return false;
6089
- }
6090
- }
6091
- return true;
6160
+ return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
6092
6161
  };
6093
6162
  const runWhenReady = (token, run, isReady) => {
6094
6163
  const startedAt = Date.now();
@@ -6111,11 +6180,7 @@ function createImperativeHandle(ctx) {
6111
6180
  };
6112
6181
  requestAnimationFrame(check);
6113
6182
  };
6114
- const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6115
- var _a3;
6116
- const token = ++imperativeScrollToken;
6117
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6118
- state.pendingScrollResolve = resolve;
6183
+ const runScrollRequest = (token, resolve, run, isReady = () => true) => {
6119
6184
  const runNow = () => {
6120
6185
  if (token !== imperativeScrollToken) {
6121
6186
  return;
@@ -6133,7 +6198,33 @@ function createImperativeHandle(ctx) {
6133
6198
  } else {
6134
6199
  runNow();
6135
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);
6136
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
+ };
6137
6228
  const scrollIndexIntoView = (options) => {
6138
6229
  if (state) {
6139
6230
  const { index, ...rest } = options;
@@ -6232,26 +6323,20 @@ function createImperativeHandle(ctx) {
6232
6323
  }
6233
6324
  return false;
6234
6325
  }),
6235
- scrollToEnd: (options) => runScrollWithPromise(
6236
- () => {
6237
- const data = state.props.data;
6238
- const stylePaddingBottom = state.props.stylePaddingBottom;
6239
- const index = data.length - 1;
6240
- if (index !== -1) {
6241
- const paddingBottom = stylePaddingBottom || 0;
6242
- const footerSize = peek$(ctx, "footerSize") || 0;
6243
- scrollToIndex(ctx, {
6244
- ...options,
6245
- index,
6246
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6247
- viewPosition: 1
6248
- });
6249
- return true;
6250
- }
6251
- return false;
6252
- },
6253
- () => isScrollToIndexReady(state.props.data.length - 1, true)
6254
- ),
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
+ }),
6255
6340
  scrollToIndex: (params) => {
6256
6341
  return runScrollWithPromise(
6257
6342
  () => {
@@ -6621,6 +6706,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6621
6706
  viewOffset: 0
6622
6707
  } : void 0;
6623
6708
  const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
6709
+ const [, scheduleImperativeScrollCommit] = React3.useReducer((value) => value + 1, 0);
6624
6710
  const ctx = useStateContext();
6625
6711
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
6626
6712
  const refScroller = useRef(null);
@@ -6985,7 +7071,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6985
7071
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
6986
7072
  useInit(() => {
6987
7073
  });
6988
- 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
+ });
6989
7079
  useEffect(() => {
6990
7080
  if (usesBootstrapInitialScroll) {
6991
7081
  return;
package/reanimated.d.ts CHANGED
@@ -389,12 +389,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
389
389
  size?: boolean;
390
390
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
391
391
  }
392
+ interface AnchoredEndSpaceReadyInfo {
393
+ anchorIndex: number | undefined;
394
+ anchorKey: string | undefined;
395
+ size: number;
396
+ }
397
+ interface ScrollToEndOptions {
398
+ animated?: boolean;
399
+ viewOffset?: number;
400
+ }
392
401
  interface AnchoredEndSpaceConfig {
393
402
  anchorIndex: number;
394
403
  anchorOffset?: number;
395
404
  anchorMaxSize?: number;
396
405
  includeInEndInset?: boolean;
397
406
  onSizeChanged?: (size: number) => void;
407
+ onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
398
408
  }
399
409
  interface StickyHeaderConfig {
400
410
  /**
@@ -526,10 +536,7 @@ type LegendListRef$1 = {
526
536
  * @param options.animated - If true, animates the scroll. Default: true.
527
537
  * @param options.viewOffset - Offset from the target position.
528
538
  */
529
- scrollToEnd(options?: {
530
- animated?: boolean | undefined;
531
- viewOffset?: number | undefined;
532
- }): Promise<void>;
539
+ scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
533
540
  /**
534
541
  * Scrolls to a specific index in the list.
535
542
  * @param params - Parameters for scrolling.
package/section-list.d.ts CHANGED
@@ -445,12 +445,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
445
445
  size?: boolean;
446
446
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
447
447
  }
448
+ interface AnchoredEndSpaceReadyInfo {
449
+ anchorIndex: number | undefined;
450
+ anchorKey: string | undefined;
451
+ size: number;
452
+ }
453
+ interface ScrollToEndOptions {
454
+ animated?: boolean;
455
+ viewOffset?: number;
456
+ }
448
457
  interface AnchoredEndSpaceConfig {
449
458
  anchorIndex: number;
450
459
  anchorOffset?: number;
451
460
  anchorMaxSize?: number;
452
461
  includeInEndInset?: boolean;
453
462
  onSizeChanged?: (size: number) => void;
463
+ onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
454
464
  }
455
465
  interface StickyHeaderConfig {
456
466
  /**
@@ -582,10 +592,7 @@ type LegendListRef$1 = {
582
592
  * @param options.animated - If true, animates the scroll. Default: true.
583
593
  * @param options.viewOffset - Offset from the target position.
584
594
  */
585
- scrollToEnd(options?: {
586
- animated?: boolean | undefined;
587
- viewOffset?: number | undefined;
588
- }): Promise<void>;
595
+ scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
589
596
  /**
590
597
  * Scrolls to a specific index in the list.
591
598
  * @param params - Parameters for scrolling.