@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.js CHANGED
@@ -143,6 +143,7 @@ function StateProvider({ children }) {
143
143
  const [value] = React2__namespace.useState(() => ({
144
144
  animatedScrollY: createAnimatedValue(0),
145
145
  columnWrapperStyle: void 0,
146
+ containerLayoutTriggers: /* @__PURE__ */ new Map(),
146
147
  contextNum: contextNum++,
147
148
  listeners: /* @__PURE__ */ new Map(),
148
149
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -153,6 +154,7 @@ function StateProvider({ children }) {
153
154
  positionListeners: /* @__PURE__ */ new Map(),
154
155
  state: void 0,
155
156
  values: /* @__PURE__ */ new Map([
157
+ ["alignItemsAtEndPadding", 0],
156
158
  ["stylePaddingTop", 0],
157
159
  ["headerSize", 0],
158
160
  ["numContainers", 0],
@@ -295,15 +297,16 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
295
297
 
296
298
  // src/state/getContentSize.ts
297
299
  function getContentSize(ctx) {
298
- var _a3;
300
+ var _a3, _b;
299
301
  const { values, state } = ctx;
300
302
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
301
303
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
304
+ const alignItemsAtEndPadding = values.get("alignItemsAtEndPadding") || 0;
302
305
  const headerSize = values.get("headerSize") || 0;
303
306
  const footerSize = values.get("footerSize") || 0;
304
307
  const contentInsetBottom = getContentInsetEnd(ctx);
305
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
306
- 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);
307
310
  }
308
311
 
309
312
  // src/components/DebugView.tsx
@@ -478,8 +481,16 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
478
481
  ...rest
479
482
  }) {
480
483
  const ctx = useStateContext();
481
- 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$([
482
492
  `containerPosition${id}`,
493
+ "alignItemsAtEndPadding",
483
494
  "headerSize",
484
495
  "stylePaddingTop",
485
496
  `containerItemKey${id}`,
@@ -493,7 +504,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
493
504
  var _a3;
494
505
  if (animatedScrollY) {
495
506
  const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
496
- const stickyStart = position + headerSize + stylePaddingTop - stickyConfigOffset;
507
+ const stickyStart = position + headerSize + stylePaddingTop + alignItemsAtEndPadding - stickyConfigOffset;
497
508
  let nextStickyPosition;
498
509
  if (pushLimit !== void 0) {
499
510
  if (pushLimit <= position) {
@@ -516,7 +527,15 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
516
527
  }
517
528
  return horizontal ? [{ translateX: nextStickyPosition }] : [{ translateY: nextStickyPosition }];
518
529
  }
519
- }, [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
+ ]);
520
539
  const viewStyle = React2__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
521
540
  const renderStickyHeaderBackdrop = React2__namespace.useMemo(() => {
522
541
  if (!(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)) {
@@ -561,9 +580,6 @@ function roundSize(size) {
561
580
  function isNullOrUndefined(value) {
562
581
  return value === null || value === void 0;
563
582
  }
564
- function comparatorDefault(a, b) {
565
- return a - b;
566
- }
567
583
  function getPadding(s, type) {
568
584
  var _a3, _b, _c;
569
585
  const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
@@ -916,18 +932,6 @@ var Container = typedMemo(function Container2({
916
932
  [itemKey, data, extraData]
917
933
  );
918
934
  const { index, renderedItem } = renderedItemInfo || {};
919
- const contextValue = React2.useMemo(() => {
920
- ctx.viewRefs.set(id, ref);
921
- return {
922
- containerId: id,
923
- index,
924
- itemKey,
925
- triggerLayout: () => {
926
- forceLayoutRender((v) => v + 1);
927
- },
928
- value: data
929
- };
930
- }, [id, itemKey, index, data]);
931
935
  const onLayoutChange = React2.useCallback((rectangle) => {
932
936
  var _a3, _b;
933
937
  const {
@@ -977,6 +981,27 @@ var Container = typedMemo(function Container2({
977
981
  });
978
982
  }
979
983
  }, []);
984
+ const triggerLayout = React2.useCallback(() => {
985
+ forceLayoutRender((v) => v + 1);
986
+ }, []);
987
+ const contextValue = React2.useMemo(() => {
988
+ ctx.viewRefs.set(id, ref);
989
+ return {
990
+ containerId: id,
991
+ index,
992
+ itemKey,
993
+ triggerLayout,
994
+ value: data
995
+ };
996
+ }, [id, itemKey, index, data, triggerLayout]);
997
+ React2.useLayoutEffect(() => {
998
+ ctx.containerLayoutTriggers.set(id, triggerLayout);
999
+ return () => {
1000
+ if (ctx.containerLayoutTriggers.get(id) === triggerLayout) {
1001
+ ctx.containerLayoutTriggers.delete(id);
1002
+ }
1003
+ };
1004
+ }, [ctx, id, triggerLayout]);
980
1005
  const { onLayout } = useOnLayoutSync(
981
1006
  {
982
1007
  onLayoutChange,
@@ -1167,6 +1192,51 @@ function WebAnchoredEndSpace({ horizontal }) {
1167
1192
  const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
1168
1193
  return /* @__PURE__ */ React2__namespace.createElement("div", { style }, null);
1169
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
+ }
1170
1240
  function useLatestRef(value) {
1171
1241
  const ref = React2__namespace.useRef(value);
1172
1242
  ref.current = value;
@@ -1225,7 +1295,7 @@ var ListComponent = typedMemo(function ListComponent2({
1225
1295
  }) {
1226
1296
  const ctx = useStateContext();
1227
1297
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1228
- const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1298
+ const [alignItemsAtEndPadding = 0, otherAxisSize = 0] = useArr$(["alignItemsAtEndPadding", "otherAxisSize"]);
1229
1299
  const autoOtherAxisStyle = getAutoOtherAxisStyle({
1230
1300
  horizontal,
1231
1301
  needsOtherAxisSize: ctx.state.needsOtherAxisSize,
@@ -1239,23 +1309,23 @@ var ListComponent = typedMemo(function ListComponent2({
1239
1309
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1240
1310
  React2.useLayoutEffect(() => {
1241
1311
  if (!ListHeaderComponent) {
1242
- set$(ctx, "headerSize", 0);
1312
+ setHeaderSize(ctx, 0);
1243
1313
  }
1244
1314
  if (!ListFooterComponent) {
1245
- set$(ctx, "footerSize", 0);
1315
+ setFooterSize(ctx, 0);
1246
1316
  }
1247
1317
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
1248
1318
  const onLayoutHeader = React2.useCallback(
1249
1319
  (rect) => {
1250
1320
  const size = rect[horizontal ? "width" : "height"];
1251
- set$(ctx, "headerSize", size);
1321
+ setHeaderSize(ctx, size);
1252
1322
  },
1253
1323
  [ctx, horizontal]
1254
1324
  );
1255
1325
  const onLayoutFooterInternal = React2.useCallback(
1256
1326
  (rect, fromLayoutEffect) => {
1257
1327
  const size = rect[horizontal ? "width" : "height"];
1258
- set$(ctx, "footerSize", size);
1328
+ setFooterSize(ctx, size);
1259
1329
  onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
1260
1330
  },
1261
1331
  [ctx, horizontal, onLayoutFooter]
@@ -1283,6 +1353,13 @@ var ListComponent = typedMemo(function ListComponent2({
1283
1353
  /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
1284
1354
  ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1285
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
+ ),
1286
1363
  canRender && !ListEmptyComponent && /* @__PURE__ */ React2__namespace.createElement(
1287
1364
  Containers,
1288
1365
  {
@@ -1774,7 +1851,7 @@ function calculateOffsetForIndex(ctx, index) {
1774
1851
 
1775
1852
  // src/core/getTopOffsetAdjustment.ts
1776
1853
  function getTopOffsetAdjustment(ctx) {
1777
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1854
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "alignItemsAtEndPadding") || 0) + (peek$(ctx, "headerSize") || 0);
1778
1855
  }
1779
1856
 
1780
1857
  // src/utils/getId.ts
@@ -1812,6 +1889,7 @@ function addTotalSize(ctx, key, add, notifyTotalSize = true) {
1812
1889
  if (notifyTotalSize) {
1813
1890
  set$(ctx, "totalSize", totalSize);
1814
1891
  }
1892
+ updateContentMetrics(ctx);
1815
1893
  }
1816
1894
  } else if (notifyTotalSize && ctx.values.get("totalSize") !== totalSize) {
1817
1895
  set$(ctx, "totalSize", totalSize);
@@ -1831,14 +1909,14 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
1831
1909
  }
1832
1910
 
1833
1911
  // src/utils/getItemSize.ts
1834
- function getKnownOrFixedSize(ctx, key, index, data) {
1835
- var _a3;
1912
+ function getKnownOrFixedSize(ctx, key, index, data, resolved) {
1913
+ var _a3, _b;
1836
1914
  const state = ctx.state;
1837
1915
  const { getFixedItemSize, getItemType } = state.props;
1838
1916
  let size = key ? state.sizesKnown.get(key) : void 0;
1839
1917
  if (size === void 0 && key && getFixedItemSize) {
1840
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1841
- size = getFixedItemSize(data, index, itemType);
1918
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1919
+ size = (resolved == null ? void 0 : resolved.didResolveFixedItemSize) ? resolved.fixedItemSize : getFixedItemSize(data, index, itemType);
1842
1920
  if (size !== void 0) {
1843
1921
  state.sizesKnown.set(key, size);
1844
1922
  }
@@ -1857,8 +1935,8 @@ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
1857
1935
  }
1858
1936
  return true;
1859
1937
  }
1860
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
1861
- var _a3, _b, _c;
1938
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize, resolved) {
1939
+ var _a3, _b, _c, _d;
1862
1940
  const state = ctx.state;
1863
1941
  const {
1864
1942
  sizes,
@@ -1877,14 +1955,14 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1877
1955
  return renderedSize;
1878
1956
  }
1879
1957
  }
1880
- size = getKnownOrFixedSize(ctx, key, index, data);
1958
+ size = getKnownOrFixedSize(ctx, key, index, data, resolved);
1881
1959
  if (size !== void 0) {
1882
1960
  setSize(ctx, key, size, notifyTotalSize);
1883
1961
  return size;
1884
1962
  }
1885
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1963
+ const itemType = (_b = resolved == null ? void 0 : resolved.itemType) != null ? _b : getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1886
1964
  if (useAverageSize && !scrollingTo) {
1887
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1965
+ const averageSizeForType = (_c = averageSizes[itemType]) == null ? void 0 : _c.avg;
1888
1966
  if (averageSizeForType !== void 0) {
1889
1967
  size = roundSize(averageSizeForType);
1890
1968
  }
@@ -1893,7 +1971,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
1893
1971
  return renderedSize;
1894
1972
  }
1895
1973
  if (size === void 0 && useAverageSize && scrollingTo) {
1896
- const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
1974
+ const averageSizeForType = (_d = scrollingTo.averageSizeSnapshot) == null ? void 0 : _d[itemType];
1897
1975
  if (averageSizeForType !== void 0) {
1898
1976
  size = roundSize(averageSizeForType);
1899
1977
  }
@@ -2600,8 +2678,8 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2600
2678
  if ((options == null ? void 0 : options.markHasScrolled) !== false) {
2601
2679
  state.hasScrolled = true;
2602
2680
  }
2603
- state.lastBatchingAction = Date.now();
2604
2681
  const currentTime = Date.now();
2682
+ state.lastBatchingAction = currentTime;
2605
2683
  const adjust = scrollAdjustHandler.getAdjust();
2606
2684
  const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
2607
2685
  if (adjustChanged) {
@@ -2910,26 +2988,22 @@ function advanceCurrentInitialScrollSession(ctx, options) {
2910
2988
  }
2911
2989
 
2912
2990
  // src/utils/checkAllSizesKnown.ts
2913
- function isNullOrUndefined2(value) {
2914
- return value === null || value === void 0;
2915
- }
2916
- function getMountedIndicesInRange(state, start, end) {
2917
- if (!isNullOrUndefined2(end) && !isNullOrUndefined2(start) && start >= 0 && end >= 0) {
2918
- 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);
2991
+ function checkAllSizesKnown(state, start, end) {
2992
+ if (start == null || end == null || start < 0 || end < start) {
2993
+ return false;
2919
2994
  }
2920
- return [];
2921
- }
2922
- function getMountedBufferedIndices(state) {
2923
- return getMountedIndicesInRange(state, state.startBuffered, state.endBuffered);
2924
- }
2925
- function getMountedNoBufferIndices(state) {
2926
- return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2927
- }
2928
- function checkAllSizesKnown(state, indices) {
2929
- return indices.length > 0 && indices.every((index) => {
2930
- const key = getId(state, index);
2931
- return key !== void 0 && state.sizesKnown.has(key);
2932
- });
2995
+ let hasMountedIndex = false;
2996
+ for (const key of state.containerItemKeys.keys()) {
2997
+ const index = state.indexByKey.get(key);
2998
+ if (index !== void 0 && index >= start && index <= end) {
2999
+ hasMountedIndex = true;
3000
+ const id = getId(state, index);
3001
+ if (id === void 0 || !state.sizesKnown.has(id)) {
3002
+ return false;
3003
+ }
3004
+ }
3005
+ }
3006
+ return hasMountedIndex;
2933
3007
  }
2934
3008
 
2935
3009
  // src/core/bootstrapInitialScroll.ts
@@ -3430,8 +3504,7 @@ function evaluateBootstrapInitialScroll(ctx) {
3430
3504
  bootstrapInitialScroll.targetIndexSeed = void 0;
3431
3505
  }
3432
3506
  const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
3433
- const mountedBufferedIndices = getMountedBufferedIndices(state);
3434
- const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
3507
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
3435
3508
  const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
3436
3509
  const { data } = state.props;
3437
3510
  const visibleIndices = getBootstrapRevealVisibleIndices({
@@ -3862,7 +3935,14 @@ function updateSnapToOffsets(ctx) {
3862
3935
  }
3863
3936
 
3864
3937
  // src/core/updateItemPositions.ts
3865
- function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP, optimizeForVisibleWindow = false } = {
3938
+ function updateItemPositions(ctx, dataChanged, {
3939
+ doMVCP,
3940
+ forceFullUpdate = false,
3941
+ optimizeForVisibleWindow = false,
3942
+ scrollBottomBuffered,
3943
+ scrollVelocity,
3944
+ startIndex
3945
+ } = {
3866
3946
  doMVCP: false,
3867
3947
  forceFullUpdate: false,
3868
3948
  optimizeForVisibleWindow: false,
@@ -3889,7 +3969,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3889
3969
  const extraData = peek$(ctx, "extraData");
3890
3970
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
3891
3971
  const lastScrollDelta = state.lastScrollDelta;
3892
- const velocity = getScrollVelocity(state);
3972
+ const velocity = scrollVelocity != null ? scrollVelocity : getScrollVelocity(state);
3893
3973
  const shouldOptimize = !forceFullUpdate && !dataChanged && (optimizeForVisibleWindow || Math.abs(velocity) > 0 || Platform.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
3894
3974
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3895
3975
  const useAverageSize = true;
@@ -4069,25 +4149,28 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4069
4149
  const configId = viewabilityConfig.id;
4070
4150
  const viewabilityState = ensureViewabilityState(ctx, configId);
4071
4151
  const { viewableItems: previousViewableItems, start, end, startBuffered, endBuffered } = viewabilityState;
4072
- const viewabilityTokens = /* @__PURE__ */ new Map();
4152
+ let staleViewabilityAmountIds;
4073
4153
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4074
- viewabilityTokens.set(
4154
+ const nextValue = computeViewability(
4155
+ state,
4156
+ ctx,
4157
+ viewabilityConfig,
4075
4158
  containerId,
4076
- computeViewability(
4077
- state,
4078
- ctx,
4079
- viewabilityConfig,
4080
- containerId,
4081
- value.key,
4082
- scrollSize,
4083
- value.item,
4084
- value.index
4085
- )
4159
+ value.key,
4160
+ scrollSize,
4161
+ value.item,
4162
+ value.index
4086
4163
  );
4164
+ if (nextValue.sizeVisible < 0) {
4165
+ staleViewabilityAmountIds != null ? staleViewabilityAmountIds : staleViewabilityAmountIds = [];
4166
+ staleViewabilityAmountIds.push(containerId);
4167
+ }
4087
4168
  }
4088
4169
  const changed = [];
4170
+ const previousViewableKeys = /* @__PURE__ */ new Set();
4089
4171
  if (previousViewableItems) {
4090
4172
  for (const viewToken of previousViewableItems) {
4173
+ previousViewableKeys.add(viewToken.key);
4091
4174
  const containerId = findContainerId(ctx, viewToken.key);
4092
4175
  if (!checkIsViewable(
4093
4176
  state,
@@ -4119,7 +4202,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4119
4202
  key
4120
4203
  };
4121
4204
  viewableItems.push(viewToken);
4122
- if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
4205
+ if (!previousViewableKeys.has(viewToken.key)) {
4123
4206
  changed.push(viewToken);
4124
4207
  }
4125
4208
  }
@@ -4140,24 +4223,21 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
4140
4223
  onViewableItemsChanged({ changed, end, endBuffered, start, startBuffered, viewableItems });
4141
4224
  }
4142
4225
  }
4143
- for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
4144
- if (value.sizeVisible < 0) {
4145
- ctx.mapViewabilityAmountValues.delete(containerId);
4226
+ if (staleViewabilityAmountIds) {
4227
+ for (const containerId of staleViewabilityAmountIds) {
4228
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
4229
+ if (value && value.sizeVisible < 0) {
4230
+ ctx.mapViewabilityAmountValues.delete(containerId);
4231
+ }
4146
4232
  }
4147
4233
  }
4148
4234
  }
4149
- function shallowEqual(prev, next) {
4150
- if (!prev) return false;
4151
- const keys = Object.keys(next);
4152
- for (let i = 0; i < keys.length; i++) {
4153
- const k = keys[i];
4154
- if (prev[k] !== next[k]) return false;
4155
- }
4156
- return true;
4235
+ function areViewabilityAmountTokensEqual(prev, next) {
4236
+ 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;
4157
4237
  }
4158
4238
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
4159
4239
  const { sizes, scroll: scrollState } = state;
4160
- 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);
4161
4241
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
4162
4242
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
4163
4243
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
@@ -4178,7 +4258,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4178
4258
  sizeVisible: -1
4179
4259
  };
4180
4260
  const prev2 = ctx.mapViewabilityAmountValues.get(containerId);
4181
- if (!shallowEqual(prev2, value2)) {
4261
+ if (!areViewabilityAmountTokensEqual(prev2, value2)) {
4182
4262
  ctx.mapViewabilityAmountValues.set(containerId, value2);
4183
4263
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4184
4264
  if (cb) {
@@ -4208,7 +4288,7 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
4208
4288
  sizeVisible
4209
4289
  };
4210
4290
  const prev = ctx.mapViewabilityAmountValues.get(containerId);
4211
- if (!shallowEqual(prev, value)) {
4291
+ if (!areViewabilityAmountTokensEqual(prev, value)) {
4212
4292
  ctx.mapViewabilityAmountValues.set(containerId, value);
4213
4293
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
4214
4294
  if (cb) {
@@ -4259,126 +4339,152 @@ function getExpandedContainerPoolSize(dataLength, numContainers) {
4259
4339
  }
4260
4340
 
4261
4341
  // src/utils/findAvailableContainers.ts
4262
- function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers, protectedKeys) {
4342
+ function findAvailableContainers(ctx, needNewContainers, startBuffered, endBuffered, pendingRemoval, getRequiredItemType, protectedKeys) {
4343
+ const numNeeded = needNewContainers.length;
4344
+ if (numNeeded === 0) {
4345
+ return [];
4346
+ }
4263
4347
  const numContainers = peek$(ctx, "numContainers");
4264
4348
  const state = ctx.state;
4265
4349
  const { stickyContainerPool, containerItemTypes } = state;
4266
4350
  const shouldAvoidAssignedContainerReuse = state.props.recycleItems && !!state.props.positionComponentInternal;
4267
- const result = [];
4268
- const availableContainers = [];
4269
- const pendingRemovalSet = new Set(pendingRemoval);
4351
+ const allocations = [];
4352
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4270
4353
  let pendingRemovalChanged = false;
4354
+ let nextNewContainerIndex = numContainers;
4355
+ const usedContainers = /* @__PURE__ */ new Set();
4356
+ let availableContainers;
4271
4357
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet;
4272
- const stickyHeaderItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyHeaderIndicesSet.has(index))) || [];
4273
4358
  const canReuseContainer = (containerIndex, requiredType) => {
4274
4359
  if (!requiredType) return true;
4275
4360
  const existingType = containerItemTypes.get(containerIndex);
4276
4361
  if (!existingType) return true;
4277
4362
  return existingType === requiredType;
4278
4363
  };
4279
- const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
4280
- let typeIndex = 0;
4281
- for (let i = 0; i < stickyHeaderItemIndices.length; i++) {
4282
- const requiredType = neededTypes[typeIndex];
4283
- let foundContainer = false;
4284
- for (const containerIndex of stickyContainerPool) {
4285
- const key = peek$(ctx, `containerItemKey${containerIndex}`);
4286
- const isPendingRemoval = pendingRemovalSet.has(containerIndex);
4287
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
4288
- result.push(containerIndex);
4289
- if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
4290
- pendingRemovalChanged = true;
4291
- }
4292
- foundContainer = true;
4293
- if (requiredItemTypes) typeIndex++;
4294
- break;
4295
- }
4364
+ const pushAllocation = (itemIndex, itemType, containerIndex) => {
4365
+ allocations.push({
4366
+ containerIndex,
4367
+ itemIndex,
4368
+ itemType
4369
+ });
4370
+ usedContainers.add(containerIndex);
4371
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.delete(containerIndex)) {
4372
+ pendingRemovalChanged = true;
4296
4373
  }
4297
- if (!foundContainer) {
4298
- const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
4299
- result.push(newContainerIndex);
4374
+ };
4375
+ const pushNewContainer = (itemIndex, itemType, isSticky) => {
4376
+ const newContainerIndex = nextNewContainerIndex++;
4377
+ pushAllocation(itemIndex, itemType, newContainerIndex);
4378
+ if (isSticky) {
4300
4379
  stickyContainerPool.add(newContainerIndex);
4301
- if (requiredItemTypes) typeIndex++;
4302
4380
  }
4303
- }
4304
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4305
- if (stickyContainerPool.has(u)) {
4306
- continue;
4307
- }
4308
- const key = peek$(ctx, `containerItemKey${u}`);
4309
- const requiredType = neededTypes[typeIndex];
4310
- const isPending = key !== void 0 && pendingRemovalSet.has(u);
4311
- const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
4312
- if (canUse) {
4313
- if (isPending) {
4314
- pendingRemovalSet.delete(u);
4315
- pendingRemovalChanged = true;
4316
- }
4317
- result.push(u);
4318
- if (requiredItemTypes) {
4319
- typeIndex++;
4320
- }
4381
+ return newContainerIndex;
4382
+ };
4383
+ const canUseContainer = (containerIndex, itemType) => {
4384
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4385
+ return false;
4321
4386
  }
4322
- }
4323
- if (!shouldAvoidAssignedContainerReuse) {
4324
- for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
4325
- if (stickyContainerPool.has(u)) {
4326
- continue;
4327
- }
4328
- const key = peek$(ctx, `containerItemKey${u}`);
4329
- if (key === void 0) continue;
4330
- if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4331
- const index = state.indexByKey.get(key);
4332
- const isOutOfView = index < startBuffered || index > endBuffered;
4333
- if (isOutOfView) {
4334
- const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4335
- if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
4336
- availableContainers.push({ distance, index: u });
4387
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4388
+ const isPending = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4389
+ return (key === void 0 || isPending) && canReuseContainer(containerIndex, itemType);
4390
+ };
4391
+ const findStickyContainer = (itemType) => {
4392
+ let foundContainer;
4393
+ for (const containerIndex of stickyContainerPool) {
4394
+ if (!usedContainers.has(containerIndex)) {
4395
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4396
+ const isPendingRemoval = !!(pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(containerIndex));
4397
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, itemType)) {
4398
+ foundContainer = containerIndex;
4399
+ break;
4337
4400
  }
4338
4401
  }
4339
4402
  }
4340
- }
4341
- const remaining = numNeeded - result.length;
4342
- if (remaining > 0) {
4343
- if (availableContainers.length > 0) {
4344
- if (availableContainers.length > remaining) {
4345
- availableContainers.sort(comparatorByDistance);
4346
- availableContainers.length = remaining;
4403
+ return foundContainer;
4404
+ };
4405
+ const findUnassignedOrPendingContainer = (itemType) => {
4406
+ let foundContainer;
4407
+ for (let containerIndex = 0; containerIndex < numContainers && foundContainer === void 0; containerIndex++) {
4408
+ if (canUseContainer(containerIndex, itemType)) {
4409
+ foundContainer = containerIndex;
4347
4410
  }
4348
- for (const container of availableContainers) {
4349
- result.push(container.index);
4350
- if (requiredItemTypes) {
4351
- typeIndex++;
4411
+ }
4412
+ return foundContainer;
4413
+ };
4414
+ const getAvailableContainers = () => {
4415
+ if (!availableContainers) {
4416
+ availableContainers = [];
4417
+ if (!shouldAvoidAssignedContainerReuse) {
4418
+ for (let containerIndex = 0; containerIndex < numContainers; containerIndex++) {
4419
+ if (usedContainers.has(containerIndex) || stickyContainerPool.has(containerIndex)) {
4420
+ continue;
4421
+ }
4422
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4423
+ if (key === void 0) continue;
4424
+ if ((protectedKeys == null ? void 0 : protectedKeys.has(key)) && state.indexByKey.has(key)) continue;
4425
+ const index = state.indexByKey.get(key);
4426
+ const isOutOfView = index < startBuffered || index > endBuffered;
4427
+ if (isOutOfView) {
4428
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
4429
+ availableContainers.push({ distance, index: containerIndex });
4430
+ }
4352
4431
  }
4432
+ availableContainers.sort(comparatorByDistance);
4353
4433
  }
4354
4434
  }
4355
- const stillNeeded = numNeeded - result.length;
4356
- if (stillNeeded > 0) {
4357
- for (let i = 0; i < stillNeeded; i++) {
4358
- result.push(numContainers + i);
4435
+ return availableContainers;
4436
+ };
4437
+ const findAvailableContainer = (itemType) => {
4438
+ const containers = getAvailableContainers();
4439
+ let matchIndex = -1;
4440
+ for (let i = 0; i < containers.length && matchIndex === -1; i++) {
4441
+ const containerIndex = containers[i].index;
4442
+ if (!usedContainers.has(containerIndex) && canReuseContainer(containerIndex, itemType)) {
4443
+ matchIndex = i;
4359
4444
  }
4360
- if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
4361
- console.warn(
4362
- "[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.",
4363
- {
4364
- debugInfo: {
4365
- numContainers,
4366
- numContainersPooled: peek$(ctx, "numContainersPooled"),
4367
- numNeeded,
4368
- stillNeeded
4369
- }
4370
- }
4371
- );
4445
+ }
4446
+ return matchIndex === -1 ? void 0 : containers.splice(matchIndex, 1)[0].index;
4447
+ };
4448
+ for (const itemIndex of needNewContainers) {
4449
+ const itemType = getRequiredItemType == null ? void 0 : getRequiredItemType(itemIndex);
4450
+ const isSticky = stickyHeaderIndicesSet.has(itemIndex);
4451
+ let containerIndex;
4452
+ if (isSticky) {
4453
+ containerIndex = findStickyContainer(itemType);
4454
+ } else {
4455
+ containerIndex = findUnassignedOrPendingContainer(itemType);
4456
+ if (containerIndex === void 0) {
4457
+ containerIndex = findAvailableContainer(itemType);
4372
4458
  }
4373
4459
  }
4460
+ if (containerIndex !== void 0) {
4461
+ pushAllocation(itemIndex, itemType, containerIndex);
4462
+ } else {
4463
+ pushNewContainer(itemIndex, itemType, isSticky);
4464
+ }
4374
4465
  }
4375
4466
  if (pendingRemovalChanged) {
4376
4467
  pendingRemoval.length = 0;
4377
- for (const value of pendingRemovalSet) {
4378
- pendingRemoval.push(value);
4468
+ if (pendingRemovalSet) {
4469
+ for (const value of pendingRemovalSet) {
4470
+ pendingRemoval.push(value);
4471
+ }
4379
4472
  }
4380
4473
  }
4381
- return result.sort(comparatorDefault);
4474
+ if (IS_DEV && nextNewContainerIndex > peek$(ctx, "numContainersPooled")) {
4475
+ console.warn(
4476
+ "[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.",
4477
+ {
4478
+ debugInfo: {
4479
+ numContainers,
4480
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
4481
+ numNeeded,
4482
+ stillNeeded: nextNewContainerIndex - numContainers
4483
+ }
4484
+ }
4485
+ );
4486
+ }
4487
+ return allocations;
4382
4488
  }
4383
4489
  function comparatorByDistance(a, b) {
4384
4490
  return b.distance - a.distance;
@@ -4404,21 +4510,28 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
4404
4510
  }
4405
4511
  return -1;
4406
4512
  }
4407
- function getActiveStickyIndices(ctx, stickyHeaderIndices) {
4513
+ function isStickyIndexActive(ctx, targetIndex) {
4408
4514
  const state = ctx.state;
4409
- return new Set(
4410
- 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))
4411
- );
4515
+ let isActive = false;
4516
+ for (const containerIndex of state.stickyContainerPool) {
4517
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
4518
+ const itemIndex = key ? state.indexByKey.get(key) : void 0;
4519
+ if (itemIndex === targetIndex) {
4520
+ isActive = true;
4521
+ break;
4522
+ }
4523
+ }
4524
+ return isActive;
4412
4525
  }
4413
- function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4526
+ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
4414
4527
  var _a3;
4415
4528
  const state = ctx.state;
4416
- const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
4417
4529
  set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
4418
4530
  for (let offset = 0; offset <= 1; offset++) {
4419
4531
  const idx = currentStickyIdx - offset;
4420
- if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
4532
+ if (idx < 0) continue;
4421
4533
  const stickyIndex = stickyArray[idx];
4534
+ if (isStickyIndexActive(ctx, stickyIndex)) continue;
4422
4535
  const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
4423
4536
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered) && !needNewContainersSet.has(stickyIndex)) {
4424
4537
  needNewContainersSet.add(stickyIndex);
@@ -4460,10 +4573,86 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
4460
4573
  }
4461
4574
  }
4462
4575
  }
4576
+ function trackVisibleRange(range, i, top, size, scroll, scrollBottom) {
4577
+ let didPassVisibleEnd = false;
4578
+ if (range.startNoBuffer === null && top + size > scroll) {
4579
+ range.startNoBuffer = i;
4580
+ }
4581
+ if (range.firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4582
+ range.firstFullyOnScreenIndex = i;
4583
+ }
4584
+ if (range.startNoBuffer !== null) {
4585
+ if (top <= scrollBottom) {
4586
+ range.endNoBuffer = i;
4587
+ } else {
4588
+ didPassVisibleEnd = true;
4589
+ }
4590
+ }
4591
+ return didPassVisibleEnd;
4592
+ }
4593
+ function getIdsInVisibleRange(state, range) {
4594
+ var _a3, _b;
4595
+ const idsInView = [];
4596
+ const firstVisibleAnchorIndex = (_a3 = range.firstFullyOnScreenIndex) != null ? _a3 : range.startNoBuffer;
4597
+ if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && range.endNoBuffer !== null) {
4598
+ for (let i = firstVisibleAnchorIndex; i <= range.endNoBuffer; i++) {
4599
+ const id = (_b = state.idCache[i]) != null ? _b : getId(state, i);
4600
+ idsInView.push(id);
4601
+ }
4602
+ }
4603
+ return idsInView;
4604
+ }
4605
+ function updateViewabilityForCachedRange(ctx, viewabilityConfigCallbackPairs, scrollLength, scroll, scrollBottom) {
4606
+ var _a3, _b;
4607
+ const state = ctx.state;
4608
+ const {
4609
+ endBuffered,
4610
+ idCache,
4611
+ positions,
4612
+ props: { data },
4613
+ sizes,
4614
+ startBuffered
4615
+ } = state;
4616
+ if (startBuffered === null || endBuffered === null || startBuffered < 0 || endBuffered < startBuffered) {
4617
+ return;
4618
+ }
4619
+ const visibleRange = {
4620
+ endNoBuffer: null,
4621
+ firstFullyOnScreenIndex: void 0,
4622
+ startNoBuffer: null
4623
+ };
4624
+ for (let i = startBuffered; i <= endBuffered && i < data.length; i++) {
4625
+ const id = (_a3 = idCache[i]) != null ? _a3 : getId(state, i);
4626
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(ctx, id, i, data[i]);
4627
+ const top = positions[i];
4628
+ const didPassVisibleEnd = trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4629
+ if (didPassVisibleEnd) {
4630
+ break;
4631
+ }
4632
+ }
4633
+ Object.assign(state, {
4634
+ endNoBuffer: visibleRange.endNoBuffer,
4635
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4636
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4637
+ startNoBuffer: visibleRange.startNoBuffer
4638
+ });
4639
+ if (visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4640
+ updateViewableItems(
4641
+ state,
4642
+ ctx,
4643
+ viewabilityConfigCallbackPairs,
4644
+ scrollLength,
4645
+ visibleRange.startNoBuffer,
4646
+ visibleRange.endNoBuffer,
4647
+ startBuffered,
4648
+ endBuffered
4649
+ );
4650
+ }
4651
+ }
4463
4652
  function calculateItemsInView(ctx, params = {}) {
4464
4653
  const state = ctx.state;
4465
4654
  batchedUpdates(() => {
4466
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
4655
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
4467
4656
  const {
4468
4657
  columns,
4469
4658
  containerItemKeys,
@@ -4499,7 +4688,7 @@ function calculateItemsInView(ctx, params = {}) {
4499
4688
  return;
4500
4689
  }
4501
4690
  let totalSize = getContentSize(ctx);
4502
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
4691
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "alignItemsAtEndPadding") + peek$(ctx, "headerSize");
4503
4692
  const numColumns = peek$(ctx, "numColumns");
4504
4693
  const speed = getScrollVelocity(state);
4505
4694
  const scrollExtra = 0;
@@ -4564,6 +4753,15 @@ function calculateItemsInView(ctx, params = {}) {
4564
4753
  state.scrollForNextCalculateItemsInView = void 0;
4565
4754
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
4566
4755
  if (Platform.OS !== "web" || !isInMVCPActiveMode(state)) {
4756
+ if (viewabilityConfigCallbackPairs) {
4757
+ updateViewabilityForCachedRange(
4758
+ ctx,
4759
+ viewabilityConfigCallbackPairs,
4760
+ scrollLength,
4761
+ scroll,
4762
+ scrollBottom
4763
+ );
4764
+ }
4567
4765
  finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
4568
4766
  return;
4569
4767
  }
@@ -4580,6 +4778,7 @@ function calculateItemsInView(ctx, params = {}) {
4580
4778
  forceFullUpdate: !!forceFullItemPositions,
4581
4779
  optimizeForVisibleWindow,
4582
4780
  scrollBottomBuffered,
4781
+ scrollVelocity: speed,
4583
4782
  startIndex
4584
4783
  });
4585
4784
  totalSize = getContentSize(ctx);
@@ -4605,10 +4804,8 @@ function calculateItemsInView(ctx, params = {}) {
4605
4804
  updateScroll2(state.scroll);
4606
4805
  updateScrollRange();
4607
4806
  }
4608
- let startNoBuffer = null;
4609
4807
  let startBuffered = null;
4610
4808
  let startBufferedId = null;
4611
- let endNoBuffer = null;
4612
4809
  let endBuffered = null;
4613
4810
  let loopStart = (_f = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _f : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
4614
4811
  for (let i = loopStart; i >= 0; i--) {
@@ -4642,19 +4839,18 @@ function calculateItemsInView(ctx, params = {}) {
4642
4839
  maxIndexRendered = Math.max(maxIndexRendered, index);
4643
4840
  }
4644
4841
  }
4645
- let firstFullyOnScreenIndex;
4842
+ const visibleRange = {
4843
+ endNoBuffer: null,
4844
+ firstFullyOnScreenIndex: void 0,
4845
+ startNoBuffer: null
4846
+ };
4646
4847
  const dataLength = data.length;
4647
4848
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
4648
4849
  const id = (_i = idCache[i]) != null ? _i : getId(state, i);
4649
4850
  const size = (_j = sizes.get(id)) != null ? _j : getItemSize(ctx, id, i, data[i]);
4650
4851
  const top = positions[i];
4651
4852
  if (!foundEnd) {
4652
- if (startNoBuffer === null && top + size > scroll) {
4653
- startNoBuffer = i;
4654
- }
4655
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10 && top <= scrollBottom) {
4656
- firstFullyOnScreenIndex = i;
4657
- }
4853
+ trackVisibleRange(visibleRange, i, top, size, scroll, scrollBottom);
4658
4854
  if (startBuffered === null && top + size > scrollTopBuffered) {
4659
4855
  startBuffered = i;
4660
4856
  startBufferedId = id;
@@ -4664,10 +4860,7 @@ function calculateItemsInView(ctx, params = {}) {
4664
4860
  nextTop = top;
4665
4861
  }
4666
4862
  }
4667
- if (startNoBuffer !== null) {
4668
- if (top <= scrollBottom) {
4669
- endNoBuffer = i;
4670
- }
4863
+ if (visibleRange.startNoBuffer !== null) {
4671
4864
  if (top <= scrollBottomBuffered) {
4672
4865
  endBuffered = i;
4673
4866
  if (scrollBottomBuffered > totalSize) {
@@ -4681,22 +4874,14 @@ function calculateItemsInView(ctx, params = {}) {
4681
4874
  }
4682
4875
  }
4683
4876
  }
4684
- const idsInView = [];
4685
- const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
4686
- if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
4687
- for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
4688
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4689
- idsInView.push(id);
4690
- }
4691
- }
4692
4877
  Object.assign(state, {
4693
4878
  endBuffered,
4694
- endNoBuffer,
4695
- firstFullyOnScreenIndex,
4696
- idsInView,
4879
+ endNoBuffer: visibleRange.endNoBuffer,
4880
+ firstFullyOnScreenIndex: visibleRange.firstFullyOnScreenIndex,
4881
+ idsInView: getIdsInVisibleRange(state, visibleRange),
4697
4882
  startBuffered,
4698
4883
  startBufferedId,
4699
- startNoBuffer
4884
+ startNoBuffer: visibleRange.startNoBuffer
4700
4885
  });
4701
4886
  if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
4702
4887
  state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
@@ -4718,7 +4903,7 @@ function calculateItemsInView(ctx, params = {}) {
4718
4903
  const needNewContainers = [];
4719
4904
  const needNewContainersSet = /* @__PURE__ */ new Set();
4720
4905
  for (let i = startBuffered; i <= endBuffered; i++) {
4721
- const id = (_l = idCache[i]) != null ? _l : getId(state, i);
4906
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
4722
4907
  if (!containerItemKeys.has(id)) {
4723
4908
  needNewContainersSet.add(i);
4724
4909
  needNewContainers.push(i);
@@ -4727,7 +4912,7 @@ function calculateItemsInView(ctx, params = {}) {
4727
4912
  if (alwaysRenderArr.length > 0) {
4728
4913
  for (const index of alwaysRenderArr) {
4729
4914
  if (index < 0 || index >= dataLength) continue;
4730
- const id = (_m = idCache[index]) != null ? _m : getId(state, index);
4915
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
4731
4916
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4732
4917
  needNewContainersSet.add(index);
4733
4918
  needNewContainers.push(index);
@@ -4737,7 +4922,6 @@ function calculateItemsInView(ctx, params = {}) {
4737
4922
  if (stickyHeaderIndicesArr.length > 0) {
4738
4923
  handleStickyActivation(
4739
4924
  ctx,
4740
- stickyHeaderIndicesSet,
4741
4925
  stickyHeaderIndicesArr,
4742
4926
  currentStickyIdx,
4743
4927
  needNewContainers,
@@ -4749,35 +4933,34 @@ function calculateItemsInView(ctx, params = {}) {
4749
4933
  set$(ctx, "activeStickyIndex", -1);
4750
4934
  }
4751
4935
  if (needNewContainers.length > 0) {
4752
- const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
4936
+ const getRequiredItemType = getItemType ? (i) => {
4753
4937
  const itemType = getItemType(data[i], i);
4754
4938
  return itemType !== void 0 ? String(itemType) : "";
4755
- }) : void 0;
4756
- const availableContainers = findAvailableContainers(
4939
+ } : void 0;
4940
+ const availableContainerAllocations = findAvailableContainers(
4757
4941
  ctx,
4758
- needNewContainers.length,
4942
+ needNewContainers,
4759
4943
  startBuffered,
4760
4944
  endBuffered,
4761
4945
  pendingRemoval,
4762
- requiredItemTypes,
4763
- needNewContainers,
4946
+ getRequiredItemType,
4764
4947
  protectedContainerKeys
4765
4948
  );
4766
- for (let idx = 0; idx < needNewContainers.length; idx++) {
4767
- const i = needNewContainers[idx];
4768
- const containerIndex = availableContainers[idx];
4769
- const id = (_n = idCache[i]) != null ? _n : getId(state, i);
4949
+ for (const allocation of availableContainerAllocations) {
4950
+ const i = allocation.itemIndex;
4951
+ const containerIndex = allocation.containerIndex;
4952
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4770
4953
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4771
4954
  if (oldKey && oldKey !== id) {
4772
4955
  containerItemKeys.delete(oldKey);
4773
4956
  }
4774
4957
  set$(ctx, `containerItemKey${containerIndex}`, id);
4775
4958
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
4776
- if (requiredItemTypes) {
4777
- state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
4959
+ if (allocation.itemType !== void 0) {
4960
+ state.containerItemTypes.set(containerIndex, allocation.itemType);
4778
4961
  }
4779
4962
  containerItemKeys.set(id, containerIndex);
4780
- (_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
4963
+ (_n = state.userScrollAnchorReset) == null ? void 0 : _n.keys.add(id);
4781
4964
  const containerSticky = `containerSticky${containerIndex}`;
4782
4965
  const isSticky = stickyHeaderIndicesSet.has(i);
4783
4966
  const isAlwaysRender = alwaysRenderSet.has(i);
@@ -4815,7 +4998,7 @@ function calculateItemsInView(ctx, params = {}) {
4815
4998
  if (alwaysRenderArr.length > 0) {
4816
4999
  for (const index of alwaysRenderArr) {
4817
5000
  if (index < 0 || index >= dataLength) continue;
4818
- const id = (_p = idCache[index]) != null ? _p : getId(state, index);
5001
+ const id = (_o = idCache[index]) != null ? _o : getId(state, index);
4819
5002
  const containerIndex = containerItemKeys.get(id);
4820
5003
  if (containerIndex !== void 0) {
4821
5004
  state.stickyContainerPool.add(containerIndex);
@@ -4834,10 +5017,11 @@ function calculateItemsInView(ctx, params = {}) {
4834
5017
  alwaysRenderSet
4835
5018
  );
4836
5019
  }
5020
+ const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
4837
5021
  let didChangePositions = false;
4838
5022
  for (let i = 0; i < numContainers; i++) {
4839
5023
  const itemKey = peek$(ctx, `containerItemKey${i}`);
4840
- if (pendingRemoval.includes(i)) {
5024
+ if (pendingRemovalSet == null ? void 0 : pendingRemovalSet.has(i)) {
4841
5025
  if (itemKey !== void 0) {
4842
5026
  containerItemKeys.delete(itemKey);
4843
5027
  }
@@ -4868,24 +5052,24 @@ function calculateItemsInView(ctx, params = {}) {
4868
5052
  evaluateBootstrapInitialScroll(ctx);
4869
5053
  return;
4870
5054
  }
4871
- const mountedBufferedIndices = getMountedBufferedIndices(state);
4872
- const mountedNoBufferIndices = getMountedNoBufferIndices(state);
4873
- const readinessIndices = hasActiveInitialScroll(state) ? mountedBufferedIndices : mountedNoBufferIndices.length > 0 ? mountedNoBufferIndices : mountedBufferedIndices;
4874
- if (!queuedInitialLayout && readinessIndices.length > 0 && checkAllSizesKnown(state, readinessIndices)) {
4875
- setDidLayout(ctx);
4876
- handleInitialScrollLayoutReady(ctx);
5055
+ if (!queuedInitialLayout && !state.didContainersLayout) {
5056
+ const isInitialLayoutReady = hasActiveInitialScroll(state) ? checkAllSizesKnown(state, state.startBuffered, state.endBuffered) : checkAllSizesKnown(state, state.startNoBuffer, state.endNoBuffer) || checkAllSizesKnown(state, state.startBuffered, state.endBuffered);
5057
+ if (isInitialLayoutReady) {
5058
+ setDidLayout(ctx);
5059
+ handleInitialScrollLayoutReady(ctx);
5060
+ }
4877
5061
  }
4878
- if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
5062
+ if (viewabilityConfigCallbackPairs && visibleRange.startNoBuffer !== null && visibleRange.endNoBuffer !== null) {
4879
5063
  if (!didMVCPAdjustScroll) {
4880
5064
  updateViewableItems(
4881
5065
  ctx.state,
4882
5066
  ctx,
4883
5067
  viewabilityConfigCallbackPairs,
4884
5068
  scrollLength,
4885
- startNoBuffer,
4886
- endNoBuffer,
4887
- startBuffered != null ? startBuffered : startNoBuffer,
4888
- endBuffered != null ? endBuffered : endNoBuffer
5069
+ visibleRange.startNoBuffer,
5070
+ visibleRange.endNoBuffer,
5071
+ startBuffered != null ? startBuffered : visibleRange.startNoBuffer,
5072
+ endBuffered != null ? endBuffered : visibleRange.endNoBuffer
4889
5073
  );
4890
5074
  }
4891
5075
  }
@@ -5044,6 +5228,7 @@ function handleLayout(ctx, layoutParam, setCanRender) {
5044
5228
  if (didChange) {
5045
5229
  state.scrollLength = scrollLength;
5046
5230
  state.otherAxisSize = otherAxisSize;
5231
+ updateContentMetrics(ctx);
5047
5232
  state.lastBatchingAction = Date.now();
5048
5233
  state.scrollForNextCalculateItemsInView = void 0;
5049
5234
  if (scrollLength > 0) {
@@ -5346,6 +5531,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5346
5531
  } = state;
5347
5532
  if (!data) return;
5348
5533
  const index = state.indexByKey.get(itemKey);
5534
+ let resolvedMeasurementItem;
5349
5535
  if (getFixedItemSize) {
5350
5536
  if (index === void 0) {
5351
5537
  return;
@@ -5356,6 +5542,12 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5356
5542
  }
5357
5543
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5358
5544
  const size2 = getFixedItemSize(itemData, index, type);
5545
+ resolvedMeasurementItem = {
5546
+ didResolveFixedItemSize: true,
5547
+ fixedItemSize: size2,
5548
+ itemData,
5549
+ itemType: type
5550
+ };
5359
5551
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
5360
5552
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5361
5553
  return;
@@ -5365,7 +5557,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5365
5557
  let shouldMaintainScrollAtEnd = false;
5366
5558
  let minIndexSizeChanged;
5367
5559
  const prevSizeKnown = state.sizesKnown.get(itemKey);
5368
- const diff = updateOneItemSize(ctx, itemKey, sizeObj);
5560
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem);
5369
5561
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
5370
5562
  if (diff !== 0) {
5371
5563
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -5390,7 +5582,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5390
5582
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
5391
5583
  }
5392
5584
  updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5393
- if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5585
+ if (didContainersLayout || checkAllSizesKnown(state, state.startBuffered, state.endBuffered)) {
5394
5586
  if (needsRecalculate) {
5395
5587
  state.scrollForNextCalculateItemsInView = void 0;
5396
5588
  runOrScheduleMVCPRecalculate(ctx);
@@ -5404,8 +5596,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5404
5596
  }
5405
5597
  }
5406
5598
  }
5407
- function updateOneItemSize(ctx, itemKey, sizeObj) {
5408
- var _a3, _b;
5599
+ function updateOneItemSize(ctx, itemKey, sizeObj, resolvedMeasurementItem) {
5600
+ var _a3, _b, _c;
5409
5601
  const state = ctx.state;
5410
5602
  const {
5411
5603
  indexByKey,
@@ -5415,14 +5607,19 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5415
5607
  } = state;
5416
5608
  if (!data) return 0;
5417
5609
  const index = indexByKey.get(itemKey);
5418
- const itemData = data[index];
5419
- let itemType;
5420
- let fixedItemSize;
5421
- if (getFixedItemSize) {
5422
- itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5610
+ const itemData = (_a3 = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemData) != null ? _a3 : data[index];
5611
+ let itemType = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.itemType;
5612
+ let fixedItemSize = resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.fixedItemSize;
5613
+ if (getFixedItemSize && !(resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize)) {
5614
+ itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5423
5615
  fixedItemSize = getFixedItemSize(itemData, index, itemType);
5424
5616
  }
5425
- const prevSize = getItemSize(ctx, itemKey, index, itemData);
5617
+ const resolvedItemSize = (resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize) || itemType !== void 0 || fixedItemSize !== void 0 ? {
5618
+ didResolveFixedItemSize: resolvedMeasurementItem == null ? void 0 : resolvedMeasurementItem.didResolveFixedItemSize,
5619
+ fixedItemSize,
5620
+ itemType
5621
+ } : void 0;
5622
+ const prevSize = getItemSize(ctx, itemKey, index, itemData, void 0, void 0, void 0, resolvedItemSize);
5426
5623
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
5427
5624
  const prevSizeKnown = sizesKnown.get(itemKey);
5428
5625
  if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
@@ -5431,7 +5628,7 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
5431
5628
  const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
5432
5629
  sizesKnown.set(itemKey, size);
5433
5630
  if (fixedItemSize === void 0 && size > 0) {
5434
- itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
5631
+ itemType != null ? itemType : itemType = getItemType ? (_c = getItemType(itemData, index)) != null ? _c : "" : "";
5435
5632
  let averages = averageSizes[itemType];
5436
5633
  if (!averages) {
5437
5634
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -5546,6 +5743,11 @@ function getAverageItemSizes(state) {
5546
5743
  }
5547
5744
  return averageItemSizes;
5548
5745
  }
5746
+ function triggerMountedContainerLayouts(ctx) {
5747
+ for (const triggerLayout of ctx.containerLayoutTriggers.values()) {
5748
+ triggerLayout();
5749
+ }
5750
+ }
5549
5751
  function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5550
5752
  const state = ctx.state;
5551
5753
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
@@ -5671,6 +5873,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5671
5873
  state.columns.length = 0;
5672
5874
  state.columnSpans.length = 0;
5673
5875
  }
5876
+ triggerMountedContainerLayouts(ctx);
5674
5877
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
5675
5878
  };
5676
5879
  return {
@@ -5713,10 +5916,7 @@ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
5713
5916
  startBuffered: state.startBuffered
5714
5917
  }),
5715
5918
  reportContentInset: (inset) => {
5716
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
5717
- const previousInset = state.contentInsetOverride;
5718
- state.contentInsetOverride = inset != null ? inset : void 0;
5719
- 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);
5720
5920
  updateScroll(ctx, state.scroll, true, { markHasScrolled: false });
5721
5921
  if (didChange) {
5722
5922
  retargetActiveInitialScrollAtEnd(ctx);
@@ -6072,10 +6272,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6072
6272
  ...restProps
6073
6273
  } = rest;
6074
6274
  const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
6075
- 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);
6076
6277
  const contentContainerStyle = {
6077
6278
  ...contentContainerStyleBase,
6078
- ...alignItemsAtEnd ? {
6279
+ ...alignItemsAtEnd && !useAlignItemsAtEndPadding ? {
6079
6280
  display: "flex",
6080
6281
  flexDirection: horizontal ? "row" : "column",
6081
6282
  ...shouldFlexGrow ? { flexGrow: 1 } : {},
@@ -6239,6 +6440,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6239
6440
  const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_g = state.props.anchoredEndSpace) == null ? void 0 : _g.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
6240
6441
  state.props = {
6241
6442
  alignItemsAtEnd,
6443
+ alignItemsAtEndPaddingEnabled: useAlignItemsAtEndPadding,
6242
6444
  alwaysRender,
6243
6445
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
6244
6446
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
@@ -6296,6 +6498,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6296
6498
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
6297
6499
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
6298
6500
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
6501
+ updateContentMetrics(ctx);
6299
6502
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
6300
6503
  if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
6301
6504
  if (state.scroll < 0) {
@@ -6419,7 +6622,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6419
6622
  }, [snapToIndices]);
6420
6623
  React2.useLayoutEffect(
6421
6624
  () => initializeStateVars(true),
6422
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
6625
+ [
6626
+ dataVersion,
6627
+ memoizedLastItemKeys.join(","),
6628
+ numColumnsProp,
6629
+ stylePaddingBottomState,
6630
+ stylePaddingTopState,
6631
+ useAlignItemsAtEndPadding
6632
+ ]
6423
6633
  );
6424
6634
  React2.useLayoutEffect(() => {
6425
6635
  const {
@@ -6478,7 +6688,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6478
6688
  viewabilityConfigCallbackPairs
6479
6689
  });
6480
6690
  state.viewabilityConfigCallbackPairs = viewability;
6481
- state.enableScrollForNextCalculateItemsInView = !viewability;
6691
+ state.enableScrollForNextCalculateItemsInView = true;
6482
6692
  if (viewability) {
6483
6693
  state.scrollForNextCalculateItemsInView = void 0;
6484
6694
  }