@jsenv/navi 0.29.496 → 0.29.498

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.
@@ -10024,8 +10024,8 @@ const suspendScrollRecording = () => {
10024
10024
  // the reader reaching for the page: where they are is theirs (see
10025
10025
  // installScrollRestoration).
10026
10026
  let pendingRestoration = null;
10027
- const startRestoration = (position) => {
10028
- const restoration = { position, due: false };
10027
+ const startRestoration = (position, { meanwhile = false } = {}) => {
10028
+ const restoration = { position, due: false, meanwhile };
10029
10029
  pendingRestoration = restoration;
10030
10030
  return restoration;
10031
10031
  };
@@ -10038,6 +10038,7 @@ const putBack = (restoration) => {
10038
10038
  restoration.due = true;
10039
10039
  if (restorationHoldCount) {
10040
10040
  // The page is not whole yet: the last release puts it back.
10041
+ putBackMeanwhile(restoration);
10041
10042
  return;
10042
10043
  }
10043
10044
  if (isDocumentHeld()) {
@@ -10084,6 +10085,24 @@ const isDocumentHeld = () => {
10084
10085
  return false;
10085
10086
  };
10086
10087
 
10088
+ // A return is photographed by its route transition as soon as its page has
10089
+ // rendered, stand-ins and all, and a position waiting for the page to be whole
10090
+ // is written after the movement, seen as a jump. So it is also written into
10091
+ // what is there meanwhile, as far as that goes — the browser clamps the rest —
10092
+ // and again once the page is whole, when what it stands on has grown or shrunk.
10093
+ const putBackMeanwhile = (restoration) => {
10094
+ if (!restoration.meanwhile) {
10095
+ return;
10096
+ }
10097
+ // Out of whatever commit or effect is asking: see scrollTo.
10098
+ queueMicrotask(() => {
10099
+ if (pendingRestoration !== restoration || isDocumentHeld()) {
10100
+ return;
10101
+ }
10102
+ scrollTo(restoration.position);
10103
+ });
10104
+ };
10105
+
10087
10106
  // What a page holds instead: not the place, which stays the url's, but the
10088
10107
  // moment it is put back (see useHoldScrollRestoration). Counted: several parts
10089
10108
  // of one page can be waiting.
@@ -10227,6 +10246,7 @@ const putBackOnceAnswered = (restoration) => {
10227
10246
  });
10228
10247
  return;
10229
10248
  }
10249
+ putBackMeanwhile(restoration);
10230
10250
  // A reader drawing its own wait subscribes in an effect, after the first
10231
10251
  // paint (see afterPaint): an answer that came before is drawn only then.
10232
10252
  let waitCount = 2;
@@ -10350,11 +10370,12 @@ const restoreScrollPosition = (url) => {
10350
10370
  };
10351
10371
 
10352
10372
  // A traversal back to `url`. The offset is written once the page returned to is
10353
- // rendered and answered (see putBackOnceAnswered): written sooner, the document
10354
- // still holds the page being left, or a stand-in for the one arriving, and
10355
- // clamps it to that height. It is read at once all the same — a page left
10356
- // taller than the one arriving is clamped by the render itself, and that clamp
10357
- // is a scroll recorded under the url already returned to.
10373
+ // rendered (see whenPageRendered): written sooner, the document still holds the
10374
+ // page being left and clamps it to that height. Again once it has answered (see
10375
+ // putBackOnceAnswered), when it rendered stand-ins (see putBackMeanwhile). It
10376
+ // is read at once all the same — a page left taller than the one arriving is
10377
+ // clamped by the render itself, and that clamp is a scroll recorded under the
10378
+ // url already returned to.
10358
10379
  const restoreScrollPositionOnReturn = (url) => {
10359
10380
  pendingRestoration = null;
10360
10381
  const href = new URL(url, window.location.href).href;
@@ -10363,7 +10384,7 @@ const restoreScrollPositionOnReturn = (url) => {
10363
10384
  if (!position) {
10364
10385
  return;
10365
10386
  }
10366
- const restoration = startRestoration(position);
10387
+ const restoration = startRestoration(position, { meanwhile: true });
10367
10388
  whenPageRendered(() => {
10368
10389
  putBackOnceAnswered(restoration);
10369
10390
  });
@@ -84872,19 +84893,28 @@ const useListScrollSync = ({
84872
84893
  });
84873
84894
  }, []);
84874
84895
  // What to do when the list's own geometry moves under it, kept fresh for the
84875
- // observer below (which is installed once).
84896
+ // observer below (which is installed once). A held list is placed inside the
84897
+ // resize delivery, so the browser paints it where it lands; answers whether
84898
+ // it was.
84876
84899
  const onGeometryChangeRef = useRef(null);
84877
84900
  onGeometryChangeRef.current = () => {
84878
- settleWindow();
84879
- if (heldSomewhere) {
84880
- placeWhereHeld();
84881
- return true;
84901
+ if (!heldSomewhere) {
84902
+ return false;
84882
84903
  }
84883
- // Items that came in at another size than what stood in for them (a
84884
- // skeleton becoming its item) leave the window short of the screen, or past
84885
- // it, and nothing scrolled to say so.
84904
+ settleWindow();
84905
+ placeWhereHeld();
84906
+ return true;
84907
+ };
84908
+ // Items that came in at another size than what stood in for them (a
84909
+ // skeleton becoming its item) leave the window short of the screen, or past
84910
+ // it, and nothing scrolled to say so. Asked on the next frame, not inside
84911
+ // the resize delivery: the window it frames is a render, which resizes what
84912
+ // is observed once more, and the browser gives up on the loop
84913
+ // ("ResizeObserver loop completed with undelivered notifications").
84914
+ const onItemsResizedRef = useRef(null);
84915
+ onItemsResizedRef.current = () => {
84916
+ settleWindow();
84886
84917
  evaluateWindowRef.current("items resized");
84887
- return false;
84888
84918
  };
84889
84919
  // The box around a held list changing shape is the hold's to answer too: it
84890
84920
  // places the list again, the way it writes every scroll of its own (see
@@ -85032,10 +85062,20 @@ const useListScrollSync = ({
85032
85062
  // which this would undo. The SCROLLER resizing is the window around it
85033
85063
  // changing shape, and then the item that was at the top goes back where it
85034
85064
  // was.
85065
+ let itemsResizedFrame;
85035
85066
  const putTopItemBack = entries => {
85036
85067
  const listResized = entries.some(entry => entry.target === listEl);
85037
- if (listResized && onGeometryChangeRef.current()) {
85038
- return;
85068
+ if (listResized) {
85069
+ if (onGeometryChangeRef.current()) {
85070
+ return;
85071
+ }
85072
+ cancelAnimationFrame(itemsResizedFrame);
85073
+ itemsResizedFrame = requestAnimationFrame(() => {
85074
+ if (pageLeftRef.current) {
85075
+ return;
85076
+ }
85077
+ onItemsResizedRef.current();
85078
+ });
85039
85079
  }
85040
85080
  if (!entries.some(entry => entry.target === scrollerEl)) {
85041
85081
  return;
@@ -85088,6 +85128,7 @@ const useListScrollSync = ({
85088
85128
  observer.observe(listEl);
85089
85129
  return () => {
85090
85130
  observer.disconnect();
85131
+ cancelAnimationFrame(itemsResizedFrame);
85091
85132
  };
85092
85133
  }, [scrollerElResolved]);
85093
85134