@legendapp/list 3.0.0-beta.21 → 3.0.0-beta.23

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.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
- import { View, ScrollView, Animated, LayoutRectangle, ScrollViewProps, Insets, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
3
+ import { View, ScrollView, Animated, LayoutRectangle, Insets, ScrollViewProps, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
4
4
  import Reanimated from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
@@ -178,6 +178,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
178
178
  initialScrollIndex?: number | {
179
179
  index: number;
180
180
  viewOffset?: number | undefined;
181
+ viewPosition?: number | undefined;
181
182
  };
182
183
  /**
183
184
  * When true, the list initializes scrolled to the last item.
@@ -466,6 +467,8 @@ interface InternalState {
466
467
  loadStartTime: number;
467
468
  maintainingScrollAtEnd?: boolean;
468
469
  minIndexSizeChanged: number | undefined;
470
+ contentInsetOverride?: Partial<Insets> | null;
471
+ nativeContentInset?: Insets;
469
472
  nativeMarginTop: number;
470
473
  needsOtherAxisSize?: boolean;
471
474
  otherAxisSize?: number;
@@ -581,6 +584,7 @@ type LegendListState = {
581
584
  positions: Map<string, number>;
582
585
  scroll: number;
583
586
  scrollLength: number;
587
+ scrollVelocity: number;
584
588
  sizeAtIndex: (index: number) => number;
585
589
  sizes: Map<string, number>;
586
590
  start: number;
@@ -686,6 +690,11 @@ type LegendListRef = {
686
690
  * @param enabled - If true, scroll processing is enabled.
687
691
  */
688
692
  setScrollProcessingEnabled(enabled: boolean): void;
693
+ /**
694
+ * Reports an externally measured content inset. Pass null/undefined to clear.
695
+ * Values are merged on top of props/animated/native insets.
696
+ */
697
+ reportContentInset(inset?: Partial<Insets> | null): void;
689
698
  };
690
699
  interface ViewToken<ItemT = any> {
691
700
  containerId: number;
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
- import { View, ScrollView, Animated, LayoutRectangle, ScrollViewProps, Insets, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
3
+ import { View, ScrollView, Animated, LayoutRectangle, Insets, ScrollViewProps, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
4
4
  import Reanimated from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
@@ -178,6 +178,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
178
178
  initialScrollIndex?: number | {
179
179
  index: number;
180
180
  viewOffset?: number | undefined;
181
+ viewPosition?: number | undefined;
181
182
  };
182
183
  /**
183
184
  * When true, the list initializes scrolled to the last item.
@@ -466,6 +467,8 @@ interface InternalState {
466
467
  loadStartTime: number;
467
468
  maintainingScrollAtEnd?: boolean;
468
469
  minIndexSizeChanged: number | undefined;
470
+ contentInsetOverride?: Partial<Insets> | null;
471
+ nativeContentInset?: Insets;
469
472
  nativeMarginTop: number;
470
473
  needsOtherAxisSize?: boolean;
471
474
  otherAxisSize?: number;
@@ -581,6 +584,7 @@ type LegendListState = {
581
584
  positions: Map<string, number>;
582
585
  scroll: number;
583
586
  scrollLength: number;
587
+ scrollVelocity: number;
584
588
  sizeAtIndex: (index: number) => number;
585
589
  sizes: Map<string, number>;
586
590
  start: number;
@@ -686,6 +690,11 @@ type LegendListRef = {
686
690
  * @param enabled - If true, scroll processing is enabled.
687
691
  */
688
692
  setScrollProcessingEnabled(enabled: boolean): void;
693
+ /**
694
+ * Reports an externally measured content inset. Pass null/undefined to clear.
695
+ * Values are merged on top of props/animated/native insets.
696
+ */
697
+ reportContentInset(inset?: Partial<Insets> | null): void;
689
698
  };
690
699
  interface ViewToken<ItemT = any> {
691
700
  containerId: number;
package/index.js CHANGED
@@ -35,7 +35,7 @@ var Text = View;
35
35
 
36
36
  // src/state/getContentInsetEnd.ts
37
37
  function getContentInsetEnd(state) {
38
- var _a3;
38
+ var _a3, _b;
39
39
  const { props } = state;
40
40
  const horizontal = props.horizontal;
41
41
  let contentInset = props.contentInset;
@@ -49,7 +49,16 @@ function getContentInsetEnd(state) {
49
49
  }
50
50
  }
51
51
  }
52
- return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
52
+ const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
53
+ const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
54
+ if (overrideInset) {
55
+ const mergedInset = { top: 0, left: 0, right: 0, bottom: 0, ...baseInset, ...overrideInset };
56
+ return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
57
+ }
58
+ if (baseInset) {
59
+ return (horizontal ? baseInset.right : baseInset.bottom) || 0;
60
+ }
61
+ return 0;
53
62
  }
54
63
 
55
64
  // src/state/getContentSize.ts
@@ -1753,7 +1762,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1753
1762
  const scrollDelta = Math.abs(newScroll - prevScroll);
1754
1763
  const scrollLength = state.scrollLength;
1755
1764
  const lastCalculated = state.scrollLastCalculate;
1756
- const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1765
+ const shouldUpdate = forceUpdate || state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1757
1766
  if (shouldUpdate) {
1758
1767
  state.scrollLastCalculate = state.scroll;
1759
1768
  state.ignoreScrollFromMVCPIgnored = false;
@@ -3243,7 +3252,7 @@ function handleLayout(ctx, layout, setCanRender) {
3243
3252
 
3244
3253
  // src/core/onScroll.ts
3245
3254
  function onScroll(ctx, event) {
3246
- var _a3, _b, _c;
3255
+ var _a3, _b, _c, _d;
3247
3256
  const state = ctx.state;
3248
3257
  const {
3249
3258
  scrollProcessingEnabled,
@@ -3255,6 +3264,15 @@ function onScroll(ctx, event) {
3255
3264
  if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
3256
3265
  return;
3257
3266
  }
3267
+ let insetChanged = false;
3268
+ if ((_d = event.nativeEvent) == null ? void 0 : _d.contentInset) {
3269
+ const { contentInset } = event.nativeEvent;
3270
+ const prevInset = state.nativeContentInset;
3271
+ if (!prevInset || prevInset.top !== contentInset.top || prevInset.bottom !== contentInset.bottom || prevInset.left !== contentInset.left || prevInset.right !== contentInset.right) {
3272
+ state.nativeContentInset = contentInset;
3273
+ insetChanged = true;
3274
+ }
3275
+ }
3258
3276
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3259
3277
  if (state.scrollingTo) {
3260
3278
  const maxOffset = clampScrollOffset(ctx, newScroll);
@@ -3270,7 +3288,7 @@ function onScroll(ctx, event) {
3270
3288
  }
3271
3289
  }
3272
3290
  state.scrollPending = newScroll;
3273
- updateScroll(ctx, newScroll);
3291
+ updateScroll(ctx, newScroll, insetChanged);
3274
3292
  if (state.scrollingTo) {
3275
3293
  checkFinishedScroll(ctx);
3276
3294
  }
@@ -3443,7 +3461,10 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
3443
3461
  if (!averages) {
3444
3462
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
3445
3463
  }
3446
- if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3464
+ if (averages.num === 0) {
3465
+ averages.avg = size;
3466
+ averages.num++;
3467
+ } else if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3447
3468
  averages.avg += (size - prevSizeKnown) / averages.num;
3448
3469
  } else {
3449
3470
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
@@ -3528,7 +3549,7 @@ function createImperativeHandle(ctx) {
3528
3549
  getScrollResponder: () => refScroller.current.getScrollResponder(),
3529
3550
  getState: () => ({
3530
3551
  activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3531
- contentLength: state.totalSize,
3552
+ contentLength: getContentSize(ctx),
3532
3553
  data: state.props.data,
3533
3554
  elementAtIndex: (index) => {
3534
3555
  var _a3;
@@ -3544,6 +3565,7 @@ function createImperativeHandle(ctx) {
3544
3565
  positions: state.positions,
3545
3566
  scroll: state.scroll,
3546
3567
  scrollLength: state.scrollLength,
3568
+ scrollVelocity: getScrollVelocity(state),
3547
3569
  sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3548
3570
  sizes: state.sizesKnown,
3549
3571
  start: state.startNoBuffer,
@@ -3581,6 +3603,10 @@ function createImperativeHandle(ctx) {
3581
3603
  }
3582
3604
  },
3583
3605
  scrollToOffset: (params) => scrollTo(ctx, params),
3606
+ reportContentInset: (inset) => {
3607
+ state.contentInsetOverride = inset != null ? inset : void 0;
3608
+ updateScroll(ctx, state.scroll, true);
3609
+ },
3584
3610
  setScrollProcessingEnabled: (enabled) => {
3585
3611
  state.scrollProcessingEnabled = enabled;
3586
3612
  },
@@ -3825,7 +3851,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3825
3851
  maintainVisibleContentPositionProp
3826
3852
  );
3827
3853
  const [renderNum, setRenderNum] = React3.useState(0);
3828
- const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3854
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? {
3855
+ index: initialScrollIndexProp.index || 0,
3856
+ viewOffset: initialScrollIndexProp.viewOffset || (initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0),
3857
+ viewPosition: initialScrollIndexProp.viewPosition || 0
3858
+ } : {
3859
+ index: initialScrollIndexProp || 0,
3860
+ viewOffset: initialScrollOffsetProp || 0
3861
+ } : void 0;
3829
3862
  const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
3830
3863
  const ctx = useStateContext();
3831
3864
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
@@ -3863,6 +3896,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3863
3896
  columns: /* @__PURE__ */ new Map(),
3864
3897
  containerItemKeys: /* @__PURE__ */ new Map(),
3865
3898
  containerItemTypes: /* @__PURE__ */ new Map(),
3899
+ contentInsetOverride: void 0,
3866
3900
  dataChangeNeedsScrollUpdate: false,
3867
3901
  didColumnsChange: false,
3868
3902
  didDataChange: false,
@@ -3892,6 +3926,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3892
3926
  lastScrollDelta: 0,
3893
3927
  loadStartTime: Date.now(),
3894
3928
  minIndexSizeChanged: 0,
3929
+ nativeContentInset: void 0,
3895
3930
  nativeMarginTop: 0,
3896
3931
  positions: /* @__PURE__ */ new Map(),
3897
3932
  props: {},
package/index.mjs CHANGED
@@ -14,7 +14,7 @@ var Text = View;
14
14
 
15
15
  // src/state/getContentInsetEnd.ts
16
16
  function getContentInsetEnd(state) {
17
- var _a3;
17
+ var _a3, _b;
18
18
  const { props } = state;
19
19
  const horizontal = props.horizontal;
20
20
  let contentInset = props.contentInset;
@@ -28,7 +28,16 @@ function getContentInsetEnd(state) {
28
28
  }
29
29
  }
30
30
  }
31
- return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
31
+ const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
32
+ const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
33
+ if (overrideInset) {
34
+ const mergedInset = { top: 0, left: 0, right: 0, bottom: 0, ...baseInset, ...overrideInset };
35
+ return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
36
+ }
37
+ if (baseInset) {
38
+ return (horizontal ? baseInset.right : baseInset.bottom) || 0;
39
+ }
40
+ return 0;
32
41
  }
33
42
 
34
43
  // src/state/getContentSize.ts
@@ -1732,7 +1741,7 @@ function updateScroll(ctx, newScroll, forceUpdate) {
1732
1741
  const scrollDelta = Math.abs(newScroll - prevScroll);
1733
1742
  const scrollLength = state.scrollLength;
1734
1743
  const lastCalculated = state.scrollLastCalculate;
1735
- const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1744
+ const shouldUpdate = forceUpdate || state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1736
1745
  if (shouldUpdate) {
1737
1746
  state.scrollLastCalculate = state.scroll;
1738
1747
  state.ignoreScrollFromMVCPIgnored = false;
@@ -3222,7 +3231,7 @@ function handleLayout(ctx, layout, setCanRender) {
3222
3231
 
3223
3232
  // src/core/onScroll.ts
3224
3233
  function onScroll(ctx, event) {
3225
- var _a3, _b, _c;
3234
+ var _a3, _b, _c, _d;
3226
3235
  const state = ctx.state;
3227
3236
  const {
3228
3237
  scrollProcessingEnabled,
@@ -3234,6 +3243,15 @@ function onScroll(ctx, event) {
3234
3243
  if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
3235
3244
  return;
3236
3245
  }
3246
+ let insetChanged = false;
3247
+ if ((_d = event.nativeEvent) == null ? void 0 : _d.contentInset) {
3248
+ const { contentInset } = event.nativeEvent;
3249
+ const prevInset = state.nativeContentInset;
3250
+ if (!prevInset || prevInset.top !== contentInset.top || prevInset.bottom !== contentInset.bottom || prevInset.left !== contentInset.left || prevInset.right !== contentInset.right) {
3251
+ state.nativeContentInset = contentInset;
3252
+ insetChanged = true;
3253
+ }
3254
+ }
3237
3255
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3238
3256
  if (state.scrollingTo) {
3239
3257
  const maxOffset = clampScrollOffset(ctx, newScroll);
@@ -3249,7 +3267,7 @@ function onScroll(ctx, event) {
3249
3267
  }
3250
3268
  }
3251
3269
  state.scrollPending = newScroll;
3252
- updateScroll(ctx, newScroll);
3270
+ updateScroll(ctx, newScroll, insetChanged);
3253
3271
  if (state.scrollingTo) {
3254
3272
  checkFinishedScroll(ctx);
3255
3273
  }
@@ -3422,7 +3440,10 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
3422
3440
  if (!averages) {
3423
3441
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
3424
3442
  }
3425
- if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3443
+ if (averages.num === 0) {
3444
+ averages.avg = size;
3445
+ averages.num++;
3446
+ } else if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3426
3447
  averages.avg += (size - prevSizeKnown) / averages.num;
3427
3448
  } else {
3428
3449
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
@@ -3507,7 +3528,7 @@ function createImperativeHandle(ctx) {
3507
3528
  getScrollResponder: () => refScroller.current.getScrollResponder(),
3508
3529
  getState: () => ({
3509
3530
  activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3510
- contentLength: state.totalSize,
3531
+ contentLength: getContentSize(ctx),
3511
3532
  data: state.props.data,
3512
3533
  elementAtIndex: (index) => {
3513
3534
  var _a3;
@@ -3523,6 +3544,7 @@ function createImperativeHandle(ctx) {
3523
3544
  positions: state.positions,
3524
3545
  scroll: state.scroll,
3525
3546
  scrollLength: state.scrollLength,
3547
+ scrollVelocity: getScrollVelocity(state),
3526
3548
  sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3527
3549
  sizes: state.sizesKnown,
3528
3550
  start: state.startNoBuffer,
@@ -3560,6 +3582,10 @@ function createImperativeHandle(ctx) {
3560
3582
  }
3561
3583
  },
3562
3584
  scrollToOffset: (params) => scrollTo(ctx, params),
3585
+ reportContentInset: (inset) => {
3586
+ state.contentInsetOverride = inset != null ? inset : void 0;
3587
+ updateScroll(ctx, state.scroll, true);
3588
+ },
3563
3589
  setScrollProcessingEnabled: (enabled) => {
3564
3590
  state.scrollProcessingEnabled = enabled;
3565
3591
  },
@@ -3804,7 +3830,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3804
3830
  maintainVisibleContentPositionProp
3805
3831
  );
3806
3832
  const [renderNum, setRenderNum] = useState(0);
3807
- const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3833
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? {
3834
+ index: initialScrollIndexProp.index || 0,
3835
+ viewOffset: initialScrollIndexProp.viewOffset || (initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0),
3836
+ viewPosition: initialScrollIndexProp.viewPosition || 0
3837
+ } : {
3838
+ index: initialScrollIndexProp || 0,
3839
+ viewOffset: initialScrollOffsetProp || 0
3840
+ } : void 0;
3808
3841
  const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
3809
3842
  const ctx = useStateContext();
3810
3843
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
@@ -3842,6 +3875,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3842
3875
  columns: /* @__PURE__ */ new Map(),
3843
3876
  containerItemKeys: /* @__PURE__ */ new Map(),
3844
3877
  containerItemTypes: /* @__PURE__ */ new Map(),
3878
+ contentInsetOverride: void 0,
3845
3879
  dataChangeNeedsScrollUpdate: false,
3846
3880
  didColumnsChange: false,
3847
3881
  didDataChange: false,
@@ -3871,6 +3905,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3871
3905
  lastScrollDelta: 0,
3872
3906
  loadStartTime: Date.now(),
3873
3907
  minIndexSizeChanged: 0,
3908
+ nativeContentInset: void 0,
3874
3909
  nativeMarginTop: 0,
3875
3910
  positions: /* @__PURE__ */ new Map(),
3876
3911
  props: {},
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
- import { View, ScrollView, Animated, LayoutRectangle, ScrollViewProps, Insets, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
3
+ import { View, ScrollView, Animated, LayoutRectangle, Insets, ScrollViewProps, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
4
4
  import Reanimated from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
@@ -178,6 +178,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
178
178
  initialScrollIndex?: number | {
179
179
  index: number;
180
180
  viewOffset?: number | undefined;
181
+ viewPosition?: number | undefined;
181
182
  };
182
183
  /**
183
184
  * When true, the list initializes scrolled to the last item.
@@ -466,6 +467,8 @@ interface InternalState {
466
467
  loadStartTime: number;
467
468
  maintainingScrollAtEnd?: boolean;
468
469
  minIndexSizeChanged: number | undefined;
470
+ contentInsetOverride?: Partial<Insets> | null;
471
+ nativeContentInset?: Insets;
469
472
  nativeMarginTop: number;
470
473
  needsOtherAxisSize?: boolean;
471
474
  otherAxisSize?: number;
@@ -581,6 +584,7 @@ type LegendListState = {
581
584
  positions: Map<string, number>;
582
585
  scroll: number;
583
586
  scrollLength: number;
587
+ scrollVelocity: number;
584
588
  sizeAtIndex: (index: number) => number;
585
589
  sizes: Map<string, number>;
586
590
  start: number;
@@ -686,6 +690,11 @@ type LegendListRef = {
686
690
  * @param enabled - If true, scroll processing is enabled.
687
691
  */
688
692
  setScrollProcessingEnabled(enabled: boolean): void;
693
+ /**
694
+ * Reports an externally measured content inset. Pass null/undefined to clear.
695
+ * Values are merged on top of props/animated/native insets.
696
+ */
697
+ reportContentInset(inset?: Partial<Insets> | null): void;
689
698
  };
690
699
  interface ViewToken<ItemT = any> {
691
700
  containerId: number;
package/index.native.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import { ComponentProps, Key, ReactNode, Dispatch, SetStateAction } from 'react';
3
- import { View, ScrollView, Animated, LayoutRectangle, ScrollViewProps, Insets, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
3
+ import { View, ScrollView, Animated, LayoutRectangle, Insets, ScrollViewProps, ScrollViewComponent, ScrollResponderMixin, StyleProp, ViewStyle, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
4
4
  import Reanimated from 'react-native-reanimated';
5
5
 
6
6
  type AnimatedValue = number;
@@ -178,6 +178,7 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
178
178
  initialScrollIndex?: number | {
179
179
  index: number;
180
180
  viewOffset?: number | undefined;
181
+ viewPosition?: number | undefined;
181
182
  };
182
183
  /**
183
184
  * When true, the list initializes scrolled to the last item.
@@ -466,6 +467,8 @@ interface InternalState {
466
467
  loadStartTime: number;
467
468
  maintainingScrollAtEnd?: boolean;
468
469
  minIndexSizeChanged: number | undefined;
470
+ contentInsetOverride?: Partial<Insets> | null;
471
+ nativeContentInset?: Insets;
469
472
  nativeMarginTop: number;
470
473
  needsOtherAxisSize?: boolean;
471
474
  otherAxisSize?: number;
@@ -581,6 +584,7 @@ type LegendListState = {
581
584
  positions: Map<string, number>;
582
585
  scroll: number;
583
586
  scrollLength: number;
587
+ scrollVelocity: number;
584
588
  sizeAtIndex: (index: number) => number;
585
589
  sizes: Map<string, number>;
586
590
  start: number;
@@ -686,6 +690,11 @@ type LegendListRef = {
686
690
  * @param enabled - If true, scroll processing is enabled.
687
691
  */
688
692
  setScrollProcessingEnabled(enabled: boolean): void;
693
+ /**
694
+ * Reports an externally measured content inset. Pass null/undefined to clear.
695
+ * Values are merged on top of props/animated/native insets.
696
+ */
697
+ reportContentInset(inset?: Partial<Insets> | null): void;
689
698
  };
690
699
  interface ViewToken<ItemT = any> {
691
700
  containerId: number;
package/index.native.js CHANGED
@@ -31,7 +31,7 @@ var Text = reactNative.Text;
31
31
 
32
32
  // src/state/getContentInsetEnd.ts
33
33
  function getContentInsetEnd(state) {
34
- var _a3;
34
+ var _a3, _b;
35
35
  const { props } = state;
36
36
  const horizontal = props.horizontal;
37
37
  let contentInset = props.contentInset;
@@ -45,7 +45,16 @@ function getContentInsetEnd(state) {
45
45
  }
46
46
  }
47
47
  }
48
- return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
48
+ const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
49
+ const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
50
+ if (overrideInset) {
51
+ const mergedInset = { top: 0, left: 0, right: 0, bottom: 0, ...baseInset, ...overrideInset };
52
+ return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
53
+ }
54
+ if (baseInset) {
55
+ return (horizontal ? baseInset.right : baseInset.bottom) || 0;
56
+ }
57
+ return 0;
49
58
  }
50
59
 
51
60
  // src/state/getContentSize.ts
@@ -3027,7 +3036,7 @@ function handleLayout(ctx, layout, setCanRender) {
3027
3036
 
3028
3037
  // src/core/onScroll.ts
3029
3038
  function onScroll(ctx, event) {
3030
- var _a3, _b, _c;
3039
+ var _a3, _b, _c, _d;
3031
3040
  const state = ctx.state;
3032
3041
  const {
3033
3042
  scrollProcessingEnabled,
@@ -3039,6 +3048,15 @@ function onScroll(ctx, event) {
3039
3048
  if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
3040
3049
  return;
3041
3050
  }
3051
+ let insetChanged = false;
3052
+ if ((_d = event.nativeEvent) == null ? void 0 : _d.contentInset) {
3053
+ const { contentInset } = event.nativeEvent;
3054
+ const prevInset = state.nativeContentInset;
3055
+ if (!prevInset || prevInset.top !== contentInset.top || prevInset.bottom !== contentInset.bottom || prevInset.left !== contentInset.left || prevInset.right !== contentInset.right) {
3056
+ state.nativeContentInset = contentInset;
3057
+ insetChanged = true;
3058
+ }
3059
+ }
3042
3060
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3043
3061
  if (state.scrollingTo) {
3044
3062
  const maxOffset = clampScrollOffset(ctx, newScroll);
@@ -3054,7 +3072,7 @@ function onScroll(ctx, event) {
3054
3072
  }
3055
3073
  }
3056
3074
  state.scrollPending = newScroll;
3057
- updateScroll(ctx, newScroll);
3075
+ updateScroll(ctx, newScroll, insetChanged);
3058
3076
  if (state.scrollingTo) {
3059
3077
  checkFinishedScroll(ctx);
3060
3078
  }
@@ -3227,7 +3245,10 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
3227
3245
  if (!averages) {
3228
3246
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
3229
3247
  }
3230
- if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3248
+ if (averages.num === 0) {
3249
+ averages.avg = size;
3250
+ averages.num++;
3251
+ } else if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3231
3252
  averages.avg += (size - prevSizeKnown) / averages.num;
3232
3253
  } else {
3233
3254
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
@@ -3331,7 +3352,7 @@ function createImperativeHandle(ctx) {
3331
3352
  getScrollResponder: () => refScroller.current.getScrollResponder(),
3332
3353
  getState: () => ({
3333
3354
  activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3334
- contentLength: state.totalSize,
3355
+ contentLength: getContentSize(ctx),
3335
3356
  data: state.props.data,
3336
3357
  elementAtIndex: (index) => {
3337
3358
  var _a3;
@@ -3347,6 +3368,7 @@ function createImperativeHandle(ctx) {
3347
3368
  positions: state.positions,
3348
3369
  scroll: state.scroll,
3349
3370
  scrollLength: state.scrollLength,
3371
+ scrollVelocity: getScrollVelocity(state),
3350
3372
  sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3351
3373
  sizes: state.sizesKnown,
3352
3374
  start: state.startNoBuffer,
@@ -3384,6 +3406,10 @@ function createImperativeHandle(ctx) {
3384
3406
  }
3385
3407
  },
3386
3408
  scrollToOffset: (params) => scrollTo(ctx, params),
3409
+ reportContentInset: (inset) => {
3410
+ state.contentInsetOverride = inset != null ? inset : void 0;
3411
+ updateScroll(ctx, state.scroll, true);
3412
+ },
3387
3413
  setScrollProcessingEnabled: (enabled) => {
3388
3414
  state.scrollProcessingEnabled = enabled;
3389
3415
  },
@@ -3628,7 +3654,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3628
3654
  maintainVisibleContentPositionProp
3629
3655
  );
3630
3656
  const [renderNum, setRenderNum] = React2.useState(0);
3631
- const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3657
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? {
3658
+ index: initialScrollIndexProp.index || 0,
3659
+ viewOffset: initialScrollIndexProp.viewOffset || (initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0),
3660
+ viewPosition: initialScrollIndexProp.viewPosition || 0
3661
+ } : {
3662
+ index: initialScrollIndexProp || 0,
3663
+ viewOffset: initialScrollOffsetProp || 0
3664
+ } : void 0;
3632
3665
  const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
3633
3666
  const ctx = useStateContext();
3634
3667
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
@@ -3666,6 +3699,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3666
3699
  columns: /* @__PURE__ */ new Map(),
3667
3700
  containerItemKeys: /* @__PURE__ */ new Map(),
3668
3701
  containerItemTypes: /* @__PURE__ */ new Map(),
3702
+ contentInsetOverride: void 0,
3669
3703
  dataChangeNeedsScrollUpdate: false,
3670
3704
  didColumnsChange: false,
3671
3705
  didDataChange: false,
@@ -3695,6 +3729,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3695
3729
  lastScrollDelta: 0,
3696
3730
  loadStartTime: Date.now(),
3697
3731
  minIndexSizeChanged: 0,
3732
+ nativeContentInset: void 0,
3698
3733
  nativeMarginTop: 0,
3699
3734
  positions: /* @__PURE__ */ new Map(),
3700
3735
  props: {},