@legendapp/list 2.1.0-beta.10 → 2.1.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/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
  }
@@ -1310,6 +1313,58 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1310
1313
  }
1311
1314
  }
1312
1315
 
1316
+ // src/core/ensureInitialAnchor.ts
1317
+ var INITIAL_ANCHOR_TOLERANCE = 0.5;
1318
+ var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1319
+ var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1320
+ function ensureInitialAnchor(ctx, state) {
1321
+ var _a3, _b, _c, _d, _e;
1322
+ const anchor = state.initialAnchor;
1323
+ const item = state.props.data[anchor.index];
1324
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1325
+ if (!containersDidLayout) {
1326
+ return;
1327
+ }
1328
+ const id = getId(state, anchor.index);
1329
+ if (state.positions.get(id) === void 0) {
1330
+ return;
1331
+ }
1332
+ const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1333
+ if (size === void 0) {
1334
+ return;
1335
+ }
1336
+ const availableSpace = Math.max(0, state.scrollLength - size);
1337
+ const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1338
+ const contentSize = getContentSize(ctx);
1339
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1340
+ const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1341
+ const delta = clampedDesiredOffset - state.scroll;
1342
+ if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1343
+ const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1344
+ if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1345
+ state.initialAnchor = void 0;
1346
+ } else {
1347
+ anchor.settledTicks = settledTicks;
1348
+ }
1349
+ return;
1350
+ }
1351
+ if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1352
+ state.initialAnchor = void 0;
1353
+ return;
1354
+ }
1355
+ const lastDelta = anchor.lastDelta;
1356
+ if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1357
+ state.initialAnchor = void 0;
1358
+ return;
1359
+ }
1360
+ Object.assign(anchor, {
1361
+ attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1362
+ lastDelta: delta,
1363
+ settledTicks: 0
1364
+ });
1365
+ requestAdjust(ctx, state, delta);
1366
+ }
1367
+
1313
1368
  // src/core/mvcp.ts
1314
1369
  function prepareMVCP(ctx, state, dataChanged) {
1315
1370
  const {
@@ -1325,6 +1380,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1325
1380
  if (maintainVisibleContentPosition) {
1326
1381
  const indexByKey = state.indexByKey;
1327
1382
  if (scrollTarget !== void 0) {
1383
+ if (!IsNewArchitecture && (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll)) {
1384
+ return void 0;
1385
+ }
1328
1386
  targetId = getId(state, scrollTarget);
1329
1387
  } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1330
1388
  if (dataChanged) {
@@ -1358,7 +1416,7 @@ function prepareMVCP(ctx, state, dataChanged) {
1358
1416
  if (targetId !== void 0 && prevPosition !== void 0) {
1359
1417
  const newPosition = positions.get(targetId);
1360
1418
  if (newPosition !== void 0) {
1361
- const totalSize = peek$(ctx, "totalSize");
1419
+ const totalSize = getContentSize(ctx);
1362
1420
  let diff = newPosition - prevPosition;
1363
1421
  if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1364
1422
  if (diff > 0) {
@@ -1438,6 +1496,29 @@ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1438
1496
  return maxSize;
1439
1497
  }
1440
1498
 
1499
+ // src/core/updateTotalSize.ts
1500
+ function updateTotalSize(ctx, state) {
1501
+ const {
1502
+ positions,
1503
+ props: { data }
1504
+ } = state;
1505
+ if (data.length === 0) {
1506
+ addTotalSize(ctx, state, null, 0);
1507
+ } else {
1508
+ const lastId = getId(state, data.length - 1);
1509
+ if (lastId !== void 0) {
1510
+ const lastPosition = positions.get(lastId);
1511
+ if (lastPosition !== void 0) {
1512
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1513
+ if (lastSize !== void 0) {
1514
+ const totalSize = lastPosition + lastSize;
1515
+ addTotalSize(ctx, state, null, totalSize);
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+ }
1521
+
1441
1522
  // src/utils/getScrollVelocity.ts
1442
1523
  var getScrollVelocity = (state) => {
1443
1524
  const { scrollHistory } = state;
@@ -2058,9 +2139,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2058
2139
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2059
2140
  const prevNumContainers = peek$(ctx, "numContainers");
2060
2141
  if (!data || scrollLength === 0 || !prevNumContainers) {
2142
+ if (state.initialAnchor) {
2143
+ ensureInitialAnchor(ctx, state);
2144
+ }
2061
2145
  return;
2062
2146
  }
2063
- const totalSize = peek$(ctx, "totalSize");
2147
+ const totalSize = getContentSize(ctx);
2064
2148
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2065
2149
  const numColumns = peek$(ctx, "numColumns");
2066
2150
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
@@ -2107,6 +2191,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2107
2191
  if (!dataChanged && scrollForNextCalculateItemsInView) {
2108
2192
  const { top, bottom } = scrollForNextCalculateItemsInView;
2109
2193
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2194
+ if (state.initialAnchor) {
2195
+ ensureInitialAnchor(ctx, state);
2196
+ }
2110
2197
  return;
2111
2198
  }
2112
2199
  }
@@ -2359,6 +2446,9 @@ function calculateItemsInView(ctx, state, params = {}) {
2359
2446
  }
2360
2447
  }
2361
2448
  });
2449
+ if (state.initialAnchor) {
2450
+ ensureInitialAnchor(ctx, state);
2451
+ }
2362
2452
  }
2363
2453
 
2364
2454
  // src/core/checkActualChange.ts
@@ -2994,7 +3084,7 @@ var LegendList = typedMemo(
2994
3084
  })
2995
3085
  );
2996
3086
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2997
- var _a3;
3087
+ var _a3, _b;
2998
3088
  const {
2999
3089
  alignItemsAtEnd = false,
3000
3090
  columnWrapperStyle,
@@ -3085,6 +3175,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3085
3175
  idCache: [],
3086
3176
  idsInView: [],
3087
3177
  indexByKey: /* @__PURE__ */ new Map(),
3178
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
3179
+ attempts: 0,
3180
+ index: initialScrollProp.index,
3181
+ settledTicks: 0,
3182
+ viewOffset: (_a3 = initialScrollProp.viewOffset) != null ? _a3 : 0,
3183
+ viewPosition: initialScrollProp.viewPosition
3184
+ } : void 0,
3088
3185
  initialScroll: initialScrollProp,
3089
3186
  isAtEnd: false,
3090
3187
  isAtStart: false,
@@ -3206,10 +3303,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3206
3303
  );
3207
3304
  }
3208
3305
  const initialContentOffset = useMemo(() => {
3306
+ var _a4, _b2;
3209
3307
  const { initialScroll } = refState.current;
3210
3308
  if (!initialScroll) {
3309
+ refState.current.initialAnchor = void 0;
3211
3310
  return 0;
3212
3311
  }
3312
+ if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3313
+ refState.current.initialAnchor = {
3314
+ attempts: 0,
3315
+ index: initialScroll.index,
3316
+ settledTicks: 0,
3317
+ viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3318
+ viewPosition: initialScroll.viewPosition
3319
+ };
3320
+ }
3213
3321
  if (initialScroll.contentOffset !== void 0) {
3214
3322
  return initialScroll.contentOffset;
3215
3323
  }
@@ -3261,6 +3369,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3261
3369
  scrollTo(ctx, state, {
3262
3370
  animated: false,
3263
3371
  index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3372
+ isInitialScroll: true,
3264
3373
  offset: initialContentOffset,
3265
3374
  precomputedWithViewOffset: true
3266
3375
  });
@@ -3375,7 +3484,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3375
3484
  }
3376
3485
  ),
3377
3486
  refScrollView: combinedRef,
3378
- scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3487
+ scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3379
3488
  scrollEventThrottle: Platform2.OS === "web" ? 16 : void 0,
3380
3489
  snapToIndices,
3381
3490
  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.11",
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,