@jsenv/navi 0.16.2 → 0.16.4
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/jsenv_navi.js +72 -83
- package/dist/jsenv_navi.js.map +3 -3
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -7522,7 +7522,6 @@ setBaseUrl(
|
|
|
7522
7522
|
// Pattern registry for building relationships before routes are created
|
|
7523
7523
|
const patternRegistry = new Map(); // pattern -> patternData
|
|
7524
7524
|
const patternRelationships = new Map(); // pattern -> relationships
|
|
7525
|
-
let patternsRegistered = false;
|
|
7526
7525
|
|
|
7527
7526
|
// Function to detect signals in route patterns and connect them
|
|
7528
7527
|
const detectSignals = (routePattern) => {
|
|
@@ -8433,8 +8432,6 @@ const setupPatterns = (patternDefinitions) => {
|
|
|
8433
8432
|
originalPattern: currentPattern,
|
|
8434
8433
|
});
|
|
8435
8434
|
}
|
|
8436
|
-
|
|
8437
|
-
patternsRegistered = true;
|
|
8438
8435
|
};
|
|
8439
8436
|
|
|
8440
8437
|
/**
|
|
@@ -8444,25 +8441,12 @@ const getPatternData = (urlPatternRaw) => {
|
|
|
8444
8441
|
return patternRegistry.get(urlPatternRaw);
|
|
8445
8442
|
};
|
|
8446
8443
|
|
|
8447
|
-
/**
|
|
8448
|
-
* Get pattern relationships for route creation
|
|
8449
|
-
*/
|
|
8450
|
-
const getPatternRelationships = () => {
|
|
8451
|
-
if (!patternsRegistered) {
|
|
8452
|
-
throw new Error(
|
|
8453
|
-
"Patterns must be registered before accessing relationships",
|
|
8454
|
-
);
|
|
8455
|
-
}
|
|
8456
|
-
return patternRelationships;
|
|
8457
|
-
};
|
|
8458
|
-
|
|
8459
8444
|
/**
|
|
8460
8445
|
* Clear all registered patterns
|
|
8461
8446
|
*/
|
|
8462
8447
|
const clearPatterns = () => {
|
|
8463
8448
|
patternRegistry.clear();
|
|
8464
8449
|
patternRelationships.clear();
|
|
8465
|
-
patternsRegistered = false;
|
|
8466
8450
|
};
|
|
8467
8451
|
|
|
8468
8452
|
const resolveRouteUrl = (relativeUrl) => {
|
|
@@ -8487,6 +8471,22 @@ const resolveRouteUrl = (relativeUrl) => {
|
|
|
8487
8471
|
*/
|
|
8488
8472
|
|
|
8489
8473
|
|
|
8474
|
+
// Helper to check if one route pattern is a parent of another
|
|
8475
|
+
const isParentRoute = (parentPattern, childPattern) => {
|
|
8476
|
+
// Normalize patterns by removing query parts and trailing slashes
|
|
8477
|
+
const normalizePath = (pattern) => {
|
|
8478
|
+
const pathPart = pattern.split("?")[0];
|
|
8479
|
+
return pathPart.replace(/\/$/, "") || "/";
|
|
8480
|
+
};
|
|
8481
|
+
|
|
8482
|
+
const parentPath = normalizePath(parentPattern);
|
|
8483
|
+
const childPath = normalizePath(childPattern);
|
|
8484
|
+
|
|
8485
|
+
// Parent route is a parent if child path starts with parent path
|
|
8486
|
+
// and child has additional segments
|
|
8487
|
+
return childPath.startsWith(parentPath) && childPath !== parentPath;
|
|
8488
|
+
};
|
|
8489
|
+
|
|
8490
8490
|
// Controls what happens to actions when their route stops matching:
|
|
8491
8491
|
// 'abort' - Cancel the action immediately when route stops matching
|
|
8492
8492
|
// 'keep-loading' - Allow action to continue running after route stops matching
|
|
@@ -8679,41 +8679,6 @@ const getRoutePrivateProperties = (route) => {
|
|
|
8679
8679
|
return routePrivatePropertiesMap.get(route);
|
|
8680
8680
|
};
|
|
8681
8681
|
|
|
8682
|
-
/**
|
|
8683
|
-
* Get child routes of a given route
|
|
8684
|
-
*/
|
|
8685
|
-
const getRouteChildren = (route) => {
|
|
8686
|
-
const children = [];
|
|
8687
|
-
const routePrivateProperties = getRoutePrivateProperties(route);
|
|
8688
|
-
if (!routePrivateProperties) {
|
|
8689
|
-
return children;
|
|
8690
|
-
}
|
|
8691
|
-
|
|
8692
|
-
const { originalPattern } = routePrivateProperties;
|
|
8693
|
-
const relationships = getPatternRelationships();
|
|
8694
|
-
const relationshipData = relationships.get(originalPattern);
|
|
8695
|
-
|
|
8696
|
-
if (!relationshipData || !relationshipData.children) {
|
|
8697
|
-
return children;
|
|
8698
|
-
}
|
|
8699
|
-
|
|
8700
|
-
// Find child routes
|
|
8701
|
-
for (const childPattern of relationshipData.children) {
|
|
8702
|
-
for (const otherRoute of routeSet) {
|
|
8703
|
-
const otherRoutePrivateProperties = getRoutePrivateProperties(otherRoute);
|
|
8704
|
-
if (
|
|
8705
|
-
otherRoutePrivateProperties &&
|
|
8706
|
-
otherRoutePrivateProperties.originalPattern === childPattern
|
|
8707
|
-
) {
|
|
8708
|
-
children.push(otherRoute);
|
|
8709
|
-
break;
|
|
8710
|
-
}
|
|
8711
|
-
}
|
|
8712
|
-
}
|
|
8713
|
-
|
|
8714
|
-
return children;
|
|
8715
|
-
};
|
|
8716
|
-
|
|
8717
8682
|
const registerRoute = (routePattern) => {
|
|
8718
8683
|
const urlPatternRaw = routePattern.originalPattern;
|
|
8719
8684
|
const patternData = getPatternData(urlPatternRaw);
|
|
@@ -8807,21 +8772,35 @@ const registerRoute = (routePattern) => {
|
|
|
8807
8772
|
);
|
|
8808
8773
|
}
|
|
8809
8774
|
|
|
8810
|
-
// URL -> Signal synchronization
|
|
8775
|
+
// URL -> Signal synchronization with parent-child route hierarchy checking
|
|
8811
8776
|
effect(() => {
|
|
8812
8777
|
const matching = matchingSignal.value;
|
|
8813
8778
|
const params = rawParamsSignal.value;
|
|
8814
8779
|
const urlParamValue = params[paramName];
|
|
8815
8780
|
|
|
8816
|
-
if (
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8781
|
+
if (matching) {
|
|
8782
|
+
// When route matches, sync signal with URL parameter value
|
|
8783
|
+
// This ensures URL is the source of truth
|
|
8784
|
+
stateSignal.value = urlParamValue;
|
|
8785
|
+
} else {
|
|
8786
|
+
// When route doesn't match, check if we're navigating to a parent route
|
|
8787
|
+
const currentRoutePattern = routePattern.cleanPattern;
|
|
8788
|
+
const parentRouteMatching = Array.from(routeSet).find((otherRoute) => {
|
|
8789
|
+
if (otherRoute === route || !otherRoute.matching) return false;
|
|
8790
|
+
|
|
8791
|
+
const otherRouteProperties = getRoutePrivateProperties(otherRoute);
|
|
8792
|
+
const otherPattern = otherRouteProperties.routePattern.cleanPattern;
|
|
8793
|
+
|
|
8794
|
+
// Check if the other route is a parent of this route
|
|
8795
|
+
return isParentRoute(otherPattern, currentRoutePattern);
|
|
8796
|
+
});
|
|
8797
|
+
|
|
8798
|
+
if (parentRouteMatching) {
|
|
8799
|
+
// We're navigating to a parent route - clear this signal to reflect the hierarchy
|
|
8800
|
+
const defaultValue = routePattern.parameterDefaults?.[paramName];
|
|
8801
|
+
stateSignal.value = defaultValue;
|
|
8802
|
+
}
|
|
8823
8803
|
}
|
|
8824
|
-
stateSignal.value = urlParamValue;
|
|
8825
8804
|
});
|
|
8826
8805
|
|
|
8827
8806
|
// Signal -> URL synchronization
|
|
@@ -8866,38 +8845,48 @@ const registerRoute = (routePattern) => {
|
|
|
8866
8845
|
return null;
|
|
8867
8846
|
}
|
|
8868
8847
|
|
|
8869
|
-
//
|
|
8870
|
-
|
|
8871
|
-
let mostSpecificRoute;
|
|
8848
|
+
// Find all matching routes and update their actions, then delegate to most specific
|
|
8849
|
+
const allMatchingRoutes = Array.from(routeSet).filter((r) => r.matching);
|
|
8872
8850
|
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
const currentRoutePrivateProperties =
|
|
8883
|
-
getRoutePrivateProperties(currentRoute);
|
|
8884
|
-
if (currentRoutePrivateProperties) {
|
|
8885
|
-
const { routePattern: currentRoutePattern } =
|
|
8886
|
-
currentRoutePrivateProperties;
|
|
8887
|
-
const currentResolvedParams = currentRoutePattern.resolveParams();
|
|
8851
|
+
// Update action params on all matching routes
|
|
8852
|
+
for (const matchingRoute of allMatchingRoutes) {
|
|
8853
|
+
if (matchingRoute.action) {
|
|
8854
|
+
const matchingRoutePrivateProperties =
|
|
8855
|
+
getRoutePrivateProperties(matchingRoute);
|
|
8856
|
+
if (matchingRoutePrivateProperties) {
|
|
8857
|
+
const { routePattern: matchingRoutePattern } =
|
|
8858
|
+
matchingRoutePrivateProperties;
|
|
8859
|
+
const currentResolvedParams = matchingRoutePattern.resolveParams();
|
|
8888
8860
|
const updatedActionParams = {
|
|
8889
8861
|
...currentResolvedParams,
|
|
8890
8862
|
...newParams,
|
|
8891
8863
|
};
|
|
8892
|
-
|
|
8864
|
+
matchingRoute.action.replaceParams(updatedActionParams);
|
|
8893
8865
|
}
|
|
8894
8866
|
}
|
|
8867
|
+
}
|
|
8895
8868
|
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8869
|
+
// Find the most specific route (the one with the longest pattern path)
|
|
8870
|
+
let mostSpecificRoute = route;
|
|
8871
|
+
let maxSegments = route.pattern.split("/").filter((s) => s !== "").length;
|
|
8872
|
+
|
|
8873
|
+
for (const matchingRoute of allMatchingRoutes) {
|
|
8874
|
+
const segments = matchingRoute.pattern
|
|
8875
|
+
.split("/")
|
|
8876
|
+
.filter((s) => s !== "").length;
|
|
8877
|
+
if (segments > maxSegments) {
|
|
8878
|
+
maxSegments = segments;
|
|
8879
|
+
mostSpecificRoute = matchingRoute;
|
|
8880
|
+
}
|
|
8899
8881
|
}
|
|
8900
|
-
|
|
8882
|
+
|
|
8883
|
+
// If we found a more specific route, delegate to it; otherwise handle it ourselves
|
|
8884
|
+
if (mostSpecificRoute !== route) {
|
|
8885
|
+
return mostSpecificRoute.redirectTo(newParams);
|
|
8886
|
+
}
|
|
8887
|
+
|
|
8888
|
+
// This route is the most specific, handle the redirect ourselves
|
|
8889
|
+
return route.redirectTo(newParams);
|
|
8901
8890
|
};
|
|
8902
8891
|
route.buildRelativeUrl = (params) => {
|
|
8903
8892
|
// buildMostPreciseUrl now handles parameter resolution internally
|