@legendapp/list 3.0.5 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/react.js CHANGED
@@ -164,6 +164,7 @@ function StateProvider({ children }) {
164
164
  positionListeners: /* @__PURE__ */ new Map(),
165
165
  state: void 0,
166
166
  values: /* @__PURE__ */ new Map([
167
+ ["alignItemsAtEndPadding", 0],
167
168
  ["stylePaddingTop", 0],
168
169
  ["headerSize", 0],
169
170
  ["numContainers", 0],
@@ -306,15 +307,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
306
307
 
307
308
  // src/state/getContentSize.ts
308
309
  function getContentSize(ctx) {
309
- var _a3;
310
+ var _a3, _b;
310
311
  const { values, state } = ctx;
311
312
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
312
313
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
314
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
313
315
  const headerSize = values.get("headerSize") || 0;
314
316
  const footerSize = values.get("footerSize") || 0;
315
317
  const contentInsetBottom = getContentInsetEnd(ctx);
316
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
317
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
318
+ const totalSize = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize");
319
+ return headerSize + footerSize + totalSize + stylePaddingTop + alignItemsAtEndPadding + stylePaddingBottom + (contentInsetBottom || 0);
318
320
  }
319
321
 
320
322
  // src/components/DebugView.tsx
@@ -1814,6 +1816,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1814
1816
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1815
1817
  return /* @__PURE__ */ React3__namespace.createElement("div", { style }, null);
1816
1818
  }
1819
+
1820
+ // src/core/updateContentMetrics.ts
1821
+ function getRawContentLength(ctx) {
1822
+ var _a3, _b, _c;
1823
+ const { state, values } = ctx;
1824
+ return (values.get("headerSize") || 0) + (values.get("footerSize") || 0) + ((_c = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize")) != null ? _c : 0) + (state.props.stylePaddingTop || 0) + (state.props.stylePaddingBottom || 0);
1825
+ }
1826
+ function getAlignItemsAtEndPadding(ctx) {
1827
+ const { state } = ctx;
1828
+ const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1829
+ return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1830
+ }
1831
+ function updateContentMetrics(ctx) {
1832
+ const nextPadding = getAlignItemsAtEndPadding(ctx);
1833
+ if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1834
+ set$(ctx, "alignItemsAtEndPadding", nextPadding);
1835
+ }
1836
+ }
1837
+ function setContentLengthSignal(ctx, signalName, size) {
1838
+ if (peek$(ctx, signalName) !== size) {
1839
+ set$(ctx, signalName, size);
1840
+ updateContentMetrics(ctx);
1841
+ }
1842
+ }
1843
+ function setHeaderSize(ctx, size) {
1844
+ setContentLengthSignal(ctx, "headerSize", size);
1845
+ }
1846
+ function setFooterSize(ctx, size) {
1847
+ setContentLengthSignal(ctx, "footerSize", size);
1848
+ }
1849
+ function areInsetsEqual(left, right) {
1850
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
1851
+ return ((_a3 = left == null ? void 0 : left.top) != null ? _a3 : 0) === ((_b = right == null ? void 0 : right.top) != null ? _b : 0) && ((_c = left == null ? void 0 : left.bottom) != null ? _c : 0) === ((_d = right == null ? void 0 : right.bottom) != null ? _d : 0) && ((_e = left == null ? void 0 : left.left) != null ? _e : 0) === ((_f = right == null ? void 0 : right.left) != null ? _f : 0) && ((_g = left == null ? void 0 : left.right) != null ? _g : 0) === ((_h = right == null ? void 0 : right.right) != null ? _h : 0);
1852
+ }
1853
+ function setContentInsetOverride(ctx, inset) {
1854
+ const { state } = ctx;
1855
+ const previousInset = state.contentInsetOverride;
1856
+ const nextInset = inset != null ? inset : void 0;
1857
+ const didChange = !areInsetsEqual(previousInset, nextInset);
1858
+ state.contentInsetOverride = nextInset;
1859
+ if (didChange) {
1860
+ updateContentMetrics(ctx);
1861
+ }
1862
+ return didChange;
1863
+ }
1817
1864
  function useStableRenderComponent(renderComponent, mapProps) {
1818
1865
  const renderComponentRef = useLatestRef(renderComponent);
1819
1866
  const mapPropsRef = useLatestRef(mapProps);
@@ -1865,7 +1912,7 @@ var ListComponent = typedMemo(function ListComponent2({
1865
1912
  }) {
1866
1913
  const ctx = useStateContext();
1867
1914
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1868
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1915
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1869
1916
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1870
1917
  horizontal,
1871
1918
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1879,23 +1926,23 @@ var ListComponent = typedMemo(function ListComponent2({
1879
1926
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1880
1927
  React3.useLayoutEffect(() => {
1881
1928
  if (!ListHeaderComponent) {
1882
- set$(ctx, "headerSize", 0);
1929
+ setHeaderSize(ctx, 0);
1883
1930
  }
1884
1931
  if (!ListFooterComponent) {
1885
- set$(ctx, "footerSize", 0);
1932
+ setFooterSize(ctx, 0);
1886
1933
  }
1887
1934
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1888
1935
  const onLayoutHeader = React3.useCallback(
1889
1936
  (rect) => {
1890
1937
  const size = rect[horizontal ? "width" : "height"];
1891
- set$(ctx, "headerSize", size);
1938
+ setHeaderSize(ctx, size);
1892
1939
  },
1893
1940
  [ctx, horizontal]
1894
1941
  );
1895
1942
  const onLayoutFooterInternal = React3.useCallback(
1896
1943
  (rect, fromLayoutEffect) => {
1897
1944
  const size = rect[horizontal ? "width" : "height"];
1898
- set$(ctx, "footerSize", size);
1945
+ setFooterSize(ctx, size);
1899
1946
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1900
1947
  },
1901
1948
  [ctx, horizontal, onLayoutFooter]
@@ -1923,6 +1970,13 @@ var ListComponent = typedMemo(function ListComponent2({
1923
1970
  /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1924
1971
  ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1925
1972
  ListEmptyComponent && getComponent(ListEmptyComponent),
1973
+ alignItemsAtEndPadding > 0 && /* @__PURE__ */ React3__namespace.createElement(
1974
+ View,
1975
+ {
1976
+ style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
1977
+ },
1978
+ null
1979
+ ),
1926
1980
  canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1927
1981
  Containers,
1928
1982
  {
@@ -2414,7 +2468,7 @@ function calculateOffsetForIndex(ctx, index) {
2414
2468
 
2415
2469
  // src/core/getTopOffsetAdjustment.ts
2416
2470
  function getTopOffsetAdjustment(ctx) {
2417
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2471
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
2418
2472
  }
2419
2473
 
2420
2474
  // src/utils/getId.ts
@@ -2450,6 +2504,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2450
2504
  if (notifyTotalSize) {
2451
2505
  set$(ctx, "totalSize", totalSize);
2452
2506
  }
2507
+ updateContentMetrics(ctx);
2453
2508
  }
2454
2509
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2455
2510
  set$(ctx, "totalSize", totalSize);
@@ -4796,7 +4851,7 @@ function areViewabilityAmountTokensEqual(prev, next) {
4796
4851
  }
4797
4852
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4798
4853
  const { sizes, scroll: scrollState } = state;
4799
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
4854
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
4800
4855
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4801
4856
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4802
4857
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -5247,7 +5302,7 @@ function calculateItemsInView(ctx, params = {}) {
5247
5302
  return;
5248
5303
  }
5249
5304
  let totalSize = getContentSize(ctx);
5250
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
5305
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
5251
5306
  const numColumns = peek$(ctx, "numColumns");
5252
5307
  const speed = getScrollVelocity(state);
5253
5308
  const scrollExtra = 0;
@@ -5791,6 +5846,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5791
5846
  if (didChange) {
5792
5847
  state.scrollLength = scrollLength;
5793
5848
  state.otherAxisSize = otherAxisSize;
5849
+ updateContentMetrics(ctx);
5794
5850
  state.lastBatchingAction = Date.now();
5795
5851
  state.scrollForNextCalculateItemsInView = void 0;
5796
5852
  if (scrollLength > 0) {
@@ -6456,10 +6512,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6456
6512
  startBuffered: state.startBuffered
6457
6513
  }),
6458
6514
  reportContentInset: (inset) => {
6459
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
6460
- const previousInset = state.contentInsetOverride;
6461
- state.contentInsetOverride = inset != null ? inset : void 0;
6462
- const didChange = ((_a3 = previousInset == null ? void 0 : previousInset.top) != null ? _a3 : 0) !== ((_c = (_b = state.contentInsetOverride) == null ? void 0 : _b.top) != null ? _c : 0) || ((_d = previousInset == null ? void 0 : previousInset.bottom) != null ? _d : 0) !== ((_f = (_e = state.contentInsetOverride) == null ? void 0 : _e.bottom) != null ? _f : 0) || ((_g = previousInset == null ? void 0 : previousInset.left) != null ? _g : 0) !== ((_i = (_h = state.contentInsetOverride) == null ? void 0 : _h.left) != null ? _i : 0) || ((_j = previousInset == null ? void 0 : previousInset.right) != null ? _j : 0) !== ((_l = (_k = state.contentInsetOverride) == null ? void 0 : _k.right) != null ? _l : 0);
6515
+ const didChange = setContentInsetOverride(ctx, inset);
6463
6516
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
6464
6517
  if (didChange) {
6465
6518
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6815,10 +6868,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6815
6868
  ...restProps
6816
6869
  } = rest;
6817
6870
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6818
- const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6871
+ const useAlignItemsAtEndPadding = alignItemsAtEnd && !horizontal && (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null && dataProp.length > 0;
6872
+ const shouldFlexGrow = alignItemsAtEnd && !useAlignItemsAtEndPadding && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6819
6873
  const contentContainerStyle = {
6820
6874
  ...contentContainerStyleBase,
6821
- ...alignItemsAtEnd ? {
6875
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6822
6876
  display: "flex",
6823
6877
  flexDirection: horizontal ? "row" : "column",
6824
6878
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6982,6 +7036,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6982
7036
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6983
7037
  state.props = {
6984
7038
  alignItemsAtEnd,
7039
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6985
7040
  alwaysRender,
6986
7041
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6987
7042
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -7039,6 +7094,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7039
7094
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
7040
7095
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
7041
7096
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
7097
+ updateContentMetrics(ctx);
7042
7098
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
7043
7099
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
7044
7100
  };
@@ -7157,7 +7213,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7157
7213
  }, [snapToIndices]);
7158
7214
  React3.useLayoutEffect(
7159
7215
  () => initializeStateVars(true),
7160
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
7216
+ [
7217
+ dataVersion,
7218
+ memoizedLastItemKeys.join(","),
7219
+ numColumnsProp,
7220
+ stylePaddingBottomState,
7221
+ stylePaddingTopState,
7222
+ useAlignItemsAtEndPadding
7223
+ ]
7161
7224
  );
7162
7225
  React3.useLayoutEffect(() => {
7163
7226
  const {
package/react.mjs CHANGED
@@ -143,6 +143,7 @@ function StateProvider({ children }) {
143
143
  positionListeners: /* @__PURE__ */ new Map(),
144
144
  state: void 0,
145
145
  values: /* @__PURE__ */ new Map([
146
+ ["alignItemsAtEndPadding", 0],
146
147
  ["stylePaddingTop", 0],
147
148
  ["headerSize", 0],
148
149
  ["numContainers", 0],
@@ -285,15 +286,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
285
286
 
286
287
  // src/state/getContentSize.ts
287
288
  function getContentSize(ctx) {
288
- var _a3;
289
+ var _a3, _b;
289
290
  const { values, state } = ctx;
290
291
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
291
292
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
293
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
292
294
  const headerSize = values.get("headerSize") || 0;
293
295
  const footerSize = values.get("footerSize") || 0;
294
296
  const contentInsetBottom = getContentInsetEnd(ctx);
295
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
296
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
297
+ const totalSize = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize");
298
+ return headerSize + footerSize + totalSize + stylePaddingTop + alignItemsAtEndPadding + stylePaddingBottom + (contentInsetBottom || 0);
297
299
  }
298
300
 
299
301
  // src/components/DebugView.tsx
@@ -1793,6 +1795,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1793
1795
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1794
1796
  return /* @__PURE__ */ React3.createElement("div", { style }, null);
1795
1797
  }
1798
+
1799
+ // src/core/updateContentMetrics.ts
1800
+ function getRawContentLength(ctx) {
1801
+ var _a3, _b, _c;
1802
+ const { state, values } = ctx;
1803
+ return (values.get("headerSize") || 0) + (values.get("footerSize") || 0) + ((_c = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize")) != null ? _c : 0) + (state.props.stylePaddingTop || 0) + (state.props.stylePaddingBottom || 0);
1804
+ }
1805
+ function getAlignItemsAtEndPadding(ctx) {
1806
+ const { state } = ctx;
1807
+ const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1808
+ return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1809
+ }
1810
+ function updateContentMetrics(ctx) {
1811
+ const nextPadding = getAlignItemsAtEndPadding(ctx);
1812
+ if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1813
+ set$(ctx, "alignItemsAtEndPadding", nextPadding);
1814
+ }
1815
+ }
1816
+ function setContentLengthSignal(ctx, signalName, size) {
1817
+ if (peek$(ctx, signalName) !== size) {
1818
+ set$(ctx, signalName, size);
1819
+ updateContentMetrics(ctx);
1820
+ }
1821
+ }
1822
+ function setHeaderSize(ctx, size) {
1823
+ setContentLengthSignal(ctx, "headerSize", size);
1824
+ }
1825
+ function setFooterSize(ctx, size) {
1826
+ setContentLengthSignal(ctx, "footerSize", size);
1827
+ }
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);
1831
+ }
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;
1842
+ }
1796
1843
  function useStableRenderComponent(renderComponent, mapProps) {
1797
1844
  const renderComponentRef = useLatestRef(renderComponent);
1798
1845
  const mapPropsRef = useLatestRef(mapProps);
@@ -1844,7 +1891,7 @@ var ListComponent = typedMemo(function ListComponent2({
1844
1891
  }) {
1845
1892
  const ctx = useStateContext();
1846
1893
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1847
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1894
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1848
1895
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1849
1896
  horizontal,
1850
1897
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1858,23 +1905,23 @@ var ListComponent = typedMemo(function ListComponent2({
1858
1905
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1859
1906
  useLayoutEffect(() => {
1860
1907
  if (!ListHeaderComponent) {
1861
- set$(ctx, "headerSize", 0);
1908
+ setHeaderSize(ctx, 0);
1862
1909
  }
1863
1910
  if (!ListFooterComponent) {
1864
- set$(ctx, "footerSize", 0);
1911
+ setFooterSize(ctx, 0);
1865
1912
  }
1866
1913
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1867
1914
  const onLayoutHeader = useCallback(
1868
1915
  (rect) => {
1869
1916
  const size = rect[horizontal ? "width" : "height"];
1870
- set$(ctx, "headerSize", size);
1917
+ setHeaderSize(ctx, size);
1871
1918
  },
1872
1919
  [ctx, horizontal]
1873
1920
  );
1874
1921
  const onLayoutFooterInternal = useCallback(
1875
1922
  (rect, fromLayoutEffect) => {
1876
1923
  const size = rect[horizontal ? "width" : "height"];
1877
- set$(ctx, "footerSize", size);
1924
+ setFooterSize(ctx, size);
1878
1925
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1879
1926
  },
1880
1927
  [ctx, horizontal, onLayoutFooter]
@@ -1902,6 +1949,13 @@ var ListComponent = typedMemo(function ListComponent2({
1902
1949
  /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
1903
1950
  ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1904
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
+ ),
1905
1959
  canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
1906
1960
  Containers,
1907
1961
  {
@@ -2393,7 +2447,7 @@ function calculateOffsetForIndex(ctx, index) {
2393
2447
 
2394
2448
  // src/core/getTopOffsetAdjustment.ts
2395
2449
  function getTopOffsetAdjustment(ctx) {
2396
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2450
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
2397
2451
  }
2398
2452
 
2399
2453
  // src/utils/getId.ts
@@ -2429,6 +2483,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
2429
2483
  if (notifyTotalSize) {
2430
2484
  set$(ctx, "totalSize", totalSize);
2431
2485
  }
2486
+ updateContentMetrics(ctx);
2432
2487
  }
2433
2488
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
2434
2489
  set$(ctx, "totalSize", totalSize);
@@ -4775,7 +4830,7 @@ function areViewabilityAmountTokensEqual(prev, next) {
4775
4830
  }
4776
4831
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4777
4832
  const { sizes, scroll: scrollState } = state;
4778
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
4833
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
4779
4834
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4780
4835
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4781
4836
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -5226,7 +5281,7 @@ function calculateItemsInView(ctx, params = {}) {
5226
5281
  return;
5227
5282
  }
5228
5283
  let totalSize = getContentSize(ctx);
5229
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
5284
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
5230
5285
  const numColumns = peek$(ctx, "numColumns");
5231
5286
  const speed = getScrollVelocity(state);
5232
5287
  const scrollExtra = 0;
@@ -5770,6 +5825,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5770
5825
  if (didChange) {
5771
5826
  state.scrollLength = scrollLength;
5772
5827
  state.otherAxisSize = otherAxisSize;
5828
+ updateContentMetrics(ctx);
5773
5829
  state.lastBatchingAction = Date.now();
5774
5830
  state.scrollForNextCalculateItemsInView = void 0;
5775
5831
  if (scrollLength > 0) {
@@ -6435,10 +6491,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6435
6491
  startBuffered: state.startBuffered
6436
6492
  }),
6437
6493
  reportContentInset: (inset) => {
6438
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
6439
- const previousInset = state.contentInsetOverride;
6440
- state.contentInsetOverride = inset != null ? inset : void 0;
6441
- const didChange = ((_a3 = previousInset == null ? void 0 : previousInset.top) != null ? _a3 : 0) !== ((_c = (_b = state.contentInsetOverride) == null ? void 0 : _b.top) != null ? _c : 0) || ((_d = previousInset == null ? void 0 : previousInset.bottom) != null ? _d : 0) !== ((_f = (_e = state.contentInsetOverride) == null ? void 0 : _e.bottom) != null ? _f : 0) || ((_g = previousInset == null ? void 0 : previousInset.left) != null ? _g : 0) !== ((_i = (_h = state.contentInsetOverride) == null ? void 0 : _h.left) != null ? _i : 0) || ((_j = previousInset == null ? void 0 : previousInset.right) != null ? _j : 0) !== ((_l = (_k = state.contentInsetOverride) == null ? void 0 : _k.right) != null ? _l : 0);
6494
+ const didChange = setContentInsetOverride(ctx, inset);
6442
6495
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
6443
6496
  if (didChange) {
6444
6497
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6794,10 +6847,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6794
6847
  ...restProps
6795
6848
  } = rest;
6796
6849
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6797
- const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6850
+ const useAlignItemsAtEndPadding = alignItemsAtEnd && !horizontal && (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null && dataProp.length > 0;
6851
+ const shouldFlexGrow = alignItemsAtEnd && !useAlignItemsAtEndPadding && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6798
6852
  const contentContainerStyle = {
6799
6853
  ...contentContainerStyleBase,
6800
- ...alignItemsAtEnd ? {
6854
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6801
6855
  display: "flex",
6802
6856
  flexDirection: horizontal ? "row" : "column",
6803
6857
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6961,6 +7015,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6961
7015
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6962
7016
  state.props = {
6963
7017
  alignItemsAtEnd,
7018
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6964
7019
  alwaysRender,
6965
7020
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6966
7021
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -7018,6 +7073,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7018
7073
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
7019
7074
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
7020
7075
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
7076
+ updateContentMetrics(ctx);
7021
7077
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
7022
7078
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
7023
7079
  };
@@ -7136,7 +7192,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7136
7192
  }, [snapToIndices]);
7137
7193
  useLayoutEffect(
7138
7194
  () => initializeStateVars(true),
7139
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
7195
+ [
7196
+ dataVersion,
7197
+ memoizedLastItemKeys.join(","),
7198
+ numColumnsProp,
7199
+ stylePaddingBottomState,
7200
+ stylePaddingTopState,
7201
+ useAlignItemsAtEndPadding
7202
+ ]
7140
7203
  );
7141
7204
  useLayoutEffect(() => {
7142
7205
  const {
package/reanimated.d.ts CHANGED
@@ -9,10 +9,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
9
9
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
10
10
  }
11
11
 
12
- type ListenerType = "activeStickyIndex" | "anchoredEndSpaceSize" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
12
+ type ListenerType = "activeStickyIndex" | "alignItemsAtEndPadding" | "anchoredEndSpaceSize" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
13
13
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
14
14
  type ListenerTypeValueMap = {
15
15
  activeStickyIndex: number;
16
+ alignItemsAtEndPadding: number;
16
17
  anchoredEndSpaceSize: number;
17
18
  animatedScrollY: any;
18
19
  debugComputedScroll: number;
package/section-list.d.ts CHANGED
@@ -65,10 +65,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
65
65
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
66
66
  }
67
67
 
68
- type ListenerType = "activeStickyIndex" | "anchoredEndSpaceSize" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
68
+ type ListenerType = "activeStickyIndex" | "alignItemsAtEndPadding" | "anchoredEndSpaceSize" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
69
69
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
70
70
  type ListenerTypeValueMap = {
71
71
  activeStickyIndex: number;
72
+ alignItemsAtEndPadding: number;
72
73
  anchoredEndSpaceSize: number;
73
74
  animatedScrollY: any;
74
75
  debugComputedScroll: number;