@jsenv/navi 0.13.4 → 0.14.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 +884 -434
- package/dist/jsenv_navi.js.map +64 -35
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -318,85 +318,95 @@ const getSignalType = (value) => {
|
|
|
318
318
|
*/
|
|
319
319
|
const SYMBOL_IDENTITY = Symbol.for("navi_object_identity");
|
|
320
320
|
|
|
321
|
-
const compareTwoJsValues = (
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const aIsIsTruthy = Boolean(a);
|
|
326
|
-
const bIsTruthy = Boolean(b);
|
|
327
|
-
if (aIsIsTruthy && !bIsTruthy) {
|
|
328
|
-
return false;
|
|
329
|
-
}
|
|
330
|
-
if (!aIsIsTruthy && !bIsTruthy) {
|
|
331
|
-
// null, undefined, 0, false, NaN
|
|
332
|
-
if (isNaN(a) && isNaN(b)) {
|
|
321
|
+
const compareTwoJsValues = (rootA, rootB, { keyComparator } = {}) => {
|
|
322
|
+
const seenSet = new Set();
|
|
323
|
+
const compare = (a, b) => {
|
|
324
|
+
if (a === b) {
|
|
333
325
|
return true;
|
|
334
326
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
return a === b;
|
|
351
|
-
}
|
|
352
|
-
if (seenSet.has(a)) {
|
|
353
|
-
return false;
|
|
354
|
-
}
|
|
355
|
-
if (seenSet.has(b)) {
|
|
356
|
-
return false;
|
|
357
|
-
}
|
|
358
|
-
seenSet.add(a);
|
|
359
|
-
seenSet.add(b);
|
|
360
|
-
const aIsArray = Array.isArray(a);
|
|
361
|
-
const bIsArray = Array.isArray(b);
|
|
362
|
-
if (aIsArray !== bIsArray) {
|
|
363
|
-
return false;
|
|
364
|
-
}
|
|
365
|
-
if (aIsArray) {
|
|
366
|
-
// compare arrays
|
|
367
|
-
if (a.length !== b.length) {
|
|
327
|
+
const aIsIsTruthy = Boolean(a);
|
|
328
|
+
const bIsTruthy = Boolean(b);
|
|
329
|
+
if (aIsIsTruthy && !bIsTruthy) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
if (!aIsIsTruthy && !bIsTruthy) {
|
|
333
|
+
// null, undefined, 0, false, NaN
|
|
334
|
+
if (isNaN(a) && isNaN(b)) {
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
return a === b;
|
|
338
|
+
}
|
|
339
|
+
const aType = typeof a;
|
|
340
|
+
const bType = typeof b;
|
|
341
|
+
if (aType !== bType) {
|
|
368
342
|
return false;
|
|
369
343
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
344
|
+
const aIsPrimitive =
|
|
345
|
+
a === null || (aType !== "object" && aType !== "function");
|
|
346
|
+
const bIsPrimitive =
|
|
347
|
+
b === null || (bType !== "object" && bType !== "function");
|
|
348
|
+
if (aIsPrimitive !== bIsPrimitive) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
if (aIsPrimitive && bIsPrimitive) {
|
|
352
|
+
return a === b;
|
|
353
|
+
}
|
|
354
|
+
if (seenSet.has(a)) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
if (seenSet.has(b)) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
seenSet.add(a);
|
|
361
|
+
seenSet.add(b);
|
|
362
|
+
const aIsArray = Array.isArray(a);
|
|
363
|
+
const bIsArray = Array.isArray(b);
|
|
364
|
+
if (aIsArray !== bIsArray) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
if (aIsArray) {
|
|
368
|
+
// compare arrays
|
|
369
|
+
if (a.length !== b.length) {
|
|
375
370
|
return false;
|
|
376
371
|
}
|
|
377
|
-
i
|
|
372
|
+
let i = 0;
|
|
373
|
+
while (i < a.length) {
|
|
374
|
+
const aValue = a[i];
|
|
375
|
+
const bValue = b[i];
|
|
376
|
+
const comparator = keyComparator || compare;
|
|
377
|
+
if (!comparator(aValue, bValue, i, compare)) {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
i++;
|
|
381
|
+
}
|
|
382
|
+
return true;
|
|
378
383
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
for (const key of aKeys) {
|
|
393
|
-
const aValue = a[key];
|
|
394
|
-
const bValue = b[key];
|
|
395
|
-
if (!compareTwoJsValues(aValue, bValue, seenSet)) {
|
|
384
|
+
// compare objects
|
|
385
|
+
const aIdentity = a[SYMBOL_IDENTITY];
|
|
386
|
+
const bIdentity = b[SYMBOL_IDENTITY];
|
|
387
|
+
if (
|
|
388
|
+
aIdentity === bIdentity &&
|
|
389
|
+
SYMBOL_IDENTITY in a &&
|
|
390
|
+
SYMBOL_IDENTITY in b
|
|
391
|
+
) {
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
const aKeys = Object.keys(a);
|
|
395
|
+
const bKeys = Object.keys(b);
|
|
396
|
+
if (aKeys.length !== bKeys.length) {
|
|
396
397
|
return false;
|
|
397
398
|
}
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
for (const key of aKeys) {
|
|
400
|
+
const aValue = a[key];
|
|
401
|
+
const bValue = b[key];
|
|
402
|
+
const comparator = keyComparator || compare;
|
|
403
|
+
if (!comparator(aValue, bValue, key, compare)) {
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return true;
|
|
408
|
+
};
|
|
409
|
+
return compare(rootA, rootB);
|
|
400
410
|
};
|
|
401
411
|
|
|
402
412
|
/**
|
|
@@ -1247,8 +1257,8 @@ ${lines.join("\n")}`);
|
|
|
1247
1257
|
};
|
|
1248
1258
|
};
|
|
1249
1259
|
|
|
1250
|
-
const NO_PARAMS
|
|
1251
|
-
const initialParamsDefault = NO_PARAMS
|
|
1260
|
+
const NO_PARAMS = {};
|
|
1261
|
+
const initialParamsDefault = NO_PARAMS;
|
|
1252
1262
|
|
|
1253
1263
|
const actionWeakMap = new WeakMap();
|
|
1254
1264
|
const createAction = (callback, rootOptions = {}) => {
|
|
@@ -1855,7 +1865,7 @@ const createActionProxyFromSignal = (
|
|
|
1855
1865
|
const _updateTarget = (params) => {
|
|
1856
1866
|
const previousActionTarget = actionTargetPreviousWeakRef?.deref();
|
|
1857
1867
|
|
|
1858
|
-
if (params === NO_PARAMS
|
|
1868
|
+
if (params === NO_PARAMS) {
|
|
1859
1869
|
actionTarget = null;
|
|
1860
1870
|
currentAction = action;
|
|
1861
1871
|
currentActionPrivateProperties = getActionPrivateProperties(action);
|
|
@@ -2060,7 +2070,7 @@ const createActionProxyFromSignal = (
|
|
|
2060
2070
|
};
|
|
2061
2071
|
|
|
2062
2072
|
const generateActionName = (name, params) => {
|
|
2063
|
-
if (params === NO_PARAMS
|
|
2073
|
+
if (params === NO_PARAMS) {
|
|
2064
2074
|
return `${name}({})`;
|
|
2065
2075
|
}
|
|
2066
2076
|
// Use stringifyForDisplay with asFunctionArgs option for the entire args array
|
|
@@ -4574,16 +4584,17 @@ const useStateArray = (
|
|
|
4574
4584
|
const createRequestCanceller = (reason = "Request superseded") => {
|
|
4575
4585
|
let previousAbortController;
|
|
4576
4586
|
return () => {
|
|
4577
|
-
previousAbortController
|
|
4587
|
+
if (previousAbortController) {
|
|
4588
|
+
const abortError = new DOMException(reason, "AbortError");
|
|
4589
|
+
abortError.isHandled = true;
|
|
4590
|
+
previousAbortController.abort(abortError);
|
|
4591
|
+
}
|
|
4578
4592
|
previousAbortController = new AbortController();
|
|
4579
4593
|
return previousAbortController.signal;
|
|
4580
4594
|
};
|
|
4581
4595
|
};
|
|
4582
4596
|
window.addEventListener("unhandledrejection", (event) => {
|
|
4583
|
-
if (
|
|
4584
|
-
event.reason?.name === "AbortError" &&
|
|
4585
|
-
event.reason?.message === "Request superseded"
|
|
4586
|
-
) {
|
|
4597
|
+
if (event.reason?.isHandled) {
|
|
4587
4598
|
event.preventDefault(); // 💥 empêche les "uncaught rejection" devtools pour nos cancellations
|
|
4588
4599
|
}
|
|
4589
4600
|
});
|
|
@@ -4733,7 +4744,7 @@ const DIMENSION_PROPS = {
|
|
|
4733
4744
|
return null;
|
|
4734
4745
|
}
|
|
4735
4746
|
if (parentBoxFlow === "column" || parentBoxFlow === "inline-column") {
|
|
4736
|
-
return { flexGrow: 1 }; // Grow horizontally in row
|
|
4747
|
+
return { flexGrow: 1, flexBasis: "0%" }; // Grow horizontally in row
|
|
4737
4748
|
}
|
|
4738
4749
|
if (parentBoxFlow === "row") {
|
|
4739
4750
|
return { minWidth: "100%", width: "auto" }; // Take full width in column
|
|
@@ -4748,7 +4759,7 @@ const DIMENSION_PROPS = {
|
|
|
4748
4759
|
return { minHeight: "100%", height: "auto" }; // Make column full height
|
|
4749
4760
|
}
|
|
4750
4761
|
if (parentBoxFlow === "row" || parentBoxFlow === "inline-row") {
|
|
4751
|
-
return { flexGrow: 1 }; // Make row full height
|
|
4762
|
+
return { flexGrow: 1, flexBasis: "0%" }; // Make row full height
|
|
4752
4763
|
}
|
|
4753
4764
|
return { minHeight: "100%", height: "auto" }; // Take full height outside flex
|
|
4754
4765
|
},
|
|
@@ -4932,6 +4943,9 @@ const VISUAL_PROPS = {
|
|
|
4932
4943
|
filter: PASS_THROUGH,
|
|
4933
4944
|
cursor: PASS_THROUGH,
|
|
4934
4945
|
transition: PASS_THROUGH,
|
|
4946
|
+
overflow: PASS_THROUGH,
|
|
4947
|
+
overflowX: PASS_THROUGH,
|
|
4948
|
+
overflowY: PASS_THROUGH,
|
|
4935
4949
|
};
|
|
4936
4950
|
const CONTENT_PROPS = {
|
|
4937
4951
|
align: applyOnTwoProps("alignX", "alignY"),
|
|
@@ -7172,26 +7186,337 @@ const useUITransitionContentId = value => {
|
|
|
7172
7186
|
}, []);
|
|
7173
7187
|
};
|
|
7174
7188
|
|
|
7189
|
+
const rawUrlPartSymbol = Symbol("raw_url_part");
|
|
7190
|
+
const rawUrlPart = (value) => {
|
|
7191
|
+
return {
|
|
7192
|
+
[rawUrlPartSymbol]: true,
|
|
7193
|
+
value,
|
|
7194
|
+
};
|
|
7195
|
+
};
|
|
7196
|
+
|
|
7197
|
+
const removeOptionalParts = (url) => {
|
|
7198
|
+
// Only remove optional parts that still have ? (weren't replaced with actual values)
|
|
7199
|
+
// Find the first unused optional part and remove everything from there onwards
|
|
7200
|
+
let result = url;
|
|
7201
|
+
|
|
7202
|
+
// Find the first occurrence of an unused optional part (still has ?)
|
|
7203
|
+
const optionalPartMatch = result.match(/(\/?\*|\/:[^/?]*|\{[^}]*\})\?/);
|
|
7204
|
+
|
|
7205
|
+
if (optionalPartMatch) {
|
|
7206
|
+
// Remove everything from the start of the first unused optional part
|
|
7207
|
+
const optionalStartIndex = optionalPartMatch.index;
|
|
7208
|
+
result = result.substring(0, optionalStartIndex);
|
|
7209
|
+
|
|
7210
|
+
// Clean up trailing slashes
|
|
7211
|
+
result = result.replace(/\/$/, "");
|
|
7212
|
+
}
|
|
7213
|
+
|
|
7214
|
+
return result;
|
|
7215
|
+
};
|
|
7216
|
+
|
|
7217
|
+
const buildRouteRelativeUrl = (
|
|
7218
|
+
urlPatternInput,
|
|
7219
|
+
params,
|
|
7220
|
+
{ extraParamEffect = "inject_as_search_param" } = {},
|
|
7221
|
+
) => {
|
|
7222
|
+
let relativeUrl = urlPatternInput;
|
|
7223
|
+
let hasRawUrlPartWithInvalidChars = false;
|
|
7224
|
+
let stringQueryParams = "";
|
|
7225
|
+
|
|
7226
|
+
// Handle string params (query string) - store for later appending
|
|
7227
|
+
if (typeof params === "string") {
|
|
7228
|
+
stringQueryParams = params;
|
|
7229
|
+
// Remove leading ? if present for processing
|
|
7230
|
+
if (stringQueryParams.startsWith("?")) {
|
|
7231
|
+
stringQueryParams = stringQueryParams.slice(1);
|
|
7232
|
+
}
|
|
7233
|
+
// Set params to empty object so the rest of the function processes the URL pattern
|
|
7234
|
+
params = null;
|
|
7235
|
+
}
|
|
7236
|
+
|
|
7237
|
+
// Encode parameter values for URL usage, with special handling for raw URL parts.
|
|
7238
|
+
// When a parameter is wrapped with rawUrlPart(), it bypasses encoding and is
|
|
7239
|
+
// inserted as-is into the URL. This allows including pre-encoded values or
|
|
7240
|
+
// special characters that should not be percent-encoded.
|
|
7241
|
+
const encodeParamValue = (value) => {
|
|
7242
|
+
if (value && value[rawUrlPartSymbol]) {
|
|
7243
|
+
const rawValue = value.value;
|
|
7244
|
+
// Check if raw value contains invalid URL characters
|
|
7245
|
+
if (/[\s<>{}|\\^`]/.test(rawValue)) {
|
|
7246
|
+
hasRawUrlPartWithInvalidChars = true;
|
|
7247
|
+
}
|
|
7248
|
+
return rawValue;
|
|
7249
|
+
}
|
|
7250
|
+
return encodeURIComponent(value);
|
|
7251
|
+
};
|
|
7252
|
+
const extraParamMap = new Map();
|
|
7253
|
+
if (params) {
|
|
7254
|
+
const keys = Object.keys(params);
|
|
7255
|
+
// Replace named parameters (:param and {param}) and remove optional markers
|
|
7256
|
+
for (const key of keys) {
|
|
7257
|
+
const value = params[key];
|
|
7258
|
+
const encodedValue = encodeParamValue(value);
|
|
7259
|
+
const beforeReplace = relativeUrl;
|
|
7260
|
+
|
|
7261
|
+
// Replace parameter and remove optional marker if present
|
|
7262
|
+
relativeUrl = relativeUrl.replace(`:${key}?`, encodedValue);
|
|
7263
|
+
relativeUrl = relativeUrl.replace(`:${key}`, encodedValue);
|
|
7264
|
+
relativeUrl = relativeUrl.replace(`{${key}}?`, encodedValue);
|
|
7265
|
+
relativeUrl = relativeUrl.replace(`{${key}}`, encodedValue);
|
|
7266
|
+
|
|
7267
|
+
// If the URL did not change we'll maybe delete that param
|
|
7268
|
+
if (relativeUrl === beforeReplace) {
|
|
7269
|
+
extraParamMap.set(key, value);
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
// Handle complex optional groups like {/time/:duration}?
|
|
7273
|
+
// Replace parameters inside optional groups and remove the optional marker
|
|
7274
|
+
relativeUrl = relativeUrl.replace(/\{([^}]*)\}\?/g, (match, group) => {
|
|
7275
|
+
let processedGroup = group;
|
|
7276
|
+
let hasReplacements = false;
|
|
7277
|
+
|
|
7278
|
+
// Check if any parameters in the group were provided
|
|
7279
|
+
for (const key of keys) {
|
|
7280
|
+
if (params[key] !== undefined) {
|
|
7281
|
+
const encodedValue = encodeParamValue(params[key]);
|
|
7282
|
+
const paramPattern = new RegExp(`:${key}\\b`);
|
|
7283
|
+
if (paramPattern.test(processedGroup)) {
|
|
7284
|
+
processedGroup = processedGroup.replace(paramPattern, encodedValue);
|
|
7285
|
+
hasReplacements = true;
|
|
7286
|
+
extraParamMap.delete(key);
|
|
7287
|
+
}
|
|
7288
|
+
}
|
|
7289
|
+
}
|
|
7290
|
+
|
|
7291
|
+
// Also check for literal parts that match parameter names (like /time where time is a param)
|
|
7292
|
+
for (const key of keys) {
|
|
7293
|
+
if (params[key] !== undefined) {
|
|
7294
|
+
const encodedValue = encodeParamValue(params[key]);
|
|
7295
|
+
// Check for literal parts like /time that match parameter names
|
|
7296
|
+
const literalPattern = new RegExp(`\\/${key}\\b`);
|
|
7297
|
+
if (literalPattern.test(processedGroup)) {
|
|
7298
|
+
processedGroup = processedGroup.replace(
|
|
7299
|
+
literalPattern,
|
|
7300
|
+
`/${encodedValue}`,
|
|
7301
|
+
);
|
|
7302
|
+
hasReplacements = true;
|
|
7303
|
+
extraParamMap.delete(key);
|
|
7304
|
+
}
|
|
7305
|
+
}
|
|
7306
|
+
}
|
|
7307
|
+
|
|
7308
|
+
// If we made replacements, include the group (without the optional marker)
|
|
7309
|
+
// If no replacements, return empty string (remove the optional group)
|
|
7310
|
+
return hasReplacements ? processedGroup : "";
|
|
7311
|
+
});
|
|
7312
|
+
}
|
|
7313
|
+
|
|
7314
|
+
// Clean up any double slashes or trailing slashes that might result
|
|
7315
|
+
relativeUrl = relativeUrl.replace(/\/+/g, "/").replace(/\/$/, "");
|
|
7316
|
+
|
|
7317
|
+
// Handle remaining wildcards
|
|
7318
|
+
if (params) {
|
|
7319
|
+
let wildcardIndex = 0;
|
|
7320
|
+
relativeUrl = relativeUrl.replace(/\*/g, () => {
|
|
7321
|
+
const paramKey = wildcardIndex.toString();
|
|
7322
|
+
const paramValue = params[paramKey];
|
|
7323
|
+
if (paramValue) {
|
|
7324
|
+
extraParamMap.delete(paramKey);
|
|
7325
|
+
}
|
|
7326
|
+
const replacement = paramValue ? encodeParamValue(paramValue) : "*";
|
|
7327
|
+
wildcardIndex++;
|
|
7328
|
+
return replacement;
|
|
7329
|
+
});
|
|
7330
|
+
}
|
|
7331
|
+
|
|
7332
|
+
// Handle optional parts after parameter replacement
|
|
7333
|
+
// This includes patterns like /*?, {/time/*}?, :param?, etc.
|
|
7334
|
+
relativeUrl = removeOptionalParts(relativeUrl);
|
|
7335
|
+
// we did not replace anything, or not enough to remove the last "*"
|
|
7336
|
+
if (relativeUrl.endsWith("*")) {
|
|
7337
|
+
relativeUrl = relativeUrl.slice(0, -1);
|
|
7338
|
+
}
|
|
7339
|
+
|
|
7340
|
+
// Normalize trailing slash: always favor URLs without trailing slash
|
|
7341
|
+
// except for root path which should remain "/"
|
|
7342
|
+
if (relativeUrl.endsWith("/") && relativeUrl.length > 1) {
|
|
7343
|
+
relativeUrl = relativeUrl.slice(0, -1);
|
|
7344
|
+
}
|
|
7345
|
+
|
|
7346
|
+
// Add remaining parameters as search params
|
|
7347
|
+
if (extraParamMap.size > 0) {
|
|
7348
|
+
if (extraParamEffect === "inject_as_search_param") {
|
|
7349
|
+
const searchParamPairs = [];
|
|
7350
|
+
for (const [key, value] of extraParamMap) {
|
|
7351
|
+
if (value !== undefined && value !== null) {
|
|
7352
|
+
const encodedKey = encodeURIComponent(key);
|
|
7353
|
+
// Handle boolean values - if true, just add the key without value
|
|
7354
|
+
if (value === true) {
|
|
7355
|
+
searchParamPairs.push(encodedKey);
|
|
7356
|
+
} else {
|
|
7357
|
+
const encodedValue = encodeParamValue(value);
|
|
7358
|
+
searchParamPairs.push(`${encodedKey}=${encodedValue}`);
|
|
7359
|
+
}
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7362
|
+
if (searchParamPairs.length > 0) {
|
|
7363
|
+
const searchString = searchParamPairs.join("&");
|
|
7364
|
+
relativeUrl += (relativeUrl.includes("?") ? "&" : "?") + searchString;
|
|
7365
|
+
}
|
|
7366
|
+
} else if (extraParamEffect === "warn") {
|
|
7367
|
+
console.warn(
|
|
7368
|
+
`Unknown parameters given to "${urlPatternInput}":`,
|
|
7369
|
+
Array.from(extraParamMap.keys()),
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
}
|
|
7373
|
+
|
|
7374
|
+
// Append string query params if any
|
|
7375
|
+
if (stringQueryParams) {
|
|
7376
|
+
relativeUrl += (relativeUrl.includes("?") ? "&" : "?") + stringQueryParams;
|
|
7377
|
+
}
|
|
7378
|
+
|
|
7379
|
+
return {
|
|
7380
|
+
relativeUrl,
|
|
7381
|
+
hasRawUrlPartWithInvalidChars,
|
|
7382
|
+
};
|
|
7383
|
+
};
|
|
7384
|
+
|
|
7385
|
+
const createRoutePattern = (urlPatternInput, baseUrl) => {
|
|
7386
|
+
// Remove leading slash from urlPattern to make it relative to baseUrl
|
|
7387
|
+
const normalizedUrlPattern = urlPatternInput.startsWith("/")
|
|
7388
|
+
? urlPatternInput.slice(1)
|
|
7389
|
+
: urlPatternInput;
|
|
7390
|
+
const urlPattern = new URLPattern(normalizedUrlPattern, baseUrl, {
|
|
7391
|
+
ignoreCase: true,
|
|
7392
|
+
});
|
|
7393
|
+
|
|
7394
|
+
// Analyze pattern once to detect optional params (named and wildcard indices)
|
|
7395
|
+
// Note: Wildcard indices are stored as strings ("0", "1", ...) to match keys from extractParams
|
|
7396
|
+
const optionalParamKeySet = new Set();
|
|
7397
|
+
normalizedUrlPattern.replace(/:([A-Za-z0-9_]+)\?/g, (_m, name) => {
|
|
7398
|
+
optionalParamKeySet.add(name);
|
|
7399
|
+
return "";
|
|
7400
|
+
});
|
|
7401
|
+
let wildcardIndex = 0;
|
|
7402
|
+
normalizedUrlPattern.replace(/\*(\?)?/g, (_m, opt) => {
|
|
7403
|
+
if (opt === "?") {
|
|
7404
|
+
optionalParamKeySet.add(String(wildcardIndex));
|
|
7405
|
+
}
|
|
7406
|
+
wildcardIndex++;
|
|
7407
|
+
return "";
|
|
7408
|
+
});
|
|
7409
|
+
|
|
7410
|
+
const applyOn = (url) => {
|
|
7411
|
+
|
|
7412
|
+
// Check if the URL matches the route pattern
|
|
7413
|
+
const match = urlPattern.exec(url);
|
|
7414
|
+
if (match) {
|
|
7415
|
+
return extractParams(match, url);
|
|
7416
|
+
}
|
|
7417
|
+
|
|
7418
|
+
// If no match, try with normalized URLs (trailing slash handling)
|
|
7419
|
+
const urlObj = new URL(url, baseUrl);
|
|
7420
|
+
const pathname = urlObj.pathname;
|
|
7421
|
+
|
|
7422
|
+
// Try removing trailing slash from pathname
|
|
7423
|
+
if (pathname.endsWith("/") && pathname.length > 1) {
|
|
7424
|
+
const pathnameWithoutSlash = pathname.slice(0, -1);
|
|
7425
|
+
urlObj.pathname = pathnameWithoutSlash;
|
|
7426
|
+
const normalizedUrl = urlObj.href;
|
|
7427
|
+
const matchWithoutTrailingSlash = urlPattern.exec(normalizedUrl);
|
|
7428
|
+
if (matchWithoutTrailingSlash) {
|
|
7429
|
+
return extractParams(matchWithoutTrailingSlash, url);
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
// Try adding trailing slash to pathname
|
|
7433
|
+
else if (!pathname.endsWith("/")) {
|
|
7434
|
+
const pathnameWithSlash = `${pathname}/`;
|
|
7435
|
+
urlObj.pathname = pathnameWithSlash;
|
|
7436
|
+
const normalizedUrl = urlObj.href;
|
|
7437
|
+
const matchWithTrailingSlash = urlPattern.exec(normalizedUrl);
|
|
7438
|
+
if (matchWithTrailingSlash) {
|
|
7439
|
+
return extractParams(matchWithTrailingSlash, url);
|
|
7440
|
+
}
|
|
7441
|
+
}
|
|
7442
|
+
return null;
|
|
7443
|
+
};
|
|
7444
|
+
|
|
7445
|
+
const extractParams = (match, originalUrl) => {
|
|
7446
|
+
const params = {};
|
|
7447
|
+
|
|
7448
|
+
// Extract search parameters from the original URL
|
|
7449
|
+
const urlObj = new URL(originalUrl, baseUrl);
|
|
7450
|
+
for (const [key, value] of urlObj.searchParams) {
|
|
7451
|
+
params[key] = value;
|
|
7452
|
+
}
|
|
7453
|
+
|
|
7454
|
+
// Collect all parameters from URLPattern groups, handling both named and numbered groups
|
|
7455
|
+
let wildcardOffset = 0;
|
|
7456
|
+
for (const property of URL_PATTERN_PROPERTIES_WITH_GROUP_SET) {
|
|
7457
|
+
const urlPartMatch = match[property];
|
|
7458
|
+
if (urlPartMatch && urlPartMatch.groups) {
|
|
7459
|
+
let localWildcardCount = 0;
|
|
7460
|
+
for (const key of Object.keys(urlPartMatch.groups)) {
|
|
7461
|
+
const value = urlPartMatch.groups[key];
|
|
7462
|
+
const keyAsNumber = parseInt(key, 10);
|
|
7463
|
+
if (!isNaN(keyAsNumber)) {
|
|
7464
|
+
// Skip group "0" from search params as it captures the entire search string
|
|
7465
|
+
if (property === "search" && key === "0") {
|
|
7466
|
+
continue;
|
|
7467
|
+
}
|
|
7468
|
+
if (value) {
|
|
7469
|
+
// Only include non-empty values and non-ignored wildcard indices
|
|
7470
|
+
const wildcardKey = String(wildcardOffset + keyAsNumber);
|
|
7471
|
+
if (!optionalParamKeySet.has(wildcardKey)) {
|
|
7472
|
+
params[wildcardKey] = decodeURIComponent(value);
|
|
7473
|
+
}
|
|
7474
|
+
localWildcardCount++;
|
|
7475
|
+
}
|
|
7476
|
+
} else if (!optionalParamKeySet.has(key)) {
|
|
7477
|
+
// Named group (:param or {param}) - only include if not ignored
|
|
7478
|
+
params[key] = decodeURIComponent(value);
|
|
7479
|
+
}
|
|
7480
|
+
}
|
|
7481
|
+
// Update wildcard offset for next URL part
|
|
7482
|
+
wildcardOffset += localWildcardCount;
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
return params;
|
|
7486
|
+
};
|
|
7487
|
+
|
|
7488
|
+
return {
|
|
7489
|
+
urlPattern,
|
|
7490
|
+
applyOn,
|
|
7491
|
+
};
|
|
7492
|
+
};
|
|
7493
|
+
|
|
7494
|
+
const URL_PATTERN_PROPERTIES_WITH_GROUP_SET = new Set([
|
|
7495
|
+
"protocol",
|
|
7496
|
+
"username",
|
|
7497
|
+
"password",
|
|
7498
|
+
"hostname",
|
|
7499
|
+
"pathname",
|
|
7500
|
+
"search",
|
|
7501
|
+
"hash",
|
|
7502
|
+
]);
|
|
7503
|
+
|
|
7175
7504
|
/**
|
|
7176
7505
|
*
|
|
7177
7506
|
*
|
|
7178
7507
|
*/
|
|
7179
7508
|
|
|
7180
7509
|
|
|
7181
|
-
let baseUrl
|
|
7510
|
+
let baseUrl;
|
|
7511
|
+
if (typeof window === "undefined") {
|
|
7512
|
+
baseUrl = "http://localhost/";
|
|
7513
|
+
} else {
|
|
7514
|
+
baseUrl = window.location.origin;
|
|
7515
|
+
}
|
|
7182
7516
|
|
|
7183
7517
|
const setBaseUrl = (value) => {
|
|
7184
7518
|
baseUrl = new URL(value, window.location).href;
|
|
7185
7519
|
};
|
|
7186
|
-
|
|
7187
|
-
const rawUrlPartSymbol = Symbol("raw_url_part");
|
|
7188
|
-
const rawUrlPart = (value) => {
|
|
7189
|
-
return {
|
|
7190
|
-
[rawUrlPartSymbol]: true,
|
|
7191
|
-
value,
|
|
7192
|
-
};
|
|
7193
|
-
};
|
|
7194
|
-
const NO_PARAMS = { [SYMBOL_IDENTITY]: Symbol("no_params") };
|
|
7195
7520
|
// Controls what happens to actions when their route becomes inactive:
|
|
7196
7521
|
// 'abort' - Cancel the action immediately when route deactivates
|
|
7197
7522
|
// 'keep-loading' - Allow action to continue running after route deactivation
|
|
@@ -7217,26 +7542,19 @@ const updateRoutes = (
|
|
|
7217
7542
|
const routeMatchInfoSet = new Set();
|
|
7218
7543
|
for (const route of routeSet) {
|
|
7219
7544
|
const routePrivateProperties = getRoutePrivateProperties(route);
|
|
7220
|
-
const {
|
|
7545
|
+
const { routePattern } = routePrivateProperties;
|
|
7221
7546
|
|
|
7222
7547
|
// Get previous state
|
|
7223
7548
|
const previousState = routePreviousStateMap.get(route) || {
|
|
7224
7549
|
active: false,
|
|
7225
|
-
params:
|
|
7550
|
+
params: null,
|
|
7226
7551
|
};
|
|
7227
7552
|
const oldActive = previousState.active;
|
|
7228
7553
|
const oldParams = previousState.params;
|
|
7229
|
-
|
|
7230
|
-
const
|
|
7231
|
-
const newActive = Boolean(match);
|
|
7554
|
+
const extractedParams = routePattern.applyOn(url);
|
|
7555
|
+
const newActive = Boolean(extractedParams);
|
|
7232
7556
|
let newParams;
|
|
7233
|
-
if (
|
|
7234
|
-
const { optionalParamKeySet } = routePrivateProperties;
|
|
7235
|
-
const extractedParams = extractParams(
|
|
7236
|
-
urlPattern,
|
|
7237
|
-
url,
|
|
7238
|
-
optionalParamKeySet,
|
|
7239
|
-
);
|
|
7557
|
+
if (extractedParams) {
|
|
7240
7558
|
if (compareTwoJsValues(oldParams, extractedParams)) {
|
|
7241
7559
|
// No change in parameters, keep the old params
|
|
7242
7560
|
newParams = oldParams;
|
|
@@ -7244,7 +7562,7 @@ const updateRoutes = (
|
|
|
7244
7562
|
newParams = extractedParams;
|
|
7245
7563
|
}
|
|
7246
7564
|
} else {
|
|
7247
|
-
newParams =
|
|
7565
|
+
newParams = null;
|
|
7248
7566
|
}
|
|
7249
7567
|
|
|
7250
7568
|
const routeMatchInfo = {
|
|
@@ -7373,51 +7691,6 @@ const updateRoutes = (
|
|
|
7373
7691
|
activeRouteSet,
|
|
7374
7692
|
};
|
|
7375
7693
|
};
|
|
7376
|
-
const extractParams = (urlPattern, url, ignoreSet = new Set()) => {
|
|
7377
|
-
const match = urlPattern.exec(url);
|
|
7378
|
-
if (!match) {
|
|
7379
|
-
return NO_PARAMS;
|
|
7380
|
-
}
|
|
7381
|
-
const params = {};
|
|
7382
|
-
|
|
7383
|
-
// Collect all parameters from URLPattern groups, handling both named and numbered groups
|
|
7384
|
-
let wildcardOffset = 0;
|
|
7385
|
-
for (const property of URL_PATTERN_PROPERTIES_WITH_GROUP_SET) {
|
|
7386
|
-
const urlPartMatch = match[property];
|
|
7387
|
-
if (urlPartMatch && urlPartMatch.groups) {
|
|
7388
|
-
let localWildcardCount = 0;
|
|
7389
|
-
for (const key of Object.keys(urlPartMatch.groups)) {
|
|
7390
|
-
const value = urlPartMatch.groups[key];
|
|
7391
|
-
const keyAsNumber = parseInt(key, 10);
|
|
7392
|
-
if (!isNaN(keyAsNumber)) {
|
|
7393
|
-
if (value) {
|
|
7394
|
-
// Only include non-empty values and non-ignored wildcard indices
|
|
7395
|
-
const wildcardKey = String(wildcardOffset + keyAsNumber);
|
|
7396
|
-
if (!ignoreSet.has(wildcardKey)) {
|
|
7397
|
-
params[wildcardKey] = decodeURIComponent(value);
|
|
7398
|
-
}
|
|
7399
|
-
localWildcardCount++;
|
|
7400
|
-
}
|
|
7401
|
-
} else if (!ignoreSet.has(key)) {
|
|
7402
|
-
// Named group (:param or {param}) - only include if not ignored
|
|
7403
|
-
params[key] = decodeURIComponent(value);
|
|
7404
|
-
}
|
|
7405
|
-
}
|
|
7406
|
-
// Update wildcard offset for next URL part
|
|
7407
|
-
wildcardOffset += localWildcardCount;
|
|
7408
|
-
}
|
|
7409
|
-
}
|
|
7410
|
-
return params;
|
|
7411
|
-
};
|
|
7412
|
-
const URL_PATTERN_PROPERTIES_WITH_GROUP_SET = new Set([
|
|
7413
|
-
"protocol",
|
|
7414
|
-
"username",
|
|
7415
|
-
"password",
|
|
7416
|
-
"hostname",
|
|
7417
|
-
"pathname",
|
|
7418
|
-
"search",
|
|
7419
|
-
"hash",
|
|
7420
|
-
]);
|
|
7421
7694
|
|
|
7422
7695
|
const routePrivatePropertiesMap = new Map();
|
|
7423
7696
|
const getRoutePrivateProperties = (route) => {
|
|
@@ -7438,7 +7711,7 @@ const createRoute = (urlPatternInput) => {
|
|
|
7438
7711
|
urlPattern: urlPatternInput,
|
|
7439
7712
|
isRoute: true,
|
|
7440
7713
|
active: false,
|
|
7441
|
-
params:
|
|
7714
|
+
params: null,
|
|
7442
7715
|
buildUrl: null,
|
|
7443
7716
|
bindAction: null,
|
|
7444
7717
|
relativeUrl: null,
|
|
@@ -7454,13 +7727,12 @@ const createRoute = (urlPatternInput) => {
|
|
|
7454
7727
|
routeSet.add(route);
|
|
7455
7728
|
|
|
7456
7729
|
const routePrivateProperties = {
|
|
7457
|
-
|
|
7730
|
+
routePattern: null,
|
|
7458
7731
|
activeSignal: null,
|
|
7459
7732
|
paramsSignal: null,
|
|
7460
7733
|
visitedSignal: null,
|
|
7461
7734
|
relativeUrlSignal: null,
|
|
7462
7735
|
urlSignal: null,
|
|
7463
|
-
optionalParamKeySet: null,
|
|
7464
7736
|
updateStatus: ({ active, params, visited }) => {
|
|
7465
7737
|
let someChange = false;
|
|
7466
7738
|
activeSignal.value = active;
|
|
@@ -7485,101 +7757,32 @@ const createRoute = (urlPatternInput) => {
|
|
|
7485
7757
|
};
|
|
7486
7758
|
routePrivatePropertiesMap.set(route, routePrivateProperties);
|
|
7487
7759
|
|
|
7488
|
-
const buildRelativeUrl = (
|
|
7489
|
-
params
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
// Encode parameter values for URL usage, with special handling for raw URL parts.
|
|
7496
|
-
// When a parameter is wrapped with rawUrlPart(), it bypasses encoding and is
|
|
7497
|
-
// inserted as-is into the URL. This allows including pre-encoded values or
|
|
7498
|
-
// special characters that should not be percent-encoded.
|
|
7499
|
-
const encodeParamValue = (value) => {
|
|
7500
|
-
if (value && value[rawUrlPartSymbol]) {
|
|
7501
|
-
const rawValue = value.value;
|
|
7502
|
-
// Check if raw value contains invalid URL characters
|
|
7503
|
-
if (/[\s<>{}|\\^`]/.test(rawValue)) {
|
|
7504
|
-
hasRawUrlPartWithInvalidChars = true;
|
|
7505
|
-
}
|
|
7506
|
-
return rawValue;
|
|
7507
|
-
}
|
|
7508
|
-
return encodeURIComponent(value);
|
|
7509
|
-
};
|
|
7510
|
-
|
|
7511
|
-
const keys = Object.keys(params);
|
|
7512
|
-
const extraParamSet = new Set(keys);
|
|
7760
|
+
const buildRelativeUrl = (params, options) =>
|
|
7761
|
+
buildRouteRelativeUrl(urlPatternInput, params, options);
|
|
7762
|
+
route.buildRelativeUrl = (params, options) => {
|
|
7763
|
+
const { relativeUrl } = buildRelativeUrl(params, options);
|
|
7764
|
+
return relativeUrl;
|
|
7765
|
+
};
|
|
7513
7766
|
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
// If the URL changed, no need to inject this param
|
|
7522
|
-
if (relativeUrl !== beforeReplace) {
|
|
7523
|
-
extraParamSet.delete(key);
|
|
7524
|
-
}
|
|
7767
|
+
route.matchesParams = (otherParams) => {
|
|
7768
|
+
const params = route.params;
|
|
7769
|
+
const paramsIsFalsyOrEmpty = !params || Object.keys(params).length === 0;
|
|
7770
|
+
const otherParamsFalsyOrEmpty =
|
|
7771
|
+
!otherParams || Object.keys(otherParams).length === 0;
|
|
7772
|
+
if (paramsIsFalsyOrEmpty) {
|
|
7773
|
+
return otherParamsFalsyOrEmpty;
|
|
7525
7774
|
}
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
// always remove the wildcard part for URL building since it's optional
|
|
7529
|
-
if (relativeUrl.endsWith("/*?")) {
|
|
7530
|
-
// Always remove the optional wildcard part for URL building
|
|
7531
|
-
relativeUrl = relativeUrl.slice(0, -"/*?".length);
|
|
7532
|
-
} else if (relativeUrl.endsWith("{/}?*")) {
|
|
7533
|
-
relativeUrl = relativeUrl.slice(0, -"{/}?*".length);
|
|
7534
|
-
} else {
|
|
7535
|
-
// For required wildcards (/*) or other patterns, replace normally
|
|
7536
|
-
let wildcardIndex = 0;
|
|
7537
|
-
relativeUrl = relativeUrl.replace(/\*/g, () => {
|
|
7538
|
-
const paramKey = wildcardIndex.toString();
|
|
7539
|
-
const paramValue = params[paramKey];
|
|
7540
|
-
if (paramValue) {
|
|
7541
|
-
extraParamSet.delete(paramKey);
|
|
7542
|
-
}
|
|
7543
|
-
const replacement = paramValue ? encodeParamValue(paramValue) : "*";
|
|
7544
|
-
wildcardIndex++;
|
|
7545
|
-
return replacement;
|
|
7546
|
-
});
|
|
7547
|
-
// we did not replace anything, or not enough to remove the last "*"
|
|
7548
|
-
if (relativeUrl.endsWith("*")) {
|
|
7549
|
-
relativeUrl = relativeUrl.slice(0, -1);
|
|
7550
|
-
}
|
|
7775
|
+
if (otherParamsFalsyOrEmpty) {
|
|
7776
|
+
return false;
|
|
7551
7777
|
}
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
const searchParamPairs = [];
|
|
7557
|
-
for (const key of extraParamSet) {
|
|
7558
|
-
const value = params[key];
|
|
7559
|
-
if (value !== undefined && value !== null) {
|
|
7560
|
-
const encodedKey = encodeURIComponent(key);
|
|
7561
|
-
const encodedValue = encodeParamValue(value);
|
|
7562
|
-
searchParamPairs.push(`${encodedKey}=${encodedValue}`);
|
|
7563
|
-
}
|
|
7564
|
-
}
|
|
7565
|
-
if (searchParamPairs.length > 0) {
|
|
7566
|
-
const searchString = searchParamPairs.join("&");
|
|
7567
|
-
relativeUrl += (relativeUrl.includes("?") ? "&" : "?") + searchString;
|
|
7568
|
-
}
|
|
7569
|
-
} else if (extraParamEffect === "warn") {
|
|
7570
|
-
console.warn(
|
|
7571
|
-
`Unknown parameters given to "${urlPatternInput}":`,
|
|
7572
|
-
Array.from(extraParamSet),
|
|
7573
|
-
);
|
|
7778
|
+
const paramsWithoutWildcards = {};
|
|
7779
|
+
for (const key of Object.keys(params)) {
|
|
7780
|
+
if (!Number.isInteger(Number(key))) {
|
|
7781
|
+
paramsWithoutWildcards[key] = params[key];
|
|
7574
7782
|
}
|
|
7575
7783
|
}
|
|
7576
|
-
|
|
7577
|
-
return {
|
|
7578
|
-
relativeUrl,
|
|
7579
|
-
hasRawUrlPartWithInvalidChars,
|
|
7580
|
-
};
|
|
7784
|
+
return compareTwoJsValues(paramsWithoutWildcards, otherParams);
|
|
7581
7785
|
};
|
|
7582
|
-
route.buildRelativeUrl = buildRelativeUrl;
|
|
7583
7786
|
|
|
7584
7787
|
/**
|
|
7585
7788
|
* Builds a complete URL for this route with the given parameters.
|
|
@@ -7607,7 +7810,7 @@ const createRoute = (urlPatternInput) => {
|
|
|
7607
7810
|
processedRelativeUrl = processedRelativeUrl.slice(1);
|
|
7608
7811
|
}
|
|
7609
7812
|
if (hasRawUrlPartWithInvalidChars) {
|
|
7610
|
-
return `${baseUrl}
|
|
7813
|
+
return `${baseUrl}${processedRelativeUrl}`;
|
|
7611
7814
|
}
|
|
7612
7815
|
const url = new URL(processedRelativeUrl, baseUrl).href;
|
|
7613
7816
|
return url;
|
|
@@ -7615,7 +7818,7 @@ const createRoute = (urlPatternInput) => {
|
|
|
7615
7818
|
route.buildUrl = buildUrl;
|
|
7616
7819
|
|
|
7617
7820
|
const activeSignal = signal(false);
|
|
7618
|
-
const paramsSignal = signal(
|
|
7821
|
+
const paramsSignal = signal(null);
|
|
7619
7822
|
const visitedSignal = signal(false);
|
|
7620
7823
|
const relativeUrlSignal = computed(() => {
|
|
7621
7824
|
const params = paramsSignal.value;
|
|
@@ -7644,7 +7847,7 @@ const createRoute = (urlPatternInput) => {
|
|
|
7644
7847
|
if (route.action) {
|
|
7645
7848
|
route.action.replaceParams(updatedParams);
|
|
7646
7849
|
}
|
|
7647
|
-
browserIntegration$1.
|
|
7850
|
+
browserIntegration$1.navTo(updatedUrl, { replace: true });
|
|
7648
7851
|
};
|
|
7649
7852
|
route.replaceParams = replaceParams;
|
|
7650
7853
|
|
|
@@ -7655,7 +7858,7 @@ const createRoute = (urlPatternInput) => {
|
|
|
7655
7858
|
* and listen store changes to do this:
|
|
7656
7859
|
*
|
|
7657
7860
|
* When we detect changes we want to update the route params
|
|
7658
|
-
* so we'll need to use
|
|
7861
|
+
* so we'll need to use navTo(buildUrl(params), { replace: true })
|
|
7659
7862
|
*
|
|
7660
7863
|
* reinserted is useful because the item id might have changed
|
|
7661
7864
|
* but not the mutable key
|
|
@@ -7720,37 +7923,14 @@ const createRoute = (urlPatternInput) => {
|
|
|
7720
7923
|
route.bindAction = bindAction;
|
|
7721
7924
|
|
|
7722
7925
|
{
|
|
7723
|
-
// Remove leading slash from urlPattern to make it relative to baseUrl
|
|
7724
|
-
const normalizedUrlPattern = urlPatternInput.startsWith("/")
|
|
7725
|
-
? urlPatternInput.slice(1)
|
|
7726
|
-
: urlPatternInput;
|
|
7727
|
-
const urlPattern = new URLPattern(normalizedUrlPattern, baseUrl, {
|
|
7728
|
-
ignoreCase: true,
|
|
7729
|
-
});
|
|
7730
|
-
routePrivateProperties.urlPattern = urlPattern;
|
|
7731
7926
|
routePrivateProperties.activeSignal = activeSignal;
|
|
7732
7927
|
routePrivateProperties.paramsSignal = paramsSignal;
|
|
7733
7928
|
routePrivateProperties.visitedSignal = visitedSignal;
|
|
7734
7929
|
routePrivateProperties.relativeUrlSignal = relativeUrlSignal;
|
|
7735
7930
|
routePrivateProperties.urlSignal = urlSignal;
|
|
7736
7931
|
routePrivateProperties.cleanupCallbackSet = cleanupCallbackSet;
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
// Note: Wildcard indices are stored as strings ("0", "1", ...) to match keys from extractParams
|
|
7740
|
-
const optionalParamKeySet = new Set();
|
|
7741
|
-
normalizedUrlPattern.replace(/:([A-Za-z0-9_]+)\?/g, (_m, name) => {
|
|
7742
|
-
optionalParamKeySet.add(name);
|
|
7743
|
-
return "";
|
|
7744
|
-
});
|
|
7745
|
-
let wildcardIndex = 0;
|
|
7746
|
-
normalizedUrlPattern.replace(/\*(\?)?/g, (_m, opt) => {
|
|
7747
|
-
if (opt === "?") {
|
|
7748
|
-
optionalParamKeySet.add(String(wildcardIndex));
|
|
7749
|
-
}
|
|
7750
|
-
wildcardIndex++;
|
|
7751
|
-
return "";
|
|
7752
|
-
});
|
|
7753
|
-
routePrivateProperties.optionalParamKeySet = optionalParamKeySet;
|
|
7932
|
+
const routePattern = createRoutePattern(urlPatternInput, baseUrl);
|
|
7933
|
+
routePrivateProperties.routePattern = routePattern;
|
|
7754
7934
|
}
|
|
7755
7935
|
|
|
7756
7936
|
return route;
|
|
@@ -7943,14 +8123,6 @@ computed(() => {
|
|
|
7943
8123
|
return reasonArray;
|
|
7944
8124
|
});
|
|
7945
8125
|
|
|
7946
|
-
const documentStateSignal = signal(null);
|
|
7947
|
-
const useDocumentState = () => {
|
|
7948
|
-
return documentStateSignal.value;
|
|
7949
|
-
};
|
|
7950
|
-
const updateDocumentState = (value) => {
|
|
7951
|
-
documentStateSignal.value = value;
|
|
7952
|
-
};
|
|
7953
|
-
|
|
7954
8126
|
const documentUrlSignal = signal(window.location.href);
|
|
7955
8127
|
const useDocumentUrl = () => {
|
|
7956
8128
|
return documentUrlSignal.value;
|
|
@@ -7993,6 +8165,14 @@ const urlToScheme = (url) => {
|
|
|
7993
8165
|
return scheme;
|
|
7994
8166
|
};
|
|
7995
8167
|
|
|
8168
|
+
const documentStateSignal = signal(null);
|
|
8169
|
+
const useDocumentState = () => {
|
|
8170
|
+
return documentStateSignal.value;
|
|
8171
|
+
};
|
|
8172
|
+
const updateDocumentState = (value) => {
|
|
8173
|
+
documentStateSignal.value = value;
|
|
8174
|
+
};
|
|
8175
|
+
|
|
7996
8176
|
const getHrefTargetInfo = (href) => {
|
|
7997
8177
|
href = String(href);
|
|
7998
8178
|
|
|
@@ -8213,12 +8393,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
8213
8393
|
});
|
|
8214
8394
|
});
|
|
8215
8395
|
|
|
8216
|
-
const
|
|
8217
|
-
const url = new URL(target, window.location.href).href;
|
|
8218
|
-
const currentUrl = documentUrlSignal.peek();
|
|
8219
|
-
if (url === currentUrl) {
|
|
8220
|
-
return;
|
|
8221
|
-
}
|
|
8396
|
+
const navTo = async (url, { state = null, replace } = {}) => {
|
|
8222
8397
|
if (replace) {
|
|
8223
8398
|
window.history.replaceState(state, null, url);
|
|
8224
8399
|
} else {
|
|
@@ -8227,7 +8402,7 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
8227
8402
|
handleRoutingTask(url, {
|
|
8228
8403
|
state,
|
|
8229
8404
|
replace,
|
|
8230
|
-
reason: `
|
|
8405
|
+
reason: `navTo called with "${url}"`,
|
|
8231
8406
|
});
|
|
8232
8407
|
};
|
|
8233
8408
|
|
|
@@ -8243,11 +8418,11 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
8243
8418
|
});
|
|
8244
8419
|
};
|
|
8245
8420
|
|
|
8246
|
-
const
|
|
8421
|
+
const navBack = () => {
|
|
8247
8422
|
window.history.back();
|
|
8248
8423
|
};
|
|
8249
8424
|
|
|
8250
|
-
const
|
|
8425
|
+
const navForward = () => {
|
|
8251
8426
|
window.history.forward();
|
|
8252
8427
|
};
|
|
8253
8428
|
|
|
@@ -8265,11 +8440,11 @@ const setupBrowserIntegrationViaHistory = ({
|
|
|
8265
8440
|
return {
|
|
8266
8441
|
integration: "browser_history_api",
|
|
8267
8442
|
init,
|
|
8268
|
-
|
|
8443
|
+
navTo,
|
|
8269
8444
|
stop,
|
|
8270
8445
|
reload,
|
|
8271
|
-
|
|
8272
|
-
|
|
8446
|
+
navBack,
|
|
8447
|
+
navForward,
|
|
8273
8448
|
getDocumentState,
|
|
8274
8449
|
replaceDocumentState,
|
|
8275
8450
|
isVisited,
|
|
@@ -8347,7 +8522,17 @@ setOnRouteDefined(() => {
|
|
|
8347
8522
|
setBrowserIntegration(browserIntegration);
|
|
8348
8523
|
|
|
8349
8524
|
const actionIntegratedVia = browserIntegration.integration;
|
|
8350
|
-
const
|
|
8525
|
+
const navTo = (target, options) => {
|
|
8526
|
+
const url = new URL(target, window.location.href).href;
|
|
8527
|
+
const currentUrl = documentUrlSignal.peek();
|
|
8528
|
+
if (url === currentUrl) {
|
|
8529
|
+
return null;
|
|
8530
|
+
}
|
|
8531
|
+
return browserIntegration.navTo(url, options);
|
|
8532
|
+
};
|
|
8533
|
+
const replaceUrl = (target, options = {}) => {
|
|
8534
|
+
return navTo(target, { ...options, replace: true });
|
|
8535
|
+
};
|
|
8351
8536
|
const stopLoad = (reason = "stopLoad() called") => {
|
|
8352
8537
|
const windowIsLoading = windowIsLoadingSignal.value;
|
|
8353
8538
|
if (windowIsLoading) {
|
|
@@ -8359,8 +8544,8 @@ const stopLoad = (reason = "stopLoad() called") => {
|
|
|
8359
8544
|
}
|
|
8360
8545
|
};
|
|
8361
8546
|
const reload = browserIntegration.reload;
|
|
8362
|
-
const
|
|
8363
|
-
const
|
|
8547
|
+
const navBack = browserIntegration.navBack;
|
|
8548
|
+
const navForward = browserIntegration.navForward;
|
|
8364
8549
|
const isVisited = browserIntegration.isVisited;
|
|
8365
8550
|
const visitedUrlsSignal = browserIntegration.visitedUrlsSignal;
|
|
8366
8551
|
browserIntegration.handleActionTask;
|
|
@@ -8450,11 +8635,11 @@ const useUrlSearchParam = (paramName, defaultValue) => {
|
|
|
8450
8635
|
setValue(searchParam);
|
|
8451
8636
|
}
|
|
8452
8637
|
|
|
8453
|
-
const setSearchParamValue = (newValue, { replace =
|
|
8638
|
+
const setSearchParamValue = (newValue, { replace = false } = {}) => {
|
|
8454
8639
|
const newUrlObject = new URL(window.location.href);
|
|
8455
8640
|
newUrlObject.searchParams.set(paramName, newValue);
|
|
8456
8641
|
const newUrl = newUrlObject.href;
|
|
8457
|
-
|
|
8642
|
+
navTo(newUrl, { replace });
|
|
8458
8643
|
};
|
|
8459
8644
|
|
|
8460
8645
|
return [value, setSearchParamValue];
|
|
@@ -8491,6 +8676,26 @@ const useForceRender = () => {
|
|
|
8491
8676
|
const debug$1 = (...args) => {
|
|
8492
8677
|
return;
|
|
8493
8678
|
};
|
|
8679
|
+
|
|
8680
|
+
// Check if a route is a "parent" route (catches multiple routes) and if current URL matches exactly
|
|
8681
|
+
const isParentRouteExactMatch = route => {
|
|
8682
|
+
if (!route) {
|
|
8683
|
+
return false;
|
|
8684
|
+
}
|
|
8685
|
+
const currentUrl = window.location.href;
|
|
8686
|
+
const parentUrl = route.buildUrl();
|
|
8687
|
+
if (currentUrl === parentUrl) {
|
|
8688
|
+
return true;
|
|
8689
|
+
}
|
|
8690
|
+
const currentUrlObject = new URL(currentUrl);
|
|
8691
|
+
if (!currentUrlObject.pathname.endsWith("/")) {
|
|
8692
|
+
return false;
|
|
8693
|
+
}
|
|
8694
|
+
const pathnameWithoutSlash = currentUrlObject.pathname.slice(0, -1);
|
|
8695
|
+
currentUrlObject.pathname = pathnameWithoutSlash;
|
|
8696
|
+
const currentUrlWithoutTrailingSlash = currentUrlObject.href;
|
|
8697
|
+
return currentUrlWithoutTrailingSlash === parentUrl;
|
|
8698
|
+
};
|
|
8494
8699
|
const RootElement = () => {
|
|
8495
8700
|
return jsx(Route.Slot, {});
|
|
8496
8701
|
};
|
|
@@ -8500,7 +8705,10 @@ const Routes = ({
|
|
|
8500
8705
|
element = RootElement,
|
|
8501
8706
|
children
|
|
8502
8707
|
}) => {
|
|
8708
|
+
const routeInfo = useActiveRouteInfo();
|
|
8709
|
+
const route = routeInfo?.route;
|
|
8503
8710
|
return jsx(Route, {
|
|
8711
|
+
route: route,
|
|
8504
8712
|
element: element,
|
|
8505
8713
|
children: children
|
|
8506
8714
|
});
|
|
@@ -8509,6 +8717,7 @@ const useActiveRouteInfo = () => useContext(RouteInfoContext);
|
|
|
8509
8717
|
const Route = ({
|
|
8510
8718
|
element,
|
|
8511
8719
|
route,
|
|
8720
|
+
index,
|
|
8512
8721
|
fallback,
|
|
8513
8722
|
meta,
|
|
8514
8723
|
children
|
|
@@ -8520,6 +8729,7 @@ const Route = ({
|
|
|
8520
8729
|
return jsx(ActiveRouteManager, {
|
|
8521
8730
|
element: element,
|
|
8522
8731
|
route: route,
|
|
8732
|
+
index: index,
|
|
8523
8733
|
fallback: fallback,
|
|
8524
8734
|
meta: meta,
|
|
8525
8735
|
onActiveInfoChange: activeInfo => {
|
|
@@ -8547,6 +8757,7 @@ it's executed once for the entier app lifecycle */
|
|
|
8547
8757
|
const ActiveRouteManager = ({
|
|
8548
8758
|
element,
|
|
8549
8759
|
route,
|
|
8760
|
+
index,
|
|
8550
8761
|
fallback,
|
|
8551
8762
|
meta,
|
|
8552
8763
|
onActiveInfoChange,
|
|
@@ -8556,23 +8767,42 @@ const ActiveRouteManager = ({
|
|
|
8556
8767
|
throw new Error("Route cannot have both route and fallback props");
|
|
8557
8768
|
}
|
|
8558
8769
|
const registerChildRouteFromContext = useContext(RegisterChildRouteContext);
|
|
8559
|
-
getElementSignature(element);
|
|
8770
|
+
const elementId = getElementSignature(element);
|
|
8560
8771
|
const candidateSet = new Set();
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8772
|
+
let indexCandidate = null;
|
|
8773
|
+
let fallbackCandidate = null;
|
|
8774
|
+
const registerChildRoute = childRouteInfo => {
|
|
8775
|
+
const childElementId = getElementSignature(childRouteInfo.element);
|
|
8776
|
+
candidateSet.add(childRouteInfo);
|
|
8777
|
+
if (childRouteInfo.index) {
|
|
8778
|
+
if (indexCandidate) {
|
|
8779
|
+
throw new Error(`Multiple index routes registered under the same parent route (${elementId}):
|
|
8780
|
+
- ${getElementSignature(indexCandidate.element)}
|
|
8781
|
+
- ${childElementId}`);
|
|
8782
|
+
}
|
|
8783
|
+
indexCandidate = childRouteInfo;
|
|
8784
|
+
}
|
|
8785
|
+
if (childRouteInfo.fallback) {
|
|
8786
|
+
if (fallbackCandidate) {
|
|
8787
|
+
throw new Error(`Multiple fallback routes registered under the same parent route (${elementId}):
|
|
8788
|
+
- ${getElementSignature(fallbackCandidate.element)}
|
|
8789
|
+
- ${childElementId}`);
|
|
8790
|
+
}
|
|
8791
|
+
if (childRouteInfo.route.routeFromProps) {
|
|
8792
|
+
throw new Error(`Fallback route cannot have a route prop (${childElementId})`);
|
|
8793
|
+
}
|
|
8794
|
+
fallbackCandidate = childRouteInfo;
|
|
8795
|
+
}
|
|
8569
8796
|
};
|
|
8570
8797
|
useLayoutEffect(() => {
|
|
8571
8798
|
initRouteObserver({
|
|
8572
8799
|
element,
|
|
8573
8800
|
route,
|
|
8801
|
+
index,
|
|
8574
8802
|
fallback,
|
|
8575
8803
|
meta,
|
|
8804
|
+
indexCandidate,
|
|
8805
|
+
fallbackCandidate,
|
|
8576
8806
|
candidateSet,
|
|
8577
8807
|
onActiveInfoChange,
|
|
8578
8808
|
registerChildRouteFromContext
|
|
@@ -8586,15 +8816,24 @@ const ActiveRouteManager = ({
|
|
|
8586
8816
|
const initRouteObserver = ({
|
|
8587
8817
|
element,
|
|
8588
8818
|
route,
|
|
8819
|
+
index,
|
|
8589
8820
|
fallback,
|
|
8590
8821
|
meta,
|
|
8822
|
+
indexCandidate,
|
|
8823
|
+
fallbackCandidate,
|
|
8591
8824
|
candidateSet,
|
|
8592
8825
|
onActiveInfoChange,
|
|
8593
8826
|
registerChildRouteFromContext
|
|
8594
8827
|
}) => {
|
|
8828
|
+
if (!fallbackCandidate && indexCandidate && indexCandidate.fallback !== false) {
|
|
8829
|
+
// no fallback + an index -> index behaves as a fallback (handle urls under a parent when no sibling matches)
|
|
8830
|
+
// to disable this behavior set fallback={false} on the index route
|
|
8831
|
+
// (in that case no route will be rendered when no child matches meaning only parent route element will be shown)
|
|
8832
|
+
fallbackCandidate = indexCandidate;
|
|
8833
|
+
}
|
|
8595
8834
|
const [teardown, addTeardown] = createPubSub();
|
|
8596
8835
|
const elementId = getElementSignature(element);
|
|
8597
|
-
const candidateElementIds = Array.from(candidateSet, c => getElementSignature(c.
|
|
8836
|
+
const candidateElementIds = Array.from(candidateSet, c => getElementSignature(c.element));
|
|
8598
8837
|
if (candidateElementIds.length === 0) ; else {
|
|
8599
8838
|
debug$1(`initRouteObserver ${elementId}, child candidates:
|
|
8600
8839
|
- ${candidateElementIds.join("\n - ")}`);
|
|
@@ -8610,19 +8849,26 @@ const initRouteObserver = ({
|
|
|
8610
8849
|
elementFromProps: element
|
|
8611
8850
|
};
|
|
8612
8851
|
const findActiveChildInfo = () => {
|
|
8613
|
-
let fallbackInfo = null;
|
|
8614
8852
|
for (const candidate of candidateSet) {
|
|
8615
8853
|
if (candidate.route?.active) {
|
|
8616
8854
|
return candidate;
|
|
8617
8855
|
}
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8856
|
+
}
|
|
8857
|
+
if (indexCandidate) {
|
|
8858
|
+
if (indexCandidate === fallbackCandidate) {
|
|
8859
|
+
// the index is also used as fallback (catch all routes under a parent)
|
|
8860
|
+
return indexCandidate;
|
|
8861
|
+
}
|
|
8862
|
+
// Only return the index candidate if the current URL matches exactly the parent route
|
|
8863
|
+
// This allows fallback routes to handle non-defined URLs under this parent route
|
|
8864
|
+
if (route && isParentRouteExactMatch(route)) {
|
|
8865
|
+
return indexCandidate;
|
|
8623
8866
|
}
|
|
8624
8867
|
}
|
|
8625
|
-
|
|
8868
|
+
if (fallbackCandidate) {
|
|
8869
|
+
return fallbackCandidate;
|
|
8870
|
+
}
|
|
8871
|
+
return null;
|
|
8626
8872
|
};
|
|
8627
8873
|
const getActiveInfo = route ? () => {
|
|
8628
8874
|
if (!route.active) {
|
|
@@ -8636,8 +8882,8 @@ const initRouteObserver = ({
|
|
|
8636
8882
|
return activeChildInfo;
|
|
8637
8883
|
}
|
|
8638
8884
|
return {
|
|
8639
|
-
ActiveElement: null,
|
|
8640
8885
|
route,
|
|
8886
|
+
element: null,
|
|
8641
8887
|
meta
|
|
8642
8888
|
};
|
|
8643
8889
|
} : () => {
|
|
@@ -8658,6 +8904,13 @@ const initRouteObserver = ({
|
|
|
8658
8904
|
const Element = element;
|
|
8659
8905
|
element = jsx(Element, {});
|
|
8660
8906
|
}
|
|
8907
|
+
// ensure we re-render on document url change (useful when navigating from /users/list to /users)
|
|
8908
|
+
// so that we re-replace urls back to /users/list when /users/list is an index
|
|
8909
|
+
useDocumentUrl();
|
|
8910
|
+
if (activeRouteInfo && activeRouteInfo.index && !activeRouteInfo.route.active) {
|
|
8911
|
+
const routeUrl = activeRouteInfo.route.routeFromProps.buildUrl();
|
|
8912
|
+
replaceUrl(routeUrl);
|
|
8913
|
+
}
|
|
8661
8914
|
return jsx(RouteInfoContext.Provider, {
|
|
8662
8915
|
value: activeRouteInfo,
|
|
8663
8916
|
children: jsx(SlotContext.Provider, {
|
|
@@ -8672,11 +8925,13 @@ const initRouteObserver = ({
|
|
|
8672
8925
|
if (newActiveInfo) {
|
|
8673
8926
|
compositeRoute.active = true;
|
|
8674
8927
|
activeRouteInfoSignal.value = newActiveInfo;
|
|
8675
|
-
SlotActiveElementSignal.value = newActiveInfo.
|
|
8928
|
+
SlotActiveElementSignal.value = newActiveInfo.element;
|
|
8676
8929
|
onActiveInfoChange({
|
|
8677
|
-
ActiveElement,
|
|
8678
|
-
SlotActiveElement: newActiveInfo.ActiveElement,
|
|
8679
8930
|
route: newActiveInfo.route,
|
|
8931
|
+
ActiveElement,
|
|
8932
|
+
SlotActiveElement: newActiveInfo.element,
|
|
8933
|
+
index: newActiveInfo.index,
|
|
8934
|
+
fallback: newActiveInfo.fallback,
|
|
8680
8935
|
meta: newActiveInfo.meta
|
|
8681
8936
|
});
|
|
8682
8937
|
} else {
|
|
@@ -8697,7 +8952,13 @@ const initRouteObserver = ({
|
|
|
8697
8952
|
addTeardown(candidate.route.subscribeStatus(onChange));
|
|
8698
8953
|
}
|
|
8699
8954
|
if (registerChildRouteFromContext) {
|
|
8700
|
-
registerChildRouteFromContext(
|
|
8955
|
+
registerChildRouteFromContext({
|
|
8956
|
+
route: compositeRoute,
|
|
8957
|
+
element: ActiveElement,
|
|
8958
|
+
index,
|
|
8959
|
+
fallback,
|
|
8960
|
+
meta
|
|
8961
|
+
});
|
|
8701
8962
|
}
|
|
8702
8963
|
updateActiveInfo();
|
|
8703
8964
|
return () => {
|
|
@@ -13731,6 +13992,10 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
13731
13992
|
.navi_text {
|
|
13732
13993
|
position: relative;
|
|
13733
13994
|
color: inherit;
|
|
13995
|
+
|
|
13996
|
+
&[data-has-absolute-child] {
|
|
13997
|
+
display: inline-block;
|
|
13998
|
+
}
|
|
13734
13999
|
}
|
|
13735
14000
|
|
|
13736
14001
|
.navi_text_overflow {
|
|
@@ -13754,6 +14019,53 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
13754
14019
|
|
|
13755
14020
|
.navi_custom_space {
|
|
13756
14021
|
}
|
|
14022
|
+
|
|
14023
|
+
.navi_text_bold_wrapper {
|
|
14024
|
+
position: relative;
|
|
14025
|
+
display: inline-block;
|
|
14026
|
+
}
|
|
14027
|
+
.navi_text_bold_clone {
|
|
14028
|
+
font-weight: bold;
|
|
14029
|
+
opacity: 0;
|
|
14030
|
+
}
|
|
14031
|
+
.navi_text_bold_foreground {
|
|
14032
|
+
position: absolute;
|
|
14033
|
+
inset: 0;
|
|
14034
|
+
}
|
|
14035
|
+
|
|
14036
|
+
.navi_text_bold_background {
|
|
14037
|
+
position: absolute;
|
|
14038
|
+
top: 0;
|
|
14039
|
+
left: 0;
|
|
14040
|
+
color: currentColor;
|
|
14041
|
+
font-weight: normal;
|
|
14042
|
+
background: currentColor;
|
|
14043
|
+
background-clip: text;
|
|
14044
|
+
-webkit-background-clip: text;
|
|
14045
|
+
transform-origin: center;
|
|
14046
|
+
-webkit-text-fill-color: transparent;
|
|
14047
|
+
opacity: 0;
|
|
14048
|
+
}
|
|
14049
|
+
|
|
14050
|
+
.navi_text[data-bold] {
|
|
14051
|
+
.navi_text_bold_background {
|
|
14052
|
+
opacity: 1;
|
|
14053
|
+
}
|
|
14054
|
+
}
|
|
14055
|
+
|
|
14056
|
+
.navi_text[data-bold-transition] {
|
|
14057
|
+
.navi_text_bold_foreground {
|
|
14058
|
+
transition-property: font-weight;
|
|
14059
|
+
transition-duration: 0.3s;
|
|
14060
|
+
transition-timing-function: ease;
|
|
14061
|
+
}
|
|
14062
|
+
|
|
14063
|
+
.navi_text_bold_background {
|
|
14064
|
+
transition-property: opacity;
|
|
14065
|
+
transition-duration: 0.3s;
|
|
14066
|
+
transition-timing-function: ease;
|
|
14067
|
+
}
|
|
14068
|
+
}
|
|
13757
14069
|
`;
|
|
13758
14070
|
const REGULAR_SPACE = jsx("span", {
|
|
13759
14071
|
"data-navi-space": "",
|
|
@@ -13923,14 +14235,65 @@ const TextWithSelectRange = ({
|
|
|
13923
14235
|
};
|
|
13924
14236
|
const TextBasic = ({
|
|
13925
14237
|
spacing = " ",
|
|
14238
|
+
boldTransition,
|
|
14239
|
+
boldStable,
|
|
14240
|
+
preventBoldLayoutShift = boldTransition,
|
|
13926
14241
|
children,
|
|
13927
14242
|
...rest
|
|
13928
14243
|
}) => {
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
14244
|
+
const shouldPreserveSpacing = rest.as === "pre" || rest.box || rest.column || rest.row;
|
|
14245
|
+
if (!shouldPreserveSpacing) {
|
|
14246
|
+
children = applySpacingOnTextChildren(children, spacing);
|
|
14247
|
+
}
|
|
14248
|
+
const boxProps = {
|
|
14249
|
+
"as": "span",
|
|
14250
|
+
"data-bold-transition": boldTransition ? "" : undefined,
|
|
13932
14251
|
...rest,
|
|
13933
|
-
|
|
14252
|
+
"baseClassName": withPropsClassName("navi_text", rest.baseClassName)
|
|
14253
|
+
};
|
|
14254
|
+
if (boldStable) {
|
|
14255
|
+
const {
|
|
14256
|
+
bold
|
|
14257
|
+
} = boxProps;
|
|
14258
|
+
return jsxs(Box, {
|
|
14259
|
+
...boxProps,
|
|
14260
|
+
bold: undefined,
|
|
14261
|
+
"data-bold": bold ? "" : undefined,
|
|
14262
|
+
"data-has-absolute-child": "",
|
|
14263
|
+
children: [jsx("span", {
|
|
14264
|
+
className: "navi_text_bold_background",
|
|
14265
|
+
"aria-hidden": "true",
|
|
14266
|
+
children: children
|
|
14267
|
+
}), children]
|
|
14268
|
+
});
|
|
14269
|
+
}
|
|
14270
|
+
if (preventBoldLayoutShift) {
|
|
14271
|
+
const alignX = rest.alignX || rest.align || "start";
|
|
14272
|
+
|
|
14273
|
+
// La technique consiste a avoid un double gras qui force une taille
|
|
14274
|
+
// et la version light par dessus en position absolute
|
|
14275
|
+
// on la centre aussi pour donner l'impression que le gras s'applique depuis le centre
|
|
14276
|
+
// ne fonctionne que sur une seul ligne de texte (donc lorsque noWrap est actif)
|
|
14277
|
+
// on pourrait auto-active cela sur une prop genre boldCanChange
|
|
14278
|
+
return jsx(Box, {
|
|
14279
|
+
...boxProps,
|
|
14280
|
+
children: jsxs("span", {
|
|
14281
|
+
className: "navi_text_bold_wrapper",
|
|
14282
|
+
children: [jsx("span", {
|
|
14283
|
+
className: "navi_text_bold_clone",
|
|
14284
|
+
"aria-hidden": "true",
|
|
14285
|
+
children: children
|
|
14286
|
+
}), jsx("span", {
|
|
14287
|
+
className: "navi_text_bold_foreground",
|
|
14288
|
+
"data-align": alignX,
|
|
14289
|
+
children: children
|
|
14290
|
+
})]
|
|
14291
|
+
})
|
|
14292
|
+
});
|
|
14293
|
+
}
|
|
14294
|
+
return jsx(Box, {
|
|
14295
|
+
...boxProps,
|
|
14296
|
+
children: children
|
|
13934
14297
|
});
|
|
13935
14298
|
};
|
|
13936
14299
|
|
|
@@ -16399,14 +16762,15 @@ const RouteLink = ({
|
|
|
16399
16762
|
}
|
|
16400
16763
|
const routeStatus = useRouteStatus(route);
|
|
16401
16764
|
const url = route.buildUrl(routeParams);
|
|
16402
|
-
const
|
|
16765
|
+
const active = routeStatus.active;
|
|
16766
|
+
const paramsAreMatching = route.matchesParams(routeParams);
|
|
16403
16767
|
return jsx(Link, {
|
|
16404
16768
|
...rest,
|
|
16405
16769
|
href: url,
|
|
16406
16770
|
pseudoState: {
|
|
16407
|
-
":-navi-href-current":
|
|
16771
|
+
":-navi-href-current": active && paramsAreMatching
|
|
16408
16772
|
},
|
|
16409
|
-
children: children
|
|
16773
|
+
children: children || route.buildRelativeUrl(routeParams)
|
|
16410
16774
|
});
|
|
16411
16775
|
};
|
|
16412
16776
|
|
|
@@ -16428,8 +16792,9 @@ import.meta.css = /* css */`
|
|
|
16428
16792
|
--tab-color: inherit;
|
|
16429
16793
|
--tab-color-hover: #010409;
|
|
16430
16794
|
--tab-color-selected: inherit;
|
|
16431
|
-
--tab-
|
|
16432
|
-
--tab-
|
|
16795
|
+
--tab-indicator-size: 2px;
|
|
16796
|
+
--tab-indicator-spacing: 5px;
|
|
16797
|
+
--tab-indicator-color: rgb(205, 52, 37);
|
|
16433
16798
|
}
|
|
16434
16799
|
}
|
|
16435
16800
|
|
|
@@ -16438,100 +16803,175 @@ import.meta.css = /* css */`
|
|
|
16438
16803
|
line-height: 2em;
|
|
16439
16804
|
overflow-x: auto;
|
|
16440
16805
|
overflow-y: hidden;
|
|
16441
|
-
}
|
|
16442
|
-
.navi_tablist > ul {
|
|
16443
|
-
display: flex;
|
|
16444
|
-
width: 100%;
|
|
16445
|
-
margin: 0;
|
|
16446
|
-
padding: 0;
|
|
16447
|
-
align-items: center;
|
|
16448
|
-
gap: 0.5rem;
|
|
16449
|
-
list-style: none;
|
|
16450
|
-
background: var(--tablist-background);
|
|
16451
|
-
border-radius: var(--tablist-border-radius);
|
|
16452
|
-
}
|
|
16453
|
-
.navi_tablist > ul > li {
|
|
16454
|
-
position: relative;
|
|
16455
|
-
display: inline-flex;
|
|
16456
|
-
}
|
|
16457
|
-
|
|
16458
|
-
.navi_tab {
|
|
16459
|
-
--x-tab-background: var(--tab-background);
|
|
16460
|
-
--x-tab-color: var(--tab-color);
|
|
16461
16806
|
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
border-radius: var(--tab-border-radius);
|
|
16466
|
-
|
|
16467
|
-
.navi_tab_content {
|
|
16468
|
-
display: flex;
|
|
16469
|
-
color: var(--x-tab-color);
|
|
16470
|
-
background: var(--x-tab-background);
|
|
16471
|
-
border-radius: inherit;
|
|
16472
|
-
transition: background 0.12s ease-out;
|
|
16473
|
-
|
|
16474
|
-
.navi_link {
|
|
16475
|
-
flex-grow: 1;
|
|
16476
|
-
text-align: center;
|
|
16477
|
-
border-radius: inherit;
|
|
16807
|
+
&[data-tab-indicator-position="start"] {
|
|
16808
|
+
.navi_tab {
|
|
16809
|
+
margin-top: var(--tab-indicator-spacing);
|
|
16478
16810
|
}
|
|
16479
16811
|
}
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
font-weight: 600; /* force bold to compute max width */
|
|
16485
|
-
visibility: hidden; /* not visible */
|
|
16486
|
-
pointer-events: none; /* inert */
|
|
16487
|
-
overflow: hidden; /* avoid any accidental height */
|
|
16812
|
+
&[data-tab-indicator-position="end"] {
|
|
16813
|
+
.navi_tab {
|
|
16814
|
+
margin-bottom: var(--tab-indicator-spacing);
|
|
16815
|
+
}
|
|
16488
16816
|
}
|
|
16489
|
-
|
|
16490
|
-
|
|
16817
|
+
|
|
16818
|
+
> ul {
|
|
16491
16819
|
display: flex;
|
|
16492
16820
|
width: 100%;
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16821
|
+
margin: 0;
|
|
16822
|
+
padding: 2px; /* space for border radius and outline */
|
|
16823
|
+
align-items: center;
|
|
16824
|
+
gap: 0.5rem;
|
|
16825
|
+
list-style: none;
|
|
16826
|
+
background: var(--tablist-background);
|
|
16827
|
+
border-radius: var(--tablist-border-radius);
|
|
16498
16828
|
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16829
|
+
> li {
|
|
16830
|
+
position: relative;
|
|
16831
|
+
display: inline-flex;
|
|
16832
|
+
|
|
16833
|
+
.navi_tab {
|
|
16834
|
+
--x-tab-background: var(--tab-background);
|
|
16835
|
+
--x-tab-color: var(--tab-color);
|
|
16836
|
+
|
|
16837
|
+
display: flex;
|
|
16838
|
+
flex-direction: column;
|
|
16839
|
+
color: var(--x-tab-color);
|
|
16840
|
+
white-space: nowrap;
|
|
16841
|
+
background: var(--x-tab-background);
|
|
16842
|
+
border-radius: var(--tab-border-radius);
|
|
16843
|
+
transition: background 0.12s ease-out;
|
|
16844
|
+
user-select: none;
|
|
16845
|
+
|
|
16846
|
+
span,
|
|
16847
|
+
a {
|
|
16848
|
+
display: inline-flex;
|
|
16849
|
+
flex-grow: 1;
|
|
16850
|
+
justify-content: center;
|
|
16851
|
+
text-align: center;
|
|
16852
|
+
border-radius: inherit;
|
|
16853
|
+
}
|
|
16854
|
+
|
|
16855
|
+
.navi_tab_indicator {
|
|
16856
|
+
position: absolute;
|
|
16857
|
+
z-index: 1;
|
|
16858
|
+
display: flex;
|
|
16859
|
+
width: 100%;
|
|
16860
|
+
height: var(--tab-indicator-size);
|
|
16861
|
+
background: transparent;
|
|
16862
|
+
border-radius: 0.1px;
|
|
16863
|
+
|
|
16864
|
+
&[data-position="start"] {
|
|
16865
|
+
top: 0;
|
|
16866
|
+
left: 0;
|
|
16867
|
+
}
|
|
16868
|
+
|
|
16869
|
+
&[data-position="end"] {
|
|
16870
|
+
bottom: 0;
|
|
16871
|
+
left: 0;
|
|
16872
|
+
}
|
|
16873
|
+
}
|
|
16874
|
+
|
|
16875
|
+
/* Interactive */
|
|
16876
|
+
&[data-interactive] {
|
|
16877
|
+
cursor: pointer;
|
|
16878
|
+
}
|
|
16879
|
+
/* Hover */
|
|
16880
|
+
&:hover {
|
|
16881
|
+
--x-tab-background: var(--tab-background-hover);
|
|
16882
|
+
--x-tab-color: var(--tab-color-hover);
|
|
16883
|
+
}
|
|
16884
|
+
/* Selected */
|
|
16885
|
+
&[data-selected] {
|
|
16886
|
+
--x-tab-background: var(--tab-background-selected);
|
|
16887
|
+
--x-tab-color: var(--tab-color-selected);
|
|
16888
|
+
font-weight: bold;
|
|
16889
|
+
|
|
16890
|
+
.navi_tab_indicator {
|
|
16891
|
+
background: var(--tab-indicator-color);
|
|
16892
|
+
}
|
|
16893
|
+
}
|
|
16894
|
+
}
|
|
16895
|
+
}
|
|
16507
16896
|
}
|
|
16508
|
-
/* Selected */
|
|
16509
|
-
&[data-selected] {
|
|
16510
|
-
--x-tab-background: var(--tab-background-selected);
|
|
16511
|
-
--x-tab-color: var(--tab-color-selected);
|
|
16512
16897
|
|
|
16513
|
-
|
|
16514
|
-
|
|
16898
|
+
/* Vertical layout */
|
|
16899
|
+
&[data-vertical] {
|
|
16900
|
+
overflow-x: hidden;
|
|
16901
|
+
overflow-y: auto;
|
|
16902
|
+
|
|
16903
|
+
.navi_tab {
|
|
16904
|
+
span,
|
|
16905
|
+
a {
|
|
16906
|
+
justify-content: start;
|
|
16907
|
+
}
|
|
16908
|
+
|
|
16909
|
+
&[data-align-x="end"] {
|
|
16910
|
+
span,
|
|
16911
|
+
a {
|
|
16912
|
+
justify-content: end;
|
|
16913
|
+
}
|
|
16914
|
+
}
|
|
16915
|
+
}
|
|
16916
|
+
|
|
16917
|
+
&[data-tab-indicator-position="start"] {
|
|
16918
|
+
.navi_tab {
|
|
16919
|
+
margin-top: 0;
|
|
16920
|
+
margin-left: var(--tab-indicator-spacing);
|
|
16921
|
+
|
|
16922
|
+
.navi_tab_indicator {
|
|
16923
|
+
top: 0;
|
|
16924
|
+
left: 0;
|
|
16925
|
+
}
|
|
16926
|
+
}
|
|
16515
16927
|
}
|
|
16516
|
-
|
|
16517
|
-
|
|
16928
|
+
&[data-tab-indicator-position="end"] {
|
|
16929
|
+
.navi_tab {
|
|
16930
|
+
margin-right: var(--tab-indicator-spacing);
|
|
16931
|
+
margin-bottom: 0;
|
|
16932
|
+
|
|
16933
|
+
.navi_tab_indicator {
|
|
16934
|
+
top: 0;
|
|
16935
|
+
right: 0;
|
|
16936
|
+
left: auto;
|
|
16937
|
+
}
|
|
16938
|
+
}
|
|
16518
16939
|
}
|
|
16519
|
-
}
|
|
16520
|
-
}
|
|
16521
16940
|
|
|
16522
|
-
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
|
|
16941
|
+
> ul {
|
|
16942
|
+
flex-direction: column;
|
|
16943
|
+
align-items: start;
|
|
16944
|
+
|
|
16945
|
+
> li {
|
|
16946
|
+
width: 100%;
|
|
16947
|
+
|
|
16948
|
+
.navi_tab {
|
|
16949
|
+
flex-direction: row;
|
|
16950
|
+
text-align: left;
|
|
16951
|
+
|
|
16952
|
+
.navi_tab_indicator {
|
|
16953
|
+
width: var(--tab-indicator-size);
|
|
16954
|
+
height: 100%;
|
|
16955
|
+
}
|
|
16956
|
+
}
|
|
16957
|
+
}
|
|
16958
|
+
}
|
|
16526
16959
|
}
|
|
16527
16960
|
|
|
16528
|
-
|
|
16529
|
-
|
|
16530
|
-
|
|
16961
|
+
&[data-expand] {
|
|
16962
|
+
> ul {
|
|
16963
|
+
.navi_tab {
|
|
16964
|
+
width: 100%;
|
|
16965
|
+
flex: 1;
|
|
16966
|
+
align-items: stretch;
|
|
16967
|
+
justify-content: center;
|
|
16968
|
+
}
|
|
16969
|
+
}
|
|
16531
16970
|
}
|
|
16532
16971
|
}
|
|
16533
16972
|
`;
|
|
16534
|
-
const
|
|
16973
|
+
const TabListIndicatorContext = createContext();
|
|
16974
|
+
const TabListAlignXContext = createContext();
|
|
16535
16975
|
const TabListStyleCSSVars = {
|
|
16536
16976
|
borderRadius: "--tablist-border-radius",
|
|
16537
16977
|
background: "--tablist-background"
|
|
@@ -16539,7 +16979,9 @@ const TabListStyleCSSVars = {
|
|
|
16539
16979
|
const TabList = ({
|
|
16540
16980
|
children,
|
|
16541
16981
|
spacing,
|
|
16542
|
-
|
|
16982
|
+
vertical,
|
|
16983
|
+
indicator = vertical ? "start" : "end",
|
|
16984
|
+
alignX,
|
|
16543
16985
|
expand,
|
|
16544
16986
|
expandX,
|
|
16545
16987
|
paddingX,
|
|
@@ -16547,11 +16989,14 @@ const TabList = ({
|
|
|
16547
16989
|
padding,
|
|
16548
16990
|
...props
|
|
16549
16991
|
}) => {
|
|
16992
|
+
children = toChildArray(children);
|
|
16550
16993
|
return jsx(Box, {
|
|
16551
16994
|
as: "nav",
|
|
16552
16995
|
baseClassName: "navi_tablist",
|
|
16553
16996
|
role: "tablist",
|
|
16997
|
+
"data-tab-indicator-position": indicator === "start" || indicator === "end" ? indicator : undefined,
|
|
16554
16998
|
"data-expand": expand || expandX ? "" : undefined,
|
|
16999
|
+
"data-vertical": vertical ? "" : undefined,
|
|
16555
17000
|
expand: expand,
|
|
16556
17001
|
expandX: expandX,
|
|
16557
17002
|
...props,
|
|
@@ -16564,16 +17009,19 @@ const TabList = ({
|
|
|
16564
17009
|
paddingY: paddingY,
|
|
16565
17010
|
padding: padding,
|
|
16566
17011
|
spacing: spacing,
|
|
16567
|
-
children: jsx(
|
|
16568
|
-
value:
|
|
16569
|
-
children:
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
17012
|
+
children: jsx(TabListIndicatorContext.Provider, {
|
|
17013
|
+
value: indicator,
|
|
17014
|
+
children: jsx(TabListAlignXContext.Provider, {
|
|
17015
|
+
value: alignX,
|
|
17016
|
+
children: children.map(child => {
|
|
17017
|
+
return jsx(Box, {
|
|
17018
|
+
as: "li",
|
|
17019
|
+
column: true,
|
|
17020
|
+
expandX: expandX,
|
|
17021
|
+
expand: expand,
|
|
17022
|
+
children: child
|
|
17023
|
+
}, child.props.key);
|
|
17024
|
+
})
|
|
16577
17025
|
})
|
|
16578
17026
|
})
|
|
16579
17027
|
})
|
|
@@ -16592,7 +17040,7 @@ const TAB_STYLE_CSS_VARS = {
|
|
|
16592
17040
|
}
|
|
16593
17041
|
};
|
|
16594
17042
|
const TAB_PSEUDO_CLASSES = [":hover", ":-navi-selected"];
|
|
16595
|
-
const TAB_PSEUDO_ELEMENTS = ["::-navi-
|
|
17043
|
+
const TAB_PSEUDO_ELEMENTS = ["::-navi-indicator"];
|
|
16596
17044
|
const Tab = props => {
|
|
16597
17045
|
if (props.route) {
|
|
16598
17046
|
return jsx(TabRoute, {
|
|
@@ -16603,8 +17051,10 @@ const Tab = props => {
|
|
|
16603
17051
|
...props
|
|
16604
17052
|
});
|
|
16605
17053
|
};
|
|
17054
|
+
TabList.Tab = Tab;
|
|
16606
17055
|
const TabRoute = ({
|
|
16607
17056
|
route,
|
|
17057
|
+
routeParams,
|
|
16608
17058
|
children,
|
|
16609
17059
|
paddingX,
|
|
16610
17060
|
padding,
|
|
@@ -16614,15 +17064,17 @@ const TabRoute = ({
|
|
|
16614
17064
|
const {
|
|
16615
17065
|
active
|
|
16616
17066
|
} = useRouteStatus(route);
|
|
17067
|
+
const paramsAreMatching = route.matchesParams(routeParams);
|
|
17068
|
+
const selected = active && paramsAreMatching;
|
|
16617
17069
|
return jsx(TabBasic, {
|
|
16618
|
-
selected:
|
|
17070
|
+
selected: selected,
|
|
16619
17071
|
paddingX: "0",
|
|
16620
17072
|
...props,
|
|
16621
17073
|
children: jsx(RouteLink, {
|
|
16622
17074
|
route: route,
|
|
17075
|
+
routeParams: routeParams,
|
|
16623
17076
|
expand: true,
|
|
16624
17077
|
discrete: true,
|
|
16625
|
-
align: "center",
|
|
16626
17078
|
paddingX: paddingX,
|
|
16627
17079
|
padding: padding,
|
|
16628
17080
|
paddingY: paddingY,
|
|
@@ -16633,18 +17085,17 @@ const TabRoute = ({
|
|
|
16633
17085
|
const TabBasic = ({
|
|
16634
17086
|
children,
|
|
16635
17087
|
selected,
|
|
16636
|
-
padding,
|
|
16637
|
-
paddingX = "s",
|
|
16638
|
-
paddingY,
|
|
16639
17088
|
onClick,
|
|
16640
17089
|
...props
|
|
16641
17090
|
}) => {
|
|
16642
|
-
const
|
|
17091
|
+
const tabListIndicator = useContext(TabListIndicatorContext);
|
|
17092
|
+
const tabListAlignX = useContext(TabListAlignXContext);
|
|
16643
17093
|
return jsxs(Box, {
|
|
16644
17094
|
role: "tab",
|
|
16645
17095
|
"aria-selected": selected ? "true" : "false",
|
|
16646
17096
|
"data-interactive": onClick ? "" : undefined,
|
|
16647
|
-
onClick: onClick
|
|
17097
|
+
onClick: onClick,
|
|
17098
|
+
paddingX: "s"
|
|
16648
17099
|
// Style system
|
|
16649
17100
|
,
|
|
16650
17101
|
baseClassName: "navi_tab",
|
|
@@ -16654,19 +17105,18 @@ const TabBasic = ({
|
|
|
16654
17105
|
basePseudoState: {
|
|
16655
17106
|
":-navi-selected": selected
|
|
16656
17107
|
},
|
|
17108
|
+
selfAlignX: tabListAlignX,
|
|
17109
|
+
"data-align-x": tabListAlignX,
|
|
16657
17110
|
...props,
|
|
16658
|
-
children: [jsx(
|
|
16659
|
-
className: "
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
"aria-hidden": "true",
|
|
17111
|
+
children: [(tabListIndicator === "start" || tabListIndicator === "end") && jsx("span", {
|
|
17112
|
+
className: "navi_tab_indicator",
|
|
17113
|
+
"data-position": tabListIndicator
|
|
17114
|
+
}), jsx(Text, {
|
|
17115
|
+
noWrap: true,
|
|
17116
|
+
preventBoldLayoutShift: true
|
|
17117
|
+
// boldTransition
|
|
17118
|
+
,
|
|
16667
17119
|
children: children
|
|
16668
|
-
}), tabListUnderline && jsx("span", {
|
|
16669
|
-
className: "navi_tab_selected_marker"
|
|
16670
17120
|
})]
|
|
16671
17121
|
});
|
|
16672
17122
|
};
|
|
@@ -23787,5 +24237,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
23787
24237
|
})
|
|
23788
24238
|
});
|
|
23789
24239
|
|
|
23790
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, BadgeCount, Box, Button, Caption, CheckSvg, Checkbox, CheckboxList, Code, Col, Colgroup, Details, DialogLayout, Editable, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, MessageBox, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, SearchSvg, Select, SelectionContext, SettingsSvg, StarSvg, SummaryMarker, Svg, Tab, TabList, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, addCustomMessage, compareTwoJsValues, createAction, createRequestCanceller, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested,
|
|
24240
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, BadgeCount, Box, Button, Caption, CheckSvg, Checkbox, CheckboxList, Code, Col, Colgroup, Details, DialogLayout, Editable, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, MessageBox, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, SearchSvg, Select, SelectionContext, SettingsSvg, StarSvg, SummaryMarker, Svg, Tab, TabList, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, addCustomMessage, compareTwoJsValues, createAction, createRequestCanceller, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useActiveRouteInfo, useCellsAndColumns, useConstraintValidityState, useDependenciesDiff, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState$1 as useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, useUrlSearchParam, valueInLocalStorage };
|
|
23791
24241
|
//# sourceMappingURL=jsenv_navi.js.map
|