@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,5 +1,5 @@
1
- import { StorageAdapter, SyncStorageAdapter } from '@weasel-js/storage';
2
- import { UnitEntry, UnitSystem, Unit, Display, InfinityText } from '@weasel-js/quantity';
1
+ import { IconRef } from '@weasel-js/icons';
2
+ import { UnitEntry, UnitSystem, Unit, UnitTable, Display, InfinityText } from '@weasel-js/quantity';
3
3
 
4
4
  /** What a condition can compare a leaf's value against. `null` stands for
5
5
  * nothing held: a missing value as well as a stored `null`. */
@@ -107,6 +107,16 @@ interface PrefAction extends PrefBase<'action', undefined> {
107
107
  * its tooltip. Unset: a button in a row, an icon in a bar. */
108
108
  control?: PrefActionControl;
109
109
  }
110
+ /**
111
+ * Every action the host registered in the action group `group`, in registry
112
+ * order, each drawn as an {@link PrefAction} naming it would be: an action
113
+ * registered later appears without the schema changing. Holds no value, as
114
+ * an `action` holds none.
115
+ */
116
+ interface PrefActions extends PrefBase<'actions', undefined> {
117
+ /** The registry action group whose actions are drawn. */
118
+ group: string;
119
+ }
110
120
 
111
121
  /**
112
122
  * A second place for another leaf: its row draws that leaf's control and
@@ -135,9 +145,24 @@ declare function prefAliasTarget(alias: PrefAlias, leafAt: (path: string) => Pre
135
145
  * nothing.
136
146
  */
137
147
  declare function prefAliasName(alias: PrefAlias, target?: PrefLeaf): string;
138
- /** A leaf drawn through an alias: the target, under the alias's own name and description where it gives them. */
148
+ /** A leaf drawn through an alias: the target, under the alias's own name, description and access letter where it gives them. */
139
149
  declare function prefAliasedLeaf(alias: PrefAlias, target: PrefLeaf): PrefLeaf;
140
150
 
151
+ /** Reads a value held beside a number leaf, by the path a condition there would name. */
152
+ type PrefBoundReader = (path: string) => unknown;
153
+ /**
154
+ * A number leaf's bound where its value is held: `undefined` for none. Asked
155
+ * per holder, so each scene node a panel edits can have its own.
156
+ */
157
+ type PrefBoundAt = (read: PrefBoundReader) => number | undefined;
158
+ /**
159
+ * `leaf` with its `minAt` and `maxAt` read against `read` and folded into
160
+ * `min` and `max`, whichever is tighter. The leaf itself when it has neither.
161
+ */
162
+ declare function prefNumberAt(leaf: PrefNumber, read: PrefBoundReader): PrefNumber;
163
+ /** `n` held to `leaf`'s `min` and `max`, except an infinity an `endless` end stands for. */
164
+ declare function prefClampNumber(leaf: PrefNumber, n: number): number;
165
+
141
166
  /**
142
167
  * A line of text among the rows, holding no value: `name` is the line and
143
168
  * `description` the note under it. A store neither reads nor writes one, and
@@ -156,7 +181,7 @@ type PrefSeparator = PrefBase<'separator', undefined>;
156
181
  * `default` is what a new entry starts as, and its `name` names one entry
157
182
  * (`'Phase'` under a list named `'Phases'`).
158
183
  */
159
- interface PrefList extends PrefBase<'list', readonly unknown[]> {
184
+ interface PrefList extends PrefValueBase<'list', readonly unknown[]> {
160
185
  item: PrefLeaf;
161
186
  /** A stored list shorter than this reads as the default, and a UI stops removing at it. */
162
187
  minItems?: number;
@@ -164,13 +189,40 @@ interface PrefList extends PrefBase<'list', readonly unknown[]> {
164
189
  maxItems?: number;
165
190
  }
166
191
 
192
+ /**
193
+ * A leaf's value split by another leaf: one member for each option of the
194
+ * `enum` leaf at `$by`. A member may itself be a locus, by a second selector.
195
+ * The alternatives are folded by weight when the value is read, and a plain
196
+ * setting of the selector gives one of them all of it.
197
+ */
198
+ interface PrefLocus {
199
+ /** The full path of the `enum` leaf whose options key `$of`. */
200
+ $by: string;
201
+ $of: Record<string, unknown>;
202
+ }
203
+ /** A value for each selector a read is made under: its path, then the option chosen. */
204
+ type PrefSelection = Readonly<Record<string, string>>;
205
+ /** A weight for each option of each selector, by the selector's path. An option left out weighs nothing. */
206
+ type PrefWeights = Readonly<Record<string, Readonly<Record<string, number>>>>;
207
+ /** One alternative of a split value, and its share of the whole. */
208
+ interface PrefWeighted {
209
+ value: unknown;
210
+ weight: number;
211
+ }
212
+ /** Whether `value` is a {@link PrefLocus}: an object of exactly `$by` and `$of`. */
213
+ declare function isPrefLocus(value: unknown): value is PrefLocus;
214
+ /** The one member `selection` names. A selector it leaves out, or an option the locus holds nothing for, reads as `absent`. */
215
+ declare function memberAt(stored: unknown, selection: PrefSelection, absent: unknown): unknown;
216
+ /** The path of every selector `stored` is split by, outermost first. */
217
+ declare function locusSelectors(stored: unknown): Set<string>;
218
+
167
219
  /**
168
220
  * A leaf whose value is an object keyed by strings nobody declared, every
169
221
  * value described by `item`: the keyed counterpart of a {@link PrefList}.
170
222
  * `item` is an ordinary leaf of any kind; its `default` is what a new entry
171
223
  * starts as, and its `name` names one entry's value.
172
224
  */
173
- interface PrefMap extends PrefBase<'map', Readonly<Record<string, unknown>>> {
225
+ interface PrefMap extends PrefValueBase<'map', Readonly<Record<string, unknown>>> {
174
226
  item: PrefLeaf;
175
227
  }
176
228
 
@@ -184,7 +236,8 @@ interface PrefMap extends PrefBase<'map', Readonly<Record<string, unknown>>> {
184
236
  * its `default` (without the tag) is what the value becomes when they choose
185
237
  * it. A stored value whose tag names no variant reads as the leaf's default.
186
238
  */
187
- interface PrefUnion extends PrefBase<'union', unknown> {
239
+ interface PrefUnion extends PrefValueBase<'union', unknown> {
240
+ /** The field of the value that names its variant. Not one of `tags`. */
188
241
  tag: string;
189
242
  variants: Record<string, PrefObject>;
190
243
  }
@@ -215,7 +268,8 @@ interface PrefLinearUnit extends PrefUnitText {
215
268
  /** The stored value a display of 0 stands for. Absent is 0. */
216
269
  offset?: number;
217
270
  /** Decimal places the shown value is rounded to. Absent, the value shows unrounded and formats to two places.
218
- * What is typed is stored unrounded either way. */
271
+ * What is typed is stored unrounded either way: a decimal typed at a decimal `scale` is stored as the
272
+ * decimal the two multiply to, without the dust of multiplying them in binary. */
219
273
  precision?: number;
220
274
  }
221
275
  /** A display unit as code, for a conversion that is not linear. It cannot be written to JSON or edited as data. */
@@ -233,6 +287,9 @@ type PrefNumberUnit = PrefLinearUnit | PrefFunctionUnit;
233
287
  interface ResolvedPrefUnit extends PrefFunctionUnit {
234
288
  format: (stored: number) => string;
235
289
  }
290
+ /** What a unit leaf's field reads as typed text: its `accepts` table, and its
291
+ * `suffix` as the display unit itself. */
292
+ declare function prefUnitAccepts(unit: PrefNumberUnit): Readonly<UnitTable>;
236
293
  /** Whether `unit` is the data form, and so can be written out and edited. */
237
294
  declare function isPrefLinearUnit(unit: PrefNumberUnit): unit is PrefLinearUnit;
238
295
  /** How to convert and format with `unit`, whichever form it was written in. */
@@ -250,7 +307,7 @@ declare function prefUnit(system: UnitSystem, display: Unit, opts?: {
250
307
  }): PrefLinearUnit;
251
308
 
252
309
  /** The value types a built-in pref leaf can hold. */
253
- type PrefKind = 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object' | 'list' | 'map' | 'union' | 'field' | 'action' | 'alias' | 'label' | 'separator';
310
+ type PrefKind = 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object' | 'list' | 'map' | 'union' | 'field' | 'action' | 'actions' | 'alias' | 'label' | 'separator';
254
311
  /** Leaves that share one row in a compact property UI, declared on the first
255
312
  * of them. Purely presentational. */
256
313
  interface PrefPair {
@@ -270,6 +327,14 @@ interface PrefBase<K extends string, Value> {
270
327
  description: string;
271
328
  /** Fallback when nothing is persisted. */
272
329
  default: Value;
330
+ /** Words the leaf is also found by and gathered under: a settings search
331
+ * matches them as it matches `name`, and `prefLeavesTagged` gathers every
332
+ * leaf carrying one. A leaf also carries the tags of every group above it
333
+ * (`prefLeafTags`). Unrelated to a union leaf's `tag`, which names the
334
+ * field its value's variant is read from. */
335
+ tags?: readonly string[];
336
+ /** The letter that picks this in a menu, and with the menu bar's chord opens a top-level menu. One character; supported, never required. */
337
+ access?: string;
273
338
  /** Hide from a host app's settings UI by default. */
274
339
  hidden?: boolean;
275
340
  /** Drawn only while this holds. Presentational: the value stays stored
@@ -288,12 +353,16 @@ interface PrefBase<K extends string, Value> {
288
353
  * (weasel-ui `PrefsForm` honors this for leaves whose control brings
289
354
  * its own chrome). */
290
355
  block?: boolean;
291
- /** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it
292
- * against `ICON_PATHS`). A plain string because this package ships no
293
- * icon set and cannot depend on one. Read where a leaf's `name` has nowhere to go — a
356
+ /** Draw the control in the heading of the group or section holding the
357
+ * leaf, in place of a row of its own. Only a built-in `boolean` or `enum`
358
+ * fits there (`prefFitsHeading`); any other leaf stays a row. Honored by
359
+ * weasel-ui `PrefsForm` and labkit's `ControlPanel`. */
360
+ heading?: boolean;
361
+ /** Glyph naming this leaf. A name from `@weasel-js/icons`; this package draws
362
+ * nothing. Read where a leaf's `name` has nowhere to go — a
294
363
  * `pair`ed row is labeled by the pair, so its fields have only the glyph
295
364
  * to tell them apart. */
296
- icon?: string;
365
+ icon?: IconRef;
297
366
  /** Puts this leaf and the ones it names on one row. */
298
367
  pair?: PrefPair;
299
368
  /** Shorter forms of `name`, longest first. A surface short of room for
@@ -314,6 +383,24 @@ interface PrefBase<K extends string, Value> {
314
383
  * schema editor shows such a leaf as one closed thing and prints the name
315
384
  * in place of its literal. */
316
385
  type?: string;
386
+ /** The `enum` leaves this one's value may be split by, each by the full
387
+ * path its value is read at: the value may then be held once per option
388
+ * of any of them (a {@link PrefLocus}), which the store folds into the one
389
+ * value read. Whether it is split is the stored value's to say. The
390
+ * order is the order a value split by several is stored in, the first
391
+ * outermost. Each must be a plain `enum`: not `clearable`, with no
392
+ * `encoding`, and not split itself. */
393
+ splitBy?: readonly string[];
394
+ /** What the leaf holds while nothing is stored for it, where that is a
395
+ * split value: a default that differs by option. Split only by entries of
396
+ * `splitBy`. `default` stays what a member it leaves out reads as, and
397
+ * what the leaf's value type is read from. */
398
+ defaultLocus?: PrefLocus;
399
+ }
400
+ /** The fields every leaf holding a value shares, besides {@link PrefBase}'s. */
401
+ interface PrefValueBase<K extends string, Value> extends PrefBase<K, Value> {
402
+ /** Drawn showing its value but not editable. */
403
+ readout?: boolean;
317
404
  }
318
405
  /** How a schema-driven UI should present a number pref. */
319
406
  type PrefNumberControl = 'input' | 'slider';
@@ -323,11 +410,16 @@ type PrefBooleanControl = 'checkbox' | 'switch' | 'toggle';
323
410
  type PrefStringControl = 'input' | 'textarea';
324
411
  /** How a schema-driven UI should present an enum pref. */
325
412
  type PrefEnumControl = 'select' | 'radio' | 'toggle' | 'menu';
326
- /** A numeric pref, optionally bounded and stepped, and optionally stored in a
327
- * different unit from the one shown. */
328
- interface PrefNumber extends PrefBase<'number', number> {
413
+ /** What every number leaf carries; {@link PrefNumber} adds `clearable`. */
414
+ interface PrefNumberBase extends PrefValueBase<'number', number | undefined> {
329
415
  min?: number;
330
416
  max?: number;
417
+ /** A lower bound read from where the value is held — a scene node's own
418
+ * minimum — taken with `min`, the larger winning. A surface resolves it
419
+ * per holder with `prefNumberAt`. */
420
+ minAt?: PrefBoundAt;
421
+ /** The upper counterpart of `minAt`, taken with `max`, the smaller winning. */
422
+ maxAt?: PrefBoundAt;
331
423
  step?: number;
332
424
  control?: PrefNumberControl;
333
425
  /** How the value shows, speaks and reads back when typed — `compact()`
@@ -339,6 +431,20 @@ interface PrefNumber extends PrefBase<'number', number> {
339
431
  /** The word infinity shows as — `'never'`, `'uncapped'`. Default `∞`. */
340
432
  infinity?: InfinityText;
341
433
  }
434
+ /**
435
+ * A numeric pref, optionally bounded and stepped, and optionally stored in a
436
+ * different unit from the one shown.
437
+ *
438
+ * `clearable` says the field may hold no number, which a person sets by
439
+ * emptying it: the value is then `undefined`, which the owner reads as unset,
440
+ * and its default may be too.
441
+ */
442
+ type PrefNumber = PrefNumberBase & ({
443
+ clearable?: false;
444
+ default: number;
445
+ } | {
446
+ clearable: true;
447
+ });
342
448
  /**
343
449
  * Stored-value bridge for a boolean leaf whose field is not a boolean — the
344
450
  * flag counterpart of {@link PrefEnumEncoding}. `TextStyle.fontStyle` is
@@ -351,12 +457,12 @@ interface PrefBooleanEncoding {
351
457
  write: (on: boolean, siblings: Record<string, unknown> | undefined) => unknown;
352
458
  }
353
459
  /** An on/off pref. */
354
- interface PrefBoolean extends PrefBase<'boolean', boolean> {
460
+ interface PrefBoolean extends PrefValueBase<'boolean', boolean> {
355
461
  control?: PrefBooleanControl;
356
462
  encoding?: PrefBooleanEncoding;
357
463
  }
358
464
  /** A free-text pref. */
359
- interface PrefString extends PrefBase<'string', string> {
465
+ interface PrefString extends PrefValueBase<'string', string> {
360
466
  control?: PrefStringControl;
361
467
  }
362
468
  /**
@@ -381,13 +487,11 @@ interface PrefEnumEncoding<T extends string = string> {
381
487
  write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;
382
488
  }
383
489
  /** What every enum leaf carries; {@link PrefEnum} adds `clearable`. */
384
- interface PrefEnumBase<T extends string = string> extends PrefBase<'enum', T | undefined> {
490
+ interface PrefEnumBase<T extends string = string> extends PrefValueBase<'enum', T | undefined> {
385
491
  /** `short` holds shorter forms of `label`, longest first, for a segmented
386
492
  * control too narrow for the full one — down to a capital or two. `icon`
387
- * names a glyph in the host UI's set (weasel-ui resolves it against
388
- * `ICON_PATHS`), drawn in place of any text form where it resolves. It is
389
- * a plain string because this package ships no icon set and cannot
390
- * depend on one. The full `label` stays the accessible name, so neither the abbreviation nor the glyph becomes the only thing naming
493
+ * names a glyph, drawn in place of any text form where it resolves. A name
494
+ * from `@weasel-js/icons`; this package draws nothing. The full `label` stays the accessible name, so neither the abbreviation nor the glyph becomes the only thing naming
391
495
  * the option.
392
496
  *
393
497
  * `disabled` marks an option a control reports but cannot author — the
@@ -398,7 +502,7 @@ interface PrefEnumBase<T extends string = string> extends PrefBase<'enum', T | u
398
502
  value: T;
399
503
  label: string;
400
504
  short?: readonly string[];
401
- icon?: string;
505
+ icon?: IconRef;
402
506
  disabled?: boolean;
403
507
  }[];
404
508
  control?: PrefEnumControl;
@@ -422,7 +526,7 @@ type PrefEnum<T extends string = string> = PrefEnumBase<T> & ({
422
526
  });
423
527
  /** A single color, stored as a hex string. For a value that may also be a
424
528
  * gradient or a pattern, use {@link PrefPaint} instead. */
425
- interface PrefColor extends PrefBase<'color', string> {
529
+ interface PrefColor extends PrefValueBase<'color', string> {
426
530
  /** Value is `#rrggbb`, or `#rrggbbaa` when `alpha` is set (UIs then
427
531
  * offer an opacity control). */
428
532
  alpha?: boolean;
@@ -432,7 +536,7 @@ interface PrefColor extends PrefBase<'color', string> {
432
536
  * UIs dispatch it to an app-supplied renderer. Deliberately NOT
433
537
  * index-signatured so concrete app interfaces stay assignable.
434
538
  */
435
- type PrefCustom = PrefBase<string, unknown>;
539
+ type PrefCustom = PrefValueBase<string, unknown>;
436
540
  /**
437
541
  * A whole `Paint`, not a color inside one. Use it wherever the value is
438
542
  * the tagged paint union — a solid color, a pattern, a gradient — rather
@@ -444,7 +548,7 @@ type PrefCustom = PrefBase<string, unknown>;
444
548
  * `'color' in paint` checks then paint flat solid. The union has to be
445
549
  * edited as a union.
446
550
  */
447
- interface PrefPaint extends PrefBase<'paint', unknown> {
551
+ interface PrefPaint extends PrefValueBase<'paint', unknown> {
448
552
  /** Offer an opacity control alongside the color. */
449
553
  alpha?: boolean;
450
554
  }
@@ -460,7 +564,7 @@ interface PrefPaint extends PrefBase<'paint', unknown> {
460
564
  * edits that union. A child may also be a {@link PrefSection}, which
461
565
  * organizes the fields under a heading without contributing to the path.
462
566
  */
463
- interface PrefObject extends PrefBase<'object', unknown> {
567
+ interface PrefObject extends PrefValueBase<'object', unknown> {
464
568
  children: Record<string, PrefLeaf | PrefSection>;
465
569
  /**
466
570
  * Lift a non-object value into the object form, for a consumer field that
@@ -475,13 +579,13 @@ interface PrefObject extends PrefBase<'object', unknown> {
475
579
  * value is read and written at (`'camera.type'`) — the currency fields refer
476
580
  * to each other in. A surface offers the fields it draws as the choices.
477
581
  */
478
- interface PrefField extends PrefBase<'field', string> {
582
+ interface PrefField extends PrefValueBase<'field', string> {
479
583
  /** Only fields of these kinds may be named. Default: any leaf. */
480
584
  kinds?: readonly string[];
481
585
  }
482
586
  /** One built-in pref leaf. `PrefLeaf` widens this to include
483
587
  * app-defined kinds. */
484
- type BuiltinPref = PrefNumber | PrefBoolean | PrefString | PrefEnum | PrefColor | PrefPaint | PrefObject | PrefList | PrefMap | PrefUnion | PrefField | PrefAction | PrefAlias | PrefLabel | PrefSeparator;
588
+ type BuiltinPref = PrefNumber | PrefBoolean | PrefString | PrefEnum | PrefColor | PrefPaint | PrefObject | PrefList | PrefMap | PrefUnion | PrefField | PrefAction | PrefActions | PrefAlias | PrefLabel | PrefSeparator;
485
589
  /**
486
590
  * The built-in kinds, as a table. A kind added to {@link PrefKind} is a
487
591
  * compile error here, and from here it is one in every renderer's `never`
@@ -513,8 +617,20 @@ type PrefLeaf = BuiltinPref | PrefCustom;
513
617
  * `fragment` draws nothing of its own, so its rows sit among its neighbors'
514
618
  * as though they were written there. A fragment exists to hold things
515
619
  * together: one key for their values to nest under, one node to move.
620
+ * `bar` puts its prefs on one line in their bar forms. `menu` is drawn as
621
+ * a menu wherever a menu fits: on a bar, a button opening its contents as a
622
+ * menu; in a menu, a submenu; in a panel, a titled box as `panel` is.
623
+ */
624
+ type PrefGroupAs = 'page' | 'tab' | 'panel' | 'section' | 'fragment' | 'bar' | 'menu';
625
+ /**
626
+ * What a group or a section drawn `as: 'bar'` does with cells its line has no
627
+ * room for: `scroll` keeps them all on it, and `menu` opens the ones past its
628
+ * end from a button there. A bar set to `menu` takes all the room its host
629
+ * has along the line, which is why it is asked for and not the default.
516
630
  */
517
- type PrefGroupAs = 'page' | 'tab' | 'panel' | 'section' | 'fragment' | 'bar';
631
+ type PrefBarOverflow = 'scroll' | 'menu';
632
+ /** What a bar's line starts with, ahead of its cells: `label` puts the bar's name there, and `icon` its `icon`. */
633
+ type PrefBarLead = 'label' | 'icon';
518
634
  /** How a {@link PrefSection} is drawn. */
519
635
  type PrefSectionAs = Exclude<PrefGroupAs, 'page'>;
520
636
  /**
@@ -531,9 +647,24 @@ interface PrefGroup {
531
647
  * reads as nothing without it). */
532
648
  name: string;
533
649
  description?: string;
650
+ /** Tags every leaf under the group carries besides its own. A settings
651
+ * search matching one keeps the whole group, as matching its name does. */
652
+ tags?: readonly string[];
534
653
  /** How the group is drawn. Unset, its depth decides: a top-level group is a
535
654
  * `page`, and one inside another is a `section`. */
536
655
  as?: PrefGroupAs;
656
+ /** Drawn `as: 'bar'`: what happens to the cells its line has no room for.
657
+ * Unset: `scroll`. A surface that takes drops keeps every cell on the line
658
+ * whatever this says, so each is there to drop beside. */
659
+ overflow?: PrefBarOverflow;
660
+ /** Drawn `as: 'bar'`: what its line starts with. Unset: its first cell. */
661
+ lead?: PrefBarLead;
662
+ /** Glyph naming the group, as a leaf's `icon` names the leaf. A bar drawn
663
+ * with `lead: 'icon'` starts its line with it; the button a bar opens the
664
+ * group from and its submenu row in a menu carry it beside its name. */
665
+ icon?: IconRef;
666
+ /** The letter that picks this in a menu, and with the menu bar's chord opens a top-level menu. One character; supported, never required. */
667
+ access?: string;
537
668
  /** Drawn, with everything under it, only while this holds. */
538
669
  showIf?: PrefCondition;
539
670
  /** Everything under it is disabled while this does not hold. */
@@ -552,173 +683,30 @@ interface PrefSection {
552
683
  * {@link PrefGroup}. */
553
684
  name: string;
554
685
  description?: string;
686
+ /** As a {@link PrefGroup}'s. */
687
+ tags?: readonly string[];
555
688
  /** How the section is drawn, as a {@link PrefGroup}'s `as` — without
556
689
  * `page`, since nothing that draws sections has a rail. Unset: a heading
557
690
  * over its rows. */
558
691
  as?: PrefSectionAs;
559
692
  /** As a {@link PrefGroup}'s. */
693
+ overflow?: PrefBarOverflow;
694
+ /** As a {@link PrefGroup}'s. */
695
+ lead?: PrefBarLead;
696
+ /** As a {@link PrefGroup}'s. */
697
+ icon?: IconRef;
698
+ /** As a {@link PrefGroup}'s. */
699
+ access?: string;
700
+ /** As a {@link PrefGroup}'s. */
560
701
  showIf?: PrefCondition;
561
702
  /** As a {@link PrefGroup}'s. */
562
703
  enableIf?: PrefCondition;
563
704
  members: Record<string, PrefLeaf | PrefSection>;
564
705
  }
706
+ /** Whether a panel draws a group or a section drawn `as` this in a bordered, titled box: a `panel`, and a `menu`,
707
+ * which a panel has no menu to open as. */
708
+ declare function prefAsBox(as: PrefGroupAs | undefined): boolean;
565
709
  /** Whether a top-level group gets a page of its own, and not a place on the page of the root's own leaves. */
566
710
  declare function prefGroupIsPage(group: PrefGroup): boolean;
567
711
 
568
- type Join<A extends string, B extends string> = A extends '' ? B : `${A}.${B}`;
569
- /** Every value's dotted path in a `PrefGroup` schema, where a group's key is a
570
- * segment; an `object` leaf is one path, its fields are not, and an `action`,
571
- * `alias`, `label`, or `separator` leaf, holding no value, has none. A `PrefSection`
572
- * has no such paths: each of its leaves is addressed by its own key. */
573
- type PrefPath<G, Prefix extends string = ''> = G extends {
574
- children: infer C;
575
- } ? string extends keyof C ? Join<Prefix, string> : {
576
- [K in keyof C & string]: C[K] extends {
577
- kind: string;
578
- } ? C[K] extends {
579
- kind: 'action' | 'alias' | 'label' | 'separator';
580
- } ? never : Join<Prefix, K> : C[K] extends {
581
- children: Record<string, unknown>;
582
- } ? PrefPath<C[K], Join<Prefix, K>> : never;
583
- }[keyof C & string] : never;
584
- /** The leaf at `P`. */
585
- type PrefAtPath<G, P extends string> = G extends {
586
- children: infer C;
587
- } ? P extends `${infer H}.${infer Rest}` ? H extends keyof C ? C[H] extends {
588
- kind: string;
589
- } ? never : PrefAtPath<C[H], Rest> : never : P extends keyof C ? C[P] extends {
590
- kind: string;
591
- } ? C[P] : never : never : never;
592
- type AllOf<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
593
- /** The fields an `object` leaf's `children` describe, sections folded in. Each is optional: an object may omit any. */
594
- type PrefFieldsOf<C> = {
595
- [K in keyof C as C[K] extends {
596
- kind: string;
597
- } ? K : never]?: PrefValueOf<C[K]>;
598
- } & AllOf<{
599
- [K in keyof C]: C[K] extends {
600
- members: infer M;
601
- } ? PrefFieldsOf<M> : never;
602
- }[keyof C]>;
603
- /** What a leaf holds: its kind's value type for a built-in kind, the type of
604
- * its `default` for an app-defined one. A list holds an array of what its
605
- * `item` holds, a map a record of it, and a union one variant's fields
606
- * under that variant's tag — where the schema keeps `tag` a literal
607
- * (`tag: 'type' as const`); one widened to `string` is typed by its default. */
608
- type PrefValueOf<L> = L extends {
609
- kind: 'number';
610
- } ? number : L extends {
611
- kind: 'boolean';
612
- } ? boolean : L extends {
613
- kind: 'string' | 'color' | 'field';
614
- } ? string : L extends {
615
- kind: 'paint';
616
- } ? unknown : L extends {
617
- kind: 'enum';
618
- options: readonly {
619
- value: infer T;
620
- }[];
621
- } ? L extends {
622
- clearable: true;
623
- } ? T | undefined : T : L extends {
624
- kind: 'list';
625
- item: infer I;
626
- } ? PrefValueOf<I>[] : L extends {
627
- kind: 'map';
628
- item: infer I;
629
- } ? Record<string, PrefValueOf<I>> : L extends {
630
- kind: 'union';
631
- tag: infer T extends string;
632
- variants: infer V;
633
- default: infer D;
634
- } ? string extends keyof V | T ? D : {
635
- [K in keyof V & string]: {
636
- [P in T]: K;
637
- } & (V[K] extends {
638
- children: infer C;
639
- } ? PrefFieldsOf<C> : unknown);
640
- }[keyof V & string] : L extends {
641
- default: infer D;
642
- } ? D : unknown;
643
- /** What the leaf at `P` holds. */
644
- type PrefValueAt<G, P extends string> = PrefValueOf<PrefAtPath<G, P>>;
645
-
646
- /** Takes stored values from one version to the next: rename, transform or
647
- * delete entries in `records`, keyed by leaf path. It sees the values, not
648
- * the stamps they are stored under, and only those at its own version. */
649
- type PrefsMigration = (records: Map<string, unknown>) => void;
650
-
651
- /** Decides what a stored value reads as for one kind of leaf: the value to
652
- * read, or `undefined` for "invalid, read the default". */
653
- type PrefValidator = (stored: unknown, leaf: PrefLeaf) => unknown;
654
- /** What `stored` reads as for `leaf`. Never writes anything back: a schema
655
- * rolled back finds the original still in storage. */
656
- declare function repairPrefValue(leaf: PrefLeaf, stored: unknown, validators?: Readonly<Record<string, PrefValidator>>): unknown;
657
-
658
- /** One leaf changing, as a store subscriber hears it: the value readers now
659
- * see, and whether this store or another writer made the change. */
660
- interface PrefChange {
661
- path: string;
662
- value: unknown;
663
- origin: 'local' | 'remote';
664
- }
665
- /** Values for one schema, held in memory and persisted behind. */
666
- interface PrefsStore<S extends PrefGroup> {
667
- readonly schema: S;
668
- /** The leaf's value, repaired against the schema; its default when unset. */
669
- get<P extends PrefPath<S>>(path: P): PrefValueAt<S, P>;
670
- set<P extends PrefPath<S>>(path: P, value: PrefValueAt<S, P>): void;
671
- /** Unset every leaf at or under `path`; with no path, all. */
672
- reset(path?: string): void;
673
- /** Whether the leaf has a value of its own rather than following its default. */
674
- isSet(path: PrefPath<S>): boolean;
675
- /** Every leaf's value as a nested tree. The same object until something changes. */
676
- values(): Record<string, unknown>;
677
- /** The leaves following their default. The same set until something changes. */
678
- unset(): ReadonlySet<string>;
679
- /** Every stored record as a nested tree, unrepaired, including records no
680
- * leaf describes. The same object until something changes. */
681
- stored(): Record<string, unknown>;
682
- /** `changes` is empty when only records no leaf describes changed. */
683
- subscribe(listener: (changes: PrefChange[]) => void): () => void;
684
- /** False while the store cannot persist: storage has not been read yet, or
685
- * was written by a newer schema. Changes still apply for this session, and
686
- * ones made before a late read lands are persisted when it does. False for
687
- * good once the store is closed. */
688
- readonly writable: boolean;
689
- /** True once `close` was called. A write after that changes what this store
690
- * reads and reaches neither storage nor its subscribers, and the first one
691
- * warns. */
692
- readonly closed: boolean;
693
- /** Try again now to read storage that could not be read at open, ahead of
694
- * the store's own retries. Resolves whether storage has been read. */
695
- read(): Promise<boolean>;
696
- /** Resolves once storage has been read: at once for a store that opened
697
- * with its values, and when a later read lands for one that could not. */
698
- whenRead(): Promise<void>;
699
- /** Resolves true when every queued write reached storage. */
700
- flush(): Promise<boolean>;
701
- close(): Promise<void>;
702
- }
703
-
704
- /** Options for `openPrefs` and `openPrefsSync`. */
705
- interface PrefsOptions {
706
- storage: StorageAdapter;
707
- /** Prepended to every record's key: `'myapp.prefs.'`. */
708
- prefix: string;
709
- /** `migrations[i]` takes stored records from version `i` to `i + 1`. The
710
- * current version is `migrations.length`. */
711
- migrations?: readonly PrefsMigration[];
712
- /** Validators for app-defined kinds, keyed by `kind`. One given for a
713
- * built-in kind replaces that kind's own rule. */
714
- validators?: Readonly<Record<string, PrefValidator>>;
715
- }
716
- /** Load every stored value for `schema`, migrate it, and return the store. */
717
- declare function openPrefs<S extends PrefGroup>(schema: S, options: PrefsOptions): Promise<PrefsStore<S>>;
718
- /** `openPrefs` for an adapter that reads synchronously: the store is ready
719
- * on return, so values can be read before anything renders. */
720
- declare function openPrefsSync<S extends PrefGroup>(schema: S, options: PrefsOptions & {
721
- storage: SyncStorageAdapter;
722
- }): PrefsStore<S>;
723
-
724
- export { isPrefCondition as $, type PrefEnumEncoding as A, type BuiltinPref as B, type PrefField as C, type PrefFunctionUnit as D, type PrefGroupAs as E, type PrefLabel as F, type PrefLinearUnit as G, type PrefNumberControl as H, type PrefNumberUnit as I, type PrefPaint as J, type PrefPair as K, type PrefPath as L, type PrefSectionAs as M, type PrefSeparator as N, type PrefString as O, type PrefLeaf as P, type PrefStringControl as Q, type PrefTest as R, type PrefUnion as S, type PrefValidator as T, type PrefValueAt as U, type PrefValueOf as V, type PrefsMigration as W, type PrefsOptions as X, type PrefsStore as Y, type ResolvedPrefUnit as Z, isBuiltinPref as _, type PrefGroup as a, isPrefLinearUnit as a0, mapPrefConditionPaths as a1, openPrefs as a2, openPrefsSync as a3, pairRowsOf as a4, prefAliasName as a5, prefAliasTarget as a6, prefAliasedLeaf as a7, prefConditionHolds as a8, prefConditionPaths as a9, prefConditionReadsItem as aa, prefGroupIsPage as ab, prefIsEnabled as ac, prefIsShown as ad, prefUnit as ae, prefVariantDefault as af, prefVariantOf as ag, repairPrefValue as ah, resolvePrefUnit as ai, type PrefSection as b, type PrefNumber as c, type PrefList as d, type PrefMap as e, type PrefCondition as f, type PrefConditionReader as g, type PrefAlias as h, type PrefObject as i, type PrefKind as j, PREF_KINDS as k, type PrefAction as l, type PrefActionContext as m, type PrefActionControl as n, type PrefAtPath as o, type PrefBase as p, type PrefBoolean as q, type PrefBooleanControl as r, type PrefBooleanEncoding as s, type PrefChange as t, type PrefColor as u, type PrefConditionValue as v, type PrefCustom as w, type PrefEnum as x, type PrefEnumBase as y, type PrefEnumControl as z };
712
+ export { type ResolvedPrefUnit as $, type PrefBoundAt as A, type BuiltinPref as B, type PrefBoundReader as C, type PrefConditionValue as D, type PrefCustom as E, type PrefEnum as F, type PrefEnumControl as G, type PrefEnumEncoding as H, type PrefField as I, type PrefFunctionUnit as J, type PrefGroupAs as K, type PrefLinearUnit as L, type PrefLocus as M, type PrefNumberBase as N, type PrefNumberControl as O, type PrefLeaf as P, type PrefNumberUnit as Q, type PrefPaint as R, type PrefPair as S, type PrefSectionAs as T, type PrefSelection as U, type PrefStringControl as V, type PrefTest as W, type PrefUnion as X, type PrefValueBase as Y, type PrefWeighted as Z, type PrefWeights as _, type PrefGroup as a, isBuiltinPref as a0, isPrefCondition as a1, isPrefLinearUnit as a2, isPrefLocus as a3, mapPrefConditionPaths as a4, pairRowsOf as a5, prefAliasName as a6, prefAliasTarget as a7, prefAliasedLeaf as a8, prefAsBox as a9, prefClampNumber as aa, prefConditionHolds as ab, prefConditionPaths as ac, prefConditionReadsItem as ad, prefGroupIsPage as ae, prefIsEnabled as af, prefIsShown as ag, memberAt as ah, locusSelectors as ai, prefNumberAt as aj, prefUnit as ak, prefUnitAccepts as al, prefVariantDefault as am, prefVariantOf as an, resolvePrefUnit as ao, type PrefSection as b, type PrefNumber as c, type PrefList as d, type PrefMap as e, type PrefCondition as f, type PrefConditionReader as g, type PrefBoolean as h, type PrefString as i, type PrefColor as j, type PrefEnumBase as k, type PrefAction as l, type PrefActions as m, type PrefLabel as n, type PrefSeparator as o, type PrefAlias as p, type PrefObject as q, type PrefKind as r, PREF_KINDS as s, type PrefActionContext as t, type PrefActionControl as u, type PrefBarLead as v, type PrefBarOverflow as w, type PrefBase as x, type PrefBooleanControl as y, type PrefBooleanEncoding as z };