@jsenv/navi 0.30.33 → 0.30.34
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 +79 -35
- package/dist/dev/jsenv_navi.js.map +2 -2
- package/dist/jsenv_navi.js +79 -35
- package/dist/jsenv_navi.js.map +2 -2
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -42668,7 +42668,7 @@ const css$16 = /* css */`.navi_route_travel {
|
|
|
42668
42668
|
display: flex;
|
|
42669
42669
|
}
|
|
42670
42670
|
|
|
42671
|
-
& > [data-route-row-pane][inert] {
|
|
42671
|
+
& > [data-route-row-pane][inert]:not([data-route-row-held]), &:has( > [data-route-row-held]) > [data-route-row-pane]:not([data-route-row-held]) {
|
|
42672
42672
|
top: var(--navi-route-row-pin, 0);
|
|
42673
42673
|
contain: paint;
|
|
42674
42674
|
max-height: 100dvh;
|
|
@@ -42718,6 +42718,12 @@ const ROW_READING = {
|
|
|
42718
42718
|
// How far a scroll position written can read back from what was written: rounded to
|
|
42719
42719
|
// the device's pixels.
|
|
42720
42720
|
const WRITE_ROUNDING = 1;
|
|
42721
|
+
// The most one frame of a travel plays: a frame of a 30fps screen, which is what a
|
|
42722
|
+
// browser saving power gives (an iPhone in Low Power Mode, Chrome's Energy Saver).
|
|
42723
|
+
// A frame later than that is a main thread busy elsewhere (the page arriving builds,
|
|
42724
|
+
// a list fills its budget), and the travel takes longer rather than jump by it. Not a
|
|
42725
|
+
// frame of a 60Hz screen: that would play every travel in slow motion at 30fps.
|
|
42726
|
+
const TRAVEL_FRAME_MAX_MS = 1000 / 30;
|
|
42721
42727
|
|
|
42722
42728
|
/**
|
|
42723
42729
|
* @type {import("preact").FunctionComponent<{
|
|
@@ -42993,18 +42999,22 @@ const RouteTravel = ({
|
|
|
42993
42999
|
// hesitates, then peaks at 1.65 times this one's speed): two rows of tabs in one
|
|
42994
43000
|
// app would not move alike. The scroll position is written at every frame, so the
|
|
42995
43001
|
// row stays a scroller all the way: what follows it (a Nav's bar) reads it as it
|
|
42996
|
-
// reads a hand, and a finger landing finds it where it is.
|
|
42997
|
-
//
|
|
43002
|
+
// reads a hand, and a finger landing finds it where it is. That is played on the
|
|
43003
|
+
// main thread: a transform on the panes would play on the compositor, but it would
|
|
43004
|
+
// capture what the page on screen holds in position: fixed. Hence a clock of its
|
|
43005
|
+
// own, which a busy main thread slows down rather than makes jump.
|
|
42998
43006
|
const playTravel = (pane, movement) => {
|
|
42999
43007
|
const row = rowRef.current;
|
|
43000
43008
|
// Already moving, so there is no ease-in to play: it would stall the row for an
|
|
43001
43009
|
// instant right where the eye is following it.
|
|
43002
43010
|
const replaced = movement.playing;
|
|
43003
43011
|
const inFlight = Boolean(replaced) || Boolean(movement.rowTaken);
|
|
43012
|
+
// Before the row is read: let go of for an instant, it would be snapped to the
|
|
43013
|
+
// nearest page by that read, and the travel would start from there.
|
|
43014
|
+
row.setAttribute("data-route-row-travelling", "");
|
|
43004
43015
|
if (replaced) {
|
|
43005
|
-
|
|
43006
|
-
|
|
43007
|
-
replaced.cancelFrame();
|
|
43016
|
+
replaced.cancel();
|
|
43017
|
+
movement.playing = null;
|
|
43008
43018
|
}
|
|
43009
43019
|
const from = row.scrollLeft;
|
|
43010
43020
|
const {
|
|
@@ -43016,56 +43026,88 @@ const RouteTravel = ({
|
|
|
43016
43026
|
const travelMs = boxes < 1 ? durationMs * boxes : durationMs;
|
|
43017
43027
|
if (!travelMs) {
|
|
43018
43028
|
row.scrollLeft = pane.offsetLeft;
|
|
43029
|
+
letRowGo(movement);
|
|
43019
43030
|
// A write that changes nothing is followed by no scroll event to say the row
|
|
43020
43031
|
// stopped. After the commit that asked, which goes on to say the row moves.
|
|
43021
43032
|
Promise.resolve().then(landRow);
|
|
43022
43033
|
return;
|
|
43023
43034
|
}
|
|
43024
43035
|
const curve = inFlight ? CSS_EASE_OUT : CSS_EASE;
|
|
43025
|
-
let start = null;
|
|
43026
43036
|
let frame = null;
|
|
43037
|
+
// How much of the travel has played, frame by frame. A travel setting off plays
|
|
43038
|
+
// nothing at its first frame, which may have begun while the press was still being
|
|
43039
|
+
// handled: that is no travel. One taking over goes on from the last frame of the
|
|
43040
|
+
// one it replaces, or the row would stand still for a frame where the eye follows it.
|
|
43041
|
+
let played = 0;
|
|
43027
43042
|
const playing = {
|
|
43028
43043
|
// Where this travel put the row, for a scroll event to tell it from a hand.
|
|
43029
43044
|
written: from,
|
|
43030
|
-
|
|
43045
|
+
lastFrame: replaced ? replaced.lastFrame : null,
|
|
43046
|
+
cancel: () => {
|
|
43031
43047
|
cancelAnimationFrame(frame);
|
|
43032
|
-
},
|
|
43033
|
-
stop: () => {
|
|
43034
|
-
playing.cancelFrame();
|
|
43035
|
-
if (movement.playing === playing) {
|
|
43036
|
-
movement.playing = null;
|
|
43037
|
-
row.removeAttribute("data-route-row-travelling");
|
|
43038
|
-
}
|
|
43039
43048
|
}
|
|
43040
43049
|
};
|
|
43041
43050
|
const step = now => {
|
|
43042
|
-
if (
|
|
43043
|
-
|
|
43044
|
-
|
|
43045
|
-
|
|
43051
|
+
if (playing.lastFrame !== null) {
|
|
43052
|
+
const gap = now - playing.lastFrame;
|
|
43053
|
+
if (gap > TRAVEL_FRAME_MAX_MS) {
|
|
43054
|
+
played += TRAVEL_FRAME_MAX_MS;
|
|
43055
|
+
} else if (gap > 0) {
|
|
43056
|
+
played += gap;
|
|
43057
|
+
}
|
|
43046
43058
|
}
|
|
43047
|
-
|
|
43048
|
-
const elapsed =
|
|
43059
|
+
playing.lastFrame = now;
|
|
43060
|
+
const elapsed = played / travelMs;
|
|
43049
43061
|
// Read at every frame: the layout may move under the travel (a scrollbar
|
|
43050
43062
|
// coming in narrows the row), and it goes where the page stands.
|
|
43051
43063
|
const to = pane.offsetLeft;
|
|
43052
43064
|
const arrived = elapsed >= 1;
|
|
43053
43065
|
playing.written = arrived ? to : from + (to - from) * easedProgress(elapsed, curve);
|
|
43054
43066
|
row.scrollLeft = playing.written;
|
|
43067
|
+
// In the frame it is written: the scroll event saying so comes a frame later,
|
|
43068
|
+
// and what follows the row would be drawn a frame behind it.
|
|
43069
|
+
sayRowMoves();
|
|
43055
43070
|
if (!arrived) {
|
|
43056
43071
|
frame = requestAnimationFrame(step);
|
|
43057
43072
|
return;
|
|
43058
43073
|
}
|
|
43059
|
-
|
|
43074
|
+
letRowGo(movement);
|
|
43060
43075
|
// Said here rather than waited for: the last frames of a curve can move the row
|
|
43061
43076
|
// by less than a pixel, and nothing then says it has stopped.
|
|
43062
43077
|
landRow();
|
|
43063
43078
|
};
|
|
43064
43079
|
movement.playing = playing;
|
|
43065
|
-
row.setAttribute("data-route-row-travelling", "");
|
|
43066
43080
|
frame = requestAnimationFrame(step);
|
|
43067
43081
|
};
|
|
43068
43082
|
|
|
43083
|
+
// The row given back to the browser: no travel writes it any more, and it snaps
|
|
43084
|
+
// again. A travel replacing another keeps it (playTravel).
|
|
43085
|
+
const letRowGo = movement => {
|
|
43086
|
+
if (movement.playing) {
|
|
43087
|
+
movement.playing.cancel();
|
|
43088
|
+
movement.playing = null;
|
|
43089
|
+
}
|
|
43090
|
+
rowRef.current.removeAttribute("data-route-row-travelling");
|
|
43091
|
+
};
|
|
43092
|
+
|
|
43093
|
+
// The address runs ahead of a hand to build the page it pulls towards (onScroll):
|
|
43094
|
+
// the pane under the hand stays laid out as the page on screen until the hand lets
|
|
43095
|
+
// go, whatever `inert` says (see the CSS). What reads the page held is told apart
|
|
43096
|
+
// (route_travel_hold.js), and both are let go of together.
|
|
43097
|
+
const heldPaneRef = useRef(null);
|
|
43098
|
+
const holdPaneOnScreen = pane => {
|
|
43099
|
+
heldPaneRef.current = pane;
|
|
43100
|
+
pane.setAttribute("data-route-row-held", "");
|
|
43101
|
+
};
|
|
43102
|
+
const releaseHold = () => {
|
|
43103
|
+
releaseHeldPage();
|
|
43104
|
+
const heldPane = heldPaneRef.current;
|
|
43105
|
+
if (heldPane) {
|
|
43106
|
+
heldPaneRef.current = null;
|
|
43107
|
+
heldPane.removeAttribute("data-route-row-held");
|
|
43108
|
+
}
|
|
43109
|
+
};
|
|
43110
|
+
|
|
43069
43111
|
// Every column back where the map says, and the row on the page of the address, in
|
|
43070
43112
|
// one go: that page stands at the same place on screen either way.
|
|
43071
43113
|
const putRowBack = movement => {
|
|
@@ -43094,7 +43136,7 @@ const RouteTravel = ({
|
|
|
43094
43136
|
const position = row.scrollLeft;
|
|
43095
43137
|
movement.rowTaken = true;
|
|
43096
43138
|
// A travel no hand set off holds nothing: it goes where it goes.
|
|
43097
|
-
|
|
43139
|
+
releaseHold();
|
|
43098
43140
|
row.style.setProperty("--navi-route-row-stand", `${-position}px`);
|
|
43099
43141
|
row.setAttribute("data-route-row-taken", "");
|
|
43100
43142
|
afterFrames(2, () => {
|
|
@@ -43122,14 +43164,11 @@ const RouteTravel = ({
|
|
|
43122
43164
|
return;
|
|
43123
43165
|
}
|
|
43124
43166
|
movementRef.current = null;
|
|
43125
|
-
|
|
43126
|
-
movement.playing.stop();
|
|
43127
|
-
}
|
|
43167
|
+
letRowGo(movement);
|
|
43128
43168
|
putRowBack(movement);
|
|
43129
|
-
row.removeAttribute("data-route-row-travelling");
|
|
43130
43169
|
row.removeAttribute("data-route-row-taken");
|
|
43131
43170
|
publishRouteRowMove(null);
|
|
43132
|
-
|
|
43171
|
+
releaseHold();
|
|
43133
43172
|
if (liveRef.current) {
|
|
43134
43173
|
liveRef.current.style.top = "";
|
|
43135
43174
|
}
|
|
@@ -43303,7 +43342,7 @@ const RouteTravel = ({
|
|
|
43303
43342
|
// Not where the travel put it: a hand has taken the row (a trackpad, a wheel),
|
|
43304
43343
|
// and the travel lets it go, snapping included, as the browser's own scroll does.
|
|
43305
43344
|
if (moving?.playing && Math.abs(row.scrollLeft - moving.playing.written) > WRITE_ROUNDING) {
|
|
43306
|
-
moving
|
|
43345
|
+
letRowGo(moving);
|
|
43307
43346
|
}
|
|
43308
43347
|
const pane = panes[currentIndex];
|
|
43309
43348
|
if (!moving && pane && restsOn(row, pane, ROW_READING)) {
|
|
@@ -43349,8 +43388,12 @@ const RouteTravel = ({
|
|
|
43349
43388
|
return;
|
|
43350
43389
|
}
|
|
43351
43390
|
leavePictureOfLive(movement);
|
|
43352
|
-
} else
|
|
43353
|
-
|
|
43391
|
+
} else {
|
|
43392
|
+
if (paneTowards.hasAttribute("data-built")) {
|
|
43393
|
+
return;
|
|
43394
|
+
}
|
|
43395
|
+
// Before the address moves: the render that makes it inert must find it held.
|
|
43396
|
+
holdPaneOnScreen(pane);
|
|
43354
43397
|
}
|
|
43355
43398
|
holdPage(pages[currentIndex], page);
|
|
43356
43399
|
askFor(page);
|
|
@@ -43382,7 +43425,7 @@ const RouteTravel = ({
|
|
|
43382
43425
|
}
|
|
43383
43426
|
// After the address: a pull coming back to its page must not light the tab the
|
|
43384
43427
|
// address ran ahead to, even for a render.
|
|
43385
|
-
|
|
43428
|
+
releaseHold();
|
|
43386
43429
|
};
|
|
43387
43430
|
const stopWatching = watchRowScroll(row, {
|
|
43388
43431
|
onScroll,
|
|
@@ -43432,12 +43475,13 @@ const RouteTravel = ({
|
|
|
43432
43475
|
});
|
|
43433
43476
|
const movement = movementRef.current;
|
|
43434
43477
|
if (movement) {
|
|
43435
|
-
movement.playing?.
|
|
43478
|
+
movement.playing?.cancel();
|
|
43436
43479
|
movement.resumeScrollRecording?.();
|
|
43437
43480
|
}
|
|
43481
|
+
row.removeAttribute("data-route-row-travelling");
|
|
43438
43482
|
movementRef.current = null;
|
|
43439
43483
|
publishRouteRowMove(null);
|
|
43440
|
-
|
|
43484
|
+
releaseHold();
|
|
43441
43485
|
};
|
|
43442
43486
|
}, [windowed]);
|
|
43443
43487
|
|