@weasel-js/labkit 1.0.4 → 1.2.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 (122) hide show
  1. package/README.md +33 -6
  2. package/dist/_dts/{DrawCommand-BkZztJsW.d.ts → DrawCommand-C_XboUpz.d.ts} +48 -6
  3. package/dist/_dts/{index-CFlDPeZh.d.ts → index-JFAYj5Tv.d.ts} +29 -7
  4. package/dist/_dts/types-DJ79Tg5J.d.ts +56 -0
  5. package/dist/_dts/useTrialState-BMNIx3Cy.d.ts +171 -0
  6. package/dist/canvas/index.d.ts +2 -1
  7. package/dist/{chunk-BAPZPDDA.js → chunk-73KA7WBO.js} +425 -394
  8. package/dist/chunk-73KA7WBO.js.map +1 -0
  9. package/dist/{chunk-DWV7SFKR.js → chunk-BOHF3PQO.js} +4397 -3726
  10. package/dist/chunk-BOHF3PQO.js.map +1 -0
  11. package/dist/{chunk-DEWXYFEU.js → chunk-G5TJVQQT.js} +3 -3
  12. package/dist/{chunk-DEWXYFEU.js.map → chunk-G5TJVQQT.js.map} +1 -1
  13. package/dist/chunk-LN6JDUGB.js +106 -0
  14. package/dist/chunk-LN6JDUGB.js.map +1 -0
  15. package/dist/chunk-THBG7FQZ.js +167 -0
  16. package/dist/chunk-THBG7FQZ.js.map +1 -0
  17. package/dist/chunk-VUU5UXHE.js +491 -0
  18. package/dist/chunk-VUU5UXHE.js.map +1 -0
  19. package/dist/dragdrop/index.d.ts +2 -1
  20. package/dist/index.d.ts +211 -151
  21. package/dist/index.js +317 -169
  22. package/dist/index.js.map +1 -1
  23. package/dist/job/index.d.ts +13 -0
  24. package/dist/job/index.js +3 -0
  25. package/dist/job/index.js.map +1 -0
  26. package/dist/layers/index.d.ts +3 -2
  27. package/dist/passthrough/weasel-canvas.d.ts +1 -1
  28. package/dist/passthrough/weasel-canvas.js +1 -1
  29. package/dist/passthrough/weasel-ui.d.ts +29 -6
  30. package/dist/passthrough/weasel-ui.js +2 -2
  31. package/dist/state/index.d.ts +12 -12
  32. package/dist/state/index.js +5 -5
  33. package/dist/state/index.js.map +1 -1
  34. package/dist/styles.css +31 -13
  35. package/dist/surface/index.d.ts +77 -0
  36. package/dist/surface/index.js +3 -0
  37. package/dist/surface/index.js.map +1 -0
  38. package/dist/ui/layers/index.js +3 -3
  39. package/dist/undo/index.d.ts +2 -1
  40. package/package.json +9 -1
  41. package/src/canvas/AGENTS.md +14 -2
  42. package/src/canvas/useOrbit.test.ts +71 -0
  43. package/src/canvas/useOrbit.ts +149 -0
  44. package/src/dragdrop/dragDrop.test.tsx +4 -7
  45. package/src/index.test.ts +70 -0
  46. package/src/index.ts +24 -7
  47. package/src/instrument/SineWave.smoke.test.tsx +2 -1
  48. package/src/instrument/capabilityDetector.ts +1 -1
  49. package/src/instrument/types.ts +30 -6
  50. package/src/job/index.ts +3 -0
  51. package/src/job/types.ts +47 -0
  52. package/src/job/useJob.test.tsx +210 -0
  53. package/src/job/useJob.ts +134 -0
  54. package/src/lab/Lab.less +16 -0
  55. package/src/lab/Lab.stories.tsx +6 -7
  56. package/src/lab/Lab.test.tsx +25 -25
  57. package/src/lab/Lab.tsx +50 -50
  58. package/src/lab/LabContext.ts +12 -12
  59. package/src/lab/LabShell.tsx +1 -1
  60. package/src/lab/{WorkspaceGrid.less → Workspace.less} +2 -2
  61. package/src/lab/{WorkspaceGrid.stories.tsx → Workspace.stories.tsx} +13 -13
  62. package/src/lab/Workspace.surface.test.tsx +49 -0
  63. package/src/lab/{WorkspaceGrid.test.tsx → Workspace.test.tsx} +24 -24
  64. package/src/lab/{WorkspaceGrid.tsx → Workspace.tsx} +32 -19
  65. package/src/lab/index.ts +2 -2
  66. package/src/layers/AGENTS.md +3 -3
  67. package/src/primitives/Toolbar.stories.tsx +2 -2
  68. package/src/state/SingletonExperiment.test.tsx +8 -8
  69. package/src/state/SingletonExperiment.tsx +9 -9
  70. package/src/state/context.tsx +12 -12
  71. package/src/state/document.test.ts +369 -0
  72. package/src/state/document.ts +194 -0
  73. package/src/state/helpers.test.ts +74 -46
  74. package/src/state/helpers.ts +21 -29
  75. package/src/state/index.ts +16 -8
  76. package/src/state/store.test.ts +440 -41
  77. package/src/state/store.ts +165 -102
  78. package/src/state/types.ts +32 -13
  79. package/src/state/{useExperimentState.test.tsx → useTrialState.test.tsx} +18 -18
  80. package/src/state/useTrialState.ts +29 -0
  81. package/src/state/view.test.ts +127 -0
  82. package/src/state/view.ts +18 -0
  83. package/src/styles.less +2 -2
  84. package/src/surface/AGENTS.md +64 -0
  85. package/src/surface/SurfaceContext.ts +5 -0
  86. package/src/surface/composeRects.test.ts +50 -0
  87. package/src/surface/composeRects.ts +19 -0
  88. package/src/surface/deviceRect.test.ts +40 -0
  89. package/src/surface/deviceRect.ts +19 -0
  90. package/src/surface/index.ts +7 -0
  91. package/src/surface/rect.ts +16 -0
  92. package/src/surface/useSurfaceTile.test.tsx +67 -0
  93. package/src/surface/useSurfaceTile.ts +32 -0
  94. package/src/surface/useTiledSurface.test.tsx +231 -0
  95. package/src/surface/useTiledSurface.ts +157 -0
  96. package/src/theme/base.less +1 -1
  97. package/src/{workspace → trial}/DefaultSidebar.tsx +3 -3
  98. package/src/trial/DefaultStatusBar.tsx +19 -0
  99. package/src/{workspace → trial}/DefaultToolbar.tsx +9 -8
  100. package/src/trial/Trial.canvas.test.tsx +80 -0
  101. package/src/trial/Trial.job.test.tsx +75 -0
  102. package/src/{workspace/Workspace.less → trial/Trial.less} +13 -1
  103. package/src/{workspace/Workspace.stories.tsx → trial/Trial.stories.tsx} +20 -18
  104. package/src/{workspace/Workspace.test.tsx → trial/Trial.test.tsx} +26 -26
  105. package/src/{workspace/Workspace.tsx → trial/Trial.tsx} +77 -46
  106. package/src/{workspace/WorkspaceChrome.tsx → trial/TrialChrome.tsx} +73 -46
  107. package/src/{workspace → trial}/index.ts +13 -13
  108. package/src/{workspace → trial}/slotTypes.ts +18 -17
  109. package/src/{workspace/workspaceOps.test.ts → trial/trialOps.test.ts} +38 -44
  110. package/src/trial/trialOps.ts +99 -0
  111. package/src/ui/format.test.ts +33 -0
  112. package/src/ui/format.ts +11 -0
  113. package/src/ui/properties/CurveField.tsx +6 -6
  114. package/src/ui/properties/SpeechBalloonPanels.stories.tsx +3 -3
  115. package/dist/_dts/useExperimentState-D7EQnnwJ.d.ts +0 -151
  116. package/dist/chunk-BAPZPDDA.js.map +0 -1
  117. package/dist/chunk-DWV7SFKR.js.map +0 -1
  118. package/dist/chunk-KSTEW2AF.js +0 -367
  119. package/dist/chunk-KSTEW2AF.js.map +0 -1
  120. package/src/state/useExperimentState.ts +0 -31
  121. package/src/workspace/DefaultStatusBar.tsx +0 -18
  122. package/src/workspace/workspaceOps.ts +0 -102
package/dist/index.d.ts CHANGED
@@ -1,21 +1,70 @@
1
1
  export { CanvasLayerDescriptor, CanvasStack, CanvasStackContext, CanvasStackContextValue, CanvasStackProps, screenToWorld, worldToScreen } from './canvas/index.js';
2
+ import * as react from 'react';
3
+ import { WheelEvent, PointerEvent, ReactNode } from 'react';
2
4
  export { ControlPanel } from './controls/index.js';
3
5
  import { C as ConfigField } from './_dts/types-x92Kfeme.js';
4
6
  export { a as CheckboxField, b as ColorField, c as ConfigFieldBase, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from './_dts/types-x92Kfeme.js';
5
- import { I as Instrument } from './_dts/index-CFlDPeZh.js';
6
- export { C as CanvasCapability, a as CanvasLayer, D as DragDropCapability, b as DragFeedback, H as HitResult, L as LayerCapability, c as LayerDescriptor, P as PaletteItem, d as Point, R as RenderContext, S as SystemEvent, U as UndoCapability, V as ViewTransform } from './_dts/index-CFlDPeZh.js';
7
+ import { I as Instrument, a as InstrumentList, V as ViewTransform } from './_dts/index-JFAYj5Tv.js';
8
+ export { C as CanvasCapability, b as CanvasLayer, D as DragDropCapability, c as DragFeedback, H as HitResult, L as LayerCapability, d as LayerDescriptor, P as PaletteItem, e as Point, R as RenderContext, S as SystemEvent, U as UndoCapability } from './_dts/index-JFAYj5Tv.js';
9
+ import { J as JobHandle } from './_dts/types-DJ79Tg5J.js';
10
+ export { a as JobCapability, b as JobEvent, c as JobFailure, d as JobStatus } from './_dts/types-DJ79Tg5J.js';
11
+ export { UseJobOptions, useJob } from './job/index.js';
7
12
  import * as react_jsx_runtime from 'react/jsx-runtime';
8
- import * as react from 'react';
9
- import { ReactNode } from 'react';
10
- import { S as StorageAdapter, o as LabMode, W as WorkspaceRecord, e as SavedSnapshot } from './_dts/useExperimentState-D7EQnnwJ.js';
11
- export { C as CreateLabStoreOptions, E as ExperimentStateHandle, b as LabStoreContext, c as LabStoreProvider, d as LabStoreState, U as UndoStack, f as WorkspaceIdContext, g as WorkspaceIdProvider, i as createMemoryAdapter, l as localStorageAdapter, n as noneAdapter, s as sessionStorageAdapter, u as urlHashAdapter, j as useExperimentState, k as useLabStore, m as useWorkspaceId } from './_dts/useExperimentState-D7EQnnwJ.js';
13
+ import { a as StorageAdapter, w as LabMode, T as TrialRecord, h as SavedSnapshot } from './_dts/useTrialState-BMNIx3Cy.js';
14
+ export { C as CURRENT_DOCUMENT_VERSION, b as CreateLabStoreOptions, L as LabDocument, e as LabStoreContext, f as LabStoreProvider, g as LabStoreState, S as SerializedTrial, i as TrialIdContext, j as TrialIdProvider, k as TrialStateHandle, U as UndoStack, m as createMemoryAdapter, n as labDocumentKey, o as localStorageAdapter, p as noneAdapter, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, r as useLabStore, t as useTrialId, v as useTrialState } from './_dts/useTrialState-BMNIx3Cy.js';
12
15
  export { LayerList, LayerListProps } from './layers/index.js';
13
16
  export { FpsMeter, ScaleIndicator, ScaleIndicatorProps, Sidebar, SidebarProps, StatusBar, StatusBarProps, Toolbar, ToolbarProps } from './primitives/index.js';
17
+ export { Box, Rect, SurfaceContext, SurfaceFrame, SurfaceHandle, UseTiledSurfaceOptions, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceOptional, useSurfaceTile, useTiledSurface } from './surface/index.js';
14
18
  export { LayerStack, LayerStackItem, LayerStackProps } from './ui/layers/index.js';
15
19
  export { EventBus, EventListener, clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './undo/index.js';
16
20
  import 'zustand/vanilla';
17
21
 
18
- /** Which optional capabilities an instrument declared what the workspace
22
+ /** A point in the space the instrument works in. */
23
+ interface Vec3 {
24
+ x: number;
25
+ y: number;
26
+ z: number;
27
+ }
28
+ /** An orbit camera as a trial view: where it looks from, and what it looks at.
29
+ * labkit does not turn this into a matrix — the host's renderer does. */
30
+ interface OrbitView {
31
+ yaw: number;
32
+ pitch: number;
33
+ distance: number;
34
+ target: Vec3;
35
+ }
36
+ /** Just short of the pole. At exactly ±PI/2 the azimuth is undefined and the
37
+ * camera rolls, which reads as the model jumping rather than as a limit. */
38
+ declare const PITCH_LIMIT: number;
39
+ declare function clampPitch(pitch: number): number;
40
+ declare function wrapYaw(yaw: number): number;
41
+ /** The view a drag of (dx, dy) from `start` produces. Absolute against the drag
42
+ * start, so it can be re-applied any number of times without compounding. */
43
+ declare function orbitAfterDrag(start: OrbitView, dx: number, dy: number): OrbitView;
44
+ /** Multiplicative, so one notch covers the same proportion of the distance
45
+ * whether the camera is near or far. */
46
+ declare function orbitAfterWheel(view: OrbitView, deltaY: number, minDistance: number, maxDistance: number): OrbitView;
47
+ interface UseOrbitOptions {
48
+ view: OrbitView;
49
+ onViewChange: (v: OrbitView) => void;
50
+ /** Restored on double-click. Defaults to the view the hook first saw. */
51
+ home?: OrbitView;
52
+ minDistance?: number;
53
+ maxDistance?: number;
54
+ }
55
+ interface OrbitHandlers {
56
+ onWheel: (e: WheelEvent<HTMLElement>) => void;
57
+ onPointerDown: (e: PointerEvent<HTMLElement>) => void;
58
+ onPointerMove: (e: PointerEvent<HTMLElement>) => void;
59
+ onPointerUp: (e: PointerEvent<HTMLElement>) => void;
60
+ onDoubleClick: () => void;
61
+ isDragging: () => boolean;
62
+ }
63
+ /** Pointer gestures over an orbit view: drag to turn, wheel or pinch to dolly,
64
+ * double-click to go home. The 3D peer of `usePanZoom`. */
65
+ declare function useOrbit({ view, onViewChange, home, minDistance, maxDistance, }: UseOrbitOptions): OrbitHandlers;
66
+
67
+ /** Which optional capabilities an instrument declared — what the trial
19
68
  * consults to decide which chrome to show. */
20
69
  interface CapabilityFlags {
21
70
  hasCanvas: boolean;
@@ -43,7 +92,7 @@ declare function validateConfigSchema(fields: ConfigField[]): ValidationResult;
43
92
 
44
93
  /** Props for `<Lab>`. */
45
94
  interface LabProps {
46
- instruments: Instrument[];
95
+ instruments: InstrumentList;
47
96
  defaultInstrument: string;
48
97
  storage?: StorageAdapter | null;
49
98
  storageKey?: string;
@@ -58,24 +107,24 @@ interface LabProps {
58
107
  title?: string;
59
108
  children?: ReactNode;
60
109
  }
61
- /** The lab runtime: creates the store, provides it, and renders one workspace
62
- * per record in a grid. Each workspace runs one of `instruments`. */
110
+ /** The lab runtime: creates the store, provides it, and renders one trial
111
+ * per record in a grid. Each trial runs one of `instruments`. */
63
112
  declare function Lab({ instruments, defaultInstrument, storage, storageKey, mode, nebula, title, children, }: LabProps): react_jsx_runtime.JSX.Element;
64
113
 
65
114
  /** Lab-wide state and commands: the available instruments, the open
66
- * workspaces and the operations over them, saved snapshots, and the color
115
+ * trials and the operations over them, saved snapshots, and the color
67
116
  * mode. */
68
117
  interface LabContextValue {
69
- instruments: Instrument[];
70
- workspaces: WorkspaceRecord[];
71
- addWorkspace: (instrumentName: string) => void;
72
- cloneWorkspace: (id: string) => void;
73
- closeWorkspace: (id: string) => void;
74
- resetWorkspace: (id: string) => void;
75
- reorderWorkspaces: (ids: readonly string[]) => void;
118
+ instruments: InstrumentList;
119
+ trials: TrialRecord[];
120
+ addTrial: (instrumentName: string) => void;
121
+ cloneTrial: (id: string) => void;
122
+ closeTrial: (id: string) => void;
123
+ resetTrial: (id: string) => void;
124
+ reorderTrials: (ids: readonly string[]) => void;
76
125
  savedSnapshots: SavedSnapshot[];
77
- saveSnapshot: (workspaceId: string, name?: string) => void;
78
- loadSnapshot: (workspaceId: string, snapshotId: string) => void;
126
+ saveSnapshot: (trialId: string, name?: string) => void;
127
+ loadSnapshot: (trialId: string, snapshotId: string) => void;
79
128
  deleteSnapshot: (snapshotId: string) => void;
80
129
  mode: LabMode;
81
130
  setMode: (m: LabMode) => void;
@@ -98,12 +147,12 @@ interface LabShellProps {
98
147
  }
99
148
  /** Page frame for a lab: a titled header, a body, and an optional footer,
100
149
  * themed for the resolved color mode. Presentational only — use `<Lab>` when
101
- * the workspace runtime is wanted too. */
150
+ * the trial runtime is wanted too. */
102
151
  declare function LabShell({ title, children, header, footer, mode }: LabShellProps): react_jsx_runtime.JSX.Element;
103
152
 
104
153
  /** A tile's persisted extent, keyed by the id its caller gave it. Grid resizes
105
154
  * write `span`; `size` is here because a strategy swap would write that. */
106
- type WorkspaceLayout = Record<string, {
155
+ type TrialLayout = Record<string, {
107
156
  size?: {
108
157
  w?: number;
109
158
  h?: number;
@@ -113,7 +162,7 @@ type WorkspaceLayout = Record<string, {
113
162
  rows?: number;
114
163
  };
115
164
  }>;
116
- interface WorkspaceGridProps {
165
+ interface WorkspaceProps {
117
166
  children: ReactNode;
118
167
  /**
119
168
  * Stable id per child, positionally matched. Supply these whenever a tile
@@ -133,10 +182,10 @@ interface WorkspaceGridProps {
133
182
  /** The full id list a drop would produce, in its new order. */
134
183
  onReorder?: (ids: string[]) => void;
135
184
  /** Extents from a previous session, applied to tiles as they register. */
136
- layout?: WorkspaceLayout;
185
+ layout?: TrialLayout;
137
186
  /** Fires when a tile's extent changes. Persist it and hand it back as
138
187
  * `layout` to make a resize survive a reload. */
139
- onLayoutChange?: (layout: WorkspaceLayout) => void;
188
+ onLayoutChange?: (layout: TrialLayout) => void;
140
189
  gap?: number;
141
190
  padding?: number;
142
191
  /**
@@ -150,13 +199,21 @@ interface WorkspaceGridProps {
150
199
  };
151
200
  }
152
201
  /**
153
- * Auto-balanced tiling of workspaces, `ceil(sqrt(n))` columns wide.
202
+ * Auto-balanced tiling of trials, `ceil(sqrt(n))` columns wide.
154
203
  *
155
204
  * Tiles are absolutely positioned at the rects `gridStrategy` computes, not
156
205
  * laid out by CSS — `windease/styles.css` (folded into
157
206
  * `@weasel-js/labkit/styles.css`) carries the rules that positioning depends on.
158
207
  */
159
- declare function WorkspaceGrid({ children, ids, resizable, reorderable, onReorder, layout, onLayoutChange, gap, padding, viewport, }: WorkspaceGridProps): react_jsx_runtime.JSX.Element;
208
+ declare function Workspace({ children, ids, resizable, reorderable, onReorder, layout, onLayoutChange, gap, padding, viewport, }: WorkspaceProps): react_jsx_runtime.JSX.Element;
209
+
210
+ /** The 2D view labkit has always shipped, and what a trial gets when it names no
211
+ * other. Re-exported under its own name so a consumer can say which it means. */
212
+ type ViewTransform2D = ViewTransform;
213
+ declare const DEFAULT_VIEW: ViewTransform2D;
214
+ /** A trial's view is opaque to labkit, so anything that needs the 2D shape — the
215
+ * zoom chrome, `CanvasStack` — asks for it and handles not getting it. */
216
+ declare function as2DView(view: unknown): ViewTransform2D | null;
160
217
 
161
218
  type TokenValue = string | number | readonly (string | number)[];
162
219
  /**
@@ -196,6 +253,131 @@ interface Theme {
196
253
  */
197
254
  declare const interstellarTheme: Theme;
198
255
 
256
+ /** What a trial hands its toolbar: which instrument is running, the undo
257
+ * state and commands, the zoom controls, and the snapshot commands. */
258
+ interface TrialToolbarContext {
259
+ trialId: string;
260
+ instrumentName: string;
261
+ hasUndo: boolean;
262
+ canUndo: boolean;
263
+ canRedo: boolean;
264
+ undo: () => void;
265
+ redo: () => void;
266
+ zoom: number;
267
+ setZoom: (z: number) => void;
268
+ zoomIn: () => void;
269
+ zoomOut: () => void;
270
+ resetZoom: () => void;
271
+ hasCanvas: boolean;
272
+ savedSnapshots: SavedSnapshot[];
273
+ saveSnapshot: (name?: string) => void;
274
+ loadSnapshot: (snapshotId: string) => void;
275
+ clone: () => void;
276
+ reset: () => void;
277
+ close: () => void;
278
+ isLastTrial: boolean;
279
+ }
280
+ /** What a trial hands its sidebar: the instrument's config schema, its
281
+ * current values, and the setter. */
282
+ interface TrialSidebarContext {
283
+ trialId: string;
284
+ instrumentName: string;
285
+ configFields: ConfigField[];
286
+ config: unknown;
287
+ setConfig: (key: string, value: unknown) => void;
288
+ }
289
+ /** What a trial hands its status bar. */
290
+ interface TrialStatusBarContext {
291
+ trialId: string;
292
+ instrumentName: string;
293
+ /** Null when the trial holds a view that is not the 2D one. */
294
+ zoom: number | null;
295
+ }
296
+ /** Replaces a trial's toolbar. Receives everything the default one uses,
297
+ * so a custom toolbar need not reach into the store. */
298
+ type ToolbarSlot = (ctx: TrialToolbarContext) => ReactNode;
299
+ /** Replaces a trial's sidebar. */
300
+ type SidebarSlot = (ctx: TrialSidebarContext) => ReactNode;
301
+ /** Replaces a trial's status bar. */
302
+ type StatusBarSlot = (ctx: TrialStatusBarContext) => ReactNode;
303
+
304
+ /** Props for `<DefaultSidebar>`. */
305
+ interface DefaultSidebarProps {
306
+ ctx: TrialSidebarContext;
307
+ }
308
+ /** The sidebar a trial renders when no `sidebar` slot is supplied: a
309
+ * control panel over the instrument's config schema. */
310
+ declare function DefaultSidebar({ ctx }: DefaultSidebarProps): react_jsx_runtime.JSX.Element;
311
+
312
+ /** Props for `<DefaultStatusBar>`. */
313
+ interface DefaultStatusBarProps {
314
+ ctx: TrialStatusBarContext;
315
+ }
316
+ /** The status bar a trial renders when no `statusBar` slot is supplied:
317
+ * the instrument's name, and the zoom when the trial's view has one. */
318
+ declare function DefaultStatusBar({ ctx }: DefaultStatusBarProps): react_jsx_runtime.JSX.Element;
319
+
320
+ /** Props for `<DefaultToolbar>`. */
321
+ interface DefaultToolbarProps {
322
+ ctx: TrialToolbarContext;
323
+ }
324
+ /** The toolbar a trial renders when no `toolbar` slot is supplied. Only
325
+ * shows the controls the instrument's declared capabilities support. */
326
+ declare function DefaultToolbar({ ctx }: DefaultToolbarProps): react_jsx_runtime.JSX.Element;
327
+
328
+ /** Props for `<Trial>`. */
329
+ interface TrialProps {
330
+ id: string;
331
+ }
332
+ /** Renders one trial from the lab store: looks up its record and
333
+ * instrument, and mounts the instrument inside the trial chrome. */
334
+ declare function Trial({ id }: TrialProps): react_jsx_runtime.JSX.Element;
335
+
336
+ interface UndoBindings {
337
+ canUndo: boolean;
338
+ canRedo: boolean;
339
+ undo: () => void;
340
+ redo: () => void;
341
+ }
342
+ /** Props for `<TrialChrome>`. */
343
+ interface TrialChromeProps {
344
+ trialId: string;
345
+ record: TrialRecord;
346
+ instrument: Instrument;
347
+ isLastTrial: boolean;
348
+ toolbar?: ToolbarSlot;
349
+ sidebar?: SidebarSlot;
350
+ statusBar?: StatusBarSlot;
351
+ undoBindings?: UndoBindings;
352
+ /** Supplied when the instrument declares a `job`. */
353
+ job?: JobHandle;
354
+ sidebarExtras?: ReactNode;
355
+ children: ReactNode;
356
+ }
357
+ /** The frame around a running instrument — toolbar, sidebar, status bar —
358
+ * each replaceable by a slot. Assembles the slot contexts and wires the undo
359
+ * keyboard shortcuts. */
360
+ declare function TrialChrome({ trialId, record, instrument, isLastTrial, toolbar, sidebar, statusBar, undoBindings, job, sidebarExtras, children, }: TrialChromeProps): react_jsx_runtime.JSX.Element;
361
+
362
+ /** Append a new trial running `instrumentName`, at that instrument's
363
+ * default config and initial state. */
364
+ declare function addTrial(trials: TrialRecord[], instruments: InstrumentList, instrumentName: string): TrialRecord[];
365
+ /** Insert a deep copy of a trial directly after it. The copy starts with
366
+ * an empty undo history — the original's is not shared. */
367
+ declare function cloneTrial(trials: TrialRecord[], id: string): TrialRecord[];
368
+ /** Remove a trial, unless it is the last one — a lab always has at least
369
+ * one. */
370
+ declare function closeTrial(trials: TrialRecord[], id: string): TrialRecord[];
371
+ /** Return a trial to its instrument's defaults, keeping its id and its
372
+ * place in the list. */
373
+ declare function resetTrial(trials: TrialRecord[], id: string, instruments: InstrumentList): TrialRecord[];
374
+ /**
375
+ * Reorder to match `ids`. Ids the list doesn't mention keep their relative
376
+ * order at the end, and ids it names that no longer exist are dropped — a
377
+ * reorder that raced a close should not resurrect the closed trial.
378
+ */
379
+ declare function reorderTrials(trials: TrialRecord[], ids: readonly string[]): TrialRecord[];
380
+
199
381
  /** An annotation drawn over a curve plot: a shaded band across a range of x,
200
382
  * or a vertical line at one x. */
201
383
  type CurveMark = {
@@ -473,127 +655,5 @@ interface ToggleRowProps<T extends string> {
473
655
  * visible at once. */
474
656
  declare function ToggleRow<T extends string>({ label, value, options, onChange, layout, }: ToggleRowProps<T>): react_jsx_runtime.JSX.Element;
475
657
 
476
- /** What a workspace hands its toolbar: which instrument is running, the undo
477
- * state and commands, the zoom controls, and the snapshot commands. */
478
- interface WorkspaceToolbarContext {
479
- workspaceId: string;
480
- instrumentName: string;
481
- hasUndo: boolean;
482
- canUndo: boolean;
483
- canRedo: boolean;
484
- undo: () => void;
485
- redo: () => void;
486
- zoom: number;
487
- setZoom: (z: number) => void;
488
- zoomIn: () => void;
489
- zoomOut: () => void;
490
- resetZoom: () => void;
491
- hasCanvas: boolean;
492
- savedSnapshots: SavedSnapshot[];
493
- saveSnapshot: (name?: string) => void;
494
- loadSnapshot: (snapshotId: string) => void;
495
- clone: () => void;
496
- reset: () => void;
497
- close: () => void;
498
- isLastWorkspace: boolean;
499
- }
500
- /** What a workspace hands its sidebar: the instrument's config schema, its
501
- * current values, and the setter. */
502
- interface WorkspaceSidebarContext {
503
- workspaceId: string;
504
- instrumentName: string;
505
- configFields: ConfigField[];
506
- config: unknown;
507
- setConfig: (key: string, value: unknown) => void;
508
- }
509
- /** What a workspace hands its status bar. */
510
- interface WorkspaceStatusBarContext {
511
- workspaceId: string;
512
- instrumentName: string;
513
- zoom: number;
514
- }
515
- /** Replaces a workspace's toolbar. Receives everything the default one uses,
516
- * so a custom toolbar need not reach into the store. */
517
- type ToolbarSlot = (ctx: WorkspaceToolbarContext) => ReactNode;
518
- /** Replaces a workspace's sidebar. */
519
- type SidebarSlot = (ctx: WorkspaceSidebarContext) => ReactNode;
520
- /** Replaces a workspace's status bar. */
521
- type StatusBarSlot = (ctx: WorkspaceStatusBarContext) => ReactNode;
522
-
523
- /** Props for `<DefaultSidebar>`. */
524
- interface DefaultSidebarProps {
525
- ctx: WorkspaceSidebarContext;
526
- }
527
- /** The sidebar a workspace renders when no `sidebar` slot is supplied: a
528
- * control panel over the instrument's config schema. */
529
- declare function DefaultSidebar({ ctx }: DefaultSidebarProps): react_jsx_runtime.JSX.Element;
530
-
531
- /** Props for `<DefaultStatusBar>`. */
532
- interface DefaultStatusBarProps {
533
- ctx: WorkspaceStatusBarContext;
534
- }
535
- /** The status bar a workspace renders when no `statusBar` slot is supplied:
536
- * the instrument's name and the current zoom. */
537
- declare function DefaultStatusBar({ ctx }: DefaultStatusBarProps): react_jsx_runtime.JSX.Element;
538
-
539
- /** Props for `<DefaultToolbar>`. */
540
- interface DefaultToolbarProps {
541
- ctx: WorkspaceToolbarContext;
542
- }
543
- /** The toolbar a workspace renders when no `toolbar` slot is supplied. Only
544
- * shows the controls the instrument's declared capabilities support. */
545
- declare function DefaultToolbar({ ctx }: DefaultToolbarProps): react_jsx_runtime.JSX.Element;
546
-
547
- /** Props for `<Workspace>`. */
548
- interface WorkspaceProps {
549
- id: string;
550
- }
551
- /** Renders one workspace from the lab store: looks up its record and
552
- * instrument, and mounts the instrument inside the workspace chrome. */
553
- declare function Workspace({ id }: WorkspaceProps): react_jsx_runtime.JSX.Element;
554
-
555
- interface UndoBindings {
556
- canUndo: boolean;
557
- canRedo: boolean;
558
- undo: () => void;
559
- redo: () => void;
560
- }
561
- /** Props for `<WorkspaceChrome>`. */
562
- interface WorkspaceChromeProps {
563
- workspaceId: string;
564
- record: WorkspaceRecord;
565
- instrument: Instrument;
566
- isLastWorkspace: boolean;
567
- toolbar?: ToolbarSlot;
568
- sidebar?: SidebarSlot;
569
- statusBar?: StatusBarSlot;
570
- undoBindings?: UndoBindings;
571
- sidebarExtras?: ReactNode;
572
- children: ReactNode;
573
- }
574
- /** The frame around a running instrument — toolbar, sidebar, status bar —
575
- * each replaceable by a slot. Assembles the slot contexts and wires the undo
576
- * keyboard shortcuts. */
577
- declare function WorkspaceChrome({ workspaceId, record, instrument, isLastWorkspace, toolbar, sidebar, statusBar, undoBindings, sidebarExtras, children, }: WorkspaceChromeProps): react_jsx_runtime.JSX.Element;
578
-
579
- /** Append a new workspace running `instrumentName`, at that instrument's
580
- * default config and initial state. */
581
- declare function addWorkspace(workspaces: WorkspaceRecord[], instruments: Instrument[], instrumentName: string): WorkspaceRecord[];
582
- /** Insert a deep copy of a workspace directly after it. The copy starts with
583
- * an empty undo history — the original's is not shared. */
584
- declare function cloneWorkspace(workspaces: WorkspaceRecord[], id: string): WorkspaceRecord[];
585
- /** Remove a workspace, unless it is the last one — a lab always has at least
586
- * one. */
587
- declare function closeWorkspace(workspaces: WorkspaceRecord[], id: string): WorkspaceRecord[];
588
- /** Return a workspace to its instrument's defaults, keeping its id and its
589
- * place in the list. */
590
- declare function resetWorkspace(workspaces: WorkspaceRecord[], id: string, instruments: Instrument[]): WorkspaceRecord[];
591
- /**
592
- * Reorder to match `ids`. Ids the list doesn't mention keep their relative
593
- * order at the end, and ids it names that no longer exist are dropped — a
594
- * reorder that raced a close should not resurrect the closed workspace.
595
- */
596
- declare function reorderWorkspaces(workspaces: WorkspaceRecord[], ids: readonly string[]): WorkspaceRecord[];
597
-
598
- export { CheckboxRow, ColorRow, ConfigField, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Instrument, Lab, LabContext, LabMode, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SavedSnapshot, SelectRow, SliderRow, StorageAdapter, Subpanel, TextRow, ToggleRow, Workspace, WorkspaceChrome, WorkspaceGrid, WorkspaceRecord, addWorkspace, cloneWorkspace, closeWorkspace, defineInstrument, detectCapabilities, interstellarTheme, reorderWorkspaces, resetWorkspace, useLabContext, validateConfigSchema };
599
- export type { CapabilityFlags, CheckboxRowProps, ColorRowProps, CurveFieldProps, CurveMark, DefaultSidebarProps, DefaultStatusBarProps, DefaultToolbarProps, EffectCardListItem, EffectCardListProps, EffectCardProps, LabContextValue, LabProps, LabShellProps, NumberRowProps, PropertyGroupProps, PropertyListPack, PropertyListProps, PropertyPanelProps, PropertyRowLayout, PropertyRowProps, PropertyRowVariant, SelectRowProps, SidebarSlot, SliderRowProps, StatusBarSlot, SubpanelProps, TextRowProps, ToggleRowProps, ToolbarSlot, ValidationResult, WorkspaceChromeProps, WorkspaceGridProps, WorkspaceProps, WorkspaceSidebarContext, WorkspaceStatusBarContext, WorkspaceToolbarContext };
658
+ export { CheckboxRow, ColorRow, ConfigField, CurveField, DEFAULT_VIEW, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Instrument, InstrumentList, JobHandle, Lab, LabContext, LabMode, LabShell, NumberRow, PITCH_LIMIT, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SavedSnapshot, SelectRow, SliderRow, StorageAdapter, Subpanel, TextRow, ToggleRow, Trial, TrialChrome, TrialRecord, ViewTransform, Workspace, addTrial, as2DView, clampPitch, cloneTrial, closeTrial, defineInstrument, detectCapabilities, interstellarTheme, orbitAfterDrag, orbitAfterWheel, reorderTrials, resetTrial, useLabContext, useOrbit, validateConfigSchema, wrapYaw };
659
+ export type { CapabilityFlags, CheckboxRowProps, ColorRowProps, CurveFieldProps, CurveMark, DefaultSidebarProps, DefaultStatusBarProps, DefaultToolbarProps, EffectCardListItem, EffectCardListProps, EffectCardProps, LabContextValue, LabProps, LabShellProps, NumberRowProps, OrbitHandlers, OrbitView, PropertyGroupProps, PropertyListPack, PropertyListProps, PropertyPanelProps, PropertyRowLayout, PropertyRowProps, PropertyRowVariant, SelectRowProps, SidebarSlot, SliderRowProps, StatusBarSlot, SubpanelProps, TextRowProps, ToggleRowProps, ToolbarSlot, TrialChromeProps, TrialProps, TrialSidebarContext, TrialStatusBarContext, TrialToolbarContext, UseOrbitOptions, ValidationResult, Vec3, ViewTransform2D, WorkspaceProps };