@weasel-js/labkit 1.0.1 → 1.0.3

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 (100) hide show
  1. package/dist/_dts/{DrawCommand-CitWPxMY.d.ts → DrawCommand-uKHt4Vul.d.ts} +56 -0
  2. package/dist/_dts/{index-C6Yze7sQ.d.ts → index-CFlDPeZh.d.ts} +30 -1
  3. package/dist/_dts/{types-Si4Fw-1F.d.ts → types-x92Kfeme.d.ts} +14 -0
  4. package/dist/_dts/{useExperimentState-CJn2hHzd.d.ts → useExperimentState-vrttakTt.d.ts} +43 -0
  5. package/dist/canvas/index.d.ts +13 -2
  6. package/dist/canvas/index.js +2 -2
  7. package/dist/{chunk-ISEK5LXT.js → chunk-3WPOGKUP.js} +1603 -1670
  8. package/dist/chunk-3WPOGKUP.js.map +1 -0
  9. package/dist/{chunk-54IQ2DX7.js → chunk-574LJAV4.js} +3 -3
  10. package/dist/chunk-574LJAV4.js.map +1 -0
  11. package/dist/{chunk-VLAHRJOC.js → chunk-5R2ATYPJ.js} +2 -2
  12. package/dist/{chunk-VLAHRJOC.js.map → chunk-5R2ATYPJ.js.map} +1 -1
  13. package/dist/{chunk-EXBV7A6X.js → chunk-73PXCRCR.js} +3 -3
  14. package/dist/chunk-73PXCRCR.js.map +1 -0
  15. package/dist/{chunk-PWC7AQZM.js → chunk-CPUJ3QXL.js} +2 -2
  16. package/dist/chunk-CPUJ3QXL.js.map +1 -0
  17. package/dist/{chunk-NRD3TDNQ.js → chunk-N5KTQKQA.js} +1462 -1487
  18. package/dist/chunk-N5KTQKQA.js.map +1 -0
  19. package/dist/{chunk-HXZHVU4G.js → chunk-PMAU3SEE.js} +3 -3
  20. package/dist/chunk-PMAU3SEE.js.map +1 -0
  21. package/dist/{chunk-7BKDG73Z.js → chunk-RL2LOLNI.js} +2 -2
  22. package/dist/chunk-RL2LOLNI.js.map +1 -0
  23. package/dist/{chunk-2QNYYL3V.js → chunk-SFL7NFKN.js} +2 -2
  24. package/dist/chunk-SFL7NFKN.js.map +1 -0
  25. package/dist/{chunk-53XSBIUK.js → chunk-T7OKNJTY.js} +2 -2
  26. package/dist/chunk-T7OKNJTY.js.map +1 -0
  27. package/dist/controls/index.d.ts +4 -2
  28. package/dist/controls/index.js +1 -1
  29. package/dist/dragdrop/index.d.ts +2 -2
  30. package/dist/index.d.ts +122 -6
  31. package/dist/index.js +18 -18
  32. package/dist/index.js.map +1 -1
  33. package/dist/layers/index.d.ts +6 -3
  34. package/dist/layers/index.js +1 -1
  35. package/dist/passthrough/weasel-canvas.d.ts +5 -1
  36. package/dist/passthrough/weasel-canvas.js +1 -1
  37. package/dist/passthrough/weasel-ui.d.ts +514 -36
  38. package/dist/passthrough/weasel-ui.js +2 -2
  39. package/dist/primitives/index.d.ts +13 -0
  40. package/dist/primitives/index.js +2 -2
  41. package/dist/state/index.d.ts +15 -2
  42. package/dist/state/index.js +2 -2
  43. package/dist/state/index.js.map +1 -1
  44. package/dist/styles.css +147 -0
  45. package/dist/ui/layers/index.d.ts +5 -0
  46. package/dist/ui/layers/index.js +3 -3
  47. package/dist/undo/index.d.ts +17 -2
  48. package/dist/undo/index.js +1 -1
  49. package/package.json +2 -2
  50. package/src/canvas/CanvasStack.tsx +4 -0
  51. package/src/canvas/CanvasStackContext.ts +3 -0
  52. package/src/canvas/canvasCoords.ts +2 -0
  53. package/src/canvas/useLayerScheduler.ts +2 -0
  54. package/src/controls/ControlPanel.tsx +2 -0
  55. package/src/controls/types.ts +14 -0
  56. package/src/instrument/capabilityDetector.ts +3 -0
  57. package/src/instrument/defineInstrument.ts +2 -0
  58. package/src/instrument/types.ts +29 -0
  59. package/src/instrument/validateConfigSchema.ts +5 -0
  60. package/src/lab/Lab.tsx +3 -0
  61. package/src/lab/LabContext.ts +5 -0
  62. package/src/lab/LabShell.tsx +4 -0
  63. package/src/lab/WorkspaceGrid.tsx +2 -0
  64. package/src/lab/gridDims.ts +2 -0
  65. package/src/layers/LayerList.tsx +3 -0
  66. package/src/primitives/FpsMeter.tsx +1 -0
  67. package/src/primitives/ScaleIndicator.tsx +4 -0
  68. package/src/primitives/Sidebar.tsx +3 -0
  69. package/src/primitives/StatusBar.tsx +3 -0
  70. package/src/primitives/Toolbar.tsx +6 -0
  71. package/src/state/SingletonExperiment.tsx +1 -0
  72. package/src/state/adapters.ts +8 -0
  73. package/src/state/context.tsx +9 -0
  74. package/src/state/helpers.ts +12 -0
  75. package/src/state/store.ts +6 -0
  76. package/src/state/types.ts +17 -0
  77. package/src/state/useExperimentState.ts +3 -0
  78. package/src/ui/layers/LayerStack.tsx +5 -0
  79. package/src/ui/properties/CurveField.tsx +4 -1
  80. package/src/ui/properties/EffectCard.tsx +12 -0
  81. package/src/ui/properties/PropertyGroup.tsx +1 -0
  82. package/src/ui/properties/PropertyPanel.tsx +28 -0
  83. package/src/undo/eventBus.ts +4 -0
  84. package/src/undo/undoStack.ts +11 -0
  85. package/src/workspace/DefaultSidebar.tsx +3 -0
  86. package/src/workspace/DefaultStatusBar.tsx +3 -0
  87. package/src/workspace/DefaultToolbar.tsx +3 -0
  88. package/src/workspace/Workspace.tsx +3 -0
  89. package/src/workspace/WorkspaceChrome.tsx +4 -0
  90. package/src/workspace/slotTypes.ts +9 -0
  91. package/src/workspace/workspaceOps.ts +8 -0
  92. package/dist/chunk-2QNYYL3V.js.map +0 -1
  93. package/dist/chunk-53XSBIUK.js.map +0 -1
  94. package/dist/chunk-54IQ2DX7.js.map +0 -1
  95. package/dist/chunk-7BKDG73Z.js.map +0 -1
  96. package/dist/chunk-EXBV7A6X.js.map +0 -1
  97. package/dist/chunk-HXZHVU4G.js.map +0 -1
  98. package/dist/chunk-ISEK5LXT.js.map +0 -1
  99. package/dist/chunk-NRD3TDNQ.js.map +0 -1
  100. package/dist/chunk-PWC7AQZM.js.map +0 -1
@@ -32,10 +32,30 @@ interface Op {
32
32
  args?: unknown;
33
33
  }
34
34
 
35
+ /** Options for `history.beginJournal()`. */
35
36
  interface BeginJournalOptions {
37
+ /** Label for the single parent-history entry the journal flushes on commit. */
36
38
  label: string;
39
+ /** Caller-supplied tag naming what this journal is scoped to — typically the
40
+ * id of the node being edited. The history layer only carries it; callers
41
+ * read it back off the journal to decide whether a suspended journal
42
+ * matches what they are about to edit. */
37
43
  targetId?: string;
38
44
  }
45
+ /**
46
+ * A scoped sub-history forked from a `History`, opened by
47
+ * `history.beginJournal()`. Applies, undoes and redoes against the same
48
+ * adapter as its parent, but keeps its entries to itself: `commit` flushes the
49
+ * journal's net forward ops to the parent as one entry, `cancel` rewinds them
50
+ * and contributes nothing. Use it when a self-contained editing session (a
51
+ * text edit, a modal drag) should collapse to a single step in the parent's
52
+ * undo stack while still offering undo *within* the session.
53
+ *
54
+ * A journal is active, suspended or closed. `commit` and `cancel` are
55
+ * terminal; `suspend` lets the parent be used again and can be reversed with
56
+ * `history.resumeJournal()`. Every mutating method throws when the journal is
57
+ * not active.
58
+ */
39
59
  interface Journal {
40
60
  readonly targetId: string | undefined;
41
61
  readonly forkedAtEntryId: number;
@@ -277,9 +297,13 @@ interface NodeBase<TData, TLayer extends string, TPose> {
277
297
  data: TData;
278
298
  parent: NodeId | null;
279
299
  }
300
+ /** A node with no children — a shape, a label, an image. */
280
301
  interface LeafNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
281
302
  kind: 'leaf';
282
303
  }
304
+ /** A node with an ordered list of children. This is the real group: what
305
+ * Cmd+G creates, what SVG `<g>` round-trips to. A container has its own pose,
306
+ * which its children's poses are relative to, and may optionally clip them. */
283
307
  interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
284
308
  kind: 'container';
285
309
  children: NodeId[];
@@ -290,20 +314,30 @@ interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends
290
314
  * paints descendants only where it covers. */
291
315
  clipFromPose?: (pose: TPose) => Path | null;
292
316
  }
317
+ /** A node in the scene tree: either a leaf or a container. Re-exported
318
+ * publicly as `SceneNode`, to avoid colliding with the DOM's `Node`. */
293
319
  type Node<TData, TLayer extends string, TPose = RectPose> = LeafNode<TData, TLayer, TPose> | ContainerNode<TData, TLayer, TPose>;
294
320
  interface LayerRecordBase<TLayer extends string> {
295
321
  id: TLayer;
296
322
  visible: boolean;
297
323
  locked: boolean;
298
324
  }
325
+ /** A layer declared when the scene was created. Fixed set, no display name —
326
+ * these are the kit's own render bands, not something a user manages. */
299
327
  interface SystemLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
300
328
  kind: 'system';
301
329
  }
330
+ /** A layer the user created and can rename, reorder or delete. */
302
331
  interface UserLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
303
332
  kind: 'user';
304
333
  name: string;
305
334
  }
335
+ /** Per-layer metadata held by the scene: whether it is visible and locked,
336
+ * and where it sits in the render stack. Distinct from a node's `layer` tag,
337
+ * which merely names one of these. */
306
338
  type LayerRecord<TLayer extends string> = SystemLayerRecord<TLayer> | UserLayerRecord<TLayer>;
339
+ /** What `Scene.add` needs to mint a node. Everything except the id is
340
+ * required; the id is generated unless one is supplied. */
307
341
  interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
308
342
  kind: 'leaf' | 'container';
309
343
  layer: TLayer;
@@ -317,10 +351,13 @@ interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
317
351
  * to the node; ignored for leaves. Mirrors `ContainerNode.clipFromPose`. */
318
352
  clipFromPose?: (pose: TPose) => Path | null;
319
353
  }
354
+ /** A custom scene mutation registered with `Scene.registerOp`: how to apply
355
+ * it and how to undo it. The pair is what makes it participate in history. */
320
356
  interface RegisteredOp<P> {
321
357
  apply: (payload: P) => void;
322
358
  revert: (payload: P) => void;
323
359
  }
360
+ /** One of the layers a scene is created with. */
324
361
  interface SystemLayerSpec<TLayer extends string> {
325
362
  id: TLayer;
326
363
  visible?: boolean;
@@ -361,6 +398,18 @@ interface SerializedNode<TData, TLayer extends string, TPose> {
361
398
  * Containers only; omitted when the container has no clip. */
362
399
  clipFromPoseKey?: string;
363
400
  }
401
+ /**
402
+ * The kit-owned scene tree: nodes, layers, and the undo history over both.
403
+ *
404
+ * A scene is logical, not visual — it says what exists and where, and nothing
405
+ * about how it is painted. Every mutating method is undoable, and reads are
406
+ * snapshots rather than live views. Nodes are addressed by `NodeId`; hold ids
407
+ * across mutations, not node objects.
408
+ *
409
+ * Three type parameters keep it domain-agnostic: `TData` is the app's payload,
410
+ * which the kit never inspects; `TPose` is the transform shape, `RectPose` by
411
+ * default; `TLayer` is the union of layer names.
412
+ */
364
413
  interface Scene<TData, TLayer extends string, TPose = RectPose> {
365
414
  readonly nodes: ReadonlyMap<NodeId, Node<TData, TLayer, TPose>>;
366
415
  readonly roots: readonly NodeId[];
@@ -865,6 +914,8 @@ interface TextStyle {
865
914
  * `runs/rangeStyle.ts` for why the model collapses the tri-state.
866
915
  */
867
916
 
917
+ /** A run with every style resolved against the node's text style — no
918
+ * optional inheritance left. This is what layout and painting consume. */
868
919
  interface ResolvedRun {
869
920
  text: string;
870
921
  fontFamily: string;
@@ -926,6 +977,8 @@ type ShaderUniform = number | [number, number] | [number, number, number] | [num
926
977
 
927
978
  /** DrawCommand variants implemented through step 6. */
928
979
  type DrawCommand = PathDrawCommand | GroupDrawCommand | TextDrawCommand | ImageDrawCommand | ShaderDrawCommand;
980
+ /** Draw a path, filled and/or stroked. The workhorse command: every shape the
981
+ * kit draws that is not text, an image, or a custom shader is one of these. */
929
982
  interface PathDrawCommand {
930
983
  kind: 'path';
931
984
  path: Path;
@@ -948,6 +1001,9 @@ interface PathDrawCommand {
948
1001
  */
949
1002
  vertexColors?: number[];
950
1003
  }
1004
+ /** Draw a list of commands under a shared transform, opacity, color matrix
1005
+ * and clip. Groups nest, and their effects accumulate down the stack — this
1006
+ * is how a container node's transform reaches its descendants. */
951
1007
  interface GroupDrawCommand {
952
1008
  kind: 'group';
953
1009
  transform?: Mat3;
@@ -1,6 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
- import { C as ConfigField } from './types-Si4Fw-1F.js';
2
+ import { C as ConfigField } from './types-x92Kfeme.js';
3
3
 
4
+ /** What an instrument's `render` is handed: its state and config, the setters
5
+ * for both, the workspace it is mounted in, and a way to emit named events. */
4
6
  interface RenderContext<TS = unknown, TC = unknown> {
5
7
  state: TS;
6
8
  config: TC;
@@ -13,6 +15,7 @@ interface RenderContext<TS = unknown, TC = unknown> {
13
15
  };
14
16
  emit: (event: string) => void;
15
17
  }
18
+ /** One 2D canvas layer of an instrument, drawn in declaration order. */
16
19
  interface CanvasLayer<TS = unknown, TC = unknown> {
17
20
  id: string;
18
21
  draw: (ctx: CanvasRenderingContext2D, args: {
@@ -21,6 +24,8 @@ interface CanvasLayer<TS = unknown, TC = unknown> {
21
24
  zoom: number;
22
25
  }) => void;
23
26
  }
27
+ /** Declares that an instrument draws to a canvas: its layers, and where the
28
+ * view starts. */
24
29
  interface CanvasCapability<TS = unknown, TC = unknown> {
25
30
  layers: CanvasLayer<TS, TC>[];
26
31
  initialView?: {
@@ -31,9 +36,14 @@ interface CanvasCapability<TS = unknown, TC = unknown> {
31
36
  };
32
37
  };
33
38
  }
39
+ /** Declares which of an instrument's layers the workspace should offer
40
+ * show/hide controls for. */
34
41
  interface LayerCapability {
35
42
  ids: string[];
36
43
  }
44
+ /** Declares that an instrument accepts items dragged from a palette: what the
45
+ * palette offers, what a drop does to the state, and — optionally — live
46
+ * feedback during the drag and the ability to drag existing items back out. */
37
47
  interface DragDropCapability<TS = unknown, TC = unknown> {
38
48
  palette: PaletteItem[] | ((state: TS, config: TC) => PaletteItem[]);
39
49
  onDrop: (worldPos: Point, item: PaletteItem, state: TS, config: TC) => TS;
@@ -43,38 +53,57 @@ interface DragDropCapability<TS = unknown, TC = unknown> {
43
53
  state: TS;
44
54
  } | null;
45
55
  }
56
+ /** Declares that an instrument's state is undoable: which emitted events
57
+ * snapshot it, and how many snapshots to keep. */
46
58
  interface UndoCapability {
47
59
  snapshotOn?: string[];
48
60
  maxDepth?: number;
49
61
  }
62
+ /** The name of an event an instrument emits through `RenderContext.emit`. */
50
63
  type SystemEvent = string;
64
+ /** A point in world coordinates. */
51
65
  type Point = {
52
66
  x: number;
53
67
  y: number;
54
68
  };
69
+ /** What a hit-test found, and where. */
55
70
  type HitResult = {
56
71
  hit: boolean;
57
72
  layerId?: string;
58
73
  pointId?: string;
59
74
  };
75
+ /** A workspace's camera. */
60
76
  type ViewTransform = {
61
77
  zoom: number;
62
78
  pan: Point;
63
79
  };
80
+ /** A layer as the layer list shows it. `alwaysOn` layers cannot be hidden. */
64
81
  type LayerDescriptor = {
65
82
  id: string;
66
83
  label: string;
67
84
  alwaysOn?: boolean;
68
85
  };
86
+ /** One draggable entry in an instrument's palette. */
69
87
  type PaletteItem = {
70
88
  id: string;
71
89
  label: string;
72
90
  data?: unknown;
73
91
  };
92
+ /** Whether a drop would be accepted at the current position, and why not if
93
+ * it would not. */
74
94
  type DragFeedback = {
75
95
  ok: boolean;
76
96
  reason?: string;
77
97
  };
98
+ /**
99
+ * An instrument: one self-contained interactive experiment a lab can host.
100
+ *
101
+ * It owns two pieces of data — `config`, the settings the control panel edits,
102
+ * and `state`, what the experiment is currently doing — and renders from both.
103
+ * The optional capability fields declare what else it wants from the runtime:
104
+ * a canvas, a layer list, palette drag-and-drop, undo. Declaring a capability
105
+ * is what makes the workspace provide the corresponding chrome.
106
+ */
78
107
  interface Instrument<TS = unknown, TC = unknown> {
79
108
  name: string;
80
109
  defaultConfig: () => TC;
@@ -1,9 +1,13 @@
1
+ /** Which control a config field is edited with. */
1
2
  type ConfigFieldType = 'slider' | 'checkbox' | 'select' | 'number' | 'text' | 'color';
3
+ /** What every config field carries: the config key it writes, the label shown
4
+ * beside it, and which control renders it. */
2
5
  interface ConfigFieldBase {
3
6
  key: string;
4
7
  label: string;
5
8
  type: ConfigFieldType;
6
9
  }
10
+ /** A bounded number edited by dragging. */
7
11
  interface SliderField extends ConfigFieldBase {
8
12
  type: 'slider';
9
13
  default: number;
@@ -11,19 +15,24 @@ interface SliderField extends ConfigFieldBase {
11
15
  max: number;
12
16
  step?: number;
13
17
  }
18
+ /** A boolean. */
14
19
  interface CheckboxField extends ConfigFieldBase {
15
20
  type: 'checkbox';
16
21
  default: boolean;
17
22
  }
23
+ /** One choice in a select field. */
18
24
  interface SelectOption {
19
25
  value: string;
20
26
  label: string;
21
27
  }
28
+ /** A fixed set of labeled choices. */
22
29
  interface SelectField extends ConfigFieldBase {
23
30
  type: 'select';
24
31
  default: string;
25
32
  options: SelectOption[];
26
33
  }
34
+ /** A number typed directly, optionally bounded. Use a slider field instead
35
+ * when the range matters more than the exact value. */
27
36
  interface NumberField extends ConfigFieldBase {
28
37
  type: 'number';
29
38
  default: number;
@@ -31,6 +40,8 @@ interface NumberField extends ConfigFieldBase {
31
40
  max?: number;
32
41
  step?: number;
33
42
  }
43
+ /** A free-text string. Writes are debounced so typing does not re-run the
44
+ * instrument on every keystroke. */
34
45
  interface TextField extends ConfigFieldBase {
35
46
  type: 'text';
36
47
  default: string;
@@ -39,10 +50,13 @@ interface TextField extends ConfigFieldBase {
39
50
  /** Milliseconds to debounce live setConfig calls. Default 150 ms. Set to 0 to disable. */
40
51
  debounceMs?: number;
41
52
  }
53
+ /** A color, as a CSS color string. */
42
54
  interface ColorField extends ConfigFieldBase {
43
55
  type: 'color';
44
56
  default: string;
45
57
  }
58
+ /** One field of an instrument's config schema. The schema is what the control
59
+ * panel renders, and what `validateConfigSchema` checks. */
46
60
  type ConfigField = SliderField | CheckboxField | SelectField | NumberField | TextField | ColorField;
47
61
 
48
62
  export type { ConfigField as C, NumberField as N, SelectField as S, TextField as T, CheckboxField as a, ColorField as b, ConfigFieldBase as c, ConfigFieldType as d, SelectOption as e, SliderField as f };
@@ -2,10 +2,14 @@ import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
3
  import { StoreApi } from 'zustand/vanilla';
4
4
 
5
+ /** A workspace's undo history, as snapshots of its state either side of the
6
+ * present. */
5
7
  interface UndoStack {
6
8
  past: unknown[];
7
9
  future: unknown[];
8
10
  }
11
+ /** One workspace as the store holds it: which instrument it runs, that
12
+ * instrument's config and state, the camera, and the undo history. */
9
13
  interface WorkspaceRecord<TS = unknown, TC = unknown> {
10
14
  id: string;
11
15
  instrumentName: string;
@@ -20,6 +24,8 @@ interface WorkspaceRecord<TS = unknown, TC = unknown> {
20
24
  };
21
25
  undoStack: UndoStack;
22
26
  }
27
+ /** A named, saved copy of a workspace's config and state, restorable into any
28
+ * workspace running the same instrument. */
23
29
  interface SavedSnapshot {
24
30
  id: string;
25
31
  name: string;
@@ -31,38 +37,59 @@ interface SavedSnapshot {
31
37
  }
32
38
  /** `auto` follows the OS; the other two are an explicit choice. */
33
39
  type LabMode = 'auto' | 'light' | 'dark';
40
+ /** Everything a lab persists: its workspaces, its saved snapshots, and the
41
+ * chosen color mode. */
34
42
  interface LabStoreState {
35
43
  workspaces: WorkspaceRecord[];
36
44
  savedSnapshots: SavedSnapshot[];
37
45
  mode: LabMode;
38
46
  }
47
+ /** Where a lab persists itself. Implementations are keyed string storage and
48
+ * nothing more, so the same store works against localStorage, the URL hash,
49
+ * or memory. */
39
50
  interface StorageAdapter {
40
51
  read(key: string): string | null;
41
52
  write(key: string, value: string): void;
42
53
  delete?(key: string): void;
43
54
  }
55
+ /** What `useExperimentState` hands an instrument: its state and config, with
56
+ * a setter for each. */
44
57
  interface ExperimentStateHandle<TS, TC> {
45
58
  state: TS;
46
59
  setState: (next: TS | ((prev: TS) => TS)) => void;
47
60
  config: TC;
48
61
  setConfig: (key: keyof TC, value: TC[keyof TC]) => void;
49
62
  }
63
+ /** Options for `createLabStore`. `storageKey` namespaces the keys written, so
64
+ * two labs on one origin do not collide. */
50
65
  interface CreateLabStoreOptions {
51
66
  storageKey: string;
52
67
  storage: StorageAdapter;
53
68
  initialMode?: LabMode;
54
69
  }
70
+ /** Per-instrument serialize/deserialize hooks, keyed by instrument name. An
71
+ * instrument whose state is already JSON-safe needs no entry. */
55
72
  type InstrumentSerializers = Record<string, {
56
73
  serialize?: (state: unknown) => unknown;
57
74
  deserialize?: (data: unknown) => unknown;
58
75
  } | undefined>;
59
76
 
77
+ /** Persist to `localStorage` — state survives a reload and a new tab. Falls
78
+ * back to no-ops when storage is unavailable. */
60
79
  declare const localStorageAdapter: StorageAdapter;
80
+ /** Persist to `sessionStorage` — state survives a reload but not a new tab. */
61
81
  declare const sessionStorageAdapter: StorageAdapter;
82
+ /** Persist into the URL fragment, so the page's link carries its state and
83
+ * can be shared or bookmarked. */
62
84
  declare const urlHashAdapter: StorageAdapter;
85
+ /** An in-memory store, discarded on reload. For tests, and for labs that
86
+ * should start fresh every time. */
63
87
  declare function createMemoryAdapter(): StorageAdapter;
88
+ /** Persists nothing and reads back nothing. */
64
89
  declare const noneAdapter: StorageAdapter;
65
90
 
91
+ /** Every mutation a lab store supports: managing workspaces, saving and
92
+ * restoring snapshots, and setting the color mode. */
66
93
  interface LabStoreActions {
67
94
  addWorkspace: (record: Omit<WorkspaceRecord, 'undoStack'>) => void;
68
95
  removeWorkspace: (id: string) => void;
@@ -77,27 +104,43 @@ interface LabStoreActions {
77
104
  listSnapshots: (workspaceId?: string) => SavedSnapshot[];
78
105
  setMode: (mode: LabMode) => void;
79
106
  }
107
+ /** A lab's store: its state and actions, plus the hook instruments use to
108
+ * register how their state is serialized. */
80
109
  type LabStore = StoreApi<LabStoreState & LabStoreActions> & {
81
110
  registerSerializers: (s: InstrumentSerializers) => void;
82
111
  };
112
+ /** Build a lab store, hydrating from storage if anything was saved under the
113
+ * same key. Writes back are debounced. */
83
114
  declare function createLabStore(options: CreateLabStoreOptions): LabStore;
84
115
 
85
116
  type LabStoreCtx = {
86
117
  store: LabStore;
87
118
  } | null;
119
+ /** Context carrying the lab store. Prefer `useLabStore`; this is exported for
120
+ * code that needs to read the context without subscribing. */
88
121
  declare const LabStoreContext: react.Context<LabStoreCtx>;
122
+ /** Provides a lab store to its subtree. */
89
123
  declare function LabStoreProvider({ store, children, }: {
90
124
  store: LabStore;
91
125
  children: ReactNode;
92
126
  }): ReactElement;
127
+ /** Subscribe to the whole lab store. Throws outside a `<LabStoreProvider>`. */
93
128
  declare function useLabStore(): LabStoreState & ReturnType<LabStore['getState']>;
129
+ /** Context carrying which workspace the subtree belongs to. */
94
130
  declare const WorkspaceIdContext: react.Context<string | null>;
131
+ /** Names the workspace its subtree belongs to, so an instrument's hooks can
132
+ * find their own record in the store without being passed an id. */
95
133
  declare function WorkspaceIdProvider({ workspaceId, children, }: {
96
134
  workspaceId: string;
97
135
  children: ReactNode;
98
136
  }): ReactElement;
137
+ /** The id of the workspace this component is inside. Throws outside a
138
+ * `<WorkspaceIdProvider>`. */
99
139
  declare function useWorkspaceId(): string;
100
140
 
141
+ /** An instrument's own state and config, plus setters. Reads the surrounding
142
+ * workspace id, so an instrument never has to know which workspace it is
143
+ * running in. Throws outside a lab store and workspace. */
101
144
  declare function useExperimentState<TS = unknown, TC = unknown>(): ExperimentStateHandle<TS, TC>;
102
145
 
103
146
  export { LabStoreContext as b, LabStoreProvider as c, WorkspaceIdContext as f, WorkspaceIdProvider as g, createLabStore as h, createMemoryAdapter as i, useExperimentState as j, useLabStore as k, localStorageAdapter as l, useWorkspaceId as m, noneAdapter as n, sessionStorageAdapter as s, urlHashAdapter as u };
@@ -1,15 +1,18 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
- import { V as ViewTransform, d as Point } from '../_dts/index-C6Yze7sQ.js';
5
- import '../_dts/types-Si4Fw-1F.js';
4
+ import { V as ViewTransform, d as Point } from '../_dts/index-CFlDPeZh.js';
5
+ import '../_dts/types-x92Kfeme.js';
6
6
 
7
+ /** One layer of a canvas stack: its id, whether it is currently shown, and how
8
+ * it paints itself. */
7
9
  interface CanvasLayerDescriptor {
8
10
  id: string;
9
11
  visible: boolean;
10
12
  render: (ctx: CanvasRenderingContext2D, view: ViewTransform) => void;
11
13
  }
12
14
 
15
+ /** Props for `<CanvasStack>`. */
13
16
  interface CanvasStackProps {
14
17
  layers: CanvasLayerDescriptor[];
15
18
  view: ViewTransform;
@@ -20,14 +23,22 @@ interface CanvasStackProps {
20
23
  onHitTest?: (worldPos: Point) => void;
21
24
  children?: ReactNode;
22
25
  }
26
+ /** Stacks one `<canvas>` per layer and drives them from a shared view, so a
27
+ * layer that changes rarely is not redrawn with one that changes every frame.
28
+ * Handles sizing, device pixel ratio, and pan/zoom. */
23
29
  declare function CanvasStack({ layers, view, onViewChange, width, height, className, onHitTest, children, }: CanvasStackProps): react_jsx_runtime.JSX.Element;
24
30
 
31
+ /** What a canvas stack publishes to its children — currently the view, so
32
+ * DOM overlays can position themselves in the same coordinates. */
25
33
  interface CanvasStackContextValue {
26
34
  view: ViewTransform;
27
35
  }
36
+ /** Context carrying the surrounding canvas stack's view. */
28
37
  declare const CanvasStackContext: react.Context<CanvasStackContextValue | null>;
29
38
 
39
+ /** Project a world point into screen coordinates under a view. */
30
40
  declare function worldToScreen(world: Point, view: ViewTransform): Point;
41
+ /** Unproject a screen point back to world coordinates under a view. */
31
42
  declare function screenToWorld(screen: Point, view: ViewTransform): Point;
32
43
 
33
44
  export { CanvasStack, CanvasStackContext, screenToWorld, worldToScreen };
@@ -1,4 +1,4 @@
1
- export { CanvasStack, screenToWorld, worldToScreen } from '../chunk-54IQ2DX7.js';
2
- export { CanvasStackContext } from '../chunk-PWC7AQZM.js';
1
+ export { CanvasStack, screenToWorld, worldToScreen } from '../chunk-574LJAV4.js';
2
+ export { CanvasStackContext } from '../chunk-CPUJ3QXL.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map