@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.mjs CHANGED
@@ -99,11 +99,12 @@ function set$(ctx, signalName, value) {
99
99
  }
100
100
  }
101
101
  function getContentSize(ctx) {
102
+ var _a3, _b;
102
103
  const { values } = ctx;
103
104
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
104
105
  const headerSize = values.get("headerSize") || 0;
105
106
  const footerSize = values.get("footerSize") || 0;
106
- const totalSize = values.get("totalSize");
107
+ const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
107
108
  return headerSize + footerSize + totalSize + stylePaddingTop;
108
109
  }
109
110
  function useArr$(signalNames) {
@@ -231,21 +232,24 @@ function findContainerId(ctx, key) {
231
232
 
232
233
  // src/hooks/useValue$.ts
233
234
  function useValue$(key, params) {
234
- var _a3;
235
235
  const { getValue, delay } = params || {};
236
236
  const ctx = useStateContext();
237
- const animValue = useAnimatedValue((_a3 = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a3 : 0);
237
+ const getNewValue = () => {
238
+ var _a3;
239
+ return (_a3 = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a3 : 0;
240
+ };
241
+ const animValue = useAnimatedValue(getNewValue());
238
242
  useMemo(() => {
239
- let newValue;
240
243
  let prevValue;
241
244
  let didQueueTask = false;
242
245
  listen$(ctx, key, (v) => {
243
- newValue = getValue ? getValue(v) : v;
246
+ const newValue = getNewValue();
244
247
  if (delay !== void 0) {
245
248
  const fn = () => {
246
249
  didQueueTask = false;
247
- if (newValue !== void 0) {
248
- animValue.setValue(newValue);
250
+ const latestValue = getNewValue();
251
+ if (latestValue !== void 0) {
252
+ animValue.setValue(latestValue);
249
253
  }
250
254
  };
251
255
  const delayValue = isFunction(delay) ? delay(newValue, prevValue) : delay;
@@ -461,10 +465,16 @@ function useOnLayoutSync({
461
465
  onLayoutProp,
462
466
  onLayoutChange
463
467
  }, deps = []) {
468
+ const lastLayoutRef = useRef(null);
464
469
  const onLayout = useCallback(
465
470
  (event) => {
466
- onLayoutChange(event.nativeEvent.layout, false);
467
- onLayoutProp == null ? void 0 : onLayoutProp(event);
471
+ var _a3, _b;
472
+ const { layout } = event.nativeEvent;
473
+ if (layout.height !== ((_a3 = lastLayoutRef.current) == null ? void 0 : _a3.height) || layout.width !== ((_b = lastLayoutRef.current) == null ? void 0 : _b.width)) {
474
+ onLayoutChange(layout, false);
475
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
476
+ lastLayoutRef.current = layout;
477
+ }
468
478
  },
469
479
  [onLayoutChange]
470
480
  );
@@ -472,7 +482,9 @@ function useOnLayoutSync({
472
482
  useLayoutEffect(() => {
473
483
  if (ref.current) {
474
484
  ref.current.measure((x, y, width, height) => {
475
- onLayoutChange({ height, width, x, y }, true);
485
+ const layout = { height, width, x, y };
486
+ lastLayoutRef.current = layout;
487
+ onLayoutChange(layout, true);
476
488
  });
477
489
  }
478
490
  }, deps);
@@ -928,44 +940,30 @@ function updateAlignItemsPaddingTop(ctx, state) {
928
940
  }
929
941
  }
930
942
 
931
- // src/core/updateTotalSize.ts
932
- function updateTotalSize(ctx, state) {
933
- const {
934
- positions,
935
- props: { data }
936
- } = state;
937
- if (data.length === 0) {
938
- addTotalSize(ctx, state, null, 0);
939
- } else {
940
- const lastId = getId(state, data.length - 1);
941
- if (lastId !== void 0) {
942
- const lastPosition = positions.get(lastId);
943
- if (lastPosition !== void 0) {
944
- const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
945
- if (lastSize !== void 0) {
946
- const totalSize = lastPosition + lastSize;
947
- addTotalSize(ctx, state, null, totalSize);
948
- }
949
- }
950
- }
951
- }
952
- }
943
+ // src/core/addTotalSize.ts
953
944
  function addTotalSize(ctx, state, key, add) {
954
945
  const { alignItemsAtEnd } = state.props;
955
946
  const prevTotalSize = state.totalSize;
947
+ let totalSize = state.totalSize;
956
948
  if (key === null) {
957
- state.totalSize = add;
949
+ totalSize = add;
958
950
  if (state.timeoutSetPaddingTop) {
959
951
  clearTimeout(state.timeoutSetPaddingTop);
960
952
  state.timeoutSetPaddingTop = void 0;
961
953
  }
962
954
  } else {
963
- state.totalSize += add;
955
+ totalSize += add;
964
956
  }
965
- if (prevTotalSize !== state.totalSize) {
966
- set$(ctx, "totalSize", state.totalSize);
967
- if (alignItemsAtEnd) {
968
- updateAlignItemsPaddingTop(ctx, state);
957
+ if (prevTotalSize !== totalSize) {
958
+ if (!IsNewArchitecture && state.initialScroll && totalSize < prevTotalSize) {
959
+ state.pendingTotalSize = totalSize;
960
+ } else {
961
+ state.pendingTotalSize = void 0;
962
+ state.totalSize = totalSize;
963
+ set$(ctx, "totalSize", totalSize);
964
+ if (alignItemsAtEnd) {
965
+ updateAlignItemsPaddingTop(ctx, state);
966
+ }
969
967
  }
970
968
  }
971
969
  }
@@ -1170,6 +1168,7 @@ function onScroll(ctx, state, event) {
1170
1168
  onScrollProp == null ? void 0 : onScrollProp(event);
1171
1169
  }
1172
1170
  function updateScroll(ctx, state, newScroll, forceUpdate) {
1171
+ var _a3;
1173
1172
  const scrollingTo = peek$(ctx, "scrollingTo");
1174
1173
  state.hasScrolled = true;
1175
1174
  state.lastBatchingAction = Date.now();
@@ -1203,7 +1202,7 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1203
1202
  }
1204
1203
  if (forceUpdate || state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1205
1204
  state.ignoreScrollFromMVCPIgnored = false;
1206
- calculateItemsInView(ctx, state, { doMVCP: scrollingTo !== void 0 });
1205
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1207
1206
  checkAtBottom(ctx, state);
1208
1207
  checkAtTop(state);
1209
1208
  state.dataChangeNeedsScrollUpdate = false;
@@ -1216,7 +1215,11 @@ function finishScrollTo(ctx, state) {
1216
1215
  if (state) {
1217
1216
  state.scrollHistory.length = 0;
1218
1217
  state.initialScroll = void 0;
1218
+ state.initialAnchor = void 0;
1219
1219
  set$(ctx, "scrollingTo", void 0);
1220
+ if (state.pendingTotalSize !== void 0) {
1221
+ addTotalSize(ctx, state, null, state.pendingTotalSize);
1222
+ }
1220
1223
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1221
1224
  (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1222
1225
  }
@@ -1252,7 +1255,16 @@ function scrollTo(ctx, state, params) {
1252
1255
  }
1253
1256
  if (!animated) {
1254
1257
  state.scroll = offset;
1255
- setTimeout(() => finishScrollTo(ctx, state), 100);
1258
+ if (Platform2.OS === "web") {
1259
+ const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1260
+ if (value) {
1261
+ finishScrollTo(ctx, state);
1262
+ unlisten();
1263
+ }
1264
+ });
1265
+ } else {
1266
+ setTimeout(() => finishScrollTo(ctx, state), 100);
1267
+ }
1256
1268
  if (isInitialScroll) {
1257
1269
  setTimeout(() => {
1258
1270
  state.initialScroll = void 0;
@@ -1310,6 +1322,58 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1310
1322
  }
1311
1323
  }
1312
1324
 
1325
+ // src/core/ensureInitialAnchor.ts
1326
+ var INITIAL_ANCHOR_TOLERANCE = 0.5;
1327
+ var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1328
+ var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1329
+ function ensureInitialAnchor(ctx, state) {
1330
+ var _a3, _b, _c, _d, _e;
1331
+ const anchor = state.initialAnchor;
1332
+ const item = state.props.data[anchor.index];
1333
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1334
+ if (!containersDidLayout) {
1335
+ return;
1336
+ }
1337
+ const id = getId(state, anchor.index);
1338
+ if (state.positions.get(id) === void 0) {
1339
+ return;
1340
+ }
1341
+ const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1342
+ if (size === void 0) {
1343
+ return;
1344
+ }
1345
+ const availableSpace = Math.max(0, state.scrollLength - size);
1346
+ const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1347
+ const contentSize = getContentSize(ctx);
1348
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1349
+ const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1350
+ const delta = clampedDesiredOffset - state.scroll;
1351
+ if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1352
+ const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1353
+ if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1354
+ state.initialAnchor = void 0;
1355
+ } else {
1356
+ anchor.settledTicks = settledTicks;
1357
+ }
1358
+ return;
1359
+ }
1360
+ if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1361
+ state.initialAnchor = void 0;
1362
+ return;
1363
+ }
1364
+ const lastDelta = anchor.lastDelta;
1365
+ if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1366
+ state.initialAnchor = void 0;
1367
+ return;
1368
+ }
1369
+ Object.assign(anchor, {
1370
+ attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1371
+ lastDelta: delta,
1372
+ settledTicks: 0
1373
+ });
1374
+ requestAdjust(ctx, state, delta);
1375
+ }
1376
+
1313
1377
  // src/core/mvcp.ts
1314
1378
  function prepareMVCP(ctx, state, dataChanged) {
1315
1379
  const {
@@ -1325,6 +1389,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1325
1389
  if (maintainVisibleContentPosition) {
1326
1390
  const indexByKey = state.indexByKey;
1327
1391
  if (scrollTarget !== void 0) {
1392
+ if (!IsNewArchitecture && (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll)) {
1393
+ return void 0;
1394
+ }
1328
1395
  targetId = getId(state, scrollTarget);
1329
1396
  } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1330
1397
  if (dataChanged) {
@@ -1358,7 +1425,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1358
1425
  if (targetId !== void 0 && prevPosition !== void 0) {
1359
1426
  const newPosition = positions.get(targetId);
1360
1427
  if (newPosition !== void 0) {
1361
- const totalSize = peek$(ctx, "totalSize");
1428
+ const totalSize = getContentSize(ctx);
1362
1429
  let diff = newPosition - prevPosition;
1363
1430
  if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1364
1431
  if (diff > 0) {
@@ -1438,6 +1505,29 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1438
1505
  return maxSize;
1439
1506
  }
1440
1507
 
1508
+ // src/core/updateTotalSize.ts
1509
+ function updateTotalSize(ctx, state) {
1510
+ const {
1511
+ positions,
1512
+ props: { data }
1513
+ } = state;
1514
+ if (data.length === 0) {
1515
+ addTotalSize(ctx, state, null, 0);
1516
+ } else {
1517
+ const lastId = getId(state, data.length - 1);
1518
+ if (lastId !== void 0) {
1519
+ const lastPosition = positions.get(lastId);
1520
+ if (lastPosition !== void 0) {
1521
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1522
+ if (lastSize !== void 0) {
1523
+ const totalSize = lastPosition + lastSize;
1524
+ addTotalSize(ctx, state, null, totalSize);
1525
+ }
1526
+ }
1527
+ }
1528
+ }
1529
+ }
1530
+
1441
1531
  // src/utils/getScrollVelocity.ts
1442
1532
  var getScrollVelocity = (state) => {
1443
1533
  const { scrollHistory } = state;
@@ -2058,9 +2148,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2058
2148
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2059
2149
  const prevNumContainers = peek$(ctx, "numContainers");
2060
2150
  if (!data || scrollLength === 0 || !prevNumContainers) {
2151
+ if (state.initialAnchor) {
2152
+ ensureInitialAnchor(ctx, state);
2153
+ }
2061
2154
  return;
2062
2155
  }
2063
- const totalSize = peek$(ctx, "totalSize");
2156
+ const totalSize = getContentSize(ctx);
2064
2157
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2065
2158
  const numColumns = peek$(ctx, "numColumns");
2066
2159
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
@@ -2107,6 +2200,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2107
2200
  if (!dataChanged && scrollForNextCalculateItemsInView) {
2108
2201
  const { top, bottom } = scrollForNextCalculateItemsInView;
2109
2202
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2203
+ if (state.initialAnchor) {
2204
+ ensureInitialAnchor(ctx, state);
2205
+ }
2110
2206
  return;
2111
2207
  }
2112
2208
  }
@@ -2359,6 +2455,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2359
2455
  }
2360
2456
  }
2361
2457
  });
2458
+ if (state.initialAnchor) {
2459
+ ensureInitialAnchor(ctx, state);
2460
+ }
2362
2461
  }
2363
2462
 
2364
2463
  // src/core/checkActualChange.ts
@@ -2994,7 +3093,7 @@ var LegendList = typedMemo(
2994
3093
  })
2995
3094
  );
2996
3095
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2997
- var _a3;
3096
+ var _a3, _b;
2998
3097
  const {
2999
3098
  alignItemsAtEnd = false,
3000
3099
  columnWrapperStyle,
@@ -3085,6 +3184,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3085
3184
  idCache: [],
3086
3185
  idsInView: [],
3087
3186
  indexByKey: /* @__PURE__ */ new Map(),
3187
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
3188
+ attempts: 0,
3189
+ index: initialScrollProp.index,
3190
+ settledTicks: 0,
3191
+ viewOffset: (_a3 = initialScrollProp.viewOffset) != null ? _a3 : 0,
3192
+ viewPosition: initialScrollProp.viewPosition
3193
+ } : void 0,
3088
3194
  initialScroll: initialScrollProp,
3089
3195
  isAtEnd: false,
3090
3196
  isAtStart: false,
@@ -3206,10 +3312,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3206
3312
  );
3207
3313
  }
3208
3314
  const initialContentOffset = useMemo(() => {
3315
+ var _a4, _b2;
3209
3316
  const { initialScroll } = refState.current;
3210
3317
  if (!initialScroll) {
3318
+ refState.current.initialAnchor = void 0;
3211
3319
  return 0;
3212
3320
  }
3321
+ if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3322
+ refState.current.initialAnchor = {
3323
+ attempts: 0,
3324
+ index: initialScroll.index,
3325
+ settledTicks: 0,
3326
+ viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3327
+ viewPosition: initialScroll.viewPosition
3328
+ };
3329
+ }
3213
3330
  if (initialScroll.contentOffset !== void 0) {
3214
3331
  return initialScroll.contentOffset;
3215
3332
  }
@@ -3261,6 +3378,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3261
3378
  scrollTo(ctx, state, {
3262
3379
  animated: false,
3263
3380
  index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3381
+ isInitialScroll: true,
3264
3382
  offset: initialContentOffset,
3265
3383
  precomputedWithViewOffset: true
3266
3384
  });
@@ -3375,7 +3493,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3375
3493
  }
3376
3494
  ),
3377
3495
  refScrollView: combinedRef,
3378
- scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3496
+ scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3379
3497
  scrollEventThrottle: Platform2.OS === "web" ? 16 : void 0,
3380
3498
  snapToIndices,
3381
3499
  stickyIndices,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.1.0-beta.10",
3
+ "version": "2.1.0-beta.12",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,