@legendapp/list 3.0.0-beta.43 → 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.mjs CHANGED
@@ -810,7 +810,6 @@ var Containers = typedMemo(function Containers2({
810
810
  horizontal,
811
811
  recycleItems,
812
812
  ItemSeparatorComponent,
813
- waitForInitialLayout,
814
813
  stickyHeaderConfig,
815
814
  updateItemSize: updateItemSize2,
816
815
  getRenderedItem: getRenderedItem2
@@ -826,7 +825,7 @@ var Containers = typedMemo(function Containers2({
826
825
  return !((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
827
826
  }
828
827
  });
829
- const animOpacity = waitForInitialLayout ? useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 }) : void 0;
828
+ const animOpacity = useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 });
830
829
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
831
830
  const containers = [];
832
831
  for (let i = 0; i < numContainers; i++) {
@@ -907,7 +906,6 @@ var ListComponent = typedMemo2(function ListComponent2({
907
906
  recycleItems,
908
907
  ItemSeparatorComponent,
909
908
  alignItemsAtEnd: _alignItemsAtEnd,
910
- waitForInitialLayout,
911
909
  onScroll: onScroll2,
912
910
  onLayout,
913
911
  ListHeaderComponent,
@@ -970,7 +968,7 @@ var ListComponent = typedMemo2(function ListComponent2({
970
968
  height: "100%"
971
969
  } : {}
972
970
  ],
973
- contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
971
+ contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
974
972
  horizontal,
975
973
  maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
976
974
  onLayout,
@@ -990,8 +988,7 @@ var ListComponent = typedMemo2(function ListComponent2({
990
988
  ItemSeparatorComponent,
991
989
  recycleItems,
992
990
  stickyHeaderConfig,
993
- updateItemSize: updateItemSize2,
994
- waitForInitialLayout
991
+ updateItemSize: updateItemSize2
995
992
  }
996
993
  ),
997
994
  ListFooterComponent && /* @__PURE__ */ React2.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
@@ -1106,6 +1103,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1106
1103
  setSize(ctx, key, size);
1107
1104
  return size;
1108
1105
  }
1106
+ function getItemSizeAtIndex(ctx, index) {
1107
+ if (index === void 0 || index < 0) {
1108
+ return void 0;
1109
+ }
1110
+ const targetId = getId(ctx.state, index);
1111
+ return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
1112
+ }
1109
1113
 
1110
1114
  // src/core/calculateOffsetWithOffsetPosition.ts
1111
1115
  function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
@@ -1156,6 +1160,458 @@ function clampScrollOffset(ctx, offset, scrollTarget) {
1156
1160
  return clampedOffset;
1157
1161
  }
1158
1162
 
1163
+ // src/core/deferredPublicOnScroll.ts
1164
+ function withResolvedContentOffset(state, event, resolvedOffset) {
1165
+ return {
1166
+ ...event,
1167
+ nativeEvent: {
1168
+ ...event.nativeEvent,
1169
+ contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1170
+ }
1171
+ };
1172
+ }
1173
+ function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
1174
+ var _a3, _b, _c, _d;
1175
+ const state = ctx.state;
1176
+ const deferredEvent = state.deferredPublicOnScrollEvent;
1177
+ state.deferredPublicOnScrollEvent = void 0;
1178
+ if (deferredEvent) {
1179
+ (_d = (_c = state.props).onScroll) == null ? void 0 : _d.call(
1180
+ _c,
1181
+ withResolvedContentOffset(
1182
+ state,
1183
+ deferredEvent,
1184
+ (_b = (_a3 = resolvedOffset != null ? resolvedOffset : state.scrollPending) != null ? _a3 : state.scroll) != null ? _b : 0
1185
+ )
1186
+ );
1187
+ }
1188
+ }
1189
+
1190
+ // src/core/initialScrollSession.ts
1191
+ var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1192
+ function hasInitialScrollSessionCompletion(completion) {
1193
+ return !!((completion == null ? void 0 : completion.didDispatchNativeScroll) || (completion == null ? void 0 : completion.didRetrySilentInitialScroll) || (completion == null ? void 0 : completion.watchdog));
1194
+ }
1195
+ function clearInitialScrollSession(state) {
1196
+ state.initialScrollSession = void 0;
1197
+ return void 0;
1198
+ }
1199
+ function createInitialScrollSession(options) {
1200
+ const { bootstrap, completion, kind, previousDataLength } = options;
1201
+ return kind === "offset" ? {
1202
+ completion,
1203
+ kind,
1204
+ previousDataLength
1205
+ } : {
1206
+ bootstrap,
1207
+ completion,
1208
+ kind,
1209
+ previousDataLength
1210
+ };
1211
+ }
1212
+ function ensureInitialScrollSessionCompletion(state, kind = ((_b) => (_b = ((_a3) => (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind)()) != null ? _b : "bootstrap")()) {
1213
+ var _a4, _b2;
1214
+ if (!state.initialScrollSession) {
1215
+ state.initialScrollSession = createInitialScrollSession({
1216
+ completion: {},
1217
+ kind,
1218
+ previousDataLength: 0
1219
+ });
1220
+ } else if (state.initialScrollSession.kind !== kind) {
1221
+ state.initialScrollSession = createInitialScrollSession({
1222
+ bootstrap: state.initialScrollSession.kind === "bootstrap" ? state.initialScrollSession.bootstrap : void 0,
1223
+ completion: state.initialScrollSession.completion,
1224
+ kind,
1225
+ previousDataLength: state.initialScrollSession.previousDataLength
1226
+ });
1227
+ }
1228
+ (_b2 = (_a4 = state.initialScrollSession).completion) != null ? _b2 : _a4.completion = {};
1229
+ return state.initialScrollSession.completion;
1230
+ }
1231
+ var initialScrollCompletion = {
1232
+ didDispatchNativeScroll(state) {
1233
+ var _a3, _b;
1234
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didDispatchNativeScroll);
1235
+ },
1236
+ didRetrySilentInitialScroll(state) {
1237
+ var _a3, _b;
1238
+ return !!((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.didRetrySilentInitialScroll);
1239
+ },
1240
+ markInitialScrollNativeDispatch(state) {
1241
+ ensureInitialScrollSessionCompletion(state).didDispatchNativeScroll = true;
1242
+ },
1243
+ markSilentInitialScrollRetry(state) {
1244
+ ensureInitialScrollSessionCompletion(state).didRetrySilentInitialScroll = true;
1245
+ },
1246
+ resetFlags(state) {
1247
+ if (!state.initialScrollSession) {
1248
+ return;
1249
+ }
1250
+ const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
1251
+ completion.didDispatchNativeScroll = void 0;
1252
+ completion.didRetrySilentInitialScroll = void 0;
1253
+ }
1254
+ };
1255
+ var initialScrollWatchdog = {
1256
+ clear(state) {
1257
+ initialScrollWatchdog.set(state, void 0);
1258
+ },
1259
+ didObserveProgress(newScroll, watchdog) {
1260
+ const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
1261
+ const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
1262
+ return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET || nextDistance + INITIAL_SCROLL_MIN_TARGET_OFFSET < previousDistance;
1263
+ },
1264
+ get(state) {
1265
+ var _a3, _b;
1266
+ return (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog;
1267
+ },
1268
+ hasNonZeroTargetOffset(targetOffset) {
1269
+ return targetOffset !== void 0 && targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1270
+ },
1271
+ isAtZeroTargetOffset(targetOffset) {
1272
+ return targetOffset <= INITIAL_SCROLL_MIN_TARGET_OFFSET;
1273
+ },
1274
+ set(state, watchdog) {
1275
+ var _a3, _b;
1276
+ if (!watchdog && !((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog)) {
1277
+ return;
1278
+ }
1279
+ const completion = ensureInitialScrollSessionCompletion(state);
1280
+ completion.watchdog = watchdog ? {
1281
+ startScroll: watchdog.startScroll,
1282
+ targetOffset: watchdog.targetOffset
1283
+ } : void 0;
1284
+ }
1285
+ };
1286
+ function setInitialScrollSession(state, options = {}) {
1287
+ var _a3, _b, _c;
1288
+ const existingSession = state.initialScrollSession;
1289
+ const kind = (_a3 = options.kind) != null ? _a3 : existingSession == null ? void 0 : existingSession.kind;
1290
+ const completion = existingSession == null ? void 0 : existingSession.completion;
1291
+ const hasBootstrapOverride = Object.hasOwn(options, "bootstrap");
1292
+ const bootstrap = kind === "bootstrap" ? hasBootstrapOverride ? options.bootstrap : (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0 : void 0;
1293
+ if (!kind) {
1294
+ return clearInitialScrollSession(state);
1295
+ }
1296
+ if (!state.initialScroll && !bootstrap && !hasInitialScrollSessionCompletion(completion)) {
1297
+ return clearInitialScrollSession(state);
1298
+ }
1299
+ const previousDataLength = (_c = (_b = options.previousDataLength) != null ? _b : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _c : 0;
1300
+ state.initialScrollSession = createInitialScrollSession({
1301
+ bootstrap,
1302
+ completion,
1303
+ kind,
1304
+ previousDataLength
1305
+ });
1306
+ return state.initialScrollSession;
1307
+ }
1308
+
1309
+ // src/core/finishScrollTo.ts
1310
+ function finishScrollTo(ctx) {
1311
+ var _a3, _b;
1312
+ const state = ctx.state;
1313
+ if (state == null ? void 0 : state.scrollingTo) {
1314
+ const resolvePendingScroll = state.pendingScrollResolve;
1315
+ state.pendingScrollResolve = void 0;
1316
+ const scrollingTo = state.scrollingTo;
1317
+ state.scrollHistory.length = 0;
1318
+ state.scrollingTo = void 0;
1319
+ if (state.pendingTotalSize !== void 0) {
1320
+ addTotalSize(ctx, null, state.pendingTotalSize);
1321
+ }
1322
+ if (PlatformAdjustBreaksScroll) {
1323
+ state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
1324
+ }
1325
+ if (scrollingTo.isInitialScroll || state.initialScroll) {
1326
+ const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1327
+ finishInitialScroll(ctx, {
1328
+ onFinished: resolvePendingScroll,
1329
+ preserveTarget: isOffsetSession && state.props.data.length === 0 || !!scrollingTo.isInitialScroll && !!((_b = state.initialScroll) == null ? void 0 : _b.preserveForFooterLayout),
1330
+ recalculateItems: true,
1331
+ syncObservedOffset: isOffsetSession,
1332
+ waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
1333
+ });
1334
+ return;
1335
+ }
1336
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1337
+ }
1338
+ }
1339
+
1340
+ // src/core/checkFinishedScroll.ts
1341
+ var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
1342
+ var INITIAL_SCROLL_COMPLETION_TARGET_EPSILON = 1;
1343
+ var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
1344
+ var SILENT_INITIAL_SCROLL_RETRY_DELAY_MS = 16;
1345
+ var SILENT_INITIAL_SCROLL_TARGET_EPSILON = 1;
1346
+ function checkFinishedScroll(ctx, options) {
1347
+ const scrollingTo = ctx.state.scrollingTo;
1348
+ if (options == null ? void 0 : options.onlyIfAligned) {
1349
+ if (!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || scrollingTo.animated) {
1350
+ return;
1351
+ }
1352
+ if (!getResolvedScrollCompletionState(ctx, scrollingTo).isAtResolvedTarget) {
1353
+ return;
1354
+ }
1355
+ }
1356
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1357
+ }
1358
+ function hasScrollCompletionOwnership(state, options) {
1359
+ const { clampedTargetOffset, scrollingTo } = options;
1360
+ return !scrollingTo.isInitialScroll || state.hasScrolled || clampedTargetOffset <= INITIAL_SCROLL_COMPLETION_TARGET_EPSILON;
1361
+ }
1362
+ function isSilentInitialDispatch(state, scrollingTo) {
1363
+ return !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled;
1364
+ }
1365
+ function getInitialScrollWatchdogTargetOffset(state) {
1366
+ var _a3;
1367
+ return (_a3 = initialScrollWatchdog.get(state)) == null ? void 0 : _a3.targetOffset;
1368
+ }
1369
+ function isNativeInitialNonZeroTarget(state) {
1370
+ const targetOffset = getInitialScrollWatchdogTargetOffset(state);
1371
+ return !state.didFinishInitialScroll && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
1372
+ }
1373
+ function shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) {
1374
+ var _a3, _b;
1375
+ if (!scrollingTo.isInitialScroll || scrollingTo.animated || !state.didContainersLayout) {
1376
+ return false;
1377
+ }
1378
+ if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap") {
1379
+ return false;
1380
+ }
1381
+ const targetOffset = (_b = scrollingTo.targetOffset) != null ? _b : scrollingTo.offset;
1382
+ if (initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset) && initialScrollCompletion.didDispatchNativeScroll(state) && !state.hasScrolled) {
1383
+ return false;
1384
+ }
1385
+ if (initialScrollWatchdog.isAtZeroTargetOffset(targetOffset) || Math.abs(state.scroll - targetOffset) > 1 || Math.abs(state.scrollPending - targetOffset) > 1) {
1386
+ return false;
1387
+ }
1388
+ return !!scrollingTo.waitForInitialScrollCompletionFrame || isNativeInitialNonZeroTarget(state);
1389
+ }
1390
+ function shouldFinishInitialZeroTargetScroll(ctx) {
1391
+ var _a3;
1392
+ const { state } = ctx;
1393
+ 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;
1394
+ }
1395
+ function getResolvedScrollCompletionState(ctx, scrollingTo) {
1396
+ var _a3;
1397
+ const { state } = ctx;
1398
+ const scroll = state.scrollPending;
1399
+ const adjust = state.scrollAdjustHandler.getAdjust();
1400
+ const clampedTargetOffset = (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
1401
+ const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
1402
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
1403
+ const diff2 = Math.abs(diff1 - adjust);
1404
+ return {
1405
+ clampedTargetOffset,
1406
+ isAtResolvedTarget: Math.abs(scroll - maxOffset) < 1 && (diff1 < 1 || !scrollingTo.animated && diff2 < 1)
1407
+ };
1408
+ }
1409
+ function checkFinishedScrollFrame(ctx) {
1410
+ const scrollingTo = ctx.state.scrollingTo;
1411
+ if (!scrollingTo) {
1412
+ return;
1413
+ }
1414
+ const { state } = ctx;
1415
+ state.animFrameCheckFinishedScroll = void 0;
1416
+ const completionState = getResolvedScrollCompletionState(ctx, scrollingTo);
1417
+ if (completionState.isAtResolvedTarget && hasScrollCompletionOwnership(state, {
1418
+ clampedTargetOffset: completionState.clampedTargetOffset,
1419
+ scrollingTo
1420
+ })) {
1421
+ finishScrollTo(ctx);
1422
+ }
1423
+ }
1424
+ function scrollToFallbackOffset(ctx, offset) {
1425
+ var _a3;
1426
+ (_a3 = ctx.state.refScroller.current) == null ? void 0 : _a3.scrollTo({
1427
+ animated: false,
1428
+ x: ctx.state.props.horizontal ? offset : 0,
1429
+ y: ctx.state.props.horizontal ? 0 : offset
1430
+ });
1431
+ }
1432
+ function checkFinishedScrollFallback(ctx) {
1433
+ const state = ctx.state;
1434
+ const scrollingTo = state.scrollingTo;
1435
+ const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1436
+ const silentInitialDispatch = isSilentInitialDispatch(state, scrollingTo);
1437
+ const canFinishInitialWithoutNativeProgress = scrollingTo !== void 0 ? shouldFinishInitialScrollWithoutNativeProgress(state, scrollingTo) : false;
1438
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget && !canFinishInitialWithoutNativeProgress || !state.didContainersLayout;
1439
+ const initialDelay = shouldFinishInitialZeroTarget || canFinishInitialWithoutNativeProgress ? 0 : silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : slowTimeout ? 500 : 100;
1440
+ state.timeoutCheckFinishedScrollFallback = setTimeout(() => {
1441
+ let numChecks = 0;
1442
+ const scheduleFallbackCheck = (delay) => {
1443
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, delay);
1444
+ };
1445
+ const checkHasScrolled = () => {
1446
+ var _a3, _b, _c;
1447
+ state.timeoutCheckFinishedScrollFallback = void 0;
1448
+ const isStillScrollingTo = state.scrollingTo;
1449
+ if (isStillScrollingTo) {
1450
+ numChecks++;
1451
+ const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
1452
+ const maxChecks = silentInitialDispatch ? 5 : isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
1453
+ const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1454
+ const canFinishInitialScrollWithoutNativeProgress = shouldFinishInitialScrollWithoutNativeProgress(
1455
+ state,
1456
+ isStillScrollingTo
1457
+ );
1458
+ const completionState = getResolvedScrollCompletionState(ctx, isStillScrollingTo);
1459
+ const canFinishAfterSilentNativeDispatch = silentInitialDispatch && completionState.isAtResolvedTarget && numChecks >= 1;
1460
+ const shouldRetrySilentInitialNativeScroll = Platform2.OS === "android" && canFinishAfterSilentNativeDispatch && !initialScrollCompletion.didRetrySilentInitialScroll(state);
1461
+ if (shouldRetrySilentInitialNativeScroll) {
1462
+ const targetOffset = (_b = (_a3 = getInitialScrollWatchdogTargetOffset(state)) != null ? _a3 : isStillScrollingTo.targetOffset) != null ? _b : 0;
1463
+ const jiggleOffset = targetOffset >= SILENT_INITIAL_SCROLL_TARGET_EPSILON ? targetOffset - SILENT_INITIAL_SCROLL_TARGET_EPSILON : targetOffset + SILENT_INITIAL_SCROLL_TARGET_EPSILON;
1464
+ initialScrollCompletion.markSilentInitialScrollRetry(state);
1465
+ scrollToFallbackOffset(ctx, jiggleOffset);
1466
+ requestAnimationFrame(() => {
1467
+ scrollToFallbackOffset(ctx, targetOffset);
1468
+ });
1469
+ scheduleFallbackCheck(SILENT_INITIAL_SCROLL_RETRY_DELAY_MS);
1470
+ } else if (shouldFinishZeroTarget || state.hasScrolled || canFinishInitialScrollWithoutNativeProgress || canFinishAfterSilentNativeDispatch || numChecks > maxChecks) {
1471
+ finishScrollTo(ctx);
1472
+ } else if (isNativeInitialPending && numChecks <= maxChecks) {
1473
+ const targetOffset = (_c = getInitialScrollWatchdogTargetOffset(state)) != null ? _c : state.scrollPending;
1474
+ scrollToFallbackOffset(ctx, targetOffset);
1475
+ scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
1476
+ } else {
1477
+ scheduleFallbackCheck(silentInitialDispatch ? SILENT_INITIAL_SCROLL_RETRY_DELAY_MS : 100);
1478
+ }
1479
+ }
1480
+ };
1481
+ checkHasScrolled();
1482
+ }, initialDelay);
1483
+ }
1484
+
1485
+ // src/core/doScrollTo.native.ts
1486
+ function doScrollTo(ctx, params) {
1487
+ const state = ctx.state;
1488
+ const { animated, horizontal, isInitialScroll, offset } = params;
1489
+ const isAnimated = !!animated;
1490
+ const { refScroller } = state;
1491
+ const scroller = refScroller.current;
1492
+ if (!scroller) {
1493
+ return;
1494
+ }
1495
+ scroller.scrollTo({
1496
+ animated: isAnimated,
1497
+ x: horizontal ? offset : 0,
1498
+ y: horizontal ? 0 : offset
1499
+ });
1500
+ if (isInitialScroll) {
1501
+ initialScrollCompletion.markInitialScrollNativeDispatch(state);
1502
+ }
1503
+ if (!isAnimated) {
1504
+ state.scroll = offset;
1505
+ checkFinishedScrollFallback(ctx);
1506
+ }
1507
+ }
1508
+
1509
+ // src/core/scrollTo.ts
1510
+ function syncInitialScrollNativeWatchdog(state, options) {
1511
+ var _a3;
1512
+ const { isInitialScroll, requestedOffset, targetOffset } = options;
1513
+ const existingWatchdog = initialScrollWatchdog.get(state);
1514
+ const shouldWatchInitialNativeScroll = !state.didFinishInitialScroll && (isInitialScroll || !!existingWatchdog) && initialScrollWatchdog.hasNonZeroTargetOffset(targetOffset);
1515
+ const shouldClearInitialNativeScrollWatchdog = !state.didFinishInitialScroll && !!existingWatchdog && initialScrollWatchdog.isAtZeroTargetOffset(requestedOffset);
1516
+ if (shouldWatchInitialNativeScroll) {
1517
+ state.hasScrolled = false;
1518
+ initialScrollWatchdog.set(state, {
1519
+ startScroll: (_a3 = existingWatchdog == null ? void 0 : existingWatchdog.startScroll) != null ? _a3 : state.scroll,
1520
+ targetOffset
1521
+ });
1522
+ return;
1523
+ }
1524
+ if (shouldClearInitialNativeScrollWatchdog) {
1525
+ initialScrollWatchdog.clear(state);
1526
+ }
1527
+ }
1528
+ function scrollTo(ctx, params) {
1529
+ var _a3;
1530
+ const state = ctx.state;
1531
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1532
+ const {
1533
+ animated,
1534
+ isInitialScroll,
1535
+ offset: scrollTargetOffset,
1536
+ precomputedWithViewOffset,
1537
+ waitForInitialScrollCompletionFrame
1538
+ } = scrollTarget;
1539
+ const {
1540
+ props: { horizontal }
1541
+ } = state;
1542
+ if (state.animFrameCheckFinishedScroll) {
1543
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1544
+ }
1545
+ if (state.timeoutCheckFinishedScrollFallback) {
1546
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1547
+ }
1548
+ const requestedOffset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1549
+ const shouldPreserveRawInitialOffsetRequest = !!isInitialScroll && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1550
+ const targetOffset = clampScrollOffset(ctx, requestedOffset, scrollTarget);
1551
+ const offset = shouldPreserveRawInitialOffsetRequest ? requestedOffset : targetOffset;
1552
+ state.scrollHistory.length = 0;
1553
+ if (!noScrollingTo) {
1554
+ if (isInitialScroll) {
1555
+ initialScrollCompletion.resetFlags(state);
1556
+ }
1557
+ state.scrollingTo = {
1558
+ ...scrollTarget,
1559
+ targetOffset,
1560
+ waitForInitialScrollCompletionFrame
1561
+ };
1562
+ }
1563
+ state.scrollPending = targetOffset;
1564
+ syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
1565
+ if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
1566
+ doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
1567
+ } else {
1568
+ state.scroll = offset;
1569
+ }
1570
+ }
1571
+
1572
+ // src/core/scrollToIndex.ts
1573
+ function clampScrollIndex(index, dataLength) {
1574
+ if (dataLength <= 0) {
1575
+ return -1;
1576
+ }
1577
+ if (index >= dataLength) {
1578
+ return dataLength - 1;
1579
+ }
1580
+ if (index < 0) {
1581
+ return 0;
1582
+ }
1583
+ return index;
1584
+ }
1585
+ function scrollToIndex(ctx, {
1586
+ index,
1587
+ viewOffset = 0,
1588
+ animated = true,
1589
+ forceScroll,
1590
+ isInitialScroll,
1591
+ viewPosition
1592
+ }) {
1593
+ const state = ctx.state;
1594
+ const { data } = state.props;
1595
+ index = clampScrollIndex(index, data.length);
1596
+ const itemSize = getItemSizeAtIndex(ctx, index);
1597
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
1598
+ const isLast = index === data.length - 1;
1599
+ if (isLast && viewPosition === void 0) {
1600
+ viewPosition = 1;
1601
+ }
1602
+ state.scrollForNextCalculateItemsInView = void 0;
1603
+ scrollTo(ctx, {
1604
+ animated,
1605
+ forceScroll,
1606
+ index,
1607
+ isInitialScroll,
1608
+ itemSize,
1609
+ offset: firstIndexOffset,
1610
+ viewOffset,
1611
+ viewPosition: viewPosition != null ? viewPosition : 0
1612
+ });
1613
+ }
1614
+
1159
1615
  // src/utils/checkThreshold.ts
1160
1616
  var HYSTERESIS_MULTIPLIER = 1.3;
1161
1617
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
@@ -1324,214 +1780,766 @@ function setInitialRenderState(ctx, {
1324
1780
  }
1325
1781
  }
1326
1782
 
1327
- // src/core/finishScrollTo.ts
1328
- function finishScrollTo(ctx) {
1329
- var _a3, _b;
1330
- const state = ctx.state;
1331
- if (state == null ? void 0 : state.scrollingTo) {
1332
- const resolvePendingScroll = state.pendingScrollResolve;
1333
- state.pendingScrollResolve = void 0;
1334
- const scrollingTo = state.scrollingTo;
1335
- state.scrollHistory.length = 0;
1336
- state.initialScroll = void 0;
1337
- state.initialScrollUsesOffset = false;
1338
- state.initialAnchor = void 0;
1339
- state.initialNativeScrollWatchdog = void 0;
1340
- state.scrollingTo = void 0;
1341
- if (state.pendingTotalSize !== void 0) {
1342
- addTotalSize(ctx, null, state.pendingTotalSize);
1343
- }
1344
- if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1345
- (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1346
- }
1347
- if (PlatformAdjustBreaksScroll) {
1348
- state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
1349
- }
1350
- setInitialRenderState(ctx, { didInitialScroll: true });
1351
- checkThresholds(ctx);
1352
- resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1353
- }
1783
+ // src/core/initialScroll.ts
1784
+ function syncInitialScrollOffset(state, offset) {
1785
+ state.scroll = offset;
1786
+ state.scrollPending = offset;
1787
+ state.scrollPrev = offset;
1354
1788
  }
1355
-
1356
- // src/core/checkFinishedScroll.ts
1357
- var INITIAL_SCROLL_MIN_TARGET_OFFSET = 1;
1358
- var INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
1359
- var INITIAL_SCROLL_ZERO_TARGET_EPSILON = 1;
1360
- function checkFinishedScroll(ctx) {
1361
- ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
1789
+ function dispatchInitialScroll(ctx, params) {
1790
+ const { forceScroll, resolvedOffset, target, waitForCompletionFrame } = params;
1791
+ const requestedIndex = target.index;
1792
+ const index = requestedIndex !== void 0 ? clampScrollIndex(requestedIndex, ctx.state.props.data.length) : void 0;
1793
+ const itemSize = getItemSizeAtIndex(ctx, index);
1794
+ scrollTo(ctx, {
1795
+ animated: false,
1796
+ forceScroll,
1797
+ index: index !== void 0 && index >= 0 ? index : void 0,
1798
+ isInitialScroll: true,
1799
+ itemSize,
1800
+ offset: resolvedOffset,
1801
+ precomputedWithViewOffset: true,
1802
+ viewOffset: target.viewOffset,
1803
+ viewPosition: target.viewPosition,
1804
+ waitForInitialScrollCompletionFrame: waitForCompletionFrame
1805
+ });
1362
1806
  }
1363
- function checkFinishedScrollFrame(ctx) {
1807
+ function setInitialScrollTarget(state, target, options) {
1364
1808
  var _a3;
1365
- const scrollingTo = ctx.state.scrollingTo;
1366
- if (scrollingTo) {
1367
- const { state } = ctx;
1368
- state.animFrameCheckFinishedScroll = void 0;
1369
- const scroll = state.scrollPending;
1370
- const adjust = state.scrollAdjustHandler.getAdjust();
1371
- const clampedTargetOffset = (_a3 = scrollingTo.targetOffset) != null ? _a3 : clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0), scrollingTo);
1372
- const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
1373
- const diff1 = Math.abs(scroll - clampedTargetOffset);
1374
- const diff2 = Math.abs(diff1 - adjust);
1375
- const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
1376
- const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
1377
- if (isNotOverscrolled && isAtTarget) {
1378
- finishScrollTo(ctx);
1379
- }
1809
+ state.initialScroll = target;
1810
+ if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
1811
+ state.didFinishInitialScroll = false;
1380
1812
  }
1813
+ setInitialScrollSession(state, {
1814
+ kind: ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? "offset" : "bootstrap"
1815
+ });
1381
1816
  }
1382
- function checkFinishedScrollFallback(ctx) {
1817
+ function finishInitialScroll(ctx, options) {
1818
+ var _a3, _b, _c;
1383
1819
  const state = ctx.state;
1384
- const scrollingTo = state.scrollingTo;
1385
- const shouldFinishInitialZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1386
- const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) && !shouldFinishInitialZeroTarget || !state.didContainersLayout;
1387
- state.timeoutCheckFinishedScrollFallback = setTimeout(
1388
- () => {
1389
- let numChecks = 0;
1390
- const checkHasScrolled = () => {
1391
- var _a3, _b;
1392
- state.timeoutCheckFinishedScrollFallback = void 0;
1393
- const isStillScrollingTo = state.scrollingTo;
1394
- if (isStillScrollingTo) {
1395
- numChecks++;
1396
- const isNativeInitialPending = isNativeInitialNonZeroTarget(state) && !state.hasScrolled;
1397
- const maxChecks = isNativeInitialPending ? INITIAL_SCROLL_MAX_FALLBACK_CHECKS : 5;
1398
- const shouldFinishZeroTarget = shouldFinishInitialZeroTargetScroll(ctx);
1399
- if (shouldFinishZeroTarget || state.hasScrolled || numChecks > maxChecks) {
1400
- finishScrollTo(ctx);
1401
- } else if (isNativeInitialPending && numChecks <= maxChecks) {
1402
- const targetOffset = (_b = (_a3 = state.initialNativeScrollWatchdog) == null ? void 0 : _a3.targetOffset) != null ? _b : state.scrollPending;
1403
- const scroller = state.refScroller.current;
1404
- if (scroller) {
1405
- scroller.scrollTo({
1406
- animated: false,
1407
- x: state.props.horizontal ? targetOffset : 0,
1408
- y: state.props.horizontal ? 0 : targetOffset
1409
- });
1410
- }
1411
- state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
1412
- } else {
1413
- state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
1414
- }
1415
- }
1416
- };
1417
- checkHasScrolled();
1418
- },
1419
- slowTimeout ? 500 : 100
1420
- );
1820
+ if ((options == null ? void 0 : options.resolvedOffset) !== void 0) {
1821
+ syncInitialScrollOffset(state, options.resolvedOffset);
1822
+ } else if ((options == null ? void 0 : options.syncObservedOffset) && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1823
+ const observedOffset = (_c = (_b = state.refScroller.current) == null ? void 0 : _b.getCurrentScrollOffset) == null ? void 0 : _c.call(_b);
1824
+ if (typeof observedOffset === "number" && Number.isFinite(observedOffset)) {
1825
+ syncInitialScrollOffset(state, observedOffset);
1826
+ }
1827
+ }
1828
+ const complete = () => {
1829
+ var _a4, _b2, _c2, _d, _e, _f, _g;
1830
+ const shouldReleaseDeferredPublicOnScroll = Platform2.OS === "web" && ((_a4 = state.initialScrollSession) == null ? void 0 : _a4.kind) === "bootstrap";
1831
+ const finalScrollOffset = (_d = (_c2 = (_b2 = options == null ? void 0 : options.resolvedOffset) != null ? _b2 : state.scrollPending) != null ? _c2 : state.scroll) != null ? _d : 0;
1832
+ initialScrollWatchdog.clear(state);
1833
+ if (!(options == null ? void 0 : options.preserveTarget)) {
1834
+ state.initialScroll = void 0;
1835
+ }
1836
+ setInitialScrollSession(state);
1837
+ if ((options == null ? void 0 : options.recalculateItems) && ((_e = state.props) == null ? void 0 : _e.data)) {
1838
+ (_f = state.triggerCalculateItemsInView) == null ? void 0 : _f.call(state, { forceFullItemPositions: true });
1839
+ }
1840
+ if (options == null ? void 0 : options.recalculateItems) {
1841
+ checkThresholds(ctx);
1842
+ }
1843
+ setInitialRenderState(ctx, { didInitialScroll: true });
1844
+ if (shouldReleaseDeferredPublicOnScroll) {
1845
+ releaseDeferredPublicOnScroll(ctx, finalScrollOffset);
1846
+ }
1847
+ (_g = options == null ? void 0 : options.onFinished) == null ? void 0 : _g.call(options);
1848
+ };
1849
+ if (options == null ? void 0 : options.waitForCompletionFrame) {
1850
+ requestAnimationFrame(complete);
1851
+ return;
1852
+ }
1853
+ complete();
1421
1854
  }
1422
- function isNativeInitialNonZeroTarget(state) {
1423
- return !state.didFinishInitialScroll && !!state.initialNativeScrollWatchdog && state.initialNativeScrollWatchdog.targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1855
+ function resolveInitialScrollOffset(ctx, initialScroll) {
1856
+ var _a3, _b;
1857
+ const state = ctx.state;
1858
+ if (((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1859
+ return (_b = initialScroll.contentOffset) != null ? _b : 0;
1860
+ }
1861
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
1862
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
1863
+ return clampScrollOffset(ctx, resolvedOffset, initialScroll);
1424
1864
  }
1425
- function shouldFinishInitialZeroTargetScroll(ctx) {
1865
+ function getAdvanceableInitialScrollState(state, options) {
1866
+ const { didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
1867
+ const initialScroll = state.initialScroll;
1868
+ const isInitialScrollInProgress = !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll);
1869
+ const shouldWaitForInitialLayout = !!(options == null ? void 0 : options.requiresMeasuredLayout) && !queuedInitialLayout && !isInitialScrollInProgress;
1870
+ if (!initialScroll || shouldWaitForInitialLayout || didFinishInitialScroll || scrollingTo && !isInitialScrollInProgress) {
1871
+ return void 0;
1872
+ }
1873
+ return {
1874
+ initialScroll,
1875
+ isInitialScrollInProgress,
1876
+ queuedInitialLayout,
1877
+ scrollingTo
1878
+ };
1879
+ }
1880
+ function advanceMeasuredInitialScroll(ctx, options) {
1881
+ var _a3, _b, _c;
1882
+ const state = ctx.state;
1883
+ const advanceableState = getAdvanceableInitialScrollState(state, {
1884
+ requiresMeasuredLayout: true
1885
+ });
1886
+ if (!advanceableState) {
1887
+ return false;
1888
+ }
1889
+ const { initialScroll, isInitialScrollInProgress, queuedInitialLayout } = advanceableState;
1890
+ const scrollingTo = isInitialScrollInProgress ? advanceableState.scrollingTo : void 0;
1891
+ const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
1892
+ const activeInitialTargetOffset = scrollingTo ? (_a3 = scrollingTo.targetOffset) != null ? _a3 : scrollingTo.offset : void 0;
1893
+ const didOffsetChange = initialScroll.contentOffset === void 0 || Math.abs(initialScroll.contentOffset - resolvedOffset) > 1;
1894
+ const didActiveInitialTargetChange = activeInitialTargetOffset !== void 0 && Math.abs(activeInitialTargetOffset - resolvedOffset) > 1;
1895
+ const isAlreadyAtDesiredInitialTarget = activeInitialTargetOffset !== void 0 && Math.abs(state.scroll - activeInitialTargetOffset) <= 1 && Math.abs(state.scrollPending - activeInitialTargetOffset) <= 1;
1896
+ if (!(options == null ? void 0 : options.forceScroll) && !didOffsetChange && isInitialScrollInProgress && !didActiveInitialTargetChange) {
1897
+ return false;
1898
+ }
1899
+ if ((options == null ? void 0 : options.forceScroll) && isAlreadyAtDesiredInitialTarget) {
1900
+ return false;
1901
+ }
1902
+ if (didOffsetChange && ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) !== "offset") {
1903
+ setInitialScrollTarget(state, { ...initialScroll, contentOffset: resolvedOffset });
1904
+ }
1905
+ const forceScroll = (_c = options == null ? void 0 : options.forceScroll) != null ? _c : !!queuedInitialLayout || isInitialScrollInProgress && didOffsetChange;
1906
+ dispatchInitialScroll(ctx, {
1907
+ forceScroll,
1908
+ resolvedOffset,
1909
+ target: initialScroll
1910
+ });
1911
+ return true;
1912
+ }
1913
+ function advanceOffsetInitialScroll(ctx, options) {
1914
+ var _a3, _b;
1915
+ const state = ctx.state;
1916
+ const advanceableState = getAdvanceableInitialScrollState(state);
1917
+ if (!advanceableState) {
1918
+ return false;
1919
+ }
1920
+ const { initialScroll, queuedInitialLayout } = advanceableState;
1921
+ const resolvedOffset = (_a3 = initialScroll.contentOffset) != null ? _a3 : 0;
1922
+ const isAlreadyAtDesiredInitialTarget = Math.abs(state.scroll - resolvedOffset) <= 1 && Math.abs(state.scrollPending - resolvedOffset) <= 1;
1923
+ if ((options == null ? void 0 : options.forceScroll) && isAlreadyAtDesiredInitialTarget) {
1924
+ return false;
1925
+ }
1926
+ const hasMeasuredScrollLayout = !!state.lastLayout && state.scrollLength > 0;
1927
+ const forceScroll = (_b = options == null ? void 0 : options.forceScroll) != null ? _b : hasMeasuredScrollLayout || !!queuedInitialLayout;
1928
+ dispatchInitialScroll(ctx, {
1929
+ forceScroll,
1930
+ resolvedOffset,
1931
+ target: initialScroll
1932
+ });
1933
+ return true;
1934
+ }
1935
+ function advanceCurrentInitialScrollSession(ctx, options) {
1426
1936
  var _a3;
1427
- const { state } = ctx;
1428
- 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;
1937
+ return ((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? advanceOffsetInitialScroll(ctx, {
1938
+ forceScroll: options == null ? void 0 : options.forceScroll
1939
+ }) : advanceMeasuredInitialScroll(ctx, {
1940
+ forceScroll: options == null ? void 0 : options.forceScroll
1941
+ });
1429
1942
  }
1430
1943
 
1431
- // src/core/doScrollTo.native.ts
1432
- function doScrollTo(ctx, params) {
1944
+ // src/utils/checkAllSizesKnown.ts
1945
+ function isNullOrUndefined2(value) {
1946
+ return value === null || value === void 0;
1947
+ }
1948
+ function getMountedBufferedIndices(state) {
1949
+ const { startBuffered, endBuffered } = state;
1950
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1951
+ 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);
1952
+ }
1953
+ return [];
1954
+ }
1955
+ function checkAllSizesKnown(state, indices = getMountedBufferedIndices(state)) {
1956
+ return indices.length > 0 && indices.every((index) => {
1957
+ const key = getId(state, index);
1958
+ return state.sizesKnown.has(key);
1959
+ });
1960
+ }
1961
+
1962
+ // src/core/bootstrapInitialScroll.ts
1963
+ var DEFAULT_BOOTSTRAP_REVEAL_EPSILON = 1;
1964
+ var DEFAULT_BOOTSTRAP_REVEAL_MAX_FRAMES = 8;
1965
+ var DEFAULT_BOOTSTRAP_REVEAL_MAX_PASSES = 24;
1966
+ var BOOTSTRAP_REVEAL_ABORT_WARNING = "LegendList bootstrap initial scroll aborted after exceeding convergence bounds.";
1967
+ function getBootstrapInitialScrollSession(state) {
1968
+ var _a3;
1969
+ return ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
1970
+ }
1971
+ function isOffsetInitialScrollSession(state) {
1972
+ var _a3;
1973
+ return ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1974
+ }
1975
+ function doVisibleIndicesMatch(previous, next) {
1976
+ if (!previous || previous.length !== next.length) {
1977
+ return false;
1978
+ }
1979
+ for (let i = 0; i < previous.length; i++) {
1980
+ if (previous[i] !== next[i]) {
1981
+ return false;
1982
+ }
1983
+ }
1984
+ return true;
1985
+ }
1986
+ function getBootstrapRevealVisibleIndices(options) {
1987
+ const { dataLength, getSize, offset, positions, scrollLength, startIndex: requestedStartIndex } = options;
1988
+ const endOffset = offset + scrollLength;
1989
+ const visibleIndices = [];
1990
+ let index = requestedStartIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, requestedStartIndex)) : 0;
1991
+ while (index > 0) {
1992
+ const previousIndex = index - 1;
1993
+ const previousPosition = positions[previousIndex];
1994
+ if (previousPosition === void 0) {
1995
+ index = previousIndex;
1996
+ continue;
1997
+ }
1998
+ const previousSize = getSize(previousIndex);
1999
+ if (previousSize === void 0) {
2000
+ index = previousIndex;
2001
+ continue;
2002
+ }
2003
+ if (previousPosition + previousSize <= offset) {
2004
+ break;
2005
+ }
2006
+ index = previousIndex;
2007
+ }
2008
+ for (; index < dataLength; index++) {
2009
+ const position = positions[index];
2010
+ if (position === void 0) {
2011
+ continue;
2012
+ }
2013
+ const size = getSize(index);
2014
+ if (size === void 0) {
2015
+ continue;
2016
+ }
2017
+ if (position < endOffset && position + size > offset) {
2018
+ visibleIndices.push(index);
2019
+ } else if (visibleIndices.length > 0 && position >= endOffset) {
2020
+ break;
2021
+ }
2022
+ }
2023
+ return visibleIndices;
2024
+ }
2025
+ function shouldAbortBootstrapReveal(options) {
2026
+ const {
2027
+ mountFrameCount,
2028
+ maxFrames = DEFAULT_BOOTSTRAP_REVEAL_MAX_FRAMES,
2029
+ maxPasses = DEFAULT_BOOTSTRAP_REVEAL_MAX_PASSES,
2030
+ passCount
2031
+ } = options;
2032
+ return mountFrameCount >= maxFrames || passCount >= maxPasses;
2033
+ }
2034
+ function abortBootstrapRevealIfNeeded(ctx, options) {
2035
+ if (!shouldAbortBootstrapReveal(options)) {
2036
+ return false;
2037
+ }
2038
+ if (IS_DEV) {
2039
+ console.warn(BOOTSTRAP_REVEAL_ABORT_WARNING);
2040
+ }
2041
+ abortBootstrapInitialScroll(ctx);
2042
+ return true;
2043
+ }
2044
+ function clearBootstrapInitialScrollSession(state) {
2045
+ var _a3;
2046
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2047
+ const frameHandle = bootstrapInitialScroll == null ? void 0 : bootstrapInitialScroll.frameHandle;
2048
+ if (frameHandle !== void 0 && typeof cancelAnimationFrame === "function") {
2049
+ cancelAnimationFrame(frameHandle);
2050
+ }
2051
+ if (bootstrapInitialScroll) {
2052
+ bootstrapInitialScroll.frameHandle = void 0;
2053
+ }
2054
+ setInitialScrollSession(state, {
2055
+ bootstrap: void 0,
2056
+ kind: (_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind
2057
+ });
2058
+ }
2059
+ function startBootstrapInitialScrollSession(state, options) {
2060
+ var _a3, _b, _c;
2061
+ const previousBootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2062
+ setInitialScrollSession(state, {
2063
+ bootstrap: {
2064
+ frameHandle: previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.frameHandle,
2065
+ // Re-arming during the initial mount should spend from the same watchdog budget.
2066
+ mountFrameCount: (_a3 = previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.mountFrameCount) != null ? _a3 : 0,
2067
+ passCount: 0,
2068
+ previousResolvedOffset: void 0,
2069
+ scroll: options.scroll,
2070
+ seedContentOffset: (_c = (_b = options.seedContentOffset) != null ? _b : previousBootstrapInitialScroll == null ? void 0 : previousBootstrapInitialScroll.seedContentOffset) != null ? _c : options.scroll,
2071
+ targetIndexSeed: options.targetIndexSeed,
2072
+ visibleIndices: void 0
2073
+ },
2074
+ kind: "bootstrap"
2075
+ });
2076
+ }
2077
+ function resetBootstrapInitialScrollSession(state, options) {
2078
+ var _a3, _b, _c;
2079
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2080
+ if (!bootstrapInitialScroll) {
2081
+ if ((options == null ? void 0 : options.scroll) !== void 0) {
2082
+ startBootstrapInitialScrollSession(state, {
2083
+ scroll: options.scroll,
2084
+ seedContentOffset: options.seedContentOffset,
2085
+ targetIndexSeed: options.targetIndexSeed
2086
+ });
2087
+ }
2088
+ } else {
2089
+ bootstrapInitialScroll.passCount = 0;
2090
+ bootstrapInitialScroll.previousResolvedOffset = void 0;
2091
+ bootstrapInitialScroll.scroll = (_a3 = options == null ? void 0 : options.scroll) != null ? _a3 : bootstrapInitialScroll.scroll;
2092
+ bootstrapInitialScroll.seedContentOffset = (_b = options == null ? void 0 : options.seedContentOffset) != null ? _b : bootstrapInitialScroll.seedContentOffset;
2093
+ bootstrapInitialScroll.targetIndexSeed = (_c = options == null ? void 0 : options.targetIndexSeed) != null ? _c : bootstrapInitialScroll.targetIndexSeed;
2094
+ bootstrapInitialScroll.visibleIndices = void 0;
2095
+ setInitialScrollSession(state, {
2096
+ bootstrap: bootstrapInitialScroll,
2097
+ kind: "bootstrap"
2098
+ });
2099
+ }
2100
+ }
2101
+ function queueBootstrapInitialScrollReevaluation(state) {
2102
+ requestAnimationFrame(() => {
2103
+ var _a3;
2104
+ if (getBootstrapInitialScrollSession(state)) {
2105
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { forceFullItemPositions: true });
2106
+ }
2107
+ });
2108
+ }
2109
+ function ensureBootstrapInitialScrollFrameTicker(ctx) {
1433
2110
  const state = ctx.state;
1434
- const { animated, horizontal, offset } = params;
1435
- const isAnimated = !!animated;
1436
- const { refScroller } = state;
1437
- const scroller = refScroller.current;
1438
- if (!scroller) {
2111
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2112
+ if (!bootstrapInitialScroll || bootstrapInitialScroll.frameHandle !== void 0) {
1439
2113
  return;
1440
2114
  }
1441
- scroller.scrollTo({
1442
- animated: isAnimated,
1443
- x: horizontal ? offset : 0,
1444
- y: horizontal ? 0 : offset
1445
- });
1446
- if (!isAnimated) {
1447
- state.scroll = offset;
1448
- checkFinishedScrollFallback(ctx);
2115
+ const tick = () => {
2116
+ const activeBootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2117
+ if (!activeBootstrapInitialScroll) {
2118
+ return;
2119
+ }
2120
+ activeBootstrapInitialScroll.frameHandle = void 0;
2121
+ activeBootstrapInitialScroll.mountFrameCount += 1;
2122
+ if (abortBootstrapRevealIfNeeded(ctx, {
2123
+ mountFrameCount: activeBootstrapInitialScroll.mountFrameCount,
2124
+ passCount: activeBootstrapInitialScroll.passCount
2125
+ })) {
2126
+ return;
2127
+ }
2128
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2129
+ };
2130
+ bootstrapInitialScroll.frameHandle = requestAnimationFrame(tick);
2131
+ }
2132
+ function rearmBootstrapInitialScroll(ctx, options) {
2133
+ resetBootstrapInitialScrollSession(ctx.state, options);
2134
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2135
+ queueBootstrapInitialScrollReevaluation(ctx.state);
2136
+ }
2137
+ function createInitialScrollAtEndTarget(options) {
2138
+ const { dataLength, footerSize, preserveForFooterLayout, stylePaddingBottom } = options;
2139
+ return {
2140
+ contentOffset: void 0,
2141
+ index: Math.max(0, dataLength - 1),
2142
+ preserveForBottomPadding: true,
2143
+ preserveForFooterLayout,
2144
+ viewOffset: -stylePaddingBottom - footerSize,
2145
+ viewPosition: 1
2146
+ };
2147
+ }
2148
+ function shouldPreserveInitialScrollForBottomPadding(target) {
2149
+ return !!(target == null ? void 0 : target.preserveForBottomPadding);
2150
+ }
2151
+ function shouldPreserveInitialScrollForFooterLayout(target) {
2152
+ return !!(target == null ? void 0 : target.preserveForFooterLayout);
2153
+ }
2154
+ function isRetargetableBottomAlignedInitialScrollTarget(target) {
2155
+ return !!(target && target.viewPosition === 1 && (shouldPreserveInitialScrollForBottomPadding(target) || shouldPreserveInitialScrollForFooterLayout(target)));
2156
+ }
2157
+ function createRetargetedBottomAlignedInitialScroll(options) {
2158
+ const { dataLength, footerSize, initialScrollAtEnd, stylePaddingBottom, target } = options;
2159
+ const preserveForFooterLayout = shouldPreserveInitialScrollForFooterLayout(target);
2160
+ return {
2161
+ ...target,
2162
+ contentOffset: void 0,
2163
+ index: initialScrollAtEnd ? Math.max(0, dataLength - 1) : target.index,
2164
+ preserveForBottomPadding: true,
2165
+ preserveForFooterLayout,
2166
+ viewOffset: -stylePaddingBottom - (preserveForFooterLayout ? footerSize : 0),
2167
+ viewPosition: 1
2168
+ };
2169
+ }
2170
+ function areEquivalentBootstrapInitialScrollTargets(current, next) {
2171
+ return current.index === next.index && current.preserveForBottomPadding === next.preserveForBottomPadding && current.preserveForFooterLayout === next.preserveForFooterLayout && current.viewOffset === next.viewOffset && current.viewPosition === next.viewPosition;
2172
+ }
2173
+ function clearPendingInitialScrollFooterLayout(state, target) {
2174
+ if (!shouldPreserveInitialScrollForFooterLayout(target)) {
2175
+ return;
1449
2176
  }
2177
+ if (state.didFinishInitialScroll && !getBootstrapInitialScrollSession(state)) {
2178
+ state.initialScroll = void 0;
2179
+ setInitialScrollSession(state);
2180
+ return;
2181
+ }
2182
+ setInitialScrollTarget(state, { ...target, preserveForFooterLayout: void 0 });
1450
2183
  }
1451
-
1452
- // src/core/scrollTo.ts
1453
- var WATCHDOG_OFFSET_EPSILON = 1;
1454
- function scrollTo(ctx, params) {
2184
+ function didFinishedInitialScrollMoveAwayFromTarget(ctx, target, epsilon = DEFAULT_BOOTSTRAP_REVEAL_EPSILON) {
2185
+ const state = ctx.state;
2186
+ if (!state.didFinishInitialScroll) {
2187
+ return false;
2188
+ }
2189
+ const currentOffset = getObservedBootstrapInitialScrollOffset(state);
2190
+ return Math.abs(currentOffset - resolveInitialScrollOffset(ctx, target)) > epsilon;
2191
+ }
2192
+ function getObservedBootstrapInitialScrollOffset(state) {
2193
+ var _a3, _b, _c, _d;
2194
+ const observedOffset = (_b = (_a3 = state.refScroller.current) == null ? void 0 : _a3.getCurrentScrollOffset) == null ? void 0 : _b.call(_a3);
2195
+ return typeof observedOffset === "number" && Number.isFinite(observedOffset) ? observedOffset : (_d = (_c = state.scrollPending) != null ? _c : state.scroll) != null ? _d : 0;
2196
+ }
2197
+ function startBootstrapInitialScrollOnMount(ctx, options) {
2198
+ var _a3, _b, _c;
2199
+ const { initialScrollAtEnd, target } = options;
2200
+ const state = ctx.state;
2201
+ const offset = resolveInitialScrollOffset(ctx, target);
2202
+ 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);
2203
+ const shouldFinishWithPreservedTarget = state.props.data.length === 0 && target.index !== void 0;
2204
+ if (shouldFinishAtOrigin) {
2205
+ clearBootstrapInitialScrollSession(state);
2206
+ finishInitialScroll(ctx, {
2207
+ resolvedOffset: offset
2208
+ });
2209
+ } else if (shouldFinishWithPreservedTarget) {
2210
+ clearBootstrapInitialScrollSession(state);
2211
+ finishInitialScroll(ctx, {
2212
+ preserveTarget: true,
2213
+ resolvedOffset: offset
2214
+ });
2215
+ } else {
2216
+ startBootstrapInitialScrollSession(state, {
2217
+ scroll: offset,
2218
+ seedContentOffset: Platform2.OS === "web" ? 0 : offset,
2219
+ targetIndexSeed: target.index
2220
+ });
2221
+ ensureBootstrapInitialScrollFrameTicker(ctx);
2222
+ }
2223
+ }
2224
+ function handleBootstrapInitialScrollDataChange(ctx, options) {
2225
+ const { dataLength, didDataChange, initialScrollAtEnd, previousDataLength, stylePaddingBottom } = options;
2226
+ const state = ctx.state;
2227
+ const initialScroll = state.initialScroll;
2228
+ if (isOffsetInitialScrollSession(state) || !initialScroll) {
2229
+ return;
2230
+ }
2231
+ const shouldResetDidFinish = !!(state.didFinishInitialScroll && previousDataLength === 0 && dataLength > 0 && initialScroll.index !== void 0);
2232
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2233
+ const shouldRetargetBottomAligned = dataLength > 0 && (initialScrollAtEnd || isRetargetableBottomAlignedInitialScrollTarget(initialScroll));
2234
+ if (!didDataChange && !shouldResetDidFinish && !shouldRetargetBottomAligned) {
2235
+ return;
2236
+ }
2237
+ if (shouldRetargetBottomAligned) {
2238
+ if (!shouldResetDidFinish && didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2239
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2240
+ return;
2241
+ }
2242
+ const updatedInitialScroll = initialScrollAtEnd ? createInitialScrollAtEndTarget({
2243
+ dataLength,
2244
+ footerSize: peek$(ctx, "footerSize") || 0,
2245
+ preserveForFooterLayout: shouldPreserveInitialScrollForFooterLayout(initialScroll),
2246
+ stylePaddingBottom
2247
+ }) : createRetargetedBottomAlignedInitialScroll({
2248
+ dataLength,
2249
+ footerSize: peek$(ctx, "footerSize") || 0,
2250
+ initialScrollAtEnd,
2251
+ stylePaddingBottom,
2252
+ target: initialScroll
2253
+ });
2254
+ if (!areEquivalentBootstrapInitialScrollTargets(initialScroll, updatedInitialScroll) || !!bootstrapInitialScroll || shouldResetDidFinish || didDataChange) {
2255
+ setInitialScrollTarget(state, updatedInitialScroll, {
2256
+ resetDidFinish: shouldResetDidFinish
2257
+ });
2258
+ rearmBootstrapInitialScroll(ctx, {
2259
+ scroll: resolveInitialScrollOffset(ctx, updatedInitialScroll),
2260
+ seedContentOffset: shouldResetDidFinish && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2261
+ targetIndexSeed: updatedInitialScroll.index
2262
+ });
2263
+ return;
2264
+ }
2265
+ }
2266
+ if (!didDataChange) {
2267
+ return;
2268
+ }
2269
+ if (bootstrapInitialScroll || shouldResetDidFinish) {
2270
+ setInitialScrollTarget(state, initialScroll, {
2271
+ resetDidFinish: shouldResetDidFinish
2272
+ });
2273
+ rearmBootstrapInitialScroll(ctx, {
2274
+ scroll: resolveInitialScrollOffset(ctx, initialScroll),
2275
+ seedContentOffset: shouldResetDidFinish && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2276
+ targetIndexSeed: initialScroll.index
2277
+ });
2278
+ }
2279
+ }
2280
+ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2281
+ const { dataLength, footerSize, initialScrollAtEnd, stylePaddingBottom } = options;
2282
+ const state = ctx.state;
2283
+ if (!initialScrollAtEnd) {
2284
+ return;
2285
+ }
2286
+ const initialScroll = state.initialScroll;
2287
+ if (isOffsetInitialScrollSession(state) || dataLength === 0 || !initialScroll) {
2288
+ return;
2289
+ }
2290
+ const shouldProcessFooterLayout = !!getBootstrapInitialScrollSession(state) || shouldPreserveInitialScrollForFooterLayout(initialScroll);
2291
+ if (!shouldProcessFooterLayout) {
2292
+ return;
2293
+ }
2294
+ if (didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2295
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2296
+ } else {
2297
+ const updatedInitialScroll = createInitialScrollAtEndTarget({
2298
+ dataLength,
2299
+ footerSize,
2300
+ preserveForFooterLayout: shouldPreserveInitialScrollForFooterLayout(initialScroll),
2301
+ stylePaddingBottom
2302
+ });
2303
+ const didTargetChange = initialScroll.index !== updatedInitialScroll.index || initialScroll.viewPosition !== updatedInitialScroll.viewPosition || initialScroll.viewOffset !== updatedInitialScroll.viewOffset;
2304
+ if (!didTargetChange) {
2305
+ clearPendingInitialScrollFooterLayout(state, initialScroll);
2306
+ } else {
2307
+ setInitialScrollTarget(state, updatedInitialScroll, {
2308
+ resetDidFinish: !!state.didFinishInitialScroll
2309
+ });
2310
+ rearmBootstrapInitialScroll(ctx, {
2311
+ scroll: resolveInitialScrollOffset(ctx, updatedInitialScroll),
2312
+ targetIndexSeed: updatedInitialScroll.index
2313
+ });
2314
+ }
2315
+ }
2316
+ }
2317
+ function evaluateBootstrapInitialScroll(ctx) {
1455
2318
  var _a3, _b;
1456
2319
  const state = ctx.state;
1457
- const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1458
- const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1459
- const {
1460
- props: { horizontal }
1461
- } = state;
1462
- if (state.animFrameCheckFinishedScroll) {
1463
- cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
2320
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2321
+ const initialScroll = state.initialScroll;
2322
+ if (!bootstrapInitialScroll || !initialScroll || isOffsetInitialScrollSession(state) || ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll)) {
2323
+ return;
1464
2324
  }
1465
- if (state.timeoutCheckFinishedScrollFallback) {
1466
- clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
2325
+ bootstrapInitialScroll.passCount += 1;
2326
+ if (abortBootstrapRevealIfNeeded(ctx, {
2327
+ mountFrameCount: bootstrapInitialScroll.mountFrameCount,
2328
+ passCount: bootstrapInitialScroll.passCount
2329
+ })) {
2330
+ return;
1467
2331
  }
1468
- let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1469
- offset = clampScrollOffset(ctx, offset, scrollTarget);
1470
- state.scrollHistory.length = 0;
1471
- if (!noScrollingTo) {
1472
- state.scrollingTo = {
1473
- ...scrollTarget,
1474
- targetOffset: offset
1475
- };
2332
+ if (initialScroll.index !== void 0 && state.startBuffered >= 0 && state.endBuffered >= 0 && initialScroll.index >= state.startBuffered && initialScroll.index <= state.endBuffered) {
2333
+ bootstrapInitialScroll.targetIndexSeed = void 0;
1476
2334
  }
1477
- state.scrollPending = offset;
1478
- const shouldWatchInitialNativeScroll = !state.didFinishInitialScroll && (isInitialScroll || !!state.initialNativeScrollWatchdog) && offset > WATCHDOG_OFFSET_EPSILON;
1479
- const shouldClearInitialNativeScrollWatchdog = !state.didFinishInitialScroll && !!state.initialNativeScrollWatchdog && offset <= WATCHDOG_OFFSET_EPSILON;
1480
- if (shouldWatchInitialNativeScroll) {
1481
- state.hasScrolled = false;
1482
- state.initialNativeScrollWatchdog = {
1483
- startScroll: (_b = (_a3 = state.initialNativeScrollWatchdog) == null ? void 0 : _a3.startScroll) != null ? _b : state.scroll,
1484
- targetOffset: offset
1485
- };
1486
- } else if (shouldClearInitialNativeScrollWatchdog) {
1487
- state.initialNativeScrollWatchdog = void 0;
2335
+ const resolvedOffset = resolveInitialScrollOffset(ctx, initialScroll);
2336
+ const mountedBufferedIndices = getMountedBufferedIndices(state);
2337
+ const areMountedBufferedIndicesMeasured = checkAllSizesKnown(state, mountedBufferedIndices);
2338
+ const didResolvedOffsetChange = Math.abs(bootstrapInitialScroll.scroll - resolvedOffset) > 1;
2339
+ const { data } = state.props;
2340
+ const visibleIndices = getBootstrapRevealVisibleIndices({
2341
+ dataLength: data.length,
2342
+ getSize: (index) => {
2343
+ var _a4, _b2;
2344
+ const id = (_a4 = state.idCache[index]) != null ? _a4 : getId(state, index);
2345
+ return (_b2 = state.sizes.get(id)) != null ? _b2 : getItemSize(ctx, id, index, data[index]);
2346
+ },
2347
+ offset: resolvedOffset,
2348
+ positions: state.positions,
2349
+ scrollLength: state.scrollLength,
2350
+ startIndex: (_b = bootstrapInitialScroll.targetIndexSeed) != null ? _b : state.startBuffered >= 0 ? state.startBuffered : void 0
2351
+ });
2352
+ const areVisibleIndicesMeasured = visibleIndices.length > 0 && visibleIndices.every((index) => {
2353
+ var _a4;
2354
+ const id = (_a4 = state.idCache[index]) != null ? _a4 : getId(state, index);
2355
+ return state.sizesKnown.has(id);
2356
+ });
2357
+ const previousResolvedOffset = bootstrapInitialScroll.previousResolvedOffset;
2358
+ const previousVisibleIndices = bootstrapInitialScroll.visibleIndices;
2359
+ bootstrapInitialScroll.previousResolvedOffset = resolvedOffset;
2360
+ bootstrapInitialScroll.visibleIndices = visibleIndices;
2361
+ if (didResolvedOffsetChange) {
2362
+ bootstrapInitialScroll.scroll = resolvedOffset;
2363
+ queueBootstrapInitialScrollReevaluation(state);
2364
+ return;
1488
2365
  }
1489
- if (forceScroll || !isInitialScroll || Platform2.OS === "android") {
1490
- doScrollTo(ctx, { animated, horizontal, offset });
2366
+ if (!areMountedBufferedIndicesMeasured || !areVisibleIndicesMeasured) {
2367
+ return;
2368
+ }
2369
+ const didRevealSettle = previousResolvedOffset !== void 0 && Math.abs(previousResolvedOffset - resolvedOffset) <= DEFAULT_BOOTSTRAP_REVEAL_EPSILON && doVisibleIndicesMatch(previousVisibleIndices, visibleIndices);
2370
+ if (!didRevealSettle) {
2371
+ queueBootstrapInitialScrollReevaluation(state);
2372
+ return;
2373
+ }
2374
+ if (Platform2.OS !== "web" && Platform2.OS !== "android" && Math.abs(bootstrapInitialScroll.seedContentOffset - resolvedOffset) <= 1) {
2375
+ finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset);
1491
2376
  } else {
1492
- state.scroll = offset;
2377
+ clearBootstrapInitialScrollSession(state);
2378
+ dispatchInitialScroll(ctx, {
2379
+ forceScroll: true,
2380
+ resolvedOffset,
2381
+ target: initialScroll,
2382
+ waitForCompletionFrame: Platform2.OS === "web"
2383
+ });
2384
+ }
2385
+ }
2386
+ function finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset) {
2387
+ const state = ctx.state;
2388
+ clearBootstrapInitialScrollSession(state);
2389
+ finishInitialScroll(ctx, {
2390
+ preserveTarget: shouldPreserveInitialScrollForFooterLayout(state.initialScroll),
2391
+ recalculateItems: true,
2392
+ resolvedOffset
2393
+ });
2394
+ }
2395
+ function abortBootstrapInitialScroll(ctx) {
2396
+ var _a3, _b, _c, _d;
2397
+ const state = ctx.state;
2398
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2399
+ const initialScroll = state.initialScroll;
2400
+ if (bootstrapInitialScroll && initialScroll && !isOffsetInitialScrollSession(state) && state.refScroller.current) {
2401
+ clearBootstrapInitialScrollSession(state);
2402
+ dispatchInitialScroll(ctx, {
2403
+ forceScroll: true,
2404
+ resolvedOffset: bootstrapInitialScroll.scroll,
2405
+ target: initialScroll,
2406
+ waitForCompletionFrame: Platform2.OS === "web"
2407
+ });
2408
+ } else {
2409
+ finishBootstrapInitialScrollWithoutScroll(
2410
+ ctx,
2411
+ (_d = (_c = (_b = (_a3 = getBootstrapInitialScrollSession(state)) == null ? void 0 : _a3.scroll) != null ? _b : state.scrollPending) != null ? _c : state.scroll) != null ? _d : 0
2412
+ );
1493
2413
  }
1494
2414
  }
1495
2415
 
1496
- // src/core/doMaintainScrollAtEnd.ts
1497
- function doMaintainScrollAtEnd(ctx) {
2416
+ // src/core/initialScrollLifecycle.ts
2417
+ function handleInitialScrollLayoutReady(ctx) {
2418
+ var _a3;
2419
+ if (!ctx.state.initialScroll) {
2420
+ return;
2421
+ }
2422
+ const runScroll = () => advanceCurrentInitialScrollSession(ctx, { forceScroll: true });
2423
+ runScroll();
2424
+ if (((_a3 = ctx.state.initialScrollSession) == null ? void 0 : _a3.kind) !== "offset") {
2425
+ requestAnimationFrame(runScroll);
2426
+ }
2427
+ checkFinishedScroll(ctx, { onlyIfAligned: true });
2428
+ }
2429
+ function initializeInitialScrollOnMount(ctx, options) {
2430
+ var _a3, _b;
2431
+ const { dataLength, hasFooterComponent, initialContentOffset, initialScrollAtEnd, useBootstrapInitialScroll } = options;
1498
2432
  const state = ctx.state;
1499
- const {
1500
- didContainersLayout,
1501
- isAtEnd,
1502
- pendingNativeMVCPAdjust,
1503
- refScroller,
1504
- props: { maintainScrollAtEnd }
1505
- } = state;
1506
- const shouldMaintainScrollAtEnd = !!(isAtEnd && maintainScrollAtEnd && didContainersLayout);
1507
- if (pendingNativeMVCPAdjust) {
1508
- state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1509
- return false;
2433
+ const initialScroll = state.initialScroll;
2434
+ const resolvedInitialContentOffset = initialContentOffset != null ? initialContentOffset : 0;
2435
+ const preserveForFooterLayout = useBootstrapInitialScroll && initialScrollAtEnd && hasFooterComponent;
2436
+ if (initialScroll && (initialScroll.contentOffset === void 0 || !!initialScroll.preserveForFooterLayout !== preserveForFooterLayout && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) !== "offset")) {
2437
+ setInitialScrollTarget(state, {
2438
+ ...initialScroll,
2439
+ contentOffset: resolvedInitialContentOffset,
2440
+ preserveForFooterLayout
2441
+ });
1510
2442
  }
1511
- state.pendingMaintainScrollAtEnd = false;
1512
- if (shouldMaintainScrollAtEnd) {
1513
- const contentSize = getContentSize(ctx);
1514
- if (contentSize < state.scrollLength) {
1515
- state.scroll = 0;
2443
+ if (useBootstrapInitialScroll && initialScroll && ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) !== "offset") {
2444
+ startBootstrapInitialScrollOnMount(ctx, {
2445
+ initialScrollAtEnd,
2446
+ target: state.initialScroll
2447
+ });
2448
+ return;
2449
+ }
2450
+ const hasPendingDataDependentInitialScroll = !!initialScroll && dataLength === 0 && !(resolvedInitialContentOffset === 0 && !initialScrollAtEnd);
2451
+ if (!resolvedInitialContentOffset && !hasPendingDataDependentInitialScroll) {
2452
+ if (initialScroll && !initialScrollAtEnd) {
2453
+ finishInitialScroll(ctx, {
2454
+ resolvedOffset: resolvedInitialContentOffset
2455
+ });
2456
+ } else {
2457
+ setInitialRenderState(ctx, { didInitialScroll: true });
1516
2458
  }
1517
- requestAnimationFrame(() => {
1518
- var _a3;
1519
- if (state.isAtEnd) {
1520
- state.maintainingScrollAtEnd = true;
1521
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
1522
- animated: maintainScrollAtEnd.animated
2459
+ }
2460
+ }
2461
+ function handleInitialScrollDataChange(ctx, options) {
2462
+ var _a3, _b, _c;
2463
+ const { dataLength, didDataChange, initialScrollAtEnd, stylePaddingBottom, useBootstrapInitialScroll } = options;
2464
+ const state = ctx.state;
2465
+ const previousDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
2466
+ if (state.initialScrollSession) {
2467
+ state.initialScrollSession.previousDataLength = dataLength;
2468
+ }
2469
+ setInitialScrollSession(state);
2470
+ if (useBootstrapInitialScroll) {
2471
+ handleBootstrapInitialScrollDataChange(ctx, {
2472
+ dataLength,
2473
+ didDataChange,
2474
+ initialScrollAtEnd,
2475
+ previousDataLength,
2476
+ stylePaddingBottom
2477
+ });
2478
+ return;
2479
+ }
2480
+ const shouldReplayFinishedOffsetInitialScroll = previousDataLength === 0 && dataLength > 0 && !!state.initialScroll && ((_c = ctx.state.initialScrollSession) == null ? void 0 : _c.kind) === "offset" && !!state.didFinishInitialScroll;
2481
+ if (previousDataLength !== 0 || dataLength === 0 || !state.initialScroll || !state.queuedInitialLayout || state.didFinishInitialScroll && !shouldReplayFinishedOffsetInitialScroll) {
2482
+ return;
2483
+ }
2484
+ if (shouldReplayFinishedOffsetInitialScroll) {
2485
+ state.didFinishInitialScroll = false;
2486
+ }
2487
+ advanceCurrentInitialScrollSession(ctx);
2488
+ }
2489
+
2490
+ // src/utils/requestAdjust.ts
2491
+ function requestAdjust(ctx, positionDiff, dataChanged) {
2492
+ const state = ctx.state;
2493
+ if (Math.abs(positionDiff) > 0.1) {
2494
+ const needsScrollWorkaround = Platform2.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
2495
+ const doit = () => {
2496
+ if (needsScrollWorkaround) {
2497
+ scrollTo(ctx, {
2498
+ noScrollingTo: true,
2499
+ offset: state.scroll
1523
2500
  });
1524
- setTimeout(
1525
- () => {
1526
- state.maintainingScrollAtEnd = false;
1527
- },
1528
- maintainScrollAtEnd.animated ? 500 : 0
1529
- );
2501
+ } else {
2502
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
2503
+ if (state.adjustingFromInitialMount) {
2504
+ state.adjustingFromInitialMount--;
2505
+ }
1530
2506
  }
1531
- });
1532
- return true;
2507
+ };
2508
+ state.scroll += positionDiff;
2509
+ state.scrollForNextCalculateItemsInView = void 0;
2510
+ const readyToRender = peek$(ctx, "readyToRender");
2511
+ if (readyToRender) {
2512
+ doit();
2513
+ if (Platform2.OS !== "web") {
2514
+ const threshold = state.scroll - positionDiff / 2;
2515
+ if (!state.ignoreScrollFromMVCP) {
2516
+ state.ignoreScrollFromMVCP = {};
2517
+ }
2518
+ if (positionDiff > 0) {
2519
+ state.ignoreScrollFromMVCP.lt = threshold;
2520
+ } else {
2521
+ state.ignoreScrollFromMVCP.gt = threshold;
2522
+ }
2523
+ if (state.ignoreScrollFromMVCPTimeout) {
2524
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
2525
+ }
2526
+ const delay = needsScrollWorkaround ? 250 : 100;
2527
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
2528
+ var _a3;
2529
+ state.ignoreScrollFromMVCP = void 0;
2530
+ const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
2531
+ if (shouldForceUpdate) {
2532
+ state.ignoreScrollFromMVCPIgnored = false;
2533
+ state.scrollPending = state.scroll;
2534
+ (_a3 = state.reprocessCurrentScroll) == null ? void 0 : _a3.call(state);
2535
+ }
2536
+ }, delay);
2537
+ }
2538
+ } else {
2539
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
2540
+ requestAnimationFrame(doit);
2541
+ }
1533
2542
  }
1534
- return false;
1535
2543
  }
1536
2544
 
1537
2545
  // src/core/mvcp.ts
@@ -1823,184 +2831,6 @@ function prepareMVCP(ctx, dataChanged) {
1823
2831
  }
1824
2832
  }
1825
2833
 
1826
- // src/platform/flushSync.native.ts
1827
- var flushSync = (fn) => {
1828
- fn();
1829
- };
1830
-
1831
- // src/core/updateScroll.ts
1832
- function updateScroll(ctx, newScroll, forceUpdate) {
1833
- var _a3;
1834
- const state = ctx.state;
1835
- const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
1836
- const prevScroll = state.scroll;
1837
- state.hasScrolled = true;
1838
- state.lastBatchingAction = Date.now();
1839
- const currentTime = Date.now();
1840
- const adjust = scrollAdjustHandler.getAdjust();
1841
- const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1842
- if (adjustChanged) {
1843
- scrollHistory.length = 0;
1844
- }
1845
- state.lastScrollAdjustForHistory = adjust;
1846
- if (scrollingTo === void 0 && !(scrollHistory.length === 0 && newScroll === state.scroll)) {
1847
- if (!adjustChanged) {
1848
- scrollHistory.push({ scroll: newScroll, time: currentTime });
1849
- }
1850
- }
1851
- if (scrollHistory.length > 5) {
1852
- scrollHistory.shift();
1853
- }
1854
- if (ignoreScrollFromMVCP && !scrollingTo) {
1855
- const { lt, gt } = ignoreScrollFromMVCP;
1856
- if (lt && newScroll < lt || gt && newScroll > gt) {
1857
- state.ignoreScrollFromMVCPIgnored = true;
1858
- return;
1859
- }
1860
- }
1861
- state.scrollPrev = prevScroll;
1862
- state.scrollPrevTime = state.scrollTime;
1863
- state.scroll = newScroll;
1864
- state.scrollTime = currentTime;
1865
- const scrollDelta = Math.abs(newScroll - prevScroll);
1866
- const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
1867
- const scrollLength = state.scrollLength;
1868
- const lastCalculated = state.scrollLastCalculate;
1869
- const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
1870
- const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1871
- if (shouldUpdate) {
1872
- state.scrollLastCalculate = state.scroll;
1873
- state.ignoreScrollFromMVCPIgnored = false;
1874
- state.lastScrollDelta = scrollDelta;
1875
- const runCalculateItems = () => {
1876
- var _a4;
1877
- (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
1878
- checkThresholds(ctx);
1879
- };
1880
- if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1881
- flushSync(runCalculateItems);
1882
- } else {
1883
- runCalculateItems();
1884
- }
1885
- const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
1886
- if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
1887
- state.pendingMaintainScrollAtEnd = false;
1888
- doMaintainScrollAtEnd(ctx);
1889
- }
1890
- state.dataChangeNeedsScrollUpdate = false;
1891
- state.lastScrollDelta = 0;
1892
- }
1893
- }
1894
-
1895
- // src/utils/requestAdjust.ts
1896
- function requestAdjust(ctx, positionDiff, dataChanged) {
1897
- const state = ctx.state;
1898
- if (Math.abs(positionDiff) > 0.1) {
1899
- const needsScrollWorkaround = Platform2.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1900
- const doit = () => {
1901
- if (needsScrollWorkaround) {
1902
- scrollTo(ctx, {
1903
- noScrollingTo: true,
1904
- offset: state.scroll
1905
- });
1906
- } else {
1907
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1908
- if (state.adjustingFromInitialMount) {
1909
- state.adjustingFromInitialMount--;
1910
- }
1911
- }
1912
- };
1913
- state.scroll += positionDiff;
1914
- state.scrollForNextCalculateItemsInView = void 0;
1915
- const readyToRender = peek$(ctx, "readyToRender");
1916
- if (readyToRender) {
1917
- doit();
1918
- if (Platform2.OS !== "web") {
1919
- const threshold = state.scroll - positionDiff / 2;
1920
- if (!state.ignoreScrollFromMVCP) {
1921
- state.ignoreScrollFromMVCP = {};
1922
- }
1923
- if (positionDiff > 0) {
1924
- state.ignoreScrollFromMVCP.lt = threshold;
1925
- } else {
1926
- state.ignoreScrollFromMVCP.gt = threshold;
1927
- }
1928
- if (state.ignoreScrollFromMVCPTimeout) {
1929
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1930
- }
1931
- const delay = needsScrollWorkaround ? 250 : 100;
1932
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
1933
- state.ignoreScrollFromMVCP = void 0;
1934
- const shouldForceUpdate = state.ignoreScrollFromMVCPIgnored && state.scrollProcessingEnabled !== false;
1935
- if (shouldForceUpdate) {
1936
- state.ignoreScrollFromMVCPIgnored = false;
1937
- state.scrollPending = state.scroll;
1938
- updateScroll(ctx, state.scroll, true);
1939
- }
1940
- }, delay);
1941
- }
1942
- } else {
1943
- state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
1944
- requestAnimationFrame(doit);
1945
- }
1946
- }
1947
- }
1948
-
1949
- // src/core/ensureInitialAnchor.ts
1950
- var INITIAL_ANCHOR_TOLERANCE = 0.5;
1951
- var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1952
- var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1953
- function ensureInitialAnchor(ctx) {
1954
- var _a3, _b, _c, _d, _e, _f;
1955
- const state = ctx.state;
1956
- const { initialAnchor, didContainersLayout, scroll, scrollLength } = state;
1957
- const anchor = initialAnchor;
1958
- if (state.initialScroll || ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll)) {
1959
- return;
1960
- }
1961
- const item = state.props.data[anchor.index];
1962
- if (!didContainersLayout) {
1963
- return;
1964
- }
1965
- const id = getId(state, anchor.index);
1966
- if (state.positions[anchor.index] === void 0) {
1967
- return;
1968
- }
1969
- const size = getItemSize(ctx, id, anchor.index, item, true, true);
1970
- if (size === void 0) {
1971
- return;
1972
- }
1973
- const availableSpace = Math.max(0, scrollLength - size);
1974
- const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1975
- const desiredOffset = calculateOffsetForIndex(ctx, anchor.index) + topOffsetAdjustment - ((_b = anchor.viewOffset) != null ? _b : 0) - ((_c = anchor.viewPosition) != null ? _c : 0) * availableSpace;
1976
- const clampedDesiredOffset = clampScrollOffset(ctx, desiredOffset, anchor);
1977
- const delta = clampedDesiredOffset - scroll;
1978
- if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1979
- const settledTicks = ((_d = anchor.settledTicks) != null ? _d : 0) + 1;
1980
- if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1981
- state.initialAnchor = void 0;
1982
- } else {
1983
- anchor.settledTicks = settledTicks;
1984
- }
1985
- return;
1986
- }
1987
- if (((_e = anchor.attempts) != null ? _e : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1988
- state.initialAnchor = void 0;
1989
- return;
1990
- }
1991
- const lastDelta = anchor.lastDelta;
1992
- if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1993
- state.initialAnchor = void 0;
1994
- return;
1995
- }
1996
- Object.assign(anchor, {
1997
- attempts: ((_f = anchor.attempts) != null ? _f : 0) + 1,
1998
- lastDelta: delta,
1999
- settledTicks: 0
2000
- });
2001
- requestAdjust(ctx, delta);
2002
- }
2003
-
2004
2834
  // src/core/prepareColumnStartState.ts
2005
2835
  function prepareColumnStartState(ctx, startIndex, useAverageSize) {
2006
2836
  var _a3;
@@ -2514,23 +3344,6 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2514
3344
  var unstableBatchedUpdates = ReactNative.unstable_batchedUpdates;
2515
3345
  var batchedUpdates = typeof unstableBatchedUpdates === "function" ? unstableBatchedUpdates : (fn) => fn();
2516
3346
 
2517
- // src/utils/checkAllSizesKnown.ts
2518
- function isNullOrUndefined2(value) {
2519
- return value === null || value === void 0;
2520
- }
2521
- function checkAllSizesKnown(state) {
2522
- const { startBuffered, endBuffered, sizesKnown } = state;
2523
- if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
2524
- let areAllKnown = true;
2525
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
2526
- const key = getId(state, i);
2527
- areAllKnown && (areAllKnown = sizesKnown.has(key));
2528
- }
2529
- return areAllKnown;
2530
- }
2531
- return false;
2532
- }
2533
-
2534
3347
  // src/utils/findAvailableContainers.ts
2535
3348
  function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2536
3349
  const numContainers = peek$(ctx, "numContainers");
@@ -2653,97 +3466,11 @@ function comparatorByDistance(a, b) {
2653
3466
  return b.distance - a.distance;
2654
3467
  }
2655
3468
 
2656
- // src/core/scrollToIndex.ts
2657
- function scrollToIndex(ctx, {
2658
- index,
2659
- viewOffset = 0,
2660
- animated = true,
2661
- forceScroll,
2662
- isInitialScroll,
2663
- viewPosition
2664
- }) {
2665
- const state = ctx.state;
2666
- const { data } = state.props;
2667
- if (index >= data.length) {
2668
- index = data.length - 1;
2669
- } else if (index < 0) {
2670
- index = 0;
2671
- }
2672
- const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2673
- const isLast = index === data.length - 1;
2674
- if (isLast && viewPosition === void 0) {
2675
- viewPosition = 1;
2676
- }
2677
- state.scrollForNextCalculateItemsInView = void 0;
2678
- const targetId = getId(state, index);
2679
- const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2680
- scrollTo(ctx, {
2681
- animated,
2682
- forceScroll,
2683
- index,
2684
- isInitialScroll,
2685
- itemSize,
2686
- offset: firstIndexOffset,
2687
- viewOffset,
2688
- viewPosition: viewPosition != null ? viewPosition : 0
2689
- });
2690
- }
2691
-
2692
- // src/utils/performInitialScroll.ts
2693
- function performInitialScroll(ctx, params) {
2694
- var _a3;
2695
- const { forceScroll, initialScrollUsesOffset, resolvedOffset, target } = params;
2696
- if (initialScrollUsesOffset || resolvedOffset !== void 0) {
2697
- scrollTo(ctx, {
2698
- animated: false,
2699
- forceScroll,
2700
- index: initialScrollUsesOffset ? void 0 : target.index,
2701
- isInitialScroll: true,
2702
- offset: (_a3 = resolvedOffset != null ? resolvedOffset : target.contentOffset) != null ? _a3 : 0,
2703
- precomputedWithViewOffset: resolvedOffset !== void 0
2704
- });
2705
- return;
2706
- }
2707
- if (target.index === void 0) {
2708
- return;
2709
- }
2710
- scrollToIndex(ctx, {
2711
- ...target,
2712
- animated: false,
2713
- forceScroll,
2714
- isInitialScroll: true
2715
- });
2716
- }
2717
-
2718
3469
  // src/utils/setDidLayout.ts
2719
3470
  function setDidLayout(ctx) {
2720
3471
  const state = ctx.state;
2721
- const { initialScroll } = state;
2722
3472
  state.queuedInitialLayout = true;
2723
- checkAtBottom(ctx);
2724
- if (initialScroll) {
2725
- const runScroll = () => {
2726
- var _a3, _b;
2727
- const target = state.initialScroll;
2728
- if (!target) {
2729
- return;
2730
- }
2731
- const activeInitialTargetOffset = ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) ? (_b = state.scrollingTo.targetOffset) != null ? _b : state.scrollingTo.offset : void 0;
2732
- const desiredInitialTargetOffset = state.initialScrollUsesOffset ? target.contentOffset : activeInitialTargetOffset;
2733
- const isAlreadyAtDesiredInitialTarget = desiredInitialTargetOffset !== void 0 && Math.abs(state.scroll - desiredInitialTargetOffset) <= 1 && Math.abs(state.scrollPending - desiredInitialTargetOffset) <= 1;
2734
- if (!isAlreadyAtDesiredInitialTarget) {
2735
- performInitialScroll(ctx, {
2736
- forceScroll: true,
2737
- initialScrollUsesOffset: state.initialScrollUsesOffset,
2738
- // Offset-based initial scrolls do not need item lookup, so they can run even before data exists.
2739
- // Re-run on the next frame to pick up measured viewport size without waiting for index resolution.
2740
- target
2741
- });
2742
- }
2743
- };
2744
- runScroll();
2745
- requestAnimationFrame(runScroll);
2746
- }
3473
+ checkAtBottom(ctx);
2747
3474
  setInitialRenderState(ctx, { didLayout: true });
2748
3475
  }
2749
3476
 
@@ -2818,7 +3545,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
2818
3545
  function calculateItemsInView(ctx, params = {}) {
2819
3546
  const state = ctx.state;
2820
3547
  batchedUpdates(() => {
2821
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
3548
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2822
3549
  const {
2823
3550
  columns,
2824
3551
  columnSpans,
@@ -2826,7 +3553,6 @@ function calculateItemsInView(ctx, params = {}) {
2826
3553
  enableScrollForNextCalculateItemsInView,
2827
3554
  idCache,
2828
3555
  indexByKey,
2829
- initialScroll,
2830
3556
  minIndexSizeChanged,
2831
3557
  positions,
2832
3558
  props: {
@@ -2850,11 +3576,10 @@ function calculateItemsInView(ctx, params = {}) {
2850
3576
  const alwaysRenderArr = alwaysRenderIndicesArr || [];
2851
3577
  const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
2852
3578
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
3579
+ const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
3580
+ const suppressInitialScrollSideEffects = !!bootstrapInitialScrollState;
2853
3581
  const prevNumContainers = peek$(ctx, "numContainers");
2854
3582
  if (!data || scrollLength === 0 || !prevNumContainers) {
2855
- if (!IsNewArchitecture && state.initialAnchor) {
2856
- ensureInitialAnchor(ctx);
2857
- }
2858
3583
  return;
2859
3584
  }
2860
3585
  let totalSize = getContentSize(ctx);
@@ -2863,16 +3588,12 @@ function calculateItemsInView(ctx, params = {}) {
2863
3588
  const speed = getScrollVelocity(state);
2864
3589
  const scrollExtra = 0;
2865
3590
  const { queuedInitialLayout } = state;
2866
- let { scroll: scrollState } = state;
2867
- if (!queuedInitialLayout && initialScroll) {
2868
- const updatedOffset = state.initialScrollUsesOffset ? (_a3 = initialScroll.contentOffset) != null ? _a3 : 0 : calculateOffsetWithOffsetPosition(
2869
- ctx,
2870
- calculateOffsetForIndex(ctx, initialScroll.index),
2871
- initialScroll
2872
- );
2873
- scrollState = updatedOffset;
2874
- }
2875
- const scrollAdjustPending = (_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0;
3591
+ const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && state.initialScroll ? (
3592
+ // Before the initial layout settles, keep viewport math anchored to the
3593
+ // current initial-scroll target instead of transient native adjustments.
3594
+ resolveInitialScrollOffset(ctx, state.initialScroll)
3595
+ ) : state.scroll;
3596
+ const scrollAdjustPending = (_c = peek$(ctx, "scrollAdjustPending")) != null ? _c : 0;
2876
3597
  const scrollAdjustPad = scrollAdjustPending - topPad;
2877
3598
  let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2878
3599
  if (scroll + scrollLength > totalSize) {
@@ -2896,20 +3617,17 @@ function calculateItemsInView(ctx, params = {}) {
2896
3617
  const scrollTopBuffered = scroll - scrollBufferTop;
2897
3618
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2898
3619
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2899
- if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
3620
+ if (!suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2900
3621
  const { top, bottom } = scrollForNextCalculateItemsInView;
2901
3622
  if (top === null && bottom === null) {
2902
3623
  state.scrollForNextCalculateItemsInView = void 0;
2903
3624
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2904
- if (!IsNewArchitecture && state.initialAnchor) {
2905
- ensureInitialAnchor(ctx);
2906
- }
2907
3625
  if (Platform2.OS !== "web" || !isInMVCPActiveMode(state)) {
2908
3626
  return;
2909
3627
  }
2910
3628
  }
2911
3629
  }
2912
- const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
3630
+ const checkMVCP = doMVCP && !suppressInitialScrollSideEffects ? prepareMVCP(ctx, dataChanged) : void 0;
2913
3631
  if (dataChanged) {
2914
3632
  indexByKey.clear();
2915
3633
  idCache.length = 0;
@@ -2917,7 +3635,7 @@ function calculateItemsInView(ctx, params = {}) {
2917
3635
  columns.length = 0;
2918
3636
  columnSpans.length = 0;
2919
3637
  }
2920
- const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
3638
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_d = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _d : 0;
2921
3639
  updateItemPositions(ctx, dataChanged, {
2922
3640
  doMVCP,
2923
3641
  forceFullUpdate: !!forceFullItemPositions,
@@ -2934,11 +3652,11 @@ function calculateItemsInView(ctx, params = {}) {
2934
3652
  let startBufferedId = null;
2935
3653
  let endNoBuffer = null;
2936
3654
  let endBuffered = null;
2937
- let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
3655
+ let loopStart = (_e = suppressInitialScrollSideEffects ? bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.targetIndexSeed : void 0) != null ? _e : !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2938
3656
  for (let i = loopStart; i >= 0; i--) {
2939
- const id = (_d = idCache[i]) != null ? _d : getId(state, i);
3657
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2940
3658
  const top = positions[i];
2941
- const size = (_e = sizes.get(id)) != null ? _e : getItemSize(ctx, id, i, data[i]);
3659
+ const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
2942
3660
  const bottom = top + size;
2943
3661
  if (bottom > scroll - scrollBufferTop) {
2944
3662
  loopStart = i;
@@ -2969,8 +3687,8 @@ function calculateItemsInView(ctx, params = {}) {
2969
3687
  let firstFullyOnScreenIndex;
2970
3688
  const dataLength = data.length;
2971
3689
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2972
- const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2973
- const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
3690
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
3691
+ const size = (_i = sizes.get(id)) != null ? _i : getItemSize(ctx, id, i, data[i]);
2974
3692
  const top = positions[i];
2975
3693
  if (!foundEnd) {
2976
3694
  if (startNoBuffer === null && top + size > scroll) {
@@ -3009,7 +3727,7 @@ function calculateItemsInView(ctx, params = {}) {
3009
3727
  const firstVisibleAnchorIndex = firstFullyOnScreenIndex != null ? firstFullyOnScreenIndex : startNoBuffer;
3010
3728
  if (firstVisibleAnchorIndex !== null && firstVisibleAnchorIndex !== void 0 && endNoBuffer !== null) {
3011
3729
  for (let i = firstVisibleAnchorIndex; i <= endNoBuffer; i++) {
3012
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
3730
+ const id = (_j = idCache[i]) != null ? _j : getId(state, i);
3013
3731
  idsInView.push(id);
3014
3732
  }
3015
3733
  }
@@ -3042,7 +3760,7 @@ function calculateItemsInView(ctx, params = {}) {
3042
3760
  const needNewContainers = [];
3043
3761
  const needNewContainersSet = /* @__PURE__ */ new Set();
3044
3762
  for (let i = startBuffered; i <= endBuffered; i++) {
3045
- const id = (_i = idCache[i]) != null ? _i : getId(state, i);
3763
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
3046
3764
  if (!containerItemKeys.has(id)) {
3047
3765
  needNewContainersSet.add(i);
3048
3766
  needNewContainers.push(i);
@@ -3051,7 +3769,7 @@ function calculateItemsInView(ctx, params = {}) {
3051
3769
  if (alwaysRenderArr.length > 0) {
3052
3770
  for (const index of alwaysRenderArr) {
3053
3771
  if (index < 0 || index >= dataLength) continue;
3054
- const id = (_j = idCache[index]) != null ? _j : getId(state, index);
3772
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
3055
3773
  if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
3056
3774
  needNewContainersSet.add(index);
3057
3775
  needNewContainers.push(index);
@@ -3089,7 +3807,7 @@ function calculateItemsInView(ctx, params = {}) {
3089
3807
  for (let idx = 0; idx < needNewContainers.length; idx++) {
3090
3808
  const i = needNewContainers[idx];
3091
3809
  const containerIndex = availableContainers[idx];
3092
- const id = (_k = idCache[i]) != null ? _k : getId(state, i);
3810
+ const id = (_m = idCache[i]) != null ? _m : getId(state, i);
3093
3811
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
3094
3812
  if (oldKey && oldKey !== id) {
3095
3813
  containerItemKeys.delete(oldKey);
@@ -3130,7 +3848,7 @@ function calculateItemsInView(ctx, params = {}) {
3130
3848
  if (alwaysRenderArr.length > 0) {
3131
3849
  for (const index of alwaysRenderArr) {
3132
3850
  if (index < 0 || index >= dataLength) continue;
3133
- const id = (_l = idCache[index]) != null ? _l : getId(state, index);
3851
+ const id = (_n = idCache[index]) != null ? _n : getId(state, index);
3134
3852
  const containerIndex = containerItemKeys.get(id);
3135
3853
  if (containerIndex !== void 0) {
3136
3854
  state.stickyContainerPool.add(containerIndex);
@@ -3201,13 +3919,23 @@ function calculateItemsInView(ctx, params = {}) {
3201
3919
  if (Platform2.OS === "web" && didChangePositions) {
3202
3920
  set$(ctx, "lastPositionUpdate", Date.now());
3203
3921
  }
3204
- if (!queuedInitialLayout && endBuffered !== null) {
3205
- if (checkAllSizesKnown(state)) {
3206
- setDidLayout(ctx);
3207
- }
3922
+ if (suppressInitialScrollSideEffects) {
3923
+ evaluateBootstrapInitialScroll(ctx);
3924
+ return;
3208
3925
  }
3209
- if (viewabilityConfigCallbackPairs) {
3210
- updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
3926
+ if (!queuedInitialLayout && endBuffered !== null && checkAllSizesKnown(state)) {
3927
+ setDidLayout(ctx);
3928
+ handleInitialScrollLayoutReady(ctx);
3929
+ }
3930
+ if (viewabilityConfigCallbackPairs && startNoBuffer !== null && endNoBuffer !== null) {
3931
+ updateViewableItems(
3932
+ ctx.state,
3933
+ ctx,
3934
+ viewabilityConfigCallbackPairs,
3935
+ scrollLength,
3936
+ startNoBuffer,
3937
+ endNoBuffer
3938
+ );
3211
3939
  }
3212
3940
  if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
3213
3941
  const item = data[nextActiveStickyIndex];
@@ -3216,9 +3944,6 @@ function calculateItemsInView(ctx, params = {}) {
3216
3944
  }
3217
3945
  }
3218
3946
  });
3219
- if (!IsNewArchitecture && state.initialAnchor) {
3220
- ensureInitialAnchor(ctx);
3221
- }
3222
3947
  }
3223
3948
 
3224
3949
  // src/core/checkActualChange.ts
@@ -3241,6 +3966,47 @@ function checkActualChange(state, dataProp, previousData) {
3241
3966
  return false;
3242
3967
  }
3243
3968
 
3969
+ // src/core/doMaintainScrollAtEnd.ts
3970
+ function doMaintainScrollAtEnd(ctx) {
3971
+ const state = ctx.state;
3972
+ const {
3973
+ didContainersLayout,
3974
+ isAtEnd,
3975
+ pendingNativeMVCPAdjust,
3976
+ refScroller,
3977
+ props: { maintainScrollAtEnd }
3978
+ } = state;
3979
+ const shouldMaintainScrollAtEnd = !!(isAtEnd && maintainScrollAtEnd && didContainersLayout);
3980
+ if (pendingNativeMVCPAdjust) {
3981
+ state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
3982
+ return false;
3983
+ }
3984
+ state.pendingMaintainScrollAtEnd = false;
3985
+ if (shouldMaintainScrollAtEnd) {
3986
+ const contentSize = getContentSize(ctx);
3987
+ if (contentSize < state.scrollLength) {
3988
+ state.scroll = 0;
3989
+ }
3990
+ requestAnimationFrame(() => {
3991
+ var _a3;
3992
+ if (state.isAtEnd) {
3993
+ state.maintainingScrollAtEnd = true;
3994
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
3995
+ animated: maintainScrollAtEnd.animated
3996
+ });
3997
+ setTimeout(
3998
+ () => {
3999
+ state.maintainingScrollAtEnd = false;
4000
+ },
4001
+ maintainScrollAtEnd.animated ? 500 : 0
4002
+ );
4003
+ }
4004
+ });
4005
+ return true;
4006
+ }
4007
+ return false;
4008
+ }
4009
+
3244
4010
  // src/utils/updateAveragesOnDataChange.ts
3245
4011
  function updateAveragesOnDataChange(state, oldData, newData) {
3246
4012
  var _a3;
@@ -3424,20 +4190,107 @@ function handleLayout(ctx, layoutParam, setCanRender) {
3424
4190
  setCanRender(true);
3425
4191
  }
3426
4192
 
4193
+ // src/platform/flushSync.native.ts
4194
+ var flushSync = (fn) => {
4195
+ fn();
4196
+ };
4197
+
4198
+ // src/core/updateScroll.ts
4199
+ function updateScroll(ctx, newScroll, forceUpdate) {
4200
+ var _a3;
4201
+ const state = ctx.state;
4202
+ const { ignoreScrollFromMVCP, lastScrollAdjustForHistory, scrollAdjustHandler, scrollHistory, scrollingTo } = state;
4203
+ const prevScroll = state.scroll;
4204
+ state.hasScrolled = true;
4205
+ state.lastBatchingAction = Date.now();
4206
+ const currentTime = Date.now();
4207
+ const adjust = scrollAdjustHandler.getAdjust();
4208
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
4209
+ if (adjustChanged) {
4210
+ scrollHistory.length = 0;
4211
+ }
4212
+ state.lastScrollAdjustForHistory = adjust;
4213
+ if (scrollingTo === void 0 && !(scrollHistory.length === 0 && newScroll === state.scroll)) {
4214
+ if (!adjustChanged) {
4215
+ scrollHistory.push({ scroll: newScroll, time: currentTime });
4216
+ }
4217
+ }
4218
+ if (scrollHistory.length > 5) {
4219
+ scrollHistory.shift();
4220
+ }
4221
+ if (ignoreScrollFromMVCP && !scrollingTo) {
4222
+ const { lt, gt } = ignoreScrollFromMVCP;
4223
+ if (lt && newScroll < lt || gt && newScroll > gt) {
4224
+ state.ignoreScrollFromMVCPIgnored = true;
4225
+ return;
4226
+ }
4227
+ }
4228
+ state.scrollPrev = prevScroll;
4229
+ state.scrollPrevTime = state.scrollTime;
4230
+ state.scroll = newScroll;
4231
+ state.scrollTime = currentTime;
4232
+ const scrollDelta = Math.abs(newScroll - prevScroll);
4233
+ const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
4234
+ const scrollLength = state.scrollLength;
4235
+ const lastCalculated = state.scrollLastCalculate;
4236
+ const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
4237
+ const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
4238
+ if (shouldUpdate) {
4239
+ state.scrollLastCalculate = state.scroll;
4240
+ state.ignoreScrollFromMVCPIgnored = false;
4241
+ state.lastScrollDelta = scrollDelta;
4242
+ const runCalculateItems = () => {
4243
+ var _a4;
4244
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0 });
4245
+ checkThresholds(ctx);
4246
+ };
4247
+ if (Platform2.OS === "web" && scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
4248
+ flushSync(runCalculateItems);
4249
+ } else {
4250
+ runCalculateItems();
4251
+ }
4252
+ const shouldMaintainScrollAtEndAfterPendingSettle = !!state.pendingMaintainScrollAtEnd || !!((_a3 = state.props.maintainScrollAtEnd) == null ? void 0 : _a3.onDataChange);
4253
+ if (didResolvePendingNativeMVCPAdjust && shouldMaintainScrollAtEndAfterPendingSettle) {
4254
+ state.pendingMaintainScrollAtEnd = false;
4255
+ doMaintainScrollAtEnd(ctx);
4256
+ }
4257
+ state.dataChangeNeedsScrollUpdate = false;
4258
+ state.lastScrollDelta = 0;
4259
+ }
4260
+ }
4261
+
3427
4262
  // src/core/onScroll.ts
3428
- var INITIAL_SCROLL_PROGRESS_EPSILON = 1;
3429
- function didObserveInitialScrollProgress(newScroll, watchdog) {
3430
- const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
3431
- const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
3432
- return nextDistance <= INITIAL_SCROLL_PROGRESS_EPSILON || nextDistance + INITIAL_SCROLL_PROGRESS_EPSILON < previousDistance;
4263
+ function trackInitialScrollNativeProgress(state, newScroll) {
4264
+ const initialNativeScrollWatchdog = initialScrollWatchdog.get(state);
4265
+ const didInitialScrollProgress = !!initialNativeScrollWatchdog && initialScrollWatchdog.didObserveProgress(newScroll, initialNativeScrollWatchdog);
4266
+ if (didInitialScrollProgress) {
4267
+ initialScrollWatchdog.clear(state);
4268
+ return;
4269
+ }
4270
+ if (initialNativeScrollWatchdog) {
4271
+ state.hasScrolled = false;
4272
+ initialScrollWatchdog.set(state, {
4273
+ startScroll: initialNativeScrollWatchdog.startScroll,
4274
+ targetOffset: initialNativeScrollWatchdog.targetOffset
4275
+ });
4276
+ }
4277
+ }
4278
+ function shouldDeferPublicOnScroll(state) {
4279
+ var _a3;
4280
+ return Platform2.OS === "web" && !!state.initialScroll && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" && !state.didFinishInitialScroll;
4281
+ }
4282
+ function cloneScrollEvent(event) {
4283
+ return {
4284
+ ...event,
4285
+ nativeEvent: {
4286
+ ...event.nativeEvent
4287
+ }
4288
+ };
3433
4289
  }
3434
4290
  function onScroll(ctx, event) {
3435
4291
  var _a3, _b, _c, _d;
3436
4292
  const state = ctx.state;
3437
- const {
3438
- scrollProcessingEnabled,
3439
- props: { onScroll: onScrollProp }
3440
- } = state;
4293
+ const { scrollProcessingEnabled } = state;
3441
4294
  if (scrollProcessingEnabled === false) {
3442
4295
  return;
3443
4296
  }
@@ -3468,20 +4321,18 @@ function onScroll(ctx, event) {
3468
4321
  }
3469
4322
  }
3470
4323
  state.scrollPending = newScroll;
3471
- const initialNativeScrollWatchdog = state.initialNativeScrollWatchdog;
3472
- const didInitialScrollProgress = !!initialNativeScrollWatchdog && didObserveInitialScrollProgress(newScroll, initialNativeScrollWatchdog);
3473
- if (didInitialScrollProgress) {
3474
- state.initialNativeScrollWatchdog = void 0;
3475
- }
3476
4324
  updateScroll(ctx, newScroll, insetChanged);
3477
- if (initialNativeScrollWatchdog && !didInitialScrollProgress) {
3478
- state.hasScrolled = false;
3479
- state.initialNativeScrollWatchdog = initialNativeScrollWatchdog;
3480
- }
4325
+ trackInitialScrollNativeProgress(state, newScroll);
3481
4326
  if (state.scrollingTo) {
3482
4327
  checkFinishedScroll(ctx);
3483
4328
  }
3484
- onScrollProp == null ? void 0 : onScrollProp(event);
4329
+ if (state.props.onScroll) {
4330
+ if (shouldDeferPublicOnScroll(state)) {
4331
+ state.deferredPublicOnScrollEvent = cloneScrollEvent(event);
4332
+ } else {
4333
+ state.props.onScroll(event);
4334
+ }
4335
+ }
3485
4336
  }
3486
4337
 
3487
4338
  // src/core/ScrollAdjustHandler.ts
@@ -4150,7 +5001,7 @@ var LegendList = typedMemo2(
4150
5001
  })
4151
5002
  );
4152
5003
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
4153
- var _a3, _b, _c, _d, _e, _f, _g, _h;
5004
+ var _a3, _b, _c, _d, _e, _f, _g;
4154
5005
  const {
4155
5006
  alignItemsAtEnd = false,
4156
5007
  alwaysRender,
@@ -4174,6 +5025,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4174
5025
  itemsAreEqual,
4175
5026
  keyExtractor: keyExtractorProp,
4176
5027
  ListEmptyComponent,
5028
+ ListFooterComponent,
5029
+ ListFooterComponentStyle,
4177
5030
  ListHeaderComponent,
4178
5031
  maintainScrollAtEnd = false,
4179
5032
  maintainScrollAtEndThreshold = 0.1,
@@ -4210,7 +5063,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4210
5063
  useWindowScroll = false,
4211
5064
  viewabilityConfig,
4212
5065
  viewabilityConfigCallbackPairs,
4213
- waitForInitialLayout = true,
4214
5066
  ...rest
4215
5067
  } = props;
4216
5068
  const animatedPropsInternal = props.animatedPropsInternal;
@@ -4243,8 +5095,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4243
5095
  const hasInitialScrollIndex = initialScrollIndexProp !== void 0 && initialScrollIndexProp !== null;
4244
5096
  const hasInitialScrollOffset = initialScrollOffsetProp !== void 0 && initialScrollOffsetProp !== null;
4245
5097
  const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && hasInitialScrollOffset;
4246
- const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
5098
+ const usesBootstrapInitialScroll = initialScrollAtEnd || hasInitialScrollIndex;
5099
+ const initialScrollProp = initialScrollAtEnd ? {
5100
+ index: Math.max(0, dataProp.length - 1),
5101
+ preserveForBottomPadding: true,
5102
+ viewOffset: -stylePaddingBottomState,
5103
+ viewPosition: 1
5104
+ } : hasInitialScrollIndex ? typeof initialScrollIndexProp === "object" ? {
4247
5105
  index: (_a3 = initialScrollIndexProp.index) != null ? _a3 : 0,
5106
+ preserveForBottomPadding: initialScrollIndexProp.viewOffset === void 0 && initialScrollIndexProp.viewPosition === 1 ? true : void 0,
4248
5107
  viewOffset: (_b = initialScrollIndexProp.viewOffset) != null ? _b : initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0,
4249
5108
  viewPosition: (_c = initialScrollIndexProp.viewPosition) != null ? _c : 0
4250
5109
  } : {
@@ -4313,22 +5172,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4313
5172
  idCache: [],
4314
5173
  idsInView: [],
4315
5174
  indexByKey: /* @__PURE__ */ new Map(),
4316
- initialAnchor: !initialScrollUsesOffsetOnly && (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
4317
- attempts: 0,
4318
- index: initialScrollProp.index,
4319
- settledTicks: 0,
4320
- viewOffset: (_f = initialScrollProp.viewOffset) != null ? _f : 0,
4321
- viewPosition: initialScrollProp.viewPosition
4322
- } : void 0,
4323
- initialNativeScrollWatchdog: void 0,
4324
5175
  initialScroll: initialScrollProp,
4325
- initialScrollLastDidFinish: false,
4326
- initialScrollLastTarget: initialScrollProp,
4327
- initialScrollLastTargetUsesOffset: initialScrollUsesOffsetOnly,
4328
- initialScrollPreviousDataLength: dataProp.length,
4329
- initialScrollRetryLastLength: void 0,
4330
- initialScrollRetryWindowUntil: 0,
4331
- initialScrollUsesOffset: initialScrollUsesOffsetOnly,
5176
+ initialScrollSession: initialScrollProp ? {
5177
+ kind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
5178
+ previousDataLength: dataProp.length
5179
+ } : void 0,
4332
5180
  isAtEnd: false,
4333
5181
  isAtStart: false,
4334
5182
  isEndReached: null,
@@ -4371,6 +5219,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4371
5219
  };
4372
5220
  const internalState = ctx.state;
4373
5221
  internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
5222
+ internalState.reprocessCurrentScroll = () => updateScroll(ctx, internalState.scroll, true);
4374
5223
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPositionConfig);
4375
5224
  set$(ctx, "extraData", extraData);
4376
5225
  }
@@ -4462,115 +5311,23 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4462
5311
  true
4463
5312
  );
4464
5313
  }
4465
- const resolveInitialScrollOffset = useCallback((initialScroll) => {
4466
- var _a4;
4467
- if (state.initialScrollUsesOffset) {
4468
- return clampScrollOffset(ctx, (_a4 = initialScroll.contentOffset) != null ? _a4 : 0);
4469
- }
4470
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
4471
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
4472
- return clampScrollOffset(ctx, resolvedOffset, initialScroll);
4473
- }, []);
4474
- const finishInitialScrollWithoutScroll = useCallback(() => {
4475
- refState.current.initialAnchor = void 0;
4476
- refState.current.initialScroll = void 0;
4477
- state.initialAnchor = void 0;
4478
- state.initialScroll = void 0;
4479
- state.initialScrollUsesOffset = false;
4480
- state.initialScrollLastTarget = void 0;
4481
- state.initialScrollLastTargetUsesOffset = false;
4482
- setInitialRenderState(ctx, { didInitialScroll: true });
4483
- }, []);
4484
- const setActiveInitialScrollTarget = useCallback(
4485
- (target, options) => {
4486
- var _a4;
4487
- const usesOffset = !!(options == null ? void 0 : options.usesOffset);
4488
- state.initialScrollUsesOffset = usesOffset;
4489
- state.initialScrollLastTarget = target;
4490
- state.initialScrollLastTargetUsesOffset = usesOffset;
4491
- refState.current.initialScroll = target;
4492
- state.initialScroll = target;
4493
- if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
4494
- state.didFinishInitialScroll = false;
4495
- }
4496
- if (!(options == null ? void 0 : options.syncAnchor)) {
4497
- return;
4498
- }
4499
- if (!IsNewArchitecture && !usesOffset && target.index !== void 0 && target.viewPosition !== void 0) {
4500
- state.initialAnchor = {
4501
- attempts: 0,
4502
- index: target.index,
4503
- settledTicks: 0,
4504
- viewOffset: (_a4 = target.viewOffset) != null ? _a4 : 0,
4505
- viewPosition: target.viewPosition
4506
- };
4507
- }
4508
- },
4509
- []
4510
- );
4511
- const shouldFinishInitialScrollAtOrigin = useCallback(
4512
- (initialScroll, offset) => {
4513
- var _a4, _b2, _c2;
4514
- if (offset !== 0 || initialScrollAtEnd) {
4515
- return false;
4516
- }
4517
- if (state.initialScrollUsesOffset) {
4518
- return Math.abs((_a4 = initialScroll.contentOffset) != null ? _a4 : 0) <= 1;
4519
- }
4520
- return initialScroll.index === 0 && ((_b2 = initialScroll.viewPosition) != null ? _b2 : 0) === 0 && Math.abs((_c2 = initialScroll.viewOffset) != null ? _c2 : 0) <= 1;
4521
- },
4522
- [initialScrollAtEnd]
4523
- );
4524
- const shouldFinishEmptyInitialScrollAtEnd = useCallback(
4525
- (initialScroll, offset) => {
4526
- return dataProp.length === 0 && initialScrollAtEnd && offset === 0 && initialScroll.viewPosition === 1;
4527
- },
4528
- [dataProp.length, initialScrollAtEnd]
4529
- );
4530
- const shouldRearmFinishedEmptyInitialScrollAtEnd = useCallback(
4531
- (initialScroll) => {
4532
- var _a4;
4533
- return !!(state.didFinishInitialScroll && dataProp.length > 0 && initialScroll && !state.initialScrollUsesOffset && initialScroll.index === 0 && initialScroll.viewPosition === 1 && ((_a4 = initialScroll.contentOffset) != null ? _a4 : 0) === 0);
4534
- },
4535
- [dataProp.length]
4536
- );
4537
5314
  const initialContentOffset = useMemo(() => {
4538
- var _a4;
4539
- let value;
4540
- const { initialScroll, initialAnchor } = refState.current;
4541
- if (initialScroll) {
4542
- if (!state.initialScrollUsesOffset && !IsNewArchitecture && initialScroll.index !== void 0 && (!initialAnchor || (initialAnchor == null ? void 0 : initialAnchor.index) !== initialScroll.index)) {
4543
- refState.current.initialAnchor = {
4544
- attempts: 0,
4545
- index: initialScroll.index,
4546
- settledTicks: 0,
4547
- viewOffset: (_a4 = initialScroll.viewOffset) != null ? _a4 : 0,
4548
- viewPosition: initialScroll.viewPosition
4549
- };
4550
- }
4551
- if (initialScroll.contentOffset !== void 0) {
4552
- value = initialScroll.contentOffset;
4553
- } else {
4554
- const clampedOffset = resolveInitialScrollOffset(initialScroll);
4555
- const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
4556
- setActiveInitialScrollTarget(updatedInitialScroll, {
4557
- usesOffset: state.initialScrollUsesOffset
4558
- });
4559
- value = clampedOffset;
4560
- }
4561
- } else {
4562
- refState.current.initialAnchor = void 0;
4563
- value = 0;
4564
- }
4565
- const hasPendingDataDependentInitialScroll = !!initialScroll && dataProp.length === 0 && !shouldFinishInitialScrollAtOrigin(initialScroll, value) && !shouldFinishEmptyInitialScrollAtEnd(initialScroll, value);
4566
- if (!value && !hasPendingDataDependentInitialScroll) {
4567
- if (initialScroll && shouldFinishInitialScrollAtOrigin(initialScroll, value)) {
4568
- finishInitialScrollWithoutScroll();
4569
- } else {
4570
- setInitialRenderState(ctx, { didInitialScroll: true });
4571
- }
5315
+ var _a4, _b2;
5316
+ const initialScroll = state.initialScroll;
5317
+ if (!initialScroll) {
5318
+ return void 0;
4572
5319
  }
4573
- return value;
5320
+ const resolvedOffset = (_a4 = initialScroll.contentOffset) != null ? _a4 : resolveInitialScrollOffset(ctx, initialScroll);
5321
+ return usesBootstrapInitialScroll && ((_b2 = state.initialScrollSession) == null ? void 0 : _b2.kind) === "bootstrap" && Platform2.OS === "web" ? void 0 : resolvedOffset;
5322
+ }, [usesBootstrapInitialScroll]);
5323
+ useLayoutEffect(() => {
5324
+ initializeInitialScrollOnMount(ctx, {
5325
+ dataLength: dataProp.length,
5326
+ hasFooterComponent: !!ListFooterComponent,
5327
+ initialContentOffset,
5328
+ initialScrollAtEnd,
5329
+ useBootstrapInitialScroll: usesBootstrapInitialScroll
5330
+ });
4574
5331
  }, []);
4575
5332
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
4576
5333
  refState.current.lastBatchingAction = Date.now();
@@ -4585,188 +5342,39 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4585
5342
  set$(ctx, "totalSize", 0);
4586
5343
  }
4587
5344
  }
4588
- const doInitialScroll = useCallback((options) => {
4589
- var _a4, _b2;
4590
- const allowPostFinishRetry = !!(options == null ? void 0 : options.allowPostFinishRetry);
4591
- const { didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
4592
- const initialScroll = (_a4 = state.initialScroll) != null ? _a4 : allowPostFinishRetry ? state.initialScrollLastTarget : void 0;
4593
- const isInitialScrollInProgress = !!(scrollingTo == null ? void 0 : scrollingTo.isInitialScroll);
4594
- const needsContainerLayoutForInitialScroll = !state.initialScrollUsesOffset;
4595
- const shouldWaitForInitialLayout = waitForInitialLayout && needsContainerLayoutForInitialScroll && !queuedInitialLayout && !allowPostFinishRetry && !isInitialScrollInProgress;
4596
- if (!initialScroll || shouldWaitForInitialLayout || didFinishInitialScroll && !allowPostFinishRetry || scrollingTo && !isInitialScrollInProgress) {
4597
- return;
4598
- }
4599
- if (allowPostFinishRetry && state.initialScrollLastTargetUsesOffset) {
4600
- return;
4601
- }
4602
- const didMoveAwayFromInitialTarget = allowPostFinishRetry && initialScroll.contentOffset !== void 0 && Math.abs(state.scroll - initialScroll.contentOffset) > 1;
4603
- if (didMoveAwayFromInitialTarget) {
4604
- state.initialScrollRetryWindowUntil = 0;
4605
- return;
4606
- }
4607
- const offset = resolveInitialScrollOffset(initialScroll);
4608
- const activeInitialTargetOffset = isInitialScrollInProgress ? (_b2 = scrollingTo.targetOffset) != null ? _b2 : scrollingTo.offset : void 0;
4609
- const didOffsetChange = initialScroll.contentOffset === void 0 || Math.abs(initialScroll.contentOffset - offset) > 1;
4610
- const didActiveInitialTargetChange = activeInitialTargetOffset !== void 0 && Math.abs(activeInitialTargetOffset - offset) > 1;
4611
- if (!didOffsetChange && (allowPostFinishRetry || isInitialScrollInProgress && !didActiveInitialTargetChange)) {
4612
- return;
4613
- }
4614
- if (didOffsetChange) {
4615
- const updatedInitialScroll = { ...initialScroll, contentOffset: offset };
4616
- if (!state.initialScrollUsesOffset) {
4617
- state.initialScrollLastTarget = updatedInitialScroll;
4618
- state.initialScrollLastTargetUsesOffset = false;
4619
- if (state.initialScroll) {
4620
- refState.current.initialScroll = updatedInitialScroll;
4621
- state.initialScroll = updatedInitialScroll;
4622
- }
4623
- }
4624
- }
4625
- const hasMeasuredScrollLayout = !!state.lastLayout && state.scrollLength > 0;
4626
- const shouldForceNativeInitialScroll = state.initialScrollUsesOffset && hasMeasuredScrollLayout || allowPostFinishRetry || !!queuedInitialLayout || isInitialScrollInProgress && didOffsetChange;
4627
- performInitialScroll(ctx, {
4628
- forceScroll: shouldForceNativeInitialScroll,
4629
- initialScrollUsesOffset: state.initialScrollUsesOffset,
4630
- resolvedOffset: offset,
4631
- target: initialScroll
4632
- });
4633
- }, []);
4634
- useLayoutEffect(() => {
4635
- var _a4;
4636
- const previousDataLength = state.initialScrollPreviousDataLength;
4637
- state.initialScrollPreviousDataLength = dataProp.length;
4638
- if (previousDataLength !== 0 || dataProp.length === 0 || !state.initialScroll || !state.queuedInitialLayout) {
4639
- return;
4640
- }
4641
- if (initialScrollAtEnd) {
4642
- const lastIndex = Math.max(0, dataProp.length - 1);
4643
- const initialScroll = state.initialScroll;
4644
- const shouldRearm = shouldRearmFinishedEmptyInitialScrollAtEnd(initialScroll);
4645
- if (state.didFinishInitialScroll && !shouldRearm) {
4646
- return;
4647
- }
4648
- if (initialScroll && !state.initialScrollUsesOffset && initialScroll.index === lastIndex && initialScroll.viewPosition === 1 && !shouldRearm) {
4649
- return;
4650
- }
4651
- const updatedInitialScroll = {
4652
- contentOffset: void 0,
4653
- index: lastIndex,
4654
- viewOffset: (_a4 = initialScroll == null ? void 0 : initialScroll.viewOffset) != null ? _a4 : -stylePaddingBottomState,
4655
- viewPosition: 1
4656
- };
4657
- setActiveInitialScrollTarget(updatedInitialScroll, {
4658
- resetDidFinish: shouldRearm,
4659
- syncAnchor: true
4660
- });
4661
- doInitialScroll();
4662
- return;
4663
- }
4664
- if (state.didFinishInitialScroll) {
4665
- return;
4666
- }
4667
- doInitialScroll();
4668
- }, [
4669
- dataProp.length,
4670
- doInitialScroll,
4671
- initialScrollAtEnd,
4672
- shouldRearmFinishedEmptyInitialScrollAtEnd,
4673
- stylePaddingBottomState
4674
- ]);
4675
5345
  useLayoutEffect(() => {
4676
- var _a4;
4677
- if (!initialScrollAtEnd) {
4678
- return;
4679
- }
4680
- const lastIndex = Math.max(0, dataProp.length - 1);
4681
- const initialScroll = state.initialScroll;
4682
- const shouldRearm = shouldRearmFinishedEmptyInitialScrollAtEnd(initialScroll);
4683
- if (state.didFinishInitialScroll && !shouldRearm) {
4684
- return;
4685
- }
4686
- if (shouldRearm) {
4687
- state.didFinishInitialScroll = false;
4688
- }
4689
- if (initialScroll && !state.initialScrollUsesOffset && initialScroll.index === lastIndex && initialScroll.viewPosition === 1 && !shouldRearm) {
4690
- return;
4691
- }
4692
- const updatedInitialScroll = {
4693
- contentOffset: void 0,
4694
- index: lastIndex,
4695
- viewOffset: (_a4 = initialScroll == null ? void 0 : initialScroll.viewOffset) != null ? _a4 : -stylePaddingBottomState,
4696
- viewPosition: 1
4697
- };
4698
- setActiveInitialScrollTarget(updatedInitialScroll, {
4699
- resetDidFinish: shouldRearm,
4700
- syncAnchor: true
5346
+ handleInitialScrollDataChange(ctx, {
5347
+ dataLength: dataProp.length,
5348
+ didDataChange: didDataChangeLocal,
5349
+ initialScrollAtEnd,
5350
+ stylePaddingBottom: stylePaddingBottomState,
5351
+ useBootstrapInitialScroll: usesBootstrapInitialScroll
4701
5352
  });
4702
- doInitialScroll();
4703
- }, [
4704
- dataProp.length,
4705
- doInitialScroll,
4706
- initialScrollAtEnd,
4707
- shouldRearmFinishedEmptyInitialScrollAtEnd,
4708
- stylePaddingBottomState
4709
- ]);
5353
+ }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
4710
5354
  const onLayoutFooter = useCallback(
4711
5355
  (layout) => {
4712
- var _a4;
4713
- if (!initialScrollAtEnd) {
4714
- return;
4715
- }
4716
- const { initialScroll } = state;
4717
- if (!initialScroll) {
5356
+ if (!usesBootstrapInitialScroll) {
4718
5357
  return;
4719
5358
  }
4720
- const lastIndex = Math.max(0, dataProp.length - 1);
4721
- if (initialScroll.index !== lastIndex || initialScroll.viewPosition !== 1) {
5359
+ handleBootstrapInitialScrollFooterLayout(ctx, {
5360
+ dataLength: dataProp.length,
5361
+ footerSize: layout[horizontal ? "width" : "height"],
5362
+ initialScrollAtEnd,
5363
+ stylePaddingBottom: stylePaddingBottomState
5364
+ });
5365
+ },
5366
+ [dataProp.length, initialScrollAtEnd, horizontal, stylePaddingBottomState, usesBootstrapInitialScroll]
5367
+ );
5368
+ const onLayoutChange = useCallback(
5369
+ (layout) => {
5370
+ handleLayout(ctx, layout, setCanRender);
5371
+ if (usesBootstrapInitialScroll) {
4722
5372
  return;
4723
5373
  }
4724
- const footerSize = layout[horizontal ? "width" : "height"];
4725
- const viewOffset = -stylePaddingBottomState - footerSize;
4726
- if (initialScroll.viewOffset !== viewOffset) {
4727
- const previousTargetOffset = (_a4 = initialScroll.contentOffset) != null ? _a4 : resolveInitialScrollOffset(initialScroll);
4728
- const didMoveAwayFromFinishedInitialTarget = state.didFinishInitialScroll && Math.abs(state.scroll - previousTargetOffset) > 1;
4729
- if (didMoveAwayFromFinishedInitialTarget) {
4730
- return;
4731
- }
4732
- const updatedInitialScroll = { ...initialScroll, viewOffset };
4733
- setActiveInitialScrollTarget(updatedInitialScroll, {
4734
- resetDidFinish: true
4735
- });
4736
- doInitialScroll();
4737
- }
5374
+ advanceCurrentInitialScrollSession(ctx);
4738
5375
  },
4739
- [
4740
- dataProp.length,
4741
- doInitialScroll,
4742
- horizontal,
4743
- initialScrollAtEnd,
4744
- resolveInitialScrollOffset,
4745
- stylePaddingBottomState
4746
- ]
5376
+ [usesBootstrapInitialScroll]
4747
5377
  );
4748
- const onLayoutChange = useCallback((layout) => {
4749
- var _a4;
4750
- handleLayout(ctx, layout, setCanRender);
4751
- const SCROLL_LENGTH_RETRY_WINDOW_MS = 600;
4752
- const now = Date.now();
4753
- const didFinishInitialScroll = !!state.didFinishInitialScroll;
4754
- if (didFinishInitialScroll && !state.initialScrollLastDidFinish) {
4755
- state.initialScrollRetryWindowUntil = now + SCROLL_LENGTH_RETRY_WINDOW_MS;
4756
- }
4757
- state.initialScrollLastDidFinish = didFinishInitialScroll;
4758
- const previousScrollLength = state.initialScrollRetryLastLength;
4759
- const currentScrollLength = state.scrollLength;
4760
- const didScrollLengthChange = previousScrollLength === void 0 || Math.abs(currentScrollLength - previousScrollLength) > 1;
4761
- if (didScrollLengthChange) {
4762
- state.initialScrollRetryLastLength = currentScrollLength;
4763
- }
4764
- if (didFinishInitialScroll && didScrollLengthChange && now <= state.initialScrollRetryWindowUntil && !state.initialScrollLastTargetUsesOffset && ((_a4 = state.initialScrollLastTarget) == null ? void 0 : _a4.index) !== void 0) {
4765
- doInitialScroll({ allowPostFinishRetry: true });
4766
- return;
4767
- }
4768
- doInitialScroll();
4769
- }, []);
4770
5378
  const { onLayout } = useOnLayoutSync({
4771
5379
  onLayoutChange,
4772
5380
  onLayoutProp,
@@ -4845,7 +5453,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4845
5453
  }
4846
5454
  useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
4847
5455
  if (Platform2.OS === "web") {
4848
- useEffect(doInitialScroll, []);
5456
+ useEffect(() => {
5457
+ if (usesBootstrapInitialScroll) {
5458
+ return;
5459
+ }
5460
+ advanceCurrentInitialScrollSession(ctx);
5461
+ }, [usesBootstrapInitialScroll]);
4849
5462
  }
4850
5463
  const fns = useMemo(
4851
5464
  () => ({
@@ -4875,6 +5488,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4875
5488
  horizontal,
4876
5489
  initialContentOffset,
4877
5490
  ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
5491
+ ListFooterComponent,
5492
+ ListFooterComponentStyle,
4878
5493
  ListHeaderComponent,
4879
5494
  onLayout,
4880
5495
  onLayoutFooter,
@@ -4882,7 +5497,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4882
5497
  onScroll: onScrollHandler,
4883
5498
  recycleItems,
4884
5499
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2.cloneElement(refreshControlElement, {
4885
- progressViewOffset: ((_g = refreshControlElement.props.progressViewOffset) != null ? _g : 0) + stylePaddingTopState
5500
+ progressViewOffset: ((_f = refreshControlElement.props.progressViewOffset) != null ? _f : 0) + stylePaddingTopState
4886
5501
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React2.createElement(
4887
5502
  RefreshControl,
4888
5503
  {
@@ -4893,14 +5508,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
4893
5508
  ),
4894
5509
  refScrollView: combinedRef,
4895
5510
  renderScrollComponent,
4896
- scrollAdjustHandler: (_h = refState.current) == null ? void 0 : _h.scrollAdjustHandler,
5511
+ scrollAdjustHandler: (_g = refState.current) == null ? void 0 : _g.scrollAdjustHandler,
4897
5512
  scrollEventThrottle: 0,
4898
5513
  snapToIndices,
4899
5514
  stickyHeaderIndices,
4900
5515
  style,
4901
5516
  updateItemSize: fns.updateItemSize,
4902
- useWindowScroll: useWindowScrollResolved,
4903
- waitForInitialLayout
5517
+ useWindowScroll: useWindowScrollResolved
4904
5518
  }
4905
5519
  ), IS_DEV && ENABLE_DEBUG_VIEW);
4906
5520
  });