@weasel-js/prefs 1.9.3 → 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/README.md +10 -0
- package/dist/index.d.ts +84 -12
- package/dist/index.js +321 -62
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js.map +1 -1
- package/dist/{store-BU2tRX5H.d.ts → store-CNFnA_3c.d.ts} +250 -31
- package/package.json +4 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers.ts","../src/migrate.ts","../src/repair.ts","../src/store.ts","../src/open.ts","../src/schema.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { PrefGroup, PrefLeaf, PrefNumber } from './schema';\n\n/**\n * A number leaf's bounds in the unit it is displayed in.\n *\n * Only what the leaf declares converts: an omitted bound has no stored\n * counterpart to put through the conversion, and its fallback — 0..100 for a\n * slider's track, a step of 1 — is a display-space number already. `min` and\n * `max` are points, so they convert the way the value does; `step` is a\n * distance, and a unit with an offset maps zero somewhere else, so converting\n * it as a point would scale it wrong. A decreasing conversion swaps which end\n * is the lower one.\n */\nexport function prefDisplayBounds(\n p: PrefNumber,\n): { min?: number; max?: number; step: number } {\n if (!p.unit) return { min: p.min, max: p.max, step: p.step ?? 1 };\n const { toDisplay } = p.unit;\n const lo = p.min === undefined ? undefined : toDisplay(p.min);\n const hi = p.max === undefined ? undefined : toDisplay(p.max);\n const flipped = lo !== undefined && hi !== undefined && lo > hi;\n const step = p.step === undefined\n ? 1\n : Math.abs(toDisplay(p.step) - toDisplay(0)) || p.step;\n return { min: flipped ? hi : lo, max: flipped ? lo : hi, step };\n}\n\n/** Distinguishes a leaf from a group while walking a schema tree. */\nexport function isPrefLeaf(node: PrefLeaf | PrefGroup): node is PrefLeaf {\n return 'kind' in node;\n}\n\n/** Get the value at a dotted path inside a nested value tree. Returns\n * `undefined` when a segment is missing or hits a non-object. */\nexport function prefValueAtPath(values: unknown, path: string): unknown {\n let cur: unknown = values;\n for (const seg of path.split('.')) {\n if (cur == null || typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[seg];\n }\n return cur;\n}\n\n/**\n * Recursively drop `hidden` leaves (unless `showHidden`), pruning groups\n * that end up empty. Returns null when the entire subtree is hidden.\n */\nexport function visiblePrefSubtree<T extends PrefLeaf | PrefGroup>(\n node: T,\n showHidden: boolean,\n): T | null {\n if (isPrefLeaf(node)) return node.hidden && !showHidden ? null : node;\n const group = node as PrefGroup;\n const children: Record<string, PrefLeaf | PrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = visiblePrefSubtree(child, showHidden);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0) return null;\n return { ...node, children };\n}\n\n/** The record holding the schema version the stored values were written at.\n * Reserved: no top-level schema key may take its name. */\nexport const VERSION_RECORD = '$version';\n\n/** Every leaf under `schema`, by dotted path, in schema order. */\nexport function prefLeaves(schema: PrefGroup): Map<string, PrefLeaf> {\n const out = new Map<string, PrefLeaf>();\n const walk = (group: PrefGroup, prefix: string): void => {\n for (const [key, child] of Object.entries(group.children)) {\n if (key.includes('.')) {\n throw new Error(`[prefs] schema key \"${key}\" contains \".\"; group keys are path segments`);\n }\n if (prefix === '' && key === VERSION_RECORD) {\n throw new Error(`[prefs] schema key \"${VERSION_RECORD}\" is reserved`);\n }\n const path = prefix === '' ? key : `${prefix}.${key}`;\n if (isPrefLeaf(child)) out.set(path, child);\n else walk(child, path);\n }\n };\n walk(schema, '');\n return out;\n}\n\n/** Set `value` at the dotted `path` in `root` itself, creating missing branches. */\nexport function assignPrefValueAtPath(root: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let cursor = root;\n for (let i = 0; i < parts.length - 1; i++) {\n cursor = (cursor[parts[i]!] ??= {}) as Record<string, unknown>;\n }\n cursor[parts[parts.length - 1]!] = value;\n}\n\n/** Each of `schema`'s leaves that `tree` holds a value for, as a path and\n * that value — the inverse of building a tree from per-leaf records. */\nexport function flattenPrefValues(schema: PrefGroup, tree: unknown): [string, unknown][] {\n const out: [string, unknown][] = [];\n for (const path of prefLeaves(schema).keys()) {\n const value = prefValueAtPath(tree, path);\n if (value !== undefined) out.push([path, value]);\n }\n return out;\n}\n\n/** Whether one leaf answers to a filter query, by name, description or path. */\nfunction prefLeafMatches(pref: PrefLeaf, path: string, query: string): boolean {\n if (pref.name.toLowerCase().includes(query)) return true;\n if (pref.description?.toLowerCase().includes(query)) return true;\n return path.toLowerCase().includes(query);\n}\n\n/**\n * Drop every leaf that does not answer to `query`, pruning groups left empty.\n * A group whose own name matches keeps all of its leaves — a reader who typed\n * the group's name is asking for the group, not for leaves repeating it.\n *\n * An empty or whitespace query matches everything, so a cleared field restores\n * the tree rather than emptying it.\n */\nexport function filterPrefSubtree<T extends PrefLeaf | PrefGroup>(\n node: T,\n query: string,\n path = '',\n): T | null {\n const q = query.trim().toLowerCase();\n if (q === '') return node;\n if (isPrefLeaf(node)) return prefLeafMatches(node, path, q) ? node : null;\n const group = node as PrefGroup;\n if (group.name.toLowerCase().includes(q)) return node;\n const children: Record<string, PrefLeaf | PrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = filterPrefSubtree(child, q, path === '' ? key : `${path}.${key}`);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0) return null;\n return { ...node, children };\n}\n","import type { OwnedRecordCache } from '@weasel-js/storage';\nimport { VERSION_RECORD } from './helpers';\n\nconst isVersion = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v >= 0;\n\n/** Takes stored records from one version to the next: rename, transform or\n * delete entries in `records`, keyed by leaf path. */\nexport type PrefsMigration = (records: Map<string, unknown>) => void;\n\n/**\n * Bring `cache` up to `migrations.length`, the current version. Every record\n * a migration leaves is written back, so a migration may replace values or\n * mutate them in place. Stops writing, and writes nothing, when the stored\n * version is newer than this build knows or a migration throws. Returns\n * whether it wrote.\n */\nexport function runPrefsMigrations(\n cache: OwnedRecordCache,\n migrations: readonly PrefsMigration[],\n): boolean {\n const target = migrations.length;\n const raw = cache.get(VERSION_RECORD);\n if (cache.has(VERSION_RECORD) && !isVersion(raw)) {\n console.warn(\n `[prefs] \"${cache.prefix}\" has an unreadable ${VERSION_RECORD} (${JSON.stringify(raw)}); opening read-only`,\n );\n cache.stopWriting();\n return false;\n }\n const stored = cache.has(VERSION_RECORD) ? (raw as number) : 0;\n if (stored > target) {\n console.warn(\n `[prefs] \"${cache.prefix}\" was written at version ${stored}, newer than this build's ${target}; opening read-only`,\n );\n cache.stopWriting();\n return false;\n }\n if (stored === target || !cache.writable) return false;\n\n const before = cache.entries().filter(([name]) => name !== VERSION_RECORD);\n const records = new Map(before.map(([name, value]): [string, unknown] => [name, structuredClone(value)]));\n for (let v = stored; v < target; v++) {\n try {\n migrations[v]!(records);\n } catch (error) {\n console.warn(\n `[prefs] migration ${v} → ${v + 1} for \"${cache.prefix}\" threw; opening read-only on the unmigrated records`,\n error,\n );\n cache.stopWriting();\n return false;\n }\n }\n for (const [name] of before) if (!records.has(name)) cache.delete(name);\n for (const [name, value] of records) {\n if (value === undefined) cache.delete(name);\n else cache.set(name, value);\n }\n cache.set(VERSION_RECORD, target);\n return true;\n}\n\n/**\n * Stop persisting when another writer, a newer build in another tab, records a\n * version past `target`: this build would otherwise keep writing the old shape.\n * Returns the unsubscribe.\n */\nexport function watchPrefsVersion(cache: OwnedRecordCache, target: number): () => void {\n return cache.subscribe((changes) => {\n for (const change of changes) {\n if (change.origin !== 'remote' || change.name !== VERSION_RECORD || change.value === undefined) continue;\n if (!isVersion(change.value)) {\n console.warn(\n `[prefs] \"${cache.prefix}\" has an unreadable ${VERSION_RECORD} (${JSON.stringify(change.value)}) from another writer; no longer persisting`,\n );\n cache.stopWriting();\n } else if (change.value > target) {\n console.warn(\n `[prefs] \"${cache.prefix}\" was migrated to version ${change.value} by another writer; this build knows ${target}; no longer persisting`,\n );\n cache.stopWriting();\n }\n }\n });\n}\n","import type { PrefBoolean, PrefEnum, PrefLeaf, PrefNumber, PrefObject } from './schema';\n\n/** Decides what a stored value reads as for one kind of leaf: the value to\n * read, or `undefined` for \"invalid, read the default\". */\nexport type PrefValidator = (stored: unknown, leaf: PrefLeaf) => unknown;\n\n/** What `stored` reads as for `leaf`. Never writes anything back: a schema\n * rolled back finds the original still in storage. */\nexport function repairPrefValue(\n leaf: PrefLeaf,\n stored: unknown,\n validators?: Readonly<Record<string, PrefValidator>>,\n): unknown {\n if (leaf.kind === 'number') {\n if (stored === 'Infinity') stored = Infinity;\n else if (stored === '-Infinity') stored = -Infinity;\n }\n const validate = validators?.[leaf.kind];\n if (validate) {\n try {\n const out = validate(stored, leaf);\n return out === undefined ? leaf.default : out;\n } catch {\n return leaf.default;\n }\n }\n switch (leaf.kind) {\n case 'number':\n return repairNumber(leaf as PrefNumber, stored);\n case 'boolean':\n return (leaf as PrefBoolean).encoding || typeof stored === 'boolean' ? stored : leaf.default;\n case 'string':\n case 'color':\n case 'field':\n return typeof stored === 'string' ? stored : leaf.default;\n case 'enum': {\n const e = leaf as PrefEnum;\n if (e.encoding) return stored;\n return e.options.some((o) => o.value === stored) ? stored : leaf.default;\n }\n case 'object':\n if ((leaf as PrefObject).fromScalar || isPlainObject(stored)) return stored;\n return leaf.default;\n default:\n return stored;\n }\n}\n\nfunction isPlainObject(v: unknown): boolean {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction repairNumber(leaf: PrefNumber, stored: unknown): unknown {\n if (typeof stored !== 'number' || Number.isNaN(stored)) return leaf.default;\n const { endless } = leaf;\n if (stored === Infinity && (endless === 'max' || endless === 'both')) return stored;\n if (stored === -Infinity && (endless === 'min' || endless === 'both')) return stored;\n let v = stored;\n if (leaf.min !== undefined && v < leaf.min) v = leaf.min;\n if (leaf.max !== undefined && v > leaf.max) v = leaf.max;\n return Number.isFinite(v) ? v : leaf.default;\n}\n","import type { OwnedRecordCache } from '@weasel-js/storage';\nimport { assignPrefValueAtPath, prefLeaves, VERSION_RECORD } from './helpers';\nimport type { PrefPath, PrefValueAt } from './paths';\nimport { type PrefValidator, repairPrefValue } from './repair';\nimport type { PrefGroup, PrefLeaf } from './schema';\n\n/** One leaf changing, as a store subscriber hears it: the value readers now\n * see, and whether this store or another writer made the change. */\nexport interface PrefChange {\n path: string;\n value: unknown;\n origin: 'local' | 'remote';\n}\n\n/** Values for one schema, held in memory and persisted behind. */\nexport interface PrefsStore<S extends PrefGroup> {\n readonly schema: S;\n /** The leaf's value, repaired against the schema; its default when unset. */\n get<P extends PrefPath<S>>(path: P): PrefValueAt<S, P>;\n set<P extends PrefPath<S>>(path: P, value: PrefValueAt<S, P>): void;\n /** Unset every leaf at or under `path`; with no path, all. */\n reset(path?: string): void;\n /** Whether the leaf has a value of its own rather than following its default. */\n isSet(path: PrefPath<S>): boolean;\n /** Every leaf's value as a nested tree. The same object until something changes. */\n values(): Record<string, unknown>;\n /** The leaves following their default. The same set until something changes. */\n unset(): ReadonlySet<string>;\n /** Every stored record as a nested tree, unrepaired, including records no\n * leaf describes. The same object until something changes. */\n stored(): Record<string, unknown>;\n /** `changes` is empty when only records no leaf describes changed. */\n subscribe(listener: (changes: PrefChange[]) => void): () => void;\n /** False when the store cannot persist: storage was unreadable, or written\n * by a newer schema. Changes still apply for this session. */\n readonly writable: boolean;\n /** Resolves true when every queued write reached storage. */\n flush(): Promise<boolean>;\n close(): Promise<void>;\n}\n\ninterface Snapshot {\n byPath: Map<string, unknown>;\n tree: Record<string, unknown>;\n unset: ReadonlySet<string>;\n}\n\n/** JSON storage cannot keep an infinity; `repairPrefValue` reads these back. */\nconst encodeInfinity = (leaf: PrefLeaf, value: unknown): unknown =>\n leaf.kind === 'number' && (value === Infinity || value === -Infinity) ? String(value) : value;\n\n/** A store over an open cache. `openPrefs` / `openPrefsSync` are the usual\n * way in; they run migrations first. */\nexport function createPrefsStore<S extends PrefGroup>(\n schema: S,\n cache: OwnedRecordCache,\n validators?: Readonly<Record<string, PrefValidator>>,\n onClose?: () => void,\n): PrefsStore<S> {\n const leaves = prefLeaves(schema);\n let snapshot: Snapshot | null = null;\n let previous: { raw: Map<string, unknown>; byPath: Map<string, unknown> } | null = null;\n\n const build = (): Snapshot => {\n const byPath = new Map<string, unknown>();\n const raw = new Map<string, unknown>();\n const unset = new Set<string>();\n const tree: Record<string, unknown> = {};\n for (const [path, leaf] of leaves) {\n const has = cache.has(path);\n let value: unknown;\n if (!has) {\n value = leaf.default;\n unset.add(path);\n } else {\n const stored = cache.get(path);\n raw.set(path, stored);\n value =\n previous?.raw.has(path) && previous.raw.get(path) === stored\n ? previous.byPath.get(path)\n : repairPrefValue(leaf, stored, validators);\n }\n byPath.set(path, value);\n assignPrefValueAtPath(tree, path, value);\n }\n previous = { raw, byPath };\n return { byPath, tree, unset };\n };\n const current = (): Snapshot => (snapshot ??= build());\n\n let storedTree: Record<string, unknown> | null = null;\n const buildStored = (): Record<string, unknown> => {\n const tree: Record<string, unknown> = {};\n const branches = new WeakSet<object>([tree]);\n for (const [name, value] of cache.entries()) {\n if (name === VERSION_RECORD) continue;\n const parts = name.split('.');\n let cursor = tree;\n for (const part of parts.slice(0, -1)) {\n const next = cursor[part];\n // A record's own value is never descended into: one named `a` and\n // another `a.b` cannot both show, and the branch wins.\n if (typeof next === 'object' && next !== null && branches.has(next)) {\n cursor = next as Record<string, unknown>;\n } else {\n const branch: Record<string, unknown> = {};\n branches.add(branch);\n cursor[part] = branch;\n cursor = branch;\n }\n }\n const last = parts[parts.length - 1]!;\n if (!branches.has(cursor[last] as object)) cursor[last] = value;\n }\n return tree;\n };\n\n const listeners = new Set<(changes: PrefChange[]) => void>();\n const stopCache = cache.subscribe((changes) => {\n const records = changes.filter((c) => c.name !== VERSION_RECORD);\n if (records.length === 0) return;\n storedTree = null;\n const mine = records.filter((c) => leaves.has(c.name));\n if (mine.length > 0) snapshot = null;\n const now = current();\n const out = mine.map((c): PrefChange => ({ path: c.name, value: now.byPath.get(c.name), origin: c.origin }));\n for (const listener of [...listeners]) listener(out);\n });\n\n return {\n schema,\n get: (path) => current().byPath.get(path) as never,\n set: (path, value) => {\n const leaf = leaves.get(path);\n if (!leaf) {\n console.warn(`[prefs] no leaf at \"${path}\"; ignoring the write`);\n return;\n }\n cache.set(path, encodeInfinity(leaf, value));\n },\n reset: (path) => {\n for (const p of leaves.keys()) {\n if (path === undefined || p === path || p.startsWith(`${path}.`)) cache.delete(p);\n }\n },\n isSet: (path) => cache.has(path),\n values: () => current().tree,\n unset: () => current().unset,\n stored: () => (storedTree ??= buildStored()),\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n get writable() {\n return cache.writable;\n },\n flush: () => cache.flush(),\n close: async () => {\n onClose?.();\n stopCache();\n listeners.clear();\n await cache.close();\n },\n };\n}\n","import {\n openRecords,\n openRecordsSync,\n type OwnedRecordCache,\n type StorageAdapter,\n type SyncStorageAdapter,\n} from '@weasel-js/storage';\nimport { type PrefsMigration, runPrefsMigrations, watchPrefsVersion } from './migrate';\nimport type { PrefValidator } from './repair';\nimport type { PrefGroup } from './schema';\nimport { createPrefsStore, type PrefsStore } from './store';\n\n/** Options for `openPrefs` and `openPrefsSync`. */\nexport interface PrefsOptions {\n storage: StorageAdapter;\n /** Prepended to every record's key: `'myapp.prefs.'`. */\n prefix: string;\n /** `migrations[i]` takes stored records from version `i` to `i + 1`. The\n * current version is `migrations.length`. */\n migrations?: readonly PrefsMigration[];\n /** Validators for app-defined kinds, keyed by `kind`. One given for a\n * built-in kind replaces that kind's own rule. */\n validators?: Readonly<Record<string, PrefValidator>>;\n}\n\n/** Load every stored value for `schema`, migrate it, and return the store. */\nexport async function openPrefs<S extends PrefGroup>(\n schema: S,\n options: PrefsOptions,\n): Promise<PrefsStore<S>> {\n const cache = await openRecords({ storage: options.storage, prefix: options.prefix });\n const stop = watch(cache, options);\n if (runPrefsMigrations(cache, options.migrations ?? [])) await cache.flush();\n return createPrefsStore(schema, cache, options.validators, stop);\n}\n\n/** `openPrefs` for an adapter that reads synchronously: the store is ready\n * on return, so values can be read before anything renders. */\nexport function openPrefsSync<S extends PrefGroup>(\n schema: S,\n options: PrefsOptions & { storage: SyncStorageAdapter },\n): PrefsStore<S> {\n const cache = openRecordsSync({ storage: options.storage, prefix: options.prefix });\n const stop = watch(cache, options);\n if (runPrefsMigrations(cache, options.migrations ?? [])) void cache.flush();\n return createPrefsStore(schema, cache, options.validators, stop);\n}\n\n/** Attached before migrations run, so a peer's version bump during the open's\n * own flush is heard. */\nconst watch = (cache: OwnedRecordCache, options: PrefsOptions): (() => void) | undefined =>\n cache.writable ? watchPrefsVersion(cache, (options.migrations ?? []).length) : undefined;\n","// The preferences schema: groups of typed leaves. Tools declare theirs as a\n// `PrefGroup`; apps compose them into one registry, which `PrefsForm` renders\n// and `openPrefs` stores.\n\nimport { formatUnit, unitScale } from '@weasel-js/quantity';\nimport type { Display, InfinityText, Unit, UnitEntry, UnitScale, UnitSystem } from '@weasel-js/quantity';\n\n/** The value types a built-in pref leaf can hold. */\nexport type PrefKind =\n | 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object' | 'field';\n\n/**\n * Leaves that share one row in a compact property UI (weasel-ui\n * `SelectionPanel`, labkit's `ControlPanel`), declared on the first of them.\n * Purely presentational.\n */\nexport interface PrefPair {\n /** The other leaves on the row, by the full path their values are read and\n * written at (`'pose.y'`, `'camera.type'`), in order. Each must follow the\n * one before it among its siblings. */\n with: string | readonly string[];\n /** What the row reads. Default: the declaring leaf's `name`. */\n label?: string;\n}\n\n/** The fields every leaf pref shares, keyed by its `kind` and typed by its stored value. */\nexport interface PrefBase<K extends string, Value> {\n kind: K;\n /** Human-readable label. */\n name: string;\n /** Longer help text — shown in tooltips / a settings pane. */\n description: string;\n /** Fallback when nothing is persisted. */\n default: Value;\n /** Hide from a host app's settings UI by default. */\n hidden?: boolean;\n /** Render full-width with no label row in schema-driven settings UIs\n * (weasel-ui `PrefsForm` honors this for leaves whose control brings\n * its own chrome). */\n block?: boolean;\n /** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it\n * against `ICON_PATHS`). A plain string because this package ships no\n * icon set and cannot depend on one. Read where a leaf's `name` has nowhere to go — a\n * `pair`ed row is labeled by the pair, so its fields have only the glyph\n * to tell them apart. */\n icon?: string;\n /** Puts this leaf and the ones it names on one row. */\n pair?: PrefPair;\n /** Shorter forms of `name`, longest first. A surface short of room for\n * `name` — a strip of controls on one line, a segment in a `pair`ed row —\n * shows the longest of them that fits. `name` stays the accessible name, so\n * these abbreviate without costing anything. */\n short?: readonly string[];\n}\n\n/** How a schema-driven UI should present a number pref. */\nexport type PrefNumberControl = 'input' | 'slider';\n/** How a schema-driven UI should present a boolean pref. */\nexport type PrefBooleanControl = 'checkbox' | 'switch' | 'toggle';\n/** How a schema-driven UI should present a string pref. */\nexport type PrefStringControl = 'input' | 'textarea';\n/** How a schema-driven UI should present an enum pref. */\nexport type PrefEnumControl = 'select' | 'radio' | 'toggle';\n\n/** Display-unit conversion for number leaves whose stored value uses a\n * canonical unit the user shouldn't see (e.g. radians stored, degrees\n * shown). The stored value stays canonical; UIs convert at the edge. */\nexport interface PrefNumberUnit {\n toDisplay: (stored: number) => number;\n fromDisplay: (display: number) => number;\n /** Shown after the input, e.g. `'°'`. */\n suffix?: string;\n /** Suffixes a person may type, each mapped to the scale that turns a\n * number in that unit into a display number: `{ mm: 0.1, cm: 1 }` for a\n * field showing centimeters. A unit that disagrees with the display unit\n * about zero carries an `offset` as well. */\n accepts?: Readonly<Record<string, UnitEntry>>;\n /** The stored value as display text, suffix included. */\n format?: (stored: number) => string;\n}\n\n/**\n * A display unit built from a {@link UnitSystem}: values are stored in the\n * system's base and shown in `display`, rounded to `precision` places when\n * given, and every unit in the system is accepted as typed text. `suffix`\n * defaults to the unit's name and is accepted too.\n */\nexport function prefUnit(\n system: UnitSystem,\n display: Unit,\n opts?: { precision?: number; suffix?: string },\n): PrefNumberUnit {\n let self: Required<UnitScale>;\n try {\n self = unitScale(system, display);\n } catch (e) {\n throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);\n }\n const scale = opts?.precision === undefined ? undefined : 10 ** opts.precision;\n const suffix = opts?.suffix ?? display;\n const accepts: Record<string, UnitEntry> = { [suffix]: 1 };\n for (const name of Object.keys(system.units)) {\n const other = unitScale(system, name);\n // A number typed in `name` reaches display units through base:\n // `(n * factor + offset - self.offset) / self.factor`.\n const factor = other.factor / self.factor;\n const offset = (other.offset - self.offset) / self.factor;\n accepts[name] = offset === 0 ? factor : { factor, offset };\n }\n const toDisplay = (stored: number) => {\n const shown = (stored - self.offset) / self.factor;\n return scale === undefined ? shown : Math.round(shown * scale) / scale;\n };\n return {\n toDisplay,\n fromDisplay: (shown) => shown * self.factor + self.offset,\n suffix,\n accepts,\n format: (stored) =>\n `${formatUnit(stored, display, system, {\n precision: opts?.precision ?? 2,\n suffix: false,\n })}${suffix}`,\n };\n}\n\n/** A numeric pref, optionally bounded and stepped, and optionally stored in a\n * different unit from the one shown. */\nexport interface PrefNumber extends PrefBase<'number', number> {\n min?: number;\n max?: number;\n step?: number;\n control?: PrefNumberControl;\n /** How the value shows, speaks and reads back when typed — `compact()`\n * reads `2.00M`. Presentation only: the stored value stays a number. */\n display?: Display;\n unit?: PrefNumberUnit;\n /** Which end of a slider stands for infinity: the value there is ±Infinity. */\n endless?: 'min' | 'max' | 'both';\n /** The word infinity shows as — `'never'`, `'uncapped'`. Default `∞`. */\n infinity?: InfinityText;\n}\n/**\n * Stored-value bridge for a boolean leaf whose field is not a boolean — the\n * flag counterpart of {@link PrefEnumEncoding}. `TextStyle.fontStyle` is\n * the case: it stores `'italic'`, and the control is an Italic toggle.\n */\nexport interface PrefBooleanEncoding {\n /** Whether `stored` reads as on. */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => boolean;\n /** What to store for `on`. `undefined` removes the field. */\n write: (on: boolean, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** An on/off pref. */\nexport interface PrefBoolean extends PrefBase<'boolean', boolean> {\n control?: PrefBooleanControl;\n encoding?: PrefBooleanEncoding;\n}\n/** A free-text pref. */\nexport interface PrefString extends PrefBase<'string', string> {\n control?: PrefStringControl;\n}\n/**\n * Stored-value bridge for an enum leaf whose value is not the option string —\n * the counterpart of {@link PrefNumberUnit}, which does the same for a\n * number stored in a canonical unit.\n *\n * A dash array is the case that needs it: `Stroke.dash` stores lengths, and\n * the thing a person chooses is a style. The presets scale by the stroke's\n * width, so both directions are given the object's other fields — a style is\n * meaningless without the width it is a multiple of.\n */\nexport interface PrefEnumEncoding<T extends string = string> {\n /**\n * The option `stored` reads as, or `undefined` for none — which a UI shows\n * the way it shows a mixed selection, by selecting nothing.\n *\n * `siblings` is the object the leaf is a field of, or `undefined` when the\n * node does not hold that object (and for a top-level leaf, which has none).\n */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => T | undefined;\n /** What to store for `option`. `undefined` removes the field. */\n write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** A pref with a fixed set of labeled choices. `default` is `undefined` only\n * for a {@link PrefEnum.clearable} leaf, whose absence is a value. */\nexport interface PrefEnum<T extends string = string>\n extends PrefBase<'enum', T | undefined> {\n /**\n * The field may hold none of the options, and that absence is a state of\n * its own rather than a missing value — a script that is neither super nor\n * sub. A toggle control then lets the chosen segment be clicked off, which\n * removes the field.\n */\n clearable?: boolean;\n /** `short` holds shorter forms of `label`, longest first, for a segmented\n * control too narrow for the full one — down to a capital or two. `icon`\n * names a glyph in the host UI's set (weasel-ui resolves it against\n * `ICON_PATHS`), drawn in place of any text form where it resolves. It is\n * a plain string because this package ships no icon set and cannot\n * depend on one. The full `label` stays the accessible name, so neither the abbreviation nor the glyph becomes the only thing naming\n * the option.\n *\n * `disabled` marks an option a control reports but cannot author — the\n * value a stored form reads as when it matches nothing offered. Dropping it\n * from the list instead would leave the control selecting nothing and\n * claiming the field is unset. */\n options: readonly {\n value: T;\n label: string;\n short?: readonly string[];\n icon?: string;\n disabled?: boolean;\n }[];\n control?: PrefEnumControl;\n encoding?: PrefEnumEncoding<T>;\n}\n\n/** A single color, stored as a hex string. For a value that may also be a\n * gradient or a pattern, use {@link PrefPaint} instead. */\nexport interface PrefColor extends PrefBase<'color', string> {\n /** Value is `#rrggbb`, or `#rrggbbaa` when `alpha` is set (UIs then\n * offer an opacity control). */\n alpha?: boolean;\n}\n\n/**\n * Open leaf: any node with a `kind` outside the built-ins. Schema-driven\n * UIs (weasel-ui `PrefsForm` / `SelectionPanel`) dispatch it to an\n * app-supplied renderer. Deliberately NOT index-signatured so concrete\n * app interfaces stay assignable. Mirrors weasel-ui's `PrefCustom`.\n */\nexport type PrefCustom = PrefBase<string, unknown>;\n\n/**\n * A whole `FillStyle`, not a color inside one. Use it wherever the value is\n * the tagged paint union — a solid color, a pattern, a gradient — rather\n * than a hex string.\n *\n * Addressing `…fill.color` instead reads `undefined` off a gradient (so the\n * control shows its default and claims the text is black) and writes a\n * hybrid `{ fill: 'gradient', stops, color }` that the renderer's structural\n * `'color' in paint` checks then paint flat solid. The union has to be\n * edited as a union.\n */\nexport interface PrefPaint extends PrefBase<'paint', unknown> {\n /** Offer an opacity control alongside the color. */\n alpha?: boolean;\n}\n\n/**\n * A leaf whose value is one object, with its own fields hanging off it.\n *\n * A compound value — a stroke, a shadow, a pattern spec — could be described\n * as several sibling leaves addressing into it (`data.stroke.width`,\n * `data.stroke.cap`). It shouldn't be: each control would then write one field\n * of a value it can only half see, and writing into something that is not an\n * object yet corrupts it. Here the fields are `children` of one leaf, and\n * every edit commits the parent object whole.\n *\n * `children` paths are relative to the object. They are ordinary leaves, so a\n * field that is itself a union (a stroke's `paint`) declares the kind that\n * edits that union. A child may also be a {@link PrefGroup}, which\n * organises the fields under a heading without contributing to the path —\n * the same rule group keys follow at the top level. A `TextStyle` needs it:\n * its character and paragraph fields belong to one value but read as two\n * lists.\n */\nexport interface PrefObject extends PrefBase<'object', unknown> {\n children: Record<string, PrefLeaf | PrefGroup>;\n /**\n * Lift a non-object value into the object form, for a consumer field that\n * may also be held as a scalar. Called before a child edit is applied;\n * without it a scalar-valued leaf shows its children empty and refuses the\n * edit.\n */\n fromScalar?: (value: unknown) => Record<string, unknown>;\n}\n\n/**\n * A reference to another field of the same schema, held as the full path its\n * value is read and written at (`'camera.type'`) — the currency fields refer\n * to each other in. A surface offers the fields it draws as the choices.\n */\nexport interface PrefField extends PrefBase<'field', string> {\n /** Only fields of these kinds may be named. Default: any leaf. */\n kinds?: readonly string[];\n}\n\n/** One built-in pref leaf. `PrefLeaf` widens this to include\n * app-defined kinds. */\nexport type BuiltinPref =\n | PrefNumber\n | PrefBoolean\n | PrefString\n | PrefEnum\n | PrefColor\n | PrefPaint\n | PrefObject\n | PrefField;\n\n// Compile-time tie: every built-in leaf kind must appear in PrefKind\n// and vice versa (PrefBase's K is open for PrefCustom's sake, so\n// the union no longer enforces it).\ntype _BuiltinKindsExact = [BuiltinPref['kind']] extends [PrefKind]\n ? [PrefKind] extends [BuiltinPref['kind']] ? true : never\n : never;\nconst _builtinKindsExact: _BuiltinKindsExact = true;\nvoid _builtinKindsExact;\n\n/**\n * The built-in kinds, as a table. A kind added to {@link PrefKind} is a\n * compile error here, and from here it is one in every renderer's `never`\n * guard — the only thing standing between a new kind and rendering as\n * nothing in four places at once.\n */\nexport const PREF_KINDS: Record<PrefKind, true> = {\n number: true,\n boolean: true,\n string: true,\n enum: true,\n color: true,\n paint: true,\n object: true,\n field: true,\n};\n\n/** Which row each pairing among `leaves` puts a path on: a `key` the row's\n * members share (the declaring leaf's path) and the `label` it reads. A\n * path no `pair` names is absent. `leaves` are given by the path each\n * surface reads and writes them at, so references resolve in its terms. */\nexport function pairRowsOf(\n leaves: Iterable<readonly [path: string, leaf: PrefLeaf]>,\n): Map<string, { key: string; label: string }> {\n const rows = new Map<string, { key: string; label: string }>();\n for (const [path, leaf] of leaves) {\n if (!leaf.pair || rows.has(path)) continue;\n const row = { key: path, label: leaf.pair.label ?? leaf.name };\n rows.set(path, row);\n const partners = typeof leaf.pair.with === 'string' ? [leaf.pair.with] : leaf.pair.with;\n for (const partner of partners) if (!rows.has(partner)) rows.set(partner, row);\n }\n return rows;\n}\n\n/**\n * Narrows a leaf to the built-in union, so a renderer's switch discriminates\n * on {@link PrefKind} instead of the open `string` that\n * {@link PrefCustom} widens `kind` to. An app-defined kind answers false\n * and belongs to the renderer's custom-renderer path.\n */\nexport function isBuiltinPref(leaf: PrefLeaf): leaf is BuiltinPref {\n return Object.hasOwn(PREF_KINDS, leaf.kind);\n}\n\n/** Built-in or app-defined leaf. */\nexport type PrefLeaf = BuiltinPref | PrefCustom;\n\n/** Nestable group: branch nodes a tool can use to organize its prefs. */\nexport interface PrefGroup {\n /** Heading for the group's rows. **Empty means no heading** — for a group\n * that exists to organise, not to name: one whose children are themselves\n * groups carrying the labels a reader needs. Give it a name whenever the\n * name is the referent (a `Border` group over `Top` / `Right` / `Bottom`\n * reads as nothing without it). */\n name: string;\n description?: string;\n children: Record<string, PrefLeaf | PrefGroup>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/alias.ts","../src/helpers.ts","../src/object.ts","../src/union.ts","../src/type.ts","../src/groups.ts","../src/stamp.ts","../src/migrate.ts","../src/repair.ts","../src/store.ts","../src/open.ts","../src/kinds.ts","../src/schema.ts"],"names":["isVersion"],"mappings":"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","file":"index.js","sourcesContent":["import type { PrefBase, PrefLeaf } from './schema';\n\n/**\n * A second place for another leaf: its row draws that leaf's control and\n * reads and writes that leaf's value, so one setting can sit on two pages.\n * It holds no value of its own. A store neither reads nor writes one, and\n * its path is not a {@link PrefPath}.\n *\n * `name` and `description` left empty are the target's.\n */\nexport interface PrefAlias extends PrefBase<'alias', undefined> {\n /** The leaf shown here, by the full path its value is read and written at (`'view.grid'`). */\n of: string;\n}\n\n/**\n * The leaf an alias stands for and the path its value lives at, following an\n * alias of an alias to its end. `undefined` when a path along the way names\n * no leaf, or the aliases lead back to one already passed.\n */\nexport function prefAliasTarget(\n alias: PrefAlias,\n leafAt: (path: string) => PrefLeaf | undefined,\n): { path: string; leaf: PrefLeaf } | undefined {\n const passed = new Set<string>();\n let path = alias.of;\n for (;;) {\n if (passed.has(path)) return undefined;\n passed.add(path);\n const leaf = leafAt(path);\n if (leaf === undefined) return undefined;\n if (leaf.kind !== 'alias') return { path, leaf };\n path = (leaf as PrefAlias).of;\n }\n}\n\n/** A leaf drawn through an alias: the target, under the alias's own name and description where it gives them. */\nexport function prefAliasedLeaf(alias: PrefAlias, target: PrefLeaf): PrefLeaf {\n return {\n ...target,\n name: alias.name === '' ? target.name : alias.name,\n description: alias.description === '' ? target.description : alias.description,\n };\n}\n","import { prefAliasedLeaf, prefAliasTarget, type PrefAlias } from './alias';\nimport type { PrefGroup, PrefSection } from './groups';\nimport type { PrefLeaf, PrefNumber, PrefObject } from './schema';\n\n/**\n * A number leaf's bounds in the unit it is displayed in.\n *\n * Only what the leaf declares converts: an omitted bound has no stored\n * counterpart to put through the conversion, and its fallback — 0..100 for a\n * slider's track, a step of 1 — is a display-space number already. `min` and\n * `max` are points, so they convert the way the value does; `step` is a\n * distance, and a unit with an offset maps zero somewhere else, so converting\n * it as a point would scale it wrong. A decreasing conversion swaps which end\n * is the lower one.\n */\nexport function prefDisplayBounds(\n p: PrefNumber,\n): { min?: number; max?: number; step: number } {\n if (!p.unit) return { min: p.min, max: p.max, step: p.step ?? 1 };\n const { toDisplay } = p.unit;\n const lo = p.min === undefined ? undefined : toDisplay(p.min);\n const hi = p.max === undefined ? undefined : toDisplay(p.max);\n const flipped = lo !== undefined && hi !== undefined && lo > hi;\n const step = p.step === undefined\n ? 1\n : Math.abs(toDisplay(p.step) - toDisplay(0)) || p.step;\n return { min: flipped ? hi : lo, max: flipped ? lo : hi, step };\n}\n\n/** Distinguishes a leaf from a group or a section while walking a schema tree. */\nexport function isPrefLeaf(node: PrefLeaf | PrefGroup | PrefSection): node is PrefLeaf {\n return 'kind' in node;\n}\n\nconst VALUELESS: ReadonlySet<string> = new Set(['action', 'alias', 'label', 'separator']);\n\n/** Whether a leaf has a value to store: an `action` is a button and holds none, an `alias` shows another leaf's,\n * and a `label` and a `separator` are text and a rule. */\nexport function prefHoldsValue(leaf: PrefLeaf): boolean {\n return !VALUELESS.has(leaf.kind);\n}\n\n/** Distinguishes a section, whose key adds nothing to a path, from a group, whose key is a segment. */\nexport function isPrefSection(node: PrefLeaf | PrefGroup | PrefSection): node is PrefSection {\n return !isPrefLeaf(node) && 'members' in node;\n}\n\n/**\n * Every leaf under a section's `members` or an object leaf's `children`, in\n * schema order, by its own key: the sections between contribute nothing.\n */\nexport function prefSectionLeaves(members: PrefSection['members']): [key: string, leaf: PrefLeaf][] {\n return Object.entries(members).flatMap(([key, child]): [string, PrefLeaf][] =>\n isPrefLeaf(child) ? [[key, child]] : prefSectionLeaves(child.members),\n );\n}\n\n/**\n * The leaf whose value lives at `path`, as the schema's own shape builds\n * paths: a segment per key under a {@link PrefGroup}, the leaf's own key\n * under a {@link PrefSection}. `undefined` for a path that names a group, a\n * field inside an `object` leaf, or nothing.\n */\nexport function prefLeafAt(schema: PrefGroup | PrefSection, path: string): PrefLeaf | undefined {\n if (isPrefSection(schema)) return prefSectionLeaves(schema.members).find(([key]) => key === path)?.[1];\n let node: PrefLeaf | PrefGroup = schema;\n for (const seg of path.split('.')) {\n if (isPrefLeaf(node) || !Object.hasOwn(node.children, seg)) return undefined;\n node = node.children[seg]!;\n }\n return isPrefLeaf(node) ? node : undefined;\n}\n\n/** Get the value at a dotted path inside a nested value tree. Returns\n * `undefined` when a segment is missing or hits a non-object. */\nexport function prefValueAtPath(values: unknown, path: string): unknown {\n let cur: unknown = values;\n for (const seg of path.split('.')) {\n if (cur == null || typeof cur !== 'object' || !Object.hasOwn(cur, seg)) return undefined;\n cur = (cur as Record<string, unknown>)[seg];\n }\n return cur;\n}\n\n/** An object leaf's fields without the `hidden` ones, and without the sections that leaves empty (unless `keepEmpty`). */\nfunction visibleFields(fields: PrefObject['children'], keepEmpty: boolean): PrefObject['children'] {\n const out: PrefObject['children'] = {};\n for (const [key, child] of Object.entries(fields)) {\n if (isPrefLeaf(child)) {\n const kept = visiblePrefSubtree(child, false, keepEmpty);\n if (kept) out[key] = kept;\n continue;\n }\n const members = visibleFields(child.members, keepEmpty);\n if (Object.keys(members).length > 0 || keepEmpty) out[key] = { ...child, members };\n }\n return out;\n}\n\n/**\n * Recursively drop `hidden` leaves (unless `showHidden`), an object leaf's\n * hidden fields among them, pruning groups\n * that end up empty (unless `keepEmpty`). Returns null when the entire\n * subtree is pruned.\n */\nexport function visiblePrefSubtree<T extends PrefLeaf | PrefGroup>(\n node: T,\n showHidden: boolean,\n keepEmpty = false,\n): T | null {\n if (isPrefLeaf(node)) {\n if (node.hidden && !showHidden) return null;\n if (showHidden || node.kind !== 'object') return node;\n return { ...node, children: visibleFields((node as PrefObject).children, keepEmpty) };\n }\n const group = node as PrefGroup;\n const children: Record<string, PrefLeaf | PrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = visiblePrefSubtree(child, showHidden, keepEmpty);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0 && !keepEmpty) return null;\n return { ...node, children };\n}\n\n/** The record holding the schema version the stored values were written at.\n * Reserved: no top-level schema key may take its name. */\nexport const VERSION_RECORD = '$version';\n\n/** Every leaf under `schema`, by dotted path, in schema order. A group's key\n * is a segment; {@link prefSectionLeaves} is the walk for a section. */\nexport function prefLeaves(schema: PrefGroup): Map<string, PrefLeaf> {\n const out = new Map<string, PrefLeaf>();\n const walk = (group: PrefGroup, prefix: string): void => {\n for (const [key, child] of Object.entries(group.children)) {\n if (key.includes('.')) {\n throw new Error(`[prefs] schema key \"${key}\" contains \".\"; group keys are path segments`);\n }\n if (prefix === '' && key === VERSION_RECORD) {\n throw new Error(`[prefs] schema key \"${VERSION_RECORD}\" is reserved`);\n }\n const path = prefix === '' ? key : `${prefix}.${key}`;\n if (isPrefLeaf(child)) out.set(path, child);\n else walk(child, path);\n }\n };\n walk(schema, '');\n return out;\n}\n\n/** Set `key` on `tree` itself. Plain assignment to `__proto__` replaces the\n * tree's prototype instead, and a schema key or a record name may be one. */\nexport function setOwnPrefValue(tree: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(tree, key, { value, writable: true, enumerable: true, configurable: true });\n}\n\n/** Set `value` at the dotted `path` in `root` itself, creating missing branches. */\nexport function assignPrefValueAtPath(root: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let cursor = root;\n for (const part of parts.slice(0, -1)) {\n if (!Object.hasOwn(cursor, part) || cursor[part] == null) setOwnPrefValue(cursor, part, {});\n cursor = cursor[part] as Record<string, unknown>;\n }\n setOwnPrefValue(cursor, parts[parts.length - 1]!, value);\n}\n\n/** Each of `schema`'s leaves that `tree` holds a value for, as a path and\n * that value — the inverse of building a tree from per-leaf records. */\nexport function flattenPrefValues(schema: PrefGroup, tree: unknown): [string, unknown][] {\n const out: [string, unknown][] = [];\n for (const path of prefLeaves(schema).keys()) {\n const value = prefValueAtPath(tree, path);\n if (value !== undefined) out.push([path, value]);\n }\n return out;\n}\n\n/** Whether one leaf answers to a filter query, by name, description or path. */\nfunction prefLeafMatches(pref: PrefLeaf, path: string, query: string): boolean {\n if (pref.name.toLowerCase().includes(query)) return true;\n if (pref.description?.toLowerCase().includes(query)) return true;\n return path.toLowerCase().includes(query);\n}\n\n/**\n * Drop every leaf that does not answer to `query`, pruning groups left empty.\n * A group whose own name matches keeps all of its leaves — a reader who typed\n * the group's name is asking for the group, not for leaves repeating it.\n *\n * An empty or whitespace query matches everything, so a cleared field restores\n * the tree rather than emptying it.\n *\n * An alias answers as the row it draws: its target's name and description\n * where it gives none. `leafAt` finds that target, and defaults to looking in\n * `node`; pass one over the whole schema when `node` is a part of it.\n */\nexport function filterPrefSubtree<T extends PrefLeaf | PrefGroup>(\n node: T,\n query: string,\n path = '',\n leafAt?: (path: string) => PrefLeaf | undefined,\n): T | null {\n const q = query.trim().toLowerCase();\n if (q === '') return node;\n const find = leafAt ?? ((p: string) => (isPrefLeaf(node) ? undefined : prefLeafAt(node as PrefGroup, p)));\n if (isPrefLeaf(node)) {\n const target = node.kind === 'alias' ? prefAliasTarget(node as PrefAlias, find) : undefined;\n const drawn = target ? prefAliasedLeaf(node as PrefAlias, target.leaf) : node;\n return prefLeafMatches(drawn, path, q) ? node : null;\n }\n const group = node as PrefGroup;\n if (group.name.toLowerCase().includes(q)) return node;\n const children: Record<string, PrefLeaf | PrefGroup> = {};\n for (const [key, child] of Object.entries(group.children)) {\n const kept = filterPrefSubtree(child, q, path === '' ? key : `${path}.${key}`, find);\n if (kept) children[key] = kept;\n }\n if (Object.keys(children).length === 0) return null;\n return { ...node, children };\n}\n","import type { PrefObject } from './schema';\n\nconst isObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null;\n\n/**\n * The object a write to one field of an `object` leaf starts from: `held` itself where it is one. Where it is\n * not, the write has to make a whole object, so it starts from the scalar lifted by the leaf's `fromScalar`, else\n * from the leaf's `default`: one field on its own is a stroke with a width and no paint.\n */\nexport function prefObjectBase(pref: PrefObject, held: unknown): Record<string, unknown> {\n if (isObject(held)) return held;\n return pref.fromScalar?.(held) ?? (isObject(pref.default) ? pref.default : {});\n}\n\n/** The object an `object` leaf holds after one of its fields is set: {@link prefObjectBase} with `key` at\n * `value`, or without the key for `undefined`. */\nexport function prefObjectWithField(pref: PrefObject, held: unknown, key: string, value: unknown): Record<string, unknown> {\n const base = prefObjectBase(pref, held);\n if (value !== undefined) return { ...base, [key]: value };\n const { [key]: _dropped, ...rest } = base;\n return rest;\n}\n","import type { PrefBase, PrefObject } from './schema';\n\n/**\n * A leaf whose value is one of several object shapes, told apart by the\n * string its `tag` field holds: `{ type: 'linear', angle: 90 }` or\n * `{ type: 'radial', radius: 1 }` under `tag: 'type'`.\n *\n * Each variant is an `object` leaf keyed by its tag value. Its `children`\n * are the fields beside the tag, its `name` is what a person chooses, and\n * its `default` (without the tag) is what the value becomes when they choose\n * it. A stored value whose tag names no variant reads as the leaf's default.\n */\nexport interface PrefUnion extends PrefBase<'union', unknown> {\n tag: string;\n variants: Record<string, PrefObject>;\n}\n\n/** The variant `value` is, or `undefined` when its tag names none. */\nexport function prefVariantOf(leaf: PrefUnion, value: unknown): [key: string, variant: PrefObject] | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const key = (value as Record<string, unknown>)[leaf.tag];\n if (typeof key !== 'string' || !Object.hasOwn(leaf.variants, key)) return undefined;\n return [key, leaf.variants[key]!];\n}\n\n/** The value a union takes on switching to the variant at `key`: that variant's default, tagged. */\nexport function prefVariantDefault(leaf: PrefUnion, key: string): Record<string, unknown> {\n const held = leaf.variants[key]?.default;\n const fields = held !== null && typeof held === 'object' ? (held as Record<string, unknown>) : {};\n return { ...fields, [leaf.tag]: key };\n}\n","import type { PrefLeaf } from './schema';\n\n/**\n * `leaf` as a named type: the same leaf carrying `name` in its `type` field.\n * Declared once beside the code that reads its value and used wherever a\n * schema wants one, spread with what that place sets for itself\n * (`{ ...GradientStop, name: 'First stop' }`), or as a list's or a map's\n * `item`. `name` is the identifier the type is exported under, which a schema\n * editor prints in place of the leaf's literal.\n */\nexport function prefType<L extends PrefLeaf>(name: string, leaf: L): L & { type: string } {\n return { ...leaf, type: name };\n}\n","// The two branch nodes of a schema. They differ in whether a key is part of\n// the path a leaf's value lives at, and each holds its members under its own\n// property, so a schema of one kind is neither assignable to nor walkable as\n// the other.\n\nimport type { PrefLeaf } from './schema';\n\n/**\n * How a {@link PrefGroup} is drawn: `page` gets an entry in a form's rail and\n * a pane of its own; `tab` shares a tab strip with the `tab` groups beside it;\n * `panel` is a bordered, titled box; `section` is a heading over its rows;\n * `fragment` draws nothing of its own, so its rows sit among its neighbors'\n * as though they were written there. A fragment exists to hold things\n * together: one key for their values to nest under, one node to move.\n */\nexport type PrefGroupAs = 'page' | 'tab' | 'panel' | 'section' | 'fragment' | 'bar';\n\n/** How a {@link PrefSection} is drawn. */\nexport type PrefSectionAs = Exclude<PrefGroupAs, 'page'>;\n\n/**\n * A group whose key is a path segment: `view` > `gridDensity` is the leaf at\n * `view.gridDensity`, and its value nests the same way. The shape of a\n * preferences schema — what `openPrefs` stores, `PrefsForm` renders, and a\n * tool declares its options as. A key holds no `.`.\n */\nexport interface PrefGroup {\n /** Heading for the group's rows. **Empty means no heading** — for a group\n * that exists to organize, not to name: one whose children are themselves\n * groups carrying the labels a reader needs. Give it a name whenever the\n * name is the referent (a `Border` group over `Top` / `Right` / `Bottom`\n * reads as nothing without it). */\n name: string;\n description?: string;\n /** How the group is drawn. Unset, its depth decides: a top-level group is a\n * `page`, and one inside another is a `section`. */\n as?: PrefGroupAs;\n children: Record<string, PrefLeaf | PrefGroup>;\n}\n\n/**\n * A heading over leaves that adds nothing to their paths: each member is\n * addressed by its own key alone, and the section's key only identifies the\n * section. The shape of a node's property schema, where a leaf's key is the\n * whole dotted node path (`pose.x`, `data.fill`), and of the headings inside\n * a {@link PrefObject}, where a key is relative to the object.\n */\nexport interface PrefSection {\n /** Heading for the section's rows. Empty means no heading, as for a\n * {@link PrefGroup}. */\n name: string;\n description?: string;\n /** How the section is drawn, as a {@link PrefGroup}'s `as` — without\n * `page`, since nothing that draws sections has a rail. Unset: a heading\n * over its rows. */\n as?: PrefSectionAs;\n members: Record<string, PrefLeaf | PrefSection>;\n}\n\n/** Whether a top-level group gets a page of its own, and not a place on the page of the root's own leaves. */\nexport function prefGroupIsPage(group: PrefGroup): boolean {\n return group.as === undefined || group.as === 'page';\n}\n","/**\n * How a pref is stored: its value, stamped with the schema version it was\n * written at. The stamp is what lets a record be migrated from its own\n * version, whatever the store's version record says by the time it is read.\n */\nexport interface StampedRecord {\n /** The schema version `value` is in the shape of. */\n $at: number;\n value: unknown;\n}\n\nconst isVersion = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v >= 0;\n\nexport function stampRecord(value: unknown, at: number): StampedRecord {\n return { $at: at, value };\n}\n\nexport function isStampedRecord(record: unknown): record is StampedRecord {\n if (record === null || typeof record !== 'object') return false;\n const keys = Object.keys(record);\n return keys.length === 2 && Object.hasOwn(record, 'value') && isVersion((record as StampedRecord).$at);\n}\n\n/**\n * A stored record's value and the version it is in. One with no stamp was\n * written by a build from before records carried one, and is read as being\n * in `unstamped`, the version the store said it was at.\n */\nexport function readRecord(record: unknown, unstamped: number): { at: number; value: unknown; stamped: boolean } {\n return isStampedRecord(record)\n ? { at: record.$at, value: record.value, stamped: true }\n : { at: unstamped, value: record, stamped: false };\n}\n\n/** A stored record's value, whatever version it is in. */\nexport function recordValue(record: unknown): unknown {\n return isStampedRecord(record) ? record.value : record;\n}\n","import type { OwnedRecordCache } from '@weasel-js/storage';\nimport { VERSION_RECORD } from './helpers';\nimport { readRecord, stampRecord } from './stamp';\n\nconst isVersion = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v >= 0;\n\n/** Takes stored values from one version to the next: rename, transform or\n * delete entries in `records`, keyed by leaf path. It sees the values, not\n * the stamps they are stored under, and only those at its own version. */\nexport type PrefsMigration = (records: Map<string, unknown>) => void;\n\n/**\n * Bring `cache` up to `migrations.length`, the current version. Each record\n * is migrated from the version it is stamped with, so one already in this\n * build's shape is left alone and one an older writer left is caught up,\n * whatever the store's version record says. A migration is handed the\n * records that are at its version; every one it leaves is written back\n * stamped with the version reached, so it may replace values or mutate them\n * in place. Stops writing, and writes nothing, when the store or a record is\n * newer than this build knows or a migration throws. Returns whether it wrote.\n *\n * `stampAll` also stamps the records that needed no migration and carry no\n * stamp. An open does that; a watcher does not, since an unstamped record\n * arriving from another writer may be in a version it has yet to announce.\n */\nexport function runPrefsMigrations(\n cache: OwnedRecordCache,\n migrations: readonly PrefsMigration[],\n { stampAll = true }: { stampAll?: boolean } = {},\n): boolean {\n const target = migrations.length;\n const raw = cache.get(VERSION_RECORD);\n if (cache.has(VERSION_RECORD) && !isVersion(raw)) {\n console.warn(\n `[prefs] \"${cache.prefix}\" has an unreadable ${VERSION_RECORD} (${JSON.stringify(raw)}); opening read-only`,\n );\n cache.stopWriting();\n return false;\n }\n const stored = cache.has(VERSION_RECORD) ? (raw as number) : 0;\n const held = cache\n .entries()\n .filter(([name]) => name !== VERSION_RECORD)\n .map(([name, record]) => ({ name, ...readRecord(record, Math.min(stored, target)) }));\n const newest = Math.max(stored, ...held.map((r) => r.at));\n if (newest > target) {\n console.warn(\n `[prefs] \"${cache.prefix}\" was written at version ${newest}, newer than this build's ${target}; opening read-only`,\n );\n cache.stopWriting();\n return false;\n }\n if (!cache.writable) return false;\n\n // Where each record now stands, and the records that are behind.\n const at = new Map(held.filter((r) => r.at < target).map((r) => [r.name, r.at]));\n const records = new Map(held.filter((r) => at.has(r.name)).map((r): [string, unknown] => [r.name, structuredClone(r.value)]));\n for (let v = Math.min(target, ...at.values()); v < target; v++) {\n const due = new Map([...records].filter(([name]) => at.get(name)! <= v));\n const before = [...due.keys()];\n try {\n migrations[v]!(due);\n } catch (error) {\n console.warn(\n `[prefs] migration ${v} → ${v + 1} for \"${cache.prefix}\" threw; opening read-only on the unmigrated records`,\n error,\n );\n cache.stopWriting();\n return false;\n }\n for (const name of before) if (!due.has(name)) records.delete(name);\n for (const [name, value] of due) {\n records.set(name, value);\n at.set(name, v + 1);\n }\n }\n let wrote = false;\n for (const r of held) {\n if (at.has(r.name)) {\n if (!records.has(r.name)) cache.delete(r.name);\n wrote = true;\n } else if (stampAll && !r.stamped) {\n cache.set(r.name, stampRecord(r.value, target));\n wrote = true;\n }\n }\n for (const [name, value] of records) {\n if (value === undefined) cache.delete(name);\n else cache.set(name, stampRecord(value, target));\n }\n if (stored !== target) {\n cache.set(VERSION_RECORD, target);\n wrote = true;\n }\n return wrote;\n}\n\n/**\n * Keep `cache` at this build's version while other writers change it. A\n * version past `migrations.length`, from a newer build in another tab, stops\n * persisting: this build would otherwise keep writing the old shape. A record\n * another writer leaves is migrated from the version it is stamped with, as\n * soon as it arrives; one with no stamp, from a build that wrote none, from\n * the version record that writer leaves with it. A version record another\n * writer deleted, a cleared store, is written back. Returns the unsubscribe.\n */\nexport function watchPrefsVersion(\n cache: OwnedRecordCache,\n migrations: readonly PrefsMigration[],\n): () => void {\n const target = migrations.length;\n // Once this cache has held a version, the records it holds are this\n // build's shape, and a missing version record is a cleared store.\n let versioned = cache.has(VERSION_RECORD);\n let stopped = false;\n const migrate = (): void => {\n const cleared = versioned && !cache.has(VERSION_RECORD);\n if (cleared) cache.set(VERSION_RECORD, target);\n else if (!runPrefsMigrations(cache, migrations, { stampAll: false })) return;\n versioned = true;\n void cache.flush();\n };\n // A late first read that finds nothing reports no change to migrate on.\n void cache.whenRead().then(() => {\n if (!stopped && cache.writable) migrate();\n });\n const heard = (version: unknown): void => {\n if (!isVersion(version)) {\n console.warn(\n `[prefs] \"${cache.prefix}\" has an unreadable ${VERSION_RECORD} (${JSON.stringify(version)}) from another writer; no longer persisting`,\n );\n cache.stopWriting();\n } else if (version > target) {\n console.warn(\n `[prefs] \"${cache.prefix}\" was migrated to version ${version} by another writer; this build knows ${target}; no longer persisting`,\n );\n cache.stopWriting();\n }\n };\n // A newer version counts even where this cache kept its own write over it.\n const stopOverruled = cache.onOverruled((changes) => {\n for (const [name, value] of changes) if (name === VERSION_RECORD && value !== undefined) heard(value);\n });\n const stopChanges = cache.subscribe((changes) => {\n const remote = changes.filter((change) => change.origin === 'remote');\n for (const change of remote) {\n if (change.name === VERSION_RECORD && change.value !== undefined) heard(change.value);\n }\n if (remote.length > 0 && cache.writable) migrate();\n versioned ||= cache.has(VERSION_RECORD);\n });\n return () => {\n stopped = true;\n stopOverruled();\n stopChanges();\n };\n}\n","import { isPlainObject } from '@weasel-js/registry';\nimport { prefSectionLeaves } from './helpers';\nimport type { PrefList } from './list';\nimport type { PrefMap } from './map';\nimport { prefVariantOf, type PrefUnion } from './union';\nimport type { PrefBoolean, PrefEnum, PrefLeaf, PrefNumber, PrefObject } from './schema';\n\n/** Decides what a stored value reads as for one kind of leaf: the value to\n * read, or `undefined` for \"invalid, read the default\". */\nexport type PrefValidator = (stored: unknown, leaf: PrefLeaf) => unknown;\n\n/** What `stored` reads as for `leaf`. Never writes anything back: a schema\n * rolled back finds the original still in storage. */\nexport function repairPrefValue(\n leaf: PrefLeaf,\n stored: unknown,\n validators?: Readonly<Record<string, PrefValidator>>,\n): unknown {\n if (leaf.kind === 'number') {\n if (stored === 'Infinity') stored = Infinity;\n else if (stored === '-Infinity') stored = -Infinity;\n }\n const validate = validators?.[leaf.kind];\n if (validate) {\n try {\n const out = validate(stored, leaf);\n return out === undefined ? leaf.default : out;\n } catch {\n return leaf.default;\n }\n }\n switch (leaf.kind) {\n case 'number':\n return repairNumber(leaf as PrefNumber, stored);\n case 'boolean':\n return (leaf as PrefBoolean).encoding || typeof stored === 'boolean' ? stored : leaf.default;\n case 'string':\n case 'color':\n case 'field':\n return typeof stored === 'string' ? stored : leaf.default;\n case 'enum': {\n const e = leaf as PrefEnum;\n if (e.encoding) return stored;\n return e.options.some((o) => o.value === stored) ? stored : leaf.default;\n }\n case 'object':\n if (isPlainObject(stored)) return repairFields(leaf as PrefObject, stored as Record<string, unknown>, validators);\n return (leaf as PrefObject).fromScalar ? stored : leaf.default;\n case 'map':\n return repairMap(leaf as PrefMap, stored, validators);\n case 'union': {\n const variant = prefVariantOf(leaf as PrefUnion, stored);\n return variant ? repairFields(variant[1], stored as Record<string, unknown>, validators) : leaf.default;\n }\n case 'list':\n return repairList(leaf as PrefList, stored, validators);\n default:\n return stored;\n }\n}\n\ntype Validators = Readonly<Record<string, PrefValidator>> | undefined;\n\n/**\n * Each field the object holds reads as its own leaf would. A field it omits\n * stays omitted: absent is a state of its own (no dash, no shadow), and not\n * the field at its default. Fields no leaf describes pass through.\n */\nfunction repairFields(leaf: PrefObject, stored: Record<string, unknown>, validators: Validators): unknown {\n let out: Record<string, unknown> | undefined;\n for (const [key, field] of prefSectionLeaves(leaf.children)) {\n if (!Object.hasOwn(stored, key) || stored[key] === undefined) continue;\n const read = repairPrefValue(field, stored[key], validators);\n if (read !== stored[key]) (out ??= { ...stored })[key] = read;\n }\n return out ?? stored;\n}\n\n/** Each value reads as `item` would on its own, under the key it was stored at. */\nfunction repairMap(leaf: PrefMap, stored: unknown, validators: Validators): unknown {\n if (!isPlainObject(stored)) return leaf.default;\n const held = stored as Record<string, unknown>;\n let out: Record<string, unknown> | undefined;\n for (const [key, value] of Object.entries(held)) {\n const read = repairPrefValue(leaf.item, value, validators);\n if (read !== value) (out ??= { ...held })[key] = read;\n }\n return out ?? stored;\n}\n\n/** Each entry reads as `item` would on its own, so one bad entry costs that entry and not the list. */\nfunction repairList(\n leaf: PrefList,\n stored: unknown,\n validators?: Readonly<Record<string, PrefValidator>>,\n): unknown {\n if (!Array.isArray(stored)) return leaf.default;\n if (leaf.minItems !== undefined && stored.length < leaf.minItems) return leaf.default;\n const kept = leaf.maxItems !== undefined && stored.length > leaf.maxItems ? stored.slice(0, leaf.maxItems) : stored;\n const read = kept.map((entry) => repairPrefValue(leaf.item, entry, validators));\n return kept === stored && read.every((entry, i) => entry === stored[i]) ? stored : read;\n}\n\n\nfunction repairNumber(leaf: PrefNumber, stored: unknown): unknown {\n if (typeof stored !== 'number' || Number.isNaN(stored)) return leaf.default;\n const { endless } = leaf;\n if (stored === Infinity && (endless === 'max' || endless === 'both')) return stored;\n if (stored === -Infinity && (endless === 'min' || endless === 'both')) return stored;\n let v = stored;\n if (leaf.min !== undefined && v < leaf.min) v = leaf.min;\n if (leaf.max !== undefined && v > leaf.max) v = leaf.max;\n return Number.isFinite(v) ? v : leaf.default;\n}\n","import type { OwnedRecordCache } from '@weasel-js/storage';\nimport { recordValue, stampRecord } from './stamp';\nimport { assignPrefValueAtPath, prefHoldsValue, prefLeaves, prefSectionLeaves, setOwnPrefValue, VERSION_RECORD } from './helpers';\nimport type { PrefList } from './list';\nimport type { PrefMap } from './map';\nimport type { PrefPath, PrefValueAt } from './paths';\nimport { type PrefValidator, repairPrefValue } from './repair';\nimport type { PrefGroup } from './groups';\nimport type { PrefLeaf, PrefObject } from './schema';\nimport { prefVariantOf, type PrefUnion } from './union';\n\n/** One leaf changing, as a store subscriber hears it: the value readers now\n * see, and whether this store or another writer made the change. */\nexport interface PrefChange {\n path: string;\n value: unknown;\n origin: 'local' | 'remote';\n}\n\n/** Values for one schema, held in memory and persisted behind. */\nexport interface PrefsStore<S extends PrefGroup> {\n readonly schema: S;\n /** The leaf's value, repaired against the schema; its default when unset. */\n get<P extends PrefPath<S>>(path: P): PrefValueAt<S, P>;\n set<P extends PrefPath<S>>(path: P, value: PrefValueAt<S, P>): void;\n /** Unset every leaf at or under `path`; with no path, all. */\n reset(path?: string): void;\n /** Whether the leaf has a value of its own rather than following its default. */\n isSet(path: PrefPath<S>): boolean;\n /** Every leaf's value as a nested tree. The same object until something changes. */\n values(): Record<string, unknown>;\n /** The leaves following their default. The same set until something changes. */\n unset(): ReadonlySet<string>;\n /** Every stored record as a nested tree, unrepaired, including records no\n * leaf describes. The same object until something changes. */\n stored(): Record<string, unknown>;\n /** `changes` is empty when only records no leaf describes changed. */\n subscribe(listener: (changes: PrefChange[]) => void): () => void;\n /** False while the store cannot persist: storage has not been read yet, or\n * was written by a newer schema. Changes still apply for this session, and\n * ones made before a late read lands are persisted when it does. */\n readonly writable: boolean;\n /** Try again now to read storage that could not be read at open, ahead of\n * the store's own retries. Resolves whether storage has been read. */\n read(): Promise<boolean>;\n /** Resolves once storage has been read: at once for a store that opened\n * with its values, and when a later read lands for one that could not. */\n whenRead(): Promise<void>;\n /** Resolves true when every queued write reached storage. */\n flush(): Promise<boolean>;\n close(): Promise<void>;\n}\n\ninterface Snapshot {\n byPath: Map<string, unknown>;\n tree: Record<string, unknown>;\n unset: ReadonlySet<string>;\n}\n\n/** JSON storage cannot keep an infinity; `repairPrefValue` reads these back. */\nconst encodeInfinity = (leaf: PrefLeaf, value: unknown): unknown => {\n if (leaf.kind === 'number') return value === Infinity || value === -Infinity ? String(value) : value;\n if (leaf.kind === 'list' && Array.isArray(value)) {\n const { item } = leaf as PrefList;\n return value.map((entry) => encodeInfinity(item, entry));\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return value;\n const held = value as Record<string, unknown>;\n if (leaf.kind === 'map') {\n const { item } = leaf as PrefMap;\n return Object.fromEntries(Object.entries(held).map(([key, entry]) => [key, encodeInfinity(item, entry)]));\n }\n const fields = leaf.kind === 'union' ? prefVariantOf(leaf as PrefUnion, held)?.[1] : leaf;\n if (fields?.kind !== 'object') return value;\n let out: Record<string, unknown> | undefined;\n for (const [key, field] of prefSectionLeaves((fields as PrefObject).children)) {\n if (!Object.hasOwn(held, key)) continue;\n const encoded = encodeInfinity(field, held[key]);\n if (encoded !== held[key]) (out ??= { ...held })[key] = encoded;\n }\n return out ?? value;\n};\n\n/** A store over an open cache. `openPrefs` / `openPrefsSync` are the usual\n * way in; they run migrations first. */\nexport function createPrefsStore<S extends PrefGroup>(\n schema: S,\n cache: OwnedRecordCache,\n validators?: Readonly<Record<string, PrefValidator>>,\n onClose?: () => void,\n /** The schema version a value set here is in, stamped on its record. */\n version = 0,\n): PrefsStore<S> {\n const leaves = new Map([...prefLeaves(schema)].filter(([, leaf]) => prefHoldsValue(leaf)));\n let snapshot: Snapshot | null = null;\n let previous: { raw: Map<string, unknown>; byPath: Map<string, unknown> } | null = null;\n\n const build = (): Snapshot => {\n const byPath = new Map<string, unknown>();\n const raw = new Map<string, unknown>();\n const unset = new Set<string>();\n const tree: Record<string, unknown> = {};\n for (const [path, leaf] of leaves) {\n const has = cache.has(path);\n let value: unknown;\n if (!has) {\n value = leaf.default;\n unset.add(path);\n } else {\n const record = cache.get(path);\n const stored = recordValue(record);\n raw.set(path, record);\n value =\n previous?.raw.has(path) && previous.raw.get(path) === record\n ? previous.byPath.get(path)\n : repairPrefValue(leaf, stored, validators);\n }\n byPath.set(path, value);\n assignPrefValueAtPath(tree, path, value);\n }\n previous = { raw, byPath };\n return { byPath, tree, unset };\n };\n const current = (): Snapshot => (snapshot ??= build());\n\n let storedTree: Record<string, unknown> | null = null;\n const buildStored = (): Record<string, unknown> => {\n const tree: Record<string, unknown> = {};\n const branches = new WeakSet<object>([tree]);\n for (const [name, record] of cache.entries()) {\n if (name === VERSION_RECORD) continue;\n const value = recordValue(record);\n const parts = name.split('.');\n let cursor = tree;\n for (const part of parts.slice(0, -1)) {\n const next = cursor[part];\n // A record's own value is never descended into: one named `a` and\n // another `a.b` cannot both show, and the branch wins.\n if (typeof next === 'object' && next !== null && branches.has(next)) {\n cursor = next as Record<string, unknown>;\n } else {\n const branch: Record<string, unknown> = {};\n branches.add(branch);\n setOwnPrefValue(cursor, part, branch);\n cursor = branch;\n }\n }\n const last = parts[parts.length - 1]!;\n if (!branches.has(cursor[last] as object)) setOwnPrefValue(cursor, last, value);\n }\n return tree;\n };\n\n const listeners = new Set<(changes: PrefChange[]) => void>();\n const stopCache = cache.subscribe((changes) => {\n const records = changes.filter((c) => c.name !== VERSION_RECORD);\n if (records.length === 0) return;\n storedTree = null;\n const mine = records.filter((c) => leaves.has(c.name));\n if (mine.length > 0) snapshot = null;\n const now = current();\n const out = mine.map((c): PrefChange => ({ path: c.name, value: now.byPath.get(c.name), origin: c.origin }));\n for (const listener of [...listeners]) listener(out);\n });\n\n return {\n schema,\n get: (path) => current().byPath.get(path) as never,\n set: (path, value) => {\n const leaf = leaves.get(path);\n if (!leaf) {\n console.warn(`[prefs] no leaf at \"${path}\"; ignoring the write`);\n return;\n }\n const stored = encodeInfinity(leaf, value);\n // Unset is stored as nothing, which a stamp would turn into something.\n cache.set(path, stored === undefined ? undefined : stampRecord(stored, version));\n },\n reset: (path) => {\n for (const p of leaves.keys()) {\n if (path === undefined || p === path || p.startsWith(`${path}.`)) cache.delete(p);\n }\n },\n isSet: (path) => cache.has(path),\n values: () => current().tree,\n unset: () => current().unset,\n stored: () => (storedTree ??= buildStored()),\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n get writable() {\n return cache.writable;\n },\n read: () => cache.read(),\n whenRead: () => cache.whenRead(),\n flush: () => cache.flush(),\n close: async () => {\n onClose?.();\n stopCache();\n listeners.clear();\n await cache.close();\n },\n };\n}\n","import {\n openRecords,\n openRecordsSync,\n type OwnedRecordCache,\n type StorageAdapter,\n type SyncStorageAdapter,\n} from '@weasel-js/storage';\nimport { type PrefsMigration, runPrefsMigrations, watchPrefsVersion } from './migrate';\nimport type { PrefValidator } from './repair';\nimport type { PrefGroup } from './groups';\nimport { createPrefsStore, type PrefsStore } from './store';\n\n/** Options for `openPrefs` and `openPrefsSync`. */\nexport interface PrefsOptions {\n storage: StorageAdapter;\n /** Prepended to every record's key: `'myapp.prefs.'`. */\n prefix: string;\n /** `migrations[i]` takes stored records from version `i` to `i + 1`. The\n * current version is `migrations.length`. */\n migrations?: readonly PrefsMigration[];\n /** Validators for app-defined kinds, keyed by `kind`. One given for a\n * built-in kind replaces that kind's own rule. */\n validators?: Readonly<Record<string, PrefValidator>>;\n}\n\n/** Load every stored value for `schema`, migrate it, and return the store. */\nexport async function openPrefs<S extends PrefGroup>(\n schema: S,\n options: PrefsOptions,\n): Promise<PrefsStore<S>> {\n const cache = await openRecords({ storage: options.storage, prefix: options.prefix });\n const stop = watch(cache, options);\n if (runPrefsMigrations(cache, options.migrations ?? [])) await cache.flush();\n return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);\n}\n\n/** `openPrefs` for an adapter that reads synchronously: the store is ready\n * on return, so values can be read before anything renders. */\nexport function openPrefsSync<S extends PrefGroup>(\n schema: S,\n options: PrefsOptions & { storage: SyncStorageAdapter },\n): PrefsStore<S> {\n const cache = openRecordsSync({ storage: options.storage, prefix: options.prefix });\n const stop = watch(cache, options);\n if (runPrefsMigrations(cache, options.migrations ?? [])) void cache.flush();\n return createPrefsStore(schema, cache, options.validators, stop, options.migrations?.length ?? 0);\n}\n\n/** Attached before migrations run, so a peer's version bump during the open's\n * own flush is heard, and on an unread cache too, whose late read reports\n * its records' version the same way. */\nconst watch = (cache: OwnedRecordCache, options: PrefsOptions): (() => void) =>\n watchPrefsVersion(cache, options.migrations ?? []);\n","import type { PrefKind } from './schema';\n\n/** What a surface has to know about a kind before it can lay its control out. */\nexport interface PrefKindTraits {\n /** Its value is made of other leaves' values: too much for one control on a\n * line, so a bar opens it in a popover and a compact panel in a dialog. */\n compound: boolean;\n /** Its control is several controls, or a button. A row drawn as a `<label>`\n * would hand a click on its text to the first of them. */\n several: boolean;\n}\n\nconst ONE: PrefKindTraits = { compound: false, several: false };\nconst MANY: PrefKindTraits = { compound: true, several: true };\n\n/**\n * The traits of every built-in kind. A `Record` over {@link PrefKind}, so a\n * kind added to the union does not compile until it says what it is here:\n * a plain set of kind names lets a new one through to draw inline in a\n * `<label>`, on a bar's line, and with no dialog row.\n */\nexport const PREF_KIND_TRAITS: Record<PrefKind, PrefKindTraits> = {\n number: ONE,\n boolean: ONE,\n string: ONE,\n enum: ONE,\n color: ONE,\n paint: ONE,\n object: MANY,\n list: MANY,\n map: MANY,\n union: MANY,\n field: ONE,\n action: { compound: false, several: true },\n alias: ONE,\n label: ONE,\n separator: ONE,\n};\n\nconst traitsOf = (leaf: { kind: string }): PrefKindTraits =>\n (Object.hasOwn(PREF_KIND_TRAITS, leaf.kind) ? PREF_KIND_TRAITS[leaf.kind as PrefKind] : ONE);\n\n/** Whether a leaf's value is made of other leaves' values. An app-defined kind is not: its renderer is one control. */\nexport function prefIsCompound(leaf: { kind: string }): boolean {\n return traitsOf(leaf).compound;\n}\n\n/** Whether a leaf's control is several controls or a button. */\nexport function prefDrawsSeveral(leaf: { kind: string }): boolean {\n return traitsOf(leaf).several;\n}\n","// The preferences schema's typed leaves. `groups.ts` holds the branch nodes\n// that arrange them: tools declare their options as a `PrefGroup`, and apps\n// compose those into one registry, which `PrefsForm` renders and `openPrefs`\n// stores.\n\nimport { formatUnit, unitScale } from '@weasel-js/quantity';\nimport type { PrefAction } from './action';\nimport type { PrefAlias } from './alias';\nimport type { PrefSection } from './groups';\nimport type { PrefLabel, PrefSeparator } from './label';\nimport type { PrefList } from './list';\nimport type { PrefMap } from './map';\nimport type { PrefUnion } from './union';\nimport type { Display, InfinityText, Unit, UnitEntry, UnitScale, UnitSystem } from '@weasel-js/quantity';\n\n/** The value types a built-in pref leaf can hold. */\nexport type PrefKind =\n | 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object' | 'list' | 'map' | 'union' | 'field' | 'action' | 'alias' | 'label' | 'separator';\n\n/**\n * Leaves that share one row in a compact property UI (weasel-ui\n * `SelectionPanel`, labkit's `ControlPanel`), declared on the first of them.\n * Purely presentational.\n */\nexport interface PrefPair {\n /** The other leaves on the row, by the full path their values are read and\n * written at (`'pose.y'`, `'camera.type'`), in order. Each must follow the\n * one before it among its siblings. */\n with: string | readonly string[];\n /** What the row reads. Default: the declaring leaf's `name`. */\n label?: string;\n}\n\n/** The fields every leaf pref shares, keyed by its `kind` and typed by its stored value. */\nexport interface PrefBase<K extends string, Value> {\n kind: K;\n /** Human-readable label. */\n name: string;\n /** Longer help text — shown in tooltips / a settings pane. */\n description: string;\n /** Fallback when nothing is persisted. */\n default: Value;\n /** Hide from a host app's settings UI by default. */\n hidden?: boolean;\n /** Nothing held where this leaf's value is read means `default`, because\n * whoever reads the value takes it that way (`pose.rotation ?? 0`). A\n * surface over sparse settings reads every leaf so already. One over a\n * scene node, where a missing key otherwise means the node has no such\n * property, shows the default only for a leaf that says this, and still\n * writes nothing until an edit. */\n absentIsDefault?: boolean;\n /** Render full-width with no label row in schema-driven settings UIs\n * (weasel-ui `PrefsForm` honors this for leaves whose control brings\n * its own chrome). */\n block?: boolean;\n /** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it\n * against `ICON_PATHS`). A plain string because this package ships no\n * icon set and cannot depend on one. Read where a leaf's `name` has nowhere to go — a\n * `pair`ed row is labeled by the pair, so its fields have only the glyph\n * to tell them apart. */\n icon?: string;\n /** Puts this leaf and the ones it names on one row. */\n pair?: PrefPair;\n /** Shorter forms of `name`, longest first. A surface short of room for\n * `name` — a strip of controls on one line, a segment in a `pair`ed row —\n * shows the longest of them that fits. `name` stays the accessible name, so\n * these abbreviate without costing anything. */\n short?: readonly string[];\n /** Never auto. A surface that lets a leaf be left for its owner to decide\n * (weasel-ui `PrefsForm`'s `onAutoChange`, labkit's `ControlPanel`) gives\n * this one no way to. */\n manual?: boolean;\n /** Starts auto, where it would start pinned at `default`. */\n unpinned?: boolean;\n /** What the leaf reads while it is auto, where its owner computes nothing\n * for it. Unset, an auto leaf has no value. */\n autoValue?: Value;\n /** The name of the type this leaf was made from, set by `prefType`. A\n * schema editor shows such a leaf as one closed thing and prints the name\n * in place of its literal. */\n type?: string;\n}\n\n/** How a schema-driven UI should present a number pref. */\nexport type PrefNumberControl = 'input' | 'slider';\n/** How a schema-driven UI should present a boolean pref. */\nexport type PrefBooleanControl = 'checkbox' | 'switch' | 'toggle';\n/** How a schema-driven UI should present a string pref. */\nexport type PrefStringControl = 'input' | 'textarea';\n/** How a schema-driven UI should present an enum pref. */\nexport type PrefEnumControl = 'select' | 'radio' | 'toggle' | 'menu';\n\n/** Display-unit conversion for number leaves whose stored value uses a\n * canonical unit the user shouldn't see (e.g. radians stored, degrees\n * shown). The stored value stays canonical; UIs convert at the edge. */\nexport interface PrefNumberUnit {\n toDisplay: (stored: number) => number;\n fromDisplay: (display: number) => number;\n /** Shown after the input, e.g. `'°'`. */\n suffix?: string;\n /** Suffixes a person may type, each mapped to the scale that turns a\n * number in that unit into a display number: `{ mm: 0.1, cm: 1 }` for a\n * field showing centimeters. A unit that disagrees with the display unit\n * about zero carries an `offset` as well. */\n accepts?: Readonly<Record<string, UnitEntry>>;\n /** The stored value as display text, suffix included. */\n format?: (stored: number) => string;\n}\n\n/**\n * A display unit built from a {@link UnitSystem}: values are stored in the\n * system's base and shown in `display`, rounded to `precision` places when\n * given, and every unit in the system is accepted as typed text. `suffix`\n * defaults to the unit's name and is accepted too.\n */\nexport function prefUnit(\n system: UnitSystem,\n display: Unit,\n opts?: { precision?: number; suffix?: string },\n): PrefNumberUnit {\n let self: Required<UnitScale>;\n try {\n self = unitScale(system, display);\n } catch (e) {\n throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);\n }\n const scale = opts?.precision === undefined ? undefined : 10 ** opts.precision;\n const suffix = opts?.suffix ?? display;\n const accepts: Record<string, UnitEntry> = { [suffix]: 1 };\n for (const name of Object.keys(system.units)) {\n const other = unitScale(system, name);\n // A number typed in `name` reaches display units through base:\n // `(n * factor + offset - self.offset) / self.factor`.\n const factor = other.factor / self.factor;\n const offset = (other.offset - self.offset) / self.factor;\n accepts[name] = offset === 0 ? factor : { factor, offset };\n }\n const toDisplay = (stored: number) => {\n const shown = (stored - self.offset) / self.factor;\n return scale === undefined ? shown : Math.round(shown * scale) / scale;\n };\n return {\n toDisplay,\n fromDisplay: (shown) => shown * self.factor + self.offset,\n suffix,\n accepts,\n format: (stored) =>\n `${formatUnit(stored, display, system, {\n precision: opts?.precision ?? 2,\n suffix: false,\n })}${suffix}`,\n };\n}\n\n/** A numeric pref, optionally bounded and stepped, and optionally stored in a\n * different unit from the one shown. */\nexport interface PrefNumber extends PrefBase<'number', number> {\n min?: number;\n max?: number;\n step?: number;\n control?: PrefNumberControl;\n /** How the value shows, speaks and reads back when typed — `compact()`\n * reads `2.00M`. Presentation only: the stored value stays a number. */\n display?: Display;\n unit?: PrefNumberUnit;\n /** Which end of a slider gets a stop for ±Infinity, one step beyond the range. */\n endless?: 'min' | 'max' | 'both';\n /** The word infinity shows as — `'never'`, `'uncapped'`. Default `∞`. */\n infinity?: InfinityText;\n}\n/**\n * Stored-value bridge for a boolean leaf whose field is not a boolean — the\n * flag counterpart of {@link PrefEnumEncoding}. `TextStyle.fontStyle` is\n * the case: it stores `'italic'`, and the control is an Italic toggle.\n */\nexport interface PrefBooleanEncoding {\n /** Whether `stored` reads as on. */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => boolean;\n /** What to store for `on`. `undefined` removes the field. */\n write: (on: boolean, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** An on/off pref. */\nexport interface PrefBoolean extends PrefBase<'boolean', boolean> {\n control?: PrefBooleanControl;\n encoding?: PrefBooleanEncoding;\n}\n/** A free-text pref. */\nexport interface PrefString extends PrefBase<'string', string> {\n control?: PrefStringControl;\n}\n/**\n * Stored-value bridge for an enum leaf whose value is not the option string —\n * the counterpart of {@link PrefNumberUnit}, which does the same for a\n * number stored in a canonical unit.\n *\n * A dash array is the case that needs it: `Stroke.dash` stores lengths, and\n * the thing a person chooses is a style. The presets scale by the stroke's\n * width, so both directions are given the object's other fields — a style is\n * meaningless without the width it is a multiple of.\n */\nexport interface PrefEnumEncoding<T extends string = string> {\n /**\n * The option `stored` reads as, or `undefined` for none — which a UI shows\n * the way it shows a mixed selection, by selecting nothing.\n *\n * `siblings` is the object the leaf is a field of, or `undefined` when the\n * node does not hold that object (and for a top-level leaf, which has none).\n */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => T | undefined;\n /** What to store for `option`. `undefined` removes the field. */\n write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** What every enum leaf carries; {@link PrefEnum} adds `clearable`. */\nexport interface PrefEnumBase<T extends string = string>\n extends PrefBase<'enum', T | undefined> {\n /** `short` holds shorter forms of `label`, longest first, for a segmented\n * control too narrow for the full one — down to a capital or two. `icon`\n * names a glyph in the host UI's set (weasel-ui resolves it against\n * `ICON_PATHS`), drawn in place of any text form where it resolves. It is\n * a plain string because this package ships no icon set and cannot\n * depend on one. The full `label` stays the accessible name, so neither the abbreviation nor the glyph becomes the only thing naming\n * the option.\n *\n * `disabled` marks an option a control reports but cannot author — the\n * value a stored form reads as when it matches nothing offered. Dropping it\n * from the list instead would leave the control selecting nothing and\n * claiming the field is unset. */\n options: readonly {\n value: T;\n label: string;\n short?: readonly string[];\n icon?: string;\n disabled?: boolean;\n }[];\n control?: PrefEnumControl;\n encoding?: PrefEnumEncoding<T>;\n}\n\n/**\n * A pref with a fixed set of labeled choices.\n *\n * `clearable` says the field may hold none of the options, and that absence\n * is a state of its own rather than a missing value — a script that is\n * neither super nor sub. A toggle control then lets the chosen segment be\n * clicked off, which removes the field. Such a leaf's `default` is\n * `undefined`: a missing value is the only stored form of cleared, so a\n * default would bring an option back the moment the field was cleared.\n */\nexport type PrefEnum<T extends string = string> = PrefEnumBase<T> & (\n | { clearable?: false }\n | { clearable: true; default: undefined }\n);\n\n/** A single color, stored as a hex string. For a value that may also be a\n * gradient or a pattern, use {@link PrefPaint} instead. */\nexport interface PrefColor extends PrefBase<'color', string> {\n /** Value is `#rrggbb`, or `#rrggbbaa` when `alpha` is set (UIs then\n * offer an opacity control). */\n alpha?: boolean;\n}\n\n/**\n * Open leaf: any node with a `kind` outside the built-ins. Schema-driven\n * UIs (weasel-ui `PrefsForm` / `SelectionPanel`) dispatch it to an\n * app-supplied renderer. Deliberately NOT index-signatured so concrete\n * app interfaces stay assignable. Mirrors weasel-ui's `PrefCustom`.\n */\nexport type PrefCustom = PrefBase<string, unknown>;\n\n/**\n * A whole `FillStyle`, not a color inside one. Use it wherever the value is\n * the tagged paint union — a solid color, a pattern, a gradient — rather\n * than a hex string.\n *\n * Addressing `…fill.color` instead reads `undefined` off a gradient (so the\n * control shows its default and claims the text is black) and writes a\n * hybrid `{ fill: 'gradient', stops, color }` that the renderer's structural\n * `'color' in paint` checks then paint flat solid. The union has to be\n * edited as a union.\n */\nexport interface PrefPaint extends PrefBase<'paint', unknown> {\n /** Offer an opacity control alongside the color. */\n alpha?: boolean;\n}\n\n/**\n * A leaf whose value is one object, with its own fields hanging off it.\n *\n * A compound value — a stroke, a shadow, a pattern spec — could be described\n * as several sibling leaves addressing into it (`data.stroke.width`,\n * `data.stroke.cap`). It shouldn't be: each control would then write one field\n * of a value it can only half see, and writing into something that is not an\n * object yet corrupts it. Here the fields are `children` of one leaf, and\n * every edit commits the parent object whole.\n *\n * `children` paths are relative to the object. They are ordinary leaves, so a\n * field that is itself a union (a stroke's `paint`) declares the kind that\n * edits that union. A child may also be a {@link PrefSection}, which\n * organizes the fields under a heading without contributing to the path. A\n * `TextStyle` needs it: its character and paragraph fields belong to one\n * value but read as two lists.\n */\nexport interface PrefObject extends PrefBase<'object', unknown> {\n children: Record<string, PrefLeaf | PrefSection>;\n /**\n * Lift a non-object value into the object form, for a consumer field that\n * may also be held as a scalar. Called before a child edit is applied;\n * without it a scalar-valued leaf shows its children empty, and an edit\n * starts from the leaf's `default`.\n */\n fromScalar?: (value: unknown) => Record<string, unknown>;\n}\n\n/**\n * A reference to another field of the same schema, held as the full path its\n * value is read and written at (`'camera.type'`) — the currency fields refer\n * to each other in. A surface offers the fields it draws as the choices.\n */\nexport interface PrefField extends PrefBase<'field', string> {\n /** Only fields of these kinds may be named. Default: any leaf. */\n kinds?: readonly string[];\n}\n\n/** One built-in pref leaf. `PrefLeaf` widens this to include\n * app-defined kinds. */\nexport type BuiltinPref =\n | PrefNumber\n | PrefBoolean\n | PrefString\n | PrefEnum\n | PrefColor\n | PrefPaint\n | PrefObject\n | PrefList\n | PrefMap\n | PrefUnion\n | PrefField\n | PrefAction\n | PrefAlias\n | PrefLabel\n | PrefSeparator;\n\n// Compile-time tie: every built-in leaf kind must appear in PrefKind\n// and vice versa (PrefBase's K is open for PrefCustom's sake, so\n// the union no longer enforces it).\ntype _BuiltinKindsExact = [BuiltinPref['kind']] extends [PrefKind]\n ? [PrefKind] extends [BuiltinPref['kind']] ? true : never\n : never;\nconst _builtinKindsExact: _BuiltinKindsExact = true;\nvoid _builtinKindsExact;\n\n/**\n * The built-in kinds, as a table. A kind added to {@link PrefKind} is a\n * compile error here, and from here it is one in every renderer's `never`\n * guard — the only thing standing between a new kind and rendering as\n * nothing in four places at once.\n */\nexport const PREF_KINDS: Record<PrefKind, true> = {\n number: true,\n boolean: true,\n string: true,\n enum: true,\n color: true,\n paint: true,\n object: true,\n list: true,\n map: true,\n union: true,\n field: true,\n action: true,\n alias: true,\n label: true,\n separator: true,\n};\n\n/** Which row each pairing among `leaves` puts a path on: a `key` the row's\n * members share (the declaring leaf's path) and the `label` it reads. A\n * path no `pair` names is absent. `leaves` are given by the path each\n * surface reads and writes them at, so references resolve in its terms. */\nexport function pairRowsOf(\n leaves: Iterable<readonly [path: string, leaf: PrefLeaf]>,\n): Map<string, { key: string; label: string }> {\n const rows = new Map<string, { key: string; label: string }>();\n for (const [path, leaf] of leaves) {\n if (!leaf.pair || rows.has(path)) continue;\n const row = { key: path, label: leaf.pair.label ?? leaf.name };\n rows.set(path, row);\n const partners = typeof leaf.pair.with === 'string' ? [leaf.pair.with] : leaf.pair.with;\n for (const partner of partners) if (!rows.has(partner)) rows.set(partner, row);\n }\n return rows;\n}\n\n/**\n * Narrows a leaf to the built-in union, so a renderer's switch discriminates\n * on {@link PrefKind} instead of the open `string` that\n * {@link PrefCustom} widens `kind` to. An app-defined kind answers false\n * and belongs to the renderer's custom-renderer path.\n */\nexport function isBuiltinPref(leaf: PrefLeaf): leaf is BuiltinPref {\n return Object.hasOwn(PREF_KINDS, leaf.kind);\n}\n\n/** Built-in or app-defined leaf. */\nexport type PrefLeaf = BuiltinPref | PrefCustom;\n"]}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as PrefGroup,
|
|
1
|
+
import { a as PrefGroup, H as PrefPath, e as PrefsStore, N as PrefValueAt } from './store-CNFnA_3c.js';
|
|
2
2
|
import '@weasel-js/quantity';
|
|
3
3
|
|
|
4
4
|
/** One leaf of `store`, as React state. */
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks.ts"],"names":[],"mappings":";;;AAMO,SAAS,OAAA,CACd,OACA,IAAA,EAIA;AACA,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,CAAC,QAAA,KAAyB,KAAA,CAAM,UAAU,QAAQ,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAC1F,EAAA,MAAM,WAAA,GAAc,MAAM,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AACtE,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,IAAA,KAA+E;AAC9E,MAAA,KAAA,CAAM,GAAA;AAAA,QACJ,IAAA;AAAA,QACA,OAAO,SAAS,UAAA,GACX,IAAA,CAAwD,MAAM,GAAA,CAAI,IAAI,CAAC,CAAA,GACxE;AAAA,OACN;AAAA,IACF,CAAA;AAAA,IACA,CAAC,OAAO,IAAI;AAAA,GACd;AACA,EAAA,OAAO,CAAC,OAAO,GAAG,CAAA;AACpB;AAKO,SAAS,eAAoC,KAAA,EAMlD;AACA,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,CAAC,QAAA,KAAyB,KAAA,CAAM,UAAU,QAAQ,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAC1F,EAAA,MAAM,SAAS,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAM,CAAA;AACzE,EAAA,MAAM,QAAQ,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,KAAA,EAAO,MAAM,KAAK,CAAA;AACtE,EAAA,MAAM,SAAS,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAM,CAAA;AACzE,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,IAAA,EAAc,KAAA,KAAmB,KAAA,CAAM,GAAA,CAAI,MAAqB,KAAc,CAAA;AAAA,IAC/E,CAAC,KAAK;AAAA,GACR;AACA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,CAAC,IAAA,KAAkB,KAAA,CAAM,MAAM,IAAI,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACvE,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,KAAA,EAAO,QAAQ,KAAA,EAAM;AAC7C","file":"react.js","sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport type { PrefPath, PrefValueAt } from './paths';\nimport type { PrefGroup } from './
|
|
1
|
+
{"version":3,"sources":["../src/hooks.ts"],"names":[],"mappings":";;;AAMO,SAAS,OAAA,CACd,OACA,IAAA,EAIA;AACA,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,CAAC,QAAA,KAAyB,KAAA,CAAM,UAAU,QAAQ,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAC1F,EAAA,MAAM,WAAA,GAAc,MAAM,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AACtE,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,IAAA,KAA+E;AAC9E,MAAA,KAAA,CAAM,GAAA;AAAA,QACJ,IAAA;AAAA,QACA,OAAO,SAAS,UAAA,GACX,IAAA,CAAwD,MAAM,GAAA,CAAI,IAAI,CAAC,CAAA,GACxE;AAAA,OACN;AAAA,IACF,CAAA;AAAA,IACA,CAAC,OAAO,IAAI;AAAA,GACd;AACA,EAAA,OAAO,CAAC,OAAO,GAAG,CAAA;AACpB;AAKO,SAAS,eAAoC,KAAA,EAMlD;AACA,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,CAAC,QAAA,KAAyB,KAAA,CAAM,UAAU,QAAQ,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAC1F,EAAA,MAAM,SAAS,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAM,CAAA;AACzE,EAAA,MAAM,QAAQ,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,KAAA,EAAO,MAAM,KAAK,CAAA;AACtE,EAAA,MAAM,SAAS,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAM,CAAA;AACzE,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,IAAA,EAAc,KAAA,KAAmB,KAAA,CAAM,GAAA,CAAI,MAAqB,KAAc,CAAA;AAAA,IAC/E,CAAC,KAAK;AAAA,GACR;AACA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,CAAC,IAAA,KAAkB,KAAA,CAAM,MAAM,IAAI,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACvE,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,KAAA,EAAO,QAAQ,KAAA,EAAM;AAC7C","file":"react.js","sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport type { PrefPath, PrefValueAt } from './paths';\nimport type { PrefGroup } from './groups';\nimport type { PrefsStore } from './store';\n\n/** One leaf of `store`, as React state. */\nexport function usePref<S extends PrefGroup, P extends PrefPath<S>>(\n store: PrefsStore<S>,\n path: P,\n): [\n PrefValueAt<S, P>,\n (next: PrefValueAt<S, P> | ((prev: PrefValueAt<S, P>) => PrefValueAt<S, P>)) => void,\n] {\n const subscribe = useCallback((onChange: () => void) => store.subscribe(onChange), [store]);\n const getSnapshot = () => store.get(path);\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const set = useCallback(\n (next: PrefValueAt<S, P> | ((prev: PrefValueAt<S, P>) => PrefValueAt<S, P>)) => {\n store.set(\n path,\n typeof next === 'function'\n ? (next as (prev: PrefValueAt<S, P>) => PrefValueAt<S, P>)(store.get(path))\n : next,\n );\n },\n [store, path],\n );\n return [value, set];\n}\n\n/** The whole of `store` as React state, shaped for `PrefsForm`: `values`,\n * `onChange={set}`, `auto={unset}`, and `reset` for `onAutoChange`. `stored`\n * is `store.stored()`. */\nexport function usePrefsValues<S extends PrefGroup>(store: PrefsStore<S>): {\n values: Record<string, unknown>;\n set: (path: string, value: unknown) => void;\n unset: ReadonlySet<string>;\n stored: Record<string, unknown>;\n reset: (path?: string) => void;\n} {\n const subscribe = useCallback((onChange: () => void) => store.subscribe(onChange), [store]);\n const values = useSyncExternalStore(subscribe, store.values, store.values);\n const unset = useSyncExternalStore(subscribe, store.unset, store.unset);\n const stored = useSyncExternalStore(subscribe, store.stored, store.stored);\n const set = useCallback(\n (path: string, value: unknown) => store.set(path as PrefPath<S>, value as never),\n [store],\n );\n const reset = useCallback((path?: string) => store.reset(path), [store]);\n return { values, set, unset, stored, reset };\n}\n"]}
|