@jsenv/navi 0.30.17 → 0.30.18
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/dev/jsenv_navi.js +219 -63
- package/dist/dev/jsenv_navi.js.map +4 -3
- package/dist/jsenv_navi.js +206 -58
- package/dist/jsenv_navi.js.map +4 -3
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -659,7 +659,7 @@ const setActionPrivateProperties = (action, properties) => {
|
|
|
659
659
|
actionPrivatePropertiesWeakMap.set(action, properties);
|
|
660
660
|
};
|
|
661
661
|
|
|
662
|
-
const isSignal = (value) => {
|
|
662
|
+
const isSignal$1 = (value) => {
|
|
663
663
|
return getSignalType(value) !== null;
|
|
664
664
|
};
|
|
665
665
|
|
|
@@ -1006,7 +1006,7 @@ const compareTwoJsValues = (
|
|
|
1006
1006
|
// counter) are enumerable, so without this they would be walked and two
|
|
1007
1007
|
// unrelated signals would pass for one — a params signal owned by one
|
|
1008
1008
|
// screen would then be handed the action bound to another's.
|
|
1009
|
-
if (isSignal(a) || isSignal(b)) {
|
|
1009
|
+
if (isSignal$1(a) || isSignal$1(b)) {
|
|
1010
1010
|
return false;
|
|
1011
1011
|
}
|
|
1012
1012
|
const aKeys = Object.keys(a);
|
|
@@ -2603,7 +2603,7 @@ const readReason = (source) => {
|
|
|
2603
2603
|
return null;
|
|
2604
2604
|
}
|
|
2605
2605
|
let reason;
|
|
2606
|
-
if (isSignal(source)) {
|
|
2606
|
+
if (isSignal$1(source)) {
|
|
2607
2607
|
reason = source.value;
|
|
2608
2608
|
} else if (typeof source === "function") {
|
|
2609
2609
|
reason = source();
|
|
@@ -4139,7 +4139,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
4139
4139
|
const childActionWeakMap = createJsValueWeakMap();
|
|
4140
4140
|
const _bindParams = (newParamsOrSignal, options = {}) => {
|
|
4141
4141
|
// Case 1: a signal → proxy that retargets as the signal changes
|
|
4142
|
-
if (isSignal(newParamsOrSignal)) {
|
|
4142
|
+
if (isSignal$1(newParamsOrSignal)) {
|
|
4143
4143
|
// A getter builds a fresh object each time a signal it reads moves,
|
|
4144
4144
|
// equal or not. Equal params are the same question: the previous
|
|
4145
4145
|
// object is kept, so the binding's paramsSignal does not move and its
|
|
@@ -4173,7 +4173,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
4173
4173
|
const keyArray = Object.keys(newParamsOrSignal);
|
|
4174
4174
|
for (const key of keyArray) {
|
|
4175
4175
|
const value = newParamsOrSignal[key];
|
|
4176
|
-
if (isSignal(value)) {
|
|
4176
|
+
if (isSignal$1(value)) {
|
|
4177
4177
|
signalMap.set(key, value);
|
|
4178
4178
|
} else {
|
|
4179
4179
|
const objectSignal = value ? value[SYMBOL_OBJECT_SIGNAL] : null;
|
|
@@ -4275,7 +4275,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
4275
4275
|
}
|
|
4276
4276
|
const { debounce, ...optionsWithoutDebounce } = options;
|
|
4277
4277
|
if (debounce) {
|
|
4278
|
-
if (!isSignal(newParamsOrSignal)) {
|
|
4278
|
+
if (!isSignal$1(newParamsOrSignal)) {
|
|
4279
4279
|
console.warn(
|
|
4280
4280
|
`bindParams({ debounce }) expects a signal, received ${typeof newParamsOrSignal}: params that cannot change have nothing to settle.`,
|
|
4281
4281
|
);
|
|
@@ -5240,7 +5240,7 @@ const generateActionCallSource = (name, params) => {
|
|
|
5240
5240
|
// them (see _bindParams): a signal is its value, and so is each signal a plain
|
|
5241
5241
|
// object holds at its first level. Read inside a computed, it follows them.
|
|
5242
5242
|
const readParamsHandedToBind = (newParamsOrSignal) => {
|
|
5243
|
-
if (isSignal(newParamsOrSignal)) {
|
|
5243
|
+
if (isSignal$1(newParamsOrSignal)) {
|
|
5244
5244
|
return newParamsOrSignal.value;
|
|
5245
5245
|
}
|
|
5246
5246
|
if (!isPlainObject$2(newParamsOrSignal)) {
|
|
@@ -5249,7 +5249,7 @@ const readParamsHandedToBind = (newParamsOrSignal) => {
|
|
|
5249
5249
|
const params = {};
|
|
5250
5250
|
for (const key of Object.keys(newParamsOrSignal)) {
|
|
5251
5251
|
const value = newParamsOrSignal[key];
|
|
5252
|
-
const valueSignal = isSignal(value)
|
|
5252
|
+
const valueSignal = isSignal$1(value)
|
|
5253
5253
|
? value
|
|
5254
5254
|
: value
|
|
5255
5255
|
? value[SYMBOL_OBJECT_SIGNAL]
|
|
@@ -5662,6 +5662,7 @@ const STATE_SIGNAL_OPTIONS = new Set([
|
|
|
5662
5662
|
"history",
|
|
5663
5663
|
"debounceUrl",
|
|
5664
5664
|
"version",
|
|
5665
|
+
"owner",
|
|
5665
5666
|
]);
|
|
5666
5667
|
/**
|
|
5667
5668
|
* Creates an advanced signal with dynamic default value, local storage persistence, and validation.
|
|
@@ -5687,11 +5688,25 @@ const STATE_SIGNAL_OPTIONS = new Set([
|
|
|
5687
5688
|
* @param {Object} [options={}] - Configuration options
|
|
5688
5689
|
* @param {string|number} [options.id] - Custom ID for the signal. If not provided, an auto-generated ID will be used. Used for localStorage key and route pattern detection.
|
|
5689
5690
|
* @param {any} [options.default] - Static fallback value used when defaultValue is a signal and that signal's value is undefined
|
|
5690
|
-
* @param {boolean} [options.persists=false] - Whether to persist the signal value in localStorage using the signal ID as key
|
|
5691
|
+
* @param {boolean} [options.persists=false] - Whether to persist the signal value in localStorage using the signal ID as key.
|
|
5692
|
+
* The copy is the device's: every account signed in on this browser reads and writes the same one,
|
|
5693
|
+
* unless `owner` says whose it is.
|
|
5691
5694
|
* @param {string} [options.version] - What makes a stored copy unusable — the deployed version, a schema
|
|
5692
5695
|
* number. The value is persisted under `${id}@${version}`, and at creation the copies of every other
|
|
5693
5696
|
* version of this id (and the one stored under the bare id) are removed: a device that opened ten
|
|
5694
5697
|
* deploys holds one copy, not ten. Only the storage key changes, the id the url reads stays `id`.
|
|
5698
|
+
* @param {import("@preact/signals").ReadonlySignal<string | number | null | undefined> | (() => string | number | null | undefined)} [options.owner] -
|
|
5699
|
+
* Whose copy this is, for a state kept per account on a device several accounts share (search
|
|
5700
|
+
* criteria, a last choice): a signal, or a function read like a `computed`, naming the owner. The
|
|
5701
|
+
* value is persisted under `${id}#${owner}` (`${id}@${version}#${owner}` with a version).
|
|
5702
|
+
* When the owner changes, the state starts again as at creation, for that owner: what the address
|
|
5703
|
+
* says when it carries the param, otherwise that owner's copy, otherwise the default. The previous
|
|
5704
|
+
* owner's value is never carried across.
|
|
5705
|
+
* `undefined` or `null` is an owner not known yet: nothing is read and nothing is kept, the state
|
|
5706
|
+
* holds its default and what is written lives in memory until an owner is known.
|
|
5707
|
+
* At creation the copy kept under the bare id (from before the state had an owner) is removed, as
|
|
5708
|
+
* `version` does; the copies of the other owners are kept. Those of an owner that is gone for good
|
|
5709
|
+
* are removed by `forgetOwner(owner)`. Requires `persists`.
|
|
5695
5710
|
* @param {string} [options.type] - Type the value is coerced to, and read back as from localStorage and the url:
|
|
5696
5711
|
* any @jsenv/validity type (`"string"`, `"number"`, `"boolean"`, `"array"`, `"object"`, `"integer"`, `"date"`,
|
|
5697
5712
|
* `"time"`…). Without it the value is not coerced. On a type that is not text (`"string"`, `"email"`,
|
|
@@ -5813,6 +5828,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5813
5828
|
history = "replace",
|
|
5814
5829
|
debounceUrl = 0,
|
|
5815
5830
|
version,
|
|
5831
|
+
owner,
|
|
5816
5832
|
} = options;
|
|
5817
5833
|
{
|
|
5818
5834
|
warnUnknownOptions(`stateSignal "${id}"`, options, STATE_SIGNAL_OPTIONS);
|
|
@@ -5835,11 +5851,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5835
5851
|
}
|
|
5836
5852
|
|
|
5837
5853
|
// Check if defaultValue is a signal (dynamic default) or static value
|
|
5838
|
-
const isDynamicDefault =
|
|
5839
|
-
defaultValue &&
|
|
5840
|
-
typeof defaultValue === "object" &&
|
|
5841
|
-
"value" in defaultValue &&
|
|
5842
|
-
"peek" in defaultValue;
|
|
5854
|
+
const isDynamicDefault = isSignal(defaultValue);
|
|
5843
5855
|
const dynamicDefaultSignal = isDynamicDefault ? defaultValue : null;
|
|
5844
5856
|
const staticDefaultValue = isDynamicDefault ? staticFallback : defaultValue;
|
|
5845
5857
|
const signalId = id || generateSignalId();
|
|
@@ -5854,14 +5866,54 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5854
5866
|
}
|
|
5855
5867
|
}
|
|
5856
5868
|
|
|
5857
|
-
|
|
5869
|
+
let ownerSignal = null;
|
|
5870
|
+
if (owner !== undefined) {
|
|
5871
|
+
if (isSignal(owner)) {
|
|
5872
|
+
ownerSignal = owner;
|
|
5873
|
+
} else if (typeof owner === "function") {
|
|
5874
|
+
ownerSignal = computed(owner);
|
|
5875
|
+
} else {
|
|
5876
|
+
// `owner: me.id` is read once: the owner of the first page, for good.
|
|
5877
|
+
throw new TypeError(
|
|
5878
|
+
`stateSignal "${signalIdString}": owner must be a signal or a function naming the owner, got ${typeof owner} ${String(owner)}.`,
|
|
5879
|
+
);
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
const versionKey =
|
|
5858
5883
|
version === undefined ? signalIdString : `${signalIdString}@${version}`;
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5884
|
+
const storageKeyOf = (ownerValue) => {
|
|
5885
|
+
if (!ownerSignal) {
|
|
5886
|
+
return versionKey;
|
|
5887
|
+
}
|
|
5888
|
+
if (ownerValue === undefined || ownerValue === null) {
|
|
5889
|
+
return undefined;
|
|
5890
|
+
}
|
|
5891
|
+
if (typeof ownerValue !== "string" && typeof ownerValue !== "number") {
|
|
5892
|
+
// an object would be "[object Object]": one copy shared by every owner
|
|
5893
|
+
throw new TypeError(
|
|
5894
|
+
`stateSignal "${signalIdString}": owner names the owner with a string or a number, got ${typeof ownerValue}.`,
|
|
5895
|
+
);
|
|
5896
|
+
}
|
|
5897
|
+
return `${versionKey}#${ownerValue}`;
|
|
5898
|
+
};
|
|
5899
|
+
// The key the value is kept under. Undefined while the owner is not known:
|
|
5900
|
+
// what is written then belongs to no one, and is not kept.
|
|
5901
|
+
const storageKeySignal = signal(storageKeyOf(ownerSignal?.peek()));
|
|
5902
|
+
if (persists) {
|
|
5903
|
+
if (version !== undefined || ownerSignal) {
|
|
5904
|
+
removeStaleCopies(signalIdString, versionKey, Boolean(ownerSignal));
|
|
5905
|
+
}
|
|
5906
|
+
} else {
|
|
5907
|
+
if (version !== undefined) {
|
|
5908
|
+
console.warn(
|
|
5909
|
+
`stateSignal "${signalIdString}": version names the copy kept in localStorage, and without persists nothing is kept.`,
|
|
5910
|
+
);
|
|
5911
|
+
}
|
|
5912
|
+
if (ownerSignal) {
|
|
5913
|
+
console.warn(
|
|
5914
|
+
`stateSignal "${signalIdString}": owner says whose copy is kept in localStorage, and without persists nothing is kept.`,
|
|
5915
|
+
);
|
|
5916
|
+
}
|
|
5865
5917
|
}
|
|
5866
5918
|
const [validity, updateValidity, clearValidity] = createValidity({
|
|
5867
5919
|
type,
|
|
@@ -5891,22 +5943,16 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5891
5943
|
);
|
|
5892
5944
|
}
|
|
5893
5945
|
}
|
|
5894
|
-
const readFromLocalStorage =
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
: () => {};
|
|
5905
|
-
const removeFromLocalStorage = persists
|
|
5906
|
-
? () => {
|
|
5907
|
-
writeLocalStorage(localStorageKey, undefined);
|
|
5908
|
-
}
|
|
5909
|
-
: () => {};
|
|
5946
|
+
const readFromLocalStorage = () => {
|
|
5947
|
+
const storageKey = storageKeySignal.peek();
|
|
5948
|
+
if (storageKey === undefined) {
|
|
5949
|
+
return undefined;
|
|
5950
|
+
}
|
|
5951
|
+
return readLocalStorage(storageKey);
|
|
5952
|
+
};
|
|
5953
|
+
const keepInLocalStorage = (storageKey) => {
|
|
5954
|
+
writeLocalStorage(storageKey, validity.representations.localStorage.value);
|
|
5955
|
+
};
|
|
5910
5956
|
|
|
5911
5957
|
/**
|
|
5912
5958
|
* Returns the current default value from code logic only (static or dynamic).
|
|
@@ -5955,7 +6001,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5955
6001
|
if (valueFromLocalStorage !== undefined) {
|
|
5956
6002
|
if (debug) {
|
|
5957
6003
|
console.debug(
|
|
5958
|
-
`[stateSignal:${signalIdString}] using value from localStorage "${
|
|
6004
|
+
`[stateSignal:${signalIdString}] using value from localStorage "${storageKeySignal.peek()}"=${valueFromLocalStorage}`,
|
|
5959
6005
|
);
|
|
5960
6006
|
}
|
|
5961
6007
|
return valueFromLocalStorage;
|
|
@@ -6154,11 +6200,17 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
6154
6200
|
});
|
|
6155
6201
|
}
|
|
6156
6202
|
persist_in_local_storage: {
|
|
6157
|
-
if (!
|
|
6203
|
+
if (!persists) {
|
|
6158
6204
|
break persist_in_local_storage;
|
|
6159
6205
|
}
|
|
6160
6206
|
effect(() => {
|
|
6207
|
+
// The key and the value are read together: an owner switch writes both
|
|
6208
|
+
// in one batch (below), so a value is never kept under another owner.
|
|
6209
|
+
const storageKey = storageKeySignal.value;
|
|
6161
6210
|
const value = preactSignal.value;
|
|
6211
|
+
if (storageKey === undefined) {
|
|
6212
|
+
return;
|
|
6213
|
+
}
|
|
6162
6214
|
|
|
6163
6215
|
if (dynamicDefaultSignal) {
|
|
6164
6216
|
// With dynamic defaults: always persist to preserve user intent
|
|
@@ -6166,10 +6218,10 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
6166
6218
|
if (value !== undefined) {
|
|
6167
6219
|
if (debug) {
|
|
6168
6220
|
console.debug(
|
|
6169
|
-
`[stateSignal:${signalIdString}] dynamic default: writing to localStorage "${
|
|
6221
|
+
`[stateSignal:${signalIdString}] dynamic default: writing to localStorage "${storageKey}"=${value}`,
|
|
6170
6222
|
);
|
|
6171
6223
|
}
|
|
6172
|
-
|
|
6224
|
+
keepInLocalStorage(storageKey);
|
|
6173
6225
|
}
|
|
6174
6226
|
return;
|
|
6175
6227
|
}
|
|
@@ -6177,18 +6229,57 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
6177
6229
|
if (isCustomValue(value)) {
|
|
6178
6230
|
if (debug) {
|
|
6179
6231
|
console.debug(
|
|
6180
|
-
`[stateSignal:${signalIdString}] writing into localStorage "${
|
|
6232
|
+
`[stateSignal:${signalIdString}] writing into localStorage "${storageKey}"=${value}`,
|
|
6181
6233
|
);
|
|
6182
6234
|
}
|
|
6183
|
-
|
|
6235
|
+
keepInLocalStorage(storageKey);
|
|
6184
6236
|
} else {
|
|
6185
6237
|
if (debug) {
|
|
6186
6238
|
console.debug(
|
|
6187
|
-
`[stateSignal:${signalIdString}] removing "${
|
|
6239
|
+
`[stateSignal:${signalIdString}] removing "${storageKey}" from localStorage (value=${value})`,
|
|
6188
6240
|
);
|
|
6189
6241
|
}
|
|
6190
|
-
|
|
6242
|
+
writeLocalStorage(storageKey, undefined);
|
|
6243
|
+
}
|
|
6244
|
+
});
|
|
6245
|
+
}
|
|
6246
|
+
// What the address says this state holds, one reader per route binding it
|
|
6247
|
+
// (see route.js): an owner switch starts the state again as creation does,
|
|
6248
|
+
// and at creation the routing pass applies the address after the storage.
|
|
6249
|
+
const addressReaderSet = new Set();
|
|
6250
|
+
owner_switch: {
|
|
6251
|
+
if (!ownerSignal || !persists) {
|
|
6252
|
+
break owner_switch;
|
|
6253
|
+
}
|
|
6254
|
+
effect(() => {
|
|
6255
|
+
const storageKey = storageKeyOf(ownerSignal.value);
|
|
6256
|
+
if (storageKey === storageKeySignal.peek()) {
|
|
6257
|
+
return;
|
|
6191
6258
|
}
|
|
6259
|
+
untracked(() => {
|
|
6260
|
+
let valueFromAddress;
|
|
6261
|
+
for (const readAddress of addressReaderSet) {
|
|
6262
|
+
valueFromAddress = readAddress();
|
|
6263
|
+
if (valueFromAddress) {
|
|
6264
|
+
break;
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
if (debug) {
|
|
6268
|
+
console.debug(
|
|
6269
|
+
`[stateSignal:${signalIdString}] owner changed, kept under "${storageKey}"`,
|
|
6270
|
+
);
|
|
6271
|
+
}
|
|
6272
|
+
batch(() => {
|
|
6273
|
+
storageKeySignal.value = storageKey;
|
|
6274
|
+
if (valueFromAddress) {
|
|
6275
|
+
// eslint-disable-next-line signals/no-conditional-value-read -- a plain { value } from an address reader, not a signal
|
|
6276
|
+
facadeSignal.value = valueFromAddress.value;
|
|
6277
|
+
} else {
|
|
6278
|
+
// read once the key is the new owner's
|
|
6279
|
+
facadeSignal.value = getFallbackValue();
|
|
6280
|
+
}
|
|
6281
|
+
});
|
|
6282
|
+
});
|
|
6192
6283
|
});
|
|
6193
6284
|
}
|
|
6194
6285
|
// Create isDefaultValue function for this signal
|
|
@@ -6209,7 +6300,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
6209
6300
|
min,
|
|
6210
6301
|
max,
|
|
6211
6302
|
persists,
|
|
6212
|
-
|
|
6303
|
+
addressReaderSet: ownerSignal && persists ? addressReaderSet : undefined,
|
|
6213
6304
|
debug,
|
|
6214
6305
|
...options,
|
|
6215
6306
|
history,
|
|
@@ -6230,7 +6321,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
6230
6321
|
hasDynamicDefault: Boolean(dynamicDefaultSignal),
|
|
6231
6322
|
hasStoredValue: persists && readFromLocalStorage() !== undefined,
|
|
6232
6323
|
persists,
|
|
6233
|
-
localStorageKey: persists ?
|
|
6324
|
+
localStorageKey: persists ? storageKeySignal.peek() : undefined,
|
|
6234
6325
|
},
|
|
6235
6326
|
);
|
|
6236
6327
|
}
|
|
@@ -6268,21 +6359,60 @@ const takeHistoryOfWriteAsOne = () => {
|
|
|
6268
6359
|
return writeAsOne.history;
|
|
6269
6360
|
};
|
|
6270
6361
|
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6362
|
+
/**
|
|
6363
|
+
* Removes every copy kept for `owner` by the states declaring an `owner`: an
|
|
6364
|
+
* account erased, a trial account that ended. Each state keeps one copy per
|
|
6365
|
+
* owner it has met, and only the app knows when an owner is gone for good.
|
|
6366
|
+
*
|
|
6367
|
+
* Only the storage is emptied: a state whose owner is `owner` right now keeps
|
|
6368
|
+
* what it holds, and keeps it again at its next write. Call it once the app
|
|
6369
|
+
* has left that owner.
|
|
6370
|
+
*
|
|
6371
|
+
* @param {string | number} owner
|
|
6372
|
+
*/
|
|
6373
|
+
const forgetOwner = (owner) => {
|
|
6374
|
+
const ownerSuffix = `#${owner}`;
|
|
6375
|
+
for (const key of listLocalStorageKeys()) {
|
|
6376
|
+
if (key.endsWith(ownerSuffix)) {
|
|
6377
|
+
writeLocalStorage(key, undefined);
|
|
6378
|
+
}
|
|
6379
|
+
}
|
|
6380
|
+
};
|
|
6381
|
+
|
|
6382
|
+
// The copies an older deploy or an older declaration left: under
|
|
6383
|
+
// `${id}@<another version>`, under the bare id from before the signal declared
|
|
6384
|
+
// a version or an owner, under the owners of another version. Read once, at
|
|
6385
|
+
// creation: they are what a previous document wrote, nothing of this one writes
|
|
6386
|
+
// there. With an owner, every owner's copy of this version stays: another
|
|
6387
|
+
// owner's copy is not stale, it is someone else's.
|
|
6388
|
+
const removeStaleCopies = (id, versionKey, byOwner) => {
|
|
6275
6389
|
const versionPrefix = `${id}@`;
|
|
6390
|
+
const ownerPrefix = `${id}#`;
|
|
6391
|
+
const ownersOfVersionPrefix = `${versionKey}#`;
|
|
6276
6392
|
for (const key of listLocalStorageKeys()) {
|
|
6277
|
-
|
|
6393
|
+
const isCopyOfId =
|
|
6394
|
+
key === id ||
|
|
6395
|
+
key.startsWith(versionPrefix) ||
|
|
6396
|
+
key.startsWith(ownerPrefix);
|
|
6397
|
+
if (!isCopyOfId) {
|
|
6278
6398
|
continue;
|
|
6279
6399
|
}
|
|
6280
|
-
|
|
6281
|
-
|
|
6400
|
+
const kept = byOwner
|
|
6401
|
+
? key.startsWith(ownersOfVersionPrefix)
|
|
6402
|
+
: key === versionKey;
|
|
6403
|
+
if (kept) {
|
|
6404
|
+
continue;
|
|
6282
6405
|
}
|
|
6406
|
+
writeLocalStorage(key, undefined);
|
|
6283
6407
|
}
|
|
6284
6408
|
};
|
|
6285
6409
|
|
|
6410
|
+
const isSignal = (value) =>
|
|
6411
|
+
Boolean(value) &&
|
|
6412
|
+
typeof value === "object" &&
|
|
6413
|
+
"value" in value &&
|
|
6414
|
+
"peek" in value;
|
|
6415
|
+
|
|
6286
6416
|
/**
|
|
6287
6417
|
* Custom route pattern matching system.
|
|
6288
6418
|
* Not built on URLPattern: matching here is simpler and more predictable.
|
|
@@ -9074,7 +9204,7 @@ const route = (pattern, options = {}) => {
|
|
|
9074
9204
|
// Signal -> URL sync: When signal changes, update URL to reflect meaningful state
|
|
9075
9205
|
// Only sync non-default values to keep URLs clean (static fallbacks stay invisible)
|
|
9076
9206
|
registerSetup(({ routeSet }) => {
|
|
9077
|
-
const
|
|
9207
|
+
const cleanupSet = new Set();
|
|
9078
9208
|
// important: read connections at setup time so it includes query connections
|
|
9079
9209
|
// inherited from ancestor patterns
|
|
9080
9210
|
const { connections } = routePattern;
|
|
@@ -9199,11 +9329,37 @@ const route = (pattern, options = {}) => {
|
|
|
9199
9329
|
// entry when the write pushes.
|
|
9200
9330
|
untracked(() => writeValueInUrl(value));
|
|
9201
9331
|
});
|
|
9202
|
-
|
|
9332
|
+
cleanupSet.add(cleanupSignalUrlEffect);
|
|
9333
|
+
// A state kept per owner starts again when the owner changes, as at
|
|
9334
|
+
// creation: the address has the last word, as the routing pass gives it
|
|
9335
|
+
// (see sync_routes_with_url). Null when the address leaves it to storage.
|
|
9336
|
+
const { addressReaderSet } = connection;
|
|
9337
|
+
if (addressReaderSet) {
|
|
9338
|
+
const readAddress = () => {
|
|
9339
|
+
if (!route.matchingSignal.peek()) {
|
|
9340
|
+
return null;
|
|
9341
|
+
}
|
|
9342
|
+
const urlParamValue = route.rawParamsSignal.peek()[paramName];
|
|
9343
|
+
if (urlParamValue !== undefined) {
|
|
9344
|
+
return { value: urlParamValue };
|
|
9345
|
+
}
|
|
9346
|
+
if (
|
|
9347
|
+
connection.paramType === "query" &&
|
|
9348
|
+
connection.history !== "push"
|
|
9349
|
+
) {
|
|
9350
|
+
return null;
|
|
9351
|
+
}
|
|
9352
|
+
return { value: connection.getDefaultValue() };
|
|
9353
|
+
};
|
|
9354
|
+
addressReaderSet.add(readAddress);
|
|
9355
|
+
cleanupSet.add(() => {
|
|
9356
|
+
addressReaderSet.delete(readAddress);
|
|
9357
|
+
});
|
|
9358
|
+
}
|
|
9203
9359
|
}
|
|
9204
9360
|
return () => {
|
|
9205
|
-
for (const
|
|
9206
|
-
|
|
9361
|
+
for (const cleanup of cleanupSet) {
|
|
9362
|
+
cleanup();
|
|
9207
9363
|
}
|
|
9208
9364
|
};
|
|
9209
9365
|
});
|
|
@@ -13458,7 +13614,7 @@ const warnSignalCollision = (props, controlType, stateProp) => {
|
|
|
13458
13614
|
*/
|
|
13459
13615
|
const warnSignalAsState = (props, controlType, stateProps) => {
|
|
13460
13616
|
for (const stateProp of stateProps) {
|
|
13461
|
-
if (isSignal(props[stateProp])) {
|
|
13617
|
+
if (isSignal$1(props[stateProp])) {
|
|
13462
13618
|
console.warn(
|
|
13463
13619
|
`[navi] "${controlType}" got a signal as "${stateProp}". ` +
|
|
13464
13620
|
`A signal binds a control through "signal" — did you mean signal={...}? ` +
|
|
@@ -26714,7 +26870,7 @@ const useActionBoundToOneParam = (
|
|
|
26714
26870
|
paramsSignal,
|
|
26715
26871
|
{ verb } = {},
|
|
26716
26872
|
) => {
|
|
26717
|
-
if (!isSignal(paramsSignal)) {
|
|
26873
|
+
if (!isSignal$1(paramsSignal)) {
|
|
26718
26874
|
throw new Error(
|
|
26719
26875
|
`useActionBoundToOneParam expects a signal as second argument, got: ${paramsSignal}`,
|
|
26720
26876
|
);
|
|
@@ -30045,7 +30201,7 @@ const resolveParams = (params) => {
|
|
|
30045
30201
|
const paramsResolved = {};
|
|
30046
30202
|
for (const key of Object.keys(params)) {
|
|
30047
30203
|
const value = params[key];
|
|
30048
|
-
paramsResolved[key] = isSignal(value) ? value.value : value;
|
|
30204
|
+
paramsResolved[key] = isSignal$1(value) ? value.value : value;
|
|
30049
30205
|
}
|
|
30050
30206
|
return paramsResolved;
|
|
30051
30207
|
};
|
|
@@ -43258,7 +43414,7 @@ const keepPageOnScreen = ({
|
|
|
43258
43414
|
when,
|
|
43259
43415
|
always = [],
|
|
43260
43416
|
} = {}) => {
|
|
43261
|
-
if (!isSignal(keptSignal)) {
|
|
43417
|
+
if (!isSignal$1(keptSignal)) {
|
|
43262
43418
|
throw new TypeError(
|
|
43263
43419
|
`keepPageOnScreen() needs a signal to write the page into, received ${keptSignal}`,
|
|
43264
43420
|
);
|
|
@@ -109795,5 +109951,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
109795
109951
|
})
|
|
109796
109952
|
});
|
|
109797
109953
|
|
|
109798
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NetworkPolicyError, NumberSpin, Paragraph, Picker, Popover, Popup, PopupGroup, Quantity, RadioGroup, Route, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, SortHeader, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRange, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, activeRouteActionsSignal, activeRouteReadsSignal, anyMatchingRouteSignal, applySearch, arraySignalMembership, askPopup, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, dispatchRequestSetUIState, enableDebugActions, enableDebugOnDocumentLoading, enableVirtualKeyboardOverlay, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, getNowHours, getNowHoursRoundedToStep, isCellSelected, isColumnSelected, isNetworkPolicyError, isPressOnControl, isRowSelected, isScrolling, isToday, keepPageOnScreen, languagesSignal, localStorageSignal, markAsOutsideTextFlow, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, preloadUrl, rawUrlPart, registerGlobalConstraint, reload, renderedPageSignal, rerunActions, resource, route, routeAction, routeFallback, routeTravelSettledPageSignal, scrollActivitySignal, setBaseUrl, setNetworkPolicy, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stateSignalGroup, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, todaySignal, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useCopyToClipboard, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useHoldScrollRestoration, useInputGroup, useKeyboardShortcuts, useListItemState, useNavState, useNetworkPolicyReason, useOrderedColumns, usePickerState, usePopupMode, usePopupValue, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useTransitionCover, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
109954
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NetworkPolicyError, NumberSpin, Paragraph, Picker, Popover, Popup, PopupGroup, Quantity, RadioGroup, Route, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, SortHeader, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRange, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, activeRouteActionsSignal, activeRouteReadsSignal, anyMatchingRouteSignal, applySearch, arraySignalMembership, askPopup, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, dispatchRequestSetUIState, enableDebugActions, enableDebugOnDocumentLoading, enableVirtualKeyboardOverlay, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, forgetOwner, getNowHours, getNowHoursRoundedToStep, isCellSelected, isColumnSelected, isNetworkPolicyError, isPressOnControl, isRowSelected, isScrolling, isToday, keepPageOnScreen, languagesSignal, localStorageSignal, markAsOutsideTextFlow, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, preloadUrl, rawUrlPart, registerGlobalConstraint, reload, renderedPageSignal, rerunActions, resource, route, routeAction, routeFallback, routeTravelSettledPageSignal, scrollActivitySignal, setBaseUrl, setNetworkPolicy, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stateSignalGroup, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, todaySignal, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useCopyToClipboard, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useHoldScrollRestoration, useInputGroup, useKeyboardShortcuts, useListItemState, useNavState, useNetworkPolicyReason, useOrderedColumns, usePickerState, usePopupMode, usePopupValue, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useTransitionCover, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
109799
109955
|
//# sourceMappingURL=jsenv_navi.js.map
|