@legendapp/list 3.0.4 → 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-native.mjs CHANGED
@@ -122,6 +122,7 @@ function StateProvider({ children }) {
122
122
  const [value] = React2.useState(() => ({
123
123
  animatedScrollY: createAnimatedValue(0),
124
124
  columnWrapperStyle: void 0,
125
+ containerLayoutTriggers: /* @__PURE__ */ new Map(),
125
126
  contextNum: contextNum++,
126
127
  listeners: /* @__PURE__ */ new Map(),
127
128
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -132,6 +133,7 @@ function StateProvider({ children }) {
132
133
  positionListeners: /* @__PURE__ */ new Map(),
133
134
  state: void 0,
134
135
  values: /* @__PURE__ */ new Map([
136
+ ["alignItemsAtEndPadding", 0],
135
137
  ["stylePaddingTop", 0],
136
138
  ["headerSize", 0],
137
139
  ["numContainers", 0],
@@ -274,15 +276,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
274
276
 
275
277
  // src/state/getContentSize.ts
276
278
  function getContentSize(ctx) {
277
- var _a3;
279
+ var _a3, _b;
278
280
  const { values, state } = ctx;
279
281
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
280
282
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
283
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
281
284
  const headerSize = values.get("headerSize") || 0;
282
285
  const footerSize = values.get("footerSize") || 0;
283
286
  const contentInsetBottom = getContentInsetEnd(ctx);
284
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
285
- 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);
286
289
  }
287
290
 
288
291
  // src/components/DebugView.tsx
@@ -457,8 +460,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
457
460
  ...rest
458
461
  }) {
459
462
  const ctx = useStateContext();
460
- 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$([
461
471
  `containerPosition${id}`,
472
+ "alignItemsAtEndPadding",
462
473
  "headerSize",
463
474
  "stylePaddingTop",
464
475
  `containerItemKey${id}`,
@@ -472,7 +483,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
472
483
  var _a3;
473
484
  if (animatedScrollY) {
474
485
  const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
475
- const stickyStart = position + headerSize + stylePaddingTop - stickyConfigOffset;
486
+ const stickyStart = position + headerSize + stylePaddingTop + alignItemsAtEndPadding - stickyConfigOffset;
476
487
  let nextStickyPosition;
477
488
  if (pushLimit !== void 0) {
478
489
  if (pushLimit <= position) {
@@ -495,7 +506,15 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
495
506
  }
496
507
  return horizontal ? [{ translateX: nextStickyPosition }] : [{ translateY: nextStickyPosition }];
497
508
  }
498
- }, [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
+ ]);
499
518
  const viewStyle = React2.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
500
519
  const renderStickyHeaderBackdrop = React2.useMemo(() => {
501
520
  if (!(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)) {
@@ -540,9 +559,6 @@ function roundSize(size) {
540
559
  function isNullOrUndefined(value) {
541
560
  return value === null || value === void 0;
542
561
  }
543
- function comparatorDefault(a, b) {
544
- return a - b;
545
- }
546
562
  function getPadding(s, type) {
547
563
  var _a3, _b, _c;
548
564
  const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
@@ -895,18 +911,6 @@ var Container = typedMemo(function Container2({
895
911
  [itemKey, data, extraData]
896
912
  );
897
913
  const { index, renderedItem } = renderedItemInfo || {};
898
- const contextValue = useMemo(() => {
899
- ctx.viewRefs.set(id, ref);
900
- return {
901
- containerId: id,
902
- index,
903
- itemKey,
904
- triggerLayout: () => {
905
- forceLayoutRender((v) => v + 1);
906
- },
907
- value: data
908
- };
909
- }, [id, itemKey, index, data]);
910
914
  const onLayoutChange = useCallback((rectangle) => {
911
915
  var _a3, _b;
912
916
  const {
@@ -956,6 +960,27 @@ var Container = typedMemo(function Container2({
956
960
  });
957
961
  }
958
962
  }, []);
963
+ const triggerLayout = useCallback(() => {
964
+ forceLayoutRender((v) => v + 1);
965
+ }, []);
966
+ const contextValue = useMemo(() => {
967
+ ctx.viewRefs.set(id, ref);
968
+ return {
969
+ containerId: id,
970
+ index,
971
+ itemKey,
972
+ triggerLayout,
973
+ value: data
974
+ };
975
+ }, [id, itemKey, index, data, triggerLayout]);
976
+ useLayoutEffect(() => {
977
+ ctx.containerLayoutTriggers.set(id, triggerLayout);
978
+ return () => {
979
+ if (ctx.containerLayoutTriggers.get(id) === triggerLayout) {
980
+ ctx.containerLayoutTriggers.delete(id);
981
+ }
982
+ };
983
+ }, [ctx, id, triggerLayout]);
959
984
  const { onLayout } = useOnLayoutSync(
960
985
  {
961
986
  onLayoutChange,
@@ -1146,6 +1171,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1146
1171
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1147
1172
  return /* @__PURE__ */ React2.createElement("div", { style }, null);
1148
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
+ }
1149
1219
  function useLatestRef(value) {
1150
1220
  const ref = React2.useRef(value);
1151
1221
  ref.current = value;
@@ -1204,7 +1274,7 @@ var ListComponent = typedMemo(function ListComponent2({
1204
1274
  }) {
1205
1275
  const ctx = useStateContext();
1206
1276
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1207
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1277
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1208
1278
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1209
1279
  horizontal,
1210
1280
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1218,23 +1288,23 @@ var ListComponent = typedMemo(function ListComponent2({
1218
1288
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1219
1289
  useLayoutEffect(() => {
1220
1290
  if (!ListHeaderComponent) {
1221
- set$(ctx, "headerSize", 0);
1291
+ setHeaderSize(ctx, 0);
1222
1292
  }
1223
1293
  if (!ListFooterComponent) {
1224
- set$(ctx, "footerSize", 0);
1294
+ setFooterSize(ctx, 0);
1225
1295
  }
1226
1296
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1227
1297
  const onLayoutHeader = useCallback(
1228
1298
  (rect) => {
1229
1299
  const size = rect[horizontal ? "width" : "height"];
1230
- set$(ctx, "headerSize", size);
1300
+ setHeaderSize(ctx, size);
1231
1301
  },
1232
1302
  [ctx, horizontal]
1233
1303
  );
1234
1304
  const onLayoutFooterInternal = useCallback(
1235
1305
  (rect, fromLayoutEffect) => {
1236
1306
  const size = rect[horizontal ? "width" : "height"];
1237
- set$(ctx, "footerSize", size);
1307
+ setFooterSize(ctx, size);
1238
1308
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1239
1309
  },
1240
1310
  [ctx, horizontal, onLayoutFooter]
@@ -1262,6 +1332,13 @@ var ListComponent = typedMemo(function ListComponent2({
1262
1332
  /* @__PURE__ */ React2.createElement(ScrollAdjust, null),
1263
1333
  ListHeaderComponent && /* @__PURE__ */ React2.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1264
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
+ ),
1265
1342
  canRender && !ListEmptyComponent && /* @__PURE__ */ React2.createElement(
1266
1343
  Containers,
1267
1344
  {
@@ -1753,7 +1830,7 @@ function calculateOffsetForIndex(ctx, index) {
1753
1830
 
1754
1831
  // src/core/getTopOffsetAdjustment.ts
1755
1832
  function getTopOffsetAdjustment(ctx) {
1756
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1833
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
1757
1834
  }
1758
1835
 
1759
1836
  // src/utils/getId.ts
@@ -1791,6 +1868,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1791
1868
  if (notifyTotalSize) {
1792
1869
  set$(ctx, "totalSize", totalSize);
1793
1870
  }
1871
+ updateContentMetrics(ctx);
1794
1872
  }
1795
1873
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1796
1874
  set$(ctx, "totalSize", totalSize);
@@ -1810,14 +1888,14 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
1810
1888
  }
1811
1889
 
1812
1890
  // src/utils/getItemSize.ts
1813
- function getKnownOrFixedSize(ctx, key, index, data) {
1814
- var _a3;
1891
+ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
1892
+ var _a3, _b;
1815
1893
  const state = ctx.state;
1816
1894
  const { getFixedItemSize, getItemType } = state.props;
1817
1895
  let size = key ? state.sizesKnown.get(key) : void 0;
1818
1896
  if (size === void 0 && key && getFixedItemSize) {
1819
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1820
- size = getFixedItemSize(data, index, itemType);
1897
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1898
+ size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
1821
1899
  if (size !== void 0) {
1822
1900
  state.sizesKnown.set(key, size);
1823
1901
  }
@@ -1836,8 +1914,8 @@ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
1836
1914
  }
1837
1915
  return true;
1838
1916
  }
1839
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
1840
- var _a3, _b, _c;
1917
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize, resolved) {
1918
+ var _a3, _b, _c, _d;
1841
1919
  const state = ctx.state;
1842
1920
  const {
1843
1921
  sizes,
@@ -1856,14 +1934,14 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1856
1934
  return renderedSize;
1857
1935
  }
1858
1936
  }
1859
- size = getKnownOrFixedSize(ctx, key, index, data);
1937
+ size = getKnownOrFixedSize(ctx, key, index, data, resolved);
1860
1938
  if (size !== void 0) {
1861
1939
  setSize(ctx, key, size, notifyTotalSize);
1862
1940
  return size;
1863
1941
  }
1864
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1942
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1865
1943
  if (useAverageSize && !scrollingTo) {
1866
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1944
+ const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
1867
1945
  if (averageSizeForType !== void 0) {
1868
1946
  size = roundSize(averageSizeForType);
1869
1947
  }
@@ -1872,7 +1950,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1872
1950
  return renderedSize;
1873
1951
  }
1874
1952
  if (size === void 0 && useAverageSize && scrollingTo) {
1875
- const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
1953
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
1876
1954
  if (averageSizeForType !== void 0) {
1877
1955
  size = roundSize(averageSizeForType);
1878
1956
  }
@@ -2579,8 +2657,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2579
2657
  if ((options == null ? void 0 : options.markHasScrolled) !== false) {
2580
2658
  state.hasScrolled = true;
2581
2659
  }
2582
- state.lastBatchingAction = Date.now();
2583
2660
  const currentTime = Date.now();
2661
+ state.lastBatchingAction = currentTime;
2584
2662
  const adjust = scrollAdjustHandler.getAdjust();
2585
2663
  const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
2586
2664
  if (adjustChanged) {
@@ -2889,26 +2967,22 @@ function advanceCurrentInitialScrollSession(ctx, options) {
2889
2967
  }
2890
2968
 
2891
2969
  // src/utils/checkAllSizesKnown.ts
2892
- function isNullOrUndefined2(value) {
2893
- return value === null || value === void 0;
2894
- }
2895
- function getMountedIndicesInRange(state, start, end) {
2896
- if (!isNullOrUndefined2(end) && !isNullOrUndefined2(start) && start >= 0 && end >= 0) {
2897
- return Array.from(state.containerItemKeys.keys()).map((key) => state.indexByKey.get(key)).filter((index) => index !== void 0 && index >= start && index <= end).sort((a, b) => a - b);
2970
+ function checkAllSizesKnown(state, start, end) {
2971
+ if (start == null || end == null || start < 0 || end < start) {
2972
+ return false;
2898
2973
  }
2899
- return [];
2900
- }
2901
- function getMountedBufferedIndices(state) {
2902
- return getMountedIndicesInRange(state, state.startBuffered, state.endBuffered);
2903
- }
2904
- function getMountedNoBufferIndices(state) {
2905
- return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2906
- }
2907
- function checkAllSizesKnown(state, indices) {
2908
- return indices.length > 0 && indices.every((index) => {
2909
- const key = getId(state, index);
2910
- return key !== void 0 && state.sizesKnown.has(key);
2911
- });
2974
+ let hasMountedIndex = false;
2975
+ for (const key of state.containerItemKeys.keys()) {
2976
+ const index = state.indexByKey.get(key);
2977
+ if (index !== void 0 && index >= start && index <= end) {
2978
+ hasMountedIndex = true;
2979
+ const id = getId(state, index);
2980
+ if (id === void 0 || !state.sizesKnown.has(id)) {
2981
+ return false;
2982
+ }
2983
+ }
2984
+ }
2985
+ return hasMountedIndex;
2912
2986
  }
2913
2987
 
2914
2988
  // src/core/bootstrapInitialScroll.ts
@@ -3409,8 +3483,7 @@ function evaluateBootstrapInitialScroll(ctx) {
3409
3483
  bootstrapInitialScroll.targetIndexSeed = void 0;
3410
3484
  }
3411
3485
  const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
3412
- const mountedBufferedIndices = getMountedBufferedIndices(state);
3413
- const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
3486
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
3414
3487
  const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
3415
3488
  const { data } = state.props;
3416
3489
  const visibleIndices = getBootstrapRevealVisibleIndices({
@@ -3841,7 +3914,14 @@ function updateSnapToOffsets(ctx) {
3841
3914
  }
3842
3915
 
3843
3916
  // src/core/updateItemPositions.ts
3844
- function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP, optimizeForVisibleWindow = false } = {
3917
+ function updateItemPositions(ctx, dataChanged, {
3918
+ doMVCP,
3919
+ forceFullUpdate = false,
3920
+ optimizeForVisibleWindow = false,
3921
+ scrollBottomBuffered,
3922
+ scrollVelocity,
3923
+ startIndex
3924
+ } = {
3845
3925
  doMVCP: false,
3846
3926
  forceFullUpdate: false,
3847
3927
  optimizeForVisibleWindow: false,
@@ -3868,7 +3948,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3868
3948
  const extraData = peek$(ctx, "extraData");
3869
3949
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
3870
3950
  const lastScrollDelta = state.lastScrollDelta;
3871
- const velocity = getScrollVelocity(state);
3951
+ const velocity = scrollVelocity != null ? scrollVelocity : getScrollVelocity(state);
3872
3952
  const shouldOptimize = !forceFullUpdate && !dataChanged && (optimizeForVisibleWindow || Math.abs(velocity) > 0 || Platform.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
3873
3953
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3874
3954
  const useAverageSize = true;
@@ -4048,25 +4128,28 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4048
4128
  const configId = viewabilityConfig.id;
4049
4129
  const viewabilityState = ensureViewabilityState(ctx, configId);
4050
4130
  const { viewableItems: previousViewableItems, start, end, startBuffered, endBuffered } = viewabilityState;
4051
- const viewabilityTokens = /* @__PURE__ */ new Map();
4131
+ let staleViewabilityAmountIds;
4052
4132
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4053
- viewabilityTokens.set(
4133
+ const nextValue = computeViewability(
4134
+ state,
4135
+ ctx,
4136
+ viewabilityConfig,
4054
4137
  containerId,
4055
- computeViewability(
4056
- state,
4057
- ctx,
4058
- viewabilityConfig,
4059
- containerId,
4060
- value.key,
4061
- scrollSize,
4062
- value.item,
4063
- value.index
4064
- )
4138
+ value.key,
4139
+ scrollSize,
4140
+ value.item,
4141
+ value.index
4065
4142
  );
4143
+ if (nextValue.sizeVisible < 0) {
4144
+ staleViewabilityAmountIds != null ? staleViewabilityAmountIds : staleViewabilityAmountIds = [];
4145
+ staleViewabilityAmountIds.push(containerId);
4146
+ }
4066
4147
  }
4067
4148
  const changed = [];
4149
+ const previousViewableKeys = /* @__PURE__ */ new Set();
4068
4150
  if (previousViewableItems) {
4069
4151
  for (const viewToken of previousViewableItems) {
4152
+ previousViewableKeys.add(viewToken.key);
4070
4153
  const containerId = findContainerId(ctx, viewToken.key);
4071
4154
  if (!checkIsViewable(
4072
4155
  state,
@@ -4098,7 +4181,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4098
4181
  key
4099
4182
  };
4100
4183
  viewableItems.push(viewToken);
4101
- if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
4184
+ if (!previousViewableKeys.has(viewToken.key)) {
4102
4185
  changed.push(viewToken);
4103
4186
  }
4104
4187
  }
@@ -4119,24 +4202,21 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4119
4202
  onViewableItemsChanged({ changed, end, endBuffered, start, startBuffered, viewableItems });
4120
4203
  }
4121
4204
  }
4122
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4123
- if (value.sizeVisible < 0) {
4124
- ctx.mapViewabilityAmountValues.delete(containerId);
4205
+ if (staleViewabilityAmountIds) {
4206
+ for (const containerId of staleViewabilityAmountIds) {
4207
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
4208
+ if (value && value.sizeVisible < 0) {
4209
+ ctx.mapViewabilityAmountValues.delete(containerId);
4210
+ }
4125
4211
  }
4126
4212
  }
4127
4213
  }
4128
- function shallowEqual(prev, next) {
4129
- if (!prev) return false;
4130
- const keys = Object.keys(next);
4131
- for (let i = 0; i < keys.length; i++) {
4132
- const k = keys[i];
4133
- if (prev[k] !== next[k]) return false;
4134
- }
4135
- return true;
4214
+ function areViewabilityAmountTokensEqual(prev, next) {
4215
+ return !!prev && prev.containerId === next.containerId && prev.index === next.index && prev.isViewable === next.isViewable && prev.item === next.item && prev.key === next.key && prev.percentOfScroller === next.percentOfScroller && prev.percentVisible === next.percentVisible && prev.scrollSize === next.scrollSize && prev.size === next.size && prev.sizeVisible === next.sizeVisible;
4136
4216
  }
4137
4217
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4138
4218
  const { sizes, scroll: scrollState } = state;
4139
- 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);
4140
4220
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4141
4221
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4142
4222
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -4157,7 +4237,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4157
4237
  sizeVisible: -1
4158
4238
  };
4159
4239
  const prev2 = ctx.mapViewabilityAmountValues.get(containerId);
4160
- if (!shallowEqual(prev2, value2)) {
4240
+ if (!areViewabilityAmountTokensEqual(prev2, value2)) {
4161
4241
  ctx.mapViewabilityAmountValues.set(containerId, value2);
4162
4242
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4163
4243
  if (cb) {
@@ -4187,7 +4267,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4187
4267
  sizeVisible
4188
4268
  };
4189
4269
  const prev = ctx.mapViewabilityAmountValues.get(containerId);
4190
- if (!shallowEqual(prev, value)) {
4270
+ if (!areViewabilityAmountTokensEqual(prev, value)) {
4191
4271
  ctx.mapViewabilityAmountValues.set(containerId, value);
4192
4272
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4193
4273
  if (cb) {
@@ -4238,126 +4318,152 @@ function getExpandedContainerPoolSize(dataLength, numContainers) {
4238
4318
  }
4239
4319
 
4240
4320
  // src/utils/findAvailableContainers.ts
4241
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4321
+ function findAvailableContainers(ctx, needNewContainers, startBuffered, endBuffered, pendingRemoval, getRequiredItemType, protectedKeys) {
4322
+ const numNeeded = needNewContainers.length;
4323
+ if (numNeeded === 0) {
4324
+ return [];
4325
+ }
4242
4326
  const numContainers = peek$(ctx, "numContainers");
4243
4327
  const state = ctx.state;
4244
4328
  const { stickyContainerPool, containerItemTypes } = state;
4245
4329
  const shouldAvoidAssignedContainerReuse = state.props.recycleItems && !!state.props.positionComponentInternal;
4246
- const result = [];
4247
- const availableContainers = [];
4248
- const pendingRemovalSet = new Set(pendingRemoval);
4330
+ const allocations = [];
4331
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4249
4332
  let pendingRemovalChanged = false;
4333
+ let nextNewContainerIndex = numContainers;
4334
+ const usedContainers = /* @__PURE__ */ new Set();
4335
+ let availableContainers;
4250
4336
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet;
4251
- const stickyHeaderItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyHeaderIndicesSet.has(index))) || [];
4252
4337
  const canReuseContainer = (containerIndex, requiredType) => {
4253
4338
  if (!requiredType) return true;
4254
4339
  const existingType = containerItemTypes.get(containerIndex);
4255
4340
  if (!existingType) return true;
4256
4341
  return existingType === requiredType;
4257
4342
  };
4258
- const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
4259
- let typeIndex = 0;
4260
- for (let i = 0; i < stickyHeaderItemIndices.length; i++) {
4261
- const requiredType = neededTypes[typeIndex];
4262
- let foundContainer = false;
4263
- for (const containerIndex of stickyContainerPool) {
4264
- const key = peek$(ctx, `containerItemKey${containerIndex}`);
4265
- const isPendingRemoval = pendingRemovalSet.has(containerIndex);
4266
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
4267
- result.push(containerIndex);
4268
- if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
4269
- pendingRemovalChanged = true;
4270
- }
4271
- foundContainer = true;
4272
- if (requiredItemTypes) typeIndex++;
4273
- break;
4274
- }
4343
+ const pushAllocation = (itemIndex, itemType, containerIndex) => {
4344
+ allocations.push({
4345
+ containerIndex,
4346
+ itemIndex,
4347
+ itemType
4348
+ });
4349
+ usedContainers.add(containerIndex);
4350
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.delete(containerIndex)) {
4351
+ pendingRemovalChanged = true;
4275
4352
  }
4276
- if (!foundContainer) {
4277
- const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
4278
- result.push(newContainerIndex);
4353
+ };
4354
+ const pushNewContainer = (itemIndex, itemType, isSticky) => {
4355
+ const newContainerIndex = nextNewContainerIndex++;
4356
+ pushAllocation(itemIndex, itemType, newContainerIndex);
4357
+ if (isSticky) {
4279
4358
  stickyContainerPool.add(newContainerIndex);
4280
- if (requiredItemTypes) typeIndex++;
4281
4359
  }
4282
- }
4283
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4284
- if (stickyContainerPool.has(u)) {
4285
- continue;
4286
- }
4287
- const key = peek$(ctx, `containerItemKey${u}`);
4288
- const requiredType = neededTypes[typeIndex];
4289
- const isPending = key !== void 0 && pendingRemovalSet.has(u);
4290
- const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
4291
- if (canUse) {
4292
- if (isPending) {
4293
- pendingRemovalSet.delete(u);
4294
- pendingRemovalChanged = true;
4295
- }
4296
- result.push(u);
4297
- if (requiredItemTypes) {
4298
- typeIndex++;
4299
- }
4360
+ return newContainerIndex;
4361
+ };
4362
+ const canUseContainer = (containerIndex, itemType) => {
4363
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4364
+ return false;
4300
4365
  }
4301
- }
4302
- if (!shouldAvoidAssignedContainerReuse) {
4303
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4304
- if (stickyContainerPool.has(u)) {
4305
- continue;
4306
- }
4307
- const key = peek$(ctx, `containerItemKey${u}`);
4308
- if (key === void 0) continue;
4309
- if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4310
- const index = state.indexByKey.get(key);
4311
- const isOutOfView = index < startBuffered || index > endBuffered;
4312
- if (isOutOfView) {
4313
- const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4314
- if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
4315
- availableContainers.push({ distance, index: u });
4366
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4367
+ const isPending = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4368
+ return (key === void 0 || isPending) && canReuseContainer(containerIndex, itemType);
4369
+ };
4370
+ const findStickyContainer = (itemType) => {
4371
+ let foundContainer;
4372
+ for (const containerIndex of stickyContainerPool) {
4373
+ if (!usedContainers.has(containerIndex)) {
4374
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4375
+ const isPendingRemoval = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4376
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, itemType)) {
4377
+ foundContainer = containerIndex;
4378
+ break;
4316
4379
  }
4317
4380
  }
4318
4381
  }
4319
- }
4320
- const remaining = numNeeded - result.length;
4321
- if (remaining > 0) {
4322
- if (availableContainers.length > 0) {
4323
- if (availableContainers.length > remaining) {
4324
- availableContainers.sort(comparatorByDistance);
4325
- availableContainers.length = remaining;
4382
+ return foundContainer;
4383
+ };
4384
+ const findUnassignedOrPendingContainer = (itemType) => {
4385
+ let foundContainer;
4386
+ for (let containerIndex = 0; containerIndex < numContainers && foundContainer === void 0; containerIndex++) {
4387
+ if (canUseContainer(containerIndex, itemType)) {
4388
+ foundContainer = containerIndex;
4326
4389
  }
4327
- for (const container of availableContainers) {
4328
- result.push(container.index);
4329
- if (requiredItemTypes) {
4330
- typeIndex++;
4390
+ }
4391
+ return foundContainer;
4392
+ };
4393
+ const getAvailableContainers = () => {
4394
+ if (!availableContainers) {
4395
+ availableContainers = [];
4396
+ if (!shouldAvoidAssignedContainerReuse) {
4397
+ for (let containerIndex = 0; containerIndex < numContainers; containerIndex++) {
4398
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4399
+ continue;
4400
+ }
4401
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4402
+ if (key === void 0) continue;
4403
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4404
+ const index = state.indexByKey.get(key);
4405
+ const isOutOfView = index < startBuffered || index > endBuffered;
4406
+ if (isOutOfView) {
4407
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4408
+ availableContainers.push({ distance, index: containerIndex });
4409
+ }
4331
4410
  }
4411
+ availableContainers.sort(comparatorByDistance);
4332
4412
  }
4333
4413
  }
4334
- const stillNeeded = numNeeded - result.length;
4335
- if (stillNeeded > 0) {
4336
- for (let i = 0; i < stillNeeded; i++) {
4337
- result.push(numContainers + i);
4414
+ return availableContainers;
4415
+ };
4416
+ const findAvailableContainer = (itemType) => {
4417
+ const containers = getAvailableContainers();
4418
+ let matchIndex = -1;
4419
+ for (let i = 0; i < containers.length && matchIndex === -1; i++) {
4420
+ const containerIndex = containers[i].index;
4421
+ if (!usedContainers.has(containerIndex) && canReuseContainer(containerIndex, itemType)) {
4422
+ matchIndex = i;
4338
4423
  }
4339
- if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
4340
- console.warn(
4341
- "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize.",
4342
- {
4343
- debugInfo: {
4344
- numContainers,
4345
- numContainersPooled: peek$(ctx, "numContainersPooled"),
4346
- numNeeded,
4347
- stillNeeded
4348
- }
4349
- }
4350
- );
4424
+ }
4425
+ return matchIndex === -1 ? void 0 : containers.splice(matchIndex, 1)[0].index;
4426
+ };
4427
+ for (const itemIndex of needNewContainers) {
4428
+ const itemType = getRequiredItemType == null ? void 0 : getRequiredItemType(itemIndex);
4429
+ const isSticky = stickyHeaderIndicesSet.has(itemIndex);
4430
+ let containerIndex;
4431
+ if (isSticky) {
4432
+ containerIndex = findStickyContainer(itemType);
4433
+ } else {
4434
+ containerIndex = findUnassignedOrPendingContainer(itemType);
4435
+ if (containerIndex === void 0) {
4436
+ containerIndex = findAvailableContainer(itemType);
4351
4437
  }
4352
4438
  }
4439
+ if (containerIndex !== void 0) {
4440
+ pushAllocation(itemIndex, itemType, containerIndex);
4441
+ } else {
4442
+ pushNewContainer(itemIndex, itemType, isSticky);
4443
+ }
4353
4444
  }
4354
4445
  if (pendingRemovalChanged) {
4355
4446
  pendingRemoval.length = 0;
4356
- for (const value of pendingRemovalSet) {
4357
- pendingRemoval.push(value);
4447
+ if (pendingRemovalSet) {
4448
+ for (const value of pendingRemovalSet) {
4449
+ pendingRemoval.push(value);
4450
+ }
4358
4451
  }
4359
4452
  }
4360
- return result.sort(comparatorDefault);
4453
+ if (IS_DEV && nextNewContainerIndex > peek$(ctx, "numContainersPooled")) {
4454
+ console.warn(
4455
+ "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize.",
4456
+ {
4457
+ debugInfo: {
4458
+ numContainers,
4459
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
4460
+ numNeeded,
4461
+ stillNeeded: nextNewContainerIndex - numContainers
4462
+ }
4463
+ }
4464
+ );
4465
+ }
4466
+ return allocations;
4361
4467
  }
4362
4468
  function comparatorByDistance(a, b) {
4363
4469
  return b.distance - a.distance;
@@ -4383,21 +4489,28 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
4383
4489
  }
4384
4490
  return -1;
4385
4491
  }
4386
- function getActiveStickyIndices(ctx, stickyHeaderIndices) {
4492
+ function isStickyIndexActive(ctx, targetIndex) {
4387
4493
  const state = ctx.state;
4388
- return new Set(
4389
- Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
4390
- );
4494
+ let isActive = false;
4495
+ for (const containerIndex of state.stickyContainerPool) {
4496
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4497
+ const itemIndex = key ? state.indexByKey.get(key) : void 0;
4498
+ if (itemIndex === targetIndex) {
4499
+ isActive = true;
4500
+ break;
4501
+ }
4502
+ }
4503
+ return isActive;
4391
4504
  }
4392
- function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4505
+ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4393
4506
  var _a3;
4394
4507
  const state = ctx.state;
4395
- const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
4396
4508
  set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
4397
4509
  for (let offset = 0; offset <= 1; offset++) {
4398
4510
  const idx = currentStickyIdx - offset;
4399
- if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
4511
+ if (idx < 0) continue;
4400
4512
  const stickyIndex = stickyArray[idx];
4513
+ if (isStickyIndexActive(ctx, stickyIndex)) continue;
4401
4514
  const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
4402
4515
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered) && !needNewContainersSet.has(stickyIndex)) {
4403
4516
  needNewContainersSet.add(stickyIndex);
@@ -4439,10 +4552,86 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4439
4552
  }
4440
4553
  }
4441
4554
  }
4555
+ function trackVisibleRange(range, i, top, size, scroll, scrollBottom) {
4556
+ let didPassVisibleEnd = false;
4557
+ if (range.startNoBuffer === null && top + size > scroll) {
4558
+ range.startNoBuffer = i;
4559
+ }
4560
+ if (range.firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4561
+ range.firstFullyOnScreenIndex = i;
4562
+ }
4563
+ if (range.startNoBuffer !== null) {
4564
+ if (top <= scrollBottom) {
4565
+ range.endNoBuffer = i;
4566
+ } else {
4567
+ didPassVisibleEnd = true;
4568
+ }
4569
+ }
4570
+ return didPassVisibleEnd;
4571
+ }
4572
+ function getIdsInVisibleRange(state, range) {
4573
+ var _a3, _b;
4574
+ const idsInView = [];
4575
+ const firstVisibleAnchorIndex = (_a3 = range.firstFullyOnScreenIndex) != null ? _a3 : range.startNoBuffer;
4576
+ if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && range.endNoBuffer !== null) {
4577
+ for (let i = firstVisibleAnchorIndex; i <= range.endNoBuffer; i++) {
4578
+ const id = (_b = state.idCache[i]) != null ? _b : getId(state, i);
4579
+ idsInView.push(id);
4580
+ }
4581
+ }
4582
+ return idsInView;
4583
+ }
4584
+ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4585
+ var _a3, _b;
4586
+ const state = ctx.state;
4587
+ const {
4588
+ endBuffered,
4589
+ idCache,
4590
+ positions,
4591
+ props: { data },
4592
+ sizes,
4593
+ startBuffered
4594
+ } = state;
4595
+ if (startBuffered === null || endBuffered === null || startBuffered < 0 || endBuffered < startBuffered) {
4596
+ return;
4597
+ }
4598
+ const visibleRange = {
4599
+ endNoBuffer: null,
4600
+ firstFullyOnScreenIndex: void 0,
4601
+ startNoBuffer: null
4602
+ };
4603
+ for (let i = startBuffered; i <= endBuffered && i < data.length; i++) {
4604
+ const id = (_a3 = idCache[i]) != null ? _a3 : getId(state, i);
4605
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(ctx, id, i, data[i]);
4606
+ const top = positions[i];
4607
+ const didPassVisibleEnd = trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4608
+ if (didPassVisibleEnd) {
4609
+ break;
4610
+ }
4611
+ }
4612
+ Object.assign(state, {
4613
+ endNoBuffer: visibleRange.endNoBuffer,
4614
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4615
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4616
+ startNoBuffer: visibleRange.startNoBuffer
4617
+ });
4618
+ if (visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4619
+ updateViewableItems(
4620
+ state,
4621
+ ctx,
4622
+ viewabilityConfigCallbackPairs,
4623
+ scrollLength,
4624
+ visibleRange.startNoBuffer,
4625
+ visibleRange.endNoBuffer,
4626
+ startBuffered,
4627
+ endBuffered
4628
+ );
4629
+ }
4630
+ }
4442
4631
  function calculateItemsInView(ctx, params = {}) {
4443
4632
  const state = ctx.state;
4444
4633
  batchedUpdates(() => {
4445
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
4634
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
4446
4635
  const {
4447
4636
  columns,
4448
4637
  containerItemKeys,
@@ -4478,7 +4667,7 @@ function calculateItemsInView(ctx, params = {}) {
4478
4667
  return;
4479
4668
  }
4480
4669
  let totalSize = getContentSize(ctx);
4481
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
4670
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
4482
4671
  const numColumns = peek$(ctx, "numColumns");
4483
4672
  const speed = getScrollVelocity(state);
4484
4673
  const scrollExtra = 0;
@@ -4543,6 +4732,15 @@ function calculateItemsInView(ctx, params = {}) {
4543
4732
  state.scrollForNextCalculateItemsInView = void 0;
4544
4733
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
4545
4734
  if (Platform.OS !== "web" || !isInMVCPActiveMode(state)) {
4735
+ if (viewabilityConfigCallbackPairs) {
4736
+ updateViewabilityForCachedRange(
4737
+ ctx,
4738
+ viewabilityConfigCallbackPairs,
4739
+ scrollLength,
4740
+ scroll,
4741
+ scrollBottom
4742
+ );
4743
+ }
4546
4744
  finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
4547
4745
  return;
4548
4746
  }
@@ -4559,6 +4757,7 @@ function calculateItemsInView(ctx, params = {}) {
4559
4757
  forceFullUpdate: !!forceFullItemPositions,
4560
4758
  optimizeForVisibleWindow,
4561
4759
  scrollBottomBuffered,
4760
+ scrollVelocity: speed,
4562
4761
  startIndex
4563
4762
  });
4564
4763
  totalSize = getContentSize(ctx);
@@ -4584,10 +4783,8 @@ function calculateItemsInView(ctx, params = {}) {
4584
4783
  updateScroll2(state.scroll);
4585
4784
  updateScrollRange();
4586
4785
  }
4587
- let startNoBuffer = null;
4588
4786
  let startBuffered = null;
4589
4787
  let startBufferedId = null;
4590
- let endNoBuffer = null;
4591
4788
  let endBuffered = null;
4592
4789
  let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4593
4790
  for (let i = loopStart; i >= 0; i--) {
@@ -4621,19 +4818,18 @@ function calculateItemsInView(ctx, params = {}) {
4621
4818
  maxIndexRendered = Math.max(maxIndexRendered, index);
4622
4819
  }
4623
4820
  }
4624
- let firstFullyOnScreenIndex;
4821
+ const visibleRange = {
4822
+ endNoBuffer: null,
4823
+ firstFullyOnScreenIndex: void 0,
4824
+ startNoBuffer: null
4825
+ };
4625
4826
  const dataLength = data.length;
4626
4827
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4627
4828
  const id = (_i = idCache[i]) != null ? _i : getId(state, i);
4628
4829
  const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
4629
4830
  const top = positions[i];
4630
4831
  if (!foundEnd) {
4631
- if (startNoBuffer === null && top + size > scroll) {
4632
- startNoBuffer = i;
4633
- }
4634
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4635
- firstFullyOnScreenIndex = i;
4636
- }
4832
+ trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4637
4833
  if (startBuffered === null && top + size > scrollTopBuffered) {
4638
4834
  startBuffered = i;
4639
4835
  startBufferedId = id;
@@ -4643,10 +4839,7 @@ function calculateItemsInView(ctx, params = {}) {
4643
4839
  nextTop = top;
4644
4840
  }
4645
4841
  }
4646
- if (startNoBuffer !== null) {
4647
- if (top <= scrollBottom) {
4648
- endNoBuffer = i;
4649
- }
4842
+ if (visibleRange.startNoBuffer !== null) {
4650
4843
  if (top <= scrollBottomBuffered) {
4651
4844
  endBuffered = i;
4652
4845
  if (scrollBottomBuffered > totalSize) {
@@ -4660,22 +4853,14 @@ function calculateItemsInView(ctx, params = {}) {
4660
4853
  }
4661
4854
  }
4662
4855
  }
4663
- const idsInView = [];
4664
- const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4665
- if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4666
- for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4667
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4668
- idsInView.push(id);
4669
- }
4670
- }
4671
4856
  Object.assign(state, {
4672
4857
  endBuffered,
4673
- endNoBuffer,
4674
- firstFullyOnScreenIndex,
4675
- idsInView,
4858
+ endNoBuffer: visibleRange.endNoBuffer,
4859
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4860
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4676
4861
  startBuffered,
4677
4862
  startBufferedId,
4678
- startNoBuffer
4863
+ startNoBuffer: visibleRange.startNoBuffer
4679
4864
  });
4680
4865
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
4681
4866
  state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
@@ -4697,7 +4882,7 @@ function calculateItemsInView(ctx, params = {}) {
4697
4882
  const needNewContainers = [];
4698
4883
  const needNewContainersSet = /* @__PURE__ */ new Set();
4699
4884
  for (let i = startBuffered; i <= endBuffered; i++) {
4700
- const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4885
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4701
4886
  if (!containerItemKeys.has(id)) {
4702
4887
  needNewContainersSet.add(i);
4703
4888
  needNewContainers.push(i);
@@ -4706,7 +4891,7 @@ function calculateItemsInView(ctx, params = {}) {
4706
4891
  if (alwaysRenderArr.length > 0) {
4707
4892
  for (const index of alwaysRenderArr) {
4708
4893
  if (index < 0 || index >= dataLength) continue;
4709
- const id = (_m = idCache[index]) != null ? _m : getId(state, index);
4894
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
4710
4895
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4711
4896
  needNewContainersSet.add(index);
4712
4897
  needNewContainers.push(index);
@@ -4716,7 +4901,6 @@ function calculateItemsInView(ctx, params = {}) {
4716
4901
  if (stickyHeaderIndicesArr.length > 0) {
4717
4902
  handleStickyActivation(
4718
4903
  ctx,
4719
- stickyHeaderIndicesSet,
4720
4904
  stickyHeaderIndicesArr,
4721
4905
  currentStickyIdx,
4722
4906
  needNewContainers,
@@ -4728,35 +4912,34 @@ function calculateItemsInView(ctx, params = {}) {
4728
4912
  set$(ctx, "activeStickyIndex", -1);
4729
4913
  }
4730
4914
  if (needNewContainers.length > 0) {
4731
- const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
4915
+ const getRequiredItemType = getItemType ? (i) => {
4732
4916
  const itemType = getItemType(data[i], i);
4733
4917
  return itemType !== void 0 ? String(itemType) : "";
4734
- }) : void 0;
4735
- const availableContainers = findAvailableContainers(
4918
+ } : void 0;
4919
+ const availableContainerAllocations = findAvailableContainers(
4736
4920
  ctx,
4737
- needNewContainers.length,
4921
+ needNewContainers,
4738
4922
  startBuffered,
4739
4923
  endBuffered,
4740
4924
  pendingRemoval,
4741
- requiredItemTypes,
4742
- needNewContainers,
4925
+ getRequiredItemType,
4743
4926
  protectedContainerKeys
4744
4927
  );
4745
- for (let idx = 0; idx < needNewContainers.length; idx++) {
4746
- const i = needNewContainers[idx];
4747
- const containerIndex = availableContainers[idx];
4748
- const id = (_n = idCache[i]) != null ? _n : getId(state, i);
4928
+ for (const allocation of availableContainerAllocations) {
4929
+ const i = allocation.itemIndex;
4930
+ const containerIndex = allocation.containerIndex;
4931
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4749
4932
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4750
4933
  if (oldKey && oldKey !== id) {
4751
4934
  containerItemKeys.delete(oldKey);
4752
4935
  }
4753
4936
  set$(ctx, `containerItemKey${containerIndex}`, id);
4754
4937
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
4755
- if (requiredItemTypes) {
4756
- state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4938
+ if (allocation.itemType !== void 0) {
4939
+ state.containerItemTypes.set(containerIndex, allocation.itemType);
4757
4940
  }
4758
4941
  containerItemKeys.set(id, containerIndex);
4759
- (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
4942
+ (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
4760
4943
  const containerSticky = `containerSticky${containerIndex}`;
4761
4944
  const isSticky = stickyHeaderIndicesSet.has(i);
4762
4945
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4794,7 +4977,7 @@ function calculateItemsInView(ctx, params = {}) {
4794
4977
  if (alwaysRenderArr.length > 0) {
4795
4978
  for (const index of alwaysRenderArr) {
4796
4979
  if (index < 0 || index >= dataLength) continue;
4797
- const id = (_p = idCache[index]) != null ? _p : getId(state, index);
4980
+ const id = (_o = idCache[index]) != null ? _o : getId(state, index);
4798
4981
  const containerIndex = containerItemKeys.get(id);
4799
4982
  if (containerIndex !== void 0) {
4800
4983
  state.stickyContainerPool.add(containerIndex);
@@ -4813,10 +4996,11 @@ function calculateItemsInView(ctx, params = {}) {
4813
4996
  alwaysRenderSet
4814
4997
  );
4815
4998
  }
4999
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4816
5000
  let didChangePositions = false;
4817
5001
  for (let i = 0; i < numContainers; i++) {
4818
5002
  const itemKey = peek$(ctx, `containerItemKey${i}`);
4819
- if (pendingRemoval.includes(i)) {
5003
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(i)) {
4820
5004
  if (itemKey !== void 0) {
4821
5005
  containerItemKeys.delete(itemKey);
4822
5006
  }
@@ -4847,24 +5031,24 @@ function calculateItemsInView(ctx, params = {}) {
4847
5031
  evaluateBootstrapInitialScroll(ctx);
4848
5032
  return;
4849
5033
  }
4850
- const mountedBufferedIndices = getMountedBufferedIndices(state);
4851
- const mountedNoBufferIndices = getMountedNoBufferIndices(state);
4852
- const readinessIndices = hasActiveInitialScroll(state) ? mountedBufferedIndices : mountedNoBufferIndices.length > 0 ? mountedNoBufferIndices : mountedBufferedIndices;
4853
- if (!queuedInitialLayout && readinessIndices.length > 0 && checkAllSizesKnown(state, readinessIndices)) {
4854
- setDidLayout(ctx);
4855
- handleInitialScrollLayoutReady(ctx);
5034
+ if (!queuedInitialLayout && !state.didContainersLayout) {
5035
+ const isInitialLayoutReady = hasActiveInitialScroll(state) ? checkAllSizesKnown(state, state.startBuffered, state.endBuffered) : checkAllSizesKnown(state, state.startNoBuffer, state.endNoBuffer) || checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
5036
+ if (isInitialLayoutReady) {
5037
+ setDidLayout(ctx);
5038
+ handleInitialScrollLayoutReady(ctx);
5039
+ }
4856
5040
  }
4857
- if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
5041
+ if (viewabilityConfigCallbackPairs && visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4858
5042
  if (!didMVCPAdjustScroll) {
4859
5043
  updateViewableItems(
4860
5044
  ctx.state,
4861
5045
  ctx,
4862
5046
  viewabilityConfigCallbackPairs,
4863
5047
  scrollLength,
4864
- startNoBuffer,
4865
- endNoBuffer,
4866
- startBuffered != null ? startBuffered : startNoBuffer,
4867
- endBuffered != null ? endBuffered : endNoBuffer
5048
+ visibleRange.startNoBuffer,
5049
+ visibleRange.endNoBuffer,
5050
+ startBuffered != null ? startBuffered : visibleRange.startNoBuffer,
5051
+ endBuffered != null ? endBuffered : visibleRange.endNoBuffer
4868
5052
  );
4869
5053
  }
4870
5054
  }
@@ -5023,6 +5207,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5023
5207
  if (didChange) {
5024
5208
  state.scrollLength = scrollLength;
5025
5209
  state.otherAxisSize = otherAxisSize;
5210
+ updateContentMetrics(ctx);
5026
5211
  state.lastBatchingAction = Date.now();
5027
5212
  state.scrollForNextCalculateItemsInView = void 0;
5028
5213
  if (scrollLength > 0) {
@@ -5325,6 +5510,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5325
5510
  } = state;
5326
5511
  if (!data) return;
5327
5512
  const index = state.indexByKey.get(itemKey);
5513
+ let resolvedMeasurementItem;
5328
5514
  if (getFixedItemSize) {
5329
5515
  if (index === void 0) {
5330
5516
  return;
@@ -5335,6 +5521,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5335
5521
  }
5336
5522
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5337
5523
  const size2 = getFixedItemSize(itemData, index, type);
5524
+ resolvedMeasurementItem = {
5525
+ didResolveFixedItemSize: true,
5526
+ fixedItemSize: size2,
5527
+ itemData,
5528
+ itemType: type
5529
+ };
5338
5530
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
5339
5531
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5340
5532
  return;
@@ -5344,7 +5536,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5344
5536
  let shouldMaintainScrollAtEnd = false;
5345
5537
  let minIndexSizeChanged;
5346
5538
  const prevSizeKnown = state.sizesKnown.get(itemKey);
5347
- const diff = updateOneItemSize(ctx, itemKey, sizeObj);
5539
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem);
5348
5540
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
5349
5541
  if (diff !== 0) {
5350
5542
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -5369,7 +5561,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5369
5561
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
5370
5562
  }
5371
5563
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5372
- if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5564
+ if (didContainersLayout || checkAllSizesKnown(state, state.startBuffered, state.endBuffered)) {
5373
5565
  if (needsRecalculate) {
5374
5566
  state.scrollForNextCalculateItemsInView = void 0;
5375
5567
  runOrScheduleMVCPRecalculate(ctx);
@@ -5383,8 +5575,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5383
5575
  }
5384
5576
  }
5385
5577
  }
5386
- function updateOneItemSize(ctx, itemKey, sizeObj) {
5387
- var _a3, _b;
5578
+ function updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem) {
5579
+ var _a3, _b, _c;
5388
5580
  const state = ctx.state;
5389
5581
  const {
5390
5582
  indexByKey,
@@ -5394,14 +5586,19 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5394
5586
  } = state;
5395
5587
  if (!data) return 0;
5396
5588
  const index = indexByKey.get(itemKey);
5397
- const itemData = data[index];
5398
- let itemType;
5399
- let fixedItemSize;
5400
- if (getFixedItemSize) {
5401
- itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5589
+ const itemData = (_a3 = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemData) != null ? _a3 : data[index];
5590
+ let itemType = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemType;
5591
+ let fixedItemSize = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.fixedItemSize;
5592
+ if (getFixedItemSize && !(resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize)) {
5593
+ itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5402
5594
  fixedItemSize = getFixedItemSize(itemData, index, itemType);
5403
5595
  }
5404
- const prevSize = getItemSize(ctx, itemKey, index, itemData);
5596
+ const resolvedItemSize = (resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize) || itemType !== void 0 || fixedItemSize !== void 0 ? {
5597
+ didResolveFixedItemSize: resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize,
5598
+ fixedItemSize,
5599
+ itemType
5600
+ } : void 0;
5601
+ const prevSize = getItemSize(ctx, itemKey, index, itemData, void 0, void 0, void 0, resolvedItemSize);
5405
5602
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5406
5603
  const prevSizeKnown = sizesKnown.get(itemKey);
5407
5604
  if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
@@ -5410,7 +5607,7 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5410
5607
  const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5411
5608
  sizesKnown.set(itemKey, size);
5412
5609
  if (fixedItemSize === void 0 && size > 0) {
5413
- itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5610
+ itemType != null ? itemType : itemType = getItemType ? (_c = getItemType(itemData, index)) != null ? _c : "" : "";
5414
5611
  let averages = averageSizes[itemType];
5415
5612
  if (!averages) {
5416
5613
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -5525,6 +5722,11 @@ function getAverageItemSizes(state) {
5525
5722
  }
5526
5723
  return averageItemSizes;
5527
5724
  }
5725
+ function triggerMountedContainerLayouts(ctx) {
5726
+ for (const triggerLayout of ctx.containerLayoutTriggers.values()) {
5727
+ triggerLayout();
5728
+ }
5729
+ }
5528
5730
  function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5529
5731
  const state = ctx.state;
5530
5732
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
@@ -5650,6 +5852,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5650
5852
  state.columns.length = 0;
5651
5853
  state.columnSpans.length = 0;
5652
5854
  }
5855
+ triggerMountedContainerLayouts(ctx);
5653
5856
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
5654
5857
  };
5655
5858
  return {
@@ -5692,10 +5895,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5692
5895
  startBuffered: state.startBuffered
5693
5896
  }),
5694
5897
  reportContentInset: (inset) => {
5695
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5696
- const previousInset = state.contentInsetOverride;
5697
- state.contentInsetOverride = inset != null ? inset : void 0;
5698
- 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);
5699
5899
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5700
5900
  if (didChange) {
5701
5901
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6051,10 +6251,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6051
6251
  ...restProps
6052
6252
  } = rest;
6053
6253
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6054
- 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);
6055
6256
  const contentContainerStyle = {
6056
6257
  ...contentContainerStyleBase,
6057
- ...alignItemsAtEnd ? {
6258
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6058
6259
  display: "flex",
6059
6260
  flexDirection: horizontal ? "row" : "column",
6060
6261
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6218,6 +6419,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6218
6419
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6219
6420
  state.props = {
6220
6421
  alignItemsAtEnd,
6422
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6221
6423
  alwaysRender,
6222
6424
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6223
6425
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -6275,6 +6477,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6275
6477
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
6276
6478
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
6277
6479
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
6480
+ updateContentMetrics(ctx);
6278
6481
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
6279
6482
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
6280
6483
  if (state.scroll < 0) {
@@ -6398,7 +6601,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6398
6601
  }, [snapToIndices]);
6399
6602
  useLayoutEffect(
6400
6603
  () => initializeStateVars(true),
6401
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
6604
+ [
6605
+ dataVersion,
6606
+ memoizedLastItemKeys.join(","),
6607
+ numColumnsProp,
6608
+ stylePaddingBottomState,
6609
+ stylePaddingTopState,
6610
+ useAlignItemsAtEndPadding
6611
+ ]
6402
6612
  );
6403
6613
  useLayoutEffect(() => {
6404
6614
  const {
@@ -6457,7 +6667,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6457
6667
  viewabilityConfigCallbackPairs
6458
6668
  });
6459
6669
  state.viewabilityConfigCallbackPairs = viewability;
6460
- state.enableScrollForNextCalculateItemsInView = !viewability;
6670
+ state.enableScrollForNextCalculateItemsInView = true;
6461
6671
  if (viewability) {
6462
6672
  state.scrollForNextCalculateItemsInView = void 0;
6463
6673
  }