@jsenv/navi 0.29.382 → 0.29.384
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 +78 -18
- package/dist/dev/jsenv_navi.js.map +4 -4
- package/dist/jsenv_navi.js +78 -18
- package/dist/jsenv_navi.js.map +4 -4
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -17917,6 +17917,11 @@ const generateSignalId = () => {
|
|
|
17917
17917
|
* `?level=3,4` becomes `[3, 4]` instead of `["3", "4"]`. Without it items stay strings.
|
|
17918
17918
|
* @param {number} [options.step] - For number type: step size for precision. Values will be rounded to nearest multiple of step.
|
|
17919
17919
|
* @param {Array} [options.oneOf] - Array of valid values for validation. Signal will be marked invalid if value is not in this array
|
|
17920
|
+
* @param {boolean} [options.autoFix=false] - Hold the repaired value instead of the refused one: a number
|
|
17921
|
+
* clamped to `min`/`max` and rounded to `step`, a value outside `oneOf` replaced by the signal's
|
|
17922
|
+
* default value (an enumeration has no nearest value, and its order says nothing). Without it the
|
|
17923
|
+
* refused value is held as-is, marked invalid, and `validSignal` reads `undefined`. When the value
|
|
17924
|
+
* came from the address, the address is rewritten with the repaired one (a replace).
|
|
17920
17925
|
* @param {boolean} [options.weak=false] - The param qualifies one visit, not the screen: it is written into a
|
|
17921
17926
|
* url only when explicitly named (`routeParams={{ edit: id }}`), never inherited from the signal's current
|
|
17922
17927
|
* value, and it goes back to the default value when the route stops matching. Use it for params like an
|
|
@@ -17951,11 +17956,11 @@ const generateSignalId = () => {
|
|
|
17951
17956
|
* });
|
|
17952
17957
|
*
|
|
17953
17958
|
* @example
|
|
17954
|
-
* // Signal with validation and auto-fix
|
|
17959
|
+
* // Signal with validation and auto-fix: an unknown tab falls back to "overview"
|
|
17955
17960
|
* const tab = stateSignal("overview", {
|
|
17956
17961
|
* id: "current-tab",
|
|
17957
17962
|
* oneOf: ["overview", "details", "settings"],
|
|
17958
|
-
* autoFix:
|
|
17963
|
+
* autoFix: true,
|
|
17959
17964
|
* persists: true
|
|
17960
17965
|
* });
|
|
17961
17966
|
*
|
|
@@ -18052,6 +18057,10 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
18052
18057
|
oneOf,
|
|
18053
18058
|
localStorageRepresentation,
|
|
18054
18059
|
autoFix,
|
|
18060
|
+
// What a value no rule can repair falls back to: the default is what the
|
|
18061
|
+
// state is when nothing says otherwise, read at repair time (from
|
|
18062
|
+
// processValue, below) so a dynamic default is read where it stands.
|
|
18063
|
+
fallback: () => getDefaultValue(false),
|
|
18055
18064
|
});
|
|
18056
18065
|
const readFromLocalStorage = persists
|
|
18057
18066
|
? () => {
|
|
@@ -27169,6 +27178,14 @@ This prevents cross-test pollution and ensures clean state.`,
|
|
|
27169
27178
|
// Apply all signal updates in a batch
|
|
27170
27179
|
const matchingRouteSet = new Set();
|
|
27171
27180
|
const routeUpdateSet = new Set();
|
|
27181
|
+
// Params the address gave and the state could not hold as written
|
|
27182
|
+
// (autoFix): the address is rewritten with what the state holds, once
|
|
27183
|
+
// the sync is over, so the repaired value is not left in the url to be
|
|
27184
|
+
// replayed by a reload or a copied link.
|
|
27185
|
+
const repairedParamsByRoute = new Map();
|
|
27186
|
+
// A query connection is inherited by the child routes of the one
|
|
27187
|
+
// declaring it: the first route to record a param answers for all.
|
|
27188
|
+
const repairedParamNameSet = new Set();
|
|
27172
27189
|
batch(() => {
|
|
27173
27190
|
for (const {
|
|
27174
27191
|
route,
|
|
@@ -27351,6 +27368,29 @@ This prevents cross-test pollution and ensures clean state.`,
|
|
|
27351
27368
|
);
|
|
27352
27369
|
}
|
|
27353
27370
|
paramSignal.value = urlParamValue;
|
|
27371
|
+
if (
|
|
27372
|
+
paramSignal.validity?.autoFixed &&
|
|
27373
|
+
!repairedParamNameSet.has(paramName)
|
|
27374
|
+
) {
|
|
27375
|
+
repairedParamNameSet.add(paramName);
|
|
27376
|
+
const repairedValue = paramSignal.peek();
|
|
27377
|
+
if (debug) {
|
|
27378
|
+
console.debug(
|
|
27379
|
+
`[route] URL->Signal: ${paramName}=${urlParamValue} repaired to ${repairedValue}, the url will be rewritten`,
|
|
27380
|
+
);
|
|
27381
|
+
}
|
|
27382
|
+
let repairedParams = repairedParamsByRoute.get(route);
|
|
27383
|
+
if (!repairedParams) {
|
|
27384
|
+
repairedParams = {};
|
|
27385
|
+
repairedParamsByRoute.set(route, repairedParams);
|
|
27386
|
+
}
|
|
27387
|
+
// A default is not written in an address (see the signal -> url sync)
|
|
27388
|
+
repairedParams[paramName] = connection.isDefaultValue(
|
|
27389
|
+
repairedValue,
|
|
27390
|
+
)
|
|
27391
|
+
? undefined
|
|
27392
|
+
: repairedValue;
|
|
27393
|
+
}
|
|
27354
27394
|
continue;
|
|
27355
27395
|
}
|
|
27356
27396
|
}
|
|
@@ -27361,6 +27401,12 @@ This prevents cross-test pollution and ensures clean state.`,
|
|
|
27361
27401
|
// Reset flag after URL -> Signal synchronization is complete
|
|
27362
27402
|
isUpdatingRoutesFromUrl = false;
|
|
27363
27403
|
Object.assign(returnValue, { matchingRouteSet });
|
|
27404
|
+
for (const [route, repairedParams] of repairedParamsByRoute) {
|
|
27405
|
+
route.replaceParams(repairedParams, {
|
|
27406
|
+
callReason: `url params repaired on ${route}: ${Object.keys(repairedParams).join(", ")}`,
|
|
27407
|
+
history: "replace",
|
|
27408
|
+
});
|
|
27409
|
+
}
|
|
27364
27410
|
}
|
|
27365
27411
|
|
|
27366
27412
|
return returnValue;
|
|
@@ -61357,10 +61403,12 @@ let releaseLiftInProgress = null;
|
|
|
61357
61403
|
// cancelled with the movement so a finished one cannot go on applying its
|
|
61358
61404
|
// last values to the next movement's picture.
|
|
61359
61405
|
let boxAnimationInProgress = null;
|
|
61360
|
-
// The page held still
|
|
61361
|
-
// anyway, and the browser keeps following the
|
|
61362
|
-
// carry the arriving box along under a page that
|
|
61363
|
-
// clip to the room between the bars, computed
|
|
61406
|
+
// The page held still from the first read about it to the end of the
|
|
61407
|
+
// movement. Its picture is frozen anyway, and the browser keeps following the
|
|
61408
|
+
// live anchor: a scroll would carry the arriving box along under a page that
|
|
61409
|
+
// does not move, and past the clip to the room between the bars, computed
|
|
61410
|
+
// where the boxes stood — and read once, before the opening waits for its
|
|
61411
|
+
// target (see liftPopupFromAnchor).
|
|
61364
61412
|
let releaseScrollHold = null;
|
|
61365
61413
|
|
|
61366
61414
|
/**
|
|
@@ -61386,11 +61434,20 @@ const liftPopupFromAnchor = (
|
|
|
61386
61434
|
releaseLiftInProgress?.();
|
|
61387
61435
|
|
|
61388
61436
|
const elementLeaving = opened ? resolveAnchor() : resolveLiftTarget(popupEl);
|
|
61389
|
-
//
|
|
61390
|
-
//
|
|
61437
|
+
// Everything read about the leaving side, before the first write. A read
|
|
61438
|
+
// brings the style up to date, and the writes below land on the root — an
|
|
61439
|
+
// attribute or an unregistered custom property there invalidates the
|
|
61440
|
+
// computed style of every element — so a read placed after any of them is
|
|
61441
|
+
// the whole document's style over again. Nothing on the leaving side moves
|
|
61442
|
+
// before the movement, the page being held from here on.
|
|
61443
|
+
releaseScrollHold = trapScrollInside(popupEl, { backdrop: true });
|
|
61391
61444
|
const duration = getComputedStyle(popupEl)
|
|
61392
61445
|
.getPropertyValue("--popup-animation-duration")
|
|
61393
61446
|
.trim();
|
|
61447
|
+
const cornersLeaving = readCorners(elementLeaving);
|
|
61448
|
+
const room = measureRoomBetweenBars();
|
|
61449
|
+
const boxLeaving = elementLeaving.getBoundingClientRect();
|
|
61450
|
+
const paintLeaving = opened ? null : readBoxPaint(elementLeaving);
|
|
61394
61451
|
const giveBackNameLeaving = wearLiftName(elementLeaving);
|
|
61395
61452
|
const root = document.documentElement;
|
|
61396
61453
|
root.setAttribute(ROOT_ATTRIBUTE, opened ? "opening" : "closing");
|
|
@@ -61401,11 +61458,10 @@ const liftPopupFromAnchor = (
|
|
|
61401
61458
|
// browser's own pace.
|
|
61402
61459
|
root.style.setProperty(DURATION_PROPERTY, duration);
|
|
61403
61460
|
}
|
|
61404
|
-
if (!opened) {
|
|
61405
|
-
publishBoxPaint(elementLeaving);
|
|
61406
|
-
}
|
|
61407
|
-
const cornersLeaving = readCorners(elementLeaving);
|
|
61408
61461
|
root.style.setProperty(BORDER_RADIUS_PROPERTY, cornersLeaving);
|
|
61462
|
+
if (paintLeaving) {
|
|
61463
|
+
publishBoxPaint(paintLeaving);
|
|
61464
|
+
}
|
|
61409
61465
|
|
|
61410
61466
|
let giveBackNameArriving = null;
|
|
61411
61467
|
let stopWaitingForTarget = null;
|
|
@@ -61437,10 +61493,6 @@ const liftPopupFromAnchor = (
|
|
|
61437
61493
|
releaseLiftInProgress = release;
|
|
61438
61494
|
|
|
61439
61495
|
const startMovement = (change, resolveElementArriving) => {
|
|
61440
|
-
releaseScrollHold?.();
|
|
61441
|
-
releaseScrollHold = trapScrollInside(popupEl, { backdrop: true });
|
|
61442
|
-
const room = measureRoomBetweenBars();
|
|
61443
|
-
const boxLeaving = elementLeaving.getBoundingClientRect();
|
|
61444
61496
|
let boxArriving = null;
|
|
61445
61497
|
let cornersArriving = null;
|
|
61446
61498
|
const viewTransition = startViewTransition(async () => {
|
|
@@ -61521,7 +61573,9 @@ const liftPopupFromAnchor = (
|
|
|
61521
61573
|
if (lift === "box") {
|
|
61522
61574
|
warnDrawingLiftedAsBox(target);
|
|
61523
61575
|
}
|
|
61524
|
-
|
|
61576
|
+
// The last write before the transition: nothing reads between it and the
|
|
61577
|
+
// style pass the browser makes on its own to take the first picture.
|
|
61578
|
+
publishBoxPaint(readBoxPaint(target));
|
|
61525
61579
|
startMovement(reveal, () => target);
|
|
61526
61580
|
};
|
|
61527
61581
|
const targetNow = findLiftTarget(popupEl);
|
|
@@ -61562,10 +61616,16 @@ const warnDrawingLiftedAsBox = (liftedElement) => {
|
|
|
61562
61616
|
}
|
|
61563
61617
|
};
|
|
61564
61618
|
|
|
61565
|
-
|
|
61619
|
+
// Read and published apart, so that a closing can read the paint with the
|
|
61620
|
+
// rest of what it reads and write it with the rest of what it writes.
|
|
61621
|
+
const readBoxPaint = (liftedElement) => {
|
|
61566
61622
|
const { backgroundColor, backgroundImage } = getComputedStyle(
|
|
61567
61623
|
findPaintedBox(liftedElement),
|
|
61568
61624
|
);
|
|
61625
|
+
return { backgroundColor, backgroundImage };
|
|
61626
|
+
};
|
|
61627
|
+
|
|
61628
|
+
const publishBoxPaint = ({ backgroundColor, backgroundImage }) => {
|
|
61569
61629
|
const root = document.documentElement;
|
|
61570
61630
|
root.style.setProperty(BACKGROUND_COLOR_PROPERTY, backgroundColor);
|
|
61571
61631
|
root.style.setProperty(BACKGROUND_IMAGE_PROPERTY, backgroundImage);
|