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

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
  }
@@ -591,7 +592,7 @@ interface ViewabilityConfig {
591
592
  type LegendListPropsOverrides<ItemT, TItemType extends string | undefined> = Omit<LegendListPropsBase<ItemT, ScrollViewProps, TItemType>, "onScroll" | "refScrollView" | "renderScrollComponent" | "ListHeaderComponentStyle" | "ListFooterComponentStyle"> & {
592
593
  onScroll?: (event: NativeSyntheticEvent$1<NativeScrollEvent$1>) => void;
593
594
  refScrollView?: React.Ref<ScrollView>;
594
- renderScrollComponent?: (props: ScrollViewProps) => ReactElement<ScrollViewProps>;
595
+ renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
595
596
  ListHeaderComponentStyle?: StyleProp$1<ViewStyle$1> | undefined;
596
597
  ListFooterComponentStyle?: StyleProp$1<ViewStyle$1> | undefined;
597
598
  };
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;
@@ -853,9 +849,9 @@ interface LegendListRecyclingState$1<T> {
853
849
  prevIndex: number | undefined;
854
850
  prevItem: T | undefined;
855
851
  }
856
- type TypedForwardRef$1 = <T, P = {}>(render: (props: P, ref: React.Ref<T>) => React.ReactNode) => (props: P & React.RefAttributes<T>) => React.ReactNode;
852
+ type TypedForwardRef$1 = <T, P = {}>(render: (props: P, ref: React.Ref<T>) => React.ReactElement | null) => (props: P & React.RefAttributes<T>) => React.ReactElement | null;
857
853
  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 & {
854
+ type TypedMemo$1 = <T extends React.ComponentType<any>>(Component: T, propsAreEqual?: (prevProps: Readonly<React.ComponentProps<T>>, nextProps: Readonly<React.ComponentProps<T>>) => boolean) => T & {
859
855
  displayName?: string;
860
856
  };
861
857
  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) {
@@ -4239,7 +4273,7 @@ var LegendList = typedMemo(
4239
4273
  })
4240
4274
  );
4241
4275
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4242
- var _a3, _b, _c, _d;
4276
+ var _a3, _b, _c, _d, _e;
4243
4277
  const {
4244
4278
  alignItemsAtEnd = false,
4245
4279
  alwaysRender,
@@ -4368,7 +4402,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4368
4402
  );
4369
4403
  }
4370
4404
  const useWindowScrollResolved = !!useWindowScroll && !renderScrollComponent;
4371
- const refState = React3.useRef();
4405
+ const refState = React3.useRef(void 0);
4372
4406
  const hasOverrideItemLayout = !!overrideItemLayout;
4373
4407
  const prevHasOverrideItemLayout = React3.useRef(hasOverrideItemLayout);
4374
4408
  if (!refState.current) {
@@ -4700,6 +4734,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4700
4734
  []
4701
4735
  );
4702
4736
  const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
4737
+ const refreshControlElement = refreshControl;
4703
4738
  return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
4704
4739
  ListComponent,
4705
4740
  {
@@ -4718,9 +4753,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4718
4753
  onMomentumScrollEnd: fns.onMomentumScrollEnd,
4719
4754
  onScroll: onScrollHandler,
4720
4755
  recycleItems,
4721
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
4722
- progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4723
- }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
4756
+ refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControlElement, {
4757
+ progressViewOffset: ((_d = refreshControlElement.props.progressViewOffset) != null ? _d : 0) + stylePaddingTopState
4758
+ }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
4724
4759
  RefreshControl,
4725
4760
  {
4726
4761
  onRefresh,
@@ -4730,7 +4765,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4730
4765
  ),
4731
4766
  refScrollView: combinedRef,
4732
4767
  renderScrollComponent,
4733
- scrollAdjustHandler: (_d = refState.current) == null ? void 0 : _d.scrollAdjustHandler,
4768
+ scrollAdjustHandler: (_e = refState.current) == null ? void 0 : _e.scrollAdjustHandler,
4734
4769
  scrollEventThrottle: 0,
4735
4770
  snapToIndices,
4736
4771
  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) {
@@ -4218,7 +4252,7 @@ var LegendList = typedMemo(
4218
4252
  })
4219
4253
  );
4220
4254
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4221
- var _a3, _b, _c, _d;
4255
+ var _a3, _b, _c, _d, _e;
4222
4256
  const {
4223
4257
  alignItemsAtEnd = false,
4224
4258
  alwaysRender,
@@ -4347,7 +4381,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4347
4381
  );
4348
4382
  }
4349
4383
  const useWindowScrollResolved = !!useWindowScroll && !renderScrollComponent;
4350
- const refState = useRef();
4384
+ const refState = useRef(void 0);
4351
4385
  const hasOverrideItemLayout = !!overrideItemLayout;
4352
4386
  const prevHasOverrideItemLayout = useRef(hasOverrideItemLayout);
4353
4387
  if (!refState.current) {
@@ -4679,6 +4713,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4679
4713
  []
4680
4714
  );
4681
4715
  const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
4716
+ const refreshControlElement = refreshControl;
4682
4717
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
4683
4718
  ListComponent,
4684
4719
  {
@@ -4697,9 +4732,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4697
4732
  onMomentumScrollEnd: fns.onMomentumScrollEnd,
4698
4733
  onScroll: onScrollHandler,
4699
4734
  recycleItems,
4700
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
4701
- progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4702
- }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
4735
+ refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControlElement, {
4736
+ progressViewOffset: ((_d = refreshControlElement.props.progressViewOffset) != null ? _d : 0) + stylePaddingTopState
4737
+ }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3.createElement(
4703
4738
  RefreshControl,
4704
4739
  {
4705
4740
  onRefresh,
@@ -4709,7 +4744,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4709
4744
  ),
4710
4745
  refScrollView: combinedRef,
4711
4746
  renderScrollComponent,
4712
- scrollAdjustHandler: (_d = refState.current) == null ? void 0 : _d.scrollAdjustHandler,
4747
+ scrollAdjustHandler: (_e = refState.current) == null ? void 0 : _e.scrollAdjustHandler,
4713
4748
  scrollEventThrottle: 0,
4714
4749
  snapToIndices,
4715
4750
  stickyHeaderIndices,