@legendapp/list 2.1.0-beta.10 → 2.1.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.native.js CHANGED
@@ -120,11 +120,12 @@ function set$(ctx, signalName, value) {
120
120
  }
121
121
  }
122
122
  function getContentSize(ctx) {
123
+ var _a3, _b;
123
124
  const { values } = ctx;
124
125
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
125
126
  const headerSize = values.get("headerSize") || 0;
126
127
  const footerSize = values.get("footerSize") || 0;
127
- const totalSize = values.get("totalSize");
128
+ const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
128
129
  return headerSize + footerSize + totalSize + stylePaddingTop;
129
130
  }
130
131
  function useArr$(signalNames) {
@@ -252,21 +253,24 @@ function findContainerId(ctx, key) {
252
253
 
253
254
  // src/hooks/useValue$.ts
254
255
  function useValue$(key, params) {
255
- var _a3;
256
256
  const { getValue, delay } = params || {};
257
257
  const ctx = useStateContext();
258
- const animValue = useAnimatedValue((_a3 = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a3 : 0);
258
+ const getNewValue = () => {
259
+ var _a3;
260
+ return (_a3 = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a3 : 0;
261
+ };
262
+ const animValue = useAnimatedValue(getNewValue());
259
263
  React2.useMemo(() => {
260
- let newValue;
261
264
  let prevValue;
262
265
  let didQueueTask = false;
263
266
  listen$(ctx, key, (v) => {
264
- newValue = getValue ? getValue(v) : v;
267
+ const newValue = getNewValue();
265
268
  if (delay !== void 0) {
266
269
  const fn = () => {
267
270
  didQueueTask = false;
268
- if (newValue !== void 0) {
269
- animValue.setValue(newValue);
271
+ const latestValue = getNewValue();
272
+ if (latestValue !== void 0) {
273
+ animValue.setValue(latestValue);
270
274
  }
271
275
  };
272
276
  const delayValue = isFunction(delay) ? delay(newValue, prevValue) : delay;
@@ -482,10 +486,16 @@ function useOnLayoutSync({
482
486
  onLayoutProp,
483
487
  onLayoutChange
484
488
  }, deps = []) {
489
+ const lastLayoutRef = React2.useRef(null);
485
490
  const onLayout = React2.useCallback(
486
491
  (event) => {
487
- onLayoutChange(event.nativeEvent.layout, false);
488
- onLayoutProp == null ? void 0 : onLayoutProp(event);
492
+ var _a3, _b;
493
+ const { layout } = event.nativeEvent;
494
+ if (layout.height !== ((_a3 = lastLayoutRef.current) == null ? void 0 : _a3.height) || layout.width !== ((_b = lastLayoutRef.current) == null ? void 0 : _b.width)) {
495
+ onLayoutChange(layout, false);
496
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
497
+ lastLayoutRef.current = layout;
498
+ }
489
499
  },
490
500
  [onLayoutChange]
491
501
  );
@@ -493,7 +503,9 @@ function useOnLayoutSync({
493
503
  React2.useLayoutEffect(() => {
494
504
  if (ref.current) {
495
505
  ref.current.measure((x, y, width, height) => {
496
- onLayoutChange({ height, width, x, y }, true);
506
+ const layout = { height, width, x, y };
507
+ lastLayoutRef.current = layout;
508
+ onLayoutChange(layout, true);
497
509
  });
498
510
  }
499
511
  }, deps);
@@ -949,44 +961,30 @@ function updateAlignItemsPaddingTop(ctx, state) {
949
961
  }
950
962
  }
951
963
 
952
- // src/core/updateTotalSize.ts
953
- function updateTotalSize(ctx, state) {
954
- const {
955
- positions,
956
- props: { data }
957
- } = state;
958
- if (data.length === 0) {
959
- addTotalSize(ctx, state, null, 0);
960
- } else {
961
- const lastId = getId(state, data.length - 1);
962
- if (lastId !== void 0) {
963
- const lastPosition = positions.get(lastId);
964
- if (lastPosition !== void 0) {
965
- const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
966
- if (lastSize !== void 0) {
967
- const totalSize = lastPosition + lastSize;
968
- addTotalSize(ctx, state, null, totalSize);
969
- }
970
- }
971
- }
972
- }
973
- }
964
+ // src/core/addTotalSize.ts
974
965
  function addTotalSize(ctx, state, key, add) {
975
966
  const { alignItemsAtEnd } = state.props;
976
967
  const prevTotalSize = state.totalSize;
968
+ let totalSize = state.totalSize;
977
969
  if (key === null) {
978
- state.totalSize = add;
970
+ totalSize = add;
979
971
  if (state.timeoutSetPaddingTop) {
980
972
  clearTimeout(state.timeoutSetPaddingTop);
981
973
  state.timeoutSetPaddingTop = void 0;
982
974
  }
983
975
  } else {
984
- state.totalSize += add;
976
+ totalSize += add;
985
977
  }
986
- if (prevTotalSize !== state.totalSize) {
987
- set$(ctx, "totalSize", state.totalSize);
988
- if (alignItemsAtEnd) {
989
- updateAlignItemsPaddingTop(ctx, state);
978
+ if (prevTotalSize !== totalSize) {
979
+ if (!IsNewArchitecture && state.initialScroll && totalSize < prevTotalSize) {
980
+ state.pendingTotalSize = totalSize;
981
+ } else {
982
+ state.pendingTotalSize = void 0;
983
+ state.totalSize = totalSize;
984
+ set$(ctx, "totalSize", totalSize);
985
+ if (alignItemsAtEnd) {
986
+ updateAlignItemsPaddingTop(ctx, state);
987
+ }
990
988
  }
991
989
  }
992
990
  }
@@ -1191,6 +1189,7 @@ function onScroll(ctx, state, event) {
1191
1189
  onScrollProp == null ? void 0 : onScrollProp(event);
1192
1190
  }
1193
1191
  function updateScroll(ctx, state, newScroll, forceUpdate) {
1192
+ var _a3;
1194
1193
  const scrollingTo = peek$(ctx, "scrollingTo");
1195
1194
  state.hasScrolled = true;
1196
1195
  state.lastBatchingAction = Date.now();
@@ -1224,7 +1223,7 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1224
1223
  }
1225
1224
  if (forceUpdate || state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1226
1225
  state.ignoreScrollFromMVCPIgnored = false;
1227
- calculateItemsInView(ctx, state, { doMVCP: scrollingTo !== void 0 });
1226
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1228
1227
  checkAtBottom(ctx, state);
1229
1228
  checkAtTop(state);
1230
1229
  state.dataChangeNeedsScrollUpdate = false;
@@ -1237,7 +1236,11 @@ function finishScrollTo(ctx, state) {
1237
1236
  if (state) {
1238
1237
  state.scrollHistory.length = 0;
1239
1238
  state.initialScroll = void 0;
1239
+ state.initialAnchor = void 0;
1240
1240
  set$(ctx, "scrollingTo", void 0);
1241
+ if (state.pendingTotalSize !== void 0) {
1242
+ addTotalSize(ctx, state, null, state.pendingTotalSize);
1243
+ }
1241
1244
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1242
1245
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1243
1246
  }
@@ -1273,7 +1276,16 @@ function scrollTo(ctx, state, params) {
1273
1276
  }
1274
1277
  if (!animated) {
1275
1278
  state.scroll = offset;
1276
- setTimeout(() => finishScrollTo(ctx, state), 100);
1279
+ if (Platform2.OS === "web") {
1280
+ const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1281
+ if (value) {
1282
+ finishScrollTo(ctx, state);
1283
+ unlisten();
1284
+ }
1285
+ });
1286
+ } else {
1287
+ setTimeout(() => finishScrollTo(ctx, state), 100);
1288
+ }
1277
1289
  if (isInitialScroll) {
1278
1290
  setTimeout(() => {
1279
1291
  state.initialScroll = void 0;
@@ -1331,6 +1343,58 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1331
1343
  }
1332
1344
  }
1333
1345
 
1346
+ // src/core/ensureInitialAnchor.ts
1347
+ var INITIAL_ANCHOR_TOLERANCE = 0.5;
1348
+ var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1349
+ var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1350
+ function ensureInitialAnchor(ctx, state) {
1351
+ var _a3, _b, _c, _d, _e;
1352
+ const anchor = state.initialAnchor;
1353
+ const item = state.props.data[anchor.index];
1354
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1355
+ if (!containersDidLayout) {
1356
+ return;
1357
+ }
1358
+ const id = getId(state, anchor.index);
1359
+ if (state.positions.get(id) === void 0) {
1360
+ return;
1361
+ }
1362
+ const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1363
+ if (size === void 0) {
1364
+ return;
1365
+ }
1366
+ const availableSpace = Math.max(0, state.scrollLength - size);
1367
+ const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1368
+ const contentSize = getContentSize(ctx);
1369
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1370
+ const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1371
+ const delta = clampedDesiredOffset - state.scroll;
1372
+ if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1373
+ const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1374
+ if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1375
+ state.initialAnchor = void 0;
1376
+ } else {
1377
+ anchor.settledTicks = settledTicks;
1378
+ }
1379
+ return;
1380
+ }
1381
+ if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1382
+ state.initialAnchor = void 0;
1383
+ return;
1384
+ }
1385
+ const lastDelta = anchor.lastDelta;
1386
+ if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1387
+ state.initialAnchor = void 0;
1388
+ return;
1389
+ }
1390
+ Object.assign(anchor, {
1391
+ attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1392
+ lastDelta: delta,
1393
+ settledTicks: 0
1394
+ });
1395
+ requestAdjust(ctx, state, delta);
1396
+ }
1397
+
1334
1398
  // src/core/mvcp.ts
1335
1399
  function prepareMVCP(ctx, state, dataChanged) {
1336
1400
  const {
@@ -1346,6 +1410,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1346
1410
  if (maintainVisibleContentPosition) {
1347
1411
  const indexByKey = state.indexByKey;
1348
1412
  if (scrollTarget !== void 0) {
1413
+ if (!IsNewArchitecture && (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll)) {
1414
+ return void 0;
1415
+ }
1349
1416
  targetId = getId(state, scrollTarget);
1350
1417
  } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1351
1418
  if (dataChanged) {
@@ -1379,7 +1446,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1379
1446
  if (targetId !== void 0 && prevPosition !== void 0) {
1380
1447
  const newPosition = positions.get(targetId);
1381
1448
  if (newPosition !== void 0) {
1382
- const totalSize = peek$(ctx, "totalSize");
1449
+ const totalSize = getContentSize(ctx);
1383
1450
  let diff = newPosition - prevPosition;
1384
1451
  if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1385
1452
  if (diff > 0) {
@@ -1459,6 +1526,29 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1459
1526
  return maxSize;
1460
1527
  }
1461
1528
 
1529
+ // src/core/updateTotalSize.ts
1530
+ function updateTotalSize(ctx, state) {
1531
+ const {
1532
+ positions,
1533
+ props: { data }
1534
+ } = state;
1535
+ if (data.length === 0) {
1536
+ addTotalSize(ctx, state, null, 0);
1537
+ } else {
1538
+ const lastId = getId(state, data.length - 1);
1539
+ if (lastId !== void 0) {
1540
+ const lastPosition = positions.get(lastId);
1541
+ if (lastPosition !== void 0) {
1542
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1543
+ if (lastSize !== void 0) {
1544
+ const totalSize = lastPosition + lastSize;
1545
+ addTotalSize(ctx, state, null, totalSize);
1546
+ }
1547
+ }
1548
+ }
1549
+ }
1550
+ }
1551
+
1462
1552
  // src/utils/getScrollVelocity.ts
1463
1553
  var getScrollVelocity = (state) => {
1464
1554
  const { scrollHistory } = state;
@@ -2079,9 +2169,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2079
2169
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2080
2170
  const prevNumContainers = peek$(ctx, "numContainers");
2081
2171
  if (!data || scrollLength === 0 || !prevNumContainers) {
2172
+ if (state.initialAnchor) {
2173
+ ensureInitialAnchor(ctx, state);
2174
+ }
2082
2175
  return;
2083
2176
  }
2084
- const totalSize = peek$(ctx, "totalSize");
2177
+ const totalSize = getContentSize(ctx);
2085
2178
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2086
2179
  const numColumns = peek$(ctx, "numColumns");
2087
2180
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
@@ -2128,6 +2221,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2128
2221
  if (!dataChanged && scrollForNextCalculateItemsInView) {
2129
2222
  const { top, bottom } = scrollForNextCalculateItemsInView;
2130
2223
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2224
+ if (state.initialAnchor) {
2225
+ ensureInitialAnchor(ctx, state);
2226
+ }
2131
2227
  return;
2132
2228
  }
2133
2229
  }
@@ -2380,6 +2476,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2380
2476
  }
2381
2477
  }
2382
2478
  });
2479
+ if (state.initialAnchor) {
2480
+ ensureInitialAnchor(ctx, state);
2481
+ }
2383
2482
  }
2384
2483
 
2385
2484
  // src/core/checkActualChange.ts
@@ -3015,7 +3114,7 @@ var LegendList = typedMemo(
3015
3114
  })
3016
3115
  );
3017
3116
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3018
- var _a3;
3117
+ var _a3, _b;
3019
3118
  const {
3020
3119
  alignItemsAtEnd = false,
3021
3120
  columnWrapperStyle,
@@ -3106,6 +3205,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3106
3205
  idCache: [],
3107
3206
  idsInView: [],
3108
3207
  indexByKey: /* @__PURE__ */ new Map(),
3208
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
3209
+ attempts: 0,
3210
+ index: initialScrollProp.index,
3211
+ settledTicks: 0,
3212
+ viewOffset: (_a3 = initialScrollProp.viewOffset) != null ? _a3 : 0,
3213
+ viewPosition: initialScrollProp.viewPosition
3214
+ } : void 0,
3109
3215
  initialScroll: initialScrollProp,
3110
3216
  isAtEnd: false,
3111
3217
  isAtStart: false,
@@ -3227,10 +3333,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3227
3333
  );
3228
3334
  }
3229
3335
  const initialContentOffset = React2.useMemo(() => {
3336
+ var _a4, _b2;
3230
3337
  const { initialScroll } = refState.current;
3231
3338
  if (!initialScroll) {
3339
+ refState.current.initialAnchor = void 0;
3232
3340
  return 0;
3233
3341
  }
3342
+ if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3343
+ refState.current.initialAnchor = {
3344
+ attempts: 0,
3345
+ index: initialScroll.index,
3346
+ settledTicks: 0,
3347
+ viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3348
+ viewPosition: initialScroll.viewPosition
3349
+ };
3350
+ }
3234
3351
  if (initialScroll.contentOffset !== void 0) {
3235
3352
  return initialScroll.contentOffset;
3236
3353
  }
@@ -3282,6 +3399,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3282
3399
  scrollTo(ctx, state, {
3283
3400
  animated: false,
3284
3401
  index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3402
+ isInitialScroll: true,
3285
3403
  offset: initialContentOffset,
3286
3404
  precomputedWithViewOffset: true
3287
3405
  });
@@ -3396,7 +3514,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3396
3514
  }
3397
3515
  ),
3398
3516
  refScrollView: combinedRef,
3399
- scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3517
+ scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3400
3518
  scrollEventThrottle: Platform2.OS === "web" ? 16 : void 0,
3401
3519
  snapToIndices,
3402
3520
  stickyIndices,