@jsenv/navi 0.30.33 → 0.30.35
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 +80 -34
- package/dist/dev/jsenv_navi.js.map +2 -2
- package/dist/jsenv_navi.js +80 -34
- package/dist/jsenv_navi.js.map +2 -2
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -41368,7 +41368,7 @@ const css$16 = /* css */`.navi_route_travel {
|
|
|
41368
41368
|
display: flex;
|
|
41369
41369
|
}
|
|
41370
41370
|
|
|
41371
|
-
& > [data-route-row-pane][inert] {
|
|
41371
|
+
& > [data-route-row-pane][inert]:not([data-route-row-held]), &:has( > [data-route-row-held]) > [data-route-row-pane]:not([data-route-row-held]) {
|
|
41372
41372
|
top: var(--navi-route-row-pin, 0);
|
|
41373
41373
|
contain: paint;
|
|
41374
41374
|
max-height: 100dvh;
|
|
@@ -41418,6 +41418,12 @@ const ROW_READING = {
|
|
|
41418
41418
|
// How far a scroll position written can read back from what was written: rounded to
|
|
41419
41419
|
// the device's pixels.
|
|
41420
41420
|
const WRITE_ROUNDING = 1;
|
|
41421
|
+
// The most one frame of a travel plays: a frame of a 30fps screen, which is what a
|
|
41422
|
+
// browser saving power gives (an iPhone in Low Power Mode, Chrome's Energy Saver).
|
|
41423
|
+
// A frame later than that is a main thread busy elsewhere (the page arriving builds,
|
|
41424
|
+
// a list fills its budget), and the travel takes longer rather than jump by it. Not a
|
|
41425
|
+
// frame of a 60Hz screen: that would play every travel in slow motion at 30fps.
|
|
41426
|
+
const TRAVEL_FRAME_MAX_MS = 1000 / 30;
|
|
41421
41427
|
|
|
41422
41428
|
/**
|
|
41423
41429
|
* @type {import("preact").FunctionComponent<{
|
|
@@ -41530,9 +41536,23 @@ const RouteTravel = ({
|
|
|
41530
41536
|
params
|
|
41531
41537
|
}) => new URL(route.buildUrl(params), window.location.href).pathname;
|
|
41532
41538
|
|
|
41539
|
+
// The pane laid out as the page on screen for the length of a movement, let go of
|
|
41540
|
+
// when the row rests. Not what readers are told the page held is
|
|
41541
|
+
// (route_travel_hold.js): that follows the hand, and goes at its lift.
|
|
41542
|
+
const heldPaneRef = useRef(null);
|
|
41543
|
+
const releasePaneAtRest = () => {
|
|
41544
|
+
const heldPane = heldPaneRef.current;
|
|
41545
|
+
if (heldPane) {
|
|
41546
|
+
heldPaneRef.current = null;
|
|
41547
|
+
heldPane.removeAttribute("data-route-row-held");
|
|
41548
|
+
}
|
|
41549
|
+
};
|
|
41550
|
+
|
|
41533
41551
|
// One movement, whoever set it off, from the first thing that moves to the row
|
|
41534
|
-
// at rest. Null when nothing moves.
|
|
41535
|
-
|
|
41552
|
+
// at rest. Null when nothing moves. `paneAtRest` is the pane the row rests on as it
|
|
41553
|
+
// begins: laid out as the page on screen until the row rests again, wherever the
|
|
41554
|
+
// address goes meanwhile (see the CSS).
|
|
41555
|
+
const beginMovement = (fields, paneAtRest) => {
|
|
41536
41556
|
const row = rowRef.current;
|
|
41537
41557
|
if (movementRef.current) {
|
|
41538
41558
|
Object.assign(movementRef.current, fields);
|
|
@@ -41547,6 +41567,11 @@ const RouteTravel = ({
|
|
|
41547
41567
|
...fields
|
|
41548
41568
|
};
|
|
41549
41569
|
movementRef.current = movement;
|
|
41570
|
+
// In a window the page is a picture, contained with what it holds.
|
|
41571
|
+
if (!windowed && paneAtRest) {
|
|
41572
|
+
heldPaneRef.current = paneAtRest;
|
|
41573
|
+
paneAtRest.setAttribute("data-route-row-held", "");
|
|
41574
|
+
}
|
|
41550
41575
|
if (movement.scrollsDocument) {
|
|
41551
41576
|
// Whatever the browser does with the offset meanwhile (clamping it to a page
|
|
41552
41577
|
// shorter than the trip) is not the reader scrolling, and the address it
|
|
@@ -41693,18 +41718,22 @@ const RouteTravel = ({
|
|
|
41693
41718
|
// hesitates, then peaks at 1.65 times this one's speed): two rows of tabs in one
|
|
41694
41719
|
// app would not move alike. The scroll position is written at every frame, so the
|
|
41695
41720
|
// row stays a scroller all the way: what follows it (a Nav's bar) reads it as it
|
|
41696
|
-
// reads a hand, and a finger landing finds it where it is.
|
|
41697
|
-
//
|
|
41721
|
+
// reads a hand, and a finger landing finds it where it is. That is played on the
|
|
41722
|
+
// main thread: a transform on the panes would play on the compositor, but it would
|
|
41723
|
+
// capture what the page on screen holds in position: fixed. Hence a clock of its
|
|
41724
|
+
// own, which a busy main thread slows down rather than makes jump.
|
|
41698
41725
|
const playTravel = (pane, movement) => {
|
|
41699
41726
|
const row = rowRef.current;
|
|
41700
41727
|
// Already moving, so there is no ease-in to play: it would stall the row for an
|
|
41701
41728
|
// instant right where the eye is following it.
|
|
41702
41729
|
const replaced = movement.playing;
|
|
41703
41730
|
const inFlight = Boolean(replaced) || Boolean(movement.rowTaken);
|
|
41731
|
+
// Before the row is read: let go of for an instant, it would be snapped to the
|
|
41732
|
+
// nearest page by that read, and the travel would start from there.
|
|
41733
|
+
row.setAttribute("data-route-row-travelling", "");
|
|
41704
41734
|
if (replaced) {
|
|
41705
|
-
|
|
41706
|
-
|
|
41707
|
-
replaced.cancelFrame();
|
|
41735
|
+
replaced.cancel();
|
|
41736
|
+
movement.playing = null;
|
|
41708
41737
|
}
|
|
41709
41738
|
const from = row.scrollLeft;
|
|
41710
41739
|
const {
|
|
@@ -41716,56 +41745,70 @@ const RouteTravel = ({
|
|
|
41716
41745
|
const travelMs = boxes < 1 ? durationMs * boxes : durationMs;
|
|
41717
41746
|
if (!travelMs) {
|
|
41718
41747
|
row.scrollLeft = pane.offsetLeft;
|
|
41748
|
+
letRowGo(movement);
|
|
41719
41749
|
// A write that changes nothing is followed by no scroll event to say the row
|
|
41720
41750
|
// stopped. After the commit that asked, which goes on to say the row moves.
|
|
41721
41751
|
Promise.resolve().then(landRow);
|
|
41722
41752
|
return;
|
|
41723
41753
|
}
|
|
41724
41754
|
const curve = inFlight ? CSS_EASE_OUT : CSS_EASE;
|
|
41725
|
-
let start = null;
|
|
41726
41755
|
let frame = null;
|
|
41756
|
+
// How much of the travel has played, frame by frame. A travel setting off plays
|
|
41757
|
+
// nothing at its first frame, which may have begun while the press was still being
|
|
41758
|
+
// handled: that is no travel. One taking over goes on from the last frame of the
|
|
41759
|
+
// one it replaces, or the row would stand still for a frame where the eye follows it.
|
|
41760
|
+
let played = 0;
|
|
41727
41761
|
const playing = {
|
|
41728
41762
|
// Where this travel put the row, for a scroll event to tell it from a hand.
|
|
41729
41763
|
written: from,
|
|
41730
|
-
|
|
41764
|
+
lastFrame: replaced ? replaced.lastFrame : null,
|
|
41765
|
+
cancel: () => {
|
|
41731
41766
|
cancelAnimationFrame(frame);
|
|
41732
|
-
},
|
|
41733
|
-
stop: () => {
|
|
41734
|
-
playing.cancelFrame();
|
|
41735
|
-
if (movement.playing === playing) {
|
|
41736
|
-
movement.playing = null;
|
|
41737
|
-
row.removeAttribute("data-route-row-travelling");
|
|
41738
|
-
}
|
|
41739
41767
|
}
|
|
41740
41768
|
};
|
|
41741
41769
|
const step = now => {
|
|
41742
|
-
if (
|
|
41743
|
-
|
|
41744
|
-
|
|
41745
|
-
|
|
41770
|
+
if (playing.lastFrame !== null) {
|
|
41771
|
+
const gap = now - playing.lastFrame;
|
|
41772
|
+
if (gap > TRAVEL_FRAME_MAX_MS) {
|
|
41773
|
+
played += TRAVEL_FRAME_MAX_MS;
|
|
41774
|
+
} else if (gap > 0) {
|
|
41775
|
+
played += gap;
|
|
41776
|
+
}
|
|
41746
41777
|
}
|
|
41747
|
-
|
|
41748
|
-
const elapsed =
|
|
41778
|
+
playing.lastFrame = now;
|
|
41779
|
+
const elapsed = played / travelMs;
|
|
41749
41780
|
// Read at every frame: the layout may move under the travel (a scrollbar
|
|
41750
41781
|
// coming in narrows the row), and it goes where the page stands.
|
|
41751
41782
|
const to = pane.offsetLeft;
|
|
41752
41783
|
const arrived = elapsed >= 1;
|
|
41753
41784
|
playing.written = arrived ? to : from + (to - from) * easedProgress(elapsed, curve);
|
|
41754
41785
|
row.scrollLeft = playing.written;
|
|
41786
|
+
// In the frame it is written: the scroll event saying so comes a frame later,
|
|
41787
|
+
// and what follows the row would be drawn a frame behind it.
|
|
41788
|
+
sayRowMoves();
|
|
41755
41789
|
if (!arrived) {
|
|
41756
41790
|
frame = requestAnimationFrame(step);
|
|
41757
41791
|
return;
|
|
41758
41792
|
}
|
|
41759
|
-
|
|
41793
|
+
letRowGo(movement);
|
|
41760
41794
|
// Said here rather than waited for: the last frames of a curve can move the row
|
|
41761
41795
|
// by less than a pixel, and nothing then says it has stopped.
|
|
41762
41796
|
landRow();
|
|
41763
41797
|
};
|
|
41764
41798
|
movement.playing = playing;
|
|
41765
|
-
row.setAttribute("data-route-row-travelling", "");
|
|
41766
41799
|
frame = requestAnimationFrame(step);
|
|
41767
41800
|
};
|
|
41768
41801
|
|
|
41802
|
+
// The row given back to the browser: no travel writes it any more, and it snaps
|
|
41803
|
+
// again. A travel replacing another keeps it (playTravel).
|
|
41804
|
+
const letRowGo = movement => {
|
|
41805
|
+
if (movement.playing) {
|
|
41806
|
+
movement.playing.cancel();
|
|
41807
|
+
movement.playing = null;
|
|
41808
|
+
}
|
|
41809
|
+
rowRef.current.removeAttribute("data-route-row-travelling");
|
|
41810
|
+
};
|
|
41811
|
+
|
|
41769
41812
|
// Every column back where the map says, and the row on the page of the address, in
|
|
41770
41813
|
// one go: that page stands at the same place on screen either way.
|
|
41771
41814
|
const putRowBack = movement => {
|
|
@@ -41822,14 +41865,12 @@ const RouteTravel = ({
|
|
|
41822
41865
|
return;
|
|
41823
41866
|
}
|
|
41824
41867
|
movementRef.current = null;
|
|
41825
|
-
|
|
41826
|
-
movement.playing.stop();
|
|
41827
|
-
}
|
|
41868
|
+
letRowGo(movement);
|
|
41828
41869
|
putRowBack(movement);
|
|
41829
|
-
row.removeAttribute("data-route-row-travelling");
|
|
41830
41870
|
row.removeAttribute("data-route-row-taken");
|
|
41831
41871
|
publishRouteRowMove(null);
|
|
41832
41872
|
releaseHeldPage();
|
|
41873
|
+
releasePaneAtRest();
|
|
41833
41874
|
if (liveRef.current) {
|
|
41834
41875
|
liveRef.current.style.top = "";
|
|
41835
41876
|
}
|
|
@@ -41942,9 +41983,11 @@ const RouteTravel = ({
|
|
|
41942
41983
|
return;
|
|
41943
41984
|
}
|
|
41944
41985
|
const movementBefore = movementRef.current;
|
|
41986
|
+
// The row still rests on the page answered before. Held in the commit that made
|
|
41987
|
+
// its pane inert, so no frame paints it contained.
|
|
41945
41988
|
const movement = beginMovement({
|
|
41946
41989
|
travelling: true
|
|
41947
|
-
});
|
|
41990
|
+
}, panesOf(row)[pages.findIndex(each => samePage(each, answered))]);
|
|
41948
41991
|
if (movementBefore?.byHand && !movementBefore.rowTaken) {
|
|
41949
41992
|
sayRowMoves();
|
|
41950
41993
|
takeRowFromHand(movement);
|
|
@@ -42003,7 +42046,7 @@ const RouteTravel = ({
|
|
|
42003
42046
|
// Not where the travel put it: a hand has taken the row (a trackpad, a wheel),
|
|
42004
42047
|
// and the travel lets it go, snapping included, as the browser's own scroll does.
|
|
42005
42048
|
if (moving?.playing && Math.abs(row.scrollLeft - moving.playing.written) > WRITE_ROUNDING) {
|
|
42006
|
-
moving
|
|
42049
|
+
letRowGo(moving);
|
|
42007
42050
|
}
|
|
42008
42051
|
const pane = panes[currentIndex];
|
|
42009
42052
|
if (!moving && pane && restsOn(row, pane, ROW_READING)) {
|
|
@@ -42012,7 +42055,7 @@ const RouteTravel = ({
|
|
|
42012
42055
|
}
|
|
42013
42056
|
const movement = moving || beginMovement({
|
|
42014
42057
|
byHand: true
|
|
42015
|
-
});
|
|
42058
|
+
}, pane);
|
|
42016
42059
|
sayRowMoves();
|
|
42017
42060
|
if (movement.travelling || !travelByDrag || !pane) {
|
|
42018
42061
|
return;
|
|
@@ -42081,7 +42124,8 @@ const RouteTravel = ({
|
|
|
42081
42124
|
askForPageOfRow(index, movement);
|
|
42082
42125
|
}
|
|
42083
42126
|
// After the address: a pull coming back to its page must not light the tab the
|
|
42084
|
-
// address ran ahead to, even for a render.
|
|
42127
|
+
// address ran ahead to, even for a render. Only what readers are told: the
|
|
42128
|
+
// panes keep their layout until the row rests.
|
|
42085
42129
|
releaseHeldPage();
|
|
42086
42130
|
};
|
|
42087
42131
|
const stopWatching = watchRowScroll(row, {
|
|
@@ -42132,12 +42176,14 @@ const RouteTravel = ({
|
|
|
42132
42176
|
});
|
|
42133
42177
|
const movement = movementRef.current;
|
|
42134
42178
|
if (movement) {
|
|
42135
|
-
movement.playing?.
|
|
42179
|
+
movement.playing?.cancel();
|
|
42136
42180
|
movement.resumeScrollRecording?.();
|
|
42137
42181
|
}
|
|
42182
|
+
row.removeAttribute("data-route-row-travelling");
|
|
42138
42183
|
movementRef.current = null;
|
|
42139
42184
|
publishRouteRowMove(null);
|
|
42140
42185
|
releaseHeldPage();
|
|
42186
|
+
releasePaneAtRest();
|
|
42141
42187
|
};
|
|
42142
42188
|
}, [windowed]);
|
|
42143
42189
|
|