@jsenv/navi 0.16.26 → 0.16.27
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 +63 -40
- package/dist/jsenv_navi.js.map +4 -4
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -2664,6 +2664,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
2664
2664
|
getDefaultValue,
|
|
2665
2665
|
defaultValue: staticDefaultValue,
|
|
2666
2666
|
dynamicDefaultSignal,
|
|
2667
|
+
isCustomValue,
|
|
2667
2668
|
type,
|
|
2668
2669
|
persists,
|
|
2669
2670
|
localStorageKey,
|
|
@@ -7847,21 +7848,26 @@ const createRoutePattern = (pattern) => {
|
|
|
7847
7848
|
|
|
7848
7849
|
/**
|
|
7849
7850
|
* Helper: Filter out default values from parameters for cleaner URLs
|
|
7851
|
+
*
|
|
7852
|
+
* This function removes parameters that match their default values (static or dynamic)
|
|
7853
|
+
* while preserving custom values and inherited parameters from ancestor routes.
|
|
7854
|
+
* Parameter inheritance from parent routes is intentional - only default values
|
|
7855
|
+
* for the current route's own parameters are filtered out.
|
|
7850
7856
|
*/
|
|
7851
7857
|
const removeDefaultValues = (params) => {
|
|
7852
7858
|
const filtered = { ...params };
|
|
7853
7859
|
|
|
7854
7860
|
for (const connection of connections) {
|
|
7855
|
-
const { paramName, signal } = connection;
|
|
7856
|
-
const defaultValue = parameterDefaults.get(paramName);
|
|
7861
|
+
const { paramName, signal, options } = connection;
|
|
7857
7862
|
|
|
7858
|
-
if (paramName in filtered
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
) {
|
|
7863
|
+
if (paramName in filtered) {
|
|
7864
|
+
// Parameter is explicitly provided - check if we should remove it
|
|
7865
|
+
if (!options.isCustomValue?.(filtered[paramName])) {
|
|
7866
|
+
// Parameter value is not custom (matches default) - remove it
|
|
7867
|
+
delete filtered[paramName];
|
|
7868
|
+
}
|
|
7869
|
+
} else if (options.isCustomValue?.(signal.value)) {
|
|
7870
|
+
// Parameter not provided but signal has custom value - add it
|
|
7865
7871
|
filtered[paramName] = signal.value;
|
|
7866
7872
|
}
|
|
7867
7873
|
}
|
|
@@ -7880,7 +7886,7 @@ const createRoutePattern = (pattern) => {
|
|
|
7880
7886
|
const effectiveValue = userValue !== undefined ? userValue : signalValue;
|
|
7881
7887
|
return (
|
|
7882
7888
|
effectiveValue === literalValue &&
|
|
7883
|
-
|
|
7889
|
+
conn.options.isCustomValue?.(effectiveValue)
|
|
7884
7890
|
);
|
|
7885
7891
|
});
|
|
7886
7892
|
|
|
@@ -7918,7 +7924,7 @@ const createRoutePattern = (pattern) => {
|
|
|
7918
7924
|
const signalValue = conn.signal?.value;
|
|
7919
7925
|
return (
|
|
7920
7926
|
signalValue === literalValue &&
|
|
7921
|
-
|
|
7927
|
+
conn.options.isCustomValue?.(signalValue)
|
|
7922
7928
|
);
|
|
7923
7929
|
});
|
|
7924
7930
|
|
|
@@ -8061,10 +8067,10 @@ const createRoutePattern = (pattern) => {
|
|
|
8061
8067
|
} else {
|
|
8062
8068
|
const { paramName: name, signal, options } = item;
|
|
8063
8069
|
paramName = name;
|
|
8064
|
-
// Only include
|
|
8070
|
+
// Only include custom parent signal values (not using defaults)
|
|
8065
8071
|
if (
|
|
8066
8072
|
signal?.value === undefined ||
|
|
8067
|
-
signal.value
|
|
8073
|
+
!options.isCustomValue?.(signal.value)
|
|
8068
8074
|
) {
|
|
8069
8075
|
return { isCompatible: true, shouldInclude: false };
|
|
8070
8076
|
}
|
|
@@ -8214,7 +8220,6 @@ const createRoutePattern = (pattern) => {
|
|
|
8214
8220
|
|
|
8215
8221
|
for (const connection of childPatternObj.connections) {
|
|
8216
8222
|
const { paramName, signal, options } = connection;
|
|
8217
|
-
const defaultValue = options.defaultValue;
|
|
8218
8223
|
|
|
8219
8224
|
// Check if parameter was explicitly provided by user
|
|
8220
8225
|
const hasExplicitParam = paramName in params;
|
|
@@ -8223,13 +8228,16 @@ const createRoutePattern = (pattern) => {
|
|
|
8223
8228
|
if (hasExplicitParam) {
|
|
8224
8229
|
// User explicitly provided this parameter - use their value
|
|
8225
8230
|
childParams[paramName] = explicitValue;
|
|
8226
|
-
if (
|
|
8231
|
+
if (
|
|
8232
|
+
explicitValue !== undefined &&
|
|
8233
|
+
options.isCustomValue?.(explicitValue)
|
|
8234
|
+
) {
|
|
8227
8235
|
hasActiveParams = true;
|
|
8228
8236
|
}
|
|
8229
8237
|
} else if (signal?.value !== undefined) {
|
|
8230
8238
|
// No explicit override - use signal value
|
|
8231
8239
|
childParams[paramName] = signal.value;
|
|
8232
|
-
if (signal.value
|
|
8240
|
+
if (options.isCustomValue?.(signal.value)) {
|
|
8233
8241
|
hasActiveParams = true;
|
|
8234
8242
|
}
|
|
8235
8243
|
}
|
|
@@ -8309,7 +8317,7 @@ const createRoutePattern = (pattern) => {
|
|
|
8309
8317
|
// Check if parameters that determine child selection are non-default
|
|
8310
8318
|
// OR if any descendant parameters indicate explicit navigation
|
|
8311
8319
|
for (const connection of connections) {
|
|
8312
|
-
const { paramName } = connection;
|
|
8320
|
+
const { paramName, options } = connection;
|
|
8313
8321
|
const defaultValue = parameterDefaults.get(paramName);
|
|
8314
8322
|
const resolvedValue = resolvedParams[paramName];
|
|
8315
8323
|
const userProvidedParam = paramName in params;
|
|
@@ -8318,9 +8326,10 @@ const createRoutePattern = (pattern) => {
|
|
|
8318
8326
|
// This literal corresponds to a parameter in the parent
|
|
8319
8327
|
if (
|
|
8320
8328
|
userProvidedParam ||
|
|
8321
|
-
(resolvedValue !== undefined &&
|
|
8329
|
+
(resolvedValue !== undefined &&
|
|
8330
|
+
options.isCustomValue?.(resolvedValue))
|
|
8322
8331
|
) {
|
|
8323
|
-
// Parameter was explicitly provided or has
|
|
8332
|
+
// Parameter was explicitly provided or has custom value - child is needed
|
|
8324
8333
|
childSpecificParamsAreDefaults = false;
|
|
8325
8334
|
break;
|
|
8326
8335
|
}
|
|
@@ -8421,7 +8430,7 @@ const createRoutePattern = (pattern) => {
|
|
|
8421
8430
|
// If explicitly undefined, don't include it (which means don't use child route)
|
|
8422
8431
|
} else if (
|
|
8423
8432
|
signal?.value !== undefined &&
|
|
8424
|
-
signal.value
|
|
8433
|
+
options.isCustomValue?.(signal.value)
|
|
8425
8434
|
) {
|
|
8426
8435
|
// No explicit override - use signal value if non-default
|
|
8427
8436
|
baseParams[paramName] = signal.value;
|
|
@@ -8439,7 +8448,6 @@ const createRoutePattern = (pattern) => {
|
|
|
8439
8448
|
// Add parent's signal parameters
|
|
8440
8449
|
for (const connection of parentPatternObj.connections) {
|
|
8441
8450
|
const { paramName, signal, options } = connection;
|
|
8442
|
-
const defaultValue = options.defaultValue;
|
|
8443
8451
|
|
|
8444
8452
|
// Skip if child route already handles this parameter
|
|
8445
8453
|
const childConnection = childPatternObj.connections.find(
|
|
@@ -8454,8 +8462,11 @@ const createRoutePattern = (pattern) => {
|
|
|
8454
8462
|
continue; // Already have this parameter
|
|
8455
8463
|
}
|
|
8456
8464
|
|
|
8457
|
-
// Only include
|
|
8458
|
-
if (
|
|
8465
|
+
// Only include custom signal values (not using defaults)
|
|
8466
|
+
if (
|
|
8467
|
+
signal?.value !== undefined &&
|
|
8468
|
+
options.isCustomValue?.(signal.value)
|
|
8469
|
+
) {
|
|
8459
8470
|
// Skip if parameter is consumed by child's literal path segments
|
|
8460
8471
|
const isConsumedByChildPath = childPatternObj.pattern.segments.some(
|
|
8461
8472
|
(segment) =>
|
|
@@ -8521,10 +8532,9 @@ const createRoutePattern = (pattern) => {
|
|
|
8521
8532
|
|
|
8522
8533
|
if (childConnection) {
|
|
8523
8534
|
const { options } = childConnection;
|
|
8524
|
-
const defaultValue = options.defaultValue;
|
|
8525
8535
|
|
|
8526
|
-
// Only include if it's
|
|
8527
|
-
if (userValue
|
|
8536
|
+
// Only include if it's a custom value (not default)
|
|
8537
|
+
if (options.isCustomValue?.(userValue)) {
|
|
8528
8538
|
baseParams[paramName] = userValue;
|
|
8529
8539
|
} else {
|
|
8530
8540
|
// User provided the default value - complete omission
|
|
@@ -8584,7 +8594,7 @@ const createRoutePattern = (pattern) => {
|
|
|
8584
8594
|
const hasNonDefaultChildParams = (childPatternObj.connections || []).some(
|
|
8585
8595
|
(childConnection) => {
|
|
8586
8596
|
const { signal, options } = childConnection;
|
|
8587
|
-
return signal?.value
|
|
8597
|
+
return options.isCustomValue?.(signal?.value);
|
|
8588
8598
|
},
|
|
8589
8599
|
);
|
|
8590
8600
|
|
|
@@ -8794,13 +8804,15 @@ const createRoutePattern = (pattern) => {
|
|
|
8794
8804
|
// 2. The source route has only query parameters that are non-default
|
|
8795
8805
|
const hasNonDefaultPathParams = connections.some((connection) => {
|
|
8796
8806
|
const resolvedValue = resolvedParams[connection.paramName];
|
|
8797
|
-
|
|
8807
|
+
|
|
8798
8808
|
// Check if this is a query parameter (not in the pattern path)
|
|
8799
8809
|
const isQueryParam = parsedPattern.queryParams.some(
|
|
8800
8810
|
(qp) => qp.name === connection.paramName,
|
|
8801
8811
|
);
|
|
8802
8812
|
// Allow non-default query parameters, but not path parameters
|
|
8803
|
-
return
|
|
8813
|
+
return (
|
|
8814
|
+
!isQueryParam && connection.options.isCustomValue?.(resolvedValue)
|
|
8815
|
+
);
|
|
8804
8816
|
});
|
|
8805
8817
|
|
|
8806
8818
|
if (hasNonDefaultPathParams) {
|
|
@@ -8830,8 +8842,7 @@ const createRoutePattern = (pattern) => {
|
|
|
8830
8842
|
// For non-immediate parents, only allow optimization if all resolved parameters have default values
|
|
8831
8843
|
const hasNonDefaultParameters = connections.some((connection) => {
|
|
8832
8844
|
const resolvedValue = resolvedParams[connection.paramName];
|
|
8833
|
-
|
|
8834
|
-
return resolvedValue !== defaultValue;
|
|
8845
|
+
return connection.options.isCustomValue?.(resolvedValue);
|
|
8835
8846
|
});
|
|
8836
8847
|
|
|
8837
8848
|
if (hasNonDefaultParameters) {
|
|
@@ -9100,13 +9111,12 @@ const createRoutePattern = (pattern) => {
|
|
|
9100
9111
|
// Also check target ancestor's own signal values for parameters not in resolvedParams
|
|
9101
9112
|
for (const connection of targetAncestor.connections) {
|
|
9102
9113
|
const { paramName, signal, options } = connection;
|
|
9103
|
-
const defaultValue = options.defaultValue;
|
|
9104
9114
|
|
|
9105
|
-
// Only include if not already processed and has
|
|
9115
|
+
// Only include if not already processed and has custom value (not default)
|
|
9106
9116
|
if (
|
|
9107
9117
|
!(paramName in ancestorParams) &&
|
|
9108
9118
|
signal?.value !== undefined &&
|
|
9109
|
-
signal.value
|
|
9119
|
+
options.isCustomValue?.(signal.value)
|
|
9110
9120
|
) {
|
|
9111
9121
|
// Don't include path parameters that correspond to literal segments we're optimizing away
|
|
9112
9122
|
const targetParam = targetParams.find((p) => p.name === paramName);
|
|
@@ -9136,13 +9146,12 @@ const createRoutePattern = (pattern) => {
|
|
|
9136
9146
|
while (currentParent) {
|
|
9137
9147
|
for (const connection of currentParent.connections) {
|
|
9138
9148
|
const { paramName, signal, options } = connection;
|
|
9139
|
-
const defaultValue = options.defaultValue;
|
|
9140
9149
|
|
|
9141
|
-
// Only inherit
|
|
9150
|
+
// Only inherit custom values (not defaults) that we don't already have
|
|
9142
9151
|
if (
|
|
9143
9152
|
!(paramName in ancestorParams) &&
|
|
9144
9153
|
signal?.value !== undefined &&
|
|
9145
|
-
signal.value
|
|
9154
|
+
options.isCustomValue?.(signal.value)
|
|
9146
9155
|
) {
|
|
9147
9156
|
// Check if this parameter would be redundant with target ancestor's literal segments
|
|
9148
9157
|
const isRedundant = isParameterRedundantWithLiteralSegments(
|
|
@@ -9217,13 +9226,12 @@ const createRoutePattern = (pattern) => {
|
|
|
9217
9226
|
// Check parent's signal connections for non-default values to inherit
|
|
9218
9227
|
for (const parentConnection of currentParent.connections) {
|
|
9219
9228
|
const { paramName, signal, options } = parentConnection;
|
|
9220
|
-
const defaultValue = options.defaultValue;
|
|
9221
9229
|
|
|
9222
|
-
// Only inherit if we don't have this param and parent has
|
|
9230
|
+
// Only inherit if we don't have this param and parent has custom value (not default)
|
|
9223
9231
|
if (
|
|
9224
9232
|
!(paramName in finalParams) &&
|
|
9225
9233
|
signal?.value !== undefined &&
|
|
9226
|
-
signal.value
|
|
9234
|
+
options.isCustomValue?.(signal.value)
|
|
9227
9235
|
) {
|
|
9228
9236
|
// Don't inherit if parameter corresponds to a literal in our path
|
|
9229
9237
|
const shouldInherit = !isParameterRedundantWithLiteralSegments(
|
|
@@ -9707,6 +9715,21 @@ const extractSearchParams = (urlObj, connections = []) => {
|
|
|
9707
9715
|
/**
|
|
9708
9716
|
* Build query parameters respecting hierarchical order from ancestor patterns
|
|
9709
9717
|
*/
|
|
9718
|
+
/**
|
|
9719
|
+
* Build hierarchical query parameters from pattern hierarchy
|
|
9720
|
+
*
|
|
9721
|
+
* IMPORTANT: This function implements parameter inheritance - child routes inherit
|
|
9722
|
+
* query parameters from their ancestor routes. This is intentional behavior that
|
|
9723
|
+
* allows child routes to preserve context from parent routes.
|
|
9724
|
+
*
|
|
9725
|
+
* For example:
|
|
9726
|
+
* - Parent route: /map/?lon=123
|
|
9727
|
+
* - Child route: /map/isochrone?iso_lon=456
|
|
9728
|
+
* - Final URL: /map/isochrone?lon=123&iso_lon=456
|
|
9729
|
+
*
|
|
9730
|
+
* The child route inherits 'lon' from its parent, maintaining navigation context.
|
|
9731
|
+
* Only parameters that match their defaults (static or dynamic) are omitted.
|
|
9732
|
+
*/
|
|
9710
9733
|
const buildHierarchicalQueryParams = (
|
|
9711
9734
|
parsedPattern,
|
|
9712
9735
|
params,
|