@weasel-js/labkit 1.4.1 → 1.4.2

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 (114) hide show
  1. package/README.md +8 -0
  2. package/dist/_dts/{CanvasStackContext-BIRUVVGH.d.ts → CanvasStackContext-kjILVnPj.d.ts} +1 -1
  3. package/dist/_dts/{frac-X7mWgd7y.d.ts → frac-A4R6v4ld.d.ts} +27 -10
  4. package/dist/_dts/{index-FEa1MudK.d.ts → index-CsU9WhjM.d.ts} +89 -29
  5. package/dist/_dts/{types-ChVJJHvk.d.ts → types-BbXpvQa8.d.ts} +20 -1
  6. package/dist/_dts/{useTrialState-Cdm13fvl.d.ts → useTrialState-DKjqpv20.d.ts} +5 -1
  7. package/dist/canvas/index.d.ts +5 -5
  8. package/dist/canvas/index.js +2 -2
  9. package/dist/chrome/index.d.ts +12 -6
  10. package/dist/chrome/index.js +5 -5
  11. package/dist/{chunk-DG2IFMLA.js → chunk-54ZWZ5FQ.js} +127 -100
  12. package/dist/chunk-54ZWZ5FQ.js.map +1 -0
  13. package/dist/{chunk-RLOXQZW3.js → chunk-D5KQ5OY6.js} +3 -3
  14. package/dist/{chunk-RLOXQZW3.js.map → chunk-D5KQ5OY6.js.map} +1 -1
  15. package/dist/{chunk-PP7ZWAMV.js → chunk-FJG4PHTL.js} +3 -3
  16. package/dist/{chunk-PP7ZWAMV.js.map → chunk-FJG4PHTL.js.map} +1 -1
  17. package/dist/chunk-ISSVF5PT.js +7263 -0
  18. package/dist/chunk-ISSVF5PT.js.map +1 -0
  19. package/dist/chunk-NSOVI3AZ.js +170 -0
  20. package/dist/chunk-NSOVI3AZ.js.map +1 -0
  21. package/dist/{chunk-D7QIPGEB.js → chunk-TN7YSJVU.js} +62 -60
  22. package/dist/chunk-TN7YSJVU.js.map +1 -0
  23. package/dist/{chunk-7TRFMIWX.js → chunk-UDXOYZEC.js} +4 -4
  24. package/dist/{chunk-7TRFMIWX.js.map → chunk-UDXOYZEC.js.map} +1 -1
  25. package/dist/{chunk-LJSIUFYD.js → chunk-ULDW42CR.js} +23 -2
  26. package/dist/chunk-ULDW42CR.js.map +1 -0
  27. package/dist/{chunk-MSR7EVS6.js → chunk-UTOEDPNU.js} +5 -5
  28. package/dist/{chunk-MSR7EVS6.js.map → chunk-UTOEDPNU.js.map} +1 -1
  29. package/dist/{chunk-BMQWLKOL.js → chunk-W2FJR5FF.js} +35 -22
  30. package/dist/chunk-W2FJR5FF.js.map +1 -0
  31. package/dist/{chunk-OFCBEZMU.js → chunk-WS6ZRV75.js} +3 -3
  32. package/dist/{chunk-OFCBEZMU.js.map → chunk-WS6ZRV75.js.map} +1 -1
  33. package/dist/{chunk-53AZ2O2N.js → chunk-XKENZTNE.js} +45 -14
  34. package/dist/chunk-XKENZTNE.js.map +1 -0
  35. package/dist/controls/index.d.ts +1 -1
  36. package/dist/controls/index.js +3 -3
  37. package/dist/dragdrop/index.d.ts +5 -5
  38. package/dist/dragdrop/index.js +2 -2
  39. package/dist/index.d.ts +71 -43
  40. package/dist/index.js +146 -113
  41. package/dist/index.js.map +1 -1
  42. package/dist/layers/index.d.ts +23 -8
  43. package/dist/layers/index.js +3 -3
  44. package/dist/loupe/index.d.ts +4 -4
  45. package/dist/loupe/index.js +2 -2
  46. package/dist/passthrough/weasel-canvas.js +1 -1
  47. package/dist/passthrough/weasel-ui.d.ts +84 -3
  48. package/dist/passthrough/weasel-ui.js +2 -2
  49. package/dist/primitives/index.js +4 -4
  50. package/dist/state/index.d.ts +3 -3
  51. package/dist/state/index.js +2 -2
  52. package/dist/styles.css +20 -3
  53. package/dist/surface/index.js +2 -2
  54. package/dist/ui/layers/index.d.ts +22 -9
  55. package/dist/ui/layers/index.js +2 -2
  56. package/dist/undo/index.d.ts +2 -2
  57. package/package.json +7 -7
  58. package/src/annotations/AnnotationTargets.tsx +6 -1
  59. package/src/annotations/Annotations.overlay.test.tsx +2 -0
  60. package/src/annotations/types.ts +4 -1
  61. package/src/canvas/useOrbit.test.ts +7 -3
  62. package/src/canvas/usePanZoom.test.ts +7 -3
  63. package/src/chrome/ChromeRegions.stories.tsx +42 -1
  64. package/src/chrome/builtins.test.ts +4 -0
  65. package/src/chrome/builtins.tsx +18 -0
  66. package/src/chrome/index.ts +1 -1
  67. package/src/chrome/regions/SidebarRegion.tsx +7 -6
  68. package/src/chrome/regions/TitleBarRegion.test.tsx +64 -0
  69. package/src/chrome/regions/TitleBarRegion.tsx +16 -7
  70. package/src/chrome/regions/ToolbarRegion.test.tsx +14 -0
  71. package/src/chrome/regions/ToolbarRegion.tsx +2 -2
  72. package/src/chrome/regions/ViewportRegion.tsx +2 -2
  73. package/src/chrome/regions/regions.test.tsx +45 -1
  74. package/src/chrome/types.ts +21 -3
  75. package/src/controls/ControlPanel.test.tsx +38 -0
  76. package/src/controls/ControlPanel.tsx +51 -6
  77. package/src/dragdrop/DragDropRuntime.tsx +74 -61
  78. package/src/dragdrop/Palette.tsx +4 -3
  79. package/src/dragdrop/dragDrop.test.tsx +35 -12
  80. package/src/index.ts +2 -1
  81. package/src/instrument/types.ts +4 -5
  82. package/src/lab/Lab.test.tsx +7 -0
  83. package/src/lab/Lab.tsx +2 -2
  84. package/src/lab/LabContext.ts +5 -1
  85. package/src/lab/LabShell.less +17 -2
  86. package/src/layers/AGENTS.md +29 -7
  87. package/src/layers/LayerList.less +16 -0
  88. package/src/layers/LayerList.stories.tsx +66 -0
  89. package/src/layers/LayerList.test.tsx +117 -5
  90. package/src/layers/LayerList.tsx +192 -53
  91. package/src/layers/index.ts +1 -1
  92. package/src/passthrough/weasel-ui.ts +5 -0
  93. package/src/primitives/FloatingPanel.test.tsx +8 -3
  94. package/src/state/store.test.ts +78 -0
  95. package/src/state/store.ts +27 -0
  96. package/src/state/types.ts +20 -0
  97. package/src/trial/Trial.less +4 -0
  98. package/src/trial/Trial.targets.test.tsx +96 -0
  99. package/src/trial/Trial.test.tsx +171 -14
  100. package/src/trial/Trial.tsx +4 -1
  101. package/src/trial/TrialChrome.tsx +22 -2
  102. package/src/trial/TrialTitleBar.tsx +7 -3
  103. package/src/trial/index.ts +1 -0
  104. package/src/trial/trialOps.test.ts +49 -1
  105. package/src/trial/trialOps.ts +28 -6
  106. package/dist/chunk-53AZ2O2N.js.map +0 -1
  107. package/dist/chunk-BMQWLKOL.js.map +0 -1
  108. package/dist/chunk-D7QIPGEB.js.map +0 -1
  109. package/dist/chunk-DG2IFMLA.js.map +0 -1
  110. package/dist/chunk-J6SBFZYT.js +0 -7121
  111. package/dist/chunk-J6SBFZYT.js.map +0 -1
  112. package/dist/chunk-LJSIUFYD.js.map +0 -1
  113. package/dist/chunk-MIT3ISW4.js +0 -100
  114. package/dist/chunk-MIT3ISW4.js.map +0 -1
package/README.md CHANGED
@@ -120,6 +120,14 @@ changed draws dashed and reports `isStale`. `meaning.statuses` is the optional
120
120
  vocabulary a mark can be labelled with — a status carries its own color, which
121
121
  the mark on the canvas follows.
122
122
 
123
+ `targets` is declared once per instrument and called once per trial, with the
124
+ asking trial as its third argument: `targets(state, config, trial)`. `trial.id`
125
+ is the id `useTileId` scopes a surface tile under, so a consumer holding its own
126
+ per-trial refs keys them by it and hands back the ones this trial owns; a
127
+ module-level ref like the one above is one ref shared by every trial of the
128
+ instrument, which only shows once a second trial is open. `trial.view` is that
129
+ trial's camera.
130
+
123
131
  Marks live in the trial's record and survive a reload. An instrument that would
124
132
  rather keep them in a format it already owns declares `annotations.storage` with
125
133
  a `load`/`save` pair, and labkit never writes its own slot.
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { RefObject } from 'react';
3
- import { V as ViewTransform, W as WorldFrame } from './frac-X7mWgd7y.js';
3
+ import { V as ViewTransform, W as WorldFrame } from './frac-A4R6v4ld.js';
4
4
 
5
5
  /** One layer of a canvas stack: its id, whether it is currently shown, and how
6
6
  * it paints itself. */
@@ -1,6 +1,6 @@
1
1
  import { ComponentType, ReactNode, RefObject } from 'react';
2
2
  import { R as ResolvedConfig, C as ConfigField, a as ConfigSchema } from './types-lg4TSCb2.js';
3
- import { c as SavedSnapshot } from './types-ChVJJHvk.js';
3
+ import { c as SavedSnapshot, i as TrialInfo } from './types-BbXpvQa8.js';
4
4
  import { J as JobHandle, a as JobCapability } from './types-DJ79Tg5J.js';
5
5
  import { S as Scene } from './weasel-canvas-FJTFi3ZZ.js';
6
6
 
@@ -53,7 +53,10 @@ interface ToolbarItem {
53
53
  pressed?: boolean;
54
54
  /** Render the label beside the glyph rather than only in the tooltip. */
55
55
  showLabel?: boolean;
56
- onActivate: () => void;
56
+ /** Handed the trial's chrome context, so a contribution declared from the
57
+ * lab can reach `ctx.saveSnapshot()` and the rest without the `render`
58
+ * escape. A zero-argument handler stays valid. */
59
+ onActivate: (ctx: TrialChromeContext) => void;
57
60
  }
58
61
  /** A selectable tool in the palette region. */
59
62
  interface ToolItem {
@@ -65,7 +68,7 @@ interface ToolItem {
65
68
  /** A titled block in the sidebar. */
66
69
  interface SidebarSection {
67
70
  title: string;
68
- /** Starts collapsed. The open/closed state itself is the region's. */
71
+ /** Starts collapsed, until the trial remembers a fold of its own. */
69
72
  defaultCollapsed?: boolean;
70
73
  /** Offer the tear-out control. On by default; a section that only makes
71
74
  * sense beside its trial sets this false. */
@@ -79,7 +82,8 @@ interface ViewportControl {
79
82
  icon: IconComponent;
80
83
  label: string;
81
84
  disabled?: boolean;
82
- onActivate: () => void;
85
+ /** Handed the trial's chrome context, as `ToolbarItem.onActivate` is. */
86
+ onActivate: (ctx: TrialChromeContext) => void;
83
87
  }
84
88
  /** A readout in the status bar. */
85
89
  interface StatusReadout {
@@ -139,6 +143,12 @@ type TrialContribution = (ContributionBase & {
139
143
  interface TrialChromeContext {
140
144
  trialId: string;
141
145
  instrumentName: string;
146
+ /** What the title bar reads, which is the instrument's name until something
147
+ * calls `setTitle`. */
148
+ title: string;
149
+ /** Retitle this trial; `null` restores the instrument name. Persisted with
150
+ * the trial, so a title survives a reload. */
151
+ setTitle: (title: string | null) => void;
142
152
  isLastTrial: boolean;
143
153
  /** Null when the trial holds a view that is not the 2D one. */
144
154
  zoom: number | null;
@@ -159,6 +169,13 @@ interface TrialChromeContext {
159
169
  configFields: ConfigField[];
160
170
  config: unknown;
161
171
  setConfig: (key: string, value: unknown) => void;
172
+ /** Which of this trial's collapsible sections are folded. A sidebar
173
+ * section's key is its contribution id; a section *inside* a contribution —
174
+ * a control panel's property group — is keyed `<contribution id>/<label>`.
175
+ * A section absent here is at its own default. Persisted with the trial. */
176
+ collapsedSections: Readonly<Record<string, boolean>>;
177
+ /** Fold or unfold one section, keyed as `collapsedSections` is. */
178
+ setSectionCollapsed: (key: string, collapsed: boolean) => void;
162
179
  /** Section ids this trial currently has torn out of its sidebar. */
163
180
  undockedPanels: readonly string[];
164
181
  /** Tear a sidebar section out into the workspace. */
@@ -283,11 +300,9 @@ interface RenderContext<TS = unknown, TC = unknown> {
283
300
  config: TC;
284
301
  setState: (next: TS | ((prev: TS) => TS)) => void;
285
302
  setConfig: (key: keyof TC, value: unknown) => void;
286
- trial: {
287
- id: string;
288
- /** The trial's view, in whatever shape this instrument chose. labkit persists
289
- * it and restores it on Reset without ever reading into it. */
290
- view: unknown;
303
+ /** labkit persists `view` and restores it on Reset without ever reading
304
+ * into it. */
305
+ trial: TrialInfo & {
291
306
  setView: (next: unknown) => void;
292
307
  /** 2D convenience over `view`. Reads 1 and writes nothing when the trial holds
293
308
  * a view that is not the 2D one. */
@@ -641,7 +656,9 @@ interface AnnotationStorage {
641
656
  /** Declares that an instrument accepts marks: which regions take them,
642
657
  * optionally what a mark is allowed to mean, and optionally where they live. */
643
658
  interface AnnotationsCapability<TS = unknown, TC = unknown> {
644
- targets: (state: TS, config: TC) => readonly AnnotationTarget[];
659
+ /** `trial` is which trial is asking: a declaration made once per instrument
660
+ * is called once per trial, and its targets are that trial's own. */
661
+ targets: (state: TS, config: TC, trial: TrialInfo) => readonly AnnotationTarget[];
645
662
  meaning?: AnnotationMeaning;
646
663
  storage?: AnnotationStorage;
647
664
  /** Fires after every finished export, labkit's own chrome included. A
@@ -2,19 +2,43 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { R as ResolvedConfig, C as ConfigField, c as ControlRenderer } from './types-lg4TSCb2.js';
4
4
 
5
+ /**
6
+ * How much room a container gives its rows — gaps, padding, and field height,
7
+ * moved together. Set on any container in the family; it reaches every
8
+ * descendant, so an inner group can differ from the panel around it.
9
+ */
10
+ type PropertyDensity = 'tight' | 'normal' | 'roomy';
11
+ /** Where an inline row's label and control sit on the row's cross axis. Set on
12
+ * a container to line a whole column of them up. */
13
+ type PropertyAlign = 'start' | 'center' | 'end' | 'baseline';
14
+ /** Metric props every container in the family takes. Both reach descendants,
15
+ * so the nearest container that states one wins. */
16
+ interface PropertyMetricProps {
17
+ /** Room the rows get. Unset inherits from an outer container, else `normal`. */
18
+ density?: PropertyDensity;
19
+ /**
20
+ * Cross-axis alignment of an inline row's label and control. `baseline` sits
21
+ * the control on the label's first-line baseline, which is what lines a
22
+ * column of swatches up against labels of different heights. Unset keeps each
23
+ * variant's own alignment — a color row centers its label and swatch and
24
+ * sinks the pair to the row's bottom edge, which keeps a paired alpha track
25
+ * level with its neighbour.
26
+ */
27
+ align?: PropertyAlign;
28
+ }
5
29
  /** Props for `<PropertyPanel>`. */
6
- interface PropertyPanelProps {
30
+ interface PropertyPanelProps extends PropertyMetricProps {
7
31
  title?: ReactNode;
8
32
  children: ReactNode;
9
33
  className?: string;
10
34
  }
11
35
  /** A titled panel holding property rows — the sidebar container the rest of
12
36
  * this module's components fill. */
13
- declare function PropertyPanel({ title, children, className }: PropertyPanelProps): react_jsx_runtime.JSX.Element;
37
+ declare function PropertyPanel({ title, children, className, density, align, }: PropertyPanelProps): react_jsx_runtime.JSX.Element;
14
38
  /** How a property list packs its rows into two columns. */
15
- type PropertyListPack = 'auto-color' | 'pairs';
39
+ type PropertyListPack = 'auto-color' | 'pairs' | 'one-up';
16
40
  /** Props for `<PropertyList>`. */
17
- interface PropertyListProps {
41
+ interface PropertyListProps extends PropertyMetricProps {
18
42
  children: ReactNode;
19
43
  className?: string;
20
44
  /**
@@ -24,6 +48,8 @@ interface PropertyListProps {
24
48
  * - `'pairs'`: every row auto-places into the 2-column grid two-per-row.
25
49
  * Headers and subpanels still span the full width; wrap any other
26
50
  * full-width child in `<PropertySpan>`. Right for dense effect bodies.
51
+ * - `'one-up'`: every row spans the full width, color rows included. Right
52
+ * for a palette — a column of swatches read as a group.
27
53
  */
28
54
  pack?: PropertyListPack;
29
55
  }
@@ -31,7 +57,7 @@ interface PropertyListProps {
31
57
  * Grid container for PropertyRows. Use standalone for chrome-less layouts, or
32
58
  * nest inside <PropertyPanel/> for the standard glass card.
33
59
  */
34
- declare function PropertyList({ children, className, pack }: PropertyListProps): react_jsx_runtime.JSX.Element;
60
+ declare function PropertyList({ children, className, pack, density, align, }: PropertyListProps): react_jsx_runtime.JSX.Element;
35
61
  /** Props for `<PropertySpan>`. */
36
62
  interface PropertySpanProps {
37
63
  children: ReactNode;
@@ -49,7 +75,7 @@ type PropertyRowVariant = 'default' | 'color' | 'checkbox';
49
75
  /** Whether a row's label sits above its control or beside it. */
50
76
  type PropertyRowLayout = 'block' | 'inline';
51
77
  /** Props for `<PropertyRow>`. */
52
- interface PropertyRowProps {
78
+ interface PropertyRowProps extends PropertyMetricProps {
53
79
  label: ReactNode;
54
80
  /** Right-aligned readout shown next to the label (e.g. current value). */
55
81
  readout?: ReactNode;
@@ -60,9 +86,9 @@ interface PropertyRowProps {
60
86
  description?: string;
61
87
  variant?: PropertyRowVariant;
62
88
  /**
63
- * Label position relative to the control. "block" (default) stacks
64
- * label above control; "inline" places the label to the left.
65
- * Color and checkbox variants are always inline by their own nature.
89
+ * Label position relative to the control. Unset takes the variant's own
90
+ * orientation: `block` — label above control — for the default variant, and
91
+ * `inline` for the color and checkbox variants, which read as a row.
66
92
  */
67
93
  layout?: PropertyRowLayout;
68
94
  /**
@@ -77,15 +103,26 @@ interface PropertyRowProps {
77
103
  }
78
104
  /** The label-plus-control frame every typed row below is built from. Use it
79
105
  * directly for a control this module does not cover. */
80
- declare function PropertyRow({ label, readout, description, variant, layout, span, children, htmlFor, className, }: PropertyRowProps): react_jsx_runtime.JSX.Element;
106
+ declare function PropertyRow({ label, readout, description, variant, layout, span, children, htmlFor, className, density, align, }: PropertyRowProps): react_jsx_runtime.JSX.Element;
81
107
  /** Props for `<SliderRow>`. */
82
- interface SliderRowProps {
108
+ interface SliderRowProps extends PropertyMetricProps {
83
109
  label: ReactNode;
84
110
  value: number;
85
111
  min: number;
86
112
  max: number;
87
113
  step?: number;
114
+ /**
115
+ * The committed value. Given `onInput` as well, it fires once a drag ends
116
+ * or a typed readout is accepted; on its own it fires on every move, which
117
+ * is what a row with one callback has always done.
118
+ */
88
119
  onChange: (next: number) => void;
120
+ /**
121
+ * The live value, fired continuously through a drag. Pass it alongside
122
+ * `onChange` when the write is expensive — cheap state here, the costly
123
+ * work there. Mirrors `<Slider>`'s `onInput` / `onChange` pair.
124
+ */
125
+ onInput?: (next: number) => void;
89
126
  /** Override how the value is rendered next to the label. Defaults to `value.toString()`. */
90
127
  format?: (value: number) => ReactNode;
91
128
  /**
@@ -101,9 +138,9 @@ interface SliderRowProps {
101
138
  }
102
139
  /** A bounded number edited by dragging, with a live readout whose precision
103
140
  * follows `step`. */
104
- declare function SliderRow({ label, value, min, max, step, onChange, format, unit, layout, description, span, }: SliderRowProps): react_jsx_runtime.JSX.Element;
141
+ declare function SliderRow({ label, value, min, max, step, onChange, onInput, format, unit, layout, description, span, density, align, }: SliderRowProps): react_jsx_runtime.JSX.Element;
105
142
  /** Props for `<ColorRow>`. */
106
- interface ColorRowProps {
143
+ interface ColorRowProps extends PropertyMetricProps {
107
144
  label: ReactNode;
108
145
  value: string;
109
146
  onChange: (next: string) => void;
@@ -115,25 +152,29 @@ interface ColorRowProps {
115
152
  * Use when the color's consumer drops alpha so the affordance reads dead.
116
153
  */
117
154
  alphaDisabled?: boolean;
155
+ /** Label beside the swatch (default) or above it. */
156
+ layout?: PropertyRowLayout;
118
157
  description?: string;
119
158
  /** Take the full width of the enclosing grid — see `<PropertyRow span>`. */
120
159
  span?: boolean;
121
160
  }
122
161
  /** A color swatch, optionally with an alpha slider beneath it. */
123
- declare function ColorRow({ label, value, onChange, alpha, onAlphaChange, alphaDisabled, description, span, }: ColorRowProps): react_jsx_runtime.JSX.Element;
162
+ declare function ColorRow({ label, value, onChange, alpha, onAlphaChange, alphaDisabled, layout, description, span, density, align, }: ColorRowProps): react_jsx_runtime.JSX.Element;
124
163
  /** Props for `<CheckboxRow>`. */
125
- interface CheckboxRowProps {
164
+ interface CheckboxRowProps extends PropertyMetricProps {
126
165
  label: ReactNode;
127
166
  value: boolean;
128
167
  onChange: (next: boolean) => void;
168
+ /** Label beside the box (default) or above it. */
169
+ layout?: PropertyRowLayout;
129
170
  description?: string;
130
171
  /** Take the full width of the enclosing grid — see `<PropertyRow span>`. */
131
172
  span?: boolean;
132
173
  }
133
174
  /** A boolean checkbox. */
134
- declare function CheckboxRow({ label, value, onChange, span, description }: CheckboxRowProps): react_jsx_runtime.JSX.Element;
175
+ declare function CheckboxRow({ label, value, onChange, layout, span, description, density, align, }: CheckboxRowProps): react_jsx_runtime.JSX.Element;
135
176
  /** Props for `<TextRow>`. */
136
- interface TextRowProps {
177
+ interface TextRowProps extends PropertyMetricProps {
137
178
  label: ReactNode;
138
179
  value: string;
139
180
  onChange: (next: string) => void;
@@ -145,9 +186,9 @@ interface TextRowProps {
145
186
  span?: boolean;
146
187
  }
147
188
  /** A single-line text input. */
148
- declare function TextRow({ label, value, onChange, placeholder, maxLength, layout, description, span, }: TextRowProps): react_jsx_runtime.JSX.Element;
189
+ declare function TextRow({ label, value, onChange, placeholder, maxLength, layout, description, span, density, align, }: TextRowProps): react_jsx_runtime.JSX.Element;
149
190
  /** Props for `<NumberRow>`. */
150
- interface NumberRowProps {
191
+ interface NumberRowProps extends PropertyMetricProps {
151
192
  label: ReactNode;
152
193
  value: number;
153
194
  onChange: (next: number) => void;
@@ -168,13 +209,13 @@ interface NumberRowProps {
168
209
  }
169
210
  /** A number typed directly. Reach for `<SliderRow>` when the range matters
170
211
  * more than the exact value. */
171
- declare function NumberRow({ label, value, onChange, min, max, step, placeholder, unit, layout, description, span, }: NumberRowProps): react_jsx_runtime.JSX.Element;
212
+ declare function NumberRow({ label, value, onChange, min, max, step, placeholder, unit, layout, description, span, density, align, }: NumberRowProps): react_jsx_runtime.JSX.Element;
172
213
  interface PropertyOption<T extends string> {
173
214
  value: T;
174
215
  label: ReactNode;
175
216
  }
176
217
  /** Props for `<SelectRow>`. */
177
- interface SelectRowProps<T extends string> {
218
+ interface SelectRowProps<T extends string> extends PropertyMetricProps {
178
219
  label: ReactNode;
179
220
  value: T;
180
221
  options: ReadonlyArray<PropertyOption<T>>;
@@ -186,9 +227,9 @@ interface SelectRowProps<T extends string> {
186
227
  }
187
228
  /** A dropdown over a fixed set of choices. Prefer `<ToggleRow>` when there
188
229
  * are only two or three and they should all stay visible. */
189
- declare function SelectRow<T extends string>({ label, value, options, onChange, layout, description, span, }: SelectRowProps<T>): react_jsx_runtime.JSX.Element;
230
+ declare function SelectRow<T extends string>({ label, value, options, onChange, layout, description, span, density, align, }: SelectRowProps<T>): react_jsx_runtime.JSX.Element;
190
231
  /** Props for `<ToggleRow>`. */
191
- interface ToggleRowProps<T extends string> {
232
+ interface ToggleRowProps<T extends string> extends PropertyMetricProps {
192
233
  label: ReactNode;
193
234
  value: T;
194
235
  options: ReadonlyArray<PropertyOption<T>>;
@@ -200,7 +241,7 @@ interface ToggleRowProps<T extends string> {
200
241
  }
201
242
  /** A segmented control: the same choice as a select, with every option
202
243
  * visible at once. */
203
- declare function ToggleRow<T extends string>({ label, value, options, onChange, layout, description, span, }: ToggleRowProps<T>): react_jsx_runtime.JSX.Element;
244
+ declare function ToggleRow<T extends string>({ label, value, options, onChange, layout, description, span, density, align, }: ToggleRowProps<T>): react_jsx_runtime.JSX.Element;
204
245
 
205
246
  /** How a panel packs its rows into the two-column property grid.
206
247
  * - `'auto'`: narrow controls (numbers, checkboxes, dropdowns, colours) sit
@@ -226,9 +267,28 @@ interface ControlPanelProps<TC extends Record<string, unknown>> {
226
267
  renderers?: Record<string, ControlRenderer>;
227
268
  /** How rows pack into the two-column grid. Defaults to `'pairs'`. */
228
269
  pack?: ControlPack;
229
- /** Where a row's label sits relative to its control. Defaults to `'block'`
230
- * — above it, which is what leaves a paired row room for its value. */
270
+ /**
271
+ * Where a row's label sits relative to its control. Unset takes each row's
272
+ * own orientation — `block` (label above, which is what leaves a paired row
273
+ * room for its value) for most, `inline` for colors and checkboxes.
274
+ */
231
275
  layout?: PropertyRowLayout;
276
+ /** Room the rows get. Passed straight to the property list. */
277
+ density?: PropertyDensity;
278
+ /** Cross-axis alignment of an inline row's label and control. */
279
+ align?: PropertyAlign;
280
+ /**
281
+ * Fold each section away behind a twisty, starting `'open'` or `'closed'`.
282
+ * Unset draws the heading alone, as the panel always has.
283
+ */
284
+ collapse?: 'open' | 'closed';
285
+ /**
286
+ * Which sections are folded, keyed by section label. Given, the panel keeps
287
+ * no state of its own: every toggle arrives at `onCollapse` instead, which
288
+ * is where a lab that remembers a trial's sections writes them.
289
+ */
290
+ collapsed?: Readonly<Record<string, boolean>>;
291
+ onCollapse?: (label: string, collapsed: boolean) => void;
232
292
  /** Draw leaves marked `hidden`. */
233
293
  showHidden?: boolean;
234
294
  className?: string;
@@ -236,7 +296,7 @@ interface ControlPanelProps<TC extends Record<string, unknown>> {
236
296
  /** Render an instrument's config schema as a stack of controls, each writing
237
297
  * back through `setConfig`. Built on the property rows, so a lab's controls
238
298
  * are the same aligned, themed rows the rest of the kit uses. */
239
- declare function ControlPanel<TC extends Record<string, unknown>>({ schema, fields, config, setConfig, renderers, pack, layout, showHidden, className, }: ControlPanelProps<TC>): react_jsx_runtime.JSX.Element;
299
+ declare function ControlPanel<TC extends Record<string, unknown>>({ schema, fields, config, setConfig, renderers, pack, layout, density, align, collapse, collapsed, onCollapse, showHidden, className, }: ControlPanelProps<TC>): react_jsx_runtime.JSX.Element;
240
300
 
241
- export { CheckboxRow as C, NumberRow as N, PropertyList as P, SelectRow as S, TextRow as T, ColorRow as b, ControlPanel as d, PropertyPanel as i, PropertyRow as k, PropertySpan as o, SliderRow as r, ToggleRow as u };
242
- export type { CheckboxRowProps as a, ColorRowProps as c, NumberRowProps as e, PropertyListPack as f, PropertyListProps as g, PropertyOption as h, PropertyPanelProps as j, PropertyRowLayout as l, PropertyRowProps as m, PropertyRowVariant as n, PropertySpanProps as p, SelectRowProps as q, SliderRowProps as s, TextRowProps as t, ToggleRowProps as v };
301
+ export { CheckboxRow as C, NumberRow as N, SelectRow as S, TextRow as T, ColorRow as c, ControlPanel as e, PropertyList as g, PropertyPanel as j, PropertyRow as l, PropertySpan as p, SliderRow as s, ToggleRow as v };
302
+ export type { PropertyMetricProps as P, PropertyListPack as a, CheckboxRowProps as b, ColorRowProps as d, NumberRowProps as f, PropertyListProps as h, PropertyOption as i, PropertyPanelProps as k, PropertyRowLayout as m, PropertyRowProps as n, PropertyRowVariant as o, PropertySpanProps as q, SelectRowProps as r, SliderRowProps as t, TextRowProps as u, ToggleRowProps as w };
@@ -18,6 +18,14 @@ interface UndoStack {
18
18
  past: unknown[];
19
19
  future: unknown[];
20
20
  }
21
+ /** The trial a per-trial call is coming from. `id` is the id `useTileId`
22
+ * scopes a surface tile under, so a consumer keying its own per-trial
23
+ * registry and labkit's tiles agree on the key. */
24
+ interface TrialInfo<TV = unknown> {
25
+ id: string;
26
+ /** The trial's view, in whatever shape the instrument keeps it. */
27
+ view: TV;
28
+ }
21
29
  /** One trial as the store holds it: which instrument it runs, that
22
30
  * instrument's config and state, the camera, and the undo history. */
23
31
  interface TrialRecord<TS = unknown, TC = unknown, TV = unknown> {
@@ -28,11 +36,22 @@ interface TrialRecord<TS = unknown, TC = unknown, TV = unknown> {
28
36
  /** Opaque to labkit: persisted, restored on Reset and handed to the instrument,
29
37
  * but never read into. A 3D lab puts an orbit here and keeps all three. */
30
38
  view: TV;
39
+ /** The config `addTrial` opened this trial on, overlaid on the instrument's
40
+ * defaults. Kept so Reset restores the trial's own subject rather than the
41
+ * bare defaults. */
42
+ configSeed?: Partial<TC>;
31
43
  /** This trial's own tool slot. Undefined means it reads the lab's. */
32
44
  activeToolId?: string | null;
33
45
  /** The extent the trial's sidebar was last dragged to, in pixels. Undefined
34
46
  * until someone moves the seam. */
35
47
  sidebarWidth?: number;
48
+ /** What the title bar reads. Undefined — the state a trial opens in, and the
49
+ * one `setTitle(null)` returns it to — means the instrument's name. */
50
+ title?: string | null;
51
+ /** Which of the trial's collapsible sections are folded, keyed as
52
+ * `TrialChromeContext.collapsedSections` describes. A key that is absent
53
+ * takes the section's own default. */
54
+ collapsedSections?: Record<string, boolean>;
36
55
  /** The marks on this trial's annotation targets, as `AnnotationsApi.toJSON`
37
56
  * wrote them. Opaque here, and absent for a trial whose instrument declares
38
57
  * no `annotations` — or declares its own `storage`. Not in `state`, which
@@ -115,4 +134,4 @@ interface LabDocument {
115
134
  type Migration = (doc: Record<string, unknown>) => Record<string, unknown>;
116
135
 
117
136
  export { dockPanel as g, panelKey as p, undockPanel as u };
118
- export type { CreateLabStoreOptions as C, InstrumentSerializers as I, LabDocument as L, Migration as M, SerializedTrial as S, TrialRecord as T, UndoStack as U, StorageAdapter as a, LabStoreState as b, SavedSnapshot as c, TrialStateHandle as d, UndockedPanel as e, UndockedPanels as f, LabMode as h };
137
+ export type { CreateLabStoreOptions as C, InstrumentSerializers as I, LabDocument as L, Migration as M, SerializedTrial as S, TrialRecord as T, UndoStack as U, StorageAdapter as a, LabStoreState as b, SavedSnapshot as c, TrialStateHandle as d, UndockedPanel as e, UndockedPanels as f, LabMode as h, TrialInfo as i };
@@ -1,4 +1,4 @@
1
- import { a as StorageAdapter, b as LabStoreState, T as TrialRecord, c as SavedSnapshot, h as LabMode, e as UndockedPanel, I as InstrumentSerializers, C as CreateLabStoreOptions, d as TrialStateHandle } from './types-ChVJJHvk.js';
1
+ import { a as StorageAdapter, b as LabStoreState, T as TrialRecord, c as SavedSnapshot, h as LabMode, e as UndockedPanel, I as InstrumentSerializers, C as CreateLabStoreOptions, d as TrialStateHandle } from './types-BbXpvQa8.js';
2
2
  import * as react from 'react';
3
3
  import { ReactNode, ReactElement } from 'react';
4
4
  import { StoreApi } from 'zustand/vanilla';
@@ -26,6 +26,10 @@ interface LabStoreActions {
26
26
  updateTrialConfig: <TC>(id: string, key: keyof TC, value: TC[keyof TC]) => void;
27
27
  updateTrialView: (id: string, view: unknown) => void;
28
28
  updateTrialSidebarWidth: (id: string, width: number) => void;
29
+ /** Retitle a trial. `null` returns it to its instrument's name. */
30
+ setTrialTitle: (id: string, title: string | null) => void;
31
+ /** Fold or unfold one of a trial's sections. */
32
+ setTrialSectionCollapsed: (id: string, key: string, collapsed: boolean) => void;
29
33
  updateTrialAnnotations: (id: string, doc: unknown) => void;
30
34
  updateTrialUndoStack: (id: string, next: TrialRecord['undoStack'] | ((prev: TrialRecord['undoStack']) => TrialRecord['undoStack'])) => void;
31
35
  setTrialInstrument: (id: string, instrumentName: string) => void;
@@ -1,13 +1,13 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, WheelEvent, PointerEvent as PointerEvent$1 } from 'react';
3
- import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-X7mWgd7y.js';
4
- export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-X7mWgd7y.js';
5
- import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-BIRUVVGH.js';
6
- export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-BIRUVVGH.js';
3
+ import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-A4R6v4ld.js';
4
+ export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-A4R6v4ld.js';
5
+ import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-kjILVnPj.js';
6
+ export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-kjILVnPj.js';
7
7
  import '../_dts/types-lg4TSCb2.js';
8
8
  import '../_dts/weasel-canvas-FJTFi3ZZ.js';
9
9
  import '../_dts/PrefsForm.d-CgxUequc.js';
10
- import '../_dts/types-ChVJJHvk.js';
10
+ import '../_dts/types-BbXpvQa8.js';
11
11
  import '../_dts/types-DJ79Tg5J.js';
12
12
 
13
13
  /** Props for `<CanvasStack>`. */
@@ -1,7 +1,7 @@
1
- export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-PP7ZWAMV.js';
1
+ export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-FJG4PHTL.js';
2
2
  export { centerOn, zoomAt } from '../chunk-CTRKTLYZ.js';
3
3
  export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from '../chunk-2AYGEN57.js';
4
4
  export { CanvasStackContext } from '../chunk-CQLQPQ4P.js';
5
- import '../chunk-DG2IFMLA.js';
5
+ import '../chunk-54ZWZ5FQ.js';
6
6
  //# sourceMappingURL=index.js.map
7
7
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,11 @@
1
1
  import { c as ControlRenderer } from '../_dts/types-lg4TSCb2.js';
2
- import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-X7mWgd7y.js';
3
- export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-X7mWgd7y.js';
2
+ import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-A4R6v4ld.js';
3
+ export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-A4R6v4ld.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import '../_dts/weasel-canvas-FJTFi3ZZ.js';
6
6
  import 'react';
7
7
  import '../_dts/PrefsForm.d-CgxUequc.js';
8
- import '../_dts/types-ChVJJHvk.js';
8
+ import '../_dts/types-BbXpvQa8.js';
9
9
  import '../_dts/types-DJ79Tg5J.js';
10
10
 
11
11
  /**
@@ -58,13 +58,19 @@ interface StatusRegionProps {
58
58
  /** Lays a trial's `status` contributions out as readouts. */
59
59
  declare function StatusRegion({ contributions, ctx }: StatusRegionProps): react_jsx_runtime.JSX.Element | null;
60
60
 
61
+ /** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders
62
+ * the contributions that leave `end` unset, before the title; `'actions'`
63
+ * renders the ones that set it, after everything else. */
64
+ type TitleBarPlacement = 'lead' | 'actions';
61
65
  /** Props for `<TitleBarRegion>`. */
62
66
  interface TitleBarRegionProps {
63
67
  contributions: readonly TrialContribution[];
64
68
  ctx: TrialChromeContext;
69
+ /** Defaults to `'actions'`, where the built-ins live. */
70
+ placement?: TitleBarPlacement;
65
71
  }
66
- /** Lays a trial's `titlebar` contributions out, at the far end of the bar. */
67
- declare function TitleBarRegion({ contributions, ctx }: TitleBarRegionProps): react_jsx_runtime.JSX.Element | null;
72
+ /** Lays a trial's `titlebar` contributions out at one end of the bar. */
73
+ declare function TitleBarRegion({ contributions, ctx, placement }: TitleBarRegionProps): react_jsx_runtime.JSX.Element | null;
68
74
 
69
75
  /** Props for `<ToolbarRegion>`. */
70
76
  interface ToolbarRegionProps {
@@ -86,4 +92,4 @@ interface ViewportRegionProps {
86
92
  declare function ViewportRegion({ contributions, ctx }: ViewportRegionProps): react_jsx_runtime.JSX.Element | null;
87
93
 
88
94
  export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, TrialChromeContext, TrialContribution, ViewportRegion, builtinContributions, mergeContributions, suppressContributions };
89
- export type { PaletteRegionProps, SidebarRegionProps, StatusRegionProps, TitleBarRegionProps, ToolbarRegionProps, ViewportRegionProps };
95
+ export type { PaletteRegionProps, SidebarRegionProps, StatusRegionProps, TitleBarPlacement, TitleBarRegionProps, ToolbarRegionProps, ViewportRegionProps };
@@ -1,9 +1,9 @@
1
- export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-BMQWLKOL.js';
2
- import '../chunk-MSR7EVS6.js';
3
- import '../chunk-53AZ2O2N.js';
1
+ export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-W2FJR5FF.js';
2
+ import '../chunk-UTOEDPNU.js';
3
+ import '../chunk-XKENZTNE.js';
4
4
  import '../chunk-SBXNQW4G.js';
5
- import '../chunk-J6SBFZYT.js';
5
+ import '../chunk-ISSVF5PT.js';
6
6
  import '../chunk-CQLQPQ4P.js';
7
- import '../chunk-DG2IFMLA.js';
7
+ import '../chunk-54ZWZ5FQ.js';
8
8
  //# sourceMappingURL=index.js.map
9
9
  //# sourceMappingURL=index.js.map