@legendapp/list 3.0.0-beta.37 → 3.0.0-beta.39

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
@@ -1,4 +1,5 @@
1
- import { Key, ReactNode, ReactElement } from 'react';
1
+ import * as React from 'react';
2
+ import { Key } from 'react';
2
3
  import { ScrollViewProps, NativeSyntheticEvent as NativeSyntheticEvent$1, NativeScrollEvent as NativeScrollEvent$1, ScrollView, StyleProp as StyleProp$1, ViewStyle as ViewStyle$1, ScrollViewComponent, ScrollResponderMixin, Insets as Insets$1, Animated } from 'react-native';
3
4
 
4
5
  type ListenerType = "activeStickyIndex" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
@@ -84,7 +85,7 @@ interface DataModeProps<ItemT, TItemType extends string | undefined> {
84
85
  * - A React component: React.ComponentType<LegendListRenderItemProps<ItemT>>
85
86
  * @required when using data mode
86
87
  */
87
- renderItem: ((props: LegendListRenderItemProps<ItemT, TItemType>) => ReactNode) | React.ComponentType<LegendListRenderItemProps<ItemT, TItemType>>;
88
+ renderItem: ((props: LegendListRenderItemProps<ItemT, TItemType>) => React.ReactNode) | React.ComponentType<LegendListRenderItemProps<ItemT, TItemType>>;
88
89
  children?: never;
89
90
  }
90
91
  interface ChildrenModeProps {
@@ -93,7 +94,7 @@ interface ChildrenModeProps {
93
94
  * Each child will be treated as an individual list item.
94
95
  * @required when using children mode
95
96
  */
96
- children: ReactNode;
97
+ children: React.ReactNode;
97
98
  data?: never;
98
99
  renderItem?: never;
99
100
  }
@@ -416,6 +417,8 @@ type LegendListState = {
416
417
  endBuffered: number;
417
418
  isAtEnd: boolean;
418
419
  isAtStart: boolean;
420
+ isEndReached: boolean;
421
+ isStartReached: boolean;
419
422
  listen: <T extends LegendListListenerType>(listenerType: T, callback: (value: ListenerTypeValueMap[T]) => void) => () => void;
420
423
  listenToPosition: (key: string, callback: (value: number) => void) => () => void;
421
424
  positionAtIndex: (index: number) => number;
@@ -591,7 +594,7 @@ interface ViewabilityConfig {
591
594
  type LegendListPropsOverrides<ItemT, TItemType extends string | undefined> = Omit<LegendListPropsBase<ItemT, ScrollViewProps, TItemType>, "onScroll" | "refScrollView" | "renderScrollComponent" | "ListHeaderComponentStyle" | "ListFooterComponentStyle"> & {
592
595
  onScroll?: (event: NativeSyntheticEvent$1<NativeScrollEvent$1>) => void;
593
596
  refScrollView?: React.Ref<ScrollView>;
594
- renderScrollComponent?: (props: ScrollViewProps) => ReactElement<ScrollViewProps>;
597
+ renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
595
598
  ListHeaderComponentStyle?: StyleProp$1<ViewStyle$1> | undefined;
596
599
  ListFooterComponentStyle?: StyleProp$1<ViewStyle$1> | undefined;
597
600
  };
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import * as React$1 from 'react';
2
- import { Key, ReactNode, ComponentType, CSSProperties, Ref, ReactElement, JSXElementConstructor, RefAttributes, Dispatch, SetStateAction } from 'react';
1
+ import * as React from 'react';
2
+ import { Key, ComponentType, ReactNode, CSSProperties, Ref, ReactElement, JSXElementConstructor, RefAttributes, Dispatch, SetStateAction } from 'react';
3
3
 
4
4
  type AnimatedValue = number;
5
5
 
@@ -68,7 +68,7 @@ interface StateContext {
68
68
  positionListeners: Map<string, Set<(value: any) => void>>;
69
69
  state: InternalState$1;
70
70
  values: Map<ListenerType, any>;
71
- viewRefs: Map<number, React$1.RefObject<LooseView>>;
71
+ viewRefs: Map<number, React.RefObject<LooseView | null>>;
72
72
  }
73
73
 
74
74
  declare class ScrollAdjustHandler {
@@ -158,7 +158,7 @@ interface DataModeProps<ItemT, TItemType extends string | undefined> {
158
158
  * - A React component: React.ComponentType<LegendListRenderItemProps<ItemT>>
159
159
  * @required when using data mode
160
160
  */
161
- renderItem: ((props: LegendListRenderItemProps$1<ItemT, TItemType>) => ReactNode) | React.ComponentType<LegendListRenderItemProps$1<ItemT, TItemType>>;
161
+ renderItem: ((props: LegendListRenderItemProps$1<ItemT, TItemType>) => React.ReactNode) | React.ComponentType<LegendListRenderItemProps$1<ItemT, TItemType>>;
162
162
  children?: never;
163
163
  }
164
164
  interface ChildrenModeProps {
@@ -167,7 +167,7 @@ interface ChildrenModeProps {
167
167
  * Each child will be treated as an individual list item.
168
168
  * @required when using children mode
169
169
  */
170
- children: ReactNode;
170
+ children: React.ReactNode;
171
171
  data?: never;
172
172
  renderItem?: never;
173
173
  }
@@ -571,10 +571,6 @@ interface InternalState$1 {
571
571
  scrollLastCalculate?: number;
572
572
  scrollLength: number;
573
573
  scrollPending: number;
574
- stableTarget?: {
575
- scroll: number;
576
- target: number;
577
- };
578
574
  scrollPrev: number;
579
575
  scrollPrevTime: number;
580
576
  scrollProcessingEnabled: boolean;
@@ -667,6 +663,8 @@ type LegendListState$1 = {
667
663
  endBuffered: number;
668
664
  isAtEnd: boolean;
669
665
  isAtStart: boolean;
666
+ isEndReached: boolean;
667
+ isStartReached: boolean;
670
668
  listen: <T extends LegendListListenerType>(listenerType: T, callback: (value: ListenerTypeValueMap[T]) => void) => () => void;
671
669
  listenToPosition: (key: string, callback: (value: number) => void) => () => void;
672
670
  positionAtIndex: (index: number) => number;
@@ -853,9 +851,9 @@ interface LegendListRecyclingState$1<T> {
853
851
  prevIndex: number | undefined;
854
852
  prevItem: T | undefined;
855
853
  }
856
- type TypedForwardRef$1 = <T, P = {}>(render: (props: P, ref: React.Ref<T>) => React.ReactNode) => (props: P & React.RefAttributes<T>) => React.ReactNode;
854
+ type TypedForwardRef$1 = <T, P = {}>(render: (props: P, ref: React.Ref<T>) => React.ReactElement | null) => (props: P & React.RefAttributes<T>) => React.ReactElement | null;
857
855
  declare const typedForwardRef: TypedForwardRef$1;
858
- type TypedMemo$1 = <T extends React.ComponentType<any>>(Component: T, propsAreEqual?: (prevProps: Readonly<React.JSXElementConstructor<T>>, nextProps: Readonly<React.JSXElementConstructor<T>>) => boolean) => T & {
856
+ type TypedMemo$1 = <T extends React.ComponentType<any>>(Component: T, propsAreEqual?: (prevProps: Readonly<React.ComponentProps<T>>, nextProps: Readonly<React.ComponentProps<T>>) => boolean) => T & {
859
857
  displayName?: string;
860
858
  };
861
859
  declare const typedMemo: TypedMemo$1;
package/index.js CHANGED
@@ -252,8 +252,8 @@ var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 :
252
252
  var POSITION_OUT_OF_VIEW = -1e7;
253
253
  var ENABLE_DEVMODE = IS_DEV && false;
254
254
  var ENABLE_DEBUG_VIEW = IS_DEV && false;
255
- var typedForwardRef = React3.forwardRef;
256
- var typedMemo = React3.memo;
255
+ var typedForwardRef = React3__namespace.forwardRef;
256
+ var typedMemo = React3__namespace.memo;
257
257
 
258
258
  // src/utils/helpers.ts
259
259
  function isFunction(obj) {
@@ -368,7 +368,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
368
368
  }
369
369
  return styleBase;
370
370
  }, [composed, horizontal, position, index, activeStickyIndex, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
371
- return /* @__PURE__ */ React3__namespace.createElement("div", { "data-index": index, ref: refView, style: viewStyle, ...webProps }, children);
371
+ return /* @__PURE__ */ React3__namespace.createElement(
372
+ "div",
373
+ {
374
+ "data-index": index,
375
+ ref: refView,
376
+ style: viewStyle,
377
+ ...webProps
378
+ },
379
+ children
380
+ );
372
381
  });
373
382
  var PositionView = PositionViewState;
374
383
  function useInit(cb) {
@@ -634,13 +643,22 @@ var Platform = {
634
643
  OS: "web"
635
644
  };
636
645
 
637
- // src/utils/isInMVCPActiveMode.ts
638
- function isInMVCPActiveMode(state) {
646
+ // src/utils/hasActiveMVCPAnchorLock.ts
647
+ function hasActiveMVCPAnchorLock(state) {
639
648
  const lock = state.mvcpAnchorLock;
640
- if (lock && Date.now() > lock.expiresAt) {
649
+ if (!lock) {
650
+ return false;
651
+ }
652
+ if (Date.now() > lock.expiresAt) {
641
653
  state.mvcpAnchorLock = void 0;
654
+ return false;
642
655
  }
643
- return state.dataChangeNeedsScrollUpdate || !!state.mvcpAnchorLock;
656
+ return true;
657
+ }
658
+
659
+ // src/utils/isInMVCPActiveMode.ts
660
+ function isInMVCPActiveMode(state) {
661
+ return state.dataChangeNeedsScrollUpdate || hasActiveMVCPAnchorLock(state);
644
662
  }
645
663
 
646
664
  // src/components/Container.tsx
@@ -1347,7 +1365,7 @@ function SnapWrapper({ ScrollComponent, ...props }) {
1347
1365
  return /* @__PURE__ */ React3__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
1348
1366
  }
1349
1367
  var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1350
- const ref = refView != null ? refView : React3.useRef();
1368
+ const ref = refView != null ? refView : React3.useRef(null);
1351
1369
  useOnLayoutSync({ onLayoutChange, ref });
1352
1370
  return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1353
1371
  };
@@ -1791,7 +1809,6 @@ function finishScrollTo(ctx) {
1791
1809
  state.initialScroll = void 0;
1792
1810
  state.initialAnchor = void 0;
1793
1811
  state.scrollingTo = void 0;
1794
- state.stableTarget = void 0;
1795
1812
  if (state.pendingTotalSize !== void 0) {
1796
1813
  addTotalSize(ctx, null, state.pendingTotalSize);
1797
1814
  }
@@ -1908,9 +1925,8 @@ function scrollTo(ctx, params) {
1908
1925
  let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1909
1926
  offset = clampScrollOffset(ctx, offset, scrollTarget);
1910
1927
  state.scrollHistory.length = 0;
1911
- state.stableTarget = void 0;
1912
1928
  if (!noScrollingTo) {
1913
- state.scrollingTo = { ...scrollTarget, offset };
1929
+ state.scrollingTo = scrollTarget;
1914
1930
  }
1915
1931
  state.scrollPending = offset;
1916
1932
  if (forceScroll || !isInitialScroll || Platform.OS === "android") {
@@ -3351,14 +3367,6 @@ function checkActualChange(state, dataProp, previousData) {
3351
3367
  }
3352
3368
 
3353
3369
  // src/core/checkFinishedScroll.ts
3354
- function getCurrentTargetOffset(ctx, scrollingTo) {
3355
- if (scrollingTo.index !== void 0) {
3356
- const baseOffset = calculateOffsetForIndex(ctx, scrollingTo.index);
3357
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, scrollingTo);
3358
- return clampScrollOffset(ctx, resolvedOffset, scrollingTo);
3359
- }
3360
- return clampScrollOffset(ctx, scrollingTo.offset, scrollingTo);
3361
- }
3362
3370
  function checkFinishedScroll(ctx) {
3363
3371
  ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
3364
3372
  }
@@ -3368,30 +3376,20 @@ function checkFinishedScrollFrame(ctx) {
3368
3376
  const { state } = ctx;
3369
3377
  state.animFrameCheckFinishedScroll = void 0;
3370
3378
  const scroll = state.scrollPending;
3371
- const clampedTargetOffset = getCurrentTargetOffset(ctx, scrollingTo);
3372
- if (Math.abs(scrollingTo.offset - clampedTargetOffset) >= 1) {
3373
- state.scrollingTo = { ...scrollingTo, offset: clampedTargetOffset };
3374
- }
3379
+ const adjust = state.scrollAdjustHandler.getAdjust();
3380
+ const clampedTargetOffset = clampScrollOffset(
3381
+ ctx,
3382
+ scrollingTo.offset - (scrollingTo.viewOffset || 0),
3383
+ scrollingTo
3384
+ );
3375
3385
  const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
3376
3386
  const diff1 = Math.abs(scroll - clampedTargetOffset);
3387
+ const diff2 = Math.abs(diff1 - adjust);
3377
3388
  const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
3378
- const isAtTarget = diff1 < 1;
3379
- const previousStableTarget = state.stableTarget;
3380
- const hasStableTargetFrame = !!previousStableTarget && Math.abs(previousStableTarget.target - clampedTargetOffset) < 1 && Math.abs(previousStableTarget.scroll - scroll) < 1;
3381
- if (isAtTarget && !hasStableTargetFrame) {
3382
- state.stableTarget = { scroll, target: clampedTargetOffset };
3383
- state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
3384
- return;
3385
- }
3386
- if (!isAtTarget) {
3387
- state.stableTarget = void 0;
3388
- }
3389
+ const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
3389
3390
  if (isNotOverscrolled && isAtTarget) {
3390
- state.stableTarget = void 0;
3391
3391
  finishScrollTo(ctx);
3392
3392
  }
3393
- } else {
3394
- ctx.state.stableTarget = void 0;
3395
3393
  }
3396
3394
  }
3397
3395
  function checkFinishedScrollFallback(ctx) {
@@ -3919,17 +3917,53 @@ function createColumnWrapperStyle(contentContainerStyle) {
3919
3917
  // src/utils/createImperativeHandle.ts
3920
3918
  function createImperativeHandle(ctx) {
3921
3919
  const state = ctx.state;
3920
+ const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
3921
+ const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
3922
+ let imperativeScrollToken = 0;
3923
+ const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0 || hasActiveMVCPAnchorLock(state);
3924
+ const runWhenSettled = (token, run) => {
3925
+ const startedAt = Date.now();
3926
+ let stableFrames = 0;
3927
+ const check = () => {
3928
+ if (token !== imperativeScrollToken) {
3929
+ return;
3930
+ }
3931
+ if (isSettlingAfterDataChange()) {
3932
+ stableFrames = 0;
3933
+ } else {
3934
+ stableFrames += 1;
3935
+ }
3936
+ const timedOut = Date.now() - startedAt >= IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS;
3937
+ if (stableFrames >= IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES || timedOut) {
3938
+ run();
3939
+ return;
3940
+ }
3941
+ requestAnimationFrame(check);
3942
+ };
3943
+ requestAnimationFrame(check);
3944
+ };
3922
3945
  const runScrollWithPromise = (run) => new Promise((resolve) => {
3923
3946
  var _a3;
3947
+ const token = ++imperativeScrollToken;
3924
3948
  (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
3925
3949
  state.pendingScrollResolve = resolve;
3926
- const didStartScroll = run();
3927
- if (!didStartScroll || !state.scrollingTo) {
3928
- if (state.pendingScrollResolve === resolve) {
3929
- state.pendingScrollResolve = void 0;
3950
+ const runNow = () => {
3951
+ if (token !== imperativeScrollToken) {
3952
+ return;
3953
+ }
3954
+ const didStartScroll = run();
3955
+ if (!didStartScroll || !state.scrollingTo) {
3956
+ if (state.pendingScrollResolve === resolve) {
3957
+ state.pendingScrollResolve = void 0;
3958
+ }
3959
+ resolve();
3930
3960
  }
3931
- resolve();
3961
+ };
3962
+ if (isSettlingAfterDataChange()) {
3963
+ runWhenSettled(token, runNow);
3964
+ return;
3932
3965
  }
3966
+ runNow();
3933
3967
  });
3934
3968
  const scrollIndexIntoView = (options) => {
3935
3969
  if (state) {
@@ -3988,6 +4022,8 @@ function createImperativeHandle(ctx) {
3988
4022
  endBuffered: state.endBuffered,
3989
4023
  isAtEnd: state.isAtEnd,
3990
4024
  isAtStart: state.isAtStart,
4025
+ isEndReached: state.isEndReached,
4026
+ isStartReached: state.isStartReached,
3991
4027
  listen: (signalName, cb) => listen$(ctx, signalName, cb),
3992
4028
  listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
3993
4029
  positionAtIndex: (index) => state.positions[index],
@@ -4239,7 +4275,7 @@ var LegendList = typedMemo(
4239
4275
  })
4240
4276
  );
4241
4277
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4242
- var _a3, _b, _c, _d;
4278
+ var _a3, _b, _c, _d, _e;
4243
4279
  const {
4244
4280
  alignItemsAtEnd = false,
4245
4281
  alwaysRender,
@@ -4368,7 +4404,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4368
4404
  );
4369
4405
  }
4370
4406
  const useWindowScrollResolved = !!useWindowScroll && !renderScrollComponent;
4371
- const refState = React3.useRef();
4407
+ const refState = React3.useRef(void 0);
4372
4408
  const hasOverrideItemLayout = !!overrideItemLayout;
4373
4409
  const prevHasOverrideItemLayout = React3.useRef(hasOverrideItemLayout);
4374
4410
  if (!refState.current) {
@@ -4700,6 +4736,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4700
4736
  []
4701
4737
  );
4702
4738
  const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
4739
+ const refreshControlElement = refreshControl;
4703
4740
  return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
4704
4741
  ListComponent,
4705
4742
  {
@@ -4718,9 +4755,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4718
4755
  onMomentumScrollEnd: fns.onMomentumScrollEnd,
4719
4756
  onScroll: onScrollHandler,
4720
4757
  recycleItems,
4721
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
4722
- progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4723
- }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
4758
+ refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControlElement, {
4759
+ progressViewOffset: ((_d = refreshControlElement.props.progressViewOffset) != null ? _d : 0) + stylePaddingTopState
4760
+ }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
4724
4761
  RefreshControl,
4725
4762
  {
4726
4763
  onRefresh,
@@ -4730,7 +4767,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4730
4767
  ),
4731
4768
  refScrollView: combinedRef,
4732
4769
  renderScrollComponent,
4733
- scrollAdjustHandler: (_d = refState.current) == null ? void 0 : _d.scrollAdjustHandler,
4770
+ scrollAdjustHandler: (_e = refState.current) == null ? void 0 : _e.scrollAdjustHandler,
4734
4771
  scrollEventThrottle: 0,
4735
4772
  snapToIndices,
4736
4773
  stickyHeaderIndices,
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React3 from 'react';
2
- import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useImperativeHandle, useLayoutEffect, memo, useContext } from 'react';
2
+ import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useImperativeHandle, useLayoutEffect, useContext } from 'react';
3
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
4
4
  import * as ReactDOM from 'react-dom';
5
5
  import { flushSync } from 'react-dom';
@@ -231,8 +231,8 @@ var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 :
231
231
  var POSITION_OUT_OF_VIEW = -1e7;
232
232
  var ENABLE_DEVMODE = IS_DEV && false;
233
233
  var ENABLE_DEBUG_VIEW = IS_DEV && false;
234
- var typedForwardRef = forwardRef;
235
- var typedMemo = memo;
234
+ var typedForwardRef = React3.forwardRef;
235
+ var typedMemo = React3.memo;
236
236
 
237
237
  // src/utils/helpers.ts
238
238
  function isFunction(obj) {
@@ -347,7 +347,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
347
347
  }
348
348
  return styleBase;
349
349
  }, [composed, horizontal, position, index, activeStickyIndex, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
350
- return /* @__PURE__ */ React3.createElement("div", { "data-index": index, ref: refView, style: viewStyle, ...webProps }, children);
350
+ return /* @__PURE__ */ React3.createElement(
351
+ "div",
352
+ {
353
+ "data-index": index,
354
+ ref: refView,
355
+ style: viewStyle,
356
+ ...webProps
357
+ },
358
+ children
359
+ );
351
360
  });
352
361
  var PositionView = PositionViewState;
353
362
  function useInit(cb) {
@@ -613,13 +622,22 @@ var Platform = {
613
622
  OS: "web"
614
623
  };
615
624
 
616
- // src/utils/isInMVCPActiveMode.ts
617
- function isInMVCPActiveMode(state) {
625
+ // src/utils/hasActiveMVCPAnchorLock.ts
626
+ function hasActiveMVCPAnchorLock(state) {
618
627
  const lock = state.mvcpAnchorLock;
619
- if (lock && Date.now() > lock.expiresAt) {
628
+ if (!lock) {
629
+ return false;
630
+ }
631
+ if (Date.now() > lock.expiresAt) {
620
632
  state.mvcpAnchorLock = void 0;
633
+ return false;
621
634
  }
622
- return state.dataChangeNeedsScrollUpdate || !!state.mvcpAnchorLock;
635
+ return true;
636
+ }
637
+
638
+ // src/utils/isInMVCPActiveMode.ts
639
+ function isInMVCPActiveMode(state) {
640
+ return state.dataChangeNeedsScrollUpdate || hasActiveMVCPAnchorLock(state);
623
641
  }
624
642
 
625
643
  // src/components/Container.tsx
@@ -1326,7 +1344,7 @@ function SnapWrapper({ ScrollComponent, ...props }) {
1326
1344
  return /* @__PURE__ */ React3.createElement(ScrollComponent, { ...props, snapToOffsets });
1327
1345
  }
1328
1346
  var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1329
- const ref = refView != null ? refView : useRef();
1347
+ const ref = refView != null ? refView : useRef(null);
1330
1348
  useOnLayoutSync({ onLayoutChange, ref });
1331
1349
  return /* @__PURE__ */ React3.createElement("div", { ...rest, ref }, children);
1332
1350
  };
@@ -1770,7 +1788,6 @@ function finishScrollTo(ctx) {
1770
1788
  state.initialScroll = void 0;
1771
1789
  state.initialAnchor = void 0;
1772
1790
  state.scrollingTo = void 0;
1773
- state.stableTarget = void 0;
1774
1791
  if (state.pendingTotalSize !== void 0) {
1775
1792
  addTotalSize(ctx, null, state.pendingTotalSize);
1776
1793
  }
@@ -1887,9 +1904,8 @@ function scrollTo(ctx, params) {
1887
1904
  let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1888
1905
  offset = clampScrollOffset(ctx, offset, scrollTarget);
1889
1906
  state.scrollHistory.length = 0;
1890
- state.stableTarget = void 0;
1891
1907
  if (!noScrollingTo) {
1892
- state.scrollingTo = { ...scrollTarget, offset };
1908
+ state.scrollingTo = scrollTarget;
1893
1909
  }
1894
1910
  state.scrollPending = offset;
1895
1911
  if (forceScroll || !isInitialScroll || Platform.OS === "android") {
@@ -3330,14 +3346,6 @@ function checkActualChange(state, dataProp, previousData) {
3330
3346
  }
3331
3347
 
3332
3348
  // src/core/checkFinishedScroll.ts
3333
- function getCurrentTargetOffset(ctx, scrollingTo) {
3334
- if (scrollingTo.index !== void 0) {
3335
- const baseOffset = calculateOffsetForIndex(ctx, scrollingTo.index);
3336
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, scrollingTo);
3337
- return clampScrollOffset(ctx, resolvedOffset, scrollingTo);
3338
- }
3339
- return clampScrollOffset(ctx, scrollingTo.offset, scrollingTo);
3340
- }
3341
3349
  function checkFinishedScroll(ctx) {
3342
3350
  ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
3343
3351
  }
@@ -3347,30 +3355,20 @@ function checkFinishedScrollFrame(ctx) {
3347
3355
  const { state } = ctx;
3348
3356
  state.animFrameCheckFinishedScroll = void 0;
3349
3357
  const scroll = state.scrollPending;
3350
- const clampedTargetOffset = getCurrentTargetOffset(ctx, scrollingTo);
3351
- if (Math.abs(scrollingTo.offset - clampedTargetOffset) >= 1) {
3352
- state.scrollingTo = { ...scrollingTo, offset: clampedTargetOffset };
3353
- }
3358
+ const adjust = state.scrollAdjustHandler.getAdjust();
3359
+ const clampedTargetOffset = clampScrollOffset(
3360
+ ctx,
3361
+ scrollingTo.offset - (scrollingTo.viewOffset || 0),
3362
+ scrollingTo
3363
+ );
3354
3364
  const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
3355
3365
  const diff1 = Math.abs(scroll - clampedTargetOffset);
3366
+ const diff2 = Math.abs(diff1 - adjust);
3356
3367
  const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
3357
- const isAtTarget = diff1 < 1;
3358
- const previousStableTarget = state.stableTarget;
3359
- const hasStableTargetFrame = !!previousStableTarget && Math.abs(previousStableTarget.target - clampedTargetOffset) < 1 && Math.abs(previousStableTarget.scroll - scroll) < 1;
3360
- if (isAtTarget && !hasStableTargetFrame) {
3361
- state.stableTarget = { scroll, target: clampedTargetOffset };
3362
- state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
3363
- return;
3364
- }
3365
- if (!isAtTarget) {
3366
- state.stableTarget = void 0;
3367
- }
3368
+ const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
3368
3369
  if (isNotOverscrolled && isAtTarget) {
3369
- state.stableTarget = void 0;
3370
3370
  finishScrollTo(ctx);
3371
3371
  }
3372
- } else {
3373
- ctx.state.stableTarget = void 0;
3374
3372
  }
3375
3373
  }
3376
3374
  function checkFinishedScrollFallback(ctx) {
@@ -3898,17 +3896,53 @@ function createColumnWrapperStyle(contentContainerStyle) {
3898
3896
  // src/utils/createImperativeHandle.ts
3899
3897
  function createImperativeHandle(ctx) {
3900
3898
  const state = ctx.state;
3899
+ const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
3900
+ const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
3901
+ let imperativeScrollToken = 0;
3902
+ const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0 || hasActiveMVCPAnchorLock(state);
3903
+ const runWhenSettled = (token, run) => {
3904
+ const startedAt = Date.now();
3905
+ let stableFrames = 0;
3906
+ const check = () => {
3907
+ if (token !== imperativeScrollToken) {
3908
+ return;
3909
+ }
3910
+ if (isSettlingAfterDataChange()) {
3911
+ stableFrames = 0;
3912
+ } else {
3913
+ stableFrames += 1;
3914
+ }
3915
+ const timedOut = Date.now() - startedAt >= IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS;
3916
+ if (stableFrames >= IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES || timedOut) {
3917
+ run();
3918
+ return;
3919
+ }
3920
+ requestAnimationFrame(check);
3921
+ };
3922
+ requestAnimationFrame(check);
3923
+ };
3901
3924
  const runScrollWithPromise = (run) => new Promise((resolve) => {
3902
3925
  var _a3;
3926
+ const token = ++imperativeScrollToken;
3903
3927
  (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
3904
3928
  state.pendingScrollResolve = resolve;
3905
- const didStartScroll = run();
3906
- if (!didStartScroll || !state.scrollingTo) {
3907
- if (state.pendingScrollResolve === resolve) {
3908
- state.pendingScrollResolve = void 0;
3929
+ const runNow = () => {
3930
+ if (token !== imperativeScrollToken) {
3931
+ return;
3932
+ }
3933
+ const didStartScroll = run();
3934
+ if (!didStartScroll || !state.scrollingTo) {
3935
+ if (state.pendingScrollResolve === resolve) {
3936
+ state.pendingScrollResolve = void 0;
3937
+ }
3938
+ resolve();
3909
3939
  }
3910
- resolve();
3940
+ };
3941
+ if (isSettlingAfterDataChange()) {
3942
+ runWhenSettled(token, runNow);
3943
+ return;
3911
3944
  }
3945
+ runNow();
3912
3946
  });
3913
3947
  const scrollIndexIntoView = (options) => {
3914
3948
  if (state) {
@@ -3967,6 +4001,8 @@ function createImperativeHandle(ctx) {
3967
4001
  endBuffered: state.endBuffered,
3968
4002
  isAtEnd: state.isAtEnd,
3969
4003
  isAtStart: state.isAtStart,
4004
+ isEndReached: state.isEndReached,
4005
+ isStartReached: state.isStartReached,
3970
4006
  listen: (signalName, cb) => listen$(ctx, signalName, cb),
3971
4007
  listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
3972
4008
  positionAtIndex: (index) => state.positions[index],
@@ -4218,7 +4254,7 @@ var LegendList = typedMemo(
4218
4254
  })
4219
4255
  );
4220
4256
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4221
- var _a3, _b, _c, _d;
4257
+ var _a3, _b, _c, _d, _e;
4222
4258
  const {
4223
4259
  alignItemsAtEnd = false,
4224
4260
  alwaysRender,
@@ -4347,7 +4383,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4347
4383
  );
4348
4384
  }
4349
4385
  const useWindowScrollResolved = !!useWindowScroll && !renderScrollComponent;
4350
- const refState = useRef();
4386
+ const refState = useRef(void 0);
4351
4387
  const hasOverrideItemLayout = !!overrideItemLayout;
4352
4388
  const prevHasOverrideItemLayout = useRef(hasOverrideItemLayout);
4353
4389
  if (!refState.current) {
@@ -4679,6 +4715,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4679
4715
  []
4680
4716
  );
4681
4717
  const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
4718
+ const refreshControlElement = refreshControl;
4682
4719
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
4683
4720
  ListComponent,
4684
4721
  {
@@ -4697,9 +4734,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4697
4734
  onMomentumScrollEnd: fns.onMomentumScrollEnd,
4698
4735
  onScroll: onScrollHandler,
4699
4736
  recycleItems,
4700
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
4701
- progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4702
- }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
4737
+ refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControlElement, {
4738
+ progressViewOffset: ((_d = refreshControlElement.props.progressViewOffset) != null ? _d : 0) + stylePaddingTopState
4739
+ }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3.createElement(
4703
4740
  RefreshControl,
4704
4741
  {
4705
4742
  onRefresh,
@@ -4709,7 +4746,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4709
4746
  ),
4710
4747
  refScrollView: combinedRef,
4711
4748
  renderScrollComponent,
4712
- scrollAdjustHandler: (_d = refState.current) == null ? void 0 : _d.scrollAdjustHandler,
4749
+ scrollAdjustHandler: (_e = refState.current) == null ? void 0 : _e.scrollAdjustHandler,
4713
4750
  scrollEventThrottle: 0,
4714
4751
  snapToIndices,
4715
4752
  stickyHeaderIndices,