@weasel-js/prefs 1.10.0 → 1.11.0

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.
@@ -1,211 +1,7 @@
1
- import { formatUnit, unitScale } from '@weasel-js/quantity';
2
- import { isPlainObject, createEmitter } from '@weasel-js/registry';
1
+ import { isPrefSection, prefSectionLeaves, isPrefLeaf, kebab, prefLeaves, prefHoldsValue, checkPrefSplits, prefSelectors, createSnapshots, VERSION_RECORD, selectionAt, selectionWeights, resolveHeld, assignPrefValueAtPath, isPrefLocus, weightsUnder, recordValue, setOwnPrefValue, readRecord, stampRecord, joinLocus, splitLocus, mapLocusMembers, writeMember, prefVariantOf, repairLocus } from './chunk-OZFER7VN.js';
2
+ import { createEmitter, isPlainObject } from '@weasel-js/registry';
3
3
  import { openRecords, openRecordsSync } from '@weasel-js/storage';
4
4
 
5
- // src/alias.ts
6
- function prefAliasTarget(alias, leafAt) {
7
- const passed = /* @__PURE__ */ new Set();
8
- let path = alias.of;
9
- for (; ; ) {
10
- if (passed.has(path)) return void 0;
11
- passed.add(path);
12
- const leaf = leafAt(path);
13
- if (leaf === void 0) return void 0;
14
- if (leaf.kind !== "alias") return { path, leaf };
15
- path = leaf.of;
16
- }
17
- }
18
- function prefAliasName(alias, target) {
19
- if (alias.name !== "") return alias.name;
20
- return target === void 0 ? "Alias" : target.name;
21
- }
22
- function prefAliasedLeaf(alias, target) {
23
- return {
24
- ...target,
25
- name: prefAliasName(alias, target),
26
- description: alias.description === "" ? target.description : alias.description
27
- };
28
- }
29
- function isPrefLinearUnit(unit) {
30
- return typeof unit.toDisplay !== "function";
31
- }
32
- var SHOWN = "shown";
33
- function resolvePrefUnit(unit) {
34
- if (!isPrefLinearUnit(unit)) {
35
- return { ...unit, format: unit.format ?? ((stored) => `${unit.toDisplay(stored)}${unit.suffix ?? ""}`) };
36
- }
37
- const { scale, offset = 0, precision, suffix, accepts } = unit;
38
- const round = precision === void 0 ? void 0 : 10 ** precision;
39
- const system = { base: "stored", units: { [SHOWN]: { factor: scale, offset } } };
40
- return {
41
- toDisplay: (stored) => {
42
- const shown = (stored - offset) / scale;
43
- return round === void 0 ? shown : Math.round(shown * round) / round;
44
- },
45
- fromDisplay: (shown) => shown * scale + offset,
46
- format: (stored) => `${formatUnit(stored, SHOWN, system, { precision: precision ?? 2, suffix: false })}${suffix ?? ""}`,
47
- ...suffix === void 0 ? {} : { suffix },
48
- ...accepts === void 0 ? {} : { accepts }
49
- };
50
- }
51
- function prefUnit(system, display, opts) {
52
- let self;
53
- try {
54
- self = unitScale(system, display);
55
- } catch (e) {
56
- throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);
57
- }
58
- const suffix = opts?.suffix ?? display;
59
- const accepts = { [suffix]: 1 };
60
- for (const name of Object.keys(system.units)) {
61
- const other = unitScale(system, name);
62
- const factor = other.factor / self.factor;
63
- const offset = (other.offset - self.offset) / self.factor;
64
- accepts[name] = offset === 0 ? factor : { factor, offset };
65
- }
66
- return {
67
- suffix,
68
- scale: self.factor,
69
- ...self.offset === 0 ? {} : { offset: self.offset },
70
- accepts,
71
- ...opts?.precision === void 0 ? {} : { precision: opts.precision }
72
- };
73
- }
74
-
75
- // src/helpers.ts
76
- function prefDisplayBounds(p) {
77
- if (!p.unit) return { min: p.min, max: p.max, step: p.step ?? 1 };
78
- const { toDisplay } = resolvePrefUnit(p.unit);
79
- const lo = p.min === void 0 ? void 0 : toDisplay(p.min);
80
- const hi = p.max === void 0 ? void 0 : toDisplay(p.max);
81
- const flipped = lo !== void 0 && hi !== void 0 && lo > hi;
82
- const step = p.step === void 0 ? 1 : Math.abs(toDisplay(p.step) - toDisplay(0)) || p.step;
83
- return { min: flipped ? hi : lo, max: flipped ? lo : hi, step };
84
- }
85
- function isPrefLeaf(node) {
86
- return "kind" in node;
87
- }
88
- var VALUELESS = /* @__PURE__ */ new Set(["action", "alias", "label", "separator"]);
89
- function prefHoldsValue(leaf) {
90
- return !VALUELESS.has(leaf.kind);
91
- }
92
- function isPrefSection(node) {
93
- return !isPrefLeaf(node) && "members" in node;
94
- }
95
- function prefSectionLeaves(members) {
96
- return Object.entries(members).flatMap(
97
- ([key, child]) => isPrefLeaf(child) ? [[key, child]] : prefSectionLeaves(child.members)
98
- );
99
- }
100
- function prefLeafAt(schema, path) {
101
- if (isPrefSection(schema)) return prefSectionLeaves(schema.members).find(([key]) => key === path)?.[1];
102
- let node = schema;
103
- for (const seg of path.split(".")) {
104
- if (isPrefLeaf(node) || !Object.hasOwn(node.children, seg)) return void 0;
105
- node = node.children[seg];
106
- }
107
- return isPrefLeaf(node) ? node : void 0;
108
- }
109
- function prefValueAtPath(values, path) {
110
- let cur = values;
111
- for (const seg of path.split(".")) {
112
- if (cur == null || typeof cur !== "object" || !Object.hasOwn(cur, seg)) return void 0;
113
- cur = cur[seg];
114
- }
115
- return cur;
116
- }
117
- function visibleFields(fields, keepEmpty) {
118
- const out = {};
119
- for (const [key, child] of Object.entries(fields)) {
120
- if (isPrefLeaf(child)) {
121
- const kept = visiblePrefSubtree(child, false, keepEmpty);
122
- if (kept) out[key] = kept;
123
- continue;
124
- }
125
- const members = visibleFields(child.members, keepEmpty);
126
- if (Object.keys(members).length > 0 || keepEmpty) out[key] = { ...child, members };
127
- }
128
- return out;
129
- }
130
- function visiblePrefSubtree(node, showHidden, keepEmpty = false) {
131
- if (isPrefLeaf(node)) {
132
- if (node.hidden && !showHidden) return null;
133
- if (showHidden || node.kind !== "object") return node;
134
- return { ...node, children: visibleFields(node.children, keepEmpty) };
135
- }
136
- const group = node;
137
- const children = {};
138
- for (const [key, child] of Object.entries(group.children)) {
139
- const kept = visiblePrefSubtree(child, showHidden, keepEmpty);
140
- if (kept) children[key] = kept;
141
- }
142
- if (Object.keys(children).length === 0 && !keepEmpty) return null;
143
- return { ...node, children };
144
- }
145
- var VERSION_RECORD = "$version";
146
- function prefLeaves(schema) {
147
- const out = /* @__PURE__ */ new Map();
148
- const walk = (group, prefix) => {
149
- for (const [key, child] of Object.entries(group.children)) {
150
- if (key.includes(".")) {
151
- throw new Error(`[prefs] schema key "${key}" contains "."; group keys are path segments`);
152
- }
153
- if (prefix === "" && key === VERSION_RECORD) {
154
- throw new Error(`[prefs] schema key "${VERSION_RECORD}" is reserved`);
155
- }
156
- const path = prefix === "" ? key : `${prefix}.${key}`;
157
- if (isPrefLeaf(child)) out.set(path, child);
158
- else walk(child, path);
159
- }
160
- };
161
- walk(schema, "");
162
- return out;
163
- }
164
- function setOwnPrefValue(tree, key, value) {
165
- Object.defineProperty(tree, key, { value, writable: true, enumerable: true, configurable: true });
166
- }
167
- function assignPrefValueAtPath(root, path, value) {
168
- const parts = path.split(".");
169
- let cursor = root;
170
- for (const part of parts.slice(0, -1)) {
171
- if (!Object.hasOwn(cursor, part) || cursor[part] == null) setOwnPrefValue(cursor, part, {});
172
- cursor = cursor[part];
173
- }
174
- setOwnPrefValue(cursor, parts[parts.length - 1], value);
175
- }
176
- function flattenPrefValues(schema, tree) {
177
- const out = [];
178
- for (const path of prefLeaves(schema).keys()) {
179
- const value = prefValueAtPath(tree, path);
180
- if (value !== void 0) out.push([path, value]);
181
- }
182
- return out;
183
- }
184
- function prefLeafMatches(pref, path, query) {
185
- if (pref.name.toLowerCase().includes(query)) return true;
186
- if (pref.description?.toLowerCase().includes(query)) return true;
187
- return path.toLowerCase().includes(query);
188
- }
189
- function filterPrefSubtree(node, query, path = "", over) {
190
- const q = query.trim().toLowerCase();
191
- if (q === "") return node;
192
- const within = over ?? (isPrefLeaf(node) ? void 0 : node);
193
- const find = (p) => within && prefLeafAt(within, p);
194
- if (isPrefLeaf(node)) {
195
- const target = node.kind === "alias" ? prefAliasTarget(node, find) : void 0;
196
- const drawn = target ? prefAliasedLeaf(node, target.leaf) : node;
197
- return prefLeafMatches(drawn, path, q) ? node : null;
198
- }
199
- const group = node;
200
- if (group.name.toLowerCase().includes(q)) return node;
201
- const children = {};
202
- for (const [key, child] of Object.entries(group.children)) {
203
- const kept = filterPrefSubtree(child, q, path === "" ? key : `${path}.${key}`, within);
204
- if (kept) children[key] = kept;
205
- }
206
- if (Object.keys(children).length === 0) return null;
207
- return { ...node, children };
208
- }
209
5
  var ORDERINGS = ["above", "below", "atLeast", "atMost"];
210
6
  var TEST_KEYS = /* @__PURE__ */ new Set(["path", "from", "is", "isNot", "in", ...ORDERINGS]);
211
7
  var isValue = (v) => v === null || typeof v === "string" || typeof v === "number" || typeof v === "boolean";
@@ -309,6 +105,7 @@ var PREF_KINDS = {
309
105
  union: true,
310
106
  field: true,
311
107
  action: true,
108
+ actions: true,
312
109
  alias: true,
313
110
  label: true,
314
111
  separator: true
@@ -412,12 +209,14 @@ function leafProblems(test, schema, site, over) {
412
209
  if (held === UNSEEN) return [];
413
210
  const { leaf } = held;
414
211
  const named = inEntry ? path === "" ? "the entry" : `the entry's "${path}"` : `"${path}"`;
415
- if (!prefHoldsValue(leaf)) return [{ code: "no-value", path, problem: `${named} is a${leaf.kind === "separator" || leaf.kind === "label" ? "" : "n"} ${leaf.kind}, which holds no value` }];
212
+ if (!prefHoldsValue(leaf)) return [{ code: "no-value", path, problem: `${named} is a${leaf.kind === "separator" || leaf.kind === "label" ? "" : "n"} ${leaf.kind === "actions" ? "actions leaf" : leaf.kind}, which holds no value` }];
416
213
  const out = [];
417
214
  const compared = [test.is, test.isNot, ...test.in ?? []].filter((value) => value !== void 0);
418
215
  for (const value of compared) {
419
216
  const why = neverHolds(leaf, value);
420
- if (why !== void 0) out.push({ code: "value", path, problem: `${named} never holds ${show(value)}: ${why}` });
217
+ if (why === void 0) continue;
218
+ const code = leaf.kind === "enum" && typeof value === "string" ? "option" : "value";
219
+ out.push({ code, path, problem: `${named} never holds ${show(value)}: ${why}` });
421
220
  }
422
221
  const ordering = ORDERINGS.find((op) => test[op] !== void 0);
423
222
  if (ordering !== void 0 && isBuiltinPref(leaf) && leaf.kind !== "number") {
@@ -483,121 +282,27 @@ function checkPrefConditions(schema, over) {
483
282
  return out;
484
283
  }
485
284
 
486
- // src/union.ts
487
- function prefVariantOf(leaf, value) {
488
- if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
489
- const key = value[leaf.tag];
490
- if (typeof key !== "string" || !Object.hasOwn(leaf.variants, key)) return void 0;
491
- return [key, leaf.variants[key]];
492
- }
493
- function prefVariantDefault(leaf, key) {
494
- const held = leaf.variants[key]?.default;
495
- const fields = held !== null && typeof held === "object" ? held : {};
496
- return { ...fields, [leaf.tag]: key };
497
- }
498
- function repairPrefValue(leaf, stored, validators) {
499
- if (leaf.kind === "number") {
500
- if (stored === "Infinity") stored = Infinity;
501
- else if (stored === "-Infinity") stored = -Infinity;
502
- }
503
- const validate = validators?.[leaf.kind];
504
- if (validate) {
505
- try {
506
- const out = validate(stored, leaf);
507
- return out === void 0 ? leaf.default : out;
508
- } catch {
509
- return leaf.default;
510
- }
511
- }
512
- switch (leaf.kind) {
513
- case "number":
514
- return repairNumber(leaf, stored);
515
- case "boolean":
516
- return leaf.encoding || typeof stored === "boolean" ? stored : leaf.default;
517
- case "string":
518
- case "color":
519
- case "field":
520
- return typeof stored === "string" ? stored : leaf.default;
521
- case "enum": {
522
- const e = leaf;
523
- if (e.encoding) return stored;
524
- return e.options.some((o) => o.value === stored) ? stored : leaf.default;
525
- }
526
- case "object":
527
- if (isPlainObject(stored)) return repairFields(leaf, stored, validators);
528
- return leaf.fromScalar ? stored : leaf.default;
529
- case "map":
530
- return repairMap(leaf, stored, validators);
531
- case "union": {
532
- const variant = prefVariantOf(leaf, stored);
533
- return variant ? repairFields(variant[1], stored, validators) : leaf.default;
534
- }
535
- case "list":
536
- return repairList(leaf, stored, validators);
537
- default:
538
- return stored;
539
- }
540
- }
541
- function repairFields(leaf, stored, validators) {
542
- let out;
543
- for (const [key, field] of prefSectionLeaves(leaf.children)) {
544
- if (!Object.hasOwn(stored, key) || stored[key] === void 0) continue;
545
- const read = repairPrefValue(field, stored[key], validators);
546
- if (read !== stored[key]) (out ??= { ...stored })[key] = read;
547
- }
548
- return out ?? stored;
549
- }
550
- function repairMap(leaf, stored, validators) {
551
- if (!isPlainObject(stored)) return leaf.default;
552
- const held = stored;
553
- let out;
554
- for (const [key, value] of Object.entries(held)) {
555
- const read = repairPrefValue(leaf.item, value, validators);
556
- if (read !== value) (out ??= { ...held })[key] = read;
557
- }
558
- return out ?? stored;
559
- }
560
- function repairList(leaf, stored, validators) {
561
- if (!Array.isArray(stored)) return leaf.default;
562
- if (leaf.minItems !== void 0 && stored.length < leaf.minItems) return leaf.default;
563
- const kept = leaf.maxItems !== void 0 && stored.length > leaf.maxItems ? stored.slice(0, leaf.maxItems) : stored;
564
- const read = kept.map((entry) => repairPrefValue(leaf.item, entry, validators));
565
- return kept === stored && read.every((entry, i) => entry === stored[i]) ? stored : read;
566
- }
567
- function repairNumber(leaf, stored) {
568
- if (typeof stored !== "number" || Number.isNaN(stored)) return leaf.default;
569
- const { endless } = leaf;
570
- if (stored === Infinity && (endless === "max" || endless === "both")) return stored;
571
- if (stored === -Infinity && (endless === "min" || endless === "both")) return stored;
572
- let v = stored;
573
- if (leaf.min !== void 0 && v < leaf.min) v = leaf.min;
574
- if (leaf.max !== void 0 && v > leaf.max) v = leaf.max;
575
- return Number.isFinite(v) ? v : leaf.default;
576
- }
577
-
578
- // src/stamp.ts
579
- var isVersion = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
580
- function stampRecord(value, at) {
581
- return { $at: at, value };
582
- }
583
- function isStampedRecord(record) {
584
- if (record === null || typeof record !== "object") return false;
585
- const keys = Object.keys(record);
586
- return keys.length === 2 && Object.hasOwn(record, "value") && isVersion(record.$at);
587
- }
588
- function readRecord(record, unstamped) {
589
- return isStampedRecord(record) ? { at: record.$at, value: record.value, stamped: true } : { at: unstamped, value: record, stamped: false };
590
- }
591
- function recordValue(record) {
592
- return isStampedRecord(record) ? record.value : record;
285
+ // src/kitCss.ts
286
+ function kitSettingsCssOptions(at) {
287
+ const under2 = (path) => {
288
+ if (at === void 0 || at === "") return path;
289
+ return path.startsWith(`${at}.`) ? path.slice(at.length + 1) : null;
290
+ };
291
+ return {
292
+ property: (path) => {
293
+ const rest = under2(path);
294
+ return rest === null ? null : `--wzl-kit-${kebab(rest)}`;
295
+ },
296
+ attribute: (selector) => `data-wzl-kit-${kebab(under2(selector) ?? selector)}`
297
+ };
593
298
  }
594
299
 
595
300
  // src/migrate.ts
596
- var isVersion2 = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
301
+ var isVersion = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
597
302
  function runPrefsMigrations(cache, migrations, { stampAll = true } = {}) {
598
303
  const target = migrations.length;
599
304
  const raw = cache.get(VERSION_RECORD);
600
- if (cache.has(VERSION_RECORD) && !isVersion2(raw)) {
305
+ if (cache.has(VERSION_RECORD) && !isVersion(raw)) {
601
306
  console.warn(
602
307
  `[prefs] "${cache.prefix}" has an unreadable ${VERSION_RECORD} (${JSON.stringify(raw)}); opening read-only`
603
308
  );
@@ -671,7 +376,7 @@ function watchPrefsVersion(cache, migrations) {
671
376
  if (!stopped && cache.writable) migrate();
672
377
  });
673
378
  const heard = (version) => {
674
- if (!isVersion2(version)) {
379
+ if (!isVersion(version)) {
675
380
  console.warn(
676
381
  `[prefs] "${cache.prefix}" has an unreadable ${VERSION_RECORD} (${JSON.stringify(version)}) from another writer; no longer persisting`
677
382
  );
@@ -700,6 +405,8 @@ function watchPrefsVersion(cache, migrations) {
700
405
  stopChanges();
701
406
  };
702
407
  }
408
+
409
+ // src/storeWrites.ts
703
410
  var encodeInfinity = (leaf, value) => {
704
411
  if (leaf.kind === "number") return value === Infinity || value === -Infinity ? String(value) : value;
705
412
  if (leaf.kind === "list" && Array.isArray(value)) {
@@ -722,6 +429,58 @@ var encodeInfinity = (leaf, value) => {
722
429
  }
723
430
  return out ?? value;
724
431
  };
432
+ function prefWrites({ leaves, cache, selectors, version, selection, warnIfClosed }) {
433
+ const unsetLocus = (leaf) => {
434
+ if (leaf.defaultLocus === void 0 || !leaf.splitBy?.length) return void 0;
435
+ return repairLocus(leaf.defaultLocus, leaf.splitBy, (by) => selectors.get(by), (member) => encodeInfinity(leaf, member));
436
+ };
437
+ const rawAt = (path, leaf) => cache.has(path) ? recordValue(cache.get(path)) : unsetLocus(leaf) ?? encodeInfinity(leaf, leaf.default);
438
+ const store = (path, stored) => {
439
+ cache.set(path, stored === void 0 ? void 0 : stampRecord(stored, version));
440
+ };
441
+ const splitOf = (path, by) => {
442
+ warnIfClosed(path);
443
+ const leaf = leaves.get(path);
444
+ const options = selectors.get(by);
445
+ if (leaf?.splitBy?.includes(by) && options) return { leaf, options };
446
+ console.warn(`[prefs] "${path}" cannot be split by "${by}"; ignoring`);
447
+ return void 0;
448
+ };
449
+ const set = (path, value, write) => {
450
+ warnIfClosed(path);
451
+ const leaf = leaves.get(path);
452
+ if (!leaf) {
453
+ console.warn(`[prefs] no leaf at "${path}"; ignoring the write`);
454
+ return;
455
+ }
456
+ if (leaf.splitBy?.length && isPrefLocus(value)) {
457
+ store(path, mapLocusMembers(value, (member) => encodeInfinity(leaf, member)));
458
+ return;
459
+ }
460
+ const stored = encodeInfinity(leaf, value);
461
+ const had = cache.has(path) ? recordValue(cache.get(path)) : unsetLocus(leaf);
462
+ const intoMember = stored !== void 0 && leaf.splitBy?.length && isPrefLocus(had);
463
+ const under2 = write?.at ? selectionAt(selectors, selection(), write.at) : selection();
464
+ store(path, intoMember ? writeMember(had, under2, stored) : stored);
465
+ };
466
+ const split = (path, by) => {
467
+ const found = splitOf(path, by);
468
+ if (!found) return;
469
+ const had = rawAt(path, found.leaf);
470
+ const next = splitLocus(had, by, found.options, found.leaf.splitBy);
471
+ if (next !== had) store(path, next);
472
+ };
473
+ const join = (path, by) => {
474
+ const found = splitOf(path, by);
475
+ if (!found) return;
476
+ const had = rawAt(path, found.leaf);
477
+ const next = joinLocus(had, by, selection(), encodeInfinity(found.leaf, found.leaf.default));
478
+ if (next !== had) store(path, next);
479
+ };
480
+ return { set, split, join };
481
+ }
482
+
483
+ // src/store.ts
725
484
  function storedRecords(cache) {
726
485
  const tree = {};
727
486
  const branches = new WeakSet([tree]);
@@ -746,37 +505,14 @@ function storedRecords(cache) {
746
505
  }
747
506
  return tree;
748
507
  }
749
- function createPrefsStore(schema, cache, validators, onClose, version = 0) {
508
+ function createPrefsStore(schema, cache, validators, onClose, version = 0, blends) {
750
509
  const leaves = new Map([...prefLeaves(schema)].filter(([, leaf]) => prefHoldsValue(leaf)));
751
510
  for (const { field, at, problem } of checkPrefConditions(schema)) {
752
511
  console.warn(`[prefs] ${field} of ${at === "" ? "the schema" : `"${at}"`}: ${problem}`);
753
512
  }
754
- let snapshot = null;
755
- let previous = null;
756
- const build = () => {
757
- const byPath = /* @__PURE__ */ new Map();
758
- const raw = /* @__PURE__ */ new Map();
759
- const unset = /* @__PURE__ */ new Set();
760
- const tree = {};
761
- for (const [path, leaf] of leaves) {
762
- const has = cache.has(path);
763
- let value;
764
- if (!has) {
765
- value = leaf.default;
766
- unset.add(path);
767
- } else {
768
- const record = cache.get(path);
769
- const stored = recordValue(record);
770
- raw.set(path, record);
771
- value = previous?.raw.has(path) && previous.raw.get(path) === record ? previous.byPath.get(path) : repairPrefValue(leaf, stored, validators);
772
- }
773
- byPath.set(path, value);
774
- assignPrefValueAtPath(tree, path, value);
775
- }
776
- previous = { raw, byPath };
777
- return { byPath, tree, unset };
778
- };
779
- const current = () => snapshot ??= build();
513
+ for (const { at, problem } of checkPrefSplits(schema)) console.warn(`[prefs] splitBy of "${at}": ${problem}`);
514
+ const source = { leaves, cache, selectors: prefSelectors(leaves), validators, blends };
515
+ const { current, peek, drop } = createSnapshots(source);
780
516
  let storedTree = null;
781
517
  let changed = createEmitter();
782
518
  const stopCache = cache.subscribe((changes) => {
@@ -784,10 +520,16 @@ function createPrefsStore(schema, cache, validators, onClose, version = 0) {
784
520
  if (records.length === 0) return;
785
521
  storedTree = null;
786
522
  const mine = records.filter((c) => leaves.has(c.name));
787
- if (mine.length > 0) snapshot = null;
523
+ const before = peek();
524
+ if (mine.length > 0) drop();
788
525
  const now = current();
789
- const out = mine.map((c) => ({ path: c.name, value: now.byPath.get(c.name), origin: c.origin }));
790
- changed.emit(out);
526
+ const origins = new Map(mine.map((c) => [c.name, c.origin]));
527
+ for (const c of mine) {
528
+ for (const path of [...before?.splitBy.get(c.name) ?? [], ...now.splitBy.get(c.name) ?? []]) {
529
+ if (!origins.has(path)) origins.set(path, c.origin);
530
+ }
531
+ }
532
+ changed.emit([...origins].map(([path, origin]) => ({ path, value: now.byPath.get(path), origin })));
791
533
  });
792
534
  let closed = false;
793
535
  let warned = false;
@@ -798,17 +540,19 @@ function createPrefsStore(schema, cache, validators, onClose, version = 0) {
798
540
  };
799
541
  return {
800
542
  schema,
801
- get: (path) => current().byPath.get(path),
802
- set: (path, value) => {
803
- warnIfClosed(path);
543
+ ...prefWrites({ leaves, cache, selectors: source.selectors, version, selection: () => current().selection, warnIfClosed }),
544
+ get: (path, read) => {
545
+ const now = current();
546
+ if (!read?.weights) return now.byPath.get(path);
804
547
  const leaf = leaves.get(path);
805
- if (!leaf) {
806
- console.warn(`[prefs] no leaf at "${path}"; ignoring the write`);
807
- return;
808
- }
809
- const stored = encodeInfinity(leaf, value);
810
- cache.set(path, stored === void 0 ? void 0 : stampRecord(stored, version));
548
+ const weights = weightsUnder(source.selectors, now.selection, read.weights);
549
+ return leaf ? resolveHeld(source, leaf, now.held.get(path), weights) : void 0;
811
550
  },
551
+ locus: (path) => {
552
+ const held = current().held.get(path);
553
+ return isPrefLocus(held) ? held : void 0;
554
+ },
555
+ loci: () => current().loci,
812
556
  reset: (path) => {
813
557
  warnIfClosed(path);
814
558
  for (const p of leaves.keys()) {
@@ -816,7 +560,18 @@ function createPrefsStore(schema, cache, validators, onClose, version = 0) {
816
560
  }
817
561
  },
818
562
  isSet: (path) => cache.has(path),
819
- values: () => current().tree,
563
+ values: (read) => {
564
+ const now = current();
565
+ if (!read?.at) return now.tree;
566
+ const selection = selectionAt(source.selectors, now.selection, read.at);
567
+ const weights = selectionWeights(selection);
568
+ const tree = {};
569
+ for (const [path, leaf] of leaves) {
570
+ const set = source.selectors.has(path) ? selection[path] : resolveHeld(source, leaf, now.held.get(path), weights);
571
+ assignPrefValueAtPath(tree, path, set);
572
+ }
573
+ return tree;
574
+ },
820
575
  unset: () => current().unset,
821
576
  stored: () => storedTree ??= storedRecords(cache),
822
577
  subscribe: (listener) => changed.subscribe(listener),
@@ -844,11 +599,11 @@ async function openPrefs(schema, options) {
844
599
  const cache = await openRecords({ storage: options.storage, prefix: options.prefix });
845
600
  const stop = watch(cache, options);
846
601
  if (runPrefsMigrations(cache, options.migrations ?? [])) await cache.flush();
847
- return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);
602
+ return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0, options.blends);
848
603
  }
849
604
  function openPrefsSync(schema, options) {
850
605
  const { cache, stop } = openPrefsCacheSync(options);
851
- return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);
606
+ return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0, options.blends);
852
607
  }
853
608
  function openPrefsCacheSync(options) {
854
609
  const cache = openRecordsSync({ storage: options.storage, prefix: options.prefix });
@@ -858,6 +613,6 @@ function openPrefsCacheSync(options) {
858
613
  }
859
614
  var watch = (cache, options) => watchPrefsVersion(cache, options.migrations ?? []);
860
615
 
861
- export { PREF_KINDS, UNSEEN, VERSION_RECORD, checkPrefCondition, checkPrefConditions, createPrefsStore, filterPrefSubtree, flattenPrefValues, isBuiltinPref, isPrefCondition, isPrefLeaf, isPrefLinearUnit, isPrefSection, mapPrefConditionPaths, openPrefs, openPrefsCacheSync, openPrefsSync, pairRowsOf, prefAliasName, prefAliasTarget, prefAliasedLeaf, prefConditionHolds, prefConditionPaths, prefConditionReadsItem, prefDisplayBounds, prefHoldsValue, prefIsEnabled, prefIsShown, prefLeafAt, prefLeafHolding, prefLeafHoldingIn, prefLeaves, prefSchemaHolding, prefSectionLeaves, prefUnit, prefValueAtPath, prefVariantDefault, prefVariantOf, repairPrefValue, resolvePrefUnit, visiblePrefSubtree };
862
- //# sourceMappingURL=chunk-5KB3WBJZ.js.map
863
- //# sourceMappingURL=chunk-5KB3WBJZ.js.map
616
+ export { PREF_KINDS, UNSEEN, checkPrefCondition, checkPrefConditions, createPrefsStore, isBuiltinPref, isPrefCondition, kitSettingsCssOptions, mapPrefConditionPaths, openPrefs, openPrefsCacheSync, openPrefsSync, pairRowsOf, prefConditionHolds, prefConditionPaths, prefConditionReadsItem, prefIsEnabled, prefIsShown, prefLeafHolding, prefLeafHoldingIn, prefSchemaHolding };
617
+ //# sourceMappingURL=chunk-WN6QQICK.js.map
618
+ //# sourceMappingURL=chunk-WN6QQICK.js.map