@jsenv/navi 0.29.477 → 0.29.478

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.
@@ -11872,7 +11872,7 @@ const putBack = (restoration) => {
11872
11872
  // The page is not whole yet: the last release puts it back.
11873
11873
  return;
11874
11874
  }
11875
- if (documentHoldCount) {
11875
+ if (isDocumentHeld()) {
11876
11876
  pendingRestoration = null;
11877
11877
  return;
11878
11878
  }
@@ -11888,20 +11888,33 @@ const putBack = (restoration) => {
11888
11888
  // height, so the same pixels now fall on other rows. Put back after the list
11889
11889
  // has placed itself, they would undo it, in the very picture a route transition
11890
11890
  // takes. So the list holds the document while it is placing itself, and the
11891
- // url's offset is not put back meanwhile. Counted: two lists can share one
11892
- // document.
11893
- let documentHoldCount = 0;
11894
- const holdDocumentScroll = () => {
11895
- documentHoldCount++;
11896
- let released = false;
11891
+ // url's offset is not put back meanwhile. One hold per list: two lists can
11892
+ // share one document.
11893
+ //
11894
+ // A hold is for the page its list is on, and mounted is not shown: a page kept
11895
+ // while its route transition plays still has its list when the page returned to
11896
+ // renders, and that list says nothing about where the page arriving goes. So a
11897
+ // hold is taken with the list's page (RoutePageContext), asked whether it is
11898
+ // shown when a position is due — `null` outside any route container: that list
11899
+ // is on whatever page is shown. Not a url: which page an address shows is the
11900
+ // routes' to say, and one page can be shown under several (its params moving
11901
+ // under it).
11902
+ const documentHolds = new Set();
11903
+ const holdDocumentScroll = (routePage) => {
11904
+ const hold = { routePage };
11905
+ documentHolds.add(hold);
11897
11906
  return () => {
11898
- if (released) {
11899
- return;
11900
- }
11901
- released = true;
11902
- documentHoldCount--;
11907
+ documentHolds.delete(hold);
11903
11908
  };
11904
11909
  };
11910
+ const isDocumentHeld = () => {
11911
+ for (const { routePage } of documentHolds) {
11912
+ if (routePage === null || routePage.isShown()) {
11913
+ return true;
11914
+ }
11915
+ }
11916
+ return false;
11917
+ };
11905
11918
 
11906
11919
  // What a page holds instead: not the place, which stays the url's, but the
11907
11920
  // moment it is put back (see useHoldScrollRestoration). Counted: several parts
@@ -12159,9 +12172,9 @@ const restoreScrollPosition = (url) => {
12159
12172
  if (!position) {
12160
12173
  return false;
12161
12174
  }
12162
- if (documentHoldCount) {
12163
- // There is a place to go back to, and the list holding the document is
12164
- // putting it back (see holdDocumentScroll).
12175
+ if (isDocumentHeld()) {
12176
+ // There is a place to go back to, and the list holding the document on
12177
+ // that page is putting it back (see holdDocumentScroll).
12165
12178
  return true;
12166
12179
  }
12167
12180
  scrollTo(position);
@@ -78038,6 +78051,19 @@ const useListScrollSync = ({
78038
78051
  // eslint-disable-next-line no-unused-expressions
78039
78052
  virtualItemSizeSignal.value;
78040
78053
  }
78054
+ // The hold ending — the user reaching for the list, something else moving
78055
+ // it, the item it opens on never coming — ends its hold on the document with
78056
+ // it (see holdDocumentScroll), rather than at the next render, which nothing
78057
+ // owes: an offset put back on this page meanwhile is the reader's.
78058
+ const releaseDocumentHoldRef = useRef(null);
78059
+ const letGo = () => {
78060
+ startPlaceRef.current.userTookOver = true;
78061
+ const releaseDocumentHold = releaseDocumentHoldRef.current;
78062
+ if (releaseDocumentHold) {
78063
+ releaseDocumentHoldRef.current = null;
78064
+ releaseDocumentHold();
78065
+ }
78066
+ };
78041
78067
  // Set around a scroll the list performs itself. What it protects against is
78042
78068
  // not the scroll event as such, but what the listener would conclude from it:
78043
78069
  // the position it is about to read was chosen to keep the items where they
@@ -78271,7 +78297,7 @@ const useListScrollSync = ({
78271
78297
  }
78272
78298
  openAt = scrolledFallback;
78273
78299
  if (openAt === "start" || openAt === undefined) {
78274
- startPlaceRef.current.userTookOver = true;
78300
+ letGo();
78275
78301
  return;
78276
78302
  }
78277
78303
  } else {
@@ -78423,13 +78449,39 @@ const useListScrollSync = ({
78423
78449
  }, []);
78424
78450
  // Held on an item of a list scrolling the document: where the document goes is
78425
78451
  // this list's to say, measured on the item, not the url's offset in pixels
78426
- // (see holdDocumentScroll).
78452
+ // (see holdDocumentScroll). The hold read again: a layout effect of this
78453
+ // commit may have let go already (see placeWhereHeld).
78454
+ const routePage = useContext(RoutePageContext);
78427
78455
  useLayoutEffect(() => {
78428
- if (!heldSomewhere || getScroller() !== document.scrollingElement) {
78456
+ if (!heldSomewhere || startPlaceRef.current.userTookOver || getScroller() !== document.scrollingElement) {
78429
78457
  return undefined;
78430
78458
  }
78431
- return holdDocumentScroll();
78432
- }, [heldSomewhere, scrollerElResolved]);
78459
+ const releaseDocumentHold = holdDocumentScroll(routePage);
78460
+ releaseDocumentHoldRef.current = releaseDocumentHold;
78461
+ return () => {
78462
+ releaseDocumentHoldRef.current = null;
78463
+ releaseDocumentHold();
78464
+ };
78465
+ }, [heldSomewhere, scrolledWanted, scrollerElResolved]);
78466
+ // A page kept while its route transition plays is hidden until it is taken
78467
+ // down: nothing of the list can be measured there any more, and its scroller
78468
+ // shows the page arriving (see route_page_context.js). So the list lets go of
78469
+ // it, and stops answering its resizes and scrolls: measured hidden, every
78470
+ // item stands at 0×0, and the top item put back where it was would scroll
78471
+ // the page arriving by that item's offset. Kept mounted on purpose, so the
78472
+ // listeners stay; what they would do is what ends.
78473
+ const pageLeftRef = useRef(false);
78474
+ useLayoutEffect(() => {
78475
+ if (!routePage) {
78476
+ return undefined;
78477
+ }
78478
+ return routePage.leavingSignal.subscribe(leaving => {
78479
+ if (leaving) {
78480
+ pageLeftRef.current = true;
78481
+ letGo();
78482
+ }
78483
+ });
78484
+ }, []);
78433
78485
  // What to do when the list's own geometry moves under it, kept fresh for the
78434
78486
  // observer below (which is installed once).
78435
78487
  const onGeometryChangeRef = useRef(null);
@@ -78463,18 +78515,15 @@ const useListScrollSync = ({
78463
78515
  return undefined;
78464
78516
  }
78465
78517
  const scrollerEl = getScroller();
78466
- const takeOver = () => {
78467
- startPlaceRef.current.userTookOver = true;
78468
- };
78469
78518
  const takeOverEvents = ["wheel", "touchstart", "pointerdown", "keydown"];
78470
78519
  for (const type of takeOverEvents) {
78471
- scrollerEl.addEventListener(type, takeOver, {
78520
+ scrollerEl.addEventListener(type, letGo, {
78472
78521
  passive: true
78473
78522
  });
78474
78523
  }
78475
78524
  return () => {
78476
78525
  for (const type of takeOverEvents) {
78477
- scrollerEl.removeEventListener(type, takeOver);
78526
+ scrollerEl.removeEventListener(type, letGo);
78478
78527
  }
78479
78528
  };
78480
78529
  }, [scrolledWanted, scrollerElResolved]);
@@ -78631,6 +78680,9 @@ const useListScrollSync = ({
78631
78680
  }
78632
78681
  };
78633
78682
  const observer = new ResizeObserver(entries => {
78683
+ if (pageLeftRef.current) {
78684
+ return;
78685
+ }
78634
78686
  // A box that grows may be a box that starts to scroll — the scroller is
78635
78687
  // resolved again before anything is done about the resize, so that a
78636
78688
  // list which has outgrown a bounded ancestor stops holding on to the
@@ -79035,6 +79087,9 @@ const useListScrollSync = ({
79035
79087
  }
79036
79088
  const scrollerEl = getScroller();
79037
79089
  const onScroll = () => {
79090
+ if (pageLeftRef.current) {
79091
+ return;
79092
+ }
79038
79093
  // Which way the user is going, read before the position is stored: what
79039
79094
  // the window keeps ahead is ahead of this.
79040
79095
  const previousScroll = currentScrollRef.current;
@@ -79092,7 +79147,7 @@ const useListScrollSync = ({
79092
79147
  const low = way.from < way.to ? way.from : way.to;
79093
79148
  const high = way.from < way.to ? way.to : way.from;
79094
79149
  if (position < low - 1 || position > high + 1) {
79095
- place.userTookOver = true;
79150
+ letGo();
79096
79151
  }
79097
79152
  };
79098
79153
  // A page-level scroller does not emit "scroll" on the element itself