@jsenv/navi 0.29.508 → 0.29.509
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 +65 -43
- package/dist/dev/jsenv_navi.js.map +3 -3
- package/dist/jsenv_navi.js +65 -43
- package/dist/jsenv_navi.js.map +3 -3
- package/docs/navigation.md +9 -6
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -8553,7 +8553,7 @@ const route = (pattern, options = {}) => {
|
|
|
8553
8553
|
};
|
|
8554
8554
|
route.redirectTo = (
|
|
8555
8555
|
params,
|
|
8556
|
-
{ callReason, history = "replace", debounceUrl } = {},
|
|
8556
|
+
{ callReason, history = "replace", debounceUrl, isSignalChange } = {},
|
|
8557
8557
|
) => {
|
|
8558
8558
|
if (!integration) {
|
|
8559
8559
|
return Promise.resolve();
|
|
@@ -8563,6 +8563,7 @@ const route = (pattern, options = {}) => {
|
|
|
8563
8563
|
replace: history !== "push",
|
|
8564
8564
|
debounce: debounceUrl,
|
|
8565
8565
|
callReason,
|
|
8566
|
+
fromSignal: isSignalChange,
|
|
8566
8567
|
});
|
|
8567
8568
|
};
|
|
8568
8569
|
route.replaceParams = (
|
|
@@ -8577,52 +8578,18 @@ const route = (pattern, options = {}) => {
|
|
|
8577
8578
|
return null;
|
|
8578
8579
|
}
|
|
8579
8580
|
|
|
8580
|
-
|
|
8581
|
-
let mostSpecificRoute = route;
|
|
8582
|
-
const routePrivateProperties = getRoutePrivateProperties(route);
|
|
8583
|
-
let maxDepth = routePrivateProperties.routePattern.depth;
|
|
8584
|
-
for (const routeCandidate of routeSet) {
|
|
8585
|
-
if (routeCandidate === route) {
|
|
8586
|
-
continue;
|
|
8587
|
-
}
|
|
8588
|
-
if (!routeCandidate.matching) {
|
|
8589
|
-
continue;
|
|
8590
|
-
}
|
|
8591
|
-
const matchingRoute = routeCandidate;
|
|
8592
|
-
const matchingRoutePrivateProperties =
|
|
8593
|
-
getRoutePrivateProperties(matchingRoute);
|
|
8594
|
-
const depth = matchingRoutePrivateProperties.routePattern.depth;
|
|
8595
|
-
if (depth > maxDepth) {
|
|
8596
|
-
maxDepth = depth;
|
|
8597
|
-
mostSpecificRoute = matchingRoute;
|
|
8598
|
-
}
|
|
8599
|
-
}
|
|
8581
|
+
const mostSpecificRoute = findMostSpecificMatchingRoute(route, routeSet);
|
|
8600
8582
|
const isMostSpecificRoute = mostSpecificRoute === route;
|
|
8601
8583
|
|
|
8602
|
-
// If we found a more specific route, delegate to it; otherwise handle it ourselves
|
|
8584
|
+
// If we found a more specific route, delegate to it; otherwise handle it ourselves.
|
|
8585
|
+
// A signal change reaches this only when the more specific route does not
|
|
8586
|
+
// carry the param (see writeValueInUrl): left to it, the change would be dropped.
|
|
8603
8587
|
if (!isMostSpecificRoute) {
|
|
8604
|
-
// For signal-originated calls, only skip delegation if the more specific route
|
|
8605
|
-
// has its own signal connection for the same params — meaning its own effect will
|
|
8606
|
-
// fire and handle the redirect. If it doesn't have the connection, the signal
|
|
8607
|
-
// change would be silently dropped, so we must delegate anyway.
|
|
8608
|
-
if (isSignalChange) {
|
|
8609
|
-
const mostSpecificRoutePrivateProperties =
|
|
8610
|
-
getRoutePrivateProperties(mostSpecificRoute);
|
|
8611
|
-
const { pathConnectionMap, queryConnectionMap } =
|
|
8612
|
-
mostSpecificRoutePrivateProperties.routePattern;
|
|
8613
|
-
const willHandleItself = Object.keys(newParams).every(
|
|
8614
|
-
(paramName) =>
|
|
8615
|
-
pathConnectionMap.has(paramName) ||
|
|
8616
|
-
queryConnectionMap.has(paramName),
|
|
8617
|
-
);
|
|
8618
|
-
if (willHandleItself) {
|
|
8619
|
-
return null;
|
|
8620
|
-
}
|
|
8621
|
-
}
|
|
8622
8588
|
return mostSpecificRoute.redirectTo(newParams, {
|
|
8623
8589
|
callReason: `replaceParams delegation from ${route} to ${mostSpecificRoute} (original reason: ${callReason})`,
|
|
8624
8590
|
history,
|
|
8625
8591
|
debounceUrl,
|
|
8592
|
+
isSignalChange,
|
|
8626
8593
|
});
|
|
8627
8594
|
}
|
|
8628
8595
|
|
|
@@ -8641,6 +8608,7 @@ const route = (pattern, options = {}) => {
|
|
|
8641
8608
|
replace: history !== "push",
|
|
8642
8609
|
debounce: debounceUrl,
|
|
8643
8610
|
callReason,
|
|
8611
|
+
fromSignal: isSignalChange,
|
|
8644
8612
|
});
|
|
8645
8613
|
};
|
|
8646
8614
|
route.matchesParams = (providedParams) => {
|
|
@@ -8703,7 +8671,7 @@ const route = (pattern, options = {}) => {
|
|
|
8703
8671
|
});
|
|
8704
8672
|
// Signal -> URL sync: When signal changes, update URL to reflect meaningful state
|
|
8705
8673
|
// Only sync non-default values to keep URLs clean (static fallbacks stay invisible)
|
|
8706
|
-
registerSetup(() => {
|
|
8674
|
+
registerSetup(({ routeSet }) => {
|
|
8707
8675
|
const cleanupSignalUrlEffectSet = new Set();
|
|
8708
8676
|
// important: read connections at setup time so it includes query connections
|
|
8709
8677
|
// inherited from ancestor patterns
|
|
@@ -8742,6 +8710,24 @@ const route = (pattern, options = {}) => {
|
|
|
8742
8710
|
// Route not matching, no URL sync needed
|
|
8743
8711
|
return;
|
|
8744
8712
|
}
|
|
8713
|
+
// A param declared on an ancestor is carried by every route below it,
|
|
8714
|
+
// each with its own connection: all of them hear the write, the most
|
|
8715
|
+
// specific one makes it. The others step aside before the history is
|
|
8716
|
+
// read — a stateSignalGroup's push goes to the first write reading it.
|
|
8717
|
+
const mostSpecificRoute = findMostSpecificMatchingRoute(
|
|
8718
|
+
route,
|
|
8719
|
+
routeSet,
|
|
8720
|
+
);
|
|
8721
|
+
if (mostSpecificRoute !== route) {
|
|
8722
|
+
const { pathConnectionMap, queryConnectionMap } =
|
|
8723
|
+
getRoutePrivateProperties(mostSpecificRoute).routePattern;
|
|
8724
|
+
if (
|
|
8725
|
+
pathConnectionMap.has(paramName) ||
|
|
8726
|
+
queryConnectionMap.has(paramName)
|
|
8727
|
+
) {
|
|
8728
|
+
return;
|
|
8729
|
+
}
|
|
8730
|
+
}
|
|
8745
8731
|
if (urlParamValue === undefined) {
|
|
8746
8732
|
// No URL parameter exists - check if signal has meaningful value to add
|
|
8747
8733
|
if (connection.isDefaultValue(value)) {
|
|
@@ -9515,6 +9501,27 @@ const urlWithoutSearchAndHash = (url) => {
|
|
|
9515
9501
|
return `${urlObject.origin}${urlObject.pathname}`;
|
|
9516
9502
|
};
|
|
9517
9503
|
|
|
9504
|
+
// Deeper is more specific: among the routes matching the address, the one a
|
|
9505
|
+
// params write lands on.
|
|
9506
|
+
const findMostSpecificMatchingRoute = (route, routeSet) => {
|
|
9507
|
+
let mostSpecificRoute = route;
|
|
9508
|
+
let maxDepth = getRoutePrivateProperties(route).routePattern.depth;
|
|
9509
|
+
for (const routeCandidate of routeSet) {
|
|
9510
|
+
if (routeCandidate === route) {
|
|
9511
|
+
continue;
|
|
9512
|
+
}
|
|
9513
|
+
if (!routeCandidate.matching) {
|
|
9514
|
+
continue;
|
|
9515
|
+
}
|
|
9516
|
+
const depth = getRoutePrivateProperties(routeCandidate).routePattern.depth;
|
|
9517
|
+
if (depth > maxDepth) {
|
|
9518
|
+
maxDepth = depth;
|
|
9519
|
+
mostSpecificRoute = routeCandidate;
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
return mostSpecificRoute;
|
|
9523
|
+
};
|
|
9524
|
+
|
|
9518
9525
|
// Every route action, with whether it asks something of the address at the
|
|
9519
9526
|
// moment: its route matches and its params getter returns something.
|
|
9520
9527
|
const routeActionEntriesSignal = signal([]);
|
|
@@ -13890,11 +13897,15 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
13890
13897
|
// browser answers — a before/after cycle here would be about a navigation
|
|
13891
13898
|
// that never happens. A push with something of its own for its entry — a
|
|
13892
13899
|
// state, what the press handed over (see carryByLinkNavigation) — is a
|
|
13893
|
-
// new entry, never one standing there already.
|
|
13900
|
+
// new entry, never one standing there already. So is a push a signal write
|
|
13901
|
+
// makes: the writes after it in the same move (a layer, then what is open
|
|
13902
|
+
// inside it) build on its address at once, and a traversal would only land
|
|
13903
|
+
// after they went to the entry being left.
|
|
13894
13904
|
if (
|
|
13895
13905
|
options.navigationType === "push" &&
|
|
13896
13906
|
options.state === undefined &&
|
|
13897
13907
|
!options.pressWrites &&
|
|
13908
|
+
!options.fromSignal &&
|
|
13898
13909
|
url !== readAddress()
|
|
13899
13910
|
) {
|
|
13900
13911
|
const delta = adjacentEntryDelta(url);
|
|
@@ -14317,12 +14328,23 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
14317
14328
|
|
|
14318
14329
|
const navTo = async (
|
|
14319
14330
|
url,
|
|
14320
|
-
{
|
|
14331
|
+
{
|
|
14332
|
+
replace,
|
|
14333
|
+
state,
|
|
14334
|
+
routeTransition,
|
|
14335
|
+
debounce,
|
|
14336
|
+
asReturn,
|
|
14337
|
+
open,
|
|
14338
|
+
fromSignal,
|
|
14339
|
+
} = {},
|
|
14321
14340
|
) => {
|
|
14322
14341
|
const routingOptions = {
|
|
14323
14342
|
reason: `navTo called with "${url}"`,
|
|
14324
14343
|
navigationType: replace ? "replace" : "push",
|
|
14325
14344
|
state,
|
|
14345
|
+
// Made by a signal written into the url (see route.js writeValueInUrl):
|
|
14346
|
+
// such a push is never turned into a traversal (see handleRoutingTask).
|
|
14347
|
+
fromSignal,
|
|
14326
14348
|
// A push that lands where its address was last left (see
|
|
14327
14349
|
// link_return.js).
|
|
14328
14350
|
asReturn,
|