@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.mjs CHANGED
@@ -141,6 +141,7 @@ function StateProvider({ children }) {
141
141
  mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
142
142
  mapViewabilityValues: /* @__PURE__ */ new Map(),
143
143
  positionListeners: /* @__PURE__ */ new Map(),
144
+ scrollAxisGap: 0,
144
145
  state: void 0,
145
146
  values: /* @__PURE__ */ new Map([
146
147
  ["alignItemsAtEndPadding", 0],
@@ -153,6 +154,7 @@ function StateProvider({ children }) {
153
154
  ["isNearEnd", false],
154
155
  ["isNearStart", false],
155
156
  ["isWithinMaintainScrollAtEndThreshold", false],
157
+ ["adaptiveRender", "light"],
156
158
  ["totalSize", 0],
157
159
  ["scrollAdjustPending", 0]
158
160
  ]),
@@ -533,6 +535,24 @@ var ContextContainer = createContext(null);
533
535
  function useContextContainer() {
534
536
  return useContext(ContextContainer);
535
537
  }
538
+ function useAdaptiveRender() {
539
+ const [mode] = useArr$(["adaptiveRender"]);
540
+ return mode;
541
+ }
542
+ function useAdaptiveRenderChange(callback) {
543
+ const ctx = useStateContext();
544
+ const callbackRef = useRef(callback);
545
+ callbackRef.current = callback;
546
+ useLayoutEffect(() => {
547
+ let mode = peek$(ctx, "adaptiveRender");
548
+ return listen$(ctx, "adaptiveRender", (nextMode) => {
549
+ if (mode !== nextMode) {
550
+ mode = nextMode;
551
+ callbackRef.current(nextMode);
552
+ }
553
+ });
554
+ }, [ctx]);
555
+ }
536
556
  function useViewability(callback, configId) {
537
557
  const ctx = useStateContext();
538
558
  const containerContext = useContextContainer();
@@ -802,6 +822,7 @@ function isInMVCPActiveMode(state) {
802
822
  // src/components/Container.tsx
803
823
  function getContainerPositionStyle({
804
824
  columnWrapperStyle,
825
+ contentContainerAlignItems,
805
826
  horizontal,
806
827
  hasItemSeparator,
807
828
  isHorizontalRTLList,
@@ -827,13 +848,14 @@ function getContainerPositionStyle({
827
848
  }
828
849
  }
829
850
  return horizontal ? {
851
+ bottom: contentContainerAlignItems === "flex-end" && numColumns === 1 ? 0 : void 0,
830
852
  boxSizing: paddingStyles ? "border-box" : void 0,
831
853
  direction: isHorizontalRTLList && Platform.OS === "web" ? "ltr" : void 0,
832
854
  flexDirection: hasItemSeparator ? "row" : void 0,
833
855
  height: otherAxisSize,
834
856
  left: 0,
835
857
  position: "absolute",
836
- top: otherAxisPos,
858
+ top: contentContainerAlignItems === "flex-end" && numColumns === 1 ? void 0 : otherAxisPos,
837
859
  ...paddingStyles || {}
838
860
  } : {
839
861
  boxSizing: paddingStyles ? "border-box" : void 0,
@@ -887,6 +909,7 @@ var Container = typedMemo(function Container2({
887
909
  const style = useMemo(
888
910
  () => getContainerPositionStyle({
889
911
  columnWrapperStyle,
912
+ contentContainerAlignItems: ctx.state.props.contentContainerAlignItems,
890
913
  hasItemSeparator: !!ItemSeparatorComponent,
891
914
  horizontal,
892
915
  isHorizontalRTLList,
@@ -900,6 +923,7 @@ var Container = typedMemo(function Container2({
900
923
  otherAxisPos,
901
924
  otherAxisSize,
902
925
  columnWrapperStyle,
926
+ ctx.state.props.contentContainerAlignItems,
903
927
  numColumns,
904
928
  ItemSeparatorComponent
905
929
  ]
@@ -1615,7 +1639,12 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1615
1639
  WebkitOverflowScrolling: "touch"
1616
1640
  // iOS momentum scrolling
1617
1641
  },
1618
- ...StyleSheet.flatten(style)
1642
+ ...StyleSheet.flatten(style),
1643
+ ...maintainVisibleContentPosition ? {
1644
+ // Chrome's native scroll anchoring can apply after LegendList's MVCP adjustment,
1645
+ // causing the same header/item-size delta to be compensated twice.
1646
+ overflowAnchor: "none"
1647
+ } : {}
1619
1648
  };
1620
1649
  const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd2(ctx);
1621
1650
  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;
@@ -1626,7 +1655,10 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1626
1655
  flexDirection: horizontal ? "row" : void 0,
1627
1656
  minHeight: horizontal ? void 0 : "100%",
1628
1657
  minWidth: horizontal ? "100%" : void 0,
1629
- ...StyleSheet.flatten(contentContainerStyle)
1658
+ ...StyleSheet.flatten(contentContainerStyle),
1659
+ ...maintainVisibleContentPosition ? {
1660
+ overflowAnchor: "none"
1661
+ } : {}
1630
1662
  };
1631
1663
  const className = contentContainerClassName ? `${LEGEND_LIST_CONTENT_CONTAINER_CLASS} ${contentContainerClassName}` : LEGEND_LIST_CONTENT_CONTAINER_CLASS;
1632
1664
  const {
@@ -1729,6 +1761,7 @@ function scrollAdjustBy(el, left, top) {
1729
1761
  function ScrollAdjust() {
1730
1762
  const ctx = useStateContext();
1731
1763
  const lastScrollOffsetRef = React3.useRef(0);
1764
+ const lastScrollAdjustUserOffsetRef = React3.useRef(0);
1732
1765
  const resetPaddingRafRef = React3.useRef(void 0);
1733
1766
  const resetPaddingBaselineRef = React3.useRef(void 0);
1734
1767
  const contentNodeRef = React3.useRef(null);
@@ -1737,20 +1770,24 @@ function ScrollAdjust() {
1737
1770
  const scrollAdjust = peek$(ctx, "scrollAdjust");
1738
1771
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1739
1772
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1740
- const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1741
- if (scrollDelta !== 0) {
1773
+ const signalScrollDelta = scrollOffset - lastScrollOffsetRef.current;
1774
+ if (signalScrollDelta !== 0) {
1742
1775
  const target = getScrollAdjustTarget(ctx, contentNodeRef.current);
1743
1776
  if (target) {
1744
1777
  const horizontal = !!ctx.state.props.horizontal;
1745
1778
  const axis = getScrollAdjustAxis(horizontal);
1746
1779
  const { contentNode, scrollElement: el } = target;
1780
+ const currentScroll = horizontal ? el.scrollLeft : el.scrollTop;
1781
+ const userOffsetDelta = (scrollAdjustUserOffset || 0) - lastScrollAdjustUserOffsetRef.current;
1782
+ const intendedScroll = userOffsetDelta !== 0 ? currentScroll + userOffsetDelta : ctx.state.scroll;
1783
+ const scrollDelta = intendedScroll - currentScroll;
1784
+ const shouldScroll = Math.abs(scrollDelta) > 0.01;
1747
1785
  const scrollBy = () => scrollAdjustBy(el, axis.x * scrollDelta, axis.y * scrollDelta);
1748
1786
  contentNodeRef.current = contentNode;
1749
- if (contentNode) {
1750
- const prevScroll = horizontal ? el.scrollLeft : el.scrollTop;
1787
+ if (shouldScroll && contentNode) {
1751
1788
  const totalSize = contentNode[axis.contentSizeKey];
1752
1789
  const viewportSize = el[axis.viewportSizeKey];
1753
- const nextScroll = prevScroll + scrollDelta;
1790
+ const nextScroll = currentScroll + scrollDelta;
1754
1791
  const needsTemporaryPadding = scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + viewportSize;
1755
1792
  if (needsTemporaryPadding) {
1756
1793
  const previousPaddingEnd = (_a3 = resetPaddingBaselineRef.current) != null ? _a3 : contentNode.style[axis.paddingEndProp];
@@ -1770,11 +1807,12 @@ function ScrollAdjust() {
1770
1807
  } else {
1771
1808
  scrollBy();
1772
1809
  }
1773
- } else {
1810
+ } else if (shouldScroll) {
1774
1811
  scrollBy();
1775
1812
  }
1776
1813
  }
1777
1814
  lastScrollOffsetRef.current = scrollOffset;
1815
+ lastScrollAdjustUserOffsetRef.current = scrollAdjustUserOffset || 0;
1778
1816
  }
1779
1817
  }, [ctx]);
1780
1818
  useValueListener$("scrollAdjust", callback);
@@ -1796,7 +1834,68 @@ function WebAnchoredEndSpace({ horizontal }) {
1796
1834
  return /* @__PURE__ */ React3.createElement("div", { style }, null);
1797
1835
  }
1798
1836
 
1799
- // src/core/updateContentMetrics.ts
1837
+ // src/core/doMaintainScrollAtEnd.ts
1838
+ function doMaintainScrollAtEnd(ctx) {
1839
+ const state = ctx.state;
1840
+ const {
1841
+ didContainersLayout,
1842
+ pendingNativeMVCPAdjust,
1843
+ refScroller,
1844
+ props: { maintainScrollAtEnd }
1845
+ } = state;
1846
+ const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
1847
+ const shouldMaintainScrollAtEnd = !!(isWithinMaintainScrollAtEndThreshold && maintainScrollAtEnd && didContainersLayout);
1848
+ if (pendingNativeMVCPAdjust) {
1849
+ state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1850
+ return false;
1851
+ }
1852
+ state.pendingMaintainScrollAtEnd = false;
1853
+ if (shouldMaintainScrollAtEnd) {
1854
+ const contentSize = getContentSize(ctx);
1855
+ if (contentSize < state.scrollLength) {
1856
+ state.scroll = 0;
1857
+ }
1858
+ if (!state.maintainingScrollAtEnd) {
1859
+ const pendingState = maintainScrollAtEnd.animated ? "pending-animated" : "pending-instant";
1860
+ const activeState = maintainScrollAtEnd.animated ? "animated" : "instant";
1861
+ state.maintainingScrollAtEnd = pendingState;
1862
+ requestAnimationFrame(() => {
1863
+ if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
1864
+ state.maintainingScrollAtEnd = activeState;
1865
+ const scroller = refScroller.current;
1866
+ if (state.props.horizontal && isHorizontalRTL(state)) {
1867
+ const currentContentSize = getContentSize(ctx);
1868
+ const logicalEndOffset = getLogicalHorizontalMaxOffset(state, currentContentSize);
1869
+ const nativeOffset = toNativeHorizontalOffset(state, logicalEndOffset, currentContentSize);
1870
+ scroller == null ? void 0 : scroller.scrollTo({
1871
+ animated: maintainScrollAtEnd.animated,
1872
+ x: nativeOffset,
1873
+ y: 0
1874
+ });
1875
+ } else {
1876
+ scroller == null ? void 0 : scroller.scrollToEnd({
1877
+ animated: maintainScrollAtEnd.animated
1878
+ });
1879
+ }
1880
+ setTimeout(
1881
+ () => {
1882
+ if (state.maintainingScrollAtEnd === activeState) {
1883
+ state.maintainingScrollAtEnd = void 0;
1884
+ }
1885
+ },
1886
+ maintainScrollAtEnd.animated ? 500 : 0
1887
+ );
1888
+ } else if (state.maintainingScrollAtEnd === pendingState) {
1889
+ state.maintainingScrollAtEnd = void 0;
1890
+ }
1891
+ });
1892
+ }
1893
+ return true;
1894
+ }
1895
+ return false;
1896
+ }
1897
+
1898
+ // src/core/updateContentMetricsState.ts
1800
1899
  function getRawContentLength(ctx) {
1801
1900
  var _a3, _b, _c;
1802
1901
  const { state, values } = ctx;
@@ -1807,320 +1906,128 @@ function getAlignItemsAtEndPadding(ctx) {
1807
1906
  const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1808
1907
  return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1809
1908
  }
1810
- function updateContentMetrics(ctx) {
1909
+ function updateContentMetricsState(ctx) {
1910
+ const previousPadding = peek$(ctx, "alignItemsAtEndPadding") || 0;
1811
1911
  const nextPadding = getAlignItemsAtEndPadding(ctx);
1812
- if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1912
+ if (previousPadding !== nextPadding) {
1813
1913
  set$(ctx, "alignItemsAtEndPadding", nextPadding);
1814
1914
  }
1815
1915
  }
1816
- function setContentLengthSignal(ctx, signalName, size) {
1817
- if (peek$(ctx, signalName) !== size) {
1818
- set$(ctx, signalName, size);
1819
- updateContentMetrics(ctx);
1916
+
1917
+ // src/core/addTotalSize.ts
1918
+ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1919
+ const state = ctx.state;
1920
+ const prevTotalSize = state.totalSize;
1921
+ let totalSize = state.totalSize;
1922
+ if (key === null) {
1923
+ totalSize = add;
1924
+ if (state.timeoutSetPaddingTop) {
1925
+ clearTimeout(state.timeoutSetPaddingTop);
1926
+ state.timeoutSetPaddingTop = void 0;
1927
+ }
1928
+ } else {
1929
+ totalSize += add;
1930
+ }
1931
+ if (prevTotalSize !== totalSize) {
1932
+ {
1933
+ state.pendingTotalSize = void 0;
1934
+ state.totalSize = totalSize;
1935
+ if (notifyTotalSize) {
1936
+ set$(ctx, "totalSize", totalSize);
1937
+ }
1938
+ updateContentMetricsState(ctx);
1939
+ }
1940
+ } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1941
+ set$(ctx, "totalSize", totalSize);
1820
1942
  }
1821
1943
  }
1822
- function setHeaderSize(ctx, size) {
1823
- setContentLengthSignal(ctx, "headerSize", size);
1944
+
1945
+ // src/core/deferredPublicOnScroll.ts
1946
+ function withResolvedContentOffset(state, event, resolvedOffset) {
1947
+ return {
1948
+ ...event,
1949
+ nativeEvent: {
1950
+ ...event.nativeEvent,
1951
+ contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1952
+ }
1953
+ };
1824
1954
  }
1825
- function setFooterSize(ctx, size) {
1826
- setContentLengthSignal(ctx, "footerSize", size);
1955
+ function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
1956
+ var _a3, _b, _c, _d;
1957
+ const state = ctx.state;
1958
+ const deferredEvent = state.deferredPublicOnScrollEvent;
1959
+ state.deferredPublicOnScrollEvent = void 0;
1960
+ if (deferredEvent) {
1961
+ (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
1962
+ _c,
1963
+ withResolvedContentOffset(
1964
+ state,
1965
+ deferredEvent,
1966
+ (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
1967
+ )
1968
+ );
1969
+ }
1827
1970
  }
1828
- function areInsetsEqual(left, right) {
1829
- var _a3, _b, _c, _d, _e, _f, _g, _h;
1830
- 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);
1971
+
1972
+ // src/core/initialScrollSession.ts
1973
+ var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1974
+ function hasInitialScrollSessionCompletion(completion) {
1975
+ return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
1831
1976
  }
1832
- function setContentInsetOverride(ctx, inset) {
1833
- const { state } = ctx;
1834
- const previousInset = state.contentInsetOverride;
1835
- const nextInset = inset != null ? inset : void 0;
1836
- const didChange = !areInsetsEqual(previousInset, nextInset);
1837
- state.contentInsetOverride = nextInset;
1838
- if (didChange) {
1839
- updateContentMetrics(ctx);
1840
- }
1841
- return didChange;
1977
+ function clearInitialScrollSession(state) {
1978
+ state.initialScrollSession = void 0;
1979
+ return void 0;
1842
1980
  }
1843
- function useStableRenderComponent(renderComponent, mapProps) {
1844
- const renderComponentRef = useLatestRef(renderComponent);
1845
- const mapPropsRef = useLatestRef(mapProps);
1846
- return React3.useMemo(
1847
- () => React3.forwardRef(
1848
- (props, ref) => {
1849
- var _a3, _b;
1850
- return (_b = (_a3 = renderComponentRef.current) == null ? void 0 : _a3.call(renderComponentRef, mapPropsRef.current(props, ref))) != null ? _b : null;
1851
- }
1852
- ),
1853
- [mapPropsRef, renderComponentRef]
1854
- );
1981
+ function createInitialScrollSession(options) {
1982
+ const { bootstrap, completion, kind, previousDataLength } = options;
1983
+ return kind === "offset" ? {
1984
+ completion,
1985
+ kind,
1986
+ previousDataLength
1987
+ } : {
1988
+ bootstrap,
1989
+ completion,
1990
+ kind,
1991
+ previousDataLength
1992
+ };
1855
1993
  }
1856
- var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1857
- const localRef = useRef(null);
1858
- const ref = refView != null ? refView : localRef;
1859
- useOnLayoutSync({ onLayoutChange, ref });
1860
- return /* @__PURE__ */ React3.createElement("div", { ...rest, ref }, children);
1861
- };
1862
-
1863
- // src/components/ListComponent.tsx
1864
- var ListComponent = typedMemo(function ListComponent2({
1865
- canRender,
1866
- style,
1867
- contentContainerStyle,
1868
- horizontal,
1869
- initialContentOffset,
1870
- recycleItems,
1871
- ItemSeparatorComponent,
1872
- alignItemsAtEnd: _alignItemsAtEnd,
1873
- onScroll: onScroll2,
1874
- onLayout,
1875
- ListHeaderComponent,
1876
- ListHeaderComponentStyle,
1877
- ListFooterComponent,
1878
- ListFooterComponentStyle,
1879
- ListEmptyComponent,
1880
- getRenderedItem: getRenderedItem2,
1881
- updateItemSize: updateItemSize2,
1882
- refScrollView,
1883
- renderScrollComponent,
1884
- onLayoutFooter,
1885
- scrollAdjustHandler,
1886
- snapToIndices,
1887
- stickyHeaderConfig,
1888
- stickyHeaderIndices,
1889
- useWindowScroll = false,
1890
- ...rest
1891
- }) {
1892
- const ctx = useStateContext();
1893
- const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1894
- const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1895
- const autoOtherAxisStyle = getAutoOtherAxisStyle({
1896
- horizontal,
1897
- needsOtherAxisSize: ctx.state.needsOtherAxisSize,
1898
- otherAxisSize
1899
- });
1900
- const CustomScrollComponent = useStableRenderComponent(
1901
- renderScrollComponent,
1902
- (props, ref) => ({ ...props, ref })
1903
- );
1904
- const ScrollComponent = renderScrollComponent ? CustomScrollComponent : ListComponentScrollView;
1905
- const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1906
- useLayoutEffect(() => {
1907
- if (!ListHeaderComponent) {
1908
- setHeaderSize(ctx, 0);
1909
- }
1910
- if (!ListFooterComponent) {
1911
- setFooterSize(ctx, 0);
1912
- }
1913
- }, [ListHeaderComponent, ListFooterComponent, ctx]);
1914
- const onLayoutHeader = useCallback(
1915
- (rect) => {
1916
- const size = rect[horizontal ? "width" : "height"];
1917
- setHeaderSize(ctx, size);
1918
- },
1919
- [ctx, horizontal]
1920
- );
1921
- const onLayoutFooterInternal = useCallback(
1922
- (rect, fromLayoutEffect) => {
1923
- const size = rect[horizontal ? "width" : "height"];
1924
- setFooterSize(ctx, size);
1925
- onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1926
- },
1927
- [ctx, horizontal, onLayoutFooter]
1928
- );
1929
- return /* @__PURE__ */ React3.createElement(
1930
- SnapOrScroll,
1931
- {
1932
- ...rest,
1933
- ...ScrollComponent === ListComponentScrollView ? { useWindowScroll } : {},
1934
- contentContainerStyle: [
1935
- horizontal ? {
1936
- height: "100%"
1937
- } : {},
1938
- contentContainerStyle
1939
- ],
1940
- contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1941
- horizontal,
1942
- maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
1943
- onLayout,
1944
- onScroll: onScroll2,
1945
- ref: refScrollView,
1946
- ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1947
- style: autoOtherAxisStyle ? [autoOtherAxisStyle, style] : style
1948
- },
1949
- /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
1950
- ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1951
- ListEmptyComponent && getComponent(ListEmptyComponent),
1952
- alignItemsAtEndPadding > 0 && /* @__PURE__ */ React3.createElement(
1953
- View,
1954
- {
1955
- style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
1956
- },
1957
- null
1958
- ),
1959
- canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
1960
- Containers,
1961
- {
1962
- getRenderedItem: getRenderedItem2,
1963
- horizontal,
1964
- ItemSeparatorComponent,
1965
- recycleItems,
1966
- stickyHeaderConfig,
1967
- updateItemSize: updateItemSize2
1968
- }
1969
- ),
1970
- ListFooterComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
1971
- /* @__PURE__ */ React3.createElement(WebAnchoredEndSpace, { horizontal }),
1972
- IS_DEV && ENABLE_DEVMODE
1973
- );
1974
- });
1975
- var WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH = 100;
1976
- var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
1977
- var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
1978
- function useDevChecksImpl(props) {
1979
- const ctx = useStateContext();
1980
- const { childrenMode, keyExtractor, renderScrollComponent, useWindowScroll } = props;
1981
- useEffect(() => {
1982
- if (useWindowScroll && renderScrollComponent) {
1983
- warnDevOnce(
1984
- "useWindowScrollRenderScrollComponent",
1985
- "useWindowScroll is not supported when renderScrollComponent is provided."
1986
- );
1987
- }
1988
- }, [renderScrollComponent, useWindowScroll]);
1989
- useEffect(() => {
1990
- if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
1991
- warnDevOnce(
1992
- "keyExtractor",
1993
- "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."
1994
- );
1995
- }
1996
- }, [childrenMode, ctx, keyExtractor]);
1997
- useEffect(() => {
1998
- const state = ctx.state;
1999
- const dataLength = state.props.data.length;
2000
- const useWindowScrollResolved = state.props.useWindowScroll;
2001
- if (useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
2002
- return;
2003
- }
2004
- const warnIfUnboundedOuterSize = () => {
2005
- const readyToRender = peek$(ctx, "readyToRender");
2006
- const numContainers = peek$(ctx, "numContainers") || 0;
2007
- const totalSize = peek$(ctx, "totalSize") || 0;
2008
- const scrollLength = ctx.state.scrollLength || 0;
2009
- if (!readyToRender || totalSize <= 0 || scrollLength <= 0) {
2010
- return;
2011
- }
2012
- const rendersAlmostEverything = numContainers >= Math.ceil(dataLength * WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO);
2013
- const viewportMatchesContent = scrollLength >= totalSize * WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO;
2014
- if (rendersAlmostEverything && viewportMatchesContent) {
2015
- warnDevOnce(
2016
- "webUnboundedOuterSize",
2017
- "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."
2018
- );
2019
- }
2020
- };
2021
- warnIfUnboundedOuterSize();
2022
- const unsubscribe = [
2023
- listen$(ctx, "numContainers", warnIfUnboundedOuterSize),
2024
- listen$(ctx, "readyToRender", warnIfUnboundedOuterSize),
2025
- listen$(ctx, "totalSize", warnIfUnboundedOuterSize)
2026
- ];
2027
- return () => {
2028
- for (const unsub of unsubscribe) {
2029
- unsub();
2030
- }
2031
- };
2032
- }, [ctx]);
2033
- }
2034
- function useDevChecksNoop(_props) {
2035
- }
2036
- var useDevChecks = IS_DEV ? useDevChecksImpl : useDevChecksNoop;
2037
-
2038
- // src/core/deferredPublicOnScroll.ts
2039
- function withResolvedContentOffset(state, event, resolvedOffset) {
2040
- return {
2041
- ...event,
2042
- nativeEvent: {
2043
- ...event.nativeEvent,
2044
- contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
2045
- }
2046
- };
2047
- }
2048
- function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
2049
- var _a3, _b, _c, _d;
2050
- const state = ctx.state;
2051
- const deferredEvent = state.deferredPublicOnScrollEvent;
2052
- state.deferredPublicOnScrollEvent = void 0;
2053
- if (deferredEvent) {
2054
- (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
2055
- _c,
2056
- withResolvedContentOffset(
2057
- state,
2058
- deferredEvent,
2059
- (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
2060
- )
2061
- );
2062
- }
2063
- }
2064
-
2065
- // src/core/initialScrollSession.ts
2066
- var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
2067
- function hasInitialScrollSessionCompletion(completion) {
2068
- return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
2069
- }
2070
- function clearInitialScrollSession(state) {
2071
- state.initialScrollSession = void 0;
2072
- return void 0;
2073
- }
2074
- function createInitialScrollSession(options) {
2075
- const { bootstrap, completion, kind, previousDataLength } = options;
2076
- return kind === "offset" ? {
2077
- completion,
2078
- kind,
2079
- previousDataLength
2080
- } : {
2081
- bootstrap,
2082
- completion,
2083
- kind,
2084
- previousDataLength
2085
- };
2086
- }
2087
- function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
2088
- var _a4, _b2;
2089
- if (!state.initialScrollSession) {
2090
- state.initialScrollSession = createInitialScrollSession({
2091
- completion: {},
2092
- kind,
2093
- previousDataLength: 0
2094
- });
2095
- } else if (state.initialScrollSession.kind !== kind) {
2096
- state.initialScrollSession = createInitialScrollSession({
2097
- bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
2098
- completion: state.initialScrollSession.completion,
2099
- kind,
2100
- previousDataLength: state.initialScrollSession.previousDataLength
2101
- });
2102
- }
2103
- (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
2104
- return state.initialScrollSession.completion;
2105
- }
2106
- var initialScrollCompletion = {
2107
- didDispatchNativeScroll(state) {
2108
- var _a3, _b;
2109
- return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
2110
- },
2111
- didRetrySilentInitialScroll(state) {
2112
- var _a3, _b;
2113
- return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
2114
- },
2115
- markInitialScrollNativeDispatch(state) {
2116
- ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
2117
- },
2118
- markSilentInitialScrollRetry(state) {
2119
- ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
2120
- },
2121
- resetFlags(state) {
2122
- if (!state.initialScrollSession) {
2123
- return;
1994
+ function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
1995
+ var _a4, _b2;
1996
+ if (!state.initialScrollSession) {
1997
+ state.initialScrollSession = createInitialScrollSession({
1998
+ completion: {},
1999
+ kind,
2000
+ previousDataLength: 0
2001
+ });
2002
+ } else if (state.initialScrollSession.kind !== kind) {
2003
+ state.initialScrollSession = createInitialScrollSession({
2004
+ bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
2005
+ completion: state.initialScrollSession.completion,
2006
+ kind,
2007
+ previousDataLength: state.initialScrollSession.previousDataLength
2008
+ });
2009
+ }
2010
+ (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
2011
+ return state.initialScrollSession.completion;
2012
+ }
2013
+ var initialScrollCompletion = {
2014
+ didDispatchNativeScroll(state) {
2015
+ var _a3, _b;
2016
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
2017
+ },
2018
+ didRetrySilentInitialScroll(state) {
2019
+ var _a3, _b;
2020
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
2021
+ },
2022
+ markInitialScrollNativeDispatch(state) {
2023
+ ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
2024
+ },
2025
+ markSilentInitialScrollRetry(state) {
2026
+ ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
2027
+ },
2028
+ resetFlags(state) {
2029
+ if (!state.initialScrollSession) {
2030
+ return;
2124
2031
  }
2125
2032
  const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
2126
2033
  completion.didDispatchNativeScroll = void 0;
@@ -2346,6 +2253,66 @@ function recalculateSettledScroll(ctx) {
2346
2253
  checkThresholds(ctx);
2347
2254
  }
2348
2255
 
2256
+ // src/core/adaptiveRender.ts
2257
+ var DEFAULT_ENTER_VELOCITY = 4;
2258
+ var DEFAULT_EXIT_VELOCITY = 1;
2259
+ var DEFAULT_EXIT_DELAY = 1e3;
2260
+ function scheduleAdaptiveRenderExit(ctx, exitDelay) {
2261
+ const state = ctx.state;
2262
+ const previousTimeout = state.timeoutAdaptiveRender;
2263
+ if (previousTimeout !== void 0) {
2264
+ clearTimeout(previousTimeout);
2265
+ state.timeouts.delete(previousTimeout);
2266
+ state.timeoutAdaptiveRender = void 0;
2267
+ }
2268
+ if (exitDelay <= 0) {
2269
+ setAdaptiveRender(ctx, "normal");
2270
+ } else {
2271
+ const timeout = setTimeout(() => {
2272
+ state.timeouts.delete(timeout);
2273
+ state.timeoutAdaptiveRender = void 0;
2274
+ setAdaptiveRender(ctx, "normal");
2275
+ }, exitDelay);
2276
+ state.timeoutAdaptiveRender = timeout;
2277
+ state.timeouts.add(timeout);
2278
+ }
2279
+ }
2280
+ function setAdaptiveRender(ctx, mode) {
2281
+ var _a3, _b;
2282
+ const previousMode = peek$(ctx, "adaptiveRender");
2283
+ if (previousMode !== mode) {
2284
+ set$(ctx, "adaptiveRender", mode);
2285
+ (_b = (_a3 = ctx.state.props.adaptiveRender) == null ? void 0 : _a3.onChange) == null ? void 0 : _b.call(_a3, mode);
2286
+ }
2287
+ }
2288
+ function updateAdaptiveRender(ctx, scrollVelocity) {
2289
+ var _a3, _b, _c;
2290
+ const state = ctx.state;
2291
+ const adaptiveRender = state.props.adaptiveRender;
2292
+ const enterVelocity = (_a3 = adaptiveRender == null ? void 0 : adaptiveRender.enterVelocity) != null ? _a3 : DEFAULT_ENTER_VELOCITY;
2293
+ const exitVelocity = (_b = adaptiveRender == null ? void 0 : adaptiveRender.exitVelocity) != null ? _b : DEFAULT_EXIT_VELOCITY;
2294
+ const exitDelay = (_c = adaptiveRender == null ? void 0 : adaptiveRender.exitDelay) != null ? _c : DEFAULT_EXIT_DELAY;
2295
+ const currentMode = peek$(ctx, "adaptiveRender");
2296
+ const threshold = currentMode === "light" ? exitVelocity : enterVelocity;
2297
+ const nextMode = Math.abs(scrollVelocity) > threshold ? "light" : "normal";
2298
+ const previousMode = state.timeoutAdaptiveRender !== void 0 ? "normal" : currentMode;
2299
+ if (nextMode !== previousMode) {
2300
+ if (nextMode === "light") {
2301
+ setAdaptiveRender(ctx, "light");
2302
+ scheduleAdaptiveRenderExit(ctx, exitDelay);
2303
+ } else if (currentMode === "light") {
2304
+ scheduleAdaptiveRenderExit(ctx, exitDelay);
2305
+ }
2306
+ }
2307
+ }
2308
+
2309
+ // src/utils/getEffectiveDrawDistance.ts
2310
+ var INITIAL_DRAW_DISTANCE = 100;
2311
+ function getEffectiveDrawDistance(ctx) {
2312
+ const drawDistance = ctx.state.props.drawDistance;
2313
+ return peek$(ctx, "readyToRender") ? drawDistance : Math.min(drawDistance, INITIAL_DRAW_DISTANCE);
2314
+ }
2315
+
2349
2316
  // src/utils/setInitialRenderState.ts
2350
2317
  function setInitialRenderState(ctx, {
2351
2318
  didLayout,
@@ -2365,6 +2332,13 @@ function setInitialRenderState(ctx, {
2365
2332
  const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
2366
2333
  if (isReadyToRender && !peek$(ctx, "readyToRender")) {
2367
2334
  set$(ctx, "readyToRender", true);
2335
+ setAdaptiveRender(ctx, "normal");
2336
+ if (state.props.drawDistance > INITIAL_DRAW_DISTANCE) {
2337
+ requestAnimationFrame(() => {
2338
+ var _a3;
2339
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
2340
+ });
2341
+ }
2368
2342
  if (onLoad) {
2369
2343
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2370
2344
  }
@@ -2439,10 +2413,420 @@ function finishInitialScroll(ctx, options) {
2439
2413
  complete();
2440
2414
  }
2441
2415
 
2442
- // src/core/calculateOffsetForIndex.ts
2443
- function calculateOffsetForIndex(ctx, index) {
2416
+ // src/core/finishScrollTo.ts
2417
+ function finishScrollTo(ctx) {
2418
+ var _a3, _b;
2444
2419
  const state = ctx.state;
2445
- return index !== void 0 ? state.positions[index] || 0 : 0;
2420
+ if (state == null ? void 0 : state.scrollingTo) {
2421
+ const resolvePendingScroll = state.pendingScrollResolve;
2422
+ state.pendingScrollResolve = void 0;
2423
+ const scrollingTo = state.scrollingTo;
2424
+ state.scrollHistory.length = 0;
2425
+ state.scrollingTo = void 0;
2426
+ if (state.pendingTotalSize !== void 0) {
2427
+ addTotalSize(ctx, null, state.pendingTotalSize);
2428
+ }
2429
+ {
2430
+ state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
2431
+ }
2432
+ if (scrollingTo.isInitialScroll || state.initialScroll) {
2433
+ const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
2434
+ const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
2435
+ finishInitialScroll(ctx, {
2436
+ onFinished: () => {
2437
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2438
+ },
2439
+ preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
2440
+ recalculateItems: true,
2441
+ schedulePreservedTargetClear: shouldPreserveResizeTarget,
2442
+ syncObservedOffset: isOffsetSession,
2443
+ waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
2444
+ });
2445
+ return;
2446
+ }
2447
+ recalculateSettledScroll(ctx);
2448
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2449
+ }
2450
+ }
2451
+
2452
+ // src/core/doScrollTo.ts
2453
+ var SCROLL_END_IDLE_MS = 80;
2454
+ var SCROLL_END_MAX_MS = 1500;
2455
+ var SMOOTH_SCROLL_DURATION_MS = 320;
2456
+ var SCROLL_END_TARGET_EPSILON = 1;
2457
+ function doScrollTo(ctx, params) {
2458
+ var _a3, _b;
2459
+ const state = ctx.state;
2460
+ const { animated, horizontal, offset } = params;
2461
+ const scroller = state.refScroller.current;
2462
+ const node = scroller == null ? void 0 : scroller.getScrollableNode();
2463
+ if (!scroller || !node) {
2464
+ return;
2465
+ }
2466
+ const isAnimated = !!animated;
2467
+ const isHorizontal = !!horizontal;
2468
+ const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
2469
+ const left = isHorizontal ? toNativeHorizontalOffset(state, offset, contentSize) : 0;
2470
+ const top = isHorizontal ? 0 : offset;
2471
+ scroller.scrollTo({ animated: isAnimated, x: left, y: top });
2472
+ if (isAnimated) {
2473
+ const target = (_b = (_a3 = scroller.getScrollEventTarget) == null ? void 0 : _a3.call(scroller)) != null ? _b : null;
2474
+ listenForScrollEnd(ctx, {
2475
+ readOffset: () => scroller.getCurrentScrollOffset(),
2476
+ target,
2477
+ targetOffset: offset
2478
+ });
2479
+ } else {
2480
+ state.scroll = offset;
2481
+ setTimeout(() => {
2482
+ finishScrollTo(ctx);
2483
+ }, 100);
2484
+ }
2485
+ }
2486
+ function listenForScrollEnd(ctx, params) {
2487
+ const { readOffset, target, targetOffset } = params;
2488
+ if (!target) {
2489
+ finishScrollTo(ctx);
2490
+ return;
2491
+ }
2492
+ const supportsScrollEnd = "onscrollend" in target;
2493
+ let idleTimeout;
2494
+ let settled = false;
2495
+ const targetToken = ctx.state.scrollingTo;
2496
+ const maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
2497
+ const cleanup = () => {
2498
+ target.removeEventListener("scroll", onScroll2);
2499
+ if (supportsScrollEnd) {
2500
+ target.removeEventListener("scrollend", onScrollEnd);
2501
+ }
2502
+ if (idleTimeout) {
2503
+ clearTimeout(idleTimeout);
2504
+ }
2505
+ clearTimeout(maxTimeout);
2506
+ };
2507
+ const finish = (reason) => {
2508
+ if (settled) return;
2509
+ if (targetToken !== ctx.state.scrollingTo) {
2510
+ settled = true;
2511
+ cleanup();
2512
+ return;
2513
+ }
2514
+ const currentOffset = readOffset();
2515
+ const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
2516
+ if (reason === "scrollend" && !isNearTarget) {
2517
+ return;
2518
+ }
2519
+ settled = true;
2520
+ cleanup();
2521
+ finishScrollTo(ctx);
2522
+ };
2523
+ const onScroll2 = () => {
2524
+ if (idleTimeout) {
2525
+ clearTimeout(idleTimeout);
2526
+ }
2527
+ idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
2528
+ };
2529
+ const onScrollEnd = () => finish("scrollend");
2530
+ target.addEventListener("scroll", onScroll2);
2531
+ if (supportsScrollEnd) {
2532
+ target.addEventListener("scrollend", onScrollEnd);
2533
+ } else {
2534
+ idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
2535
+ }
2536
+ }
2537
+
2538
+ // src/utils/requestAdjust.ts
2539
+ function requestAdjust(ctx, positionDiff, dataChanged) {
2540
+ const state = ctx.state;
2541
+ if (Math.abs(positionDiff) > 0.1) {
2542
+ const doit = () => {
2543
+ {
2544
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
2545
+ if (state.adjustingFromInitialMount) {
2546
+ state.adjustingFromInitialMount--;
2547
+ }
2548
+ }
2549
+ };
2550
+ state.scroll += positionDiff;
2551
+ state.scrollForNextCalculateItemsInView = void 0;
2552
+ const readyToRender = peek$(ctx, "readyToRender");
2553
+ if (readyToRender) {
2554
+ doit();
2555
+ } else {
2556
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2557
+ requestAnimationFrame(doit);
2558
+ }
2559
+ }
2560
+ }
2561
+
2562
+ // src/core/updateContentMetrics.ts
2563
+ var SCROLL_ADJUST_EPSILON = 0.1;
2564
+ function setContentLengthSignal(ctx, signalName, size) {
2565
+ const didChange = peek$(ctx, signalName) !== size;
2566
+ if (didChange) {
2567
+ set$(ctx, signalName, size);
2568
+ updateContentMetricsState(ctx);
2569
+ }
2570
+ return didChange;
2571
+ }
2572
+ function shouldAdjustForHeaderSizeChange(ctx, previousHeaderSize, nextHeaderSize) {
2573
+ const { didContainersLayout, didFinishInitialScroll, props, scroll, scrollingTo } = ctx.state;
2574
+ const sizeDiff = nextHeaderSize - previousHeaderSize;
2575
+ const leadingPadding = props.horizontal ? props.stylePaddingLeft : props.stylePaddingTop;
2576
+ const previousHeaderEnd = (leadingPadding || 0) + previousHeaderSize;
2577
+ return props.maintainVisibleContentPosition.size && didContainersLayout && didFinishInitialScroll && !scrollingTo && scroll >= previousHeaderEnd - SCROLL_ADJUST_EPSILON && Math.abs(sizeDiff) > SCROLL_ADJUST_EPSILON;
2578
+ }
2579
+ function setHeaderSize(ctx, size) {
2580
+ const { state } = ctx;
2581
+ const previousHeaderSize = peek$(ctx, "headerSize") || 0;
2582
+ const didChange = previousHeaderSize !== size;
2583
+ const hasMeasuredOrEstimatedHeaderBaseline = state.didMeasureHeader || previousHeaderSize > SCROLL_ADJUST_EPSILON;
2584
+ if (didChange) {
2585
+ set$(ctx, "headerSize", size);
2586
+ updateContentMetricsState(ctx);
2587
+ if (hasMeasuredOrEstimatedHeaderBaseline && shouldAdjustForHeaderSizeChange(ctx, previousHeaderSize, size)) {
2588
+ requestAdjust(ctx, size - previousHeaderSize);
2589
+ }
2590
+ }
2591
+ state.didMeasureHeader = true;
2592
+ }
2593
+ function setFooterSize(ctx, size) {
2594
+ return setContentLengthSignal(ctx, "footerSize", size);
2595
+ }
2596
+ function areInsetsEqual(left, right) {
2597
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
2598
+ 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);
2599
+ }
2600
+ function setContentInsetOverride(ctx, inset) {
2601
+ const { state } = ctx;
2602
+ const previousInset = state.contentInsetOverride;
2603
+ const nextInset = inset != null ? inset : void 0;
2604
+ const didChange = !areInsetsEqual(previousInset, nextInset);
2605
+ state.contentInsetOverride = nextInset;
2606
+ if (didChange) {
2607
+ updateContentMetricsState(ctx);
2608
+ }
2609
+ return didChange;
2610
+ }
2611
+ function useStableRenderComponent(renderComponent, mapProps) {
2612
+ const renderComponentRef = useLatestRef(renderComponent);
2613
+ const mapPropsRef = useLatestRef(mapProps);
2614
+ return React3.useMemo(
2615
+ () => React3.forwardRef(
2616
+ (props, ref) => {
2617
+ var _a3, _b;
2618
+ return (_b = (_a3 = renderComponentRef.current) == null ? void 0 : _a3.call(renderComponentRef, mapPropsRef.current(props, ref))) != null ? _b : null;
2619
+ }
2620
+ ),
2621
+ [mapPropsRef, renderComponentRef]
2622
+ );
2623
+ }
2624
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
2625
+ const localRef = useRef(null);
2626
+ const ref = refView != null ? refView : localRef;
2627
+ useOnLayoutSync({ onLayoutChange, ref });
2628
+ return /* @__PURE__ */ React3.createElement("div", { ...rest, ref }, children);
2629
+ };
2630
+
2631
+ // src/components/ListComponent.tsx
2632
+ var AlignItemsAtEndSpacer = typedMemo(function AlignItemsAtEndSpacer2({ horizontal }) {
2633
+ const [alignItemsAtEndPadding = 0] = useArr$(["alignItemsAtEndPadding"]);
2634
+ if (alignItemsAtEndPadding <= 0) {
2635
+ return null;
2636
+ }
2637
+ return /* @__PURE__ */ React3.createElement(
2638
+ View,
2639
+ {
2640
+ style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
2641
+ },
2642
+ null
2643
+ );
2644
+ });
2645
+ var ListComponent = typedMemo(function ListComponent2({
2646
+ canRender,
2647
+ style,
2648
+ contentContainerStyle,
2649
+ horizontal,
2650
+ initialContentOffset,
2651
+ recycleItems,
2652
+ ItemSeparatorComponent,
2653
+ alignItemsAtEnd: _alignItemsAtEnd,
2654
+ onScroll: onScroll2,
2655
+ onLayout,
2656
+ ListHeaderComponent,
2657
+ ListHeaderComponentStyle,
2658
+ ListFooterComponent,
2659
+ ListFooterComponentStyle,
2660
+ ListEmptyComponent,
2661
+ getRenderedItem: getRenderedItem2,
2662
+ updateItemSize: updateItemSize2,
2663
+ refScrollView,
2664
+ renderScrollComponent,
2665
+ onLayoutFooter,
2666
+ scrollAdjustHandler,
2667
+ snapToIndices,
2668
+ stickyHeaderConfig,
2669
+ stickyHeaderIndices,
2670
+ useWindowScroll = false,
2671
+ ...rest
2672
+ }) {
2673
+ const ctx = useStateContext();
2674
+ const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
2675
+ const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
2676
+ const shouldRenderAlignItemsAtEndSpacer = ctx.state.props.alignItemsAtEndPaddingEnabled;
2677
+ const autoOtherAxisStyle = getAutoOtherAxisStyle({
2678
+ horizontal,
2679
+ needsOtherAxisSize: ctx.state.needsOtherAxisSize,
2680
+ otherAxisSize
2681
+ });
2682
+ const CustomScrollComponent = useStableRenderComponent(
2683
+ renderScrollComponent,
2684
+ (props, ref) => ({ ...props, ref })
2685
+ );
2686
+ const ScrollComponent = renderScrollComponent ? CustomScrollComponent : ListComponentScrollView;
2687
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
2688
+ const updateFooterSize = useCallback(
2689
+ (size, afterSizeUpdate) => {
2690
+ var _a3;
2691
+ const didFooterSizeChange = setFooterSize(ctx, size);
2692
+ afterSizeUpdate == null ? void 0 : afterSizeUpdate();
2693
+ if (didFooterSizeChange && ((_a3 = ctx.state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onFooterLayout)) {
2694
+ doMaintainScrollAtEnd(ctx);
2695
+ }
2696
+ },
2697
+ [ctx]
2698
+ );
2699
+ useLayoutEffect(() => {
2700
+ if (!ListHeaderComponent) {
2701
+ setHeaderSize(ctx, 0);
2702
+ }
2703
+ if (!ListFooterComponent) {
2704
+ updateFooterSize(0);
2705
+ }
2706
+ }, [ListHeaderComponent, ListFooterComponent, ctx, updateFooterSize]);
2707
+ const onLayoutHeader = useCallback(
2708
+ (rect) => {
2709
+ const size = rect[horizontal ? "width" : "height"];
2710
+ setHeaderSize(ctx, size);
2711
+ },
2712
+ [ctx, horizontal]
2713
+ );
2714
+ const onLayoutFooterInternal = useCallback(
2715
+ (rect, fromLayoutEffect) => {
2716
+ const size = rect[horizontal ? "width" : "height"];
2717
+ updateFooterSize(size, () => {
2718
+ onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
2719
+ });
2720
+ },
2721
+ [horizontal, onLayoutFooter, updateFooterSize]
2722
+ );
2723
+ return /* @__PURE__ */ React3.createElement(
2724
+ SnapOrScroll,
2725
+ {
2726
+ ...rest,
2727
+ ...ScrollComponent === ListComponentScrollView ? { useWindowScroll } : {},
2728
+ contentContainerStyle: [
2729
+ horizontal ? {
2730
+ height: "100%"
2731
+ } : {},
2732
+ contentContainerStyle
2733
+ ],
2734
+ contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
2735
+ horizontal,
2736
+ maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
2737
+ onLayout,
2738
+ onScroll: onScroll2,
2739
+ ref: refScrollView,
2740
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
2741
+ style: autoOtherAxisStyle ? [autoOtherAxisStyle, style] : style
2742
+ },
2743
+ /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
2744
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
2745
+ ListEmptyComponent && getComponent(ListEmptyComponent),
2746
+ shouldRenderAlignItemsAtEndSpacer && /* @__PURE__ */ React3.createElement(AlignItemsAtEndSpacer, { horizontal }),
2747
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
2748
+ Containers,
2749
+ {
2750
+ getRenderedItem: getRenderedItem2,
2751
+ horizontal,
2752
+ ItemSeparatorComponent,
2753
+ recycleItems,
2754
+ stickyHeaderConfig,
2755
+ updateItemSize: updateItemSize2
2756
+ }
2757
+ ),
2758
+ ListFooterComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
2759
+ /* @__PURE__ */ React3.createElement(WebAnchoredEndSpace, { horizontal }),
2760
+ IS_DEV && ENABLE_DEVMODE
2761
+ );
2762
+ });
2763
+ var WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH = 100;
2764
+ var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
2765
+ var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
2766
+ function useDevChecksImpl(props) {
2767
+ const ctx = useStateContext();
2768
+ const { childrenMode, keyExtractor, renderScrollComponent, useWindowScroll } = props;
2769
+ useEffect(() => {
2770
+ if (useWindowScroll && renderScrollComponent) {
2771
+ warnDevOnce(
2772
+ "useWindowScrollRenderScrollComponent",
2773
+ "useWindowScroll is not supported when renderScrollComponent is provided."
2774
+ );
2775
+ }
2776
+ }, [renderScrollComponent, useWindowScroll]);
2777
+ useEffect(() => {
2778
+ if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
2779
+ warnDevOnce(
2780
+ "keyExtractor",
2781
+ "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."
2782
+ );
2783
+ }
2784
+ }, [childrenMode, ctx, keyExtractor]);
2785
+ useEffect(() => {
2786
+ const state = ctx.state;
2787
+ const dataLength = state.props.data.length;
2788
+ const useWindowScrollResolved = state.props.useWindowScroll;
2789
+ if (useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
2790
+ return;
2791
+ }
2792
+ const warnIfUnboundedOuterSize = () => {
2793
+ const readyToRender = peek$(ctx, "readyToRender");
2794
+ const numContainers = peek$(ctx, "numContainers") || 0;
2795
+ const totalSize = peek$(ctx, "totalSize") || 0;
2796
+ const scrollLength = ctx.state.scrollLength || 0;
2797
+ if (!readyToRender || totalSize <= 0 || scrollLength <= 0) {
2798
+ return;
2799
+ }
2800
+ const rendersAlmostEverything = numContainers >= Math.ceil(dataLength * WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO);
2801
+ const viewportMatchesContent = scrollLength >= totalSize * WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO;
2802
+ if (rendersAlmostEverything && viewportMatchesContent) {
2803
+ warnDevOnce(
2804
+ "webUnboundedOuterSize",
2805
+ "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."
2806
+ );
2807
+ }
2808
+ };
2809
+ warnIfUnboundedOuterSize();
2810
+ const unsubscribe = [
2811
+ listen$(ctx, "numContainers", warnIfUnboundedOuterSize),
2812
+ listen$(ctx, "readyToRender", warnIfUnboundedOuterSize),
2813
+ listen$(ctx, "totalSize", warnIfUnboundedOuterSize)
2814
+ ];
2815
+ return () => {
2816
+ for (const unsub of unsubscribe) {
2817
+ unsub();
2818
+ }
2819
+ };
2820
+ }, [ctx]);
2821
+ }
2822
+ function useDevChecksNoop(_props) {
2823
+ }
2824
+ var useDevChecks = IS_DEV ? useDevChecksImpl : useDevChecksNoop;
2825
+
2826
+ // src/core/calculateOffsetForIndex.ts
2827
+ function calculateOffsetForIndex(ctx, index) {
2828
+ const state = ctx.state;
2829
+ return index !== void 0 ? state.positions[index] || 0 : 0;
2446
2830
  }
2447
2831
 
2448
2832
  // src/core/getTopOffsetAdjustment.ts
@@ -2462,34 +2846,6 @@ function getId(state, index) {
2462
2846
  return id;
2463
2847
  }
2464
2848
 
2465
- // src/core/addTotalSize.ts
2466
- function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2467
- const state = ctx.state;
2468
- const prevTotalSize = state.totalSize;
2469
- let totalSize = state.totalSize;
2470
- if (key === null) {
2471
- totalSize = add;
2472
- if (state.timeoutSetPaddingTop) {
2473
- clearTimeout(state.timeoutSetPaddingTop);
2474
- state.timeoutSetPaddingTop = void 0;
2475
- }
2476
- } else {
2477
- totalSize += add;
2478
- }
2479
- if (prevTotalSize !== totalSize) {
2480
- {
2481
- state.pendingTotalSize = void 0;
2482
- state.totalSize = totalSize;
2483
- if (notifyTotalSize) {
2484
- set$(ctx, "totalSize", totalSize);
2485
- }
2486
- updateContentMetrics(ctx);
2487
- }
2488
- } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2489
- set$(ctx, "totalSize", totalSize);
2490
- }
2491
- }
2492
-
2493
2849
  // src/core/setSize.ts
2494
2850
  function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2495
2851
  const state = ctx.state;
@@ -2510,8 +2866,9 @@ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
2510
2866
  let size = key ? state.sizesKnown.get(key) : void 0;
2511
2867
  if (size === void 0 && key && getFixedItemSize) {
2512
2868
  const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2513
- size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
2514
- if (size !== void 0) {
2869
+ const fixedSize = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
2870
+ if (fixedSize !== void 0) {
2871
+ size = fixedSize + ctx.scrollAxisGap;
2515
2872
  state.sizesKnown.set(key, size);
2516
2873
  }
2517
2874
  }
@@ -2558,281 +2915,79 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2558
2915
  if (useAverageSize && !scrollingTo) {
2559
2916
  const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
2560
2917
  if (averageSizeForType !== void 0) {
2561
- size = roundSize(averageSizeForType);
2562
- }
2563
- }
2564
- if (size === void 0 && renderedSize !== void 0) {
2565
- return renderedSize;
2566
- }
2567
- if (size === void 0 && useAverageSize && scrollingTo) {
2568
- const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
2569
- if (averageSizeForType !== void 0) {
2570
- size = roundSize(averageSizeForType);
2571
- }
2572
- }
2573
- if (size === void 0) {
2574
- size = estimatedItemSize;
2575
- }
2576
- setSize(ctx, key, size, notifyTotalSize);
2577
- return size;
2578
- }
2579
- function getItemSizeAtIndex(ctx, index) {
2580
- if (index === void 0 || index < 0) {
2581
- return void 0;
2582
- }
2583
- const targetId = getId(ctx.state, index);
2584
- return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
2585
- }
2586
-
2587
- // src/core/calculateOffsetWithOffsetPosition.ts
2588
- function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
2589
- var _a3;
2590
- const state = ctx.state;
2591
- const { index, viewOffset, viewPosition } = params;
2592
- let offset = offsetParam;
2593
- if (viewOffset) {
2594
- offset -= viewOffset;
2595
- }
2596
- if (index !== void 0) {
2597
- const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
2598
- if (topOffsetAdjustment) {
2599
- offset += topOffsetAdjustment;
2600
- }
2601
- }
2602
- if (viewPosition !== void 0 && index !== void 0) {
2603
- const dataLength = state.props.data.length;
2604
- if (dataLength === 0) {
2605
- return offset;
2606
- }
2607
- const isOutOfBounds = index < 0 || index >= dataLength;
2608
- const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
2609
- const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
2610
- const trailingInset = getContentInsetEnd(ctx);
2611
- offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
2612
- if (!isOutOfBounds && index === state.props.data.length - 1) {
2613
- const footerSize = peek$(ctx, "footerSize") || 0;
2614
- offset += footerSize;
2615
- }
2616
- }
2617
- return offset;
2618
- }
2619
-
2620
- // src/core/clampScrollOffset.ts
2621
- function clampScrollOffset(ctx, offset, scrollTarget) {
2622
- const state = ctx.state;
2623
- const contentSize = getContentSize(ctx);
2624
- let clampedOffset = offset;
2625
- if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
2626
- const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
2627
- const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
2628
- const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
2629
- const maxOffset = baseMaxOffset + extraEndOffset;
2630
- clampedOffset = Math.min(offset, maxOffset);
2631
- }
2632
- clampedOffset = Math.max(0, clampedOffset);
2633
- return clampedOffset;
2634
- }
2635
-
2636
- // src/core/finishScrollTo.ts
2637
- function finishScrollTo(ctx) {
2638
- var _a3, _b;
2639
- const state = ctx.state;
2640
- if (state == null ? void 0 : state.scrollingTo) {
2641
- const resolvePendingScroll = state.pendingScrollResolve;
2642
- state.pendingScrollResolve = void 0;
2643
- const scrollingTo = state.scrollingTo;
2644
- state.scrollHistory.length = 0;
2645
- state.scrollingTo = void 0;
2646
- if (state.pendingTotalSize !== void 0) {
2647
- addTotalSize(ctx, null, state.pendingTotalSize);
2648
- }
2649
- {
2650
- state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
2651
- }
2652
- if (scrollingTo.isInitialScroll || state.initialScroll) {
2653
- const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
2654
- const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
2655
- finishInitialScroll(ctx, {
2656
- onFinished: () => {
2657
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2658
- },
2659
- preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
2660
- recalculateItems: true,
2661
- schedulePreservedTargetClear: shouldPreserveResizeTarget,
2662
- syncObservedOffset: isOffsetSession,
2663
- waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
2664
- });
2665
- return;
2666
- }
2667
- recalculateSettledScroll(ctx);
2668
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
2669
- }
2670
- }
2671
-
2672
- // src/core/doScrollTo.ts
2673
- var SCROLL_END_IDLE_MS = 80;
2674
- var SCROLL_END_MAX_MS = 1500;
2675
- var SMOOTH_SCROLL_DURATION_MS = 320;
2676
- var SCROLL_END_TARGET_EPSILON = 1;
2677
- function doScrollTo(ctx, params) {
2678
- var _a3, _b;
2679
- const state = ctx.state;
2680
- const { animated, horizontal, offset } = params;
2681
- const scroller = state.refScroller.current;
2682
- const node = scroller == null ? void 0 : scroller.getScrollableNode();
2683
- if (!scroller || !node) {
2684
- return;
2685
- }
2686
- const isAnimated = !!animated;
2687
- const isHorizontal = !!horizontal;
2688
- const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
2689
- const left = isHorizontal ? toNativeHorizontalOffset(state, offset, contentSize) : 0;
2690
- const top = isHorizontal ? 0 : offset;
2691
- scroller.scrollTo({ animated: isAnimated, x: left, y: top });
2692
- if (isAnimated) {
2693
- const target = (_b = (_a3 = scroller.getScrollEventTarget) == null ? void 0 : _a3.call(scroller)) != null ? _b : null;
2694
- listenForScrollEnd(ctx, {
2695
- readOffset: () => scroller.getCurrentScrollOffset(),
2696
- target,
2697
- targetOffset: offset
2698
- });
2699
- } else {
2700
- state.scroll = offset;
2701
- setTimeout(() => {
2702
- finishScrollTo(ctx);
2703
- }, 100);
2704
- }
2705
- }
2706
- function listenForScrollEnd(ctx, params) {
2707
- const { readOffset, target, targetOffset } = params;
2708
- if (!target) {
2709
- finishScrollTo(ctx);
2710
- return;
2711
- }
2712
- const supportsScrollEnd = "onscrollend" in target;
2713
- let idleTimeout;
2714
- let settled = false;
2715
- const targetToken = ctx.state.scrollingTo;
2716
- const maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
2717
- const cleanup = () => {
2718
- target.removeEventListener("scroll", onScroll2);
2719
- if (supportsScrollEnd) {
2720
- target.removeEventListener("scrollend", onScrollEnd);
2721
- }
2722
- if (idleTimeout) {
2723
- clearTimeout(idleTimeout);
2724
- }
2725
- clearTimeout(maxTimeout);
2726
- };
2727
- const finish = (reason) => {
2728
- if (settled) return;
2729
- if (targetToken !== ctx.state.scrollingTo) {
2730
- settled = true;
2731
- cleanup();
2732
- return;
2733
- }
2734
- const currentOffset = readOffset();
2735
- const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
2736
- if (reason === "scrollend" && !isNearTarget) {
2737
- return;
2738
- }
2739
- settled = true;
2740
- cleanup();
2741
- finishScrollTo(ctx);
2742
- };
2743
- const onScroll2 = () => {
2744
- if (idleTimeout) {
2745
- clearTimeout(idleTimeout);
2918
+ size = roundSize(averageSizeForType);
2746
2919
  }
2747
- idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
2748
- };
2749
- const onScrollEnd = () => finish("scrollend");
2750
- target.addEventListener("scroll", onScroll2);
2751
- if (supportsScrollEnd) {
2752
- target.addEventListener("scrollend", onScrollEnd);
2753
- } else {
2754
- idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
2755
2920
  }
2921
+ if (size === void 0 && renderedSize !== void 0) {
2922
+ return renderedSize;
2923
+ }
2924
+ if (size === void 0 && useAverageSize && scrollingTo) {
2925
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
2926
+ if (averageSizeForType !== void 0) {
2927
+ size = roundSize(averageSizeForType);
2928
+ }
2929
+ }
2930
+ if (size === void 0) {
2931
+ size = estimatedItemSize + ctx.scrollAxisGap;
2932
+ }
2933
+ setSize(ctx, key, size, notifyTotalSize);
2934
+ return size;
2935
+ }
2936
+ function getItemSizeAtIndex(ctx, index) {
2937
+ if (index === void 0 || index < 0) {
2938
+ return void 0;
2939
+ }
2940
+ const targetId = getId(ctx.state, index);
2941
+ return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
2756
2942
  }
2757
2943
 
2758
- // src/core/doMaintainScrollAtEnd.ts
2759
- function doMaintainScrollAtEnd(ctx) {
2944
+ // src/core/calculateOffsetWithOffsetPosition.ts
2945
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
2946
+ var _a3;
2760
2947
  const state = ctx.state;
2761
- const {
2762
- didContainersLayout,
2763
- pendingNativeMVCPAdjust,
2764
- refScroller,
2765
- props: { maintainScrollAtEnd }
2766
- } = state;
2767
- const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
2768
- const shouldMaintainScrollAtEnd = !!(isWithinMaintainScrollAtEndThreshold && maintainScrollAtEnd && didContainersLayout);
2769
- if (pendingNativeMVCPAdjust) {
2770
- state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
2771
- return false;
2948
+ const { index, viewOffset, viewPosition } = params;
2949
+ let offset = offsetParam;
2950
+ if (viewOffset) {
2951
+ offset -= viewOffset;
2772
2952
  }
2773
- state.pendingMaintainScrollAtEnd = false;
2774
- if (shouldMaintainScrollAtEnd) {
2775
- const contentSize = getContentSize(ctx);
2776
- if (contentSize < state.scrollLength) {
2777
- state.scroll = 0;
2953
+ if (index !== void 0) {
2954
+ const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
2955
+ if (topOffsetAdjustment) {
2956
+ offset += topOffsetAdjustment;
2778
2957
  }
2779
- if (!state.maintainingScrollAtEnd) {
2780
- state.maintainingScrollAtEnd = true;
2781
- requestAnimationFrame(() => {
2782
- if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
2783
- const scroller = refScroller.current;
2784
- if (state.props.horizontal && isHorizontalRTL(state)) {
2785
- const currentContentSize = getContentSize(ctx);
2786
- const logicalEndOffset = getLogicalHorizontalMaxOffset(state, currentContentSize);
2787
- const nativeOffset = toNativeHorizontalOffset(state, logicalEndOffset, currentContentSize);
2788
- scroller == null ? void 0 : scroller.scrollTo({
2789
- animated: maintainScrollAtEnd.animated,
2790
- x: nativeOffset,
2791
- y: 0
2792
- });
2793
- } else {
2794
- scroller == null ? void 0 : scroller.scrollToEnd({
2795
- animated: maintainScrollAtEnd.animated
2796
- });
2797
- }
2798
- setTimeout(
2799
- () => {
2800
- state.maintainingScrollAtEnd = false;
2801
- },
2802
- maintainScrollAtEnd.animated ? 500 : 0
2803
- );
2804
- } else {
2805
- state.maintainingScrollAtEnd = false;
2806
- }
2807
- });
2958
+ }
2959
+ if (viewPosition !== void 0 && index !== void 0) {
2960
+ const dataLength = state.props.data.length;
2961
+ if (dataLength === 0) {
2962
+ return offset;
2963
+ }
2964
+ const isOutOfBounds = index < 0 || index >= dataLength;
2965
+ const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
2966
+ const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
2967
+ const trailingInset = getContentInsetEnd(ctx);
2968
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
2969
+ if (!isOutOfBounds && index === state.props.data.length - 1) {
2970
+ const footerSize = peek$(ctx, "footerSize") || 0;
2971
+ offset += footerSize;
2808
2972
  }
2809
- return true;
2810
2973
  }
2811
- return false;
2974
+ return offset;
2812
2975
  }
2813
2976
 
2814
- // src/utils/requestAdjust.ts
2815
- function requestAdjust(ctx, positionDiff, dataChanged) {
2977
+ // src/core/clampScrollOffset.ts
2978
+ function clampScrollOffset(ctx, offset, scrollTarget) {
2816
2979
  const state = ctx.state;
2817
- if (Math.abs(positionDiff) > 0.1) {
2818
- const doit = () => {
2819
- {
2820
- state.scrollAdjustHandler.requestAdjust(positionDiff);
2821
- if (state.adjustingFromInitialMount) {
2822
- state.adjustingFromInitialMount--;
2823
- }
2824
- }
2825
- };
2826
- state.scroll += positionDiff;
2827
- state.scrollForNextCalculateItemsInView = void 0;
2828
- const readyToRender = peek$(ctx, "readyToRender");
2829
- if (readyToRender) {
2830
- doit();
2831
- } else {
2832
- state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2833
- requestAnimationFrame(doit);
2834
- }
2980
+ const contentSize = getContentSize(ctx);
2981
+ let clampedOffset = offset;
2982
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
2983
+ const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
2984
+ const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
2985
+ const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
2986
+ const maxOffset = baseMaxOffset + extraEndOffset;
2987
+ clampedOffset = Math.min(offset, maxOffset);
2835
2988
  }
2989
+ clampedOffset = Math.max(0, clampedOffset);
2990
+ return clampedOffset;
2836
2991
  }
2837
2992
 
2838
2993
  // src/core/mvcp.ts
@@ -2980,6 +3135,10 @@ function prepareMVCP(ctx, dataChanged) {
2980
3135
  const now = Date.now();
2981
3136
  const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
2982
3137
  const scrollingTo = state.scrollingTo;
3138
+ if (dataChanged && state.pendingScrollToEnd && scrollingTo === void 0) {
3139
+ state.mvcpAnchorLock = void 0;
3140
+ return void 0;
3141
+ }
2983
3142
  const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
2984
3143
  let prevPosition;
2985
3144
  let targetId;
@@ -3108,7 +3267,7 @@ function prepareMVCP(ctx, dataChanged) {
3108
3267
  return;
3109
3268
  }
3110
3269
  if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
3111
- const shouldSkipAdjustForMaintainedEnd = state.maintainingScrollAtEnd && peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
3270
+ const shouldSkipAdjustForMaintainedEnd = (state.maintainingScrollAtEnd === "pending-animated" || state.maintainingScrollAtEnd === "animated") && peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
3112
3271
  if (!shouldSkipAdjustForMaintainedEnd) {
3113
3272
  requestAdjust(ctx, positionDiff);
3114
3273
  }
@@ -3117,6 +3276,45 @@ function prepareMVCP(ctx, dataChanged) {
3117
3276
  }
3118
3277
  }
3119
3278
 
3279
+ // src/utils/getScrollVelocity.ts
3280
+ var getScrollVelocity = (state) => {
3281
+ const { scrollHistory } = state;
3282
+ const newestIndex = scrollHistory.length - 1;
3283
+ if (newestIndex < 1) {
3284
+ return 0;
3285
+ }
3286
+ const newest = scrollHistory[newestIndex];
3287
+ const now = Date.now();
3288
+ let direction = 0;
3289
+ for (let i = newestIndex; i > 0; i--) {
3290
+ const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
3291
+ if (delta !== 0) {
3292
+ direction = Math.sign(delta);
3293
+ break;
3294
+ }
3295
+ }
3296
+ if (direction === 0) {
3297
+ return 0;
3298
+ }
3299
+ let oldest = newest;
3300
+ for (let i = newestIndex - 1; i >= 0; i--) {
3301
+ const current = scrollHistory[i];
3302
+ const next = scrollHistory[i + 1];
3303
+ const delta = next.scroll - current.scroll;
3304
+ const deltaSign = Math.sign(delta);
3305
+ if (deltaSign !== 0 && deltaSign !== direction) {
3306
+ break;
3307
+ }
3308
+ if (now - current.time > 1e3) {
3309
+ break;
3310
+ }
3311
+ oldest = current;
3312
+ }
3313
+ const scrollDiff = newest.scroll - oldest.scroll;
3314
+ const timeDiff = newest.time - oldest.time;
3315
+ return timeDiff > 0 ? scrollDiff / timeDiff : 0;
3316
+ };
3317
+
3120
3318
  // src/core/updateScroll.ts
3121
3319
  function updateScroll(ctx, newScroll, forceUpdate, options) {
3122
3320
  var _a3;
@@ -3142,6 +3340,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3142
3340
  if (scrollHistory.length > 5) {
3143
3341
  scrollHistory.shift();
3144
3342
  }
3343
+ const scrollVelocity = getScrollVelocity(state);
3344
+ updateAdaptiveRender(ctx, scrollVelocity);
3145
3345
  if (ignoreScrollFromMVCP && !scrollingTo) {
3146
3346
  const { lt, gt } = ignoreScrollFromMVCP;
3147
3347
  if (lt && newScroll < lt || gt && newScroll > gt) {
@@ -3165,7 +3365,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
3165
3365
  state.lastScrollDelta = scrollDelta;
3166
3366
  const runCalculateItems = () => {
3167
3367
  var _a4;
3168
- (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
3368
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0, scrollVelocity });
3169
3369
  checkThresholds(ctx);
3170
3370
  };
3171
3371
  if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
@@ -4245,9 +4445,32 @@ function initializeInitialScrollOnMount(ctx, options) {
4245
4445
  }
4246
4446
  function handleInitialScrollDataChange(ctx, options) {
4247
4447
  var _a3, _b, _c;
4248
- const { dataLength, didDataChange, initialScrollAtEnd, stylePaddingBottom, useBootstrapInitialScroll } = options;
4448
+ const {
4449
+ dataLength,
4450
+ didDataChange,
4451
+ initialScrollAtEnd,
4452
+ latestInitialScroll,
4453
+ latestInitialScrollSessionKind,
4454
+ stylePaddingBottom,
4455
+ useBootstrapInitialScroll
4456
+ } = options;
4249
4457
  const state = ctx.state;
4250
4458
  const previousDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
4459
+ const isFirstNonEmptyData = !state.hasHadNonEmptyData && dataLength > 0;
4460
+ if (dataLength > 0) {
4461
+ state.hasHadNonEmptyData = true;
4462
+ }
4463
+ if (isFirstNonEmptyData) {
4464
+ if (latestInitialScroll) {
4465
+ setInitialScrollTarget(state, latestInitialScroll);
4466
+ setInitialScrollSession(state, {
4467
+ kind: latestInitialScrollSessionKind,
4468
+ previousDataLength
4469
+ });
4470
+ } else {
4471
+ clearPreservedInitialScrollTarget(state);
4472
+ }
4473
+ }
4251
4474
  if (state.initialScrollSession) {
4252
4475
  state.initialScrollSession.previousDataLength = dataLength;
4253
4476
  }
@@ -4471,45 +4694,6 @@ function updateTotalSize(ctx) {
4471
4694
  }
4472
4695
  }
4473
4696
 
4474
- // src/utils/getScrollVelocity.ts
4475
- var getScrollVelocity = (state) => {
4476
- const { scrollHistory } = state;
4477
- const newestIndex = scrollHistory.length - 1;
4478
- if (newestIndex < 1) {
4479
- return 0;
4480
- }
4481
- const newest = scrollHistory[newestIndex];
4482
- const now = Date.now();
4483
- let direction = 0;
4484
- for (let i = newestIndex; i > 0; i--) {
4485
- const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
4486
- if (delta !== 0) {
4487
- direction = Math.sign(delta);
4488
- break;
4489
- }
4490
- }
4491
- if (direction === 0) {
4492
- return 0;
4493
- }
4494
- let oldest = newest;
4495
- for (let i = newestIndex - 1; i >= 0; i--) {
4496
- const current = scrollHistory[i];
4497
- const next = scrollHistory[i + 1];
4498
- const delta = next.scroll - current.scroll;
4499
- const deltaSign = Math.sign(delta);
4500
- if (deltaSign !== 0 && deltaSign !== direction) {
4501
- break;
4502
- }
4503
- if (now - current.time > 1e3) {
4504
- break;
4505
- }
4506
- oldest = current;
4507
- }
4508
- const scrollDiff = newest.scroll - oldest.scroll;
4509
- const timeDiff = newest.time - oldest.time;
4510
- return timeDiff > 0 ? scrollDiff / timeDiff : 0;
4511
- };
4512
-
4513
4697
  // src/utils/updateSnapToOffsets.ts
4514
4698
  function updateSnapToOffsets(ctx) {
4515
4699
  const state = ctx.state;
@@ -5245,7 +5429,7 @@ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, sc
5245
5429
  function calculateItemsInView(ctx, params = {}) {
5246
5430
  const state = ctx.state;
5247
5431
  batchedUpdates(() => {
5248
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
5432
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
5249
5433
  const {
5250
5434
  columns,
5251
5435
  containerItemKeys,
@@ -5254,14 +5438,7 @@ function calculateItemsInView(ctx, params = {}) {
5254
5438
  indexByKey,
5255
5439
  minIndexSizeChanged,
5256
5440
  positions,
5257
- props: {
5258
- alwaysRenderIndicesArr,
5259
- alwaysRenderIndicesSet,
5260
- drawDistance,
5261
- getItemType,
5262
- keyExtractor,
5263
- onStickyHeaderChange
5264
- },
5441
+ props: { alwaysRenderIndicesArr, alwaysRenderIndicesSet, getItemType, keyExtractor, onStickyHeaderChange },
5265
5442
  scrollForNextCalculateItemsInView,
5266
5443
  scrollLength,
5267
5444
  sizes,
@@ -5273,6 +5450,7 @@ function calculateItemsInView(ctx, params = {}) {
5273
5450
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
5274
5451
  const alwaysRenderArr = alwaysRenderIndicesArr || [];
5275
5452
  const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
5453
+ const drawDistance = getEffectiveDrawDistance(ctx);
5276
5454
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
5277
5455
  const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
5278
5456
  const suppressInitialScrollSideEffects = !!bootstrapInitialScrollState;
@@ -5283,10 +5461,10 @@ function calculateItemsInView(ctx, params = {}) {
5283
5461
  let totalSize = getContentSize(ctx);
5284
5462
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
5285
5463
  const numColumns = peek$(ctx, "numColumns");
5286
- const speed = getScrollVelocity(state);
5464
+ const speed = (_b = params.scrollVelocity) != null ? _b : getScrollVelocity(state);
5287
5465
  const scrollExtra = 0;
5288
5466
  const { initialScroll, queuedInitialLayout } = state;
5289
- const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && hasActiveInitialScroll(state) && initialScroll ? (
5467
+ const scrollState = suppressInitialScrollSideEffects ? (_c = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _c : state.scroll : !queuedInitialLayout && hasActiveInitialScroll(state) && initialScroll ? (
5290
5468
  // Before the initial layout settles, keep viewport math anchored to the
5291
5469
  // current initial-scroll target instead of transient native adjustments.
5292
5470
  resolveInitialScrollOffset(ctx, initialScroll)
@@ -5310,19 +5488,25 @@ function calculateItemsInView(ctx, params = {}) {
5310
5488
  };
5311
5489
  updateScroll2(scrollState);
5312
5490
  const previousStickyIndex = peek$(ctx, "activeStickyIndex");
5313
- const currentStickyIdx = stickyHeaderIndicesArr.length > 0 ? findCurrentStickyIndex(stickyHeaderIndicesArr, scroll, state) : -1;
5314
- const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyHeaderIndicesArr[currentStickyIdx] : -1;
5315
- const stickyIndexDidChange = previousStickyIndex !== nextActiveStickyIndex;
5316
- if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
5317
- set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
5318
- }
5319
- const shouldNotifyStickyHeaderChange = !!onStickyHeaderChange && stickyHeaderIndicesArr.length > 0 && stickyIndexDidChange;
5320
- const finishCalculateItemsInView = shouldNotifyStickyHeaderChange ? () => {
5321
- const item = data[nextActiveStickyIndex];
5322
- if (item !== void 0) {
5323
- onStickyHeaderChange == null ? void 0 : onStickyHeaderChange({ index: nextActiveStickyIndex, item });
5491
+ const resolveStickyState = () => {
5492
+ const currentStickyIdx = stickyHeaderIndicesArr.length > 0 ? findCurrentStickyIndex(stickyHeaderIndicesArr, scroll, state) : -1;
5493
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyHeaderIndicesArr[currentStickyIdx] : -1;
5494
+ const stickyIndexDidChange = previousStickyIndex !== nextActiveStickyIndex;
5495
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
5496
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
5324
5497
  }
5325
- } : void 0;
5498
+ const shouldNotifyStickyHeaderChange = !!onStickyHeaderChange && stickyHeaderIndicesArr.length > 0 && stickyIndexDidChange;
5499
+ return {
5500
+ currentStickyIdx,
5501
+ finishCalculateItemsInView: shouldNotifyStickyHeaderChange ? () => {
5502
+ const item = data[nextActiveStickyIndex];
5503
+ if (item !== void 0) {
5504
+ onStickyHeaderChange == null ? void 0 : onStickyHeaderChange({ index: nextActiveStickyIndex, item });
5505
+ }
5506
+ } : void 0
5507
+ };
5508
+ };
5509
+ let stickyState = dataChanged ? void 0 : resolveStickyState();
5326
5510
  let scrollBufferTop = drawDistance;
5327
5511
  let scrollBufferBottom = drawDistance;
5328
5512
  if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
@@ -5355,7 +5539,7 @@ function calculateItemsInView(ctx, params = {}) {
5355
5539
  scrollBottom
5356
5540
  );
5357
5541
  }
5358
- finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
5542
+ (_d = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _d.call(stickyState);
5359
5543
  return;
5360
5544
  }
5361
5545
  }
@@ -5364,7 +5548,7 @@ function calculateItemsInView(ctx, params = {}) {
5364
5548
  if (dataChanged) {
5365
5549
  resetLayoutCachesForDataChange(state);
5366
5550
  }
5367
- const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
5551
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_e = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _e : 0;
5368
5552
  const optimizeForVisibleWindow = !forceFullItemPositions && !dataChanged && numColumns > 1 && minIndexSizeChanged !== void 0;
5369
5553
  updateItemPositions(ctx, dataChanged, {
5370
5554
  doMVCP,
@@ -5390,21 +5574,24 @@ function calculateItemsInView(ctx, params = {}) {
5390
5574
  }
5391
5575
  }
5392
5576
  const scrollBeforeMVCP = state.scroll;
5393
- const scrollAdjustPendingBeforeMVCP = (_d = peek$(ctx, "scrollAdjustPending")) != null ? _d : 0;
5577
+ const scrollAdjustPendingBeforeMVCP = (_f = peek$(ctx, "scrollAdjustPending")) != null ? _f : 0;
5394
5578
  checkMVCP == null ? void 0 : checkMVCP();
5395
- const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_e = peek$(ctx, "scrollAdjustPending")) != null ? _e : 0) !== scrollAdjustPendingBeforeMVCP);
5579
+ const didMVCPAdjustScroll = !!checkMVCP && (state.scroll !== scrollBeforeMVCP || ((_g = peek$(ctx, "scrollAdjustPending")) != null ? _g : 0) !== scrollAdjustPendingBeforeMVCP);
5396
5580
  if (didMVCPAdjustScroll && initialScroll) {
5397
5581
  updateScroll2(state.scroll);
5398
5582
  updateScrollRange();
5399
5583
  }
5584
+ if (dataChanged) {
5585
+ stickyState = resolveStickyState();
5586
+ }
5400
5587
  let startBuffered = null;
5401
5588
  let startBufferedId = null;
5402
5589
  let endBuffered = null;
5403
- let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
5590
+ let loopStart = (_h = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _h : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
5404
5591
  for (let i = loopStart; i >= 0; i--) {
5405
- const id = (_g = idCache[i]) != null ? _g : getId(state, i);
5592
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
5406
5593
  const top = positions[i];
5407
- const size = (_h = sizes.get(id)) != null ? _h : getItemSize(ctx, id, i, data[i]);
5594
+ const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
5408
5595
  const bottom = top + size;
5409
5596
  if (bottom > scrollTopBuffered) {
5410
5597
  loopStart = i;
@@ -5439,8 +5626,8 @@ function calculateItemsInView(ctx, params = {}) {
5439
5626
  };
5440
5627
  const dataLength = data.length;
5441
5628
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
5442
- const id = (_i = idCache[i]) != null ? _i : getId(state, i);
5443
- const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
5629
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5630
+ const size = (_l = sizes.get(id)) != null ? _l : getItemSize(ctx, id, i, data[i]);
5444
5631
  const top = positions[i];
5445
5632
  if (!foundEnd) {
5446
5633
  trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
@@ -5496,7 +5683,7 @@ function calculateItemsInView(ctx, params = {}) {
5496
5683
  const needNewContainers = [];
5497
5684
  const needNewContainersSet = /* @__PURE__ */ new Set();
5498
5685
  for (let i = startBuffered; i <= endBuffered; i++) {
5499
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
5686
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
5500
5687
  if (!containerItemKeys.has(id)) {
5501
5688
  needNewContainersSet.add(i);
5502
5689
  needNewContainers.push(i);
@@ -5505,7 +5692,7 @@ function calculateItemsInView(ctx, params = {}) {
5505
5692
  if (alwaysRenderArr.length > 0) {
5506
5693
  for (const index of alwaysRenderArr) {
5507
5694
  if (index < 0 || index >= dataLength) continue;
5508
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
5695
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
5509
5696
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
5510
5697
  needNewContainersSet.add(index);
5511
5698
  needNewContainers.push(index);
@@ -5516,7 +5703,7 @@ function calculateItemsInView(ctx, params = {}) {
5516
5703
  handleStickyActivation(
5517
5704
  ctx,
5518
5705
  stickyHeaderIndicesArr,
5519
- currentStickyIdx,
5706
+ (_o = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _o : -1,
5520
5707
  needNewContainers,
5521
5708
  needNewContainersSet,
5522
5709
  startBuffered,
@@ -5542,7 +5729,7 @@ function calculateItemsInView(ctx, params = {}) {
5542
5729
  for (const allocation of availableContainerAllocations) {
5543
5730
  const i = allocation.itemIndex;
5544
5731
  const containerIndex = allocation.containerIndex;
5545
- const id = (_m = idCache[i]) != null ? _m : getId(state, i);
5732
+ const id = (_p = idCache[i]) != null ? _p : getId(state, i);
5546
5733
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
5547
5734
  if (oldKey && oldKey !== id) {
5548
5735
  containerItemKeys.delete(oldKey);
@@ -5553,7 +5740,7 @@ function calculateItemsInView(ctx, params = {}) {
5553
5740
  state.containerItemTypes.set(containerIndex, allocation.itemType);
5554
5741
  }
5555
5742
  containerItemKeys.set(id, containerIndex);
5556
- (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
5743
+ (_q = state.userScrollAnchorReset) == null ? void 0 : _q.keys.add(id);
5557
5744
  const containerSticky = `containerSticky${containerIndex}`;
5558
5745
  const isSticky = stickyHeaderIndicesSet.has(i);
5559
5746
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -5584,14 +5771,12 @@ function calculateItemsInView(ctx, params = {}) {
5584
5771
  if (state.userScrollAnchorReset) {
5585
5772
  if (state.userScrollAnchorReset.keys.size === 0) {
5586
5773
  state.userScrollAnchorReset = void 0;
5587
- } else {
5588
- state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
5589
5774
  }
5590
5775
  }
5591
5776
  if (alwaysRenderArr.length > 0) {
5592
5777
  for (const index of alwaysRenderArr) {
5593
5778
  if (index < 0 || index >= dataLength) continue;
5594
- const id = (_o = idCache[index]) != null ? _o : getId(state, index);
5779
+ const id = (_r = idCache[index]) != null ? _r : getId(state, index);
5595
5780
  const containerIndex = containerItemKeys.get(id);
5596
5781
  if (containerIndex !== void 0) {
5597
5782
  state.stickyContainerPool.add(containerIndex);
@@ -5605,7 +5790,7 @@ function calculateItemsInView(ctx, params = {}) {
5605
5790
  stickyHeaderIndicesArr,
5606
5791
  scroll,
5607
5792
  drawDistance,
5608
- currentStickyIdx,
5793
+ (_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
5609
5794
  pendingRemoval,
5610
5795
  alwaysRenderSet
5611
5796
  );
@@ -5666,7 +5851,7 @@ function calculateItemsInView(ctx, params = {}) {
5666
5851
  );
5667
5852
  }
5668
5853
  }
5669
- finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
5854
+ (_t = stickyState == null ? void 0 : stickyState.finishCalculateItemsInView) == null ? void 0 : _t.call(stickyState);
5670
5855
  });
5671
5856
  }
5672
5857
 
@@ -5749,8 +5934,9 @@ function doInitialAllocateContainers(ctx) {
5749
5934
  const state = ctx.state;
5750
5935
  const {
5751
5936
  scrollLength,
5752
- props: { data, drawDistance, getFixedItemSize, getItemType, numColumns, estimatedItemSize }
5937
+ props: { data, getFixedItemSize, getItemType, numColumns, estimatedItemSize }
5753
5938
  } = state;
5939
+ const drawDistance = getEffectiveDrawDistance(ctx);
5754
5940
  const hasContainers = peek$(ctx, "numContainers");
5755
5941
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
5756
5942
  let averageItemSize;
@@ -5761,12 +5947,12 @@ function doInitialAllocateContainers(ctx) {
5761
5947
  const item = data[i];
5762
5948
  if (item !== void 0) {
5763
5949
  const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
5764
- totalSize += (_b = getFixedItemSize(item, i, itemType)) != null ? _b : estimatedItemSize;
5950
+ totalSize += ((_b = getFixedItemSize(item, i, itemType)) != null ? _b : estimatedItemSize) + ctx.scrollAxisGap;
5765
5951
  }
5766
5952
  }
5767
5953
  averageItemSize = totalSize / num;
5768
5954
  } else {
5769
- averageItemSize = estimatedItemSize;
5955
+ averageItemSize = estimatedItemSize + ctx.scrollAxisGap;
5770
5956
  }
5771
5957
  const numContainers = Math.max(
5772
5958
  1,
@@ -5825,7 +6011,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5825
6011
  if (didChange) {
5826
6012
  state.scrollLength = scrollLength;
5827
6013
  state.otherAxisSize = otherAxisSize;
5828
- updateContentMetrics(ctx);
6014
+ updateContentMetricsState(ctx);
5829
6015
  state.lastBatchingAction = Date.now();
5830
6016
  state.scrollForNextCalculateItemsInView = void 0;
5831
6017
  if (scrollLength > 0) {
@@ -6062,28 +6248,12 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
6062
6248
 
6063
6249
  // src/core/updateItemSize.ts
6064
6250
  function runOrScheduleMVCPRecalculate(ctx) {
6065
- var _a3, _b;
6251
+ var _a3;
6066
6252
  const state = ctx.state;
6067
6253
  if (state.userScrollAnchorReset !== void 0) {
6068
- const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
6069
- const replacementMeasurementBatchThreshold = 3;
6070
- const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
6071
- if (shouldBatchReplacementMeasurements) {
6072
- if (state.queuedMVCPRecalculate === void 0) {
6073
- state.queuedMVCPRecalculate = requestAnimationFrame(() => {
6074
- var _a4;
6075
- state.queuedMVCPRecalculate = void 0;
6076
- calculateItemsInView(ctx);
6077
- if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
6078
- state.userScrollAnchorReset = void 0;
6079
- }
6080
- });
6081
- }
6082
- } else {
6083
- calculateItemsInView(ctx);
6084
- if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
6085
- state.userScrollAnchorReset = void 0;
6086
- }
6254
+ calculateItemsInView(ctx);
6255
+ if (((_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys.size) === 0) {
6256
+ state.userScrollAnchorReset = void 0;
6087
6257
  }
6088
6258
  } else {
6089
6259
  if (!state.mvcpAnchorLock) {
@@ -6543,6 +6713,9 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6543
6713
  scrollTo(ctx, params);
6544
6714
  return true;
6545
6715
  }),
6716
+ setItemSize: (itemKey, size) => {
6717
+ updateItemSize(ctx, itemKey, size);
6718
+ },
6546
6719
  setScrollProcessingEnabled: (enabled) => {
6547
6720
  state.scrollProcessingEnabled = enabled;
6548
6721
  },
@@ -6640,12 +6813,13 @@ function getRenderedItem(ctx, key) {
6640
6813
 
6641
6814
  // src/utils/normalizeMaintainScrollAtEnd.ts
6642
6815
  function normalizeMaintainScrollAtEndOn(on, hasExplicitOn) {
6643
- var _a3, _b, _c;
6816
+ var _a3, _b, _c, _d;
6644
6817
  return {
6645
6818
  animated: false,
6646
6819
  onDataChange: hasExplicitOn ? (_a3 = on == null ? void 0 : on.dataChange) != null ? _a3 : false : true,
6647
- onItemLayout: hasExplicitOn ? (_b = on == null ? void 0 : on.itemLayout) != null ? _b : false : true,
6648
- onLayout: hasExplicitOn ? (_c = on == null ? void 0 : on.layout) != null ? _c : false : true
6820
+ onFooterLayout: hasExplicitOn ? (_b = on == null ? void 0 : on.footerLayout) != null ? _b : false : true,
6821
+ onItemLayout: hasExplicitOn ? (_c = on == null ? void 0 : on.itemLayout) != null ? _c : false : true,
6822
+ onLayout: hasExplicitOn ? (_d = on == null ? void 0 : on.layout) != null ? _d : false : true
6649
6823
  };
6650
6824
  }
6651
6825
  function normalizeMaintainScrollAtEnd(value) {
@@ -6767,7 +6941,7 @@ var LegendList = typedMemo(
6767
6941
  })
6768
6942
  );
6769
6943
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
6770
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
6944
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
6771
6945
  const noopOnScroll = useCallback((_event) => {
6772
6946
  }, []);
6773
6947
  if (props.recycleItems === void 0) {
@@ -6798,6 +6972,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6798
6972
  initialScrollAtEnd = false,
6799
6973
  initialScrollIndex: initialScrollIndexProp,
6800
6974
  initialScrollOffset: initialScrollOffsetProp,
6975
+ experimental_adaptiveRender,
6801
6976
  itemsAreEqual,
6802
6977
  keyExtractor: keyExtractorProp,
6803
6978
  ListEmptyComponent,
@@ -6894,6 +7069,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6894
7069
  const [, scheduleImperativeScrollCommit] = React3.useReducer((value) => value + 1, 0);
6895
7070
  const ctx = useStateContext();
6896
7071
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
7072
+ 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;
7073
+ const nextScrollAxisGap = typeof scrollAxisGap === "number" && Number.isFinite(scrollAxisGap) ? scrollAxisGap : 0;
6897
7074
  const refScroller = useRef(null);
6898
7075
  const combinedRef = useCombinedRef(refScroller, refScrollView);
6899
7076
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
@@ -6907,8 +7084,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6907
7084
  anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
6908
7085
  alwaysRender == null ? void 0 : alwaysRender.top,
6909
7086
  alwaysRender == null ? void 0 : alwaysRender.bottom,
6910
- (_d = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _d.join(","),
6911
- (_e = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _e.join(","),
7087
+ (_j = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _j.join(","),
7088
+ (_k = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _k.join(","),
6912
7089
  dataProp,
6913
7090
  dataVersion,
6914
7091
  keyExtractor
@@ -6936,6 +7113,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6936
7113
  endNoBuffer: -1,
6937
7114
  endReachedSnapshot: void 0,
6938
7115
  firstFullyOnScreenIndex: -1,
7116
+ hasHadNonEmptyData: dataProp.length > 0,
6939
7117
  idCache: [],
6940
7118
  idsInView: [],
6941
7119
  indexByKey: /* @__PURE__ */ new Map(),
@@ -6978,6 +7156,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6978
7156
  startReachedSnapshotDataChangeEpoch: void 0,
6979
7157
  stickyContainerPool: /* @__PURE__ */ new Set(),
6980
7158
  stickyContainers: /* @__PURE__ */ new Map(),
7159
+ timeoutAdaptiveRender: void 0,
6981
7160
  timeouts: /* @__PURE__ */ new Set(),
6982
7161
  totalSize: 0,
6983
7162
  viewabilityConfigCallbackPairs: void 0
@@ -6996,11 +7175,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6996
7175
  const state = refState.current;
6997
7176
  const isFirstLocal = state.isFirst;
6998
7177
  const previousNumColumnsProp = state.props.numColumns;
6999
- state.didColumnsChange = numColumnsProp !== previousNumColumnsProp;
7178
+ const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
7179
+ ctx.scrollAxisGap = nextScrollAxisGap;
7180
+ state.didColumnsChange = numColumnsProp !== previousNumColumnsProp || didScrollAxisGapChange;
7000
7181
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
7001
7182
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
7002
7183
  const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
7003
- if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.props.data.length > 0) {
7184
+ if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_l = state.initialScroll) == null ? void 0 : _l.viewPosition) === 1 && state.props.data.length > 0) {
7004
7185
  clearPreservedInitialScrollTarget(state);
7005
7186
  }
7006
7187
  if (didDataChangeLocal) {
@@ -7012,8 +7193,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7012
7193
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
7013
7194
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
7014
7195
  const anchoredEndSpaceResolved = anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
7015
- const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7196
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_m = state.props.anchoredEndSpace) == null ? void 0 : _m.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7016
7197
  state.props = {
7198
+ adaptiveRender: experimental_adaptiveRender,
7017
7199
  alignItemsAtEnd,
7018
7200
  alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
7019
7201
  alwaysRender,
@@ -7021,6 +7203,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7021
7203
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
7022
7204
  anchoredEndSpace: anchoredEndSpaceResolved,
7023
7205
  animatedProps: animatedPropsInternal,
7206
+ contentContainerAlignItems: contentContainerStyle.alignItems,
7024
7207
  contentInset,
7025
7208
  contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
7026
7209
  data: dataProp,
@@ -7073,7 +7256,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7073
7256
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
7074
7257
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
7075
7258
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
7076
- updateContentMetrics(ctx);
7259
+ updateContentMetricsState(ctx);
7077
7260
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
7078
7261
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
7079
7262
  };
@@ -7105,7 +7288,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7105
7288
  useBootstrapInitialScroll: usesBootstrapInitialScroll
7106
7289
  });
7107
7290
  }, []);
7108
- if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
7291
+ if (isFirstLocal || didDataChangeLocal || state.didColumnsChange) {
7109
7292
  refState.current.lastBatchingAction = Date.now();
7110
7293
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
7111
7294
  refState.current.sizes.clear();
@@ -7122,6 +7305,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7122
7305
  dataLength: dataProp.length,
7123
7306
  didDataChange: didDataChangeLocal,
7124
7307
  initialScrollAtEnd,
7308
+ latestInitialScroll: initialScrollProp,
7309
+ latestInitialScrollSessionKind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
7125
7310
  stylePaddingBottom: stylePaddingBottomState,
7126
7311
  useBootstrapInitialScroll: usesBootstrapInitialScroll
7127
7312
  });
@@ -7196,6 +7381,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7196
7381
  dataVersion,
7197
7382
  memoizedLastItemKeys.join(","),
7198
7383
  numColumnsProp,
7384
+ nextScrollAxisGap,
7199
7385
  stylePaddingBottomState,
7200
7386
  stylePaddingTopState,
7201
7387
  useAlignItemsAtEndPadding
@@ -7218,7 +7404,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7218
7404
  state.didColumnsChange = false;
7219
7405
  state.didDataChange = false;
7220
7406
  state.isFirst = false;
7221
- }, [dataProp, dataVersion, numColumnsProp]);
7407
+ }, [dataProp, dataVersion, numColumnsProp, nextScrollAxisGap]);
7222
7408
  useLayoutEffect(() => {
7223
7409
  var _a4;
7224
7410
  set$(ctx, "extraData", extraData);
@@ -7266,6 +7452,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7266
7452
  useInit(() => {
7267
7453
  });
7268
7454
  useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7455
+ useEffect(() => {
7456
+ return () => {
7457
+ for (const timeout of state.timeouts) {
7458
+ clearTimeout(timeout);
7459
+ }
7460
+ state.timeouts.clear();
7461
+ };
7462
+ }, [state]);
7269
7463
  useLayoutEffect(() => {
7270
7464
  var _a4;
7271
7465
  (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
@@ -7313,7 +7507,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7313
7507
  onScroll: onScrollHandler,
7314
7508
  recycleItems,
7315
7509
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControlElement, {
7316
- progressViewOffset: ((_h = refreshControlElement.props.progressViewOffset) != null ? _h : 0) + stylePaddingTopState
7510
+ progressViewOffset: ((_n = refreshControlElement.props.progressViewOffset) != null ? _n : 0) + stylePaddingTopState
7317
7511
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3.createElement(
7318
7512
  RefreshControl,
7319
7513
  {
@@ -7324,7 +7518,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7324
7518
  ),
7325
7519
  refScrollView: combinedRef,
7326
7520
  renderScrollComponent,
7327
- scrollAdjustHandler: (_i = refState.current) == null ? void 0 : _i.scrollAdjustHandler,
7521
+ scrollAdjustHandler: (_o = refState.current) == null ? void 0 : _o.scrollAdjustHandler,
7328
7522
  scrollEventThrottle: 0,
7329
7523
  snapToIndices,
7330
7524
  stickyHeaderIndices,
@@ -7380,4 +7574,4 @@ var internal = {
7380
7574
  var LegendList3 = LegendListRuntime;
7381
7575
  var internal2 = internal;
7382
7576
 
7383
- export { LegendList3 as LegendList, internal2 as internal, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
7577
+ export { LegendList3 as LegendList, internal2 as internal, useAdaptiveRender, useAdaptiveRenderChange, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };