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

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/section-list.js CHANGED
@@ -34,31 +34,65 @@ var View = React3.forwardRef(function View2(props, ref) {
34
34
  });
35
35
  var Text = View;
36
36
 
37
+ // src/state/getContentInsetEnd.ts
38
+ function getContentInsetEnd(state) {
39
+ var _a3;
40
+ const { props } = state;
41
+ const horizontal = props.horizontal;
42
+ let contentInset = props.contentInset;
43
+ if (!contentInset) {
44
+ const animatedInset = (_a3 = props.animatedProps) == null ? void 0 : _a3.contentInset;
45
+ if (animatedInset) {
46
+ if ("get" in animatedInset) {
47
+ contentInset = animatedInset.get();
48
+ } else {
49
+ contentInset = animatedInset;
50
+ }
51
+ }
52
+ }
53
+ return (horizontal ? contentInset == null ? void 0 : contentInset.right : contentInset == null ? void 0 : contentInset.bottom) || 0;
54
+ }
55
+
56
+ // src/state/getContentSize.ts
57
+ function getContentSize(ctx) {
58
+ var _a3;
59
+ const { values, state } = ctx;
60
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
61
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
62
+ const headerSize = values.get("headerSize") || 0;
63
+ const footerSize = values.get("footerSize") || 0;
64
+ const contentInsetBottom = getContentInsetEnd(state);
65
+ const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
66
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
67
+ }
68
+
37
69
  // src/platform/Animated.tsx
38
70
  var createAnimatedValue = (value) => value;
39
71
 
40
72
  // src/state/state.tsx
41
73
  var ContextState = React3__namespace.createContext(null);
74
+ var contextNum = 0;
42
75
  function StateProvider({ children }) {
43
76
  const [value] = React3__namespace.useState(() => ({
44
77
  animatedScrollY: createAnimatedValue(0),
45
78
  columnWrapperStyle: void 0,
46
- internalState: void 0,
79
+ contextNum: contextNum++,
47
80
  listeners: /* @__PURE__ */ new Map(),
48
81
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
49
82
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
50
83
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
51
84
  mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
52
85
  mapViewabilityValues: /* @__PURE__ */ new Map(),
86
+ positionListeners: /* @__PURE__ */ new Map(),
87
+ state: void 0,
53
88
  values: /* @__PURE__ */ new Map([
54
89
  ["alignItemsPaddingTop", 0],
55
90
  ["stylePaddingTop", 0],
56
91
  ["headerSize", 0],
57
92
  ["numContainers", 0],
58
- ["activeStickyIndex", void 0],
93
+ ["activeStickyIndex", -1],
59
94
  ["totalSize", 0],
60
- ["scrollAdjustPending", 0],
61
- ["scrollingTo", void 0]
95
+ ["scrollAdjustPending", 0]
62
96
  ]),
63
97
  viewRefs: /* @__PURE__ */ new Map()
64
98
  }));
@@ -126,15 +160,24 @@ function set$(ctx, signalName, value) {
126
160
  }
127
161
  }
128
162
  }
129
- function getContentSize(ctx) {
130
- var _a3, _b;
131
- const { values, internalState } = ctx;
132
- const stylePaddingTop = values.get("stylePaddingTop") || 0;
133
- const stylePaddingBottom = (internalState == null ? void 0 : internalState.props.stylePaddingBottom) || 0;
134
- const headerSize = values.get("headerSize") || 0;
135
- const footerSize = values.get("footerSize") || 0;
136
- const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
137
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom;
163
+ function listenPosition$(ctx, key, cb) {
164
+ const { positionListeners } = ctx;
165
+ let setListeners = positionListeners.get(key);
166
+ if (!setListeners) {
167
+ setListeners = /* @__PURE__ */ new Set();
168
+ positionListeners.set(key, setListeners);
169
+ }
170
+ setListeners.add(cb);
171
+ return () => setListeners.delete(cb);
172
+ }
173
+ function notifyPosition$(ctx, key, value) {
174
+ const { positionListeners } = ctx;
175
+ const setListeners = positionListeners.get(key);
176
+ if (setListeners) {
177
+ for (const listener of setListeners) {
178
+ listener(value);
179
+ }
180
+ }
138
181
  }
139
182
  function useArr$(signalNames) {
140
183
  const ctx = React3__namespace.useContext(ContextState);
@@ -256,12 +299,12 @@ function findContainerId(ctx, key) {
256
299
  }
257
300
 
258
301
  // src/components/PositionView.tsx
259
- var PositionViewState = typedMemo(function PositionView({
302
+ var PositionViewState = typedMemo(function PositionViewState2({
260
303
  id,
261
304
  horizontal,
262
305
  style,
263
306
  refView,
264
- ...rest
307
+ ...props
265
308
  }) {
266
309
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
267
310
  const base = {
@@ -269,7 +312,8 @@ var PositionViewState = typedMemo(function PositionView({
269
312
  };
270
313
  const composed = isArray(style) ? Object.assign({}, ...style) : style;
271
314
  const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
272
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
315
+ const { animatedScrollY, stickyOffset, onLayout, ...webProps } = props;
316
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, ...webProps, style: combinedStyle });
273
317
  });
274
318
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
275
319
  id,
@@ -314,16 +358,27 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
314
358
  }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
315
359
  return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
316
360
  });
317
- var PositionView2 = PositionViewState;
361
+ var PositionView = PositionViewState;
318
362
 
319
363
  // src/constants-platform.ts
320
364
  var IsNewArchitecture = true;
321
365
 
322
366
  // src/state/ContextContainer.ts
323
367
  var ContextContainer = React3.createContext(null);
368
+ function useContextContainer() {
369
+ return React3.useContext(ContextContainer);
370
+ }
324
371
  function useIsLastItem() {
325
- const { itemKey } = React3.useContext(ContextContainer);
326
- const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
372
+ const containerContext = useContextContainer();
373
+ const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
374
+ if (containerContext) {
375
+ const { itemKey } = containerContext;
376
+ if (!isNullOrUndefined(itemKey)) {
377
+ return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
378
+ }
379
+ }
380
+ return false;
381
+ });
327
382
  return isLast;
328
383
  }
329
384
 
@@ -369,10 +424,9 @@ function createResizeObserver(element, callback) {
369
424
  }
370
425
  callbacks.add(callback);
371
426
  return () => {
372
- const callbacks2 = callbackMap.get(element);
373
- if (callbacks2) {
374
- callbacks2.delete(callback);
375
- if (callbacks2.size === 0) {
427
+ if (callbacks) {
428
+ callbacks.delete(callback);
429
+ if (callbacks.size === 0) {
376
430
  callbackMap.delete(element);
377
431
  observer.unobserve(element);
378
432
  }
@@ -407,10 +461,10 @@ function useOnLayoutSync({
407
461
  return createResizeObserver(element, (entry) => {
408
462
  var _a4;
409
463
  const target = entry.target instanceof HTMLElement ? entry.target : void 0;
410
- const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
411
- if (rect2.width !== prevRect.width || rect2.height !== prevRect.height) {
412
- prevRect = rect2;
413
- emit(toLayout(rect2), false);
464
+ const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
465
+ if (rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height) {
466
+ prevRect = rectObserved;
467
+ emit(toLayout(rectObserved), false);
414
468
  }
415
469
  });
416
470
  }, deps || []);
@@ -538,7 +592,7 @@ var Container = typedMemo(function Container2({
538
592
  },
539
593
  [itemKey, layoutRenderCount]
540
594
  );
541
- const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
595
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView;
542
596
  return /* @__PURE__ */ React3__namespace.createElement(
543
597
  PositionComponent,
544
598
  {
@@ -731,7 +785,8 @@ var Containers = typedMemo(function Containers2({
731
785
  return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
732
786
  });
733
787
  function DevNumbers() {
734
- return IS_DEV && React3__namespace.memo(function DevNumbers2() {
788
+ return IS_DEV && // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
789
+ React3__namespace.memo(function DevNumbers2() {
735
790
  return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
736
791
  "div",
737
792
  {
@@ -779,7 +834,6 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
779
834
  }, ref) {
780
835
  const scrollRef = React3.useRef(null);
781
836
  const contentRef = React3.useRef(null);
782
- const momentumTimeout = React3.useRef(null);
783
837
  React3.useImperativeHandle(ref, () => {
784
838
  const api = {
785
839
  getBoundingClientRect: () => {
@@ -845,16 +899,6 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
845
899
  }
846
900
  };
847
901
  onScroll2(scrollEvent);
848
- if (onMomentumScrollEnd) {
849
- if (momentumTimeout.current != null) clearTimeout(momentumTimeout.current);
850
- momentumTimeout.current = setTimeout(() => {
851
- onMomentumScrollEnd({
852
- nativeEvent: {
853
- contentOffset: scrollEvent.nativeEvent.contentOffset
854
- }
855
- });
856
- }, 100);
857
- }
858
902
  },
859
903
  [onScroll2, onMomentumScrollEnd]
860
904
  );
@@ -916,7 +960,8 @@ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView
916
960
  minWidth: horizontal ? "100%" : void 0,
917
961
  ...StyleSheet.flatten(contentContainerStyle)
918
962
  };
919
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
963
+ const { contentInset, scrollEventThrottle, ScrollComponent, ...webProps } = props;
964
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, ...webProps, style: scrollViewStyle }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
920
965
  });
921
966
  function Padding() {
922
967
  const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
@@ -957,7 +1002,7 @@ function ScrollAdjust() {
957
1002
  const scrollAdjust = peek$(ctx, "scrollAdjust");
958
1003
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
959
1004
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
960
- const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
1005
+ const scrollView = (_a3 = ctx.state) == null ? void 0 : _a3.refScroller.current;
961
1006
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
962
1007
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
963
1008
  if (scrollDelta !== 0) {
@@ -965,26 +1010,23 @@ function ScrollAdjust() {
965
1010
  const prevScroll = el.scrollTop;
966
1011
  const nextScroll = prevScroll + scrollDelta;
967
1012
  const totalSize = el.scrollHeight;
968
- if (scrollDelta > 0 && !ctx.internalState.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1013
+ if (scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
969
1014
  const child = el.firstElementChild;
970
1015
  const prevPaddingBottom = child.style.paddingBottom;
971
1016
  const pad = (nextScroll + el.clientHeight - totalSize) * 2;
972
1017
  child.style.paddingBottom = `${pad}px`;
973
1018
  void el.offsetHeight;
974
1019
  scrollView.scrollBy(0, scrollDelta);
975
- setTimeout(() => {
1020
+ requestAnimationFrame(() => {
976
1021
  child.style.paddingBottom = prevPaddingBottom;
977
- }, 100);
1022
+ });
978
1023
  } else {
979
1024
  scrollView.scrollBy(0, scrollDelta);
980
1025
  }
981
- if (IS_DEV) {
982
- console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
983
- }
984
1026
  }
985
1027
  lastScrollOffsetRef.current = scrollOffset;
986
1028
  }
987
- }, []);
1029
+ }, [ctx]);
988
1030
  useValueListener$("scrollAdjust", callback);
989
1031
  useValueListener$("scrollAdjustUserOffset", callback);
990
1032
  return null;
@@ -1042,13 +1084,6 @@ var ListComponent = typedMemo(function ListComponent2({
1042
1084
  () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1043
1085
  [renderScrollComponent]
1044
1086
  ) : ListComponentScrollView;
1045
- React3__namespace.useEffect(() => {
1046
- if (canRender) {
1047
- setTimeout(() => {
1048
- scrollAdjustHandler.setMounted();
1049
- }, 0);
1050
- }
1051
- }, [canRender]);
1052
1087
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1053
1088
  return /* @__PURE__ */ React3__namespace.createElement(
1054
1089
  SnapOrScroll,
@@ -1112,10 +1147,11 @@ function getId(state, index) {
1112
1147
  }
1113
1148
 
1114
1149
  // src/core/calculateOffsetForIndex.ts
1115
- function calculateOffsetForIndex(ctx, state, index) {
1150
+ function calculateOffsetForIndex(ctx, index) {
1151
+ const state = ctx.state;
1116
1152
  let position = 0;
1117
1153
  if (index !== void 0) {
1118
- position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
1154
+ position = state.positions.get(getId(state, index)) || 0;
1119
1155
  const paddingTop = peek$(ctx, "stylePaddingTop");
1120
1156
  if (paddingTop) {
1121
1157
  position += paddingTop;
@@ -1129,7 +1165,8 @@ function calculateOffsetForIndex(ctx, state, index) {
1129
1165
  }
1130
1166
 
1131
1167
  // src/utils/setPaddingTop.ts
1132
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1168
+ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1169
+ const state = ctx.state;
1133
1170
  if (stylePaddingTop !== void 0) {
1134
1171
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1135
1172
  if (stylePaddingTop < prevStylePaddingTop) {
@@ -1148,7 +1185,8 @@ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1148
1185
  }
1149
1186
 
1150
1187
  // src/utils/updateAlignItemsPaddingTop.ts
1151
- function updateAlignItemsPaddingTop(ctx, state) {
1188
+ function updateAlignItemsPaddingTop(ctx) {
1189
+ const state = ctx.state;
1152
1190
  const {
1153
1191
  scrollLength,
1154
1192
  props: { alignItemsAtEnd, data }
@@ -1159,12 +1197,13 @@ function updateAlignItemsPaddingTop(ctx, state) {
1159
1197
  const contentSize = getContentSize(ctx);
1160
1198
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1161
1199
  }
1162
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
1200
+ setPaddingTop(ctx, { alignItemsPaddingTop });
1163
1201
  }
1164
1202
  }
1165
1203
 
1166
1204
  // src/core/addTotalSize.ts
1167
- function addTotalSize(ctx, state, key, add) {
1205
+ function addTotalSize(ctx, key, add) {
1206
+ const state = ctx.state;
1168
1207
  const { alignItemsAtEnd } = state.props;
1169
1208
  const prevTotalSize = state.totalSize;
1170
1209
  let totalSize = state.totalSize;
@@ -1183,31 +1222,34 @@ function addTotalSize(ctx, state, key, add) {
1183
1222
  state.totalSize = totalSize;
1184
1223
  set$(ctx, "totalSize", totalSize);
1185
1224
  if (alignItemsAtEnd) {
1186
- updateAlignItemsPaddingTop(ctx, state);
1225
+ updateAlignItemsPaddingTop(ctx);
1187
1226
  }
1188
1227
  }
1189
1228
  }
1190
1229
  }
1191
1230
 
1192
1231
  // src/core/setSize.ts
1193
- function setSize(ctx, state, itemKey, size) {
1232
+ function setSize(ctx, itemKey, size) {
1233
+ const state = ctx.state;
1194
1234
  const { sizes } = state;
1195
1235
  const previousSize = sizes.get(itemKey);
1196
1236
  const diff = previousSize !== void 0 ? size - previousSize : size;
1197
1237
  if (diff !== 0) {
1198
- addTotalSize(ctx, state, itemKey, diff);
1238
+ addTotalSize(ctx, itemKey, diff);
1199
1239
  }
1200
1240
  sizes.set(itemKey, size);
1201
1241
  }
1202
1242
 
1203
1243
  // src/utils/getItemSize.ts
1204
- function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1244
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1205
1245
  var _a3, _b;
1246
+ const state = ctx.state;
1206
1247
  const {
1207
1248
  sizesKnown,
1208
1249
  sizes,
1209
1250
  averageSizes,
1210
- props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1251
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1252
+ scrollingTo
1211
1253
  } = state;
1212
1254
  const sizeKnown = sizesKnown.get(key);
1213
1255
  if (sizeKnown !== void 0) {
@@ -1215,7 +1257,6 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1215
1257
  }
1216
1258
  let size;
1217
1259
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1218
- const scrollingTo = peek$(ctx, "scrollingTo");
1219
1260
  if (preferCachedSize) {
1220
1261
  const cachedSize = sizes.get(key);
1221
1262
  if (cachedSize !== void 0) {
@@ -1243,81 +1284,169 @@ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedS
1243
1284
  if (size === void 0) {
1244
1285
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1245
1286
  }
1246
- setSize(ctx, state, key, size);
1287
+ setSize(ctx, key, size);
1247
1288
  return size;
1248
1289
  }
1249
1290
 
1250
1291
  // src/core/calculateOffsetWithOffsetPosition.ts
1251
- function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1292
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1293
+ const state = ctx.state;
1252
1294
  const { index, viewOffset, viewPosition } = params;
1253
1295
  let offset = offsetParam;
1254
1296
  if (viewOffset) {
1255
1297
  offset -= viewOffset;
1256
1298
  }
1257
1299
  if (viewPosition !== void 0 && index !== void 0) {
1258
- offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1300
+ const itemSize = getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1301
+ const trailingInset = getContentInsetEnd(state);
1302
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1259
1303
  }
1260
1304
  return offset;
1261
1305
  }
1262
1306
 
1307
+ // src/core/clampScrollOffset.ts
1308
+ function clampScrollOffset(ctx, offset) {
1309
+ const state = ctx.state;
1310
+ const contentSize = getContentSize(ctx);
1311
+ let clampedOffset = offset;
1312
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength)) {
1313
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1314
+ clampedOffset = Math.min(offset, maxOffset);
1315
+ }
1316
+ clampedOffset = Math.max(0, clampedOffset);
1317
+ return clampedOffset;
1318
+ }
1319
+
1320
+ // src/utils/setInitialRenderState.ts
1321
+ function setInitialRenderState(ctx, {
1322
+ didLayout,
1323
+ didInitialScroll
1324
+ }) {
1325
+ const { state } = ctx;
1326
+ if (didLayout) {
1327
+ state.didContainersLayout = true;
1328
+ }
1329
+ if (didInitialScroll) {
1330
+ state.didFinishInitialScroll = true;
1331
+ }
1332
+ if (state.didContainersLayout && state.didFinishInitialScroll) {
1333
+ set$(ctx, "readyToRender", true);
1334
+ }
1335
+ }
1336
+
1263
1337
  // src/core/finishScrollTo.ts
1264
- function finishScrollTo(ctx, state) {
1338
+ function finishScrollTo(ctx) {
1265
1339
  var _a3, _b;
1266
- if (state) {
1340
+ const state = ctx.state;
1341
+ if (state == null ? void 0 : state.scrollingTo) {
1267
1342
  state.scrollHistory.length = 0;
1268
1343
  state.initialScroll = void 0;
1269
1344
  state.initialAnchor = void 0;
1270
- set$(ctx, "scrollingTo", void 0);
1345
+ state.scrollingTo = void 0;
1271
1346
  if (state.pendingTotalSize !== void 0) {
1272
- addTotalSize(ctx, state, null, state.pendingTotalSize);
1347
+ addTotalSize(ctx, null, state.pendingTotalSize);
1273
1348
  }
1274
1349
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1275
1350
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1276
1351
  }
1352
+ {
1353
+ state.scrollAdjustHandler.commitPendingAdjust();
1354
+ }
1355
+ setInitialRenderState(ctx, { didInitialScroll: true });
1356
+ }
1357
+ }
1358
+
1359
+ // src/core/doScrollTo.ts
1360
+ var SCROLL_END_IDLE_MS = 80;
1361
+ var SCROLL_END_MAX_MS = 1500;
1362
+ var SMOOTH_SCROLL_DURATION_MS = 320;
1363
+ function doScrollTo(ctx, params) {
1364
+ const state = ctx.state;
1365
+ const { animated, horizontal, offset } = params;
1366
+ const scroller = state.refScroller.current;
1367
+ const node = typeof (scroller == null ? void 0 : scroller.getScrollableNode) === "function" ? scroller.getScrollableNode() : scroller;
1368
+ if (node) {
1369
+ const left = horizontal ? offset : 0;
1370
+ const top = horizontal ? 0 : offset;
1371
+ node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
1372
+ if (animated) {
1373
+ listenForScrollEnd(ctx, node);
1374
+ } else {
1375
+ state.scroll = offset;
1376
+ setTimeout(() => {
1377
+ finishScrollTo(ctx);
1378
+ }, 100);
1379
+ }
1380
+ }
1381
+ }
1382
+ function listenForScrollEnd(ctx, node) {
1383
+ const supportsScrollEnd = "onscrollend" in node;
1384
+ let idleTimeout;
1385
+ let maxTimeout;
1386
+ let settled = false;
1387
+ const targetToken = ctx.state.scrollingTo;
1388
+ const finish = () => {
1389
+ if (settled) return;
1390
+ settled = true;
1391
+ cleanup();
1392
+ if (targetToken === ctx.state.scrollingTo) {
1393
+ finishScrollTo(ctx);
1394
+ }
1395
+ };
1396
+ const onScroll2 = () => {
1397
+ if (idleTimeout) {
1398
+ clearTimeout(idleTimeout);
1399
+ }
1400
+ idleTimeout = setTimeout(finish, SCROLL_END_IDLE_MS);
1401
+ };
1402
+ const cleanup = () => {
1403
+ if (supportsScrollEnd) {
1404
+ node.removeEventListener("scrollend", finish);
1405
+ } else {
1406
+ node.removeEventListener("scroll", onScroll2);
1407
+ }
1408
+ if (idleTimeout) {
1409
+ clearTimeout(idleTimeout);
1410
+ }
1411
+ if (maxTimeout) {
1412
+ clearTimeout(maxTimeout);
1413
+ }
1414
+ };
1415
+ if (supportsScrollEnd) {
1416
+ node.addEventListener("scrollend", finish, { once: true });
1417
+ } else {
1418
+ node.addEventListener("scroll", onScroll2);
1419
+ idleTimeout = setTimeout(finish, SMOOTH_SCROLL_DURATION_MS);
1420
+ maxTimeout = setTimeout(finish, SCROLL_END_MAX_MS);
1277
1421
  }
1422
+ return cleanup;
1278
1423
  }
1279
1424
 
1280
1425
  // src/core/scrollTo.ts
1281
- function scrollTo(ctx, state, params) {
1282
- var _a3;
1283
- const { noScrollingTo, ...scrollTarget } = params;
1426
+ function scrollTo(ctx, params) {
1427
+ const state = ctx.state;
1428
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1284
1429
  const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1285
1430
  const {
1286
- refScroller,
1287
1431
  props: { horizontal }
1288
1432
  } = state;
1289
- let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1290
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1291
- const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1292
- offset = Math.min(offset, maxOffset);
1433
+ if (state.animFrameCheckFinishedScroll) {
1434
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1435
+ }
1436
+ if (state.timeoutCheckFinishedScrollFallback) {
1437
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1293
1438
  }
1439
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1440
+ offset = clampScrollOffset(ctx, offset);
1294
1441
  state.scrollHistory.length = 0;
1295
1442
  if (!noScrollingTo) {
1296
- set$(ctx, "scrollingTo", scrollTarget);
1443
+ state.scrollingTo = scrollTarget;
1297
1444
  }
1298
1445
  state.scrollPending = offset;
1299
- if (!isInitialScroll || Platform.OS === "android") {
1300
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1301
- animated: !!animated,
1302
- x: horizontal ? offset : 0,
1303
- y: horizontal ? 0 : offset
1304
- });
1305
- }
1306
- if (!animated) {
1446
+ if (forceScroll || !isInitialScroll || Platform.OS === "android") {
1447
+ doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
1448
+ } else {
1307
1449
  state.scroll = offset;
1308
- {
1309
- const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1310
- if (value && peek$(ctx, "scrollingTo")) {
1311
- finishScrollTo(ctx, state);
1312
- unlisten();
1313
- }
1314
- });
1315
- }
1316
- if (isInitialScroll) {
1317
- setTimeout(() => {
1318
- state.initialScroll = void 0;
1319
- }, 500);
1320
- }
1321
1450
  }
1322
1451
  }
1323
1452
 
@@ -1326,6 +1455,12 @@ var HYSTERESIS_MULTIPLIER = 1.3;
1326
1455
  var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1327
1456
  const absDistance = Math.abs(distance);
1328
1457
  const within = atThreshold || threshold > 0 && absDistance <= threshold;
1458
+ if (wasReached === null) {
1459
+ if (!within && distance >= 0) {
1460
+ return false;
1461
+ }
1462
+ return null;
1463
+ }
1329
1464
  const updateSnapshot = () => {
1330
1465
  setSnapshot == null ? void 0 : setSnapshot({
1331
1466
  atThreshold,
@@ -1358,8 +1493,9 @@ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, co
1358
1493
  };
1359
1494
 
1360
1495
  // src/utils/checkAtBottom.ts
1361
- function checkAtBottom(ctx, state) {
1496
+ function checkAtBottom(ctx) {
1362
1497
  var _a3;
1498
+ const state = ctx.state;
1363
1499
  if (!state) {
1364
1500
  return;
1365
1501
  }
@@ -1432,15 +1568,15 @@ function checkAtTop(state) {
1432
1568
  }
1433
1569
 
1434
1570
  // src/core/updateScroll.ts
1435
- function updateScroll(ctx, state, newScroll, forceUpdate) {
1571
+ function updateScroll(ctx, newScroll, forceUpdate) {
1436
1572
  var _a3;
1437
- const scrollingTo = peek$(ctx, "scrollingTo");
1573
+ const state = ctx.state;
1574
+ const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1438
1575
  state.hasScrolled = true;
1439
1576
  state.lastBatchingAction = Date.now();
1440
1577
  const currentTime = Date.now();
1441
- const adjust = state.scrollAdjustHandler.getAdjust();
1442
- const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1443
- const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1578
+ const adjust = scrollAdjustHandler.getAdjust();
1579
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1444
1580
  if (adjustChanged) {
1445
1581
  state.scrollHistory.length = 0;
1446
1582
  }
@@ -1465,17 +1601,21 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1465
1601
  return;
1466
1602
  }
1467
1603
  }
1468
- if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1604
+ const lastCalculated = state.scrollLastCalculate;
1605
+ const shouldUpdate = state.dataChangeNeedsScrollUpdate || state.scrollLastCalculate === void 0 || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1606
+ if (shouldUpdate) {
1607
+ state.scrollLastCalculate = state.scroll;
1469
1608
  state.ignoreScrollFromMVCPIgnored = false;
1470
1609
  (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1471
- checkAtBottom(ctx, state);
1610
+ checkAtBottom(ctx);
1472
1611
  checkAtTop(state);
1473
1612
  state.dataChangeNeedsScrollUpdate = false;
1474
1613
  }
1475
1614
  }
1476
1615
 
1477
1616
  // src/utils/requestAdjust.ts
1478
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
1617
+ function requestAdjust(ctx, positionDiff, dataChanged) {
1618
+ const state = ctx.state;
1479
1619
  if (Math.abs(positionDiff) > 0.1) {
1480
1620
  const doit = () => {
1481
1621
  {
@@ -1487,8 +1627,8 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1487
1627
  };
1488
1628
  state.scroll += positionDiff;
1489
1629
  state.scrollForNextCalculateItemsInView = void 0;
1490
- const didLayout = peek$(ctx, "containersDidLayout");
1491
- if (didLayout) {
1630
+ const readyToRender = peek$(ctx, "readyToRender");
1631
+ if (readyToRender) {
1492
1632
  doit();
1493
1633
  } else {
1494
1634
  state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
@@ -1497,73 +1637,23 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1497
1637
  }
1498
1638
  }
1499
1639
 
1500
- // src/core/ensureInitialAnchor.ts
1501
- var INITIAL_ANCHOR_TOLERANCE = 0.5;
1502
- var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1503
- var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1504
- function ensureInitialAnchor(ctx, state) {
1505
- var _a3, _b, _c, _d, _e;
1506
- const anchor = state.initialAnchor;
1507
- const item = state.props.data[anchor.index];
1508
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1509
- if (!containersDidLayout) {
1510
- return;
1511
- }
1512
- const id = getId(state, anchor.index);
1513
- if (state.positions.get(id) === void 0) {
1514
- return;
1515
- }
1516
- const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1517
- if (size === void 0) {
1518
- return;
1519
- }
1520
- const availableSpace = Math.max(0, state.scrollLength - size);
1521
- const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1522
- const contentSize = getContentSize(ctx);
1523
- const maxOffset = Math.max(0, contentSize - state.scrollLength);
1524
- const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1525
- const delta = clampedDesiredOffset - state.scroll;
1526
- if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1527
- const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1528
- if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1529
- state.initialAnchor = void 0;
1530
- } else {
1531
- anchor.settledTicks = settledTicks;
1532
- }
1533
- return;
1534
- }
1535
- if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1536
- state.initialAnchor = void 0;
1537
- return;
1538
- }
1539
- const lastDelta = anchor.lastDelta;
1540
- if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1541
- state.initialAnchor = void 0;
1542
- return;
1543
- }
1544
- Object.assign(anchor, {
1545
- attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1546
- lastDelta: delta,
1547
- settledTicks: 0
1548
- });
1549
- requestAdjust(ctx, state, delta);
1550
- }
1551
-
1552
1640
  // src/core/mvcp.ts
1553
- function prepareMVCP(ctx, state, dataChanged) {
1641
+ function prepareMVCP(ctx, dataChanged) {
1642
+ const state = ctx.state;
1554
1643
  const { idsInView, positions, props } = state;
1555
1644
  const { maintainVisibleContentPosition } = props;
1556
- const scrollingTo = peek$(ctx, "scrollingTo");
1645
+ const scrollingTo = state.scrollingTo;
1557
1646
  let prevPosition;
1558
1647
  let targetId;
1559
1648
  const idsInViewWithPositions = [];
1560
1649
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1650
+ const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
1561
1651
  const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1562
1652
  const indexByKey = state.indexByKey;
1563
1653
  if (shouldMVCP) {
1564
1654
  if (scrollTarget !== void 0) {
1565
1655
  targetId = getId(state, scrollTarget);
1566
- } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1656
+ } else if (idsInView.length > 0 && state.didContainersLayout) {
1567
1657
  if (dataChanged) {
1568
1658
  for (let i = 0; i < idsInView.length; i++) {
1569
1659
  const id = idsInView[i];
@@ -1580,7 +1670,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1580
1670
  prevPosition = positions.get(targetId);
1581
1671
  }
1582
1672
  return () => {
1583
- let positionDiff;
1673
+ let positionDiff = 0;
1584
1674
  if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1585
1675
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1586
1676
  const { id, position } = idsInViewWithPositions[i];
@@ -1606,16 +1696,28 @@ function prepareMVCP(ctx, state, dataChanged) {
1606
1696
  positionDiff = diff;
1607
1697
  }
1608
1698
  }
1609
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1610
- requestAdjust(ctx, state, positionDiff);
1699
+ if (scrollingToViewPosition && scrollingToViewPosition > 0) {
1700
+ const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
1701
+ const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
1702
+ if (newSize !== void 0 && prevSize !== void 0 && newSize !== (scrollingTo == null ? void 0 : scrollingTo.itemSize)) {
1703
+ const diff = newSize - prevSize;
1704
+ if (diff !== 0) {
1705
+ positionDiff += (newSize - prevSize) * scrollingToViewPosition;
1706
+ scrollingTo.itemSize = newSize;
1707
+ }
1708
+ }
1709
+ }
1710
+ if (Math.abs(positionDiff) > 0.1) {
1711
+ requestAdjust(ctx, positionDiff);
1611
1712
  }
1612
1713
  };
1613
1714
  }
1614
1715
  }
1615
1716
 
1616
1717
  // src/core/prepareColumnStartState.ts
1617
- function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1718
+ function prepareColumnStartState(ctx, startIndex, useAverageSize) {
1618
1719
  var _a3;
1720
+ const state = ctx.state;
1619
1721
  const numColumns = peek$(ctx, "numColumns");
1620
1722
  let rowStartIndex = startIndex;
1621
1723
  const columnAtStart = state.columns.get(state.idCache[startIndex]);
@@ -1630,7 +1732,7 @@ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1630
1732
  const prevId = state.idCache[prevIndex];
1631
1733
  const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1632
1734
  const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1633
- const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1735
+ const prevRowHeight = calculateRowMaxSize(ctx, prevRowStart, prevIndex, useAverageSize);
1634
1736
  currentRowTop = prevPosition + prevRowHeight;
1635
1737
  }
1636
1738
  return {
@@ -1653,7 +1755,8 @@ function findRowStartIndex(state, numColumns, index) {
1653
1755
  }
1654
1756
  return rowStart;
1655
1757
  }
1656
- function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1758
+ function calculateRowMaxSize(ctx, startIndex, endIndex, useAverageSize) {
1759
+ const state = ctx.state;
1657
1760
  if (endIndex < startIndex) {
1658
1761
  return 0;
1659
1762
  }
@@ -1667,7 +1770,7 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1667
1770
  continue;
1668
1771
  }
1669
1772
  const id = state.idCache[i];
1670
- const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1773
+ const size = getItemSize(ctx, id, i, data[i], useAverageSize);
1671
1774
  if (size > maxSize) {
1672
1775
  maxSize = size;
1673
1776
  }
@@ -1676,22 +1779,23 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1676
1779
  }
1677
1780
 
1678
1781
  // src/core/updateTotalSize.ts
1679
- function updateTotalSize(ctx, state) {
1782
+ function updateTotalSize(ctx) {
1783
+ const state = ctx.state;
1680
1784
  const {
1681
1785
  positions,
1682
1786
  props: { data }
1683
1787
  } = state;
1684
1788
  if (data.length === 0) {
1685
- addTotalSize(ctx, state, null, 0);
1789
+ addTotalSize(ctx, null, 0);
1686
1790
  } else {
1687
1791
  const lastId = getId(state, data.length - 1);
1688
1792
  if (lastId !== void 0) {
1689
1793
  const lastPosition = positions.get(lastId);
1690
1794
  if (lastPosition !== void 0) {
1691
- const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1795
+ const lastSize = getItemSize(ctx, lastId, data.length - 1, data[data.length - 1]);
1692
1796
  if (lastSize !== void 0) {
1693
1797
  const totalSize = lastPosition + lastSize;
1694
- addTotalSize(ctx, state, null, totalSize);
1798
+ addTotalSize(ctx, null, totalSize);
1695
1799
  }
1696
1800
  }
1697
1801
  }
@@ -1737,7 +1841,8 @@ var getScrollVelocity = (state) => {
1737
1841
  };
1738
1842
 
1739
1843
  // src/utils/updateSnapToOffsets.ts
1740
- function updateSnapToOffsets(ctx, state) {
1844
+ function updateSnapToOffsets(ctx) {
1845
+ const state = ctx.state;
1741
1846
  const {
1742
1847
  positions,
1743
1848
  props: { snapToIndices }
@@ -1752,30 +1857,30 @@ function updateSnapToOffsets(ctx, state) {
1752
1857
  }
1753
1858
 
1754
1859
  // src/core/updateItemPositions.ts
1755
- function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1860
+ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1756
1861
  doMVCP: false,
1757
1862
  forceFullUpdate: false,
1758
1863
  scrollBottomBuffered: -1,
1759
1864
  startIndex: 0
1760
1865
  }) {
1761
1866
  var _a3, _b, _c, _d, _e;
1867
+ const state = ctx.state;
1762
1868
  const {
1763
1869
  columns,
1764
1870
  indexByKey,
1765
1871
  positions,
1766
1872
  idCache,
1767
1873
  sizesKnown,
1768
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1874
+ props: { data, getEstimatedItemSize, snapToIndices },
1875
+ scrollingTo
1769
1876
  } = state;
1770
- const data = state.props.data;
1771
1877
  const dataLength = data.length;
1772
1878
  const numColumns = peek$(ctx, "numColumns");
1773
- const scrollingTo = peek$(ctx, "scrollingTo");
1774
1879
  const hasColumns = numColumns > 1;
1775
1880
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1776
1881
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1777
1882
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1778
- const useAverageSize = enableAverages && !getEstimatedItemSize;
1883
+ const useAverageSize = !getEstimatedItemSize;
1779
1884
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
1780
1885
  let currentRowTop = 0;
1781
1886
  let column = 1;
@@ -1784,7 +1889,6 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1784
1889
  if (hasColumns) {
1785
1890
  const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1786
1891
  ctx,
1787
- state,
1788
1892
  startIndex,
1789
1893
  useAverageSize
1790
1894
  );
@@ -1794,7 +1898,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1794
1898
  const prevIndex = startIndex - 1;
1795
1899
  const prevId = getId(state, prevIndex);
1796
1900
  const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1797
- const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1901
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1798
1902
  currentRowTop = prevPosition + prevSize;
1799
1903
  }
1800
1904
  }
@@ -1811,7 +1915,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1811
1915
  breakAt = i + itemsPerRow + 10;
1812
1916
  }
1813
1917
  const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1814
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1918
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
1815
1919
  if (IS_DEV && needsIndexByKey) {
1816
1920
  if (indexByKeyForChecking.has(id)) {
1817
1921
  console.error(
@@ -1820,7 +1924,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1820
1924
  }
1821
1925
  indexByKeyForChecking.set(id, i);
1822
1926
  }
1823
- positions.set(id, currentRowTop);
1927
+ if (currentRowTop !== positions.get(id)) {
1928
+ positions.set(id, currentRowTop);
1929
+ notifyPosition$(ctx, id, currentRowTop);
1930
+ }
1824
1931
  if (needsIndexByKey) {
1825
1932
  indexByKey.set(id, i);
1826
1933
  }
@@ -1840,10 +1947,10 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1840
1947
  }
1841
1948
  }
1842
1949
  if (!didBreakEarly) {
1843
- updateTotalSize(ctx, state);
1950
+ updateTotalSize(ctx);
1844
1951
  }
1845
1952
  if (snapToIndices) {
1846
- updateSnapToOffsets(ctx, state);
1953
+ updateSnapToOffsets(ctx);
1847
1954
  }
1848
1955
  }
1849
1956
 
@@ -1921,7 +2028,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1921
2028
  if (previousViewableItems) {
1922
2029
  for (const viewToken of previousViewableItems) {
1923
2030
  const containerId = findContainerId(ctx, viewToken.key);
1924
- if (!isViewable(
2031
+ if (!checkIsViewable(
1925
2032
  state,
1926
2033
  ctx,
1927
2034
  viewabilityConfig,
@@ -1942,7 +2049,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1942
2049
  if (item) {
1943
2050
  const key = getId(state, i);
1944
2051
  const containerId = findContainerId(ctx, key);
1945
- if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
2052
+ if (checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1946
2053
  const viewToken = {
1947
2054
  containerId,
1948
2055
  index: i,
@@ -2002,11 +2109,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
2002
2109
  const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
2003
2110
  const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
2004
2111
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
2005
- const isViewable2 = percent >= viewablePercentThreshold;
2112
+ const isViewable = percent >= viewablePercentThreshold;
2006
2113
  const value = {
2007
2114
  containerId,
2008
2115
  index,
2009
- isViewable: isViewable2,
2116
+ isViewable,
2010
2117
  item,
2011
2118
  key,
2012
2119
  percentOfScroller,
@@ -2025,8 +2132,11 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
2025
2132
  }
2026
2133
  return value;
2027
2134
  }
2028
- function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2029
- const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2135
+ function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2136
+ let value = ctx.mapViewabilityAmountValues.get(containerId);
2137
+ if (!value || value.key !== key) {
2138
+ value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2139
+ }
2030
2140
  return value.isViewable;
2031
2141
  }
2032
2142
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
@@ -2054,8 +2164,9 @@ function checkAllSizesKnown(state) {
2054
2164
  }
2055
2165
 
2056
2166
  // src/utils/findAvailableContainers.ts
2057
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2167
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2058
2168
  const numContainers = peek$(ctx, "numContainers");
2169
+ const state = ctx.state;
2059
2170
  const { stickyContainerPool, containerItemTypes } = state;
2060
2171
  const result = [];
2061
2172
  const availableContainers = [];
@@ -2099,14 +2210,14 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2099
2210
  continue;
2100
2211
  }
2101
2212
  const key = peek$(ctx, `containerItemKey${u}`);
2102
- let isOk = key === void 0;
2103
- if (!isOk && pendingRemovalSet.has(u)) {
2104
- pendingRemovalSet.delete(u);
2105
- pendingRemovalChanged = true;
2106
- const requiredType = neededTypes[typeIndex];
2107
- isOk = canReuseContainer(u, requiredType);
2108
- }
2109
- if (isOk) {
2213
+ const requiredType = neededTypes[typeIndex];
2214
+ const isPending = key !== void 0 && pendingRemovalSet.has(u);
2215
+ const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
2216
+ if (canUse) {
2217
+ if (isPending) {
2218
+ pendingRemovalSet.delete(u);
2219
+ pendingRemovalChanged = true;
2220
+ }
2110
2221
  result.push(u);
2111
2222
  if (requiredItemTypes) {
2112
2223
  typeIndex++;
@@ -2175,21 +2286,26 @@ function comparatorByDistance(a, b) {
2175
2286
  }
2176
2287
 
2177
2288
  // src/core/scrollToIndex.ts
2178
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
2179
- if (index >= state.props.data.length) {
2180
- index = state.props.data.length - 1;
2289
+ function scrollToIndex(ctx, { index, viewOffset = 0, animated = true, viewPosition }) {
2290
+ const state = ctx.state;
2291
+ const { data } = state.props;
2292
+ if (index >= data.length) {
2293
+ index = data.length - 1;
2181
2294
  } else if (index < 0) {
2182
2295
  index = 0;
2183
2296
  }
2184
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
2185
- const isLast = index === state.props.data.length - 1;
2297
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2298
+ const isLast = index === data.length - 1;
2186
2299
  if (isLast && viewPosition === void 0) {
2187
2300
  viewPosition = 1;
2188
2301
  }
2189
2302
  state.scrollForNextCalculateItemsInView = void 0;
2190
- scrollTo(ctx, state, {
2303
+ const targetId = getId(state, index);
2304
+ const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2305
+ scrollTo(ctx, {
2191
2306
  animated,
2192
2307
  index,
2308
+ itemSize,
2193
2309
  offset: firstIndexOffset,
2194
2310
  viewOffset,
2195
2311
  viewPosition: viewPosition != null ? viewPosition : 0
@@ -2197,16 +2313,17 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
2197
2313
  }
2198
2314
 
2199
2315
  // src/utils/setDidLayout.ts
2200
- function setDidLayout(ctx, state) {
2316
+ function setDidLayout(ctx) {
2317
+ const state = ctx.state;
2201
2318
  const {
2202
2319
  loadStartTime,
2203
2320
  initialScroll,
2204
2321
  props: { onLoad }
2205
2322
  } = state;
2206
2323
  state.queuedInitialLayout = true;
2207
- checkAtBottom(ctx, state);
2324
+ checkAtBottom(ctx);
2208
2325
  const setIt = () => {
2209
- set$(ctx, "containersDidLayout", true);
2326
+ setInitialRenderState(ctx, { didLayout: true });
2210
2327
  if (onLoad) {
2211
2328
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2212
2329
  }
@@ -2231,15 +2348,17 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
2231
2348
  }
2232
2349
  return -1;
2233
2350
  }
2234
- function getActiveStickyIndices(ctx, state, stickyHeaderIndices) {
2351
+ function getActiveStickyIndices(ctx, stickyHeaderIndices) {
2352
+ const state = ctx.state;
2235
2353
  return new Set(
2236
2354
  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))
2237
2355
  );
2238
2356
  }
2239
- function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2357
+ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2240
2358
  var _a3;
2241
- const activeIndices = getActiveStickyIndices(ctx, state, stickyHeaderIndices);
2242
- state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
2359
+ const state = ctx.state;
2360
+ const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
2361
+ set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
2243
2362
  for (let offset = 0; offset <= 1; offset++) {
2244
2363
  const idx = currentStickyIdx - offset;
2245
2364
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
@@ -2250,8 +2369,9 @@ function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, cu
2250
2369
  }
2251
2370
  }
2252
2371
  }
2253
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2372
+ function handleStickyRecycling(ctx, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2254
2373
  var _a3, _b, _c;
2374
+ const state = ctx.state;
2255
2375
  for (const containerIndex of state.stickyContainerPool) {
2256
2376
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2257
2377
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
@@ -2275,7 +2395,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2275
2395
  const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2276
2396
  if (currentId) {
2277
2397
  const currentPos = state.positions.get(currentId);
2278
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
2398
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
2279
2399
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2280
2400
  }
2281
2401
  }
@@ -2284,7 +2404,8 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2284
2404
  }
2285
2405
  }
2286
2406
  }
2287
- function calculateItemsInView(ctx, state, params = {}) {
2407
+ function calculateItemsInView(ctx, params = {}) {
2408
+ const state = ctx.state;
2288
2409
  reactDom.unstable_batchedUpdates(() => {
2289
2410
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2290
2411
  const {
@@ -2308,9 +2429,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2308
2429
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2309
2430
  const prevNumContainers = peek$(ctx, "numContainers");
2310
2431
  if (!data || scrollLength === 0 || !prevNumContainers) {
2311
- if (state.initialAnchor) {
2312
- ensureInitialAnchor(ctx, state);
2313
- }
2314
2432
  return;
2315
2433
  }
2316
2434
  const totalSize = getContentSize(ctx);
@@ -2324,15 +2442,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2324
2442
  if (!queuedInitialLayout && initialScroll) {
2325
2443
  const updatedOffset = calculateOffsetWithOffsetPosition(
2326
2444
  ctx,
2327
- state,
2328
- calculateOffsetForIndex(ctx, state, initialScroll.index),
2445
+ calculateOffsetForIndex(ctx, initialScroll.index),
2329
2446
  initialScroll
2330
2447
  );
2331
2448
  scrollState = updatedOffset;
2332
2449
  }
2333
2450
  const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2334
2451
  const scrollAdjustPad = scrollAdjustPending - topPad;
2335
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
2452
+ let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2336
2453
  if (scroll + scrollLength > totalSize) {
2337
2454
  scroll = Math.max(0, totalSize - scrollLength);
2338
2455
  }
@@ -2340,11 +2457,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2340
2457
  set$(ctx, "debugRawScroll", scrollState);
2341
2458
  set$(ctx, "debugComputedScroll", scroll);
2342
2459
  }
2343
- const previousStickyIndex = state.activeStickyIndex;
2460
+ const previousStickyIndex = peek$(ctx, "activeStickyIndex");
2344
2461
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2345
- const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2346
- state.activeStickyIndex = nextActiveStickyIndex;
2347
- set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2462
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
2463
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
2464
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2465
+ }
2348
2466
  let scrollBufferTop = scrollBuffer;
2349
2467
  let scrollBufferBottom = scrollBuffer;
2350
2468
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2357,23 +2475,20 @@ function calculateItemsInView(ctx, state, params = {}) {
2357
2475
  const scrollTopBuffered = scroll - scrollBufferTop;
2358
2476
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2359
2477
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2360
- if (!dataChanged && scrollForNextCalculateItemsInView) {
2478
+ if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2361
2479
  const { top, bottom } = scrollForNextCalculateItemsInView;
2362
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2363
- if (state.initialAnchor) {
2364
- ensureInitialAnchor(ctx, state);
2365
- }
2480
+ if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2366
2481
  return;
2367
2482
  }
2368
2483
  }
2369
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2484
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
2370
2485
  if (dataChanged) {
2371
2486
  indexByKey.clear();
2372
2487
  idCache.length = 0;
2373
2488
  positions.clear();
2374
2489
  }
2375
- const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2376
- updateItemPositions(ctx, state, dataChanged, {
2490
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2491
+ updateItemPositions(ctx, dataChanged, {
2377
2492
  doMVCP,
2378
2493
  forceFullUpdate: !!forceFullItemPositions,
2379
2494
  scrollBottomBuffered,
@@ -2392,9 +2507,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2392
2507
  for (let i = loopStart; i >= 0; i--) {
2393
2508
  const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2394
2509
  const top = positions.get(id);
2395
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2510
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, id, i, data[i]);
2396
2511
  const bottom = top + size;
2397
- if (bottom > scroll - scrollBuffer) {
2512
+ if (bottom > scroll - scrollBufferTop) {
2398
2513
  loopStart = i;
2399
2514
  } else {
2400
2515
  break;
@@ -2419,7 +2534,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2419
2534
  const dataLength = data.length;
2420
2535
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2421
2536
  const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2422
- const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2537
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, id, i, data[i]);
2423
2538
  const top = positions.get(id);
2424
2539
  if (!foundEnd) {
2425
2540
  if (startNoBuffer === null && top + size > scroll) {
@@ -2431,7 +2546,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2431
2546
  if (startBuffered === null && top + size > scrollTopBuffered) {
2432
2547
  startBuffered = i;
2433
2548
  startBufferedId = id;
2434
- nextTop = top;
2549
+ if (scrollTopBuffered < 0) {
2550
+ nextTop = null;
2551
+ } else {
2552
+ nextTop = top;
2553
+ }
2435
2554
  }
2436
2555
  if (startNoBuffer !== null) {
2437
2556
  if (top <= scrollBottom) {
@@ -2439,7 +2558,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2439
2558
  }
2440
2559
  if (top <= scrollBottomBuffered) {
2441
2560
  endBuffered = i;
2442
- nextBottom = top + size;
2561
+ if (scrollBottomBuffered > totalSize) {
2562
+ nextBottom = null;
2563
+ } else {
2564
+ nextBottom = top + size;
2565
+ }
2443
2566
  } else {
2444
2567
  foundEnd = true;
2445
2568
  }
@@ -2466,7 +2589,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2466
2589
  top: nextTop
2467
2590
  } : void 0;
2468
2591
  }
2469
- const numContainers = peek$(ctx, "numContainers");
2592
+ let numContainers = prevNumContainers;
2470
2593
  const pendingRemoval = [];
2471
2594
  if (dataChanged) {
2472
2595
  for (let i = 0; i < numContainers; i++) {
@@ -2477,7 +2600,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2477
2600
  }
2478
2601
  }
2479
2602
  if (startBuffered !== null && endBuffered !== null) {
2480
- let numContainers2 = prevNumContainers;
2481
2603
  const needNewContainers = [];
2482
2604
  for (let i = startBuffered; i <= endBuffered; i++) {
2483
2605
  const id = (_h = idCache[i]) != null ? _h : getId(state, i);
@@ -2488,7 +2610,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2488
2610
  if (stickyIndicesArr.length > 0) {
2489
2611
  handleStickyActivation(
2490
2612
  ctx,
2491
- state,
2492
2613
  stickyIndicesSet,
2493
2614
  stickyIndicesArr,
2494
2615
  currentStickyIdx,
@@ -2496,9 +2617,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2496
2617
  startBuffered,
2497
2618
  endBuffered
2498
2619
  );
2499
- } else {
2500
- state.activeStickyIndex = void 0;
2501
- set$(ctx, "activeStickyIndex", void 0);
2620
+ } else if (previousStickyIndex !== -1) {
2621
+ set$(ctx, "activeStickyIndex", -1);
2502
2622
  }
2503
2623
  if (needNewContainers.length > 0) {
2504
2624
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2507,7 +2627,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2507
2627
  }) : void 0;
2508
2628
  const availableContainers = findAvailableContainers(
2509
2629
  ctx,
2510
- state,
2511
2630
  needNewContainers.length,
2512
2631
  startBuffered,
2513
2632
  endBuffered,
@@ -2529,29 +2648,30 @@ function calculateItemsInView(ctx, state, params = {}) {
2529
2648
  state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2530
2649
  }
2531
2650
  containerItemKeys.add(id);
2651
+ const containerSticky = `containerSticky${containerIndex}`;
2532
2652
  if (stickyIndicesSet.has(i)) {
2533
- set$(ctx, `containerSticky${containerIndex}`, true);
2653
+ set$(ctx, containerSticky, true);
2534
2654
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2535
2655
  set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2536
2656
  state.stickyContainerPool.add(containerIndex);
2537
- } else {
2538
- set$(ctx, `containerSticky${containerIndex}`, false);
2657
+ } else if (peek$(ctx, containerSticky)) {
2658
+ set$(ctx, containerSticky, false);
2539
2659
  state.stickyContainerPool.delete(containerIndex);
2540
2660
  }
2541
- if (containerIndex >= numContainers2) {
2542
- numContainers2 = containerIndex + 1;
2661
+ if (containerIndex >= numContainers) {
2662
+ numContainers = containerIndex + 1;
2543
2663
  }
2544
2664
  }
2545
- if (numContainers2 !== prevNumContainers) {
2546
- set$(ctx, "numContainers", numContainers2);
2547
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
2548
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
2665
+ if (numContainers !== prevNumContainers) {
2666
+ set$(ctx, "numContainers", numContainers);
2667
+ if (numContainers > peek$(ctx, "numContainersPooled")) {
2668
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
2549
2669
  }
2550
2670
  }
2551
2671
  }
2552
2672
  }
2553
2673
  if (stickyIndicesArr.length > 0) {
2554
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2674
+ handleStickyRecycling(ctx, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2555
2675
  }
2556
2676
  let didChangePositions = false;
2557
2677
  for (let i = 0; i < numContainers; i++) {
@@ -2603,7 +2723,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2603
2723
  }
2604
2724
  if (!queuedInitialLayout && endBuffered !== null) {
2605
2725
  if (checkAllSizesKnown(state)) {
2606
- setDidLayout(ctx, state);
2726
+ setDidLayout(ctx);
2607
2727
  }
2608
2728
  }
2609
2729
  if (viewabilityConfigCallbackPairs) {
@@ -2616,9 +2736,6 @@ function calculateItemsInView(ctx, state, params = {}) {
2616
2736
  }
2617
2737
  }
2618
2738
  });
2619
- if (state.initialAnchor) {
2620
- ensureInitialAnchor(ctx, state);
2621
- }
2622
2739
  }
2623
2740
 
2624
2741
  // src/core/checkActualChange.ts
@@ -2641,20 +2758,69 @@ function checkActualChange(state, dataProp, previousData) {
2641
2758
  return false;
2642
2759
  }
2643
2760
 
2761
+ // src/core/checkFinishedScroll.ts
2762
+ function checkFinishedScroll(ctx) {
2763
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
2764
+ }
2765
+ function checkFinishedScrollFrame(ctx) {
2766
+ const scrollingTo = ctx.state.scrollingTo;
2767
+ if (scrollingTo) {
2768
+ const { state } = ctx;
2769
+ state.animFrameCheckFinishedScroll = void 0;
2770
+ const scroll = state.scroll;
2771
+ const adjust = state.scrollAdjustHandler.getAdjust();
2772
+ const clampedTargetOffset = clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0));
2773
+ const maxOffset = clampScrollOffset(ctx, scroll);
2774
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
2775
+ const diff2 = Math.abs(diff1 - adjust);
2776
+ const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
2777
+ if (isNotOverscrolled && (diff1 < 1 || diff2 < 1)) {
2778
+ finishScrollTo(ctx);
2779
+ }
2780
+ }
2781
+ }
2782
+ function checkFinishedScrollFallback(ctx) {
2783
+ const state = ctx.state;
2784
+ const scrollingTo = state.scrollingTo;
2785
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || !state.didContainersLayout;
2786
+ state.timeoutCheckFinishedScrollFallback = setTimeout(
2787
+ () => {
2788
+ let numChecks = 0;
2789
+ const checkHasScrolled = () => {
2790
+ state.timeoutCheckFinishedScrollFallback = void 0;
2791
+ const isStillScrollingTo = state.scrollingTo;
2792
+ if (isStillScrollingTo) {
2793
+ numChecks++;
2794
+ if (state.hasScrolled || numChecks > 5) {
2795
+ finishScrollTo(ctx);
2796
+ } else {
2797
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
2798
+ }
2799
+ }
2800
+ };
2801
+ checkHasScrolled();
2802
+ },
2803
+ slowTimeout ? 500 : 100
2804
+ );
2805
+ }
2806
+
2644
2807
  // src/core/doMaintainScrollAtEnd.ts
2645
- function doMaintainScrollAtEnd(ctx, state, animated) {
2808
+ function doMaintainScrollAtEnd(ctx, animated) {
2809
+ const state = ctx.state;
2646
2810
  const {
2811
+ didContainersLayout,
2812
+ isAtEnd,
2647
2813
  refScroller,
2648
2814
  props: { maintainScrollAtEnd }
2649
2815
  } = state;
2650
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2816
+ if (isAtEnd && maintainScrollAtEnd && didContainersLayout) {
2651
2817
  const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2652
2818
  if (paddingTop > 0) {
2653
2819
  state.scroll = 0;
2654
2820
  }
2655
2821
  requestAnimationFrame(() => {
2656
2822
  var _a3;
2657
- if (state == null ? void 0 : state.isAtEnd) {
2823
+ if (state.isAtEnd) {
2658
2824
  state.maintainingScrollAtEnd = true;
2659
2825
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2660
2826
  animated
@@ -2725,28 +2891,30 @@ function updateAveragesOnDataChange(state, oldData, newData) {
2725
2891
  }
2726
2892
 
2727
2893
  // src/core/checkResetContainers.ts
2728
- function checkResetContainers(ctx, state, dataProp) {
2894
+ function checkResetContainers(ctx, dataProp) {
2895
+ const state = ctx.state;
2729
2896
  const { previousData } = state;
2730
2897
  if (previousData) {
2731
2898
  updateAveragesOnDataChange(state, previousData, dataProp);
2732
2899
  }
2733
2900
  const { maintainScrollAtEnd } = state.props;
2734
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2901
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2735
2902
  const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2736
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2903
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, false);
2737
2904
  if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2738
2905
  state.isEndReached = false;
2739
2906
  }
2740
2907
  if (!didMaintainScrollAtEnd) {
2741
2908
  checkAtTop(state);
2742
- checkAtBottom(ctx, state);
2909
+ checkAtBottom(ctx);
2743
2910
  }
2744
2911
  delete state.previousData;
2745
2912
  }
2746
2913
 
2747
2914
  // src/core/doInitialAllocateContainers.ts
2748
- function doInitialAllocateContainers(ctx, state) {
2915
+ function doInitialAllocateContainers(ctx) {
2749
2916
  var _a3, _b, _c;
2917
+ const state = ctx.state;
2750
2918
  const {
2751
2919
  scrollLength,
2752
2920
  props: {
@@ -2784,10 +2952,10 @@ function doInitialAllocateContainers(ctx, state) {
2784
2952
  if (state.lastLayout) {
2785
2953
  if (state.initialScroll) {
2786
2954
  requestAnimationFrame(() => {
2787
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2955
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2788
2956
  });
2789
2957
  } else {
2790
- calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2958
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
2791
2959
  }
2792
2960
  }
2793
2961
  return true;
@@ -2795,7 +2963,8 @@ function doInitialAllocateContainers(ctx, state) {
2795
2963
  }
2796
2964
 
2797
2965
  // src/core/handleLayout.ts
2798
- function handleLayout(ctx, state, layout, setCanRender) {
2966
+ function handleLayout(ctx, layout, setCanRender) {
2967
+ const state = ctx.state;
2799
2968
  const { maintainScrollAtEnd } = state.props;
2800
2969
  const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2801
2970
  const previousLength = state.scrollLength;
@@ -2811,19 +2980,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2811
2980
  state.lastBatchingAction = Date.now();
2812
2981
  state.scrollForNextCalculateItemsInView = void 0;
2813
2982
  if (scrollLength > 0) {
2814
- doInitialAllocateContainers(ctx, state);
2983
+ doInitialAllocateContainers(ctx);
2815
2984
  }
2816
2985
  if (needsCalculate) {
2817
- calculateItemsInView(ctx, state, { doMVCP: true });
2986
+ calculateItemsInView(ctx, { doMVCP: true });
2818
2987
  }
2819
2988
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
2820
2989
  set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2821
2990
  }
2822
2991
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2823
- doMaintainScrollAtEnd(ctx, state, false);
2992
+ doMaintainScrollAtEnd(ctx, false);
2824
2993
  }
2825
- updateAlignItemsPaddingTop(ctx, state);
2826
- checkAtBottom(ctx, state);
2994
+ updateAlignItemsPaddingTop(ctx);
2995
+ checkAtBottom(ctx);
2827
2996
  checkAtTop(state);
2828
2997
  if (state) {
2829
2998
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
@@ -2839,8 +3008,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2839
3008
  }
2840
3009
 
2841
3010
  // src/core/onScroll.ts
2842
- function onScroll(ctx, state, event) {
3011
+ function onScroll(ctx, event) {
2843
3012
  var _a3, _b, _c;
3013
+ const state = ctx.state;
2844
3014
  const {
2845
3015
  scrollProcessingEnabled,
2846
3016
  props: { onScroll: onScrollProp }
@@ -2851,9 +3021,23 @@ function onScroll(ctx, state, event) {
2851
3021
  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) {
2852
3022
  return;
2853
3023
  }
2854
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3024
+ let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2855
3025
  state.scrollPending = newScroll;
2856
- updateScroll(ctx, state, newScroll);
3026
+ if (state.scrollingTo) {
3027
+ const maxOffset = clampScrollOffset(ctx, newScroll);
3028
+ if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
3029
+ newScroll = maxOffset;
3030
+ scrollTo(ctx, {
3031
+ forceScroll: true,
3032
+ isInitialScroll: true,
3033
+ noScrollingTo: true,
3034
+ offset: newScroll
3035
+ });
3036
+ return;
3037
+ }
3038
+ }
3039
+ updateScroll(ctx, newScroll);
3040
+ checkFinishedScroll(ctx);
2857
3041
  onScrollProp == null ? void 0 : onScrollProp(event);
2858
3042
  }
2859
3043
 
@@ -2862,51 +3046,47 @@ var ScrollAdjustHandler = class {
2862
3046
  constructor(ctx) {
2863
3047
  this.appliedAdjust = 0;
2864
3048
  this.pendingAdjust = 0;
2865
- this.mounted = false;
2866
- this.context = ctx;
2867
- {
2868
- const commitPendingAdjust = () => {
2869
- const state = this.context.internalState;
2870
- const pending = this.pendingAdjust;
2871
- if (pending !== 0) {
2872
- this.pendingAdjust = 0;
2873
- this.appliedAdjust += pending;
2874
- state.scroll += pending;
2875
- state.scrollForNextCalculateItemsInView = void 0;
2876
- set$(this.context, "scrollAdjustPending", 0);
2877
- set$(this.context, "scrollAdjust", this.appliedAdjust);
2878
- calculateItemsInView(this.context, this.context.internalState);
2879
- }
2880
- };
2881
- listen$(this.context, "scrollingTo", (value) => {
2882
- if (value === void 0) {
2883
- commitPendingAdjust();
2884
- }
2885
- });
2886
- }
3049
+ this.ctx = ctx;
2887
3050
  }
2888
3051
  requestAdjust(add) {
2889
- const scrollingTo = peek$(this.context, "scrollingTo");
3052
+ const scrollingTo = this.ctx.state.scrollingTo;
2890
3053
  if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2891
3054
  this.pendingAdjust += add;
2892
- set$(this.context, "scrollAdjustPending", this.pendingAdjust);
3055
+ set$(this.ctx, "scrollAdjustPending", this.pendingAdjust);
2893
3056
  } else {
2894
3057
  this.appliedAdjust += add;
2895
- set$(this.context, "scrollAdjust", this.appliedAdjust);
3058
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3059
+ }
3060
+ if (this.ctx.state.scrollingTo) {
3061
+ checkFinishedScroll(this.ctx);
2896
3062
  }
2897
- }
2898
- setMounted() {
2899
- this.mounted = true;
2900
3063
  }
2901
3064
  getAdjust() {
2902
3065
  return this.appliedAdjust;
2903
3066
  }
3067
+ commitPendingAdjust() {
3068
+ {
3069
+ const state = this.ctx.state;
3070
+ const pending = this.pendingAdjust;
3071
+ if (pending !== 0) {
3072
+ this.pendingAdjust = 0;
3073
+ this.appliedAdjust += pending;
3074
+ state.scroll += pending;
3075
+ state.scrollForNextCalculateItemsInView = void 0;
3076
+ set$(this.ctx, "scrollAdjustPending", 0);
3077
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3078
+ calculateItemsInView(this.ctx);
3079
+ }
3080
+ }
3081
+ }
2904
3082
  };
2905
3083
 
2906
3084
  // src/core/updateItemSize.ts
2907
- function updateItemSize(ctx, state, itemKey, sizeObj) {
3085
+ function updateItemSize(ctx, itemKey, sizeObj) {
2908
3086
  var _a3;
3087
+ const state = ctx.state;
2909
3088
  const {
3089
+ didContainersLayout,
2910
3090
  sizesKnown,
2911
3091
  props: {
2912
3092
  getFixedItemSize,
@@ -2934,13 +3114,12 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2934
3114
  return;
2935
3115
  }
2936
3116
  }
2937
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2938
- let needsRecalculate = !containersDidLayout;
3117
+ let needsRecalculate = !didContainersLayout;
2939
3118
  let shouldMaintainScrollAtEnd = false;
2940
3119
  let minIndexSizeChanged;
2941
3120
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2942
3121
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2943
- const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
3122
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj);
2944
3123
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
2945
3124
  if (diff !== 0) {
2946
3125
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -2989,22 +3168,22 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2989
3168
  if (!cur || maxOtherAxisSize > cur) {
2990
3169
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
2991
3170
  }
2992
- if (containersDidLayout || checkAllSizesKnown(state)) {
3171
+ if (didContainersLayout || checkAllSizesKnown(state)) {
2993
3172
  if (needsRecalculate) {
2994
3173
  state.scrollForNextCalculateItemsInView = void 0;
2995
- calculateItemsInView(ctx, state, { doMVCP: true });
3174
+ calculateItemsInView(ctx, { doMVCP: true });
2996
3175
  }
2997
3176
  if (shouldMaintainScrollAtEnd) {
2998
3177
  if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
2999
- doMaintainScrollAtEnd(ctx, state, false);
3178
+ doMaintainScrollAtEnd(ctx, false);
3000
3179
  }
3001
3180
  }
3002
3181
  }
3003
3182
  }
3004
- function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3183
+ function updateOneItemSize(ctx, itemKey, sizeObj) {
3005
3184
  var _a3;
3185
+ const state = ctx.state;
3006
3186
  const {
3007
- sizes,
3008
3187
  indexByKey,
3009
3188
  sizesKnown,
3010
3189
  averageSizes,
@@ -3012,9 +3191,10 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3012
3191
  } = state;
3013
3192
  if (!data) return 0;
3014
3193
  const index = indexByKey.get(itemKey);
3015
- const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
3194
+ const prevSize = getItemSize(ctx, itemKey, index, data[index]);
3016
3195
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
3017
3196
  const size = Math.round(rawSize) ;
3197
+ const prevSizeKnown = sizesKnown.get(itemKey);
3018
3198
  sizesKnown.set(itemKey, size);
3019
3199
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
3020
3200
  const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
@@ -3022,11 +3202,15 @@ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3022
3202
  if (!averages) {
3023
3203
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
3024
3204
  }
3025
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3026
- averages.num++;
3205
+ if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3206
+ averages.avg += (size - prevSizeKnown) / averages.num;
3207
+ } else {
3208
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3209
+ averages.num++;
3210
+ }
3027
3211
  }
3028
3212
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
3029
- setSize(ctx, state, itemKey, size);
3213
+ setSize(ctx, itemKey, size);
3030
3214
  return size - prevSize;
3031
3215
  }
3032
3216
  return 0;
@@ -3073,14 +3257,15 @@ function createColumnWrapperStyle(contentContainerStyle) {
3073
3257
  }
3074
3258
 
3075
3259
  // src/utils/createImperativeHandle.ts
3076
- function createImperativeHandle(ctx, state) {
3260
+ function createImperativeHandle(ctx) {
3261
+ const state = ctx.state;
3077
3262
  const scrollIndexIntoView = (options) => {
3078
3263
  if (state) {
3079
3264
  const { index, ...rest } = options;
3080
3265
  const { startNoBuffer, endNoBuffer } = state;
3081
3266
  if (index < startNoBuffer || index > endNoBuffer) {
3082
3267
  const viewPosition = index < startNoBuffer ? 0 : 1;
3083
- scrollToIndex(ctx, state, {
3268
+ scrollToIndex(ctx, {
3084
3269
  ...rest,
3085
3270
  index,
3086
3271
  viewPosition
@@ -3095,7 +3280,7 @@ function createImperativeHandle(ctx, state) {
3095
3280
  getScrollableNode: () => refScroller.current.getScrollableNode(),
3096
3281
  getScrollResponder: () => refScroller.current.getScrollResponder(),
3097
3282
  getState: () => ({
3098
- activeStickyIndex: state.activeStickyIndex,
3283
+ activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3099
3284
  contentLength: state.totalSize,
3100
3285
  data: state.props.data,
3101
3286
  elementAtIndex: (index) => {
@@ -3106,6 +3291,8 @@ function createImperativeHandle(ctx, state) {
3106
3291
  endBuffered: state.endBuffered,
3107
3292
  isAtEnd: state.isAtEnd,
3108
3293
  isAtStart: state.isAtStart,
3294
+ listen: (signalName, cb) => listen$(ctx, signalName, cb),
3295
+ listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
3109
3296
  positionAtIndex: (index) => state.positions.get(getId(state, index)),
3110
3297
  positions: state.positions,
3111
3298
  scroll: state.scroll,
@@ -3130,23 +3317,23 @@ function createImperativeHandle(ctx, state) {
3130
3317
  if (index !== -1) {
3131
3318
  const paddingBottom = stylePaddingBottom || 0;
3132
3319
  const footerSize = peek$(ctx, "footerSize") || 0;
3133
- scrollToIndex(ctx, state, {
3320
+ scrollToIndex(ctx, {
3321
+ ...options,
3134
3322
  index,
3135
3323
  viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3136
- viewPosition: 1,
3137
- ...options
3324
+ viewPosition: 1
3138
3325
  });
3139
3326
  }
3140
3327
  },
3141
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3328
+ scrollToIndex: (params) => scrollToIndex(ctx, params),
3142
3329
  scrollToItem: ({ item, ...props }) => {
3143
3330
  const data = state.props.data;
3144
3331
  const index = data.indexOf(item);
3145
3332
  if (index !== -1) {
3146
- scrollToIndex(ctx, state, { index, ...props });
3333
+ scrollToIndex(ctx, { index, ...props });
3147
3334
  }
3148
3335
  },
3149
- scrollToOffset: (params) => scrollTo(ctx, state, params),
3336
+ scrollToOffset: (params) => scrollTo(ctx, params),
3150
3337
  setScrollProcessingEnabled: (enabled) => {
3151
3338
  state.scrollProcessingEnabled = enabled;
3152
3339
  },
@@ -3156,8 +3343,9 @@ function createImperativeHandle(ctx, state) {
3156
3343
  }
3157
3344
  };
3158
3345
  }
3159
- function getRenderedItem(ctx, state, key) {
3346
+ function getRenderedItem(ctx, key) {
3160
3347
  var _a3;
3348
+ const state = ctx.state;
3161
3349
  if (!state) {
3162
3350
  return null;
3163
3351
  }
@@ -3234,11 +3422,13 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3234
3422
  var DEFAULT_DRAW_DISTANCE = 250;
3235
3423
  var DEFAULT_ITEM_SIZE = 100;
3236
3424
  var LegendList = typedMemo(
3425
+ // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
3237
3426
  typedForwardRef(function LegendList2(props, forwardedRef) {
3238
3427
  const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
3239
3428
  const isChildrenMode = children !== void 0 && dataProp === void 0;
3240
3429
  const processedProps = isChildrenMode ? {
3241
3430
  ...restProps,
3431
+ childrenMode: true,
3242
3432
  data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
3243
3433
  renderItem: ({ item }) => item
3244
3434
  } : {
@@ -3255,10 +3445,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3255
3445
  alignItemsAtEnd = false,
3256
3446
  columnWrapperStyle,
3257
3447
  contentContainerStyle: contentContainerStyleProp,
3448
+ contentInset,
3258
3449
  data: dataProp = [],
3259
3450
  dataVersion,
3260
3451
  drawDistance = 250,
3261
- enableAverages = true,
3262
3452
  estimatedItemSize: estimatedItemSizeProp,
3263
3453
  estimatedListSize,
3264
3454
  extraData,
@@ -3300,6 +3490,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3300
3490
  snapToIndices,
3301
3491
  stickyHeaderIndices: stickyHeaderIndicesProp,
3302
3492
  stickyIndices: stickyIndicesDeprecated,
3493
+ // TODOV3: Remove from v3 release
3303
3494
  style: styleProp,
3304
3495
  suggestEstimatedItemSize,
3305
3496
  viewabilityConfig,
@@ -3307,6 +3498,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3307
3498
  waitForInitialLayout = true,
3308
3499
  ...rest
3309
3500
  } = props;
3501
+ const animatedPropsInternal = props.animatedPropsInternal;
3502
+ const { childrenMode } = rest;
3310
3503
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3311
3504
  const style = { ...StyleSheet.flatten(styleProp) };
3312
3505
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
@@ -3330,10 +3523,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3330
3523
  }
3331
3524
  const refState = React3.useRef();
3332
3525
  if (!refState.current) {
3333
- if (!ctx.internalState) {
3526
+ if (!ctx.state) {
3334
3527
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
3335
- ctx.internalState = {
3336
- activeStickyIndex: void 0,
3528
+ ctx.state = {
3529
+ activeStickyIndex: -1,
3337
3530
  averageSizes: {},
3338
3531
  columns: /* @__PURE__ */ new Map(),
3339
3532
  containerItemKeys: /* @__PURE__ */ new Set(),
@@ -3359,9 +3552,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3359
3552
  initialScroll: initialScrollProp,
3360
3553
  isAtEnd: false,
3361
3554
  isAtStart: false,
3362
- isEndReached: false,
3555
+ isEndReached: null,
3363
3556
  isFirst: true,
3364
- isStartReached: false,
3557
+ isStartReached: null,
3365
3558
  lastBatchingAction: Date.now(),
3366
3559
  lastLayout: void 0,
3367
3560
  loadStartTime: Date.now(),
@@ -3393,12 +3586,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3393
3586
  totalSize: 0,
3394
3587
  viewabilityConfigCallbackPairs: void 0
3395
3588
  };
3396
- const internalState = ctx.internalState;
3397
- internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3589
+ const internalState = ctx.state;
3590
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
3398
3591
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3399
3592
  set$(ctx, "extraData", extraData);
3400
3593
  }
3401
- refState.current = ctx.internalState;
3594
+ refState.current = ctx.state;
3402
3595
  }
3403
3596
  const state = refState.current;
3404
3597
  const isFirstLocal = state.isFirst;
@@ -3412,9 +3605,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3412
3605
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
3413
3606
  state.props = {
3414
3607
  alignItemsAtEnd,
3608
+ animatedProps: animatedPropsInternal,
3609
+ contentInset,
3415
3610
  data: dataProp,
3416
3611
  dataVersion,
3417
- enableAverages,
3418
3612
  estimatedItemSize,
3419
3613
  getEstimatedItemSize,
3420
3614
  getFixedItemSize,
@@ -3457,62 +3651,52 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3457
3651
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3458
3652
  set$(ctx, "numColumns", numColumnsProp);
3459
3653
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
3460
- setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
3654
+ setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
3461
3655
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3462
3656
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3463
3657
  if (paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3464
3658
  if (state.scroll < 0) {
3465
3659
  paddingDiff += state.scroll;
3466
3660
  }
3467
- requestAdjust(ctx, state, paddingDiff);
3661
+ requestAdjust(ctx, paddingDiff);
3468
3662
  }
3469
3663
  };
3470
3664
  if (isFirstLocal) {
3471
3665
  initializeStateVars();
3472
3666
  updateItemPositions(
3473
3667
  ctx,
3474
- state,
3475
3668
  /*dataChanged*/
3476
3669
  true
3477
3670
  );
3478
3671
  }
3479
3672
  const initialContentOffset = React3.useMemo(() => {
3480
- var _a4, _b2;
3481
- const { initialScroll } = refState.current;
3482
- if (!initialScroll) {
3673
+ let value;
3674
+ const { initialScroll, initialAnchor } = refState.current;
3675
+ if (initialScroll) {
3676
+ if (initialScroll.contentOffset !== void 0) {
3677
+ value = initialScroll.contentOffset;
3678
+ } else {
3679
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
3680
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
3681
+ const clampedOffset = clampScrollOffset(ctx, resolvedOffset);
3682
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3683
+ refState.current.initialScroll = updatedInitialScroll;
3684
+ state.initialScroll = updatedInitialScroll;
3685
+ value = clampedOffset;
3686
+ }
3687
+ } else {
3483
3688
  refState.current.initialAnchor = void 0;
3484
- return 0;
3485
- }
3486
- if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3487
- refState.current.initialAnchor = {
3488
- attempts: 0,
3489
- index: initialScroll.index,
3490
- settledTicks: 0,
3491
- viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3492
- viewPosition: initialScroll.viewPosition
3493
- };
3689
+ value = 0;
3494
3690
  }
3495
- if (initialScroll.contentOffset !== void 0) {
3496
- return initialScroll.contentOffset;
3497
- }
3498
- const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3499
- const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3500
- let clampedOffset = resolvedOffset;
3501
- if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3502
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3503
- clampedOffset = Math.min(clampedOffset, maxOffset);
3504
- }
3505
- clampedOffset = Math.max(0, clampedOffset);
3506
- const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3507
- refState.current.initialScroll = updatedInitialScroll;
3508
- state.initialScroll = updatedInitialScroll;
3509
- refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3510
- return clampedOffset;
3691
+ if (!value) {
3692
+ state.didFinishInitialScroll = true;
3693
+ }
3694
+ return value;
3511
3695
  }, [renderNum]);
3512
3696
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3513
3697
  refState.current.lastBatchingAction = Date.now();
3514
3698
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3515
- IS_DEV && warnDevOnce(
3699
+ IS_DEV && !childrenMode && warnDevOnce(
3516
3700
  "keyExtractor",
3517
3701
  "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."
3518
3702
  );
@@ -3535,12 +3719,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3535
3719
  }
3536
3720
  }, []);
3537
3721
  const doInitialScroll = React3.useCallback(() => {
3538
- var _a4;
3539
3722
  const initialScroll = state.initialScroll;
3540
3723
  if (initialScroll) {
3541
- scrollTo(ctx, state, {
3724
+ scrollTo(ctx, {
3542
3725
  animated: false,
3543
- index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3726
+ index: initialScroll == null ? void 0 : initialScroll.index,
3544
3727
  isInitialScroll: true,
3545
3728
  offset: initialContentOffset,
3546
3729
  precomputedWithViewOffset: true
@@ -3549,7 +3732,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3549
3732
  }, [initialContentOffset]);
3550
3733
  const onLayoutChange = React3.useCallback((layout) => {
3551
3734
  doInitialScroll();
3552
- handleLayout(ctx, state, layout, setCanRender);
3735
+ handleLayout(ctx, layout, setCanRender);
3553
3736
  }, []);
3554
3737
  const { onLayout } = useOnLayoutSync({
3555
3738
  onLayoutChange,
@@ -3559,7 +3742,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3559
3742
  });
3560
3743
  React3.useLayoutEffect(() => {
3561
3744
  if (snapToIndices) {
3562
- updateSnapToOffsets(ctx, state);
3745
+ updateSnapToOffsets(ctx);
3563
3746
  }
3564
3747
  }, [snapToIndices]);
3565
3748
  React3.useLayoutEffect(() => {
@@ -3569,9 +3752,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3569
3752
  isFirst,
3570
3753
  props: { data }
3571
3754
  } = state;
3572
- const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3755
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx);
3573
3756
  if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3574
- checkResetContainers(ctx, state, data);
3757
+ checkResetContainers(ctx, data);
3575
3758
  }
3576
3759
  state.didColumnsChange = false;
3577
3760
  state.didDataChange = false;
@@ -3596,15 +3779,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3596
3779
  state.viewabilityConfigCallbackPairs = viewability;
3597
3780
  state.enableScrollForNextCalculateItemsInView = !viewability;
3598
3781
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3599
- React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3782
+ React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
3600
3783
  {
3601
3784
  React3.useEffect(doInitialScroll, []);
3602
3785
  }
3603
3786
  const fns = React3.useMemo(
3604
3787
  () => ({
3605
- getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3606
- onScroll: (event) => onScroll(ctx, state, event),
3607
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
3788
+ getRenderedItem: (key) => getRenderedItem(ctx, key),
3789
+ onMomentumScrollEnd: (event) => {
3790
+ checkFinishedScrollFallback(ctx);
3791
+ if (onMomentumScrollEnd) {
3792
+ onMomentumScrollEnd(event);
3793
+ }
3794
+ },
3795
+ onScroll: (event) => onScroll(ctx, event),
3796
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, itemKey, sizeObj)
3608
3797
  }),
3609
3798
  []
3610
3799
  );
@@ -3616,6 +3805,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3616
3805
  alignItemsAtEnd,
3617
3806
  canRender,
3618
3807
  contentContainerStyle,
3808
+ contentInset,
3619
3809
  getRenderedItem: fns.getRenderedItem,
3620
3810
  horizontal,
3621
3811
  initialContentOffset,
@@ -3624,16 +3814,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3624
3814
  maintainVisibleContentPosition,
3625
3815
  onLayout,
3626
3816
  onLayoutHeader,
3627
- onMomentumScrollEnd: (event) => {
3628
- {
3629
- requestAnimationFrame(() => {
3630
- finishScrollTo(ctx, refState.current);
3631
- });
3632
- }
3633
- if (onMomentumScrollEnd) {
3634
- onMomentumScrollEnd(event);
3635
- }
3636
- },
3817
+ onMomentumScrollEnd: fns.onMomentumScrollEnd,
3637
3818
  onScroll: onScrollHandler,
3638
3819
  recycleItems,
3639
3820
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
@@ -3648,7 +3829,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3648
3829
  ),
3649
3830
  refScrollView: combinedRef,
3650
3831
  scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3651
- scrollEventThrottle: 16 ,
3832
+ scrollEventThrottle: 0,
3652
3833
  snapToIndices,
3653
3834
  stickyHeaderIndices,
3654
3835
  style,
@@ -3694,8 +3875,8 @@ function buildSectionListData({
3694
3875
  if (hasHeader) {
3695
3876
  const headerIndex = data.length;
3696
3877
  data.push({
3697
- kind: "header",
3698
3878
  key: `${sectionKey}:header`,
3879
+ kind: "header",
3699
3880
  section,
3700
3881
  sectionIndex
3701
3882
  });
@@ -3709,31 +3890,31 @@ function buildSectionListData({
3709
3890
  const itemKeyExtractor = (_b = section.keyExtractor) != null ? _b : keyExtractor;
3710
3891
  const itemKey = itemKeyExtractor(item, itemIndex);
3711
3892
  data.push({
3712
- kind: "item",
3713
- key: `${sectionKey}:item:${itemKey}`,
3714
- section,
3715
- sectionIndex,
3893
+ absoluteItemIndex: absoluteItemIndex++,
3716
3894
  item,
3717
3895
  itemIndex,
3718
- absoluteItemIndex: absoluteItemIndex++
3896
+ key: `${sectionKey}:item:${itemKey}`,
3897
+ kind: "item",
3898
+ section,
3899
+ sectionIndex
3719
3900
  });
3720
3901
  meta.items.push(data.length - 1);
3721
3902
  if (hasItemSeparator && itemIndex < items.length - 1) {
3722
3903
  data.push({
3723
- kind: "item-separator",
3724
3904
  key: `${sectionKey}:separator:${itemIndex}`,
3725
- section,
3726
- sectionIndex,
3905
+ kind: "item-separator",
3727
3906
  leadingItem: item,
3728
3907
  leadingItemIndex: itemIndex,
3908
+ section,
3909
+ sectionIndex,
3729
3910
  trailingItem: items[itemIndex + 1]
3730
3911
  });
3731
3912
  }
3732
3913
  }
3733
3914
  if (hasFooter) {
3734
3915
  data.push({
3735
- kind: "footer",
3736
3916
  key: `${sectionKey}:footer`,
3917
+ kind: "footer",
3737
3918
  section,
3738
3919
  sectionIndex
3739
3920
  });
@@ -3742,8 +3923,8 @@ function buildSectionListData({
3742
3923
  const isLastSection = sectionIndex === sections.length - 1;
3743
3924
  if (hasSectionSeparator && !isLastSection) {
3744
3925
  data.push({
3745
- kind: "section-separator",
3746
3926
  key: `${sectionKey}:section-separator`,
3927
+ kind: "section-separator",
3747
3928
  leadingSection: section,
3748
3929
  leadingSectionIndex: sectionIndex,
3749
3930
  trailingSection: sections[sectionIndex + 1]