@legendapp/list 3.0.0-beta.10 → 3.0.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
@@ -411,48 +411,70 @@ function useInit(cb) {
411
411
 
412
412
  // src/state/ContextContainer.ts
413
413
  var ContextContainer = React2.createContext(null);
414
+ function useContextContainer() {
415
+ return React2.useContext(ContextContainer);
416
+ }
414
417
  function useViewability(callback, configId) {
415
418
  const ctx = useStateContext();
416
- const { containerId } = React2.useContext(ContextContainer);
417
- const key = containerId + (configId != null ? configId : "");
419
+ const containerContext = useContextContainer();
418
420
  useInit(() => {
421
+ if (!containerContext) {
422
+ return;
423
+ }
424
+ const { containerId } = containerContext;
425
+ const key = containerId + (configId != null ? configId : "");
419
426
  const value = ctx.mapViewabilityValues.get(key);
420
427
  if (value) {
421
428
  callback(value);
422
429
  }
423
430
  });
424
- ctx.mapViewabilityCallbacks.set(key, callback);
425
- React2.useEffect(
426
- () => () => {
431
+ React2.useEffect(() => {
432
+ if (!containerContext) {
433
+ return;
434
+ }
435
+ const { containerId } = containerContext;
436
+ const key = containerId + (configId != null ? configId : "");
437
+ ctx.mapViewabilityCallbacks.set(key, callback);
438
+ return () => {
427
439
  ctx.mapViewabilityCallbacks.delete(key);
428
- },
429
- []
430
- );
440
+ };
441
+ }, [ctx, callback, configId, containerContext]);
431
442
  }
432
443
  function useViewabilityAmount(callback) {
433
444
  const ctx = useStateContext();
434
- const { containerId } = React2.useContext(ContextContainer);
445
+ const containerContext = useContextContainer();
435
446
  useInit(() => {
447
+ if (!containerContext) {
448
+ return;
449
+ }
450
+ const { containerId } = containerContext;
436
451
  const value = ctx.mapViewabilityAmountValues.get(containerId);
437
452
  if (value) {
438
453
  callback(value);
439
454
  }
440
455
  });
441
- ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
442
- React2.useEffect(
443
- () => () => {
456
+ React2.useEffect(() => {
457
+ if (!containerContext) {
458
+ return;
459
+ }
460
+ const { containerId } = containerContext;
461
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
462
+ return () => {
444
463
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
445
- },
446
- []
447
- );
464
+ };
465
+ }, [ctx, callback, containerContext]);
448
466
  }
449
467
  function useRecyclingEffect(effect) {
450
- const { index, value } = React2.useContext(ContextContainer);
468
+ const containerContext = useContextContainer();
451
469
  const prevValues = React2.useRef({
452
470
  prevIndex: void 0,
453
471
  prevItem: void 0
454
472
  });
455
473
  React2.useEffect(() => {
474
+ if (!containerContext) {
475
+ return;
476
+ }
477
+ const { index, value } = containerContext;
456
478
  let ret;
457
479
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
458
480
  ret = effect({
@@ -467,38 +489,58 @@ function useRecyclingEffect(effect) {
467
489
  prevItem: value
468
490
  };
469
491
  return ret;
470
- }, [index, value, effect]);
492
+ }, [effect, containerContext]);
471
493
  }
472
494
  function useRecyclingState(valueOrFun) {
473
- const { index, value, itemKey, triggerLayout } = React2.useContext(ContextContainer);
474
- const refState = React2.useRef({
475
- itemKey: null,
476
- value: null
495
+ var _a3, _b;
496
+ const containerContext = useContextContainer();
497
+ const computeValue = (ctx) => {
498
+ if (isFunction(valueOrFun)) {
499
+ const initializer = valueOrFun;
500
+ return ctx ? initializer({
501
+ index: ctx.index,
502
+ item: ctx.value,
503
+ prevIndex: void 0,
504
+ prevItem: void 0
505
+ }) : initializer();
506
+ }
507
+ return valueOrFun;
508
+ };
509
+ const [stateValue, setStateValue] = React2.useState(() => {
510
+ return computeValue(containerContext);
477
511
  });
478
- const [_, setRenderNum] = React2.useState(0);
479
- const state = refState.current;
480
- if (state.itemKey !== itemKey) {
481
- state.itemKey = itemKey;
482
- state.value = isFunction(valueOrFun) ? valueOrFun({
483
- index,
484
- item: value,
485
- prevIndex: void 0,
486
- prevItem: void 0
487
- }) : valueOrFun;
512
+ const prevItemKeyRef = React2.useRef((_a3 = containerContext == null ? void 0 : containerContext.itemKey) != null ? _a3 : null);
513
+ const currentItemKey = (_b = containerContext == null ? void 0 : containerContext.itemKey) != null ? _b : null;
514
+ if (currentItemKey !== null && prevItemKeyRef.current !== currentItemKey) {
515
+ prevItemKeyRef.current = currentItemKey;
516
+ setStateValue(computeValue(containerContext));
488
517
  }
518
+ const triggerLayout = containerContext == null ? void 0 : containerContext.triggerLayout;
489
519
  const setState = React2.useCallback(
490
520
  (newState) => {
491
- state.value = isFunction(newState) ? newState(state.value) : newState;
492
- setRenderNum((v) => v + 1);
521
+ if (!triggerLayout) {
522
+ return;
523
+ }
524
+ setStateValue((prevValue) => {
525
+ return isFunction(newState) ? newState(prevValue) : newState;
526
+ });
493
527
  triggerLayout();
494
528
  },
495
- [triggerLayout, state]
529
+ [triggerLayout]
496
530
  );
497
- return [state.value, setState];
531
+ return [stateValue, setState];
498
532
  }
499
533
  function useIsLastItem() {
500
- const { itemKey } = React2.useContext(ContextContainer);
501
- const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
534
+ const containerContext = useContextContainer();
535
+ const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
536
+ if (containerContext) {
537
+ const { itemKey } = containerContext;
538
+ if (!isNullOrUndefined(itemKey)) {
539
+ return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
540
+ }
541
+ }
542
+ return false;
543
+ });
502
544
  return isLast;
503
545
  }
504
546
  function useListScrollSize() {
@@ -508,8 +550,9 @@ function useListScrollSize() {
508
550
  var noop = () => {
509
551
  };
510
552
  function useSyncLayout() {
511
- if (IsNewArchitecture) {
512
- const { triggerLayout: syncLayout } = React2.useContext(ContextContainer);
553
+ const containerContext = useContextContainer();
554
+ if (IsNewArchitecture && containerContext) {
555
+ const { triggerLayout: syncLayout } = containerContext;
513
556
  return syncLayout;
514
557
  } else {
515
558
  return noop;
@@ -869,7 +912,6 @@ var ListComponent = typedMemo(function ListComponent2({
869
912
  getRenderedItem: getRenderedItem2,
870
913
  updateItemSize: updateItemSize2,
871
914
  refScrollView,
872
- maintainVisibleContentPosition,
873
915
  renderScrollComponent,
874
916
  scrollAdjustHandler,
875
917
  onLayoutHeader,
@@ -878,6 +920,7 @@ var ListComponent = typedMemo(function ListComponent2({
878
920
  ...rest
879
921
  }) {
880
922
  const ctx = useStateContext();
923
+ const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
881
924
  const ScrollComponent = renderScrollComponent ? React2.useMemo(
882
925
  () => React2__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
883
926
  [renderScrollComponent]
@@ -895,7 +938,7 @@ var ListComponent = typedMemo(function ListComponent2({
895
938
  ],
896
939
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
897
940
  horizontal,
898
- maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
941
+ maintainVisibleContentPosition: maintainVisibleContentPosition.scroll || maintainVisibleContentPosition.dataChanges ? { minIndexForVisible: 0 } : void 0,
899
942
  onLayout,
900
943
  onScroll: onScroll2,
901
944
  ref: refScrollView,
@@ -1166,7 +1209,7 @@ function checkFinishedScrollFrame(ctx) {
1166
1209
  if (scrollingTo) {
1167
1210
  const { state } = ctx;
1168
1211
  state.animFrameCheckFinishedScroll = void 0;
1169
- const scroll = state.scroll;
1212
+ const scroll = state.scrollPending;
1170
1213
  const adjust = state.scrollAdjustHandler.getAdjust();
1171
1214
  const clampedTargetOffset = clampScrollOffset(ctx, scrollingTo.offset - (scrollingTo.viewOffset || 0));
1172
1215
  const maxOffset = clampScrollOffset(ctx, scroll);
@@ -1521,14 +1564,16 @@ function ensureInitialAnchor(ctx) {
1521
1564
  function prepareMVCP(ctx, dataChanged) {
1522
1565
  const state = ctx.state;
1523
1566
  const { idsInView, positions, props } = state;
1524
- const { maintainVisibleContentPosition } = props;
1567
+ const {
1568
+ maintainVisibleContentPosition: { dataChanges: mvcpDataChanges, scroll: mvcpScroll }
1569
+ } = props;
1525
1570
  const scrollingTo = state.scrollingTo;
1526
1571
  let prevPosition;
1527
1572
  let targetId;
1528
1573
  const idsInViewWithPositions = [];
1529
1574
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1530
1575
  const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
1531
- const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1576
+ const shouldMVCP = dataChanged ? mvcpDataChanges : mvcpScroll;
1532
1577
  const indexByKey = state.indexByKey;
1533
1578
  if (shouldMVCP) {
1534
1579
  if (scrollTarget !== void 0) {
@@ -1554,7 +1599,7 @@ function prepareMVCP(ctx, dataChanged) {
1554
1599
  }
1555
1600
  return () => {
1556
1601
  let positionDiff = 0;
1557
- if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1602
+ if (dataChanged && targetId === void 0 && mvcpDataChanges) {
1558
1603
  for (let i = 0; i < idsInViewWithPositions.length; i++) {
1559
1604
  const { id, position } = idsInViewWithPositions[i];
1560
1605
  const newPosition = positions.get(id);
@@ -1591,7 +1636,7 @@ function prepareMVCP(ctx, dataChanged) {
1591
1636
  }
1592
1637
  }
1593
1638
  if (Math.abs(positionDiff) > 0.1) {
1594
- requestAdjust(ctx, positionDiff, dataChanged && maintainVisibleContentPosition);
1639
+ requestAdjust(ctx, positionDiff, dataChanged && mvcpDataChanges);
1595
1640
  }
1596
1641
  };
1597
1642
  }
@@ -1688,39 +1733,40 @@ function updateTotalSize(ctx) {
1688
1733
  // src/utils/getScrollVelocity.ts
1689
1734
  var getScrollVelocity = (state) => {
1690
1735
  const { scrollHistory } = state;
1691
- let velocity = 0;
1692
- if (scrollHistory.length >= 1) {
1693
- const newest = scrollHistory[scrollHistory.length - 1];
1694
- let oldest;
1695
- let start = 0;
1696
- const now = Date.now();
1697
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1698
- const entry = scrollHistory[i];
1699
- const nextEntry = scrollHistory[i + 1];
1700
- if (i > 0) {
1701
- const prevEntry = scrollHistory[i - 1];
1702
- const prevDirection = entry.scroll - prevEntry.scroll;
1703
- const currentDirection = nextEntry.scroll - entry.scroll;
1704
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1705
- start = i;
1706
- break;
1707
- }
1708
- }
1736
+ const newestIndex = scrollHistory.length - 1;
1737
+ if (newestIndex < 1) {
1738
+ return 0;
1739
+ }
1740
+ const newest = scrollHistory[newestIndex];
1741
+ const now = Date.now();
1742
+ let direction = 0;
1743
+ for (let i = newestIndex; i > 0; i--) {
1744
+ const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
1745
+ if (delta !== 0) {
1746
+ direction = Math.sign(delta);
1747
+ break;
1709
1748
  }
1710
- for (let i = start; i < scrollHistory.length - 1; i++) {
1711
- const entry = scrollHistory[i];
1712
- if (now - entry.time <= 1e3) {
1713
- oldest = entry;
1714
- break;
1715
- }
1749
+ }
1750
+ if (direction === 0) {
1751
+ return 0;
1752
+ }
1753
+ let oldest = newest;
1754
+ for (let i = newestIndex - 1; i >= 0; i--) {
1755
+ const current = scrollHistory[i];
1756
+ const next = scrollHistory[i + 1];
1757
+ const delta = next.scroll - current.scroll;
1758
+ const deltaSign = Math.sign(delta);
1759
+ if (deltaSign !== 0 && deltaSign !== direction) {
1760
+ break;
1716
1761
  }
1717
- if (oldest && oldest !== newest) {
1718
- const scrollDiff = newest.scroll - oldest.scroll;
1719
- const timeDiff = newest.time - oldest.time;
1720
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1762
+ if (now - current.time > 1e3) {
1763
+ break;
1721
1764
  }
1765
+ oldest = current;
1722
1766
  }
1723
- return velocity;
1767
+ const scrollDiff = newest.scroll - oldest.scroll;
1768
+ const timeDiff = newest.time - oldest.time;
1769
+ return timeDiff > 0 ? scrollDiff / timeDiff : 0;
1724
1770
  };
1725
1771
 
1726
1772
  // src/utils/updateSnapToOffsets.ts
@@ -2879,7 +2925,6 @@ function onScroll(ctx, event) {
2879
2925
  return;
2880
2926
  }
2881
2927
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2882
- state.scrollPending = newScroll;
2883
2928
  if (state.scrollingTo) {
2884
2929
  const maxOffset = clampScrollOffset(ctx, newScroll);
2885
2930
  if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
@@ -2893,8 +2938,11 @@ function onScroll(ctx, event) {
2893
2938
  return;
2894
2939
  }
2895
2940
  }
2941
+ state.scrollPending = newScroll;
2896
2942
  updateScroll(ctx, newScroll);
2897
- checkFinishedScroll(ctx);
2943
+ if (state.scrollingTo) {
2944
+ checkFinishedScroll(ctx);
2945
+ }
2898
2946
  onScrollProp == null ? void 0 : onScrollProp(event);
2899
2947
  }
2900
2948
 
@@ -3248,6 +3296,24 @@ function getRenderedItem(ctx, key) {
3248
3296
  }
3249
3297
  return { index, item: data[index], renderedItem };
3250
3298
  }
3299
+
3300
+ // src/utils/normalizeMaintainVisibleContentPosition.ts
3301
+ function normalizeMaintainVisibleContentPosition(value) {
3302
+ var _a3, _b;
3303
+ if (value === true) {
3304
+ return { dataChanges: true, scroll: true };
3305
+ }
3306
+ if (value && typeof value === "object") {
3307
+ return {
3308
+ dataChanges: (_a3 = value.dataChanges) != null ? _a3 : false,
3309
+ scroll: (_b = value.scroll) != null ? _b : true
3310
+ };
3311
+ }
3312
+ if (value === false) {
3313
+ return { dataChanges: false, scroll: false };
3314
+ }
3315
+ return { dataChanges: false, scroll: true };
3316
+ }
3251
3317
  function useThrottleDebounce(mode) {
3252
3318
  const timeoutRef = React2.useRef(null);
3253
3319
  const lastCallTimeRef = React2.useRef(0);
@@ -3342,7 +3408,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3342
3408
  ListHeaderComponent,
3343
3409
  maintainScrollAtEnd = false,
3344
3410
  maintainScrollAtEndThreshold = 0.1,
3345
- maintainVisibleContentPosition = false,
3411
+ maintainVisibleContentPosition: maintainVisibleContentPositionProp,
3346
3412
  numColumns: numColumnsProp = 1,
3347
3413
  onEndReached,
3348
3414
  onEndReachedThreshold = 0.5,
@@ -3380,6 +3446,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3380
3446
  const style = { ...StyleSheet.flatten(styleProp) };
3381
3447
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
3382
3448
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3449
+ const maintainVisibleContentPositionConfig = normalizeMaintainVisibleContentPosition(
3450
+ maintainVisibleContentPositionProp
3451
+ );
3383
3452
  const [renderNum, setRenderNum] = React2.useState(0);
3384
3453
  const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3385
3454
  const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
@@ -3464,7 +3533,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3464
3533
  };
3465
3534
  const internalState = ctx.state;
3466
3535
  internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
3467
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3536
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPositionConfig);
3468
3537
  set$(ctx, "extraData", extraData);
3469
3538
  }
3470
3539
  refState.current = ctx.state;
@@ -3495,7 +3564,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3495
3564
  keyExtractor,
3496
3565
  maintainScrollAtEnd,
3497
3566
  maintainScrollAtEndThreshold,
3498
- maintainVisibleContentPosition,
3567
+ maintainVisibleContentPosition: maintainVisibleContentPositionConfig,
3499
3568
  numColumns: numColumnsProp,
3500
3569
  onEndReached,
3501
3570
  onEndReachedThreshold,
@@ -3530,7 +3599,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3530
3599
  setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
3531
3600
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3532
3601
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3533
- if (paddingDiff && prevPaddingTop !== void 0 && Platform2.OS === "ios") {
3602
+ if (maintainVisibleContentPositionConfig.scroll && paddingDiff && prevPaddingTop !== void 0 && Platform2.OS === "ios") {
3534
3603
  if (state.scroll < 0) {
3535
3604
  paddingDiff += state.scroll;
3536
3605
  }
@@ -3575,7 +3644,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3575
3644
  value = 0;
3576
3645
  }
3577
3646
  if (!value) {
3578
- state.didFinishInitialScroll = true;
3647
+ setInitialRenderState(ctx, { didInitialScroll: true });
3579
3648
  }
3580
3649
  return value;
3581
3650
  }, [renderNum]);
@@ -3704,7 +3773,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3704
3773
  initialContentOffset,
3705
3774
  ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
3706
3775
  ListHeaderComponent,
3707
- maintainVisibleContentPosition,
3708
3776
  onLayout,
3709
3777
  onLayoutHeader,
3710
3778
  onMomentumScrollEnd: fns.onMomentumScrollEnd,