@weasel-js/prefs 0.0.0-stage → 1.9.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 orochi235
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,30 @@
1
- # Temporary Holding Version
1
+ # @weasel-js/prefs
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A preferences schema — groups of typed leaves with names, defaults and
4
+ rendering hints — and a store that keeps values for it.
5
+
6
+ ```ts
7
+ const store = await openPrefs(SCHEMA, { storage: indexedDbAdapter, prefix: 'myapp.prefs.' });
8
+ store.get('view.gridVisible');
9
+ store.set('view.gridVisible', false);
10
+ ```
11
+
12
+ One record per leaf. A leaf with no record follows its schema default. Reads
13
+ repair stored values that no longer fit the schema without writing them back.
14
+ `migrations[i]` takes stored records from version `i` to `i + 1`.
15
+ `openPrefsSync` opens from an adapter that reads synchronously, such as
16
+ `localStorageAdapter`, with no `await`.
17
+
18
+ `usePref(store, path)` and `usePrefsValues(store)` bind it to React. They
19
+ live in `@weasel-js/prefs/react`, so the main entry never loads React.
20
+ `usePrefsValues` returns the pieces `@weasel-js/ui`'s `PrefsForm` takes.
21
+
22
+ ## Ranges
23
+
24
+ A number leaf's range is one scale: the low end is the least of what its label
25
+ names and the high end the most. Do not give zero a second meaning such as
26
+ "no limit" or "automatic" — on a slider it reads as the least, and the form
27
+ draws it there. Put an unlimited setting at the end of the range it is nearest:
28
+ a 0–100% limit is off at 100, and a scale with no such end takes `endless`,
29
+ which adds a stop one step past the range that stores `Infinity` and reads the
30
+ leaf's `infinity` word.
@@ -0,0 +1,153 @@
1
+ import { P as PrefLeaf, a as PrefGroup, b as PrefSection, c as PrefNumber, d as PrefObject, e as PrefsStore, f as PrefKind } from './store-CNFnA_3c.js';
2
+ export { B as BuiltinPref, g as PREF_KINDS, h as PrefAction, i as PrefActionContext, j as PrefActionControl, k as PrefAlias, l as PrefAtPath, m as PrefBase, n as PrefBoolean, o as PrefBooleanControl, p as PrefBooleanEncoding, q as PrefChange, r as PrefColor, s as PrefCustom, t as PrefEnum, u as PrefEnumBase, v as PrefEnumControl, w as PrefEnumEncoding, x as PrefField, y as PrefGroupAs, z as PrefLabel, A as PrefList, C as PrefMap, D as PrefNumberControl, E as PrefNumberUnit, F as PrefPaint, G as PrefPair, H as PrefPath, I as PrefSectionAs, J as PrefSeparator, K as PrefString, L as PrefStringControl, M as PrefUnion, N as PrefValueAt, O as PrefValueOf, Q as isBuiltinPref, R as pairRowsOf, S as prefAliasTarget, T as prefAliasedLeaf, U as prefGroupIsPage, V as prefUnit, W as prefVariantDefault, X as prefVariantOf } from './store-CNFnA_3c.js';
3
+ import { StorageAdapter, SyncStorageAdapter } from '@weasel-js/storage';
4
+ import '@weasel-js/quantity';
5
+
6
+ /**
7
+ * A number leaf's bounds in the unit it is displayed in.
8
+ *
9
+ * Only what the leaf declares converts: an omitted bound has no stored
10
+ * counterpart to put through the conversion, and its fallback — 0..100 for a
11
+ * slider's track, a step of 1 — is a display-space number already. `min` and
12
+ * `max` are points, so they convert the way the value does; `step` is a
13
+ * distance, and a unit with an offset maps zero somewhere else, so converting
14
+ * it as a point would scale it wrong. A decreasing conversion swaps which end
15
+ * is the lower one.
16
+ */
17
+ declare function prefDisplayBounds(p: PrefNumber): {
18
+ min?: number;
19
+ max?: number;
20
+ step: number;
21
+ };
22
+ /** Distinguishes a leaf from a group or a section while walking a schema tree. */
23
+ declare function isPrefLeaf(node: PrefLeaf | PrefGroup | PrefSection): node is PrefLeaf;
24
+ /** Whether a leaf has a value to store: an `action` is a button and holds none, an `alias` shows another leaf's,
25
+ * and a `label` and a `separator` are text and a rule. */
26
+ declare function prefHoldsValue(leaf: PrefLeaf): boolean;
27
+ /** Distinguishes a section, whose key adds nothing to a path, from a group, whose key is a segment. */
28
+ declare function isPrefSection(node: PrefLeaf | PrefGroup | PrefSection): node is PrefSection;
29
+ /**
30
+ * Every leaf under a section's `members` or an object leaf's `children`, in
31
+ * schema order, by its own key: the sections between contribute nothing.
32
+ */
33
+ declare function prefSectionLeaves(members: PrefSection['members']): [key: string, leaf: PrefLeaf][];
34
+ /**
35
+ * The leaf whose value lives at `path`, as the schema's own shape builds
36
+ * paths: a segment per key under a {@link PrefGroup}, the leaf's own key
37
+ * under a {@link PrefSection}. `undefined` for a path that names a group, a
38
+ * field inside an `object` leaf, or nothing.
39
+ */
40
+ declare function prefLeafAt(schema: PrefGroup | PrefSection, path: string): PrefLeaf | undefined;
41
+ /** Get the value at a dotted path inside a nested value tree. Returns
42
+ * `undefined` when a segment is missing or hits a non-object. */
43
+ declare function prefValueAtPath(values: unknown, path: string): unknown;
44
+ /**
45
+ * Recursively drop `hidden` leaves (unless `showHidden`), an object leaf's
46
+ * hidden fields among them, pruning groups
47
+ * that end up empty (unless `keepEmpty`). Returns null when the entire
48
+ * subtree is pruned.
49
+ */
50
+ declare function visiblePrefSubtree<T extends PrefLeaf | PrefGroup>(node: T, showHidden: boolean, keepEmpty?: boolean): T | null;
51
+ /** The record holding the schema version the stored values were written at.
52
+ * Reserved: no top-level schema key may take its name. */
53
+ declare const VERSION_RECORD = "$version";
54
+ /** Every leaf under `schema`, by dotted path, in schema order. A group's key
55
+ * is a segment; {@link prefSectionLeaves} is the walk for a section. */
56
+ declare function prefLeaves(schema: PrefGroup): Map<string, PrefLeaf>;
57
+ /** Each of `schema`'s leaves that `tree` holds a value for, as a path and
58
+ * that value — the inverse of building a tree from per-leaf records. */
59
+ declare function flattenPrefValues(schema: PrefGroup, tree: unknown): [string, unknown][];
60
+ /**
61
+ * Drop every leaf that does not answer to `query`, pruning groups left empty.
62
+ * A group whose own name matches keeps all of its leaves — a reader who typed
63
+ * the group's name is asking for the group, not for leaves repeating it.
64
+ *
65
+ * An empty or whitespace query matches everything, so a cleared field restores
66
+ * the tree rather than emptying it.
67
+ *
68
+ * An alias answers as the row it draws: its target's name and description
69
+ * where it gives none. `leafAt` finds that target, and defaults to looking in
70
+ * `node`; pass one over the whole schema when `node` is a part of it.
71
+ */
72
+ declare function filterPrefSubtree<T extends PrefLeaf | PrefGroup>(node: T, query: string, path?: string, leafAt?: (path: string) => PrefLeaf | undefined): T | null;
73
+
74
+ /**
75
+ * The object a write to one field of an `object` leaf starts from: `held` itself where it is one. Where it is
76
+ * not, the write has to make a whole object, so it starts from the scalar lifted by the leaf's `fromScalar`, else
77
+ * from the leaf's `default`: one field on its own is a stroke with a width and no paint.
78
+ */
79
+ declare function prefObjectBase(pref: PrefObject, held: unknown): Record<string, unknown>;
80
+ /** The object an `object` leaf holds after one of its fields is set: {@link prefObjectBase} with `key` at
81
+ * `value`, or without the key for `undefined`. */
82
+ declare function prefObjectWithField(pref: PrefObject, held: unknown, key: string, value: unknown): Record<string, unknown>;
83
+
84
+ /**
85
+ * `leaf` as a named type: the same leaf carrying `name` in its `type` field.
86
+ * Declared once beside the code that reads its value and used wherever a
87
+ * schema wants one, spread with what that place sets for itself
88
+ * (`{ ...GradientStop, name: 'First stop' }`), or as a list's or a map's
89
+ * `item`. `name` is the identifier the type is exported under, which a schema
90
+ * editor prints in place of the leaf's literal.
91
+ */
92
+ declare function prefType<L extends PrefLeaf>(name: string, leaf: L): L & {
93
+ type: string;
94
+ };
95
+
96
+ /** Takes stored values from one version to the next: rename, transform or
97
+ * delete entries in `records`, keyed by leaf path. It sees the values, not
98
+ * the stamps they are stored under, and only those at its own version. */
99
+ type PrefsMigration = (records: Map<string, unknown>) => void;
100
+
101
+ /** Decides what a stored value reads as for one kind of leaf: the value to
102
+ * read, or `undefined` for "invalid, read the default". */
103
+ type PrefValidator = (stored: unknown, leaf: PrefLeaf) => unknown;
104
+ /** What `stored` reads as for `leaf`. Never writes anything back: a schema
105
+ * rolled back finds the original still in storage. */
106
+ declare function repairPrefValue(leaf: PrefLeaf, stored: unknown, validators?: Readonly<Record<string, PrefValidator>>): unknown;
107
+
108
+ /** Options for `openPrefs` and `openPrefsSync`. */
109
+ interface PrefsOptions {
110
+ storage: StorageAdapter;
111
+ /** Prepended to every record's key: `'myapp.prefs.'`. */
112
+ prefix: string;
113
+ /** `migrations[i]` takes stored records from version `i` to `i + 1`. The
114
+ * current version is `migrations.length`. */
115
+ migrations?: readonly PrefsMigration[];
116
+ /** Validators for app-defined kinds, keyed by `kind`. One given for a
117
+ * built-in kind replaces that kind's own rule. */
118
+ validators?: Readonly<Record<string, PrefValidator>>;
119
+ }
120
+ /** Load every stored value for `schema`, migrate it, and return the store. */
121
+ declare function openPrefs<S extends PrefGroup>(schema: S, options: PrefsOptions): Promise<PrefsStore<S>>;
122
+ /** `openPrefs` for an adapter that reads synchronously: the store is ready
123
+ * on return, so values can be read before anything renders. */
124
+ declare function openPrefsSync<S extends PrefGroup>(schema: S, options: PrefsOptions & {
125
+ storage: SyncStorageAdapter;
126
+ }): PrefsStore<S>;
127
+
128
+ /** What a surface has to know about a kind before it can lay its control out. */
129
+ interface PrefKindTraits {
130
+ /** Its value is made of other leaves' values: too much for one control on a
131
+ * line, so a bar opens it in a popover and a compact panel in a dialog. */
132
+ compound: boolean;
133
+ /** Its control is several controls, or a button. A row drawn as a `<label>`
134
+ * would hand a click on its text to the first of them. */
135
+ several: boolean;
136
+ }
137
+ /**
138
+ * The traits of every built-in kind. A `Record` over {@link PrefKind}, so a
139
+ * kind added to the union does not compile until it says what it is here:
140
+ * a plain set of kind names lets a new one through to draw inline in a
141
+ * `<label>`, on a bar's line, and with no dialog row.
142
+ */
143
+ declare const PREF_KIND_TRAITS: Record<PrefKind, PrefKindTraits>;
144
+ /** Whether a leaf's value is made of other leaves' values. An app-defined kind is not: its renderer is one control. */
145
+ declare function prefIsCompound(leaf: {
146
+ kind: string;
147
+ }): boolean;
148
+ /** Whether a leaf's control is several controls or a button. */
149
+ declare function prefDrawsSeveral(leaf: {
150
+ kind: string;
151
+ }): boolean;
152
+
153
+ export { PREF_KIND_TRAITS, PrefGroup, PrefKind, type PrefKindTraits, PrefLeaf, PrefNumber, PrefObject, PrefSection, type PrefValidator, type PrefsMigration, type PrefsOptions, PrefsStore, VERSION_RECORD, filterPrefSubtree, flattenPrefValues, isPrefLeaf, isPrefSection, openPrefs, openPrefsSync, prefDisplayBounds, prefDrawsSeveral, prefHoldsValue, prefIsCompound, prefLeafAt, prefLeaves, prefObjectBase, prefObjectWithField, prefSectionLeaves, prefType, prefValueAtPath, repairPrefValue, visiblePrefSubtree };