@legendapp/list 3.0.0-beta.35 → 3.0.0-beta.37

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/index.native.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var React2 = require('react');
4
- var reactNative = require('react-native');
4
+ var ReactNative = require('react-native');
5
5
  var shim = require('use-sync-external-store/shim');
6
6
 
7
7
  function _interopNamespace(e) {
@@ -23,11 +23,12 @@ function _interopNamespace(e) {
23
23
  }
24
24
 
25
25
  var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
26
+ var ReactNative__namespace = /*#__PURE__*/_interopNamespace(ReactNative);
26
27
 
27
28
  // src/components/LegendList.tsx
28
- reactNative.Animated.View;
29
- var View = reactNative.View;
30
- var Text = reactNative.Text;
29
+ ReactNative.Animated.View;
30
+ var View = ReactNative.View;
31
+ var Text = ReactNative.Text;
31
32
 
32
33
  // src/state/getContentInsetEnd.ts
33
34
  function getContentInsetEnd(state) {
@@ -59,7 +60,7 @@ function getContentSize(ctx) {
59
60
  const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
60
61
  return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
61
62
  }
62
- var createAnimatedValue = (value) => new reactNative.Animated.Value(value);
63
+ var createAnimatedValue = (value) => new ReactNative.Animated.Value(value);
63
64
 
64
65
  // src/state/state.tsx
65
66
  var ContextState = React2__namespace.createContext(null);
@@ -250,7 +251,7 @@ var ENABLE_DEBUG_VIEW = IS_DEV && false;
250
251
  var f = global.nativeFabricUIManager;
251
252
  var IsNewArchitecture = f !== void 0 && f != null;
252
253
  var useAnimatedValue = (initialValue) => {
253
- const [animAnimatedValue] = React2.useState(() => new reactNative.Animated.Value(initialValue));
254
+ const [animAnimatedValue] = React2.useState(() => new ReactNative.Animated.Value(initialValue));
254
255
  return animAnimatedValue;
255
256
  };
256
257
 
@@ -362,7 +363,7 @@ var PositionViewState = typedMemo(function PositionViewState2({
362
363
  }) {
363
364
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
364
365
  return /* @__PURE__ */ React2__namespace.createElement(
365
- reactNative.View,
366
+ ReactNative.View,
366
367
  {
367
368
  ref: refView,
368
369
  style: [
@@ -384,12 +385,12 @@ var PositionViewAnimated = typedMemo(function PositionViewAnimated2({
384
385
  getValue: (v) => v != null ? v : POSITION_OUT_OF_VIEW
385
386
  });
386
387
  let position;
387
- if (reactNative.Platform.OS === "ios" || reactNative.Platform.OS === "android") {
388
+ if (ReactNative.Platform.OS === "ios" || ReactNative.Platform.OS === "android") {
388
389
  position = horizontal ? { transform: [{ translateX: position$ }] } : { transform: [{ translateY: position$ }] };
389
390
  } else {
390
391
  position = horizontal ? { left: position$ } : { top: position$ };
391
392
  }
392
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { ref: refView, style: [style, position], ...rest });
393
+ return /* @__PURE__ */ React2__namespace.createElement(ReactNative.Animated.View, { ref: refView, style: [style, position], ...rest });
393
394
  });
394
395
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
395
396
  id,
@@ -427,7 +428,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
427
428
  return null;
428
429
  }
429
430
  return /* @__PURE__ */ React2__namespace.createElement(
430
- reactNative.View,
431
+ ReactNative.View,
431
432
  {
432
433
  style: {
433
434
  inset: 0,
@@ -438,7 +439,7 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
438
439
  getComponent(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)
439
440
  );
440
441
  }, [stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent]);
441
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest }, renderStickyHeaderBackdrop, children);
442
+ return /* @__PURE__ */ React2__namespace.createElement(ReactNative.Animated.View, { ref: refView, style: viewStyle, ...rest }, renderStickyHeaderBackdrop, children);
442
443
  });
443
444
  var PositionView = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
444
445
  function useInit(cb) {
@@ -631,7 +632,7 @@ function useOnLayoutSync({
631
632
  }
632
633
  return { onLayout };
633
634
  }
634
- var Platform2 = reactNative.Platform;
635
+ var Platform2 = ReactNative.Platform;
635
636
  var PlatformAdjustBreaksScroll = Platform2.OS === "android";
636
637
  var typedForwardRef = React2.forwardRef;
637
638
  var typedMemo2 = React2.memo;
@@ -835,6 +836,7 @@ var Containers = typedMemo(function Containers2({
835
836
  updateItemSize: updateItemSize2,
836
837
  getRenderedItem: getRenderedItem2
837
838
  }) {
839
+ var _a3;
838
840
  const ctx = useStateContext();
839
841
  const columnWrapperStyle = ctx.columnWrapperStyle;
840
842
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
@@ -842,11 +844,13 @@ var Containers = typedMemo(function Containers2({
842
844
  // Use a microtask if increasing the size significantly, otherwise use a timeout
843
845
  // If this is the initial scroll, we don't want to delay because we want to update the size immediately
844
846
  delay: (value, prevValue) => {
845
- var _a3;
846
- return !((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
847
+ var _a4;
848
+ return !((_a4 = ctx.state) == null ? void 0 : _a4.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
847
849
  }
848
850
  });
849
- const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 }) : void 0;
851
+ const readyToRenderOpacity = useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 });
852
+ const shouldWaitForReadyToRender = !!waitForInitialLayout && (!IsNewArchitecture || !!((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll));
853
+ const animOpacity = shouldWaitForReadyToRender ? readyToRenderOpacity : void 0;
850
854
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
851
855
  const containers = [];
852
856
  for (let i = 0; i < numContainers; i++) {
@@ -887,15 +891,15 @@ var Containers = typedMemo(function Containers2({
887
891
  }
888
892
  }
889
893
  }
890
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style }, containers);
894
+ return /* @__PURE__ */ React2__namespace.createElement(ReactNative.Animated.View, { style }, containers);
891
895
  });
892
- var ListComponentScrollView = reactNative.Animated.ScrollView;
896
+ var ListComponentScrollView = ReactNative.Animated.ScrollView;
893
897
  function ScrollAdjust() {
894
898
  const bias = 1e7;
895
899
  const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
896
900
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
897
901
  return /* @__PURE__ */ React2__namespace.createElement(
898
- reactNative.View,
902
+ ReactNative.View,
899
903
  {
900
904
  style: {
901
905
  height: 0,
@@ -914,7 +918,7 @@ function SnapWrapper({ ScrollComponent, ...props }) {
914
918
  var LayoutView = ({ onLayoutChange, refView, ...rest }) => {
915
919
  const ref = refView != null ? refView : React2.useRef();
916
920
  const { onLayout } = useOnLayoutSync({ onLayoutChange, ref });
917
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { ...rest, onLayout, ref });
921
+ return /* @__PURE__ */ React2__namespace.createElement(ReactNative.View, { ...rest, onLayout, ref });
918
922
  };
919
923
 
920
924
  // src/components/ListComponent.tsx
@@ -939,8 +943,8 @@ var ListComponent = typedMemo2(function ListComponent2({
939
943
  updateItemSize: updateItemSize2,
940
944
  refScrollView,
941
945
  renderScrollComponent,
946
+ onLayoutFooter,
942
947
  scrollAdjustHandler,
943
- onLayoutHeader,
944
948
  snapToIndices,
945
949
  stickyHeaderConfig,
946
950
  stickyHeaderIndices,
@@ -964,6 +968,21 @@ var ListComponent = typedMemo2(function ListComponent2({
964
968
  set$(ctx, "footerSize", 0);
965
969
  }
966
970
  }, [ListHeaderComponent, ListFooterComponent, ctx]);
971
+ const onLayoutHeader = React2.useCallback(
972
+ (rect) => {
973
+ const size = rect[horizontal ? "width" : "height"];
974
+ set$(ctx, "headerSize", size);
975
+ },
976
+ [ctx, horizontal]
977
+ );
978
+ const onLayoutFooterInternal = React2.useCallback(
979
+ (rect, fromLayoutEffect) => {
980
+ const size = rect[horizontal ? "width" : "height"];
981
+ set$(ctx, "footerSize", size);
982
+ onLayoutFooter == null ? void 0 : onLayoutFooter(rect, fromLayoutEffect);
983
+ },
984
+ [ctx, horizontal, onLayoutFooter]
985
+ );
967
986
  return /* @__PURE__ */ React2__namespace.createElement(
968
987
  SnapOrScroll,
969
988
  {
@@ -999,17 +1018,7 @@ var ListComponent = typedMemo2(function ListComponent2({
999
1018
  waitForInitialLayout
1000
1019
  }
1001
1020
  ),
1002
- ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(
1003
- LayoutView,
1004
- {
1005
- onLayoutChange: (layout) => {
1006
- const size = layout[horizontal ? "width" : "height"];
1007
- set$(ctx, "footerSize", size);
1008
- },
1009
- style: ListFooterComponentStyle
1010
- },
1011
- getComponent(ListFooterComponent)
1012
- ),
1021
+ ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
1013
1022
  IS_DEV && ENABLE_DEVMODE
1014
1023
  );
1015
1024
  });
@@ -1017,19 +1026,12 @@ var ListComponent = typedMemo2(function ListComponent2({
1017
1026
  // src/core/calculateOffsetForIndex.ts
1018
1027
  function calculateOffsetForIndex(ctx, index) {
1019
1028
  const state = ctx.state;
1020
- let position = 0;
1021
- if (index !== void 0) {
1022
- position = state.positions[index] || 0;
1023
- const paddingTop = peek$(ctx, "stylePaddingTop");
1024
- if (paddingTop) {
1025
- position += paddingTop;
1026
- }
1027
- const headerSize = peek$(ctx, "headerSize");
1028
- if (headerSize) {
1029
- position += headerSize;
1030
- }
1031
- }
1032
- return position;
1029
+ return index !== void 0 ? state.positions[index] || 0 : 0;
1030
+ }
1031
+
1032
+ // src/core/getTopOffsetAdjustment.ts
1033
+ function getTopOffsetAdjustment(ctx) {
1034
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1033
1035
  }
1034
1036
 
1035
1037
  // src/utils/getId.ts
@@ -1137,10 +1139,20 @@ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1137
1139
  if (viewOffset) {
1138
1140
  offset -= viewOffset;
1139
1141
  }
1142
+ if (index !== void 0) {
1143
+ const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1144
+ if (topOffsetAdjustment) {
1145
+ offset += topOffsetAdjustment;
1146
+ }
1147
+ }
1140
1148
  if (viewPosition !== void 0 && index !== void 0) {
1141
1149
  const itemSize = getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1142
1150
  const trailingInset = getContentInsetEnd(state);
1143
1151
  offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1152
+ if (index === state.props.data.length - 1) {
1153
+ const footerSize = peek$(ctx, "footerSize") || 0;
1154
+ offset += footerSize;
1155
+ }
1144
1156
  }
1145
1157
  return offset;
1146
1158
  }
@@ -1341,6 +1353,7 @@ function finishScrollTo(ctx) {
1341
1353
  state.initialScroll = void 0;
1342
1354
  state.initialAnchor = void 0;
1343
1355
  state.scrollingTo = void 0;
1356
+ state.stableTarget = void 0;
1344
1357
  if (state.pendingTotalSize !== void 0) {
1345
1358
  addTotalSize(ctx, null, state.pendingTotalSize);
1346
1359
  }
@@ -1357,6 +1370,14 @@ function finishScrollTo(ctx) {
1357
1370
  }
1358
1371
 
1359
1372
  // src/core/checkFinishedScroll.ts
1373
+ function getCurrentTargetOffset(ctx, scrollingTo) {
1374
+ if (scrollingTo.index !== void 0) {
1375
+ const baseOffset = calculateOffsetForIndex(ctx, scrollingTo.index);
1376
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, scrollingTo);
1377
+ return clampScrollOffset(ctx, resolvedOffset, scrollingTo);
1378
+ }
1379
+ return clampScrollOffset(ctx, scrollingTo.offset, scrollingTo);
1380
+ }
1360
1381
  function checkFinishedScroll(ctx) {
1361
1382
  ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1362
1383
  }
@@ -1366,20 +1387,30 @@ function checkFinishedScrollFrame(ctx) {
1366
1387
  const { state } = ctx;
1367
1388
  state.animFrameCheckFinishedScroll = void 0;
1368
1389
  const scroll = state.scrollPending;
1369
- const adjust = state.scrollAdjustHandler.getAdjust();
1370
- const clampedTargetOffset = clampScrollOffset(
1371
- ctx,
1372
- scrollingTo.offset - (scrollingTo.viewOffset || 0),
1373
- scrollingTo
1374
- );
1390
+ const clampedTargetOffset = getCurrentTargetOffset(ctx, scrollingTo);
1391
+ if (Math.abs(scrollingTo.offset - clampedTargetOffset) >= 1) {
1392
+ state.scrollingTo = { ...scrollingTo, offset: clampedTargetOffset };
1393
+ }
1375
1394
  const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
1376
1395
  const diff1 = Math.abs(scroll - clampedTargetOffset);
1377
- const diff2 = Math.abs(diff1 - adjust);
1378
1396
  const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
1379
- const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
1397
+ const isAtTarget = diff1 < 1;
1398
+ const previousStableTarget = state.stableTarget;
1399
+ const hasStableTargetFrame = !!previousStableTarget && Math.abs(previousStableTarget.target - clampedTargetOffset) < 1 && Math.abs(previousStableTarget.scroll - scroll) < 1;
1400
+ if (isAtTarget && !hasStableTargetFrame) {
1401
+ state.stableTarget = { scroll, target: clampedTargetOffset };
1402
+ state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1403
+ return;
1404
+ }
1405
+ if (!isAtTarget) {
1406
+ state.stableTarget = void 0;
1407
+ }
1380
1408
  if (isNotOverscrolled && isAtTarget) {
1409
+ state.stableTarget = void 0;
1381
1410
  finishScrollTo(ctx);
1382
1411
  }
1412
+ } else {
1413
+ ctx.state.stableTarget = void 0;
1383
1414
  }
1384
1415
  }
1385
1416
  function checkFinishedScrollFallback(ctx) {
@@ -1445,8 +1476,9 @@ function scrollTo(ctx, params) {
1445
1476
  let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1446
1477
  offset = clampScrollOffset(ctx, offset, scrollTarget);
1447
1478
  state.scrollHistory.length = 0;
1479
+ state.stableTarget = void 0;
1448
1480
  if (!noScrollingTo) {
1449
- state.scrollingTo = scrollTarget;
1481
+ state.scrollingTo = { ...scrollTarget, offset };
1450
1482
  }
1451
1483
  state.scrollPending = offset;
1452
1484
  if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
@@ -1594,7 +1626,8 @@ function ensureInitialAnchor(ctx) {
1594
1626
  return;
1595
1627
  }
1596
1628
  const availableSpace = Math.max(0, scrollLength - size);
1597
- const desiredOffset = calculateOffsetForIndex(ctx, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1629
+ const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1630
+ const desiredOffset = calculateOffsetForIndex(ctx, anchor.index) + topOffsetAdjustment - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1598
1631
  const clampedDesiredOffset = clampScrollOffset(ctx, desiredOffset, anchor);
1599
1632
  const delta = clampedDesiredOffset - scroll;
1600
1633
  if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
@@ -2311,6 +2344,8 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2311
2344
  const cb = ctx.mapViewabilityCallbacks.get(key);
2312
2345
  cb == null ? void 0 : cb(viewToken);
2313
2346
  }
2347
+ var unstableBatchedUpdates = ReactNative__namespace.unstable_batchedUpdates;
2348
+ var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
2314
2349
 
2315
2350
  // src/utils/checkAllSizesKnown.ts
2316
2351
  function isNullOrUndefined2(value) {
@@ -2563,7 +2598,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
2563
2598
  }
2564
2599
  function calculateItemsInView(ctx, params = {}) {
2565
2600
  const state = ctx.state;
2566
- reactNative.unstable_batchedUpdates(() => {
2601
+ batchedUpdates(() => {
2567
2602
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2568
2603
  const {
2569
2604
  columns,
@@ -3457,19 +3492,19 @@ var useCombinedRef = (...refs) => {
3457
3492
  return callback;
3458
3493
  };
3459
3494
  function getWindowSize() {
3460
- const screenSize = reactNative.Dimensions.get("window");
3495
+ const screenSize = ReactNative.Dimensions.get("window");
3461
3496
  return {
3462
3497
  height: screenSize.height,
3463
3498
  width: screenSize.width
3464
3499
  };
3465
3500
  }
3466
- var StyleSheet = reactNative.StyleSheet;
3501
+ var StyleSheet = ReactNative.StyleSheet;
3467
3502
  function useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, onScroll2) {
3468
3503
  const shouldUseRnAnimatedEngine = !ctx.state.props.stickyPositionComponentInternal;
3469
3504
  return React2.useMemo(() => {
3470
3505
  if ((stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.length) && shouldUseRnAnimatedEngine) {
3471
3506
  const { animatedScrollY } = ctx;
3472
- return reactNative.Animated.event(
3507
+ return ReactNative.Animated.event(
3473
3508
  [
3474
3509
  {
3475
3510
  nativeEvent: {
@@ -3914,7 +3949,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3914
3949
  const maintainVisibleContentPositionConfig = normalizeMaintainVisibleContentPosition(
3915
3950
  maintainVisibleContentPositionProp
3916
3951
  );
3917
- const [renderNum, setRenderNum] = React2.useState(0);
3918
3952
  const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? {
3919
3953
  index: initialScrollIndexProp.index || 0,
3920
3954
  viewOffset: initialScrollIndexProp.viewOffset || (initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0),
@@ -4119,6 +4153,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4119
4153
  true
4120
4154
  );
4121
4155
  }
4156
+ const resolveInitialScrollOffset = React2.useCallback((initialScroll) => {
4157
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
4158
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
4159
+ return clampScrollOffset(ctx, resolvedOffset, initialScroll);
4160
+ }, []);
4122
4161
  const initialContentOffset = React2.useMemo(() => {
4123
4162
  var _a4;
4124
4163
  let value;
@@ -4136,9 +4175,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4136
4175
  if (initialScroll.contentOffset !== void 0) {
4137
4176
  value = initialScroll.contentOffset;
4138
4177
  } else {
4139
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
4140
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
4141
- const clampedOffset = clampScrollOffset(ctx, resolvedOffset, initialScroll);
4178
+ const clampedOffset = resolveInitialScrollOffset(initialScroll);
4142
4179
  const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
4143
4180
  refState.current.initialScroll = updatedInitialScroll;
4144
4181
  state.initialScroll = updatedInitialScroll;
@@ -4152,7 +4189,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4152
4189
  setInitialRenderState(ctx, { didInitialScroll: true });
4153
4190
  }
4154
4191
  return value;
4155
- }, [renderNum]);
4192
+ }, []);
4156
4193
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
4157
4194
  refState.current.lastBatchingAction = Date.now();
4158
4195
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
@@ -4166,32 +4203,45 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4166
4203
  set$(ctx, "totalSize", 0);
4167
4204
  }
4168
4205
  }
4169
- const onLayoutHeader = React2.useCallback((rect, fromLayoutEffect) => {
4170
- const { initialScroll } = refState.current;
4171
- const size = rect[horizontal ? "width" : "height"];
4172
- set$(ctx, "headerSize", size);
4173
- if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
4174
- if (IsNewArchitecture && Platform2.OS !== "android") {
4175
- if (fromLayoutEffect) {
4176
- setRenderNum((v) => v + 1);
4177
- }
4178
- } else {
4179
- setTimeout(doInitialScroll, 17);
4180
- }
4181
- }
4182
- }, []);
4183
4206
  const doInitialScroll = React2.useCallback(() => {
4184
4207
  const { initialScroll, didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
4185
4208
  if (initialScroll && !queuedInitialLayout && !didFinishInitialScroll && !scrollingTo) {
4209
+ const offset = resolveInitialScrollOffset(initialScroll);
4210
+ const updatedInitialScroll = { ...initialScroll, contentOffset: offset };
4211
+ refState.current.initialScroll = updatedInitialScroll;
4212
+ state.initialScroll = updatedInitialScroll;
4186
4213
  scrollTo(ctx, {
4187
4214
  animated: false,
4188
- index: initialScroll == null ? void 0 : initialScroll.index,
4215
+ index: initialScroll.index,
4189
4216
  isInitialScroll: true,
4190
- offset: initialContentOffset,
4217
+ offset,
4191
4218
  precomputedWithViewOffset: true
4192
4219
  });
4193
4220
  }
4194
- }, [initialContentOffset]);
4221
+ }, []);
4222
+ const onLayoutFooter = React2.useCallback(
4223
+ (layout) => {
4224
+ if (!initialScrollAtEnd) {
4225
+ return;
4226
+ }
4227
+ const { initialScroll } = state;
4228
+ if (!initialScroll) {
4229
+ return;
4230
+ }
4231
+ const lastIndex = Math.max(0, dataProp.length - 1);
4232
+ if (initialScroll.index !== lastIndex || initialScroll.viewPosition !== 1) {
4233
+ return;
4234
+ }
4235
+ const footerSize = layout[horizontal ? "width" : "height"];
4236
+ const viewOffset = -stylePaddingBottomState - footerSize;
4237
+ if (initialScroll.viewOffset !== viewOffset) {
4238
+ const updatedInitialScroll = { ...initialScroll, viewOffset };
4239
+ refState.current.initialScroll = updatedInitialScroll;
4240
+ state.initialScroll = updatedInitialScroll;
4241
+ }
4242
+ },
4243
+ [dataProp.length, horizontal, initialScrollAtEnd, stylePaddingBottomState]
4244
+ );
4195
4245
  const onLayoutChange = React2.useCallback((layout) => {
4196
4246
  doInitialScroll();
4197
4247
  handleLayout(ctx, layout, setCanRender);
@@ -4305,14 +4355,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4305
4355
  ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
4306
4356
  ListHeaderComponent,
4307
4357
  onLayout,
4308
- onLayoutHeader,
4358
+ onLayoutFooter,
4309
4359
  onMomentumScrollEnd: fns.onMomentumScrollEnd,
4310
4360
  onScroll: onScrollHandler,
4311
4361
  recycleItems,
4312
4362
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControl, {
4313
4363
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4314
4364
  }) : refreshControl : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
4315
- reactNative.RefreshControl,
4365
+ ReactNative.RefreshControl,
4316
4366
  {
4317
4367
  onRefresh,
4318
4368
  progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,