@weasel-js/labkit 1.4.4 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/README.md +13 -2
  2. package/dist/_dts/{CanvasStackContext-kTEZvEgE.d.ts → CanvasStackContext-CqkxkFJW.d.ts} +1 -1
  3. package/dist/_dts/ToggleBar.d-DbHoWKIA.d.ts +116 -0
  4. package/dist/_dts/{frac-z7ker2Vx.d.ts → frac-8R6UmlvN.d.ts} +253 -31
  5. package/dist/_dts/index-B8uu2ba7.d.ts +237 -0
  6. package/dist/_dts/{index-Blv9uQzu.d.ts → index-retnAut7.d.ts} +18 -10
  7. package/dist/_dts/{types-B9_zrHmb.d.ts → types-Ca2LCnPq.d.ts} +65 -2
  8. package/dist/_dts/usePanZoom-nS798rOF.d.ts +160 -0
  9. package/dist/_dts/useTrialState-jcx_TdU6.d.ts +212 -0
  10. package/dist/canvas/index.d.ts +17 -128
  11. package/dist/canvas/index.js +4 -2
  12. package/dist/chrome/index.d.ts +4 -92
  13. package/dist/chrome/index.js +9 -5
  14. package/dist/chunk-67SJLMC7.js +704 -0
  15. package/dist/chunk-67SJLMC7.js.map +1 -0
  16. package/dist/chunk-6ZDGOZQV.js +310 -0
  17. package/dist/chunk-6ZDGOZQV.js.map +1 -0
  18. package/dist/{chunk-MOM3GOVY.js → chunk-EKIICY6X.js} +111 -25
  19. package/dist/chunk-EKIICY6X.js.map +1 -0
  20. package/dist/{chunk-CTRKTLYZ.js → chunk-H6ZAOWNE.js} +11 -11
  21. package/dist/chunk-H6ZAOWNE.js.map +1 -0
  22. package/dist/{chunk-SMHP6XZ4.js → chunk-KJALCDWE.js} +9 -7
  23. package/dist/chunk-KJALCDWE.js.map +1 -0
  24. package/dist/{chunk-BKFVHKJH.js → chunk-MUKOW3TC.js} +3 -3
  25. package/dist/{chunk-BKFVHKJH.js.map → chunk-MUKOW3TC.js.map} +1 -1
  26. package/dist/chunk-NDRYLVOW.js +15 -0
  27. package/dist/chunk-NDRYLVOW.js.map +1 -0
  28. package/dist/{chunk-64ZCN3DA.js → chunk-NS64DXMN.js} +226 -159
  29. package/dist/chunk-NS64DXMN.js.map +1 -0
  30. package/dist/{chunk-I6JCVE24.js → chunk-PGETSEDK.js} +135 -13
  31. package/dist/chunk-PGETSEDK.js.map +1 -0
  32. package/dist/{chunk-FQMJUVHJ.js → chunk-QLSV2N3G.js} +32 -37
  33. package/dist/chunk-QLSV2N3G.js.map +1 -0
  34. package/dist/chunk-RWNDDKOH.js +682 -0
  35. package/dist/chunk-RWNDDKOH.js.map +1 -0
  36. package/dist/chunk-S2SHZRD7.js +7681 -0
  37. package/dist/chunk-S2SHZRD7.js.map +1 -0
  38. package/dist/{chunk-U3IYHIAE.js → chunk-TQBBYTAF.js} +19 -82
  39. package/dist/chunk-TQBBYTAF.js.map +1 -0
  40. package/dist/chunk-UU3NJO6N.js +72 -0
  41. package/dist/chunk-UU3NJO6N.js.map +1 -0
  42. package/dist/chunk-WIG6XHJ7.js +35 -0
  43. package/dist/chunk-WIG6XHJ7.js.map +1 -0
  44. package/dist/{chunk-TJ7QY3OC.js → chunk-ZPH5WTWF.js} +21 -15
  45. package/dist/chunk-ZPH5WTWF.js.map +1 -0
  46. package/dist/config/index.d.ts +232 -0
  47. package/dist/config/index.js +6 -0
  48. package/dist/config/index.js.map +1 -0
  49. package/dist/controls/index.d.ts +2 -3
  50. package/dist/controls/index.js +3 -2
  51. package/dist/dragdrop/index.d.ts +2 -4
  52. package/dist/index.d.ts +110 -381
  53. package/dist/index.js +691 -817
  54. package/dist/index.js.map +1 -1
  55. package/dist/layers/index.d.ts +3 -5
  56. package/dist/layers/index.js +2 -2
  57. package/dist/loupe/index.d.ts +6 -8
  58. package/dist/loupe/index.js +2 -2
  59. package/dist/passthrough/weasel-ui.d.ts +164 -122
  60. package/dist/passthrough/weasel-ui.js +1 -1
  61. package/dist/primitives/index.d.ts +53 -6
  62. package/dist/primitives/index.js +6 -4
  63. package/dist/state/index.d.ts +12 -7
  64. package/dist/state/index.js +16 -13
  65. package/dist/state/index.js.map +1 -1
  66. package/dist/styles.css +84 -50
  67. package/dist/surface/index.d.ts +44 -7
  68. package/dist/surface/index.js +2 -1
  69. package/dist/ui/layers/index.js +1 -1
  70. package/dist/undo/index.d.ts +2 -4
  71. package/package.json +15 -8
  72. package/src/annotations/AnnotationOverlay.tsx +53 -5
  73. package/src/annotations/Annotations.overlay.test.tsx +85 -6
  74. package/src/annotations/drawOne.test.ts +1 -1
  75. package/src/annotations/drawOne.ts +2 -2
  76. package/src/annotations/paint.test.ts +2 -2
  77. package/src/annotations/paint.ts +1 -1
  78. package/src/annotations/preload.ts +6 -0
  79. package/src/annotations/store.test.ts +18 -0
  80. package/src/annotations/store.ts +5 -4
  81. package/src/annotations/svgNodes.test.ts +2 -2
  82. package/src/annotations/toolMap.ts +3 -3
  83. package/src/annotations/types.ts +6 -3
  84. package/src/canvas/CameraWheelContext.ts +12 -0
  85. package/src/canvas/CanvasStack.test.tsx +25 -0
  86. package/src/canvas/CanvasStack.tsx +31 -4
  87. package/src/canvas/Stage.less +18 -0
  88. package/src/canvas/Stage.test.tsx +186 -0
  89. package/src/canvas/Stage.tsx +134 -0
  90. package/src/canvas/camera.test.ts +17 -2
  91. package/src/canvas/camera.ts +9 -9
  92. package/src/canvas/index.ts +4 -0
  93. package/src/canvas/usePanZoom.ts +10 -5
  94. package/src/chrome/ChromeRegions.stories.tsx +0 -3
  95. package/src/chrome/LabChrome.tsx +114 -0
  96. package/src/chrome/builtins.tsx +20 -31
  97. package/src/chrome/index.ts +15 -0
  98. package/src/chrome/labRegions.test.tsx +208 -0
  99. package/src/chrome/labTypes.ts +50 -0
  100. package/src/chrome/merge.ts +7 -9
  101. package/src/chrome/regions/PaletteRegion.test.tsx +6 -4
  102. package/src/chrome/regions/PaletteRegion.tsx +21 -9
  103. package/src/chrome/regions/SidebarRegion.tsx +25 -13
  104. package/src/chrome/regions/StatusRegion.tsx +15 -8
  105. package/src/chrome/regions/ToolbarRegion.tsx +30 -16
  106. package/src/chrome/types.ts +47 -20
  107. package/src/config/builder.test.ts +4 -0
  108. package/src/config/builder.ts +16 -10
  109. package/src/config/declarationEmit.fixture.ts +11 -0
  110. package/src/config/declarationEmit.test.ts +51 -0
  111. package/src/config/entry.test.ts +46 -0
  112. package/src/config/index.ts +13 -1
  113. package/src/config/nodeClasses.test.ts +18 -0
  114. package/src/config/types.ts +3 -1
  115. package/src/controls/ControlPanel.test.tsx +16 -0
  116. package/src/controls/ControlPanel.tsx +5 -2
  117. package/src/fake-indexeddb-auto.d.ts +5 -0
  118. package/src/index.test.ts +7 -0
  119. package/src/index.ts +38 -5
  120. package/src/instrument/serializers.test.ts +22 -0
  121. package/src/instrument/serializers.ts +11 -0
  122. package/src/instrument/types.ts +25 -1
  123. package/src/lab/Lab.less +4 -13
  124. package/src/lab/Lab.persist.test.tsx +147 -0
  125. package/src/lab/Lab.stories.tsx +0 -2
  126. package/src/lab/Lab.surface.test.tsx +66 -3
  127. package/src/lab/Lab.test.tsx +91 -17
  128. package/src/lab/Lab.tsx +337 -124
  129. package/src/lab/LabFit.stories.less +18 -0
  130. package/src/lab/LabFit.stories.tsx +219 -0
  131. package/src/lab/LabFullChrome.stories.tsx +0 -3
  132. package/src/lab/LabHeader.test.tsx +40 -9
  133. package/src/lab/LabHeader.tsx +7 -13
  134. package/src/lab/LabPalette.tsx +13 -26
  135. package/src/lab/LabShell.less +49 -12
  136. package/src/lab/LabSwitcher.less +8 -1
  137. package/src/lab/Workspace.surface.test.tsx +2 -1
  138. package/src/lab/fitCheck.test.ts +57 -0
  139. package/src/lab/fitCheck.ts +125 -0
  140. package/src/loupe/AGENTS.md +1 -1
  141. package/src/loupe/Loupe.less +1 -1
  142. package/src/loupe/canvasLens.ts +1 -1
  143. package/src/loupe/types.ts +1 -1
  144. package/src/loupe/useLoupe.test.tsx +1 -1
  145. package/src/loupe/useLoupe.ts +1 -1
  146. package/src/passthrough/weasel-ui.ts +9 -0
  147. package/src/primitives/FloatingPanel.stories.tsx +13 -1
  148. package/src/primitives/FloatingPanel.test.tsx +47 -16
  149. package/src/primitives/FloatingPanel.tsx +11 -25
  150. package/src/primitives/Split.less +14 -0
  151. package/src/primitives/Split.test.tsx +108 -0
  152. package/src/primitives/Split.tsx +159 -0
  153. package/src/primitives/ZoomControl.tsx +5 -2
  154. package/src/primitives/index.ts +2 -0
  155. package/src/state/Persistence.stories.tsx +75 -0
  156. package/src/state/Persistence.tsx +33 -0
  157. package/src/state/SingletonExperiment.test.tsx +47 -53
  158. package/src/state/SingletonExperiment.tsx +24 -13
  159. package/src/state/adapterContract.ts +116 -0
  160. package/src/state/adapters.test.ts +113 -61
  161. package/src/state/adapters.ts +328 -69
  162. package/src/state/document.test.ts +71 -96
  163. package/src/state/document.ts +66 -52
  164. package/src/state/helpers.test.ts +1 -1
  165. package/src/state/index.ts +8 -0
  166. package/src/state/labRecords.test.ts +105 -0
  167. package/src/state/labRecords.ts +160 -0
  168. package/src/state/openLabStore.test.ts +658 -0
  169. package/src/state/openLabStore.ts +403 -0
  170. package/src/state/records.test.ts +234 -0
  171. package/src/state/records.ts +219 -0
  172. package/src/state/store.test.ts +104 -635
  173. package/src/state/store.ts +116 -157
  174. package/src/state/toolSlot.test.ts +1 -1
  175. package/src/state/types.ts +39 -15
  176. package/src/state/useOpenOnce.ts +68 -0
  177. package/src/state/usePersistedState.test.tsx +125 -0
  178. package/src/state/usePersistedState.ts +66 -0
  179. package/src/state/useTrialState.test.tsx +2 -3
  180. package/src/state/view.test.ts +49 -15
  181. package/src/state/view.ts +18 -1
  182. package/src/styles.less +2 -0
  183. package/src/surface/AGENTS.md +39 -7
  184. package/src/surface/SurfaceContext.ts +26 -3
  185. package/src/surface/index.ts +2 -0
  186. package/src/surface/useSurfaceTile.test.tsx +2 -1
  187. package/src/surface/useSurfaceTile.ts +6 -5
  188. package/src/surface/useTiledSurface.test.tsx +175 -0
  189. package/src/surface/useTiledSurface.ts +54 -5
  190. package/src/theme/Interstellar.stories.tsx +7 -7
  191. package/src/theme/interstellar.test.ts +1 -1
  192. package/src/theme/interstellar.tokens.json +2 -2
  193. package/src/tools/labTool.ts +11 -0
  194. package/src/trial/Trial.annotations.persist.test.tsx +100 -58
  195. package/src/trial/Trial.annotations.test.tsx +47 -4
  196. package/src/trial/Trial.job.test.tsx +3 -3
  197. package/src/trial/Trial.less +1 -26
  198. package/src/trial/Trial.stories.tsx +1 -2
  199. package/src/trial/Trial.test.tsx +28 -4
  200. package/src/trial/Trial.trialId.test.tsx +23 -1
  201. package/src/trial/Trial.tsx +118 -38
  202. package/src/trial/TrialBody.tsx +17 -141
  203. package/src/trial/TrialChrome.tsx +7 -4
  204. package/src/trial/trialOps.ts +5 -3
  205. package/dist/_dts/types-BP2OCcpg.d.ts +0 -155
  206. package/dist/_dts/types-x92Kfeme.d.ts +0 -62
  207. package/dist/_dts/useTrialState-D6Vb3T-g.d.ts +0 -99
  208. package/dist/chunk-2P6PP5N4.js +0 -553
  209. package/dist/chunk-2P6PP5N4.js.map +0 -1
  210. package/dist/chunk-64ZCN3DA.js.map +0 -1
  211. package/dist/chunk-CTRKTLYZ.js.map +0 -1
  212. package/dist/chunk-FQMJUVHJ.js.map +0 -1
  213. package/dist/chunk-I6JCVE24.js.map +0 -1
  214. package/dist/chunk-MOM3GOVY.js.map +0 -1
  215. package/dist/chunk-SMHP6XZ4.js.map +0 -1
  216. package/dist/chunk-TJ7QY3OC.js.map +0 -1
  217. package/dist/chunk-U3IYHIAE.js.map +0 -1
  218. package/dist/chunk-W3ECWC2K.js +0 -7335
  219. package/dist/chunk-W3ECWC2K.js.map +0 -1
@@ -0,0 +1,212 @@
1
+ import { c as StorageAdapter, d as LabStoreState, T as TrialRecord, e as SavedSnapshot, o as LabMode, h as UndockedPanel, q as InstrumentList, s as InstrumentHooks, C as CreateLabStoreOptions, g as TrialStateHandle } from './frac-8R6UmlvN.js';
2
+ import * as react from 'react';
3
+ import { ReactNode, ReactElement, Dispatch, SetStateAction } from 'react';
4
+ import { StoreApi } from 'zustand/vanilla';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+
7
+ /** Persist to `localStorage`, one JSON value per record. Survives a reload and
8
+ * reaches other tabs through the `storage` event. */
9
+ declare const localStorageAdapter: StorageAdapter;
10
+ /** Persist to `sessionStorage` — survives a reload but not a new tab. */
11
+ declare const sessionStorageAdapter: StorageAdapter;
12
+ /** Persist into the URL fragment, so the page's link carries its state and can
13
+ * be shared or bookmarked. Changes to the fragment made elsewhere — a pasted
14
+ * link, back and forward — arrive through `hashchange`. */
15
+ declare const urlHashAdapter: StorageAdapter;
16
+ /** An in-memory store, discarded on reload. Values are copied in and out, as a
17
+ * real substrate would. Adapters built over one shared `backing` hear each
18
+ * other's writes — two tabs, for a test. */
19
+ declare function createMemoryAdapter(backing?: Map<string, unknown>): StorageAdapter;
20
+ /** Persists nothing and reads back nothing. */
21
+ declare const noneAdapter: StorageAdapter;
22
+ /** Options for `createIndexedDbAdapter`. */
23
+ interface IndexedDbAdapterOptions {
24
+ /** Default `'labkit'`. */
25
+ database?: string;
26
+ /** Default `'records'`. One object store per database: a store added to a
27
+ * database that already exists is not created. */
28
+ store?: string;
29
+ }
30
+ /** Persist to IndexedDB, which stores structured-clone values natively — typed
31
+ * arrays, `Map`s, `Blob`s — and holds far more than localStorage. Other tabs
32
+ * hear writes through a `BroadcastChannel`. The database opens on first use. */
33
+ declare function createIndexedDbAdapter({ database, store, }?: IndexedDbAdapterOptions): StorageAdapter;
34
+ /** IndexedDB under the default database and store. */
35
+ declare const indexedDbAdapter: StorageAdapter;
36
+
37
+ /** Every mutation a lab store supports: managing trials, saving and
38
+ * restoring snapshots, and setting the color mode. */
39
+ interface LabStoreActions {
40
+ addTrial: (record: Omit<TrialRecord, 'undoStack'>) => void;
41
+ removeTrial: (id: string) => void;
42
+ updateTrialState: <TS>(id: string, next: TS | ((prev: TS) => TS)) => void;
43
+ /** Write one config value. `path` is dotted for a value nested under an
44
+ * `f.group`, and the bare key for one at the root. */
45
+ updateTrialConfig: (id: string, path: string, value: unknown) => void;
46
+ updateTrialView: (id: string, view: unknown) => void;
47
+ updateTrialSidebarWidth: (id: string, width: number) => void;
48
+ /** Retitle a trial. `null` returns it to its instrument's name. */
49
+ setTrialTitle: (id: string, title: string | null) => void;
50
+ /** Fold or unfold one of a trial's sections. */
51
+ setTrialSectionCollapsed: (id: string, key: string, collapsed: boolean) => void;
52
+ updateTrialAnnotations: (id: string, doc: unknown) => void;
53
+ updateTrialUndoStack: (id: string, next: TrialRecord['undoStack'] | ((prev: TrialRecord['undoStack']) => TrialRecord['undoStack'])) => void;
54
+ setTrialInstrument: (id: string, instrumentName: string) => void;
55
+ saveSnapshot: (trialId: string, name: string) => void;
56
+ loadSnapshot: (snapshotId: string, trialId: string) => void;
57
+ deleteSnapshot: (snapshotId: string) => void;
58
+ listSnapshots: (trialId?: string) => SavedSnapshot[];
59
+ setMode: (mode: LabMode) => void;
60
+ setLabTool: (id: string | null) => void;
61
+ setTrialTool: (trialId: string, id: string | null) => void;
62
+ setLayout: (layout: Record<string, unknown>) => void;
63
+ /** Tear a sidebar section out of its trial. Default target is a workspace tile. */
64
+ undockPanel: (trialId: string, sectionId: string, as?: UndockedPanel['as']) => void;
65
+ /** Put one section back, or — with no `sectionId` — every panel the trial owns. */
66
+ dockPanel: (trialId: string, sectionId?: string) => void;
67
+ /** Replace the lab's instruments. Trials and saves of an instrument that is
68
+ * new or a different object are brought up to date against it in the same
69
+ * write; every other trial keeps its object. */
70
+ setInstruments: (instruments: InstrumentList) => void;
71
+ /** The per-instrument hooks in force now. Read them at use; never keep them. */
72
+ instrumentHooks: () => InstrumentHooks;
73
+ }
74
+ /** A lab's store: its state and its actions. How each instrument's state is
75
+ * serialized comes in through `CreateLabStoreOptions.instruments`. */
76
+ type LabStore = StoreApi<LabStoreState & LabStoreActions>;
77
+ /** Build a lab store holding `initial`, or an empty lab. It knows nothing
78
+ * about storage; `openLabStore` reads a stored lab and binds one of these to
79
+ * it. */
80
+ declare function createLabStore(options?: CreateLabStoreOptions): LabStore;
81
+
82
+ type LabStoreCtx = {
83
+ store: LabStore;
84
+ } | null;
85
+ /** Context carrying the lab store. Prefer `useLabStore`; this is exported for
86
+ * code that needs to read the context without subscribing. */
87
+ declare const LabStoreContext: react.Context<LabStoreCtx>;
88
+ /** Provides a lab store to its subtree. */
89
+ declare function LabStoreProvider({ store, children, }: {
90
+ store: LabStore;
91
+ children: ReactNode;
92
+ }): ReactElement;
93
+ /** Subscribe to the whole lab store. Throws outside a `<LabStoreProvider>`. */
94
+ declare function useLabStore(): LabStoreState & ReturnType<LabStore['getState']>;
95
+ /** Context carrying which trial the subtree belongs to. */
96
+ declare const TrialIdContext: react.Context<string | null>;
97
+ /** Names the trial its subtree belongs to, so an instrument's hooks can
98
+ * find their own record in the store without being passed an id. */
99
+ declare function TrialIdProvider({ trialId, children, }: {
100
+ trialId: string;
101
+ children: ReactNode;
102
+ }): ReactElement;
103
+ /** The id of the trial this component is inside. Throws outside a
104
+ * `<TrialIdProvider>`. */
105
+ declare function useTrialId(): string;
106
+
107
+ /** Bumped whenever the persisted shape changes; every bump needs a migration. */
108
+ declare const CURRENT_DOCUMENT_VERSION = 4;
109
+ /** Where a version-3 lab kept its one document. Read once, to fold it into
110
+ * records, then deleted. */
111
+ declare function labDocumentKey(storageKey: string): string;
112
+ /** Where a document that failed to migrate is set aside, so a bad migration
113
+ * loses state loudly rather than silently. */
114
+ declare function quarantineKey(storageKey: string): string;
115
+
116
+ /** One record changing, as a cache listener hears it. `value` is `undefined`
117
+ * for a delete. `local` changes were made through this cache; `remote` ones
118
+ * came from another writer. */
119
+ interface RecordChange {
120
+ name: string;
121
+ value: unknown;
122
+ origin: 'local' | 'remote';
123
+ }
124
+ /**
125
+ * Every record under one prefix, held in memory: the only thing that talks to
126
+ * a `StorageAdapter`. Names are keys with the prefix removed.
127
+ *
128
+ * Writes land in memory at once and reach storage on a debounce. The newest
129
+ * write to a record wins: another writer's change to a record with a write
130
+ * still queued here is ignored, since the queued write lands after it.
131
+ */
132
+ interface RecordCache {
133
+ readonly prefix: string;
134
+ /** False once writing is off — the records could not be read, or were
135
+ * written by a newer labkit — so nothing here can overwrite them. */
136
+ readonly writable: boolean;
137
+ has(name: string): boolean;
138
+ get(name: string): unknown;
139
+ /** Every record whose name starts with `namePrefix`. */
140
+ entries(namePrefix?: string): [string, unknown][];
141
+ set(name: string, value: unknown): void;
142
+ delete(name: string): void;
143
+ subscribe(listener: (changes: RecordChange[]) => void): () => void;
144
+ /** Send queued writes now. */
145
+ flush(): Promise<void>;
146
+ /** Send queued writes and stop hearing other writers. */
147
+ close(): Promise<void>;
148
+ }
149
+
150
+ /** Options for `openLabStore`. `storageKey` names the lab, so two labs on one
151
+ * origin keep separate records. */
152
+ interface OpenLabStoreOptions extends Omit<CreateLabStoreOptions, 'initial'> {
153
+ storageKey: string;
154
+ storage: StorageAdapter;
155
+ }
156
+ /** A lab store bound to its records. */
157
+ interface OpenedLabStore {
158
+ store: LabStore;
159
+ /** Every record of the lab, `usePersistedState` values included. */
160
+ records: RecordCache;
161
+ /** Send queued writes and stop hearing other writers. */
162
+ close(): Promise<void>;
163
+ }
164
+ /**
165
+ * Read a stored lab and return a store bound to it: every change to the store
166
+ * is written as the records it touched, and another writer's records are
167
+ * applied back into the store. A lab stored before records existed is folded
168
+ * forward on the way in.
169
+ */
170
+ declare function openLabStore(options: OpenLabStoreOptions): Promise<OpenedLabStore>;
171
+
172
+ /** Props for `<Persistence>`. */
173
+ interface PersistenceProps {
174
+ /** Names the records, as `<Lab storageKey>` does. A lab and a
175
+ * `<Persistence>` given the same key share lab-scoped values. */
176
+ storageKey: string;
177
+ /** Default: IndexedDB, or localStorage where IndexedDB will not open. */
178
+ storage?: StorageAdapter;
179
+ /** Rendered until the records have loaded. Default: nothing. */
180
+ fallback?: ReactNode;
181
+ children: ReactNode;
182
+ }
183
+ /** Persisted values for a page with no lab: `usePersistedState` below it keeps
184
+ * what it holds across a reload. Both props are read once, at mount. */
185
+ declare function Persistence({ storageKey, storage, fallback, children }: PersistenceProps): react_jsx_runtime.JSX.Element;
186
+
187
+ /** Options for `usePersistedState`. */
188
+ interface PersistedStateOptions {
189
+ /** `'trial'` — the default inside a trial — keeps a value per trial, and
190
+ * closing the trial deletes it. `'lab'` shares one value across the lab. */
191
+ scope?: 'trial' | 'lab';
192
+ }
193
+ /**
194
+ * `useState` whose value survives a reload: a widget's open tab, a panel's
195
+ * position. Inside a `<Lab>`, `SingletonExperimentProvider` or `<Persistence>`
196
+ * the value is a record, loaded before first render and re-rendered when
197
+ * another tab changes it. With no provider above it, or a null `name`, it is
198
+ * plain `useState` — so a component can offer optional persistence and still
199
+ * mount anywhere.
200
+ *
201
+ * Values must be structured-clone values; the JSON-backed adapters warn about
202
+ * one JSON would change. Snapshots do not include them.
203
+ */
204
+ declare function usePersistedState<T>(name: string | null | undefined, initial: T | (() => T), options?: PersistedStateOptions): [T, Dispatch<SetStateAction<T>>];
205
+
206
+ /** An instrument's own state and config, plus setters. Reads the surrounding
207
+ * trial id, so an instrument never has to know which trial it is
208
+ * running in. Throws outside a lab store and trial. */
209
+ declare function useTrialState<TS = unknown, TC = unknown>(): TrialStateHandle<TS, TC>;
210
+
211
+ export { CURRENT_DOCUMENT_VERSION as C, TrialIdContext as T, LabStoreContext as b, LabStoreProvider as c, Persistence as e, TrialIdProvider as h, createIndexedDbAdapter as i, createLabStore as j, createMemoryAdapter as k, indexedDbAdapter as l, labDocumentKey as m, localStorageAdapter as n, noneAdapter as o, openLabStore as p, quarantineKey as q, useLabStore as r, sessionStorageAdapter as s, usePersistedState as t, urlHashAdapter as u, useTrialId as v, useTrialState as w };
212
+ export type { IndexedDbAdapterOptions as I, LabStore as L, OpenLabStoreOptions as O, PersistedStateOptions as P, RecordCache as R, LabStoreActions as a, OpenedLabStore as d, PersistenceProps as f, RecordChange as g };
@@ -1,135 +1,24 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
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-z7ker2Vx.js';
4
- export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-z7ker2Vx.js';
5
- import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-kTEZvEgE.js';
6
- export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-kTEZvEgE.js';
7
- import '../_dts/types-B9_zrHmb.js';
1
+ import * as react from 'react';
2
+ export { C as CanvasStack, a as CanvasStackProps, O as OrbitHandlers, b as OrbitView, P as PITCH_LIMIT, c as PanZoomHandlers, S as Stage, d as StageProps, U as UseOrbitOptions, e as UsePanZoomOptions, V as Vec3, Z as ZoomAtOptions, f as centerOn, g as clampPitch, h as fitStage, o as orbitAfterDrag, i as orbitAfterWheel, s as screenToWorld, u as useOrbit, j as usePanZoom, w as worldToScreen, k as wrapYaw, z as zoomAt } from '../_dts/usePanZoom-nS798rOF.js';
3
+ export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-CqkxkFJW.js';
4
+ export { D as DEFAULT_FRAME, V as ViewportSize, W as WorldFrame, a as WorldSpec, b as applyCamera, r as resolveFrame } from '../_dts/frac-8R6UmlvN.js';
5
+ import 'react/jsx-runtime';
6
+ import '../_dts/types-Ca2LCnPq.js';
8
7
  import '@weasel-js/core';
9
8
  import '../_dts/PrefsForm.d-DDHFANkc.js';
10
- import '../_dts/types-x92Kfeme.js';
11
- import '../_dts/types-BP2OCcpg.js';
12
9
  import '../_dts/types-DJ79Tg5J.js';
13
10
 
14
- /** Props for `<CanvasStack>`. */
15
- interface CanvasStackProps {
16
- layers: CanvasLayerDescriptor[];
17
- view: ViewTransform;
18
- onViewChange: (v: ViewTransform) => void;
19
- /** The instrument's coordinate system. Omitted, world (0,0) sits at the
20
- * element's top-left with y running down. */
21
- worldSpec?: WorldSpec;
22
- minZoom?: number;
23
- maxZoom?: number;
24
- width?: number | string;
25
- height?: number | string;
26
- className?: string;
27
- /** Fired whenever the stack is measured, so a consumer can place a view that
28
- * only makes sense in terms of the viewport. */
29
- onResize?: (size: ViewportSize) => void;
30
- onHitTest?: (worldPos: Point) => void;
31
- children?: ReactNode;
32
- }
33
- /** Stacks one `<canvas>` per layer and drives them from a shared view, so a
34
- * layer that changes rarely is not redrawn with one that changes every frame.
35
- * Handles sizing, device pixel ratio, and pan/zoom. */
36
- declare function CanvasStack({ layers, view, onViewChange, worldSpec, minZoom, maxZoom, width, height, className, onResize, onHitTest, children, }: CanvasStackProps): react_jsx_runtime.JSX.Element;
37
-
38
- /** Bounds and coordinate system a {@link zoomAt} works in. */
39
- interface ZoomAtOptions {
40
- /** The instrument's coordinate system, resolved against the viewport.
41
- * Omitted, `at` is measured from the element's top-left. */
42
- frame?: WorldFrame;
43
- min?: number;
44
- max?: number;
45
- }
11
+ /** Where a trial's camera takes a wheel event from outside its own element. */
12
+ type CameraWheelSlot = {
13
+ current: ((e: WheelEvent) => void) | null;
14
+ };
46
15
  /**
47
- * Zoom a view by `factor` about a fixed point, so whatever world coordinate
48
- * `at` was over stays under it.
49
- *
50
- * `at` is in the element's own pixels — a cursor position, or the centre of a
51
- * lens. The clamp is applied before the pan is solved, so a zoom that hits a
52
- * bound still anchors on the zoom it actually reached.
16
+ * The trial's camera, for input that lands outside it. An annotation target's
17
+ * input box is portalled into the surface container, so a wheel over a mark
18
+ * never bubbles through the stage or canvas stack it sits on; the box hands
19
+ * the event here instead.
53
20
  */
54
- declare function zoomAt(view: ViewTransform, factor: number, at: Point, { frame, min, max }?: ZoomAtOptions): ViewTransform;
55
- /** The view that puts a world point at the centre of a `size` viewport, at
56
- * `zoom`. What a lens showing a region around one point renders through. */
57
- declare function centerOn(world: Point, zoom: number, size: ViewportSize, frame?: WorldFrame): ViewTransform;
58
-
59
- /** Project a world point into screen coordinates under a view.
60
- *
61
- * `frame` is the instrument's declared coordinate system, resolved against the
62
- * viewport; omitting it gives labkit's original one — origin at the top-left,
63
- * y downward. */
64
- declare function worldToScreen(world: Point, view: ViewTransform, frame?: WorldFrame): Point;
65
- /** Unproject a screen point back to world coordinates under a view. */
66
- declare function screenToWorld(screen: Point, view: ViewTransform, frame?: WorldFrame): Point;
67
-
68
- /** A point in the space the instrument works in. */
69
- interface Vec3 {
70
- x: number;
71
- y: number;
72
- z: number;
73
- }
74
- /** An orbit camera as a trial view: where it looks from, and what it looks at.
75
- * labkit does not turn this into a matrix — the host's renderer does. */
76
- interface OrbitView {
77
- yaw: number;
78
- pitch: number;
79
- distance: number;
80
- target: Vec3;
81
- }
82
- /** Just short of the pole. At exactly ±PI/2 the azimuth is undefined and the
83
- * camera rolls, which reads as the model jumping rather than as a limit. */
84
- declare const PITCH_LIMIT: number;
85
- declare function clampPitch(pitch: number): number;
86
- declare function wrapYaw(yaw: number): number;
87
- /** The view a drag of (dx, dy) from `start` produces. Absolute against the drag
88
- * start, so it can be re-applied any number of times without compounding. */
89
- declare function orbitAfterDrag(start: OrbitView, dx: number, dy: number): OrbitView;
90
- /** Multiplicative, so one notch covers the same proportion of the distance
91
- * whether the camera is near or far. */
92
- declare function orbitAfterWheel(view: OrbitView, deltaY: number, minDistance: number, maxDistance: number): OrbitView;
93
- interface UseOrbitOptions {
94
- view: OrbitView;
95
- onViewChange: (v: OrbitView) => void;
96
- /** Restored on double-click. Defaults to the view the hook first saw. */
97
- home?: OrbitView;
98
- minDistance?: number;
99
- maxDistance?: number;
100
- }
101
- interface OrbitHandlers {
102
- onWheel: (e: WheelEvent<HTMLElement>) => void;
103
- onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
104
- onDoubleClick: () => void;
105
- isDragging: () => boolean;
106
- }
107
- /** Pointer gestures over an orbit view: drag to turn, wheel or pinch to dolly,
108
- * double-click to go home. The 3D peer of `usePanZoom`. */
109
- declare function useOrbit({ view, onViewChange, home, minDistance, maxDistance, }: UseOrbitOptions): OrbitHandlers;
110
-
111
- interface UsePanZoomOptions {
112
- view: ViewTransform;
113
- onViewChange: (v: ViewTransform) => void;
114
- /** The opening `view.zoom` always stays reachable, widening these past
115
- * whatever is passed here if it would otherwise exclude it. */
116
- minZoom?: number;
117
- maxZoom?: number;
118
- /** The instrument's coordinate system, resolved against the viewport. The
119
- * wheel anchors in this frame; omitting it anchors at the element's
120
- * top-left, which is what labkit did before a frame could be declared. */
121
- frame?: WorldFrame;
122
- /** A primary-button press released without ever crossing the drag
123
- * threshold. The pointer session owns the release, so the gesture's end is
124
- * reported here rather than left for a consumer's own `onPointerUp`. */
125
- onTap?: (e: PointerEvent) => void;
126
- }
127
- interface PanZoomHandlers {
128
- onWheel: (e: WheelEvent<HTMLElement>) => void;
129
- onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
130
- isDragging: () => boolean;
131
- }
132
- declare function usePanZoom({ view, onViewChange, minZoom, maxZoom, frame, onTap, }: UsePanZoomOptions): PanZoomHandlers;
21
+ declare const CameraWheelContext: react.Context<CameraWheelSlot | null>;
133
22
 
134
- export { CanvasLayerDescriptor, CanvasStack, PITCH_LIMIT, ViewportSize, WorldFrame, WorldSpec, centerOn, clampPitch, orbitAfterDrag, orbitAfterWheel, screenToWorld, useOrbit, usePanZoom, worldToScreen, wrapYaw, zoomAt };
135
- export type { CanvasStackProps, OrbitHandlers, OrbitView, PanZoomHandlers, UseOrbitOptions, UsePanZoomOptions, Vec3, ZoomAtOptions };
23
+ export { CameraWheelContext };
24
+ export type { CameraWheelSlot };
@@ -1,6 +1,8 @@
1
- export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-I6JCVE24.js';
2
- export { centerOn, zoomAt } from '../chunk-CTRKTLYZ.js';
1
+ export { CameraWheelContext, CanvasStack, PITCH_LIMIT, Stage, clampPitch, fitStage, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-PGETSEDK.js';
2
+ export { centerOn, zoomAt } from '../chunk-H6ZAOWNE.js';
3
3
  export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from '../chunk-2AYGEN57.js';
4
+ import '../chunk-WIG6XHJ7.js';
4
5
  export { CanvasStackContext } from '../chunk-CQLQPQ4P.js';
6
+ import '../chunk-2YILQ7Y5.js';
5
7
  //# sourceMappingURL=index.js.map
6
8
  //# sourceMappingURL=index.js.map
@@ -1,96 +1,8 @@
1
- import { c as ControlRenderer } from '../_dts/types-B9_zrHmb.js';
2
- import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-z7ker2Vx.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-z7ker2Vx.js';
4
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ export { a as LabChromeContext, L as LabContribution, d as LabFooterRegion, e as LabHeaderRegion, f as LabRegion, g as LabRegionProps, h as LabSidebarRegion, P as PaletteRegion, i as PaletteRegionProps, S as SidebarRegion, j as SidebarRegionProps, k as StatusRegion, l as StatusRegionProps, T as TitleBarPlacement, m as TitleBarRegion, n as TitleBarRegionProps, o as ToolbarRegion, p as ToolbarRegionProps, V as ViewportRegion, q as ViewportRegionProps, s as builtinContributions, v as contributionsIn, w as labContributions, x as mergeContributions, B as suppressContributions, C as toolContributions, D as useLabChromeContext } from '../_dts/index-B8uu2ba7.js';
2
+ export { a2 as ContributionBase, a6 as IconComponent, ad as RegionContribution, ah as SidebarSection, ai as SidebarSlotContext, ak as StatusReadout, an as ToolItem, ao as ToolSlotContext, ap as ToolbarItem, aq as TrialChromeContext, N as TrialContribution, ar as TrialRegion, at as ViewportControl } from '../_dts/frac-8R6UmlvN.js';
3
+ import '../_dts/types-Ca2LCnPq.js';
5
4
  import '@weasel-js/core';
6
5
  import '../_dts/PrefsForm.d-DDHFANkc.js';
7
6
  import 'react';
8
- import '../_dts/types-x92Kfeme.js';
9
- import '../_dts/types-BP2OCcpg.js';
7
+ import 'react/jsx-runtime';
10
8
  import '../_dts/types-DJ79Tg5J.js';
11
-
12
- /**
13
- * The contributions a trial gets from what its instrument declared. This is
14
- * the whole "declaring a capability provides the chrome" rule — it replaces
15
- * the presence checks that used to be spread across the runtime.
16
- */
17
- declare function builtinContributions(instrument: Instrument, ctx: TrialChromeContext, controls?: Record<string, ControlRenderer>): TrialContribution[];
18
-
19
- /**
20
- * Concatenate contribution bundles into one list, preserving order — order
21
- * decides how a region lays its contributions out, so it is part of the
22
- * result, not an accident of it.
23
- *
24
- * Throws on a duplicate id rather than dropping one: a contribution silently
25
- * losing to a later bundle is the failure a registry exists to prevent.
26
- */
27
- declare function mergeContributions(...bundles: readonly TrialContribution[][]): TrialContribution[];
28
- /**
29
- * Drop contributions by id. Throws when an id is not present: a typo that
30
- * silently suppresses nothing is the same class of bug as a duplicate id
31
- * silently winning.
32
- */
33
- declare function suppressContributions(bundle: readonly TrialContribution[], ids: readonly string[]): TrialContribution[];
34
-
35
- /** Props for `<PaletteRegion>`. */
36
- interface PaletteRegionProps {
37
- contributions: readonly TrialContribution[];
38
- ctx: TrialChromeContext;
39
- }
40
- /** A trial's tool strip. Selection lives in the trial's or the lab's tool
41
- * slot; this region only reflects it. */
42
- declare function PaletteRegion({ contributions, ctx }: PaletteRegionProps): react_jsx_runtime.JSX.Element | null;
43
-
44
- /** Props for `<SidebarRegion>`. */
45
- interface SidebarRegionProps {
46
- contributions: readonly TrialContribution[];
47
- ctx: TrialChromeContext;
48
- }
49
- /** Lays a trial's `sidebar` contributions out as titled, collapsible sections.
50
- * A section the trial has torn out is not rendered here — `Trial` portals its
51
- * body into the workspace instead. */
52
- declare function SidebarRegion({ contributions, ctx }: SidebarRegionProps): react_jsx_runtime.JSX.Element | null;
53
-
54
- /** Props for `<StatusRegion>`. */
55
- interface StatusRegionProps {
56
- contributions: readonly TrialContribution[];
57
- ctx: TrialChromeContext;
58
- }
59
- /** Lays a trial's `status` contributions out as readouts. */
60
- declare function StatusRegion({ contributions, ctx }: StatusRegionProps): react_jsx_runtime.JSX.Element | null;
61
-
62
- /** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders
63
- * the contributions that leave `end` unset, before the title; `'actions'`
64
- * renders the ones that set it, after everything else. */
65
- type TitleBarPlacement = 'lead' | 'actions';
66
- /** Props for `<TitleBarRegion>`. */
67
- interface TitleBarRegionProps {
68
- contributions: readonly TrialContribution[];
69
- ctx: TrialChromeContext;
70
- /** Defaults to `'actions'`, where the built-ins live. */
71
- placement?: TitleBarPlacement;
72
- }
73
- /** Lays a trial's `titlebar` contributions out at one end of the bar. */
74
- declare function TitleBarRegion({ contributions, ctx, placement }: TitleBarRegionProps): react_jsx_runtime.JSX.Element | null;
75
-
76
- /** Props for `<ToolbarRegion>`. */
77
- interface ToolbarRegionProps {
78
- contributions: readonly TrialContribution[];
79
- ctx: TrialChromeContext;
80
- }
81
- /** Lays a trial's `toolbar` contributions out, grouped by their `group`. */
82
- declare function ToolbarRegion({ contributions, ctx }: ToolbarRegionProps): react_jsx_runtime.JSX.Element | null;
83
-
84
- /** Props for `<ViewportRegion>`. */
85
- interface ViewportRegionProps {
86
- contributions: readonly TrialContribution[];
87
- ctx: TrialChromeContext;
88
- }
89
- /**
90
- * Controls acting on the view of a trial. Anchored inside the content well
91
- * rather than in the toolbar, which acts on the trial itself.
92
- */
93
- declare function ViewportRegion({ contributions, ctx }: ViewportRegionProps): react_jsx_runtime.JSX.Element | null;
94
-
95
- export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, TrialChromeContext, TrialContribution, ViewportRegion, builtinContributions, mergeContributions, suppressContributions };
96
- export type { PaletteRegionProps, SidebarRegionProps, StatusRegionProps, TitleBarPlacement, TitleBarRegionProps, ToolbarRegionProps, ViewportRegionProps };
@@ -1,9 +1,13 @@
1
- export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-64ZCN3DA.js';
2
- import '../chunk-SMHP6XZ4.js';
3
- import '../chunk-U3IYHIAE.js';
1
+ export { LabFooterRegion, LabHeaderRegion, LabSidebarRegion, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, contributionsIn, labContributions, mergeContributions, suppressContributions, toolContributions, useLabChromeContext } from '../chunk-NS64DXMN.js';
2
+ import '../chunk-KJALCDWE.js';
3
+ import '../chunk-RWNDDKOH.js';
4
+ import '../chunk-TQBBYTAF.js';
5
+ import '../chunk-NDRYLVOW.js';
6
+ import '../chunk-UU3NJO6N.js';
4
7
  import '../chunk-E44SU6XS.js';
5
- import '../chunk-SBXNQW4G.js';
6
- import '../chunk-W3ECWC2K.js';
7
8
  import '../chunk-CQLQPQ4P.js';
9
+ import '../chunk-2YILQ7Y5.js';
10
+ import '../chunk-SBXNQW4G.js';
11
+ import '../chunk-S2SHZRD7.js';
8
12
  //# sourceMappingURL=index.js.map
9
13
  //# sourceMappingURL=index.js.map