@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.
@@ -12300,7 +12300,7 @@ const putBack = (restoration) => {
12300
12300
  // The page is not whole yet: the last release puts it back.
12301
12301
  return;
12302
12302
  }
12303
- if (documentHoldCount) {
12303
+ if (isDocumentHeld()) {
12304
12304
  pendingRestoration = null;
12305
12305
  return;
12306
12306
  }
@@ -12316,20 +12316,33 @@ const putBack = (restoration) => {
12316
12316
  // height, so the same pixels now fall on other rows. Put back after the list
12317
12317
  // has placed itself, they would undo it, in the very picture a route transition
12318
12318
  // takes. So the list holds the document while it is placing itself, and the
12319
- // url's offset is not put back meanwhile. Counted: two lists can share one
12320
- // document.
12321
- let documentHoldCount = 0;
12322
- const holdDocumentScroll = () => {
12323
- documentHoldCount++;
12324
- let released = false;
12319
+ // url's offset is not put back meanwhile. One hold per list: two lists can
12320
+ // share one document.
12321
+ //
12322
+ // A hold is for the page its list is on, and mounted is not shown: a page kept
12323
+ // while its route transition plays still has its list when the page returned to
12324
+ // renders, and that list says nothing about where the page arriving goes. So a
12325
+ // hold is taken with the list's page (RoutePageContext), asked whether it is
12326
+ // shown when a position is due — `null` outside any route container: that list
12327
+ // is on whatever page is shown. Not a url: which page an address shows is the
12328
+ // routes' to say, and one page can be shown under several (its params moving
12329
+ // under it).
12330
+ const documentHolds = new Set();
12331
+ const holdDocumentScroll = (routePage) => {
12332
+ const hold = { routePage };
12333
+ documentHolds.add(hold);
12325
12334
  return () => {
12326
- if (released) {
12327
- return;
12328
- }
12329
- released = true;
12330
- documentHoldCount--;
12335
+ documentHolds.delete(hold);
12331
12336
  };
12332
12337
  };
12338
+ const isDocumentHeld = () => {
12339
+ for (const { routePage } of documentHolds) {
12340
+ if (routePage === null || routePage.isShown()) {
12341
+ return true;
12342
+ }
12343
+ }
12344
+ return false;
12345
+ };
12333
12346
 
12334
12347
  // What a page holds instead: not the place, which stays the url's, but the
12335
12348
  // moment it is put back (see useHoldScrollRestoration). Counted: several parts
@@ -12587,9 +12600,9 @@ const restoreScrollPosition = (url) => {
12587
12600
  if (!position) {
12588
12601
  return false;
12589
12602
  }
12590
- if (documentHoldCount) {
12591
- // There is a place to go back to, and the list holding the document is
12592
- // putting it back (see holdDocumentScroll).
12603
+ if (isDocumentHeld()) {
12604
+ // There is a place to go back to, and the list holding the document on
12605
+ // that page is putting it back (see holdDocumentScroll).
12593
12606
  return true;
12594
12607
  }
12595
12608
  scrollTo(position);
@@ -79515,6 +79528,19 @@ const useListScrollSync = ({
79515
79528
  // eslint-disable-next-line no-unused-expressions
79516
79529
  virtualItemSizeSignal.value;
79517
79530
  }
79531
+ // The hold ending — the user reaching for the list, something else moving
79532
+ // it, the item it opens on never coming — ends its hold on the document with
79533
+ // it (see holdDocumentScroll), rather than at the next render, which nothing
79534
+ // owes: an offset put back on this page meanwhile is the reader's.
79535
+ const releaseDocumentHoldRef = useRef(null);
79536
+ const letGo = () => {
79537
+ startPlaceRef.current.userTookOver = true;
79538
+ const releaseDocumentHold = releaseDocumentHoldRef.current;
79539
+ if (releaseDocumentHold) {
79540
+ releaseDocumentHoldRef.current = null;
79541
+ releaseDocumentHold();
79542
+ }
79543
+ };
79518
79544
  // Set around a scroll the list performs itself. What it protects against is
79519
79545
  // not the scroll event as such, but what the listener would conclude from it:
79520
79546
  // the position it is about to read was chosen to keep the items where they
@@ -79749,7 +79775,7 @@ const useListScrollSync = ({
79749
79775
  }
79750
79776
  openAt = scrolledFallback;
79751
79777
  if (openAt === "start" || openAt === undefined) {
79752
- startPlaceRef.current.userTookOver = true;
79778
+ letGo();
79753
79779
  return;
79754
79780
  }
79755
79781
  } else {
@@ -79901,13 +79927,39 @@ const useListScrollSync = ({
79901
79927
  }, []);
79902
79928
  // Held on an item of a list scrolling the document: where the document goes is
79903
79929
  // this list's to say, measured on the item, not the url's offset in pixels
79904
- // (see holdDocumentScroll).
79930
+ // (see holdDocumentScroll). The hold read again: a layout effect of this
79931
+ // commit may have let go already (see placeWhereHeld).
79932
+ const routePage = useContext(RoutePageContext);
79905
79933
  useLayoutEffect(() => {
79906
- if (!heldSomewhere || getScroller() !== document.scrollingElement) {
79934
+ if (!heldSomewhere || startPlaceRef.current.userTookOver || getScroller() !== document.scrollingElement) {
79907
79935
  return undefined;
79908
79936
  }
79909
- return holdDocumentScroll();
79910
- }, [heldSomewhere, scrollerElResolved]);
79937
+ const releaseDocumentHold = holdDocumentScroll(routePage);
79938
+ releaseDocumentHoldRef.current = releaseDocumentHold;
79939
+ return () => {
79940
+ releaseDocumentHoldRef.current = null;
79941
+ releaseDocumentHold();
79942
+ };
79943
+ }, [heldSomewhere, scrolledWanted, scrollerElResolved]);
79944
+ // A page kept while its route transition plays is hidden until it is taken
79945
+ // down: nothing of the list can be measured there any more, and its scroller
79946
+ // shows the page arriving (see route_page_context.js). So the list lets go of
79947
+ // it, and stops answering its resizes and scrolls: measured hidden, every
79948
+ // item stands at 0×0, and the top item put back where it was would scroll
79949
+ // the page arriving by that item's offset. Kept mounted on purpose, so the
79950
+ // listeners stay; what they would do is what ends.
79951
+ const pageLeftRef = useRef(false);
79952
+ useLayoutEffect(() => {
79953
+ if (!routePage) {
79954
+ return undefined;
79955
+ }
79956
+ return routePage.leavingSignal.subscribe(leaving => {
79957
+ if (leaving) {
79958
+ pageLeftRef.current = true;
79959
+ letGo();
79960
+ }
79961
+ });
79962
+ }, []);
79911
79963
  // What to do when the list's own geometry moves under it, kept fresh for the
79912
79964
  // observer below (which is installed once).
79913
79965
  const onGeometryChangeRef = useRef(null);
@@ -79941,18 +79993,15 @@ const useListScrollSync = ({
79941
79993
  return undefined;
79942
79994
  }
79943
79995
  const scrollerEl = getScroller();
79944
- const takeOver = () => {
79945
- startPlaceRef.current.userTookOver = true;
79946
- };
79947
79996
  const takeOverEvents = ["wheel", "touchstart", "pointerdown", "keydown"];
79948
79997
  for (const type of takeOverEvents) {
79949
- scrollerEl.addEventListener(type, takeOver, {
79998
+ scrollerEl.addEventListener(type, letGo, {
79950
79999
  passive: true
79951
80000
  });
79952
80001
  }
79953
80002
  return () => {
79954
80003
  for (const type of takeOverEvents) {
79955
- scrollerEl.removeEventListener(type, takeOver);
80004
+ scrollerEl.removeEventListener(type, letGo);
79956
80005
  }
79957
80006
  };
79958
80007
  }, [scrolledWanted, scrollerElResolved]);
@@ -80110,6 +80159,9 @@ const useListScrollSync = ({
80110
80159
  }
80111
80160
  };
80112
80161
  const observer = new ResizeObserver(entries => {
80162
+ if (pageLeftRef.current) {
80163
+ return;
80164
+ }
80113
80165
  // A box that grows may be a box that starts to scroll — the scroller is
80114
80166
  // resolved again before anything is done about the resize, so that a
80115
80167
  // list which has outgrown a bounded ancestor stops holding on to the
@@ -80523,6 +80575,9 @@ const useListScrollSync = ({
80523
80575
  }
80524
80576
  const scrollerEl = getScroller();
80525
80577
  const onScroll = () => {
80578
+ if (pageLeftRef.current) {
80579
+ return;
80580
+ }
80526
80581
  // Which way the user is going, read before the position is stored: what
80527
80582
  // the window keeps ahead is ahead of this.
80528
80583
  const previousScroll = currentScrollRef.current;
@@ -80580,7 +80635,7 @@ const useListScrollSync = ({
80580
80635
  const low = way.from < way.to ? way.from : way.to;
80581
80636
  const high = way.from < way.to ? way.to : way.from;
80582
80637
  if (position < low - 1 || position > high + 1) {
80583
- place.userTookOver = true;
80638
+ letGo();
80584
80639
  }
80585
80640
  };
80586
80641
  // A page-level scroller does not emit "scroll" on the element itself