@legendapp/list 3.4.0 → 3.6.0

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.
@@ -880,8 +880,14 @@ function scheduleFullDrawDistancePrewarm(ctx) {
880
880
  return;
881
881
  }
882
882
  state.scheduledWork.frame(() => {
883
- var _a3;
884
- return (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
883
+ var _a3, _b, _c;
884
+ if (state.props.hasExternalScroll && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust) {
885
+ const offset = (_b = (_a3 = state.refScroller.current) == null ? void 0 : _a3.getRawScrollOffset) == null ? void 0 : _b.call(_a3);
886
+ if (offset !== void 0) {
887
+ state.scroll = state.scrollPending = state.props.horizontal ? toLogicalHorizontalOffset(state, offset, state.totalSize) : offset;
888
+ }
889
+ }
890
+ (_c = state.triggerCalculateItemsInView) == null ? void 0 : _c.call(state);
885
891
  }, "fullDrawDistancePrewarm");
886
892
  }
887
893
 
@@ -894,6 +900,9 @@ function resetInitialRenderState(ctx, {
894
900
  if (resetLayout) {
895
901
  state.didContainersLayout = false;
896
902
  state.queuedInitialLayout = false;
903
+ state.scrollBufferDirection = void 0;
904
+ state.scrollHistory.length = 0;
905
+ state.scheduledWork.cancel("renderRangeProjection");
897
906
  state.edgeReachedGate = void 0;
898
907
  state.isStartReached = null;
899
908
  state.isEndReached = null;
@@ -1120,6 +1129,7 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
1120
1129
  const previousSize = sizes.get(itemKey);
1121
1130
  const diff = previousSize !== void 0 ? size - previousSize : size;
1122
1131
  if (diff !== 0) {
1132
+ state.positionsAreCurrent = false;
1123
1133
  addTotalSize(ctx, itemKey, diff, notifyTotalSize);
1124
1134
  }
1125
1135
  sizes.set(itemKey, size);
@@ -1180,6 +1190,7 @@ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
1180
1190
  const fixedSize = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
1181
1191
  if (fixedSize !== void 0) {
1182
1192
  size = fixedSize + ctx.scrollAxisGap;
1193
+ state.positionsAreCurrent = false;
1183
1194
  state.sizesKnown.set(key, size);
1184
1195
  }
1185
1196
  }
@@ -1253,10 +1264,17 @@ function getItemSizeAtIndex(ctx, index) {
1253
1264
  }
1254
1265
 
1255
1266
  // src/core/calculateOffsetWithOffsetPosition.ts
1267
+ function getViewPositionOffset(availableSpace, viewPosition, viewPositionFallback) {
1268
+ let alignment = viewPosition;
1269
+ if (availableSpace < 0 && viewPositionFallback !== void 0) {
1270
+ alignment = viewPositionFallback === "start" ? 0 : 1;
1271
+ }
1272
+ return -alignment * availableSpace;
1273
+ }
1256
1274
  function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1257
1275
  var _a3;
1258
1276
  const state = ctx.state;
1259
- const { index, viewOffset, viewPosition } = params;
1277
+ const { index, viewOffset, viewPosition, viewPositionFallback } = params;
1260
1278
  let offset = offsetParam;
1261
1279
  if (viewOffset) {
1262
1280
  offset -= viewOffset;
@@ -1277,7 +1295,8 @@ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1277
1295
  const measuredItemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1278
1296
  const itemSize = Math.max(0, measuredItemSize - (isOutOfBounds ? 0 : ctx.scrollAxisGap));
1279
1297
  const trailingInset = getContentInsetEnd(ctx);
1280
- offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1298
+ const availableSpace = state.scrollLength - trailingInset - itemSize;
1299
+ offset += getViewPositionOffset(availableSpace, viewPosition, viewPositionFallback);
1281
1300
  }
1282
1301
  return offset;
1283
1302
  }
@@ -1624,15 +1643,27 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) {
1624
1643
  anchorPositionForLock = newPosition;
1625
1644
  }
1626
1645
  }
1627
- if (scrollingToViewPosition && scrollingToViewPosition > 0) {
1646
+ if (scrollingTo && scrollingToViewPosition !== void 0 && (scrollingToViewPosition > 0 || scrollingTo.viewPositionFallback)) {
1628
1647
  const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
1629
- const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
1648
+ const prevSize = scrollingTo.itemSize;
1630
1649
  if (newSize !== void 0 && prevSize !== void 0 && newSize !== prevSize) {
1631
- const diff = newSize - prevSize;
1632
- if (diff !== 0) {
1633
- positionDiff += diff * scrollingToViewPosition;
1634
- scrollingTo.itemSize = newSize;
1650
+ if (scrollingTo.viewPositionFallback) {
1651
+ const viewport = state.scrollLength - getContentInsetEnd(ctx);
1652
+ const previousSpace = viewport - Math.max(0, prevSize - ctx.scrollAxisGap);
1653
+ const nextSpace = viewport - Math.max(0, newSize - ctx.scrollAxisGap);
1654
+ positionDiff += getViewPositionOffset(
1655
+ nextSpace,
1656
+ scrollingToViewPosition,
1657
+ scrollingTo.viewPositionFallback
1658
+ ) - getViewPositionOffset(
1659
+ previousSpace,
1660
+ scrollingToViewPosition,
1661
+ scrollingTo.viewPositionFallback
1662
+ );
1663
+ } else {
1664
+ positionDiff += (newSize - prevSize) * scrollingToViewPosition;
1635
1665
  }
1666
+ scrollingTo.itemSize = newSize;
1636
1667
  }
1637
1668
  }
1638
1669
  updateAnchorLock(state, {
@@ -1761,6 +1792,9 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
1761
1792
  state.scrollTime = currentTime;
1762
1793
  const scrollDelta = Math.abs(newScroll - prevScroll);
1763
1794
  const isUserScrollEvent = !!(options == null ? void 0 : options.fromNativeScrollEvent) && scrollDelta > 0.1 && !adjustChanged && scrollingTo === void 0 && !state.pendingNativeMVCPAdjust;
1795
+ if (isUserScrollEvent) {
1796
+ state.scrollBufferDirection = newScroll > prevScroll ? 1 : -1;
1797
+ }
1764
1798
  const didCancelMaintainScrollAtEnd = isUserScrollEvent && newScroll < prevScroll && !!(state.maintainingScrollAtEnd || state.pendingMaintainScrollAtEnd);
1765
1799
  if (didCancelMaintainScrollAtEnd) {
1766
1800
  finishMaintainScrollAtEnd(ctx);
@@ -1840,10 +1874,10 @@ function finishMaintainScrollAtEnd(ctx) {
1840
1874
  }
1841
1875
  }
1842
1876
  function doMaintainScrollAtEnd(ctx, options) {
1843
- var _a3, _b, _c, _d, _e, _f;
1877
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
1844
1878
  const state = ctx.state;
1845
1879
  let didMaintain = false;
1846
- if (state.isDragging) {
1880
+ if (state.isDragging || ((_b = (_a3 = state.refScroller.current) == null ? void 0 : _a3.isScrollInRange) == null ? void 0 : _b.call(_a3)) === false) {
1847
1881
  finishMaintainScrollAtEnd(ctx);
1848
1882
  } else {
1849
1883
  const {
@@ -1855,11 +1889,11 @@ function doMaintainScrollAtEnd(ctx, options) {
1855
1889
  const immediate = (options == null ? void 0 : options.immediate) && Platform.OS === "web" && !(maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.animated);
1856
1890
  const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
1857
1891
  const isReplayingPendingMaintain = !!state.pendingMaintainScrollAtEnd;
1858
- const shouldMaintainScrollAtEnd = !!(!((_a3 = ctx.scrollRequestTracker) == null ? void 0 : _a3.isWaitingToRun()) && (!state.scrollingTo || state.scrollingTo.isScrollToEnd) && (isWithinMaintainScrollAtEndThreshold || isReplayingPendingMaintain || ((_b = state.scrollingTo) == null ? void 0 : _b.isScrollToEnd)) && maintainScrollAtEnd && didFinishInitialScroll);
1892
+ const shouldMaintainScrollAtEnd = !!(!((_c = ctx.scrollRequestTracker) == null ? void 0 : _c.isWaitingToRun()) && (!state.scrollingTo || state.scrollingTo.isScrollToEnd) && (isWithinMaintainScrollAtEndThreshold || isReplayingPendingMaintain || ((_d = state.scrollingTo) == null ? void 0 : _d.isScrollToEnd)) && maintainScrollAtEnd && didFinishInitialScroll);
1859
1893
  if (shouldMaintainScrollAtEnd && !state.scrollingTo) {
1860
1894
  const scroller = state.refScroller.current;
1861
- const nativeMax = (_c = scroller == null ? void 0 : scroller.getMaxScrollOffset) == null ? void 0 : _c.call(scroller);
1862
- const observed = (_d = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _d.call(scroller);
1895
+ const nativeMax = (_e = scroller == null ? void 0 : scroller.getMaxScrollOffset) == null ? void 0 : _e.call(scroller);
1896
+ const observed = (_f = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _f.call(scroller);
1863
1897
  if (nativeMax !== void 0 && observed !== void 0 && nativeMax < state.scroll - 1 && Math.abs(observed - nativeMax) <= 1) {
1864
1898
  state.pendingMaintainScrollAtEnd = true;
1865
1899
  state.scrollPending = observed;
@@ -1871,13 +1905,13 @@ function doMaintainScrollAtEnd(ctx, options) {
1871
1905
  } else if (pendingNativeMVCPAdjust) {
1872
1906
  state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1873
1907
  } else if (shouldMaintainScrollAtEnd && (state.scrollingTo || state.pendingScrollResolve)) {
1874
- if (immediate && ((_e = state.scrollingTo) == null ? void 0 : _e.isScrollToEnd) && !state.scrollingTo.animated) {
1908
+ if (immediate && ((_g = state.scrollingTo) == null ? void 0 : _g.isScrollToEnd) && !state.scrollingTo.animated) {
1875
1909
  state.pendingMaintainScrollAtEnd = false;
1876
1910
  ctx.scrollToEnd({ animated: false });
1877
1911
  didMaintain = true;
1878
1912
  } else {
1879
1913
  state.pendingMaintainScrollAtEnd = true;
1880
- (_f = state.maintainingScrollAtEnd) != null ? _f : state.maintainingScrollAtEnd = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
1914
+ (_h = state.maintainingScrollAtEnd) != null ? _h : state.maintainingScrollAtEnd = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
1881
1915
  }
1882
1916
  } else if (shouldMaintainScrollAtEnd && didContainersLayout) {
1883
1917
  state.pendingMaintainScrollAtEnd = false;
@@ -1891,8 +1925,9 @@ function doMaintainScrollAtEnd(ctx, options) {
1891
1925
  const scrollAtRequest = state.scroll;
1892
1926
  state.maintainingScrollAtEnd = pendingState;
1893
1927
  const run = () => {
1928
+ var _a4, _b2;
1894
1929
  if (state.maintainingScrollAtEnd === pendingState) {
1895
- if (state.isDragging) {
1930
+ if (state.isDragging || ((_b2 = (_a4 = state.refScroller.current) == null ? void 0 : _a4.isScrollInRange) == null ? void 0 : _b2.call(_a4)) === false) {
1896
1931
  finishMaintainScrollAtEnd(ctx);
1897
1932
  } else {
1898
1933
  const isStillWithinThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
@@ -2278,7 +2313,8 @@ function scrollToIndex(ctx, {
2278
2313
  animated = true,
2279
2314
  forceScroll,
2280
2315
  isInitialScroll,
2281
- viewPosition
2316
+ viewPosition,
2317
+ viewPositionFallback
2282
2318
  }) {
2283
2319
  const state = ctx.state;
2284
2320
  const { data } = state.props;
@@ -2298,7 +2334,8 @@ function scrollToIndex(ctx, {
2298
2334
  itemSize,
2299
2335
  offset: firstIndexOffset,
2300
2336
  viewOffset,
2301
- viewPosition: viewPosition != null ? viewPosition : 0
2337
+ viewPosition: viewPosition != null ? viewPosition : 0,
2338
+ viewPositionFallback
2302
2339
  });
2303
2340
  }
2304
2341
 
@@ -2318,6 +2355,7 @@ function dispatchInitialScroll(ctx, params) {
2318
2355
  precomputedWithViewOffset: true,
2319
2356
  viewOffset: target.viewOffset,
2320
2357
  viewPosition: target.viewPosition,
2358
+ viewPositionFallback: target.viewPositionFallback,
2321
2359
  waitForInitialScrollCompletionFrame: waitForCompletionFrame
2322
2360
  });
2323
2361
  }
@@ -2652,7 +2690,7 @@ function createRetargetedBottomAlignedInitialScroll(options) {
2652
2690
  };
2653
2691
  }
2654
2692
  function areEquivalentBootstrapInitialScrollTargets(current, next) {
2655
- return current.index === next.index && current.preserveForBottomPadding === next.preserveForBottomPadding && current.preserveForFooterLayout === next.preserveForFooterLayout && current.viewOffset === next.viewOffset && current.viewPosition === next.viewPosition;
2693
+ return current.index === next.index && current.preserveForBottomPadding === next.preserveForBottomPadding && current.preserveForFooterLayout === next.preserveForFooterLayout && current.viewOffset === next.viewOffset && current.viewPosition === next.viewPosition && current.viewPositionFallback === next.viewPositionFallback;
2656
2694
  }
2657
2695
  function clearPendingInitialScrollFooterLayout(ctx, options) {
2658
2696
  const { dataLength, stylePaddingEnd, target } = options;
@@ -2867,7 +2905,7 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2867
2905
  preserveForFooterLayout: shouldPreserveInitialScrollForFooterLayout(initialScroll),
2868
2906
  stylePaddingEnd
2869
2907
  });
2870
- const didTargetChange = initialScroll.index !== updatedInitialScroll.index || initialScroll.viewPosition !== updatedInitialScroll.viewPosition || initialScroll.viewOffset !== updatedInitialScroll.viewOffset;
2908
+ const didTargetChange = initialScroll.index !== updatedInitialScroll.index || initialScroll.viewPosition !== updatedInitialScroll.viewPosition || initialScroll.viewPositionFallback !== updatedInitialScroll.viewPositionFallback || initialScroll.viewOffset !== updatedInitialScroll.viewOffset;
2871
2909
  if (!didTargetChange) {
2872
2910
  clearPendingInitialScrollFooterLayout(ctx, {
2873
2911
  dataLength,
@@ -3335,6 +3373,7 @@ function handleInitialScrollDataChange(ctx, options) {
3335
3373
 
3336
3374
  // src/core/resetLayoutCachesForDataChange.ts
3337
3375
  function resetLayoutCachesForDataChange(state) {
3376
+ state.positionsAreCurrent = false;
3338
3377
  state.indexByKey.clear();
3339
3378
  state.idCache.length = 0;
3340
3379
  state.positions.length = 0;
@@ -3615,7 +3654,7 @@ function updateItemPositions(ctx, dataChanged, {
3615
3654
  scrollBottomBuffered: -1,
3616
3655
  startIndex: 0
3617
3656
  }) {
3618
- var _a3, _b, _c, _d, _e;
3657
+ var _a3, _b, _c, _d, _e, _f;
3619
3658
  const state = ctx.state;
3620
3659
  const hasPositionListeners = ctx.positionListeners.size > 0;
3621
3660
  const {
@@ -3631,6 +3670,11 @@ function updateItemPositions(ctx, dataChanged, {
3631
3670
  const dataLength = data.length;
3632
3671
  const numColumns = (_a3 = peek$(ctx, "numColumns")) != null ? _a3 : 1;
3633
3672
  const hasColumns = numColumns > 1;
3673
+ const canReuseEstimates = !doMVCP || !state.didContainersLayout && Object.keys(state.averageSizes).length === 0;
3674
+ if (state.positionsAreCurrent && !dataChanged && !forceFullUpdate && state.positionRecalculationStartIndex === void 0 && !scrollingTo && !hasColumns && !snapToIndices && positions.length === dataLength && canReuseEstimates) {
3675
+ return;
3676
+ }
3677
+ state.positionsAreCurrent = false;
3634
3678
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
3635
3679
  const extraData = peek$(ctx, "extraData");
3636
3680
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
@@ -3745,6 +3789,10 @@ function updateItemPositions(ctx, dataChanged, {
3745
3789
  }
3746
3790
  if (!didBreakEarly) {
3747
3791
  updateTotalSize(ctx);
3792
+ state.positionsAreCurrent = !hasColumns;
3793
+ if (startIndex <= ((_f = state.positionRecalculationStartIndex) != null ? _f : -1)) {
3794
+ state.positionRecalculationStartIndex = void 0;
3795
+ }
3748
3796
  }
3749
3797
  if (snapToIndices) {
3750
3798
  updateSnapToOffsets(ctx);
@@ -4307,7 +4355,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4307
4355
  }
4308
4356
  function trackVisibleRange(range, i, top, size, scroll, scrollBottom) {
4309
4357
  let didPassVisibleEnd = false;
4310
- if (range.startNoBuffer === null && top + size > scroll) {
4358
+ if (range.startNoBuffer === null && top + size > scroll && top <= scrollBottom) {
4311
4359
  range.startNoBuffer = i;
4312
4360
  }
4313
4361
  if (range.firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
@@ -4373,7 +4421,7 @@ function findFirstVisibleIndexInCachedRange(ctx, scroll) {
4373
4421
  return null;
4374
4422
  }
4375
4423
  function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4376
- var _a3, _b;
4424
+ var _a3, _b, _c, _d;
4377
4425
  const state = ctx.state;
4378
4426
  const {
4379
4427
  endBuffered,
@@ -4407,14 +4455,14 @@ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, sc
4407
4455
  startNoBuffer: visibleRange.startNoBuffer
4408
4456
  });
4409
4457
  maybeEmitFirstVisibleItemChanged(state, visibleRange.startNoBuffer);
4410
- if (visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4458
+ if (state.props.hasExternalScroll || visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4411
4459
  updateViewableItems(
4412
4460
  state,
4413
4461
  ctx,
4414
4462
  viewabilityConfigCallbackPairs,
4415
4463
  scrollLength,
4416
- visibleRange.startNoBuffer,
4417
- visibleRange.endNoBuffer,
4464
+ (_c = visibleRange.startNoBuffer) != null ? _c : 0,
4465
+ (_d = visibleRange.endNoBuffer) != null ? _d : -1,
4418
4466
  startBuffered,
4419
4467
  endBuffered
4420
4468
  );
@@ -4423,7 +4471,7 @@ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, sc
4423
4471
  function calculateItemsInView(ctx, params = {}) {
4424
4472
  const state = ctx.state;
4425
4473
  batchedUpdates(() => {
4426
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
4474
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
4427
4475
  const {
4428
4476
  columns,
4429
4477
  containerItemKeys,
@@ -4475,7 +4523,7 @@ function calculateItemsInView(ctx, params = {}) {
4475
4523
  scrollAdjustPending = (_a4 = peek$(ctx, "scrollAdjustPending")) != null ? _a4 : 0;
4476
4524
  scrollAdjustPad = scrollAdjustPending - topPad;
4477
4525
  scroll = Math.round(nextScrollState + scrollExtra + scrollAdjustPad);
4478
- if (scroll + scrollLength > totalSize) {
4526
+ if (!state.props.hasExternalScroll && scroll + scrollLength > totalSize) {
4479
4527
  scroll = Math.max(0, totalSize - scrollLength);
4480
4528
  }
4481
4529
  };
@@ -4502,7 +4550,11 @@ function calculateItemsInView(ctx, params = {}) {
4502
4550
  let stickyState = dataChanged ? void 0 : resolveStickyState();
4503
4551
  let scrollBufferTop = drawDistance;
4504
4552
  let scrollBufferBottom = drawDistance;
4505
- if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
4553
+ if (speed !== 0) {
4554
+ state.scrollBufferDirection = speed > 0 ? 1 : -1;
4555
+ }
4556
+ const bufferForward = state.scrollBufferDirection === 1 || state.scrollBufferDirection === void 0 && scroll < Math.max(50, drawDistance);
4557
+ if (bufferForward) {
4506
4558
  scrollBufferTop = drawDistance * 0.5;
4507
4559
  scrollBufferBottom = drawDistance * 1.5;
4508
4560
  } else {
@@ -4512,8 +4564,8 @@ function calculateItemsInView(ctx, params = {}) {
4512
4564
  const shouldProjectRenderRange = !dataChanged && !forceFullItemPositions && !suppressInitialScrollSideEffects && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust && !!peek$(ctx, "readyToRender");
4513
4565
  const projectedBufferAdjustment = shouldProjectRenderRange ? getProjectedBufferAdjustment(speed, Math.min(scrollBufferTop, scrollBufferBottom)) : 0;
4514
4566
  const updateScrollRange = () => {
4515
- const scrollStart = Math.max(0, scroll);
4516
- const overscrollBeforeContent = Math.max(0, -nativeScrollState);
4567
+ const scrollStart = state.props.hasExternalScroll ? scroll : Math.max(0, scroll);
4568
+ const overscrollBeforeContent = state.props.hasExternalScroll ? 0 : Math.max(0, -nativeScrollState);
4517
4569
  scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
4518
4570
  scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
4519
4571
  scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
@@ -4642,7 +4694,7 @@ function calculateItemsInView(ctx, params = {}) {
4642
4694
  nextTop = top;
4643
4695
  }
4644
4696
  }
4645
- if (visibleRange.startNoBuffer !== null) {
4697
+ if (startBuffered !== null) {
4646
4698
  if (top <= scrollBottomBuffered) {
4647
4699
  endBuffered = i;
4648
4700
  if (scrollBottomBuffered > totalSize) {
@@ -4653,6 +4705,8 @@ function calculateItemsInView(ctx, params = {}) {
4653
4705
  } else {
4654
4706
  foundEnd = true;
4655
4707
  }
4708
+ } else if (top > scrollBottomBuffered) {
4709
+ foundEnd = true;
4656
4710
  }
4657
4711
  }
4658
4712
  }
@@ -4670,6 +4724,12 @@ function calculateItemsInView(ctx, params = {}) {
4670
4724
  bottom: nextBottom,
4671
4725
  top: nextTop
4672
4726
  };
4727
+ } else if (enableScrollForNextCalculateItemsInView && state.props.hasExternalScroll) {
4728
+ if (scrollBottomBuffered < 0) {
4729
+ state.scrollForNextCalculateItemsInView = { bottom: 0, top: null };
4730
+ } else if (scrollTopBuffered > totalSize) {
4731
+ state.scrollForNextCalculateItemsInView = { bottom: null, top: totalSize };
4732
+ }
4673
4733
  }
4674
4734
  let numContainers = prevNumContainers;
4675
4735
  const pendingRemoval = [];
@@ -4693,7 +4753,9 @@ function calculateItemsInView(ctx, params = {}) {
4693
4753
  }
4694
4754
  const hasScrollTargetPinnedRange = scrollTargetPinnedStart <= scrollTargetPinnedEnd;
4695
4755
  const isPinnedRenderIndex = (index) => alwaysRenderIndicesSet.has(index) || hasScrollTargetPinnedRange && index >= scrollTargetPinnedStart && index <= scrollTargetPinnedEnd;
4696
- if (startBuffered !== null && endBuffered !== null) {
4756
+ if (startBuffered !== null && endBuffered !== null || alwaysRenderIndicesArr.length || hasScrollTargetPinnedRange) {
4757
+ const allocationStart = startBuffered != null ? startBuffered : 0;
4758
+ const allocationEnd = endBuffered != null ? endBuffered : -1;
4697
4759
  const needNewContainers = [];
4698
4760
  const needNewContainersSet = /* @__PURE__ */ new Set();
4699
4761
  const addPinnedIndex = (index) => {
@@ -4709,7 +4771,7 @@ function calculateItemsInView(ctx, params = {}) {
4709
4771
  }
4710
4772
  }
4711
4773
  };
4712
- for (let i = startBuffered; i <= endBuffered; i++) {
4774
+ for (let i = allocationStart; i <= allocationEnd; i++) {
4713
4775
  const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4714
4776
  if (!containerItemKeys.has(id)) {
4715
4777
  needNewContainersSet.add(i);
@@ -4731,8 +4793,8 @@ function calculateItemsInView(ctx, params = {}) {
4731
4793
  (_n = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _n : -1,
4732
4794
  needNewContainers,
4733
4795
  needNewContainersSet,
4734
- startBuffered,
4735
- endBuffered
4796
+ allocationStart,
4797
+ allocationEnd
4736
4798
  );
4737
4799
  } else if (previousStickyIndex !== -1) {
4738
4800
  set$(ctx, "activeStickyIndex", -1);
@@ -4741,8 +4803,8 @@ function calculateItemsInView(ctx, params = {}) {
4741
4803
  const availableContainerAllocations = findAvailableContainers(
4742
4804
  ctx,
4743
4805
  needNewContainers,
4744
- startBuffered,
4745
- endBuffered,
4806
+ allocationStart,
4807
+ allocationEnd,
4746
4808
  pendingRemoval,
4747
4809
  protectedContainerKeys,
4748
4810
  // Initial end alignment has no scroll velocity yet. Keep its
@@ -4869,19 +4931,19 @@ function calculateItemsInView(ctx, params = {}) {
4869
4931
  handleInitialScrollLayoutReady(ctx);
4870
4932
  }
4871
4933
  }
4872
- if (viewabilityConfigCallbackPairs && visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4934
+ if (viewabilityConfigCallbackPairs && (state.props.hasExternalScroll || visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null)) {
4873
4935
  updateViewableItems(
4874
4936
  ctx.state,
4875
4937
  ctx,
4876
4938
  viewabilityConfigCallbackPairs,
4877
4939
  scrollLength,
4878
- visibleRange.startNoBuffer,
4879
- visibleRange.endNoBuffer,
4880
- startBuffered != null ? startBuffered : visibleRange.startNoBuffer,
4881
- endBuffered != null ? endBuffered : visibleRange.endNoBuffer
4940
+ (_u = visibleRange.startNoBuffer) != null ? _u : 0,
4941
+ (_v = visibleRange.endNoBuffer) != null ? _v : -1,
4942
+ (_w = startBuffered != null ? startBuffered : visibleRange.startNoBuffer) != null ? _w : 0,
4943
+ (_x = endBuffered != null ? endBuffered : visibleRange.endNoBuffer) != null ? _x : -1
4882
4944
  );
4883
4945
  }
4884
- (_u = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _u.call(stickyState);
4946
+ (_y = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _y.call(stickyState);
4885
4947
  });
4886
4948
  }
4887
4949
 
@@ -5160,6 +5222,7 @@ function updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem, notif
5160
5222
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5161
5223
  const prevSizeKnown = sizesKnown.get(itemKey);
5162
5224
  const size = Math.round(rawSize) ;
5225
+ if (prevSizeKnown !== size) state.positionsAreCurrent = false;
5163
5226
  sizesKnown.set(itemKey, size);
5164
5227
  if (fixedItemSize === void 0 && size > 0) {
5165
5228
  itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
@@ -5580,10 +5643,19 @@ function useOnLayoutSync({
5580
5643
  measureInLayoutEffect = true,
5581
5644
  onLayoutProp,
5582
5645
  onLayoutChange,
5583
- webLayoutResync
5646
+ webLayoutResync,
5647
+ webExternalScroll = false
5584
5648
  }, deps) {
5649
+ const onExternalLayout = useCallback(
5650
+ (event) => {
5651
+ onLayoutChange(event.nativeEvent.layout, false);
5652
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
5653
+ },
5654
+ [onLayoutChange, onLayoutProp]
5655
+ );
5585
5656
  useLayoutEffect(() => {
5586
5657
  var _a3, _b;
5658
+ if (webExternalScroll) return;
5587
5659
  const current = ref.current;
5588
5660
  const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
5589
5661
  const element = scrollableNode || current;
@@ -5621,8 +5693,8 @@ function useOnLayoutSync({
5621
5693
  emit(toLayout(rectObserved), false);
5622
5694
  }
5623
5695
  });
5624
- }, [measureInLayoutEffect, ...deps || []]);
5625
- return {};
5696
+ }, [measureInLayoutEffect, webExternalScroll, ...deps || []]);
5697
+ return webExternalScroll ? { onLayout: onExternalLayout } : {};
5626
5698
  }
5627
5699
  function toLayout(rect) {
5628
5700
  if (!rect) {
@@ -6184,94 +6256,121 @@ function useRafCoalescer(callback) {
6184
6256
  return coalescer;
6185
6257
  }
6186
6258
 
6187
- // src/components/webConstants.ts
6188
- var LEGEND_LIST_CONTENT_CONTAINER_CLASS = "legend-list-content-container";
6189
- var LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS = "legend-list-scrollbar-x-hidden";
6190
- var LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS = "legend-list-scrollbar-y-hidden";
6191
-
6192
6259
  // src/components/webScrollUtils.ts
6193
- function getDocumentScrollerNode() {
6194
- if (typeof document === "undefined") {
6195
- return null;
6196
- }
6197
- return document.scrollingElement || document.documentElement || document.body;
6260
+ function isWindowTarget(target) {
6261
+ return typeof window !== "undefined" && target === window;
6198
6262
  }
6199
- function getWindowScrollPosition() {
6200
- var _a3, _b, _c, _d;
6201
- if (typeof window === "undefined") {
6202
- return { x: 0, y: 0 };
6263
+ function getScrollPosition(target) {
6264
+ var _a3, _b, _c, _d, _e, _f;
6265
+ if (isWindowTarget(target)) {
6266
+ return { x: (_b = (_a3 = target.scrollX) != null ? _a3 : target.pageXOffset) != null ? _b : 0, y: (_d = (_c = target.scrollY) != null ? _c : target.pageYOffset) != null ? _d : 0 };
6203
6267
  }
6204
- return {
6205
- x: (_b = (_a3 = window.scrollX) != null ? _a3 : window.pageXOffset) != null ? _b : 0,
6206
- y: (_d = (_c = window.scrollY) != null ? _c : window.pageYOffset) != null ? _d : 0
6207
- };
6268
+ return { x: (_e = target == null ? void 0 : target.scrollLeft) != null ? _e : 0, y: (_f = target == null ? void 0 : target.scrollTop) != null ? _f : 0 };
6208
6269
  }
6209
- function getElementDocumentPosition(element, scroll) {
6210
- var _a3, _b;
6270
+ function getElementScrollPosition(element, target) {
6271
+ var _a3, _b, _c, _d, _e, _f;
6211
6272
  const rect = element == null ? void 0 : element.getBoundingClientRect();
6273
+ const scroll = getScrollPosition(target);
6274
+ const parent = target && !isWindowTarget(target) ? target : null;
6275
+ const parentRect = parent == null ? void 0 : parent.getBoundingClientRect();
6212
6276
  return {
6213
- left: ((_a3 = rect == null ? void 0 : rect.left) != null ? _a3 : 0) + scroll.x,
6214
- top: ((_b = rect == null ? void 0 : rect.top) != null ? _b : 0) + scroll.y
6277
+ left: ((_a3 = rect == null ? void 0 : rect.left) != null ? _a3 : 0) - ((_b = parentRect == null ? void 0 : parentRect.left) != null ? _b : 0) - ((_c = parent == null ? void 0 : parent.clientLeft) != null ? _c : 0) + scroll.x,
6278
+ top: ((_d = rect == null ? void 0 : rect.top) != null ? _d : 0) - ((_e = parentRect == null ? void 0 : parentRect.top) != null ? _e : 0) - ((_f = parent == null ? void 0 : parent.clientTop) != null ? _f : 0) + scroll.y
6215
6279
  };
6216
6280
  }
6217
6281
  function getContentSize2(content) {
6218
6282
  var _a3, _b;
6219
- return {
6220
- height: (_a3 = content == null ? void 0 : content.scrollHeight) != null ? _a3 : 0,
6221
- width: (_b = content == null ? void 0 : content.scrollWidth) != null ? _b : 0
6222
- };
6283
+ return { height: (_a3 = content == null ? void 0 : content.scrollHeight) != null ? _a3 : 0, width: (_b = content == null ? void 0 : content.scrollWidth) != null ? _b : 0 };
6223
6284
  }
6224
- function getScrollContentSize(scrollElement, contentElement, isWindowScroll) {
6225
- return getContentSize2(isWindowScroll ? contentElement : scrollElement);
6285
+ function getScrollContentSize(scrollElement, contentElement, externalTarget) {
6286
+ return getContentSize2(externalTarget !== void 0 ? contentElement : scrollElement);
6226
6287
  }
6227
- function getLayoutMeasurement(scrollElement, isWindowScroll, horizontal) {
6228
- var _a3, _b, _c, _d, _e, _f;
6229
- if (isWindowScroll && typeof window !== "undefined") {
6288
+ function getLayoutMeasurement(scrollElement, externalTarget, horizontal) {
6289
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
6290
+ if (externalTarget !== void 0) {
6230
6291
  const rect = scrollElement == null ? void 0 : scrollElement.getBoundingClientRect();
6292
+ const viewport = isWindowTarget(externalTarget) ? { height: externalTarget.innerHeight, width: externalTarget.innerWidth } : { height: (_a3 = externalTarget == null ? void 0 : externalTarget.clientHeight) != null ? _a3 : 0, width: (_b = externalTarget == null ? void 0 : externalTarget.clientWidth) != null ? _b : 0 };
6231
6293
  return {
6232
- // In window-scroll mode, use viewport size on the scroll axis.
6233
- height: horizontal ? (_b = (_a3 = rect == null ? void 0 : rect.height) != null ? _a3 : scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _b : window.innerHeight : window.innerHeight,
6234
- // Keep the cross-axis size list-relative to avoid inflating container measurements.
6235
- width: horizontal ? window.innerWidth : (_d = (_c = rect == null ? void 0 : rect.width) != null ? _c : scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _d : window.innerWidth
6294
+ height: horizontal ? (_d = (_c = rect == null ? void 0 : rect.height) != null ? _c : scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _d : 0 : viewport.height,
6295
+ width: horizontal ? viewport.width : (_f = (_e = rect == null ? void 0 : rect.width) != null ? _e : scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _f : 0
6236
6296
  };
6237
6297
  }
6238
- return {
6239
- height: (_e = scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _e : 0,
6240
- width: (_f = scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _f : 0
6241
- };
6298
+ return { height: (_g = scrollElement == null ? void 0 : scrollElement.clientHeight) != null ? _g : 0, width: (_h = scrollElement == null ? void 0 : scrollElement.clientWidth) != null ? _h : 0 };
6242
6299
  }
6243
6300
  function clampOffset(offset, maxOffset) {
6244
6301
  return Math.max(0, Math.min(offset, maxOffset));
6245
6302
  }
6246
- function getAxisSize(size, horizontal) {
6247
- return horizontal ? size.width : size.height;
6248
- }
6249
6303
  function getMaxOffset(contentSize, layoutMeasurement, horizontal) {
6250
- return Math.max(0, getAxisSize(contentSize, horizontal) - getAxisSize(layoutMeasurement, horizontal));
6304
+ const axis = horizontal ? "width" : "height";
6305
+ return Math.max(0, contentSize[axis] - layoutMeasurement[axis]);
6251
6306
  }
6252
- function resolveScrollableNode(scrollElement, isWindowScroll) {
6253
- return isWindowScroll ? getDocumentScrollerNode() || scrollElement : scrollElement;
6307
+ function resolveScrollableNode(scrollElement, externalTarget) {
6308
+ if (isWindowTarget(externalTarget)) {
6309
+ return document.scrollingElement || document.documentElement || document.body;
6310
+ }
6311
+ return externalTarget === void 0 ? scrollElement : externalTarget;
6254
6312
  }
6255
- function resolveScrollEventTarget(scrollElement, isWindowScroll) {
6256
- return isWindowScroll && typeof window !== "undefined" ? window : scrollElement;
6313
+ function resolveScrollEventTarget(scrollElement, externalTarget) {
6314
+ return externalTarget === void 0 ? scrollElement : externalTarget;
6257
6315
  }
6258
- function getLayoutRectangle(element, isWindowScroll, horizontal) {
6259
- const rect = element.getBoundingClientRect();
6260
- const scroll = getWindowScrollPosition();
6261
- return {
6262
- height: isWindowScroll && typeof window !== "undefined" && !horizontal ? window.innerHeight : rect.height,
6263
- width: isWindowScroll && typeof window !== "undefined" && horizontal ? window.innerWidth : rect.width,
6264
- x: isWindowScroll ? rect.left + scroll.x : rect.left,
6265
- y: isWindowScroll ? rect.top + scroll.y : rect.top
6266
- };
6316
+ function getLayoutRectangle(element, externalTarget, horizontal) {
6317
+ if (externalTarget === void 0) {
6318
+ const rect = element.getBoundingClientRect();
6319
+ return { height: rect.height, width: rect.width, x: rect.left, y: rect.top };
6320
+ }
6321
+ const { left, top } = getElementScrollPosition(element, externalTarget);
6322
+ const { height, width } = getLayoutMeasurement(element, externalTarget, horizontal);
6323
+ return { height, width, x: left, y: top };
6267
6324
  }
6268
- function resolveWindowScrollTarget({ clampedOffset, horizontal, listPos, scroll }) {
6325
+ function resolveExternalScrollOffset({
6326
+ clampedOffset,
6327
+ horizontal,
6328
+ listPos,
6329
+ scroll
6330
+ }) {
6269
6331
  return {
6270
6332
  left: horizontal ? listPos.left + clampedOffset : scroll.x,
6271
6333
  top: horizontal ? scroll.y : listPos.top + clampedOffset
6272
6334
  };
6273
6335
  }
6274
6336
 
6337
+ // src/components/observeScrollLayout.ts
6338
+ function observeScrollLayout(element, owner, onLayout) {
6339
+ if (owner === null) return;
6340
+ const resizeObserver = new ResizeObserver(onLayout);
6341
+ const mutationObserver = owner === void 0 ? void 0 : new MutationObserver(observe);
6342
+ function observe() {
6343
+ resizeObserver.disconnect();
6344
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
6345
+ resizeObserver.observe(element);
6346
+ if (owner !== void 0) {
6347
+ for (let node = element; node && node !== owner; node = node.parentElement) {
6348
+ const parent = node.parentElement;
6349
+ if (parent) {
6350
+ resizeObserver.observe(parent);
6351
+ mutationObserver == null ? void 0 : mutationObserver.observe(parent, { childList: true });
6352
+ }
6353
+ for (let sibling = node.previousElementSibling; sibling; sibling = sibling.previousElementSibling) {
6354
+ resizeObserver.observe(sibling);
6355
+ }
6356
+ }
6357
+ }
6358
+ onLayout();
6359
+ }
6360
+ observe();
6361
+ if (isWindowTarget(owner)) owner.addEventListener("resize", onLayout);
6362
+ return () => {
6363
+ resizeObserver.disconnect();
6364
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
6365
+ if (isWindowTarget(owner)) owner.removeEventListener("resize", onLayout);
6366
+ };
6367
+ }
6368
+
6369
+ // src/components/webConstants.ts
6370
+ var LEGEND_LIST_CONTENT_CONTAINER_CLASS = "legend-list-content-container";
6371
+ var LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS = "legend-list-scrollbar-x-hidden";
6372
+ var LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS = "legend-list-scrollbar-y-hidden";
6373
+
6275
6374
  // src/components/ListComponentScrollView.tsx
6276
6375
  var SCROLLBAR_HIDDEN_STYLE_ID = "legend-list-scrollbar-axis-hidden-style";
6277
6376
  var SCROLL_END_FALLBACK_MS = 200;
@@ -6330,6 +6429,7 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6330
6429
  showsVerticalScrollIndicator = true,
6331
6430
  refreshControl,
6332
6431
  useWindowScroll = false,
6432
+ scrollElement: externalScrollElement,
6333
6433
  onLayout,
6334
6434
  ...props
6335
6435
  }, ref) {
@@ -6338,31 +6438,38 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6338
6438
  const [anchoredEndSpaceSize] = useArr$(["anchoredEndSpaceSize"]);
6339
6439
  const scrollRef = useRef(null);
6340
6440
  const contentRef = useRef(null);
6341
- const isWindowScroll = useWindowScroll;
6441
+ const externalTarget = externalScrollElement === void 0 && useWindowScroll ? typeof window === "undefined" ? null : window : externalScrollElement;
6442
+ const isWindowScroll = isWindowTarget(externalTarget);
6443
+ const isExternalScroll = externalTarget !== void 0;
6342
6444
  const getScrollTarget = useCallback(
6343
- () => resolveScrollEventTarget(scrollRef.current, isWindowScroll),
6344
- [isWindowScroll]
6445
+ () => resolveScrollEventTarget(scrollRef.current, externalTarget),
6446
+ [externalTarget]
6345
6447
  );
6346
6448
  const getMaxScrollOffset = useCallback(() => {
6347
6449
  const scrollElement = scrollRef.current;
6348
- const contentSize = getScrollContentSize(scrollElement, contentRef.current, isWindowScroll);
6349
- const layoutMeasurement = getLayoutMeasurement(scrollElement, isWindowScroll, horizontal);
6450
+ const contentSize = getScrollContentSize(scrollElement, contentRef.current, externalTarget);
6451
+ const layoutMeasurement = getLayoutMeasurement(scrollElement, externalTarget, horizontal);
6350
6452
  return getMaxOffset(contentSize, layoutMeasurement, horizontal);
6351
- }, [horizontal, isWindowScroll]);
6453
+ }, [externalTarget, horizontal]);
6454
+ const getRawScrollOffset = useCallback(() => {
6455
+ var _a4;
6456
+ const element = scrollRef.current;
6457
+ if (isExternalScroll) {
6458
+ const scroll = getScrollPosition(externalTarget);
6459
+ const listPos = getElementScrollPosition(element, externalTarget);
6460
+ return horizontal ? scroll.x - listPos.left : scroll.y - listPos.top;
6461
+ }
6462
+ return (_a4 = horizontal ? element == null ? void 0 : element.scrollLeft : element == null ? void 0 : element.scrollTop) != null ? _a4 : 0;
6463
+ }, [externalTarget, horizontal, isExternalScroll]);
6464
+ const isScrollInRange = useCallback(() => {
6465
+ if (!isExternalScroll) return true;
6466
+ const offset = getRawScrollOffset();
6467
+ return offset >= -1 && offset <= getMaxScrollOffset() + 1;
6468
+ }, [getMaxScrollOffset, getRawScrollOffset, isExternalScroll]);
6352
6469
  const getCurrentScrollOffset = useCallback(() => {
6353
- const scrollElement = scrollRef.current;
6354
- if (isWindowScroll) {
6355
- const maxOffset = getMaxScrollOffset();
6356
- const scroll = getWindowScrollPosition();
6357
- const listPos = getElementDocumentPosition(scrollElement, scroll);
6358
- const rawOffset = horizontal ? scroll.x - listPos.left : scroll.y - listPos.top;
6359
- return clampOffset(rawOffset, maxOffset);
6360
- }
6361
- if (!scrollElement) {
6362
- return 0;
6363
- }
6364
- return horizontal ? scrollElement.scrollLeft : scrollElement.scrollTop;
6365
- }, [getMaxScrollOffset, horizontal, isWindowScroll]);
6470
+ const offset = getRawScrollOffset();
6471
+ return isExternalScroll ? clampOffset(offset, getMaxScrollOffset()) : offset;
6472
+ }, [getMaxScrollOffset, getRawScrollOffset, isExternalScroll]);
6366
6473
  const scrollToLocalOffset = useCallback(
6367
6474
  (offset, animated) => {
6368
6475
  const scrollElement = scrollRef.current;
@@ -6374,10 +6481,10 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6374
6481
  const clampedOffset = clampOffset(offset, maxOffset);
6375
6482
  const behavior = animated ? "smooth" : "auto";
6376
6483
  const options = { behavior };
6377
- if (isWindowScroll) {
6378
- const scroll = getWindowScrollPosition();
6379
- const listPos = getElementDocumentPosition(scrollElement, scroll);
6380
- const { left, top } = resolveWindowScrollTarget({
6484
+ if (isExternalScroll) {
6485
+ const scroll = getScrollPosition(externalTarget);
6486
+ const listPos = getElementScrollPosition(scrollElement, externalTarget);
6487
+ const { left, top } = resolveExternalScrollOffset({
6381
6488
  clampedOffset,
6382
6489
  horizontal,
6383
6490
  listPos,
@@ -6392,7 +6499,7 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6392
6499
  }
6393
6500
  target.scrollTo(options);
6394
6501
  },
6395
- [getMaxScrollOffset, getScrollTarget, horizontal, isWindowScroll]
6502
+ [externalTarget, getMaxScrollOffset, getScrollTarget, horizontal, isExternalScroll]
6396
6503
  );
6397
6504
  useImperativeHandle(ref, () => {
6398
6505
  const api = {
@@ -6400,11 +6507,14 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6400
6507
  var _a4;
6401
6508
  return (_a4 = scrollRef.current) == null ? void 0 : _a4.getBoundingClientRect();
6402
6509
  },
6510
+ getContentNode: () => contentRef.current,
6403
6511
  getCurrentScrollOffset,
6404
6512
  getMaxScrollOffset,
6405
- getScrollableNode: () => resolveScrollableNode(scrollRef.current, isWindowScroll),
6406
- getScrollEventTarget: () => getScrollTarget(),
6407
- getScrollResponder: () => resolveScrollableNode(scrollRef.current, isWindowScroll),
6513
+ getRawScrollOffset,
6514
+ getScrollableNode: () => resolveScrollableNode(scrollRef.current, externalTarget),
6515
+ getScrollEventTarget: getScrollTarget,
6516
+ getScrollResponder: () => resolveScrollableNode(scrollRef.current, externalTarget),
6517
+ isScrollInRange,
6408
6518
  isWindowScroll: () => isWindowScroll,
6409
6519
  scrollBy: (x, y) => {
6410
6520
  const target = getScrollTarget();
@@ -6428,14 +6538,24 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6428
6538
  }
6429
6539
  };
6430
6540
  return api;
6431
- }, [getCurrentScrollOffset, getMaxScrollOffset, getScrollTarget, horizontal, isWindowScroll, scrollToLocalOffset]);
6541
+ }, [
6542
+ externalTarget,
6543
+ getCurrentScrollOffset,
6544
+ getRawScrollOffset,
6545
+ getMaxScrollOffset,
6546
+ isScrollInRange,
6547
+ getScrollTarget,
6548
+ horizontal,
6549
+ isWindowScroll,
6550
+ scrollToLocalOffset
6551
+ ]);
6432
6552
  const emitScroll = useCallback(() => {
6433
6553
  if (!onScroll2 || !scrollRef.current) {
6434
6554
  return;
6435
6555
  }
6436
6556
  const contentSize = getContentSize2(contentRef.current);
6437
- const layoutMeasurement = getLayoutMeasurement(scrollRef.current, isWindowScroll, horizontal);
6438
- const offset = getCurrentScrollOffset();
6557
+ const layoutMeasurement = getLayoutMeasurement(scrollRef.current, externalTarget, horizontal);
6558
+ const offset = getRawScrollOffset();
6439
6559
  const scrollEvent = {
6440
6560
  nativeEvent: {
6441
6561
  contentOffset: {
@@ -6453,7 +6573,7 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6453
6573
  }
6454
6574
  };
6455
6575
  onScroll2(scrollEvent);
6456
- }, [getCurrentScrollOffset, horizontal, isWindowScroll, onScroll2]);
6576
+ }, [externalTarget, getRawScrollOffset, horizontal, onScroll2]);
6457
6577
  const scrollEventCoalescer = useRafCoalescer(emitScroll);
6458
6578
  const scrollEndFallbackRef = useRef(void 0);
6459
6579
  const emitScrollEnd = useCallback(() => {
@@ -6515,14 +6635,14 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6515
6635
  const delta = horizontal ? event.deltaX || (event.shiftKey ? event.deltaY : 0) : event.deltaY;
6516
6636
  if (delta < 0 && !event.ctrlKey && !event.defaultPrevented && (ctx.state.maintainingScrollAtEnd || ctx.state.pendingMaintainScrollAtEnd)) {
6517
6637
  const offset = getCurrentScrollOffset();
6518
- if (interruptMaintainScrollAtEnd(ctx)) {
6638
+ if (interruptMaintainScrollAtEnd(ctx) && isScrollInRange()) {
6519
6639
  scrollToLocalOffset(offset, false);
6520
6640
  }
6521
6641
  }
6522
6642
  };
6523
6643
  target.addEventListener("wheel", onWheel, { passive: true });
6524
6644
  return () => target.removeEventListener("wheel", onWheel);
6525
- }, [ctx, getCurrentScrollOffset, getScrollTarget, horizontal, scrollToLocalOffset]);
6645
+ }, [ctx, getCurrentScrollOffset, getScrollTarget, horizontal, isScrollInRange, scrollToLocalOffset]);
6526
6646
  useEffect(() => {
6527
6647
  const doScroll = () => {
6528
6648
  if (contentOffset) {
@@ -6530,44 +6650,28 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6530
6650
  }
6531
6651
  };
6532
6652
  doScroll();
6533
- requestAnimationFrame(doScroll);
6653
+ const frame = requestAnimationFrame(doScroll);
6654
+ return () => cancelAnimationFrame(frame);
6534
6655
  }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y, horizontal, scrollToLocalOffset]);
6535
6656
  useLayoutEffect(() => {
6536
- if (!onLayout || !scrollRef.current) return;
6537
6657
  const element = scrollRef.current;
6538
- const fireLayout = () => {
6539
- onLayout({
6540
- nativeEvent: {
6541
- layout: getLayoutRectangle(element, isWindowScroll, horizontal)
6542
- }
6543
- });
6544
- };
6545
- fireLayout();
6546
- const resizeObserver = new ResizeObserver(() => {
6547
- fireLayout();
6548
- });
6549
- resizeObserver.observe(element);
6550
- const onWindowResize = () => {
6551
- fireLayout();
6552
- };
6553
- if (isWindowScroll && typeof window !== "undefined" && typeof window.addEventListener === "function") {
6554
- window.addEventListener("resize", onWindowResize);
6555
- }
6556
- return () => {
6557
- resizeObserver.disconnect();
6558
- if (isWindowScroll && typeof window !== "undefined" && typeof window.removeEventListener === "function") {
6559
- window.removeEventListener("resize", onWindowResize);
6658
+ if (!onLayout || !element) return;
6659
+ return observeScrollLayout(element, externalTarget, () => {
6660
+ if (isExternalScroll && !ctx.state.lastLayout && !ctx.state.initialScroll) {
6661
+ ctx.state.scroll = ctx.state.scrollPending = getRawScrollOffset();
6560
6662
  }
6561
- };
6562
- }, [isWindowScroll, onLayout]);
6563
- const hiddenScrollIndicatorClassName = !isWindowScroll && (horizontal ? !showsHorizontalScrollIndicator && LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS : !showsVerticalScrollIndicator && LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS);
6663
+ onLayout({ nativeEvent: { layout: getLayoutRectangle(element, externalTarget, horizontal) } });
6664
+ if (isExternalScroll) emitScroll();
6665
+ });
6666
+ }, [ctx, emitScroll, externalTarget, getRawScrollOffset, horizontal, isExternalScroll, onLayout]);
6667
+ const hiddenScrollIndicatorClassName = !isExternalScroll && (horizontal ? !showsHorizontalScrollIndicator && LEGEND_LIST_SCROLLBAR_X_HIDDEN_CLASS : !showsVerticalScrollIndicator && LEGEND_LIST_SCROLLBAR_Y_HIDDEN_CLASS);
6564
6668
  useLayoutEffect(() => {
6565
6669
  if (hiddenScrollIndicatorClassName) {
6566
6670
  ensureScrollbarHiddenStyle();
6567
6671
  }
6568
6672
  }, [hiddenScrollIndicatorClassName]);
6569
6673
  const scrollViewStyle = {
6570
- ...isWindowScroll ? {} : {
6674
+ ...isExternalScroll ? {} : {
6571
6675
  overflow: "auto",
6572
6676
  overflowX: horizontal ? "auto" : showsHorizontalScrollIndicator ? "auto" : "hidden",
6573
6677
  overflowY: horizontal ? showsVerticalScrollIndicator ? "auto" : "hidden" : "auto",
@@ -6602,11 +6706,10 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
6602
6706
  scrollEventThrottle: _scrollEventThrottle,
6603
6707
  ScrollComponent: _ScrollComponent,
6604
6708
  snapToOffsets,
6605
- useWindowScroll: _useWindowScroll,
6606
6709
  className: scrollViewClassNameProp,
6607
6710
  ...webProps
6608
6711
  } = props;
6609
- const snapOffsets = !isWindowScroll ? getFiniteSnapOffsets(snapToOffsets) : [];
6712
+ const snapOffsets = !isExternalScroll ? getFiniteSnapOffsets(snapToOffsets) : [];
6610
6713
  if (snapOffsets.length > 0) {
6611
6714
  scrollViewStyle.scrollSnapType = horizontal ? "x mandatory" : "y mandatory";
6612
6715
  contentStyle.position = (_c = contentStyle.position) != null ? _c : "relative";
@@ -6681,12 +6784,12 @@ function getScrollAdjustAxis(horizontal) {
6681
6784
  };
6682
6785
  }
6683
6786
  function getScrollAdjustTarget(ctx, contentNode) {
6684
- var _a3, _b, _c;
6787
+ var _a3, _b, _c, _d, _e;
6685
6788
  const scrollView = (_a3 = ctx.state) == null ? void 0 : _a3.refScroller.current;
6686
6789
  const scrollElement = (_c = (_b = scrollView == null ? void 0 : scrollView.getScrollableNode) == null ? void 0 : _b.call(scrollView)) != null ? _c : null;
6687
6790
  let resolvedContentNode = null;
6688
6791
  if (scrollElement) {
6689
- resolvedContentNode = (contentNode == null ? void 0 : contentNode.isConnected) && contentNode.parentElement === scrollElement ? contentNode : scrollElement.querySelector(`:scope > .${LEGEND_LIST_CONTENT_CONTAINER_CLASS}`);
6792
+ resolvedContentNode = (_e = (_d = scrollView == null ? void 0 : scrollView.getContentNode) == null ? void 0 : _d.call(scrollView)) != null ? _e : (contentNode == null ? void 0 : contentNode.isConnected) && contentNode.parentElement === scrollElement ? contentNode : scrollElement.querySelector(`:scope > .${LEGEND_LIST_CONTENT_CONTAINER_CLASS}`);
6690
6793
  }
6691
6794
  return scrollElement ? { contentNode: resolvedContentNode, scrollElement } : null;
6692
6795
  }
@@ -6701,6 +6804,7 @@ function ScrollAdjust() {
6701
6804
  const temporaryPaddingRef = React3.useRef(void 0);
6702
6805
  const contentNodeRef = React3.useRef(null);
6703
6806
  const callback = React3.useCallback(() => {
6807
+ var _a3, _b, _c;
6704
6808
  const scrollAdjust = peek$(ctx, "scrollAdjust");
6705
6809
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
6706
6810
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
@@ -6711,17 +6815,21 @@ function ScrollAdjust() {
6711
6815
  const horizontal = !!ctx.state.props.horizontal;
6712
6816
  const axis = getScrollAdjustAxis(horizontal);
6713
6817
  const { contentNode, scrollElement: el } = target;
6714
- const currentScroll = horizontal ? el.scrollLeft : el.scrollTop;
6818
+ const scroller = ctx.state.refScroller.current;
6819
+ const parentScroll = horizontal ? el.scrollLeft : el.scrollTop;
6820
+ const isExternal = ctx.state.props.hasExternalScroll;
6821
+ const currentScroll = (_b = isExternal ? (_a3 = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _a3.call(scroller) : void 0) != null ? _b : parentScroll;
6822
+ const isOutsideList = ((_c = scroller == null ? void 0 : scroller.isScrollInRange) == null ? void 0 : _c.call(scroller)) === false;
6715
6823
  const userOffsetDelta = (scrollAdjustUserOffset || 0) - lastScrollAdjustUserOffsetRef.current;
6716
6824
  const intendedScroll = userOffsetDelta !== 0 ? currentScroll + userOffsetDelta : ctx.state.scroll;
6717
6825
  const scrollDelta = intendedScroll - currentScroll;
6718
- const shouldScroll = Math.abs(scrollDelta) > 0.01;
6826
+ const shouldScroll = !isOutsideList && Math.abs(scrollDelta) > 0.01;
6719
6827
  const scrollBy = () => scrollAdjustBy(el, axis.x * scrollDelta, axis.y * scrollDelta);
6720
6828
  contentNodeRef.current = contentNode;
6721
6829
  if (shouldScroll && contentNode) {
6722
- const totalSize = contentNode[axis.contentSizeKey];
6830
+ const totalSize = isExternal ? el[axis.contentSizeKey] : contentNode[axis.contentSizeKey];
6723
6831
  const viewportSize = el[axis.viewportSizeKey];
6724
- const nextScroll = currentScroll + scrollDelta;
6832
+ const nextScroll = parentScroll + scrollDelta;
6725
6833
  const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize;
6726
6834
  if (needsTemporaryPadding) {
6727
6835
  const currentInlinePaddingEnd = contentNode.style[axis.paddingEndProp];
@@ -6886,6 +6994,7 @@ var ListComponent = typedMemo(function ListComponent2({
6886
6994
  stickyHeaderConfig,
6887
6995
  stickyHeaderIndices,
6888
6996
  useWindowScroll = false,
6997
+ scrollElement,
6889
6998
  ...rest
6890
6999
  }) {
6891
7000
  const ctx = useStateContext();
@@ -6951,7 +7060,7 @@ var ListComponent = typedMemo(function ListComponent2({
6951
7060
  SnapOrScroll,
6952
7061
  {
6953
7062
  ...rest,
6954
- ...ScrollComponent === ListComponentScrollView ? { onInternalScrollEnd, useWindowScroll } : {} ,
7063
+ ...ScrollComponent === ListComponentScrollView ? { onInternalScrollEnd, scrollElement, useWindowScroll } : {} ,
6955
7064
  contentContainerStyle: [
6956
7065
  horizontal ? { height: "100%" } : {},
6957
7066
  contentContainerStyle,
@@ -6991,7 +7100,15 @@ var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
6991
7100
  var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
6992
7101
  function useDevChecksImpl(props) {
6993
7102
  const ctx = useStateContext();
6994
- const { anchoredEndSpace, childrenMode, keyExtractor, numColumns, renderScrollComponent, useWindowScroll } = props;
7103
+ const {
7104
+ anchoredEndSpace,
7105
+ childrenMode,
7106
+ keyExtractor,
7107
+ numColumns,
7108
+ renderScrollComponent,
7109
+ scrollElement,
7110
+ useWindowScroll
7111
+ } = props;
6995
7112
  const hasAnchoredEndSpace = !!anchoredEndSpace;
6996
7113
  useEffect(() => {
6997
7114
  if (hasAnchoredEndSpace && (numColumns != null ? numColumns : 1) > 1) {
@@ -7002,13 +7119,13 @@ function useDevChecksImpl(props) {
7002
7119
  }
7003
7120
  }, [hasAnchoredEndSpace, numColumns]);
7004
7121
  useEffect(() => {
7005
- if (useWindowScroll && renderScrollComponent) {
7122
+ if ((useWindowScroll || scrollElement !== void 0) && renderScrollComponent) {
7006
7123
  warnDevOnce(
7007
7124
  "useWindowScrollRenderScrollComponent",
7008
- "useWindowScroll is not supported when renderScrollComponent is provided."
7125
+ "useWindowScroll and scrollElement are not supported when renderScrollComponent is provided."
7009
7126
  );
7010
7127
  }
7011
- }, [renderScrollComponent, useWindowScroll]);
7128
+ }, [renderScrollComponent, scrollElement, useWindowScroll]);
7012
7129
  useEffect(() => {
7013
7130
  if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
7014
7131
  warnDevOnce(
@@ -7020,8 +7137,8 @@ function useDevChecksImpl(props) {
7020
7137
  useEffect(() => {
7021
7138
  const state = ctx.state;
7022
7139
  const dataLength = state.props.data.length;
7023
- const useWindowScrollResolved = state.props.useWindowScroll;
7024
- if (useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
7140
+ const usesExternalScroll = state.props.hasExternalScroll;
7141
+ if (usesExternalScroll || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
7025
7142
  return;
7026
7143
  }
7027
7144
  const warnIfUnboundedOuterSize = () => {
@@ -7185,7 +7302,8 @@ function doInitialAllocateContainers(ctx) {
7185
7302
  calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
7186
7303
  });
7187
7304
  } else {
7188
- calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
7305
+ const reuseInitialPositions = !state.didLoad && state.positionsAreCurrent && !state.didDataChange && !state.didColumnsChange;
7306
+ calculateItemsInView(ctx, { dataChanged: !reuseInitialPositions, doMVCP: true });
7189
7307
  }
7190
7308
  }
7191
7309
  return true;
@@ -7228,12 +7346,14 @@ function handleLayout(ctx, layoutParam, setCanRender) {
7228
7346
  updateContentMetricsState(ctx);
7229
7347
  state.lastBatchingAction = Date.now();
7230
7348
  state.scrollForNextCalculateItemsInView = void 0;
7231
- if (scrollLength > 0) {
7232
- doInitialAllocateContainers(ctx);
7233
- }
7234
- if (needsCalculate) {
7349
+ const didAllocate = scrollLength > 0 && doInitialAllocateContainers(ctx);
7350
+ if (needsCalculate && (!didAllocate || state.initialScroll)) {
7235
7351
  calculateItemsInView(ctx, { doMVCP: true });
7236
7352
  }
7353
+ const scrollTarget = state.scrollingTo;
7354
+ if (scrollLength !== previousLength && (scrollTarget == null ? void 0 : scrollTarget.viewPositionFallback) && !scrollTarget.isInitialScroll && scrollTarget.index !== void 0) {
7355
+ scrollToIndex(ctx, { ...scrollTarget, forceScroll: true, index: scrollTarget.index });
7356
+ }
7237
7357
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
7238
7358
  set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
7239
7359
  }
@@ -7309,7 +7429,7 @@ function onScroll(ctx, event) {
7309
7429
  state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.scroll > state.scrollLength;
7310
7430
  state.lastNativeScroll = newScroll;
7311
7431
  state.lastNativeScrollTime = Date.now();
7312
- if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
7432
+ if (!state.props.hasExternalScroll && state.scrollingTo && state.scrollingTo.offset >= newScroll) {
7313
7433
  const maxOffset = clampScrollOffset(ctx, newScroll, state.scrollingTo);
7314
7434
  if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
7315
7435
  newScroll = maxOffset;
@@ -8076,6 +8196,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8076
8196
  stickyHeaderIndices: stickyHeaderIndicesProp,
8077
8197
  style: styleProp,
8078
8198
  useWindowScroll = false,
8199
+ scrollElement,
8079
8200
  viewabilityConfig,
8080
8201
  viewabilityConfigCallbackPairs,
8081
8202
  ...rest
@@ -8131,9 +8252,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8131
8252
  viewPosition: 1
8132
8253
  } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
8133
8254
  index: (_b = initialScrollIndexProp.index) != null ? _b : 0,
8134
- preserveForBottomPadding: initialScrollIndexProp.viewOffset === void 0 && initialScrollIndexProp.viewPosition === 1 ? true : void 0,
8135
- viewOffset: (_c = initialScrollIndexProp.viewOffset) != null ? _c : initialScrollIndexProp.viewPosition === 1 ? getEndAlignedViewOffset(stylePaddingEndState) : 0,
8136
- viewPosition: (_d = initialScrollIndexProp.viewPosition) != null ? _d : 0
8255
+ preserveForBottomPadding: initialScrollIndexProp.viewOffset === void 0 && initialScrollIndexProp.viewPosition === 1 && initialScrollIndexProp.viewPositionFallback === void 0 ? true : void 0,
8256
+ viewOffset: (_c = initialScrollIndexProp.viewOffset) != null ? _c : initialScrollIndexProp.viewPosition === 1 && initialScrollIndexProp.viewPositionFallback === void 0 ? getEndAlignedViewOffset(stylePaddingEndState) : 0,
8257
+ viewPosition: (_d = initialScrollIndexProp.viewPosition) != null ? _d : 0,
8258
+ viewPositionFallback: initialScrollIndexProp.viewPositionFallback
8137
8259
  } : {
8138
8260
  index: initialScrollIndexProp != null ? initialScrollIndexProp : 0,
8139
8261
  preserveForBottomPadding: shouldBottomAlignNumericInitialScrollIndex ? true : void 0,
@@ -8170,7 +8292,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8170
8292
  dataVersion,
8171
8293
  keyExtractor
8172
8294
  ]);
8173
- const useWindowScrollResolved = !!useWindowScroll && !renderScrollComponent;
8295
+ const scrollElementResolved = !renderScrollComponent ? scrollElement : void 0;
8296
+ const useWindowScrollResolved = !!useWindowScroll && scrollElementResolved === void 0 && !renderScrollComponent;
8297
+ const hasExternalScroll = useWindowScrollResolved || scrollElementResolved !== void 0;
8174
8298
  const refState = useRef(void 0);
8175
8299
  const hasOverrideItemLayout = !!overrideItemLayout;
8176
8300
  const prevHasOverrideItemLayout = useRef(hasOverrideItemLayout);
@@ -8308,6 +8432,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8308
8432
  estimatedItemSize,
8309
8433
  getFixedItemSize: useWrapIfItem(getFixedItemSize),
8310
8434
  getItemType: useWrapIfItem(getItemType),
8435
+ hasExternalScroll,
8311
8436
  hideItemsUntilMeasured: experimental_hideItemsUntilMeasured,
8312
8437
  horizontal: !!horizontal,
8313
8438
  itemsAreEqual,
@@ -8499,8 +8624,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8499
8624
  const { onLayout } = useOnLayoutSync({
8500
8625
  onLayoutChange,
8501
8626
  onLayoutProp,
8502
- ref: refScroller
8627
+ ref: refScroller,
8503
8628
  // the type of ScrollView doesn't include measure?
8629
+ webExternalScroll: hasExternalScroll
8504
8630
  });
8505
8631
  useLayoutEffect(() => {
8506
8632
  if (snapToIndices) {
@@ -8666,6 +8792,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8666
8792
  refScrollView: combinedRef,
8667
8793
  renderScrollComponent,
8668
8794
  scrollAdjustHandler: (_s = refState.current) == null ? void 0 : _s.scrollAdjustHandler,
8795
+ scrollElement: scrollElementResolved,
8669
8796
  scrollEventThrottle: 0,
8670
8797
  snapToIndices,
8671
8798
  stickyHeaderIndices,