@jsenv/navi 0.29.513 → 0.29.515
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 +111 -14
- package/dist/dev/jsenv_navi.js.map +8 -8
- package/dist/jsenv_navi.js +111 -14
- package/dist/jsenv_navi.js.map +8 -8
- package/docs/route_transitions.md +3 -2
- package/docs/scroll.md +31 -0
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -10568,6 +10568,19 @@ const recallScrollerPosition = (name) => {
|
|
|
10568
10568
|
return positionByName.get(name);
|
|
10569
10569
|
};
|
|
10570
10570
|
|
|
10571
|
+
// Said by a scroller sent back to its start while it stays mounted: where it
|
|
10572
|
+
// was is a place in what it no longer shows, so nothing is carried and nothing
|
|
10573
|
+
// is come back to under this address until it says where it is again. What it
|
|
10574
|
+
// said under another address stays, for the way back to that address.
|
|
10575
|
+
const forgetScrollerPosition = (name) => {
|
|
10576
|
+
loadStore();
|
|
10577
|
+
saidByScrollerName.delete(name);
|
|
10578
|
+
const positionByName = scrollerPositionsByUrl.get(readShownUrl());
|
|
10579
|
+
if (positionByName) {
|
|
10580
|
+
positionByName.delete(name);
|
|
10581
|
+
}
|
|
10582
|
+
};
|
|
10583
|
+
|
|
10571
10584
|
// Said by a scroller as it unmounts. Its page is being left when the url is
|
|
10572
10585
|
// already another one — the history is written before the page it names is
|
|
10573
10586
|
// taken down — and then its position is kept for the way back. The url still
|
|
@@ -37105,9 +37118,11 @@ const releaseTransitionDestination = (owner) => {
|
|
|
37105
37118
|
* inside its rectangle — which is where the hand thinks it pressed. The same
|
|
37106
37119
|
* move route_travel.jsx makes for the box a finger reaches for mid-flight.
|
|
37107
37120
|
*
|
|
37108
|
-
* A `RouteTravel` holds this too
|
|
37109
|
-
* gets its click on its own
|
|
37110
|
-
*
|
|
37121
|
+
* A `RouteTravel` holds this too, for the bars it leaves live. A control there
|
|
37122
|
+
* gets its click on its own except in the first frames of the travel, when a
|
|
37123
|
+
* press falls to the document root like any other; the part of a bar photographed
|
|
37124
|
+
* for the travel (`data-navi-fixed-bar-overhang`, fixed_bar.jsx) is deaf
|
|
37125
|
+
* throughout.
|
|
37111
37126
|
*
|
|
37112
37127
|
* ASKED FOR, never derived, and that is the whole safety of it: only the
|
|
37113
37128
|
* application knows the control does not move. One that travels with the pages
|
|
@@ -38071,6 +38086,21 @@ const placeTransitionWindow = (owner, groupName) => {
|
|
|
38071
38086
|
document.documentElement.setAttribute(WINDOW_PLACED_ATTRIBUTE, "");
|
|
38072
38087
|
};
|
|
38073
38088
|
|
|
38089
|
+
/**
|
|
38090
|
+
* Whether a point of the window lies in a band the furniture keeps: the pictures
|
|
38091
|
+
* are cut at those bands, so what is seen there is never a page, however far the
|
|
38092
|
+
* box runs under it.
|
|
38093
|
+
*/
|
|
38094
|
+
const isPointInTransitionBand = (clientX, clientY) => {
|
|
38095
|
+
const band = readBand();
|
|
38096
|
+
return (
|
|
38097
|
+
clientX < band.left ||
|
|
38098
|
+
clientX > window.innerWidth - band.right ||
|
|
38099
|
+
clientY < band.top ||
|
|
38100
|
+
clientY > window.innerHeight - band.bottom
|
|
38101
|
+
);
|
|
38102
|
+
};
|
|
38103
|
+
|
|
38074
38104
|
// The live layout takes the box back. A discontinuity by construction — the
|
|
38075
38105
|
// window stands at the held height, the box is at its own — and an invisible
|
|
38076
38106
|
// one: the page arriving is fully in place, and the strip below it that the
|
|
@@ -41255,11 +41285,16 @@ const RouteTravel = ({
|
|
|
41255
41285
|
gestureRef.current = gesture;
|
|
41256
41286
|
};
|
|
41257
41287
|
|
|
41258
|
-
// A press
|
|
41259
|
-
// the browser's transition covers the page and the press
|
|
41260
|
-
// document root instead, whatever the pictures are told about pointer
|
|
41261
|
-
// So while a travel plays, the press is caught at the document and
|
|
41262
|
-
// the box when it fell
|
|
41288
|
+
// A press aimed at a page while a travel is playing does not always reach the
|
|
41289
|
+
// box: the browser's transition covers the page and the press can be delivered
|
|
41290
|
+
// to the document root instead, whatever the pictures are told about pointer
|
|
41291
|
+
// events. So while a travel plays, the press is caught at the document and
|
|
41292
|
+
// handed to the box when it fell where a page is SEEN, which is where the hand
|
|
41293
|
+
// thinks it pressed.
|
|
41294
|
+
//
|
|
41295
|
+
// Decided by the position and never by the target: in the first frames of a
|
|
41296
|
+
// travel a press on a live bar falls to the root like any other, and what lies
|
|
41297
|
+
// under a picture is not what the hand is aiming at.
|
|
41263
41298
|
pointerDownRef.current = onPointerDown;
|
|
41264
41299
|
useLayoutEffect(() => {
|
|
41265
41300
|
const onDocumentPointerDown = pointerDownEvent => {
|
|
@@ -41284,6 +41319,11 @@ const RouteTravel = ({
|
|
|
41284
41319
|
if (clientX < left || clientX > right || clientY < top || clientY > bottom) {
|
|
41285
41320
|
return;
|
|
41286
41321
|
}
|
|
41322
|
+
// A box scrolled under a bar still has the press in its rectangle, but
|
|
41323
|
+
// the pictures are cut at that bar: the press is aimed at the bar.
|
|
41324
|
+
if (isPointInTransitionBand(clientX, clientY)) {
|
|
41325
|
+
return;
|
|
41326
|
+
}
|
|
41287
41327
|
pointerDownRef.current(pointerDownEvent);
|
|
41288
41328
|
};
|
|
41289
41329
|
document.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
@@ -56467,8 +56507,9 @@ const LinkPseudoElements = ["::-navi-loader", "::-navi-indicator"];
|
|
|
56467
56507
|
* press on it is aimed at what the reader can see. Say it there, and only
|
|
56468
56508
|
* there: a control that TRAVELS with the pages has a rectangle where it will
|
|
56469
56509
|
* be, not where it is seen, and a press handed to it fires something nobody
|
|
56470
|
-
* aimed at. A `RouteTravel` honours it as well, for a control in
|
|
56471
|
-
*
|
|
56510
|
+
* aimed at. A `RouteTravel` honours it as well, for a control in a `FixedBar`:
|
|
56511
|
+
* the part it photographs (`data-navi-fixed-bar-overhang`) is deaf for the
|
|
56512
|
+
* whole travel, and the rest for its first frames.
|
|
56472
56513
|
* @param {boolean} [props.replace] - Go to the destination by TAKING THE PLACE
|
|
56473
56514
|
* of the current history entry instead of stacking onto it: the link stays a
|
|
56474
56515
|
* link (an address, a middle click, the keyboard, `aria-current`), only the
|
|
@@ -62432,7 +62473,8 @@ const COMMAND_DEFAULT_PROPS_FACTORIES = {
|
|
|
62432
62473
|
* drawn — must still close it. What `<Link pressableDuringRouteTransition>`
|
|
62433
62474
|
* says, for the other half of a toggle. Only for a control that does not
|
|
62434
62475
|
* travel with the pages. A `RouteTravel` honours it as well, for a control in
|
|
62435
|
-
*
|
|
62476
|
+
* a `FixedBar`: the part it photographs (`data-navi-fixed-bar-overhang`) is
|
|
62477
|
+
* deaf for the whole travel, and the rest for its first frames.
|
|
62436
62478
|
* @param {Function} [action] What the press runs: a button holds no value, so
|
|
62437
62479
|
* every press is one call. Inside a `<Form>` or a group it carries the value
|
|
62438
62480
|
* around it, merged over the action's bound params — a value that is not an
|
|
@@ -84026,6 +84068,7 @@ const ListUI = props => {
|
|
|
84026
84068
|
scroller = "self",
|
|
84027
84069
|
hoverWhileScrolling = false,
|
|
84028
84070
|
scrollResetOnNavigation = false,
|
|
84071
|
+
scrollResetKey,
|
|
84029
84072
|
lockSize,
|
|
84030
84073
|
columns,
|
|
84031
84074
|
itemColumns,
|
|
@@ -84144,6 +84187,7 @@ const ListUI = props => {
|
|
|
84144
84187
|
scrolled,
|
|
84145
84188
|
defaultScrolled,
|
|
84146
84189
|
onScrolledChange,
|
|
84190
|
+
scrollResetKey,
|
|
84147
84191
|
rememberScroll,
|
|
84148
84192
|
listId: rest.id,
|
|
84149
84193
|
scroller,
|
|
@@ -84475,6 +84519,7 @@ const useListScrollSync = ({
|
|
|
84475
84519
|
scrolled,
|
|
84476
84520
|
defaultScrolled,
|
|
84477
84521
|
onScrolledChange,
|
|
84522
|
+
scrollResetKey,
|
|
84478
84523
|
rememberScroll,
|
|
84479
84524
|
listId,
|
|
84480
84525
|
scroller,
|
|
@@ -84483,6 +84528,8 @@ const useListScrollSync = ({
|
|
|
84483
84528
|
columns
|
|
84484
84529
|
}) => {
|
|
84485
84530
|
const debugScroll = useDebugScroll();
|
|
84531
|
+
// The offset a search gives back once emptied (see below).
|
|
84532
|
+
const savedScrollRef = useRef(null);
|
|
84486
84533
|
// Where the list must be: what the caller holds it at (`scrolled`), or where
|
|
84487
84534
|
// it opens and then lets go (`defaultScrolled`). A `scrolled` that changes is
|
|
84488
84535
|
// the caller moving the list, so the hold is armed again — that is what makes
|
|
@@ -84491,7 +84538,9 @@ const useListScrollSync = ({
|
|
|
84491
84538
|
// one kept from the previous visit): followed for as long as nobody has
|
|
84492
84539
|
// moved the list, and compared by value, since it is said at every render.
|
|
84493
84540
|
// Nothing to hold it at (a position not saved yet) is not a position: the
|
|
84494
|
-
// list opens where it opens.
|
|
84541
|
+
// list opens where it opens. A `scrollResetKey` that changes sends it back to
|
|
84542
|
+
// its start ("back_to_start", see placeBackAtStart), unless a `scrolled`
|
|
84543
|
+
// changing in the same render says where it goes.
|
|
84495
84544
|
const startPlaceRef = useRef(null);
|
|
84496
84545
|
if (startPlaceRef.current === null) {
|
|
84497
84546
|
startPlaceRef.current = {
|
|
@@ -84499,6 +84548,7 @@ const useListScrollSync = ({
|
|
|
84499
84548
|
wanted: scrolled ?? defaultScrolled,
|
|
84500
84549
|
scrolled,
|
|
84501
84550
|
defaultScrolled,
|
|
84551
|
+
scrollResetKey,
|
|
84502
84552
|
way: null,
|
|
84503
84553
|
arrived: false,
|
|
84504
84554
|
// Whether the hold's writes glide (--navi-scroll:smooth).
|
|
@@ -84506,6 +84556,20 @@ const useListScrollSync = ({
|
|
|
84506
84556
|
};
|
|
84507
84557
|
} else {
|
|
84508
84558
|
const place = startPlaceRef.current;
|
|
84559
|
+
if (!compareTwoJsValues(place.scrollResetKey, scrollResetKey)) {
|
|
84560
|
+
place.scrollResetKey = scrollResetKey;
|
|
84561
|
+
place.wanted = "back_to_start";
|
|
84562
|
+
place.userTookOver = false;
|
|
84563
|
+
place.way = null;
|
|
84564
|
+
place.arrived = false;
|
|
84565
|
+
place.smooth = false;
|
|
84566
|
+
// What the list said it was reading, and what a search would give back,
|
|
84567
|
+
// are places in what it no longer shows.
|
|
84568
|
+
savedScrollRef.current = null;
|
|
84569
|
+
if (rememberScroll) {
|
|
84570
|
+
forgetScrollerPosition(listId);
|
|
84571
|
+
}
|
|
84572
|
+
}
|
|
84509
84573
|
if (place.scrolled !== scrolled) {
|
|
84510
84574
|
place.scrolled = scrolled;
|
|
84511
84575
|
place.defaultScrolled = defaultScrolled;
|
|
@@ -84514,7 +84578,7 @@ const useListScrollSync = ({
|
|
|
84514
84578
|
place.smooth = false;
|
|
84515
84579
|
} else if ((scrolled === undefined || scrolled === null) && !compareTwoJsValues(place.defaultScrolled, defaultScrolled)) {
|
|
84516
84580
|
place.defaultScrolled = defaultScrolled;
|
|
84517
|
-
if (!place.userTookOver) {
|
|
84581
|
+
if (!place.userTookOver && place.wanted !== "back_to_start") {
|
|
84518
84582
|
place.wanted = defaultScrolled;
|
|
84519
84583
|
// Placed again from where it stands: the way to the previous place
|
|
84520
84584
|
// says nothing about whose the next scrolls are.
|
|
@@ -84847,6 +84911,8 @@ const useListScrollSync = ({
|
|
|
84847
84911
|
wantedStart = total - windowSize;
|
|
84848
84912
|
} else if (typeof scrolledWanted === "number") {
|
|
84849
84913
|
heldItem = scrolledWanted;
|
|
84914
|
+
} else if (scrolledWanted === "back_to_start") {
|
|
84915
|
+
heldItem = 0;
|
|
84850
84916
|
} else if (scrolledWanted && scrolledWanted.id !== undefined) {
|
|
84851
84917
|
const itemIndex = listItems.locateItem(scrolledWanted.id);
|
|
84852
84918
|
if (itemIndex !== null) {
|
|
@@ -85081,7 +85147,6 @@ const useListScrollSync = ({
|
|
|
85081
85147
|
// Lorsqu'on selectionne quelque chose pendant une recherche, alors ensuite meme si on clear
|
|
85082
85148
|
// on veut pas revenir a la position scroll précédente car on veut garde l'item qu'on a selectionné visible
|
|
85083
85149
|
// (pour l'instant pas grave car on travaille pour le mode select qui fermera le dialog au select)
|
|
85084
|
-
const savedScrollRef = useRef(null);
|
|
85085
85150
|
const topMatchScoresKeyRef = useRef("");
|
|
85086
85151
|
const restoreScrollRafRef = useRef(null);
|
|
85087
85152
|
useLayoutEffect(() => {
|
|
@@ -85190,6 +85255,10 @@ const useListScrollSync = ({
|
|
|
85190
85255
|
if (scrolledWanted === "start" || scrolledWanted === undefined || startPlaceRef.current.userTookOver || !ref.current) {
|
|
85191
85256
|
return;
|
|
85192
85257
|
}
|
|
85258
|
+
if (scrolledWanted === "back_to_start") {
|
|
85259
|
+
placeBackAtStart();
|
|
85260
|
+
return;
|
|
85261
|
+
}
|
|
85193
85262
|
if (listItems.totalSignal.peek() === 0 || virtualItemSizeSignal.peek() === 0) {
|
|
85194
85263
|
return;
|
|
85195
85264
|
}
|
|
@@ -85288,6 +85357,24 @@ const useListScrollSync = ({
|
|
|
85288
85357
|
}
|
|
85289
85358
|
sendHeldScroll(scrollNow + delta);
|
|
85290
85359
|
};
|
|
85360
|
+
// The start of the list, what comes before its first item included, not an
|
|
85361
|
+
// item: a box of its own goes to 0. A box the list is further down of also
|
|
85362
|
+
// shows what stands above it, the control that asked for this among others, so
|
|
85363
|
+
// the list is brought back to the box's start and never sent forward to it.
|
|
85364
|
+
const placeBackAtStart = () => {
|
|
85365
|
+
const scrollerEl = getScroller();
|
|
85366
|
+
if (ref.current.contains(scrollerEl)) {
|
|
85367
|
+
sendHeldScroll(0);
|
|
85368
|
+
return;
|
|
85369
|
+
}
|
|
85370
|
+
const scale = readScrollerScale(scrollerEl, horizontal);
|
|
85371
|
+
const viewportRect = getScrollerViewportRect(scrollerEl);
|
|
85372
|
+
const listRect = ref.current.getBoundingClientRect();
|
|
85373
|
+
const offsetNow = (horizontal ? listRect.left - viewportRect.left : listRect.top - viewportRect.top) / scale;
|
|
85374
|
+
const delta = offsetNow - getItemScrollInset(scrollerEl, ref.current, horizontal);
|
|
85375
|
+
const scrollNow = horizontal ? scrollerEl.scrollLeft : scrollerEl.scrollTop;
|
|
85376
|
+
sendHeldScroll(delta < 0 ? scrollNow + delta : scrollNow);
|
|
85377
|
+
};
|
|
85291
85378
|
// Every placement goes through here, the ones that find the list in place
|
|
85292
85379
|
// too: it keeps the way from where the scroller was to where it is sent,
|
|
85293
85380
|
// which is how a scroll event tells the hold's own scrolls from anyone
|
|
@@ -90005,6 +90092,7 @@ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, Li
|
|
|
90005
90092
|
* scroller?: "self" | "parent" | "document" | Element | {current: Element},
|
|
90006
90093
|
* hoverWhileScrolling?: boolean,
|
|
90007
90094
|
* scrollResetOnNavigation?: boolean,
|
|
90095
|
+
* scrollResetKey?: any,
|
|
90008
90096
|
* fallback?: import("preact").ComponentChildren,
|
|
90009
90097
|
* searchFallback?: import("preact").ComponentChildren,
|
|
90010
90098
|
* searchText?: string,
|
|
@@ -90249,6 +90337,15 @@ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, Li
|
|
|
90249
90337
|
* overwrite each other (see docs/scroll.md). A fresh arrival at the page
|
|
90250
90338
|
* opens at `defaultScrolled` either way, and so does a list the caller holds
|
|
90251
90339
|
* through `scrolled`.
|
|
90340
|
+
* @param {any} [props.scrollResetKey]
|
|
90341
|
+
* What the list shows, said as a value: another order, another filter. When
|
|
90342
|
+
* it changes after mount (compared by value: `[order, filter]` can be written
|
|
90343
|
+
* at every render) the list goes back to its start before the paint, in
|
|
90344
|
+
* whichever box `scroller` names, and is held there until the user reaches
|
|
90345
|
+
* for it. A list whose start is in view in a box that also shows what stands
|
|
90346
|
+
* above it does not move. A `scrolled` changing in the same render wins. The
|
|
90347
|
+
* position remembered under the `id` for the address shown is dropped; see
|
|
90348
|
+
* docs/scroll.md.
|
|
90252
90349
|
* @param {boolean} [props.deselectable]
|
|
90253
90350
|
* A single-select list allowed to hold nothing: the selected item, pressed
|
|
90254
90351
|
* again, lets go. Without it the list is a radio group — a choice, once
|