@jsenv/navi 0.16.0 → 0.16.1
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 +100 -0
- package/dist/jsenv_navi.js.map +4 -4
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -7793,6 +7793,41 @@ const createRoutePattern = (pattern) => {
|
|
|
7793
7793
|
}
|
|
7794
7794
|
}
|
|
7795
7795
|
|
|
7796
|
+
// PARENT PARAMETER INHERITANCE: Inherit query parameters from parent patterns
|
|
7797
|
+
// This allows child routes like "/map/isochrone" to inherit "zoom=15" from parent "/map/?zoom=..."
|
|
7798
|
+
const parentPatterns = relationships?.parentPatterns || [];
|
|
7799
|
+
for (const parentPattern of parentPatterns) {
|
|
7800
|
+
const parentPatternData = getPatternData(parentPattern);
|
|
7801
|
+
if (!parentPatternData) continue;
|
|
7802
|
+
|
|
7803
|
+
// Check parent's signal connections for non-default values to inherit
|
|
7804
|
+
for (const parentConnection of parentPatternData.connections) {
|
|
7805
|
+
const { paramName, signal, options } = parentConnection;
|
|
7806
|
+
const defaultValue = options.defaultValue;
|
|
7807
|
+
|
|
7808
|
+
// If we don't already have this parameter and parent signal has non-default value
|
|
7809
|
+
if (
|
|
7810
|
+
!(paramName in finalParams) &&
|
|
7811
|
+
signal?.value !== undefined &&
|
|
7812
|
+
signal.value !== defaultValue
|
|
7813
|
+
) {
|
|
7814
|
+
// Check if this parameter corresponds to a literal segment in our path
|
|
7815
|
+
// E.g., don't inherit "section=analytics" if our path is "/admin/analytics"
|
|
7816
|
+
const shouldInherit = !isParameterRedundantWithLiteralSegments(
|
|
7817
|
+
parsedPattern,
|
|
7818
|
+
parentPatternData.parsedPattern,
|
|
7819
|
+
paramName,
|
|
7820
|
+
signal.value,
|
|
7821
|
+
);
|
|
7822
|
+
|
|
7823
|
+
if (shouldInherit) {
|
|
7824
|
+
// Inherit the parent's signal value
|
|
7825
|
+
finalParams[paramName] = signal.value;
|
|
7826
|
+
}
|
|
7827
|
+
}
|
|
7828
|
+
}
|
|
7829
|
+
}
|
|
7830
|
+
|
|
7796
7831
|
if (!parsedPattern.segments) {
|
|
7797
7832
|
return "/";
|
|
7798
7833
|
}
|
|
@@ -8157,6 +8192,27 @@ const buildUrlFromPattern = (parsedPattern, params = {}) => {
|
|
|
8157
8192
|
path = path.slice(0, -1);
|
|
8158
8193
|
}
|
|
8159
8194
|
|
|
8195
|
+
// Check if we'll have query parameters to decide on trailing slash removal
|
|
8196
|
+
const willHaveQueryParams =
|
|
8197
|
+
parsedPattern.queryParams?.some((qp) => {
|
|
8198
|
+
const value = params[qp.name];
|
|
8199
|
+
return value !== undefined;
|
|
8200
|
+
}) ||
|
|
8201
|
+
Object.entries(params).some(([key, value]) => {
|
|
8202
|
+
const isPathParam = parsedPattern.segments.some(
|
|
8203
|
+
(s) => s.type === "param" && s.name === key,
|
|
8204
|
+
);
|
|
8205
|
+
const isQueryParam = parsedPattern.queryParams?.some(
|
|
8206
|
+
(qp) => qp.name === key,
|
|
8207
|
+
);
|
|
8208
|
+
return value !== undefined && !isPathParam && !isQueryParam;
|
|
8209
|
+
});
|
|
8210
|
+
|
|
8211
|
+
// Remove trailing slash when we have query params for prettier URLs
|
|
8212
|
+
if (willHaveQueryParams && path.endsWith("/") && path !== "/") {
|
|
8213
|
+
path = path.slice(0, -1);
|
|
8214
|
+
}
|
|
8215
|
+
|
|
8160
8216
|
// Add search parameters
|
|
8161
8217
|
const pathParamNames = new Set(
|
|
8162
8218
|
parsedPattern.segments.filter((s) => s.type === "param").map((s) => s.name),
|
|
@@ -8255,6 +8311,43 @@ const isChildPattern = (childPattern, parentPattern) => {
|
|
|
8255
8311
|
return childSegments.length > parentSegments.length || hasMoreSpecificSegment;
|
|
8256
8312
|
};
|
|
8257
8313
|
|
|
8314
|
+
/**
|
|
8315
|
+
* Check if a parameter is redundant because the child pattern already has it as a literal segment
|
|
8316
|
+
* E.g., parameter "section" is redundant for pattern "/admin/settings/:tab" because "settings" is literal
|
|
8317
|
+
*/
|
|
8318
|
+
const isParameterRedundantWithLiteralSegments = (
|
|
8319
|
+
childPattern,
|
|
8320
|
+
parentPattern,
|
|
8321
|
+
paramName,
|
|
8322
|
+
) => {
|
|
8323
|
+
// Find which segment position corresponds to this parameter in the parent
|
|
8324
|
+
let paramSegmentIndex = -1;
|
|
8325
|
+
for (let i = 0; i < parentPattern.segments.length; i++) {
|
|
8326
|
+
const segment = parentPattern.segments[i];
|
|
8327
|
+
if (segment.type === "param" && segment.name === paramName) {
|
|
8328
|
+
paramSegmentIndex = i;
|
|
8329
|
+
break;
|
|
8330
|
+
}
|
|
8331
|
+
}
|
|
8332
|
+
|
|
8333
|
+
// If parameter not found in parent segments, it's not redundant with path
|
|
8334
|
+
if (paramSegmentIndex === -1) {
|
|
8335
|
+
return false;
|
|
8336
|
+
}
|
|
8337
|
+
|
|
8338
|
+
// Check if child has a literal segment at the same position
|
|
8339
|
+
if (childPattern.segments.length > paramSegmentIndex) {
|
|
8340
|
+
const childSegment = childPattern.segments[paramSegmentIndex];
|
|
8341
|
+
if (childSegment.type === "literal") {
|
|
8342
|
+
// Child has a literal segment where parent has parameter
|
|
8343
|
+
// This means the child is more specific and shouldn't inherit this parameter
|
|
8344
|
+
return true; // Redundant - child already specifies this position with a literal
|
|
8345
|
+
}
|
|
8346
|
+
}
|
|
8347
|
+
|
|
8348
|
+
return false;
|
|
8349
|
+
};
|
|
8350
|
+
|
|
8258
8351
|
/**
|
|
8259
8352
|
* Register all patterns at once and build their relationships
|
|
8260
8353
|
*/
|
|
@@ -8626,6 +8719,13 @@ const registerRoute = (routePattern) => {
|
|
|
8626
8719
|
for (const { signal: stateSignal, paramName, options = {} } of connections) {
|
|
8627
8720
|
const { debug } = options;
|
|
8628
8721
|
|
|
8722
|
+
if (debug) {
|
|
8723
|
+
console.debug(
|
|
8724
|
+
`[route] connecting param "${paramName}" to signal`,
|
|
8725
|
+
stateSignal,
|
|
8726
|
+
);
|
|
8727
|
+
}
|
|
8728
|
+
|
|
8629
8729
|
// URL -> Signal synchronization
|
|
8630
8730
|
effect(() => {
|
|
8631
8731
|
const matching = matchingSignal.value;
|