@weasel-js/prefs 1.9.4 → 1.10.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/README.md +107 -0
- package/dist/chunk-ASSX3JHY.js +1180 -0
- package/dist/chunk-ASSX3JHY.js.map +1 -0
- package/dist/index.d.ts +376 -43
- package/dist/index.js +385 -564
- package/dist/index.js.map +1 -1
- package/dist/{store-CNFnA_3c.d.ts → open-C83pU7Va.d.ts} +315 -61
- package/dist/react.d.ts +33 -4
- package/dist/react.js +75 -3
- package/dist/react.js.map +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,191 +1,394 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { unitScale, formatUnit } from '@weasel-js/quantity';
|
|
1
|
+
import { prefLeafHoldingIn, prefLeafHolding, prefSchemaHolding, UNSEEN, prefConditionHolds, prefValueAtPath, isPrefSection, prefSectionLeaves, isPrefLeaf, prefLeafAt, prefLeaves, prefHoldsValue, prefSelectors, prefAliasTarget, prefAliasedLeaf, isBuiltinPref, pairRowsOf, prefConditionReadsItem, visiblePrefSubtree, resolvePrefUnit, isPrefLocus } from './chunk-ASSX3JHY.js';
|
|
2
|
+
export { PREF_BLENDS, PREF_KINDS, VERSION_RECORD, checkPrefCondition, checkPrefConditions, checkPrefSplits, filterPrefSubtree, flattenPrefValues, isBuiltinPref, isPrefCondition, isPrefLeaf, isPrefLinearUnit, isPrefLocus, isPrefSection, mapPrefConditionPaths, openPrefs, openPrefsSync, pairRowsOf, prefAliasName, prefAliasTarget, prefAliasedLeaf, prefConditionHolds, prefConditionPaths, prefConditionReadsItem, prefDisplayBounds, prefHoldsValue, prefIsEnabled, prefIsShown, prefLeafAt, prefLeaves, memberAt as prefLocusMember, locusSelectors as prefLocusSelectors, prefSchemaHolding, prefSectionLeaves, prefUnit, prefValueAtPath, prefVariantDefault, prefVariantOf, repairPrefValue, resolvePrefUnit, visiblePrefSubtree } from './chunk-ASSX3JHY.js';
|
|
4
3
|
|
|
5
|
-
// src/
|
|
6
|
-
function
|
|
7
|
-
const
|
|
8
|
-
let
|
|
9
|
-
for (
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
// src/tabRuns.ts
|
|
5
|
+
function prefTabRuns(items, isTab) {
|
|
6
|
+
const out = [];
|
|
7
|
+
let run;
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
if (!isTab(item)) {
|
|
10
|
+
run = void 0;
|
|
11
|
+
out.push({ item });
|
|
12
|
+
} else if (run) {
|
|
13
|
+
run.push(item);
|
|
14
|
+
} else {
|
|
15
|
+
out.push({ tabs: run = [item] });
|
|
16
|
+
}
|
|
16
17
|
}
|
|
18
|
+
return out;
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
// src/shown.ts
|
|
22
|
+
function prefShownValue(leaf2, stored, siblings) {
|
|
23
|
+
if (leaf2.kind !== "boolean" && leaf2.kind !== "enum") return stored;
|
|
24
|
+
const { encoding } = leaf2;
|
|
25
|
+
return encoding ? encoding.read(stored, siblings) : stored;
|
|
26
|
+
}
|
|
27
|
+
function prefShownReader(schema, read, item, over) {
|
|
28
|
+
return (path, from) => {
|
|
29
|
+
const stored = read(path, from);
|
|
30
|
+
const held = from === "item" ? item && prefLeafHoldingIn(item, path) : prefLeafHolding(prefSchemaHolding(schema, path, over), path);
|
|
31
|
+
if (held === void 0 || held === UNSEEN) return stored;
|
|
32
|
+
const object = held.within === void 0 ? void 0 : read(held.within, from);
|
|
33
|
+
return prefShownValue(held.leaf, stored, typeof object === "object" && object !== null ? object : void 0);
|
|
23
34
|
};
|
|
24
35
|
}
|
|
25
36
|
|
|
26
|
-
// src/
|
|
27
|
-
function
|
|
28
|
-
if (
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
// src/judge.ts
|
|
38
|
+
function entryValue({ item, value }, path) {
|
|
39
|
+
if (path === "") return value !== void 0 ? value : item.default;
|
|
40
|
+
const held = prefValueAtPath(value, path);
|
|
41
|
+
return held !== void 0 ? held : prefValueAtPath(item.default, path);
|
|
42
|
+
}
|
|
43
|
+
function prefJudge(schema, read, entry, over) {
|
|
44
|
+
const stored = (path, from) => from === "item" ? entry && entryValue(entry, path) : read(path);
|
|
45
|
+
const shown = prefShownReader(schema, stored, entry?.item, over);
|
|
46
|
+
return (condition) => prefConditionHolds(condition, shown);
|
|
47
|
+
}
|
|
48
|
+
function deferEntryConditions(holds) {
|
|
49
|
+
return (condition, field) => prefConditionReadsItem(condition) || holds(condition, field);
|
|
50
|
+
}
|
|
51
|
+
function prefReader(schema, values, over) {
|
|
52
|
+
const beyond = over && prefReader(over, values);
|
|
53
|
+
return (path) => {
|
|
54
|
+
const held = prefValueAtPath(values, path);
|
|
55
|
+
if (held !== void 0) return held;
|
|
56
|
+
if (beyond && prefSchemaHolding(schema, path, over) === over) return beyond(path);
|
|
57
|
+
if (isPrefSection(schema)) {
|
|
58
|
+
for (const [key, leaf2] of prefSectionLeaves(schema.members)) {
|
|
59
|
+
if (path === key) return leaf2.default;
|
|
60
|
+
if (path.startsWith(`${key}.`)) return prefValueAtPath(leaf2.default, path.slice(key.length + 1));
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
const steps = path.split(".");
|
|
65
|
+
let node = schema;
|
|
66
|
+
for (let i = 0; i < steps.length; i++) {
|
|
67
|
+
if (!Object.hasOwn(node.children, steps[i])) return void 0;
|
|
68
|
+
const child = node.children[steps[i]];
|
|
69
|
+
if (!isPrefLeaf(child)) node = child;
|
|
70
|
+
else return i === steps.length - 1 ? child.default : prefValueAtPath(child.default, steps.slice(i + 1).join("."));
|
|
71
|
+
}
|
|
72
|
+
return void 0;
|
|
73
|
+
};
|
|
45
74
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
75
|
+
|
|
76
|
+
// src/scopeAt.ts
|
|
77
|
+
var PREF_ENTRY = "*";
|
|
78
|
+
var PREF_SCOPE = Object.freeze({ shown: true, enabled: true });
|
|
79
|
+
function prefScopeUnder(above, node, holds) {
|
|
80
|
+
const shown = above.shown && (node.showIf === void 0 || holds(node.showIf, "showIf"));
|
|
81
|
+
const enabled = above.enabled && (node.enableIf === void 0 || holds(node.enableIf, "enableIf"));
|
|
82
|
+
return shown === above.shown && enabled === above.enabled ? above : { shown, enabled };
|
|
83
|
+
}
|
|
84
|
+
function scopeAmong(held, rest, above, holds) {
|
|
85
|
+
for (const [key, child] of Object.entries(held)) {
|
|
86
|
+
if (!isPrefLeaf(child)) {
|
|
87
|
+
const found = scopeAmong(child.members, rest, prefScopeUnder(above, child, holds), holds);
|
|
88
|
+
if (found) return found;
|
|
89
|
+
} else if (rest === key) return prefScopeUnder(above, child, holds);
|
|
90
|
+
else if (rest.startsWith(`${key}.`)) return scopeInside(child, rest.slice(key.length + 1), prefScopeUnder(above, child, holds), holds);
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
function scopeInside(leaf2, rest, scope, holds) {
|
|
95
|
+
if (leaf2.kind === "object") return scopeAmong(leaf2.children, rest, scope, holds) ?? scope;
|
|
96
|
+
if (leaf2.kind === "list" || leaf2.kind === "map") {
|
|
97
|
+
const { item } = leaf2;
|
|
98
|
+
if (item === void 0) return scope;
|
|
99
|
+
const inItem = deferEntryConditions(holds);
|
|
100
|
+
const entry = prefScopeUnder(scope, { enableIf: item.enableIf }, inItem);
|
|
101
|
+
const dot = rest.indexOf(".");
|
|
102
|
+
return dot < 0 ? entry : scopeInside(item, rest.slice(dot + 1), entry, inItem);
|
|
103
|
+
}
|
|
104
|
+
if (leaf2.kind !== "union") return scope;
|
|
105
|
+
for (const variant of Object.values(leaf2.variants)) {
|
|
106
|
+
const found = scopeAmong(variant.children, rest, scope, holds);
|
|
107
|
+
if (found) return found;
|
|
108
|
+
}
|
|
109
|
+
return scope;
|
|
50
110
|
}
|
|
51
|
-
function
|
|
52
|
-
|
|
111
|
+
function scopeAt(schema, path, holds) {
|
|
112
|
+
let scope = prefScopeUnder(PREF_SCOPE, schema, holds);
|
|
113
|
+
if (path === "") return scope;
|
|
114
|
+
if (isPrefSection(schema)) return scopeAmong(schema.members, path, scope, holds) ?? scope;
|
|
53
115
|
let node = schema;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
116
|
+
const steps = path.split(".");
|
|
117
|
+
for (let i = 0; i < steps.length; i++) {
|
|
118
|
+
if (!Object.hasOwn(node.children, steps[i])) return scope;
|
|
119
|
+
const child = node.children[steps[i]];
|
|
120
|
+
scope = prefScopeUnder(scope, child, holds);
|
|
121
|
+
if (isPrefLeaf(child)) return i === steps.length - 1 ? scope : scopeInside(child, steps.slice(i + 1).join("."), scope, holds);
|
|
122
|
+
node = child;
|
|
57
123
|
}
|
|
58
|
-
return
|
|
124
|
+
return scope;
|
|
59
125
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return
|
|
126
|
+
function prefAliasScope(own, alias, over, holds) {
|
|
127
|
+
const target = prefAliasTarget(alias, (path) => prefLeafAt(over, path));
|
|
128
|
+
if (target === void 0) return own;
|
|
129
|
+
const theirs = scopeAt(over, target.path, holds);
|
|
130
|
+
const shown = own.shown && theirs.shown;
|
|
131
|
+
const enabled = own.enabled && theirs.enabled;
|
|
132
|
+
return shown === own.shown && enabled === own.enabled ? own : { shown, enabled };
|
|
133
|
+
}
|
|
134
|
+
function prefScopeAt(schema, path, holds, { aliasOver, aliasHolds } = {}) {
|
|
135
|
+
const own = scopeAt(schema, path, holds);
|
|
136
|
+
const leaf2 = prefLeafAt(schema, path);
|
|
137
|
+
return leaf2?.kind === "alias" ? prefAliasScope(own, leaf2, aliasOver ?? schema, aliasHolds ?? holds) : own;
|
|
67
138
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
139
|
+
|
|
140
|
+
// src/scope.ts
|
|
141
|
+
var under = (prefix, key) => prefix === "" ? key : `${prefix}.${key}`;
|
|
142
|
+
function leafWalk({ keepEmpty, keepHidden, inItem, aliasOver, aliasHolds }) {
|
|
143
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
144
|
+
const hidden = /* @__PURE__ */ new Set();
|
|
145
|
+
const leaf2 = (node, path, above, holds) => {
|
|
146
|
+
const own = prefScopeUnder(above, node, holds);
|
|
147
|
+
const scope = node.kind === "alias" && aliasOver ? prefAliasScope(own, node, aliasOver, aliasHolds ?? holds) : own;
|
|
148
|
+
return scope.shown || keepHidden ? inside(node, path, scope, holds) : null;
|
|
149
|
+
};
|
|
150
|
+
const inside = (node, path, scope, holds) => {
|
|
151
|
+
if (!scope.shown) hidden.add(path);
|
|
152
|
+
if (!scope.enabled) disabled.add(path);
|
|
153
|
+
if (node.kind === "object") {
|
|
154
|
+
const children = members(node.children, path, scope, holds);
|
|
155
|
+
return children === node.children ? node : { ...node, children };
|
|
75
156
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
157
|
+
if (node.kind === "list" || node.kind === "map") {
|
|
158
|
+
const { item } = node;
|
|
159
|
+
if (item === void 0) return node;
|
|
160
|
+
const entry = inside(item, under(path, PREF_ENTRY), prefScopeUnder(scope, { enableIf: item.enableIf }, inItem), inItem);
|
|
161
|
+
return entry === item ? node : { ...node, item: entry };
|
|
162
|
+
}
|
|
163
|
+
if (node.kind !== "union") return node;
|
|
164
|
+
const { variants } = node;
|
|
165
|
+
let changed = false;
|
|
166
|
+
const next = {};
|
|
167
|
+
for (const [key, variant] of Object.entries(variants)) {
|
|
168
|
+
const children = members(variant.children, path, scope, holds);
|
|
169
|
+
changed ||= children !== variant.children;
|
|
170
|
+
next[key] = children === variant.children ? variant : { ...variant, children };
|
|
171
|
+
}
|
|
172
|
+
return changed ? { ...node, variants: next } : node;
|
|
173
|
+
};
|
|
174
|
+
const members = (held, prefix, above, holds) => {
|
|
175
|
+
let changed = false;
|
|
176
|
+
const out = {};
|
|
177
|
+
for (const [key, child] of Object.entries(held)) {
|
|
178
|
+
const kept = isPrefLeaf(child) ? leaf2(child, under(prefix, key), above, holds) : section(child, prefix, above, holds);
|
|
179
|
+
changed ||= kept !== child;
|
|
180
|
+
if (kept !== null) out[key] = kept;
|
|
181
|
+
}
|
|
182
|
+
return changed ? out : held;
|
|
183
|
+
};
|
|
184
|
+
const section = (node, prefix, above, holds) => {
|
|
185
|
+
const scope = prefScopeUnder(above, node, holds);
|
|
186
|
+
if (!scope.shown && !keepHidden) return null;
|
|
187
|
+
const kept = members(node.members, prefix, scope, holds);
|
|
188
|
+
if (kept === node.members) return node;
|
|
189
|
+
return Object.keys(kept).length === 0 && !keepEmpty ? null : { ...node, members: kept };
|
|
190
|
+
};
|
|
191
|
+
return { disabled, hidden, leaf: leaf2, inside, members };
|
|
192
|
+
}
|
|
193
|
+
function applyPrefConditions(schema, holds, { keepEmpty = false, keepHidden = false, aliasOver, aliasHolds } = {}) {
|
|
194
|
+
const walk = leafWalk({ keepEmpty, keepHidden, inItem: deferEntryConditions(holds), aliasOver: aliasOver ?? schema, aliasHolds });
|
|
195
|
+
const { disabled, hidden } = walk;
|
|
196
|
+
const group = (node, path, above) => {
|
|
197
|
+
const scope2 = prefScopeUnder(above, node, holds);
|
|
198
|
+
if (!scope2.shown && !keepHidden) return null;
|
|
199
|
+
if (!scope2.shown && path !== "") hidden.add(path);
|
|
200
|
+
if (!scope2.enabled && path !== "") disabled.add(path);
|
|
201
|
+
let changed = false;
|
|
202
|
+
const children = {};
|
|
203
|
+
for (const [key, child] of Object.entries(node.children)) {
|
|
204
|
+
const at = under(path, key);
|
|
205
|
+
const kept2 = isPrefLeaf(child) ? walk.leaf(child, at, scope2, holds) : group(child, at, scope2);
|
|
206
|
+
changed ||= kept2 !== child;
|
|
207
|
+
if (kept2 !== null) children[key] = kept2;
|
|
208
|
+
}
|
|
209
|
+
if (!changed) return node;
|
|
210
|
+
return Object.keys(children).length === 0 && !keepEmpty && path !== "" ? null : { ...node, children };
|
|
211
|
+
};
|
|
212
|
+
if (!isPrefSection(schema)) return { shown: group(schema, "", PREF_SCOPE), disabled, hidden };
|
|
213
|
+
const scope = prefScopeUnder(PREF_SCOPE, schema, holds);
|
|
214
|
+
if (!scope.shown && !keepHidden) return { shown: null, disabled, hidden };
|
|
215
|
+
const kept = walk.members(schema.members, "", scope, holds);
|
|
216
|
+
return { shown: kept === schema.members ? schema : { ...schema, members: kept }, disabled, hidden };
|
|
217
|
+
}
|
|
218
|
+
var ALWAYS = () => true;
|
|
219
|
+
function applyPrefEntryConditions(item, path, holds, { keepEmpty = false, keepHidden = false } = {}) {
|
|
220
|
+
const asked = (condition, field) => !prefConditionReadsItem(condition) || holds(condition, field);
|
|
221
|
+
const walk = leafWalk({ keepEmpty, keepHidden, inItem: ALWAYS });
|
|
222
|
+
const scope = prefScopeUnder(PREF_SCOPE, { enableIf: item.enableIf }, asked);
|
|
223
|
+
return { item: walk.inside(item, path, scope, asked), disabled: walk.disabled, hidden: walk.hidden };
|
|
80
224
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
225
|
+
|
|
226
|
+
// src/build.ts
|
|
227
|
+
var leaf = (kind, name, def, rest) => ({ kind, name, description: "", default: def, ...rest });
|
|
228
|
+
var labeled = (value) => value === "" ? value : value[0].toUpperCase() + value.slice(1);
|
|
229
|
+
var pref = {
|
|
230
|
+
/** A group: `children` nest under its key, which is a segment of their paths. */
|
|
231
|
+
group(name, children, options) {
|
|
232
|
+
return { name, ...options, children };
|
|
233
|
+
},
|
|
234
|
+
/** A section: a heading over `members`, whose key adds nothing to their paths. */
|
|
235
|
+
section(name, members, options) {
|
|
236
|
+
return { name, ...options, members };
|
|
237
|
+
},
|
|
238
|
+
number: (name, def, rest) => leaf("number", name, def, rest),
|
|
239
|
+
boolean: (name, def, rest) => leaf("boolean", name, def, rest),
|
|
240
|
+
string: (name, def, rest) => leaf("string", name, def, rest),
|
|
241
|
+
color: (name, def, rest) => leaf("color", name, def, rest),
|
|
242
|
+
/** A fixed set of choices. An option given as its value alone is labeled with that value, its first letter raised. */
|
|
243
|
+
enum(name, def, options, rest) {
|
|
244
|
+
const full = options.map((option) => typeof option === "string" ? { value: option, label: labeled(option) } : option);
|
|
245
|
+
return { kind: "enum", name, description: "", default: def, ...rest, options: full };
|
|
86
246
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/css.ts
|
|
250
|
+
var kebab = (path) => path.replace(/\./g, "-").replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
251
|
+
var CSS_UNITS = {
|
|
252
|
+
px: "px",
|
|
253
|
+
"%": "%",
|
|
254
|
+
em: "em",
|
|
255
|
+
rem: "rem",
|
|
256
|
+
ch: "ch",
|
|
257
|
+
pt: "pt",
|
|
258
|
+
vw: "vw",
|
|
259
|
+
vh: "vh",
|
|
260
|
+
ms: "ms",
|
|
261
|
+
s: "s",
|
|
262
|
+
"\xB0": "deg",
|
|
263
|
+
deg: "deg",
|
|
264
|
+
rad: "rad",
|
|
265
|
+
turn: "turn"
|
|
266
|
+
};
|
|
267
|
+
var IDENT = /^-?[A-Za-z_][\w-]*$/;
|
|
268
|
+
var quoted = (text) => `'${text.replace(/[\\']/g, "\\$&")}'`;
|
|
269
|
+
function cssValue(leaf2, value) {
|
|
270
|
+
switch (leaf2.kind) {
|
|
271
|
+
case "number": {
|
|
272
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
273
|
+
const { unit } = leaf2;
|
|
274
|
+
const resolved = unit ? resolvePrefUnit(unit) : void 0;
|
|
275
|
+
const shown = resolved ? resolved.toDisplay(value) : value;
|
|
276
|
+
const suffix = resolved?.suffix !== void 0 && Object.hasOwn(CSS_UNITS, resolved.suffix) ? CSS_UNITS[resolved.suffix] : "";
|
|
277
|
+
return `${Number(shown.toFixed(6))}${suffix}`;
|
|
278
|
+
}
|
|
279
|
+
case "boolean":
|
|
280
|
+
return typeof value === "boolean" ? value ? "1" : "0" : null;
|
|
281
|
+
case "color":
|
|
282
|
+
return typeof value === "string" && value !== "" ? value : null;
|
|
283
|
+
case "enum":
|
|
284
|
+
if (typeof value !== "string" || leaf2.encoding) return null;
|
|
285
|
+
return IDENT.test(value) ? value : quoted(value);
|
|
286
|
+
case "string":
|
|
287
|
+
return typeof value === "string" ? quoted(value) : null;
|
|
288
|
+
default:
|
|
289
|
+
return null;
|
|
92
290
|
}
|
|
93
|
-
if (Object.keys(children).length === 0 && !keepEmpty) return null;
|
|
94
|
-
return { ...node, children };
|
|
95
291
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
throw new Error(`[prefs] schema key "${VERSION_RECORD}" is reserved`);
|
|
106
|
-
}
|
|
107
|
-
const path = prefix === "" ? key : `${prefix}.${key}`;
|
|
108
|
-
if (isPrefLeaf(child)) out.set(path, child);
|
|
109
|
-
else walk(child, path);
|
|
292
|
+
function toldApart(held, optionsOf, absent) {
|
|
293
|
+
const out = [];
|
|
294
|
+
const walk = (value, under2) => {
|
|
295
|
+
if (!isPrefLocus(value)) {
|
|
296
|
+
out.push({ under: under2, value });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
for (const option of optionsOf(value.$by)) {
|
|
300
|
+
walk(Object.hasOwn(value.$of, option) ? value.$of[option] : absent, [...under2, [value.$by, option]]);
|
|
110
301
|
}
|
|
111
302
|
};
|
|
112
|
-
walk(
|
|
303
|
+
walk(held, []);
|
|
113
304
|
return out;
|
|
114
305
|
}
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
306
|
+
function prefsCss(store, options = {}) {
|
|
307
|
+
const root = options.root ?? ":root";
|
|
308
|
+
const property = options.property ?? ((path) => `--${kebab(path)}`);
|
|
309
|
+
const attribute = options.attribute ?? ((selector) => `data-${kebab(selector)}`);
|
|
310
|
+
const leaves = new Map([...prefLeaves(store.schema)].filter(([, leaf2]) => prefHoldsValue(leaf2)));
|
|
311
|
+
const selectors = prefSelectors(leaves);
|
|
312
|
+
const defaults = Object.fromEntries([...selectors.keys()].map((path) => [path, leaves.get(path).default]));
|
|
313
|
+
const base = store.values({ at: defaults });
|
|
314
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
315
|
+
const declare = (under2, path, leaf2, value) => {
|
|
316
|
+
const name = property(path, leaf2);
|
|
317
|
+
if (name === null) return;
|
|
318
|
+
const given = options.value?.(value, leaf2, path);
|
|
319
|
+
const text = given === void 0 ? cssValue(leaf2, value) : given;
|
|
320
|
+
if (text === null) return;
|
|
321
|
+
const key = under2.map(([selector, option]) => `${selector}=${option}`).join("&");
|
|
322
|
+
if (!blocks.has(key)) blocks.set(key, { under: under2, lines: [] });
|
|
323
|
+
blocks.get(key).lines.push(` ${name}: ${text};`);
|
|
324
|
+
};
|
|
325
|
+
for (const [path, leaf2] of leaves) {
|
|
326
|
+
declare([], path, leaf2, prefValueAtPath(base, path));
|
|
327
|
+
const own = selectors.get(path);
|
|
328
|
+
if (own) for (const option of own) declare([[path, option]], path, leaf2, option);
|
|
329
|
+
const held = store.locus(path);
|
|
330
|
+
if (!held) continue;
|
|
331
|
+
for (const { under: under2, value } of toldApart(held, (selector) => selectors.get(selector) ?? [], leaf2.default)) {
|
|
332
|
+
declare(under2, path, leaf2, value);
|
|
333
|
+
}
|
|
132
334
|
}
|
|
133
|
-
return
|
|
335
|
+
return [...blocks.values()].map((block, i) => ({ ...block, i })).sort((a, b) => a.under.length - b.under.length || a.i - b.i).map(({ under: under2, lines }) => {
|
|
336
|
+
const matched = under2.map(([selector, option]) => `[${attribute(selector)}=${quoted(option)}]`).join("");
|
|
337
|
+
return `:where(${root}${matched}) {
|
|
338
|
+
${lines.join("\n")}
|
|
339
|
+
}`;
|
|
340
|
+
}).join("\n\n");
|
|
341
|
+
}
|
|
342
|
+
function prefsCssAttributes(store, options = {}) {
|
|
343
|
+
const attribute = options.attribute ?? ((selector) => `data-${kebab(selector)}`);
|
|
344
|
+
const leaves = prefLeaves(store.schema);
|
|
345
|
+
return Object.fromEntries([...prefSelectors(leaves).keys()].map((path) => [attribute(path), store.get(path)]));
|
|
134
346
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
347
|
+
|
|
348
|
+
// src/aliasTargets.ts
|
|
349
|
+
function visibleFieldsOf(leaf2) {
|
|
350
|
+
if (leaf2.kind !== "object") return leaf2;
|
|
351
|
+
const shown = visiblePrefSubtree({ ...leaf2, hidden: false }, false, true);
|
|
352
|
+
return { ...leaf2, children: shown.children };
|
|
353
|
+
}
|
|
354
|
+
function prefAliasTargets(over, judge, { showHidden = false, markHidden = false } = {}) {
|
|
355
|
+
const holds = judge();
|
|
356
|
+
let applied;
|
|
357
|
+
const get = () => applied ??= applyPrefConditions(over, holds, { keepEmpty: true, keepHidden: markHidden });
|
|
358
|
+
const leafAt = (path) => {
|
|
359
|
+
const { shown } = get();
|
|
360
|
+
const leaf2 = shown === null ? void 0 : prefLeafAt(shown, path);
|
|
361
|
+
return leaf2 === void 0 || showHidden ? leaf2 : visibleFieldsOf(leaf2);
|
|
362
|
+
};
|
|
363
|
+
return {
|
|
364
|
+
holds,
|
|
365
|
+
leafAt,
|
|
366
|
+
shown: (alias) => {
|
|
367
|
+
const target = prefAliasTarget(alias, leafAt);
|
|
368
|
+
return target && { path: target.path, leaf: prefAliasedLeaf(alias, target.leaf) };
|
|
369
|
+
},
|
|
370
|
+
disabledAt: (path) => get().disabled.has(path),
|
|
371
|
+
...markHidden ? { hiddenAt: (path) => get().hidden.has(path) } : {},
|
|
372
|
+
entryAt: (item, path, value) => applyPrefEntryConditions(item, path, judge({ item, value }), { keepHidden: markHidden })
|
|
373
|
+
};
|
|
158
374
|
}
|
|
159
375
|
|
|
160
376
|
// src/object.ts
|
|
161
377
|
var isObject = (v) => typeof v === "object" && v !== null;
|
|
162
|
-
function prefObjectBase(
|
|
378
|
+
function prefObjectBase(pref2, held) {
|
|
163
379
|
if (isObject(held)) return held;
|
|
164
|
-
return
|
|
380
|
+
return pref2.fromScalar?.(held) ?? (isObject(pref2.default) ? pref2.default : {});
|
|
165
381
|
}
|
|
166
|
-
function prefObjectWithField(
|
|
167
|
-
const base = prefObjectBase(
|
|
382
|
+
function prefObjectWithField(pref2, held, key, value) {
|
|
383
|
+
const base = prefObjectBase(pref2, held);
|
|
168
384
|
if (value !== void 0) return { ...base, [key]: value };
|
|
169
385
|
const { [key]: _dropped, ...rest } = base;
|
|
170
386
|
return rest;
|
|
171
387
|
}
|
|
172
388
|
|
|
173
|
-
// src/union.ts
|
|
174
|
-
function prefVariantOf(leaf, value) {
|
|
175
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
176
|
-
const key = value[leaf.tag];
|
|
177
|
-
if (typeof key !== "string" || !Object.hasOwn(leaf.variants, key)) return void 0;
|
|
178
|
-
return [key, leaf.variants[key]];
|
|
179
|
-
}
|
|
180
|
-
function prefVariantDefault(leaf, key) {
|
|
181
|
-
const held = leaf.variants[key]?.default;
|
|
182
|
-
const fields = held !== null && typeof held === "object" ? held : {};
|
|
183
|
-
return { ...fields, [leaf.tag]: key };
|
|
184
|
-
}
|
|
185
|
-
|
|
186
389
|
// src/type.ts
|
|
187
|
-
function prefType(name,
|
|
188
|
-
return { ...
|
|
390
|
+
function prefType(name, leaf2) {
|
|
391
|
+
return { ...leaf2, type: name };
|
|
189
392
|
}
|
|
190
393
|
|
|
191
394
|
// src/groups.ts
|
|
@@ -193,354 +396,34 @@ function prefGroupIsPage(group) {
|
|
|
193
396
|
return group.as === void 0 || group.as === "page";
|
|
194
397
|
}
|
|
195
398
|
|
|
196
|
-
// src/
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
function readRecord(record, unstamped) {
|
|
207
|
-
return isStampedRecord(record) ? { at: record.$at, value: record.value, stamped: true } : { at: unstamped, value: record, stamped: false };
|
|
208
|
-
}
|
|
209
|
-
function recordValue(record) {
|
|
210
|
-
return isStampedRecord(record) ? record.value : record;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// src/migrate.ts
|
|
214
|
-
var isVersion2 = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
|
|
215
|
-
function runPrefsMigrations(cache, migrations, { stampAll = true } = {}) {
|
|
216
|
-
const target = migrations.length;
|
|
217
|
-
const raw = cache.get(VERSION_RECORD);
|
|
218
|
-
if (cache.has(VERSION_RECORD) && !isVersion2(raw)) {
|
|
219
|
-
console.warn(
|
|
220
|
-
`[prefs] "${cache.prefix}" has an unreadable ${VERSION_RECORD} (${JSON.stringify(raw)}); opening read-only`
|
|
221
|
-
);
|
|
222
|
-
cache.stopWriting();
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
const stored = cache.has(VERSION_RECORD) ? raw : 0;
|
|
226
|
-
const held = cache.entries().filter(([name]) => name !== VERSION_RECORD).map(([name, record]) => ({ name, ...readRecord(record, Math.min(stored, target)) }));
|
|
227
|
-
const newest = Math.max(stored, ...held.map((r) => r.at));
|
|
228
|
-
if (newest > target) {
|
|
229
|
-
console.warn(
|
|
230
|
-
`[prefs] "${cache.prefix}" was written at version ${newest}, newer than this build's ${target}; opening read-only`
|
|
231
|
-
);
|
|
232
|
-
cache.stopWriting();
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
if (!cache.writable) return false;
|
|
236
|
-
const at = new Map(held.filter((r) => r.at < target).map((r) => [r.name, r.at]));
|
|
237
|
-
const records = new Map(held.filter((r) => at.has(r.name)).map((r) => [r.name, structuredClone(r.value)]));
|
|
238
|
-
for (let v = Math.min(target, ...at.values()); v < target; v++) {
|
|
239
|
-
const due = new Map([...records].filter(([name]) => at.get(name) <= v));
|
|
240
|
-
const before = [...due.keys()];
|
|
241
|
-
try {
|
|
242
|
-
migrations[v](due);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.warn(
|
|
245
|
-
`[prefs] migration ${v} \u2192 ${v + 1} for "${cache.prefix}" threw; opening read-only on the unmigrated records`,
|
|
246
|
-
error
|
|
247
|
-
);
|
|
248
|
-
cache.stopWriting();
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
for (const name of before) if (!due.has(name)) records.delete(name);
|
|
252
|
-
for (const [name, value] of due) {
|
|
253
|
-
records.set(name, value);
|
|
254
|
-
at.set(name, v + 1);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
let wrote = false;
|
|
258
|
-
for (const r of held) {
|
|
259
|
-
if (at.has(r.name)) {
|
|
260
|
-
if (!records.has(r.name)) cache.delete(r.name);
|
|
261
|
-
wrote = true;
|
|
262
|
-
} else if (stampAll && !r.stamped) {
|
|
263
|
-
cache.set(r.name, stampRecord(r.value, target));
|
|
264
|
-
wrote = true;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
for (const [name, value] of records) {
|
|
268
|
-
if (value === void 0) cache.delete(name);
|
|
269
|
-
else cache.set(name, stampRecord(value, target));
|
|
270
|
-
}
|
|
271
|
-
if (stored !== target) {
|
|
272
|
-
cache.set(VERSION_RECORD, target);
|
|
273
|
-
wrote = true;
|
|
274
|
-
}
|
|
275
|
-
return wrote;
|
|
276
|
-
}
|
|
277
|
-
function watchPrefsVersion(cache, migrations) {
|
|
278
|
-
const target = migrations.length;
|
|
279
|
-
let versioned = cache.has(VERSION_RECORD);
|
|
280
|
-
let stopped = false;
|
|
281
|
-
const migrate = () => {
|
|
282
|
-
const cleared = versioned && !cache.has(VERSION_RECORD);
|
|
283
|
-
if (cleared) cache.set(VERSION_RECORD, target);
|
|
284
|
-
else if (!runPrefsMigrations(cache, migrations, { stampAll: false })) return;
|
|
285
|
-
versioned = true;
|
|
286
|
-
void cache.flush();
|
|
287
|
-
};
|
|
288
|
-
void cache.whenRead().then(() => {
|
|
289
|
-
if (!stopped && cache.writable) migrate();
|
|
290
|
-
});
|
|
291
|
-
const heard = (version) => {
|
|
292
|
-
if (!isVersion2(version)) {
|
|
293
|
-
console.warn(
|
|
294
|
-
`[prefs] "${cache.prefix}" has an unreadable ${VERSION_RECORD} (${JSON.stringify(version)}) from another writer; no longer persisting`
|
|
295
|
-
);
|
|
296
|
-
cache.stopWriting();
|
|
297
|
-
} else if (version > target) {
|
|
298
|
-
console.warn(
|
|
299
|
-
`[prefs] "${cache.prefix}" was migrated to version ${version} by another writer; this build knows ${target}; no longer persisting`
|
|
300
|
-
);
|
|
301
|
-
cache.stopWriting();
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
const stopOverruled = cache.onOverruled((changes) => {
|
|
305
|
-
for (const [name, value] of changes) if (name === VERSION_RECORD && value !== void 0) heard(value);
|
|
306
|
-
});
|
|
307
|
-
const stopChanges = cache.subscribe((changes) => {
|
|
308
|
-
const remote = changes.filter((change) => change.origin === "remote");
|
|
309
|
-
for (const change of remote) {
|
|
310
|
-
if (change.name === VERSION_RECORD && change.value !== void 0) heard(change.value);
|
|
311
|
-
}
|
|
312
|
-
if (remote.length > 0 && cache.writable) migrate();
|
|
313
|
-
versioned ||= cache.has(VERSION_RECORD);
|
|
314
|
-
});
|
|
315
|
-
return () => {
|
|
316
|
-
stopped = true;
|
|
317
|
-
stopOverruled();
|
|
318
|
-
stopChanges();
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
function repairPrefValue(leaf, stored, validators) {
|
|
322
|
-
if (leaf.kind === "number") {
|
|
323
|
-
if (stored === "Infinity") stored = Infinity;
|
|
324
|
-
else if (stored === "-Infinity") stored = -Infinity;
|
|
325
|
-
}
|
|
326
|
-
const validate = validators?.[leaf.kind];
|
|
327
|
-
if (validate) {
|
|
328
|
-
try {
|
|
329
|
-
const out = validate(stored, leaf);
|
|
330
|
-
return out === void 0 ? leaf.default : out;
|
|
331
|
-
} catch {
|
|
332
|
-
return leaf.default;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
switch (leaf.kind) {
|
|
336
|
-
case "number":
|
|
337
|
-
return repairNumber(leaf, stored);
|
|
338
|
-
case "boolean":
|
|
339
|
-
return leaf.encoding || typeof stored === "boolean" ? stored : leaf.default;
|
|
340
|
-
case "string":
|
|
341
|
-
case "color":
|
|
342
|
-
case "field":
|
|
343
|
-
return typeof stored === "string" ? stored : leaf.default;
|
|
344
|
-
case "enum": {
|
|
345
|
-
const e = leaf;
|
|
346
|
-
if (e.encoding) return stored;
|
|
347
|
-
return e.options.some((o) => o.value === stored) ? stored : leaf.default;
|
|
348
|
-
}
|
|
349
|
-
case "object":
|
|
350
|
-
if (isPlainObject(stored)) return repairFields(leaf, stored, validators);
|
|
351
|
-
return leaf.fromScalar ? stored : leaf.default;
|
|
352
|
-
case "map":
|
|
353
|
-
return repairMap(leaf, stored, validators);
|
|
354
|
-
case "union": {
|
|
355
|
-
const variant = prefVariantOf(leaf, stored);
|
|
356
|
-
return variant ? repairFields(variant[1], stored, validators) : leaf.default;
|
|
357
|
-
}
|
|
358
|
-
case "list":
|
|
359
|
-
return repairList(leaf, stored, validators);
|
|
360
|
-
default:
|
|
361
|
-
return stored;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
function repairFields(leaf, stored, validators) {
|
|
365
|
-
let out;
|
|
366
|
-
for (const [key, field] of prefSectionLeaves(leaf.children)) {
|
|
367
|
-
if (!Object.hasOwn(stored, key) || stored[key] === void 0) continue;
|
|
368
|
-
const read = repairPrefValue(field, stored[key], validators);
|
|
369
|
-
if (read !== stored[key]) (out ??= { ...stored })[key] = read;
|
|
370
|
-
}
|
|
371
|
-
return out ?? stored;
|
|
372
|
-
}
|
|
373
|
-
function repairMap(leaf, stored, validators) {
|
|
374
|
-
if (!isPlainObject(stored)) return leaf.default;
|
|
375
|
-
const held = stored;
|
|
376
|
-
let out;
|
|
377
|
-
for (const [key, value] of Object.entries(held)) {
|
|
378
|
-
const read = repairPrefValue(leaf.item, value, validators);
|
|
379
|
-
if (read !== value) (out ??= { ...held })[key] = read;
|
|
399
|
+
// src/heading.ts
|
|
400
|
+
function prefFitsHeading(leaf2) {
|
|
401
|
+
return (leaf2.kind === "boolean" || leaf2.kind === "enum") && isBuiltinPref(leaf2);
|
|
402
|
+
}
|
|
403
|
+
function prefHeadingKey(node) {
|
|
404
|
+
if (node.name === "") return void 0;
|
|
405
|
+
const held = "members" in node ? node.members : node.children;
|
|
406
|
+
for (const [key, child] of Object.entries(held)) {
|
|
407
|
+
if (isPrefLeaf(child) && child.heading === true && prefFitsHeading(child)) return key;
|
|
380
408
|
}
|
|
381
|
-
return
|
|
382
|
-
}
|
|
383
|
-
function repairList(leaf, stored, validators) {
|
|
384
|
-
if (!Array.isArray(stored)) return leaf.default;
|
|
385
|
-
if (leaf.minItems !== void 0 && stored.length < leaf.minItems) return leaf.default;
|
|
386
|
-
const kept = leaf.maxItems !== void 0 && stored.length > leaf.maxItems ? stored.slice(0, leaf.maxItems) : stored;
|
|
387
|
-
const read = kept.map((entry) => repairPrefValue(leaf.item, entry, validators));
|
|
388
|
-
return kept === stored && read.every((entry, i) => entry === stored[i]) ? stored : read;
|
|
389
|
-
}
|
|
390
|
-
function repairNumber(leaf, stored) {
|
|
391
|
-
if (typeof stored !== "number" || Number.isNaN(stored)) return leaf.default;
|
|
392
|
-
const { endless } = leaf;
|
|
393
|
-
if (stored === Infinity && (endless === "max" || endless === "both")) return stored;
|
|
394
|
-
if (stored === -Infinity && (endless === "min" || endless === "both")) return stored;
|
|
395
|
-
let v = stored;
|
|
396
|
-
if (leaf.min !== void 0 && v < leaf.min) v = leaf.min;
|
|
397
|
-
if (leaf.max !== void 0 && v > leaf.max) v = leaf.max;
|
|
398
|
-
return Number.isFinite(v) ? v : leaf.default;
|
|
409
|
+
return void 0;
|
|
399
410
|
}
|
|
400
411
|
|
|
401
|
-
// src/
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
412
|
+
// src/pair.ts
|
|
413
|
+
function pairRuns(items, leafOf) {
|
|
414
|
+
const leaves = items.map(leafOf);
|
|
415
|
+
const pairs = pairRowsOf(leaves.filter((entry) => entry !== void 0));
|
|
416
|
+
const keys = leaves.map((entry) => entry === void 0 ? void 0 : pairs.get(entry[0]));
|
|
417
|
+
const runs = [];
|
|
418
|
+
for (let i = 0; i < items.length; ) {
|
|
419
|
+
const pair = keys[i];
|
|
420
|
+
let j = i + 1;
|
|
421
|
+
while (pair !== void 0 && keys[j]?.key === pair.key) j += 1;
|
|
422
|
+
runs.push(j - i > 1 ? { items: items.slice(i, j), pair } : { items: [items[i]] });
|
|
423
|
+
i = j;
|
|
413
424
|
}
|
|
414
|
-
|
|
415
|
-
if (fields?.kind !== "object") return value;
|
|
416
|
-
let out;
|
|
417
|
-
for (const [key, field] of prefSectionLeaves(fields.children)) {
|
|
418
|
-
if (!Object.hasOwn(held, key)) continue;
|
|
419
|
-
const encoded = encodeInfinity(field, held[key]);
|
|
420
|
-
if (encoded !== held[key]) (out ??= { ...held })[key] = encoded;
|
|
421
|
-
}
|
|
422
|
-
return out ?? value;
|
|
423
|
-
};
|
|
424
|
-
function createPrefsStore(schema, cache, validators, onClose, version = 0) {
|
|
425
|
-
const leaves = new Map([...prefLeaves(schema)].filter(([, leaf]) => prefHoldsValue(leaf)));
|
|
426
|
-
let snapshot = null;
|
|
427
|
-
let previous = null;
|
|
428
|
-
const build = () => {
|
|
429
|
-
const byPath = /* @__PURE__ */ new Map();
|
|
430
|
-
const raw = /* @__PURE__ */ new Map();
|
|
431
|
-
const unset = /* @__PURE__ */ new Set();
|
|
432
|
-
const tree = {};
|
|
433
|
-
for (const [path, leaf] of leaves) {
|
|
434
|
-
const has = cache.has(path);
|
|
435
|
-
let value;
|
|
436
|
-
if (!has) {
|
|
437
|
-
value = leaf.default;
|
|
438
|
-
unset.add(path);
|
|
439
|
-
} else {
|
|
440
|
-
const record = cache.get(path);
|
|
441
|
-
const stored = recordValue(record);
|
|
442
|
-
raw.set(path, record);
|
|
443
|
-
value = previous?.raw.has(path) && previous.raw.get(path) === record ? previous.byPath.get(path) : repairPrefValue(leaf, stored, validators);
|
|
444
|
-
}
|
|
445
|
-
byPath.set(path, value);
|
|
446
|
-
assignPrefValueAtPath(tree, path, value);
|
|
447
|
-
}
|
|
448
|
-
previous = { raw, byPath };
|
|
449
|
-
return { byPath, tree, unset };
|
|
450
|
-
};
|
|
451
|
-
const current = () => snapshot ??= build();
|
|
452
|
-
let storedTree = null;
|
|
453
|
-
const buildStored = () => {
|
|
454
|
-
const tree = {};
|
|
455
|
-
const branches = new WeakSet([tree]);
|
|
456
|
-
for (const [name, record] of cache.entries()) {
|
|
457
|
-
if (name === VERSION_RECORD) continue;
|
|
458
|
-
const value = recordValue(record);
|
|
459
|
-
const parts = name.split(".");
|
|
460
|
-
let cursor = tree;
|
|
461
|
-
for (const part of parts.slice(0, -1)) {
|
|
462
|
-
const next = cursor[part];
|
|
463
|
-
if (typeof next === "object" && next !== null && branches.has(next)) {
|
|
464
|
-
cursor = next;
|
|
465
|
-
} else {
|
|
466
|
-
const branch = {};
|
|
467
|
-
branches.add(branch);
|
|
468
|
-
setOwnPrefValue(cursor, part, branch);
|
|
469
|
-
cursor = branch;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
const last = parts[parts.length - 1];
|
|
473
|
-
if (!branches.has(cursor[last])) setOwnPrefValue(cursor, last, value);
|
|
474
|
-
}
|
|
475
|
-
return tree;
|
|
476
|
-
};
|
|
477
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
478
|
-
const stopCache = cache.subscribe((changes) => {
|
|
479
|
-
const records = changes.filter((c) => c.name !== VERSION_RECORD);
|
|
480
|
-
if (records.length === 0) return;
|
|
481
|
-
storedTree = null;
|
|
482
|
-
const mine = records.filter((c) => leaves.has(c.name));
|
|
483
|
-
if (mine.length > 0) snapshot = null;
|
|
484
|
-
const now = current();
|
|
485
|
-
const out = mine.map((c) => ({ path: c.name, value: now.byPath.get(c.name), origin: c.origin }));
|
|
486
|
-
for (const listener of [...listeners]) listener(out);
|
|
487
|
-
});
|
|
488
|
-
return {
|
|
489
|
-
schema,
|
|
490
|
-
get: (path) => current().byPath.get(path),
|
|
491
|
-
set: (path, value) => {
|
|
492
|
-
const leaf = leaves.get(path);
|
|
493
|
-
if (!leaf) {
|
|
494
|
-
console.warn(`[prefs] no leaf at "${path}"; ignoring the write`);
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
const stored = encodeInfinity(leaf, value);
|
|
498
|
-
cache.set(path, stored === void 0 ? void 0 : stampRecord(stored, version));
|
|
499
|
-
},
|
|
500
|
-
reset: (path) => {
|
|
501
|
-
for (const p of leaves.keys()) {
|
|
502
|
-
if (path === void 0 || p === path || p.startsWith(`${path}.`)) cache.delete(p);
|
|
503
|
-
}
|
|
504
|
-
},
|
|
505
|
-
isSet: (path) => cache.has(path),
|
|
506
|
-
values: () => current().tree,
|
|
507
|
-
unset: () => current().unset,
|
|
508
|
-
stored: () => storedTree ??= buildStored(),
|
|
509
|
-
subscribe: (listener) => {
|
|
510
|
-
listeners.add(listener);
|
|
511
|
-
return () => {
|
|
512
|
-
listeners.delete(listener);
|
|
513
|
-
};
|
|
514
|
-
},
|
|
515
|
-
get writable() {
|
|
516
|
-
return cache.writable;
|
|
517
|
-
},
|
|
518
|
-
read: () => cache.read(),
|
|
519
|
-
whenRead: () => cache.whenRead(),
|
|
520
|
-
flush: () => cache.flush(),
|
|
521
|
-
close: async () => {
|
|
522
|
-
onClose?.();
|
|
523
|
-
stopCache();
|
|
524
|
-
listeners.clear();
|
|
525
|
-
await cache.close();
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// src/open.ts
|
|
531
|
-
async function openPrefs(schema, options) {
|
|
532
|
-
const cache = await openRecords({ storage: options.storage, prefix: options.prefix });
|
|
533
|
-
const stop = watch(cache, options);
|
|
534
|
-
if (runPrefsMigrations(cache, options.migrations ?? [])) await cache.flush();
|
|
535
|
-
return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);
|
|
536
|
-
}
|
|
537
|
-
function openPrefsSync(schema, options) {
|
|
538
|
-
const cache = openRecordsSync({ storage: options.storage, prefix: options.prefix });
|
|
539
|
-
const stop = watch(cache, options);
|
|
540
|
-
if (runPrefsMigrations(cache, options.migrations ?? [])) void cache.flush();
|
|
541
|
-
return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);
|
|
425
|
+
return runs;
|
|
542
426
|
}
|
|
543
|
-
var watch = (cache, options) => watchPrefsVersion(cache, options.migrations ?? []);
|
|
544
427
|
|
|
545
428
|
// src/kinds.ts
|
|
546
429
|
var ONE = { compound: false, several: false };
|
|
@@ -562,76 +445,14 @@ var PREF_KIND_TRAITS = {
|
|
|
562
445
|
label: ONE,
|
|
563
446
|
separator: ONE
|
|
564
447
|
};
|
|
565
|
-
var traitsOf = (
|
|
566
|
-
function prefIsCompound(
|
|
567
|
-
return traitsOf(
|
|
568
|
-
}
|
|
569
|
-
function prefDrawsSeveral(leaf) {
|
|
570
|
-
return traitsOf(leaf).several;
|
|
571
|
-
}
|
|
572
|
-
function prefUnit(system, display, opts) {
|
|
573
|
-
let self;
|
|
574
|
-
try {
|
|
575
|
-
self = unitScale(system, display);
|
|
576
|
-
} catch (e) {
|
|
577
|
-
throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);
|
|
578
|
-
}
|
|
579
|
-
const scale = opts?.precision === void 0 ? void 0 : 10 ** opts.precision;
|
|
580
|
-
const suffix = opts?.suffix ?? display;
|
|
581
|
-
const accepts = { [suffix]: 1 };
|
|
582
|
-
for (const name of Object.keys(system.units)) {
|
|
583
|
-
const other = unitScale(system, name);
|
|
584
|
-
const factor = other.factor / self.factor;
|
|
585
|
-
const offset = (other.offset - self.offset) / self.factor;
|
|
586
|
-
accepts[name] = offset === 0 ? factor : { factor, offset };
|
|
587
|
-
}
|
|
588
|
-
const toDisplay = (stored) => {
|
|
589
|
-
const shown = (stored - self.offset) / self.factor;
|
|
590
|
-
return scale === void 0 ? shown : Math.round(shown * scale) / scale;
|
|
591
|
-
};
|
|
592
|
-
return {
|
|
593
|
-
toDisplay,
|
|
594
|
-
fromDisplay: (shown) => shown * self.factor + self.offset,
|
|
595
|
-
suffix,
|
|
596
|
-
accepts,
|
|
597
|
-
format: (stored) => `${formatUnit(stored, display, system, {
|
|
598
|
-
precision: opts?.precision ?? 2,
|
|
599
|
-
suffix: false
|
|
600
|
-
})}${suffix}`
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
var PREF_KINDS = {
|
|
604
|
-
number: true,
|
|
605
|
-
boolean: true,
|
|
606
|
-
string: true,
|
|
607
|
-
enum: true,
|
|
608
|
-
color: true,
|
|
609
|
-
paint: true,
|
|
610
|
-
object: true,
|
|
611
|
-
list: true,
|
|
612
|
-
map: true,
|
|
613
|
-
union: true,
|
|
614
|
-
field: true,
|
|
615
|
-
action: true,
|
|
616
|
-
alias: true,
|
|
617
|
-
label: true,
|
|
618
|
-
separator: true
|
|
619
|
-
};
|
|
620
|
-
function pairRowsOf(leaves) {
|
|
621
|
-
const rows = /* @__PURE__ */ new Map();
|
|
622
|
-
for (const [path, leaf] of leaves) {
|
|
623
|
-
if (!leaf.pair || rows.has(path)) continue;
|
|
624
|
-
const row = { key: path, label: leaf.pair.label ?? leaf.name };
|
|
625
|
-
rows.set(path, row);
|
|
626
|
-
const partners = typeof leaf.pair.with === "string" ? [leaf.pair.with] : leaf.pair.with;
|
|
627
|
-
for (const partner of partners) if (!rows.has(partner)) rows.set(partner, row);
|
|
628
|
-
}
|
|
629
|
-
return rows;
|
|
448
|
+
var traitsOf = (leaf2) => Object.hasOwn(PREF_KIND_TRAITS, leaf2.kind) ? PREF_KIND_TRAITS[leaf2.kind] : ONE;
|
|
449
|
+
function prefIsCompound(leaf2) {
|
|
450
|
+
return traitsOf(leaf2).compound;
|
|
630
451
|
}
|
|
631
|
-
function
|
|
632
|
-
return
|
|
452
|
+
function prefDrawsSeveral(leaf2) {
|
|
453
|
+
return traitsOf(leaf2).several;
|
|
633
454
|
}
|
|
634
455
|
|
|
635
|
-
export {
|
|
456
|
+
export { PREF_ENTRY, PREF_KIND_TRAITS, PREF_SCOPE, applyPrefConditions, applyPrefEntryConditions, pairRuns, pref, prefAliasTargets, prefDrawsSeveral, prefFitsHeading, prefGroupIsPage, prefHeadingKey, prefIsCompound, prefJudge, prefObjectBase, prefObjectWithField, prefReader, prefScopeAt, prefScopeUnder, prefShownReader, prefShownValue, prefTabRuns, prefType, prefsCss, prefsCssAttributes };
|
|
636
457
|
//# sourceMappingURL=index.js.map
|
|
637
458
|
//# sourceMappingURL=index.js.map
|