@weasel-js/labkit 1.4.4 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/README.md +13 -2
  2. package/dist/_dts/{CanvasStackContext-kTEZvEgE.d.ts → CanvasStackContext-CqkxkFJW.d.ts} +1 -1
  3. package/dist/_dts/ToggleBar.d-DbHoWKIA.d.ts +116 -0
  4. package/dist/_dts/{frac-z7ker2Vx.d.ts → frac-8R6UmlvN.d.ts} +253 -31
  5. package/dist/_dts/index-B8uu2ba7.d.ts +237 -0
  6. package/dist/_dts/{index-Blv9uQzu.d.ts → index-retnAut7.d.ts} +18 -10
  7. package/dist/_dts/{types-B9_zrHmb.d.ts → types-Ca2LCnPq.d.ts} +65 -2
  8. package/dist/_dts/usePanZoom-nS798rOF.d.ts +160 -0
  9. package/dist/_dts/useTrialState-jcx_TdU6.d.ts +212 -0
  10. package/dist/canvas/index.d.ts +17 -128
  11. package/dist/canvas/index.js +4 -2
  12. package/dist/chrome/index.d.ts +4 -92
  13. package/dist/chrome/index.js +9 -5
  14. package/dist/chunk-67SJLMC7.js +704 -0
  15. package/dist/chunk-67SJLMC7.js.map +1 -0
  16. package/dist/chunk-6ZDGOZQV.js +310 -0
  17. package/dist/chunk-6ZDGOZQV.js.map +1 -0
  18. package/dist/{chunk-MOM3GOVY.js → chunk-EKIICY6X.js} +111 -25
  19. package/dist/chunk-EKIICY6X.js.map +1 -0
  20. package/dist/{chunk-CTRKTLYZ.js → chunk-H6ZAOWNE.js} +11 -11
  21. package/dist/chunk-H6ZAOWNE.js.map +1 -0
  22. package/dist/{chunk-SMHP6XZ4.js → chunk-KJALCDWE.js} +9 -7
  23. package/dist/chunk-KJALCDWE.js.map +1 -0
  24. package/dist/{chunk-BKFVHKJH.js → chunk-MUKOW3TC.js} +3 -3
  25. package/dist/{chunk-BKFVHKJH.js.map → chunk-MUKOW3TC.js.map} +1 -1
  26. package/dist/chunk-NDRYLVOW.js +15 -0
  27. package/dist/chunk-NDRYLVOW.js.map +1 -0
  28. package/dist/{chunk-64ZCN3DA.js → chunk-NS64DXMN.js} +226 -159
  29. package/dist/chunk-NS64DXMN.js.map +1 -0
  30. package/dist/{chunk-I6JCVE24.js → chunk-PGETSEDK.js} +135 -13
  31. package/dist/chunk-PGETSEDK.js.map +1 -0
  32. package/dist/{chunk-FQMJUVHJ.js → chunk-QLSV2N3G.js} +32 -37
  33. package/dist/chunk-QLSV2N3G.js.map +1 -0
  34. package/dist/chunk-RWNDDKOH.js +682 -0
  35. package/dist/chunk-RWNDDKOH.js.map +1 -0
  36. package/dist/chunk-S2SHZRD7.js +7681 -0
  37. package/dist/chunk-S2SHZRD7.js.map +1 -0
  38. package/dist/{chunk-U3IYHIAE.js → chunk-TQBBYTAF.js} +19 -82
  39. package/dist/chunk-TQBBYTAF.js.map +1 -0
  40. package/dist/chunk-UU3NJO6N.js +72 -0
  41. package/dist/chunk-UU3NJO6N.js.map +1 -0
  42. package/dist/chunk-WIG6XHJ7.js +35 -0
  43. package/dist/chunk-WIG6XHJ7.js.map +1 -0
  44. package/dist/{chunk-TJ7QY3OC.js → chunk-ZPH5WTWF.js} +21 -15
  45. package/dist/chunk-ZPH5WTWF.js.map +1 -0
  46. package/dist/config/index.d.ts +232 -0
  47. package/dist/config/index.js +6 -0
  48. package/dist/config/index.js.map +1 -0
  49. package/dist/controls/index.d.ts +2 -3
  50. package/dist/controls/index.js +3 -2
  51. package/dist/dragdrop/index.d.ts +2 -4
  52. package/dist/index.d.ts +110 -381
  53. package/dist/index.js +691 -817
  54. package/dist/index.js.map +1 -1
  55. package/dist/layers/index.d.ts +3 -5
  56. package/dist/layers/index.js +2 -2
  57. package/dist/loupe/index.d.ts +6 -8
  58. package/dist/loupe/index.js +2 -2
  59. package/dist/passthrough/weasel-ui.d.ts +164 -122
  60. package/dist/passthrough/weasel-ui.js +1 -1
  61. package/dist/primitives/index.d.ts +53 -6
  62. package/dist/primitives/index.js +6 -4
  63. package/dist/state/index.d.ts +12 -7
  64. package/dist/state/index.js +16 -13
  65. package/dist/state/index.js.map +1 -1
  66. package/dist/styles.css +84 -50
  67. package/dist/surface/index.d.ts +44 -7
  68. package/dist/surface/index.js +2 -1
  69. package/dist/ui/layers/index.js +1 -1
  70. package/dist/undo/index.d.ts +2 -4
  71. package/package.json +15 -8
  72. package/src/annotations/AnnotationOverlay.tsx +53 -5
  73. package/src/annotations/Annotations.overlay.test.tsx +85 -6
  74. package/src/annotations/drawOne.test.ts +1 -1
  75. package/src/annotations/drawOne.ts +2 -2
  76. package/src/annotations/paint.test.ts +2 -2
  77. package/src/annotations/paint.ts +1 -1
  78. package/src/annotations/preload.ts +6 -0
  79. package/src/annotations/store.test.ts +18 -0
  80. package/src/annotations/store.ts +5 -4
  81. package/src/annotations/svgNodes.test.ts +2 -2
  82. package/src/annotations/toolMap.ts +3 -3
  83. package/src/annotations/types.ts +6 -3
  84. package/src/canvas/CameraWheelContext.ts +12 -0
  85. package/src/canvas/CanvasStack.test.tsx +25 -0
  86. package/src/canvas/CanvasStack.tsx +31 -4
  87. package/src/canvas/Stage.less +18 -0
  88. package/src/canvas/Stage.test.tsx +186 -0
  89. package/src/canvas/Stage.tsx +134 -0
  90. package/src/canvas/camera.test.ts +17 -2
  91. package/src/canvas/camera.ts +9 -9
  92. package/src/canvas/index.ts +4 -0
  93. package/src/canvas/usePanZoom.ts +10 -5
  94. package/src/chrome/ChromeRegions.stories.tsx +0 -3
  95. package/src/chrome/LabChrome.tsx +114 -0
  96. package/src/chrome/builtins.tsx +20 -31
  97. package/src/chrome/index.ts +15 -0
  98. package/src/chrome/labRegions.test.tsx +208 -0
  99. package/src/chrome/labTypes.ts +50 -0
  100. package/src/chrome/merge.ts +7 -9
  101. package/src/chrome/regions/PaletteRegion.test.tsx +6 -4
  102. package/src/chrome/regions/PaletteRegion.tsx +21 -9
  103. package/src/chrome/regions/SidebarRegion.tsx +25 -13
  104. package/src/chrome/regions/StatusRegion.tsx +15 -8
  105. package/src/chrome/regions/ToolbarRegion.tsx +30 -16
  106. package/src/chrome/types.ts +47 -20
  107. package/src/config/builder.test.ts +4 -0
  108. package/src/config/builder.ts +16 -10
  109. package/src/config/declarationEmit.fixture.ts +11 -0
  110. package/src/config/declarationEmit.test.ts +51 -0
  111. package/src/config/entry.test.ts +46 -0
  112. package/src/config/index.ts +13 -1
  113. package/src/config/nodeClasses.test.ts +18 -0
  114. package/src/config/types.ts +3 -1
  115. package/src/controls/ControlPanel.test.tsx +16 -0
  116. package/src/controls/ControlPanel.tsx +5 -2
  117. package/src/fake-indexeddb-auto.d.ts +5 -0
  118. package/src/index.test.ts +7 -0
  119. package/src/index.ts +38 -5
  120. package/src/instrument/serializers.test.ts +22 -0
  121. package/src/instrument/serializers.ts +11 -0
  122. package/src/instrument/types.ts +25 -1
  123. package/src/lab/Lab.less +4 -13
  124. package/src/lab/Lab.persist.test.tsx +147 -0
  125. package/src/lab/Lab.stories.tsx +0 -2
  126. package/src/lab/Lab.surface.test.tsx +66 -3
  127. package/src/lab/Lab.test.tsx +91 -17
  128. package/src/lab/Lab.tsx +337 -124
  129. package/src/lab/LabFit.stories.less +18 -0
  130. package/src/lab/LabFit.stories.tsx +219 -0
  131. package/src/lab/LabFullChrome.stories.tsx +0 -3
  132. package/src/lab/LabHeader.test.tsx +40 -9
  133. package/src/lab/LabHeader.tsx +7 -13
  134. package/src/lab/LabPalette.tsx +13 -26
  135. package/src/lab/LabShell.less +49 -12
  136. package/src/lab/LabSwitcher.less +8 -1
  137. package/src/lab/Workspace.surface.test.tsx +2 -1
  138. package/src/lab/fitCheck.test.ts +57 -0
  139. package/src/lab/fitCheck.ts +125 -0
  140. package/src/loupe/AGENTS.md +1 -1
  141. package/src/loupe/Loupe.less +1 -1
  142. package/src/loupe/canvasLens.ts +1 -1
  143. package/src/loupe/types.ts +1 -1
  144. package/src/loupe/useLoupe.test.tsx +1 -1
  145. package/src/loupe/useLoupe.ts +1 -1
  146. package/src/passthrough/weasel-ui.ts +9 -0
  147. package/src/primitives/FloatingPanel.stories.tsx +13 -1
  148. package/src/primitives/FloatingPanel.test.tsx +47 -16
  149. package/src/primitives/FloatingPanel.tsx +11 -25
  150. package/src/primitives/Split.less +14 -0
  151. package/src/primitives/Split.test.tsx +108 -0
  152. package/src/primitives/Split.tsx +159 -0
  153. package/src/primitives/ZoomControl.tsx +5 -2
  154. package/src/primitives/index.ts +2 -0
  155. package/src/state/Persistence.stories.tsx +75 -0
  156. package/src/state/Persistence.tsx +33 -0
  157. package/src/state/SingletonExperiment.test.tsx +47 -53
  158. package/src/state/SingletonExperiment.tsx +24 -13
  159. package/src/state/adapterContract.ts +116 -0
  160. package/src/state/adapters.test.ts +113 -61
  161. package/src/state/adapters.ts +328 -69
  162. package/src/state/document.test.ts +71 -96
  163. package/src/state/document.ts +66 -52
  164. package/src/state/helpers.test.ts +1 -1
  165. package/src/state/index.ts +8 -0
  166. package/src/state/labRecords.test.ts +105 -0
  167. package/src/state/labRecords.ts +160 -0
  168. package/src/state/openLabStore.test.ts +658 -0
  169. package/src/state/openLabStore.ts +403 -0
  170. package/src/state/records.test.ts +234 -0
  171. package/src/state/records.ts +219 -0
  172. package/src/state/store.test.ts +104 -635
  173. package/src/state/store.ts +116 -157
  174. package/src/state/toolSlot.test.ts +1 -1
  175. package/src/state/types.ts +39 -15
  176. package/src/state/useOpenOnce.ts +68 -0
  177. package/src/state/usePersistedState.test.tsx +125 -0
  178. package/src/state/usePersistedState.ts +66 -0
  179. package/src/state/useTrialState.test.tsx +2 -3
  180. package/src/state/view.test.ts +49 -15
  181. package/src/state/view.ts +18 -1
  182. package/src/styles.less +2 -0
  183. package/src/surface/AGENTS.md +39 -7
  184. package/src/surface/SurfaceContext.ts +26 -3
  185. package/src/surface/index.ts +2 -0
  186. package/src/surface/useSurfaceTile.test.tsx +2 -1
  187. package/src/surface/useSurfaceTile.ts +6 -5
  188. package/src/surface/useTiledSurface.test.tsx +175 -0
  189. package/src/surface/useTiledSurface.ts +54 -5
  190. package/src/theme/Interstellar.stories.tsx +7 -7
  191. package/src/theme/interstellar.test.ts +1 -1
  192. package/src/theme/interstellar.tokens.json +2 -2
  193. package/src/tools/labTool.ts +11 -0
  194. package/src/trial/Trial.annotations.persist.test.tsx +100 -58
  195. package/src/trial/Trial.annotations.test.tsx +47 -4
  196. package/src/trial/Trial.job.test.tsx +3 -3
  197. package/src/trial/Trial.less +1 -26
  198. package/src/trial/Trial.stories.tsx +1 -2
  199. package/src/trial/Trial.test.tsx +28 -4
  200. package/src/trial/Trial.trialId.test.tsx +23 -1
  201. package/src/trial/Trial.tsx +118 -38
  202. package/src/trial/TrialBody.tsx +17 -141
  203. package/src/trial/TrialChrome.tsx +7 -4
  204. package/src/trial/trialOps.ts +5 -3
  205. package/dist/_dts/types-BP2OCcpg.d.ts +0 -155
  206. package/dist/_dts/types-x92Kfeme.d.ts +0 -62
  207. package/dist/_dts/useTrialState-D6Vb3T-g.d.ts +0 -99
  208. package/dist/chunk-2P6PP5N4.js +0 -553
  209. package/dist/chunk-2P6PP5N4.js.map +0 -1
  210. package/dist/chunk-64ZCN3DA.js.map +0 -1
  211. package/dist/chunk-CTRKTLYZ.js.map +0 -1
  212. package/dist/chunk-FQMJUVHJ.js.map +0 -1
  213. package/dist/chunk-I6JCVE24.js.map +0 -1
  214. package/dist/chunk-MOM3GOVY.js.map +0 -1
  215. package/dist/chunk-SMHP6XZ4.js.map +0 -1
  216. package/dist/chunk-TJ7QY3OC.js.map +0 -1
  217. package/dist/chunk-U3IYHIAE.js.map +0 -1
  218. package/dist/chunk-W3ECWC2K.js +0 -7335
  219. package/dist/chunk-W3ECWC2K.js.map +0 -1
@@ -0,0 +1,232 @@
1
+ import { ToolPrefNumberFormat, ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
2
+ import { l as ConfigNode, A as Annotations, N as NodeOptions, d as ControlRenderer, n as ConfigOption, p as ConfigShape, h as ConfigBranch, B as BranchAnnotations, e as BranchOptions, b as ConfigSchema, I as InferConfig, i as ConfigEntry, a as ConfigField, R as ResolvedConfig, c as ConfigRule, L as LeafPatch, o as ConfigRuleContext } from '../_dts/types-Ca2LCnPq.js';
3
+ export { m as ConfigOf, C as ConfigPath, E as EntryValue, q as NodeValue, S as SectionSpec, V as ValueAtPath } from '../_dts/types-Ca2LCnPq.js';
4
+ import { K as Instrument } from '../_dts/frac-8R6UmlvN.js';
5
+ import '../_dts/PrefsForm.d-DDHFANkc.js';
6
+ import 'react';
7
+ import '../_dts/types-DJ79Tg5J.js';
8
+
9
+ /** Whether a schema entry is a branch rather than a leaf. */
10
+ declare function isConfigBranch(entry: ConfigEntry): entry is ConfigBranch;
11
+ /** Shared chaining surface. Every method clones, so a node can be reused as a
12
+ * base for several leaves without one bleeding into the next. */
13
+ declare abstract class BaseNode<T> implements ConfigNode<T> {
14
+ readonly annotations: Readonly<Annotations>;
15
+ readonly options: Readonly<NodeOptions>;
16
+ abstract readonly kind: string | null;
17
+ readonly default: T;
18
+ constructor(defaultValue: T, annotations?: Readonly<Annotations>, options?: Readonly<NodeOptions>);
19
+ /** Clone into the same subclass. Subclasses with extra constructor
20
+ * arguments override this. */
21
+ protected with(annotations: Annotations, options: NodeOptions): this;
22
+ protected ann(patch: Annotations): this;
23
+ protected opt(patch: NodeOptions): this;
24
+ /** Human-readable label. Defaults to the key, title-cased. */
25
+ label(name: string): this;
26
+ /** Longer help text, surfaced as a tooltip on the row label. */
27
+ describe(description: string): this;
28
+ /** Omit from the panel unless it is asked to show hidden leaves. */
29
+ hidden(): this;
30
+ /** Pair with a sibling sharing this id, side-by-side on one row. */
31
+ pair(pair: string): this;
32
+ /** Render under a named section heading. `collapsed` opens the section
33
+ * folded — say it on any one of the section's leaves. */
34
+ section(label: string, opts?: {
35
+ collapsed?: boolean;
36
+ }): this;
37
+ /** Show this row only while the predicate holds. Presentational — the value
38
+ * stays in config and the instrument still reads it. */
39
+ showIf(predicate: (config: Record<string, unknown>) => boolean): this;
40
+ /** Draw this one row yourself, keeping the kind, default and validation. */
41
+ render(renderer: ControlRenderer): this;
42
+ }
43
+ declare class NumberNode extends BaseNode<number> {
44
+ readonly kind = "number";
45
+ /** Bound the value. A number with both bounds renders as a slider. */
46
+ range(min: number, max: number): this;
47
+ step(step: number): this;
48
+ /** A display suffix for the value — `'px'`, `'ms'`, `'°'`. Presentation only:
49
+ * it is never parsed, and the stored value stays a plain number. */
50
+ suffix(suffix: string): this;
51
+ /** Show the value in a named format — `'compact'` reads `2.0M`. Presentation
52
+ * only: the stored value stays a plain number, and a typed `2.5m` reads back. */
53
+ format(format: ToolPrefNumberFormat): this;
54
+ /** Force a slider even without both bounds. */
55
+ slider(): this;
56
+ /** Force a typed input even when both bounds are set. */
57
+ input(): this;
58
+ }
59
+ declare class BooleanNode extends BaseNode<boolean> {
60
+ readonly kind = "boolean";
61
+ /** Ask for a switch. `ControlPanel` still draws a checkbox; weasel-ui's
62
+ * `PrefsForm` honors the distinction. */
63
+ toggle(): this;
64
+ }
65
+ declare class StringNode extends BaseNode<string> {
66
+ readonly kind = "string";
67
+ placeholder(placeholder: string): this;
68
+ maxLength(maxLength: number): this;
69
+ /** Milliseconds to debounce live writes. 0 commits every keystroke. */
70
+ debounce(debounceMs: number): this;
71
+ }
72
+ declare class ColorNode extends BaseNode<string> {
73
+ readonly kind = "color";
74
+ }
75
+ declare class EnumNode<T extends string> extends BaseNode<T> {
76
+ readonly kind = "enum";
77
+ /** Render as a segmented control rather than a select. */
78
+ radio(): this;
79
+ /** Relabel the choices. Named `labels` rather than `options` because
80
+ * `options` is the node's own extras bag. */
81
+ labels(options: readonly ConfigOption[]): this;
82
+ }
83
+ /** A leaf whose kind the rule chain decides. */
84
+ declare class ValueNode<T> extends BaseNode<T> {
85
+ readonly kind: null;
86
+ }
87
+ /** A leaf of a kind labkit does not ship a row for. */
88
+ declare class CustomNode<T> extends BaseNode<T> {
89
+ readonly kind: string;
90
+ constructor(kind: string, defaultValue: T, annotations?: Readonly<Annotations>, options?: Readonly<NodeOptions>);
91
+ protected with(annotations: Annotations, options: NodeOptions): this;
92
+ }
93
+ /**
94
+ * A branch of the schema: its children nest under its key, so a leaf inside
95
+ * one is read and written at a dotted path. Distinct from `.section()`, which
96
+ * puts a heading over sibling leaves and leaves their paths alone.
97
+ */
98
+ declare class GroupNode<S extends ConfigShape> implements ConfigBranch<S> {
99
+ readonly children: S;
100
+ readonly annotations: Readonly<BranchAnnotations>;
101
+ readonly options: Readonly<BranchOptions>;
102
+ constructor(children: S, annotations?: Readonly<BranchAnnotations>, options?: Readonly<BranchOptions>);
103
+ private with;
104
+ /** Heading for the group's rows. Defaults to the key, title-cased. */
105
+ label(name: string): GroupNode<S>;
106
+ /** Longer help text. Carried on the resolved `PrefGroup`, where weasel-ui's
107
+ * `PrefsForm` draws it under the heading; `ControlPanel` has no place for
108
+ * it yet and shows the heading alone. */
109
+ describe(description: string): GroupNode<S>;
110
+ /** Render this whole group under a named section heading. */
111
+ section(label: string, opts?: {
112
+ collapsed?: boolean;
113
+ }): GroupNode<S>;
114
+ /** Show this group only while the predicate holds. Presentational — every
115
+ * value beneath it stays in config and the instrument still reads it. */
116
+ showIf(predicate: (config: Record<string, unknown>) => boolean): GroupNode<S>;
117
+ }
118
+ /**
119
+ * Builds an instrument's config: the values, their types, and how each is
120
+ * edited, in one declaration.
121
+ *
122
+ * ```ts
123
+ * const config = f.schema({
124
+ * showGrid: f.boolean(true),
125
+ * cellSize: f.number(20).range(5, 80).step(5).label('Grid spacing'),
126
+ * // Nested: read and written at `grid.color`.
127
+ * grid: f.group({ color: f.color('#ffffff') }),
128
+ * })
129
+ * ```
130
+ */
131
+ declare const f: {
132
+ number: (def: number) => NumberNode;
133
+ boolean: (def: boolean) => BooleanNode;
134
+ string: (def: string) => StringNode;
135
+ color: (def: string) => ColorNode;
136
+ /** A fixed set of choices. The default's literal type flows into the config
137
+ * type, so `f.enum('fast', ['fast', 'accurate'])` gives
138
+ * `'fast' | 'accurate'` with no `as const`. */
139
+ enum: <const T extends string>(def: T, options: readonly T[] | readonly ConfigOption[]) => EnumNode<T>;
140
+ /** A leaf with no declared kind: the rule chain decides, which is how a lab
141
+ * states a convention like "every `*Color` key is a color picker". */
142
+ value: <T>(def: T) => ValueNode<T>;
143
+ /** A branch: its children nest under this key, so `grid: f.group({ size })`
144
+ * puts the value at `config.grid.size` and addresses it as `'grid.size'`.
145
+ * Groups nest as deeply as the schema wants. */
146
+ group: <const S extends ConfigShape>(children: S) => GroupNode<S>;
147
+ /** A leaf of a kind a lab supplies the control for, through `controls`. */
148
+ custom: <T>(kind: string, def: T, validate?: (leaf: ToolPrefLeaf) => string[]) => CustomNode<T>;
149
+ /** Collect leaves and groups into an instrument's config. */
150
+ schema<S extends ConfigShape>(nodes: S): ConfigSchema<InferConfig<S>>;
151
+ };
152
+
153
+ /**
154
+ * Adapt a legacy `configSchema(): ConfigField[]` into the resolved shape, so
155
+ * both instrument paths reach one renderer.
156
+ *
157
+ * Rules do not run here: a hand-written `ConfigField` already states its label
158
+ * and control, which is everything the rule chain would have inferred.
159
+ */
160
+ declare function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig;
161
+
162
+ /** The value at a dotted path. `undefined` when a segment is missing or the
163
+ * walk hits something that is not a record. */
164
+ declare function valueAtPath(config: unknown, path: string): unknown;
165
+ /** Whether a dotted path is actually present, which a `undefined` value is
166
+ * not enough to tell you. */
167
+ declare function hasConfigPath(config: unknown, path: string): boolean;
168
+ /** A copy of `config` with `value` written at a dotted path. Every record on
169
+ * the way down is copied and the input is left alone; a missing — or
170
+ * non-record — intermediate is replaced with the branch the path implies. */
171
+ declare function withValueAtPath<T>(config: T, path: string, value: unknown): T;
172
+ /**
173
+ * `stored` with every gap filled from `defaults`, down the whole tree.
174
+ *
175
+ * This is how a config written before its schema grew a branch still loads:
176
+ * the branch arrives at its defaults instead of `undefined`, and a key the
177
+ * defaults no longer mention is kept rather than dropped, so nothing is lost
178
+ * to a schema change the author has not finished making.
179
+ */
180
+ declare function fillConfigDefaults<T>(stored: unknown, defaults: T): T;
181
+ /** A node in a resolved schema tree, by dotted path. Structural rather than
182
+ * `isPrefLeaf` so this stays free of a runtime import. */
183
+ declare function schemaNodeAtPath(group: ToolPrefGroup, path: string): ToolPrefLeaf | ToolPrefGroup | undefined;
184
+
185
+ /**
186
+ * Resolve a schema into the vocabulary weasel-ui renders, running each leaf
187
+ * through the consumer's rules and then labkit's own.
188
+ *
189
+ * The group mirrors the schema's own nesting: an `f.group` becomes a nested
190
+ * `PrefGroup`, so a leaf's dotted path within the tree is the path its value
191
+ * is written at, and both `ControlPanel` and `PrefsForm` address it
192
+ * identically.
193
+ */
194
+ declare function resolveConfigSchema<TC>(schema: ConfigSchema<TC>, rules?: readonly ConfigRule[]): ResolvedConfig;
195
+
196
+ /** `cellSize` -> `Cell size`. Splits camelCase without shattering acronyms. */
197
+ declare function titleCase(key: string): string;
198
+ /**
199
+ * labkit's own inference, expressed in the same vocabulary a consumer
200
+ * extends. Runs after the consumer's rules, so a lab always wins.
201
+ *
202
+ * If one of these ever needs something a `ConfigRule` cannot express, the
203
+ * seam is too weak — that is the point of writing them this way.
204
+ */
205
+ declare const builtinRules: readonly ConfigRule[];
206
+ /**
207
+ * Fold a rule chain into one leaf patch. Gap-filling: a property already
208
+ * settled is never overwritten, so the accumulator seeded with the author's
209
+ * annotations beats every rule, and earlier rules beat later ones.
210
+ */
211
+ declare function applyRules(seed: LeafPatch, ctx: Omit<ConfigRuleContext, 'leaf'>, rules: readonly ConfigRule[]): LeafPatch;
212
+
213
+ /**
214
+ * An instrument's controls, resolved against the surrounding lab's rules.
215
+ *
216
+ * Resolution cannot happen in `defineInstrument` — rules are lab-scoped and
217
+ * that runs at module load — so it happens here, at render. Both instrument
218
+ * paths land in the same shape, so callers never branch on which was used.
219
+ */
220
+ declare function useConfigSchema(instrument: Instrument<any, any, any>): ResolvedConfig;
221
+
222
+ /**
223
+ * Whether the row at a dotted path should be drawn right now. A group answers
224
+ * for its whole subtree — hiding one hides everything under it.
225
+ *
226
+ * `hidden` is the node's own static flag; `showIf` is the schema's predicate
227
+ * over the live config. Both are presentational — a hidden leaf keeps its
228
+ * value and the instrument still reads it.
229
+ */
230
+ declare function isLeafVisible(resolved: ResolvedConfig, path: string, config: Record<string, unknown>, showHidden?: boolean): boolean;
231
+
232
+ export { Annotations, BaseNode, BooleanNode, BranchAnnotations, BranchOptions, ColorNode, ConfigBranch, ConfigEntry, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ConfigShape, ControlRenderer, CustomNode, EnumNode, GroupNode, InferConfig, LeafPatch, NodeOptions, NumberNode, ResolvedConfig, StringNode, ValueNode, applyRules, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveConfigSchema, schemaNodeAtPath, titleCase, useConfigSchema, valueAtPath, withValueAtPath };
@@ -0,0 +1,6 @@
1
+ export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useConfigSchema } from '../chunk-6ZDGOZQV.js';
2
+ import '../chunk-NDRYLVOW.js';
3
+ export { fromConfigFields, isLeafVisible } from '../chunk-UU3NJO6N.js';
4
+ export { fillConfigDefaults, hasConfigPath, schemaNodeAtPath, valueAtPath, withValueAtPath } from '../chunk-E44SU6XS.js';
5
+ //# sourceMappingURL=index.js.map
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1,7 +1,6 @@
1
- export { e as ControlPanel } from '../_dts/index-Blv9uQzu.js';
2
- export { a as CheckboxField, b as ColorField, C as ConfigField, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from '../_dts/types-x92Kfeme.js';
1
+ export { e as ControlPanel } from '../_dts/index-retnAut7.js';
2
+ export { f as CheckboxField, g as ColorField, a as ConfigField, k as ConfigFieldType, r as NumberField, s as SelectField, t as SelectOption, u as SliderField, T as TextField } from '../_dts/types-Ca2LCnPq.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
- import '../_dts/types-B9_zrHmb.js';
6
5
  import '@weasel-js/core';
7
6
  import '../_dts/PrefsForm.d-DDHFANkc.js';
@@ -1,5 +1,6 @@
1
- export { ControlPanel } from '../chunk-U3IYHIAE.js';
1
+ export { ControlPanel } from '../chunk-TQBBYTAF.js';
2
+ import '../chunk-UU3NJO6N.js';
2
3
  import '../chunk-E44SU6XS.js';
3
- import '../chunk-W3ECWC2K.js';
4
+ import '../chunk-S2SHZRD7.js';
4
5
  //# sourceMappingURL=index.js.map
5
6
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,9 @@
1
- import { P as PaletteItem, a as Point, D as DragFeedback, b as DragDropCapability, V as ViewTransform, c as WorldSpec } from '../_dts/frac-z7ker2Vx.js';
1
+ import { P as PaletteItem, l as Point, m as DragFeedback, n as DragDropCapability, k as ViewTransform, a as WorldSpec } from '../_dts/frac-8R6UmlvN.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { RefObject, PointerEvent, ReactPortal } from 'react';
4
- import '../_dts/types-B9_zrHmb.js';
4
+ import '../_dts/types-Ca2LCnPq.js';
5
5
  import '@weasel-js/core';
6
6
  import '../_dts/PrefsForm.d-DDHFANkc.js';
7
- import '../_dts/types-x92Kfeme.js';
8
- import '../_dts/types-BP2OCcpg.js';
9
7
  import '../_dts/types-DJ79Tg5J.js';
10
8
 
11
9
  interface DragState {