virtua 0.43.0 → 0.43.2

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.
@@ -23,6 +23,18 @@ const microtask = typeof queueMicrotask === "function"
23
23
  : (fn) => {
24
24
  Promise.resolve().then(fn);
25
25
  };
26
+ /**
27
+ * @internal
28
+ */
29
+ const createPromise = () => {
30
+ let resolve;
31
+ let reject;
32
+ const promise = new Promise((res, rej) => {
33
+ resolve = res;
34
+ reject = rej;
35
+ });
36
+ return [promise, resolve, reject];
37
+ };
26
38
  /**
27
39
  * @internal
28
40
  */
@@ -692,16 +704,15 @@ const createScroller = (store, isHorizontal) => {
692
704
  let viewportElement;
693
705
  let scrollObserver;
694
706
  let cancelScroll;
707
+ const [initialized, resolveInitialized, rejectInitialized] = createPromise();
695
708
  const scrollOffsetKey = isHorizontal ? "scrollLeft" : "scrollTop";
696
709
  const overflowKey = isHorizontal ? "overflowX" : "overflowY";
697
710
  // The given offset will be clamped by browser
698
711
  // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
699
712
  const scheduleImperativeScroll = async (getTargetOffset, smooth) => {
700
- if (!viewportElement) {
701
- // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.
702
- microtask(() => scheduleImperativeScroll(getTargetOffset, smooth));
703
- return;
704
- }
713
+ // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.
714
+ // https://github.com/inokawa/virtua/pull/733
715
+ await initialized;
705
716
  if (cancelScroll) {
706
717
  // Cancel waiting scrollTo
707
718
  cancelScroll();
@@ -709,21 +720,19 @@ const createScroller = (store, isHorizontal) => {
709
720
  const waitForMeasurement = () => {
710
721
  // Wait for the scroll destination items to be measured.
711
722
  // The measurement will be done asynchronously and the timing is not predictable so we use promise.
712
- let queue;
723
+ const [promise, resolve, reject] = createPromise();
724
+ cancelScroll = reject;
725
+ // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.
726
+ // We have to wait for the initial measurement to avoid failing imperative scroll on mount.
727
+ // https://github.com/inokawa/virtua/issues/450
728
+ if (isInitialMeasurementDone(store)) {
729
+ // Reject when items around scroll destination completely measured
730
+ timeout(reject, 150);
731
+ }
713
732
  return [
714
- new Promise((resolve, reject) => {
715
- queue = resolve;
716
- cancelScroll = reject;
717
- // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.
718
- // We have to wait for the initial measurement to avoid failing imperative scroll on mount.
719
- // https://github.com/inokawa/virtua/issues/450
720
- if (isInitialMeasurementDone(store)) {
721
- // Reject when items around scroll destination completely measured
722
- timeout(reject, 150);
723
- }
724
- }),
733
+ promise,
725
734
  store.$subscribe(UPDATE_SIZE_EVENT, () => {
726
- queue && queue();
735
+ resolve();
727
736
  }),
728
737
  ];
729
738
  };
@@ -793,9 +802,11 @@ const createScroller = (store, isHorizontal) => {
793
802
  viewport[scrollOffsetKey] += jump;
794
803
  }
795
804
  });
805
+ resolveInitialized();
796
806
  },
797
807
  $dispose() {
798
808
  scrollObserver && scrollObserver._dispose();
809
+ rejectInitialized();
799
810
  },
800
811
  $scrollTo(offset) {
801
812
  scheduleImperativeScroll(() => offset);
@@ -844,6 +855,7 @@ const createWindowScroller = (store, isHorizontal) => {
844
855
  let containerElement;
845
856
  let scrollObserver;
846
857
  let cancelScroll;
858
+ const [initialized, resolveInitialized, rejectInitialized] = createPromise();
847
859
  const calcOffsetToViewport = (node, viewport, window, isHorizontal, offset = 0) => {
848
860
  // TODO calc offset only when it changes (maybe impossible)
849
861
  const offsetKey = isHorizontal ? "offsetLeft" : "offsetTop";
@@ -858,26 +870,28 @@ const createWindowScroller = (store, isHorizontal) => {
858
870
  return calcOffsetToViewport(parent, viewport, window, isHorizontal, offsetSum);
859
871
  };
860
872
  const scheduleImperativeScroll = async (getTargetOffset, smooth) => {
861
- if (!containerElement) {
862
- // Wait for element assign
863
- microtask(() => scheduleImperativeScroll(getTargetOffset, smooth));
864
- return;
865
- }
873
+ // Wait for element assign. The element may be undefined if scrollRef prop is used and scroll is scheduled on mount.
874
+ // https://github.com/inokawa/virtua/pull/733
875
+ await initialized;
866
876
  if (cancelScroll) {
867
877
  cancelScroll();
868
878
  }
869
879
  const waitForMeasurement = () => {
870
- let queue;
880
+ // Wait for the scroll destination items to be measured.
881
+ // The measurement will be done asynchronously and the timing is not predictable so we use promise.
882
+ const [promise, resolve, reject] = createPromise();
883
+ cancelScroll = reject;
884
+ // Resize event may not happen when the window/tab is not visible, or during browser back in Safari.
885
+ // We have to wait for the initial measurement to avoid failing imperative scroll on mount.
886
+ // https://github.com/inokawa/virtua/issues/450
887
+ if (isInitialMeasurementDone(store)) {
888
+ // Reject when items around scroll destination completely measured
889
+ timeout(reject, 150);
890
+ }
871
891
  return [
872
- new Promise((resolve, reject) => {
873
- queue = resolve;
874
- cancelScroll = reject;
875
- if (isInitialMeasurementDone(store)) {
876
- timeout(reject, 150);
877
- }
878
- }),
892
+ promise,
879
893
  store.$subscribe(UPDATE_SIZE_EVENT, () => {
880
- queue && queue();
894
+ resolve();
881
895
  }),
882
896
  ];
883
897
  };
@@ -941,10 +955,12 @@ const createWindowScroller = (store, isHorizontal) => {
941
955
  window.scrollBy(isHorizontal ? jump : 0, isHorizontal ? 0 : jump);
942
956
  }
943
957
  }, () => calcOffsetToViewport(container, documentBody, window, isHorizontal));
958
+ resolveInitialized();
944
959
  },
945
960
  $dispose() {
946
961
  scrollObserver && scrollObserver._dispose();
947
962
  containerElement = undefined;
963
+ rejectInitialized();
948
964
  },
949
965
  $fixScrollJump: () => {
950
966
  scrollObserver && scrollObserver._fixScrollJump();