@legendapp/list 3.0.0-beta.51 → 3.0.0-beta.53

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/animated.d.ts CHANGED
@@ -248,6 +248,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
248
248
  * Keeps an item visually anchored to the start by adding trailing space when the content below it underflows.
249
249
  */
250
250
  anchoredEndSpace?: AnchoredEndSpaceConfig;
251
+ /**
252
+ * Adjusts the effective end content inset for web lists without replacing the base contentInset.
253
+ * The adjustment is also rendered as real content padding so the browser scroll range includes it.
254
+ */
255
+ contentInsetEndAdjustment?: number;
251
256
  /**
252
257
  * Number of columns to render items in.
253
258
  * @default 1
@@ -641,7 +646,7 @@ interface ViewabilityConfig {
641
646
  waitForInteraction?: boolean | undefined;
642
647
  }
643
648
 
644
- type LegendListPropsOverrides<ItemT, TItemType extends string | undefined> = Omit<LegendListPropsBase<ItemT, ScrollViewProps, TItemType>, "anchoredEndSpace" | "onScroll" | "refScrollView" | "renderScrollComponent" | "ListHeaderComponentStyle" | "ListFooterComponentStyle"> & {
649
+ type LegendListPropsOverrides<ItemT, TItemType extends string | undefined> = Omit<LegendListPropsBase<ItemT, ScrollViewProps, TItemType>, "anchoredEndSpace" | "contentInsetEndAdjustment" | "onScroll" | "refScrollView" | "renderScrollComponent" | "ListHeaderComponentStyle" | "ListFooterComponentStyle"> & {
645
650
  onScroll?: (event: NativeSyntheticEvent$1<NativeScrollEvent$1>) => void;
646
651
  refScrollView?: React.Ref<ScrollView>;
647
652
  renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
package/index.d.ts CHANGED
@@ -249,6 +249,7 @@ interface InternalState$1 {
249
249
  data: readonly any[];
250
250
  dataVersion: Key | undefined;
251
251
  drawDistance: number;
252
+ contentInsetEndAdjustment: number | undefined;
252
253
  estimatedItemSize: number | undefined;
253
254
  getEstimatedItemSize: LegendListPropsInternal["getEstimatedItemSize"];
254
255
  getFixedItemSize: LegendListPropsInternal["getFixedItemSize"];
@@ -573,6 +574,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
573
574
  * Keeps an item visually anchored to the start by adding trailing space when the content below it underflows.
574
575
  */
575
576
  anchoredEndSpace?: AnchoredEndSpaceConfig$1;
577
+ /**
578
+ * Adjusts the effective end content inset for web lists without replacing the base contentInset.
579
+ * The adjustment is also rendered as real content padding so the browser scroll range includes it.
580
+ */
581
+ contentInsetEndAdjustment?: number;
576
582
  /**
577
583
  * Number of columns to render items in.
578
584
  * @default 1
package/index.js CHANGED
@@ -166,7 +166,10 @@ function useSelector$(signalName, selector) {
166
166
  }
167
167
 
168
168
  // src/state/getContentInsetEnd.ts
169
- function getContentInsetEnd(ctx) {
169
+ function getContentInsetEndAdjustmentEnd(adjustment) {
170
+ return Math.max(0, adjustment != null ? adjustment : 0);
171
+ }
172
+ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
170
173
  var _a3, _b;
171
174
  const state = ctx.state;
172
175
  const { props } = state;
@@ -174,14 +177,21 @@ function getContentInsetEnd(ctx) {
174
177
  const contentInset = props.contentInset;
175
178
  const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
176
179
  const baseEndInset = (horizontal ? baseInset == null ? void 0 : baseInset.right : baseInset == null ? void 0 : baseInset.bottom) || 0;
180
+ const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
181
+ contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
182
+ );
177
183
  const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
178
184
  const anchoredEndInset = ((_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
179
185
  const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
186
+ const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
180
187
  if (overrideInset) {
181
188
  const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
182
- return Math.max((horizontal ? mergedInset.right : mergedInset.bottom) || 0, anchoredEndInset);
189
+ return Math.max(
190
+ ((horizontal ? mergedInset.right : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
191
+ anchoredEndInset
192
+ );
183
193
  }
184
- return Math.max(baseEndInset, anchoredEndInset);
194
+ return Math.max(adjustedBaseEndInset, anchoredEndInset);
185
195
  }
186
196
 
187
197
  // src/state/getContentSize.ts
@@ -679,6 +689,49 @@ function isInMVCPActiveMode(state) {
679
689
  }
680
690
 
681
691
  // src/components/Container.tsx
692
+ function getContainerPositionStyle({
693
+ columnWrapperStyle,
694
+ horizontal,
695
+ hasItemSeparator,
696
+ numColumns,
697
+ otherAxisPos,
698
+ otherAxisSize
699
+ }) {
700
+ let paddingStyles;
701
+ if (columnWrapperStyle) {
702
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
703
+ if (horizontal) {
704
+ paddingStyles = {
705
+ paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
706
+ paddingRight: columnGap || gap || void 0,
707
+ paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
708
+ };
709
+ } else {
710
+ paddingStyles = {
711
+ paddingBottom: rowGap || gap || void 0,
712
+ paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
713
+ paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
714
+ };
715
+ }
716
+ }
717
+ return horizontal ? {
718
+ boxSizing: paddingStyles ? "border-box" : void 0,
719
+ flexDirection: hasItemSeparator ? "row" : void 0,
720
+ height: otherAxisSize,
721
+ left: 0,
722
+ position: "absolute",
723
+ top: otherAxisPos,
724
+ ...paddingStyles || {}
725
+ } : {
726
+ boxSizing: paddingStyles ? "border-box" : void 0,
727
+ left: otherAxisPos,
728
+ position: "absolute",
729
+ right: numColumns > 1 ? null : 0,
730
+ top: 0,
731
+ width: otherAxisSize,
732
+ ...paddingStyles || {}
733
+ };
734
+ }
682
735
  var Container = typedMemo(function Container2({
683
736
  id,
684
737
  recycleItems,
@@ -717,42 +770,17 @@ var Container = typedMemo(function Container2({
717
770
  const resolvedSpan = Math.min(Math.max(span || 1, 1), numColumns);
718
771
  const otherAxisPos = numColumns > 1 ? `${(resolvedColumn - 1) / numColumns * 100}%` : 0;
719
772
  const otherAxisSize = numColumns > 1 ? `${resolvedSpan / numColumns * 100}%` : void 0;
720
- const style = React3.useMemo(() => {
721
- let paddingStyles;
722
- if (columnWrapperStyle) {
723
- const { columnGap, rowGap, gap } = columnWrapperStyle;
724
- if (horizontal) {
725
- paddingStyles = {
726
- paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
727
- paddingRight: columnGap || gap || void 0,
728
- paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
729
- };
730
- } else {
731
- paddingStyles = {
732
- paddingBottom: rowGap || gap || void 0,
733
- paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
734
- paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
735
- };
736
- }
737
- }
738
- return horizontal ? {
739
- boxSizing: paddingStyles ? "border-box" : void 0,
740
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
741
- height: otherAxisSize,
742
- left: 0,
743
- position: "absolute",
744
- top: otherAxisPos,
745
- ...paddingStyles || {}
746
- } : {
747
- boxSizing: paddingStyles ? "border-box" : void 0,
748
- left: otherAxisPos,
749
- position: "absolute",
750
- right: numColumns > 1 ? null : 0,
751
- top: 0,
752
- width: otherAxisSize,
753
- ...paddingStyles || {}
754
- };
755
- }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
773
+ const style = React3.useMemo(
774
+ () => getContainerPositionStyle({
775
+ columnWrapperStyle,
776
+ hasItemSeparator: !!ItemSeparatorComponent,
777
+ horizontal,
778
+ numColumns,
779
+ otherAxisPos,
780
+ otherAxisSize
781
+ }),
782
+ [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns, ItemSeparatorComponent]
783
+ );
756
784
  const renderedItemInfo = React3.useMemo(
757
785
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
758
786
  [itemKey, data, extraData]
@@ -1063,6 +1091,9 @@ function useRafCoalescer(callback) {
1063
1091
  return coalescer;
1064
1092
  }
1065
1093
 
1094
+ // src/components/webConstants.ts
1095
+ var LEGEND_LIST_CONTENT_CONTAINER_CLASS = "legend-list-content-container";
1096
+
1066
1097
  // src/components/webScrollUtils.ts
1067
1098
  function getDocumentScrollerNode() {
1068
1099
  if (typeof document === "undefined") {
@@ -1147,6 +1178,11 @@ function resolveWindowScrollTarget({ clampedOffset, horizontal, listPos, scroll
1147
1178
  }
1148
1179
 
1149
1180
  // src/components/ListComponentScrollView.tsx
1181
+ function getContentInsetEndAdjustmentEnd2(ctx) {
1182
+ var _a3, _b;
1183
+ const adjustment = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.props) == null ? void 0 : _b.contentInsetEndAdjustment;
1184
+ return Math.max(0, adjustment != null ? adjustment : 0);
1185
+ }
1150
1186
  var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
1151
1187
  children,
1152
1188
  style,
@@ -1164,7 +1200,9 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1164
1200
  onLayout,
1165
1201
  ...props
1166
1202
  }, ref) {
1203
+ var _a3, _b, _c;
1167
1204
  const ctx = useStateContext();
1205
+ const [anchoredEndSpaceSize] = useArr$(["anchoredEndSpaceSize"]);
1168
1206
  const scrollRef = React3.useRef(null);
1169
1207
  const contentRef = React3.useRef(null);
1170
1208
  const isWindowScroll = useWindowScroll;
@@ -1226,10 +1264,9 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1226
1264
  React3.useImperativeHandle(ref, () => {
1227
1265
  const api = {
1228
1266
  getBoundingClientRect: () => {
1229
- var _a3;
1230
- return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
1267
+ var _a4;
1268
+ return (_a4 = scrollRef.current) == null ? void 0 : _a4.getBoundingClientRect();
1231
1269
  },
1232
- getContentNode: () => contentRef.current,
1233
1270
  getCurrentScrollOffset,
1234
1271
  getScrollableNode: () => resolveScrollableNode(scrollRef.current, isWindowScroll),
1235
1272
  getScrollEventTarget: () => getScrollTarget(),
@@ -1355,6 +1392,10 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1355
1392
  },
1356
1393
  ...StyleSheet.flatten(style)
1357
1394
  };
1395
+ const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd2(ctx);
1396
+ const anchoredEndInset = ((_c = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.props) == null ? void 0 : _b.anchoredEndSpace) == null ? void 0 : _c.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
1397
+ const renderedContentInsetEndAdjustment = Math.max(0, contentInsetEndAdjustment - anchoredEndInset);
1398
+ const contentInsetEndAdjustmentSpacerStyle = renderedContentInsetEndAdjustment ? horizontal ? { flexShrink: 0, width: renderedContentInsetEndAdjustment } : { height: renderedContentInsetEndAdjustment } : void 0;
1358
1399
  const contentStyle = {
1359
1400
  display: horizontal ? "flex" : "block",
1360
1401
  flexDirection: horizontal ? "row" : void 0,
@@ -1362,6 +1403,7 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1362
1403
  minWidth: horizontal ? "100%" : void 0,
1363
1404
  ...StyleSheet.flatten(contentContainerStyle)
1364
1405
  };
1406
+ const className = contentContainerClassName ? `${LEGEND_LIST_CONTENT_CONTAINER_CLASS} ${contentContainerClassName}` : LEGEND_LIST_CONTENT_CONTAINER_CLASS;
1365
1407
  const {
1366
1408
  contentContainerClassName: _contentContainerClassName,
1367
1409
  contentInset: _contentInset,
@@ -1370,7 +1412,7 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1370
1412
  useWindowScroll: _useWindowScroll,
1371
1413
  ...webProps
1372
1414
  } = props;
1373
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, ...webProps, style: scrollViewStyle }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { className: contentContainerClassName, ref: contentRef, style: contentStyle }, children));
1415
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, ...webProps, style: scrollViewStyle }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { className, ref: contentRef, style: contentStyle }, children, contentInsetEndAdjustmentSpacerStyle ? /* @__PURE__ */ React3__namespace.createElement("div", { "aria-hidden": true, style: contentInsetEndAdjustmentSpacerStyle }) : null));
1374
1416
  });
1375
1417
  function useValueListener$(key, callback) {
1376
1418
  const ctx = useStateContext();
@@ -1398,11 +1440,18 @@ function getScrollAdjustAxis(horizontal) {
1398
1440
  y: 1
1399
1441
  };
1400
1442
  }
1443
+ function resolveScrollAdjustContentNode(el, contentNode) {
1444
+ if ((contentNode == null ? void 0 : contentNode.isConnected) && contentNode.parentElement === el) {
1445
+ return contentNode;
1446
+ }
1447
+ return el.querySelector(`:scope > .${LEGEND_LIST_CONTENT_CONTAINER_CLASS}`);
1448
+ }
1401
1449
  function ScrollAdjust() {
1402
1450
  const ctx = useStateContext();
1403
1451
  const lastScrollOffsetRef = React3__namespace.useRef(0);
1404
1452
  const resetPaddingRafRef = React3__namespace.useRef(void 0);
1405
1453
  const resetPaddingBaselineRef = React3__namespace.useRef(void 0);
1454
+ const contentNodeRef = React3__namespace.useRef(null);
1406
1455
  const callback = React3__namespace.useCallback(() => {
1407
1456
  var _a3, _b;
1408
1457
  const scrollAdjust = peek$(ctx, "scrollAdjust");
@@ -1413,9 +1462,10 @@ function ScrollAdjust() {
1413
1462
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1414
1463
  if (scrollDelta !== 0) {
1415
1464
  const axis = getScrollAdjustAxis(!!ctx.state.props.horizontal);
1416
- const contentNode = scrollView.getContentNode();
1417
1465
  const prevScroll = scrollView.getCurrentScrollOffset();
1418
1466
  const el = scrollView.getScrollableNode();
1467
+ const contentNode = resolveScrollAdjustContentNode(el, contentNodeRef.current);
1468
+ contentNodeRef.current = contentNode;
1419
1469
  const scrollBy = () => scrollView.scrollBy(axis.x * scrollDelta, axis.y * scrollDelta);
1420
1470
  if (!contentNode) {
1421
1471
  scrollBy();
@@ -3270,6 +3320,15 @@ function checkFinishedScrollFallback(ctx) {
3270
3320
  }
3271
3321
 
3272
3322
  // src/core/initialScrollLifecycle.ts
3323
+ function retargetActiveInitialScrollAtEnd(ctx) {
3324
+ var _a3;
3325
+ const state = ctx.state;
3326
+ const initialScroll = state.initialScroll;
3327
+ if (!initialScroll || state.didFinishInitialScroll || ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" || initialScroll.viewPosition !== 1 || state.props.data.length === 0) {
3328
+ return false;
3329
+ }
3330
+ return advanceCurrentInitialScrollSession(ctx, { forceScroll: true });
3331
+ }
3273
3332
  function handleInitialScrollLayoutReady(ctx) {
3274
3333
  var _a3;
3275
3334
  if (!ctx.state.initialScroll) {
@@ -5326,17 +5385,32 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5326
5385
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5327
5386
  }
5328
5387
  }
5329
- if (previousSize === nextSize) {
5330
- return nextSize;
5331
- }
5332
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5333
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5334
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5335
- updateScroll(ctx, state.scroll, true);
5388
+ if (previousSize !== nextSize) {
5389
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5390
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5391
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5392
+ updateScroll(ctx, state.scroll, true);
5393
+ }
5336
5394
  }
5337
5395
  return nextSize;
5338
5396
  }
5339
5397
 
5398
+ // src/core/updateContentInsetEndAdjustment.ts
5399
+ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment) {
5400
+ const state = ctx.state;
5401
+ const previousContentInsetEnd = getContentInsetEnd(ctx, previousContentInsetEndAdjustment);
5402
+ const nextContentInsetEnd = getContentInsetEnd(ctx);
5403
+ const insetDiff = nextContentInsetEnd - previousContentInsetEnd;
5404
+ if (insetDiff !== 0) {
5405
+ const wasWithinEndThreshold = !!peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
5406
+ updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5407
+ const didRetargetInitialScroll = retargetActiveInitialScrollAtEnd(ctx);
5408
+ if (!didRetargetInitialScroll && wasWithinEndThreshold && (insetDiff > 0)) {
5409
+ requestAdjust(ctx, insetDiff);
5410
+ }
5411
+ }
5412
+ }
5413
+
5340
5414
  // src/core/updateItemSize.ts
5341
5415
  function runOrScheduleMVCPRecalculate(ctx) {
5342
5416
  const state = ctx.state;
@@ -5561,14 +5635,14 @@ function createImperativeHandle(ctx) {
5561
5635
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5562
5636
  let imperativeScrollToken = 0;
5563
5637
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5564
- const runWhenSettled = (token, run) => {
5638
+ const runWhenReady = (token, run, isReady) => {
5565
5639
  const startedAt = Date.now();
5566
5640
  let stableFrames = 0;
5567
5641
  const check = () => {
5568
5642
  if (token !== imperativeScrollToken) {
5569
5643
  return;
5570
5644
  }
5571
- if (isSettlingAfterDataChange()) {
5645
+ if (isSettlingAfterDataChange() || !isReady()) {
5572
5646
  stableFrames = 0;
5573
5647
  } else {
5574
5648
  stableFrames += 1;
@@ -5583,10 +5657,10 @@ function createImperativeHandle(ctx) {
5583
5657
  requestAnimationFrame(check);
5584
5658
  };
5585
5659
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5586
- var _a3;
5660
+ var _a3, _b;
5587
5661
  const token = ++imperativeScrollToken;
5588
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5589
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5662
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5663
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5590
5664
  state.pendingScrollResolve = resolve;
5591
5665
  const runNow = () => {
5592
5666
  if (token !== imperativeScrollToken) {
@@ -5600,11 +5674,10 @@ function createImperativeHandle(ctx) {
5600
5674
  resolve();
5601
5675
  }
5602
5676
  };
5603
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5604
- if (isSettlingAfterDataChange()) {
5605
- runWhenSettled(token, execute);
5677
+ if (isSettlingAfterDataChange() || !isReady()) {
5678
+ runWhenReady(token, runNow, isReady);
5606
5679
  } else {
5607
- execute();
5680
+ runNow();
5608
5681
  }
5609
5682
  });
5610
5683
  const scrollIndexIntoView = (options) => {
@@ -5685,8 +5758,14 @@ function createImperativeHandle(ctx) {
5685
5758
  startBuffered: state.startBuffered
5686
5759
  }),
5687
5760
  reportContentInset: (inset) => {
5761
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5762
+ const previousInset = state.contentInsetOverride;
5688
5763
  state.contentInsetOverride = inset != null ? inset : void 0;
5764
+ const didChange = ((_a3 = previousInset == null ? void 0 : previousInset.top) != null ? _a3 : 0) !== ((_c = (_b = state.contentInsetOverride) == null ? void 0 : _b.top) != null ? _c : 0) || ((_d = previousInset == null ? void 0 : previousInset.bottom) != null ? _d : 0) !== ((_f = (_e = state.contentInsetOverride) == null ? void 0 : _e.bottom) != null ? _f : 0) || ((_g = previousInset == null ? void 0 : previousInset.left) != null ? _g : 0) !== ((_i = (_h = state.contentInsetOverride) == null ? void 0 : _h.left) != null ? _i : 0) || ((_j = previousInset == null ? void 0 : previousInset.right) != null ? _j : 0) !== ((_l = (_k = state.contentInsetOverride) == null ? void 0 : _k.right) != null ? _l : 0);
5689
5765
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5766
+ if (didChange) {
5767
+ retargetActiveInitialScrollAtEnd(ctx);
5768
+ }
5690
5769
  },
5691
5770
  scrollIndexIntoView: (options) => runScrollWithPromise(() => scrollIndexIntoView(options)),
5692
5771
  scrollItemIntoView: ({ item, ...props }) => runScrollWithPromise(() => {
@@ -5715,15 +5794,24 @@ function createImperativeHandle(ctx) {
5715
5794
  }
5716
5795
  return false;
5717
5796
  }),
5718
- scrollToIndex: (params) => runScrollWithPromise(
5719
- () => {
5797
+ scrollToIndex: (params) => {
5798
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5799
+ const options = shouldWaitForOutOfRangeTarget ? {
5800
+ isReady: () => {
5801
+ var _a3;
5802
+ const props = state.props;
5803
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5804
+ const lastIndex = props.data.length - 1;
5805
+ const isInRange = params.index < props.data.length;
5806
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5807
+ return isInRange && !shouldWaitForAnchorSize;
5808
+ }
5809
+ } : void 0;
5810
+ return runScrollWithPromise(() => {
5720
5811
  scrollToIndex(ctx, params);
5721
5812
  return true;
5722
- },
5723
- {
5724
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5725
- }
5726
- ),
5813
+ }, options);
5814
+ },
5727
5815
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5728
5816
  const data = state.props.data;
5729
5817
  const index = data.indexOf(item);
@@ -5978,6 +6066,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5978
6066
  data: dataProp = [],
5979
6067
  dataVersion,
5980
6068
  drawDistance = 250,
6069
+ contentInsetEndAdjustment,
5981
6070
  estimatedItemSize = 100,
5982
6071
  estimatedListSize,
5983
6072
  extraData,
@@ -6087,6 +6176,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6087
6176
  const combinedRef = useCombinedRef(refScroller, refScrollView);
6088
6177
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
6089
6178
  const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
6179
+ const contentInsetEndAdjustmentResolved = contentInsetEndAdjustment ;
6180
+ const previousContentInsetEndAdjustmentRef = React3.useRef(contentInsetEndAdjustmentResolved);
6090
6181
  const alwaysRenderIndices = React3.useMemo(() => {
6091
6182
  const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor, anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
6092
6183
  return { arr: indices, set: new Set(indices) };
@@ -6206,6 +6297,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6206
6297
  anchoredEndSpace: anchoredEndSpaceResolved,
6207
6298
  animatedProps: animatedPropsInternal,
6208
6299
  contentInset,
6300
+ contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
6209
6301
  data: dataProp,
6210
6302
  dataVersion,
6211
6303
  drawDistance,
@@ -6323,6 +6415,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6323
6415
  didAnchoredEndSpaceAnchorIndexChange,
6324
6416
  numColumnsProp
6325
6417
  ]);
6418
+ React3.useLayoutEffect(() => {
6419
+ const previousContentInsetEndAdjustment = previousContentInsetEndAdjustmentRef.current;
6420
+ previousContentInsetEndAdjustmentRef.current = contentInsetEndAdjustmentResolved;
6421
+ updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment);
6422
+ }, [ctx, contentInsetEndAdjustmentResolved]);
6326
6423
  const onLayoutFooter = React3.useCallback(
6327
6424
  (layout) => {
6328
6425
  if (!usesBootstrapInitialScroll) {