@jsenv/navi 0.13.3 → 0.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jsenv_navi.js +380 -188
- package/dist/jsenv_navi.js.map +9 -5
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -2103,6 +2103,340 @@ const localStorageSignal = (key) => {
|
|
|
2103
2103
|
return valueSignal;
|
|
2104
2104
|
};
|
|
2105
2105
|
|
|
2106
|
+
const valueInLocalStorage = (
|
|
2107
|
+
key,
|
|
2108
|
+
{ type = "string", fallback } = {},
|
|
2109
|
+
) => {
|
|
2110
|
+
const converter = typeConverters[type];
|
|
2111
|
+
if (converter === undefined) {
|
|
2112
|
+
console.warn(
|
|
2113
|
+
`Invalid type "${type}" for "${key}" in local storage, expected one of ${Object.keys(
|
|
2114
|
+
typeConverters,
|
|
2115
|
+
).join(", ")}`,
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2118
|
+
const getValidityMessage = (
|
|
2119
|
+
valueToCheck,
|
|
2120
|
+
valueInLocalStorage = valueToCheck,
|
|
2121
|
+
) => {
|
|
2122
|
+
if (!converter) {
|
|
2123
|
+
return "";
|
|
2124
|
+
}
|
|
2125
|
+
if (!converter.checkValidity) {
|
|
2126
|
+
return "";
|
|
2127
|
+
}
|
|
2128
|
+
const checkValidityResult = converter.checkValidity(valueToCheck);
|
|
2129
|
+
if (checkValidityResult === false) {
|
|
2130
|
+
return `${valueInLocalStorage}`;
|
|
2131
|
+
}
|
|
2132
|
+
if (!checkValidityResult) {
|
|
2133
|
+
return "";
|
|
2134
|
+
}
|
|
2135
|
+
return `${checkValidityResult}, got "${valueInLocalStorage}"`;
|
|
2136
|
+
};
|
|
2137
|
+
|
|
2138
|
+
const get = () => {
|
|
2139
|
+
let valueInLocalStorage = window.localStorage.getItem(key);
|
|
2140
|
+
if (valueInLocalStorage === null) {
|
|
2141
|
+
return fallback;
|
|
2142
|
+
}
|
|
2143
|
+
if (converter && converter.decode) {
|
|
2144
|
+
const valueDecoded = converter.decode(valueInLocalStorage);
|
|
2145
|
+
const validityMessage = getValidityMessage(
|
|
2146
|
+
valueDecoded,
|
|
2147
|
+
valueInLocalStorage,
|
|
2148
|
+
);
|
|
2149
|
+
if (validityMessage) {
|
|
2150
|
+
console.warn(
|
|
2151
|
+
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
2152
|
+
);
|
|
2153
|
+
return undefined;
|
|
2154
|
+
}
|
|
2155
|
+
return valueDecoded;
|
|
2156
|
+
}
|
|
2157
|
+
const validityMessage = getValidityMessage(valueInLocalStorage);
|
|
2158
|
+
if (validityMessage) {
|
|
2159
|
+
console.warn(
|
|
2160
|
+
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
2161
|
+
);
|
|
2162
|
+
return undefined;
|
|
2163
|
+
}
|
|
2164
|
+
return valueInLocalStorage;
|
|
2165
|
+
};
|
|
2166
|
+
const set = (value) => {
|
|
2167
|
+
if (value === undefined) {
|
|
2168
|
+
window.localStorage.removeItem(key);
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
const validityMessage = getValidityMessage(value);
|
|
2172
|
+
if (validityMessage) {
|
|
2173
|
+
console.warn(
|
|
2174
|
+
`The value to set in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
if (converter && converter.encode) {
|
|
2178
|
+
const valueEncoded = converter.encode(value);
|
|
2179
|
+
window.localStorage.setItem(key, valueEncoded);
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
window.localStorage.setItem(key, value);
|
|
2183
|
+
};
|
|
2184
|
+
const remove = () => {
|
|
2185
|
+
window.localStorage.removeItem(key);
|
|
2186
|
+
};
|
|
2187
|
+
|
|
2188
|
+
return [get, set, remove];
|
|
2189
|
+
};
|
|
2190
|
+
|
|
2191
|
+
const createNumberValidator = ({ min, max, step } = {}) => {
|
|
2192
|
+
return {
|
|
2193
|
+
decode: (value) => {
|
|
2194
|
+
const valueParsed = parseFloat(value);
|
|
2195
|
+
return valueParsed;
|
|
2196
|
+
},
|
|
2197
|
+
checkValidity: (value) => {
|
|
2198
|
+
if (typeof value !== "number") {
|
|
2199
|
+
return `must be a number`;
|
|
2200
|
+
}
|
|
2201
|
+
if (!Number.isFinite(value)) {
|
|
2202
|
+
return `must be finite`;
|
|
2203
|
+
}
|
|
2204
|
+
if (min !== undefined && value < min) {
|
|
2205
|
+
return min === 0 ? `must be positive` : `must be >= ${min}`;
|
|
2206
|
+
}
|
|
2207
|
+
if (max !== undefined && value > max) {
|
|
2208
|
+
return max === 0 ? `must be negative` : `must be <= ${max}`;
|
|
2209
|
+
}
|
|
2210
|
+
if (step !== undefined) {
|
|
2211
|
+
const remainder = (value - (min || 0)) % step;
|
|
2212
|
+
const epsilon = 0.0000001;
|
|
2213
|
+
if (remainder > epsilon && step - remainder > epsilon) {
|
|
2214
|
+
if (step === 1) {
|
|
2215
|
+
return `must be an integer`;
|
|
2216
|
+
}
|
|
2217
|
+
return `must be a multiple of ${step}`;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
return "";
|
|
2221
|
+
},
|
|
2222
|
+
};
|
|
2223
|
+
};
|
|
2224
|
+
const typeConverters = {
|
|
2225
|
+
boolean: {
|
|
2226
|
+
checkValidity: (value) => {
|
|
2227
|
+
if (typeof value !== "boolean") {
|
|
2228
|
+
return `must be a boolean`;
|
|
2229
|
+
}
|
|
2230
|
+
return "";
|
|
2231
|
+
},
|
|
2232
|
+
decode: (value) => {
|
|
2233
|
+
return value === "true";
|
|
2234
|
+
},
|
|
2235
|
+
encode: (value) => {
|
|
2236
|
+
return value ? "true" : "false";
|
|
2237
|
+
},
|
|
2238
|
+
},
|
|
2239
|
+
string: {
|
|
2240
|
+
checkValidity: (value) => {
|
|
2241
|
+
if (typeof value !== "string") {
|
|
2242
|
+
return `must be a string`;
|
|
2243
|
+
}
|
|
2244
|
+
return "";
|
|
2245
|
+
},
|
|
2246
|
+
},
|
|
2247
|
+
number: createNumberValidator(),
|
|
2248
|
+
float: createNumberValidator(),
|
|
2249
|
+
positive_number: createNumberValidator({ min: 0 }),
|
|
2250
|
+
integer: createNumberValidator({ step: 1 }),
|
|
2251
|
+
positive_integer: createNumberValidator({ min: 0, step: 1 }),
|
|
2252
|
+
percentage: {
|
|
2253
|
+
checkValidity: (value) => {
|
|
2254
|
+
if (typeof value !== "string") {
|
|
2255
|
+
return `must be a percentage`;
|
|
2256
|
+
}
|
|
2257
|
+
if (!value.endsWith("%")) {
|
|
2258
|
+
return `must end with %`;
|
|
2259
|
+
}
|
|
2260
|
+
const percentageString = value.slice(0, -1);
|
|
2261
|
+
const percentageFloat = parseFloat(percentageString);
|
|
2262
|
+
if (typeof percentageFloat !== "number") {
|
|
2263
|
+
return `must be a percentage`;
|
|
2264
|
+
}
|
|
2265
|
+
if (percentageFloat < 0 || percentageFloat > 100) {
|
|
2266
|
+
return `must be between 0 and 100`;
|
|
2267
|
+
}
|
|
2268
|
+
return "";
|
|
2269
|
+
},
|
|
2270
|
+
},
|
|
2271
|
+
object: {
|
|
2272
|
+
decode: (value) => {
|
|
2273
|
+
const valueParsed = JSON.parse(value);
|
|
2274
|
+
return valueParsed;
|
|
2275
|
+
},
|
|
2276
|
+
encode: (value) => {
|
|
2277
|
+
const valueStringified = JSON.stringify(value);
|
|
2278
|
+
return valueStringified;
|
|
2279
|
+
},
|
|
2280
|
+
checkValidity: (value) => {
|
|
2281
|
+
if (value === null || typeof value !== "object") {
|
|
2282
|
+
return `must be an object`;
|
|
2283
|
+
}
|
|
2284
|
+
return "";
|
|
2285
|
+
},
|
|
2286
|
+
},
|
|
2287
|
+
};
|
|
2288
|
+
|
|
2289
|
+
/**
|
|
2290
|
+
* Creates an advanced signal with optional source signal synchronization and local storage persistence.
|
|
2291
|
+
*
|
|
2292
|
+
* The sourceSignal option creates a fallback mechanism where:
|
|
2293
|
+
* 1. The signal initially takes the value from sourceSignal (if defined) or falls back to defaultValue
|
|
2294
|
+
* 2. The signal can be manually overridden with any value
|
|
2295
|
+
* 3. When sourceSignal changes, it will override the current value again
|
|
2296
|
+
*
|
|
2297
|
+
* This is useful for scenarios like UI state management where you want to:
|
|
2298
|
+
* - Start with a value from an external source (e.g., backend data)
|
|
2299
|
+
* - Allow temporary local overrides (e.g., user interactions)
|
|
2300
|
+
* - Reset to the external source when context changes (e.g., navigation, data refresh)
|
|
2301
|
+
*
|
|
2302
|
+
* @param {any} defaultValue - The default value to use when no other value is available
|
|
2303
|
+
* @param {Object} [options={}] - Configuration options
|
|
2304
|
+
* @param {import("@preact/signals").Signal} [options.sourceSignal] - Source signal to synchronize with. When the source signal changes, this signal will be updated
|
|
2305
|
+
* @param {string} [options.localStorageKey] - Key for local storage persistence. When provided, the signal value will be saved to and restored from localStorage
|
|
2306
|
+
* @param {"string" | "number" | "boolean" | "object"} [options.type="string"] - Type for localStorage serialization/deserialization
|
|
2307
|
+
* @returns {import("@preact/signals").Signal} A signal that can be synchronized with a source signal and/or persisted in localStorage
|
|
2308
|
+
*
|
|
2309
|
+
* @example
|
|
2310
|
+
* // Basic signal with default value
|
|
2311
|
+
* const count = stateSignal(0);
|
|
2312
|
+
*
|
|
2313
|
+
* @example
|
|
2314
|
+
* // Position that follows backend data but allows temporary overrides
|
|
2315
|
+
* const backendPosition = signal({ x: 100, y: 50 });
|
|
2316
|
+
* const currentPosition = stateSignal({ x: 0, y: 0 }, { sourceSignal: backendPosition });
|
|
2317
|
+
*
|
|
2318
|
+
* // Initially: currentPosition.value = { x: 100, y: 50 } (from backend)
|
|
2319
|
+
* // User drags: currentPosition.value = { x: 150, y: 80 } (manual override)
|
|
2320
|
+
* // Backend updates: backendPosition.value = { x: 200, y: 60 }
|
|
2321
|
+
* // Result: currentPosition.value = { x: 200, y: 60 } (reset to new backend value)
|
|
2322
|
+
*
|
|
2323
|
+
* @example
|
|
2324
|
+
* // Signal with localStorage persistence
|
|
2325
|
+
* const userPreference = stateSignal("light", {
|
|
2326
|
+
* localStorageKey: "theme",
|
|
2327
|
+
* type: "string"
|
|
2328
|
+
* });
|
|
2329
|
+
*
|
|
2330
|
+
* @example
|
|
2331
|
+
* // Combined: follows source with localStorage backup
|
|
2332
|
+
* const serverConfig = signal({ timeout: 5000 });
|
|
2333
|
+
* const appConfig = stateSignal({ timeout: 3000 }, {
|
|
2334
|
+
* sourceSignal: serverConfig,
|
|
2335
|
+
* localStorageKey: "app-config",
|
|
2336
|
+
* type: "object"
|
|
2337
|
+
* });
|
|
2338
|
+
*/
|
|
2339
|
+
const stateSignal = (
|
|
2340
|
+
defaultValue,
|
|
2341
|
+
{ sourceSignal, localStorageKey, type } = {},
|
|
2342
|
+
) => {
|
|
2343
|
+
const advancedSignal = signal();
|
|
2344
|
+
if (sourceSignal) {
|
|
2345
|
+
connectSignalToSource(advancedSignal, sourceSignal, defaultValue);
|
|
2346
|
+
} else {
|
|
2347
|
+
advancedSignal.value = defaultValue;
|
|
2348
|
+
}
|
|
2349
|
+
if (localStorageKey) {
|
|
2350
|
+
connectSignalWithLocalStorage(advancedSignal, localStorageKey, { type });
|
|
2351
|
+
}
|
|
2352
|
+
return advancedSignal;
|
|
2353
|
+
};
|
|
2354
|
+
|
|
2355
|
+
const connectSignalToSource = (signal, sourceSignal, defaultValue) => {
|
|
2356
|
+
connectSignalFallbacks(signal, [sourceSignal], defaultValue);
|
|
2357
|
+
updateSignalOnChange(sourceSignal, signal);
|
|
2358
|
+
};
|
|
2359
|
+
const connectSignalFallbacks = (signal, fallbackSignals, defaultValue) => {
|
|
2360
|
+
if (fallbackSignals.length === 0) {
|
|
2361
|
+
signal.value = defaultValue;
|
|
2362
|
+
return () => {};
|
|
2363
|
+
}
|
|
2364
|
+
if (fallbackSignals.length === 1) {
|
|
2365
|
+
const [fallbackSignal] = fallbackSignals;
|
|
2366
|
+
const applyFallback = () => {
|
|
2367
|
+
const value = signal.value;
|
|
2368
|
+
const fallbackValue = fallbackSignal.value;
|
|
2369
|
+
if (value !== undefined) {
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
if (fallbackValue !== undefined) {
|
|
2373
|
+
signal.value = fallbackValue;
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
signal.value = defaultValue;
|
|
2377
|
+
};
|
|
2378
|
+
applyFallback();
|
|
2379
|
+
return effect(() => {
|
|
2380
|
+
applyFallback();
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
const applyFallback = () => {
|
|
2384
|
+
const fallbackValues = fallbackSignals.map((s) => s.value);
|
|
2385
|
+
const value = signal.value;
|
|
2386
|
+
if (value !== undefined) {
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
for (const fallbackValue of fallbackValues) {
|
|
2390
|
+
if (fallbackValue === undefined) {
|
|
2391
|
+
continue;
|
|
2392
|
+
}
|
|
2393
|
+
signal.value = fallbackValue;
|
|
2394
|
+
return;
|
|
2395
|
+
}
|
|
2396
|
+
signal.value = defaultValue;
|
|
2397
|
+
};
|
|
2398
|
+
applyFallback();
|
|
2399
|
+
return effect(() => {
|
|
2400
|
+
applyFallback();
|
|
2401
|
+
});
|
|
2402
|
+
};
|
|
2403
|
+
const updateSignalOnChange = (sourceSignal, targetSignal) => {
|
|
2404
|
+
let sourcePreviousValue = sourceSignal.value;
|
|
2405
|
+
return effect(() => {
|
|
2406
|
+
const sourceValue = sourceSignal.value;
|
|
2407
|
+
if (sourcePreviousValue !== undefined && sourceValue !== undefined) {
|
|
2408
|
+
// console.log(
|
|
2409
|
+
// "value modified from",
|
|
2410
|
+
// sourcePreviousValue,
|
|
2411
|
+
// "to",
|
|
2412
|
+
// sourceValue,
|
|
2413
|
+
// );
|
|
2414
|
+
targetSignal.value = sourceValue;
|
|
2415
|
+
}
|
|
2416
|
+
sourcePreviousValue = sourceValue;
|
|
2417
|
+
});
|
|
2418
|
+
};
|
|
2419
|
+
|
|
2420
|
+
const connectSignalWithLocalStorage = (
|
|
2421
|
+
signal,
|
|
2422
|
+
key,
|
|
2423
|
+
{ type = "string" } = {},
|
|
2424
|
+
) => {
|
|
2425
|
+
const [get, set, remove] = valueInLocalStorage(key, { type });
|
|
2426
|
+
const valueFromLocalStorage = get();
|
|
2427
|
+
if (valueFromLocalStorage !== undefined) {
|
|
2428
|
+
signal.value = valueFromLocalStorage;
|
|
2429
|
+
}
|
|
2430
|
+
effect(() => {
|
|
2431
|
+
const value = signal.value;
|
|
2432
|
+
if (value === undefined || value === null) {
|
|
2433
|
+
remove();
|
|
2434
|
+
} else {
|
|
2435
|
+
set(value);
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
};
|
|
2439
|
+
|
|
2106
2440
|
const getCallerInfo = (targetFunction = null, additionalOffset = 0) => {
|
|
2107
2441
|
const originalPrepareStackTrace = Error.prepareStackTrace;
|
|
2108
2442
|
try {
|
|
@@ -4208,193 +4542,51 @@ const useStateArray = (
|
|
|
4208
4542
|
return [array, add, remove, reset];
|
|
4209
4543
|
};
|
|
4210
4544
|
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
if (converter && converter.decode) {
|
|
4247
|
-
const valueDecoded = converter.decode(valueInLocalStorage);
|
|
4248
|
-
const validityMessage = getValidityMessage(
|
|
4249
|
-
valueDecoded,
|
|
4250
|
-
valueInLocalStorage,
|
|
4251
|
-
);
|
|
4252
|
-
if (validityMessage) {
|
|
4253
|
-
console.warn(
|
|
4254
|
-
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
4255
|
-
);
|
|
4256
|
-
return undefined;
|
|
4257
|
-
}
|
|
4258
|
-
return valueDecoded;
|
|
4259
|
-
}
|
|
4260
|
-
const validityMessage = getValidityMessage(valueInLocalStorage);
|
|
4261
|
-
if (validityMessage) {
|
|
4262
|
-
console.warn(
|
|
4263
|
-
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
4264
|
-
);
|
|
4265
|
-
return undefined;
|
|
4266
|
-
}
|
|
4267
|
-
return valueInLocalStorage;
|
|
4268
|
-
};
|
|
4269
|
-
const set = (value) => {
|
|
4270
|
-
if (value === undefined) {
|
|
4271
|
-
window.localStorage.removeItem(key);
|
|
4272
|
-
return;
|
|
4273
|
-
}
|
|
4274
|
-
const validityMessage = getValidityMessage(value);
|
|
4275
|
-
if (validityMessage) {
|
|
4276
|
-
console.warn(
|
|
4277
|
-
`The value to set in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
4278
|
-
);
|
|
4279
|
-
}
|
|
4280
|
-
if (converter && converter.encode) {
|
|
4281
|
-
const valueEncoded = converter.encode(value);
|
|
4282
|
-
window.localStorage.setItem(key, valueEncoded);
|
|
4283
|
-
return;
|
|
4284
|
-
}
|
|
4285
|
-
window.localStorage.setItem(key, value);
|
|
4286
|
-
};
|
|
4287
|
-
const remove = () => {
|
|
4288
|
-
window.localStorage.removeItem(key);
|
|
4545
|
+
/**
|
|
4546
|
+
* Creates a function that generates abort signals, automatically cancelling previous requests.
|
|
4547
|
+
*
|
|
4548
|
+
* This prevents race conditions when multiple fetch requests are triggered rapidly,
|
|
4549
|
+
* ensuring only the most recent request completes while canceling outdated ones.
|
|
4550
|
+
*
|
|
4551
|
+
* @param {string} [reason="Request superseded"] - Custom reason for the abort signal
|
|
4552
|
+
* @returns {() => AbortSignal} A function that returns a fresh AbortSignal and cancels the previous one
|
|
4553
|
+
*
|
|
4554
|
+
* @example
|
|
4555
|
+
* // Setup the request canceller
|
|
4556
|
+
* const cancelPrevious = createRequestCanceller();
|
|
4557
|
+
*
|
|
4558
|
+
* // Use it in sequential fetch operations
|
|
4559
|
+
* const searchUsers = async (query) => {
|
|
4560
|
+
* const signal = cancelPrevious(); // Cancels previous search
|
|
4561
|
+
* const response = await fetch(`/api/users?q=${query}`, { signal });
|
|
4562
|
+
* return response.json();
|
|
4563
|
+
* };
|
|
4564
|
+
*
|
|
4565
|
+
* // Rapid successive calls - only the last one will complete
|
|
4566
|
+
* searchUsers("john"); // Will be aborted
|
|
4567
|
+
* searchUsers("jane"); // Will be aborted
|
|
4568
|
+
* searchUsers("jack"); // Will complete
|
|
4569
|
+
*
|
|
4570
|
+
* @example
|
|
4571
|
+
* // With custom reason
|
|
4572
|
+
* const cancelPrevious = createRequestCanceller("Search cancelled");
|
|
4573
|
+
*/
|
|
4574
|
+
const createRequestCanceller = (reason = "Request superseded") => {
|
|
4575
|
+
let previousAbortController;
|
|
4576
|
+
return () => {
|
|
4577
|
+
previousAbortController?.abort(reason);
|
|
4578
|
+
previousAbortController = new AbortController();
|
|
4579
|
+
return previousAbortController.signal;
|
|
4289
4580
|
};
|
|
4290
|
-
|
|
4291
|
-
return [get, set, remove];
|
|
4292
|
-
};
|
|
4293
|
-
|
|
4294
|
-
const typeConverters = {
|
|
4295
|
-
boolean: {
|
|
4296
|
-
checkValidity: (value) => {
|
|
4297
|
-
if (typeof value !== "boolean") {
|
|
4298
|
-
return `must be a boolean`;
|
|
4299
|
-
}
|
|
4300
|
-
return "";
|
|
4301
|
-
},
|
|
4302
|
-
decode: (value) => {
|
|
4303
|
-
return value === "true";
|
|
4304
|
-
},
|
|
4305
|
-
},
|
|
4306
|
-
string: {
|
|
4307
|
-
checkValidity: (value) => {
|
|
4308
|
-
if (typeof value !== "string") {
|
|
4309
|
-
return `must be a string`;
|
|
4310
|
-
}
|
|
4311
|
-
return "";
|
|
4312
|
-
},
|
|
4313
|
-
},
|
|
4314
|
-
number: {
|
|
4315
|
-
decode: (value) => {
|
|
4316
|
-
const valueParsed = parseFloat(value);
|
|
4317
|
-
return valueParsed;
|
|
4318
|
-
},
|
|
4319
|
-
checkValidity: (value) => {
|
|
4320
|
-
if (typeof value !== "number") {
|
|
4321
|
-
return `must be a number`;
|
|
4322
|
-
}
|
|
4323
|
-
if (!Number.isFinite(value)) {
|
|
4324
|
-
return `must be finite`;
|
|
4325
|
-
}
|
|
4326
|
-
return "";
|
|
4327
|
-
},
|
|
4328
|
-
},
|
|
4329
|
-
positive_number: {
|
|
4330
|
-
decode: (value) => {
|
|
4331
|
-
const valueParsed = parseFloat(value);
|
|
4332
|
-
return valueParsed;
|
|
4333
|
-
},
|
|
4334
|
-
checkValidity: (value) => {
|
|
4335
|
-
if (typeof value !== "number") {
|
|
4336
|
-
return `must be a number`;
|
|
4337
|
-
}
|
|
4338
|
-
if (value < 0) {
|
|
4339
|
-
return `must be positive`;
|
|
4340
|
-
}
|
|
4341
|
-
return "";
|
|
4342
|
-
},
|
|
4343
|
-
},
|
|
4344
|
-
positive_integer: {
|
|
4345
|
-
decode: (value) => {
|
|
4346
|
-
const valueParsed = parseInt(value, 10);
|
|
4347
|
-
return valueParsed;
|
|
4348
|
-
},
|
|
4349
|
-
checkValidity: (value) => {
|
|
4350
|
-
if (typeof value !== "number") {
|
|
4351
|
-
return `must be a number`;
|
|
4352
|
-
}
|
|
4353
|
-
if (!Number.isInteger(value)) {
|
|
4354
|
-
return `must be an integer`;
|
|
4355
|
-
}
|
|
4356
|
-
if (value < 0) {
|
|
4357
|
-
return `must be positive`;
|
|
4358
|
-
}
|
|
4359
|
-
return "";
|
|
4360
|
-
},
|
|
4361
|
-
},
|
|
4362
|
-
percentage: {
|
|
4363
|
-
checkValidity: (value) => {
|
|
4364
|
-
if (typeof value !== "string") {
|
|
4365
|
-
return `must be a percentage`;
|
|
4366
|
-
}
|
|
4367
|
-
if (!value.endsWith("%")) {
|
|
4368
|
-
return `must end with %`;
|
|
4369
|
-
}
|
|
4370
|
-
const percentageString = value.slice(0, -1);
|
|
4371
|
-
const percentageFloat = parseFloat(percentageString);
|
|
4372
|
-
if (typeof percentageFloat !== "number") {
|
|
4373
|
-
return `must be a percentage`;
|
|
4374
|
-
}
|
|
4375
|
-
if (percentageFloat < 0 || percentageFloat > 100) {
|
|
4376
|
-
return `must be between 0 and 100`;
|
|
4377
|
-
}
|
|
4378
|
-
return "";
|
|
4379
|
-
},
|
|
4380
|
-
},
|
|
4381
|
-
object: {
|
|
4382
|
-
decode: (value) => {
|
|
4383
|
-
const valueParsed = JSON.parse(value);
|
|
4384
|
-
return valueParsed;
|
|
4385
|
-
},
|
|
4386
|
-
encode: (value) => {
|
|
4387
|
-
const valueStringified = JSON.stringify(value);
|
|
4388
|
-
return valueStringified;
|
|
4389
|
-
},
|
|
4390
|
-
checkValidity: (value) => {
|
|
4391
|
-
if (value === null || typeof value !== "object") {
|
|
4392
|
-
return `must be an object`;
|
|
4393
|
-
}
|
|
4394
|
-
return "";
|
|
4395
|
-
},
|
|
4396
|
-
},
|
|
4397
4581
|
};
|
|
4582
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
4583
|
+
if (
|
|
4584
|
+
event.reason?.name === "AbortError" &&
|
|
4585
|
+
event.reason?.message === "Request superseded"
|
|
4586
|
+
) {
|
|
4587
|
+
event.preventDefault(); // 💥 empêche les "uncaught rejection" devtools pour nos cancellations
|
|
4588
|
+
}
|
|
4589
|
+
});
|
|
4398
4590
|
|
|
4399
4591
|
/**
|
|
4400
4592
|
* Merges a component's base className with className received from props.
|
|
@@ -4562,7 +4754,7 @@ const DIMENSION_PROPS = {
|
|
|
4562
4754
|
},
|
|
4563
4755
|
shrinkX: (value, { parentBoxFlow }) => {
|
|
4564
4756
|
if (parentBoxFlow === "row" || parentBoxFlow === "inline-row") {
|
|
4565
|
-
if (!value) {
|
|
4757
|
+
if (!value || value === "0") {
|
|
4566
4758
|
return { flexShrink: 0 };
|
|
4567
4759
|
}
|
|
4568
4760
|
return { flexShrink: 1 };
|
|
@@ -4571,7 +4763,7 @@ const DIMENSION_PROPS = {
|
|
|
4571
4763
|
},
|
|
4572
4764
|
shrinkY: (value, { parentBoxFlow }) => {
|
|
4573
4765
|
if (parentBoxFlow === "column" || parentBoxFlow === "inline-column") {
|
|
4574
|
-
if (!value) {
|
|
4766
|
+
if (!value || value === "0") {
|
|
4575
4767
|
return { flexShrink: 0 };
|
|
4576
4768
|
}
|
|
4577
4769
|
return { flexShrink: 1 };
|
|
@@ -23595,5 +23787,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
23595
23787
|
})
|
|
23596
23788
|
});
|
|
23597
23789
|
|
|
23598
|
-
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, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, goBack, goForward, goTo, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, setupRoutes, 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 };
|
|
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, goBack, goForward, goTo, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, 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 };
|
|
23599
23791
|
//# sourceMappingURL=jsenv_navi.js.map
|