@legendapp/list 2.1.0-beta.1 → 2.1.0-beta.2

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.
Files changed (5) hide show
  1. package/index.d.mts +13 -11
  2. package/index.d.ts +13 -11
  3. package/index.js +294 -249
  4. package/index.mjs +294 -249
  5. package/package.json +1 -1
package/index.js CHANGED
@@ -54,7 +54,10 @@ function StateProvider({ children }) {
54
54
  ["stylePaddingTop", 0],
55
55
  ["headerSize", 0],
56
56
  ["numContainers", 0],
57
- ["totalSize", 0]
57
+ ["activeStickyIndex", void 0],
58
+ ["totalSize", 0],
59
+ ["scrollAdjustPending", 0],
60
+ ["scrollingTo", void 0]
58
61
  ]),
59
62
  viewRefs: /* @__PURE__ */ new Map()
60
63
  }));
@@ -217,8 +220,11 @@ var PositionViewState = typedMemo(function PositionView({
217
220
  ...rest
218
221
  }) {
219
222
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
220
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
221
- const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
223
+ const base = {
224
+ contain: "paint layout style"
225
+ };
226
+ const composed = Array.isArray(style) ? Object.assign({}, ...style) : style;
227
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
222
228
  return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
223
229
  });
224
230
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
@@ -227,19 +233,42 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
227
233
  style,
228
234
  refView,
229
235
  index,
236
+ stickyOffset,
237
+ animatedScrollY: _animatedScrollY,
238
+ children,
230
239
  ...rest
231
240
  }) {
232
- const [position = POSITION_OUT_OF_VIEW, _headerSize] = useArr$([`containerPosition${id}`, "headerSize"]);
241
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, activeStickyIndex] = useArr$([
242
+ `containerPosition${id}`,
243
+ "headerSize",
244
+ "activeStickyIndex"
245
+ ]);
246
+ const base = {
247
+ contain: "paint layout style"
248
+ };
249
+ const composed = React3__namespace.useMemo(
250
+ () => {
251
+ var _a3;
252
+ return (_a3 = Array.isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
253
+ },
254
+ [style]
255
+ );
233
256
  const viewStyle = React3__namespace.useMemo(() => {
234
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
235
- const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
236
- return {
237
- ...base,
238
- zIndex: index + 1e3,
239
- ...axisStyle
240
- };
241
- }, [style, position, horizontal, index]);
242
- return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest });
257
+ var _a3;
258
+ const styleBase = { ...base, ...composed };
259
+ delete styleBase.transform;
260
+ const offset = (_a3 = stickyOffset != null ? stickyOffset : headerSize) != null ? _a3 : 0;
261
+ const isActive = activeStickyIndex === index;
262
+ styleBase.position = isActive ? "sticky" : "absolute";
263
+ styleBase.zIndex = index + 1e3;
264
+ if (horizontal) {
265
+ styleBase.left = isActive ? offset : position;
266
+ } else {
267
+ styleBase.top = isActive ? offset : position;
268
+ }
269
+ return styleBase;
270
+ }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
271
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
243
272
  });
244
273
  var PositionView2 = PositionViewState;
245
274
 
@@ -991,10 +1020,11 @@ function PaddingDevMode() {
991
1020
  function useValueListener$(key, callback) {
992
1021
  const ctx = useStateContext();
993
1022
  React3.useLayoutEffect(() => {
994
- listen$(ctx, key, (value) => {
1023
+ const unsubscribe = listen$(ctx, key, (value) => {
995
1024
  callback(value);
996
1025
  });
997
- }, []);
1026
+ return unsubscribe;
1027
+ }, [callback, ctx, key]);
998
1028
  }
999
1029
 
1000
1030
  // src/components/ScrollAdjust.tsx
@@ -1160,12 +1190,11 @@ function calculateOffsetForIndex(ctx, state, index) {
1160
1190
  }
1161
1191
 
1162
1192
  // src/utils/getItemSize.ts
1163
- function getItemSize(state, key, index, data, useAverageSize) {
1193
+ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1164
1194
  var _a3, _b;
1165
1195
  const {
1166
1196
  sizesKnown,
1167
1197
  sizes,
1168
- scrollingTo,
1169
1198
  averageSizes,
1170
1199
  props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1171
1200
  } = state;
@@ -1175,6 +1204,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
1175
1204
  }
1176
1205
  let size;
1177
1206
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1207
+ const scrollingTo = peek$(ctx, "scrollingTo");
1178
1208
  if (getFixedItemSize) {
1179
1209
  size = getFixedItemSize(index, data, itemType);
1180
1210
  if (size !== void 0) {
@@ -1201,41 +1231,211 @@ function getItemSize(state, key, index, data, useAverageSize) {
1201
1231
  }
1202
1232
 
1203
1233
  // src/core/calculateOffsetWithOffsetPosition.ts
1204
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1234
+ function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1205
1235
  const { index, viewOffset, viewPosition } = params;
1206
1236
  let offset = offsetParam;
1207
1237
  if (viewOffset) {
1208
1238
  offset -= viewOffset;
1209
1239
  }
1210
1240
  if (viewPosition !== void 0 && index !== void 0) {
1211
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1241
+ offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1212
1242
  }
1213
1243
  return offset;
1214
1244
  }
1215
1245
 
1246
+ // src/utils/checkThreshold.ts
1247
+ var HYSTERESIS_MULTIPLIER = 1.3;
1248
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1249
+ const absDistance = Math.abs(distance);
1250
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1251
+ const updateSnapshot = () => {
1252
+ setSnapshot == null ? void 0 : setSnapshot({
1253
+ atThreshold,
1254
+ contentSize: context.contentSize,
1255
+ dataLength: context.dataLength,
1256
+ scrollPosition: context.scrollPosition
1257
+ });
1258
+ };
1259
+ if (!wasReached) {
1260
+ if (!within) {
1261
+ return false;
1262
+ }
1263
+ onReached == null ? void 0 : onReached(distance);
1264
+ updateSnapshot();
1265
+ return true;
1266
+ }
1267
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1268
+ if (reset) {
1269
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
1270
+ return false;
1271
+ }
1272
+ if (within) {
1273
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1274
+ if (changed) {
1275
+ onReached == null ? void 0 : onReached(distance);
1276
+ updateSnapshot();
1277
+ }
1278
+ }
1279
+ return true;
1280
+ };
1281
+
1282
+ // src/utils/checkAtBottom.ts
1283
+ function checkAtBottom(ctx, state) {
1284
+ var _a3;
1285
+ if (!state) {
1286
+ return;
1287
+ }
1288
+ const {
1289
+ queuedInitialLayout,
1290
+ scrollLength,
1291
+ scroll,
1292
+ maintainingScrollAtEnd,
1293
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1294
+ } = state;
1295
+ const contentSize = getContentSize(ctx);
1296
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1297
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1298
+ const isContentLess = contentSize < scrollLength;
1299
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1300
+ state.isEndReached = checkThreshold(
1301
+ distanceFromEnd,
1302
+ isContentLess,
1303
+ onEndReachedThreshold * scrollLength,
1304
+ state.isEndReached,
1305
+ state.endReachedSnapshot,
1306
+ {
1307
+ contentSize,
1308
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1309
+ scrollPosition: scroll
1310
+ },
1311
+ (distance) => {
1312
+ var _a4, _b;
1313
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1314
+ },
1315
+ (snapshot) => {
1316
+ state.endReachedSnapshot = snapshot;
1317
+ }
1318
+ );
1319
+ }
1320
+ }
1321
+
1322
+ // src/utils/checkAtTop.ts
1323
+ function checkAtTop(state) {
1324
+ var _a3;
1325
+ if (!state) {
1326
+ return;
1327
+ }
1328
+ const {
1329
+ scrollLength,
1330
+ scroll,
1331
+ props: { onStartReachedThreshold }
1332
+ } = state;
1333
+ const distanceFromTop = scroll;
1334
+ state.isAtStart = distanceFromTop <= 0;
1335
+ state.isStartReached = checkThreshold(
1336
+ distanceFromTop,
1337
+ false,
1338
+ onStartReachedThreshold * scrollLength,
1339
+ state.isStartReached,
1340
+ state.startReachedSnapshot,
1341
+ {
1342
+ contentSize: state.totalSize,
1343
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1344
+ scrollPosition: scroll
1345
+ },
1346
+ (distance) => {
1347
+ var _a4, _b;
1348
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1349
+ },
1350
+ (snapshot) => {
1351
+ state.startReachedSnapshot = snapshot;
1352
+ }
1353
+ );
1354
+ }
1355
+
1356
+ // src/core/onScroll.ts
1357
+ function onScroll(ctx, state, event) {
1358
+ var _a3, _b, _c;
1359
+ const {
1360
+ scrollProcessingEnabled,
1361
+ props: { onScroll: onScrollProp }
1362
+ } = state;
1363
+ if (scrollProcessingEnabled === false) {
1364
+ return;
1365
+ }
1366
+ 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) {
1367
+ return;
1368
+ }
1369
+ const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
1370
+ state.scrollPending = newScroll;
1371
+ updateScroll(ctx, state, newScroll);
1372
+ onScrollProp == null ? void 0 : onScrollProp(event);
1373
+ }
1374
+ function updateScroll(ctx, state, newScroll, forceUpdate) {
1375
+ const scrollingTo = peek$(ctx, "scrollingTo");
1376
+ state.hasScrolled = true;
1377
+ state.lastBatchingAction = Date.now();
1378
+ const currentTime = Date.now();
1379
+ const adjust = state.scrollAdjustHandler.getAdjust();
1380
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1381
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1382
+ if (adjustChanged) {
1383
+ state.scrollHistory.length = 0;
1384
+ }
1385
+ state.lastScrollAdjustForHistory = adjust;
1386
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1387
+ if (!adjustChanged) {
1388
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1389
+ }
1390
+ }
1391
+ if (state.scrollHistory.length > 5) {
1392
+ state.scrollHistory.shift();
1393
+ }
1394
+ state.scrollPrev = state.scroll;
1395
+ state.scrollPrevTime = state.scrollTime;
1396
+ state.scroll = newScroll;
1397
+ state.scrollTime = currentTime;
1398
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1399
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1400
+ const { lt, gt } = ignoreScrollFromMVCP;
1401
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1402
+ state.ignoreScrollFromMVCPIgnored = true;
1403
+ return;
1404
+ }
1405
+ }
1406
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1407
+ state.ignoreScrollFromMVCPIgnored = false;
1408
+ calculateItemsInView(ctx, state, { doMVCP: scrollingTo !== void 0 });
1409
+ checkAtBottom(ctx, state);
1410
+ checkAtTop(state);
1411
+ state.dataChangeNeedsScrollUpdate = false;
1412
+ }
1413
+ }
1414
+
1216
1415
  // src/core/finishScrollTo.ts
1217
- var finishScrollTo = (state) => {
1416
+ function finishScrollTo(ctx, state) {
1218
1417
  if (state) {
1219
- state.scrollingTo = void 0;
1418
+ set$(ctx, "scrollingTo", void 0);
1220
1419
  state.scrollHistory.length = 0;
1221
1420
  }
1222
- };
1421
+ }
1223
1422
 
1224
1423
  // src/core/scrollTo.ts
1225
- function scrollTo(state, params = {}) {
1424
+ function scrollTo(ctx, state, params) {
1226
1425
  var _a3;
1227
- const { animated, noScrollingTo, isInitialScroll } = params;
1426
+ const { noScrollingTo, ...scrollTarget } = params;
1427
+ const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1228
1428
  const {
1229
1429
  refScroller,
1230
1430
  props: { horizontal }
1231
1431
  } = state;
1232
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1432
+ const offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1233
1433
  state.scrollHistory.length = 0;
1234
1434
  if (!noScrollingTo) {
1235
- state.scrollingTo = params;
1435
+ set$(ctx, "scrollingTo", scrollTarget);
1236
1436
  }
1237
1437
  state.scrollPending = offset;
1238
- if (!params.isInitialScroll || Platform.OS === "android") {
1438
+ if (!isInitialScroll || Platform.OS === "android") {
1239
1439
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1240
1440
  animated: !!animated,
1241
1441
  x: horizontal ? offset : 0,
@@ -1244,7 +1444,7 @@ function scrollTo(state, params = {}) {
1244
1444
  }
1245
1445
  if (!animated) {
1246
1446
  state.scroll = offset;
1247
- setTimeout(() => finishScrollTo(state), 100);
1447
+ setTimeout(() => finishScrollTo(ctx, state), 100);
1248
1448
  if (isInitialScroll) {
1249
1449
  setTimeout(() => {
1250
1450
  state.initialScroll = void 0;
@@ -1266,24 +1466,6 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1266
1466
  const didLayout = peek$(ctx, "containersDidLayout");
1267
1467
  if (didLayout) {
1268
1468
  doit();
1269
- const threshold = state.scroll - positionDiff / 2;
1270
- if (!state.ignoreScrollFromMVCP) {
1271
- state.ignoreScrollFromMVCP = {};
1272
- }
1273
- if (positionDiff > 0) {
1274
- state.ignoreScrollFromMVCP.lt = threshold;
1275
- } else {
1276
- state.ignoreScrollFromMVCP.gt = threshold;
1277
- }
1278
- if (state.ignoreScrollFromMVCPTimeout) {
1279
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1280
- }
1281
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1282
- () => {
1283
- state.ignoreScrollFromMVCP = void 0;
1284
- },
1285
- 100
1286
- );
1287
1469
  } else {
1288
1470
  requestAnimationFrame(doit);
1289
1471
  }
@@ -1295,9 +1477,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1295
1477
  const {
1296
1478
  idsInView,
1297
1479
  positions,
1298
- scrollingTo,
1299
1480
  props: { maintainVisibleContentPosition }
1300
1481
  } = state;
1482
+ const scrollingTo = peek$(ctx, "scrollingTo");
1301
1483
  let prevPosition;
1302
1484
  let targetId;
1303
1485
  const idsInViewWithPositions = [];
@@ -1373,7 +1555,7 @@ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1373
1555
  const prevId = state.idCache[prevIndex];
1374
1556
  const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1375
1557
  const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1376
- const prevRowHeight = calculateRowMaxSize(state, prevRowStart, prevIndex, useAverageSize);
1558
+ const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1377
1559
  currentRowTop = prevPosition + prevRowHeight;
1378
1560
  }
1379
1561
  return {
@@ -1396,7 +1578,7 @@ function findRowStartIndex(state, numColumns, index) {
1396
1578
  }
1397
1579
  return rowStart;
1398
1580
  }
1399
- function calculateRowMaxSize(state, startIndex, endIndex, useAverageSize) {
1581
+ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1400
1582
  if (endIndex < startIndex) {
1401
1583
  return 0;
1402
1584
  }
@@ -1410,7 +1592,7 @@ function calculateRowMaxSize(state, startIndex, endIndex, useAverageSize) {
1410
1592
  continue;
1411
1593
  }
1412
1594
  const id = state.idCache[i];
1413
- const size = getItemSize(state, id, i, data[i], useAverageSize);
1595
+ const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1414
1596
  if (size > maxSize) {
1415
1597
  maxSize = size;
1416
1598
  }
@@ -1466,7 +1648,7 @@ function updateTotalSize(ctx, state) {
1466
1648
  if (lastId !== void 0) {
1467
1649
  const lastPosition = positions.get(lastId);
1468
1650
  if (lastPosition !== void 0) {
1469
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1651
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1470
1652
  if (lastSize !== void 0) {
1471
1653
  const totalSize = lastPosition + lastSize;
1472
1654
  addTotalSize(ctx, state, null, totalSize);
@@ -1524,6 +1706,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1524
1706
  const data = state.props.data;
1525
1707
  const dataLength = data.length;
1526
1708
  const numColumns = peek$(ctx, "numColumns");
1709
+ const scrollingTo = peek$(ctx, "scrollingTo");
1527
1710
  const hasColumns = numColumns > 1;
1528
1711
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1529
1712
  const maxVisibleArea = scrollBottomBuffered + 1e3;
@@ -1545,7 +1728,7 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1545
1728
  const prevIndex = startIndex - 1;
1546
1729
  const prevId = getId(state, prevIndex);
1547
1730
  const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1548
- const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1731
+ const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1549
1732
  currentRowTop = prevPosition + prevSize;
1550
1733
  }
1551
1734
  }
@@ -1557,12 +1740,12 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1557
1740
  didBreakEarly = true;
1558
1741
  break;
1559
1742
  }
1560
- if (breakAt === void 0 && !dataChanged && currentRowTop > maxVisibleArea) {
1743
+ if (breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
1561
1744
  const itemsPerRow = hasColumns ? numColumns : 1;
1562
1745
  breakAt = i + itemsPerRow + 10;
1563
1746
  }
1564
1747
  const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1565
- const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(state, id, i, data[i], useAverageSize);
1748
+ const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1566
1749
  if (IS_DEV && needsIndexByKey) {
1567
1750
  if (indexByKeyForChecking.has(id)) {
1568
1751
  console.error(
@@ -1986,7 +2169,7 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1986
2169
  viewPosition = 1;
1987
2170
  }
1988
2171
  state.scrollForNextCalculateItemsInView = void 0;
1989
- scrollTo(state, {
2172
+ scrollTo(ctx, state, {
1990
2173
  animated,
1991
2174
  index,
1992
2175
  offset: firstIndexOffset,
@@ -1995,82 +2178,6 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1995
2178
  });
1996
2179
  }
1997
2180
 
1998
- // src/utils/checkThreshold.ts
1999
- var HYSTERESIS_MULTIPLIER = 1.3;
2000
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
2001
- const absDistance = Math.abs(distance);
2002
- const within = atThreshold || threshold > 0 && absDistance <= threshold;
2003
- const updateSnapshot = () => {
2004
- setSnapshot == null ? void 0 : setSnapshot({
2005
- atThreshold,
2006
- contentSize: context.contentSize,
2007
- dataLength: context.dataLength,
2008
- scrollPosition: context.scrollPosition
2009
- });
2010
- };
2011
- if (!wasReached) {
2012
- if (!within) {
2013
- return false;
2014
- }
2015
- onReached == null ? void 0 : onReached(distance);
2016
- updateSnapshot();
2017
- return true;
2018
- }
2019
- const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
2020
- if (reset) {
2021
- setSnapshot == null ? void 0 : setSnapshot(void 0);
2022
- return false;
2023
- }
2024
- if (within) {
2025
- const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
2026
- if (changed) {
2027
- onReached == null ? void 0 : onReached(distance);
2028
- updateSnapshot();
2029
- }
2030
- }
2031
- return true;
2032
- };
2033
-
2034
- // src/utils/checkAtBottom.ts
2035
- function checkAtBottom(ctx, state) {
2036
- var _a3;
2037
- if (!state) {
2038
- return;
2039
- }
2040
- const {
2041
- queuedInitialLayout,
2042
- scrollLength,
2043
- scroll,
2044
- maintainingScrollAtEnd,
2045
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
2046
- } = state;
2047
- const contentSize = getContentSize(ctx);
2048
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
2049
- const distanceFromEnd = contentSize - scroll - scrollLength;
2050
- const isContentLess = contentSize < scrollLength;
2051
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
2052
- state.isEndReached = checkThreshold(
2053
- distanceFromEnd,
2054
- isContentLess,
2055
- onEndReachedThreshold * scrollLength,
2056
- state.isEndReached,
2057
- state.endReachedSnapshot,
2058
- {
2059
- scrollPosition: scroll,
2060
- contentSize,
2061
- dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length
2062
- },
2063
- (distance) => {
2064
- var _a4, _b;
2065
- return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
2066
- },
2067
- (snapshot) => {
2068
- state.endReachedSnapshot = snapshot;
2069
- }
2070
- );
2071
- }
2072
- }
2073
-
2074
2181
  // src/utils/setDidLayout.ts
2075
2182
  function setDidLayout(ctx, state) {
2076
2183
  const {
@@ -2150,7 +2257,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2150
2257
  const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2151
2258
  if (currentId) {
2152
2259
  const currentPos = state.positions.get(currentId);
2153
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2260
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
2154
2261
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2155
2262
  }
2156
2263
  }
@@ -2161,7 +2268,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, cu
2161
2268
  }
2162
2269
  function calculateItemsInView(ctx, state, params = {}) {
2163
2270
  reactDom.unstable_batchedUpdates(() => {
2164
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
2271
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2165
2272
  const {
2166
2273
  columns,
2167
2274
  containerItemKeys,
@@ -2194,13 +2301,15 @@ function calculateItemsInView(ctx, state, params = {}) {
2194
2301
  let { scroll: scrollState } = state;
2195
2302
  if (!queuedInitialLayout && initialScroll) {
2196
2303
  const updatedOffset = calculateOffsetWithOffsetPosition(
2304
+ ctx,
2197
2305
  state,
2198
2306
  calculateOffsetForIndex(ctx, state, initialScroll.index),
2199
2307
  initialScroll
2200
2308
  );
2201
2309
  scrollState = updatedOffset;
2202
2310
  }
2203
- const scrollAdjustPad = -topPad;
2311
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2312
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2204
2313
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2205
2314
  if (scroll + scrollLength > totalSize) {
2206
2315
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2213,6 +2322,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2213
2322
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2214
2323
  const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2215
2324
  state.activeStickyIndex = nextActiveStickyIndex;
2325
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2216
2326
  let scrollBufferTop = scrollBuffer;
2217
2327
  let scrollBufferBottom = scrollBuffer;
2218
2328
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2237,7 +2347,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2237
2347
  idCache.length = 0;
2238
2348
  positions.clear();
2239
2349
  }
2240
- const startIndex = dataChanged ? 0 : (_a3 = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _a3 : 0;
2350
+ const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2241
2351
  updateItemPositions(ctx, state, dataChanged, { scrollBottomBuffered, startIndex });
2242
2352
  if (minIndexSizeChanged !== void 0) {
2243
2353
  state.minIndexSizeChanged = void 0;
@@ -2250,9 +2360,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2250
2360
  let endBuffered = null;
2251
2361
  let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2252
2362
  for (let i = loopStart; i >= 0; i--) {
2253
- const id = (_b = idCache[i]) != null ? _b : getId(state, i);
2363
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2254
2364
  const top = positions.get(id);
2255
- const size = (_c = sizes.get(id)) != null ? _c : getItemSize(state, id, i, data[i]);
2365
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2256
2366
  const bottom = top + size;
2257
2367
  if (bottom > scroll - scrollBuffer) {
2258
2368
  loopStart = i;
@@ -2278,8 +2388,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2278
2388
  let firstFullyOnScreenIndex;
2279
2389
  const dataLength = data.length;
2280
2390
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2281
- const id = (_d = idCache[i]) != null ? _d : getId(state, i);
2282
- const size = (_e = sizes.get(id)) != null ? _e : getItemSize(state, id, i, data[i]);
2391
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2392
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2283
2393
  const top = positions.get(id);
2284
2394
  if (!foundEnd) {
2285
2395
  if (startNoBuffer === null && top + size > scroll) {
@@ -2308,7 +2418,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2308
2418
  }
2309
2419
  const idsInView = [];
2310
2420
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2311
- const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2421
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2312
2422
  idsInView.push(id);
2313
2423
  }
2314
2424
  Object.assign(state, {
@@ -2340,7 +2450,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2340
2450
  let numContainers2 = prevNumContainers;
2341
2451
  const needNewContainers = [];
2342
2452
  for (let i = startBuffered; i <= endBuffered; i++) {
2343
- const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2453
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2344
2454
  if (!containerItemKeys.has(id)) {
2345
2455
  needNewContainers.push(i);
2346
2456
  }
@@ -2358,6 +2468,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2358
2468
  );
2359
2469
  } else {
2360
2470
  state.activeStickyIndex = void 0;
2471
+ set$(ctx, "activeStickyIndex", void 0);
2361
2472
  }
2362
2473
  if (needNewContainers.length > 0) {
2363
2474
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2377,7 +2488,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2377
2488
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2378
2489
  const i = needNewContainers[idx];
2379
2490
  const containerIndex = availableContainers[idx];
2380
- const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2491
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2381
2492
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2382
2493
  if (oldKey && oldKey !== id) {
2383
2494
  containerItemKeys.delete(oldKey);
@@ -2433,11 +2544,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2433
2544
  const itemIndex = indexByKey.get(itemKey);
2434
2545
  const item = data[itemIndex];
2435
2546
  if (item !== void 0) {
2436
- const id = (_i = idCache[itemIndex]) != null ? _i : getId(state, itemIndex);
2437
- const position = positions.get(id);
2438
- if (position === void 0) {
2547
+ const id = (_j = idCache[itemIndex]) != null ? _j : getId(state, itemIndex);
2548
+ const positionValue = positions.get(id);
2549
+ if (positionValue === void 0) {
2439
2550
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2440
2551
  } else {
2552
+ const position = (positionValue || 0) - scrollAdjustPending;
2441
2553
  const column = columns.get(id) || 1;
2442
2554
  const prevPos = peek$(ctx, `containerPosition${i}`);
2443
2555
  const prevColumn = peek$(ctx, `containerColumn${i}`);
@@ -2506,40 +2618,6 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
2506
2618
  }
2507
2619
  }
2508
2620
 
2509
- // src/utils/checkAtTop.ts
2510
- function checkAtTop(state) {
2511
- var _a3;
2512
- if (!state) {
2513
- return;
2514
- }
2515
- const {
2516
- scrollLength,
2517
- scroll,
2518
- props: { onStartReachedThreshold }
2519
- } = state;
2520
- const distanceFromTop = scroll;
2521
- state.isAtStart = distanceFromTop <= 0;
2522
- state.isStartReached = checkThreshold(
2523
- distanceFromTop,
2524
- false,
2525
- onStartReachedThreshold * scrollLength,
2526
- state.isStartReached,
2527
- state.startReachedSnapshot,
2528
- {
2529
- scrollPosition: scroll,
2530
- contentSize: state.totalSize,
2531
- dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length
2532
- },
2533
- (distance) => {
2534
- var _a4, _b;
2535
- return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
2536
- },
2537
- (snapshot) => {
2538
- state.startReachedSnapshot = snapshot;
2539
- }
2540
- );
2541
- }
2542
-
2543
2621
  // src/utils/updateAveragesOnDataChange.ts
2544
2622
  function updateAveragesOnDataChange(state, oldData, newData) {
2545
2623
  var _a3;
@@ -2708,78 +2786,45 @@ function handleLayout(ctx, state, layout, setCanRender) {
2708
2786
  setCanRender(true);
2709
2787
  }
2710
2788
 
2711
- // src/core/onScroll.ts
2712
- function onScroll(ctx, state, event) {
2713
- var _a3, _b, _c;
2714
- const {
2715
- scrollProcessingEnabled,
2716
- props: { onScroll: onScrollProp }
2717
- } = state;
2718
- if (scrollProcessingEnabled === false) {
2719
- return;
2720
- }
2721
- 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) {
2722
- return;
2723
- }
2724
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2725
- state.scrollPending = newScroll;
2726
- updateScroll(ctx, state, newScroll);
2727
- onScrollProp == null ? void 0 : onScrollProp(event);
2728
- }
2729
- function updateScroll(ctx, state, newScroll) {
2730
- const scrollingTo = state.scrollingTo;
2731
- state.hasScrolled = true;
2732
- state.lastBatchingAction = Date.now();
2733
- const currentTime = Date.now();
2734
- const adjust = state.scrollAdjustHandler.getAdjust();
2735
- const lastHistoryAdjust = state.lastScrollAdjustForHistory;
2736
- const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
2737
- if (adjustChanged) {
2738
- state.scrollHistory.length = 0;
2739
- }
2740
- state.lastScrollAdjustForHistory = adjust;
2741
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2742
- if (!adjustChanged) {
2743
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2744
- }
2745
- }
2746
- if (state.scrollHistory.length > 5) {
2747
- state.scrollHistory.shift();
2748
- }
2749
- state.scrollPrev = state.scroll;
2750
- state.scrollPrevTime = state.scrollTime;
2751
- state.scroll = newScroll;
2752
- state.scrollTime = currentTime;
2753
- const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2754
- if (ignoreScrollFromMVCP && !state.scrollingTo) {
2755
- const { lt, gt } = ignoreScrollFromMVCP;
2756
- if (lt && newScroll < lt || gt && newScroll > gt) {
2757
- return;
2758
- }
2759
- }
2760
- if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
2761
- calculateItemsInView(ctx, state, { doMVCP: state.scrollingTo !== void 0 });
2762
- checkAtBottom(ctx, state);
2763
- checkAtTop(state);
2764
- state.dataChangeNeedsScrollUpdate = false;
2765
- }
2766
- }
2767
-
2768
2789
  // src/core/ScrollAdjustHandler.ts
2769
2790
  var ScrollAdjustHandler = class {
2770
2791
  constructor(ctx) {
2771
2792
  this.appliedAdjust = 0;
2793
+ this.pendingAdjust = 0;
2772
2794
  this.mounted = false;
2773
2795
  this.context = ctx;
2796
+ {
2797
+ const commitPendingAdjust = () => {
2798
+ const state = this.context.internalState;
2799
+ const pending = this.pendingAdjust;
2800
+ this.pendingAdjust = 0;
2801
+ this.appliedAdjust += pending;
2802
+ state.scroll += pending;
2803
+ state.scrollForNextCalculateItemsInView = void 0;
2804
+ set$(this.context, "scrollAdjustPending", 0);
2805
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2806
+ calculateItemsInView(this.context, this.context.internalState);
2807
+ };
2808
+ listen$(this.context, "scrollingTo", (value) => {
2809
+ if (value === void 0) {
2810
+ commitPendingAdjust();
2811
+ }
2812
+ });
2813
+ }
2774
2814
  }
2775
2815
  requestAdjust(add) {
2776
- const oldAdjustTop = this.appliedAdjust;
2777
- this.appliedAdjust = add + oldAdjustTop;
2778
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2779
- if (this.mounted) {
2780
- set();
2816
+ const scrollingTo = peek$(this.context, "scrollingTo");
2817
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2818
+ this.pendingAdjust += add;
2819
+ set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2781
2820
  } else {
2782
- requestAnimationFrame(set);
2821
+ this.appliedAdjust += add;
2822
+ const setter = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2823
+ if (this.mounted) {
2824
+ setter();
2825
+ } else {
2826
+ requestAnimationFrame(setter);
2827
+ }
2783
2828
  }
2784
2829
  }
2785
2830
  setMounted() {
@@ -2827,7 +2872,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2827
2872
  let minIndexSizeChanged;
2828
2873
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2829
2874
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2830
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2875
+ const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
2831
2876
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2832
2877
  if (diff !== 0) {
2833
2878
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
@@ -2889,7 +2934,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2889
2934
  }
2890
2935
  }
2891
2936
  }
2892
- function updateOneItemSize(state, itemKey, sizeObj) {
2937
+ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
2893
2938
  var _a3;
2894
2939
  const {
2895
2940
  sizes,
@@ -2900,7 +2945,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2900
2945
  } = state;
2901
2946
  if (!data) return 0;
2902
2947
  const index = indexByKey.get(itemKey);
2903
- const prevSize = getItemSize(state, itemKey, index, data[index]);
2948
+ const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
2904
2949
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2905
2950
  const size = Math.round(rawSize) ;
2906
2951
  sizesKnown.set(itemKey, size);
@@ -3263,7 +3308,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3263
3308
  }
3264
3309
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3265
3310
  if (initialContentOffset2 > 0) {
3266
- scrollTo(state, {
3311
+ scrollTo(ctx, state, {
3267
3312
  animated: false,
3268
3313
  index,
3269
3314
  isInitialScroll: true,
@@ -3413,7 +3458,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3413
3458
  scrollToIndex(ctx, state, { index, ...props2 });
3414
3459
  }
3415
3460
  },
3416
- scrollToOffset: (params) => scrollTo(state, params),
3461
+ scrollToOffset: (params) => scrollTo(ctx, state, params),
3417
3462
  setScrollProcessingEnabled: (enabled) => {
3418
3463
  refState.current.scrollProcessingEnabled = enabled;
3419
3464
  },
@@ -3426,7 +3471,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3426
3471
  {
3427
3472
  React3.useEffect(() => {
3428
3473
  if (initialContentOffset) {
3429
- scrollTo(state, { animated: false, offset: initialContentOffset, ...initialScroll || {} });
3474
+ scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...initialScroll || {} });
3430
3475
  }
3431
3476
  }, []);
3432
3477
  }
@@ -3457,7 +3502,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3457
3502
  onMomentumScrollEnd: (event) => {
3458
3503
  {
3459
3504
  requestAnimationFrame(() => {
3460
- finishScrollTo(refState.current);
3505
+ finishScrollTo(ctx, refState.current);
3461
3506
  });
3462
3507
  }
3463
3508
  if (onMomentumScrollEnd) {