@legendapp/list 3.0.0-beta.42 → 3.0.0-beta.44

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
@@ -831,7 +831,6 @@ var Containers = typedMemo(function Containers2({
831
831
  horizontal,
832
832
  recycleItems,
833
833
  ItemSeparatorComponent,
834
- waitForInitialLayout,
835
834
  stickyHeaderConfig,
836
835
  updateItemSize: updateItemSize2,
837
836
  getRenderedItem: getRenderedItem2
@@ -847,7 +846,7 @@ var Containers = typedMemo(function Containers2({
847
846
  return !((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
848
847
  }
849
848
  });
850
- const animOpacity = waitForInitialLayout ? useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 }) : void 0;
849
+ const animOpacity = useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 });
851
850
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
852
851
  const containers = [];
853
852
  for (let i = 0; i < numContainers; i++) {
@@ -928,7 +927,6 @@ var ListComponent = typedMemo2(function ListComponent2({
928
927
  recycleItems,
929
928
  ItemSeparatorComponent,
930
929
  alignItemsAtEnd: _alignItemsAtEnd,
931
- waitForInitialLayout,
932
930
  onScroll: onScroll2,
933
931
  onLayout,
934
932
  ListHeaderComponent,
@@ -991,7 +989,7 @@ var ListComponent = typedMemo2(function ListComponent2({
991
989
  height: "100%"
992
990
  } : {}
993
991
  ],
994
- contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
992
+ contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
995
993
  horizontal,
996
994
  maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
997
995
  onLayout,
@@ -1011,8 +1009,7 @@ var ListComponent = typedMemo2(function ListComponent2({
1011
1009
  ItemSeparatorComponent,
1012
1010
  recycleItems,
1013
1011
  stickyHeaderConfig,
1014
- updateItemSize: updateItemSize2,
1015
- waitForInitialLayout
1012
+ updateItemSize: updateItemSize2
1016
1013
  }
1017
1014
  ),
1018
1015
  ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
@@ -1127,6 +1124,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1127
1124
  setSize(ctx, key, size);
1128
1125
  return size;
1129
1126
  }
1127
+ function getItemSizeAtIndex(ctx, index) {
1128
+ if (index === void 0 || index < 0) {
1129
+ return void 0;
1130
+ }
1131
+ const targetId = getId(ctx.state, index);
1132
+ return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
1133
+ }
1130
1134
 
1131
1135
  // src/core/calculateOffsetWithOffsetPosition.ts
1132
1136
  function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
@@ -1177,6 +1181,458 @@ function clampScrollOffset(ctx, offset, scrollTarget) {
1177
1181
  return clampedOffset;
1178
1182
  }
1179
1183
 
1184
+ // src/core/deferredPublicOnScroll.ts
1185
+ function withResolvedContentOffset(state, event, resolvedOffset) {
1186
+ return {
1187
+ ...event,
1188
+ nativeEvent: {
1189
+ ...event.nativeEvent,
1190
+ contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1191
+ }
1192
+ };
1193
+ }
1194
+ function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
1195
+ var _a3, _b, _c, _d;
1196
+ const state = ctx.state;
1197
+ const deferredEvent = state.deferredPublicOnScrollEvent;
1198
+ state.deferredPublicOnScrollEvent = void 0;
1199
+ if (deferredEvent) {
1200
+ (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
1201
+ _c,
1202
+ withResolvedContentOffset(
1203
+ state,
1204
+ deferredEvent,
1205
+ (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
1206
+ )
1207
+ );
1208
+ }
1209
+ }
1210
+
1211
+ // src/core/initialScrollSession.ts
1212
+ var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1213
+ function hasInitialScrollSessionCompletion(completion) {
1214
+ return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
1215
+ }
1216
+ function clearInitialScrollSession(state) {
1217
+ state.initialScrollSession = void 0;
1218
+ return void 0;
1219
+ }
1220
+ function createInitialScrollSession(options) {
1221
+ const { bootstrap, completion, kind, previousDataLength } = options;
1222
+ return kind === "offset" ? {
1223
+ completion,
1224
+ kind,
1225
+ previousDataLength
1226
+ } : {
1227
+ bootstrap,
1228
+ completion,
1229
+ kind,
1230
+ previousDataLength
1231
+ };
1232
+ }
1233
+ function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
1234
+ var _a4, _b2;
1235
+ if (!state.initialScrollSession) {
1236
+ state.initialScrollSession = createInitialScrollSession({
1237
+ completion: {},
1238
+ kind,
1239
+ previousDataLength: 0
1240
+ });
1241
+ } else if (state.initialScrollSession.kind !== kind) {
1242
+ state.initialScrollSession = createInitialScrollSession({
1243
+ bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
1244
+ completion: state.initialScrollSession.completion,
1245
+ kind,
1246
+ previousDataLength: state.initialScrollSession.previousDataLength
1247
+ });
1248
+ }
1249
+ (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
1250
+ return state.initialScrollSession.completion;
1251
+ }
1252
+ var initialScrollCompletion = {
1253
+ didDispatchNativeScroll(state) {
1254
+ var _a3, _b;
1255
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
1256
+ },
1257
+ didRetrySilentInitialScroll(state) {
1258
+ var _a3, _b;
1259
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
1260
+ },
1261
+ markInitialScrollNativeDispatch(state) {
1262
+ ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
1263
+ },
1264
+ markSilentInitialScrollRetry(state) {
1265
+ ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
1266
+ },
1267
+ resetFlags(state) {
1268
+ if (!state.initialScrollSession) {
1269
+ return;
1270
+ }
1271
+ const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
1272
+ completion.didDispatchNativeScroll = void 0;
1273
+ completion.didRetrySilentInitialScroll = void 0;
1274
+ }
1275
+ };
1276
+ var initialScrollWatchdog = {
1277
+ clear(state) {
1278
+ initialScrollWatchdog.set(state, void 0);
1279
+ },
1280
+ didObserveProgress(newScroll, watchdog) {
1281
+ const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
1282
+ const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
1283
+ return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET || nextDistance + INITIAL_SCROLL_MIN_TARGET_OFFSET < previousDistance;
1284
+ },
1285
+ get(state) {
1286
+ var _a3, _b;
1287
+ return (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog;
1288
+ },
1289
+ hasNonZeroTargetOffset(targetOffset) {
1290
+ return targetOffset !== void 0 && targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1291
+ },
1292
+ isAtZeroTargetOffset(targetOffset) {
1293
+ return targetOffset <= INITIAL_SCROLL_MIN_TARGET_OFFSET;
1294
+ },
1295
+ set(state, watchdog) {
1296
+ var _a3, _b;
1297
+ if (!watchdog && !((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog)) {
1298
+ return;
1299
+ }
1300
+ const completion = ensureInitialScrollSessionCompletion(state);
1301
+ completion.watchdog = watchdog ? {
1302
+ startScroll: watchdog.startScroll,
1303
+ targetOffset: watchdog.targetOffset
1304
+ } : void 0;
1305
+ }
1306
+ };
1307
+ function setInitialScrollSession(state, options = {}) {
1308
+ var _a3, _b, _c;
1309
+ const existingSession = state.initialScrollSession;
1310
+ const kind = (_a3 = options.kind) != null ? _a3 : existingSession == null ? void 0 : existingSession.kind;
1311
+ const completion = existingSession == null ? void 0 : existingSession.completion;
1312
+ const hasBootstrapOverride = Object.hasOwn(options, "bootstrap");
1313
+ const bootstrap = kind === "bootstrap" ? hasBootstrapOverride ? options.bootstrap : (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0 : void 0;
1314
+ if (!kind) {
1315
+ return clearInitialScrollSession(state);
1316
+ }
1317
+ if (!state.initialScroll && !bootstrap && !hasInitialScrollSessionCompletion(completion)) {
1318
+ return clearInitialScrollSession(state);
1319
+ }
1320
+ const previousDataLength = (_c = (_b = options.previousDataLength) != null ? _b : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _c : 0;
1321
+ state.initialScrollSession = createInitialScrollSession({
1322
+ bootstrap,
1323
+ completion,
1324
+ kind,
1325
+ previousDataLength
1326
+ });
1327
+ return state.initialScrollSession;
1328
+ }
1329
+
1330
+ // src/core/finishScrollTo.ts
1331
+ function finishScrollTo(ctx) {
1332
+ var _a3, _b;
1333
+ const state = ctx.state;
1334
+ if (state == null ? void 0 : state.scrollingTo) {
1335
+ const resolvePendingScroll = state.pendingScrollResolve;
1336
+ state.pendingScrollResolve = void 0;
1337
+ const scrollingTo = state.scrollingTo;
1338
+ state.scrollHistory.length = 0;
1339
+ state.scrollingTo = void 0;
1340
+ if (state.pendingTotalSize !== void 0) {
1341
+ addTotalSize(ctx, null, state.pendingTotalSize);
1342
+ }
1343
+ if (PlatformAdjustBreaksScroll) {
1344
+ state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
1345
+ }
1346
+ if (scrollingTo.isInitialScroll || state.initialScroll) {
1347
+ const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1348
+ finishInitialScroll(ctx, {
1349
+ onFinished: resolvePendingScroll,
1350
+ preserveTarget: isOffsetSession && state.props.data.length === 0 || !!scrollingTo.isInitialScroll && !!((_b = state.initialScroll) == null ? void 0 : _b.preserveForFooterLayout),
1351
+ recalculateItems: true,
1352
+ syncObservedOffset: isOffsetSession,
1353
+ waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
1354
+ });
1355
+ return;
1356
+ }
1357
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1358
+ }
1359
+ }
1360
+
1361
+ // src/core/checkFinishedScroll.ts
1362
+ var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
1363
+ var INITIAL_SCROLL_COMPLETION_TARGET_EPSILON = 1;
1364
+ var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
1365
+ var SILENT_INITIAL_SCROLL_RETRY_DELAY_MS = 16;
1366
+ var SILENT_INITIAL_SCROLL_TARGET_EPSILON = 1;
1367
+ function checkFinishedScroll(ctx, options) {
1368
+ const scrollingTo = ctx.state.scrollingTo;
1369
+ if (options == null ? void 0 : options.onlyIfAligned) {
1370
+ if (!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || scrollingTo.animated) {
1371
+ return;
1372
+ }
1373
+ if (!getResolvedScrollCompletionState(ctx, scrollingTo).isAtResolvedTarget) {
1374
+ return;
1375
+ }
1376
+ }
1377
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1378
+ }
1379
+ function hasScrollCompletionOwnership(state, options) {
1380
+ const { clampedTargetOffset, scrollingTo } = options;
1381
+ return !scrollingTo.isInitialScroll || state.hasScrolled || clampedTargetOffset <= INITIAL_SCROLL_COMPLETION_TARGET_EPSILON;
1382
+ }
1383
+ function isSilentInitialDispatch(state, scrollingTo) {
1384
+ return !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled;
1385
+ }
1386
+ function getInitialScrollWatchdogTargetOffset(state) {
1387
+ var _a3;
1388
+ return (_a3 = initialScrollWatchdog.get(state)) == null ? void 0 : _a3.targetOffset;
1389
+ }
1390
+ function isNativeInitialNonZeroTarget(state) {
1391
+ const targetOffset = getInitialScrollWatchdogTargetOffset(state);
1392
+ return !state.didFinishInitialScroll && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
1393
+ }
1394
+ function shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) {
1395
+ var _a3, _b;
1396
+ if (!scrollingTo.isInitialScroll || scrollingTo.animated || !state.didContainersLayout) {
1397
+ return false;
1398
+ }
1399
+ if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap") {
1400
+ return false;
1401
+ }
1402
+ const targetOffset = (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset;
1403
+ if (initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled) {
1404
+ return false;
1405
+ }
1406
+ if (initialScrollWatchdog.isAtZeroTargetOffset(targetOffset) || Math.abs(state.scroll - targetOffset) > 1 || Math.abs(state.scrollPending - targetOffset) > 1) {
1407
+ return false;
1408
+ }
1409
+ return !!scrollingTo.waitForInitialScrollCompletionFrame || isNativeInitialNonZeroTarget(state);
1410
+ }
1411
+ function shouldFinishInitialZeroTargetScroll(ctx) {
1412
+ var _a3;
1413
+ const { state } = ctx;
1414
+ return !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) && state.props.data.length > 0 && getContentSize(ctx) <= state.scrollLength && state.scrollPending <= INITIAL_SCROLL_ZERO_TARGET_EPSILON;
1415
+ }
1416
+ function getResolvedScrollCompletionState(ctx, scrollingTo) {
1417
+ var _a3;
1418
+ const { state } = ctx;
1419
+ const scroll = state.scrollPending;
1420
+ const adjust = state.scrollAdjustHandler.getAdjust();
1421
+ const clampedTargetOffset = (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
1422
+ const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
1423
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
1424
+ const diff2 = Math.abs(diff1 - adjust);
1425
+ return {
1426
+ clampedTargetOffset,
1427
+ isAtResolvedTarget: Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || !scrollingTo.animated && diff2 < 1)
1428
+ };
1429
+ }
1430
+ function checkFinishedScrollFrame(ctx) {
1431
+ const scrollingTo = ctx.state.scrollingTo;
1432
+ if (!scrollingTo) {
1433
+ return;
1434
+ }
1435
+ const { state } = ctx;
1436
+ state.animFrameCheckFinishedScroll = void 0;
1437
+ const completionState = getResolvedScrollCompletionState(ctx, scrollingTo);
1438
+ if (completionState.isAtResolvedTarget && hasScrollCompletionOwnership(state, {
1439
+ clampedTargetOffset: completionState.clampedTargetOffset,
1440
+ scrollingTo
1441
+ })) {
1442
+ finishScrollTo(ctx);
1443
+ }
1444
+ }
1445
+ function scrollToFallbackOffset(ctx, offset) {
1446
+ var _a3;
1447
+ (_a3 = ctx.state.refScroller.current) == null ? void 0 : _a3.scrollTo({
1448
+ animated: false,
1449
+ x: ctx.state.props.horizontal ? offset : 0,
1450
+ y: ctx.state.props.horizontal ? 0 : offset
1451
+ });
1452
+ }
1453
+ function checkFinishedScrollFallback(ctx) {
1454
+ const state = ctx.state;
1455
+ const scrollingTo = state.scrollingTo;
1456
+ const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1457
+ const silentInitialDispatch = isSilentInitialDispatch(state, scrollingTo);
1458
+ const canFinishInitialWithoutNativeProgress = scrollingTo !== void 0 ? shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) : false;
1459
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget && !canFinishInitialWithoutNativeProgress || !state.didContainersLayout;
1460
+ const initialDelay = shouldFinishInitialZeroTarget || canFinishInitialWithoutNativeProgress ? 0 : silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : slowTimeout ? 500 : 100;
1461
+ state.timeoutCheckFinishedScrollFallback = setTimeout(() => {
1462
+ let numChecks = 0;
1463
+ const scheduleFallbackCheck = (delay) => {
1464
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, delay);
1465
+ };
1466
+ const checkHasScrolled = () => {
1467
+ var _a3, _b, _c;
1468
+ state.timeoutCheckFinishedScrollFallback = void 0;
1469
+ const isStillScrollingTo = state.scrollingTo;
1470
+ if (isStillScrollingTo) {
1471
+ numChecks++;
1472
+ const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
1473
+ const maxChecks = silentInitialDispatch ? 5 : isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
1474
+ const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1475
+ const canFinishInitialScrollWithoutNativeProgress = shouldFinishInitialScrollWithoutNativeProgress(
1476
+ state,
1477
+ isStillScrollingTo
1478
+ );
1479
+ const completionState = getResolvedScrollCompletionState(ctx, isStillScrollingTo);
1480
+ const canFinishAfterSilentNativeDispatch = silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
1481
+ const shouldRetrySilentInitialNativeScroll = Platform2.OS === "android" && canFinishAfterSilentNativeDispatch && !initialScrollCompletion.didRetrySilentInitialScroll(state);
1482
+ if (shouldRetrySilentInitialNativeScroll) {
1483
+ const targetOffset = (_b = (_a3 = getInitialScrollWatchdogTargetOffset(state)) != null ? _a3 : isStillScrollingTo.targetOffset) != null ? _b : 0;
1484
+ const jiggleOffset = targetOffset >= SILENT_INITIAL_SCROLL_TARGET_EPSILON ? targetOffset - SILENT_INITIAL_SCROLL_TARGET_EPSILON : targetOffset + SILENT_INITIAL_SCROLL_TARGET_EPSILON;
1485
+ initialScrollCompletion.markSilentInitialScrollRetry(state);
1486
+ scrollToFallbackOffset(ctx, jiggleOffset);
1487
+ requestAnimationFrame(() => {
1488
+ scrollToFallbackOffset(ctx, targetOffset);
1489
+ });
1490
+ scheduleFallbackCheck(SILENT_INITIAL_SCROLL_RETRY_DELAY_MS);
1491
+ } else if (shouldFinishZeroTarget || state.hasScrolled || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
1492
+ finishScrollTo(ctx);
1493
+ } else if (isNativeInitialPending && numChecks <= maxChecks) {
1494
+ const targetOffset = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : state.scrollPending;
1495
+ scrollToFallbackOffset(ctx, targetOffset);
1496
+ scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
1497
+ } else {
1498
+ scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
1499
+ }
1500
+ }
1501
+ };
1502
+ checkHasScrolled();
1503
+ }, initialDelay);
1504
+ }
1505
+
1506
+ // src/core/doScrollTo.native.ts
1507
+ function doScrollTo(ctx, params) {
1508
+ const state = ctx.state;
1509
+ const { animated, horizontal, isInitialScroll, offset } = params;
1510
+ const isAnimated = !!animated;
1511
+ const { refScroller } = state;
1512
+ const scroller = refScroller.current;
1513
+ if (!scroller) {
1514
+ return;
1515
+ }
1516
+ scroller.scrollTo({
1517
+ animated: isAnimated,
1518
+ x: horizontal ? offset : 0,
1519
+ y: horizontal ? 0 : offset
1520
+ });
1521
+ if (isInitialScroll) {
1522
+ initialScrollCompletion.markInitialScrollNativeDispatch(state);
1523
+ }
1524
+ if (!isAnimated) {
1525
+ state.scroll = offset;
1526
+ checkFinishedScrollFallback(ctx);
1527
+ }
1528
+ }
1529
+
1530
+ // src/core/scrollTo.ts
1531
+ function syncInitialScrollNativeWatchdog(state, options) {
1532
+ var _a3;
1533
+ const { isInitialScroll, requestedOffset, targetOffset } = options;
1534
+ const existingWatchdog = initialScrollWatchdog.get(state);
1535
+ const shouldWatchInitialNativeScroll = !state.didFinishInitialScroll && (isInitialScroll || !!existingWatchdog) && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
1536
+ const shouldClearInitialNativeScrollWatchdog = !state.didFinishInitialScroll && !!existingWatchdog && initialScrollWatchdog.isAtZeroTargetOffset(requestedOffset);
1537
+ if (shouldWatchInitialNativeScroll) {
1538
+ state.hasScrolled = false;
1539
+ initialScrollWatchdog.set(state, {
1540
+ startScroll: (_a3 = existingWatchdog == null ? void 0 : existingWatchdog.startScroll) != null ? _a3 : state.scroll,
1541
+ targetOffset
1542
+ });
1543
+ return;
1544
+ }
1545
+ if (shouldClearInitialNativeScrollWatchdog) {
1546
+ initialScrollWatchdog.clear(state);
1547
+ }
1548
+ }
1549
+ function scrollTo(ctx, params) {
1550
+ var _a3;
1551
+ const state = ctx.state;
1552
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1553
+ const {
1554
+ animated,
1555
+ isInitialScroll,
1556
+ offset: scrollTargetOffset,
1557
+ precomputedWithViewOffset,
1558
+ waitForInitialScrollCompletionFrame
1559
+ } = scrollTarget;
1560
+ const {
1561
+ props: { horizontal }
1562
+ } = state;
1563
+ if (state.animFrameCheckFinishedScroll) {
1564
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1565
+ }
1566
+ if (state.timeoutCheckFinishedScrollFallback) {
1567
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1568
+ }
1569
+ const requestedOffset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1570
+ const shouldPreserveRawInitialOffsetRequest = !!isInitialScroll && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1571
+ const targetOffset = clampScrollOffset(ctx, requestedOffset, scrollTarget);
1572
+ const offset = shouldPreserveRawInitialOffsetRequest ? requestedOffset : targetOffset;
1573
+ state.scrollHistory.length = 0;
1574
+ if (!noScrollingTo) {
1575
+ if (isInitialScroll) {
1576
+ initialScrollCompletion.resetFlags(state);
1577
+ }
1578
+ state.scrollingTo = {
1579
+ ...scrollTarget,
1580
+ targetOffset,
1581
+ waitForInitialScrollCompletionFrame
1582
+ };
1583
+ }
1584
+ state.scrollPending = targetOffset;
1585
+ syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
1586
+ if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
1587
+ doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
1588
+ } else {
1589
+ state.scroll = offset;
1590
+ }
1591
+ }
1592
+
1593
+ // src/core/scrollToIndex.ts
1594
+ function clampScrollIndex(index, dataLength) {
1595
+ if (dataLength <= 0) {
1596
+ return -1;
1597
+ }
1598
+ if (index >= dataLength) {
1599
+ return dataLength - 1;
1600
+ }
1601
+ if (index < 0) {
1602
+ return 0;
1603
+ }
1604
+ return index;
1605
+ }
1606
+ function scrollToIndex(ctx, {
1607
+ index,
1608
+ viewOffset = 0,
1609
+ animated = true,
1610
+ forceScroll,
1611
+ isInitialScroll,
1612
+ viewPosition
1613
+ }) {
1614
+ const state = ctx.state;
1615
+ const { data } = state.props;
1616
+ index = clampScrollIndex(index, data.length);
1617
+ const itemSize = getItemSizeAtIndex(ctx, index);
1618
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
1619
+ const isLast = index === data.length - 1;
1620
+ if (isLast && viewPosition === void 0) {
1621
+ viewPosition = 1;
1622
+ }
1623
+ state.scrollForNextCalculateItemsInView = void 0;
1624
+ scrollTo(ctx, {
1625
+ animated,
1626
+ forceScroll,
1627
+ index,
1628
+ isInitialScroll,
1629
+ itemSize,
1630
+ offset: firstIndexOffset,
1631
+ viewOffset,
1632
+ viewPosition: viewPosition != null ? viewPosition : 0
1633
+ });
1634
+ }
1635
+
1180
1636
  // src/utils/checkThreshold.ts
1181
1637
  var HYSTERESIS_MULTIPLIER = 1.3;
1182
1638
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
@@ -1345,214 +1801,766 @@ function setInitialRenderState(ctx, {
1345
1801
  }
1346
1802
  }
1347
1803
 
1348
- // src/core/finishScrollTo.ts
1349
- function finishScrollTo(ctx) {
1350
- var _a3, _b;
1351
- const state = ctx.state;
1352
- if (state == null ? void 0 : state.scrollingTo) {
1353
- const resolvePendingScroll = state.pendingScrollResolve;
1354
- state.pendingScrollResolve = void 0;
1355
- const scrollingTo = state.scrollingTo;
1356
- state.scrollHistory.length = 0;
1357
- state.initialScroll = void 0;
1358
- state.initialScrollUsesOffset = false;
1359
- state.initialAnchor = void 0;
1360
- state.initialNativeScrollWatchdog = void 0;
1361
- state.scrollingTo = void 0;
1362
- if (state.pendingTotalSize !== void 0) {
1363
- addTotalSize(ctx, null, state.pendingTotalSize);
1364
- }
1365
- if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1366
- (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1367
- }
1368
- if (PlatformAdjustBreaksScroll) {
1369
- state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
1370
- }
1371
- setInitialRenderState(ctx, { didInitialScroll: true });
1372
- checkThresholds(ctx);
1373
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1374
- }
1804
+ // src/core/initialScroll.ts
1805
+ function syncInitialScrollOffset(state, offset) {
1806
+ state.scroll = offset;
1807
+ state.scrollPending = offset;
1808
+ state.scrollPrev = offset;
1375
1809
  }
1376
-
1377
- // src/core/checkFinishedScroll.ts
1378
- var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1379
- var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
1380
- var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
1381
- function checkFinishedScroll(ctx) {
1382
- ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1810
+ function dispatchInitialScroll(ctx, params) {
1811
+ const { forceScroll, resolvedOffset, target, waitForCompletionFrame } = params;
1812
+ const requestedIndex = target.index;
1813
+ const index = requestedIndex !== void 0 ? clampScrollIndex(requestedIndex, ctx.state.props.data.length) : void 0;
1814
+ const itemSize = getItemSizeAtIndex(ctx, index);
1815
+ scrollTo(ctx, {
1816
+ animated: false,
1817
+ forceScroll,
1818
+ index: index !== void 0 && index >= 0 ? index : void 0,
1819
+ isInitialScroll: true,
1820
+ itemSize,
1821
+ offset: resolvedOffset,
1822
+ precomputedWithViewOffset: true,
1823
+ viewOffset: target.viewOffset,
1824
+ viewPosition: target.viewPosition,
1825
+ waitForInitialScrollCompletionFrame: waitForCompletionFrame
1826
+ });
1383
1827
  }
1384
- function checkFinishedScrollFrame(ctx) {
1828
+ function setInitialScrollTarget(state, target, options) {
1385
1829
  var _a3;
1386
- const scrollingTo = ctx.state.scrollingTo;
1387
- if (scrollingTo) {
1388
- const { state } = ctx;
1389
- state.animFrameCheckFinishedScroll = void 0;
1390
- const scroll = state.scrollPending;
1391
- const adjust = state.scrollAdjustHandler.getAdjust();
1392
- const clampedTargetOffset = (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
1393
- const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
1394
- const diff1 = Math.abs(scroll - clampedTargetOffset);
1395
- const diff2 = Math.abs(diff1 - adjust);
1396
- const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
1397
- const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
1398
- if (isNotOverscrolled && isAtTarget) {
1399
- finishScrollTo(ctx);
1400
- }
1830
+ state.initialScroll = target;
1831
+ if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
1832
+ state.didFinishInitialScroll = false;
1401
1833
  }
1834
+ setInitialScrollSession(state, {
1835
+ kind: ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? "offset" : "bootstrap"
1836
+ });
1402
1837
  }
1403
- function checkFinishedScrollFallback(ctx) {
1838
+ function finishInitialScroll(ctx, options) {
1839
+ var _a3, _b, _c;
1404
1840
  const state = ctx.state;
1405
- const scrollingTo = state.scrollingTo;
1406
- const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1407
- const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget || !state.didContainersLayout;
1408
- state.timeoutCheckFinishedScrollFallback = setTimeout(
1409
- () => {
1410
- let numChecks = 0;
1411
- const checkHasScrolled = () => {
1412
- var _a3, _b;
1413
- state.timeoutCheckFinishedScrollFallback = void 0;
1414
- const isStillScrollingTo = state.scrollingTo;
1415
- if (isStillScrollingTo) {
1416
- numChecks++;
1417
- const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
1418
- const maxChecks = isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
1419
- const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1420
- if (shouldFinishZeroTarget || state.hasScrolled || numChecks > maxChecks) {
1421
- finishScrollTo(ctx);
1422
- } else if (isNativeInitialPending && numChecks <= maxChecks) {
1423
- const targetOffset = (_b = (_a3 = state.initialNativeScrollWatchdog) == null ? void 0 : _a3.targetOffset) != null ? _b : state.scrollPending;
1424
- const scroller = state.refScroller.current;
1425
- if (scroller) {
1426
- scroller.scrollTo({
1427
- animated: false,
1428
- x: state.props.horizontal ? targetOffset : 0,
1429
- y: state.props.horizontal ? 0 : targetOffset
1430
- });
1431
- }
1432
- state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
1433
- } else {
1434
- state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
1435
- }
1436
- }
1437
- };
1438
- checkHasScrolled();
1439
- },
1440
- slowTimeout ? 500 : 100
1441
- );
1841
+ if ((options == null ? void 0 : options.resolvedOffset) !== void 0) {
1842
+ syncInitialScrollOffset(state, options.resolvedOffset);
1843
+ } else if ((options == null ? void 0 : options.syncObservedOffset) && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1844
+ const observedOffset = (_c = (_b = state.refScroller.current) == null ? void 0 : _b.getCurrentScrollOffset) == null ? void 0 : _c.call(_b);
1845
+ if (typeof observedOffset === "number" && Number.isFinite(observedOffset)) {
1846
+ syncInitialScrollOffset(state, observedOffset);
1847
+ }
1848
+ }
1849
+ const complete = () => {
1850
+ var _a4, _b2, _c2, _d, _e, _f, _g;
1851
+ const shouldReleaseDeferredPublicOnScroll = Platform2.OS === "web" && ((_a4 = state.initialScrollSession) == null ? void 0 : _a4.kind) === "bootstrap";
1852
+ const finalScrollOffset = (_d = (_c2 = (_b2 = options == null ? void 0 : options.resolvedOffset) != null ? _b2 : state.scrollPending) != null ? _c2 : state.scroll) != null ? _d : 0;
1853
+ initialScrollWatchdog.clear(state);
1854
+ if (!(options == null ? void 0 : options.preserveTarget)) {
1855
+ state.initialScroll = void 0;
1856
+ }
1857
+ setInitialScrollSession(state);
1858
+ if ((options == null ? void 0 : options.recalculateItems) && ((_e = state.props) == null ? void 0 : _e.data)) {
1859
+ (_f = state.triggerCalculateItemsInView) == null ? void 0 : _f.call(state, { forceFullItemPositions: true });
1860
+ }
1861
+ if (options == null ? void 0 : options.recalculateItems) {
1862
+ checkThresholds(ctx);
1863
+ }
1864
+ setInitialRenderState(ctx, { didInitialScroll: true });
1865
+ if (shouldReleaseDeferredPublicOnScroll) {
1866
+ releaseDeferredPublicOnScroll(ctx, finalScrollOffset);
1867
+ }
1868
+ (_g = options == null ? void 0 : options.onFinished) == null ? void 0 : _g.call(options);
1869
+ };
1870
+ if (options == null ? void 0 : options.waitForCompletionFrame) {
1871
+ requestAnimationFrame(complete);
1872
+ return;
1873
+ }
1874
+ complete();
1442
1875
  }
1443
- function isNativeInitialNonZeroTarget(state) {
1444
- return !state.didFinishInitialScroll && !!state.initialNativeScrollWatchdog && state.initialNativeScrollWatchdog.targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1876
+ function resolveInitialScrollOffset(ctx, initialScroll) {
1877
+ var _a3, _b;
1878
+ const state = ctx.state;
1879
+ if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1880
+ return (_b = initialScroll.contentOffset) != null ? _b : 0;
1881
+ }
1882
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
1883
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
1884
+ return clampScrollOffset(ctx, resolvedOffset, initialScroll);
1445
1885
  }
1446
- function shouldFinishInitialZeroTargetScroll(ctx) {
1886
+ function getAdvanceableInitialScrollState(state, options) {
1887
+ const { didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
1888
+ const initialScroll = state.initialScroll;
1889
+ const isInitialScrollInProgress = !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll);
1890
+ const shouldWaitForInitialLayout = !!(options == null ? void 0 : options.requiresMeasuredLayout) && !queuedInitialLayout && !isInitialScrollInProgress;
1891
+ if (!initialScroll || shouldWaitForInitialLayout || didFinishInitialScroll || scrollingTo && !isInitialScrollInProgress) {
1892
+ return void 0;
1893
+ }
1894
+ return {
1895
+ initialScroll,
1896
+ isInitialScrollInProgress,
1897
+ queuedInitialLayout,
1898
+ scrollingTo
1899
+ };
1900
+ }
1901
+ function advanceMeasuredInitialScroll(ctx, options) {
1902
+ var _a3, _b, _c;
1903
+ const state = ctx.state;
1904
+ const advanceableState = getAdvanceableInitialScrollState(state, {
1905
+ requiresMeasuredLayout: true
1906
+ });
1907
+ if (!advanceableState) {
1908
+ return false;
1909
+ }
1910
+ const { initialScroll, isInitialScrollInProgress, queuedInitialLayout } = advanceableState;
1911
+ const scrollingTo = isInitialScrollInProgress ? advanceableState.scrollingTo : void 0;
1912
+ const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
1913
+ const activeInitialTargetOffset = scrollingTo ? (_a3 = scrollingTo.targetOffset) != null ? _a3 : scrollingTo.offset : void 0;
1914
+ const didOffsetChange = initialScroll.contentOffset === void 0 || Math.abs(initialScroll.contentOffset - resolvedOffset) > 1;
1915
+ const didActiveInitialTargetChange = activeInitialTargetOffset !== void 0 && Math.abs(activeInitialTargetOffset - resolvedOffset) > 1;
1916
+ const isAlreadyAtDesiredInitialTarget = activeInitialTargetOffset !== void 0 && Math.abs(state.scroll - activeInitialTargetOffset) <= 1 && Math.abs(state.scrollPending - activeInitialTargetOffset) <= 1;
1917
+ if (!(options == null ? void 0 : options.forceScroll) && !didOffsetChange && isInitialScrollInProgress && !didActiveInitialTargetChange) {
1918
+ return false;
1919
+ }
1920
+ if ((options == null ? void 0 : options.forceScroll) && isAlreadyAtDesiredInitialTarget) {
1921
+ return false;
1922
+ }
1923
+ if (didOffsetChange && ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) !== "offset") {
1924
+ setInitialScrollTarget(state, { ...initialScroll, contentOffset: resolvedOffset });
1925
+ }
1926
+ const forceScroll = (_c = options == null ? void 0 : options.forceScroll) != null ? _c : !!queuedInitialLayout || isInitialScrollInProgress && didOffsetChange;
1927
+ dispatchInitialScroll(ctx, {
1928
+ forceScroll,
1929
+ resolvedOffset,
1930
+ target: initialScroll
1931
+ });
1932
+ return true;
1933
+ }
1934
+ function advanceOffsetInitialScroll(ctx, options) {
1935
+ var _a3, _b;
1936
+ const state = ctx.state;
1937
+ const advanceableState = getAdvanceableInitialScrollState(state);
1938
+ if (!advanceableState) {
1939
+ return false;
1940
+ }
1941
+ const { initialScroll, queuedInitialLayout } = advanceableState;
1942
+ const resolvedOffset = (_a3 = initialScroll.contentOffset) != null ? _a3 : 0;
1943
+ const isAlreadyAtDesiredInitialTarget = Math.abs(state.scroll - resolvedOffset) <= 1 && Math.abs(state.scrollPending - resolvedOffset) <= 1;
1944
+ if ((options == null ? void 0 : options.forceScroll) && isAlreadyAtDesiredInitialTarget) {
1945
+ return false;
1946
+ }
1947
+ const hasMeasuredScrollLayout = !!state.lastLayout && state.scrollLength > 0;
1948
+ const forceScroll = (_b = options == null ? void 0 : options.forceScroll) != null ? _b : hasMeasuredScrollLayout || !!queuedInitialLayout;
1949
+ dispatchInitialScroll(ctx, {
1950
+ forceScroll,
1951
+ resolvedOffset,
1952
+ target: initialScroll
1953
+ });
1954
+ return true;
1955
+ }
1956
+ function advanceCurrentInitialScrollSession(ctx, options) {
1447
1957
  var _a3;
1448
- const { state } = ctx;
1449
- return !!((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) && state.props.data.length > 0 && getContentSize(ctx) <= state.scrollLength && state.scrollPending <= INITIAL_SCROLL_ZERO_TARGET_EPSILON;
1958
+ return ((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? advanceOffsetInitialScroll(ctx, {
1959
+ forceScroll: options == null ? void 0 : options.forceScroll
1960
+ }) : advanceMeasuredInitialScroll(ctx, {
1961
+ forceScroll: options == null ? void 0 : options.forceScroll
1962
+ });
1450
1963
  }
1451
1964
 
1452
- // src/core/doScrollTo.native.ts
1453
- function doScrollTo(ctx, params) {
1965
+ // src/utils/checkAllSizesKnown.ts
1966
+ function isNullOrUndefined2(value) {
1967
+ return value === null || value === void 0;
1968
+ }
1969
+ function getMountedBufferedIndices(state) {
1970
+ const { startBuffered, endBuffered } = state;
1971
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1972
+ return Array.from(state.containerItemKeys.keys()).map((key) => state.indexByKey.get(key)).filter((index) => index !== void 0 && index >= startBuffered && index <= endBuffered).sort((a, b) => a - b);
1973
+ }
1974
+ return [];
1975
+ }
1976
+ function checkAllSizesKnown(state, indices = getMountedBufferedIndices(state)) {
1977
+ return indices.length > 0 && indices.every((index) => {
1978
+ const key = getId(state, index);
1979
+ return state.sizesKnown.has(key);
1980
+ });
1981
+ }
1982
+
1983
+ // src/core/bootstrapInitialScroll.ts
1984
+ var DEFAULT_BOOTSTRAP_REVEAL_EPSILON = 1;
1985
+ var DEFAULT_BOOTSTRAP_REVEAL_MAX_FRAMES = 8;
1986
+ var DEFAULT_BOOTSTRAP_REVEAL_MAX_PASSES = 24;
1987
+ var BOOTSTRAP_REVEAL_ABORT_WARNING = "LegendList bootstrap initial scroll aborted after exceeding convergence bounds.";
1988
+ function getBootstrapInitialScrollSession(state) {
1989
+ var _a3;
1990
+ return ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
1991
+ }
1992
+ function isOffsetInitialScrollSession(state) {
1993
+ var _a3;
1994
+ return ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1995
+ }
1996
+ function doVisibleIndicesMatch(previous, next) {
1997
+ if (!previous || previous.length !== next.length) {
1998
+ return false;
1999
+ }
2000
+ for (let i = 0; i < previous.length; i++) {
2001
+ if (previous[i] !== next[i]) {
2002
+ return false;
2003
+ }
2004
+ }
2005
+ return true;
2006
+ }
2007
+ function getBootstrapRevealVisibleIndices(options) {
2008
+ const { dataLength, getSize, offset, positions, scrollLength, startIndex: requestedStartIndex } = options;
2009
+ const endOffset = offset + scrollLength;
2010
+ const visibleIndices = [];
2011
+ let index = requestedStartIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, requestedStartIndex)) : 0;
2012
+ while (index > 0) {
2013
+ const previousIndex = index - 1;
2014
+ const previousPosition = positions[previousIndex];
2015
+ if (previousPosition === void 0) {
2016
+ index = previousIndex;
2017
+ continue;
2018
+ }
2019
+ const previousSize = getSize(previousIndex);
2020
+ if (previousSize === void 0) {
2021
+ index = previousIndex;
2022
+ continue;
2023
+ }
2024
+ if (previousPosition + previousSize <= offset) {
2025
+ break;
2026
+ }
2027
+ index = previousIndex;
2028
+ }
2029
+ for (; index < dataLength; index++) {
2030
+ const position = positions[index];
2031
+ if (position === void 0) {
2032
+ continue;
2033
+ }
2034
+ const size = getSize(index);
2035
+ if (size === void 0) {
2036
+ continue;
2037
+ }
2038
+ if (position < endOffset && position + size > offset) {
2039
+ visibleIndices.push(index);
2040
+ } else if (visibleIndices.length > 0 && position >= endOffset) {
2041
+ break;
2042
+ }
2043
+ }
2044
+ return visibleIndices;
2045
+ }
2046
+ function shouldAbortBootstrapReveal(options) {
2047
+ const {
2048
+ mountFrameCount,
2049
+ maxFrames = DEFAULT_BOOTSTRAP_REVEAL_MAX_FRAMES,
2050
+ maxPasses = DEFAULT_BOOTSTRAP_REVEAL_MAX_PASSES,
2051
+ passCount
2052
+ } = options;
2053
+ return mountFrameCount >= maxFrames || passCount >= maxPasses;
2054
+ }
2055
+ function abortBootstrapRevealIfNeeded(ctx, options) {
2056
+ if (!shouldAbortBootstrapReveal(options)) {
2057
+ return false;
2058
+ }
2059
+ if (IS_DEV) {
2060
+ console.warn(BOOTSTRAP_REVEAL_ABORT_WARNING);
2061
+ }
2062
+ abortBootstrapInitialScroll(ctx);
2063
+ return true;
2064
+ }
2065
+ function clearBootstrapInitialScrollSession(state) {
2066
+ var _a3;
2067
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2068
+ const frameHandle = bootstrapInitialScroll == null ? void 0 : bootstrapInitialScroll.frameHandle;
2069
+ if (frameHandle !== void 0 && typeof cancelAnimationFrame === "function") {
2070
+ cancelAnimationFrame(frameHandle);
2071
+ }
2072
+ if (bootstrapInitialScroll) {
2073
+ bootstrapInitialScroll.frameHandle = void 0;
2074
+ }
2075
+ setInitialScrollSession(state, {
2076
+ bootstrap: void 0,
2077
+ kind: (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind
2078
+ });
2079
+ }
2080
+ function startBootstrapInitialScrollSession(state, options) {
2081
+ var _a3, _b, _c;
2082
+ const previousBootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2083
+ setInitialScrollSession(state, {
2084
+ bootstrap: {
2085
+ frameHandle: previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.frameHandle,
2086
+ // Re-arming during the initial mount should spend from the same watchdog budget.
2087
+ mountFrameCount: (_a3 = previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.mountFrameCount) != null ? _a3 : 0,
2088
+ passCount: 0,
2089
+ previousResolvedOffset: void 0,
2090
+ scroll: options.scroll,
2091
+ seedContentOffset: (_c = (_b = options.seedContentOffset) != null ? _b : previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.seedContentOffset) != null ? _c : options.scroll,
2092
+ targetIndexSeed: options.targetIndexSeed,
2093
+ visibleIndices: void 0
2094
+ },
2095
+ kind: "bootstrap"
2096
+ });
2097
+ }
2098
+ function resetBootstrapInitialScrollSession(state, options) {
2099
+ var _a3, _b, _c;
2100
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2101
+ if (!bootstrapInitialScroll) {
2102
+ if ((options == null ? void 0 : options.scroll) !== void 0) {
2103
+ startBootstrapInitialScrollSession(state, {
2104
+ scroll: options.scroll,
2105
+ seedContentOffset: options.seedContentOffset,
2106
+ targetIndexSeed: options.targetIndexSeed
2107
+ });
2108
+ }
2109
+ } else {
2110
+ bootstrapInitialScroll.passCount = 0;
2111
+ bootstrapInitialScroll.previousResolvedOffset = void 0;
2112
+ bootstrapInitialScroll.scroll = (_a3 = options == null ? void 0 : options.scroll) != null ? _a3 : bootstrapInitialScroll.scroll;
2113
+ bootstrapInitialScroll.seedContentOffset = (_b = options == null ? void 0 : options.seedContentOffset) != null ? _b : bootstrapInitialScroll.seedContentOffset;
2114
+ bootstrapInitialScroll.targetIndexSeed = (_c = options == null ? void 0 : options.targetIndexSeed) != null ? _c : bootstrapInitialScroll.targetIndexSeed;
2115
+ bootstrapInitialScroll.visibleIndices = void 0;
2116
+ setInitialScrollSession(state, {
2117
+ bootstrap: bootstrapInitialScroll,
2118
+ kind: "bootstrap"
2119
+ });
2120
+ }
2121
+ }
2122
+ function queueBootstrapInitialScrollReevaluation(state) {
2123
+ requestAnimationFrame(() => {
2124
+ var _a3;
2125
+ if (getBootstrapInitialScrollSession(state)) {
2126
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { forceFullItemPositions: true });
2127
+ }
2128
+ });
2129
+ }
2130
+ function ensureBootstrapInitialScrollFrameTicker(ctx) {
1454
2131
  const state = ctx.state;
1455
- const { animated, horizontal, offset } = params;
1456
- const isAnimated = !!animated;
1457
- const { refScroller } = state;
1458
- const scroller = refScroller.current;
1459
- if (!scroller) {
2132
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2133
+ if (!bootstrapInitialScroll || bootstrapInitialScroll.frameHandle !== void 0) {
1460
2134
  return;
1461
2135
  }
1462
- scroller.scrollTo({
1463
- animated: isAnimated,
1464
- x: horizontal ? offset : 0,
1465
- y: horizontal ? 0 : offset
1466
- });
1467
- if (!isAnimated) {
1468
- state.scroll = offset;
1469
- checkFinishedScrollFallback(ctx);
2136
+ const tick = () => {
2137
+ const activeBootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2138
+ if (!activeBootstrapInitialScroll) {
2139
+ return;
2140
+ }
2141
+ activeBootstrapInitialScroll.frameHandle = void 0;
2142
+ activeBootstrapInitialScroll.mountFrameCount += 1;
2143
+ if (abortBootstrapRevealIfNeeded(ctx, {
2144
+ mountFrameCount: activeBootstrapInitialScroll.mountFrameCount,
2145
+ passCount: activeBootstrapInitialScroll.passCount
2146
+ })) {
2147
+ return;
2148
+ }
2149
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2150
+ };
2151
+ bootstrapInitialScroll.frameHandle = requestAnimationFrame(tick);
2152
+ }
2153
+ function rearmBootstrapInitialScroll(ctx, options) {
2154
+ resetBootstrapInitialScrollSession(ctx.state, options);
2155
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2156
+ queueBootstrapInitialScrollReevaluation(ctx.state);
2157
+ }
2158
+ function createInitialScrollAtEndTarget(options) {
2159
+ const { dataLength, footerSize, preserveForFooterLayout, stylePaddingBottom } = options;
2160
+ return {
2161
+ contentOffset: void 0,
2162
+ index: Math.max(0, dataLength - 1),
2163
+ preserveForBottomPadding: true,
2164
+ preserveForFooterLayout,
2165
+ viewOffset: -stylePaddingBottom - footerSize,
2166
+ viewPosition: 1
2167
+ };
2168
+ }
2169
+ function shouldPreserveInitialScrollForBottomPadding(target) {
2170
+ return !!(target == null ? void 0 : target.preserveForBottomPadding);
2171
+ }
2172
+ function shouldPreserveInitialScrollForFooterLayout(target) {
2173
+ return !!(target == null ? void 0 : target.preserveForFooterLayout);
2174
+ }
2175
+ function isRetargetableBottomAlignedInitialScrollTarget(target) {
2176
+ return !!(target && target.viewPosition === 1 && (shouldPreserveInitialScrollForBottomPadding(target) || shouldPreserveInitialScrollForFooterLayout(target)));
2177
+ }
2178
+ function createRetargetedBottomAlignedInitialScroll(options) {
2179
+ const { dataLength, footerSize, initialScrollAtEnd, stylePaddingBottom, target } = options;
2180
+ const preserveForFooterLayout = shouldPreserveInitialScrollForFooterLayout(target);
2181
+ return {
2182
+ ...target,
2183
+ contentOffset: void 0,
2184
+ index: initialScrollAtEnd ? Math.max(0, dataLength - 1) : target.index,
2185
+ preserveForBottomPadding: true,
2186
+ preserveForFooterLayout,
2187
+ viewOffset: -stylePaddingBottom - (preserveForFooterLayout ? footerSize : 0),
2188
+ viewPosition: 1
2189
+ };
2190
+ }
2191
+ function areEquivalentBootstrapInitialScrollTargets(current, next) {
2192
+ return current.index === next.index && current.preserveForBottomPadding === next.preserveForBottomPadding && current.preserveForFooterLayout === next.preserveForFooterLayout && current.viewOffset === next.viewOffset && current.viewPosition === next.viewPosition;
2193
+ }
2194
+ function clearPendingInitialScrollFooterLayout(state, target) {
2195
+ if (!shouldPreserveInitialScrollForFooterLayout(target)) {
2196
+ return;
1470
2197
  }
2198
+ if (state.didFinishInitialScroll && !getBootstrapInitialScrollSession(state)) {
2199
+ state.initialScroll = void 0;
2200
+ setInitialScrollSession(state);
2201
+ return;
2202
+ }
2203
+ setInitialScrollTarget(state, { ...target, preserveForFooterLayout: void 0 });
1471
2204
  }
1472
-
1473
- // src/core/scrollTo.ts
1474
- var WATCHDOG_OFFSET_EPSILON = 1;
1475
- function scrollTo(ctx, params) {
2205
+ function didFinishedInitialScrollMoveAwayFromTarget(ctx, target, epsilon = DEFAULT_BOOTSTRAP_REVEAL_EPSILON) {
2206
+ const state = ctx.state;
2207
+ if (!state.didFinishInitialScroll) {
2208
+ return false;
2209
+ }
2210
+ const currentOffset = getObservedBootstrapInitialScrollOffset(state);
2211
+ return Math.abs(currentOffset - resolveInitialScrollOffset(ctx, target)) > epsilon;
2212
+ }
2213
+ function getObservedBootstrapInitialScrollOffset(state) {
2214
+ var _a3, _b, _c, _d;
2215
+ const observedOffset = (_b = (_a3 = state.refScroller.current) == null ? void 0 : _a3.getCurrentScrollOffset) == null ? void 0 : _b.call(_a3);
2216
+ return typeof observedOffset === "number" && Number.isFinite(observedOffset) ? observedOffset : (_d = (_c = state.scrollPending) != null ? _c : state.scroll) != null ? _d : 0;
2217
+ }
2218
+ function startBootstrapInitialScrollOnMount(ctx, options) {
2219
+ var _a3, _b, _c;
2220
+ const { initialScrollAtEnd, target } = options;
2221
+ const state = ctx.state;
2222
+ const offset = resolveInitialScrollOffset(ctx, target);
2223
+ const shouldFinishAtOrigin = offset === 0 && !initialScrollAtEnd && (isOffsetInitialScrollSession(state) ? Math.abs((_a3 = target.contentOffset) != null ? _a3 : 0) <= 1 : target.index === 0 && ((_b = target.viewPosition) != null ? _b : 0) === 0 && Math.abs((_c = target.viewOffset) != null ? _c : 0) <= 1);
2224
+ const shouldFinishWithPreservedTarget = state.props.data.length === 0 && target.index !== void 0;
2225
+ if (shouldFinishAtOrigin) {
2226
+ clearBootstrapInitialScrollSession(state);
2227
+ finishInitialScroll(ctx, {
2228
+ resolvedOffset: offset
2229
+ });
2230
+ } else if (shouldFinishWithPreservedTarget) {
2231
+ clearBootstrapInitialScrollSession(state);
2232
+ finishInitialScroll(ctx, {
2233
+ preserveTarget: true,
2234
+ resolvedOffset: offset
2235
+ });
2236
+ } else {
2237
+ startBootstrapInitialScrollSession(state, {
2238
+ scroll: offset,
2239
+ seedContentOffset: Platform2.OS === "web" ? 0 : offset,
2240
+ targetIndexSeed: target.index
2241
+ });
2242
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2243
+ }
2244
+ }
2245
+ function handleBootstrapInitialScrollDataChange(ctx, options) {
2246
+ const { dataLength, didDataChange, initialScrollAtEnd, previousDataLength, stylePaddingBottom } = options;
2247
+ const state = ctx.state;
2248
+ const initialScroll = state.initialScroll;
2249
+ if (isOffsetInitialScrollSession(state) || !initialScroll) {
2250
+ return;
2251
+ }
2252
+ const shouldResetDidFinish = !!(state.didFinishInitialScroll && previousDataLength === 0 && dataLength > 0 && initialScroll.index !== void 0);
2253
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2254
+ const shouldRetargetBottomAligned = dataLength > 0 && (initialScrollAtEnd || isRetargetableBottomAlignedInitialScrollTarget(initialScroll));
2255
+ if (!didDataChange && !shouldResetDidFinish && !shouldRetargetBottomAligned) {
2256
+ return;
2257
+ }
2258
+ if (shouldRetargetBottomAligned) {
2259
+ if (!shouldResetDidFinish && didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2260
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2261
+ return;
2262
+ }
2263
+ const updatedInitialScroll = initialScrollAtEnd ? createInitialScrollAtEndTarget({
2264
+ dataLength,
2265
+ footerSize: peek$(ctx, "footerSize") || 0,
2266
+ preserveForFooterLayout: shouldPreserveInitialScrollForFooterLayout(initialScroll),
2267
+ stylePaddingBottom
2268
+ }) : createRetargetedBottomAlignedInitialScroll({
2269
+ dataLength,
2270
+ footerSize: peek$(ctx, "footerSize") || 0,
2271
+ initialScrollAtEnd,
2272
+ stylePaddingBottom,
2273
+ target: initialScroll
2274
+ });
2275
+ if (!areEquivalentBootstrapInitialScrollTargets(initialScroll, updatedInitialScroll) || !!bootstrapInitialScroll || shouldResetDidFinish || didDataChange) {
2276
+ setInitialScrollTarget(state, updatedInitialScroll, {
2277
+ resetDidFinish: shouldResetDidFinish
2278
+ });
2279
+ rearmBootstrapInitialScroll(ctx, {
2280
+ scroll: resolveInitialScrollOffset(ctx, updatedInitialScroll),
2281
+ seedContentOffset: shouldResetDidFinish && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2282
+ targetIndexSeed: updatedInitialScroll.index
2283
+ });
2284
+ return;
2285
+ }
2286
+ }
2287
+ if (!didDataChange) {
2288
+ return;
2289
+ }
2290
+ if (bootstrapInitialScroll || shouldResetDidFinish) {
2291
+ setInitialScrollTarget(state, initialScroll, {
2292
+ resetDidFinish: shouldResetDidFinish
2293
+ });
2294
+ rearmBootstrapInitialScroll(ctx, {
2295
+ scroll: resolveInitialScrollOffset(ctx, initialScroll),
2296
+ seedContentOffset: shouldResetDidFinish && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2297
+ targetIndexSeed: initialScroll.index
2298
+ });
2299
+ }
2300
+ }
2301
+ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2302
+ const { dataLength, footerSize, initialScrollAtEnd, stylePaddingBottom } = options;
2303
+ const state = ctx.state;
2304
+ if (!initialScrollAtEnd) {
2305
+ return;
2306
+ }
2307
+ const initialScroll = state.initialScroll;
2308
+ if (isOffsetInitialScrollSession(state) || dataLength === 0 || !initialScroll) {
2309
+ return;
2310
+ }
2311
+ const shouldProcessFooterLayout = !!getBootstrapInitialScrollSession(state) || shouldPreserveInitialScrollForFooterLayout(initialScroll);
2312
+ if (!shouldProcessFooterLayout) {
2313
+ return;
2314
+ }
2315
+ if (didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2316
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2317
+ } else {
2318
+ const updatedInitialScroll = createInitialScrollAtEndTarget({
2319
+ dataLength,
2320
+ footerSize,
2321
+ preserveForFooterLayout: shouldPreserveInitialScrollForFooterLayout(initialScroll),
2322
+ stylePaddingBottom
2323
+ });
2324
+ const didTargetChange = initialScroll.index !== updatedInitialScroll.index || initialScroll.viewPosition !== updatedInitialScroll.viewPosition || initialScroll.viewOffset !== updatedInitialScroll.viewOffset;
2325
+ if (!didTargetChange) {
2326
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2327
+ } else {
2328
+ setInitialScrollTarget(state, updatedInitialScroll, {
2329
+ resetDidFinish: !!state.didFinishInitialScroll
2330
+ });
2331
+ rearmBootstrapInitialScroll(ctx, {
2332
+ scroll: resolveInitialScrollOffset(ctx, updatedInitialScroll),
2333
+ targetIndexSeed: updatedInitialScroll.index
2334
+ });
2335
+ }
2336
+ }
2337
+ }
2338
+ function evaluateBootstrapInitialScroll(ctx) {
1476
2339
  var _a3, _b;
1477
2340
  const state = ctx.state;
1478
- const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1479
- const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1480
- const {
1481
- props: { horizontal }
1482
- } = state;
1483
- if (state.animFrameCheckFinishedScroll) {
1484
- cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
2341
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2342
+ const initialScroll = state.initialScroll;
2343
+ if (!bootstrapInitialScroll || !initialScroll || isOffsetInitialScrollSession(state) || ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll)) {
2344
+ return;
1485
2345
  }
1486
- if (state.timeoutCheckFinishedScrollFallback) {
1487
- clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
2346
+ bootstrapInitialScroll.passCount += 1;
2347
+ if (abortBootstrapRevealIfNeeded(ctx, {
2348
+ mountFrameCount: bootstrapInitialScroll.mountFrameCount,
2349
+ passCount: bootstrapInitialScroll.passCount
2350
+ })) {
2351
+ return;
1488
2352
  }
1489
- let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1490
- offset = clampScrollOffset(ctx, offset, scrollTarget);
1491
- state.scrollHistory.length = 0;
1492
- if (!noScrollingTo) {
1493
- state.scrollingTo = {
1494
- ...scrollTarget,
1495
- targetOffset: offset
1496
- };
2353
+ if (initialScroll.index !== void 0 && state.startBuffered >= 0 && state.endBuffered >= 0 && initialScroll.index >= state.startBuffered && initialScroll.index <= state.endBuffered) {
2354
+ bootstrapInitialScroll.targetIndexSeed = void 0;
1497
2355
  }
1498
- state.scrollPending = offset;
1499
- const shouldWatchInitialNativeScroll = !state.didFinishInitialScroll && (isInitialScroll || !!state.initialNativeScrollWatchdog) && offset > WATCHDOG_OFFSET_EPSILON;
1500
- const shouldClearInitialNativeScrollWatchdog = !state.didFinishInitialScroll && !!state.initialNativeScrollWatchdog && offset <= WATCHDOG_OFFSET_EPSILON;
1501
- if (shouldWatchInitialNativeScroll) {
1502
- state.hasScrolled = false;
1503
- state.initialNativeScrollWatchdog = {
1504
- startScroll: (_b = (_a3 = state.initialNativeScrollWatchdog) == null ? void 0 : _a3.startScroll) != null ? _b : state.scroll,
1505
- targetOffset: offset
1506
- };
1507
- } else if (shouldClearInitialNativeScrollWatchdog) {
1508
- state.initialNativeScrollWatchdog = void 0;
2356
+ const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
2357
+ const mountedBufferedIndices = getMountedBufferedIndices(state);
2358
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
2359
+ const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
2360
+ const { data } = state.props;
2361
+ const visibleIndices = getBootstrapRevealVisibleIndices({
2362
+ dataLength: data.length,
2363
+ getSize: (index) => {
2364
+ var _a4, _b2;
2365
+ const id = (_a4 = state.idCache[index]) != null ? _a4 : getId(state, index);
2366
+ return (_b2 = state.sizes.get(id)) != null ? _b2 : getItemSize(ctx, id, index, data[index]);
2367
+ },
2368
+ offset: resolvedOffset,
2369
+ positions: state.positions,
2370
+ scrollLength: state.scrollLength,
2371
+ startIndex: (_b = bootstrapInitialScroll.targetIndexSeed) != null ? _b : state.startBuffered >= 0 ? state.startBuffered : void 0
2372
+ });
2373
+ const areVisibleIndicesMeasured = visibleIndices.length > 0 && visibleIndices.every((index) => {
2374
+ var _a4;
2375
+ const id = (_a4 = state.idCache[index]) != null ? _a4 : getId(state, index);
2376
+ return state.sizesKnown.has(id);
2377
+ });
2378
+ const previousResolvedOffset = bootstrapInitialScroll.previousResolvedOffset;
2379
+ const previousVisibleIndices = bootstrapInitialScroll.visibleIndices;
2380
+ bootstrapInitialScroll.previousResolvedOffset = resolvedOffset;
2381
+ bootstrapInitialScroll.visibleIndices = visibleIndices;
2382
+ if (didResolvedOffsetChange) {
2383
+ bootstrapInitialScroll.scroll = resolvedOffset;
2384
+ queueBootstrapInitialScrollReevaluation(state);
2385
+ return;
1509
2386
  }
1510
- if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
1511
- doScrollTo(ctx, { animated, horizontal, offset });
2387
+ if (!areMountedBufferedIndicesMeasured || !areVisibleIndicesMeasured) {
2388
+ return;
2389
+ }
2390
+ const didRevealSettle = previousResolvedOffset !== void 0 && Math.abs(previousResolvedOffset - resolvedOffset) <= DEFAULT_BOOTSTRAP_REVEAL_EPSILON && doVisibleIndicesMatch(previousVisibleIndices, visibleIndices);
2391
+ if (!didRevealSettle) {
2392
+ queueBootstrapInitialScrollReevaluation(state);
2393
+ return;
2394
+ }
2395
+ if (Platform2.OS !== "web" && Platform2.OS !== "android" && Math.abs(bootstrapInitialScroll.seedContentOffset - resolvedOffset) <= 1) {
2396
+ finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset);
1512
2397
  } else {
1513
- state.scroll = offset;
2398
+ clearBootstrapInitialScrollSession(state);
2399
+ dispatchInitialScroll(ctx, {
2400
+ forceScroll: true,
2401
+ resolvedOffset,
2402
+ target: initialScroll,
2403
+ waitForCompletionFrame: Platform2.OS === "web"
2404
+ });
2405
+ }
2406
+ }
2407
+ function finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset) {
2408
+ const state = ctx.state;
2409
+ clearBootstrapInitialScrollSession(state);
2410
+ finishInitialScroll(ctx, {
2411
+ preserveTarget: shouldPreserveInitialScrollForFooterLayout(state.initialScroll),
2412
+ recalculateItems: true,
2413
+ resolvedOffset
2414
+ });
2415
+ }
2416
+ function abortBootstrapInitialScroll(ctx) {
2417
+ var _a3, _b, _c, _d;
2418
+ const state = ctx.state;
2419
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2420
+ const initialScroll = state.initialScroll;
2421
+ if (bootstrapInitialScroll && initialScroll && !isOffsetInitialScrollSession(state) && state.refScroller.current) {
2422
+ clearBootstrapInitialScrollSession(state);
2423
+ dispatchInitialScroll(ctx, {
2424
+ forceScroll: true,
2425
+ resolvedOffset: bootstrapInitialScroll.scroll,
2426
+ target: initialScroll,
2427
+ waitForCompletionFrame: Platform2.OS === "web"
2428
+ });
2429
+ } else {
2430
+ finishBootstrapInitialScrollWithoutScroll(
2431
+ ctx,
2432
+ (_d = (_c = (_b = (_a3 = getBootstrapInitialScrollSession(state)) == null ? void 0 : _a3.scroll) != null ? _b : state.scrollPending) != null ? _c : state.scroll) != null ? _d : 0
2433
+ );
1514
2434
  }
1515
2435
  }
1516
2436
 
1517
- // src/core/doMaintainScrollAtEnd.ts
1518
- function doMaintainScrollAtEnd(ctx) {
2437
+ // src/core/initialScrollLifecycle.ts
2438
+ function handleInitialScrollLayoutReady(ctx) {
2439
+ var _a3;
2440
+ if (!ctx.state.initialScroll) {
2441
+ return;
2442
+ }
2443
+ const runScroll = () => advanceCurrentInitialScrollSession(ctx, { forceScroll: true });
2444
+ runScroll();
2445
+ if (((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) !== "offset") {
2446
+ requestAnimationFrame(runScroll);
2447
+ }
2448
+ checkFinishedScroll(ctx, { onlyIfAligned: true });
2449
+ }
2450
+ function initializeInitialScrollOnMount(ctx, options) {
2451
+ var _a3, _b;
2452
+ const { dataLength, hasFooterComponent, initialContentOffset, initialScrollAtEnd, useBootstrapInitialScroll } = options;
1519
2453
  const state = ctx.state;
1520
- const {
1521
- didContainersLayout,
1522
- isAtEnd,
1523
- pendingNativeMVCPAdjust,
1524
- refScroller,
1525
- props: { maintainScrollAtEnd }
1526
- } = state;
1527
- const shouldMaintainScrollAtEnd = !!(isAtEnd && maintainScrollAtEnd && didContainersLayout);
1528
- if (pendingNativeMVCPAdjust) {
1529
- state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1530
- return false;
2454
+ const initialScroll = state.initialScroll;
2455
+ const resolvedInitialContentOffset = initialContentOffset != null ? initialContentOffset : 0;
2456
+ const preserveForFooterLayout = useBootstrapInitialScroll && initialScrollAtEnd && hasFooterComponent;
2457
+ if (initialScroll && (initialScroll.contentOffset === void 0 || !!initialScroll.preserveForFooterLayout !== preserveForFooterLayout && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) !== "offset")) {
2458
+ setInitialScrollTarget(state, {
2459
+ ...initialScroll,
2460
+ contentOffset: resolvedInitialContentOffset,
2461
+ preserveForFooterLayout
2462
+ });
1531
2463
  }
1532
- state.pendingMaintainScrollAtEnd = false;
1533
- if (shouldMaintainScrollAtEnd) {
1534
- const contentSize = getContentSize(ctx);
1535
- if (contentSize < state.scrollLength) {
1536
- state.scroll = 0;
2464
+ if (useBootstrapInitialScroll && initialScroll && ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) !== "offset") {
2465
+ startBootstrapInitialScrollOnMount(ctx, {
2466
+ initialScrollAtEnd,
2467
+ target: state.initialScroll
2468
+ });
2469
+ return;
2470
+ }
2471
+ const hasPendingDataDependentInitialScroll = !!initialScroll && dataLength === 0 && !(resolvedInitialContentOffset === 0 && !initialScrollAtEnd);
2472
+ if (!resolvedInitialContentOffset && !hasPendingDataDependentInitialScroll) {
2473
+ if (initialScroll && !initialScrollAtEnd) {
2474
+ finishInitialScroll(ctx, {
2475
+ resolvedOffset: resolvedInitialContentOffset
2476
+ });
2477
+ } else {
2478
+ setInitialRenderState(ctx, { didInitialScroll: true });
1537
2479
  }
1538
- requestAnimationFrame(() => {
1539
- var _a3;
1540
- if (state.isAtEnd) {
1541
- state.maintainingScrollAtEnd = true;
1542
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
1543
- animated: maintainScrollAtEnd.animated
2480
+ }
2481
+ }
2482
+ function handleInitialScrollDataChange(ctx, options) {
2483
+ var _a3, _b, _c;
2484
+ const { dataLength, didDataChange, initialScrollAtEnd, stylePaddingBottom, useBootstrapInitialScroll } = options;
2485
+ const state = ctx.state;
2486
+ const previousDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
2487
+ if (state.initialScrollSession) {
2488
+ state.initialScrollSession.previousDataLength = dataLength;
2489
+ }
2490
+ setInitialScrollSession(state);
2491
+ if (useBootstrapInitialScroll) {
2492
+ handleBootstrapInitialScrollDataChange(ctx, {
2493
+ dataLength,
2494
+ didDataChange,
2495
+ initialScrollAtEnd,
2496
+ previousDataLength,
2497
+ stylePaddingBottom
2498
+ });
2499
+ return;
2500
+ }
2501
+ const shouldReplayFinishedOffsetInitialScroll = previousDataLength === 0 && dataLength > 0 && !!state.initialScroll && ((_c = ctx.state.initialScrollSession) == null ? void 0 : _c.kind) === "offset" && !!state.didFinishInitialScroll;
2502
+ if (previousDataLength !== 0 || dataLength === 0 || !state.initialScroll || !state.queuedInitialLayout || state.didFinishInitialScroll && !shouldReplayFinishedOffsetInitialScroll) {
2503
+ return;
2504
+ }
2505
+ if (shouldReplayFinishedOffsetInitialScroll) {
2506
+ state.didFinishInitialScroll = false;
2507
+ }
2508
+ advanceCurrentInitialScrollSession(ctx);
2509
+ }
2510
+
2511
+ // src/utils/requestAdjust.ts
2512
+ function requestAdjust(ctx, positionDiff, dataChanged) {
2513
+ const state = ctx.state;
2514
+ if (Math.abs(positionDiff) > 0.1) {
2515
+ const needsScrollWorkaround = Platform2.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2516
+ const doit = () => {
2517
+ if (needsScrollWorkaround) {
2518
+ scrollTo(ctx, {
2519
+ noScrollingTo: true,
2520
+ offset: state.scroll
1544
2521
  });
1545
- setTimeout(
1546
- () => {
1547
- state.maintainingScrollAtEnd = false;
1548
- },
1549
- maintainScrollAtEnd.animated ? 500 : 0
1550
- );
2522
+ } else {
2523
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
2524
+ if (state.adjustingFromInitialMount) {
2525
+ state.adjustingFromInitialMount--;
2526
+ }
1551
2527
  }
1552
- });
1553
- return true;
2528
+ };
2529
+ state.scroll += positionDiff;
2530
+ state.scrollForNextCalculateItemsInView = void 0;
2531
+ const readyToRender = peek$(ctx, "readyToRender");
2532
+ if (readyToRender) {
2533
+ doit();
2534
+ if (Platform2.OS !== "web") {
2535
+ const threshold = state.scroll - positionDiff / 2;
2536
+ if (!state.ignoreScrollFromMVCP) {
2537
+ state.ignoreScrollFromMVCP = {};
2538
+ }
2539
+ if (positionDiff > 0) {
2540
+ state.ignoreScrollFromMVCP.lt = threshold;
2541
+ } else {
2542
+ state.ignoreScrollFromMVCP.gt = threshold;
2543
+ }
2544
+ if (state.ignoreScrollFromMVCPTimeout) {
2545
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
2546
+ }
2547
+ const delay = needsScrollWorkaround ? 250 : 100;
2548
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
2549
+ var _a3;
2550
+ state.ignoreScrollFromMVCP = void 0;
2551
+ const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
2552
+ if (shouldForceUpdate) {
2553
+ state.ignoreScrollFromMVCPIgnored = false;
2554
+ state.scrollPending = state.scroll;
2555
+ (_a3 = state.reprocessCurrentScroll) == null ? void 0 : _a3.call(state);
2556
+ }
2557
+ }, delay);
2558
+ }
2559
+ } else {
2560
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2561
+ requestAnimationFrame(doit);
2562
+ }
1554
2563
  }
1555
- return false;
1556
2564
  }
1557
2565
 
1558
2566
  // src/core/mvcp.ts
@@ -1844,184 +2852,6 @@ function prepareMVCP(ctx, dataChanged) {
1844
2852
  }
1845
2853
  }
1846
2854
 
1847
- // src/platform/flushSync.native.ts
1848
- var flushSync = (fn) => {
1849
- fn();
1850
- };
1851
-
1852
- // src/core/updateScroll.ts
1853
- function updateScroll(ctx, newScroll, forceUpdate) {
1854
- var _a3;
1855
- const state = ctx.state;
1856
- const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
1857
- const prevScroll = state.scroll;
1858
- state.hasScrolled = true;
1859
- state.lastBatchingAction = Date.now();
1860
- const currentTime = Date.now();
1861
- const adjust = scrollAdjustHandler.getAdjust();
1862
- const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1863
- if (adjustChanged) {
1864
- scrollHistory.length = 0;
1865
- }
1866
- state.lastScrollAdjustForHistory = adjust;
1867
- if (scrollingTo === void 0 && !(scrollHistory.length === 0 && newScroll === state.scroll)) {
1868
- if (!adjustChanged) {
1869
- scrollHistory.push({ scroll: newScroll, time: currentTime });
1870
- }
1871
- }
1872
- if (scrollHistory.length > 5) {
1873
- scrollHistory.shift();
1874
- }
1875
- if (ignoreScrollFromMVCP && !scrollingTo) {
1876
- const { lt, gt } = ignoreScrollFromMVCP;
1877
- if (lt && newScroll < lt || gt && newScroll > gt) {
1878
- state.ignoreScrollFromMVCPIgnored = true;
1879
- return;
1880
- }
1881
- }
1882
- state.scrollPrev = prevScroll;
1883
- state.scrollPrevTime = state.scrollTime;
1884
- state.scroll = newScroll;
1885
- state.scrollTime = currentTime;
1886
- const scrollDelta = Math.abs(newScroll - prevScroll);
1887
- const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
1888
- const scrollLength = state.scrollLength;
1889
- const lastCalculated = state.scrollLastCalculate;
1890
- const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
1891
- const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1892
- if (shouldUpdate) {
1893
- state.scrollLastCalculate = state.scroll;
1894
- state.ignoreScrollFromMVCPIgnored = false;
1895
- state.lastScrollDelta = scrollDelta;
1896
- const runCalculateItems = () => {
1897
- var _a4;
1898
- (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
1899
- checkThresholds(ctx);
1900
- };
1901
- if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1902
- flushSync(runCalculateItems);
1903
- } else {
1904
- runCalculateItems();
1905
- }
1906
- const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
1907
- if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
1908
- state.pendingMaintainScrollAtEnd = false;
1909
- doMaintainScrollAtEnd(ctx);
1910
- }
1911
- state.dataChangeNeedsScrollUpdate = false;
1912
- state.lastScrollDelta = 0;
1913
- }
1914
- }
1915
-
1916
- // src/utils/requestAdjust.ts
1917
- function requestAdjust(ctx, positionDiff, dataChanged) {
1918
- const state = ctx.state;
1919
- if (Math.abs(positionDiff) > 0.1) {
1920
- const needsScrollWorkaround = Platform2.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1921
- const doit = () => {
1922
- if (needsScrollWorkaround) {
1923
- scrollTo(ctx, {
1924
- noScrollingTo: true,
1925
- offset: state.scroll
1926
- });
1927
- } else {
1928
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1929
- if (state.adjustingFromInitialMount) {
1930
- state.adjustingFromInitialMount--;
1931
- }
1932
- }
1933
- };
1934
- state.scroll += positionDiff;
1935
- state.scrollForNextCalculateItemsInView = void 0;
1936
- const readyToRender = peek$(ctx, "readyToRender");
1937
- if (readyToRender) {
1938
- doit();
1939
- if (Platform2.OS !== "web") {
1940
- const threshold = state.scroll - positionDiff / 2;
1941
- if (!state.ignoreScrollFromMVCP) {
1942
- state.ignoreScrollFromMVCP = {};
1943
- }
1944
- if (positionDiff > 0) {
1945
- state.ignoreScrollFromMVCP.lt = threshold;
1946
- } else {
1947
- state.ignoreScrollFromMVCP.gt = threshold;
1948
- }
1949
- if (state.ignoreScrollFromMVCPTimeout) {
1950
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1951
- }
1952
- const delay = needsScrollWorkaround ? 250 : 100;
1953
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
1954
- state.ignoreScrollFromMVCP = void 0;
1955
- const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
1956
- if (shouldForceUpdate) {
1957
- state.ignoreScrollFromMVCPIgnored = false;
1958
- state.scrollPending = state.scroll;
1959
- updateScroll(ctx, state.scroll, true);
1960
- }
1961
- }, delay);
1962
- }
1963
- } else {
1964
- state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
1965
- requestAnimationFrame(doit);
1966
- }
1967
- }
1968
- }
1969
-
1970
- // src/core/ensureInitialAnchor.ts
1971
- var INITIAL_ANCHOR_TOLERANCE = 0.5;
1972
- var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1973
- var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1974
- function ensureInitialAnchor(ctx) {
1975
- var _a3, _b, _c, _d, _e, _f;
1976
- const state = ctx.state;
1977
- const { initialAnchor, didContainersLayout, scroll, scrollLength } = state;
1978
- const anchor = initialAnchor;
1979
- if (state.initialScroll || ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll)) {
1980
- return;
1981
- }
1982
- const item = state.props.data[anchor.index];
1983
- if (!didContainersLayout) {
1984
- return;
1985
- }
1986
- const id = getId(state, anchor.index);
1987
- if (state.positions[anchor.index] === void 0) {
1988
- return;
1989
- }
1990
- const size = getItemSize(ctx, id, anchor.index, item, true, true);
1991
- if (size === void 0) {
1992
- return;
1993
- }
1994
- const availableSpace = Math.max(0, scrollLength - size);
1995
- const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1996
- const desiredOffset = calculateOffsetForIndex(ctx, anchor.index) + topOffsetAdjustment - ((_b = anchor.viewOffset) != null ? _b : 0) - ((_c = anchor.viewPosition) != null ? _c : 0) * availableSpace;
1997
- const clampedDesiredOffset = clampScrollOffset(ctx, desiredOffset, anchor);
1998
- const delta = clampedDesiredOffset - scroll;
1999
- if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
2000
- const settledTicks = ((_d = anchor.settledTicks) != null ? _d : 0) + 1;
2001
- if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
2002
- state.initialAnchor = void 0;
2003
- } else {
2004
- anchor.settledTicks = settledTicks;
2005
- }
2006
- return;
2007
- }
2008
- if (((_e = anchor.attempts) != null ? _e : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
2009
- state.initialAnchor = void 0;
2010
- return;
2011
- }
2012
- const lastDelta = anchor.lastDelta;
2013
- if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
2014
- state.initialAnchor = void 0;
2015
- return;
2016
- }
2017
- Object.assign(anchor, {
2018
- attempts: ((_f = anchor.attempts) != null ? _f : 0) + 1,
2019
- lastDelta: delta,
2020
- settledTicks: 0
2021
- });
2022
- requestAdjust(ctx, delta);
2023
- }
2024
-
2025
2855
  // src/core/prepareColumnStartState.ts
2026
2856
  function prepareColumnStartState(ctx, startIndex, useAverageSize) {
2027
2857
  var _a3;
@@ -2535,23 +3365,6 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2535
3365
  var unstableBatchedUpdates = ReactNative__namespace.unstable_batchedUpdates;
2536
3366
  var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
2537
3367
 
2538
- // src/utils/checkAllSizesKnown.ts
2539
- function isNullOrUndefined2(value) {
2540
- return value === null || value === void 0;
2541
- }
2542
- function checkAllSizesKnown(state) {
2543
- const { startBuffered, endBuffered, sizesKnown } = state;
2544
- if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
2545
- let areAllKnown = true;
2546
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
2547
- const key = getId(state, i);
2548
- areAllKnown && (areAllKnown = sizesKnown.has(key));
2549
- }
2550
- return areAllKnown;
2551
- }
2552
- return false;
2553
- }
2554
-
2555
3368
  // src/utils/findAvailableContainers.ts
2556
3369
  function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2557
3370
  const numContainers = peek$(ctx, "numContainers");
@@ -2674,97 +3487,11 @@ function comparatorByDistance(a, b) {
2674
3487
  return b.distance - a.distance;
2675
3488
  }
2676
3489
 
2677
- // src/core/scrollToIndex.ts
2678
- function scrollToIndex(ctx, {
2679
- index,
2680
- viewOffset = 0,
2681
- animated = true,
2682
- forceScroll,
2683
- isInitialScroll,
2684
- viewPosition
2685
- }) {
2686
- const state = ctx.state;
2687
- const { data } = state.props;
2688
- if (index >= data.length) {
2689
- index = data.length - 1;
2690
- } else if (index < 0) {
2691
- index = 0;
2692
- }
2693
- const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2694
- const isLast = index === data.length - 1;
2695
- if (isLast && viewPosition === void 0) {
2696
- viewPosition = 1;
2697
- }
2698
- state.scrollForNextCalculateItemsInView = void 0;
2699
- const targetId = getId(state, index);
2700
- const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2701
- scrollTo(ctx, {
2702
- animated,
2703
- forceScroll,
2704
- index,
2705
- isInitialScroll,
2706
- itemSize,
2707
- offset: firstIndexOffset,
2708
- viewOffset,
2709
- viewPosition: viewPosition != null ? viewPosition : 0
2710
- });
2711
- }
2712
-
2713
- // src/utils/performInitialScroll.ts
2714
- function performInitialScroll(ctx, params) {
2715
- var _a3;
2716
- const { forceScroll, initialScrollUsesOffset, resolvedOffset, target } = params;
2717
- if (initialScrollUsesOffset || resolvedOffset !== void 0) {
2718
- scrollTo(ctx, {
2719
- animated: false,
2720
- forceScroll,
2721
- index: initialScrollUsesOffset ? void 0 : target.index,
2722
- isInitialScroll: true,
2723
- offset: (_a3 = resolvedOffset != null ? resolvedOffset : target.contentOffset) != null ? _a3 : 0,
2724
- precomputedWithViewOffset: resolvedOffset !== void 0
2725
- });
2726
- return;
2727
- }
2728
- if (target.index === void 0) {
2729
- return;
2730
- }
2731
- scrollToIndex(ctx, {
2732
- ...target,
2733
- animated: false,
2734
- forceScroll,
2735
- isInitialScroll: true
2736
- });
2737
- }
2738
-
2739
3490
  // src/utils/setDidLayout.ts
2740
3491
  function setDidLayout(ctx) {
2741
3492
  const state = ctx.state;
2742
- const { initialScroll } = state;
2743
3493
  state.queuedInitialLayout = true;
2744
- checkAtBottom(ctx);
2745
- if (initialScroll) {
2746
- const runScroll = () => {
2747
- var _a3, _b;
2748
- const target = state.initialScroll;
2749
- if (!target) {
2750
- return;
2751
- }
2752
- const activeInitialTargetOffset = ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) ? (_b = state.scrollingTo.targetOffset) != null ? _b : state.scrollingTo.offset : void 0;
2753
- const desiredInitialTargetOffset = state.initialScrollUsesOffset ? target.contentOffset : activeInitialTargetOffset;
2754
- const isAlreadyAtDesiredInitialTarget = desiredInitialTargetOffset !== void 0 && Math.abs(state.scroll - desiredInitialTargetOffset) <= 1 && Math.abs(state.scrollPending - desiredInitialTargetOffset) <= 1;
2755
- if (!isAlreadyAtDesiredInitialTarget) {
2756
- performInitialScroll(ctx, {
2757
- forceScroll: true,
2758
- initialScrollUsesOffset: state.initialScrollUsesOffset,
2759
- // Offset-based initial scrolls do not need item lookup, so they can run even before data exists.
2760
- // Re-run on the next frame to pick up measured viewport size without waiting for index resolution.
2761
- target
2762
- });
2763
- }
2764
- };
2765
- runScroll();
2766
- requestAnimationFrame(runScroll);
2767
- }
3494
+ checkAtBottom(ctx);
2768
3495
  setInitialRenderState(ctx, { didLayout: true });
2769
3496
  }
2770
3497
 
@@ -2839,7 +3566,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
2839
3566
  function calculateItemsInView(ctx, params = {}) {
2840
3567
  const state = ctx.state;
2841
3568
  batchedUpdates(() => {
2842
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
3569
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2843
3570
  const {
2844
3571
  columns,
2845
3572
  columnSpans,
@@ -2847,7 +3574,6 @@ function calculateItemsInView(ctx, params = {}) {
2847
3574
  enableScrollForNextCalculateItemsInView,
2848
3575
  idCache,
2849
3576
  indexByKey,
2850
- initialScroll,
2851
3577
  minIndexSizeChanged,
2852
3578
  positions,
2853
3579
  props: {
@@ -2871,11 +3597,10 @@ function calculateItemsInView(ctx, params = {}) {
2871
3597
  const alwaysRenderArr = alwaysRenderIndicesArr || [];
2872
3598
  const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
2873
3599
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
3600
+ const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
3601
+ const suppressInitialScrollSideEffects = !!bootstrapInitialScrollState;
2874
3602
  const prevNumContainers = peek$(ctx, "numContainers");
2875
3603
  if (!data || scrollLength === 0 || !prevNumContainers) {
2876
- if (!IsNewArchitecture && state.initialAnchor) {
2877
- ensureInitialAnchor(ctx);
2878
- }
2879
3604
  return;
2880
3605
  }
2881
3606
  let totalSize = getContentSize(ctx);
@@ -2884,16 +3609,12 @@ function calculateItemsInView(ctx, params = {}) {
2884
3609
  const speed = getScrollVelocity(state);
2885
3610
  const scrollExtra = 0;
2886
3611
  const { queuedInitialLayout } = state;
2887
- let { scroll: scrollState } = state;
2888
- if (!queuedInitialLayout && initialScroll) {
2889
- const updatedOffset = state.initialScrollUsesOffset ? (_a3 = initialScroll.contentOffset) != null ? _a3 : 0 : calculateOffsetWithOffsetPosition(
2890
- ctx,
2891
- calculateOffsetForIndex(ctx, initialScroll.index),
2892
- initialScroll
2893
- );
2894
- scrollState = updatedOffset;
2895
- }
2896
- const scrollAdjustPending = (_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0;
3612
+ const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && state.initialScroll ? (
3613
+ // Before the initial layout settles, keep viewport math anchored to the
3614
+ // current initial-scroll target instead of transient native adjustments.
3615
+ resolveInitialScrollOffset(ctx, state.initialScroll)
3616
+ ) : state.scroll;
3617
+ const scrollAdjustPending = (_c = peek$(ctx, "scrollAdjustPending")) != null ? _c : 0;
2897
3618
  const scrollAdjustPad = scrollAdjustPending - topPad;
2898
3619
  let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2899
3620
  if (scroll + scrollLength > totalSize) {
@@ -2917,20 +3638,17 @@ function calculateItemsInView(ctx, params = {}) {
2917
3638
  const scrollTopBuffered = scroll - scrollBufferTop;
2918
3639
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2919
3640
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2920
- if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
3641
+ if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2921
3642
  const { top, bottom } = scrollForNextCalculateItemsInView;
2922
3643
  if (top === null && bottom === null) {
2923
3644
  state.scrollForNextCalculateItemsInView = void 0;
2924
3645
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2925
- if (!IsNewArchitecture && state.initialAnchor) {
2926
- ensureInitialAnchor(ctx);
2927
- }
2928
3646
  if (Platform2.OS !== "web" || !isInMVCPActiveMode(state)) {
2929
3647
  return;
2930
3648
  }
2931
3649
  }
2932
3650
  }
2933
- const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
3651
+ const checkMVCP = doMVCP && !suppressInitialScrollSideEffects ? prepareMVCP(ctx, dataChanged) : void 0;
2934
3652
  if (dataChanged) {
2935
3653
  indexByKey.clear();
2936
3654
  idCache.length = 0;
@@ -2938,7 +3656,7 @@ function calculateItemsInView(ctx, params = {}) {
2938
3656
  columns.length = 0;
2939
3657
  columnSpans.length = 0;
2940
3658
  }
2941
- const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
3659
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_d = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _d : 0;
2942
3660
  updateItemPositions(ctx, dataChanged, {
2943
3661
  doMVCP,
2944
3662
  forceFullUpdate: !!forceFullItemPositions,
@@ -2955,11 +3673,11 @@ function calculateItemsInView(ctx, params = {}) {
2955
3673
  let startBufferedId = null;
2956
3674
  let endNoBuffer = null;
2957
3675
  let endBuffered = null;
2958
- let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
3676
+ let loopStart = (_e = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _e : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2959
3677
  for (let i = loopStart; i >= 0; i--) {
2960
- const id = (_d = idCache[i]) != null ? _d : getId(state, i);
3678
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2961
3679
  const top = positions[i];
2962
- const size = (_e = sizes.get(id)) != null ? _e : getItemSize(ctx, id, i, data[i]);
3680
+ const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
2963
3681
  const bottom = top + size;
2964
3682
  if (bottom > scroll - scrollBufferTop) {
2965
3683
  loopStart = i;
@@ -2990,8 +3708,8 @@ function calculateItemsInView(ctx, params = {}) {
2990
3708
  let firstFullyOnScreenIndex;
2991
3709
  const dataLength = data.length;
2992
3710
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2993
- const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2994
- const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
3711
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
3712
+ const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
2995
3713
  const top = positions[i];
2996
3714
  if (!foundEnd) {
2997
3715
  if (startNoBuffer === null && top + size > scroll) {
@@ -3030,7 +3748,7 @@ function calculateItemsInView(ctx, params = {}) {
3030
3748
  const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
3031
3749
  if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
3032
3750
  for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
3033
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
3751
+ const id = (_j = idCache[i]) != null ? _j : getId(state, i);
3034
3752
  idsInView.push(id);
3035
3753
  }
3036
3754
  }
@@ -3063,7 +3781,7 @@ function calculateItemsInView(ctx, params = {}) {
3063
3781
  const needNewContainers = [];
3064
3782
  const needNewContainersSet = /* @__PURE__ */ new Set();
3065
3783
  for (let i = startBuffered; i <= endBuffered; i++) {
3066
- const id = (_i = idCache[i]) != null ? _i : getId(state, i);
3784
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
3067
3785
  if (!containerItemKeys.has(id)) {
3068
3786
  needNewContainersSet.add(i);
3069
3787
  needNewContainers.push(i);
@@ -3072,7 +3790,7 @@ function calculateItemsInView(ctx, params = {}) {
3072
3790
  if (alwaysRenderArr.length > 0) {
3073
3791
  for (const index of alwaysRenderArr) {
3074
3792
  if (index < 0 || index >= dataLength) continue;
3075
- const id = (_j = idCache[index]) != null ? _j : getId(state, index);
3793
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
3076
3794
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
3077
3795
  needNewContainersSet.add(index);
3078
3796
  needNewContainers.push(index);
@@ -3110,7 +3828,7 @@ function calculateItemsInView(ctx, params = {}) {
3110
3828
  for (let idx = 0; idx < needNewContainers.length; idx++) {
3111
3829
  const i = needNewContainers[idx];
3112
3830
  const containerIndex = availableContainers[idx];
3113
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
3831
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
3114
3832
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
3115
3833
  if (oldKey && oldKey !== id) {
3116
3834
  containerItemKeys.delete(oldKey);
@@ -3151,7 +3869,7 @@ function calculateItemsInView(ctx, params = {}) {
3151
3869
  if (alwaysRenderArr.length > 0) {
3152
3870
  for (const index of alwaysRenderArr) {
3153
3871
  if (index < 0 || index >= dataLength) continue;
3154
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
3872
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
3155
3873
  const containerIndex = containerItemKeys.get(id);
3156
3874
  if (containerIndex !== void 0) {
3157
3875
  state.stickyContainerPool.add(containerIndex);
@@ -3222,13 +3940,23 @@ function calculateItemsInView(ctx, params = {}) {
3222
3940
  if (Platform2.OS === "web" && didChangePositions) {
3223
3941
  set$(ctx, "lastPositionUpdate", Date.now());
3224
3942
  }
3225
- if (!queuedInitialLayout && endBuffered !== null) {
3226
- if (checkAllSizesKnown(state)) {
3227
- setDidLayout(ctx);
3228
- }
3943
+ if (suppressInitialScrollSideEffects) {
3944
+ evaluateBootstrapInitialScroll(ctx);
3945
+ return;
3229
3946
  }
3230
- if (viewabilityConfigCallbackPairs) {
3231
- updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
3947
+ if (!queuedInitialLayout && endBuffered !== null && checkAllSizesKnown(state)) {
3948
+ setDidLayout(ctx);
3949
+ handleInitialScrollLayoutReady(ctx);
3950
+ }
3951
+ if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
3952
+ updateViewableItems(
3953
+ ctx.state,
3954
+ ctx,
3955
+ viewabilityConfigCallbackPairs,
3956
+ scrollLength,
3957
+ startNoBuffer,
3958
+ endNoBuffer
3959
+ );
3232
3960
  }
3233
3961
  if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
3234
3962
  const item = data[nextActiveStickyIndex];
@@ -3237,9 +3965,6 @@ function calculateItemsInView(ctx, params = {}) {
3237
3965
  }
3238
3966
  }
3239
3967
  });
3240
- if (!IsNewArchitecture && state.initialAnchor) {
3241
- ensureInitialAnchor(ctx);
3242
- }
3243
3968
  }
3244
3969
 
3245
3970
  // src/core/checkActualChange.ts
@@ -3262,6 +3987,47 @@ function checkActualChange(state, dataProp, previousData) {
3262
3987
  return false;
3263
3988
  }
3264
3989
 
3990
+ // src/core/doMaintainScrollAtEnd.ts
3991
+ function doMaintainScrollAtEnd(ctx) {
3992
+ const state = ctx.state;
3993
+ const {
3994
+ didContainersLayout,
3995
+ isAtEnd,
3996
+ pendingNativeMVCPAdjust,
3997
+ refScroller,
3998
+ props: { maintainScrollAtEnd }
3999
+ } = state;
4000
+ const shouldMaintainScrollAtEnd = !!(isAtEnd && maintainScrollAtEnd && didContainersLayout);
4001
+ if (pendingNativeMVCPAdjust) {
4002
+ state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
4003
+ return false;
4004
+ }
4005
+ state.pendingMaintainScrollAtEnd = false;
4006
+ if (shouldMaintainScrollAtEnd) {
4007
+ const contentSize = getContentSize(ctx);
4008
+ if (contentSize < state.scrollLength) {
4009
+ state.scroll = 0;
4010
+ }
4011
+ requestAnimationFrame(() => {
4012
+ var _a3;
4013
+ if (state.isAtEnd) {
4014
+ state.maintainingScrollAtEnd = true;
4015
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
4016
+ animated: maintainScrollAtEnd.animated
4017
+ });
4018
+ setTimeout(
4019
+ () => {
4020
+ state.maintainingScrollAtEnd = false;
4021
+ },
4022
+ maintainScrollAtEnd.animated ? 500 : 0
4023
+ );
4024
+ }
4025
+ });
4026
+ return true;
4027
+ }
4028
+ return false;
4029
+ }
4030
+
3265
4031
  // src/utils/updateAveragesOnDataChange.ts
3266
4032
  function updateAveragesOnDataChange(state, oldData, newData) {
3267
4033
  var _a3;
@@ -3445,20 +4211,107 @@ function handleLayout(ctx, layoutParam, setCanRender) {
3445
4211
  setCanRender(true);
3446
4212
  }
3447
4213
 
4214
+ // src/platform/flushSync.native.ts
4215
+ var flushSync = (fn) => {
4216
+ fn();
4217
+ };
4218
+
4219
+ // src/core/updateScroll.ts
4220
+ function updateScroll(ctx, newScroll, forceUpdate) {
4221
+ var _a3;
4222
+ const state = ctx.state;
4223
+ const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
4224
+ const prevScroll = state.scroll;
4225
+ state.hasScrolled = true;
4226
+ state.lastBatchingAction = Date.now();
4227
+ const currentTime = Date.now();
4228
+ const adjust = scrollAdjustHandler.getAdjust();
4229
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
4230
+ if (adjustChanged) {
4231
+ scrollHistory.length = 0;
4232
+ }
4233
+ state.lastScrollAdjustForHistory = adjust;
4234
+ if (scrollingTo === void 0 && !(scrollHistory.length === 0 && newScroll === state.scroll)) {
4235
+ if (!adjustChanged) {
4236
+ scrollHistory.push({ scroll: newScroll, time: currentTime });
4237
+ }
4238
+ }
4239
+ if (scrollHistory.length > 5) {
4240
+ scrollHistory.shift();
4241
+ }
4242
+ if (ignoreScrollFromMVCP && !scrollingTo) {
4243
+ const { lt, gt } = ignoreScrollFromMVCP;
4244
+ if (lt && newScroll < lt || gt && newScroll > gt) {
4245
+ state.ignoreScrollFromMVCPIgnored = true;
4246
+ return;
4247
+ }
4248
+ }
4249
+ state.scrollPrev = prevScroll;
4250
+ state.scrollPrevTime = state.scrollTime;
4251
+ state.scroll = newScroll;
4252
+ state.scrollTime = currentTime;
4253
+ const scrollDelta = Math.abs(newScroll - prevScroll);
4254
+ const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
4255
+ const scrollLength = state.scrollLength;
4256
+ const lastCalculated = state.scrollLastCalculate;
4257
+ const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
4258
+ const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
4259
+ if (shouldUpdate) {
4260
+ state.scrollLastCalculate = state.scroll;
4261
+ state.ignoreScrollFromMVCPIgnored = false;
4262
+ state.lastScrollDelta = scrollDelta;
4263
+ const runCalculateItems = () => {
4264
+ var _a4;
4265
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
4266
+ checkThresholds(ctx);
4267
+ };
4268
+ if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
4269
+ flushSync(runCalculateItems);
4270
+ } else {
4271
+ runCalculateItems();
4272
+ }
4273
+ const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
4274
+ if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
4275
+ state.pendingMaintainScrollAtEnd = false;
4276
+ doMaintainScrollAtEnd(ctx);
4277
+ }
4278
+ state.dataChangeNeedsScrollUpdate = false;
4279
+ state.lastScrollDelta = 0;
4280
+ }
4281
+ }
4282
+
3448
4283
  // src/core/onScroll.ts
3449
- var INITIAL_SCROLL_PROGRESS_EPSILON = 1;
3450
- function didObserveInitialScrollProgress(newScroll, watchdog) {
3451
- const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
3452
- const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
3453
- return nextDistance <= INITIAL_SCROLL_PROGRESS_EPSILON || nextDistance + INITIAL_SCROLL_PROGRESS_EPSILON < previousDistance;
4284
+ function trackInitialScrollNativeProgress(state, newScroll) {
4285
+ const initialNativeScrollWatchdog = initialScrollWatchdog.get(state);
4286
+ const didInitialScrollProgress = !!initialNativeScrollWatchdog && initialScrollWatchdog.didObserveProgress(newScroll, initialNativeScrollWatchdog);
4287
+ if (didInitialScrollProgress) {
4288
+ initialScrollWatchdog.clear(state);
4289
+ return;
4290
+ }
4291
+ if (initialNativeScrollWatchdog) {
4292
+ state.hasScrolled = false;
4293
+ initialScrollWatchdog.set(state, {
4294
+ startScroll: initialNativeScrollWatchdog.startScroll,
4295
+ targetOffset: initialNativeScrollWatchdog.targetOffset
4296
+ });
4297
+ }
4298
+ }
4299
+ function shouldDeferPublicOnScroll(state) {
4300
+ var _a3;
4301
+ return Platform2.OS === "web" && !!state.initialScroll && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" && !state.didFinishInitialScroll;
4302
+ }
4303
+ function cloneScrollEvent(event) {
4304
+ return {
4305
+ ...event,
4306
+ nativeEvent: {
4307
+ ...event.nativeEvent
4308
+ }
4309
+ };
3454
4310
  }
3455
4311
  function onScroll(ctx, event) {
3456
4312
  var _a3, _b, _c, _d;
3457
4313
  const state = ctx.state;
3458
- const {
3459
- scrollProcessingEnabled,
3460
- props: { onScroll: onScrollProp }
3461
- } = state;
4314
+ const { scrollProcessingEnabled } = state;
3462
4315
  if (scrollProcessingEnabled === false) {
3463
4316
  return;
3464
4317
  }
@@ -3489,20 +4342,18 @@ function onScroll(ctx, event) {
3489
4342
  }
3490
4343
  }
3491
4344
  state.scrollPending = newScroll;
3492
- const initialNativeScrollWatchdog = state.initialNativeScrollWatchdog;
3493
- const didInitialScrollProgress = !!initialNativeScrollWatchdog && didObserveInitialScrollProgress(newScroll, initialNativeScrollWatchdog);
3494
- if (didInitialScrollProgress) {
3495
- state.initialNativeScrollWatchdog = void 0;
3496
- }
3497
4345
  updateScroll(ctx, newScroll, insetChanged);
3498
- if (initialNativeScrollWatchdog && !didInitialScrollProgress) {
3499
- state.hasScrolled = false;
3500
- state.initialNativeScrollWatchdog = initialNativeScrollWatchdog;
3501
- }
4346
+ trackInitialScrollNativeProgress(state, newScroll);
3502
4347
  if (state.scrollingTo) {
3503
4348
  checkFinishedScroll(ctx);
3504
4349
  }
3505
- onScrollProp == null ? void 0 : onScrollProp(event);
4350
+ if (state.props.onScroll) {
4351
+ if (shouldDeferPublicOnScroll(state)) {
4352
+ state.deferredPublicOnScrollEvent = cloneScrollEvent(event);
4353
+ } else {
4354
+ state.props.onScroll(event);
4355
+ }
4356
+ }
3506
4357
  }
3507
4358
 
3508
4359
  // src/core/ScrollAdjustHandler.ts
@@ -4171,7 +5022,7 @@ var LegendList = typedMemo2(
4171
5022
  })
4172
5023
  );
4173
5024
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4174
- var _a3, _b, _c, _d, _e, _f, _g, _h;
5025
+ var _a3, _b, _c, _d, _e, _f, _g;
4175
5026
  const {
4176
5027
  alignItemsAtEnd = false,
4177
5028
  alwaysRender,
@@ -4195,6 +5046,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4195
5046
  itemsAreEqual,
4196
5047
  keyExtractor: keyExtractorProp,
4197
5048
  ListEmptyComponent,
5049
+ ListFooterComponent,
5050
+ ListFooterComponentStyle,
4198
5051
  ListHeaderComponent,
4199
5052
  maintainScrollAtEnd = false,
4200
5053
  maintainScrollAtEndThreshold = 0.1,
@@ -4231,7 +5084,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4231
5084
  useWindowScroll = false,
4232
5085
  viewabilityConfig,
4233
5086
  viewabilityConfigCallbackPairs,
4234
- waitForInitialLayout = true,
4235
5087
  ...rest
4236
5088
  } = props;
4237
5089
  const animatedPropsInternal = props.animatedPropsInternal;
@@ -4264,8 +5116,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4264
5116
  const hasInitialScrollIndex = initialScrollIndexProp !== void 0 && initialScrollIndexProp !== null;
4265
5117
  const hasInitialScrollOffset = initialScrollOffsetProp !== void 0 && initialScrollOffsetProp !== null;
4266
5118
  const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && hasInitialScrollOffset;
4267
- const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
5119
+ const usesBootstrapInitialScroll = initialScrollAtEnd || hasInitialScrollIndex;
5120
+ const initialScrollProp = initialScrollAtEnd ? {
5121
+ index: Math.max(0, dataProp.length - 1),
5122
+ preserveForBottomPadding: true,
5123
+ viewOffset: -stylePaddingBottomState,
5124
+ viewPosition: 1
5125
+ } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
4268
5126
  index: (_a3 = initialScrollIndexProp.index) != null ? _a3 : 0,
5127
+ preserveForBottomPadding: initialScrollIndexProp.viewOffset === void 0 && initialScrollIndexProp.viewPosition === 1 ? true : void 0,
4269
5128
  viewOffset: (_b = initialScrollIndexProp.viewOffset) != null ? _b : initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0,
4270
5129
  viewPosition: (_c = initialScrollIndexProp.viewPosition) != null ? _c : 0
4271
5130
  } : {
@@ -4334,22 +5193,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4334
5193
  idCache: [],
4335
5194
  idsInView: [],
4336
5195
  indexByKey: /* @__PURE__ */ new Map(),
4337
- initialAnchor: !initialScrollUsesOffsetOnly && (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
4338
- attempts: 0,
4339
- index: initialScrollProp.index,
4340
- settledTicks: 0,
4341
- viewOffset: (_f = initialScrollProp.viewOffset) != null ? _f : 0,
4342
- viewPosition: initialScrollProp.viewPosition
4343
- } : void 0,
4344
- initialNativeScrollWatchdog: void 0,
4345
5196
  initialScroll: initialScrollProp,
4346
- initialScrollLastDidFinish: false,
4347
- initialScrollLastTarget: initialScrollProp,
4348
- initialScrollLastTargetUsesOffset: initialScrollUsesOffsetOnly,
4349
- initialScrollPreviousDataLength: dataProp.length,
4350
- initialScrollRetryLastLength: void 0,
4351
- initialScrollRetryWindowUntil: 0,
4352
- initialScrollUsesOffset: initialScrollUsesOffsetOnly,
5197
+ initialScrollSession: initialScrollProp ? {
5198
+ kind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
5199
+ previousDataLength: dataProp.length
5200
+ } : void 0,
4353
5201
  isAtEnd: false,
4354
5202
  isAtStart: false,
4355
5203
  isEndReached: null,
@@ -4392,6 +5240,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4392
5240
  };
4393
5241
  const internalState = ctx.state;
4394
5242
  internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
5243
+ internalState.reprocessCurrentScroll = () => updateScroll(ctx, internalState.scroll, true);
4395
5244
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPositionConfig);
4396
5245
  set$(ctx, "extraData", extraData);
4397
5246
  }
@@ -4483,115 +5332,23 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4483
5332
  true
4484
5333
  );
4485
5334
  }
4486
- const resolveInitialScrollOffset = React2.useCallback((initialScroll) => {
4487
- var _a4;
4488
- if (state.initialScrollUsesOffset) {
4489
- return clampScrollOffset(ctx, (_a4 = initialScroll.contentOffset) != null ? _a4 : 0);
4490
- }
4491
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
4492
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
4493
- return clampScrollOffset(ctx, resolvedOffset, initialScroll);
4494
- }, []);
4495
- const finishInitialScrollWithoutScroll = React2.useCallback(() => {
4496
- refState.current.initialAnchor = void 0;
4497
- refState.current.initialScroll = void 0;
4498
- state.initialAnchor = void 0;
4499
- state.initialScroll = void 0;
4500
- state.initialScrollUsesOffset = false;
4501
- state.initialScrollLastTarget = void 0;
4502
- state.initialScrollLastTargetUsesOffset = false;
4503
- setInitialRenderState(ctx, { didInitialScroll: true });
4504
- }, []);
4505
- const setActiveInitialScrollTarget = React2.useCallback(
4506
- (target, options) => {
4507
- var _a4;
4508
- const usesOffset = !!(options == null ? void 0 : options.usesOffset);
4509
- state.initialScrollUsesOffset = usesOffset;
4510
- state.initialScrollLastTarget = target;
4511
- state.initialScrollLastTargetUsesOffset = usesOffset;
4512
- refState.current.initialScroll = target;
4513
- state.initialScroll = target;
4514
- if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
4515
- state.didFinishInitialScroll = false;
4516
- }
4517
- if (!(options == null ? void 0 : options.syncAnchor)) {
4518
- return;
4519
- }
4520
- if (!IsNewArchitecture && !usesOffset && target.index !== void 0 && target.viewPosition !== void 0) {
4521
- state.initialAnchor = {
4522
- attempts: 0,
4523
- index: target.index,
4524
- settledTicks: 0,
4525
- viewOffset: (_a4 = target.viewOffset) != null ? _a4 : 0,
4526
- viewPosition: target.viewPosition
4527
- };
4528
- }
4529
- },
4530
- []
4531
- );
4532
- const shouldFinishInitialScrollAtOrigin = React2.useCallback(
4533
- (initialScroll, offset) => {
4534
- var _a4, _b2, _c2;
4535
- if (offset !== 0 || initialScrollAtEnd) {
4536
- return false;
4537
- }
4538
- if (state.initialScrollUsesOffset) {
4539
- return Math.abs((_a4 = initialScroll.contentOffset) != null ? _a4 : 0) <= 1;
4540
- }
4541
- return initialScroll.index === 0 && ((_b2 = initialScroll.viewPosition) != null ? _b2 : 0) === 0 && Math.abs((_c2 = initialScroll.viewOffset) != null ? _c2 : 0) <= 1;
4542
- },
4543
- [initialScrollAtEnd]
4544
- );
4545
- const shouldFinishEmptyInitialScrollAtEnd = React2.useCallback(
4546
- (initialScroll, offset) => {
4547
- return dataProp.length === 0 && initialScrollAtEnd && offset === 0 && initialScroll.viewPosition === 1;
4548
- },
4549
- [dataProp.length, initialScrollAtEnd]
4550
- );
4551
- const shouldRearmFinishedEmptyInitialScrollAtEnd = React2.useCallback(
4552
- (initialScroll) => {
4553
- var _a4;
4554
- return !!(state.didFinishInitialScroll && dataProp.length > 0 && initialScroll && !state.initialScrollUsesOffset && initialScroll.index === 0 && initialScroll.viewPosition === 1 && ((_a4 = initialScroll.contentOffset) != null ? _a4 : 0) === 0);
4555
- },
4556
- [dataProp.length]
4557
- );
4558
5335
  const initialContentOffset = React2.useMemo(() => {
4559
- var _a4;
4560
- let value;
4561
- const { initialScroll, initialAnchor } = refState.current;
4562
- if (initialScroll) {
4563
- if (!state.initialScrollUsesOffset && !IsNewArchitecture && initialScroll.index !== void 0 && (!initialAnchor || (initialAnchor == null ? void 0 : initialAnchor.index) !== initialScroll.index)) {
4564
- refState.current.initialAnchor = {
4565
- attempts: 0,
4566
- index: initialScroll.index,
4567
- settledTicks: 0,
4568
- viewOffset: (_a4 = initialScroll.viewOffset) != null ? _a4 : 0,
4569
- viewPosition: initialScroll.viewPosition
4570
- };
4571
- }
4572
- if (initialScroll.contentOffset !== void 0) {
4573
- value = initialScroll.contentOffset;
4574
- } else {
4575
- const clampedOffset = resolveInitialScrollOffset(initialScroll);
4576
- const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
4577
- setActiveInitialScrollTarget(updatedInitialScroll, {
4578
- usesOffset: state.initialScrollUsesOffset
4579
- });
4580
- value = clampedOffset;
4581
- }
4582
- } else {
4583
- refState.current.initialAnchor = void 0;
4584
- value = 0;
4585
- }
4586
- const hasPendingDataDependentInitialScroll = !!initialScroll && dataProp.length === 0 && !shouldFinishInitialScrollAtOrigin(initialScroll, value) && !shouldFinishEmptyInitialScrollAtEnd(initialScroll, value);
4587
- if (!value && !hasPendingDataDependentInitialScroll) {
4588
- if (initialScroll && shouldFinishInitialScrollAtOrigin(initialScroll, value)) {
4589
- finishInitialScrollWithoutScroll();
4590
- } else {
4591
- setInitialRenderState(ctx, { didInitialScroll: true });
4592
- }
5336
+ var _a4, _b2;
5337
+ const initialScroll = state.initialScroll;
5338
+ if (!initialScroll) {
5339
+ return void 0;
4593
5340
  }
4594
- return value;
5341
+ const resolvedOffset = (_a4 = initialScroll.contentOffset) != null ? _a4 : resolveInitialScrollOffset(ctx, initialScroll);
5342
+ return usesBootstrapInitialScroll && ((_b2 = state.initialScrollSession) == null ? void 0 : _b2.kind) === "bootstrap" && Platform2.OS === "web" ? void 0 : resolvedOffset;
5343
+ }, [usesBootstrapInitialScroll]);
5344
+ React2.useLayoutEffect(() => {
5345
+ initializeInitialScrollOnMount(ctx, {
5346
+ dataLength: dataProp.length,
5347
+ hasFooterComponent: !!ListFooterComponent,
5348
+ initialContentOffset,
5349
+ initialScrollAtEnd,
5350
+ useBootstrapInitialScroll: usesBootstrapInitialScroll
5351
+ });
4595
5352
  }, []);
4596
5353
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
4597
5354
  refState.current.lastBatchingAction = Date.now();
@@ -4606,188 +5363,39 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4606
5363
  set$(ctx, "totalSize", 0);
4607
5364
  }
4608
5365
  }
4609
- const doInitialScroll = React2.useCallback((options) => {
4610
- var _a4, _b2;
4611
- const allowPostFinishRetry = !!(options == null ? void 0 : options.allowPostFinishRetry);
4612
- const { didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
4613
- const initialScroll = (_a4 = state.initialScroll) != null ? _a4 : allowPostFinishRetry ? state.initialScrollLastTarget : void 0;
4614
- const isInitialScrollInProgress = !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll);
4615
- const needsContainerLayoutForInitialScroll = !state.initialScrollUsesOffset;
4616
- const shouldWaitForInitialLayout = waitForInitialLayout && needsContainerLayoutForInitialScroll && !queuedInitialLayout && !allowPostFinishRetry && !isInitialScrollInProgress;
4617
- if (!initialScroll || shouldWaitForInitialLayout || didFinishInitialScroll && !allowPostFinishRetry || scrollingTo && !isInitialScrollInProgress) {
4618
- return;
4619
- }
4620
- if (allowPostFinishRetry && state.initialScrollLastTargetUsesOffset) {
4621
- return;
4622
- }
4623
- const didMoveAwayFromInitialTarget = allowPostFinishRetry && initialScroll.contentOffset !== void 0 && Math.abs(state.scroll - initialScroll.contentOffset) > 1;
4624
- if (didMoveAwayFromInitialTarget) {
4625
- state.initialScrollRetryWindowUntil = 0;
4626
- return;
4627
- }
4628
- const offset = resolveInitialScrollOffset(initialScroll);
4629
- const activeInitialTargetOffset = isInitialScrollInProgress ? (_b2 = scrollingTo.targetOffset) != null ? _b2 : scrollingTo.offset : void 0;
4630
- const didOffsetChange = initialScroll.contentOffset === void 0 || Math.abs(initialScroll.contentOffset - offset) > 1;
4631
- const didActiveInitialTargetChange = activeInitialTargetOffset !== void 0 && Math.abs(activeInitialTargetOffset - offset) > 1;
4632
- if (!didOffsetChange && (allowPostFinishRetry || isInitialScrollInProgress && !didActiveInitialTargetChange)) {
4633
- return;
4634
- }
4635
- if (didOffsetChange) {
4636
- const updatedInitialScroll = { ...initialScroll, contentOffset: offset };
4637
- if (!state.initialScrollUsesOffset) {
4638
- state.initialScrollLastTarget = updatedInitialScroll;
4639
- state.initialScrollLastTargetUsesOffset = false;
4640
- if (state.initialScroll) {
4641
- refState.current.initialScroll = updatedInitialScroll;
4642
- state.initialScroll = updatedInitialScroll;
4643
- }
4644
- }
4645
- }
4646
- const hasMeasuredScrollLayout = !!state.lastLayout && state.scrollLength > 0;
4647
- const shouldForceNativeInitialScroll = state.initialScrollUsesOffset && hasMeasuredScrollLayout || allowPostFinishRetry || !!queuedInitialLayout || isInitialScrollInProgress && didOffsetChange;
4648
- performInitialScroll(ctx, {
4649
- forceScroll: shouldForceNativeInitialScroll,
4650
- initialScrollUsesOffset: state.initialScrollUsesOffset,
4651
- resolvedOffset: offset,
4652
- target: initialScroll
4653
- });
4654
- }, []);
4655
- React2.useLayoutEffect(() => {
4656
- var _a4;
4657
- const previousDataLength = state.initialScrollPreviousDataLength;
4658
- state.initialScrollPreviousDataLength = dataProp.length;
4659
- if (previousDataLength !== 0 || dataProp.length === 0 || !state.initialScroll || !state.queuedInitialLayout) {
4660
- return;
4661
- }
4662
- if (initialScrollAtEnd) {
4663
- const lastIndex = Math.max(0, dataProp.length - 1);
4664
- const initialScroll = state.initialScroll;
4665
- const shouldRearm = shouldRearmFinishedEmptyInitialScrollAtEnd(initialScroll);
4666
- if (state.didFinishInitialScroll && !shouldRearm) {
4667
- return;
4668
- }
4669
- if (initialScroll && !state.initialScrollUsesOffset && initialScroll.index === lastIndex && initialScroll.viewPosition === 1 && !shouldRearm) {
4670
- return;
4671
- }
4672
- const updatedInitialScroll = {
4673
- contentOffset: void 0,
4674
- index: lastIndex,
4675
- viewOffset: (_a4 = initialScroll == null ? void 0 : initialScroll.viewOffset) != null ? _a4 : -stylePaddingBottomState,
4676
- viewPosition: 1
4677
- };
4678
- setActiveInitialScrollTarget(updatedInitialScroll, {
4679
- resetDidFinish: shouldRearm,
4680
- syncAnchor: true
4681
- });
4682
- doInitialScroll();
4683
- return;
4684
- }
4685
- if (state.didFinishInitialScroll) {
4686
- return;
4687
- }
4688
- doInitialScroll();
4689
- }, [
4690
- dataProp.length,
4691
- doInitialScroll,
4692
- initialScrollAtEnd,
4693
- shouldRearmFinishedEmptyInitialScrollAtEnd,
4694
- stylePaddingBottomState
4695
- ]);
4696
5366
  React2.useLayoutEffect(() => {
4697
- var _a4;
4698
- if (!initialScrollAtEnd) {
4699
- return;
4700
- }
4701
- const lastIndex = Math.max(0, dataProp.length - 1);
4702
- const initialScroll = state.initialScroll;
4703
- const shouldRearm = shouldRearmFinishedEmptyInitialScrollAtEnd(initialScroll);
4704
- if (state.didFinishInitialScroll && !shouldRearm) {
4705
- return;
4706
- }
4707
- if (shouldRearm) {
4708
- state.didFinishInitialScroll = false;
4709
- }
4710
- if (initialScroll && !state.initialScrollUsesOffset && initialScroll.index === lastIndex && initialScroll.viewPosition === 1 && !shouldRearm) {
4711
- return;
4712
- }
4713
- const updatedInitialScroll = {
4714
- contentOffset: void 0,
4715
- index: lastIndex,
4716
- viewOffset: (_a4 = initialScroll == null ? void 0 : initialScroll.viewOffset) != null ? _a4 : -stylePaddingBottomState,
4717
- viewPosition: 1
4718
- };
4719
- setActiveInitialScrollTarget(updatedInitialScroll, {
4720
- resetDidFinish: shouldRearm,
4721
- syncAnchor: true
5367
+ handleInitialScrollDataChange(ctx, {
5368
+ dataLength: dataProp.length,
5369
+ didDataChange: didDataChangeLocal,
5370
+ initialScrollAtEnd,
5371
+ stylePaddingBottom: stylePaddingBottomState,
5372
+ useBootstrapInitialScroll: usesBootstrapInitialScroll
4722
5373
  });
4723
- doInitialScroll();
4724
- }, [
4725
- dataProp.length,
4726
- doInitialScroll,
4727
- initialScrollAtEnd,
4728
- shouldRearmFinishedEmptyInitialScrollAtEnd,
4729
- stylePaddingBottomState
4730
- ]);
5374
+ }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
4731
5375
  const onLayoutFooter = React2.useCallback(
4732
5376
  (layout) => {
4733
- var _a4;
4734
- if (!initialScrollAtEnd) {
4735
- return;
4736
- }
4737
- const { initialScroll } = state;
4738
- if (!initialScroll) {
5377
+ if (!usesBootstrapInitialScroll) {
4739
5378
  return;
4740
5379
  }
4741
- const lastIndex = Math.max(0, dataProp.length - 1);
4742
- if (initialScroll.index !== lastIndex || initialScroll.viewPosition !== 1) {
5380
+ handleBootstrapInitialScrollFooterLayout(ctx, {
5381
+ dataLength: dataProp.length,
5382
+ footerSize: layout[horizontal ? "width" : "height"],
5383
+ initialScrollAtEnd,
5384
+ stylePaddingBottom: stylePaddingBottomState
5385
+ });
5386
+ },
5387
+ [dataProp.length, initialScrollAtEnd, horizontal, stylePaddingBottomState, usesBootstrapInitialScroll]
5388
+ );
5389
+ const onLayoutChange = React2.useCallback(
5390
+ (layout) => {
5391
+ handleLayout(ctx, layout, setCanRender);
5392
+ if (usesBootstrapInitialScroll) {
4743
5393
  return;
4744
5394
  }
4745
- const footerSize = layout[horizontal ? "width" : "height"];
4746
- const viewOffset = -stylePaddingBottomState - footerSize;
4747
- if (initialScroll.viewOffset !== viewOffset) {
4748
- const previousTargetOffset = (_a4 = initialScroll.contentOffset) != null ? _a4 : resolveInitialScrollOffset(initialScroll);
4749
- const didMoveAwayFromFinishedInitialTarget = state.didFinishInitialScroll && Math.abs(state.scroll - previousTargetOffset) > 1;
4750
- if (didMoveAwayFromFinishedInitialTarget) {
4751
- return;
4752
- }
4753
- const updatedInitialScroll = { ...initialScroll, viewOffset };
4754
- setActiveInitialScrollTarget(updatedInitialScroll, {
4755
- resetDidFinish: true
4756
- });
4757
- doInitialScroll();
4758
- }
5395
+ advanceCurrentInitialScrollSession(ctx);
4759
5396
  },
4760
- [
4761
- dataProp.length,
4762
- doInitialScroll,
4763
- horizontal,
4764
- initialScrollAtEnd,
4765
- resolveInitialScrollOffset,
4766
- stylePaddingBottomState
4767
- ]
5397
+ [usesBootstrapInitialScroll]
4768
5398
  );
4769
- const onLayoutChange = React2.useCallback((layout) => {
4770
- var _a4;
4771
- handleLayout(ctx, layout, setCanRender);
4772
- const SCROLL_LENGTH_RETRY_WINDOW_MS = 600;
4773
- const now = Date.now();
4774
- const didFinishInitialScroll = !!state.didFinishInitialScroll;
4775
- if (didFinishInitialScroll && !state.initialScrollLastDidFinish) {
4776
- state.initialScrollRetryWindowUntil = now + SCROLL_LENGTH_RETRY_WINDOW_MS;
4777
- }
4778
- state.initialScrollLastDidFinish = didFinishInitialScroll;
4779
- const previousScrollLength = state.initialScrollRetryLastLength;
4780
- const currentScrollLength = state.scrollLength;
4781
- const didScrollLengthChange = previousScrollLength === void 0 || Math.abs(currentScrollLength - previousScrollLength) > 1;
4782
- if (didScrollLengthChange) {
4783
- state.initialScrollRetryLastLength = currentScrollLength;
4784
- }
4785
- if (didFinishInitialScroll && didScrollLengthChange && now <= state.initialScrollRetryWindowUntil && !state.initialScrollLastTargetUsesOffset && ((_a4 = state.initialScrollLastTarget) == null ? void 0 : _a4.index) !== void 0) {
4786
- doInitialScroll({ allowPostFinishRetry: true });
4787
- return;
4788
- }
4789
- doInitialScroll();
4790
- }, []);
4791
5399
  const { onLayout } = useOnLayoutSync({
4792
5400
  onLayoutChange,
4793
5401
  onLayoutProp,
@@ -4866,7 +5474,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4866
5474
  }
4867
5475
  React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
4868
5476
  if (Platform2.OS === "web") {
4869
- React2.useEffect(doInitialScroll, []);
5477
+ React2.useEffect(() => {
5478
+ if (usesBootstrapInitialScroll) {
5479
+ return;
5480
+ }
5481
+ advanceCurrentInitialScrollSession(ctx);
5482
+ }, [usesBootstrapInitialScroll]);
4870
5483
  }
4871
5484
  const fns = React2.useMemo(
4872
5485
  () => ({
@@ -4896,6 +5509,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4896
5509
  horizontal,
4897
5510
  initialContentOffset,
4898
5511
  ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
5512
+ ListFooterComponent,
5513
+ ListFooterComponentStyle,
4899
5514
  ListHeaderComponent,
4900
5515
  onLayout,
4901
5516
  onLayoutFooter,
@@ -4903,7 +5518,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4903
5518
  onScroll: onScrollHandler,
4904
5519
  recycleItems,
4905
5520
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControlElement, {
4906
- progressViewOffset: ((_g = refreshControlElement.props.progressViewOffset) != null ? _g : 0) + stylePaddingTopState
5521
+ progressViewOffset: ((_f = refreshControlElement.props.progressViewOffset) != null ? _f : 0) + stylePaddingTopState
4907
5522
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
4908
5523
  ReactNative.RefreshControl,
4909
5524
  {
@@ -4914,14 +5529,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4914
5529
  ),
4915
5530
  refScrollView: combinedRef,
4916
5531
  renderScrollComponent,
4917
- scrollAdjustHandler: (_h = refState.current) == null ? void 0 : _h.scrollAdjustHandler,
5532
+ scrollAdjustHandler: (_g = refState.current) == null ? void 0 : _g.scrollAdjustHandler,
4918
5533
  scrollEventThrottle: 0,
4919
5534
  snapToIndices,
4920
5535
  stickyHeaderIndices,
4921
5536
  style,
4922
5537
  updateItemSize: fns.updateItemSize,
4923
- useWindowScroll: useWindowScrollResolved,
4924
- waitForInitialLayout
5538
+ useWindowScroll: useWindowScrollResolved
4925
5539
  }
4926
5540
  ), IS_DEV && ENABLE_DEBUG_VIEW);
4927
5541
  });