@legendapp/list 3.0.3 → 3.0.4

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/react.mjs CHANGED
@@ -2441,17 +2441,42 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
2441
2441
  }
2442
2442
 
2443
2443
  // src/utils/getItemSize.ts
2444
+ function getKnownOrFixedSize(ctx, key, index, data) {
2445
+ var _a3;
2446
+ const state = ctx.state;
2447
+ const { getFixedItemSize, getItemType } = state.props;
2448
+ let size = key ? state.sizesKnown.get(key) : void 0;
2449
+ if (size === void 0 && key && getFixedItemSize) {
2450
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2451
+ size = getFixedItemSize(data, index, itemType);
2452
+ if (size !== void 0) {
2453
+ state.sizesKnown.set(key, size);
2454
+ }
2455
+ }
2456
+ return size;
2457
+ }
2458
+ function getKnownOrFixedItemSize(ctx, index) {
2459
+ const key = getId(ctx.state, index);
2460
+ return getKnownOrFixedSize(ctx, key, index, ctx.state.props.data[index]);
2461
+ }
2462
+ function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
2463
+ for (let index = startIndex; index <= endIndex; index++) {
2464
+ if (getKnownOrFixedItemSize(ctx, index) === void 0) {
2465
+ return false;
2466
+ }
2467
+ }
2468
+ return true;
2469
+ }
2444
2470
  function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
2445
2471
  var _a3, _b, _c;
2446
2472
  const state = ctx.state;
2447
2473
  const {
2448
- sizesKnown,
2449
2474
  sizes,
2450
2475
  averageSizes,
2451
- props: { estimatedItemSize, getFixedItemSize, getItemType },
2476
+ props: { estimatedItemSize, getItemType },
2452
2477
  scrollingTo
2453
2478
  } = state;
2454
- const sizeKnown = sizesKnown.get(key);
2479
+ const sizeKnown = state.sizesKnown.get(key);
2455
2480
  if (sizeKnown !== void 0) {
2456
2481
  return sizeKnown;
2457
2482
  }
@@ -2462,14 +2487,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2462
2487
  return renderedSize;
2463
2488
  }
2464
2489
  }
2465
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2466
- if (getFixedItemSize) {
2467
- size = getFixedItemSize(data, index, itemType);
2468
- if (size !== void 0) {
2469
- sizesKnown.set(key, size);
2470
- }
2490
+ size = getKnownOrFixedSize(ctx, key, index, data);
2491
+ if (size !== void 0) {
2492
+ setSize(ctx, key, size, notifyTotalSize);
2493
+ return size;
2471
2494
  }
2472
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
2495
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
2496
+ if (useAverageSize && !scrollingTo) {
2473
2497
  const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
2474
2498
  if (averageSizeForType !== void 0) {
2475
2499
  size = roundSize(averageSizeForType);
@@ -2478,7 +2502,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
2478
2502
  if (size === void 0 && renderedSize !== void 0) {
2479
2503
  return renderedSize;
2480
2504
  }
2481
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && scrollingTo) {
2505
+ if (size === void 0 && useAverageSize && scrollingTo) {
2482
2506
  const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
2483
2507
  if (averageSizeForType !== void 0) {
2484
2508
  size = roundSize(averageSizeForType);
@@ -5798,22 +5822,27 @@ var ScrollAdjustHandler = class {
5798
5822
 
5799
5823
  // src/core/updateAnchoredEndSpace.ts
5800
5824
  function maybeUpdateAnchoredEndSpace(ctx) {
5801
- var _a3;
5825
+ var _a3, _b;
5802
5826
  const state = ctx.state;
5803
5827
  const anchoredEndSpace = state.props.anchoredEndSpace;
5804
5828
  const previousSize = peek$(ctx, "anchoredEndSpaceSize");
5829
+ const previousReadyAnchorIndex = state.anchoredEndSpaceReadyAnchorIndex;
5830
+ const previousReadyAnchorKey = state.anchoredEndSpaceReadyAnchorKey;
5831
+ const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
5832
+ let nextAnchorKey;
5833
+ let isReady = true;
5805
5834
  let nextSize = 0;
5806
5835
  if (anchoredEndSpace) {
5807
5836
  const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
5808
5837
  const { data } = state.props;
5809
5838
  if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
5839
+ nextAnchorKey = getId(state, anchorIndex);
5810
5840
  let contentBelowAnchor = 0;
5811
5841
  const footerSize = ctx.values.get("footerSize") || 0;
5812
5842
  const stylePaddingBottom = state.props.stylePaddingBottom || 0;
5813
5843
  let hasUnknownTailSize = false;
5814
5844
  for (let index = anchorIndex; index < data.length; index++) {
5815
- const itemKey = getId(state, index);
5816
- const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
5845
+ const size = getKnownOrFixedItemSize(ctx, index);
5817
5846
  const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
5818
5847
  if (size === void 0) {
5819
5848
  hasUnknownTailSize = true;
@@ -5823,15 +5852,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
5823
5852
  }
5824
5853
  }
5825
5854
  contentBelowAnchor += footerSize + stylePaddingBottom;
5855
+ isReady = !hasUnknownTailSize;
5826
5856
  nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
5857
+ } else if (anchorIndex >= 0) {
5858
+ isReady = false;
5827
5859
  }
5828
5860
  }
5829
- if (previousSize !== nextSize) {
5830
- set$(ctx, "anchoredEndSpaceSize", nextSize);
5831
- (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5832
- if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
5861
+ const didSizeChange = previousSize !== nextSize;
5862
+ const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
5863
+ if (isReady && (didSizeChange || didReadyAnchorChange)) {
5864
+ state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
5865
+ state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
5866
+ if (didSizeChange) {
5867
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
5868
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
5869
+ }
5870
+ if (didSizeChange && (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset)) {
5833
5871
  updateScroll(ctx, state.scroll, true);
5834
5872
  }
5873
+ (_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
5835
5874
  }
5836
5875
  return nextSize;
5837
5876
  }
@@ -6064,6 +6103,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
6064
6103
  }
6065
6104
  }
6066
6105
 
6106
+ // src/core/scrollToEnd.ts
6107
+ function scrollToEnd(ctx, options) {
6108
+ const state = ctx.state;
6109
+ const data = state.props.data;
6110
+ const index = data.length - 1;
6111
+ if (index === -1) {
6112
+ return false;
6113
+ }
6114
+ const paddingBottom = state.props.stylePaddingBottom || 0;
6115
+ const footerSize = peek$(ctx, "footerSize") || 0;
6116
+ scrollToIndex(ctx, {
6117
+ ...options,
6118
+ index,
6119
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6120
+ viewPosition: 1
6121
+ });
6122
+ return true;
6123
+ }
6124
+
6067
6125
  // src/utils/createImperativeHandle.ts
6068
6126
  var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
6069
6127
  function getAverageItemSizes(state) {
@@ -6079,7 +6137,7 @@ function getAverageItemSizes(state) {
6079
6137
  }
6080
6138
  return averageItemSizes;
6081
6139
  }
6082
- function createImperativeHandle(ctx) {
6140
+ function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
6083
6141
  const state = ctx.state;
6084
6142
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
6085
6143
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
@@ -6096,15 +6154,10 @@ function createImperativeHandle(ctx) {
6096
6154
  if (targetIndex >= dataLength) {
6097
6155
  return false;
6098
6156
  }
6099
- if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex || props.getFixedItemSize) {
6157
+ if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
6100
6158
  return true;
6101
6159
  }
6102
- for (let index = anchorIndex; index < dataLength; index++) {
6103
- if (!state.sizesKnown.has(getId(state, index))) {
6104
- return false;
6105
- }
6106
- }
6107
- return true;
6160
+ return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
6108
6161
  };
6109
6162
  const runWhenReady = (token, run, isReady) => {
6110
6163
  const startedAt = Date.now();
@@ -6127,11 +6180,7 @@ function createImperativeHandle(ctx) {
6127
6180
  };
6128
6181
  requestAnimationFrame(check);
6129
6182
  };
6130
- const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6131
- var _a3;
6132
- const token = ++imperativeScrollToken;
6133
- (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6134
- state.pendingScrollResolve = resolve;
6183
+ const runScrollRequest = (token, resolve, run, isReady = () => true) => {
6135
6184
  const runNow = () => {
6136
6185
  if (token !== imperativeScrollToken) {
6137
6186
  return;
@@ -6149,7 +6198,33 @@ function createImperativeHandle(ctx) {
6149
6198
  } else {
6150
6199
  runNow();
6151
6200
  }
6201
+ };
6202
+ const startImperativeScroll = (resolve) => {
6203
+ var _a3;
6204
+ const token = ++imperativeScrollToken;
6205
+ state.pendingScrollToEnd = void 0;
6206
+ (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
6207
+ state.pendingScrollResolve = resolve;
6208
+ return token;
6209
+ };
6210
+ const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
6211
+ const token = startImperativeScroll(resolve);
6212
+ runScrollRequest(token, resolve, run, isReady);
6152
6213
  });
6214
+ state.runPendingScrollToEnd = () => {
6215
+ const pendingScroll = state.pendingScrollToEnd;
6216
+ if (pendingScroll) {
6217
+ state.pendingScrollToEnd = void 0;
6218
+ if (pendingScroll.token === imperativeScrollToken) {
6219
+ runScrollRequest(
6220
+ pendingScroll.token,
6221
+ pendingScroll.resolve,
6222
+ () => scrollToEnd(ctx, pendingScroll.options),
6223
+ () => isScrollToIndexReady(state.props.data.length - 1, true)
6224
+ );
6225
+ }
6226
+ }
6227
+ };
6153
6228
  const scrollIndexIntoView = (options) => {
6154
6229
  if (state) {
6155
6230
  const { index, ...rest } = options;
@@ -6248,26 +6323,20 @@ function createImperativeHandle(ctx) {
6248
6323
  }
6249
6324
  return false;
6250
6325
  }),
6251
- scrollToEnd: (options) => runScrollWithPromise(
6252
- () => {
6253
- const data = state.props.data;
6254
- const stylePaddingBottom = state.props.stylePaddingBottom;
6255
- const index = data.length - 1;
6256
- if (index !== -1) {
6257
- const paddingBottom = stylePaddingBottom || 0;
6258
- const footerSize = peek$(ctx, "footerSize") || 0;
6259
- scrollToIndex(ctx, {
6260
- ...options,
6261
- index,
6262
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
6263
- viewPosition: 1
6264
- });
6265
- return true;
6266
- }
6267
- return false;
6268
- },
6269
- () => isScrollToIndexReady(state.props.data.length - 1, true)
6270
- ),
6326
+ scrollToEnd: (options) => new Promise((resolve) => {
6327
+ var _a3;
6328
+ const token = startImperativeScroll(resolve);
6329
+ state.pendingScrollToEnd = {
6330
+ options,
6331
+ resolve,
6332
+ token
6333
+ };
6334
+ if (scheduleImperativeScrollCommit) {
6335
+ scheduleImperativeScrollCommit();
6336
+ } else {
6337
+ (_a3 = state.runPendingScrollToEnd) == null ? void 0 : _a3.call(state);
6338
+ }
6339
+ }),
6271
6340
  scrollToIndex: (params) => {
6272
6341
  return runScrollWithPromise(
6273
6342
  () => {
@@ -6637,6 +6706,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
6637
6706
  viewOffset: 0
6638
6707
  } : void 0;
6639
6708
  const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
6709
+ const [, scheduleImperativeScrollCommit] = React3.useReducer((value) => value + 1, 0);
6640
6710
  const ctx = useStateContext();
6641
6711
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
6642
6712
  const refScroller = useRef(null);
@@ -7001,7 +7071,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7001
7071
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
7002
7072
  useInit(() => {
7003
7073
  });
7004
- useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
7074
+ useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7075
+ useLayoutEffect(() => {
7076
+ var _a4;
7077
+ (_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
7078
+ });
7005
7079
  useEffect(() => {
7006
7080
  if (usesBootstrapInitialScroll) {
7007
7081
  return;
package/reanimated.d.ts CHANGED
@@ -389,12 +389,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
389
389
  size?: boolean;
390
390
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
391
391
  }
392
+ interface AnchoredEndSpaceReadyInfo {
393
+ anchorIndex: number | undefined;
394
+ anchorKey: string | undefined;
395
+ size: number;
396
+ }
397
+ interface ScrollToEndOptions {
398
+ animated?: boolean;
399
+ viewOffset?: number;
400
+ }
392
401
  interface AnchoredEndSpaceConfig {
393
402
  anchorIndex: number;
394
403
  anchorOffset?: number;
395
404
  anchorMaxSize?: number;
396
405
  includeInEndInset?: boolean;
397
406
  onSizeChanged?: (size: number) => void;
407
+ onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
398
408
  }
399
409
  interface StickyHeaderConfig {
400
410
  /**
@@ -526,10 +536,7 @@ type LegendListRef$1 = {
526
536
  * @param options.animated - If true, animates the scroll. Default: true.
527
537
  * @param options.viewOffset - Offset from the target position.
528
538
  */
529
- scrollToEnd(options?: {
530
- animated?: boolean | undefined;
531
- viewOffset?: number | undefined;
532
- }): Promise<void>;
539
+ scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
533
540
  /**
534
541
  * Scrolls to a specific index in the list.
535
542
  * @param params - Parameters for scrolling.
package/section-list.d.ts CHANGED
@@ -445,12 +445,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
445
445
  size?: boolean;
446
446
  shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
447
447
  }
448
+ interface AnchoredEndSpaceReadyInfo {
449
+ anchorIndex: number | undefined;
450
+ anchorKey: string | undefined;
451
+ size: number;
452
+ }
453
+ interface ScrollToEndOptions {
454
+ animated?: boolean;
455
+ viewOffset?: number;
456
+ }
448
457
  interface AnchoredEndSpaceConfig {
449
458
  anchorIndex: number;
450
459
  anchorOffset?: number;
451
460
  anchorMaxSize?: number;
452
461
  includeInEndInset?: boolean;
453
462
  onSizeChanged?: (size: number) => void;
463
+ onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
454
464
  }
455
465
  interface StickyHeaderConfig {
456
466
  /**
@@ -582,10 +592,7 @@ type LegendListRef$1 = {
582
592
  * @param options.animated - If true, animates the scroll. Default: true.
583
593
  * @param options.viewOffset - Offset from the target position.
584
594
  */
585
- scrollToEnd(options?: {
586
- animated?: boolean | undefined;
587
- viewOffset?: number | undefined;
588
- }): Promise<void>;
595
+ scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
589
596
  /**
590
597
  * Scrolls to a specific index in the list.
591
598
  * @param params - Parameters for scrolling.