@jsenv/navi 0.30.17 → 0.30.19
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 +235 -64
- package/dist/dev/jsenv_navi.js.map +5 -4
- package/dist/jsenv_navi.js +222 -59
- package/dist/jsenv_navi.js.map +5 -4
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -632,7 +632,7 @@ const setActionPrivateProperties = (action, properties) => {
|
|
|
632
632
|
actionPrivatePropertiesWeakMap.set(action, properties);
|
|
633
633
|
};
|
|
634
634
|
|
|
635
|
-
const isSignal = (value) => {
|
|
635
|
+
const isSignal$1 = (value) => {
|
|
636
636
|
return getSignalType(value) !== null;
|
|
637
637
|
};
|
|
638
638
|
|
|
@@ -979,7 +979,7 @@ const compareTwoJsValues = (
|
|
|
979
979
|
// counter) are enumerable, so without this they would be walked and two
|
|
980
980
|
// unrelated signals would pass for one — a params signal owned by one
|
|
981
981
|
// screen would then be handed the action bound to another's.
|
|
982
|
-
if (isSignal(a) || isSignal(b)) {
|
|
982
|
+
if (isSignal$1(a) || isSignal$1(b)) {
|
|
983
983
|
return false;
|
|
984
984
|
}
|
|
985
985
|
const aKeys = Object.keys(a);
|
|
@@ -2504,7 +2504,7 @@ const readReason = (source) => {
|
|
|
2504
2504
|
return null;
|
|
2505
2505
|
}
|
|
2506
2506
|
let reason;
|
|
2507
|
-
if (isSignal(source)) {
|
|
2507
|
+
if (isSignal$1(source)) {
|
|
2508
2508
|
reason = source.value;
|
|
2509
2509
|
} else if (typeof source === "function") {
|
|
2510
2510
|
reason = source();
|
|
@@ -3883,7 +3883,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3883
3883
|
const childActionWeakMap = createJsValueWeakMap();
|
|
3884
3884
|
const _bindParams = (newParamsOrSignal, options = {}) => {
|
|
3885
3885
|
// Case 1: a signal → proxy that retargets as the signal changes
|
|
3886
|
-
if (isSignal(newParamsOrSignal)) {
|
|
3886
|
+
if (isSignal$1(newParamsOrSignal)) {
|
|
3887
3887
|
// A getter builds a fresh object each time a signal it reads moves,
|
|
3888
3888
|
// equal or not. Equal params are the same question: the previous
|
|
3889
3889
|
// object is kept, so the binding's paramsSignal does not move and its
|
|
@@ -3917,7 +3917,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
3917
3917
|
const keyArray = Object.keys(newParamsOrSignal);
|
|
3918
3918
|
for (const key of keyArray) {
|
|
3919
3919
|
const value = newParamsOrSignal[key];
|
|
3920
|
-
if (isSignal(value)) {
|
|
3920
|
+
if (isSignal$1(value)) {
|
|
3921
3921
|
signalMap.set(key, value);
|
|
3922
3922
|
} else {
|
|
3923
3923
|
const objectSignal = value ? value[SYMBOL_OBJECT_SIGNAL] : null;
|
|
@@ -4019,7 +4019,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
4019
4019
|
}
|
|
4020
4020
|
const { debounce, ...optionsWithoutDebounce } = options;
|
|
4021
4021
|
if (debounce) {
|
|
4022
|
-
if (!isSignal(newParamsOrSignal)) {
|
|
4022
|
+
if (!isSignal$1(newParamsOrSignal)) {
|
|
4023
4023
|
console.warn(
|
|
4024
4024
|
`bindParams({ debounce }) expects a signal, received ${typeof newParamsOrSignal}: params that cannot change have nothing to settle.`,
|
|
4025
4025
|
);
|
|
@@ -4971,7 +4971,7 @@ const generateActionCallSource = (name, params) => {
|
|
|
4971
4971
|
// them (see _bindParams): a signal is its value, and so is each signal a plain
|
|
4972
4972
|
// object holds at its first level. Read inside a computed, it follows them.
|
|
4973
4973
|
const readParamsHandedToBind = (newParamsOrSignal) => {
|
|
4974
|
-
if (isSignal(newParamsOrSignal)) {
|
|
4974
|
+
if (isSignal$1(newParamsOrSignal)) {
|
|
4975
4975
|
return newParamsOrSignal.value;
|
|
4976
4976
|
}
|
|
4977
4977
|
if (!isPlainObject$2(newParamsOrSignal)) {
|
|
@@ -4980,7 +4980,7 @@ const readParamsHandedToBind = (newParamsOrSignal) => {
|
|
|
4980
4980
|
const params = {};
|
|
4981
4981
|
for (const key of Object.keys(newParamsOrSignal)) {
|
|
4982
4982
|
const value = newParamsOrSignal[key];
|
|
4983
|
-
const valueSignal = isSignal(value)
|
|
4983
|
+
const valueSignal = isSignal$1(value)
|
|
4984
4984
|
? value
|
|
4985
4985
|
: value
|
|
4986
4986
|
? value[SYMBOL_OBJECT_SIGNAL]
|
|
@@ -5396,11 +5396,25 @@ const generateSignalId = () => {
|
|
|
5396
5396
|
* @param {Object} [options={}] - Configuration options
|
|
5397
5397
|
* @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.
|
|
5398
5398
|
* @param {any} [options.default] - Static fallback value used when defaultValue is a signal and that signal's value is undefined
|
|
5399
|
-
* @param {boolean} [options.persists=false] - Whether to persist the signal value in localStorage using the signal ID as key
|
|
5399
|
+
* @param {boolean} [options.persists=false] - Whether to persist the signal value in localStorage using the signal ID as key.
|
|
5400
|
+
* The copy is the device's: every account signed in on this browser reads and writes the same one,
|
|
5401
|
+
* unless `owner` says whose it is.
|
|
5400
5402
|
* @param {string} [options.version] - What makes a stored copy unusable — the deployed version, a schema
|
|
5401
5403
|
* number. The value is persisted under `${id}@${version}`, and at creation the copies of every other
|
|
5402
5404
|
* version of this id (and the one stored under the bare id) are removed: a device that opened ten
|
|
5403
5405
|
* deploys holds one copy, not ten. Only the storage key changes, the id the url reads stays `id`.
|
|
5406
|
+
* @param {import("@preact/signals").ReadonlySignal<string | number | null | undefined> | (() => string | number | null | undefined)} [options.owner] -
|
|
5407
|
+
* Whose copy this is, for a state kept per account on a device several accounts share (search
|
|
5408
|
+
* criteria, a last choice): a signal, or a function read like a `computed`, naming the owner. The
|
|
5409
|
+
* value is persisted under `${id}#${owner}` (`${id}@${version}#${owner}` with a version).
|
|
5410
|
+
* When the owner changes, the state starts again as at creation, for that owner: what the address
|
|
5411
|
+
* says when it carries the param, otherwise that owner's copy, otherwise the default. The previous
|
|
5412
|
+
* owner's value is never carried across.
|
|
5413
|
+
* `undefined` or `null` is an owner not known yet: nothing is read and nothing is kept, the state
|
|
5414
|
+
* holds its default and what is written lives in memory until an owner is known.
|
|
5415
|
+
* At creation the copy kept under the bare id (from before the state had an owner) is removed, as
|
|
5416
|
+
* `version` does; the copies of the other owners are kept. Those of an owner that is gone for good
|
|
5417
|
+
* are removed by `forgetOwner(owner)`. Requires `persists`.
|
|
5404
5418
|
* @param {string} [options.type] - Type the value is coerced to, and read back as from localStorage and the url:
|
|
5405
5419
|
* any @jsenv/validity type (`"string"`, `"number"`, `"boolean"`, `"array"`, `"object"`, `"integer"`, `"date"`,
|
|
5406
5420
|
* `"time"`…). Without it the value is not coerced. On a type that is not text (`"string"`, `"email"`,
|
|
@@ -5522,6 +5536,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5522
5536
|
history = "replace",
|
|
5523
5537
|
debounceUrl = 0,
|
|
5524
5538
|
version,
|
|
5539
|
+
owner,
|
|
5525
5540
|
} = options;
|
|
5526
5541
|
|
|
5527
5542
|
if (history !== "replace" && history !== "push") {
|
|
@@ -5541,11 +5556,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5541
5556
|
}
|
|
5542
5557
|
|
|
5543
5558
|
// Check if defaultValue is a signal (dynamic default) or static value
|
|
5544
|
-
const isDynamicDefault =
|
|
5545
|
-
defaultValue &&
|
|
5546
|
-
typeof defaultValue === "object" &&
|
|
5547
|
-
"value" in defaultValue &&
|
|
5548
|
-
"peek" in defaultValue;
|
|
5559
|
+
const isDynamicDefault = isSignal(defaultValue);
|
|
5549
5560
|
const dynamicDefaultSignal = isDynamicDefault ? defaultValue : null;
|
|
5550
5561
|
const staticDefaultValue = isDynamicDefault ? staticFallback : defaultValue;
|
|
5551
5562
|
const signalId = id || generateSignalId();
|
|
@@ -5560,10 +5571,43 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5560
5571
|
}
|
|
5561
5572
|
}
|
|
5562
5573
|
|
|
5563
|
-
|
|
5574
|
+
let ownerSignal = null;
|
|
5575
|
+
if (owner !== undefined) {
|
|
5576
|
+
if (isSignal(owner)) {
|
|
5577
|
+
ownerSignal = owner;
|
|
5578
|
+
} else if (typeof owner === "function") {
|
|
5579
|
+
ownerSignal = computed(owner);
|
|
5580
|
+
} else {
|
|
5581
|
+
// `owner: me.id` is read once: the owner of the first page, for good.
|
|
5582
|
+
throw new TypeError(
|
|
5583
|
+
`stateSignal "${signalIdString}": owner must be a signal or a function naming the owner, got ${typeof owner} ${String(owner)}.`,
|
|
5584
|
+
);
|
|
5585
|
+
}
|
|
5586
|
+
}
|
|
5587
|
+
const versionKey =
|
|
5564
5588
|
version === undefined ? signalIdString : `${signalIdString}@${version}`;
|
|
5565
|
-
|
|
5566
|
-
|
|
5589
|
+
const storageKeyOf = (ownerValue) => {
|
|
5590
|
+
if (!ownerSignal) {
|
|
5591
|
+
return versionKey;
|
|
5592
|
+
}
|
|
5593
|
+
if (ownerValue === undefined || ownerValue === null) {
|
|
5594
|
+
return undefined;
|
|
5595
|
+
}
|
|
5596
|
+
if (typeof ownerValue !== "string" && typeof ownerValue !== "number") {
|
|
5597
|
+
// an object would be "[object Object]": one copy shared by every owner
|
|
5598
|
+
throw new TypeError(
|
|
5599
|
+
`stateSignal "${signalIdString}": owner names the owner with a string or a number, got ${typeof ownerValue}.`,
|
|
5600
|
+
);
|
|
5601
|
+
}
|
|
5602
|
+
return `${versionKey}#${ownerValue}`;
|
|
5603
|
+
};
|
|
5604
|
+
// The key the value is kept under. Undefined while the owner is not known:
|
|
5605
|
+
// what is written then belongs to no one, and is not kept.
|
|
5606
|
+
const storageKeySignal = signal(storageKeyOf(ownerSignal?.peek()));
|
|
5607
|
+
if (persists) {
|
|
5608
|
+
if (version !== undefined || ownerSignal) {
|
|
5609
|
+
removeStaleCopies(signalIdString, versionKey, Boolean(ownerSignal));
|
|
5610
|
+
}
|
|
5567
5611
|
}
|
|
5568
5612
|
const [validity, updateValidity, clearValidity] = createValidity({
|
|
5569
5613
|
type,
|
|
@@ -5578,22 +5622,16 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5578
5622
|
// processValue, below) so a dynamic default is read where it stands.
|
|
5579
5623
|
fallback: () => getDefaultValue(false),
|
|
5580
5624
|
});
|
|
5581
|
-
const readFromLocalStorage =
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
: () => {};
|
|
5592
|
-
const removeFromLocalStorage = persists
|
|
5593
|
-
? () => {
|
|
5594
|
-
writeLocalStorage(localStorageKey, undefined);
|
|
5595
|
-
}
|
|
5596
|
-
: () => {};
|
|
5625
|
+
const readFromLocalStorage = () => {
|
|
5626
|
+
const storageKey = storageKeySignal.peek();
|
|
5627
|
+
if (storageKey === undefined) {
|
|
5628
|
+
return undefined;
|
|
5629
|
+
}
|
|
5630
|
+
return readLocalStorage(storageKey);
|
|
5631
|
+
};
|
|
5632
|
+
const keepInLocalStorage = (storageKey) => {
|
|
5633
|
+
writeLocalStorage(storageKey, validity.representations.localStorage.value);
|
|
5634
|
+
};
|
|
5597
5635
|
|
|
5598
5636
|
/**
|
|
5599
5637
|
* Returns the current default value from code logic only (static or dynamic).
|
|
@@ -5642,7 +5680,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5642
5680
|
if (valueFromLocalStorage !== undefined) {
|
|
5643
5681
|
if (debug) {
|
|
5644
5682
|
console.debug(
|
|
5645
|
-
`[stateSignal:${signalIdString}] using value from localStorage "${
|
|
5683
|
+
`[stateSignal:${signalIdString}] using value from localStorage "${storageKeySignal.peek()}"=${valueFromLocalStorage}`,
|
|
5646
5684
|
);
|
|
5647
5685
|
}
|
|
5648
5686
|
return valueFromLocalStorage;
|
|
@@ -5841,11 +5879,17 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5841
5879
|
});
|
|
5842
5880
|
}
|
|
5843
5881
|
persist_in_local_storage: {
|
|
5844
|
-
if (!
|
|
5882
|
+
if (!persists) {
|
|
5845
5883
|
break persist_in_local_storage;
|
|
5846
5884
|
}
|
|
5847
5885
|
effect(() => {
|
|
5886
|
+
// The key and the value are read together: an owner switch writes both
|
|
5887
|
+
// in one batch (below), so a value is never kept under another owner.
|
|
5888
|
+
const storageKey = storageKeySignal.value;
|
|
5848
5889
|
const value = preactSignal.value;
|
|
5890
|
+
if (storageKey === undefined) {
|
|
5891
|
+
return;
|
|
5892
|
+
}
|
|
5849
5893
|
|
|
5850
5894
|
if (dynamicDefaultSignal) {
|
|
5851
5895
|
// With dynamic defaults: always persist to preserve user intent
|
|
@@ -5853,10 +5897,10 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5853
5897
|
if (value !== undefined) {
|
|
5854
5898
|
if (debug) {
|
|
5855
5899
|
console.debug(
|
|
5856
|
-
`[stateSignal:${signalIdString}] dynamic default: writing to localStorage "${
|
|
5900
|
+
`[stateSignal:${signalIdString}] dynamic default: writing to localStorage "${storageKey}"=${value}`,
|
|
5857
5901
|
);
|
|
5858
5902
|
}
|
|
5859
|
-
|
|
5903
|
+
keepInLocalStorage(storageKey);
|
|
5860
5904
|
}
|
|
5861
5905
|
return;
|
|
5862
5906
|
}
|
|
@@ -5864,18 +5908,57 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5864
5908
|
if (isCustomValue(value)) {
|
|
5865
5909
|
if (debug) {
|
|
5866
5910
|
console.debug(
|
|
5867
|
-
`[stateSignal:${signalIdString}] writing into localStorage "${
|
|
5911
|
+
`[stateSignal:${signalIdString}] writing into localStorage "${storageKey}"=${value}`,
|
|
5868
5912
|
);
|
|
5869
5913
|
}
|
|
5870
|
-
|
|
5914
|
+
keepInLocalStorage(storageKey);
|
|
5871
5915
|
} else {
|
|
5872
5916
|
if (debug) {
|
|
5873
5917
|
console.debug(
|
|
5874
|
-
`[stateSignal:${signalIdString}] removing "${
|
|
5918
|
+
`[stateSignal:${signalIdString}] removing "${storageKey}" from localStorage (value=${value})`,
|
|
5875
5919
|
);
|
|
5876
5920
|
}
|
|
5877
|
-
|
|
5921
|
+
writeLocalStorage(storageKey, undefined);
|
|
5922
|
+
}
|
|
5923
|
+
});
|
|
5924
|
+
}
|
|
5925
|
+
// What the address says this state holds, one reader per route binding it
|
|
5926
|
+
// (see route.js): an owner switch starts the state again as creation does,
|
|
5927
|
+
// and at creation the routing pass applies the address after the storage.
|
|
5928
|
+
const addressReaderSet = new Set();
|
|
5929
|
+
owner_switch: {
|
|
5930
|
+
if (!ownerSignal || !persists) {
|
|
5931
|
+
break owner_switch;
|
|
5932
|
+
}
|
|
5933
|
+
effect(() => {
|
|
5934
|
+
const storageKey = storageKeyOf(ownerSignal.value);
|
|
5935
|
+
if (storageKey === storageKeySignal.peek()) {
|
|
5936
|
+
return;
|
|
5878
5937
|
}
|
|
5938
|
+
untracked(() => {
|
|
5939
|
+
let valueFromAddress;
|
|
5940
|
+
for (const readAddress of addressReaderSet) {
|
|
5941
|
+
valueFromAddress = readAddress();
|
|
5942
|
+
if (valueFromAddress) {
|
|
5943
|
+
break;
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
if (debug) {
|
|
5947
|
+
console.debug(
|
|
5948
|
+
`[stateSignal:${signalIdString}] owner changed, kept under "${storageKey}"`,
|
|
5949
|
+
);
|
|
5950
|
+
}
|
|
5951
|
+
batch(() => {
|
|
5952
|
+
storageKeySignal.value = storageKey;
|
|
5953
|
+
if (valueFromAddress) {
|
|
5954
|
+
// eslint-disable-next-line signals/no-conditional-value-read -- a plain { value } from an address reader, not a signal
|
|
5955
|
+
facadeSignal.value = valueFromAddress.value;
|
|
5956
|
+
} else {
|
|
5957
|
+
// read once the key is the new owner's
|
|
5958
|
+
facadeSignal.value = getFallbackValue();
|
|
5959
|
+
}
|
|
5960
|
+
});
|
|
5961
|
+
});
|
|
5879
5962
|
});
|
|
5880
5963
|
}
|
|
5881
5964
|
// Create isDefaultValue function for this signal
|
|
@@ -5896,7 +5979,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5896
5979
|
min,
|
|
5897
5980
|
max,
|
|
5898
5981
|
persists,
|
|
5899
|
-
|
|
5982
|
+
addressReaderSet: ownerSignal && persists ? addressReaderSet : undefined,
|
|
5900
5983
|
debug,
|
|
5901
5984
|
...options,
|
|
5902
5985
|
history,
|
|
@@ -5917,7 +6000,7 @@ const stateSignal = (defaultValue, options = {}) => {
|
|
|
5917
6000
|
hasDynamicDefault: Boolean(dynamicDefaultSignal),
|
|
5918
6001
|
hasStoredValue: persists && readFromLocalStorage() !== undefined,
|
|
5919
6002
|
persists,
|
|
5920
|
-
localStorageKey: persists ?
|
|
6003
|
+
localStorageKey: persists ? storageKeySignal.peek() : undefined,
|
|
5921
6004
|
},
|
|
5922
6005
|
);
|
|
5923
6006
|
}
|
|
@@ -5955,21 +6038,60 @@ const takeHistoryOfWriteAsOne = () => {
|
|
|
5955
6038
|
return writeAsOne.history;
|
|
5956
6039
|
};
|
|
5957
6040
|
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
6041
|
+
/**
|
|
6042
|
+
* Removes every copy kept for `owner` by the states declaring an `owner`: an
|
|
6043
|
+
* account erased, a trial account that ended. Each state keeps one copy per
|
|
6044
|
+
* owner it has met, and only the app knows when an owner is gone for good.
|
|
6045
|
+
*
|
|
6046
|
+
* Only the storage is emptied: a state whose owner is `owner` right now keeps
|
|
6047
|
+
* what it holds, and keeps it again at its next write. Call it once the app
|
|
6048
|
+
* has left that owner.
|
|
6049
|
+
*
|
|
6050
|
+
* @param {string | number} owner
|
|
6051
|
+
*/
|
|
6052
|
+
const forgetOwner = (owner) => {
|
|
6053
|
+
const ownerSuffix = `#${owner}`;
|
|
6054
|
+
for (const key of listLocalStorageKeys()) {
|
|
6055
|
+
if (key.endsWith(ownerSuffix)) {
|
|
6056
|
+
writeLocalStorage(key, undefined);
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
};
|
|
6060
|
+
|
|
6061
|
+
// The copies an older deploy or an older declaration left: under
|
|
6062
|
+
// `${id}@<another version>`, under the bare id from before the signal declared
|
|
6063
|
+
// a version or an owner, under the owners of another version. Read once, at
|
|
6064
|
+
// creation: they are what a previous document wrote, nothing of this one writes
|
|
6065
|
+
// there. With an owner, every owner's copy of this version stays: another
|
|
6066
|
+
// owner's copy is not stale, it is someone else's.
|
|
6067
|
+
const removeStaleCopies = (id, versionKey, byOwner) => {
|
|
5962
6068
|
const versionPrefix = `${id}@`;
|
|
6069
|
+
const ownerPrefix = `${id}#`;
|
|
6070
|
+
const ownersOfVersionPrefix = `${versionKey}#`;
|
|
5963
6071
|
for (const key of listLocalStorageKeys()) {
|
|
5964
|
-
|
|
6072
|
+
const isCopyOfId =
|
|
6073
|
+
key === id ||
|
|
6074
|
+
key.startsWith(versionPrefix) ||
|
|
6075
|
+
key.startsWith(ownerPrefix);
|
|
6076
|
+
if (!isCopyOfId) {
|
|
5965
6077
|
continue;
|
|
5966
6078
|
}
|
|
5967
|
-
|
|
5968
|
-
|
|
6079
|
+
const kept = byOwner
|
|
6080
|
+
? key.startsWith(ownersOfVersionPrefix)
|
|
6081
|
+
: key === versionKey;
|
|
6082
|
+
if (kept) {
|
|
6083
|
+
continue;
|
|
5969
6084
|
}
|
|
6085
|
+
writeLocalStorage(key, undefined);
|
|
5970
6086
|
}
|
|
5971
6087
|
};
|
|
5972
6088
|
|
|
6089
|
+
const isSignal = (value) =>
|
|
6090
|
+
Boolean(value) &&
|
|
6091
|
+
typeof value === "object" &&
|
|
6092
|
+
"value" in value &&
|
|
6093
|
+
"peek" in value;
|
|
6094
|
+
|
|
5973
6095
|
/**
|
|
5974
6096
|
* Custom route pattern matching system.
|
|
5975
6097
|
* Not built on URLPattern: matching here is simpler and more predictable.
|
|
@@ -8699,7 +8821,7 @@ const route = (pattern, options = {}) => {
|
|
|
8699
8821
|
// Signal -> URL sync: When signal changes, update URL to reflect meaningful state
|
|
8700
8822
|
// Only sync non-default values to keep URLs clean (static fallbacks stay invisible)
|
|
8701
8823
|
registerSetup(({ routeSet }) => {
|
|
8702
|
-
const
|
|
8824
|
+
const cleanupSet = new Set();
|
|
8703
8825
|
// important: read connections at setup time so it includes query connections
|
|
8704
8826
|
// inherited from ancestor patterns
|
|
8705
8827
|
const { connections } = routePattern;
|
|
@@ -8824,11 +8946,37 @@ const route = (pattern, options = {}) => {
|
|
|
8824
8946
|
// entry when the write pushes.
|
|
8825
8947
|
untracked(() => writeValueInUrl(value));
|
|
8826
8948
|
});
|
|
8827
|
-
|
|
8949
|
+
cleanupSet.add(cleanupSignalUrlEffect);
|
|
8950
|
+
// A state kept per owner starts again when the owner changes, as at
|
|
8951
|
+
// creation: the address has the last word, as the routing pass gives it
|
|
8952
|
+
// (see sync_routes_with_url). Null when the address leaves it to storage.
|
|
8953
|
+
const { addressReaderSet } = connection;
|
|
8954
|
+
if (addressReaderSet) {
|
|
8955
|
+
const readAddress = () => {
|
|
8956
|
+
if (!route.matchingSignal.peek()) {
|
|
8957
|
+
return null;
|
|
8958
|
+
}
|
|
8959
|
+
const urlParamValue = route.rawParamsSignal.peek()[paramName];
|
|
8960
|
+
if (urlParamValue !== undefined) {
|
|
8961
|
+
return { value: urlParamValue };
|
|
8962
|
+
}
|
|
8963
|
+
if (
|
|
8964
|
+
connection.paramType === "query" &&
|
|
8965
|
+
connection.history !== "push"
|
|
8966
|
+
) {
|
|
8967
|
+
return null;
|
|
8968
|
+
}
|
|
8969
|
+
return { value: connection.getDefaultValue() };
|
|
8970
|
+
};
|
|
8971
|
+
addressReaderSet.add(readAddress);
|
|
8972
|
+
cleanupSet.add(() => {
|
|
8973
|
+
addressReaderSet.delete(readAddress);
|
|
8974
|
+
});
|
|
8975
|
+
}
|
|
8828
8976
|
}
|
|
8829
8977
|
return () => {
|
|
8830
|
-
for (const
|
|
8831
|
-
|
|
8978
|
+
for (const cleanup of cleanupSet) {
|
|
8979
|
+
cleanup();
|
|
8832
8980
|
}
|
|
8833
8981
|
};
|
|
8834
8982
|
});
|
|
@@ -25656,7 +25804,7 @@ const useActionBoundToOneParam = (
|
|
|
25656
25804
|
paramsSignal,
|
|
25657
25805
|
{ verb } = {},
|
|
25658
25806
|
) => {
|
|
25659
|
-
if (!isSignal(paramsSignal)) {
|
|
25807
|
+
if (!isSignal$1(paramsSignal)) {
|
|
25660
25808
|
throw new Error(
|
|
25661
25809
|
`useActionBoundToOneParam expects a signal as second argument, got: ${paramsSignal}`,
|
|
25662
25810
|
);
|
|
@@ -28980,7 +29128,7 @@ const resolveParams = (params) => {
|
|
|
28980
29128
|
const paramsResolved = {};
|
|
28981
29129
|
for (const key of Object.keys(params)) {
|
|
28982
29130
|
const value = params[key];
|
|
28983
|
-
paramsResolved[key] = isSignal(value) ? value.value : value;
|
|
29131
|
+
paramsResolved[key] = isSignal$1(value) ? value.value : value;
|
|
28984
29132
|
}
|
|
28985
29133
|
return paramsResolved;
|
|
28986
29134
|
};
|
|
@@ -41966,7 +42114,7 @@ const keepPageOnScreen = ({
|
|
|
41966
42114
|
when,
|
|
41967
42115
|
always = [],
|
|
41968
42116
|
} = {}) => {
|
|
41969
|
-
if (!isSignal(keptSignal)) {
|
|
42117
|
+
if (!isSignal$1(keptSignal)) {
|
|
41970
42118
|
throw new TypeError(
|
|
41971
42119
|
`keepPageOnScreen() needs a signal to write the page into, received ${keptSignal}`,
|
|
41972
42120
|
);
|
|
@@ -57218,6 +57366,7 @@ const NOTHING = {
|
|
|
57218
57366
|
known: false,
|
|
57219
57367
|
current: undefined,
|
|
57220
57368
|
toward: undefined,
|
|
57369
|
+
base: undefined,
|
|
57221
57370
|
areas: NO_WAYS,
|
|
57222
57371
|
ways: NO_WAYS,
|
|
57223
57372
|
held: NO_WAYS,
|
|
@@ -57240,6 +57389,14 @@ const readSlideContainerState = (element) => ({
|
|
|
57240
57389
|
known: true,
|
|
57241
57390
|
current: readSlideOnScreen(element),
|
|
57242
57391
|
toward: element.getAttribute(SLIDE_TOWARD_ATTRIBUTE) ?? undefined,
|
|
57392
|
+
// The slide --slide-travel-progress counts from, which is what a follower
|
|
57393
|
+
// drawing the travel measures from (a Nav's bar, a StepList's halo). Not the
|
|
57394
|
+
// slide on screen: a landing changes it after the heading has already said
|
|
57395
|
+
// where the row was going.
|
|
57396
|
+
base:
|
|
57397
|
+
element.getAttribute(SLIDE_BASE_ATTRIBUTE) ??
|
|
57398
|
+
element.getAttribute(SLIDE_CURRENT_ATTRIBUTE) ??
|
|
57399
|
+
undefined,
|
|
57243
57400
|
// In DOM order — which is the order of the WALK for a line, and not
|
|
57244
57401
|
// necessarily for a map: there the order is the one the areas are written in
|
|
57245
57402
|
// (see parseAreas). Ask `can("first")` / `can("last")` about the ends rather
|
|
@@ -57257,6 +57414,7 @@ const sameSlideContainerState = (a, b) =>
|
|
|
57257
57414
|
a.known === b.known &&
|
|
57258
57415
|
a.current === b.current &&
|
|
57259
57416
|
a.toward === b.toward &&
|
|
57417
|
+
a.base === b.base &&
|
|
57260
57418
|
a.areas.join(" ") === b.areas.join(" ") &&
|
|
57261
57419
|
a.ways.join(" ") === b.ways.join(" ") &&
|
|
57262
57420
|
a.held.join(" ") === b.held.join(" ");
|
|
@@ -57319,7 +57477,12 @@ const useSlideContainer = (target) => {
|
|
|
57319
57477
|
// (the box was already standing somewhere when this mounted), and one way
|
|
57320
57478
|
// of reading is one thing that can be wrong.
|
|
57321
57479
|
const read = () => {
|
|
57322
|
-
|
|
57480
|
+
// Without the base, which this does not return: a landing changes it
|
|
57481
|
+
// alone, and that is no reason to render the readers.
|
|
57482
|
+
const nextState = {
|
|
57483
|
+
...readSlideContainerState(element),
|
|
57484
|
+
base: undefined,
|
|
57485
|
+
};
|
|
57323
57486
|
setState((previous) =>
|
|
57324
57487
|
sameSlideContainerState(previous, nextState) ? previous : nextState,
|
|
57325
57488
|
);
|
|
@@ -107663,5 +107826,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
107663
107826
|
})
|
|
107664
107827
|
});
|
|
107665
107828
|
|
|
107666
|
-
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 };
|
|
107829
|
+
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 };
|
|
107667
107830
|
//# sourceMappingURL=jsenv_navi.js.map
|