@legendapp/list 3.7.0 → 3.7.1

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.js CHANGED
@@ -345,27 +345,20 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
345
345
  const { props } = state;
346
346
  const horizontal = props.horizontal;
347
347
  const baseInset = state.nativeContentInset;
348
- const baseEndInset = (horizontal ? getHorizontalInsetEnd(state, baseInset) : baseInset == null ? void 0 : baseInset.bottom) || 0;
349
348
  const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
350
349
  contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
351
350
  );
352
351
  const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
353
352
  const anchoredEndInset = props.anchoredEndSpace && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
354
353
  const overrideInset = (_a3 = state.contentInsetOverride) != null ? _a3 : void 0;
355
- const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
356
- if (overrideInset) {
357
- const mergedInset = { bottom: 0, left: 0, right: 0, ...baseInset, ...overrideInset };
358
- return Math.max(
359
- ((horizontal ? getHorizontalInsetEnd(state, mergedInset) : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
360
- anchoredEndInset
361
- );
362
- }
363
- return Math.max(adjustedBaseEndInset, anchoredEndInset);
354
+ const mergedInset = overrideInset ? { bottom: 0, left: 0, right: 0, ...baseInset, ...overrideInset } : baseInset;
355
+ const endInset = ((horizontal ? getHorizontalInsetEnd(state, mergedInset) : mergedInset == null ? void 0 : mergedInset.bottom) || 0) + contentInsetEndAdjustment;
356
+ return Math.max(endInset, anchoredEndInset);
364
357
  }
365
358
 
366
359
  // src/state/getContentSize.ts
367
- function getContentSize(ctx) {
368
- var _a3, _b;
360
+ function getContentSize(ctx, includeContentContainerMinSize = true) {
361
+ var _a3, _b, _c;
369
362
  const { values, state } = ctx;
370
363
  const stylePaddingStart = state.props.horizontal ? state.props.stylePaddingLeft || 0 : values.get("stylePaddingTop") || 0;
371
364
  const stylePaddingEnd = state.props.horizontal ? state.props.stylePaddingRight || 0 : state.props.stylePaddingBottom || 0;
@@ -375,7 +368,10 @@ function getContentSize(ctx) {
375
368
  const contentInsetEnd = getContentInsetEnd(ctx);
376
369
  const totalSize = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize");
377
370
  const layoutSize = Math.max(0, totalSize - (state.props.data.length > 0 ? ctx.scrollAxisGap : 0));
378
- return headerSize + footerSize + layoutSize + stylePaddingStart + alignItemsAtEndPadding + stylePaddingEnd + (contentInsetEnd || 0);
371
+ const contentSize = headerSize + footerSize + layoutSize + stylePaddingStart + alignItemsAtEndPadding + stylePaddingEnd;
372
+ const inContentInset = contentInsetEnd ;
373
+ const containerSize = contentSize + inContentInset;
374
+ return (includeContentContainerMinSize ? Math.max(containerSize, (_c = state.props.contentContainerMinSize) != null ? _c : 0) : containerSize) + contentInsetEnd - inContentInset;
379
375
  }
380
376
 
381
377
  // src/components/DebugView.tsx
@@ -491,6 +487,33 @@ function cancelImperativeScroll(state) {
491
487
  settlePendingImperativeScroll(state);
492
488
  }
493
489
 
490
+ // src/core/clampScrollOffset.ts
491
+ function getContentInsetTop(ctx) {
492
+ ctx.state;
493
+ {
494
+ return 0;
495
+ }
496
+ }
497
+ function getScrollRangeEnd(ctx, contentSize = getContentSize(ctx)) {
498
+ return Math.max(0 - getContentInsetTop(ctx), contentSize - ctx.state.scrollLength);
499
+ }
500
+ function clampScrollOffset(ctx, offset, scrollTarget) {
501
+ var _a3;
502
+ const state = ctx.state;
503
+ const minOffset = 0 - getContentInsetTop(ctx);
504
+ const contentSize = getContentSize(ctx, !scrollTarget || !!scrollTarget.clampToContentContainerMinSize);
505
+ let clampedOffset = offset;
506
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
507
+ const baseMaxOffset = getScrollRangeEnd(ctx, contentSize);
508
+ const viewOffset = (scrollTarget == null ? void 0 : scrollTarget.isInitialScroll) ? void 0 : scrollTarget == null ? void 0 : scrollTarget.viewOffset;
509
+ const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
510
+ const isRawOffset = (scrollTarget == null ? void 0 : scrollTarget.offset) !== void 0 && (scrollTarget.index === void 0 || scrollTarget.isInitialScroll && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset");
511
+ const maxOffset = Math.max(isRawOffset ? 0 : minOffset, baseMaxOffset + extraEndOffset);
512
+ clampedOffset = Math.min(offset, maxOffset);
513
+ }
514
+ return Math.max(minOffset, clampedOffset);
515
+ }
516
+
494
517
  // src/core/doScrollParams.ts
495
518
  function getNativeScrollPoint(ctx, offset, horizontal = ctx.state.props.horizontal) {
496
519
  var _a3;
@@ -668,23 +691,6 @@ function getObservedScrollOffset(ctx, fallbackOffset = ctx.state.scroll) {
668
691
  return state.props.horizontal ? peekLogicalHorizontalOffset(state, observed, (_c = scroller.getMaxScrollOffset) == null ? void 0 : _c.call(scroller)) : observed;
669
692
  }
670
693
 
671
- // src/core/clampScrollOffset.ts
672
- function clampScrollOffset(ctx, offset, scrollTarget) {
673
- const state = ctx.state;
674
- const minSize = (scrollTarget == null ? void 0 : scrollTarget.clampToContentContainerMinSize) ? state.props.contentContainerMinSize : void 0;
675
- const contentSize = minSize === void 0 ? getContentSize(ctx) : Math.max(getContentSize(ctx), minSize);
676
- let clampedOffset = offset;
677
- if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
678
- const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
679
- const viewOffset = (scrollTarget == null ? void 0 : scrollTarget.isInitialScroll) ? void 0 : scrollTarget == null ? void 0 : scrollTarget.viewOffset;
680
- const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
681
- const maxOffset = baseMaxOffset + extraEndOffset;
682
- clampedOffset = Math.min(offset, maxOffset);
683
- }
684
- clampedOffset = Math.max(0, clampedOffset);
685
- return clampedOffset;
686
- }
687
-
688
694
  // src/core/updateContentMetricsState.ts
689
695
  function getRawContentLength(ctx) {
690
696
  var _a3, _b, _c;
@@ -694,7 +700,7 @@ function getRawContentLength(ctx) {
694
700
  function getAlignItemsAtEndPadding(ctx) {
695
701
  const { state } = ctx;
696
702
  const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
697
- return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
703
+ return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetTop(ctx) - getContentInsetEnd(ctx)) : 0;
698
704
  }
699
705
  function updateContentMetricsState(ctx) {
700
706
  var _a3;
@@ -801,70 +807,66 @@ function isOutsideThresholdHysteresis(distance, atThreshold, threshold) {
801
807
  const absDistance = Math.abs(distance);
802
808
  return !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
803
809
  }
810
+ function didThresholdDataChange(snapshot, context) {
811
+ return !!snapshot && (snapshot.dataLength !== context.dataLength || snapshot.data !== context.data && snapshot.contentSize !== context.contentSize);
812
+ }
804
813
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
805
814
  const absDistance = Math.abs(distance);
806
- const within = atThreshold || threshold > 0 && absDistance <= threshold;
807
- const updateSnapshot = () => {
808
- setSnapshot({
809
- atThreshold,
810
- contentSize: context.contentSize,
811
- dataLength: context.dataLength,
812
- scrollPosition: context.scrollPosition
813
- });
814
- };
815
- let reached = !!wasReached;
816
- if (!wasReached) {
817
- if (within && onReached(distance)) {
818
- updateSnapshot();
819
- reached = true;
820
- }
821
- } else {
822
- const reset = isOutsideThresholdHysteresis(distance, atThreshold, threshold);
823
- if (reset) {
815
+ const within = context.dataLength !== 0 && (atThreshold || threshold > 0 && absDistance <= threshold);
816
+ const didScroll = (snapshot == null ? void 0 : snapshot.scroll) !== context.scroll;
817
+ if (snapshot) snapshot.scroll = context.scroll;
818
+ if (!within) {
819
+ if ((context.dataLength === 0 || didScroll && isOutsideThresholdHysteresis(distance, atThreshold, threshold)) && (wasReached || snapshot)) {
824
820
  setSnapshot(void 0);
825
- reached = false;
826
- } else if (within) {
827
- const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
828
- if (changed) {
829
- updateSnapshot();
830
- }
831
821
  }
822
+ return false;
832
823
  }
833
- return reached;
824
+ if ((!wasReached || didThresholdDataChange(snapshot, context)) && onReached(distance)) {
825
+ return true;
826
+ }
827
+ return !!wasReached;
834
828
  };
835
829
 
836
830
  // src/utils/edgeReachedGate.ts
837
- function resetEdgeLatch(ctx, edge) {
838
- const state = ctx.state;
839
- if (edge === "start") {
840
- state.isStartReached = false;
841
- state.startReachedSnapshot = void 0;
842
- } else {
843
- state.isEndReached = false;
844
- state.endReachedSnapshot = void 0;
845
- }
831
+ function getDistanceFromStart(ctx) {
832
+ return ctx.state.scroll + getContentInsetTop(ctx);
846
833
  }
847
834
  function resetSharedEdgeGateIfOutsideHysteresis(ctx) {
848
835
  const state = ctx.state;
849
- if (!state.edgeReachedGate) {
836
+ if (!state.edgeReachedGate || state.edgeReachedGateScroll === state.scroll) {
850
837
  return;
851
838
  }
839
+ state.edgeReachedGateScroll = state.scroll;
852
840
  const contentSize = getContentSize(ctx);
853
841
  const endDistance = contentSize - state.scroll - state.scrollLength;
854
842
  const isContentLess = contentSize < state.scrollLength;
855
843
  const startThreshold = state.props.onStartReachedThreshold * state.scrollLength;
856
844
  const endThreshold = state.props.onEndReachedThreshold * state.scrollLength;
857
- const isOutsideStart = isOutsideThresholdHysteresis(state.scroll, false, startThreshold);
845
+ const isOutsideStart = isOutsideThresholdHysteresis(getDistanceFromStart(ctx), false, startThreshold);
858
846
  const isOutsideEnd = isOutsideThresholdHysteresis(endDistance, isContentLess, endThreshold);
859
847
  if (isOutsideStart && isOutsideEnd) {
860
848
  state.edgeReachedGate = void 0;
861
849
  }
862
850
  }
863
851
  function canDispatchReachedEdge(ctx, edge, allowedEdge, allowGateCreatedInCurrentCheck) {
864
- return !ctx.state.edgeReachedGate || allowedEdge === edge || !!allowGateCreatedInCurrentCheck;
852
+ const state = ctx.state;
853
+ return !state.edgeReachedGate || allowedEdge === edge || !!allowGateCreatedInCurrentCheck || didThresholdDataChange(
854
+ edge === "start" ? state.startReachedSnapshot : state.endReachedSnapshot,
855
+ getThresholdSnapshot(ctx)
856
+ );
865
857
  }
866
- function markReachedEdge(ctx) {
867
- ctx.state.edgeReachedGate = "closed";
858
+ function markReachedEdge(ctx, edge) {
859
+ const state = ctx.state;
860
+ state.edgeReachedGate = "closed";
861
+ state.edgeReachedGateScroll = state.scroll;
862
+ const snapshotKey = edge === "start" ? "startReachedSnapshot" : "endReachedSnapshot";
863
+ const snapshot = getThresholdSnapshot(ctx);
864
+ snapshot.didRearmForData = didThresholdDataChange(state[snapshotKey], snapshot);
865
+ state[snapshotKey] = snapshot;
866
+ }
867
+ function getThresholdSnapshot(ctx) {
868
+ const { data } = ctx.state.props;
869
+ return { contentSize: getContentSize(ctx), data, dataLength: data.length, scroll: ctx.state.scroll };
868
870
  }
869
871
  function prepareReachedEdgeForNextUserScroll(ctx) {
870
872
  if (ctx.state.edgeReachedGate) {
@@ -873,11 +875,19 @@ function prepareReachedEdgeForNextUserScroll(ctx) {
873
875
  }
874
876
  function beginReachedEdgeUserScroll(ctx, scrollDelta) {
875
877
  const state = ctx.state;
876
- if (state.edgeReachedGate !== "prepared") {
878
+ const allowedEdge = scrollDelta < 0 ? "start" : "end";
879
+ if (state.edgeReachedGate !== "prepared" && state.edgeReachedGate !== (allowedEdge === "start" ? "consumed-end" : "consumed-start")) {
877
880
  return void 0;
878
881
  }
879
- const allowedEdge = scrollDelta < 0 ? "start" : "end";
880
- resetEdgeLatch(ctx, allowedEdge);
882
+ const snapshotKey = allowedEdge === "start" ? "startReachedSnapshot" : "endReachedSnapshot";
883
+ const snapshot = state[snapshotKey];
884
+ if ((snapshot == null ? void 0 : snapshot.didRearmForData) && snapshot.data === state.props.data) {
885
+ snapshot.didRearmForData = false;
886
+ state.edgeReachedGate = state.edgeReachedGate === "prepared" ? `consumed-${allowedEdge}` : "closed";
887
+ return void 0;
888
+ }
889
+ state[allowedEdge === "start" ? "isStartReached" : "isEndReached"] = false;
890
+ state[snapshotKey] = void 0;
881
891
  return allowedEdge;
882
892
  }
883
893
 
@@ -888,7 +898,6 @@ function hasActiveInitialScroll(state) {
888
898
 
889
899
  // src/utils/checkAtBottom.ts
890
900
  function checkAtBottom(ctx, allowedEdge, allowGateCreatedInCurrentCheck) {
891
- var _a3;
892
901
  const state = ctx.state;
893
902
  if (!state) {
894
903
  return;
@@ -928,19 +937,14 @@ function checkAtBottom(ctx, allowedEdge, allowGateCreatedInCurrentCheck) {
928
937
  onEndReachedThreshold * scrollLength,
929
938
  state.isEndReached,
930
939
  state.endReachedSnapshot,
931
- {
932
- contentSize,
933
- dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
934
- scrollPosition: scroll
935
- },
940
+ { contentSize, data: state.props.data, dataLength: state.props.data.length, scroll },
936
941
  (distance) => {
937
- let dispatched = false;
938
942
  if (state.props.onEndReached && canDispatchReachedEdge(ctx, "end", allowedEdge, allowGateCreatedInCurrentCheck)) {
939
- markReachedEdge(ctx);
943
+ markReachedEdge(ctx, "end");
940
944
  state.props.onEndReached({ distanceFromEnd: distance });
941
- dispatched = true;
945
+ return true;
942
946
  }
943
- return dispatched;
947
+ return false;
944
948
  },
945
949
  (snapshot) => {
946
950
  state.endReachedSnapshot = snapshot;
@@ -957,43 +961,30 @@ function checkAtTop(ctx, allowedEdge, allowGateCreatedInCurrentCheck) {
957
961
  return;
958
962
  }
959
963
  const {
960
- isStartReached,
961
964
  props: { data, onStartReachedThreshold },
962
- scroll,
963
- scrollLength,
964
- startReachedSnapshot,
965
- totalSize
965
+ scrollLength
966
966
  } = state;
967
- const dataLength = data.length;
968
967
  const threshold = onStartReachedThreshold * scrollLength;
968
+ const distanceFromStart = getDistanceFromStart(ctx);
969
969
  resetSharedEdgeGateIfOutsideHysteresis(ctx);
970
- if (isStartReached && threshold > 0 && scroll > threshold && startReachedSnapshot && (startReachedSnapshot.contentSize !== totalSize || startReachedSnapshot.dataLength !== dataLength)) {
971
- state.isStartReached = false;
972
- state.startReachedSnapshot = void 0;
973
- }
974
- set$(ctx, "isAtStart", scroll <= EDGE_POSITION_EPSILON);
975
- set$(ctx, "isNearStart", scroll <= threshold);
970
+ set$(ctx, "isAtStart", distanceFromStart <= EDGE_POSITION_EPSILON);
971
+ set$(ctx, "isNearStart", distanceFromStart <= threshold);
976
972
  const shouldSkipThresholdChecks = !state.queuedInitialLayout || hasActiveInitialScroll(state) || !!state.scrollingTo;
977
973
  if (!shouldSkipThresholdChecks) {
978
974
  state.isStartReached = checkThreshold(
979
- scroll,
975
+ distanceFromStart,
980
976
  false,
981
977
  threshold,
982
978
  state.isStartReached,
983
- startReachedSnapshot,
984
- {
985
- contentSize: totalSize,
986
- dataLength,
987
- scrollPosition: scroll
988
- },
979
+ state.startReachedSnapshot,
980
+ { contentSize: getContentSize(ctx), data, dataLength: data.length, scroll: state.scroll },
989
981
  (distance) => {
990
- let dispatched = false;
991
982
  if (state.props.onStartReached && canDispatchReachedEdge(ctx, "start", allowedEdge, allowGateCreatedInCurrentCheck)) {
992
- markReachedEdge(ctx);
983
+ markReachedEdge(ctx, "start");
993
984
  state.props.onStartReached({ distanceFromStart: distance });
994
- dispatched = true;
985
+ return true;
995
986
  }
996
- return dispatched;
987
+ return false;
997
988
  },
998
989
  (snapshot) => {
999
990
  state.startReachedSnapshot = snapshot;
@@ -1463,11 +1454,9 @@ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1463
1454
  if (viewOffset) {
1464
1455
  offset -= viewOffset;
1465
1456
  }
1457
+ const leadingInset = index !== void 0 ? getContentInsetTop(ctx) : 0;
1466
1458
  if (index !== void 0) {
1467
- const startOffsetAdjustment = getStartOffsetAdjustment(ctx);
1468
- if (startOffsetAdjustment) {
1469
- offset += startOffsetAdjustment;
1470
- }
1459
+ offset += getStartOffsetAdjustment(ctx) - leadingInset;
1471
1460
  }
1472
1461
  if (viewPosition !== void 0 && index !== void 0) {
1473
1462
  const dataLength = state.props.data.length;
@@ -1479,9 +1468,12 @@ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1479
1468
  const measuredItemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1480
1469
  const itemSize = Math.max(0, measuredItemSize - (isOutOfBounds ? 0 : ctx.scrollAxisGap));
1481
1470
  const trailingInset = getContentInsetEnd(ctx);
1482
- const availableSpace = state.scrollLength - trailingInset - itemSize;
1471
+ const availableSpace = state.scrollLength - leadingInset - trailingInset - itemSize;
1483
1472
  offset += getViewPositionOffset(availableSpace, viewPosition, viewPositionFallback);
1484
1473
  }
1474
+ if (index !== void 0 && params.clampToContentContainerMinSize) {
1475
+ offset += getContentSize(ctx) - getContentSize(ctx, false);
1476
+ }
1485
1477
  return offset;
1486
1478
  }
1487
1479
 
@@ -1534,11 +1526,12 @@ function shouldQueueNativeMVCPAdjust(dataChanged, state, positionDiff, prevTotal
1534
1526
  return false;
1535
1527
  }
1536
1528
  }
1537
- function getPredictedNativeClamp(state, unresolvedAmount, totalSize) {
1529
+ function getPredictedNativeClamp(ctx, unresolvedAmount, totalSize) {
1538
1530
  if (Math.abs(unresolvedAmount) <= MVCP_POSITION_EPSILON) {
1539
1531
  return 0;
1540
1532
  }
1541
- const maxScroll = Math.max(0, totalSize - state.scrollLength);
1533
+ const state = ctx.state;
1534
+ const maxScroll = getScrollRangeEnd(ctx, totalSize);
1542
1535
  const clampDelta = maxScroll - state.scroll;
1543
1536
  if (unresolvedAmount < 0) {
1544
1537
  return Math.max(unresolvedAmount, Math.min(0, clampDelta));
@@ -1566,7 +1559,7 @@ function maybeApplyPredictedNativeMVCPAdjust(ctx) {
1566
1559
  return;
1567
1560
  }
1568
1561
  const totalSize = getContentSize(ctx);
1569
- const predictedNativeClamp = getPredictedNativeClamp(state, pending.amount, totalSize);
1562
+ const predictedNativeClamp = getPredictedNativeClamp(ctx, pending.amount, totalSize);
1570
1563
  if (Math.abs(predictedNativeClamp) <= MVCP_POSITION_EPSILON) {
1571
1564
  return;
1572
1565
  }
@@ -1600,7 +1593,7 @@ function resolvePendingNativeMVCPAdjust(ctx, newScroll) {
1600
1593
  settlePendingNativeMVCPAdjust(ctx, remainingAfterManual, nativeDelta);
1601
1594
  return true;
1602
1595
  }
1603
- const expectedNativeClampScroll = Math.max(0, getContentSize(ctx) - state.scrollLength);
1596
+ const expectedNativeClampScroll = getScrollRangeEnd(ctx);
1604
1597
  const distanceToClamp = Math.abs(newScroll - expectedNativeClampScroll);
1605
1598
  const isAtExpectedNativeClamp = distanceToClamp <= NATIVE_END_CLAMP_EPSILON;
1606
1599
  if (isAtExpectedNativeClamp) {
@@ -1741,7 +1734,7 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) {
1741
1734
  if (diff > 0) {
1742
1735
  diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1743
1736
  } else {
1744
- const maxScroll = Math.max(0, totalSize - state.scrollLength);
1737
+ const maxScroll = getScrollRangeEnd(ctx, totalSize);
1745
1738
  state.scroll = maxScroll;
1746
1739
  state.scrollPending = maxScroll;
1747
1740
  diff = 0;
@@ -1758,7 +1751,7 @@ function prepareMVCP(ctx, dataChanged, adjustmentSource) {
1758
1751
  const prevSize = scrollingTo.itemSize;
1759
1752
  if (prevSize !== void 0 && newSize !== prevSize) {
1760
1753
  if (scrollingTo.viewPositionFallback) {
1761
- const viewport = state.scrollLength - getContentInsetEnd(ctx);
1754
+ const viewport = state.scrollLength - getContentInsetTop(ctx) - getContentInsetEnd(ctx);
1762
1755
  const previousSpace = viewport - Math.max(0, prevSize - ctx.scrollAxisGap);
1763
1756
  const nextSpace = viewport - Math.max(0, newSize - ctx.scrollAxisGap);
1764
1757
  positionDiff += getViewPositionOffset(
@@ -1965,27 +1958,31 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
1965
1958
  }
1966
1959
 
1967
1960
  // src/core/cancelScroll.ts
1968
- function cancelScroll(ctx, stopAnimation = true, commitAdjust = true) {
1961
+ function cancelScroll(ctx, stopAnimation = true, commitAdjust = true, inputDelta = 0) {
1969
1962
  var _a3, _b;
1970
1963
  const { state } = ctx;
1971
1964
  const observed = getObservedScrollOffset(ctx, peek$(ctx, "scrollAdjustPending") ? state.scrollPending : void 0);
1972
1965
  const wasAnimating = !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.animated) || !!((_b = ctx.scrollRequestTracker) == null ? void 0 : _b.cancel());
1966
+ const stopped = wasAnimating && stopAnimation;
1967
+ const stopOffset = stopped && inputDelta ? clampScrollOffset(ctx, observed + inputDelta) : observed;
1973
1968
  releaseScrollOwners(ctx, true);
1974
- state.scrollPending = observed;
1969
+ state.scrollPending = stopOffset;
1975
1970
  const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1976
1971
  if (peek$(ctx, "scrollAdjustPending")) state.ignoreScrollFromMVCP = void 0;
1977
- updateScroll(ctx, observed, true, { markHasScrolled: false });
1972
+ updateScroll(ctx, stopOffset, true, { markHasScrolled: false });
1978
1973
  state.ignoreScrollFromMVCP = ignoreScrollFromMVCP;
1979
- if (wasAnimating && stopAnimation) stopScrollAnimation(ctx, observed);
1974
+ if (stopped) stopScrollAnimation(ctx, observed, inputDelta);
1980
1975
  if (commitAdjust) state.scrollAdjustHandler.commitPendingAdjust();
1981
1976
  else state.scrollAdjustHandler.supersedePendingAdjust();
1977
+ return stopped;
1982
1978
  }
1983
- function stopScrollAnimation(ctx, observed = getObservedScrollOffset(ctx)) {
1979
+ function stopScrollAnimation(ctx, observed = getObservedScrollOffset(ctx), inputDelta = 0) {
1984
1980
  var _a3, _b;
1985
1981
  const { state } = ctx;
1986
1982
  const scroller = state.refScroller.current;
1987
- const x = state.props.horizontal ? (_b = (_a3 = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _a3.call(scroller)) != null ? _b : getNativeScrollPoint(ctx, observed).x : 0;
1988
- scroller == null ? void 0 : scroller.scrollTo({ animated: false, x, y: state.props.horizontal ? 0 : observed });
1983
+ const offset = observed + inputDelta;
1984
+ const x = !state.props.horizontal ? 0 : inputDelta ? getNativeScrollPoint(ctx, offset).x : (_b = (_a3 = scroller == null ? void 0 : scroller.getCurrentScrollOffset) == null ? void 0 : _a3.call(scroller)) != null ? _b : getNativeScrollPoint(ctx, observed).x;
1985
+ scroller == null ? void 0 : scroller.scrollTo({ animated: false, x, y: state.props.horizontal ? 0 : offset });
1989
1986
  }
1990
1987
  function releaseScrollOwners(ctx, supersedeInitial) {
1991
1988
  var _a3;
@@ -1999,12 +1996,39 @@ function releaseScrollOwners(ctx, supersedeInitial) {
1999
1996
  clearPreservedInitialScrollTarget(state);
2000
1997
  syncScrollActive(ctx);
2001
1998
  }
2002
- function interruptUserScroll(ctx) {
2003
- if (ctx.state.scrollingTo || ctx.state.initialScroll && !ctx.state.didFinishInitialScroll) {
2004
- cancelScroll(ctx, Platform.OS === "web");
2005
- } else {
2006
- releaseScrollOwners(ctx, false);
1999
+ function interruptUserScroll(ctx, inputDelta = 0) {
2000
+ var _a3;
2001
+ if (ctx.state.scrollingTo || ((_a3 = ctx.scrollRequestTracker) == null ? void 0 : _a3.isWaitingToRun()) || ctx.state.initialScroll && !ctx.state.didFinishInitialScroll) {
2002
+ return cancelScroll(ctx, Platform.OS === "web", true, inputDelta) && inputDelta !== 0;
2003
+ }
2004
+ releaseScrollOwners(ctx, false);
2005
+ return false;
2006
+ }
2007
+
2008
+ // src/utils/clampScrollIndex.ts
2009
+ function clampScrollIndex(index, dataLength) {
2010
+ if (dataLength <= 0) {
2011
+ return -1;
2012
+ }
2013
+ if (index >= dataLength) {
2014
+ return dataLength - 1;
2007
2015
  }
2016
+ if (index < 0) {
2017
+ return 0;
2018
+ }
2019
+ return index;
2020
+ }
2021
+
2022
+ // src/core/getCurrentTargetOffset.ts
2023
+ function isEndAlignedLastItemTarget(ctx, scrollingTo) {
2024
+ return (scrollingTo.isScrollToEnd || scrollingTo.index === ctx.state.props.data.length - 1) && scrollingTo.viewPosition === 1;
2025
+ }
2026
+ function getCurrentTargetOffset(ctx, scrollingTo) {
2027
+ var _a3, _b;
2028
+ const index = scrollingTo.isScrollToEnd ? ctx.state.props.data.length - 1 : scrollingTo.index === void 0 ? void 0 : clampScrollIndex(scrollingTo.index, ctx.state.props.data.length);
2029
+ const isRetargetingWebScroll = (!scrollingTo.isInitialScroll || ((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap");
2030
+ const requestedTargetOffset = index !== void 0 && (isRetargetingWebScroll || isEndAlignedLastItemTarget(ctx, scrollingTo)) ? calculateOffsetWithOffsetPosition(ctx, calculateOffsetForIndex(ctx, index), { ...scrollingTo, index }) : isRetargetingWebScroll ? calculateOffsetWithOffsetPosition(ctx, scrollingTo.offset, scrollingTo) : (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset - (scrollingTo.viewOffset || 0);
2031
+ return clampScrollOffset(ctx, requestedTargetOffset, scrollingTo);
2008
2032
  }
2009
2033
 
2010
2034
  // src/core/scrollRequestTracker.ts
@@ -2048,7 +2072,7 @@ function getScrollRequestTracker(ctx) {
2048
2072
  state.scrollAdjustHandler.commitPendingAdjust();
2049
2073
  }
2050
2074
  }
2051
- if (didStartScroll === "unreachable") {
2075
+ if (didStartScroll === "unreachable" || !didStartScroll && state.scrollingTo) {
2052
2076
  cancelScroll(ctx);
2053
2077
  return;
2054
2078
  }
@@ -2089,6 +2113,18 @@ function getScrollRequestTracker(ctx) {
2089
2113
  }
2090
2114
 
2091
2115
  // src/core/doMaintainScrollAtEnd.ts
2116
+ function reissueClampedNativeEndScroll(ctx) {
2117
+ var _a3, _b, _c;
2118
+ const state = ctx.state;
2119
+ const target = state.scrollingTo;
2120
+ if ((target == null ? void 0 : target.isScrollToEnd) && !target.animated && !((_a3 = ctx.scrollRequestTracker) == null ? void 0 : _a3.isWaitingToRun())) {
2121
+ const targetOffset = getCurrentTargetOffset(ctx, target);
2122
+ const distanceToTarget = targetOffset - ((_b = state.lastNativeScroll) != null ? _b : state.scroll);
2123
+ if (distanceToTarget > 1 || state.lastNativeScroll === void 0 && distanceToTarget < -1) {
2124
+ (_c = state.refScroller.current) == null ? void 0 : _c.scrollTo({ animated: false, ...getNativeScrollPoint(ctx, targetOffset) });
2125
+ }
2126
+ }
2127
+ }
2092
2128
  function doMaintainScrollAtEnd(ctx, options) {
2093
2129
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2094
2130
  const state = ctx.state;
@@ -2137,7 +2173,7 @@ function doMaintainScrollAtEnd(ctx, options) {
2137
2173
  return false;
2138
2174
  }
2139
2175
  if (state.scrollingTo || state.pendingScrollResolve) {
2140
- if (immediate && ((_k = state.scrollingTo) == null ? void 0 : _k.isScrollToEnd) && !state.scrollingTo.animated) {
2176
+ if ((options == null ? void 0 : options.immediate) && !maintainScrollAtEnd.animated && ((_k = state.scrollingTo) == null ? void 0 : _k.isScrollToEnd) && !state.scrollingTo.animated) {
2141
2177
  state.pendingMaintainScrollAtEnd = false;
2142
2178
  ctx.scrollToEnd({ animated: false });
2143
2179
  return true;
@@ -2148,7 +2184,7 @@ function doMaintainScrollAtEnd(ctx, options) {
2148
2184
  state.pendingMaintainScrollAtEnd = false;
2149
2185
  const contentSize = getContentSize(ctx);
2150
2186
  if (contentSize < state.scrollLength) {
2151
- state.scroll = 0;
2187
+ state.scroll = clampScrollOffset(ctx, 0);
2152
2188
  }
2153
2189
  if (!state.maintainingScrollAtEnd || immediate && (state.maintainingScrollAtEnd === "pending-instant" || state.maintainingScrollAtEnd === "instant")) {
2154
2190
  const pendingState = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
@@ -2241,20 +2277,6 @@ function finishScrollTo(ctx) {
2241
2277
  }
2242
2278
  }
2243
2279
 
2244
- // src/utils/clampScrollIndex.ts
2245
- function clampScrollIndex(index, dataLength) {
2246
- if (dataLength <= 0) {
2247
- return -1;
2248
- }
2249
- if (index >= dataLength) {
2250
- return dataLength - 1;
2251
- }
2252
- if (index < 0) {
2253
- return 0;
2254
- }
2255
- return index;
2256
- }
2257
-
2258
2280
  // src/core/checkFinishedScroll.ts
2259
2281
  var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
2260
2282
  var INITIAL_SCROLL_COMPLETION_TARGET_EPSILON = 1;
@@ -2302,16 +2324,6 @@ function shouldFinishInitialZeroTargetScroll(ctx) {
2302
2324
  const { state } = ctx;
2303
2325
  return !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) && state.props.data.length > 0 && getContentSize(ctx) <= state.scrollLength && state.scrollPending <= INITIAL_SCROLL_ZERO_TARGET_EPSILON;
2304
2326
  }
2305
- function isEndAlignedLastItemTarget(ctx, scrollingTo) {
2306
- return (scrollingTo.isScrollToEnd || scrollingTo.index === ctx.state.props.data.length - 1) && scrollingTo.viewPosition === 1;
2307
- }
2308
- function getCurrentTargetOffset(ctx, scrollingTo) {
2309
- var _a3, _b;
2310
- const index = scrollingTo.isScrollToEnd ? ctx.state.props.data.length - 1 : scrollingTo.index === void 0 ? void 0 : clampScrollIndex(scrollingTo.index, ctx.state.props.data.length);
2311
- const isRetargetingWebScroll = (!scrollingTo.isInitialScroll || ((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap");
2312
- const requestedTargetOffset = index !== void 0 && (isRetargetingWebScroll || isEndAlignedLastItemTarget(ctx, scrollingTo)) ? calculateOffsetWithOffsetPosition(ctx, calculateOffsetForIndex(ctx, index), { ...scrollingTo, index }) : isRetargetingWebScroll ? calculateOffsetWithOffsetPosition(ctx, scrollingTo.offset, scrollingTo) : (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset - (scrollingTo.viewOffset || 0);
2313
- return clampScrollOffset(ctx, requestedTargetOffset, scrollingTo);
2314
- }
2315
2327
  function getResolvedScrollCompletionState(ctx, scrollingTo) {
2316
2328
  const { state } = ctx;
2317
2329
  const isWebInitialScroll = scrollingTo.isInitialScroll;
@@ -2323,9 +2335,10 @@ function getResolvedScrollCompletionState(ctx, scrollingTo) {
2323
2335
  const adjustedTargetOffset = clampedTargetOffset + adjust;
2324
2336
  const diff2 = Math.abs(scroll - adjustedTargetOffset);
2325
2337
  const canUseAdjustedCompletion = !isWebInitialScroll && (!scrollingTo.animated || Platform.OS === "ios");
2338
+ const isWaitingForNativeEnd = Platform.OS !== "web";
2326
2339
  return {
2327
2340
  clampedTargetOffset,
2328
- isAtResolvedTarget: Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || canUseAdjustedCompletion && diff2 < 1)
2341
+ isAtResolvedTarget: !isWaitingForNativeEnd && Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || canUseAdjustedCompletion && diff2 < 1)
2329
2342
  };
2330
2343
  }
2331
2344
  function checkFinishedScrollFrame(ctx) {
@@ -2709,18 +2722,20 @@ function scrollTo(ctx, params) {
2709
2722
  if (forceScroll || !isInitialScroll || Platform.OS === "android") {
2710
2723
  doScrollTo(ctx, { animated, horizontal, offset });
2711
2724
  } else {
2712
- state.scroll = offset;
2725
+ state.scroll = targetOffset;
2713
2726
  }
2714
2727
  }
2715
2728
 
2716
2729
  // src/core/initialScroll.ts
2717
2730
  function dispatchInitialScroll(ctx, params) {
2731
+ var _a3;
2718
2732
  const { forceScroll, resolvedOffset, target, waitForCompletionFrame } = params;
2719
2733
  const requestedIndex = target.index;
2720
2734
  const index = requestedIndex !== void 0 ? clampScrollIndex(requestedIndex, ctx.state.props.data.length) : void 0;
2721
2735
  const itemSize = getItemSizeAtIndex(ctx, index);
2722
2736
  scrollTo(ctx, {
2723
2737
  animated: false,
2738
+ clampToContentContainerMinSize: ((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" || isEndOfContentTarget(target, ctx.state.props.data.length),
2724
2739
  forceScroll,
2725
2740
  index: index !== void 0 && index >= 0 ? index : void 0,
2726
2741
  isInitialScroll: true,
@@ -2753,8 +2768,12 @@ function resolveInitialScrollOffset(ctx, initialScroll) {
2753
2768
  return (_b = initialScroll.contentOffset) != null ? _b : 0;
2754
2769
  }
2755
2770
  const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
2756
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
2757
- return clampScrollOffset(ctx, resolvedOffset, initialScroll);
2771
+ const target = {
2772
+ ...initialScroll,
2773
+ clampToContentContainerMinSize: isEndOfContentTarget(initialScroll, state.props.data.length)
2774
+ };
2775
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, target);
2776
+ return clampScrollOffset(ctx, resolvedOffset, target);
2758
2777
  }
2759
2778
  function getAdvanceableInitialScrollState(state, options) {
2760
2779
  const { didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
@@ -3573,7 +3592,7 @@ function updateSnapToOffsets(ctx) {
3573
3592
  const {
3574
3593
  props: { snapToIndices }
3575
3594
  } = state;
3576
- const contentSize = state.props.horizontal ? getContentSize(ctx) : void 0;
3595
+ const contentSize = state.props.horizontal ? getContentSize(ctx, false) : void 0;
3577
3596
  const snapToOffsets = Array(snapToIndices.length);
3578
3597
  for (let i = 0; i < snapToIndices.length; i++) {
3579
3598
  const idx = snapToIndices[i];
@@ -4632,31 +4651,7 @@ function maybeEmitFirstVisibleItemChanged(state, index) {
4632
4651
  state.lastFirstVisibleItemCallback = { index, key };
4633
4652
  onFirstVisibleItemChanged({ index, item: state.props.data[index], key });
4634
4653
  }
4635
- function findFirstVisibleIndexInCachedRange(ctx, scroll) {
4636
- var _a3, _b;
4637
- const state = ctx.state;
4638
- const {
4639
- endBuffered,
4640
- idCache,
4641
- positions,
4642
- props: { data },
4643
- sizes,
4644
- startBuffered
4645
- } = state;
4646
- if (startBuffered === null || endBuffered === null || startBuffered < 0 || endBuffered < startBuffered) {
4647
- return null;
4648
- }
4649
- for (let i = startBuffered; i <= endBuffered && i < data.length; i++) {
4650
- const id = (_a3 = idCache[i]) != null ? _a3 : getId(state, i);
4651
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(ctx, id, i, data[i]);
4652
- const top = positions[i];
4653
- if (top + size > scroll) {
4654
- return i;
4655
- }
4656
- }
4657
- return null;
4658
- }
4659
- function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4654
+ function updateVisibleRangeForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4660
4655
  var _a3, _b, _c, _d;
4661
4656
  const state = ctx.state;
4662
4657
  const {
@@ -4684,14 +4679,11 @@ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, sc
4684
4679
  break;
4685
4680
  }
4686
4681
  }
4687
- Object.assign(state, {
4688
- endNoBuffer: visibleRange.endNoBuffer,
4689
- firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4690
- idsInView: getIdsInVisibleRange(state, visibleRange),
4691
- startNoBuffer: visibleRange.startNoBuffer
4682
+ Object.assign(state, visibleRange, {
4683
+ idsInView: getIdsInVisibleRange(state, visibleRange)
4692
4684
  });
4693
4685
  maybeEmitFirstVisibleItemChanged(state, visibleRange.startNoBuffer);
4694
- if (state.props.hasExternalScroll || visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4686
+ if (viewabilityConfigCallbackPairs && (state.props.hasExternalScroll || visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null)) {
4695
4687
  updateViewableItems(
4696
4688
  state,
4697
4689
  ctx,
@@ -4734,7 +4726,8 @@ function calculateItemsInView(ctx, params = {}) {
4734
4726
  if (!data || scrollLength === 0 || !prevNumContainers) {
4735
4727
  return;
4736
4728
  }
4737
- let totalSize = getContentSize(ctx);
4729
+ const includeContentContainerMinSize = Platform.OS === "web";
4730
+ let totalSize = getContentSize(ctx, includeContentContainerMinSize);
4738
4731
  let changedContainerIds;
4739
4732
  const topPad = getStartOffsetAdjustment(ctx);
4740
4733
  const numColumns = peek$(ctx, "numColumns");
@@ -4801,8 +4794,9 @@ function calculateItemsInView(ctx, params = {}) {
4801
4794
  const scrollStart = state.props.hasExternalScroll ? scroll : Math.max(0, scroll);
4802
4795
  const overscrollBeforeContent = state.props.hasExternalScroll ? 0 : Math.max(0, -nativeScrollState);
4803
4796
  scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
4797
+ const unusedTopBuffer = state.props.hasExternalScroll ? 0 : Math.max(0, scrollBufferTop - scroll);
4804
4798
  scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
4805
- scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
4799
+ scrollBottomBuffered = scrollBottom + scrollBufferBottom + unusedTopBuffer + projectedBufferAdjustment;
4806
4800
  };
4807
4801
  updateScrollRange();
4808
4802
  if (projectedBufferAdjustment !== 0) {
@@ -4814,17 +4808,13 @@ function calculateItemsInView(ctx, params = {}) {
4814
4808
  state.scrollForNextCalculateItemsInView = void 0;
4815
4809
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
4816
4810
  if (!isInMVCPActiveMode(state)) {
4817
- if (viewabilityConfigCallbackPairs) {
4818
- updateViewabilityForCachedRange(
4819
- ctx,
4820
- viewabilityConfigCallbackPairs,
4821
- scrollLength,
4822
- scroll,
4823
- scrollBottom
4824
- );
4825
- } else if (state.props.onFirstVisibleItemChanged) {
4826
- maybeEmitFirstVisibleItemChanged(state, findFirstVisibleIndexInCachedRange(ctx, scroll));
4827
- }
4811
+ updateVisibleRangeForCachedRange(
4812
+ ctx,
4813
+ viewabilityConfigCallbackPairs,
4814
+ scrollLength,
4815
+ scroll,
4816
+ scrollBottom
4817
+ );
4828
4818
  (_d = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _d.call(stickyState);
4829
4819
  return;
4830
4820
  }
@@ -4846,7 +4836,7 @@ function calculateItemsInView(ctx, params = {}) {
4846
4836
  scrollVelocity: speed,
4847
4837
  startIndex
4848
4838
  });
4849
- totalSize = getContentSize(ctx);
4839
+ totalSize = getContentSize(ctx, includeContentContainerMinSize);
4850
4840
  if (positionRecalculationStartIndex !== void 0) {
4851
4841
  state.positionRecalculationStartIndex = void 0;
4852
4842
  }
@@ -4944,14 +4934,11 @@ function calculateItemsInView(ctx, params = {}) {
4944
4934
  }
4945
4935
  }
4946
4936
  }
4947
- Object.assign(state, {
4937
+ Object.assign(state, visibleRange, {
4948
4938
  endBuffered,
4949
- endNoBuffer: visibleRange.endNoBuffer,
4950
- firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4951
4939
  idsInView: getIdsInVisibleRange(state, visibleRange),
4952
4940
  startBuffered,
4953
- startBufferedId,
4954
- startNoBuffer: visibleRange.startNoBuffer
4941
+ startBufferedId
4955
4942
  });
4956
4943
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
4957
4944
  state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
@@ -5214,7 +5201,11 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5214
5201
  contentBelowAnchor = Math.max(0, contentBelowAnchor - ctx.scrollAxisGap);
5215
5202
  contentBelowAnchor += (ctx.values.get("footerSize") || 0) + getStylePaddingEnd(state.props);
5216
5203
  isReady = !hasUnknownTailSize;
5217
- const knownSizeBound = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5204
+ const externalEndInset = 0;
5205
+ const knownSizeBound = Math.max(
5206
+ 0,
5207
+ state.scrollLength - contentBelowAnchor - anchorOffset - externalEndInset
5208
+ );
5218
5209
  nextSize = hasUnknownTailSize ? Math.min(previousSize || 0, knownSizeBound) : knownSizeBound;
5219
5210
  } else if (anchorIndex >= 0) {
5220
5211
  isReady = false;
@@ -5331,13 +5322,27 @@ function updateItemSizes(ctx, measurement) {
5331
5322
  updateItemSizesBatch(ctx, [measurement]);
5332
5323
  }
5333
5324
  }
5325
+ function isContainerItemCurrent(ctx, containerId, itemKey) {
5326
+ if (peek$(ctx, `containerItemKey${containerId}`) !== itemKey) return false;
5327
+ const state = ctx.state;
5328
+ const index = state.indexByKey.get(itemKey);
5329
+ if (index !== void 0 && index < state.props.data.length && getId(state, index) === itemKey) return true;
5330
+ state.scheduledWork.microtask(
5331
+ () => {
5332
+ var _a3;
5333
+ return (_a3 = ctx.containerLayoutTriggers.get(containerId)) == null ? void 0 : _a3();
5334
+ },
5335
+ `containerMeasurementRetry${containerId}`
5336
+ );
5337
+ return false;
5338
+ }
5334
5339
  function updateItemSizesBatch(ctx, measurements) {
5335
5340
  var _a3;
5336
5341
  const state = ctx.state;
5337
5342
  const result = {};
5338
5343
  const previousTotalSize = state.totalSize;
5339
5344
  for (const measurement of measurements) {
5340
- const ownsMeasuredItem = measurement.containerId === void 0 || peek$(ctx, `containerItemKey${measurement.containerId}`) === measurement.itemKey;
5345
+ const ownsMeasuredItem = measurement.containerId === void 0 || isContainerItemCurrent(ctx, measurement.containerId, measurement.itemKey);
5341
5346
  if (ownsMeasuredItem) {
5342
5347
  const index = state.indexByKey.get(measurement.itemKey);
5343
5348
  const itemData = index === void 0 ? void 0 : (_a3 = state.props.data) == null ? void 0 : _a3[index];
@@ -5496,7 +5501,7 @@ function measureContainersInLayoutEffect(ctx, targetContainerIds = null) {
5496
5501
  const viewRef = ctx.viewRefs.get(containerId);
5497
5502
  const itemKey = peek$(ctx, `containerItemKey${containerId}`);
5498
5503
  const element = viewRef == null ? void 0 : viewRef.current;
5499
- if (itemKey !== void 0 && element) {
5504
+ if (itemKey !== void 0 && element && isContainerItemCurrent(ctx, containerId, itemKey)) {
5500
5505
  const generation = (_b = ctx.state.containerItemGenerations[containerId]) != null ? _b : 0;
5501
5506
  const rect = element.getBoundingClientRect();
5502
5507
  setContainerLayoutBaseline(element, rect);
@@ -5530,7 +5535,7 @@ function measureContainersInLayoutEffect(ctx, targetContainerIds = null) {
5530
5535
  return index === void 0 || index < state.startBuffered || index > state.endBuffered || measuredKeys.has(key);
5531
5536
  });
5532
5537
  const physicalMax = (_e = (_d = state.refScroller.current) == null ? void 0 : _d.getMaxScrollOffset) == null ? void 0 : _e.call(_d);
5533
- const layoutMax = Math.max(0, getContentSize(ctx) - state.scrollLength);
5538
+ const layoutMax = getScrollRangeEnd(ctx);
5534
5539
  if (isCurrentViewportMeasured && isCurrentBufferMeasured && physicalMax !== void 0 && Math.abs(physicalMax - layoutMax) <= 1) {
5535
5540
  evaluateBootstrapInitialScroll(ctx);
5536
5541
  }
@@ -6985,7 +6990,8 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
6985
6990
  if (isWheel && !wheelAccepted) wheelStartedNested = true;
6986
6991
  return false;
6987
6992
  }
6988
- if (explicit ? !keepsExplicitOwner : direction <= 0) interruptUserScroll(ctx);
6993
+ if ((explicit ? !keepsExplicitOwner : direction <= 0) && interruptUserScroll(ctx, isWheel && event.cancelable ? direction : 0) && event.cancelable)
6994
+ event.preventDefault();
6989
6995
  if (isNew) (_b2 = (_a4 = state.props).onUserScroll) == null ? void 0 : _b2.call(_a4);
6990
6996
  return true;
6991
6997
  }
@@ -6997,11 +7003,15 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
6997
7003
  const inputDirection = (delta) => isHorizontalRTL(ctx.state) && getNativeHorizontalRTLScrollType(ctx.state) !== "normal" ? -delta : delta;
6998
7004
  const onWheel = (nativeEvent) => {
6999
7005
  const event = nativeEvent;
7000
- const delta = horizontal ? event.deltaX || (event.shiftKey ? event.deltaY : 0) : event.deltaY;
7006
+ const delta = normalizeWheelDelta(
7007
+ horizontal ? event.deltaX || (event.shiftKey ? event.deltaY : 0) : event.deltaY,
7008
+ event.deltaMode,
7009
+ ctx.state.scrollLength
7010
+ );
7001
7011
  if (delta !== 0 && !event.ctrlKey && !event.defaultPrevented) {
7002
7012
  wheelGesture = getWheelGesture(
7003
7013
  wheelGesture,
7004
- normalizeWheelDelta(delta, event.deltaMode, ctx.state.scrollLength),
7014
+ delta,
7005
7015
  event.timeStamp,
7006
7016
  event.momentum
7007
7017
  );
@@ -7071,7 +7081,15 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
7071
7081
  scrollbarPressOffset = void 0;
7072
7082
  if (offset !== void 0 && getCurrentScrollOffset() === offset) rearmEndFollowIfSettled(ctx);
7073
7083
  };
7074
- target.addEventListener("wheel", onWheel, { passive: true });
7084
+ let wheelPassive;
7085
+ const setWheelPassive = (passive) => {
7086
+ if (passive === wheelPassive) return;
7087
+ if (wheelPassive !== void 0) target.removeEventListener("wheel", onWheel);
7088
+ target.addEventListener("wheel", onWheel, { passive });
7089
+ wheelPassive = passive;
7090
+ };
7091
+ setWheelPassive(!peek$(ctx, "isScrollActive"));
7092
+ const unlistenScrollActive = listen$(ctx, "isScrollActive", (active) => setWheelPassive(!active));
7075
7093
  target.addEventListener("touchstart", onTouchStart, { passive: true });
7076
7094
  target.addEventListener("touchmove", onTouchMove, { passive: true });
7077
7095
  target.addEventListener("keydown", onKeyDown);
@@ -7079,6 +7097,7 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
7079
7097
  target.addEventListener("pointerup", onPointerRelease);
7080
7098
  target.addEventListener("pointercancel", onPointerRelease);
7081
7099
  return () => {
7100
+ unlistenScrollActive();
7082
7101
  target.removeEventListener("wheel", onWheel);
7083
7102
  target.removeEventListener("touchstart", onTouchStart);
7084
7103
  target.removeEventListener("touchmove", onTouchMove);
@@ -7501,6 +7520,14 @@ var ListComponent = typedMemo(function ListComponent2({
7501
7520
  },
7502
7521
  [ctx, onScrollToTop]
7503
7522
  );
7523
+ const { onContentSizeChange } = rest;
7524
+ React3.useCallback(
7525
+ (width, height) => {
7526
+ reissueClampedNativeEndScroll(ctx);
7527
+ onContentSizeChange == null ? void 0 : onContentSizeChange(width, height);
7528
+ },
7529
+ [ctx, onContentSizeChange]
7530
+ );
7504
7531
  const onLayoutHeader = React3.useCallback(
7505
7532
  (rect) => {
7506
7533
  const size = rect[horizontal ? "width" : "height"];
@@ -7656,6 +7683,7 @@ function checkResetContainers(ctx, dataProp, { didColumnsChange = false } = {})
7656
7683
  state.positionRecalculationStartIndex = 0;
7657
7684
  state.scrollForNextCalculateItemsInView = void 0;
7658
7685
  }
7686
+ state.positionsAreCurrent = false;
7659
7687
  calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
7660
7688
  if ((_a3 = state.pendingEndMeasurements) == null ? void 0 : _a3.size) {
7661
7689
  const removedMeasurements = new Set(state.pendingEndMeasurements);
@@ -7678,9 +7706,6 @@ function checkResetContainers(ctx, dataProp, { didColumnsChange = false } = {})
7678
7706
  if (!didMaintainScrollAtEnd && !state.pendingMaintainScrollAtEnd) {
7679
7707
  state.pendingEndMeasurements = void 0;
7680
7708
  }
7681
- if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
7682
- state.isEndReached = false;
7683
- }
7684
7709
  if (!didMaintainScrollAtEnd) {
7685
7710
  checkThresholds(ctx);
7686
7711
  }
@@ -7803,6 +7828,7 @@ function scrollToIndex(ctx, {
7803
7828
  animated = true,
7804
7829
  forceScroll,
7805
7830
  isInitialScroll,
7831
+ clampToContentContainerMinSize,
7806
7832
  viewPosition,
7807
7833
  viewPositionFallback
7808
7834
  }) {
@@ -7818,6 +7844,7 @@ function scrollToIndex(ctx, {
7818
7844
  state.scrollForNextCalculateItemsInView = void 0;
7819
7845
  scrollTo(ctx, {
7820
7846
  animated,
7847
+ clampToContentContainerMinSize,
7821
7848
  forceScroll,
7822
7849
  index,
7823
7850
  isInitialScroll,
@@ -8106,7 +8133,7 @@ var ScrollAdjustHandler = class {
8106
8133
  targetScroll = clampScrollOffset(this.ctx, targetScroll, scrollTarget);
8107
8134
  } else {
8108
8135
  targetScroll = clampScrollOffset(this.ctx, state.scroll + pending - superseded, {
8109
- clampToContentContainerMinSize: scrollTarget == null ? void 0 : scrollTarget.clampToContentContainerMinSize
8136
+ clampToContentContainerMinSize: !scrollTarget || scrollTarget.clampToContentContainerMinSize
8110
8137
  });
8111
8138
  }
8112
8139
  const adjustment = targetScroll - state.scroll;
@@ -8135,6 +8162,7 @@ function scrollToEnd(ctx, options) {
8135
8162
  const footerSize = peek$(ctx, "footerSize") || 0;
8136
8163
  scrollToIndex(ctx, {
8137
8164
  ...options,
8165
+ clampToContentContainerMinSize: true,
8138
8166
  index,
8139
8167
  viewOffset: getEndAlignedViewOffset(paddingBottom, footerSize) + ((options == null ? void 0 : options.viewOffset) || 0),
8140
8168
  viewPosition: 1
@@ -8354,9 +8382,10 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
8354
8382
  const observed = getObservedScrollOffset(ctx);
8355
8383
  const position = calculateOffsetForIndex(ctx, index) + getStartOffsetAdjustment(ctx) + (itemOffset != null ? itemOffset : 0);
8356
8384
  const size = hasRegion ? itemLength != null ? itemLength : 0 : ((_a3 = getItemSizeAtIndex(ctx, index)) != null ? _a3 : 0) - ctx.scrollAxisGap;
8357
- const viewportLength = state.scrollLength - getContentInsetEnd(ctx);
8358
- const viewportStart = observed + ((_b = viewportMargin == null ? void 0 : viewportMargin.start) != null ? _b : 0);
8359
- const viewportEnd = observed + viewportLength - ((_c = viewportMargin == null ? void 0 : viewportMargin.end) != null ? _c : 0);
8385
+ const insetTop = getContentInsetTop(ctx);
8386
+ const viewportLength = state.scrollLength - insetTop - getContentInsetEnd(ctx);
8387
+ const viewportStart = observed + insetTop + ((_b = viewportMargin == null ? void 0 : viewportMargin.start) != null ? _b : 0);
8388
+ const viewportEnd = observed + insetTop + viewportLength - ((_c = viewportMargin == null ? void 0 : viewportMargin.end) != null ? _c : 0);
8360
8389
  if (!hasRegion && position <= viewportStart && position + size >= viewportEnd) return false;
8361
8390
  const above = position < viewportStart;
8362
8391
  const below = position + size > viewportEnd;
@@ -8791,7 +8820,7 @@ var LegendList = typedMemo(
8791
8820
  })
8792
8821
  );
8793
8822
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
8794
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
8823
+ var _a3, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
8795
8824
  React3.useEffect(subscribeScreenReader, []);
8796
8825
  const noopOnScroll = React3.useCallback((_event) => {
8797
8826
  }, []);
@@ -8916,7 +8945,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8916
8945
  const hasInitialScrollIndex = initialScrollIndexProp !== void 0 && initialScrollIndexProp !== null;
8917
8946
  const hasInitialScrollOffset = initialScrollOffsetProp !== void 0 && initialScrollOffsetProp !== null;
8918
8947
  const shouldInitializeHorizontalRTL = !initialScrollAtEnd && !hasInitialScrollIndex && !hasInitialScrollOffset && isHorizontalRTLProps({ horizontal, rtl });
8919
- const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && (hasInitialScrollOffset || shouldInitializeHorizontalRTL);
8948
+ const initialInsetTop = 0;
8949
+ const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && (hasInitialScrollOffset || shouldInitializeHorizontalRTL || initialInsetTop > 0);
8920
8950
  const usesBootstrapInitialScroll = initialScrollAtEnd || hasInitialScrollIndex;
8921
8951
  const shouldBottomAlignNumericInitialScrollIndex = typeof initialScrollIndexProp === "number" && !hasInitialScrollOffset && dataProp.length > 1 && initialScrollIndexProp >= dataProp.length - 1;
8922
8952
  const initialScrollProp = initialScrollAtEnd ? {
@@ -8925,10 +8955,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8925
8955
  viewOffset: getEndAlignedViewOffset(stylePaddingEndState),
8926
8956
  viewPosition: 1
8927
8957
  } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
8928
- index: (_b = initialScrollIndexProp.index) != null ? _b : 0,
8958
+ index: (_c = initialScrollIndexProp.index) != null ? _c : 0,
8929
8959
  preserveForBottomPadding: initialScrollIndexProp.viewOffset === void 0 && initialScrollIndexProp.viewPosition === 1 && initialScrollIndexProp.viewPositionFallback === void 0 ? true : void 0,
8930
- viewOffset: (_c = initialScrollIndexProp.viewOffset) != null ? _c : initialScrollIndexProp.viewPosition === 1 && initialScrollIndexProp.viewPositionFallback === void 0 ? getEndAlignedViewOffset(stylePaddingEndState) : 0,
8931
- viewPosition: (_d = initialScrollIndexProp.viewPosition) != null ? _d : 0,
8960
+ viewOffset: (_d = initialScrollIndexProp.viewOffset) != null ? _d : initialScrollIndexProp.viewPosition === 1 && initialScrollIndexProp.viewPositionFallback === void 0 ? getEndAlignedViewOffset(stylePaddingEndState) : 0,
8961
+ viewPosition: (_e = initialScrollIndexProp.viewPosition) != null ? _e : 0,
8932
8962
  viewPositionFallback: initialScrollIndexProp.viewPositionFallback
8933
8963
  } : {
8934
8964
  index: initialScrollIndexProp != null ? initialScrollIndexProp : 0,
@@ -8936,7 +8966,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8936
8966
  viewOffset: initialScrollOffsetProp != null ? initialScrollOffsetProp : shouldBottomAlignNumericInitialScrollIndex ? getEndAlignedViewOffset(stylePaddingEndState) : 0,
8937
8967
  viewPosition: shouldBottomAlignNumericInitialScrollIndex ? 1 : void 0
8938
8968
  } : initialScrollUsesOffsetOnly ? {
8939
- contentOffset: initialScrollOffsetProp != null ? initialScrollOffsetProp : 0,
8969
+ contentOffset: initialScrollOffsetProp != null ? initialScrollOffsetProp : -initialInsetTop,
8940
8970
  index: 0,
8941
8971
  viewOffset: 0
8942
8972
  } : void 0;
@@ -8944,7 +8974,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8944
8974
  const [, scheduleImperativeScrollCommit] = React3__namespace.useReducer((value) => value + 1, 0);
8945
8975
  const ctx = useStateContext();
8946
8976
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
8947
- const scrollAxisGap = horizontal ? (_g = (_e = ctx.columnWrapperStyle) == null ? void 0 : _e.columnGap) != null ? _g : (_f = ctx.columnWrapperStyle) == null ? void 0 : _f.gap : (_j = (_h = ctx.columnWrapperStyle) == null ? void 0 : _h.rowGap) != null ? _j : (_i = ctx.columnWrapperStyle) == null ? void 0 : _i.gap;
8977
+ const scrollAxisGap = horizontal ? (_h = (_f = ctx.columnWrapperStyle) == null ? void 0 : _f.columnGap) != null ? _h : (_g = ctx.columnWrapperStyle) == null ? void 0 : _g.gap : (_k = (_i = ctx.columnWrapperStyle) == null ? void 0 : _i.rowGap) != null ? _k : (_j = ctx.columnWrapperStyle) == null ? void 0 : _j.gap;
8948
8978
  const nextScrollAxisGap = typeof scrollAxisGap === "number" && Number.isFinite(scrollAxisGap) ? scrollAxisGap : 0;
8949
8979
  const refScroller = React3.useRef(null);
8950
8980
  const combinedRef = useCombinedRef(refScroller, refScrollView);
@@ -8959,8 +8989,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8959
8989
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
8960
8990
  alwaysRender == null ? void 0 : alwaysRender.top,
8961
8991
  alwaysRender == null ? void 0 : alwaysRender.bottom,
8962
- (_k = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _k.join(","),
8963
- (_l = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _l.join(","),
8992
+ (_l = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _l.join(","),
8993
+ (_m = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _m.join(","),
8964
8994
  dataProp,
8965
8995
  dataKey,
8966
8996
  dataVersion,
@@ -8975,7 +9005,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
8975
9005
  if (!refState.current) {
8976
9006
  if (!ctx.state) {
8977
9007
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
8978
- ctx.values.set("adaptiveRender", (_m = experimental_adaptiveRender == null ? void 0 : experimental_adaptiveRender.initialMode) != null ? _m : "normal");
9008
+ ctx.values.set("adaptiveRender", (_n = experimental_adaptiveRender == null ? void 0 : experimental_adaptiveRender.initialMode) != null ? _n : "normal");
8979
9009
  ctx.state = {
8980
9010
  averageSizes: {},
8981
9011
  columnSpans: [],
@@ -9067,13 +9097,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9067
9097
  const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
9068
9098
  ctx.scrollAxisGap = nextScrollAxisGap;
9069
9099
  state.didColumnsChange = numColumnsProp !== previousNumColumnsProp || didScrollAxisGapChange;
9070
- const previousDataLength = (_o = (_n = state.props.data) == null ? void 0 : _n.length) != null ? _o : 0;
9100
+ const previousDataLength = (_p = (_o = state.props.data) == null ? void 0 : _o.length) != null ? _p : 0;
9071
9101
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
9072
9102
  const didDataKeyChangeLocal = state.props.dataKey !== dataKey;
9073
9103
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
9074
9104
  const didDataChangeLocal = didDataKeyChangeLocal || didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
9075
9105
  const shouldResetFreshDataLayout = !isFirstLocal && didDataChangeLocal && state.hasHadNonEmptyData && (didDataKeyChangeLocal || previousDataLength === 0) && dataProp.length > 0;
9076
- if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_p = state.initialScroll) == null ? void 0 : _p.viewPosition) === 1 && state.props.data.length > 0) {
9106
+ if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_q = state.initialScroll) == null ? void 0 : _q.viewPosition) === 1 && state.props.data.length > 0) {
9077
9107
  clearPreservedInitialScrollTarget(state);
9078
9108
  }
9079
9109
  if (didDataChangeLocal) {
@@ -9089,7 +9119,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9089
9119
  const freshDataTransitionEpoch = state.freshDataTransitionEpoch;
9090
9120
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
9091
9121
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
9092
- const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_q = state.props.anchoredEndSpace) == null ? void 0 : _q.anchorIndex) !== (anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
9122
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_r = state.props.anchoredEndSpace) == null ? void 0 : _r.anchorIndex) !== (anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
9093
9123
  state.props = {
9094
9124
  adaptiveRender: experimental_adaptiveRender,
9095
9125
  alignItemsAtEnd,
@@ -9272,6 +9302,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9272
9302
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
9273
9303
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorMaxSize,
9274
9304
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorOffset,
9305
+ anchoredEndSpaceOwner,
9306
+ contentInset == null ? void 0 : contentInset.bottom,
9307
+ contentInset == null ? void 0 : contentInset.left,
9308
+ contentInset == null ? void 0 : contentInset.right,
9275
9309
  didAnchoredEndSpaceAnchorIndexChange,
9276
9310
  horizontal,
9277
9311
  numColumnsProp,
@@ -9331,6 +9365,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9331
9365
  React3.useLayoutEffect(
9332
9366
  () => initializeStateVars(true),
9333
9367
  [
9368
+ contentInset == null ? void 0 : contentInset.bottom,
9369
+ contentInset == null ? void 0 : contentInset.top,
9334
9370
  dataKey,
9335
9371
  dataVersion,
9336
9372
  memoizedLastItemKeys.join(","),
@@ -9341,6 +9377,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9341
9377
  useAlignItemsAtEndPadding
9342
9378
  ]
9343
9379
  );
9380
+ const previousContentInsetTop = React3.useRef(contentInset == null ? void 0 : contentInset.top);
9381
+ React3.useLayoutEffect(() => {
9382
+ var _a4;
9383
+ Math.max(0, (_a4 = previousContentInsetTop.current) != null ? _a4 : 0);
9384
+ previousContentInsetTop.current !== (contentInset == null ? void 0 : contentInset.top);
9385
+ previousContentInsetTop.current = contentInset == null ? void 0 : contentInset.top;
9386
+ }, [contentInset == null ? void 0 : contentInset.top]);
9387
+ React3.useLayoutEffect(() => {
9388
+ checkThresholds(ctx);
9389
+ }, [maintainScrollAtEndThreshold]);
9344
9390
  React3.useLayoutEffect(() => {
9345
9391
  if (!maintainScrollAtEndConfig) {
9346
9392
  finishMaintainScrollAtEnd(ctx);
@@ -9516,7 +9562,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9516
9562
  onScroll: onScrollHandler,
9517
9563
  recycleItems,
9518
9564
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControlElement, {
9519
- progressViewOffset: ((_r = refreshControlElement.props.progressViewOffset) != null ? _r : 0) + stylePaddingTopState
9565
+ progressViewOffset: ((_s = refreshControlElement.props.progressViewOffset) != null ? _s : 0) + stylePaddingTopState
9520
9566
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
9521
9567
  RefreshControl,
9522
9568
  {
@@ -9527,7 +9573,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
9527
9573
  ),
9528
9574
  refScrollView: combinedRef,
9529
9575
  renderScrollComponent,
9530
- scrollAdjustHandler: (_s = refState.current) == null ? void 0 : _s.scrollAdjustHandler,
9576
+ scrollAdjustHandler: (_t = refState.current) == null ? void 0 : _t.scrollAdjustHandler,
9531
9577
  scrollElement: scrollElementResolved,
9532
9578
  scrollEventThrottle: 0,
9533
9579
  snapToIndices,