virtua 0.51.0 → 0.51.1

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.
@@ -20,28 +20,19 @@ var createPromise = () => {
20
20
  });
21
21
  return [promise, resolve];
22
22
  };
23
- var once = (fn) => {
24
- let cache;
25
- return () => {
26
- if (fn) {
27
- cache = fn();
28
- fn = undefined;
29
- }
30
- return cache;
31
- };
32
- };
33
23
 
34
24
  //#endregion
35
25
  //#region src/core/environment.ts
36
26
  var isBrowser = typeof window !== "undefined";
37
27
  var getCurrentDocument = (node) => node.ownerDocument;
38
28
  var getCurrentWindow = (doc) => doc.defaultView;
39
- var isIOSWebKit = /*#__PURE__*/ once(() => {
40
- if (/iP(hone|od|ad)/.test(navigator.userAgent)) {
41
- return true;
29
+ var isIOS;
30
+ var isIOSWebKit = () => {
31
+ if (isIOS == null) {
32
+ isIOS = /iP(hone|od|ad)/.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 0;
42
33
  }
43
- return navigator.platform === "MacIntel" && navigator.maxTouchPoints > 0;
44
- });
34
+ return isIOS;
35
+ };
45
36
 
46
37
  //#endregion
47
38
  //#region src/core/store.ts
@@ -418,17 +409,27 @@ var createResizeObserver = (cb) => {
418
409
  }
419
410
  };
420
411
  };
421
- var normalizeScrollOffset = (offset, isNegative) => {
422
- return isNegative ? -offset : offset;
423
- };
424
- var createScrollObserver = (store, viewport, isHorizontal, getScrollOffset, updateScrollOffset, getStartOffset) => {
412
+ var createScrollObserver = (store, viewport, scroller, isHorizontal, isRtl, onMomentumJump, getStartOffset) => {
425
413
  let lastScrollTime = 0;
426
414
  let wheeling = false;
427
415
  let touching = false;
428
416
  let justTouchEnded = false;
429
417
  let stillMomentumScrolling = false;
418
+ let cancelScroll;
430
419
  let scrollEndTimer;
431
420
  const now = Date.now;
421
+ const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
422
+ const scrollToKey = isHorizontal ? "left" : "top";
423
+ const normalizeScrollOffset = (offset) => {
424
+ return isRtl ? -offset : offset;
425
+ };
426
+ const getScrollOffset = () => normalizeScrollOffset(scroller[scrollOffsetKey]);
427
+ const scrollTo = (offset, smooth) => {
428
+ scroller.scrollTo({
429
+ [scrollToKey]: normalizeScrollOffset(offset),
430
+ behavior: smooth ? "smooth" : "instant"
431
+ });
432
+ };
432
433
  const onScrollEnd = () => {
433
434
  if (wheeling || touching) {
434
435
  wheeling = false;
@@ -487,94 +488,90 @@ var createScrollObserver = (store, viewport, isHorizontal, getScrollOffset, upda
487
488
  _fixScrollJump: () => {
488
489
  const [jump, shift] = store._flushJump();
489
490
  if (!jump) return;
490
- updateScrollOffset(jump, shift, stillMomentumScrolling);
491
+ if (stillMomentumScrolling && onMomentumJump) {
492
+ onMomentumJump();
493
+ }
491
494
  stillMomentumScrolling = false;
492
- if (shift && store.$getViewportSize() > store.$getTotalSize()) {
493
- store.$update(1, getScrollOffset());
495
+ const target = store.$getScrollOffset() + jump;
496
+ if (target <= 0 || target >= store.$getStartSpacerSize() + store.$getTotalSize() - store.$getViewportSize()) {
497
+ scrollTo(target);
498
+ } else {
499
+ scroller.scrollBy({
500
+ [scrollToKey]: normalizeScrollOffset(jump),
501
+ behavior: "instant"
502
+ });
494
503
  }
495
- }
496
- };
497
- };
498
-
499
- //#endregion
500
- //#region src/core/driver.ts
501
- var createScrollScheduler = (store, initialized, scroll) => {
502
- let cancelScroll;
503
- return [async (getTargetOffset, smooth) => {
504
- if (!await initialized()) {
505
- return;
506
- }
507
- if (cancelScroll) {
508
- cancelScroll();
509
- }
510
- let stopped;
511
- let timerId;
512
- let unsubscribe;
513
- const stop = cancelScroll = () => {
514
- stopped = true;
515
- cancelTimeout(timerId);
516
- unsubscribe && unsubscribe();
517
- };
518
- const onMeasured = () => {
519
- if (stopped) {
520
- return;
504
+ if (shift) {
505
+ cancelScroll && cancelScroll();
506
+ if (store.$getViewportSize() > store.$getTotalSize()) {
507
+ store.$update(1, getScrollOffset());
508
+ }
521
509
  }
522
- if (store.$getViewportSize()) {
523
- cancelTimeout(timerId);
524
- timerId = timeout(stop, 150);
510
+ },
511
+ _scroll: (getTargetOffset, smooth) => {
512
+ if (cancelScroll) {
513
+ cancelScroll();
525
514
  }
526
- if (smooth) {
527
- for (let [i, end] = store.$getRange(0); i <= end; i++) {
528
- if (store.$isUnmeasuredItem(i)) {
529
- return;
515
+ let stopped;
516
+ let timerId;
517
+ let unsubscribe;
518
+ const stop = cancelScroll = () => {
519
+ stopped = true;
520
+ cancelTimeout(timerId);
521
+ unsubscribe && unsubscribe();
522
+ };
523
+ const onMeasured = () => {
524
+ if (stopped) {
525
+ return;
526
+ }
527
+ if (store.$getViewportSize()) {
528
+ cancelTimeout(timerId);
529
+ timerId = timeout(stop, 150);
530
+ }
531
+ if (smooth) {
532
+ for (let [i, end] = store.$getRange(0); i <= end; i++) {
533
+ if (store.$isUnmeasuredItem(i)) {
534
+ return;
535
+ }
530
536
  }
537
+ stop();
531
538
  }
532
- stop();
533
- }
534
- store.$update(7);
535
- scroll(getTargetOffset(), smooth);
536
- };
537
- const start = () => {
538
- if (stopped) {
539
- return;
540
- }
541
- let queued;
542
- unsubscribe = store.$subscribe(2, () => {
543
- if (queued) {
539
+ store.$update(7);
540
+ scrollTo(getTargetOffset(), smooth);
541
+ };
542
+ const start = () => {
543
+ if (stopped) {
544
544
  return;
545
545
  }
546
- queued = true;
547
- microtask(() => {
548
- queued = false;
549
- onMeasured();
546
+ let queued;
547
+ unsubscribe = store.$subscribe(2, () => {
548
+ if (queued) {
549
+ return;
550
+ }
551
+ queued = true;
552
+ microtask(() => {
553
+ queued = false;
554
+ onMeasured();
555
+ });
550
556
  });
551
- });
552
- onMeasured();
553
- };
554
- if (smooth) {
555
- store.$update(8, getTargetOffset());
556
- microtask(start);
557
- } else {
558
- start();
557
+ onMeasured();
558
+ };
559
+ if (smooth) {
560
+ store.$update(8, getTargetOffset());
561
+ microtask(start);
562
+ } else {
563
+ start();
564
+ }
559
565
  }
560
- }, () => {
561
- cancelScroll && cancelScroll();
562
- }];
566
+ };
563
567
  };
568
+
569
+ //#endregion
570
+ //#region src/core/driver.ts
564
571
  var createContainerDriver = (store, isHorizontal) => {
565
572
  let viewportElement;
566
573
  let scrollObserver;
567
574
  let initialized = createPromise();
568
- let isRtl = false;
569
- const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
570
- const scrollToKey = isHorizontal ? "left" : "top";
571
- const overflowKey = isHorizontal ? "overflowX" : "overflowY";
572
- const [scheduleScroll, cancelScroll] = createScrollScheduler(store, () => initialized[0], (offset, smooth) => {
573
- viewportElement.scrollTo({
574
- [scrollToKey]: normalizeScrollOffset(offset, isRtl),
575
- behavior: smooth ? "smooth" : "instant"
576
- });
577
- });
578
575
  const sizeKey = isHorizontal ? "width" : "height";
579
576
  const mountedIndexes = new WeakMap();
580
577
  const resizeObserver = createResizeObserver((entries) => {
@@ -597,33 +594,14 @@ var createContainerDriver = (store, isHorizontal) => {
597
594
  return {
598
595
  $observe(containerElement, viewport = containerElement.parentElement) {
599
596
  resizeObserver._observe(viewportElement = viewport);
600
- if (isHorizontal) {
601
- isRtl = getComputedStyle(viewport).direction === "rtl";
602
- }
603
- scrollObserver = createScrollObserver(store, viewport, isHorizontal, () => normalizeScrollOffset(viewport[scrollOffsetKey], isRtl), (jump, shift, isMomentumScrolling) => {
604
- if (isMomentumScrolling) {
605
- const style = viewport.style;
606
- const prev = style[overflowKey];
607
- style[overflowKey] = "hidden";
608
- timeout(() => {
609
- style[overflowKey] = prev;
610
- });
611
- }
612
- const target = store.$getScrollOffset() + jump;
613
- if (target <= 0 || target >= store.$getStartSpacerSize() + store.$getTotalSize() - store.$getViewportSize()) {
614
- viewport.scrollTo({
615
- [scrollToKey]: normalizeScrollOffset(target, isRtl),
616
- behavior: "instant"
617
- });
618
- } else {
619
- viewport.scrollBy({
620
- [scrollToKey]: normalizeScrollOffset(jump, isRtl),
621
- behavior: "instant"
622
- });
623
- }
624
- if (shift) {
625
- cancelScroll();
626
- }
597
+ scrollObserver = createScrollObserver(store, viewport, viewport, isHorizontal, isHorizontal && getComputedStyle(viewport).direction === "rtl", () => {
598
+ const overflowKey = isHorizontal ? "overflowX" : "overflowY";
599
+ const style = viewport.style;
600
+ const prev = style[overflowKey];
601
+ style[overflowKey] = "hidden";
602
+ timeout(() => {
603
+ style[overflowKey] = prev;
604
+ });
627
605
  });
628
606
  initialized[1](true);
629
607
  },
@@ -641,7 +619,11 @@ var createContainerDriver = (store, isHorizontal) => {
641
619
  resizeObserver._unobserve(el);
642
620
  };
643
621
  },
644
- $scroll: scheduleScroll,
622
+ async $scroll(getTargetOffset, smooth) {
623
+ if (await initialized[0]) {
624
+ scrollObserver._scroll(getTargetOffset, smooth);
625
+ }
626
+ },
645
627
  $effect() {
646
628
  scrollObserver && scrollObserver._fixScrollJump();
647
629
  },
@@ -655,15 +637,6 @@ var createWindowDriver = (store, isHorizontal) => {
655
637
  let getBaseOffset;
656
638
  let onViewportResize;
657
639
  let initialized = createPromise();
658
- let isRtl = false;
659
- const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
660
- const scrollToKey = isHorizontal ? "left" : "top";
661
- const [scheduleScroll, cancelScroll] = createScrollScheduler(store, () => initialized[0], (offset, smooth) => {
662
- viewportElement.scrollTo({
663
- [scrollToKey]: normalizeScrollOffset(offset, isRtl),
664
- behavior: smooth ? "smooth" : "instant"
665
- });
666
- });
667
640
  const sizeKey = isHorizontal ? "width" : "height";
668
641
  const mountedIndexes = new WeakMap();
669
642
  const resizeObserver = createResizeObserver((entries) => {
@@ -683,20 +656,21 @@ var createWindowDriver = (store, isHorizontal) => {
683
656
  store.$update(3, resizes);
684
657
  }
685
658
  });
686
- const calcOffsetToViewport = (node, viewport, until, isHorizontal, offset = 0) => {
687
- const offsetKey = isHorizontal ? "offsetLeft" : "offsetTop";
688
- const offsetSum = offset + (isRtl ? viewport.clientWidth - node[offsetKey] - node.offsetWidth : node[offsetKey]);
689
- const parent = node.offsetParent;
690
- if (node === until || !parent) {
691
- return offsetSum;
692
- }
693
- return calcOffsetToViewport(parent, viewport, until, isHorizontal, offsetSum);
694
- };
695
659
  return {
696
660
  $observe(container) {
697
661
  const document = getCurrentDocument(container);
698
662
  const window = getCurrentWindow(document);
699
663
  const viewport = viewportElement = document.scrollingElement;
664
+ const isRtl = isHorizontal && getComputedStyle(viewport).direction === "rtl";
665
+ const calcOffsetToViewport = (node, viewport, until, isHorizontal, offset = 0) => {
666
+ const offsetKey = isHorizontal ? "offsetLeft" : "offsetTop";
667
+ const offsetSum = offset + (isRtl ? viewport.clientWidth - node[offsetKey] - node.offsetWidth : node[offsetKey]);
668
+ const parent = node.offsetParent;
669
+ if (node === until || !parent) {
670
+ return offsetSum;
671
+ }
672
+ return calcOffsetToViewport(parent, viewport, until, isHorizontal, offsetSum);
673
+ };
700
674
  const baseOffset = getBaseOffset = () => {
701
675
  return calcOffsetToViewport(container, viewport, document.body, isHorizontal);
702
676
  };
@@ -708,26 +682,7 @@ var createWindowDriver = (store, isHorizontal) => {
708
682
  cleanupOnWindowResize = () => {
709
683
  window.removeEventListener("resize", onWindowResize);
710
684
  };
711
- if (isHorizontal) {
712
- isRtl = getComputedStyle(viewport).direction === "rtl";
713
- }
714
- scrollObserver = createScrollObserver(store, window, isHorizontal, () => normalizeScrollOffset(viewport[scrollOffsetKey], isRtl), (jump, shift) => {
715
- const target = store.$getScrollOffset() + jump;
716
- if (target <= 0 || target >= store.$getStartSpacerSize() + store.$getTotalSize() - store.$getViewportSize()) {
717
- viewport.scrollTo({
718
- [scrollToKey]: normalizeScrollOffset(target, isRtl),
719
- behavior: "instant"
720
- });
721
- } else {
722
- viewport.scrollBy({
723
- [scrollToKey]: normalizeScrollOffset(jump, isRtl),
724
- behavior: "instant"
725
- });
726
- }
727
- if (shift) {
728
- cancelScroll();
729
- }
730
- }, baseOffset);
685
+ scrollObserver = createScrollObserver(store, window, viewport, isHorizontal, isRtl, null, baseOffset);
731
686
  initialized[1](true);
732
687
  },
733
688
  $dispose() {
@@ -746,7 +701,11 @@ var createWindowDriver = (store, isHorizontal) => {
746
701
  resizeObserver._unobserve(el);
747
702
  };
748
703
  },
749
- $scroll: scheduleScroll,
704
+ async $scroll(getTargetOffset, smooth) {
705
+ if (await initialized[0]) {
706
+ scrollObserver._scroll(getTargetOffset, smooth);
707
+ }
708
+ },
750
709
  $effect() {
751
710
  scrollObserver && scrollObserver._fixScrollJump();
752
711
  },
@@ -760,19 +719,6 @@ var createContainerGridDriver = (rowStore, colStore) => {
760
719
  let rowScrollObserver;
761
720
  let colScrollObserver;
762
721
  let initialized = createPromise();
763
- let isRtl = false;
764
- const [scheduleScrollX, cancelScrollX] = createScrollScheduler(colStore, () => initialized[0], (offset, smooth) => {
765
- viewportElement.scrollTo({
766
- left: normalizeScrollOffset(offset, isRtl),
767
- behavior: smooth ? "smooth" : "instant"
768
- });
769
- });
770
- const [scheduleScrollY, cancelScrollY] = createScrollScheduler(rowStore, () => initialized[0], (offset, smooth) => {
771
- viewportElement.scrollTo({
772
- top: offset,
773
- behavior: smooth ? "smooth" : "instant"
774
- });
775
- });
776
722
  const mountedIndexes = new WeakMap();
777
723
  const maybeCachedRowIndexes = new Set();
778
724
  const maybeCachedColIndexes = new Set();
@@ -849,43 +795,20 @@ var createContainerGridDriver = (rowStore, colStore) => {
849
795
  colStore.$update(3, widthResizes);
850
796
  }
851
797
  });
852
- const observeAxisScroll = (store, isHorizontal, cancelScroll) => {
853
- const viewport = viewportElement;
854
- const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
855
- const overflowKey = isHorizontal ? "overflowX" : "overflowY";
856
- const rtl = isHorizontal && isRtl;
857
- return createScrollObserver(store, viewport, isHorizontal, () => normalizeScrollOffset(viewport[scrollOffsetKey], rtl), (jump, shift, isMomentumScrolling) => {
858
- if (isMomentumScrolling) {
798
+ return {
799
+ $observe(containerElement, viewport = containerElement.parentElement) {
800
+ resizeObserver._observe(viewportElement = viewport);
801
+ const isRtl = getComputedStyle(viewport).direction === "rtl";
802
+ const hackOverflow = (overflowKey) => () => {
859
803
  const style = viewport.style;
860
804
  const prev = style[overflowKey];
861
805
  style[overflowKey] = "hidden";
862
806
  timeout(() => {
863
807
  style[overflowKey] = prev;
864
808
  });
865
- }
866
- const target = store.$getScrollOffset() + jump;
867
- if (target <= 0 || target >= store.$getStartSpacerSize() + store.$getTotalSize() - store.$getViewportSize()) {
868
- viewport.scrollTo({
869
- [isHorizontal ? "left" : "top"]: normalizeScrollOffset(target, rtl),
870
- behavior: "instant"
871
- });
872
- } else {
873
- viewport.scrollBy({
874
- [isHorizontal ? "left" : "top"]: normalizeScrollOffset(jump, rtl),
875
- behavior: "instant"
876
- });
877
- }
878
- if (shift) {
879
- cancelScroll();
880
- }
881
- });
882
- };
883
- return {
884
- $observe(containerElement, viewport = containerElement.parentElement) {
885
- resizeObserver._observe(viewportElement = viewport);
886
- isRtl = getComputedStyle(viewport).direction === "rtl";
887
- rowScrollObserver = observeAxisScroll(rowStore, false, cancelScrollY);
888
- colScrollObserver = observeAxisScroll(colStore, true, cancelScrollX);
809
+ };
810
+ rowScrollObserver = createScrollObserver(rowStore, viewport, viewport, false, false, hackOverflow("overflowY"));
811
+ colScrollObserver = createScrollObserver(colStore, viewport, viewport, true, isRtl, hackOverflow("overflowX"));
889
812
  initialized[1](true);
890
813
  },
891
814
  $dispose() {
@@ -921,8 +844,16 @@ var createContainerGridDriver = (rowStore, colStore) => {
921
844
  }
922
845
  colStore.$update(3, cols);
923
846
  },
924
- $scrollX: scheduleScrollX,
925
- $scrollY: scheduleScrollY,
847
+ async $scrollX(getTargetOffset, smooth) {
848
+ if (await initialized[0]) {
849
+ colScrollObserver._scroll(getTargetOffset, smooth);
850
+ }
851
+ },
852
+ async $scrollY(getTargetOffset, smooth) {
853
+ if (await initialized[0]) {
854
+ rowScrollObserver._scroll(getTargetOffset, smooth);
855
+ }
856
+ },
926
857
  $effect() {
927
858
  rowScrollObserver && rowScrollObserver._fixScrollJump();
928
859
  colScrollObserver && colScrollObserver._fixScrollJump();
@@ -1010,7 +941,7 @@ var ListItem = (props) => {
1010
941
  }
1011
942
  return style;
1012
943
  });
1013
- return <Dynamic component={props._as} index={props._index} ref={elementRef} style={style()}>
944
+ return <Dynamic component={props._as} index={typeof props._as === "string" ? undefined : props._index} ref={elementRef} style={style()}>
1014
945
  {props._children}
1015
946
  </Dynamic>;
1016
947
  };