@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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 3.0.6
2
+
3
+ - Fix: KeyboardAwareLegendList now accounts for bottom insets when alignItemsAtEnd is used, so short chat-style lists stay pinned above the keyboard or safe area instead of being pushed too low or leaving extra scroll space.
4
+
1
5
  ## 3.0.5
2
6
 
3
7
  - Fix: clearCaches now rechecks the rows that are already on screen, so resetting the size cache does not leave items stuck in old positions.
package/animated.d.ts CHANGED
@@ -8,10 +8,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
8
8
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
9
9
  }
10
10
 
11
- 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}`;
11
+ 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}`;
12
12
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
13
13
  type ListenerTypeValueMap = {
14
14
  activeStickyIndex: number;
15
+ alignItemsAtEndPadding: number;
15
16
  anchoredEndSpaceSize: number;
16
17
  animatedScrollY: any;
17
18
  debugComputedScroll: number;
@@ -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/keyboard.d.ts CHANGED
@@ -10,10 +10,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
10
10
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
11
11
  }
12
12
 
13
- 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}`;
13
+ 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}`;
14
14
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
15
15
  type ListenerTypeValueMap = {
16
16
  activeStickyIndex: number;
17
+ alignItemsAtEndPadding: number;
17
18
  anchoredEndSpaceSize: number;
18
19
  animatedScrollY: any;
19
20
  debugComputedScroll: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.0.5",
3
+ "version": "3.0.6",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,
package/react-native.d.ts CHANGED
@@ -8,10 +8,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
8
8
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
9
9
  }
10
10
 
11
- 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}`;
11
+ 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}`;
12
12
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
13
13
  type ListenerTypeValueMap = {
14
14
  activeStickyIndex: number;
15
+ alignItemsAtEndPadding: number;
15
16
  anchoredEndSpaceSize: number;
16
17
  animatedScrollY: any;
17
18
  debugComputedScroll: number;
package/react-native.js CHANGED
@@ -154,6 +154,7 @@ function StateProvider({ children }) {
154
154
  positionListeners: /* @__PURE__ */ new Map(),
155
155
  state: void 0,
156
156
  values: /* @__PURE__ */ new Map([
157
+ ["alignItemsAtEndPadding", 0],
157
158
  ["stylePaddingTop", 0],
158
159
  ["headerSize", 0],
159
160
  ["numContainers", 0],
@@ -296,15 +297,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
296
297
 
297
298
  // src/state/getContentSize.ts
298
299
  function getContentSize(ctx) {
299
- var _a3;
300
+ var _a3, _b;
300
301
  const { values, state } = ctx;
301
302
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
302
303
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
304
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
303
305
  const headerSize = values.get("headerSize") || 0;
304
306
  const footerSize = values.get("footerSize") || 0;
305
307
  const contentInsetBottom = getContentInsetEnd(ctx);
306
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
307
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
308
+ const totalSize = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize");
309
+ return headerSize + footerSize + totalSize + stylePaddingTop + alignItemsAtEndPadding + stylePaddingBottom + (contentInsetBottom || 0);
308
310
  }
309
311
 
310
312
  // src/components/DebugView.tsx
@@ -479,8 +481,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
479
481
  ...rest
480
482
  }) {
481
483
  const ctx = useStateContext();
482
- const [position = POSITION_OUT_OF_VIEW, headerSize = 0, stylePaddingTop = 0, itemKey, _totalSize = 0] = useArr$([
484
+ const [
485
+ position = POSITION_OUT_OF_VIEW,
486
+ alignItemsAtEndPadding = 0,
487
+ headerSize = 0,
488
+ stylePaddingTop = 0,
489
+ itemKey,
490
+ _totalSize = 0
491
+ ] = useArr$([
483
492
  `containerPosition${id}`,
493
+ "alignItemsAtEndPadding",
484
494
  "headerSize",
485
495
  "stylePaddingTop",
486
496
  `containerItemKey${id}`,
@@ -494,7 +504,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
494
504
  var _a3;
495
505
  if (animatedScrollY) {
496
506
  const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
497
- const stickyStart = position + headerSize + stylePaddingTop - stickyConfigOffset;
507
+ const stickyStart = position + headerSize + stylePaddingTop + alignItemsAtEndPadding - stickyConfigOffset;
498
508
  let nextStickyPosition;
499
509
  if (pushLimit !== void 0) {
500
510
  if (pushLimit <= position) {
@@ -517,7 +527,15 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
517
527
  }
518
528
  return horizontal ? [{ translateX: nextStickyPosition }] : [{ translateY: nextStickyPosition }];
519
529
  }
520
- }, [animatedScrollY, headerSize, position, pushLimit, stylePaddingTop, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
530
+ }, [
531
+ alignItemsAtEndPadding,
532
+ animatedScrollY,
533
+ headerSize,
534
+ position,
535
+ pushLimit,
536
+ stylePaddingTop,
537
+ stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset
538
+ ]);
521
539
  const viewStyle = React2__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
522
540
  const renderStickyHeaderBackdrop = React2__namespace.useMemo(() => {
523
541
  if (!(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)) {
@@ -1174,6 +1192,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1174
1192
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1175
1193
  return /* @__PURE__ */ React2__namespace.createElement("div", { style }, null);
1176
1194
  }
1195
+
1196
+ // src/core/updateContentMetrics.ts
1197
+ function getRawContentLength(ctx) {
1198
+ var _a3, _b, _c;
1199
+ const { state, values } = ctx;
1200
+ 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);
1201
+ }
1202
+ function getAlignItemsAtEndPadding(ctx) {
1203
+ const { state } = ctx;
1204
+ const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1205
+ return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1206
+ }
1207
+ function updateContentMetrics(ctx) {
1208
+ const nextPadding = getAlignItemsAtEndPadding(ctx);
1209
+ if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1210
+ set$(ctx, "alignItemsAtEndPadding", nextPadding);
1211
+ }
1212
+ }
1213
+ function setContentLengthSignal(ctx, signalName, size) {
1214
+ if (peek$(ctx, signalName) !== size) {
1215
+ set$(ctx, signalName, size);
1216
+ updateContentMetrics(ctx);
1217
+ }
1218
+ }
1219
+ function setHeaderSize(ctx, size) {
1220
+ setContentLengthSignal(ctx, "headerSize", size);
1221
+ }
1222
+ function setFooterSize(ctx, size) {
1223
+ setContentLengthSignal(ctx, "footerSize", size);
1224
+ }
1225
+ function areInsetsEqual(left, right) {
1226
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
1227
+ 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);
1228
+ }
1229
+ function setContentInsetOverride(ctx, inset) {
1230
+ const { state } = ctx;
1231
+ const previousInset = state.contentInsetOverride;
1232
+ const nextInset = inset != null ? inset : void 0;
1233
+ const didChange = !areInsetsEqual(previousInset, nextInset);
1234
+ state.contentInsetOverride = nextInset;
1235
+ if (didChange) {
1236
+ updateContentMetrics(ctx);
1237
+ }
1238
+ return didChange;
1239
+ }
1177
1240
  function useLatestRef(value) {
1178
1241
  const ref = React2__namespace.useRef(value);
1179
1242
  ref.current = value;
@@ -1232,7 +1295,7 @@ var ListComponent = typedMemo(function ListComponent2({
1232
1295
  }) {
1233
1296
  const ctx = useStateContext();
1234
1297
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1235
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1298
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1236
1299
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1237
1300
  horizontal,
1238
1301
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1246,23 +1309,23 @@ var ListComponent = typedMemo(function ListComponent2({
1246
1309
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1247
1310
  React2.useLayoutEffect(() => {
1248
1311
  if (!ListHeaderComponent) {
1249
- set$(ctx, "headerSize", 0);
1312
+ setHeaderSize(ctx, 0);
1250
1313
  }
1251
1314
  if (!ListFooterComponent) {
1252
- set$(ctx, "footerSize", 0);
1315
+ setFooterSize(ctx, 0);
1253
1316
  }
1254
1317
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1255
1318
  const onLayoutHeader = React2.useCallback(
1256
1319
  (rect) => {
1257
1320
  const size = rect[horizontal ? "width" : "height"];
1258
- set$(ctx, "headerSize", size);
1321
+ setHeaderSize(ctx, size);
1259
1322
  },
1260
1323
  [ctx, horizontal]
1261
1324
  );
1262
1325
  const onLayoutFooterInternal = React2.useCallback(
1263
1326
  (rect, fromLayoutEffect) => {
1264
1327
  const size = rect[horizontal ? "width" : "height"];
1265
- set$(ctx, "footerSize", size);
1328
+ setFooterSize(ctx, size);
1266
1329
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1267
1330
  },
1268
1331
  [ctx, horizontal, onLayoutFooter]
@@ -1290,6 +1353,13 @@ var ListComponent = typedMemo(function ListComponent2({
1290
1353
  /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
1291
1354
  ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1292
1355
  ListEmptyComponent && getComponent(ListEmptyComponent),
1356
+ alignItemsAtEndPadding > 0 && /* @__PURE__ */ React2__namespace.createElement(
1357
+ View,
1358
+ {
1359
+ style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
1360
+ },
1361
+ null
1362
+ ),
1293
1363
  canRender && !ListEmptyComponent && /* @__PURE__ */ React2__namespace.createElement(
1294
1364
  Containers,
1295
1365
  {
@@ -1781,7 +1851,7 @@ function calculateOffsetForIndex(ctx, index) {
1781
1851
 
1782
1852
  // src/core/getTopOffsetAdjustment.ts
1783
1853
  function getTopOffsetAdjustment(ctx) {
1784
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1854
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
1785
1855
  }
1786
1856
 
1787
1857
  // src/utils/getId.ts
@@ -1819,6 +1889,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1819
1889
  if (notifyTotalSize) {
1820
1890
  set$(ctx, "totalSize", totalSize);
1821
1891
  }
1892
+ updateContentMetrics(ctx);
1822
1893
  }
1823
1894
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1824
1895
  set$(ctx, "totalSize", totalSize);
@@ -4166,7 +4237,7 @@ function areViewabilityAmountTokensEqual(prev, next) {
4166
4237
  }
4167
4238
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4168
4239
  const { sizes, scroll: scrollState } = state;
4169
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
4240
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
4170
4241
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4171
4242
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4172
4243
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -4617,7 +4688,7 @@ function calculateItemsInView(ctx, params = {}) {
4617
4688
  return;
4618
4689
  }
4619
4690
  let totalSize = getContentSize(ctx);
4620
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
4691
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
4621
4692
  const numColumns = peek$(ctx, "numColumns");
4622
4693
  const speed = getScrollVelocity(state);
4623
4694
  const scrollExtra = 0;
@@ -5157,6 +5228,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5157
5228
  if (didChange) {
5158
5229
  state.scrollLength = scrollLength;
5159
5230
  state.otherAxisSize = otherAxisSize;
5231
+ updateContentMetrics(ctx);
5160
5232
  state.lastBatchingAction = Date.now();
5161
5233
  state.scrollForNextCalculateItemsInView = void 0;
5162
5234
  if (scrollLength > 0) {
@@ -5844,10 +5916,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5844
5916
  startBuffered: state.startBuffered
5845
5917
  }),
5846
5918
  reportContentInset: (inset) => {
5847
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5848
- const previousInset = state.contentInsetOverride;
5849
- state.contentInsetOverride = inset != null ? inset : void 0;
5850
- 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);
5919
+ const didChange = setContentInsetOverride(ctx, inset);
5851
5920
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5852
5921
  if (didChange) {
5853
5922
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6203,10 +6272,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6203
6272
  ...restProps
6204
6273
  } = rest;
6205
6274
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6206
- const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6275
+ const useAlignItemsAtEndPadding = alignItemsAtEnd && !horizontal && (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null && dataProp.length > 0;
6276
+ const shouldFlexGrow = alignItemsAtEnd && !useAlignItemsAtEndPadding && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6207
6277
  const contentContainerStyle = {
6208
6278
  ...contentContainerStyleBase,
6209
- ...alignItemsAtEnd ? {
6279
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6210
6280
  display: "flex",
6211
6281
  flexDirection: horizontal ? "row" : "column",
6212
6282
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6370,6 +6440,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6370
6440
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6371
6441
  state.props = {
6372
6442
  alignItemsAtEnd,
6443
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6373
6444
  alwaysRender,
6374
6445
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6375
6446
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -6427,6 +6498,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6427
6498
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
6428
6499
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
6429
6500
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
6501
+ updateContentMetrics(ctx);
6430
6502
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
6431
6503
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
6432
6504
  if (state.scroll < 0) {
@@ -6550,7 +6622,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6550
6622
  }, [snapToIndices]);
6551
6623
  React2.useLayoutEffect(
6552
6624
  () => initializeStateVars(true),
6553
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
6625
+ [
6626
+ dataVersion,
6627
+ memoizedLastItemKeys.join(","),
6628
+ numColumnsProp,
6629
+ stylePaddingBottomState,
6630
+ stylePaddingTopState,
6631
+ useAlignItemsAtEndPadding
6632
+ ]
6554
6633
  );
6555
6634
  React2.useLayoutEffect(() => {
6556
6635
  const {
package/react-native.mjs CHANGED
@@ -133,6 +133,7 @@ function StateProvider({ children }) {
133
133
  positionListeners: /* @__PURE__ */ new Map(),
134
134
  state: void 0,
135
135
  values: /* @__PURE__ */ new Map([
136
+ ["alignItemsAtEndPadding", 0],
136
137
  ["stylePaddingTop", 0],
137
138
  ["headerSize", 0],
138
139
  ["numContainers", 0],
@@ -275,15 +276,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
275
276
 
276
277
  // src/state/getContentSize.ts
277
278
  function getContentSize(ctx) {
278
- var _a3;
279
+ var _a3, _b;
279
280
  const { values, state } = ctx;
280
281
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
281
282
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
283
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
282
284
  const headerSize = values.get("headerSize") || 0;
283
285
  const footerSize = values.get("footerSize") || 0;
284
286
  const contentInsetBottom = getContentInsetEnd(ctx);
285
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
286
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
287
+ const totalSize = (_b = (_a3 = state.pendingTotalSize) != null ? _a3 : state.totalSize) != null ? _b : values.get("totalSize");
288
+ return headerSize + footerSize + totalSize + stylePaddingTop + alignItemsAtEndPadding + stylePaddingBottom + (contentInsetBottom || 0);
287
289
  }
288
290
 
289
291
  // src/components/DebugView.tsx
@@ -458,8 +460,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
458
460
  ...rest
459
461
  }) {
460
462
  const ctx = useStateContext();
461
- const [position = POSITION_OUT_OF_VIEW, headerSize = 0, stylePaddingTop = 0, itemKey, _totalSize = 0] = useArr$([
463
+ const [
464
+ position = POSITION_OUT_OF_VIEW,
465
+ alignItemsAtEndPadding = 0,
466
+ headerSize = 0,
467
+ stylePaddingTop = 0,
468
+ itemKey,
469
+ _totalSize = 0
470
+ ] = useArr$([
462
471
  `containerPosition${id}`,
472
+ "alignItemsAtEndPadding",
463
473
  "headerSize",
464
474
  "stylePaddingTop",
465
475
  `containerItemKey${id}`,
@@ -473,7 +483,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
473
483
  var _a3;
474
484
  if (animatedScrollY) {
475
485
  const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
476
- const stickyStart = position + headerSize + stylePaddingTop - stickyConfigOffset;
486
+ const stickyStart = position + headerSize + stylePaddingTop + alignItemsAtEndPadding - stickyConfigOffset;
477
487
  let nextStickyPosition;
478
488
  if (pushLimit !== void 0) {
479
489
  if (pushLimit <= position) {
@@ -496,7 +506,15 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
496
506
  }
497
507
  return horizontal ? [{ translateX: nextStickyPosition }] : [{ translateY: nextStickyPosition }];
498
508
  }
499
- }, [animatedScrollY, headerSize, position, pushLimit, stylePaddingTop, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
509
+ }, [
510
+ alignItemsAtEndPadding,
511
+ animatedScrollY,
512
+ headerSize,
513
+ position,
514
+ pushLimit,
515
+ stylePaddingTop,
516
+ stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset
517
+ ]);
500
518
  const viewStyle = React2.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
501
519
  const renderStickyHeaderBackdrop = React2.useMemo(() => {
502
520
  if (!(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)) {
@@ -1153,6 +1171,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1153
1171
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1154
1172
  return /* @__PURE__ */ React2.createElement("div", { style }, null);
1155
1173
  }
1174
+
1175
+ // src/core/updateContentMetrics.ts
1176
+ function getRawContentLength(ctx) {
1177
+ var _a3, _b, _c;
1178
+ const { state, values } = ctx;
1179
+ 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);
1180
+ }
1181
+ function getAlignItemsAtEndPadding(ctx) {
1182
+ const { state } = ctx;
1183
+ const shouldPad = !!state.props.alignItemsAtEndPaddingEnabled && !state.props.horizontal && state.props.data.length > 0 && state.scrollLength > 0;
1184
+ return shouldPad ? Math.max(0, state.scrollLength - getRawContentLength(ctx) - getContentInsetEnd(ctx)) : 0;
1185
+ }
1186
+ function updateContentMetrics(ctx) {
1187
+ const nextPadding = getAlignItemsAtEndPadding(ctx);
1188
+ if (peek$(ctx, "alignItemsAtEndPadding") !== nextPadding) {
1189
+ set$(ctx, "alignItemsAtEndPadding", nextPadding);
1190
+ }
1191
+ }
1192
+ function setContentLengthSignal(ctx, signalName, size) {
1193
+ if (peek$(ctx, signalName) !== size) {
1194
+ set$(ctx, signalName, size);
1195
+ updateContentMetrics(ctx);
1196
+ }
1197
+ }
1198
+ function setHeaderSize(ctx, size) {
1199
+ setContentLengthSignal(ctx, "headerSize", size);
1200
+ }
1201
+ function setFooterSize(ctx, size) {
1202
+ setContentLengthSignal(ctx, "footerSize", size);
1203
+ }
1204
+ function areInsetsEqual(left, right) {
1205
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
1206
+ 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);
1207
+ }
1208
+ function setContentInsetOverride(ctx, inset) {
1209
+ const { state } = ctx;
1210
+ const previousInset = state.contentInsetOverride;
1211
+ const nextInset = inset != null ? inset : void 0;
1212
+ const didChange = !areInsetsEqual(previousInset, nextInset);
1213
+ state.contentInsetOverride = nextInset;
1214
+ if (didChange) {
1215
+ updateContentMetrics(ctx);
1216
+ }
1217
+ return didChange;
1218
+ }
1156
1219
  function useLatestRef(value) {
1157
1220
  const ref = React2.useRef(value);
1158
1221
  ref.current = value;
@@ -1211,7 +1274,7 @@ var ListComponent = typedMemo(function ListComponent2({
1211
1274
  }) {
1212
1275
  const ctx = useStateContext();
1213
1276
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1214
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1277
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1215
1278
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1216
1279
  horizontal,
1217
1280
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1225,23 +1288,23 @@ var ListComponent = typedMemo(function ListComponent2({
1225
1288
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1226
1289
  useLayoutEffect(() => {
1227
1290
  if (!ListHeaderComponent) {
1228
- set$(ctx, "headerSize", 0);
1291
+ setHeaderSize(ctx, 0);
1229
1292
  }
1230
1293
  if (!ListFooterComponent) {
1231
- set$(ctx, "footerSize", 0);
1294
+ setFooterSize(ctx, 0);
1232
1295
  }
1233
1296
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1234
1297
  const onLayoutHeader = useCallback(
1235
1298
  (rect) => {
1236
1299
  const size = rect[horizontal ? "width" : "height"];
1237
- set$(ctx, "headerSize", size);
1300
+ setHeaderSize(ctx, size);
1238
1301
  },
1239
1302
  [ctx, horizontal]
1240
1303
  );
1241
1304
  const onLayoutFooterInternal = useCallback(
1242
1305
  (rect, fromLayoutEffect) => {
1243
1306
  const size = rect[horizontal ? "width" : "height"];
1244
- set$(ctx, "footerSize", size);
1307
+ setFooterSize(ctx, size);
1245
1308
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1246
1309
  },
1247
1310
  [ctx, horizontal, onLayoutFooter]
@@ -1269,6 +1332,13 @@ var ListComponent = typedMemo(function ListComponent2({
1269
1332
  /* @__PURE__ */ React2.createElement(ScrollAdjust, null),
1270
1333
  ListHeaderComponent && /* @__PURE__ */ React2.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1271
1334
  ListEmptyComponent && getComponent(ListEmptyComponent),
1335
+ alignItemsAtEndPadding > 0 && /* @__PURE__ */ React2.createElement(
1336
+ View,
1337
+ {
1338
+ style: horizontal ? { flexShrink: 0, width: alignItemsAtEndPadding } : { flexShrink: 0, height: alignItemsAtEndPadding }
1339
+ },
1340
+ null
1341
+ ),
1272
1342
  canRender && !ListEmptyComponent && /* @__PURE__ */ React2.createElement(
1273
1343
  Containers,
1274
1344
  {
@@ -1760,7 +1830,7 @@ function calculateOffsetForIndex(ctx, index) {
1760
1830
 
1761
1831
  // src/core/getTopOffsetAdjustment.ts
1762
1832
  function getTopOffsetAdjustment(ctx) {
1763
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1833
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
1764
1834
  }
1765
1835
 
1766
1836
  // src/utils/getId.ts
@@ -1798,6 +1868,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1798
1868
  if (notifyTotalSize) {
1799
1869
  set$(ctx, "totalSize", totalSize);
1800
1870
  }
1871
+ updateContentMetrics(ctx);
1801
1872
  }
1802
1873
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1803
1874
  set$(ctx, "totalSize", totalSize);
@@ -4145,7 +4216,7 @@ function areViewabilityAmountTokensEqual(prev, next) {
4145
4216
  }
4146
4217
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4147
4218
  const { sizes, scroll: scrollState } = state;
4148
- const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
4219
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
4149
4220
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4150
4221
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4151
4222
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -4596,7 +4667,7 @@ function calculateItemsInView(ctx, params = {}) {
4596
4667
  return;
4597
4668
  }
4598
4669
  let totalSize = getContentSize(ctx);
4599
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
4670
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
4600
4671
  const numColumns = peek$(ctx, "numColumns");
4601
4672
  const speed = getScrollVelocity(state);
4602
4673
  const scrollExtra = 0;
@@ -5136,6 +5207,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5136
5207
  if (didChange) {
5137
5208
  state.scrollLength = scrollLength;
5138
5209
  state.otherAxisSize = otherAxisSize;
5210
+ updateContentMetrics(ctx);
5139
5211
  state.lastBatchingAction = Date.now();
5140
5212
  state.scrollForNextCalculateItemsInView = void 0;
5141
5213
  if (scrollLength > 0) {
@@ -5823,10 +5895,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5823
5895
  startBuffered: state.startBuffered
5824
5896
  }),
5825
5897
  reportContentInset: (inset) => {
5826
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5827
- const previousInset = state.contentInsetOverride;
5828
- state.contentInsetOverride = inset != null ? inset : void 0;
5829
- 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);
5898
+ const didChange = setContentInsetOverride(ctx, inset);
5830
5899
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5831
5900
  if (didChange) {
5832
5901
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6182,10 +6251,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6182
6251
  ...restProps
6183
6252
  } = rest;
6184
6253
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6185
- const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6254
+ const useAlignItemsAtEndPadding = alignItemsAtEnd && !horizontal && (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null && dataProp.length > 0;
6255
+ const shouldFlexGrow = alignItemsAtEnd && !useAlignItemsAtEndPadding && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
6186
6256
  const contentContainerStyle = {
6187
6257
  ...contentContainerStyleBase,
6188
- ...alignItemsAtEnd ? {
6258
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6189
6259
  display: "flex",
6190
6260
  flexDirection: horizontal ? "row" : "column",
6191
6261
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6349,6 +6419,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6349
6419
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6350
6420
  state.props = {
6351
6421
  alignItemsAtEnd,
6422
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6352
6423
  alwaysRender,
6353
6424
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6354
6425
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -6406,6 +6477,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6406
6477
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
6407
6478
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
6408
6479
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
6480
+ updateContentMetrics(ctx);
6409
6481
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
6410
6482
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
6411
6483
  if (state.scroll < 0) {
@@ -6529,7 +6601,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6529
6601
  }, [snapToIndices]);
6530
6602
  useLayoutEffect(
6531
6603
  () => initializeStateVars(true),
6532
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
6604
+ [
6605
+ dataVersion,
6606
+ memoizedLastItemKeys.join(","),
6607
+ numColumnsProp,
6608
+ stylePaddingBottomState,
6609
+ stylePaddingTopState,
6610
+ useAlignItemsAtEndPadding
6611
+ ]
6533
6612
  );
6534
6613
  useLayoutEffect(() => {
6535
6614
  const {
@@ -31,10 +31,11 @@ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
31
31
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
32
32
  }
33
33
 
34
- 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}`;
34
+ 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}`;
35
35
  type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "anchoredEndSpaceSize" | "footerSize" | "headerSize" | "isAtEnd" | "isAtStart" | "isNearEnd" | "isNearStart" | "isWithinMaintainScrollAtEndThreshold" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
36
36
  type ListenerTypeValueMap = {
37
37
  activeStickyIndex: number;
38
+ alignItemsAtEndPadding: number;
38
39
  anchoredEndSpaceSize: number;
39
40
  animatedScrollY: any;
40
41
  debugComputedScroll: number;