@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/index.native.js CHANGED
@@ -160,7 +160,10 @@ function useSelector$(signalName, selector) {
160
160
  }
161
161
 
162
162
  // src/state/getContentInsetEnd.ts
163
- function getContentInsetEnd(ctx) {
163
+ function getContentInsetEndAdjustmentEnd(adjustment) {
164
+ return Math.max(0, adjustment != null ? adjustment : 0);
165
+ }
166
+ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
164
167
  var _a3, _b;
165
168
  const state = ctx.state;
166
169
  const { props } = state;
@@ -168,14 +171,21 @@ function getContentInsetEnd(ctx) {
168
171
  const contentInset = props.contentInset;
169
172
  const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
170
173
  const baseEndInset = (horizontal ? baseInset == null ? void 0 : baseInset.right : baseInset == null ? void 0 : baseInset.bottom) || 0;
174
+ const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
175
+ contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
176
+ );
171
177
  const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
172
178
  const anchoredEndInset = ((_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
173
179
  const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
180
+ const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
174
181
  if (overrideInset) {
175
182
  const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
176
- return Math.max((horizontal ? mergedInset.right : mergedInset.bottom) || 0, anchoredEndInset);
183
+ return Math.max(
184
+ ((horizontal ? mergedInset.right : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
185
+ anchoredEndInset
186
+ );
177
187
  }
178
- return Math.max(baseEndInset, anchoredEndInset);
188
+ return Math.max(adjustedBaseEndInset, anchoredEndInset);
179
189
  }
180
190
 
181
191
  // src/state/getContentSize.ts
@@ -667,6 +677,49 @@ function isInMVCPActiveMode(state) {
667
677
  }
668
678
 
669
679
  // src/components/Container.tsx
680
+ function getContainerPositionStyle({
681
+ columnWrapperStyle,
682
+ horizontal,
683
+ hasItemSeparator,
684
+ numColumns,
685
+ otherAxisPos,
686
+ otherAxisSize
687
+ }) {
688
+ let paddingStyles;
689
+ if (columnWrapperStyle) {
690
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
691
+ if (horizontal) {
692
+ paddingStyles = {
693
+ paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
694
+ paddingRight: columnGap || gap || void 0,
695
+ paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
696
+ };
697
+ } else {
698
+ paddingStyles = {
699
+ paddingBottom: rowGap || gap || void 0,
700
+ paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
701
+ paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
702
+ };
703
+ }
704
+ }
705
+ return horizontal ? {
706
+ boxSizing: paddingStyles ? "border-box" : void 0,
707
+ flexDirection: hasItemSeparator ? "row" : void 0,
708
+ height: otherAxisSize,
709
+ left: 0,
710
+ position: "absolute",
711
+ top: otherAxisPos,
712
+ ...paddingStyles || {}
713
+ } : {
714
+ boxSizing: paddingStyles ? "border-box" : void 0,
715
+ left: otherAxisPos,
716
+ position: "absolute",
717
+ right: numColumns > 1 ? null : 0,
718
+ top: 0,
719
+ width: otherAxisSize,
720
+ ...paddingStyles || {}
721
+ };
722
+ }
670
723
  var Container = typedMemo(function Container2({
671
724
  id,
672
725
  recycleItems,
@@ -705,42 +758,17 @@ var Container = typedMemo(function Container2({
705
758
  const resolvedSpan = Math.min(Math.max(span || 1, 1), numColumns);
706
759
  const otherAxisPos = numColumns > 1 ? `${(resolvedColumn - 1) / numColumns * 100}%` : 0;
707
760
  const otherAxisSize = numColumns > 1 ? `${resolvedSpan / numColumns * 100}%` : void 0;
708
- const style = React2.useMemo(() => {
709
- let paddingStyles;
710
- if (columnWrapperStyle) {
711
- const { columnGap, rowGap, gap } = columnWrapperStyle;
712
- if (horizontal) {
713
- paddingStyles = {
714
- paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
715
- paddingRight: columnGap || gap || void 0,
716
- paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
717
- };
718
- } else {
719
- paddingStyles = {
720
- paddingBottom: rowGap || gap || void 0,
721
- paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
722
- paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
723
- };
724
- }
725
- }
726
- return horizontal ? {
727
- boxSizing: paddingStyles ? "border-box" : void 0,
728
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
729
- height: otherAxisSize,
730
- left: 0,
731
- position: "absolute",
732
- top: otherAxisPos,
733
- ...paddingStyles || {}
734
- } : {
735
- boxSizing: paddingStyles ? "border-box" : void 0,
736
- left: otherAxisPos,
737
- position: "absolute",
738
- right: numColumns > 1 ? null : 0,
739
- top: 0,
740
- width: otherAxisSize,
741
- ...paddingStyles || {}
742
- };
743
- }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
761
+ const style = React2.useMemo(
762
+ () => getContainerPositionStyle({
763
+ columnWrapperStyle,
764
+ hasItemSeparator: !!ItemSeparatorComponent,
765
+ horizontal,
766
+ numColumns,
767
+ otherAxisPos,
768
+ otherAxisSize
769
+ }),
770
+ [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns, ItemSeparatorComponent]
771
+ );
744
772
  const renderedItemInfo = React2.useMemo(
745
773
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
746
774
  [itemKey, data, extraData]
@@ -2698,6 +2726,15 @@ function abortBootstrapInitialScroll(ctx) {
2698
2726
  }
2699
2727
 
2700
2728
  // src/core/initialScrollLifecycle.ts
2729
+ function retargetActiveInitialScrollAtEnd(ctx) {
2730
+ var _a3;
2731
+ const state = ctx.state;
2732
+ const initialScroll = state.initialScroll;
2733
+ if (!initialScroll || state.didFinishInitialScroll || ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" || initialScroll.viewPosition !== 1 || state.props.data.length === 0) {
2734
+ return false;
2735
+ }
2736
+ return advanceCurrentInitialScrollSession(ctx, { forceScroll: true });
2737
+ }
2701
2738
  function handleInitialScrollLayoutReady(ctx) {
2702
2739
  var _a3;
2703
2740
  if (!ctx.state.initialScroll) {
@@ -4796,17 +4833,32 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4796
4833
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4797
4834
  }
4798
4835
  }
4799
- if (previousSize === nextSize) {
4800
- return nextSize;
4801
- }
4802
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4803
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4804
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4805
- updateScroll(ctx, state.scroll, true);
4836
+ if (previousSize !== nextSize) {
4837
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4838
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4839
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4840
+ updateScroll(ctx, state.scroll, true);
4841
+ }
4806
4842
  }
4807
4843
  return nextSize;
4808
4844
  }
4809
4845
 
4846
+ // src/core/updateContentInsetEndAdjustment.ts
4847
+ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment) {
4848
+ const state = ctx.state;
4849
+ const previousContentInsetEnd = getContentInsetEnd(ctx, previousContentInsetEndAdjustment);
4850
+ const nextContentInsetEnd = getContentInsetEnd(ctx);
4851
+ const insetDiff = nextContentInsetEnd - previousContentInsetEnd;
4852
+ if (insetDiff !== 0) {
4853
+ const wasWithinEndThreshold = !!peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
4854
+ updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
4855
+ const didRetargetInitialScroll = retargetActiveInitialScrollAtEnd(ctx);
4856
+ if (!didRetargetInitialScroll && wasWithinEndThreshold && (Platform.OS !== "web" || insetDiff > 0)) {
4857
+ requestAdjust(ctx, insetDiff);
4858
+ }
4859
+ }
4860
+ }
4861
+
4810
4862
  // src/core/updateItemSize.ts
4811
4863
  function runOrScheduleMVCPRecalculate(ctx) {
4812
4864
  const state = ctx.state;
@@ -5046,14 +5098,14 @@ function createImperativeHandle(ctx) {
5046
5098
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5047
5099
  let imperativeScrollToken = 0;
5048
5100
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5049
- const runWhenSettled = (token, run) => {
5101
+ const runWhenReady = (token, run, isReady) => {
5050
5102
  const startedAt = Date.now();
5051
5103
  let stableFrames = 0;
5052
5104
  const check = () => {
5053
5105
  if (token !== imperativeScrollToken) {
5054
5106
  return;
5055
5107
  }
5056
- if (isSettlingAfterDataChange()) {
5108
+ if (isSettlingAfterDataChange() || !isReady()) {
5057
5109
  stableFrames = 0;
5058
5110
  } else {
5059
5111
  stableFrames += 1;
@@ -5068,10 +5120,10 @@ function createImperativeHandle(ctx) {
5068
5120
  requestAnimationFrame(check);
5069
5121
  };
5070
5122
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5071
- var _a3;
5123
+ var _a3, _b;
5072
5124
  const token = ++imperativeScrollToken;
5073
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5074
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5125
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5126
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5075
5127
  state.pendingScrollResolve = resolve;
5076
5128
  const runNow = () => {
5077
5129
  if (token !== imperativeScrollToken) {
@@ -5085,11 +5137,10 @@ function createImperativeHandle(ctx) {
5085
5137
  resolve();
5086
5138
  }
5087
5139
  };
5088
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5089
- if (isSettlingAfterDataChange()) {
5090
- runWhenSettled(token, execute);
5140
+ if (isSettlingAfterDataChange() || !isReady()) {
5141
+ runWhenReady(token, runNow, isReady);
5091
5142
  } else {
5092
- execute();
5143
+ runNow();
5093
5144
  }
5094
5145
  });
5095
5146
  const scrollIndexIntoView = (options) => {
@@ -5170,8 +5221,14 @@ function createImperativeHandle(ctx) {
5170
5221
  startBuffered: state.startBuffered
5171
5222
  }),
5172
5223
  reportContentInset: (inset) => {
5224
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5225
+ const previousInset = state.contentInsetOverride;
5173
5226
  state.contentInsetOverride = inset != null ? inset : void 0;
5227
+ 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);
5174
5228
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5229
+ if (didChange) {
5230
+ retargetActiveInitialScrollAtEnd(ctx);
5231
+ }
5175
5232
  },
5176
5233
  scrollIndexIntoView: (options) => runScrollWithPromise(() => scrollIndexIntoView(options)),
5177
5234
  scrollItemIntoView: ({ item, ...props }) => runScrollWithPromise(() => {
@@ -5200,15 +5257,24 @@ function createImperativeHandle(ctx) {
5200
5257
  }
5201
5258
  return false;
5202
5259
  }),
5203
- scrollToIndex: (params) => runScrollWithPromise(
5204
- () => {
5260
+ scrollToIndex: (params) => {
5261
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5262
+ const options = shouldWaitForOutOfRangeTarget ? {
5263
+ isReady: () => {
5264
+ var _a3;
5265
+ const props = state.props;
5266
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5267
+ const lastIndex = props.data.length - 1;
5268
+ const isInRange = params.index < props.data.length;
5269
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5270
+ return isInRange && !shouldWaitForAnchorSize;
5271
+ }
5272
+ } : void 0;
5273
+ return runScrollWithPromise(() => {
5205
5274
  scrollToIndex(ctx, params);
5206
5275
  return true;
5207
- },
5208
- {
5209
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5210
- }
5211
- ),
5276
+ }, options);
5277
+ },
5212
5278
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5213
5279
  const data = state.props.data;
5214
5280
  const index = data.indexOf(item);
@@ -5463,6 +5529,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5463
5529
  data: dataProp = [],
5464
5530
  dataVersion,
5465
5531
  drawDistance = 250,
5532
+ contentInsetEndAdjustment,
5466
5533
  estimatedItemSize = 100,
5467
5534
  estimatedListSize,
5468
5535
  extraData,
@@ -5572,6 +5639,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5572
5639
  const combinedRef = useCombinedRef(refScroller, refScrollView);
5573
5640
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
5574
5641
  const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
5642
+ const contentInsetEndAdjustmentResolved = Platform.OS === "web" ? contentInsetEndAdjustment : void 0;
5643
+ const previousContentInsetEndAdjustmentRef = React2.useRef(contentInsetEndAdjustmentResolved);
5575
5644
  const alwaysRenderIndices = React2.useMemo(() => {
5576
5645
  const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor, anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
5577
5646
  return { arr: indices, set: new Set(indices) };
@@ -5691,6 +5760,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5691
5760
  anchoredEndSpace: anchoredEndSpaceResolved,
5692
5761
  animatedProps: animatedPropsInternal,
5693
5762
  contentInset,
5763
+ contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
5694
5764
  data: dataProp,
5695
5765
  dataVersion,
5696
5766
  drawDistance,
@@ -5813,6 +5883,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5813
5883
  didAnchoredEndSpaceAnchorIndexChange,
5814
5884
  numColumnsProp
5815
5885
  ]);
5886
+ React2.useLayoutEffect(() => {
5887
+ const previousContentInsetEndAdjustment = previousContentInsetEndAdjustmentRef.current;
5888
+ previousContentInsetEndAdjustmentRef.current = contentInsetEndAdjustmentResolved;
5889
+ updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment);
5890
+ }, [ctx, contentInsetEndAdjustmentResolved]);
5816
5891
  const onLayoutFooter = React2.useCallback(
5817
5892
  (layout) => {
5818
5893
  if (!usesBootstrapInitialScroll) {
package/index.native.mjs CHANGED
@@ -139,7 +139,10 @@ function useSelector$(signalName, selector) {
139
139
  }
140
140
 
141
141
  // src/state/getContentInsetEnd.ts
142
- function getContentInsetEnd(ctx) {
142
+ function getContentInsetEndAdjustmentEnd(adjustment) {
143
+ return Math.max(0, adjustment != null ? adjustment : 0);
144
+ }
145
+ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
143
146
  var _a3, _b;
144
147
  const state = ctx.state;
145
148
  const { props } = state;
@@ -147,14 +150,21 @@ function getContentInsetEnd(ctx) {
147
150
  const contentInset = props.contentInset;
148
151
  const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
149
152
  const baseEndInset = (horizontal ? baseInset == null ? void 0 : baseInset.right : baseInset == null ? void 0 : baseInset.bottom) || 0;
153
+ const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
154
+ contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
155
+ );
150
156
  const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
151
157
  const anchoredEndInset = ((_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
152
158
  const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
159
+ const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
153
160
  if (overrideInset) {
154
161
  const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
155
- return Math.max((horizontal ? mergedInset.right : mergedInset.bottom) || 0, anchoredEndInset);
162
+ return Math.max(
163
+ ((horizontal ? mergedInset.right : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
164
+ anchoredEndInset
165
+ );
156
166
  }
157
- return Math.max(baseEndInset, anchoredEndInset);
167
+ return Math.max(adjustedBaseEndInset, anchoredEndInset);
158
168
  }
159
169
 
160
170
  // src/state/getContentSize.ts
@@ -646,6 +656,49 @@ function isInMVCPActiveMode(state) {
646
656
  }
647
657
 
648
658
  // src/components/Container.tsx
659
+ function getContainerPositionStyle({
660
+ columnWrapperStyle,
661
+ horizontal,
662
+ hasItemSeparator,
663
+ numColumns,
664
+ otherAxisPos,
665
+ otherAxisSize
666
+ }) {
667
+ let paddingStyles;
668
+ if (columnWrapperStyle) {
669
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
670
+ if (horizontal) {
671
+ paddingStyles = {
672
+ paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
673
+ paddingRight: columnGap || gap || void 0,
674
+ paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
675
+ };
676
+ } else {
677
+ paddingStyles = {
678
+ paddingBottom: rowGap || gap || void 0,
679
+ paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
680
+ paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
681
+ };
682
+ }
683
+ }
684
+ return horizontal ? {
685
+ boxSizing: paddingStyles ? "border-box" : void 0,
686
+ flexDirection: hasItemSeparator ? "row" : void 0,
687
+ height: otherAxisSize,
688
+ left: 0,
689
+ position: "absolute",
690
+ top: otherAxisPos,
691
+ ...paddingStyles || {}
692
+ } : {
693
+ boxSizing: paddingStyles ? "border-box" : void 0,
694
+ left: otherAxisPos,
695
+ position: "absolute",
696
+ right: numColumns > 1 ? null : 0,
697
+ top: 0,
698
+ width: otherAxisSize,
699
+ ...paddingStyles || {}
700
+ };
701
+ }
649
702
  var Container = typedMemo(function Container2({
650
703
  id,
651
704
  recycleItems,
@@ -684,42 +737,17 @@ var Container = typedMemo(function Container2({
684
737
  const resolvedSpan = Math.min(Math.max(span || 1, 1), numColumns);
685
738
  const otherAxisPos = numColumns > 1 ? `${(resolvedColumn - 1) / numColumns * 100}%` : 0;
686
739
  const otherAxisSize = numColumns > 1 ? `${resolvedSpan / numColumns * 100}%` : void 0;
687
- const style = useMemo(() => {
688
- let paddingStyles;
689
- if (columnWrapperStyle) {
690
- const { columnGap, rowGap, gap } = columnWrapperStyle;
691
- if (horizontal) {
692
- paddingStyles = {
693
- paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
694
- paddingRight: columnGap || gap || void 0,
695
- paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
696
- };
697
- } else {
698
- paddingStyles = {
699
- paddingBottom: rowGap || gap || void 0,
700
- paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
701
- paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
702
- };
703
- }
704
- }
705
- return horizontal ? {
706
- boxSizing: paddingStyles ? "border-box" : void 0,
707
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
708
- height: otherAxisSize,
709
- left: 0,
710
- position: "absolute",
711
- top: otherAxisPos,
712
- ...paddingStyles || {}
713
- } : {
714
- boxSizing: paddingStyles ? "border-box" : void 0,
715
- left: otherAxisPos,
716
- position: "absolute",
717
- right: numColumns > 1 ? null : 0,
718
- top: 0,
719
- width: otherAxisSize,
720
- ...paddingStyles || {}
721
- };
722
- }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
740
+ const style = useMemo(
741
+ () => getContainerPositionStyle({
742
+ columnWrapperStyle,
743
+ hasItemSeparator: !!ItemSeparatorComponent,
744
+ horizontal,
745
+ numColumns,
746
+ otherAxisPos,
747
+ otherAxisSize
748
+ }),
749
+ [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns, ItemSeparatorComponent]
750
+ );
723
751
  const renderedItemInfo = useMemo(
724
752
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
725
753
  [itemKey, data, extraData]
@@ -2677,6 +2705,15 @@ function abortBootstrapInitialScroll(ctx) {
2677
2705
  }
2678
2706
 
2679
2707
  // src/core/initialScrollLifecycle.ts
2708
+ function retargetActiveInitialScrollAtEnd(ctx) {
2709
+ var _a3;
2710
+ const state = ctx.state;
2711
+ const initialScroll = state.initialScroll;
2712
+ if (!initialScroll || state.didFinishInitialScroll || ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" || initialScroll.viewPosition !== 1 || state.props.data.length === 0) {
2713
+ return false;
2714
+ }
2715
+ return advanceCurrentInitialScrollSession(ctx, { forceScroll: true });
2716
+ }
2680
2717
  function handleInitialScrollLayoutReady(ctx) {
2681
2718
  var _a3;
2682
2719
  if (!ctx.state.initialScroll) {
@@ -4775,17 +4812,32 @@ function maybeUpdateAnchoredEndSpace(ctx) {
4775
4812
  nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4776
4813
  }
4777
4814
  }
4778
- if (previousSize === nextSize) {
4779
- return nextSize;
4780
- }
4781
- set$(ctx, "anchoredEndSpaceSize", nextSize);
4782
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4783
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4784
- updateScroll(ctx, state.scroll, true);
4815
+ if (previousSize !== nextSize) {
4816
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4817
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4818
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4819
+ updateScroll(ctx, state.scroll, true);
4820
+ }
4785
4821
  }
4786
4822
  return nextSize;
4787
4823
  }
4788
4824
 
4825
+ // src/core/updateContentInsetEndAdjustment.ts
4826
+ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment) {
4827
+ const state = ctx.state;
4828
+ const previousContentInsetEnd = getContentInsetEnd(ctx, previousContentInsetEndAdjustment);
4829
+ const nextContentInsetEnd = getContentInsetEnd(ctx);
4830
+ const insetDiff = nextContentInsetEnd - previousContentInsetEnd;
4831
+ if (insetDiff !== 0) {
4832
+ const wasWithinEndThreshold = !!peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
4833
+ updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
4834
+ const didRetargetInitialScroll = retargetActiveInitialScrollAtEnd(ctx);
4835
+ if (!didRetargetInitialScroll && wasWithinEndThreshold && (Platform.OS !== "web" || insetDiff > 0)) {
4836
+ requestAdjust(ctx, insetDiff);
4837
+ }
4838
+ }
4839
+ }
4840
+
4789
4841
  // src/core/updateItemSize.ts
4790
4842
  function runOrScheduleMVCPRecalculate(ctx) {
4791
4843
  const state = ctx.state;
@@ -5025,14 +5077,14 @@ function createImperativeHandle(ctx) {
5025
5077
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
5026
5078
  let imperativeScrollToken = 0;
5027
5079
  const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
5028
- const runWhenSettled = (token, run) => {
5080
+ const runWhenReady = (token, run, isReady) => {
5029
5081
  const startedAt = Date.now();
5030
5082
  let stableFrames = 0;
5031
5083
  const check = () => {
5032
5084
  if (token !== imperativeScrollToken) {
5033
5085
  return;
5034
5086
  }
5035
- if (isSettlingAfterDataChange()) {
5087
+ if (isSettlingAfterDataChange() || !isReady()) {
5036
5088
  stableFrames = 0;
5037
5089
  } else {
5038
5090
  stableFrames += 1;
@@ -5047,10 +5099,10 @@ function createImperativeHandle(ctx) {
5047
5099
  requestAnimationFrame(check);
5048
5100
  };
5049
5101
  const runScrollWithPromise = (run, options) => new Promise((resolve) => {
5050
- var _a3;
5102
+ var _a3, _b;
5051
5103
  const token = ++imperativeScrollToken;
5052
- const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
5053
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
5104
+ const isReady = (_a3 = options == null ? void 0 : options.isReady) != null ? _a3 : (() => true);
5105
+ (_b = state.pendingScrollResolve) == null ? void 0 : _b.call(state);
5054
5106
  state.pendingScrollResolve = resolve;
5055
5107
  const runNow = () => {
5056
5108
  if (token !== imperativeScrollToken) {
@@ -5064,11 +5116,10 @@ function createImperativeHandle(ctx) {
5064
5116
  resolve();
5065
5117
  }
5066
5118
  };
5067
- const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
5068
- if (isSettlingAfterDataChange()) {
5069
- runWhenSettled(token, execute);
5119
+ if (isSettlingAfterDataChange() || !isReady()) {
5120
+ runWhenReady(token, runNow, isReady);
5070
5121
  } else {
5071
- execute();
5122
+ runNow();
5072
5123
  }
5073
5124
  });
5074
5125
  const scrollIndexIntoView = (options) => {
@@ -5149,8 +5200,14 @@ function createImperativeHandle(ctx) {
5149
5200
  startBuffered: state.startBuffered
5150
5201
  }),
5151
5202
  reportContentInset: (inset) => {
5203
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5204
+ const previousInset = state.contentInsetOverride;
5152
5205
  state.contentInsetOverride = inset != null ? inset : void 0;
5206
+ 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);
5153
5207
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5208
+ if (didChange) {
5209
+ retargetActiveInitialScrollAtEnd(ctx);
5210
+ }
5154
5211
  },
5155
5212
  scrollIndexIntoView: (options) => runScrollWithPromise(() => scrollIndexIntoView(options)),
5156
5213
  scrollItemIntoView: ({ item, ...props }) => runScrollWithPromise(() => {
@@ -5179,15 +5236,24 @@ function createImperativeHandle(ctx) {
5179
5236
  }
5180
5237
  return false;
5181
5238
  }),
5182
- scrollToIndex: (params) => runScrollWithPromise(
5183
- () => {
5239
+ scrollToIndex: (params) => {
5240
+ const shouldWaitForOutOfRangeTarget = params.index >= 0 && params.index >= state.props.data.length;
5241
+ const options = shouldWaitForOutOfRangeTarget ? {
5242
+ isReady: () => {
5243
+ var _a3;
5244
+ const props = state.props;
5245
+ const anchorIndex = (_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.anchorIndex;
5246
+ const lastIndex = props.data.length - 1;
5247
+ const isInRange = params.index < props.data.length;
5248
+ const shouldWaitForAnchorSize = isInRange && anchorIndex !== void 0 && anchorIndex >= 0 && params.index >= anchorIndex && !props.getFixedItemSize && !state.sizesKnown.has(getId(state, lastIndex));
5249
+ return isInRange && !shouldWaitForAnchorSize;
5250
+ }
5251
+ } : void 0;
5252
+ return runScrollWithPromise(() => {
5184
5253
  scrollToIndex(ctx, params);
5185
5254
  return true;
5186
- },
5187
- {
5188
- shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5189
- }
5190
- ),
5255
+ }, options);
5256
+ },
5191
5257
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
5192
5258
  const data = state.props.data;
5193
5259
  const index = data.indexOf(item);
@@ -5442,6 +5508,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5442
5508
  data: dataProp = [],
5443
5509
  dataVersion,
5444
5510
  drawDistance = 250,
5511
+ contentInsetEndAdjustment,
5445
5512
  estimatedItemSize = 100,
5446
5513
  estimatedListSize,
5447
5514
  extraData,
@@ -5551,6 +5618,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5551
5618
  const combinedRef = useCombinedRef(refScroller, refScrollView);
5552
5619
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
5553
5620
  const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
5621
+ const contentInsetEndAdjustmentResolved = Platform.OS === "web" ? contentInsetEndAdjustment : void 0;
5622
+ const previousContentInsetEndAdjustmentRef = useRef(contentInsetEndAdjustmentResolved);
5554
5623
  const alwaysRenderIndices = useMemo(() => {
5555
5624
  const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor, anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex);
5556
5625
  return { arr: indices, set: new Set(indices) };
@@ -5670,6 +5739,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5670
5739
  anchoredEndSpace: anchoredEndSpaceResolved,
5671
5740
  animatedProps: animatedPropsInternal,
5672
5741
  contentInset,
5742
+ contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
5673
5743
  data: dataProp,
5674
5744
  dataVersion,
5675
5745
  drawDistance,
@@ -5792,6 +5862,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5792
5862
  didAnchoredEndSpaceAnchorIndexChange,
5793
5863
  numColumnsProp
5794
5864
  ]);
5865
+ useLayoutEffect(() => {
5866
+ const previousContentInsetEndAdjustment = previousContentInsetEndAdjustmentRef.current;
5867
+ previousContentInsetEndAdjustmentRef.current = contentInsetEndAdjustmentResolved;
5868
+ updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment);
5869
+ }, [ctx, contentInsetEndAdjustmentResolved]);
5795
5870
  const onLayoutFooter = useCallback(
5796
5871
  (layout) => {
5797
5872
  if (!usesBootstrapInitialScroll) {