@jsenv/navi 0.29.432 → 0.29.433
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.
- package/dist/dev/jsenv_navi.js +85 -49
- package/dist/dev/jsenv_navi.js.map +6 -6
- package/dist/jsenv_navi.js +85 -49
- package/dist/jsenv_navi.js.map +6 -6
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -11537,6 +11537,11 @@ const [publishRouteRender, observeRouteRender] = createPubSub();
|
|
|
11537
11537
|
const STORAGE_KEY = "navi_scroll_positions";
|
|
11538
11538
|
|
|
11539
11539
|
const positionByUrl = new Map();
|
|
11540
|
+
// Where the document stands, as its scroll events last said, whoever it
|
|
11541
|
+
// belongs to: what a url shown without the document moving is given (see
|
|
11542
|
+
// stayInPlace). Null until the restoration is installed — nothing is recorded
|
|
11543
|
+
// before.
|
|
11544
|
+
let documentOffset = null;
|
|
11540
11545
|
// url -> (scroller name -> position). The position is whatever the scroller
|
|
11541
11546
|
// handed in: what it can put itself back on, in its own terms.
|
|
11542
11547
|
const scrollerPositionsByUrl = new Map();
|
|
@@ -11653,30 +11658,25 @@ const installScrollRestoration = () => {
|
|
|
11653
11658
|
}
|
|
11654
11659
|
window.history.scrollRestoration = "manual";
|
|
11655
11660
|
loadStore();
|
|
11661
|
+
documentOffset = { x: window.scrollX, y: window.scrollY };
|
|
11656
11662
|
// Read as it happens rather than when leaving: a traverse changes the url
|
|
11657
11663
|
// before anything here is told, so a position read then would be read for
|
|
11658
11664
|
// the wrong page.
|
|
11659
11665
|
window.addEventListener(
|
|
11660
11666
|
"scroll",
|
|
11661
11667
|
() => {
|
|
11668
|
+
documentOffset = { x: window.scrollX, y: window.scrollY };
|
|
11662
11669
|
if (suspendCount) {
|
|
11663
11670
|
return;
|
|
11664
11671
|
}
|
|
11665
|
-
positionByUrl.set(window.location.href,
|
|
11666
|
-
x: window.scrollX,
|
|
11667
|
-
y: window.scrollY,
|
|
11668
|
-
});
|
|
11672
|
+
positionByUrl.set(window.location.href, documentOffset);
|
|
11669
11673
|
},
|
|
11670
11674
|
{ passive: true },
|
|
11671
11675
|
);
|
|
11672
11676
|
const positionOnLoad = positionByUrl.get(window.location.href);
|
|
11673
11677
|
if (!positionOnLoad) {
|
|
11674
|
-
//
|
|
11675
|
-
|
|
11676
|
-
positionByUrl.set(window.location.href, {
|
|
11677
|
-
x: window.scrollX,
|
|
11678
|
-
y: window.scrollY,
|
|
11679
|
-
});
|
|
11678
|
+
// The first page, where the browser landed it.
|
|
11679
|
+
stayInPlace(window.location.href);
|
|
11680
11680
|
return;
|
|
11681
11681
|
}
|
|
11682
11682
|
// What a reload asks for, now that the browser has been told not to do it.
|
|
@@ -11767,6 +11767,7 @@ const restoreScrollPositionOnReturn = (url) => {
|
|
|
11767
11767
|
// app that scrolls an element of its own scrolls it itself.
|
|
11768
11768
|
const startAtTop = (url, { from } = {}) => {
|
|
11769
11769
|
if (!isArrival(url, { from })) {
|
|
11770
|
+
stayInPlace(url);
|
|
11770
11771
|
return;
|
|
11771
11772
|
}
|
|
11772
11773
|
arrivalCount++;
|
|
@@ -11788,6 +11789,23 @@ const isArrival = (url, { from }) => {
|
|
|
11788
11789
|
return true;
|
|
11789
11790
|
};
|
|
11790
11791
|
|
|
11792
|
+
// A url the document is shown under without moving: a replace, a push that
|
|
11793
|
+
// keeps the page (see startAtTop), the first page loaded. No scroll event says
|
|
11794
|
+
// where it stands, so it is written down here, or a return to it would find
|
|
11795
|
+
// nothing and keep the offset of the page being left. The offset the scroll
|
|
11796
|
+
// events last told, not read again: a read here would lay the page out in the
|
|
11797
|
+
// middle of a routing, once per address a settling param writes.
|
|
11798
|
+
//
|
|
11799
|
+
// Deaf with the recording: a row of tabs replaces the url as it travels, and
|
|
11800
|
+
// the offset belongs to nobody until the row says where its tab lands (see
|
|
11801
|
+
// arriveAtScrollPosition).
|
|
11802
|
+
const stayInPlace = (url) => {
|
|
11803
|
+
if (documentOffset === null || suspendCount) {
|
|
11804
|
+
return;
|
|
11805
|
+
}
|
|
11806
|
+
positionByUrl.set(new URL(url, window.location.href).href, documentOffset);
|
|
11807
|
+
};
|
|
11808
|
+
|
|
11791
11809
|
// The same arrival, for the page's own scrollers. The document is scrolled to
|
|
11792
11810
|
// its top once the page is there; a list opens where it decides to in its
|
|
11793
11811
|
// first render, so what it must not find is dropped before the routing
|
|
@@ -12263,14 +12281,18 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
12263
12281
|
// also waits for the page it returns to: an offset is clamped to whatever
|
|
12264
12282
|
// page the document holds when it is written.
|
|
12265
12283
|
//
|
|
12266
|
-
// A replace
|
|
12267
|
-
// settling, a state written — and moving the reader
|
|
12268
|
-
// them out of a page they never left.
|
|
12269
|
-
//
|
|
12270
|
-
//
|
|
12271
|
-
//
|
|
12284
|
+
// A replace leaves the document where it is: it is the same place said
|
|
12285
|
+
// differently — a param settling, a state written — and moving the reader
|
|
12286
|
+
// for it would throw them out of a page they never left. Where they stay
|
|
12287
|
+
// is written down for the new address (see stayInPlace). A push that keeps
|
|
12288
|
+
// the pathname is read the same way, by startAtTop itself. The one replace
|
|
12289
|
+
// that IS an arrival is a row of tabs travelling, and the row says so for
|
|
12290
|
+
// itself (see route_travel.jsx) — from inside the routing above, which is
|
|
12291
|
+
// why the replace is written down after it.
|
|
12272
12292
|
if (navigationType === "push") {
|
|
12273
12293
|
whenRenderingResumes(() => startAtTop(url, { from: urlLeft }));
|
|
12294
|
+
} else if (navigationType === "replace") {
|
|
12295
|
+
stayInPlace(url);
|
|
12274
12296
|
} else if (navigationType === "traverse") {
|
|
12275
12297
|
restoreScrollPositionOnReturn(url);
|
|
12276
12298
|
}
|
|
@@ -71723,32 +71745,43 @@ document.addEventListener(
|
|
|
71723
71745
|
);
|
|
71724
71746
|
|
|
71725
71747
|
/*
|
|
71726
|
-
* Whether a
|
|
71727
|
-
*
|
|
71728
|
-
*
|
|
71729
|
-
*
|
|
71730
|
-
*
|
|
71731
|
-
*
|
|
71732
|
-
*
|
|
71733
|
-
*
|
|
71734
|
-
* from
|
|
71735
|
-
*
|
|
71736
|
-
*
|
|
71737
|
-
*
|
|
71738
|
-
*
|
|
71739
|
-
*
|
|
71740
|
-
*
|
|
71741
|
-
*
|
|
71742
|
-
*
|
|
71743
|
-
*
|
|
71744
|
-
*
|
|
71745
|
-
*
|
|
71748
|
+
* Whether writing a scroll position now would cost the user the scroll in
|
|
71749
|
+
* progress. A write is an instant scroll, and the browser abandons for it any
|
|
71750
|
+
* scroll it is playing on its own, short of where that one was going: a key
|
|
71751
|
+
* (Home, PageDown, Space), a smooth `scrollTo` or `scrollIntoView`, the status
|
|
71752
|
+
* bar tap on iOS, the fling a finger leaves behind once it lifts. A scroll
|
|
71753
|
+
* following a hand is not abandoned: the wheel's next turn carries on, and on
|
|
71754
|
+
* most engines a finger keeps dragging from wherever the write left it.
|
|
71755
|
+
*
|
|
71756
|
+
* Not on iOS. Its finger places the content from where the drag began, so a
|
|
71757
|
+
* write under it is undone at the finger's next move — or, when the finger
|
|
71758
|
+
* lifts first, lands after the lift and stops the fling dead. And a fling
|
|
71759
|
+
* stops on any write during its momentum, as the status bar's scroll to the
|
|
71760
|
+
* top does (Safari 26.5 on the simulator: flings of 1700px stopped 130 to 340px
|
|
71761
|
+
* after the lift, 3 in 3; a write 50ms before the lift stopped 2 flings in 3).
|
|
71762
|
+
* No finger there is a hand a write could hold to. Chrome flings on through a
|
|
71763
|
+
* write, and loses nothing by not getting one.
|
|
71764
|
+
*
|
|
71765
|
+
* A scroll is followed from its first "scroll" event to its "scrollend", and
|
|
71766
|
+
* is a hand's while a finger is down, or when a wheel turned around the time it
|
|
71767
|
+
* started or since. A finger is down from its touchstart to its touchend,
|
|
71768
|
+
* heard on what it touched: a list removes the items scrolled out of its window
|
|
71769
|
+
* while the finger is still on one of them, and the touchend of a removed
|
|
71770
|
+
* element never reaches the document.
|
|
71771
|
+
*
|
|
71772
|
+
* In a browser without "scrollend", no write is said to interrupt anything: a
|
|
71773
|
+
* scroll would never be seen ending.
|
|
71746
71774
|
*/
|
|
71747
71775
|
|
|
71748
71776
|
// The scroll a wheel turn causes starts in the frame the turn is read, or the
|
|
71749
71777
|
// next one. A turn further from it moved nothing (a wheel at an edge) and is no
|
|
71750
71778
|
// hand on a scroll that came from elsewhere.
|
|
71751
71779
|
const WHEEL_REACH = 100;
|
|
71780
|
+
// iOS's touch handling, the one engine whose finger drops writes (see above).
|
|
71781
|
+
const FINGER_KEEPS_WRITES = !window.CSS.supports(
|
|
71782
|
+
"-webkit-touch-callout",
|
|
71783
|
+
"none",
|
|
71784
|
+
);
|
|
71752
71785
|
|
|
71753
71786
|
const flightMap = new WeakMap();
|
|
71754
71787
|
let fingersDown = 0;
|
|
@@ -71758,13 +71791,13 @@ let wheelTimeStamp = -Infinity;
|
|
|
71758
71791
|
* @param {Element} scrollerEl
|
|
71759
71792
|
* @returns {boolean}
|
|
71760
71793
|
*/
|
|
71761
|
-
const
|
|
71794
|
+
const wouldInterruptScroll = (scrollerEl) => {
|
|
71762
71795
|
const flight = flightMap.get(scrollerEl);
|
|
71763
71796
|
if (!flight) {
|
|
71764
71797
|
return false;
|
|
71765
71798
|
}
|
|
71766
|
-
if (
|
|
71767
|
-
return
|
|
71799
|
+
if (fingersDown > 0) {
|
|
71800
|
+
return !FINGER_KEEPS_WRITES;
|
|
71768
71801
|
}
|
|
71769
71802
|
if (wheelTimeStamp > flight.timeStamp - WHEEL_REACH) {
|
|
71770
71803
|
return false;
|
|
@@ -71794,10 +71827,7 @@ if ("onscrollend" in window) {
|
|
|
71794
71827
|
if (flightMap.has(scroller)) {
|
|
71795
71828
|
return;
|
|
71796
71829
|
}
|
|
71797
|
-
flightMap.set(scroller, {
|
|
71798
|
-
timeStamp: e.timeStamp,
|
|
71799
|
-
fingerDown: fingersDown > 0,
|
|
71800
|
-
});
|
|
71830
|
+
flightMap.set(scroller, { timeStamp: e.timeStamp });
|
|
71801
71831
|
},
|
|
71802
71832
|
{ capture: true, passive: true },
|
|
71803
71833
|
);
|
|
@@ -75487,6 +75517,13 @@ const useListScrollSync = ({
|
|
|
75487
75517
|
if (delta > -0.5 && delta < 0.5) {
|
|
75488
75518
|
return;
|
|
75489
75519
|
}
|
|
75520
|
+
if (wouldInterruptScroll(scrollerEl)) {
|
|
75521
|
+
// As the anchoring's write would (see holdAnchorStill). The document's
|
|
75522
|
+
// box is the scroller of a list scrolling the page, and it resizes with
|
|
75523
|
+
// every item drawn taller than its filler: while the page scrolls, that
|
|
75524
|
+
// is at every window move.
|
|
75525
|
+
return;
|
|
75526
|
+
}
|
|
75490
75527
|
anchorRef.current = null;
|
|
75491
75528
|
if (horizontal) {
|
|
75492
75529
|
scrollerEl.scrollLeft += delta;
|
|
@@ -75584,13 +75621,12 @@ const useListScrollSync = ({
|
|
|
75584
75621
|
return;
|
|
75585
75622
|
}
|
|
75586
75623
|
anchorRef.current = null;
|
|
75587
|
-
if (
|
|
75624
|
+
if (wouldInterruptScroll(scrollerEl)) {
|
|
75588
75625
|
// Nobody is looking at items standing still: they are passing by, on
|
|
75589
|
-
// their way somewhere the browser
|
|
75590
|
-
//
|
|
75591
|
-
//
|
|
75592
|
-
//
|
|
75593
|
-
// of it moves, and the glide lands.
|
|
75626
|
+
// their way somewhere the browser takes them (a key, a smooth scrollTo,
|
|
75627
|
+
// the status bar, a fling). The write would stop that scroll short of
|
|
75628
|
+
// where it was going. Left alone, the items drawn above push the rest by
|
|
75629
|
+
// `drift` while all of it moves, and the scroll lands.
|
|
75594
75630
|
return;
|
|
75595
75631
|
}
|
|
75596
75632
|
scrolledByListRef.current = true;
|