@legendapp/list 3.0.0-beta.1 → 3.0.0-beta.10

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.js CHANGED
@@ -33,31 +33,65 @@ var View = React3.forwardRef(function View2(props, ref) {
33
33
  });
34
34
  var Text = View;
35
35
 
36
+ // src/state/getContentInsetEnd.ts
37
+ function getContentInsetEnd(state) {
38
+ var _a3;
39
+ const { props } = state;
40
+ const horizontal = props.horizontal;
41
+ let contentInset = props.contentInset;
42
+ if (!contentInset) {
43
+ const animatedInset = (_a3 = props.animatedProps) == null ? void 0 : _a3.contentInset;
44
+ if (animatedInset) {
45
+ if ("get" in animatedInset) {
46
+ contentInset = animatedInset.get();
47
+ } else {
48
+ contentInset = animatedInset;
49
+ }
50
+ }
51
+ }
52
+ return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
53
+ }
54
+
55
+ // src/state/getContentSize.ts
56
+ function getContentSize(ctx) {
57
+ var _a3;
58
+ const { values, state } = ctx;
59
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
60
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
61
+ const headerSize = values.get("headerSize") || 0;
62
+ const footerSize = values.get("footerSize") || 0;
63
+ const contentInsetBottom = getContentInsetEnd(state);
64
+ const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
65
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
66
+ }
67
+
36
68
  // src/platform/Animated.tsx
37
69
  var createAnimatedValue = (value) => value;
38
70
 
39
71
  // src/state/state.tsx
40
72
  var ContextState = React3__namespace.createContext(null);
73
+ var contextNum = 0;
41
74
  function StateProvider({ children }) {
42
75
  const [value] = React3__namespace.useState(() => ({
43
76
  animatedScrollY: createAnimatedValue(0),
44
77
  columnWrapperStyle: void 0,
45
- internalState: void 0,
78
+ contextNum: contextNum++,
46
79
  listeners: /* @__PURE__ */ new Map(),
47
80
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
48
81
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
49
82
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
50
83
  mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
51
84
  mapViewabilityValues: /* @__PURE__ */ new Map(),
85
+ positionListeners: /* @__PURE__ */ new Map(),
86
+ state: void 0,
52
87
  values: /* @__PURE__ */ new Map([
53
88
  ["alignItemsPaddingTop", 0],
54
89
  ["stylePaddingTop", 0],
55
90
  ["headerSize", 0],
56
91
  ["numContainers", 0],
57
- ["activeStickyIndex", void 0],
92
+ ["activeStickyIndex", -1],
58
93
  ["totalSize", 0],
59
- ["scrollAdjustPending", 0],
60
- ["scrollingTo", void 0]
94
+ ["scrollAdjustPending", 0]
61
95
  ]),
62
96
  viewRefs: /* @__PURE__ */ new Map()
63
97
  }));
@@ -125,15 +159,24 @@ function set$(ctx, signalName, value) {
125
159
  }
126
160
  }
127
161
  }
128
- function getContentSize(ctx) {
129
- var _a3, _b;
130
- const { values, internalState } = ctx;
131
- const stylePaddingTop = values.get("stylePaddingTop") || 0;
132
- const stylePaddingBottom = (internalState == null ? void 0 : internalState.props.stylePaddingBottom) || 0;
133
- const headerSize = values.get("headerSize") || 0;
134
- const footerSize = values.get("footerSize") || 0;
135
- const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
136
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom;
162
+ function listenPosition$(ctx, key, cb) {
163
+ const { positionListeners } = ctx;
164
+ let setListeners = positionListeners.get(key);
165
+ if (!setListeners) {
166
+ setListeners = /* @__PURE__ */ new Set();
167
+ positionListeners.set(key, setListeners);
168
+ }
169
+ setListeners.add(cb);
170
+ return () => setListeners.delete(cb);
171
+ }
172
+ function notifyPosition$(ctx, key, value) {
173
+ const { positionListeners } = ctx;
174
+ const setListeners = positionListeners.get(key);
175
+ if (setListeners) {
176
+ for (const listener of setListeners) {
177
+ listener(value);
178
+ }
179
+ }
137
180
  }
138
181
  function useArr$(signalNames) {
139
182
  const ctx = React3__namespace.useContext(ContextState);
@@ -255,12 +298,12 @@ function findContainerId(ctx, key) {
255
298
  }
256
299
 
257
300
  // src/components/PositionView.tsx
258
- var PositionViewState = typedMemo(function PositionView({
301
+ var PositionViewState = typedMemo(function PositionViewState2({
259
302
  id,
260
303
  horizontal,
261
304
  style,
262
305
  refView,
263
- ...rest
306
+ ...props
264
307
  }) {
265
308
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
266
309
  const base = {
@@ -268,7 +311,8 @@ var PositionViewState = typedMemo(function PositionView({
268
311
  };
269
312
  const composed = isArray(style) ? Object.assign({}, ...style) : style;
270
313
  const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
271
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
314
+ const { animatedScrollY, stickyOffset, onLayout, ...webProps } = props;
315
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, ...webProps, style: combinedStyle });
272
316
  });
273
317
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
274
318
  id,
@@ -313,17 +357,12 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
313
357
  }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
314
358
  return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
315
359
  });
316
- var PositionView2 = PositionViewState;
360
+ var PositionView = PositionViewState;
317
361
 
318
362
  // src/constants-platform.ts
319
363
  var IsNewArchitecture = true;
320
- var symbolFirst = Symbol();
321
364
  function useInit(cb) {
322
- const refValue = React3.useRef(symbolFirst);
323
- if (refValue.current === symbolFirst) {
324
- refValue.current = cb();
325
- }
326
- return refValue.current;
365
+ React3.useState(() => cb());
327
366
  }
328
367
 
329
368
  // src/state/ContextContainer.ts
@@ -471,10 +510,9 @@ function createResizeObserver(element, callback) {
471
510
  }
472
511
  callbacks.add(callback);
473
512
  return () => {
474
- const callbacks2 = callbackMap.get(element);
475
- if (callbacks2) {
476
- callbacks2.delete(callback);
477
- if (callbacks2.size === 0) {
513
+ if (callbacks) {
514
+ callbacks.delete(callback);
515
+ if (callbacks.size === 0) {
478
516
  callbackMap.delete(element);
479
517
  observer.unobserve(element);
480
518
  }
@@ -509,10 +547,10 @@ function useOnLayoutSync({
509
547
  return createResizeObserver(element, (entry) => {
510
548
  var _a4;
511
549
  const target = entry.target instanceof HTMLElement ? entry.target : void 0;
512
- const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
513
- if (rect2.width !== prevRect.width || rect2.height !== prevRect.height) {
514
- prevRect = rect2;
515
- emit(toLayout(rect2), false);
550
+ const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
551
+ if (rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height) {
552
+ prevRect = rectObserved;
553
+ emit(toLayout(rectObserved), false);
516
554
  }
517
555
  });
518
556
  }, deps || []);
@@ -640,7 +678,7 @@ var Container = typedMemo(function Container2({
640
678
  },
641
679
  [itemKey, layoutRenderCount]
642
680
  );
643
- const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
681
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView;
644
682
  return /* @__PURE__ */ React3__namespace.createElement(
645
683
  PositionComponent,
646
684
  {
@@ -833,7 +871,8 @@ var Containers = typedMemo(function Containers2({
833
871
  return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
834
872
  });
835
873
  function DevNumbers() {
836
- return IS_DEV && React3__namespace.memo(function DevNumbers2() {
874
+ return IS_DEV && // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
875
+ React3__namespace.memo(function DevNumbers2() {
837
876
  return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
838
877
  "div",
839
878
  {
@@ -881,7 +920,6 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
881
920
  }, ref) {
882
921
  const scrollRef = React3.useRef(null);
883
922
  const contentRef = React3.useRef(null);
884
- const momentumTimeout = React3.useRef(null);
885
923
  React3.useImperativeHandle(ref, () => {
886
924
  const api = {
887
925
  getBoundingClientRect: () => {
@@ -947,16 +985,6 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
947
985
  }
948
986
  };
949
987
  onScroll2(scrollEvent);
950
- if (onMomentumScrollEnd) {
951
- if (momentumTimeout.current != null) clearTimeout(momentumTimeout.current);
952
- momentumTimeout.current = setTimeout(() => {
953
- onMomentumScrollEnd({
954
- nativeEvent: {
955
- contentOffset: scrollEvent.nativeEvent.contentOffset
956
- }
957
- });
958
- }, 100);
959
- }
960
988
  },
961
989
  [onScroll2, onMomentumScrollEnd]
962
990
  );
@@ -1018,7 +1046,8 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
1018
1046
  minWidth: horizontal ? "100%" : void 0,
1019
1047
  ...StyleSheet.flatten(contentContainerStyle)
1020
1048
  };
1021
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
1049
+ const { contentInset, scrollEventThrottle, ScrollComponent, ...webProps } = props;
1050
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, ...webProps, style: scrollViewStyle }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
1022
1051
  });
1023
1052
  function Padding() {
1024
1053
  const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
@@ -1059,7 +1088,7 @@ function ScrollAdjust() {
1059
1088
  const scrollAdjust = peek$(ctx, "scrollAdjust");
1060
1089
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1061
1090
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1062
- const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
1091
+ const scrollView = (_a3 = ctx.state) == null ? void 0 : _a3.refScroller.current;
1063
1092
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
1064
1093
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1065
1094
  if (scrollDelta !== 0) {
@@ -1067,16 +1096,16 @@ function ScrollAdjust() {
1067
1096
  const prevScroll = el.scrollTop;
1068
1097
  const nextScroll = prevScroll + scrollDelta;
1069
1098
  const totalSize = el.scrollHeight;
1070
- if (scrollDelta > 0 && !ctx.internalState.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1099
+ if (scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1071
1100
  const child = el.firstElementChild;
1072
1101
  const prevPaddingBottom = child.style.paddingBottom;
1073
1102
  const pad = (nextScroll + el.clientHeight - totalSize) * 2;
1074
1103
  child.style.paddingBottom = `${pad}px`;
1075
1104
  void el.offsetHeight;
1076
1105
  scrollView.scrollBy(0, scrollDelta);
1077
- setTimeout(() => {
1106
+ requestAnimationFrame(() => {
1078
1107
  child.style.paddingBottom = prevPaddingBottom;
1079
- }, 100);
1108
+ });
1080
1109
  } else {
1081
1110
  scrollView.scrollBy(0, scrollDelta);
1082
1111
  }
@@ -1086,7 +1115,7 @@ function ScrollAdjust() {
1086
1115
  }
1087
1116
  lastScrollOffsetRef.current = scrollOffset;
1088
1117
  }
1089
- }, []);
1118
+ }, [ctx]);
1090
1119
  useValueListener$("scrollAdjust", callback);
1091
1120
  useValueListener$("scrollAdjustUserOffset", callback);
1092
1121
  return null;
@@ -1144,13 +1173,6 @@ var ListComponent = typedMemo(function ListComponent2({
1144
1173
  () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1145
1174
  [renderScrollComponent]
1146
1175
  ) : ListComponentScrollView;
1147
- React3__namespace.useEffect(() => {
1148
- if (canRender) {
1149
- setTimeout(() => {
1150
- scrollAdjustHandler.setMounted();
1151
- }, 0);
1152
- }
1153
- }, [canRender]);
1154
1176
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1155
1177
  return /* @__PURE__ */ React3__namespace.createElement(
1156
1178
  SnapOrScroll,
@@ -1214,10 +1236,11 @@ function getId(state, index) {
1214
1236
  }
1215
1237
 
1216
1238
  // src/core/calculateOffsetForIndex.ts
1217
- function calculateOffsetForIndex(ctx, state, index) {
1239
+ function calculateOffsetForIndex(ctx, index) {
1240
+ const state = ctx.state;
1218
1241
  let position = 0;
1219
1242
  if (index !== void 0) {
1220
- position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
1243
+ position = state.positions.get(getId(state, index)) || 0;
1221
1244
  const paddingTop = peek$(ctx, "stylePaddingTop");
1222
1245
  if (paddingTop) {
1223
1246
  position += paddingTop;
@@ -1231,7 +1254,8 @@ function calculateOffsetForIndex(ctx, state, index) {
1231
1254
  }
1232
1255
 
1233
1256
  // src/utils/setPaddingTop.ts
1234
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1257
+ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1258
+ const state = ctx.state;
1235
1259
  if (stylePaddingTop !== void 0) {
1236
1260
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1237
1261
  if (stylePaddingTop < prevStylePaddingTop) {
@@ -1250,7 +1274,8 @@ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1250
1274
  }
1251
1275
 
1252
1276
  // src/utils/updateAlignItemsPaddingTop.ts
1253
- function updateAlignItemsPaddingTop(ctx, state) {
1277
+ function updateAlignItemsPaddingTop(ctx) {
1278
+ const state = ctx.state;
1254
1279
  const {
1255
1280
  scrollLength,
1256
1281
  props: { alignItemsAtEnd, data }
@@ -1261,12 +1286,13 @@ function updateAlignItemsPaddingTop(ctx, state) {
1261
1286
  const contentSize = getContentSize(ctx);
1262
1287
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1263
1288
  }
1264
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
1289
+ setPaddingTop(ctx, { alignItemsPaddingTop });
1265
1290
  }
1266
1291
  }
1267
1292
 
1268
1293
  // src/core/addTotalSize.ts
1269
- function addTotalSize(ctx, state, key, add) {
1294
+ function addTotalSize(ctx, key, add) {
1295
+ const state = ctx.state;
1270
1296
  const { alignItemsAtEnd } = state.props;
1271
1297
  const prevTotalSize = state.totalSize;
1272
1298
  let totalSize = state.totalSize;
@@ -1285,31 +1311,34 @@ function addTotalSize(ctx, state, key, add) {
1285
1311
  state.totalSize = totalSize;
1286
1312
  set$(ctx, "totalSize", totalSize);
1287
1313
  if (alignItemsAtEnd) {
1288
- updateAlignItemsPaddingTop(ctx, state);
1314
+ updateAlignItemsPaddingTop(ctx);
1289
1315
  }
1290
1316
  }
1291
1317
  }
1292
1318
  }
1293
1319
 
1294
1320
  // src/core/setSize.ts
1295
- function setSize(ctx, state, itemKey, size) {
1321
+ function setSize(ctx, itemKey, size) {
1322
+ const state = ctx.state;
1296
1323
  const { sizes } = state;
1297
1324
  const previousSize = sizes.get(itemKey);
1298
1325
  const diff = previousSize !== void 0 ? size - previousSize : size;
1299
1326
  if (diff !== 0) {
1300
- addTotalSize(ctx, state, itemKey, diff);
1327
+ addTotalSize(ctx, itemKey, diff);
1301
1328
  }
1302
1329
  sizes.set(itemKey, size);
1303
1330
  }
1304
1331
 
1305
1332
  // src/utils/getItemSize.ts
1306
- function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1333
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1307
1334
  var _a3, _b;
1335
+ const state = ctx.state;
1308
1336
  const {
1309
1337
  sizesKnown,
1310
1338
  sizes,
1311
1339
  averageSizes,
1312
- props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1340
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1341
+ scrollingTo
1313
1342
  } = state;
1314
1343
  const sizeKnown = sizesKnown.get(key);
1315
1344
  if (sizeKnown !== void 0) {
@@ -1317,7 +1346,6 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1317
1346
  }
1318
1347
  let size;
1319
1348
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1320
- const scrollingTo = peek$(ctx, "scrollingTo");
1321
1349
  if (preferCachedSize) {
1322
1350
  const cachedSize = sizes.get(key);
1323
1351
  if (cachedSize !== void 0) {
@@ -1345,81 +1373,169 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1345
1373
  if (size === void 0) {
1346
1374
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1347
1375
  }
1348
- setSize(ctx, state, key, size);
1376
+ setSize(ctx, key, size);
1349
1377
  return size;
1350
1378
  }
1351
1379
 
1352
1380
  // src/core/calculateOffsetWithOffsetPosition.ts
1353
- function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1381
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1382
+ const state = ctx.state;
1354
1383
  const { index, viewOffset, viewPosition } = params;
1355
1384
  let offset = offsetParam;
1356
1385
  if (viewOffset) {
1357
1386
  offset -= viewOffset;
1358
1387
  }
1359
1388
  if (viewPosition !== void 0 && index !== void 0) {
1360
- offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1389
+ const itemSize = getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1390
+ const trailingInset = getContentInsetEnd(state);
1391
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1361
1392
  }
1362
1393
  return offset;
1363
1394
  }
1364
1395
 
1396
+ // src/core/clampScrollOffset.ts
1397
+ function clampScrollOffset(ctx, offset) {
1398
+ const state = ctx.state;
1399
+ const contentSize = getContentSize(ctx);
1400
+ let clampedOffset = offset;
1401
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength)) {
1402
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1403
+ clampedOffset = Math.min(offset, maxOffset);
1404
+ }
1405
+ clampedOffset = Math.max(0, clampedOffset);
1406
+ return clampedOffset;
1407
+ }
1408
+
1409
+ // src/utils/setInitialRenderState.ts
1410
+ function setInitialRenderState(ctx, {
1411
+ didLayout,
1412
+ didInitialScroll
1413
+ }) {
1414
+ const { state } = ctx;
1415
+ if (didLayout) {
1416
+ state.didContainersLayout = true;
1417
+ }
1418
+ if (didInitialScroll) {
1419
+ state.didFinishInitialScroll = true;
1420
+ }
1421
+ if (state.didContainersLayout && state.didFinishInitialScroll) {
1422
+ set$(ctx, "readyToRender", true);
1423
+ }
1424
+ }
1425
+
1365
1426
  // src/core/finishScrollTo.ts
1366
- function finishScrollTo(ctx, state) {
1427
+ function finishScrollTo(ctx) {
1367
1428
  var _a3, _b;
1368
- if (state) {
1429
+ const state = ctx.state;
1430
+ if (state == null ? void 0 : state.scrollingTo) {
1369
1431
  state.scrollHistory.length = 0;
1370
1432
  state.initialScroll = void 0;
1371
1433
  state.initialAnchor = void 0;
1372
- set$(ctx, "scrollingTo", void 0);
1434
+ state.scrollingTo = void 0;
1373
1435
  if (state.pendingTotalSize !== void 0) {
1374
- addTotalSize(ctx, state, null, state.pendingTotalSize);
1436
+ addTotalSize(ctx, null, state.pendingTotalSize);
1375
1437
  }
1376
1438
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1377
1439
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1378
1440
  }
1441
+ {
1442
+ state.scrollAdjustHandler.commitPendingAdjust();
1443
+ }
1444
+ setInitialRenderState(ctx, { didInitialScroll: true });
1445
+ }
1446
+ }
1447
+
1448
+ // src/core/doScrollTo.ts
1449
+ var SCROLL_END_IDLE_MS = 80;
1450
+ var SCROLL_END_MAX_MS = 1500;
1451
+ var SMOOTH_SCROLL_DURATION_MS = 320;
1452
+ function doScrollTo(ctx, params) {
1453
+ const state = ctx.state;
1454
+ const { animated, horizontal, offset } = params;
1455
+ const scroller = state.refScroller.current;
1456
+ const node = typeof (scroller == null ? void 0 : scroller.getScrollableNode) === "function" ? scroller.getScrollableNode() : scroller;
1457
+ if (node) {
1458
+ const left = horizontal ? offset : 0;
1459
+ const top = horizontal ? 0 : offset;
1460
+ node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
1461
+ if (animated) {
1462
+ listenForScrollEnd(ctx, node);
1463
+ } else {
1464
+ state.scroll = offset;
1465
+ setTimeout(() => {
1466
+ finishScrollTo(ctx);
1467
+ }, 100);
1468
+ }
1469
+ }
1470
+ }
1471
+ function listenForScrollEnd(ctx, node) {
1472
+ const supportsScrollEnd = "onscrollend" in node;
1473
+ let idleTimeout;
1474
+ let maxTimeout;
1475
+ let settled = false;
1476
+ const targetToken = ctx.state.scrollingTo;
1477
+ const finish = () => {
1478
+ if (settled) return;
1479
+ settled = true;
1480
+ cleanup();
1481
+ if (targetToken === ctx.state.scrollingTo) {
1482
+ finishScrollTo(ctx);
1483
+ }
1484
+ };
1485
+ const onScroll2 = () => {
1486
+ if (idleTimeout) {
1487
+ clearTimeout(idleTimeout);
1488
+ }
1489
+ idleTimeout = setTimeout(finish, SCROLL_END_IDLE_MS);
1490
+ };
1491
+ const cleanup = () => {
1492
+ if (supportsScrollEnd) {
1493
+ node.removeEventListener("scrollend", finish);
1494
+ } else {
1495
+ node.removeEventListener("scroll", onScroll2);
1496
+ }
1497
+ if (idleTimeout) {
1498
+ clearTimeout(idleTimeout);
1499
+ }
1500
+ if (maxTimeout) {
1501
+ clearTimeout(maxTimeout);
1502
+ }
1503
+ };
1504
+ if (supportsScrollEnd) {
1505
+ node.addEventListener("scrollend", finish, { once: true });
1506
+ } else {
1507
+ node.addEventListener("scroll", onScroll2);
1508
+ idleTimeout = setTimeout(finish, SMOOTH_SCROLL_DURATION_MS);
1509
+ maxTimeout = setTimeout(finish, SCROLL_END_MAX_MS);
1379
1510
  }
1511
+ return cleanup;
1380
1512
  }
1381
1513
 
1382
1514
  // src/core/scrollTo.ts
1383
- function scrollTo(ctx, state, params) {
1384
- var _a3;
1385
- const { noScrollingTo, ...scrollTarget } = params;
1515
+ function scrollTo(ctx, params) {
1516
+ const state = ctx.state;
1517
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1386
1518
  const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1387
1519
  const {
1388
- refScroller,
1389
1520
  props: { horizontal }
1390
1521
  } = state;
1391
- let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1392
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1393
- const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1394
- offset = Math.min(offset, maxOffset);
1522
+ if (state.animFrameCheckFinishedScroll) {
1523
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1524
+ }
1525
+ if (state.timeoutCheckFinishedScrollFallback) {
1526
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1395
1527
  }
1528
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1529
+ offset = clampScrollOffset(ctx, offset);
1396
1530
  state.scrollHistory.length = 0;
1397
1531
  if (!noScrollingTo) {
1398
- set$(ctx, "scrollingTo", scrollTarget);
1532
+ state.scrollingTo = scrollTarget;
1399
1533
  }
1400
1534
  state.scrollPending = offset;
1401
- if (!isInitialScroll || Platform.OS === "android") {
1402
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1403
- animated: !!animated,
1404
- x: horizontal ? offset : 0,
1405
- y: horizontal ? 0 : offset
1406
- });
1407
- }
1408
- if (!animated) {
1535
+ if (forceScroll || !isInitialScroll || Platform.OS === "android") {
1536
+ doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
1537
+ } else {
1409
1538
  state.scroll = offset;
1410
- {
1411
- const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1412
- if (value && peek$(ctx, "scrollingTo")) {
1413
- finishScrollTo(ctx, state);
1414
- unlisten();
1415
- }
1416
- });
1417
- }
1418
- if (isInitialScroll) {
1419
- setTimeout(() => {
1420
- state.initialScroll = void 0;
1421
- }, 500);
1422
- }
1423
1539
  }
1424
1540
  }
1425
1541
 
@@ -1428,6 +1544,12 @@ var HYSTERESIS_MULTIPLIER = 1.3;
1428
1544
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1429
1545
  const absDistance = Math.abs(distance);
1430
1546
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1547
+ if (wasReached === null) {
1548
+ if (!within && distance >= 0) {
1549
+ return false;
1550
+ }
1551
+ return null;
1552
+ }
1431
1553
  const updateSnapshot = () => {
1432
1554
  setSnapshot == null ? void 0 : setSnapshot({
1433
1555
  atThreshold,
@@ -1460,8 +1582,9 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1460
1582
  };
1461
1583
 
1462
1584
  // src/utils/checkAtBottom.ts
1463
- function checkAtBottom(ctx, state) {
1585
+ function checkAtBottom(ctx) {
1464
1586
  var _a3;
1587
+ const state = ctx.state;
1465
1588
  if (!state) {
1466
1589
  return;
1467
1590
  }
@@ -1534,15 +1657,15 @@ function checkAtTop(state) {
1534
1657
  }
1535
1658
 
1536
1659
  // src/core/updateScroll.ts
1537
- function updateScroll(ctx, state, newScroll, forceUpdate) {
1660
+ function updateScroll(ctx, newScroll, forceUpdate) {
1538
1661
  var _a3;
1539
- const scrollingTo = peek$(ctx, "scrollingTo");
1662
+ const state = ctx.state;
1663
+ const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1540
1664
  state.hasScrolled = true;
1541
1665
  state.lastBatchingAction = Date.now();
1542
1666
  const currentTime = Date.now();
1543
- const adjust = state.scrollAdjustHandler.getAdjust();
1544
- const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1545
- const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1667
+ const adjust = scrollAdjustHandler.getAdjust();
1668
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1546
1669
  if (adjustChanged) {
1547
1670
  state.scrollHistory.length = 0;
1548
1671
  }
@@ -1567,17 +1690,21 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1567
1690
  return;
1568
1691
  }
1569
1692
  }
1570
- if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1693
+ const lastCalculated = state.scrollLastCalculate;
1694
+ const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1695
+ if (shouldUpdate) {
1696
+ state.scrollLastCalculate = state.scroll;
1571
1697
  state.ignoreScrollFromMVCPIgnored = false;
1572
1698
  (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1573
- checkAtBottom(ctx, state);
1699
+ checkAtBottom(ctx);
1574
1700
  checkAtTop(state);
1575
1701
  state.dataChangeNeedsScrollUpdate = false;
1576
1702
  }
1577
1703
  }
1578
1704
 
1579
1705
  // src/utils/requestAdjust.ts
1580
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
1706
+ function requestAdjust(ctx, positionDiff, dataChanged) {
1707
+ const state = ctx.state;
1581
1708
  if (Math.abs(positionDiff) > 0.1) {
1582
1709
  const doit = () => {
1583
1710
  {
@@ -1589,8 +1716,8 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1589
1716
  };
1590
1717
  state.scroll += positionDiff;
1591
1718
  state.scrollForNextCalculateItemsInView = void 0;
1592
- const didLayout = peek$(ctx, "containersDidLayout");
1593
- if (didLayout) {
1719
+ const readyToRender = peek$(ctx, "readyToRender");
1720
+ if (readyToRender) {
1594
1721
  doit();
1595
1722
  } else {
1596
1723
  state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
@@ -1599,73 +1726,23 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1599
1726
  }
1600
1727
  }
1601
1728
 
1602
- // src/core/ensureInitialAnchor.ts
1603
- var INITIAL_ANCHOR_TOLERANCE = 0.5;
1604
- var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1605
- var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1606
- function ensureInitialAnchor(ctx, state) {
1607
- var _a3, _b, _c, _d, _e;
1608
- const anchor = state.initialAnchor;
1609
- const item = state.props.data[anchor.index];
1610
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1611
- if (!containersDidLayout) {
1612
- return;
1613
- }
1614
- const id = getId(state, anchor.index);
1615
- if (state.positions.get(id) === void 0) {
1616
- return;
1617
- }
1618
- const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1619
- if (size === void 0) {
1620
- return;
1621
- }
1622
- const availableSpace = Math.max(0, state.scrollLength - size);
1623
- const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1624
- const contentSize = getContentSize(ctx);
1625
- const maxOffset = Math.max(0, contentSize - state.scrollLength);
1626
- const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1627
- const delta = clampedDesiredOffset - state.scroll;
1628
- if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1629
- const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1630
- if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1631
- state.initialAnchor = void 0;
1632
- } else {
1633
- anchor.settledTicks = settledTicks;
1634
- }
1635
- return;
1636
- }
1637
- if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1638
- state.initialAnchor = void 0;
1639
- return;
1640
- }
1641
- const lastDelta = anchor.lastDelta;
1642
- if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1643
- state.initialAnchor = void 0;
1644
- return;
1645
- }
1646
- Object.assign(anchor, {
1647
- attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1648
- lastDelta: delta,
1649
- settledTicks: 0
1650
- });
1651
- requestAdjust(ctx, state, delta);
1652
- }
1653
-
1654
1729
  // src/core/mvcp.ts
1655
- function prepareMVCP(ctx, state, dataChanged) {
1730
+ function prepareMVCP(ctx, dataChanged) {
1731
+ const state = ctx.state;
1656
1732
  const { idsInView, positions, props } = state;
1657
1733
  const { maintainVisibleContentPosition } = props;
1658
- const scrollingTo = peek$(ctx, "scrollingTo");
1734
+ const scrollingTo = state.scrollingTo;
1659
1735
  let prevPosition;
1660
1736
  let targetId;
1661
1737
  const idsInViewWithPositions = [];
1662
1738
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1739
+ const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
1663
1740
  const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1664
1741
  const indexByKey = state.indexByKey;
1665
1742
  if (shouldMVCP) {
1666
1743
  if (scrollTarget !== void 0) {
1667
1744
  targetId = getId(state, scrollTarget);
1668
- } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1745
+ } else if (idsInView.length > 0 && state.didContainersLayout) {
1669
1746
  if (dataChanged) {
1670
1747
  for (let i = 0; i < idsInView.length; i++) {
1671
1748
  const id = idsInView[i];
@@ -1682,7 +1759,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1682
1759
  prevPosition = positions.get(targetId);
1683
1760
  }
1684
1761
  return () => {
1685
- let positionDiff;
1762
+ let positionDiff = 0;
1686
1763
  if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1687
1764
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1688
1765
  const { id, position } = idsInViewWithPositions[i];
@@ -1708,16 +1785,28 @@ function prepareMVCP(ctx, state, dataChanged) {
1708
1785
  positionDiff = diff;
1709
1786
  }
1710
1787
  }
1711
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1712
- requestAdjust(ctx, state, positionDiff);
1788
+ if (scrollingToViewPosition && scrollingToViewPosition > 0) {
1789
+ const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
1790
+ const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
1791
+ if (newSize !== void 0 && prevSize !== void 0 && newSize !== (scrollingTo == null ? void 0 : scrollingTo.itemSize)) {
1792
+ const diff = newSize - prevSize;
1793
+ if (diff !== 0) {
1794
+ positionDiff += (newSize - prevSize) * scrollingToViewPosition;
1795
+ scrollingTo.itemSize = newSize;
1796
+ }
1797
+ }
1798
+ }
1799
+ if (Math.abs(positionDiff) > 0.1) {
1800
+ requestAdjust(ctx, positionDiff);
1713
1801
  }
1714
1802
  };
1715
1803
  }
1716
1804
  }
1717
1805
 
1718
1806
  // src/core/prepareColumnStartState.ts
1719
- function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1807
+ function prepareColumnStartState(ctx, startIndex, useAverageSize) {
1720
1808
  var _a3;
1809
+ const state = ctx.state;
1721
1810
  const numColumns = peek$(ctx, "numColumns");
1722
1811
  let rowStartIndex = startIndex;
1723
1812
  const columnAtStart = state.columns.get(state.idCache[startIndex]);
@@ -1732,7 +1821,7 @@ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1732
1821
  const prevId = state.idCache[prevIndex];
1733
1822
  const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1734
1823
  const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1735
- const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1824
+ const prevRowHeight = calculateRowMaxSize(ctx, prevRowStart, prevIndex, useAverageSize);
1736
1825
  currentRowTop = prevPosition + prevRowHeight;
1737
1826
  }
1738
1827
  return {
@@ -1755,7 +1844,8 @@ function findRowStartIndex(state, numColumns, index) {
1755
1844
  }
1756
1845
  return rowStart;
1757
1846
  }
1758
- function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1847
+ function calculateRowMaxSize(ctx, startIndex, endIndex, useAverageSize) {
1848
+ const state = ctx.state;
1759
1849
  if (endIndex < startIndex) {
1760
1850
  return 0;
1761
1851
  }
@@ -1769,7 +1859,7 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1769
1859
  continue;
1770
1860
  }
1771
1861
  const id = state.idCache[i];
1772
- const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1862
+ const size = getItemSize(ctx, id, i, data[i], useAverageSize);
1773
1863
  if (size > maxSize) {
1774
1864
  maxSize = size;
1775
1865
  }
@@ -1778,22 +1868,23 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1778
1868
  }
1779
1869
 
1780
1870
  // src/core/updateTotalSize.ts
1781
- function updateTotalSize(ctx, state) {
1871
+ function updateTotalSize(ctx) {
1872
+ const state = ctx.state;
1782
1873
  const {
1783
1874
  positions,
1784
1875
  props: { data }
1785
1876
  } = state;
1786
1877
  if (data.length === 0) {
1787
- addTotalSize(ctx, state, null, 0);
1878
+ addTotalSize(ctx, null, 0);
1788
1879
  } else {
1789
1880
  const lastId = getId(state, data.length - 1);
1790
1881
  if (lastId !== void 0) {
1791
1882
  const lastPosition = positions.get(lastId);
1792
1883
  if (lastPosition !== void 0) {
1793
- const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1884
+ const lastSize = getItemSize(ctx, lastId, data.length - 1, data[data.length - 1]);
1794
1885
  if (lastSize !== void 0) {
1795
1886
  const totalSize = lastPosition + lastSize;
1796
- addTotalSize(ctx, state, null, totalSize);
1887
+ addTotalSize(ctx, null, totalSize);
1797
1888
  }
1798
1889
  }
1799
1890
  }
@@ -1839,7 +1930,8 @@ var getScrollVelocity = (state) => {
1839
1930
  };
1840
1931
 
1841
1932
  // src/utils/updateSnapToOffsets.ts
1842
- function updateSnapToOffsets(ctx, state) {
1933
+ function updateSnapToOffsets(ctx) {
1934
+ const state = ctx.state;
1843
1935
  const {
1844
1936
  positions,
1845
1937
  props: { snapToIndices }
@@ -1854,30 +1946,30 @@ function updateSnapToOffsets(ctx, state) {
1854
1946
  }
1855
1947
 
1856
1948
  // src/core/updateItemPositions.ts
1857
- function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1949
+ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1858
1950
  doMVCP: false,
1859
1951
  forceFullUpdate: false,
1860
1952
  scrollBottomBuffered: -1,
1861
1953
  startIndex: 0
1862
1954
  }) {
1863
1955
  var _a3, _b, _c, _d, _e;
1956
+ const state = ctx.state;
1864
1957
  const {
1865
1958
  columns,
1866
1959
  indexByKey,
1867
1960
  positions,
1868
1961
  idCache,
1869
1962
  sizesKnown,
1870
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1963
+ props: { data, getEstimatedItemSize, snapToIndices },
1964
+ scrollingTo
1871
1965
  } = state;
1872
- const data = state.props.data;
1873
1966
  const dataLength = data.length;
1874
1967
  const numColumns = peek$(ctx, "numColumns");
1875
- const scrollingTo = peek$(ctx, "scrollingTo");
1876
1968
  const hasColumns = numColumns > 1;
1877
1969
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1878
1970
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1879
1971
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1880
- const useAverageSize = enableAverages && !getEstimatedItemSize;
1972
+ const useAverageSize = !getEstimatedItemSize;
1881
1973
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
1882
1974
  let currentRowTop = 0;
1883
1975
  let column = 1;
@@ -1886,7 +1978,6 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1886
1978
  if (hasColumns) {
1887
1979
  const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1888
1980
  ctx,
1889
- state,
1890
1981
  startIndex,
1891
1982
  useAverageSize
1892
1983
  );
@@ -1896,7 +1987,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1896
1987
  const prevIndex = startIndex - 1;
1897
1988
  const prevId = getId(state, prevIndex);
1898
1989
  const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1899
- const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1990
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1900
1991
  currentRowTop = prevPosition + prevSize;
1901
1992
  }
1902
1993
  }
@@ -1913,7 +2004,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1913
2004
  breakAt = i + itemsPerRow + 10;
1914
2005
  }
1915
2006
  const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1916
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
2007
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
1917
2008
  if (IS_DEV && needsIndexByKey) {
1918
2009
  if (indexByKeyForChecking.has(id)) {
1919
2010
  console.error(
@@ -1922,7 +2013,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1922
2013
  }
1923
2014
  indexByKeyForChecking.set(id, i);
1924
2015
  }
1925
- positions.set(id, currentRowTop);
2016
+ if (currentRowTop !== positions.get(id)) {
2017
+ positions.set(id, currentRowTop);
2018
+ notifyPosition$(ctx, id, currentRowTop);
2019
+ }
1926
2020
  if (needsIndexByKey) {
1927
2021
  indexByKey.set(id, i);
1928
2022
  }
@@ -1942,10 +2036,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1942
2036
  }
1943
2037
  }
1944
2038
  if (!didBreakEarly) {
1945
- updateTotalSize(ctx, state);
2039
+ updateTotalSize(ctx);
1946
2040
  }
1947
2041
  if (snapToIndices) {
1948
- updateSnapToOffsets(ctx, state);
2042
+ updateSnapToOffsets(ctx);
1949
2043
  }
1950
2044
  }
1951
2045
 
@@ -2023,7 +2117,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
2023
2117
  if (previousViewableItems) {
2024
2118
  for (const viewToken of previousViewableItems) {
2025
2119
  const containerId = findContainerId(ctx, viewToken.key);
2026
- if (!isViewable(
2120
+ if (!checkIsViewable(
2027
2121
  state,
2028
2122
  ctx,
2029
2123
  viewabilityConfig,
@@ -2044,7 +2138,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
2044
2138
  if (item) {
2045
2139
  const key = getId(state, i);
2046
2140
  const containerId = findContainerId(ctx, key);
2047
- if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
2141
+ if (checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
2048
2142
  const viewToken = {
2049
2143
  containerId,
2050
2144
  index: i,
@@ -2104,11 +2198,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
2104
2198
  const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
2105
2199
  const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
2106
2200
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
2107
- const isViewable2 = percent >= viewablePercentThreshold;
2201
+ const isViewable = percent >= viewablePercentThreshold;
2108
2202
  const value = {
2109
2203
  containerId,
2110
2204
  index,
2111
- isViewable: isViewable2,
2205
+ isViewable,
2112
2206
  item,
2113
2207
  key,
2114
2208
  percentOfScroller,
@@ -2127,8 +2221,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
2127
2221
  }
2128
2222
  return value;
2129
2223
  }
2130
- function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2131
- const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2224
+ function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2225
+ let value = ctx.mapViewabilityAmountValues.get(containerId);
2226
+ if (!value || value.key !== key) {
2227
+ value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2228
+ }
2132
2229
  return value.isViewable;
2133
2230
  }
2134
2231
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
@@ -2156,8 +2253,9 @@ function checkAllSizesKnown(state) {
2156
2253
  }
2157
2254
 
2158
2255
  // src/utils/findAvailableContainers.ts
2159
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2256
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2160
2257
  const numContainers = peek$(ctx, "numContainers");
2258
+ const state = ctx.state;
2161
2259
  const { stickyContainerPool, containerItemTypes } = state;
2162
2260
  const result = [];
2163
2261
  const availableContainers = [];
@@ -2201,14 +2299,14 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2201
2299
  continue;
2202
2300
  }
2203
2301
  const key = peek$(ctx, `containerItemKey${u}`);
2204
- let isOk = key === void 0;
2205
- if (!isOk && pendingRemovalSet.has(u)) {
2206
- pendingRemovalSet.delete(u);
2207
- pendingRemovalChanged = true;
2208
- const requiredType = neededTypes[typeIndex];
2209
- isOk = canReuseContainer(u, requiredType);
2210
- }
2211
- if (isOk) {
2302
+ const requiredType = neededTypes[typeIndex];
2303
+ const isPending = key !== void 0 && pendingRemovalSet.has(u);
2304
+ const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
2305
+ if (canUse) {
2306
+ if (isPending) {
2307
+ pendingRemovalSet.delete(u);
2308
+ pendingRemovalChanged = true;
2309
+ }
2212
2310
  result.push(u);
2213
2311
  if (requiredItemTypes) {
2214
2312
  typeIndex++;
@@ -2277,21 +2375,26 @@ function comparatorByDistance(a, b) {
2277
2375
  }
2278
2376
 
2279
2377
  // src/core/scrollToIndex.ts
2280
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
2281
- if (index >= state.props.data.length) {
2282
- index = state.props.data.length - 1;
2378
+ function scrollToIndex(ctx, { index, viewOffset = 0, animated = true, viewPosition }) {
2379
+ const state = ctx.state;
2380
+ const { data } = state.props;
2381
+ if (index >= data.length) {
2382
+ index = data.length - 1;
2283
2383
  } else if (index < 0) {
2284
2384
  index = 0;
2285
2385
  }
2286
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
2287
- const isLast = index === state.props.data.length - 1;
2386
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2387
+ const isLast = index === data.length - 1;
2288
2388
  if (isLast && viewPosition === void 0) {
2289
2389
  viewPosition = 1;
2290
2390
  }
2291
2391
  state.scrollForNextCalculateItemsInView = void 0;
2292
- scrollTo(ctx, state, {
2392
+ const targetId = getId(state, index);
2393
+ const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2394
+ scrollTo(ctx, {
2293
2395
  animated,
2294
2396
  index,
2397
+ itemSize,
2295
2398
  offset: firstIndexOffset,
2296
2399
  viewOffset,
2297
2400
  viewPosition: viewPosition != null ? viewPosition : 0
@@ -2299,16 +2402,17 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
2299
2402
  }
2300
2403
 
2301
2404
  // src/utils/setDidLayout.ts
2302
- function setDidLayout(ctx, state) {
2405
+ function setDidLayout(ctx) {
2406
+ const state = ctx.state;
2303
2407
  const {
2304
2408
  loadStartTime,
2305
2409
  initialScroll,
2306
2410
  props: { onLoad }
2307
2411
  } = state;
2308
2412
  state.queuedInitialLayout = true;
2309
- checkAtBottom(ctx, state);
2413
+ checkAtBottom(ctx);
2310
2414
  const setIt = () => {
2311
- set$(ctx, "containersDidLayout", true);
2415
+ setInitialRenderState(ctx, { didLayout: true });
2312
2416
  if (onLoad) {
2313
2417
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2314
2418
  }
@@ -2333,15 +2437,17 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
2333
2437
  }
2334
2438
  return -1;
2335
2439
  }
2336
- function getActiveStickyIndices(ctx, state, stickyHeaderIndices) {
2440
+ function getActiveStickyIndices(ctx, stickyHeaderIndices) {
2441
+ const state = ctx.state;
2337
2442
  return new Set(
2338
2443
  Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
2339
2444
  );
2340
2445
  }
2341
- function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2446
+ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2342
2447
  var _a3;
2343
- const activeIndices = getActiveStickyIndices(ctx, state, stickyHeaderIndices);
2344
- state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
2448
+ const state = ctx.state;
2449
+ const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
2450
+ set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
2345
2451
  for (let offset = 0; offset <= 1; offset++) {
2346
2452
  const idx = currentStickyIdx - offset;
2347
2453
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
@@ -2352,8 +2458,9 @@ function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, cu
2352
2458
  }
2353
2459
  }
2354
2460
  }
2355
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2461
+ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2356
2462
  var _a3, _b, _c;
2463
+ const state = ctx.state;
2357
2464
  for (const containerIndex of state.stickyContainerPool) {
2358
2465
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2359
2466
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
@@ -2377,7 +2484,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2377
2484
  const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2378
2485
  if (currentId) {
2379
2486
  const currentPos = state.positions.get(currentId);
2380
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
2487
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
2381
2488
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2382
2489
  }
2383
2490
  }
@@ -2386,7 +2493,8 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2386
2493
  }
2387
2494
  }
2388
2495
  }
2389
- function calculateItemsInView(ctx, state, params = {}) {
2496
+ function calculateItemsInView(ctx, params = {}) {
2497
+ const state = ctx.state;
2390
2498
  reactDom.unstable_batchedUpdates(() => {
2391
2499
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2392
2500
  const {
@@ -2410,9 +2518,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2410
2518
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2411
2519
  const prevNumContainers = peek$(ctx, "numContainers");
2412
2520
  if (!data || scrollLength === 0 || !prevNumContainers) {
2413
- if (state.initialAnchor) {
2414
- ensureInitialAnchor(ctx, state);
2415
- }
2416
2521
  return;
2417
2522
  }
2418
2523
  const totalSize = getContentSize(ctx);
@@ -2426,15 +2531,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2426
2531
  if (!queuedInitialLayout && initialScroll) {
2427
2532
  const updatedOffset = calculateOffsetWithOffsetPosition(
2428
2533
  ctx,
2429
- state,
2430
- calculateOffsetForIndex(ctx, state, initialScroll.index),
2534
+ calculateOffsetForIndex(ctx, initialScroll.index),
2431
2535
  initialScroll
2432
2536
  );
2433
2537
  scrollState = updatedOffset;
2434
2538
  }
2435
2539
  const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2436
2540
  const scrollAdjustPad = scrollAdjustPending - topPad;
2437
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
2541
+ let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2438
2542
  if (scroll + scrollLength > totalSize) {
2439
2543
  scroll = Math.max(0, totalSize - scrollLength);
2440
2544
  }
@@ -2442,11 +2546,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2442
2546
  set$(ctx, "debugRawScroll", scrollState);
2443
2547
  set$(ctx, "debugComputedScroll", scroll);
2444
2548
  }
2445
- const previousStickyIndex = state.activeStickyIndex;
2549
+ const previousStickyIndex = peek$(ctx, "activeStickyIndex");
2446
2550
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2447
- const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2448
- state.activeStickyIndex = nextActiveStickyIndex;
2449
- set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2551
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
2552
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
2553
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2554
+ }
2450
2555
  let scrollBufferTop = scrollBuffer;
2451
2556
  let scrollBufferBottom = scrollBuffer;
2452
2557
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2459,23 +2564,20 @@ function calculateItemsInView(ctx, state, params = {}) {
2459
2564
  const scrollTopBuffered = scroll - scrollBufferTop;
2460
2565
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2461
2566
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2462
- if (!dataChanged && scrollForNextCalculateItemsInView) {
2567
+ if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2463
2568
  const { top, bottom } = scrollForNextCalculateItemsInView;
2464
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2465
- if (state.initialAnchor) {
2466
- ensureInitialAnchor(ctx, state);
2467
- }
2569
+ if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2468
2570
  return;
2469
2571
  }
2470
2572
  }
2471
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2573
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
2472
2574
  if (dataChanged) {
2473
2575
  indexByKey.clear();
2474
2576
  idCache.length = 0;
2475
2577
  positions.clear();
2476
2578
  }
2477
- const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2478
- updateItemPositions(ctx, state, dataChanged, {
2579
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2580
+ updateItemPositions(ctx, dataChanged, {
2479
2581
  doMVCP,
2480
2582
  forceFullUpdate: !!forceFullItemPositions,
2481
2583
  scrollBottomBuffered,
@@ -2494,9 +2596,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2494
2596
  for (let i = loopStart; i >= 0; i--) {
2495
2597
  const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2496
2598
  const top = positions.get(id);
2497
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2599
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, id, i, data[i]);
2498
2600
  const bottom = top + size;
2499
- if (bottom > scroll - scrollBuffer) {
2601
+ if (bottom > scroll - scrollBufferTop) {
2500
2602
  loopStart = i;
2501
2603
  } else {
2502
2604
  break;
@@ -2521,7 +2623,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2521
2623
  const dataLength = data.length;
2522
2624
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2523
2625
  const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2524
- const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2626
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, id, i, data[i]);
2525
2627
  const top = positions.get(id);
2526
2628
  if (!foundEnd) {
2527
2629
  if (startNoBuffer === null && top + size > scroll) {
@@ -2533,7 +2635,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2533
2635
  if (startBuffered === null && top + size > scrollTopBuffered) {
2534
2636
  startBuffered = i;
2535
2637
  startBufferedId = id;
2536
- nextTop = top;
2638
+ if (scrollTopBuffered < 0) {
2639
+ nextTop = null;
2640
+ } else {
2641
+ nextTop = top;
2642
+ }
2537
2643
  }
2538
2644
  if (startNoBuffer !== null) {
2539
2645
  if (top <= scrollBottom) {
@@ -2541,7 +2647,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2541
2647
  }
2542
2648
  if (top <= scrollBottomBuffered) {
2543
2649
  endBuffered = i;
2544
- nextBottom = top + size;
2650
+ if (scrollBottomBuffered > totalSize) {
2651
+ nextBottom = null;
2652
+ } else {
2653
+ nextBottom = top + size;
2654
+ }
2545
2655
  } else {
2546
2656
  foundEnd = true;
2547
2657
  }
@@ -2568,7 +2678,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2568
2678
  top: nextTop
2569
2679
  } : void 0;
2570
2680
  }
2571
- const numContainers = peek$(ctx, "numContainers");
2681
+ let numContainers = prevNumContainers;
2572
2682
  const pendingRemoval = [];
2573
2683
  if (dataChanged) {
2574
2684
  for (let i = 0; i < numContainers; i++) {
@@ -2579,7 +2689,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2579
2689
  }
2580
2690
  }
2581
2691
  if (startBuffered !== null && endBuffered !== null) {
2582
- let numContainers2 = prevNumContainers;
2583
2692
  const needNewContainers = [];
2584
2693
  for (let i = startBuffered; i <= endBuffered; i++) {
2585
2694
  const id = (_h = idCache[i]) != null ? _h : getId(state, i);
@@ -2590,7 +2699,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2590
2699
  if (stickyIndicesArr.length > 0) {
2591
2700
  handleStickyActivation(
2592
2701
  ctx,
2593
- state,
2594
2702
  stickyIndicesSet,
2595
2703
  stickyIndicesArr,
2596
2704
  currentStickyIdx,
@@ -2598,9 +2706,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2598
2706
  startBuffered,
2599
2707
  endBuffered
2600
2708
  );
2601
- } else {
2602
- state.activeStickyIndex = void 0;
2603
- set$(ctx, "activeStickyIndex", void 0);
2709
+ } else if (previousStickyIndex !== -1) {
2710
+ set$(ctx, "activeStickyIndex", -1);
2604
2711
  }
2605
2712
  if (needNewContainers.length > 0) {
2606
2713
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2609,7 +2716,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2609
2716
  }) : void 0;
2610
2717
  const availableContainers = findAvailableContainers(
2611
2718
  ctx,
2612
- state,
2613
2719
  needNewContainers.length,
2614
2720
  startBuffered,
2615
2721
  endBuffered,
@@ -2631,29 +2737,30 @@ function calculateItemsInView(ctx, state, params = {}) {
2631
2737
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2632
2738
  }
2633
2739
  containerItemKeys.add(id);
2740
+ const containerSticky = `containerSticky${containerIndex}`;
2634
2741
  if (stickyIndicesSet.has(i)) {
2635
- set$(ctx, `containerSticky${containerIndex}`, true);
2742
+ set$(ctx, containerSticky, true);
2636
2743
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2637
2744
  set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2638
2745
  state.stickyContainerPool.add(containerIndex);
2639
- } else {
2640
- set$(ctx, `containerSticky${containerIndex}`, false);
2746
+ } else if (peek$(ctx, containerSticky)) {
2747
+ set$(ctx, containerSticky, false);
2641
2748
  state.stickyContainerPool.delete(containerIndex);
2642
2749
  }
2643
- if (containerIndex >= numContainers2) {
2644
- numContainers2 = containerIndex + 1;
2750
+ if (containerIndex >= numContainers) {
2751
+ numContainers = containerIndex + 1;
2645
2752
  }
2646
2753
  }
2647
- if (numContainers2 !== prevNumContainers) {
2648
- set$(ctx, "numContainers", numContainers2);
2649
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
2650
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
2754
+ if (numContainers !== prevNumContainers) {
2755
+ set$(ctx, "numContainers", numContainers);
2756
+ if (numContainers > peek$(ctx, "numContainersPooled")) {
2757
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
2651
2758
  }
2652
2759
  }
2653
2760
  }
2654
2761
  }
2655
2762
  if (stickyIndicesArr.length > 0) {
2656
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2763
+ handleStickyRecycling(ctx, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2657
2764
  }
2658
2765
  let didChangePositions = false;
2659
2766
  for (let i = 0; i < numContainers; i++) {
@@ -2705,7 +2812,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2705
2812
  }
2706
2813
  if (!queuedInitialLayout && endBuffered !== null) {
2707
2814
  if (checkAllSizesKnown(state)) {
2708
- setDidLayout(ctx, state);
2815
+ setDidLayout(ctx);
2709
2816
  }
2710
2817
  }
2711
2818
  if (viewabilityConfigCallbackPairs) {
@@ -2718,9 +2825,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2718
2825
  }
2719
2826
  }
2720
2827
  });
2721
- if (state.initialAnchor) {
2722
- ensureInitialAnchor(ctx, state);
2723
- }
2724
2828
  }
2725
2829
 
2726
2830
  // src/core/checkActualChange.ts
@@ -2743,20 +2847,69 @@ function checkActualChange(state, dataProp, previousData) {
2743
2847
  return false;
2744
2848
  }
2745
2849
 
2850
+ // src/core/checkFinishedScroll.ts
2851
+ function checkFinishedScroll(ctx) {
2852
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
2853
+ }
2854
+ function checkFinishedScrollFrame(ctx) {
2855
+ const scrollingTo = ctx.state.scrollingTo;
2856
+ if (scrollingTo) {
2857
+ const { state } = ctx;
2858
+ state.animFrameCheckFinishedScroll = void 0;
2859
+ const scroll = state.scroll;
2860
+ const adjust = state.scrollAdjustHandler.getAdjust();
2861
+ const clampedTargetOffset = clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0));
2862
+ const maxOffset = clampScrollOffset(ctx, scroll);
2863
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
2864
+ const diff2 = Math.abs(diff1 - adjust);
2865
+ const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
2866
+ if (isNotOverscrolled && (diff1 < 1 || diff2 < 1)) {
2867
+ finishScrollTo(ctx);
2868
+ }
2869
+ }
2870
+ }
2871
+ function checkFinishedScrollFallback(ctx) {
2872
+ const state = ctx.state;
2873
+ const scrollingTo = state.scrollingTo;
2874
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || !state.didContainersLayout;
2875
+ state.timeoutCheckFinishedScrollFallback = setTimeout(
2876
+ () => {
2877
+ let numChecks = 0;
2878
+ const checkHasScrolled = () => {
2879
+ state.timeoutCheckFinishedScrollFallback = void 0;
2880
+ const isStillScrollingTo = state.scrollingTo;
2881
+ if (isStillScrollingTo) {
2882
+ numChecks++;
2883
+ if (state.hasScrolled || numChecks > 5) {
2884
+ finishScrollTo(ctx);
2885
+ } else {
2886
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
2887
+ }
2888
+ }
2889
+ };
2890
+ checkHasScrolled();
2891
+ },
2892
+ slowTimeout ? 500 : 100
2893
+ );
2894
+ }
2895
+
2746
2896
  // src/core/doMaintainScrollAtEnd.ts
2747
- function doMaintainScrollAtEnd(ctx, state, animated) {
2897
+ function doMaintainScrollAtEnd(ctx, animated) {
2898
+ const state = ctx.state;
2748
2899
  const {
2900
+ didContainersLayout,
2901
+ isAtEnd,
2749
2902
  refScroller,
2750
2903
  props: { maintainScrollAtEnd }
2751
2904
  } = state;
2752
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2905
+ if (isAtEnd && maintainScrollAtEnd && didContainersLayout) {
2753
2906
  const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2754
2907
  if (paddingTop > 0) {
2755
2908
  state.scroll = 0;
2756
2909
  }
2757
2910
  requestAnimationFrame(() => {
2758
2911
  var _a3;
2759
- if (state == null ? void 0 : state.isAtEnd) {
2912
+ if (state.isAtEnd) {
2760
2913
  state.maintainingScrollAtEnd = true;
2761
2914
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2762
2915
  animated
@@ -2827,28 +2980,30 @@ function updateAveragesOnDataChange(state, oldData, newData) {
2827
2980
  }
2828
2981
 
2829
2982
  // src/core/checkResetContainers.ts
2830
- function checkResetContainers(ctx, state, dataProp) {
2983
+ function checkResetContainers(ctx, dataProp) {
2984
+ const state = ctx.state;
2831
2985
  const { previousData } = state;
2832
2986
  if (previousData) {
2833
2987
  updateAveragesOnDataChange(state, previousData, dataProp);
2834
2988
  }
2835
2989
  const { maintainScrollAtEnd } = state.props;
2836
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2990
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2837
2991
  const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2838
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2992
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, false);
2839
2993
  if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2840
2994
  state.isEndReached = false;
2841
2995
  }
2842
2996
  if (!didMaintainScrollAtEnd) {
2843
2997
  checkAtTop(state);
2844
- checkAtBottom(ctx, state);
2998
+ checkAtBottom(ctx);
2845
2999
  }
2846
3000
  delete state.previousData;
2847
3001
  }
2848
3002
 
2849
3003
  // src/core/doInitialAllocateContainers.ts
2850
- function doInitialAllocateContainers(ctx, state) {
3004
+ function doInitialAllocateContainers(ctx) {
2851
3005
  var _a3, _b, _c;
3006
+ const state = ctx.state;
2852
3007
  const {
2853
3008
  scrollLength,
2854
3009
  props: {
@@ -2886,10 +3041,10 @@ function doInitialAllocateContainers(ctx, state) {
2886
3041
  if (state.lastLayout) {
2887
3042
  if (state.initialScroll) {
2888
3043
  requestAnimationFrame(() => {
2889
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
3044
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2890
3045
  });
2891
3046
  } else {
2892
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
3047
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2893
3048
  }
2894
3049
  }
2895
3050
  return true;
@@ -2897,7 +3052,8 @@ function doInitialAllocateContainers(ctx, state) {
2897
3052
  }
2898
3053
 
2899
3054
  // src/core/handleLayout.ts
2900
- function handleLayout(ctx, state, layout, setCanRender) {
3055
+ function handleLayout(ctx, layout, setCanRender) {
3056
+ const state = ctx.state;
2901
3057
  const { maintainScrollAtEnd } = state.props;
2902
3058
  const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2903
3059
  const previousLength = state.scrollLength;
@@ -2913,19 +3069,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2913
3069
  state.lastBatchingAction = Date.now();
2914
3070
  state.scrollForNextCalculateItemsInView = void 0;
2915
3071
  if (scrollLength > 0) {
2916
- doInitialAllocateContainers(ctx, state);
3072
+ doInitialAllocateContainers(ctx);
2917
3073
  }
2918
3074
  if (needsCalculate) {
2919
- calculateItemsInView(ctx, state, { doMVCP: true });
3075
+ calculateItemsInView(ctx, { doMVCP: true });
2920
3076
  }
2921
3077
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
2922
3078
  set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2923
3079
  }
2924
3080
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2925
- doMaintainScrollAtEnd(ctx, state, false);
3081
+ doMaintainScrollAtEnd(ctx, false);
2926
3082
  }
2927
- updateAlignItemsPaddingTop(ctx, state);
2928
- checkAtBottom(ctx, state);
3083
+ updateAlignItemsPaddingTop(ctx);
3084
+ checkAtBottom(ctx);
2929
3085
  checkAtTop(state);
2930
3086
  if (state) {
2931
3087
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
@@ -2941,8 +3097,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2941
3097
  }
2942
3098
 
2943
3099
  // src/core/onScroll.ts
2944
- function onScroll(ctx, state, event) {
3100
+ function onScroll(ctx, event) {
2945
3101
  var _a3, _b, _c;
3102
+ const state = ctx.state;
2946
3103
  const {
2947
3104
  scrollProcessingEnabled,
2948
3105
  props: { onScroll: onScrollProp }
@@ -2953,9 +3110,23 @@ function onScroll(ctx, state, event) {
2953
3110
  if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2954
3111
  return;
2955
3112
  }
2956
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3113
+ let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2957
3114
  state.scrollPending = newScroll;
2958
- updateScroll(ctx, state, newScroll);
3115
+ if (state.scrollingTo) {
3116
+ const maxOffset = clampScrollOffset(ctx, newScroll);
3117
+ if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
3118
+ newScroll = maxOffset;
3119
+ scrollTo(ctx, {
3120
+ forceScroll: true,
3121
+ isInitialScroll: true,
3122
+ noScrollingTo: true,
3123
+ offset: newScroll
3124
+ });
3125
+ return;
3126
+ }
3127
+ }
3128
+ updateScroll(ctx, newScroll);
3129
+ checkFinishedScroll(ctx);
2959
3130
  onScrollProp == null ? void 0 : onScrollProp(event);
2960
3131
  }
2961
3132
 
@@ -2964,51 +3135,47 @@ var ScrollAdjustHandler = class {
2964
3135
  constructor(ctx) {
2965
3136
  this.appliedAdjust = 0;
2966
3137
  this.pendingAdjust = 0;
2967
- this.mounted = false;
2968
- this.context = ctx;
2969
- {
2970
- const commitPendingAdjust = () => {
2971
- const state = this.context.internalState;
2972
- const pending = this.pendingAdjust;
2973
- if (pending !== 0) {
2974
- this.pendingAdjust = 0;
2975
- this.appliedAdjust += pending;
2976
- state.scroll += pending;
2977
- state.scrollForNextCalculateItemsInView = void 0;
2978
- set$(this.context, "scrollAdjustPending", 0);
2979
- set$(this.context, "scrollAdjust", this.appliedAdjust);
2980
- calculateItemsInView(this.context, this.context.internalState);
2981
- }
2982
- };
2983
- listen$(this.context, "scrollingTo", (value) => {
2984
- if (value === void 0) {
2985
- commitPendingAdjust();
2986
- }
2987
- });
2988
- }
3138
+ this.ctx = ctx;
2989
3139
  }
2990
3140
  requestAdjust(add) {
2991
- const scrollingTo = peek$(this.context, "scrollingTo");
3141
+ const scrollingTo = this.ctx.state.scrollingTo;
2992
3142
  if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2993
3143
  this.pendingAdjust += add;
2994
- set$(this.context, "scrollAdjustPending", this.pendingAdjust);
3144
+ set$(this.ctx, "scrollAdjustPending", this.pendingAdjust);
2995
3145
  } else {
2996
3146
  this.appliedAdjust += add;
2997
- set$(this.context, "scrollAdjust", this.appliedAdjust);
3147
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3148
+ }
3149
+ if (this.ctx.state.scrollingTo) {
3150
+ checkFinishedScroll(this.ctx);
2998
3151
  }
2999
- }
3000
- setMounted() {
3001
- this.mounted = true;
3002
3152
  }
3003
3153
  getAdjust() {
3004
3154
  return this.appliedAdjust;
3005
3155
  }
3156
+ commitPendingAdjust() {
3157
+ {
3158
+ const state = this.ctx.state;
3159
+ const pending = this.pendingAdjust;
3160
+ if (pending !== 0) {
3161
+ this.pendingAdjust = 0;
3162
+ this.appliedAdjust += pending;
3163
+ state.scroll += pending;
3164
+ state.scrollForNextCalculateItemsInView = void 0;
3165
+ set$(this.ctx, "scrollAdjustPending", 0);
3166
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3167
+ calculateItemsInView(this.ctx);
3168
+ }
3169
+ }
3170
+ }
3006
3171
  };
3007
3172
 
3008
3173
  // src/core/updateItemSize.ts
3009
- function updateItemSize(ctx, state, itemKey, sizeObj) {
3174
+ function updateItemSize(ctx, itemKey, sizeObj) {
3010
3175
  var _a3;
3176
+ const state = ctx.state;
3011
3177
  const {
3178
+ didContainersLayout,
3012
3179
  sizesKnown,
3013
3180
  props: {
3014
3181
  getFixedItemSize,
@@ -3036,13 +3203,12 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
3036
3203
  return;
3037
3204
  }
3038
3205
  }
3039
- const containersDidLayout = peek$(ctx, "containersDidLayout");
3040
- let needsRecalculate = !containersDidLayout;
3206
+ let needsRecalculate = !didContainersLayout;
3041
3207
  let shouldMaintainScrollAtEnd = false;
3042
3208
  let minIndexSizeChanged;
3043
3209
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
3044
3210
  const prevSizeKnown = state.sizesKnown.get(itemKey);
3045
- const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
3211
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj);
3046
3212
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
3047
3213
  if (diff !== 0) {
3048
3214
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -3091,22 +3257,22 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
3091
3257
  if (!cur || maxOtherAxisSize > cur) {
3092
3258
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
3093
3259
  }
3094
- if (containersDidLayout || checkAllSizesKnown(state)) {
3260
+ if (didContainersLayout || checkAllSizesKnown(state)) {
3095
3261
  if (needsRecalculate) {
3096
3262
  state.scrollForNextCalculateItemsInView = void 0;
3097
- calculateItemsInView(ctx, state, { doMVCP: true });
3263
+ calculateItemsInView(ctx, { doMVCP: true });
3098
3264
  }
3099
3265
  if (shouldMaintainScrollAtEnd) {
3100
3266
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
3101
- doMaintainScrollAtEnd(ctx, state, false);
3267
+ doMaintainScrollAtEnd(ctx, false);
3102
3268
  }
3103
3269
  }
3104
3270
  }
3105
3271
  }
3106
- function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3272
+ function updateOneItemSize(ctx, itemKey, sizeObj) {
3107
3273
  var _a3;
3274
+ const state = ctx.state;
3108
3275
  const {
3109
- sizes,
3110
3276
  indexByKey,
3111
3277
  sizesKnown,
3112
3278
  averageSizes,
@@ -3114,9 +3280,10 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3114
3280
  } = state;
3115
3281
  if (!data) return 0;
3116
3282
  const index = indexByKey.get(itemKey);
3117
- const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
3283
+ const prevSize = getItemSize(ctx, itemKey, index, data[index]);
3118
3284
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
3119
3285
  const size = Math.round(rawSize) ;
3286
+ const prevSizeKnown = sizesKnown.get(itemKey);
3120
3287
  sizesKnown.set(itemKey, size);
3121
3288
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
3122
3289
  const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
@@ -3124,11 +3291,15 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3124
3291
  if (!averages) {
3125
3292
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
3126
3293
  }
3127
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3128
- averages.num++;
3294
+ if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3295
+ averages.avg += (size - prevSizeKnown) / averages.num;
3296
+ } else {
3297
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3298
+ averages.num++;
3299
+ }
3129
3300
  }
3130
3301
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
3131
- setSize(ctx, state, itemKey, size);
3302
+ setSize(ctx, itemKey, size);
3132
3303
  return size - prevSize;
3133
3304
  }
3134
3305
  return 0;
@@ -3175,14 +3346,15 @@ function createColumnWrapperStyle(contentContainerStyle) {
3175
3346
  }
3176
3347
 
3177
3348
  // src/utils/createImperativeHandle.ts
3178
- function createImperativeHandle(ctx, state) {
3349
+ function createImperativeHandle(ctx) {
3350
+ const state = ctx.state;
3179
3351
  const scrollIndexIntoView = (options) => {
3180
3352
  if (state) {
3181
3353
  const { index, ...rest } = options;
3182
3354
  const { startNoBuffer, endNoBuffer } = state;
3183
3355
  if (index < startNoBuffer || index > endNoBuffer) {
3184
3356
  const viewPosition = index < startNoBuffer ? 0 : 1;
3185
- scrollToIndex(ctx, state, {
3357
+ scrollToIndex(ctx, {
3186
3358
  ...rest,
3187
3359
  index,
3188
3360
  viewPosition
@@ -3197,7 +3369,7 @@ function createImperativeHandle(ctx, state) {
3197
3369
  getScrollableNode: () => refScroller.current.getScrollableNode(),
3198
3370
  getScrollResponder: () => refScroller.current.getScrollResponder(),
3199
3371
  getState: () => ({
3200
- activeStickyIndex: state.activeStickyIndex,
3372
+ activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3201
3373
  contentLength: state.totalSize,
3202
3374
  data: state.props.data,
3203
3375
  elementAtIndex: (index) => {
@@ -3208,6 +3380,8 @@ function createImperativeHandle(ctx, state) {
3208
3380
  endBuffered: state.endBuffered,
3209
3381
  isAtEnd: state.isAtEnd,
3210
3382
  isAtStart: state.isAtStart,
3383
+ listen: (signalName, cb) => listen$(ctx, signalName, cb),
3384
+ listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
3211
3385
  positionAtIndex: (index) => state.positions.get(getId(state, index)),
3212
3386
  positions: state.positions,
3213
3387
  scroll: state.scroll,
@@ -3232,23 +3406,23 @@ function createImperativeHandle(ctx, state) {
3232
3406
  if (index !== -1) {
3233
3407
  const paddingBottom = stylePaddingBottom || 0;
3234
3408
  const footerSize = peek$(ctx, "footerSize") || 0;
3235
- scrollToIndex(ctx, state, {
3409
+ scrollToIndex(ctx, {
3410
+ ...options,
3236
3411
  index,
3237
3412
  viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3238
- viewPosition: 1,
3239
- ...options
3413
+ viewPosition: 1
3240
3414
  });
3241
3415
  }
3242
3416
  },
3243
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3417
+ scrollToIndex: (params) => scrollToIndex(ctx, params),
3244
3418
  scrollToItem: ({ item, ...props }) => {
3245
3419
  const data = state.props.data;
3246
3420
  const index = data.indexOf(item);
3247
3421
  if (index !== -1) {
3248
- scrollToIndex(ctx, state, { index, ...props });
3422
+ scrollToIndex(ctx, { index, ...props });
3249
3423
  }
3250
3424
  },
3251
- scrollToOffset: (params) => scrollTo(ctx, state, params),
3425
+ scrollToOffset: (params) => scrollTo(ctx, params),
3252
3426
  setScrollProcessingEnabled: (enabled) => {
3253
3427
  state.scrollProcessingEnabled = enabled;
3254
3428
  },
@@ -3258,8 +3432,9 @@ function createImperativeHandle(ctx, state) {
3258
3432
  }
3259
3433
  };
3260
3434
  }
3261
- function getRenderedItem(ctx, state, key) {
3435
+ function getRenderedItem(ctx, key) {
3262
3436
  var _a3;
3437
+ const state = ctx.state;
3263
3438
  if (!state) {
3264
3439
  return null;
3265
3440
  }
@@ -3336,11 +3511,13 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3336
3511
  var DEFAULT_DRAW_DISTANCE = 250;
3337
3512
  var DEFAULT_ITEM_SIZE = 100;
3338
3513
  var LegendList = typedMemo(
3514
+ // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
3339
3515
  typedForwardRef(function LegendList2(props, forwardedRef) {
3340
3516
  const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
3341
3517
  const isChildrenMode = children !== void 0 && dataProp === void 0;
3342
3518
  const processedProps = isChildrenMode ? {
3343
3519
  ...restProps,
3520
+ childrenMode: true,
3344
3521
  data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
3345
3522
  renderItem: ({ item }) => item
3346
3523
  } : {
@@ -3357,10 +3534,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3357
3534
  alignItemsAtEnd = false,
3358
3535
  columnWrapperStyle,
3359
3536
  contentContainerStyle: contentContainerStyleProp,
3537
+ contentInset,
3360
3538
  data: dataProp = [],
3361
3539
  dataVersion,
3362
3540
  drawDistance = 250,
3363
- enableAverages = true,
3364
3541
  estimatedItemSize: estimatedItemSizeProp,
3365
3542
  estimatedListSize,
3366
3543
  extraData,
@@ -3402,6 +3579,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3402
3579
  snapToIndices,
3403
3580
  stickyHeaderIndices: stickyHeaderIndicesProp,
3404
3581
  stickyIndices: stickyIndicesDeprecated,
3582
+ // TODOV3: Remove from v3 release
3405
3583
  style: styleProp,
3406
3584
  suggestEstimatedItemSize,
3407
3585
  viewabilityConfig,
@@ -3409,6 +3587,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3409
3587
  waitForInitialLayout = true,
3410
3588
  ...rest
3411
3589
  } = props;
3590
+ const animatedPropsInternal = props.animatedPropsInternal;
3591
+ const { childrenMode } = rest;
3412
3592
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3413
3593
  const style = { ...StyleSheet.flatten(styleProp) };
3414
3594
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
@@ -3432,10 +3612,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3432
3612
  }
3433
3613
  const refState = React3.useRef();
3434
3614
  if (!refState.current) {
3435
- if (!ctx.internalState) {
3615
+ if (!ctx.state) {
3436
3616
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
3437
- ctx.internalState = {
3438
- activeStickyIndex: void 0,
3617
+ ctx.state = {
3618
+ activeStickyIndex: -1,
3439
3619
  averageSizes: {},
3440
3620
  columns: /* @__PURE__ */ new Map(),
3441
3621
  containerItemKeys: /* @__PURE__ */ new Set(),
@@ -3461,9 +3641,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3461
3641
  initialScroll: initialScrollProp,
3462
3642
  isAtEnd: false,
3463
3643
  isAtStart: false,
3464
- isEndReached: false,
3644
+ isEndReached: null,
3465
3645
  isFirst: true,
3466
- isStartReached: false,
3646
+ isStartReached: null,
3467
3647
  lastBatchingAction: Date.now(),
3468
3648
  lastLayout: void 0,
3469
3649
  loadStartTime: Date.now(),
@@ -3495,12 +3675,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3495
3675
  totalSize: 0,
3496
3676
  viewabilityConfigCallbackPairs: void 0
3497
3677
  };
3498
- const internalState = ctx.internalState;
3499
- internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3678
+ const internalState = ctx.state;
3679
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
3500
3680
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3501
3681
  set$(ctx, "extraData", extraData);
3502
3682
  }
3503
- refState.current = ctx.internalState;
3683
+ refState.current = ctx.state;
3504
3684
  }
3505
3685
  const state = refState.current;
3506
3686
  const isFirstLocal = state.isFirst;
@@ -3514,9 +3694,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3514
3694
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
3515
3695
  state.props = {
3516
3696
  alignItemsAtEnd,
3697
+ animatedProps: animatedPropsInternal,
3698
+ contentInset,
3517
3699
  data: dataProp,
3518
3700
  dataVersion,
3519
- enableAverages,
3520
3701
  estimatedItemSize,
3521
3702
  getEstimatedItemSize,
3522
3703
  getFixedItemSize,
@@ -3559,62 +3740,52 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3559
3740
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3560
3741
  set$(ctx, "numColumns", numColumnsProp);
3561
3742
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
3562
- setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
3743
+ setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
3563
3744
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3564
3745
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3565
3746
  if (paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3566
3747
  if (state.scroll < 0) {
3567
3748
  paddingDiff += state.scroll;
3568
3749
  }
3569
- requestAdjust(ctx, state, paddingDiff);
3750
+ requestAdjust(ctx, paddingDiff);
3570
3751
  }
3571
3752
  };
3572
3753
  if (isFirstLocal) {
3573
3754
  initializeStateVars();
3574
3755
  updateItemPositions(
3575
3756
  ctx,
3576
- state,
3577
3757
  /*dataChanged*/
3578
3758
  true
3579
3759
  );
3580
3760
  }
3581
3761
  const initialContentOffset = React3.useMemo(() => {
3582
- var _a4, _b2;
3583
- const { initialScroll } = refState.current;
3584
- if (!initialScroll) {
3762
+ let value;
3763
+ const { initialScroll, initialAnchor } = refState.current;
3764
+ if (initialScroll) {
3765
+ if (initialScroll.contentOffset !== void 0) {
3766
+ value = initialScroll.contentOffset;
3767
+ } else {
3768
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
3769
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
3770
+ const clampedOffset = clampScrollOffset(ctx, resolvedOffset);
3771
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3772
+ refState.current.initialScroll = updatedInitialScroll;
3773
+ state.initialScroll = updatedInitialScroll;
3774
+ value = clampedOffset;
3775
+ }
3776
+ } else {
3585
3777
  refState.current.initialAnchor = void 0;
3586
- return 0;
3587
- }
3588
- if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3589
- refState.current.initialAnchor = {
3590
- attempts: 0,
3591
- index: initialScroll.index,
3592
- settledTicks: 0,
3593
- viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3594
- viewPosition: initialScroll.viewPosition
3595
- };
3778
+ value = 0;
3596
3779
  }
3597
- if (initialScroll.contentOffset !== void 0) {
3598
- return initialScroll.contentOffset;
3599
- }
3600
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3601
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3602
- let clampedOffset = resolvedOffset;
3603
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3604
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3605
- clampedOffset = Math.min(clampedOffset, maxOffset);
3606
- }
3607
- clampedOffset = Math.max(0, clampedOffset);
3608
- const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3609
- refState.current.initialScroll = updatedInitialScroll;
3610
- state.initialScroll = updatedInitialScroll;
3611
- refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3612
- return clampedOffset;
3780
+ if (!value) {
3781
+ state.didFinishInitialScroll = true;
3782
+ }
3783
+ return value;
3613
3784
  }, [renderNum]);
3614
3785
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3615
3786
  refState.current.lastBatchingAction = Date.now();
3616
3787
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3617
- IS_DEV && warnDevOnce(
3788
+ IS_DEV && !childrenMode && warnDevOnce(
3618
3789
  "keyExtractor",
3619
3790
  "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
3620
3791
  );
@@ -3637,12 +3808,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3637
3808
  }
3638
3809
  }, []);
3639
3810
  const doInitialScroll = React3.useCallback(() => {
3640
- var _a4;
3641
3811
  const initialScroll = state.initialScroll;
3642
3812
  if (initialScroll) {
3643
- scrollTo(ctx, state, {
3813
+ scrollTo(ctx, {
3644
3814
  animated: false,
3645
- index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3815
+ index: initialScroll == null ? void 0 : initialScroll.index,
3646
3816
  isInitialScroll: true,
3647
3817
  offset: initialContentOffset,
3648
3818
  precomputedWithViewOffset: true
@@ -3651,7 +3821,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3651
3821
  }, [initialContentOffset]);
3652
3822
  const onLayoutChange = React3.useCallback((layout) => {
3653
3823
  doInitialScroll();
3654
- handleLayout(ctx, state, layout, setCanRender);
3824
+ handleLayout(ctx, layout, setCanRender);
3655
3825
  }, []);
3656
3826
  const { onLayout } = useOnLayoutSync({
3657
3827
  onLayoutChange,
@@ -3661,7 +3831,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3661
3831
  });
3662
3832
  React3.useLayoutEffect(() => {
3663
3833
  if (snapToIndices) {
3664
- updateSnapToOffsets(ctx, state);
3834
+ updateSnapToOffsets(ctx);
3665
3835
  }
3666
3836
  }, [snapToIndices]);
3667
3837
  React3.useLayoutEffect(() => {
@@ -3671,9 +3841,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3671
3841
  isFirst,
3672
3842
  props: { data }
3673
3843
  } = state;
3674
- const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3844
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx);
3675
3845
  if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3676
- checkResetContainers(ctx, state, data);
3846
+ checkResetContainers(ctx, data);
3677
3847
  }
3678
3848
  state.didColumnsChange = false;
3679
3849
  state.didDataChange = false;
@@ -3698,15 +3868,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3698
3868
  state.viewabilityConfigCallbackPairs = viewability;
3699
3869
  state.enableScrollForNextCalculateItemsInView = !viewability;
3700
3870
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3701
- React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3871
+ React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
3702
3872
  {
3703
3873
  React3.useEffect(doInitialScroll, []);
3704
3874
  }
3705
3875
  const fns = React3.useMemo(
3706
3876
  () => ({
3707
- getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3708
- onScroll: (event) => onScroll(ctx, state, event),
3709
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
3877
+ getRenderedItem: (key) => getRenderedItem(ctx, key),
3878
+ onMomentumScrollEnd: (event) => {
3879
+ checkFinishedScrollFallback(ctx);
3880
+ if (onMomentumScrollEnd) {
3881
+ onMomentumScrollEnd(event);
3882
+ }
3883
+ },
3884
+ onScroll: (event) => onScroll(ctx, event),
3885
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, itemKey, sizeObj)
3710
3886
  }),
3711
3887
  []
3712
3888
  );
@@ -3718,6 +3894,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3718
3894
  alignItemsAtEnd,
3719
3895
  canRender,
3720
3896
  contentContainerStyle,
3897
+ contentInset,
3721
3898
  getRenderedItem: fns.getRenderedItem,
3722
3899
  horizontal,
3723
3900
  initialContentOffset,
@@ -3726,16 +3903,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3726
3903
  maintainVisibleContentPosition,
3727
3904
  onLayout,
3728
3905
  onLayoutHeader,
3729
- onMomentumScrollEnd: (event) => {
3730
- {
3731
- requestAnimationFrame(() => {
3732
- finishScrollTo(ctx, refState.current);
3733
- });
3734
- }
3735
- if (onMomentumScrollEnd) {
3736
- onMomentumScrollEnd(event);
3737
- }
3738
- },
3906
+ onMomentumScrollEnd: fns.onMomentumScrollEnd,
3739
3907
  onScroll: onScrollHandler,
3740
3908
  recycleItems,
3741
3909
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
@@ -3750,7 +3918,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3750
3918
  ),
3751
3919
  refScrollView: combinedRef,
3752
3920
  scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3753
- scrollEventThrottle: 16 ,
3921
+ scrollEventThrottle: 0,
3754
3922
  snapToIndices,
3755
3923
  stickyHeaderIndices,
3756
3924
  style,