@legendapp/list 3.0.6 → 3.1.1

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/react.js CHANGED
@@ -162,6 +162,7 @@ function StateProvider({ children }) {
162
162
  mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
163
163
  mapViewabilityValues: /* @__PURE__ */ new Map(),
164
164
  positionListeners: /* @__PURE__ */ new Map(),
165
+ scrollAxisGap: 0,
165
166
  state: void 0,
166
167
  values: /* @__PURE__ */ new Map([
167
168
  ["alignItemsAtEndPadding", 0],
@@ -174,6 +175,7 @@ function StateProvider({ children }) {
174
175
  ["isNearEnd", false],
175
176
  ["isNearStart", false],
176
177
  ["isWithinMaintainScrollAtEndThreshold", false],
178
+ ["adaptiveRender", "light"],
177
179
  ["totalSize", 0],
178
180
  ["scrollAdjustPending", 0]
179
181
  ]),
@@ -554,6 +556,24 @@ var ContextContainer = React3.createContext(null);
554
556
  function useContextContainer() {
555
557
  return React3.useContext(ContextContainer);
556
558
  }
559
+ function useAdaptiveRender() {
560
+ const [mode] = useArr$(["adaptiveRender"]);
561
+ return mode;
562
+ }
563
+ function useAdaptiveRenderChange(callback) {
564
+ const ctx = useStateContext();
565
+ const callbackRef = React3.useRef(callback);
566
+ callbackRef.current = callback;
567
+ React3.useLayoutEffect(() => {
568
+ let mode = peek$(ctx, "adaptiveRender");
569
+ return listen$(ctx, "adaptiveRender", (nextMode) => {
570
+ if (mode !== nextMode) {
571
+ mode = nextMode;
572
+ callbackRef.current(nextMode);
573
+ }
574
+ });
575
+ }, [ctx]);
576
+ }
557
577
  function useViewability(callback, configId) {
558
578
  const ctx = useStateContext();
559
579
  const containerContext = useContextContainer();
@@ -823,6 +843,7 @@ function isInMVCPActiveMode(state) {
823
843
  // src/components/Container.tsx
824
844
  function getContainerPositionStyle({
825
845
  columnWrapperStyle,
846
+ contentContainerAlignItems,
826
847
  horizontal,
827
848
  hasItemSeparator,
828
849
  isHorizontalRTLList,
@@ -848,13 +869,14 @@ function getContainerPositionStyle({
848
869
  }
849
870
  }
850
871
  return horizontal ? {
872
+ bottom: contentContainerAlignItems === "flex-end" && numColumns === 1 ? 0 : void 0,
851
873
  boxSizing: paddingStyles ? "border-box" : void 0,
852
874
  direction: isHorizontalRTLList && Platform.OS === "web" ? "ltr" : void 0,
853
875
  flexDirection: hasItemSeparator ? "row" : void 0,
854
876
  height: otherAxisSize,
855
877
  left: 0,
856
878
  position: "absolute",
857
- top: otherAxisPos,
879
+ top: contentContainerAlignItems === "flex-end" && numColumns === 1 ? void 0 : otherAxisPos,
858
880
  ...paddingStyles || {}
859
881
  } : {
860
882
  boxSizing: paddingStyles ? "border-box" : void 0,
@@ -908,6 +930,7 @@ var Container = typedMemo(function Container2({
908
930
  const style = React3.useMemo(
909
931
  () => getContainerPositionStyle({
910
932
  columnWrapperStyle,
933
+ contentContainerAlignItems: ctx.state.props.contentContainerAlignItems,
911
934
  hasItemSeparator: !!ItemSeparatorComponent,
912
935
  horizontal,
913
936
  isHorizontalRTLList,
@@ -921,6 +944,7 @@ var Container = typedMemo(function Container2({
921
944
  otherAxisPos,
922
945
  otherAxisSize,
923
946
  columnWrapperStyle,
947
+ ctx.state.props.contentContainerAlignItems,
924
948
  numColumns,
925
949
  ItemSeparatorComponent
926
950
  ]
@@ -1636,7 +1660,12 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1636
1660
  WebkitOverflowScrolling: "touch"
1637
1661
  // iOS momentum scrolling
1638
1662
  },
1639
- ...StyleSheet.flatten(style)
1663
+ ...StyleSheet.flatten(style),
1664
+ ...maintainVisibleContentPosition ? {
1665
+ // Chrome's native scroll anchoring can apply after LegendList's MVCP adjustment,
1666
+ // causing the same header/item-size delta to be compensated twice.
1667
+ overflowAnchor: "none"
1668
+ } : {}
1640
1669
  };
1641
1670
  const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd2(ctx);
1642
1671
  const anchoredEndInset = ((_c = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.props) == null ? void 0 : _b.anchoredEndSpace) == null ? void 0 : _c.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
@@ -1647,7 +1676,10 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1647
1676
  flexDirection: horizontal ? "row" : void 0,
1648
1677
  minHeight: horizontal ? void 0 : "100%",
1649
1678
  minWidth: horizontal ? "100%" : void 0,
1650
- ...StyleSheet.flatten(contentContainerStyle)
1679
+ ...StyleSheet.flatten(contentContainerStyle),
1680
+ ...maintainVisibleContentPosition ? {
1681
+ overflowAnchor: "none"
1682
+ } : {}
1651
1683
  };
1652
1684
  const className = contentContainerClassName ? `${LEGEND_LIST_CONTENT_CONTAINER_CLASS} ${contentContainerClassName}` : LEGEND_LIST_CONTENT_CONTAINER_CLASS;
1653
1685
  const {
@@ -1750,6 +1782,7 @@ function scrollAdjustBy(el, left, top) {
1750
1782
  function ScrollAdjust() {
1751
1783
  const ctx = useStateContext();
1752
1784
  const lastScrollOffsetRef = React3__namespace.useRef(0);
1785
+ const lastScrollAdjustUserOffsetRef = React3__namespace.useRef(0);
1753
1786
  const resetPaddingRafRef = React3__namespace.useRef(void 0);
1754
1787
  const resetPaddingBaselineRef = React3__namespace.useRef(void 0);
1755
1788
  const contentNodeRef = React3__namespace.useRef(null);
@@ -1758,20 +1791,24 @@ function ScrollAdjust() {
1758
1791
  const scrollAdjust = peek$(ctx, "scrollAdjust");
1759
1792
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1760
1793
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1761
- const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1762
- if (scrollDelta !== 0) {
1794
+ const signalScrollDelta = scrollOffset - lastScrollOffsetRef.current;
1795
+ if (signalScrollDelta !== 0) {
1763
1796
  const target = getScrollAdjustTarget(ctx, contentNodeRef.current);
1764
1797
  if (target) {
1765
1798
  const horizontal = !!ctx.state.props.horizontal;
1766
1799
  const axis = getScrollAdjustAxis(horizontal);
1767
1800
  const { contentNode, scrollElement: el } = target;
1801
+ const currentScroll = horizontal ? el.scrollLeft : el.scrollTop;
1802
+ const userOffsetDelta = (scrollAdjustUserOffset || 0) - lastScrollAdjustUserOffsetRef.current;
1803
+ const intendedScroll = userOffsetDelta !== 0 ? currentScroll + userOffsetDelta : ctx.state.scroll;
1804
+ const scrollDelta = intendedScroll - currentScroll;
1805
+ const shouldScroll = Math.abs(scrollDelta) > 0.01;
1768
1806
  const scrollBy = () => scrollAdjustBy(el, axis.x * scrollDelta, axis.y * scrollDelta);
1769
1807
  contentNodeRef.current = contentNode;
1770
- if (contentNode) {
1771
- const prevScroll = horizontal ? el.scrollLeft : el.scrollTop;
1808
+ if (shouldScroll && contentNode) {
1772
1809
  const totalSize = contentNode[axis.contentSizeKey];
1773
1810
  const viewportSize = el[axis.viewportSizeKey];
1774
- const nextScroll = prevScroll + scrollDelta;
1811
+ const nextScroll = currentScroll + scrollDelta;
1775
1812
  const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize;
1776
1813
  if (needsTemporaryPadding) {
1777
1814
  const previousPaddingEnd = (_a3 = resetPaddingBaselineRef.current) != null ? _a3 : contentNode.style[axis.paddingEndProp];
@@ -1791,11 +1828,12 @@ function ScrollAdjust() {
1791
1828
  } else {
1792
1829
  scrollBy();
1793
1830
  }
1794
- } else {
1831
+ } else if (shouldScroll) {
1795
1832
  scrollBy();
1796
1833
  }
1797
1834
  }
1798
1835
  lastScrollOffsetRef.current = scrollOffset;
1836
+ lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0;
1799
1837
  }
1800
1838
  }, [ctx]);
1801
1839
  useValueListener$("scrollAdjust", callback);
@@ -1817,7 +1855,68 @@ function WebAnchoredEndSpace({ horizontal }) {
1817
1855
  return /* @__PURE__ */ React3__namespace.createElement("div", { style }, null);
1818
1856
  }
1819
1857
 
1820
- // src/core/updateContentMetrics.ts
1858
+ // src/core/doMaintainScrollAtEnd.ts
1859
+ function doMaintainScrollAtEnd(ctx) {
1860
+ const state = ctx.state;
1861
+ const {
1862
+ didContainersLayout,
1863
+ pendingNativeMVCPAdjust,
1864
+ refScroller,
1865
+ props: { maintainScrollAtEnd }
1866
+ } = state;
1867
+ const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
1868
+ const shouldMaintainScrollAtEnd = !!(isWithinMaintainScrollAtEndThreshold && maintainScrollAtEnd && didContainersLayout);
1869
+ if (pendingNativeMVCPAdjust) {
1870
+ state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1871
+ return false;
1872
+ }
1873
+ state.pendingMaintainScrollAtEnd = false;
1874
+ if (shouldMaintainScrollAtEnd) {
1875
+ const contentSize = getContentSize(ctx);
1876
+ if (contentSize < state.scrollLength) {
1877
+ state.scroll = 0;
1878
+ }
1879
+ if (!state.maintainingScrollAtEnd) {
1880
+ const pendingState = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
1881
+ const activeState = maintainScrollAtEnd.animated ? "animated" : "instant";
1882
+ state.maintainingScrollAtEnd = pendingState;
1883
+ requestAnimationFrame(() => {
1884
+ if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
1885
+ state.maintainingScrollAtEnd = activeState;
1886
+ const scroller = refScroller.current;
1887
+ if (state.props.horizontal && isHorizontalRTL(state)) {
1888
+ const currentContentSize = getContentSize(ctx);
1889
+ const logicalEndOffset = getLogicalHorizontalMaxOffset(state, currentContentSize);
1890
+ const nativeOffset = toNativeHorizontalOffset(state, logicalEndOffset, currentContentSize);
1891
+ scroller == null ? void 0 : scroller.scrollTo({
1892
+ animated: maintainScrollAtEnd.animated,
1893
+ x: nativeOffset,
1894
+ y: 0
1895
+ });
1896
+ } else {
1897
+ scroller == null ? void 0 : scroller.scrollToEnd({
1898
+ animated: maintainScrollAtEnd.animated
1899
+ });
1900
+ }
1901
+ setTimeout(
1902
+ () => {
1903
+ if (state.maintainingScrollAtEnd === activeState) {
1904
+ state.maintainingScrollAtEnd = void 0;
1905
+ }
1906
+ },
1907
+ maintainScrollAtEnd.animated ? 500 : 0
1908
+ );
1909
+ } else if (state.maintainingScrollAtEnd === pendingState) {
1910
+ state.maintainingScrollAtEnd = void 0;
1911
+ }
1912
+ });
1913
+ }
1914
+ return true;
1915
+ }
1916
+ return false;
1917
+ }
1918
+
1919
+ // src/core/updateContentMetricsState.ts
1821
1920
  function getRawContentLength(ctx) {
1822
1921
  var _a3, _b, _c;
1823
1922
  const { state, values } = ctx;
@@ -1828,320 +1927,128 @@ function getAlignItemsAtEndPadding(ctx) {
1828
1927
  const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1829
1928
  return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1830
1929
  }
1831
- function updateContentMetrics(ctx) {
1930
+ function updateContentMetricsState(ctx) {
1931
+ const previousPadding = peek$(ctx, "alignItemsAtEndPadding") || 0;
1832
1932
  const nextPadding = getAlignItemsAtEndPadding(ctx);
1833
- if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1933
+ if (previousPadding !== nextPadding) {
1834
1934
  set$(ctx, "alignItemsAtEndPadding", nextPadding);
1835
1935
  }
1836
1936
  }
1837
- function setContentLengthSignal(ctx, signalName, size) {
1838
- if (peek$(ctx, signalName) !== size) {
1839
- set$(ctx, signalName, size);
1840
- updateContentMetrics(ctx);
1937
+
1938
+ // src/core/addTotalSize.ts
1939
+ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1940
+ const state = ctx.state;
1941
+ const prevTotalSize = state.totalSize;
1942
+ let totalSize = state.totalSize;
1943
+ if (key === null) {
1944
+ totalSize = add;
1945
+ if (state.timeoutSetPaddingTop) {
1946
+ clearTimeout(state.timeoutSetPaddingTop);
1947
+ state.timeoutSetPaddingTop = void 0;
1948
+ }
1949
+ } else {
1950
+ totalSize += add;
1951
+ }
1952
+ if (prevTotalSize !== totalSize) {
1953
+ {
1954
+ state.pendingTotalSize = void 0;
1955
+ state.totalSize = totalSize;
1956
+ if (notifyTotalSize) {
1957
+ set$(ctx, "totalSize", totalSize);
1958
+ }
1959
+ updateContentMetricsState(ctx);
1960
+ }
1961
+ } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1962
+ set$(ctx, "totalSize", totalSize);
1841
1963
  }
1842
1964
  }
1843
- function setHeaderSize(ctx, size) {
1844
- setContentLengthSignal(ctx, "headerSize", size);
1965
+
1966
+ // src/core/deferredPublicOnScroll.ts
1967
+ function withResolvedContentOffset(state, event, resolvedOffset) {
1968
+ return {
1969
+ ...event,
1970
+ nativeEvent: {
1971
+ ...event.nativeEvent,
1972
+ contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1973
+ }
1974
+ };
1845
1975
  }
1846
- function setFooterSize(ctx, size) {
1847
- setContentLengthSignal(ctx, "footerSize", size);
1976
+ function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
1977
+ var _a3, _b, _c, _d;
1978
+ const state = ctx.state;
1979
+ const deferredEvent = state.deferredPublicOnScrollEvent;
1980
+ state.deferredPublicOnScrollEvent = void 0;
1981
+ if (deferredEvent) {
1982
+ (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
1983
+ _c,
1984
+ withResolvedContentOffset(
1985
+ state,
1986
+ deferredEvent,
1987
+ (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
1988
+ )
1989
+ );
1990
+ }
1848
1991
  }
1849
- function areInsetsEqual(left, right) {
1850
- var _a3, _b, _c, _d, _e, _f, _g, _h;
1851
- return ((_a3 = left == null ? void 0 : left.top) != null ? _a3 : 0) === ((_b = right == null ? void 0 : right.top) != null ? _b : 0) && ((_c = left == null ? void 0 : left.bottom) != null ? _c : 0) === ((_d = right == null ? void 0 : right.bottom) != null ? _d : 0) && ((_e = left == null ? void 0 : left.left) != null ? _e : 0) === ((_f = right == null ? void 0 : right.left) != null ? _f : 0) && ((_g = left == null ? void 0 : left.right) != null ? _g : 0) === ((_h = right == null ? void 0 : right.right) != null ? _h : 0);
1992
+
1993
+ // src/core/initialScrollSession.ts
1994
+ var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1995
+ function hasInitialScrollSessionCompletion(completion) {
1996
+ return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
1852
1997
  }
1853
- function setContentInsetOverride(ctx, inset) {
1854
- const { state } = ctx;
1855
- const previousInset = state.contentInsetOverride;
1856
- const nextInset = inset != null ? inset : void 0;
1857
- const didChange = !areInsetsEqual(previousInset, nextInset);
1858
- state.contentInsetOverride = nextInset;
1859
- if (didChange) {
1860
- updateContentMetrics(ctx);
1861
- }
1862
- return didChange;
1998
+ function clearInitialScrollSession(state) {
1999
+ state.initialScrollSession = void 0;
2000
+ return void 0;
1863
2001
  }
1864
- function useStableRenderComponent(renderComponent, mapProps) {
1865
- const renderComponentRef = useLatestRef(renderComponent);
1866
- const mapPropsRef = useLatestRef(mapProps);
1867
- return React3__namespace.useMemo(
1868
- () => React3__namespace.forwardRef(
1869
- (props, ref) => {
1870
- var _a3, _b;
1871
- return (_b = (_a3 = renderComponentRef.current) == null ? void 0 : _a3.call(renderComponentRef, mapPropsRef.current(props, ref))) != null ? _b : null;
1872
- }
1873
- ),
1874
- [mapPropsRef, renderComponentRef]
1875
- );
2002
+ function createInitialScrollSession(options) {
2003
+ const { bootstrap, completion, kind, previousDataLength } = options;
2004
+ return kind === "offset" ? {
2005
+ completion,
2006
+ kind,
2007
+ previousDataLength
2008
+ } : {
2009
+ bootstrap,
2010
+ completion,
2011
+ kind,
2012
+ previousDataLength
2013
+ };
1876
2014
  }
1877
- var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1878
- const localRef = React3.useRef(null);
1879
- const ref = refView != null ? refView : localRef;
1880
- useOnLayoutSync({ onLayoutChange, ref });
1881
- return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1882
- };
1883
-
1884
- // src/components/ListComponent.tsx
1885
- var ListComponent = typedMemo(function ListComponent2({
1886
- canRender,
1887
- style,
1888
- contentContainerStyle,
1889
- horizontal,
1890
- initialContentOffset,
1891
- recycleItems,
1892
- ItemSeparatorComponent,
1893
- alignItemsAtEnd: _alignItemsAtEnd,
1894
- onScroll: onScroll2,
1895
- onLayout,
1896
- ListHeaderComponent,
1897
- ListHeaderComponentStyle,
1898
- ListFooterComponent,
1899
- ListFooterComponentStyle,
1900
- ListEmptyComponent,
1901
- getRenderedItem: getRenderedItem2,
1902
- updateItemSize: updateItemSize2,
1903
- refScrollView,
1904
- renderScrollComponent,
1905
- onLayoutFooter,
1906
- scrollAdjustHandler,
1907
- snapToIndices,
1908
- stickyHeaderConfig,
1909
- stickyHeaderIndices,
1910
- useWindowScroll = false,
1911
- ...rest
1912
- }) {
1913
- const ctx = useStateContext();
1914
- const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1915
- const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1916
- const autoOtherAxisStyle = getAutoOtherAxisStyle({
1917
- horizontal,
1918
- needsOtherAxisSize: ctx.state.needsOtherAxisSize,
1919
- otherAxisSize
1920
- });
1921
- const CustomScrollComponent = useStableRenderComponent(
1922
- renderScrollComponent,
1923
- (props, ref) => ({ ...props, ref })
1924
- );
1925
- const ScrollComponent = renderScrollComponent ? CustomScrollComponent : ListComponentScrollView;
1926
- const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1927
- React3.useLayoutEffect(() => {
1928
- if (!ListHeaderComponent) {
1929
- setHeaderSize(ctx, 0);
1930
- }
1931
- if (!ListFooterComponent) {
1932
- setFooterSize(ctx, 0);
1933
- }
1934
- }, [ListHeaderComponent, ListFooterComponent, ctx]);
1935
- const onLayoutHeader = React3.useCallback(
1936
- (rect) => {
1937
- const size = rect[horizontal ? "width" : "height"];
1938
- setHeaderSize(ctx, size);
1939
- },
1940
- [ctx, horizontal]
1941
- );
1942
- const onLayoutFooterInternal = React3.useCallback(
1943
- (rect, fromLayoutEffect) => {
1944
- const size = rect[horizontal ? "width" : "height"];
1945
- setFooterSize(ctx, size);
1946
- onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1947
- },
1948
- [ctx, horizontal, onLayoutFooter]
1949
- );
1950
- return /* @__PURE__ */ React3__namespace.createElement(
1951
- SnapOrScroll,
1952
- {
1953
- ...rest,
1954
- ...ScrollComponent === ListComponentScrollView ? { useWindowScroll } : {},
1955
- contentContainerStyle: [
1956
- horizontal ? {
1957
- height: "100%"
1958
- } : {},
1959
- contentContainerStyle
1960
- ],
1961
- contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1962
- horizontal,
1963
- maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
1964
- onLayout,
1965
- onScroll: onScroll2,
1966
- ref: refScrollView,
1967
- ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1968
- style: autoOtherAxisStyle ? [autoOtherAxisStyle, style] : style
1969
- },
1970
- /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1971
- ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1972
- ListEmptyComponent && getComponent(ListEmptyComponent),
1973
- alignItemsAtEndPadding > 0 && /* @__PURE__ */ React3__namespace.createElement(
1974
- View,
1975
- {
1976
- style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
1977
- },
1978
- null
1979
- ),
1980
- canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1981
- Containers,
1982
- {
1983
- getRenderedItem: getRenderedItem2,
1984
- horizontal,
1985
- ItemSeparatorComponent,
1986
- recycleItems,
1987
- stickyHeaderConfig,
1988
- updateItemSize: updateItemSize2
1989
- }
1990
- ),
1991
- ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
1992
- /* @__PURE__ */ React3__namespace.createElement(WebAnchoredEndSpace, { horizontal }),
1993
- IS_DEV && ENABLE_DEVMODE
1994
- );
1995
- });
1996
- var WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH = 100;
1997
- var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
1998
- var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
1999
- function useDevChecksImpl(props) {
2000
- const ctx = useStateContext();
2001
- const { childrenMode, keyExtractor, renderScrollComponent, useWindowScroll } = props;
2002
- React3.useEffect(() => {
2003
- if (useWindowScroll && renderScrollComponent) {
2004
- warnDevOnce(
2005
- "useWindowScrollRenderScrollComponent",
2006
- "useWindowScroll is not supported when renderScrollComponent is provided."
2007
- );
2008
- }
2009
- }, [renderScrollComponent, useWindowScroll]);
2010
- React3.useEffect(() => {
2011
- if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
2012
- warnDevOnce(
2013
- "keyExtractor",
2014
- "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
2015
- );
2016
- }
2017
- }, [childrenMode, ctx, keyExtractor]);
2018
- React3.useEffect(() => {
2019
- const state = ctx.state;
2020
- const dataLength = state.props.data.length;
2021
- const useWindowScrollResolved = state.props.useWindowScroll;
2022
- if (useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
2023
- return;
2024
- }
2025
- const warnIfUnboundedOuterSize = () => {
2026
- const readyToRender = peek$(ctx, "readyToRender");
2027
- const numContainers = peek$(ctx, "numContainers") || 0;
2028
- const totalSize = peek$(ctx, "totalSize") || 0;
2029
- const scrollLength = ctx.state.scrollLength || 0;
2030
- if (!readyToRender || totalSize <= 0 || scrollLength <= 0) {
2031
- return;
2032
- }
2033
- const rendersAlmostEverything = numContainers >= Math.ceil(dataLength * WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO);
2034
- const viewportMatchesContent = scrollLength >= totalSize * WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO;
2035
- if (rendersAlmostEverything && viewportMatchesContent) {
2036
- warnDevOnce(
2037
- "webUnboundedOuterSize",
2038
- "LegendList appears to have an unbounded outer height on web, so virtualization is effectively disabled. Set a bounded height or flex: 1 on the list container, or use useWindowScroll."
2039
- );
2040
- }
2041
- };
2042
- warnIfUnboundedOuterSize();
2043
- const unsubscribe = [
2044
- listen$(ctx, "numContainers", warnIfUnboundedOuterSize),
2045
- listen$(ctx, "readyToRender", warnIfUnboundedOuterSize),
2046
- listen$(ctx, "totalSize", warnIfUnboundedOuterSize)
2047
- ];
2048
- return () => {
2049
- for (const unsub of unsubscribe) {
2050
- unsub();
2051
- }
2052
- };
2053
- }, [ctx]);
2054
- }
2055
- function useDevChecksNoop(_props) {
2056
- }
2057
- var useDevChecks = IS_DEV ? useDevChecksImpl : useDevChecksNoop;
2058
-
2059
- // src/core/deferredPublicOnScroll.ts
2060
- function withResolvedContentOffset(state, event, resolvedOffset) {
2061
- return {
2062
- ...event,
2063
- nativeEvent: {
2064
- ...event.nativeEvent,
2065
- contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
2066
- }
2067
- };
2068
- }
2069
- function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
2070
- var _a3, _b, _c, _d;
2071
- const state = ctx.state;
2072
- const deferredEvent = state.deferredPublicOnScrollEvent;
2073
- state.deferredPublicOnScrollEvent = void 0;
2074
- if (deferredEvent) {
2075
- (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
2076
- _c,
2077
- withResolvedContentOffset(
2078
- state,
2079
- deferredEvent,
2080
- (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
2081
- )
2082
- );
2083
- }
2084
- }
2085
-
2086
- // src/core/initialScrollSession.ts
2087
- var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
2088
- function hasInitialScrollSessionCompletion(completion) {
2089
- return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
2090
- }
2091
- function clearInitialScrollSession(state) {
2092
- state.initialScrollSession = void 0;
2093
- return void 0;
2094
- }
2095
- function createInitialScrollSession(options) {
2096
- const { bootstrap, completion, kind, previousDataLength } = options;
2097
- return kind === "offset" ? {
2098
- completion,
2099
- kind,
2100
- previousDataLength
2101
- } : {
2102
- bootstrap,
2103
- completion,
2104
- kind,
2105
- previousDataLength
2106
- };
2107
- }
2108
- function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
2109
- var _a4, _b2;
2110
- if (!state.initialScrollSession) {
2111
- state.initialScrollSession = createInitialScrollSession({
2112
- completion: {},
2113
- kind,
2114
- previousDataLength: 0
2115
- });
2116
- } else if (state.initialScrollSession.kind !== kind) {
2117
- state.initialScrollSession = createInitialScrollSession({
2118
- bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
2119
- completion: state.initialScrollSession.completion,
2120
- kind,
2121
- previousDataLength: state.initialScrollSession.previousDataLength
2122
- });
2123
- }
2124
- (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
2125
- return state.initialScrollSession.completion;
2126
- }
2127
- var initialScrollCompletion = {
2128
- didDispatchNativeScroll(state) {
2129
- var _a3, _b;
2130
- return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
2131
- },
2132
- didRetrySilentInitialScroll(state) {
2133
- var _a3, _b;
2134
- return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
2135
- },
2136
- markInitialScrollNativeDispatch(state) {
2137
- ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
2138
- },
2139
- markSilentInitialScrollRetry(state) {
2140
- ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
2141
- },
2142
- resetFlags(state) {
2143
- if (!state.initialScrollSession) {
2144
- return;
2015
+ function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
2016
+ var _a4, _b2;
2017
+ if (!state.initialScrollSession) {
2018
+ state.initialScrollSession = createInitialScrollSession({
2019
+ completion: {},
2020
+ kind,
2021
+ previousDataLength: 0
2022
+ });
2023
+ } else if (state.initialScrollSession.kind !== kind) {
2024
+ state.initialScrollSession = createInitialScrollSession({
2025
+ bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
2026
+ completion: state.initialScrollSession.completion,
2027
+ kind,
2028
+ previousDataLength: state.initialScrollSession.previousDataLength
2029
+ });
2030
+ }
2031
+ (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
2032
+ return state.initialScrollSession.completion;
2033
+ }
2034
+ var initialScrollCompletion = {
2035
+ didDispatchNativeScroll(state) {
2036
+ var _a3, _b;
2037
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
2038
+ },
2039
+ didRetrySilentInitialScroll(state) {
2040
+ var _a3, _b;
2041
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
2042
+ },
2043
+ markInitialScrollNativeDispatch(state) {
2044
+ ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
2045
+ },
2046
+ markSilentInitialScrollRetry(state) {
2047
+ ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
2048
+ },
2049
+ resetFlags(state) {
2050
+ if (!state.initialScrollSession) {
2051
+ return;
2145
2052
  }
2146
2053
  const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
2147
2054
  completion.didDispatchNativeScroll = void 0;
@@ -2367,6 +2274,66 @@ function recalculateSettledScroll(ctx) {
2367
2274
  checkThresholds(ctx);
2368
2275
  }
2369
2276
 
2277
+ // src/core/adaptiveRender.ts
2278
+ var DEFAULT_ENTER_VELOCITY = 4;
2279
+ var DEFAULT_EXIT_VELOCITY = 1;
2280
+ var DEFAULT_EXIT_DELAY = 1e3;
2281
+ function scheduleAdaptiveRenderExit(ctx, exitDelay) {
2282
+ const state = ctx.state;
2283
+ const previousTimeout = state.timeoutAdaptiveRender;
2284
+ if (previousTimeout !== void 0) {
2285
+ clearTimeout(previousTimeout);
2286
+ state.timeouts.delete(previousTimeout);
2287
+ state.timeoutAdaptiveRender = void 0;
2288
+ }
2289
+ if (exitDelay <= 0) {
2290
+ setAdaptiveRender(ctx, "normal");
2291
+ } else {
2292
+ const timeout = setTimeout(() => {
2293
+ state.timeouts.delete(timeout);
2294
+ state.timeoutAdaptiveRender = void 0;
2295
+ setAdaptiveRender(ctx, "normal");
2296
+ }, exitDelay);
2297
+ state.timeoutAdaptiveRender = timeout;
2298
+ state.timeouts.add(timeout);
2299
+ }
2300
+ }
2301
+ function setAdaptiveRender(ctx, mode) {
2302
+ var _a3, _b;
2303
+ const previousMode = peek$(ctx, "adaptiveRender");
2304
+ if (previousMode !== mode) {
2305
+ set$(ctx, "adaptiveRender", mode);
2306
+ (_b = (_a3 = ctx.state.props.adaptiveRender) == null ? void 0 : _a3.onChange) == null ? void 0 : _b.call(_a3, mode);
2307
+ }
2308
+ }
2309
+ function updateAdaptiveRender(ctx, scrollVelocity) {
2310
+ var _a3, _b, _c;
2311
+ const state = ctx.state;
2312
+ const adaptiveRender = state.props.adaptiveRender;
2313
+ const enterVelocity = (_a3 = adaptiveRender == null ? void 0 : adaptiveRender.enterVelocity) != null ? _a3 : DEFAULT_ENTER_VELOCITY;
2314
+ const exitVelocity = (_b = adaptiveRender == null ? void 0 : adaptiveRender.exitVelocity) != null ? _b : DEFAULT_EXIT_VELOCITY;
2315
+ const exitDelay = (_c = adaptiveRender == null ? void 0 : adaptiveRender.exitDelay) != null ? _c : DEFAULT_EXIT_DELAY;
2316
+ const currentMode = peek$(ctx, "adaptiveRender");
2317
+ const threshold = currentMode === "light" ? exitVelocity : enterVelocity;
2318
+ const nextMode = Math.abs(scrollVelocity) > threshold ? "light" : "normal";
2319
+ const previousMode = state.timeoutAdaptiveRender !== void 0 ? "normal" : currentMode;
2320
+ if (nextMode !== previousMode) {
2321
+ if (nextMode === "light") {
2322
+ setAdaptiveRender(ctx, "light");
2323
+ scheduleAdaptiveRenderExit(ctx, exitDelay);
2324
+ } else if (currentMode === "light") {
2325
+ scheduleAdaptiveRenderExit(ctx, exitDelay);
2326
+ }
2327
+ }
2328
+ }
2329
+
2330
+ // src/utils/getEffectiveDrawDistance.ts
2331
+ var INITIAL_DRAW_DISTANCE = 100;
2332
+ function getEffectiveDrawDistance(ctx) {
2333
+ const drawDistance = ctx.state.props.drawDistance;
2334
+ return peek$(ctx, "readyToRender") ? drawDistance : Math.min(drawDistance, INITIAL_DRAW_DISTANCE);
2335
+ }
2336
+
2370
2337
  // src/utils/setInitialRenderState.ts
2371
2338
  function setInitialRenderState(ctx, {
2372
2339
  didLayout,
@@ -2386,6 +2353,13 @@ function setInitialRenderState(ctx, {
2386
2353
  const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
2387
2354
  if (isReadyToRender && !peek$(ctx, "readyToRender")) {
2388
2355
  set$(ctx, "readyToRender", true);
2356
+ setAdaptiveRender(ctx, "normal");
2357
+ if (state.props.drawDistance > INITIAL_DRAW_DISTANCE) {
2358
+ requestAnimationFrame(() => {
2359
+ var _a3;
2360
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
2361
+ });
2362
+ }
2389
2363
  if (onLoad) {
2390
2364
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2391
2365
  }
@@ -2460,10 +2434,420 @@ function finishInitialScroll(ctx, options) {
2460
2434
  complete();
2461
2435
  }
2462
2436
 
2463
- // src/core/calculateOffsetForIndex.ts
2464
- function calculateOffsetForIndex(ctx, index) {
2437
+ // src/core/finishScrollTo.ts
2438
+ function finishScrollTo(ctx) {
2439
+ var _a3, _b;
2465
2440
  const state = ctx.state;
2466
- return index !== void 0 ? state.positions[index] || 0 : 0;
2441
+ if (state == null ? void 0 : state.scrollingTo) {
2442
+ const resolvePendingScroll = state.pendingScrollResolve;
2443
+ state.pendingScrollResolve = void 0;
2444
+ const scrollingTo = state.scrollingTo;
2445
+ state.scrollHistory.length = 0;
2446
+ state.scrollingTo = void 0;
2447
+ if (state.pendingTotalSize !== void 0) {
2448
+ addTotalSize(ctx, null, state.pendingTotalSize);
2449
+ }
2450
+ {
2451
+ state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
2452
+ }
2453
+ if (scrollingTo.isInitialScroll || state.initialScroll) {
2454
+ const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
2455
+ const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
2456
+ finishInitialScroll(ctx, {
2457
+ onFinished: () => {
2458
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2459
+ },
2460
+ preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
2461
+ recalculateItems: true,
2462
+ schedulePreservedTargetClear: shouldPreserveResizeTarget,
2463
+ syncObservedOffset: isOffsetSession,
2464
+ waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
2465
+ });
2466
+ return;
2467
+ }
2468
+ recalculateSettledScroll(ctx);
2469
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2470
+ }
2471
+ }
2472
+
2473
+ // src/core/doScrollTo.ts
2474
+ var SCROLL_END_IDLE_MS = 80;
2475
+ var SCROLL_END_MAX_MS = 1500;
2476
+ var SMOOTH_SCROLL_DURATION_MS = 320;
2477
+ var SCROLL_END_TARGET_EPSILON = 1;
2478
+ function doScrollTo(ctx, params) {
2479
+ var _a3, _b;
2480
+ const state = ctx.state;
2481
+ const { animated, horizontal, offset } = params;
2482
+ const scroller = state.refScroller.current;
2483
+ const node = scroller == null ? void 0 : scroller.getScrollableNode();
2484
+ if (!scroller || !node) {
2485
+ return;
2486
+ }
2487
+ const isAnimated = !!animated;
2488
+ const isHorizontal = !!horizontal;
2489
+ const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
2490
+ const left = isHorizontal ? toNativeHorizontalOffset(state, offset, contentSize) : 0;
2491
+ const top = isHorizontal ? 0 : offset;
2492
+ scroller.scrollTo({ animated: isAnimated, x: left, y: top });
2493
+ if (isAnimated) {
2494
+ const target = (_b = (_a3 = scroller.getScrollEventTarget) == null ? void 0 : _a3.call(scroller)) != null ? _b : null;
2495
+ listenForScrollEnd(ctx, {
2496
+ readOffset: () => scroller.getCurrentScrollOffset(),
2497
+ target,
2498
+ targetOffset: offset
2499
+ });
2500
+ } else {
2501
+ state.scroll = offset;
2502
+ setTimeout(() => {
2503
+ finishScrollTo(ctx);
2504
+ }, 100);
2505
+ }
2506
+ }
2507
+ function listenForScrollEnd(ctx, params) {
2508
+ const { readOffset, target, targetOffset } = params;
2509
+ if (!target) {
2510
+ finishScrollTo(ctx);
2511
+ return;
2512
+ }
2513
+ const supportsScrollEnd = "onscrollend" in target;
2514
+ let idleTimeout;
2515
+ let settled = false;
2516
+ const targetToken = ctx.state.scrollingTo;
2517
+ const maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
2518
+ const cleanup = () => {
2519
+ target.removeEventListener("scroll", onScroll2);
2520
+ if (supportsScrollEnd) {
2521
+ target.removeEventListener("scrollend", onScrollEnd);
2522
+ }
2523
+ if (idleTimeout) {
2524
+ clearTimeout(idleTimeout);
2525
+ }
2526
+ clearTimeout(maxTimeout);
2527
+ };
2528
+ const finish = (reason) => {
2529
+ if (settled) return;
2530
+ if (targetToken !== ctx.state.scrollingTo) {
2531
+ settled = true;
2532
+ cleanup();
2533
+ return;
2534
+ }
2535
+ const currentOffset = readOffset();
2536
+ const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
2537
+ if (reason === "scrollend" && !isNearTarget) {
2538
+ return;
2539
+ }
2540
+ settled = true;
2541
+ cleanup();
2542
+ finishScrollTo(ctx);
2543
+ };
2544
+ const onScroll2 = () => {
2545
+ if (idleTimeout) {
2546
+ clearTimeout(idleTimeout);
2547
+ }
2548
+ idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
2549
+ };
2550
+ const onScrollEnd = () => finish("scrollend");
2551
+ target.addEventListener("scroll", onScroll2);
2552
+ if (supportsScrollEnd) {
2553
+ target.addEventListener("scrollend", onScrollEnd);
2554
+ } else {
2555
+ idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
2556
+ }
2557
+ }
2558
+
2559
+ // src/utils/requestAdjust.ts
2560
+ function requestAdjust(ctx, positionDiff, dataChanged) {
2561
+ const state = ctx.state;
2562
+ if (Math.abs(positionDiff) > 0.1) {
2563
+ const doit = () => {
2564
+ {
2565
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
2566
+ if (state.adjustingFromInitialMount) {
2567
+ state.adjustingFromInitialMount--;
2568
+ }
2569
+ }
2570
+ };
2571
+ state.scroll += positionDiff;
2572
+ state.scrollForNextCalculateItemsInView = void 0;
2573
+ const readyToRender = peek$(ctx, "readyToRender");
2574
+ if (readyToRender) {
2575
+ doit();
2576
+ } else {
2577
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2578
+ requestAnimationFrame(doit);
2579
+ }
2580
+ }
2581
+ }
2582
+
2583
+ // src/core/updateContentMetrics.ts
2584
+ var SCROLL_ADJUST_EPSILON = 0.1;
2585
+ function setContentLengthSignal(ctx, signalName, size) {
2586
+ const didChange = peek$(ctx, signalName) !== size;
2587
+ if (didChange) {
2588
+ set$(ctx, signalName, size);
2589
+ updateContentMetricsState(ctx);
2590
+ }
2591
+ return didChange;
2592
+ }
2593
+ function shouldAdjustForHeaderSizeChange(ctx, previousHeaderSize, nextHeaderSize) {
2594
+ const { didContainersLayout, didFinishInitialScroll, props, scroll, scrollingTo } = ctx.state;
2595
+ const sizeDiff = nextHeaderSize - previousHeaderSize;
2596
+ const leadingPadding = props.horizontal ? props.stylePaddingLeft : props.stylePaddingTop;
2597
+ const previousHeaderEnd = (leadingPadding || 0) + previousHeaderSize;
2598
+ return props.maintainVisibleContentPosition.size && didContainersLayout && didFinishInitialScroll && !scrollingTo && scroll >= previousHeaderEnd - SCROLL_ADJUST_EPSILON && Math.abs(sizeDiff) > SCROLL_ADJUST_EPSILON;
2599
+ }
2600
+ function setHeaderSize(ctx, size) {
2601
+ const { state } = ctx;
2602
+ const previousHeaderSize = peek$(ctx, "headerSize") || 0;
2603
+ const didChange = previousHeaderSize !== size;
2604
+ const hasMeasuredOrEstimatedHeaderBaseline = state.didMeasureHeader || previousHeaderSize > SCROLL_ADJUST_EPSILON;
2605
+ if (didChange) {
2606
+ set$(ctx, "headerSize", size);
2607
+ updateContentMetricsState(ctx);
2608
+ if (hasMeasuredOrEstimatedHeaderBaseline && shouldAdjustForHeaderSizeChange(ctx, previousHeaderSize, size)) {
2609
+ requestAdjust(ctx, size - previousHeaderSize);
2610
+ }
2611
+ }
2612
+ state.didMeasureHeader = true;
2613
+ }
2614
+ function setFooterSize(ctx, size) {
2615
+ return setContentLengthSignal(ctx, "footerSize", size);
2616
+ }
2617
+ function areInsetsEqual(left, right) {
2618
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
2619
+ return ((_a3 = left == null ? void 0 : left.top) != null ? _a3 : 0) === ((_b = right == null ? void 0 : right.top) != null ? _b : 0) && ((_c = left == null ? void 0 : left.bottom) != null ? _c : 0) === ((_d = right == null ? void 0 : right.bottom) != null ? _d : 0) && ((_e = left == null ? void 0 : left.left) != null ? _e : 0) === ((_f = right == null ? void 0 : right.left) != null ? _f : 0) && ((_g = left == null ? void 0 : left.right) != null ? _g : 0) === ((_h = right == null ? void 0 : right.right) != null ? _h : 0);
2620
+ }
2621
+ function setContentInsetOverride(ctx, inset) {
2622
+ const { state } = ctx;
2623
+ const previousInset = state.contentInsetOverride;
2624
+ const nextInset = inset != null ? inset : void 0;
2625
+ const didChange = !areInsetsEqual(previousInset, nextInset);
2626
+ state.contentInsetOverride = nextInset;
2627
+ if (didChange) {
2628
+ updateContentMetricsState(ctx);
2629
+ }
2630
+ return didChange;
2631
+ }
2632
+ function useStableRenderComponent(renderComponent, mapProps) {
2633
+ const renderComponentRef = useLatestRef(renderComponent);
2634
+ const mapPropsRef = useLatestRef(mapProps);
2635
+ return React3__namespace.useMemo(
2636
+ () => React3__namespace.forwardRef(
2637
+ (props, ref) => {
2638
+ var _a3, _b;
2639
+ return (_b = (_a3 = renderComponentRef.current) == null ? void 0 : _a3.call(renderComponentRef, mapPropsRef.current(props, ref))) != null ? _b : null;
2640
+ }
2641
+ ),
2642
+ [mapPropsRef, renderComponentRef]
2643
+ );
2644
+ }
2645
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
2646
+ const localRef = React3.useRef(null);
2647
+ const ref = refView != null ? refView : localRef;
2648
+ useOnLayoutSync({ onLayoutChange, ref });
2649
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
2650
+ };
2651
+
2652
+ // src/components/ListComponent.tsx
2653
+ var AlignItemsAtEndSpacer = typedMemo(function AlignItemsAtEndSpacer2({ horizontal }) {
2654
+ const [alignItemsAtEndPadding = 0] = useArr$(["alignItemsAtEndPadding"]);
2655
+ if (alignItemsAtEndPadding <= 0) {
2656
+ return null;
2657
+ }
2658
+ return /* @__PURE__ */ React3__namespace.createElement(
2659
+ View,
2660
+ {
2661
+ style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
2662
+ },
2663
+ null
2664
+ );
2665
+ });
2666
+ var ListComponent = typedMemo(function ListComponent2({
2667
+ canRender,
2668
+ style,
2669
+ contentContainerStyle,
2670
+ horizontal,
2671
+ initialContentOffset,
2672
+ recycleItems,
2673
+ ItemSeparatorComponent,
2674
+ alignItemsAtEnd: _alignItemsAtEnd,
2675
+ onScroll: onScroll2,
2676
+ onLayout,
2677
+ ListHeaderComponent,
2678
+ ListHeaderComponentStyle,
2679
+ ListFooterComponent,
2680
+ ListFooterComponentStyle,
2681
+ ListEmptyComponent,
2682
+ getRenderedItem: getRenderedItem2,
2683
+ updateItemSize: updateItemSize2,
2684
+ refScrollView,
2685
+ renderScrollComponent,
2686
+ onLayoutFooter,
2687
+ scrollAdjustHandler,
2688
+ snapToIndices,
2689
+ stickyHeaderConfig,
2690
+ stickyHeaderIndices,
2691
+ useWindowScroll = false,
2692
+ ...rest
2693
+ }) {
2694
+ const ctx = useStateContext();
2695
+ const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
2696
+ const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
2697
+ const shouldRenderAlignItemsAtEndSpacer = ctx.state.props.alignItemsAtEndPaddingEnabled;
2698
+ const autoOtherAxisStyle = getAutoOtherAxisStyle({
2699
+ horizontal,
2700
+ needsOtherAxisSize: ctx.state.needsOtherAxisSize,
2701
+ otherAxisSize
2702
+ });
2703
+ const CustomScrollComponent = useStableRenderComponent(
2704
+ renderScrollComponent,
2705
+ (props, ref) => ({ ...props, ref })
2706
+ );
2707
+ const ScrollComponent = renderScrollComponent ? CustomScrollComponent : ListComponentScrollView;
2708
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
2709
+ const updateFooterSize = React3.useCallback(
2710
+ (size, afterSizeUpdate) => {
2711
+ var _a3;
2712
+ const didFooterSizeChange = setFooterSize(ctx, size);
2713
+ afterSizeUpdate == null ? void 0 : afterSizeUpdate();
2714
+ if (didFooterSizeChange && ((_a3 = ctx.state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onFooterLayout)) {
2715
+ doMaintainScrollAtEnd(ctx);
2716
+ }
2717
+ },
2718
+ [ctx]
2719
+ );
2720
+ React3.useLayoutEffect(() => {
2721
+ if (!ListHeaderComponent) {
2722
+ setHeaderSize(ctx, 0);
2723
+ }
2724
+ if (!ListFooterComponent) {
2725
+ updateFooterSize(0);
2726
+ }
2727
+ }, [ListHeaderComponent, ListFooterComponent, ctx, updateFooterSize]);
2728
+ const onLayoutHeader = React3.useCallback(
2729
+ (rect) => {
2730
+ const size = rect[horizontal ? "width" : "height"];
2731
+ setHeaderSize(ctx, size);
2732
+ },
2733
+ [ctx, horizontal]
2734
+ );
2735
+ const onLayoutFooterInternal = React3.useCallback(
2736
+ (rect, fromLayoutEffect) => {
2737
+ const size = rect[horizontal ? "width" : "height"];
2738
+ updateFooterSize(size, () => {
2739
+ onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
2740
+ });
2741
+ },
2742
+ [horizontal, onLayoutFooter, updateFooterSize]
2743
+ );
2744
+ return /* @__PURE__ */ React3__namespace.createElement(
2745
+ SnapOrScroll,
2746
+ {
2747
+ ...rest,
2748
+ ...ScrollComponent === ListComponentScrollView ? { useWindowScroll } : {},
2749
+ contentContainerStyle: [
2750
+ horizontal ? {
2751
+ height: "100%"
2752
+ } : {},
2753
+ contentContainerStyle
2754
+ ],
2755
+ contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
2756
+ horizontal,
2757
+ maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
2758
+ onLayout,
2759
+ onScroll: onScroll2,
2760
+ ref: refScrollView,
2761
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
2762
+ style: autoOtherAxisStyle ? [autoOtherAxisStyle, style] : style
2763
+ },
2764
+ /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
2765
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
2766
+ ListEmptyComponent && getComponent(ListEmptyComponent),
2767
+ shouldRenderAlignItemsAtEndSpacer && /* @__PURE__ */ React3__namespace.createElement(AlignItemsAtEndSpacer, { horizontal }),
2768
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
2769
+ Containers,
2770
+ {
2771
+ getRenderedItem: getRenderedItem2,
2772
+ horizontal,
2773
+ ItemSeparatorComponent,
2774
+ recycleItems,
2775
+ stickyHeaderConfig,
2776
+ updateItemSize: updateItemSize2
2777
+ }
2778
+ ),
2779
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
2780
+ /* @__PURE__ */ React3__namespace.createElement(WebAnchoredEndSpace, { horizontal }),
2781
+ IS_DEV && ENABLE_DEVMODE
2782
+ );
2783
+ });
2784
+ var WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH = 100;
2785
+ var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
2786
+ var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
2787
+ function useDevChecksImpl(props) {
2788
+ const ctx = useStateContext();
2789
+ const { childrenMode, keyExtractor, renderScrollComponent, useWindowScroll } = props;
2790
+ React3.useEffect(() => {
2791
+ if (useWindowScroll && renderScrollComponent) {
2792
+ warnDevOnce(
2793
+ "useWindowScrollRenderScrollComponent",
2794
+ "useWindowScroll is not supported when renderScrollComponent is provided."
2795
+ );
2796
+ }
2797
+ }, [renderScrollComponent, useWindowScroll]);
2798
+ React3.useEffect(() => {
2799
+ if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
2800
+ warnDevOnce(
2801
+ "keyExtractor",
2802
+ "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
2803
+ );
2804
+ }
2805
+ }, [childrenMode, ctx, keyExtractor]);
2806
+ React3.useEffect(() => {
2807
+ const state = ctx.state;
2808
+ const dataLength = state.props.data.length;
2809
+ const useWindowScrollResolved = state.props.useWindowScroll;
2810
+ if (useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
2811
+ return;
2812
+ }
2813
+ const warnIfUnboundedOuterSize = () => {
2814
+ const readyToRender = peek$(ctx, "readyToRender");
2815
+ const numContainers = peek$(ctx, "numContainers") || 0;
2816
+ const totalSize = peek$(ctx, "totalSize") || 0;
2817
+ const scrollLength = ctx.state.scrollLength || 0;
2818
+ if (!readyToRender || totalSize <= 0 || scrollLength <= 0) {
2819
+ return;
2820
+ }
2821
+ const rendersAlmostEverything = numContainers >= Math.ceil(dataLength * WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO);
2822
+ const viewportMatchesContent = scrollLength >= totalSize * WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO;
2823
+ if (rendersAlmostEverything && viewportMatchesContent) {
2824
+ warnDevOnce(
2825
+ "webUnboundedOuterSize",
2826
+ "LegendList appears to have an unbounded outer height on web, so virtualization is effectively disabled. Set a bounded height or flex: 1 on the list container, or use useWindowScroll."
2827
+ );
2828
+ }
2829
+ };
2830
+ warnIfUnboundedOuterSize();
2831
+ const unsubscribe = [
2832
+ listen$(ctx, "numContainers", warnIfUnboundedOuterSize),
2833
+ listen$(ctx, "readyToRender", warnIfUnboundedOuterSize),
2834
+ listen$(ctx, "totalSize", warnIfUnboundedOuterSize)
2835
+ ];
2836
+ return () => {
2837
+ for (const unsub of unsubscribe) {
2838
+ unsub();
2839
+ }
2840
+ };
2841
+ }, [ctx]);
2842
+ }
2843
+ function useDevChecksNoop(_props) {
2844
+ }
2845
+ var useDevChecks = IS_DEV ? useDevChecksImpl : useDevChecksNoop;
2846
+
2847
+ // src/core/calculateOffsetForIndex.ts
2848
+ function calculateOffsetForIndex(ctx, index) {
2849
+ const state = ctx.state;
2850
+ return index !== void 0 ? state.positions[index] || 0 : 0;
2467
2851
  }
2468
2852
 
2469
2853
  // src/core/getTopOffsetAdjustment.ts
@@ -2483,34 +2867,6 @@ function getId(state, index) {
2483
2867
  return id;
2484
2868
  }
2485
2869
 
2486
- // src/core/addTotalSize.ts
2487
- function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2488
- const state = ctx.state;
2489
- const prevTotalSize = state.totalSize;
2490
- let totalSize = state.totalSize;
2491
- if (key === null) {
2492
- totalSize = add;
2493
- if (state.timeoutSetPaddingTop) {
2494
- clearTimeout(state.timeoutSetPaddingTop);
2495
- state.timeoutSetPaddingTop = void 0;
2496
- }
2497
- } else {
2498
- totalSize += add;
2499
- }
2500
- if (prevTotalSize !== totalSize) {
2501
- {
2502
- state.pendingTotalSize = void 0;
2503
- state.totalSize = totalSize;
2504
- if (notifyTotalSize) {
2505
- set$(ctx, "totalSize", totalSize);
2506
- }
2507
- updateContentMetrics(ctx);
2508
- }
2509
- } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2510
- set$(ctx, "totalSize", totalSize);
2511
- }
2512
- }
2513
-
2514
2870
  // src/core/setSize.ts
2515
2871
  function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2516
2872
  const state = ctx.state;
@@ -2531,8 +2887,9 @@ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
2531
2887
  let size = key ? state.sizesKnown.get(key) : void 0;
2532
2888
  if (size === void 0 && key && getFixedItemSize) {
2533
2889
  const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2534
- size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
2535
- if (size !== void 0) {
2890
+ const fixedSize = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
2891
+ if (fixedSize !== void 0) {
2892
+ size = fixedSize + ctx.scrollAxisGap;
2536
2893
  state.sizesKnown.set(key, size);
2537
2894
  }
2538
2895
  }
@@ -2579,281 +2936,79 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2579
2936
  if (useAverageSize && !scrollingTo) {
2580
2937
  const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
2581
2938
  if (averageSizeForType !== void 0) {
2582
- size = roundSize(averageSizeForType);
2583
- }
2584
- }
2585
- if (size === void 0 && renderedSize !== void 0) {
2586
- return renderedSize;
2587
- }
2588
- if (size === void 0 && useAverageSize && scrollingTo) {
2589
- const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
2590
- if (averageSizeForType !== void 0) {
2591
- size = roundSize(averageSizeForType);
2592
- }
2593
- }
2594
- if (size === void 0) {
2595
- size = estimatedItemSize;
2596
- }
2597
- setSize(ctx, key, size, notifyTotalSize);
2598
- return size;
2599
- }
2600
- function getItemSizeAtIndex(ctx, index) {
2601
- if (index === void 0 || index < 0) {
2602
- return void 0;
2603
- }
2604
- const targetId = getId(ctx.state, index);
2605
- return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
2606
- }
2607
-
2608
- // src/core/calculateOffsetWithOffsetPosition.ts
2609
- function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
2610
- var _a3;
2611
- const state = ctx.state;
2612
- const { index, viewOffset, viewPosition } = params;
2613
- let offset = offsetParam;
2614
- if (viewOffset) {
2615
- offset -= viewOffset;
2616
- }
2617
- if (index !== void 0) {
2618
- const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
2619
- if (topOffsetAdjustment) {
2620
- offset += topOffsetAdjustment;
2621
- }
2622
- }
2623
- if (viewPosition !== void 0 && index !== void 0) {
2624
- const dataLength = state.props.data.length;
2625
- if (dataLength === 0) {
2626
- return offset;
2627
- }
2628
- const isOutOfBounds = index < 0 || index >= dataLength;
2629
- const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
2630
- const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
2631
- const trailingInset = getContentInsetEnd(ctx);
2632
- offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
2633
- if (!isOutOfBounds && index === state.props.data.length - 1) {
2634
- const footerSize = peek$(ctx, "footerSize") || 0;
2635
- offset += footerSize;
2636
- }
2637
- }
2638
- return offset;
2639
- }
2640
-
2641
- // src/core/clampScrollOffset.ts
2642
- function clampScrollOffset(ctx, offset, scrollTarget) {
2643
- const state = ctx.state;
2644
- const contentSize = getContentSize(ctx);
2645
- let clampedOffset = offset;
2646
- if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
2647
- const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
2648
- const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
2649
- const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
2650
- const maxOffset = baseMaxOffset + extraEndOffset;
2651
- clampedOffset = Math.min(offset, maxOffset);
2652
- }
2653
- clampedOffset = Math.max(0, clampedOffset);
2654
- return clampedOffset;
2655
- }
2656
-
2657
- // src/core/finishScrollTo.ts
2658
- function finishScrollTo(ctx) {
2659
- var _a3, _b;
2660
- const state = ctx.state;
2661
- if (state == null ? void 0 : state.scrollingTo) {
2662
- const resolvePendingScroll = state.pendingScrollResolve;
2663
- state.pendingScrollResolve = void 0;
2664
- const scrollingTo = state.scrollingTo;
2665
- state.scrollHistory.length = 0;
2666
- state.scrollingTo = void 0;
2667
- if (state.pendingTotalSize !== void 0) {
2668
- addTotalSize(ctx, null, state.pendingTotalSize);
2669
- }
2670
- {
2671
- state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
2672
- }
2673
- if (scrollingTo.isInitialScroll || state.initialScroll) {
2674
- const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
2675
- const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
2676
- finishInitialScroll(ctx, {
2677
- onFinished: () => {
2678
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2679
- },
2680
- preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
2681
- recalculateItems: true,
2682
- schedulePreservedTargetClear: shouldPreserveResizeTarget,
2683
- syncObservedOffset: isOffsetSession,
2684
- waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
2685
- });
2686
- return;
2687
- }
2688
- recalculateSettledScroll(ctx);
2689
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2690
- }
2691
- }
2692
-
2693
- // src/core/doScrollTo.ts
2694
- var SCROLL_END_IDLE_MS = 80;
2695
- var SCROLL_END_MAX_MS = 1500;
2696
- var SMOOTH_SCROLL_DURATION_MS = 320;
2697
- var SCROLL_END_TARGET_EPSILON = 1;
2698
- function doScrollTo(ctx, params) {
2699
- var _a3, _b;
2700
- const state = ctx.state;
2701
- const { animated, horizontal, offset } = params;
2702
- const scroller = state.refScroller.current;
2703
- const node = scroller == null ? void 0 : scroller.getScrollableNode();
2704
- if (!scroller || !node) {
2705
- return;
2706
- }
2707
- const isAnimated = !!animated;
2708
- const isHorizontal = !!horizontal;
2709
- const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
2710
- const left = isHorizontal ? toNativeHorizontalOffset(state, offset, contentSize) : 0;
2711
- const top = isHorizontal ? 0 : offset;
2712
- scroller.scrollTo({ animated: isAnimated, x: left, y: top });
2713
- if (isAnimated) {
2714
- const target = (_b = (_a3 = scroller.getScrollEventTarget) == null ? void 0 : _a3.call(scroller)) != null ? _b : null;
2715
- listenForScrollEnd(ctx, {
2716
- readOffset: () => scroller.getCurrentScrollOffset(),
2717
- target,
2718
- targetOffset: offset
2719
- });
2720
- } else {
2721
- state.scroll = offset;
2722
- setTimeout(() => {
2723
- finishScrollTo(ctx);
2724
- }, 100);
2725
- }
2726
- }
2727
- function listenForScrollEnd(ctx, params) {
2728
- const { readOffset, target, targetOffset } = params;
2729
- if (!target) {
2730
- finishScrollTo(ctx);
2731
- return;
2732
- }
2733
- const supportsScrollEnd = "onscrollend" in target;
2734
- let idleTimeout;
2735
- let settled = false;
2736
- const targetToken = ctx.state.scrollingTo;
2737
- const maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
2738
- const cleanup = () => {
2739
- target.removeEventListener("scroll", onScroll2);
2740
- if (supportsScrollEnd) {
2741
- target.removeEventListener("scrollend", onScrollEnd);
2742
- }
2743
- if (idleTimeout) {
2744
- clearTimeout(idleTimeout);
2745
- }
2746
- clearTimeout(maxTimeout);
2747
- };
2748
- const finish = (reason) => {
2749
- if (settled) return;
2750
- if (targetToken !== ctx.state.scrollingTo) {
2751
- settled = true;
2752
- cleanup();
2753
- return;
2754
- }
2755
- const currentOffset = readOffset();
2756
- const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
2757
- if (reason === "scrollend" && !isNearTarget) {
2758
- return;
2759
- }
2760
- settled = true;
2761
- cleanup();
2762
- finishScrollTo(ctx);
2763
- };
2764
- const onScroll2 = () => {
2765
- if (idleTimeout) {
2766
- clearTimeout(idleTimeout);
2939
+ size = roundSize(averageSizeForType);
2767
2940
  }
2768
- idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
2769
- };
2770
- const onScrollEnd = () => finish("scrollend");
2771
- target.addEventListener("scroll", onScroll2);
2772
- if (supportsScrollEnd) {
2773
- target.addEventListener("scrollend", onScrollEnd);
2774
- } else {
2775
- idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
2776
2941
  }
2942
+ if (size === void 0 && renderedSize !== void 0) {
2943
+ return renderedSize;
2944
+ }
2945
+ if (size === void 0 && useAverageSize && scrollingTo) {
2946
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
2947
+ if (averageSizeForType !== void 0) {
2948
+ size = roundSize(averageSizeForType);
2949
+ }
2950
+ }
2951
+ if (size === void 0) {
2952
+ size = estimatedItemSize + ctx.scrollAxisGap;
2953
+ }
2954
+ setSize(ctx, key, size, notifyTotalSize);
2955
+ return size;
2956
+ }
2957
+ function getItemSizeAtIndex(ctx, index) {
2958
+ if (index === void 0 || index < 0) {
2959
+ return void 0;
2960
+ }
2961
+ const targetId = getId(ctx.state, index);
2962
+ return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
2777
2963
  }
2778
2964
 
2779
- // src/core/doMaintainScrollAtEnd.ts
2780
- function doMaintainScrollAtEnd(ctx) {
2965
+ // src/core/calculateOffsetWithOffsetPosition.ts
2966
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
2967
+ var _a3;
2781
2968
  const state = ctx.state;
2782
- const {
2783
- didContainersLayout,
2784
- pendingNativeMVCPAdjust,
2785
- refScroller,
2786
- props: { maintainScrollAtEnd }
2787
- } = state;
2788
- const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
2789
- const shouldMaintainScrollAtEnd = !!(isWithinMaintainScrollAtEndThreshold && maintainScrollAtEnd && didContainersLayout);
2790
- if (pendingNativeMVCPAdjust) {
2791
- state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
2792
- return false;
2969
+ const { index, viewOffset, viewPosition } = params;
2970
+ let offset = offsetParam;
2971
+ if (viewOffset) {
2972
+ offset -= viewOffset;
2793
2973
  }
2794
- state.pendingMaintainScrollAtEnd = false;
2795
- if (shouldMaintainScrollAtEnd) {
2796
- const contentSize = getContentSize(ctx);
2797
- if (contentSize < state.scrollLength) {
2798
- state.scroll = 0;
2974
+ if (index !== void 0) {
2975
+ const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
2976
+ if (topOffsetAdjustment) {
2977
+ offset += topOffsetAdjustment;
2799
2978
  }
2800
- if (!state.maintainingScrollAtEnd) {
2801
- state.maintainingScrollAtEnd = true;
2802
- requestAnimationFrame(() => {
2803
- if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
2804
- const scroller = refScroller.current;
2805
- if (state.props.horizontal && isHorizontalRTL(state)) {
2806
- const currentContentSize = getContentSize(ctx);
2807
- const logicalEndOffset = getLogicalHorizontalMaxOffset(state, currentContentSize);
2808
- const nativeOffset = toNativeHorizontalOffset(state, logicalEndOffset, currentContentSize);
2809
- scroller == null ? void 0 : scroller.scrollTo({
2810
- animated: maintainScrollAtEnd.animated,
2811
- x: nativeOffset,
2812
- y: 0
2813
- });
2814
- } else {
2815
- scroller == null ? void 0 : scroller.scrollToEnd({
2816
- animated: maintainScrollAtEnd.animated
2817
- });
2818
- }
2819
- setTimeout(
2820
- () => {
2821
- state.maintainingScrollAtEnd = false;
2822
- },
2823
- maintainScrollAtEnd.animated ? 500 : 0
2824
- );
2825
- } else {
2826
- state.maintainingScrollAtEnd = false;
2827
- }
2828
- });
2979
+ }
2980
+ if (viewPosition !== void 0 && index !== void 0) {
2981
+ const dataLength = state.props.data.length;
2982
+ if (dataLength === 0) {
2983
+ return offset;
2984
+ }
2985
+ const isOutOfBounds = index < 0 || index >= dataLength;
2986
+ const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
2987
+ const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
2988
+ const trailingInset = getContentInsetEnd(ctx);
2989
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
2990
+ if (!isOutOfBounds && index === state.props.data.length - 1) {
2991
+ const footerSize = peek$(ctx, "footerSize") || 0;
2992
+ offset += footerSize;
2829
2993
  }
2830
- return true;
2831
2994
  }
2832
- return false;
2995
+ return offset;
2833
2996
  }
2834
2997
 
2835
- // src/utils/requestAdjust.ts
2836
- function requestAdjust(ctx, positionDiff, dataChanged) {
2998
+ // src/core/clampScrollOffset.ts
2999
+ function clampScrollOffset(ctx, offset, scrollTarget) {
2837
3000
  const state = ctx.state;
2838
- if (Math.abs(positionDiff) > 0.1) {
2839
- const doit = () => {
2840
- {
2841
- state.scrollAdjustHandler.requestAdjust(positionDiff);
2842
- if (state.adjustingFromInitialMount) {
2843
- state.adjustingFromInitialMount--;
2844
- }
2845
- }
2846
- };
2847
- state.scroll += positionDiff;
2848
- state.scrollForNextCalculateItemsInView = void 0;
2849
- const readyToRender = peek$(ctx, "readyToRender");
2850
- if (readyToRender) {
2851
- doit();
2852
- } else {
2853
- state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2854
- requestAnimationFrame(doit);
2855
- }
3001
+ const contentSize = getContentSize(ctx);
3002
+ let clampedOffset = offset;
3003
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
3004
+ const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
3005
+ const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
3006
+ const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
3007
+ const maxOffset = baseMaxOffset + extraEndOffset;
3008
+ clampedOffset = Math.min(offset, maxOffset);
2856
3009
  }
3010
+ clampedOffset = Math.max(0, clampedOffset);
3011
+ return clampedOffset;
2857
3012
  }
2858
3013
 
2859
3014
  // src/core/mvcp.ts
@@ -3001,6 +3156,10 @@ function prepareMVCP(ctx, dataChanged) {
3001
3156
  const now = Date.now();
3002
3157
  const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
3003
3158
  const scrollingTo = state.scrollingTo;
3159
+ if (dataChanged && state.pendingScrollToEnd && scrollingTo === void 0) {
3160
+ state.mvcpAnchorLock = void 0;
3161
+ return void 0;
3162
+ }
3004
3163
  const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
3005
3164
  let prevPosition;
3006
3165
  let targetId;
@@ -3129,7 +3288,7 @@ function prepareMVCP(ctx, dataChanged) {
3129
3288
  return;
3130
3289
  }
3131
3290
  if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
3132
- const shouldSkipAdjustForMaintainedEnd = state.maintainingScrollAtEnd && peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
3291
+ const shouldSkipAdjustForMaintainedEnd = (state.maintainingScrollAtEnd === "pending-animated" || state.maintainingScrollAtEnd === "animated") && peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
3133
3292
  if (!shouldSkipAdjustForMaintainedEnd) {
3134
3293
  requestAdjust(ctx, positionDiff);
3135
3294
  }
@@ -3138,6 +3297,45 @@ function prepareMVCP(ctx, dataChanged) {
3138
3297
  }
3139
3298
  }
3140
3299
 
3300
+ // src/utils/getScrollVelocity.ts
3301
+ var getScrollVelocity = (state) => {
3302
+ const { scrollHistory } = state;
3303
+ const newestIndex = scrollHistory.length - 1;
3304
+ if (newestIndex < 1) {
3305
+ return 0;
3306
+ }
3307
+ const newest = scrollHistory[newestIndex];
3308
+ const now = Date.now();
3309
+ let direction = 0;
3310
+ for (let i = newestIndex; i > 0; i--) {
3311
+ const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
3312
+ if (delta !== 0) {
3313
+ direction = Math.sign(delta);
3314
+ break;
3315
+ }
3316
+ }
3317
+ if (direction === 0) {
3318
+ return 0;
3319
+ }
3320
+ let oldest = newest;
3321
+ for (let i = newestIndex - 1; i >= 0; i--) {
3322
+ const current = scrollHistory[i];
3323
+ const next = scrollHistory[i + 1];
3324
+ const delta = next.scroll - current.scroll;
3325
+ const deltaSign = Math.sign(delta);
3326
+ if (deltaSign !== 0 && deltaSign !== direction) {
3327
+ break;
3328
+ }
3329
+ if (now - current.time > 1e3) {
3330
+ break;
3331
+ }
3332
+ oldest = current;
3333
+ }
3334
+ const scrollDiff = newest.scroll - oldest.scroll;
3335
+ const timeDiff = newest.time - oldest.time;
3336
+ return timeDiff > 0 ? scrollDiff / timeDiff : 0;
3337
+ };
3338
+
3141
3339
  // src/core/updateScroll.ts
3142
3340
  function updateScroll(ctx, newScroll, forceUpdate, options) {
3143
3341
  var _a3;
@@ -3163,6 +3361,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3163
3361
  if (scrollHistory.length > 5) {
3164
3362
  scrollHistory.shift();
3165
3363
  }
3364
+ const scrollVelocity = getScrollVelocity(state);
3365
+ updateAdaptiveRender(ctx, scrollVelocity);
3166
3366
  if (ignoreScrollFromMVCP && !scrollingTo) {
3167
3367
  const { lt, gt } = ignoreScrollFromMVCP;
3168
3368
  if (lt && newScroll < lt || gt && newScroll > gt) {
@@ -3186,7 +3386,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3186
3386
  state.lastScrollDelta = scrollDelta;
3187
3387
  const runCalculateItems = () => {
3188
3388
  var _a4;
3189
- (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
3389
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0, scrollVelocity });
3190
3390
  checkThresholds(ctx);
3191
3391
  };
3192
3392
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
@@ -4266,9 +4466,32 @@ function initializeInitialScrollOnMount(ctx, options) {
4266
4466
  }
4267
4467
  function handleInitialScrollDataChange(ctx, options) {
4268
4468
  var _a3, _b, _c;
4269
- const { dataLength, didDataChange, initialScrollAtEnd, stylePaddingBottom, useBootstrapInitialScroll } = options;
4469
+ const {
4470
+ dataLength,
4471
+ didDataChange,
4472
+ initialScrollAtEnd,
4473
+ latestInitialScroll,
4474
+ latestInitialScrollSessionKind,
4475
+ stylePaddingBottom,
4476
+ useBootstrapInitialScroll
4477
+ } = options;
4270
4478
  const state = ctx.state;
4271
4479
  const previousDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
4480
+ const isFirstNonEmptyData = !state.hasHadNonEmptyData && dataLength > 0;
4481
+ if (dataLength > 0) {
4482
+ state.hasHadNonEmptyData = true;
4483
+ }
4484
+ if (isFirstNonEmptyData) {
4485
+ if (latestInitialScroll) {
4486
+ setInitialScrollTarget(state, latestInitialScroll);
4487
+ setInitialScrollSession(state, {
4488
+ kind: latestInitialScrollSessionKind,
4489
+ previousDataLength
4490
+ });
4491
+ } else {
4492
+ clearPreservedInitialScrollTarget(state);
4493
+ }
4494
+ }
4272
4495
  if (state.initialScrollSession) {
4273
4496
  state.initialScrollSession.previousDataLength = dataLength;
4274
4497
  }
@@ -4492,45 +4715,6 @@ function updateTotalSize(ctx) {
4492
4715
  }
4493
4716
  }
4494
4717
 
4495
- // src/utils/getScrollVelocity.ts
4496
- var getScrollVelocity = (state) => {
4497
- const { scrollHistory } = state;
4498
- const newestIndex = scrollHistory.length - 1;
4499
- if (newestIndex < 1) {
4500
- return 0;
4501
- }
4502
- const newest = scrollHistory[newestIndex];
4503
- const now = Date.now();
4504
- let direction = 0;
4505
- for (let i = newestIndex; i > 0; i--) {
4506
- const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
4507
- if (delta !== 0) {
4508
- direction = Math.sign(delta);
4509
- break;
4510
- }
4511
- }
4512
- if (direction === 0) {
4513
- return 0;
4514
- }
4515
- let oldest = newest;
4516
- for (let i = newestIndex - 1; i >= 0; i--) {
4517
- const current = scrollHistory[i];
4518
- const next = scrollHistory[i + 1];
4519
- const delta = next.scroll - current.scroll;
4520
- const deltaSign = Math.sign(delta);
4521
- if (deltaSign !== 0 && deltaSign !== direction) {
4522
- break;
4523
- }
4524
- if (now - current.time > 1e3) {
4525
- break;
4526
- }
4527
- oldest = current;
4528
- }
4529
- const scrollDiff = newest.scroll - oldest.scroll;
4530
- const timeDiff = newest.time - oldest.time;
4531
- return timeDiff > 0 ? scrollDiff / timeDiff : 0;
4532
- };
4533
-
4534
4718
  // src/utils/updateSnapToOffsets.ts
4535
4719
  function updateSnapToOffsets(ctx) {
4536
4720
  const state = ctx.state;
@@ -5266,7 +5450,7 @@ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, sc
5266
5450
  function calculateItemsInView(ctx, params = {}) {
5267
5451
  const state = ctx.state;
5268
5452
  batchedUpdates(() => {
5269
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
5453
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
5270
5454
  const {
5271
5455
  columns,
5272
5456
  containerItemKeys,
@@ -5275,14 +5459,7 @@ function calculateItemsInView(ctx, params = {}) {
5275
5459
  indexByKey,
5276
5460
  minIndexSizeChanged,
5277
5461
  positions,
5278
- props: {
5279
- alwaysRenderIndicesArr,
5280
- alwaysRenderIndicesSet,
5281
- drawDistance,
5282
- getItemType,
5283
- keyExtractor,
5284
- onStickyHeaderChange
5285
- },
5462
+ props: { alwaysRenderIndicesArr, alwaysRenderIndicesSet, getItemType, keyExtractor, onStickyHeaderChange },
5286
5463
  scrollForNextCalculateItemsInView,
5287
5464
  scrollLength,
5288
5465
  sizes,
@@ -5294,6 +5471,7 @@ function calculateItemsInView(ctx, params = {}) {
5294
5471
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
5295
5472
  const alwaysRenderArr = alwaysRenderIndicesArr || [];
5296
5473
  const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
5474
+ const drawDistance = getEffectiveDrawDistance(ctx);
5297
5475
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
5298
5476
  const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
5299
5477
  const suppressInitialScrollSideEffects = !!bootstrapInitialScrollState;
@@ -5304,10 +5482,10 @@ function calculateItemsInView(ctx, params = {}) {
5304
5482
  let totalSize = getContentSize(ctx);
5305
5483
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
5306
5484
  const numColumns = peek$(ctx, "numColumns");
5307
- const speed = getScrollVelocity(state);
5485
+ const speed = (_b = params.scrollVelocity) != null ? _b : getScrollVelocity(state);
5308
5486
  const scrollExtra = 0;
5309
5487
  const { initialScroll, queuedInitialLayout } = state;
5310
- const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && hasActiveInitialScroll(state) && initialScroll ? (
5488
+ const scrollState = suppressInitialScrollSideEffects ? (_c = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _c : state.scroll : !queuedInitialLayout && hasActiveInitialScroll(state) && initialScroll ? (
5311
5489
  // Before the initial layout settles, keep viewport math anchored to the
5312
5490
  // current initial-scroll target instead of transient native adjustments.
5313
5491
  resolveInitialScrollOffset(ctx, initialScroll)
@@ -5331,19 +5509,25 @@ function calculateItemsInView(ctx, params = {}) {
5331
5509
  };
5332
5510
  updateScroll2(scrollState);
5333
5511
  const previousStickyIndex = peek$(ctx, "activeStickyIndex");
5334
- const currentStickyIdx = stickyHeaderIndicesArr.length > 0 ? findCurrentStickyIndex(stickyHeaderIndicesArr, scroll, state) : -1;
5335
- const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyHeaderIndicesArr[currentStickyIdx] : -1;
5336
- const stickyIndexDidChange = previousStickyIndex !== nextActiveStickyIndex;
5337
- if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
5338
- set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
5339
- }
5340
- const shouldNotifyStickyHeaderChange = !!onStickyHeaderChange && stickyHeaderIndicesArr.length > 0 && stickyIndexDidChange;
5341
- const finishCalculateItemsInView = shouldNotifyStickyHeaderChange ? () => {
5342
- const item = data[nextActiveStickyIndex];
5343
- if (item !== void 0) {
5344
- onStickyHeaderChange == null ? void 0 : onStickyHeaderChange({ index: nextActiveStickyIndex, item });
5512
+ const resolveStickyState = () => {
5513
+ const currentStickyIdx = stickyHeaderIndicesArr.length > 0 ? findCurrentStickyIndex(stickyHeaderIndicesArr, scroll, state) : -1;
5514
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyHeaderIndicesArr[currentStickyIdx] : -1;
5515
+ const stickyIndexDidChange = previousStickyIndex !== nextActiveStickyIndex;
5516
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
5517
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
5345
5518
  }
5346
- } : void 0;
5519
+ const shouldNotifyStickyHeaderChange = !!onStickyHeaderChange && stickyHeaderIndicesArr.length > 0 && stickyIndexDidChange;
5520
+ return {
5521
+ currentStickyIdx,
5522
+ finishCalculateItemsInView: shouldNotifyStickyHeaderChange ? () => {
5523
+ const item = data[nextActiveStickyIndex];
5524
+ if (item !== void 0) {
5525
+ onStickyHeaderChange == null ? void 0 : onStickyHeaderChange({ index: nextActiveStickyIndex, item });
5526
+ }
5527
+ } : void 0
5528
+ };
5529
+ };
5530
+ let stickyState = dataChanged ? void 0 : resolveStickyState();
5347
5531
  let scrollBufferTop = drawDistance;
5348
5532
  let scrollBufferBottom = drawDistance;
5349
5533
  if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
@@ -5376,7 +5560,7 @@ function calculateItemsInView(ctx, params = {}) {
5376
5560
  scrollBottom
5377
5561
  );
5378
5562
  }
5379
- finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
5563
+ (_d = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _d.call(stickyState);
5380
5564
  return;
5381
5565
  }
5382
5566
  }
@@ -5385,7 +5569,7 @@ function calculateItemsInView(ctx, params = {}) {
5385
5569
  if (dataChanged) {
5386
5570
  resetLayoutCachesForDataChange(state);
5387
5571
  }
5388
- const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
5572
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_e = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _e : 0;
5389
5573
  const optimizeForVisibleWindow = !forceFullItemPositions && !dataChanged && numColumns > 1 && minIndexSizeChanged !== void 0;
5390
5574
  updateItemPositions(ctx, dataChanged, {
5391
5575
  doMVCP,
@@ -5411,21 +5595,24 @@ function calculateItemsInView(ctx, params = {}) {
5411
5595
  }
5412
5596
  }
5413
5597
  const scrollBeforeMVCP = state.scroll;
5414
- const scrollAdjustPendingBeforeMVCP = (_d = peek$(ctx, "scrollAdjustPending")) != null ? _d : 0;
5598
+ const scrollAdjustPendingBeforeMVCP = (_f = peek$(ctx, "scrollAdjustPending")) != null ? _f : 0;
5415
5599
  checkMVCP == null ? void 0 : checkMVCP();
5416
- const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0) !== scrollAdjustPendingBeforeMVCP);
5600
+ const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_g = peek$(ctx, "scrollAdjustPending")) != null ? _g : 0) !== scrollAdjustPendingBeforeMVCP);
5417
5601
  if (didMVCPAdjustScroll && initialScroll) {
5418
5602
  updateScroll2(state.scroll);
5419
5603
  updateScrollRange();
5420
5604
  }
5605
+ if (dataChanged) {
5606
+ stickyState = resolveStickyState();
5607
+ }
5421
5608
  let startBuffered = null;
5422
5609
  let startBufferedId = null;
5423
5610
  let endBuffered = null;
5424
- let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
5611
+ let loopStart = (_h = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _h : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
5425
5612
  for (let i = loopStart; i >= 0; i--) {
5426
- const id = (_g = idCache[i]) != null ? _g : getId(state, i);
5613
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
5427
5614
  const top = positions[i];
5428
- const size = (_h = sizes.get(id)) != null ? _h : getItemSize(ctx, id, i, data[i]);
5615
+ const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
5429
5616
  const bottom = top + size;
5430
5617
  if (bottom > scrollTopBuffered) {
5431
5618
  loopStart = i;
@@ -5460,8 +5647,8 @@ function calculateItemsInView(ctx, params = {}) {
5460
5647
  };
5461
5648
  const dataLength = data.length;
5462
5649
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
5463
- const id = (_i = idCache[i]) != null ? _i : getId(state, i);
5464
- const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
5650
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5651
+ const size = (_l = sizes.get(id)) != null ? _l : getItemSize(ctx, id, i, data[i]);
5465
5652
  const top = positions[i];
5466
5653
  if (!foundEnd) {
5467
5654
  trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
@@ -5517,7 +5704,7 @@ function calculateItemsInView(ctx, params = {}) {
5517
5704
  const needNewContainers = [];
5518
5705
  const needNewContainersSet = /* @__PURE__ */ new Set();
5519
5706
  for (let i = startBuffered; i <= endBuffered; i++) {
5520
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5707
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
5521
5708
  if (!containerItemKeys.has(id)) {
5522
5709
  needNewContainersSet.add(i);
5523
5710
  needNewContainers.push(i);
@@ -5526,7 +5713,7 @@ function calculateItemsInView(ctx, params = {}) {
5526
5713
  if (alwaysRenderArr.length > 0) {
5527
5714
  for (const index of alwaysRenderArr) {
5528
5715
  if (index < 0 || index >= dataLength) continue;
5529
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
5716
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
5530
5717
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
5531
5718
  needNewContainersSet.add(index);
5532
5719
  needNewContainers.push(index);
@@ -5537,7 +5724,7 @@ function calculateItemsInView(ctx, params = {}) {
5537
5724
  handleStickyActivation(
5538
5725
  ctx,
5539
5726
  stickyHeaderIndicesArr,
5540
- currentStickyIdx,
5727
+ (_o = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _o : -1,
5541
5728
  needNewContainers,
5542
5729
  needNewContainersSet,
5543
5730
  startBuffered,
@@ -5563,7 +5750,7 @@ function calculateItemsInView(ctx, params = {}) {
5563
5750
  for (const allocation of availableContainerAllocations) {
5564
5751
  const i = allocation.itemIndex;
5565
5752
  const containerIndex = allocation.containerIndex;
5566
- const id = (_m = idCache[i]) != null ? _m : getId(state, i);
5753
+ const id = (_p = idCache[i]) != null ? _p : getId(state, i);
5567
5754
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
5568
5755
  if (oldKey && oldKey !== id) {
5569
5756
  containerItemKeys.delete(oldKey);
@@ -5574,7 +5761,7 @@ function calculateItemsInView(ctx, params = {}) {
5574
5761
  state.containerItemTypes.set(containerIndex, allocation.itemType);
5575
5762
  }
5576
5763
  containerItemKeys.set(id, containerIndex);
5577
- (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
5764
+ (_q = state.userScrollAnchorReset) == null ? void 0 : _q.keys.add(id);
5578
5765
  const containerSticky = `containerSticky${containerIndex}`;
5579
5766
  const isSticky = stickyHeaderIndicesSet.has(i);
5580
5767
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5605,14 +5792,12 @@ function calculateItemsInView(ctx, params = {}) {
5605
5792
  if (state.userScrollAnchorReset) {
5606
5793
  if (state.userScrollAnchorReset.keys.size === 0) {
5607
5794
  state.userScrollAnchorReset = void 0;
5608
- } else {
5609
- state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5610
5795
  }
5611
5796
  }
5612
5797
  if (alwaysRenderArr.length > 0) {
5613
5798
  for (const index of alwaysRenderArr) {
5614
5799
  if (index < 0 || index >= dataLength) continue;
5615
- const id = (_o = idCache[index]) != null ? _o : getId(state, index);
5800
+ const id = (_r = idCache[index]) != null ? _r : getId(state, index);
5616
5801
  const containerIndex = containerItemKeys.get(id);
5617
5802
  if (containerIndex !== void 0) {
5618
5803
  state.stickyContainerPool.add(containerIndex);
@@ -5626,7 +5811,7 @@ function calculateItemsInView(ctx, params = {}) {
5626
5811
  stickyHeaderIndicesArr,
5627
5812
  scroll,
5628
5813
  drawDistance,
5629
- currentStickyIdx,
5814
+ (_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
5630
5815
  pendingRemoval,
5631
5816
  alwaysRenderSet
5632
5817
  );
@@ -5687,7 +5872,7 @@ function calculateItemsInView(ctx, params = {}) {
5687
5872
  );
5688
5873
  }
5689
5874
  }
5690
- finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
5875
+ (_t = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _t.call(stickyState);
5691
5876
  });
5692
5877
  }
5693
5878
 
@@ -5770,8 +5955,9 @@ function doInitialAllocateContainers(ctx) {
5770
5955
  const state = ctx.state;
5771
5956
  const {
5772
5957
  scrollLength,
5773
- props: { data, drawDistance, getFixedItemSize, getItemType, numColumns, estimatedItemSize }
5958
+ props: { data, getFixedItemSize, getItemType, numColumns, estimatedItemSize }
5774
5959
  } = state;
5960
+ const drawDistance = getEffectiveDrawDistance(ctx);
5775
5961
  const hasContainers = peek$(ctx, "numContainers");
5776
5962
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
5777
5963
  let averageItemSize;
@@ -5782,12 +5968,12 @@ function doInitialAllocateContainers(ctx) {
5782
5968
  const item = data[i];
5783
5969
  if (item !== void 0) {
5784
5970
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
5785
- totalSize += (_b = getFixedItemSize(item, i, itemType)) != null ? _b : estimatedItemSize;
5971
+ totalSize += ((_b = getFixedItemSize(item, i, itemType)) != null ? _b : estimatedItemSize) + ctx.scrollAxisGap;
5786
5972
  }
5787
5973
  }
5788
5974
  averageItemSize = totalSize / num;
5789
5975
  } else {
5790
- averageItemSize = estimatedItemSize;
5976
+ averageItemSize = estimatedItemSize + ctx.scrollAxisGap;
5791
5977
  }
5792
5978
  const numContainers = Math.max(
5793
5979
  1,
@@ -5846,7 +6032,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5846
6032
  if (didChange) {
5847
6033
  state.scrollLength = scrollLength;
5848
6034
  state.otherAxisSize = otherAxisSize;
5849
- updateContentMetrics(ctx);
6035
+ updateContentMetricsState(ctx);
5850
6036
  state.lastBatchingAction = Date.now();
5851
6037
  state.scrollForNextCalculateItemsInView = void 0;
5852
6038
  if (scrollLength > 0) {
@@ -6083,28 +6269,12 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
6083
6269
 
6084
6270
  // src/core/updateItemSize.ts
6085
6271
  function runOrScheduleMVCPRecalculate(ctx) {
6086
- var _a3, _b;
6272
+ var _a3;
6087
6273
  const state = ctx.state;
6088
6274
  if (state.userScrollAnchorReset !== void 0) {
6089
- const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
6090
- const replacementMeasurementBatchThreshold = 3;
6091
- const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
6092
- if (shouldBatchReplacementMeasurements) {
6093
- if (state.queuedMVCPRecalculate === void 0) {
6094
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
6095
- var _a4;
6096
- state.queuedMVCPRecalculate = void 0;
6097
- calculateItemsInView(ctx);
6098
- if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
6099
- state.userScrollAnchorReset = void 0;
6100
- }
6101
- });
6102
- }
6103
- } else {
6104
- calculateItemsInView(ctx);
6105
- if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
6106
- state.userScrollAnchorReset = void 0;
6107
- }
6275
+ calculateItemsInView(ctx);
6276
+ if (((_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys.size) === 0) {
6277
+ state.userScrollAnchorReset = void 0;
6108
6278
  }
6109
6279
  } else {
6110
6280
  if (!state.mvcpAnchorLock) {
@@ -6564,6 +6734,9 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6564
6734
  scrollTo(ctx, params);
6565
6735
  return true;
6566
6736
  }),
6737
+ setItemSize: (itemKey, size) => {
6738
+ updateItemSize(ctx, itemKey, size);
6739
+ },
6567
6740
  setScrollProcessingEnabled: (enabled) => {
6568
6741
  state.scrollProcessingEnabled = enabled;
6569
6742
  },
@@ -6661,12 +6834,13 @@ function getRenderedItem(ctx, key) {
6661
6834
 
6662
6835
  // src/utils/normalizeMaintainScrollAtEnd.ts
6663
6836
  function normalizeMaintainScrollAtEndOn(on, hasExplicitOn) {
6664
- var _a3, _b, _c;
6837
+ var _a3, _b, _c, _d;
6665
6838
  return {
6666
6839
  animated: false,
6667
6840
  onDataChange: hasExplicitOn ? (_a3 = on == null ? void 0 : on.dataChange) != null ? _a3 : false : true,
6668
- onItemLayout: hasExplicitOn ? (_b = on == null ? void 0 : on.itemLayout) != null ? _b : false : true,
6669
- onLayout: hasExplicitOn ? (_c = on == null ? void 0 : on.layout) != null ? _c : false : true
6841
+ onFooterLayout: hasExplicitOn ? (_b = on == null ? void 0 : on.footerLayout) != null ? _b : false : true,
6842
+ onItemLayout: hasExplicitOn ? (_c = on == null ? void 0 : on.itemLayout) != null ? _c : false : true,
6843
+ onLayout: hasExplicitOn ? (_d = on == null ? void 0 : on.layout) != null ? _d : false : true
6670
6844
  };
6671
6845
  }
6672
6846
  function normalizeMaintainScrollAtEnd(value) {
@@ -6788,7 +6962,7 @@ var LegendList = typedMemo(
6788
6962
  })
6789
6963
  );
6790
6964
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
6791
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
6965
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
6792
6966
  const noopOnScroll = React3.useCallback((_event) => {
6793
6967
  }, []);
6794
6968
  if (props.recycleItems === void 0) {
@@ -6819,6 +6993,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6819
6993
  initialScrollAtEnd = false,
6820
6994
  initialScrollIndex: initialScrollIndexProp,
6821
6995
  initialScrollOffset: initialScrollOffsetProp,
6996
+ experimental_adaptiveRender,
6822
6997
  itemsAreEqual,
6823
6998
  keyExtractor: keyExtractorProp,
6824
6999
  ListEmptyComponent,
@@ -6915,6 +7090,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6915
7090
  const [, scheduleImperativeScrollCommit] = React3__namespace.useReducer((value) => value + 1, 0);
6916
7091
  const ctx = useStateContext();
6917
7092
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
7093
+ const scrollAxisGap = horizontal ? (_f = (_d = ctx.columnWrapperStyle) == null ? void 0 : _d.columnGap) != null ? _f : (_e = ctx.columnWrapperStyle) == null ? void 0 : _e.gap : (_i = (_g = ctx.columnWrapperStyle) == null ? void 0 : _g.rowGap) != null ? _i : (_h = ctx.columnWrapperStyle) == null ? void 0 : _h.gap;
7094
+ const nextScrollAxisGap = typeof scrollAxisGap === "number" && Number.isFinite(scrollAxisGap) ? scrollAxisGap : 0;
6918
7095
  const refScroller = React3.useRef(null);
6919
7096
  const combinedRef = useCombinedRef(refScroller, refScrollView);
6920
7097
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
@@ -6928,8 +7105,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6928
7105
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
6929
7106
  alwaysRender == null ? void 0 : alwaysRender.top,
6930
7107
  alwaysRender == null ? void 0 : alwaysRender.bottom,
6931
- (_d = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _d.join(","),
6932
- (_e = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _e.join(","),
7108
+ (_j = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _j.join(","),
7109
+ (_k = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _k.join(","),
6933
7110
  dataProp,
6934
7111
  dataVersion,
6935
7112
  keyExtractor
@@ -6957,6 +7134,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6957
7134
  endNoBuffer: -1,
6958
7135
  endReachedSnapshot: void 0,
6959
7136
  firstFullyOnScreenIndex: -1,
7137
+ hasHadNonEmptyData: dataProp.length > 0,
6960
7138
  idCache: [],
6961
7139
  idsInView: [],
6962
7140
  indexByKey: /* @__PURE__ */ new Map(),
@@ -6999,6 +7177,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6999
7177
  startReachedSnapshotDataChangeEpoch: void 0,
7000
7178
  stickyContainerPool: /* @__PURE__ */ new Set(),
7001
7179
  stickyContainers: /* @__PURE__ */ new Map(),
7180
+ timeoutAdaptiveRender: void 0,
7002
7181
  timeouts: /* @__PURE__ */ new Set(),
7003
7182
  totalSize: 0,
7004
7183
  viewabilityConfigCallbackPairs: void 0
@@ -7017,11 +7196,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7017
7196
  const state = refState.current;
7018
7197
  const isFirstLocal = state.isFirst;
7019
7198
  const previousNumColumnsProp = state.props.numColumns;
7020
- state.didColumnsChange = numColumnsProp !== previousNumColumnsProp;
7199
+ const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
7200
+ ctx.scrollAxisGap = nextScrollAxisGap;
7201
+ state.didColumnsChange = numColumnsProp !== previousNumColumnsProp || didScrollAxisGapChange;
7021
7202
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
7022
7203
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
7023
7204
  const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
7024
- if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.props.data.length > 0) {
7205
+ if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_l = state.initialScroll) == null ? void 0 : _l.viewPosition) === 1 && state.props.data.length > 0) {
7025
7206
  clearPreservedInitialScrollTarget(state);
7026
7207
  }
7027
7208
  if (didDataChangeLocal) {
@@ -7033,8 +7214,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7033
7214
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
7034
7215
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
7035
7216
  const anchoredEndSpaceResolved = anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
7036
- const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7217
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_m = state.props.anchoredEndSpace) == null ? void 0 : _m.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7037
7218
  state.props = {
7219
+ adaptiveRender: experimental_adaptiveRender,
7038
7220
  alignItemsAtEnd,
7039
7221
  alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
7040
7222
  alwaysRender,
@@ -7042,6 +7224,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7042
7224
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
7043
7225
  anchoredEndSpace: anchoredEndSpaceResolved,
7044
7226
  animatedProps: animatedPropsInternal,
7227
+ contentContainerAlignItems: contentContainerStyle.alignItems,
7045
7228
  contentInset,
7046
7229
  contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
7047
7230
  data: dataProp,
@@ -7094,7 +7277,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7094
7277
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
7095
7278
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
7096
7279
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
7097
- updateContentMetrics(ctx);
7280
+ updateContentMetricsState(ctx);
7098
7281
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
7099
7282
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
7100
7283
  };
@@ -7126,7 +7309,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7126
7309
  useBootstrapInitialScroll: usesBootstrapInitialScroll
7127
7310
  });
7128
7311
  }, []);
7129
- if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
7312
+ if (isFirstLocal || didDataChangeLocal || state.didColumnsChange) {
7130
7313
  refState.current.lastBatchingAction = Date.now();
7131
7314
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
7132
7315
  refState.current.sizes.clear();
@@ -7143,6 +7326,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7143
7326
  dataLength: dataProp.length,
7144
7327
  didDataChange: didDataChangeLocal,
7145
7328
  initialScrollAtEnd,
7329
+ latestInitialScroll: initialScrollProp,
7330
+ latestInitialScrollSessionKind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
7146
7331
  stylePaddingBottom: stylePaddingBottomState,
7147
7332
  useBootstrapInitialScroll: usesBootstrapInitialScroll
7148
7333
  });
@@ -7217,6 +7402,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7217
7402
  dataVersion,
7218
7403
  memoizedLastItemKeys.join(","),
7219
7404
  numColumnsProp,
7405
+ nextScrollAxisGap,
7220
7406
  stylePaddingBottomState,
7221
7407
  stylePaddingTopState,
7222
7408
  useAlignItemsAtEndPadding
@@ -7239,7 +7425,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7239
7425
  state.didColumnsChange = false;
7240
7426
  state.didDataChange = false;
7241
7427
  state.isFirst = false;
7242
- }, [dataProp, dataVersion, numColumnsProp]);
7428
+ }, [dataProp, dataVersion, numColumnsProp, nextScrollAxisGap]);
7243
7429
  React3.useLayoutEffect(() => {
7244
7430
  var _a4;
7245
7431
  set$(ctx, "extraData", extraData);
@@ -7287,6 +7473,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7287
7473
  useInit(() => {
7288
7474
  });
7289
7475
  React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7476
+ React3.useEffect(() => {
7477
+ return () => {
7478
+ for (const timeout of state.timeouts) {
7479
+ clearTimeout(timeout);
7480
+ }
7481
+ state.timeouts.clear();
7482
+ };
7483
+ }, [state]);
7290
7484
  React3.useLayoutEffect(() => {
7291
7485
  var _a4;
7292
7486
  (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
@@ -7334,7 +7528,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7334
7528
  onScroll: onScrollHandler,
7335
7529
  recycleItems,
7336
7530
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControlElement, {
7337
- progressViewOffset: ((_h = refreshControlElement.props.progressViewOffset) != null ? _h : 0) + stylePaddingTopState
7531
+ progressViewOffset: ((_n = refreshControlElement.props.progressViewOffset) != null ? _n : 0) + stylePaddingTopState
7338
7532
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
7339
7533
  RefreshControl,
7340
7534
  {
@@ -7345,7 +7539,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7345
7539
  ),
7346
7540
  refScrollView: combinedRef,
7347
7541
  renderScrollComponent,
7348
- scrollAdjustHandler: (_i = refState.current) == null ? void 0 : _i.scrollAdjustHandler,
7542
+ scrollAdjustHandler: (_o = refState.current) == null ? void 0 : _o.scrollAdjustHandler,
7349
7543
  scrollEventThrottle: 0,
7350
7544
  snapToIndices,
7351
7545
  stickyHeaderIndices,
@@ -7403,6 +7597,8 @@ var internal2 = internal;
7403
7597
 
7404
7598
  exports.LegendList = LegendList3;
7405
7599
  exports.internal = internal2;
7600
+ exports.useAdaptiveRender = useAdaptiveRender;
7601
+ exports.useAdaptiveRenderChange = useAdaptiveRenderChange;
7406
7602
  exports.useIsLastItem = useIsLastItem;
7407
7603
  exports.useListScrollSize = useListScrollSize;
7408
7604
  exports.useRecyclingEffect = useRecyclingEffect;