@weasel-js/labkit 1.4.4 → 1.5.1

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 (278) hide show
  1. package/README.md +54 -6
  2. package/dist/_dts/{CanvasStackContext-kTEZvEgE.d.ts → CanvasStackContext-CJNMS6mz.d.ts} +1 -1
  3. package/dist/_dts/{PrefsForm.d-DDHFANkc.d.ts → PrefsForm.d-DPy9I8It.d.ts} +4 -0
  4. package/dist/_dts/Select.d-Gwr8fLpK.d.ts +453 -0
  5. package/dist/_dts/{frac-z7ker2Vx.d.ts → frac-B4okC2lX.d.ts} +291 -31
  6. package/dist/_dts/{index-Blv9uQzu.d.ts → index-BNdz-tNd.d.ts} +105 -17
  7. package/dist/_dts/index-CSJoj4LC.d.ts +248 -0
  8. package/dist/_dts/{types-B9_zrHmb.d.ts → types-DzoNY1pO.d.ts} +91 -4
  9. package/dist/_dts/usePanZoom-Pzf9f2jh.d.ts +160 -0
  10. package/dist/_dts/useTrialState-uLlmaccn.d.ts +212 -0
  11. package/dist/canvas/index.d.ts +18 -129
  12. package/dist/canvas/index.js +4 -2
  13. package/dist/chrome/index.d.ts +5 -93
  14. package/dist/chrome/index.js +10 -6
  15. package/dist/chunk-7PFH3CNM.js +150 -0
  16. package/dist/chunk-7PFH3CNM.js.map +1 -0
  17. package/dist/{chunk-I6JCVE24.js → chunk-CEIUBPPW.js} +143 -17
  18. package/dist/chunk-CEIUBPPW.js.map +1 -0
  19. package/dist/chunk-EH7UEQV7.js +590 -0
  20. package/dist/chunk-EH7UEQV7.js.map +1 -0
  21. package/dist/{chunk-MOM3GOVY.js → chunk-EHGVROVV.js} +125 -27
  22. package/dist/chunk-EHGVROVV.js.map +1 -0
  23. package/dist/{chunk-TJ7QY3OC.js → chunk-ERFMC6WU.js} +160 -78
  24. package/dist/chunk-ERFMC6WU.js.map +1 -0
  25. package/dist/{chunk-CTRKTLYZ.js → chunk-H6ZAOWNE.js} +11 -11
  26. package/dist/chunk-H6ZAOWNE.js.map +1 -0
  27. package/dist/{chunk-64ZCN3DA.js → chunk-IHUVQ3TX.js} +250 -160
  28. package/dist/chunk-IHUVQ3TX.js.map +1 -0
  29. package/dist/{chunk-FQMJUVHJ.js → chunk-IJJUK4FU.js} +53 -46
  30. package/dist/chunk-IJJUK4FU.js.map +1 -0
  31. package/dist/chunk-IXTQI7JX.js +737 -0
  32. package/dist/chunk-IXTQI7JX.js.map +1 -0
  33. package/dist/{chunk-BKFVHKJH.js → chunk-MDVTK5U3.js} +4 -4
  34. package/dist/{chunk-BKFVHKJH.js.map → chunk-MDVTK5U3.js.map} +1 -1
  35. package/dist/chunk-PHK4W562.js +72 -0
  36. package/dist/chunk-PHK4W562.js.map +1 -0
  37. package/dist/chunk-PJ7WEQBJ.js +18 -0
  38. package/dist/chunk-PJ7WEQBJ.js.map +1 -0
  39. package/dist/chunk-RWNDDKOH.js +682 -0
  40. package/dist/chunk-RWNDDKOH.js.map +1 -0
  41. package/dist/chunk-T3EC2DXD.js +12628 -0
  42. package/dist/chunk-T3EC2DXD.js.map +1 -0
  43. package/dist/{chunk-SMHP6XZ4.js → chunk-UN4U4P63.js} +10 -8
  44. package/dist/chunk-UN4U4P63.js.map +1 -0
  45. package/dist/chunk-WIG6XHJ7.js +35 -0
  46. package/dist/chunk-WIG6XHJ7.js.map +1 -0
  47. package/dist/chunk-Z76KEZAX.js +15 -0
  48. package/dist/chunk-Z76KEZAX.js.map +1 -0
  49. package/dist/chunk-ZDHY47EV.js +363 -0
  50. package/dist/chunk-ZDHY47EV.js.map +1 -0
  51. package/dist/config/index.d.ts +276 -0
  52. package/dist/config/index.js +8 -0
  53. package/dist/config/index.js.map +1 -0
  54. package/dist/controls/index.d.ts +3 -4
  55. package/dist/controls/index.js +4 -3
  56. package/dist/dragdrop/index.d.ts +3 -5
  57. package/dist/index.d.ts +266 -413
  58. package/dist/index.js +1775 -2251
  59. package/dist/index.js.map +1 -1
  60. package/dist/layers/index.d.ts +4 -6
  61. package/dist/layers/index.js +2 -2
  62. package/dist/loupe/index.d.ts +69 -20
  63. package/dist/loupe/index.js +2 -2
  64. package/dist/passthrough/weasel-ui.d.ts +175 -309
  65. package/dist/passthrough/weasel-ui.js +1 -1
  66. package/dist/primitives/index.d.ts +55 -6
  67. package/dist/primitives/index.js +6 -4
  68. package/dist/state/index.d.ts +13 -8
  69. package/dist/state/index.js +18 -13
  70. package/dist/state/index.js.map +1 -1
  71. package/dist/styles.css +223 -76
  72. package/dist/surface/index.d.ts +44 -7
  73. package/dist/surface/index.js +2 -1
  74. package/dist/ui/layers/index.js +1 -1
  75. package/dist/undo/index.d.ts +3 -5
  76. package/package.json +15 -8
  77. package/src/annotations/AnnotationOverlay.tsx +56 -5
  78. package/src/annotations/Annotations.less +4 -0
  79. package/src/annotations/Annotations.overlay.test.tsx +105 -6
  80. package/src/annotations/drawOne.test.ts +1 -1
  81. package/src/annotations/drawOne.ts +2 -2
  82. package/src/annotations/paint.test.ts +2 -2
  83. package/src/annotations/paint.ts +1 -1
  84. package/src/annotations/preload.ts +6 -0
  85. package/src/annotations/store.test.ts +18 -0
  86. package/src/annotations/store.ts +5 -4
  87. package/src/annotations/svgNodes.test.ts +2 -2
  88. package/src/annotations/svgNodes.ts +1 -0
  89. package/src/annotations/toolMap.test.ts +9 -5
  90. package/src/annotations/toolMap.ts +6 -3
  91. package/src/annotations/types.ts +6 -3
  92. package/src/canvas/CameraWheelContext.ts +12 -0
  93. package/src/canvas/CanvasStack.stories.tsx +1 -1
  94. package/src/canvas/CanvasStack.test.tsx +25 -0
  95. package/src/canvas/CanvasStack.tsx +31 -4
  96. package/src/canvas/Stage.less +18 -0
  97. package/src/canvas/Stage.test.tsx +186 -0
  98. package/src/canvas/Stage.tsx +134 -0
  99. package/src/canvas/camera.test.ts +17 -2
  100. package/src/canvas/camera.ts +9 -9
  101. package/src/canvas/index.ts +4 -0
  102. package/src/canvas/usePanZoom.test.ts +28 -0
  103. package/src/canvas/usePanZoom.ts +21 -9
  104. package/src/chrome/ChromeRegions.stories.tsx +1 -4
  105. package/src/chrome/LabChrome.tsx +130 -0
  106. package/src/chrome/builtins.test.ts +1 -0
  107. package/src/chrome/builtins.tsx +21 -31
  108. package/src/chrome/index.ts +16 -0
  109. package/src/chrome/labRegions.test.tsx +208 -0
  110. package/src/chrome/labTypes.ts +50 -0
  111. package/src/chrome/merge.ts +7 -9
  112. package/src/chrome/regions/PaletteRegion.test.tsx +6 -4
  113. package/src/chrome/regions/PaletteRegion.tsx +16 -9
  114. package/src/chrome/regions/SidebarRegion.stories.tsx +44 -0
  115. package/src/chrome/regions/SidebarRegion.tsx +25 -13
  116. package/src/chrome/regions/StatusRegion.tsx +15 -8
  117. package/src/chrome/regions/ToolbarRegion.tsx +34 -16
  118. package/src/chrome/types.ts +50 -20
  119. package/src/config/auto.test.ts +12 -0
  120. package/src/config/auto.ts +15 -0
  121. package/src/config/autoConfig.test.ts +107 -0
  122. package/src/config/autoConfig.ts +153 -0
  123. package/src/config/builder.test.ts +42 -0
  124. package/src/config/builder.ts +68 -17
  125. package/src/config/declarationEmit.fixture.ts +11 -0
  126. package/src/config/declarationEmit.test.ts +51 -0
  127. package/src/config/entry.test.ts +46 -0
  128. package/src/config/index.ts +16 -1
  129. package/src/config/nodeClasses.test.ts +18 -0
  130. package/src/config/path.ts +7 -2
  131. package/src/config/resolve.test.ts +25 -0
  132. package/src/config/resolve.ts +17 -1
  133. package/src/config/types.ts +34 -2
  134. package/src/config/useResolvedConfig.ts +26 -0
  135. package/src/controls/AutoControls.stories.tsx +88 -0
  136. package/src/controls/ControlPanel.stories.tsx +42 -1
  137. package/src/controls/ControlPanel.test.tsx +530 -4
  138. package/src/controls/ControlPanel.tsx +562 -82
  139. package/src/fake-indexeddb-auto.d.ts +5 -0
  140. package/src/index.test.ts +7 -0
  141. package/src/index.ts +66 -5
  142. package/src/instrument/serializers.test.ts +22 -0
  143. package/src/instrument/serializers.ts +40 -1
  144. package/src/instrument/types.ts +25 -1
  145. package/src/lab/Lab.chrome.test.tsx +16 -0
  146. package/src/lab/Lab.less +4 -13
  147. package/src/lab/Lab.persist.test.tsx +147 -0
  148. package/src/lab/Lab.stories.tsx +1 -3
  149. package/src/lab/Lab.surface.test.tsx +71 -3
  150. package/src/lab/Lab.test.tsx +168 -16
  151. package/src/lab/Lab.tsx +434 -129
  152. package/src/lab/LabContext.ts +8 -0
  153. package/src/lab/LabFit.stories.less +18 -0
  154. package/src/lab/LabFit.stories.tsx +219 -0
  155. package/src/lab/LabFullChrome.stories.tsx +1 -4
  156. package/src/lab/LabHeader.test.tsx +40 -9
  157. package/src/lab/LabHeader.tsx +7 -14
  158. package/src/lab/LabPalette.tsx +13 -26
  159. package/src/lab/LabRoot.test.tsx +56 -0
  160. package/src/lab/LabRoot.tsx +47 -0
  161. package/src/lab/LabShell.less +73 -15
  162. package/src/lab/LabShell.stories.tsx +50 -1
  163. package/src/lab/LabShell.tsx +18 -27
  164. package/src/lab/LabSwitcher.less +18 -11
  165. package/src/lab/LabSwitcher.test.tsx +14 -9
  166. package/src/lab/LabSwitcher.tsx +8 -4
  167. package/src/lab/Workspace.less +1 -1
  168. package/src/lab/Workspace.stories.tsx +1 -1
  169. package/src/lab/Workspace.surface.test.tsx +1 -0
  170. package/src/lab/fitCheck.test.ts +57 -0
  171. package/src/lab/fitCheck.ts +125 -0
  172. package/src/lab/index.ts +2 -0
  173. package/src/layers/LayerList.stories.tsx +1 -1
  174. package/src/loupe/AGENTS.md +17 -5
  175. package/src/loupe/Loupe.less +1 -1
  176. package/src/loupe/LoupeGestures.tsx +67 -0
  177. package/src/loupe/TrialLoupe.tsx +43 -28
  178. package/src/loupe/canvasLens.ts +1 -1
  179. package/src/loupe/index.ts +4 -0
  180. package/src/loupe/loupeActions.ts +98 -0
  181. package/src/loupe/types.ts +1 -1
  182. package/src/loupe/useLoupe.test.tsx +60 -3
  183. package/src/loupe/useLoupe.ts +29 -49
  184. package/src/passthrough/weasel-ui.ts +9 -0
  185. package/src/primitives/FloatingPanel.stories.tsx +14 -2
  186. package/src/primitives/FloatingPanel.test.tsx +47 -16
  187. package/src/primitives/FloatingPanel.tsx +11 -25
  188. package/src/primitives/FpsMeter.stories.tsx +1 -1
  189. package/src/primitives/JobProgress.stories.tsx +1 -1
  190. package/src/primitives/Legend.stories.tsx +1 -1
  191. package/src/primitives/ScaleIndicator.stories.tsx +1 -1
  192. package/src/primitives/Sidebar.less +7 -0
  193. package/src/primitives/Sidebar.stories.tsx +1 -1
  194. package/src/primitives/Split.less +14 -0
  195. package/src/primitives/Split.test.tsx +133 -0
  196. package/src/primitives/Split.tsx +175 -0
  197. package/src/primitives/StatusBar.stories.tsx +1 -1
  198. package/src/primitives/Toolbar.stories.tsx +1 -1
  199. package/src/primitives/ZoomControl.tsx +5 -2
  200. package/src/primitives/index.ts +2 -0
  201. package/src/specimen/Specimen.less +95 -0
  202. package/src/specimen/Specimen.stories.tsx +13 -0
  203. package/src/specimen/Specimen.test.tsx +13 -0
  204. package/src/specimen/Specimen.tsx +888 -0
  205. package/src/state/Persistence.stories.tsx +75 -0
  206. package/src/state/Persistence.tsx +33 -0
  207. package/src/state/SingletonExperiment.test.tsx +47 -53
  208. package/src/state/SingletonExperiment.tsx +24 -13
  209. package/src/state/adapterContract.ts +116 -0
  210. package/src/state/adapters.test.ts +113 -61
  211. package/src/state/adapters.ts +328 -69
  212. package/src/state/document.test.ts +71 -96
  213. package/src/state/document.ts +66 -52
  214. package/src/state/helpers.test.ts +1 -1
  215. package/src/state/index.ts +8 -0
  216. package/src/state/labRecords.test.ts +105 -0
  217. package/src/state/labRecords.ts +160 -0
  218. package/src/state/openLabStore.test.ts +658 -0
  219. package/src/state/openLabStore.ts +403 -0
  220. package/src/state/records.test.ts +234 -0
  221. package/src/state/records.ts +219 -0
  222. package/src/state/store.test.ts +169 -635
  223. package/src/state/store.ts +146 -163
  224. package/src/state/toolSlot.test.ts +1 -1
  225. package/src/state/types.ts +65 -17
  226. package/src/state/useOpenOnce.ts +68 -0
  227. package/src/state/usePersistedState.test.tsx +125 -0
  228. package/src/state/usePersistedState.ts +66 -0
  229. package/src/state/useTrialState.test.tsx +87 -3
  230. package/src/state/useTrialState.ts +9 -1
  231. package/src/state/view.test.ts +49 -15
  232. package/src/state/view.ts +18 -1
  233. package/src/styles.less +3 -0
  234. package/src/surface/AGENTS.md +39 -7
  235. package/src/surface/SurfaceContext.ts +26 -3
  236. package/src/surface/index.ts +2 -0
  237. package/src/surface/useSurfaceTile.test.tsx +1 -0
  238. package/src/surface/useSurfaceTile.ts +6 -5
  239. package/src/surface/useTiledSurface.test.tsx +231 -1
  240. package/src/surface/useTiledSurface.ts +76 -15
  241. package/src/theme/Interstellar.stories.tsx +9 -9
  242. package/src/theme/interstellar.test.ts +17 -6
  243. package/src/theme/interstellar.theme.json +180 -0
  244. package/src/theme/interstellar.ts +8 -5
  245. package/src/tools/labTool.ts +11 -0
  246. package/src/trial/Trial.annotations.persist.test.tsx +100 -58
  247. package/src/trial/Trial.annotations.test.tsx +59 -7
  248. package/src/trial/Trial.canvas.test.tsx +32 -0
  249. package/src/trial/Trial.config.test.tsx +75 -2
  250. package/src/trial/Trial.job.test.tsx +3 -3
  251. package/src/trial/Trial.less +5 -26
  252. package/src/trial/Trial.stories.tsx +5 -3
  253. package/src/trial/Trial.test.tsx +31 -4
  254. package/src/trial/Trial.trialId.test.tsx +23 -1
  255. package/src/trial/Trial.tsx +139 -52
  256. package/src/trial/TrialBody.tsx +17 -141
  257. package/src/trial/TrialChrome.tsx +24 -7
  258. package/src/trial/trialOps.test.ts +101 -1
  259. package/src/trial/trialOps.ts +67 -7
  260. package/dist/_dts/types-BP2OCcpg.d.ts +0 -155
  261. package/dist/_dts/types-x92Kfeme.d.ts +0 -62
  262. package/dist/_dts/useTrialState-D6Vb3T-g.d.ts +0 -99
  263. package/dist/chunk-2P6PP5N4.js +0 -553
  264. package/dist/chunk-2P6PP5N4.js.map +0 -1
  265. package/dist/chunk-64ZCN3DA.js.map +0 -1
  266. package/dist/chunk-CTRKTLYZ.js.map +0 -1
  267. package/dist/chunk-E44SU6XS.js +0 -50
  268. package/dist/chunk-E44SU6XS.js.map +0 -1
  269. package/dist/chunk-FQMJUVHJ.js.map +0 -1
  270. package/dist/chunk-I6JCVE24.js.map +0 -1
  271. package/dist/chunk-MOM3GOVY.js.map +0 -1
  272. package/dist/chunk-SMHP6XZ4.js.map +0 -1
  273. package/dist/chunk-TJ7QY3OC.js.map +0 -1
  274. package/dist/chunk-U3IYHIAE.js +0 -343
  275. package/dist/chunk-U3IYHIAE.js.map +0 -1
  276. package/dist/chunk-W3ECWC2K.js +0 -7335
  277. package/dist/chunk-W3ECWC2K.js.map +0 -1
  278. package/src/theme/interstellar.tokens.json +0 -61
@@ -1,8 +1,12 @@
1
- import { Toolbar, ZoomControl, ScaleIndicator, FpsMeter, useRovingTabIndex, StatusBar } from './chunk-SMHP6XZ4.js';
2
- import { ControlPanel } from './chunk-U3IYHIAE.js';
3
- import { p, u, c, n, f, r2, h, b, g3, u2, A, j, U, M, x, N, g, _, v, P, y, n6, o3 } from './chunk-W3ECWC2K.js';
4
- import { createContext, useContext, useState, useId, useRef, useSyncExternalStore, useCallback } from 'react';
1
+ import { Toolbar, ZoomControl, ScaleIndicator, FpsMeter, StatusBar, useRovingTabIndex } from './chunk-UN4U4P63.js';
2
+ import { usePersistedState } from './chunk-RWNDDKOH.js';
3
+ import { ControlPanel } from './chunk-EH7UEQV7.js';
4
+ import { useLabContext } from './chunk-Z76KEZAX.js';
5
+ import { LabStoreContext } from './chunk-2YILQ7Y5.js';
6
+ import { b, g3, u2, A, j, G, M, x, N, l7, _, v, P, y, n7, o4 } from './chunk-T3EC2DXD.js';
7
+ import { createContext, useContext, useState, useId, useMemo, useRef, useSyncExternalStore, useCallback } from 'react';
5
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+ import { useStore } from 'zustand/react';
6
10
 
7
11
  var AnnotationsContext = createContext(null);
8
12
  function useMarkVersion(api) {
@@ -121,18 +125,18 @@ function ExportMenu() {
121
125
  ] }),
122
126
  /* @__PURE__ */ jsxs("div", { className: "lk-export__row", children: [
123
127
  /* @__PURE__ */ jsx("span", { children: "Format" }),
124
- /* @__PURE__ */ jsx("span", { className: "lk-export__choices", role: "radiogroup", "aria-label": "Format", children: FORMATS.map((f2) => /* @__PURE__ */ jsxs("label", { children: [
128
+ /* @__PURE__ */ jsx("span", { className: "lk-export__choices", role: "radiogroup", "aria-label": "Format", children: FORMATS.map((f) => /* @__PURE__ */ jsxs("label", { children: [
125
129
  /* @__PURE__ */ jsx(
126
130
  "input",
127
131
  {
128
132
  type: "radio",
129
133
  name: "lk-export-format",
130
- checked: format === f2.id,
131
- onChange: () => setFormat(f2.id)
134
+ checked: format === f.id,
135
+ onChange: () => setFormat(f.id)
132
136
  }
133
137
  ),
134
- f2.label
135
- ] }, f2.id)) })
138
+ f.label
139
+ ] }, f.id)) })
136
140
  ] }),
137
141
  /* @__PURE__ */ jsxs("div", { className: "lk-export__row", children: [
138
142
  /* @__PURE__ */ jsx("span", { children: "Scale" }),
@@ -215,32 +219,6 @@ function MarkList({ meaning, config }) {
215
219
  ] }, a.id);
216
220
  }) });
217
221
  }
218
-
219
- // src/annotations/toolMap.ts
220
- var TOOLS = {
221
- select: { weaselTool: "select" },
222
- stroke: { weaselTool: "pencil", kind: "stroke" },
223
- line: { weaselTool: "line", kind: "line" },
224
- arrow: { weaselTool: "line", kind: "arrow" },
225
- rect: { weaselTool: "rect", kind: "rect" },
226
- ellipse: { weaselTool: "ellipse", kind: "ellipse" },
227
- text: { weaselTool: "text", kind: "text" }
228
- };
229
- var ANNOTATION_TOOLS = [
230
- { id: "select", label: "Select", icon: p, group: "annotate" },
231
- { id: "stroke", label: "Freehand", icon: u, group: "annotate" },
232
- { id: "line", label: "Line", icon: c, group: "annotate" },
233
- { id: "arrow", label: "Arrow", icon: n, group: "annotate" },
234
- { id: "rect", label: "Rectangle", icon: f, group: "annotate" },
235
- { id: "ellipse", label: "Ellipse", icon: r2, group: "annotate" },
236
- { id: "text", label: "Text", icon: h, group: "annotate" }
237
- ];
238
- function annotationToolInfo(id) {
239
- return id === null ? void 0 : TOOLS[id];
240
- }
241
- var ANNOTATION_WEASEL_TOOLS = [
242
- ...new Set(Object.values(TOOLS).map((t) => t.weaselTool))
243
- ];
244
222
  var ZOOM_STEP = 1.25;
245
223
  function groupFolds(collapsedSections, id) {
246
224
  const prefix = `${id}/`;
@@ -279,11 +257,7 @@ function builtinContributions(instrument, ctx, controls) {
279
257
  }
280
258
  });
281
259
  }
282
- const tools = [
283
- ...instrument.annotations ? ANNOTATION_TOOLS : [],
284
- ...instrument.tools?.tools ?? []
285
- ];
286
- for (const t of tools) {
260
+ for (const t of instrument.tools?.tools ?? []) {
287
261
  out.push({
288
262
  id: t.id,
289
263
  region: "palette",
@@ -297,14 +271,14 @@ function builtinContributions(instrument, ctx, controls) {
297
271
  region: "toolbar",
298
272
  group: "view",
299
273
  item: {
300
- icon: U,
274
+ icon: G,
301
275
  label: "Loupe",
302
276
  pressed: ctx.loupeOn,
303
277
  onActivate: ctx.toggleLoupe
304
278
  }
305
279
  });
306
280
  }
307
- if (instrument.canvas != null && zoom !== null) {
281
+ if ((instrument.canvas != null || instrument.stage != null) && zoom !== null) {
308
282
  out.push({
309
283
  id: "zoom-out",
310
284
  region: "viewport",
@@ -335,21 +309,23 @@ function builtinContributions(instrument, ctx, controls) {
335
309
  id: "zoom-control",
336
310
  region: "viewport",
337
311
  group: "zoom",
338
- render: (c2) => /* @__PURE__ */ jsx(ZoomControl, { zoom: c2.zoom ?? 1, onZoomChange: c2.setZoom })
312
+ render: (c) => /* @__PURE__ */ jsx(ZoomControl, { zoom: c.zoom ?? 1, onZoomChange: c.setZoom })
339
313
  });
340
314
  out.push({
341
315
  id: "scale",
342
316
  region: "status",
343
317
  group: "view",
344
- render: () => /* @__PURE__ */ jsx(ScaleIndicator, {})
345
- });
346
- out.push({
347
- id: "fps",
348
- region: "status",
349
- group: "view",
350
- end: true,
351
- render: () => /* @__PURE__ */ jsx(FpsMeter, {})
318
+ render: (c) => /* @__PURE__ */ jsx(ScaleIndicator, { zoom: c.zoom ?? 1 })
352
319
  });
320
+ if (instrument.canvas != null) {
321
+ out.push({
322
+ id: "fps",
323
+ region: "status",
324
+ group: "view",
325
+ end: true,
326
+ render: () => /* @__PURE__ */ jsx(FpsMeter, {})
327
+ });
328
+ }
353
329
  }
354
330
  if (instrument.annotations != null) {
355
331
  out.push({
@@ -379,6 +355,7 @@ function builtinContributions(instrument, ctx, controls) {
379
355
  {
380
356
  schema: ctx.configSchema,
381
357
  config: ctx.config,
358
+ auto: ctx.auto,
382
359
  setConfig: (key, value) => ctx.setConfig(String(key), value),
383
360
  renderers: controls,
384
361
  collapsed: groupFolds(ctx.collapsedSections, "settings"),
@@ -394,17 +371,13 @@ function builtinContributions(instrument, ctx, controls) {
394
371
  region: "toolbar",
395
372
  group: "trial",
396
373
  end: true,
397
- render: (c2) => /* @__PURE__ */ jsx(
398
- g,
374
+ render: (c) => /* @__PURE__ */ jsx(
375
+ l7,
399
376
  {
400
- className: "lk-toolbar__load-select",
401
377
  "aria-label": "Load snapshot",
402
- placeholder: "Load\u2026",
403
- selectedKey: null,
404
- options: c2.savedSnapshots.map((sn) => ({ value: sn.id, label: sn.name })),
405
- onSelectionChange: (id) => {
406
- if (id != null) c2.loadSnapshot(String(id));
407
- }
378
+ label: "Load\u2026",
379
+ items: c.savedSnapshots.map((sn) => ({ value: sn.id, label: sn.name })),
380
+ onAction: (id) => c.loadSnapshot(id)
408
381
  }
409
382
  )
410
383
  });
@@ -447,6 +420,12 @@ function builtinContributions(instrument, ctx, controls) {
447
420
  return out;
448
421
  }
449
422
 
423
+ // src/tools/labTool.ts
424
+ function resolveLabTool(slot, instruments) {
425
+ if (slot !== null) return slot;
426
+ return instruments.some((i) => i.annotations != null) ? "pointer" : null;
427
+ }
428
+
450
429
  // src/chrome/merge.ts
451
430
  function mergeContributions(...bundles) {
452
431
  const out = [];
@@ -465,7 +444,7 @@ function mergeContributions(...bundles) {
465
444
  return out;
466
445
  }
467
446
  function suppressContributions(bundle, ids) {
468
- const present = new Set(bundle.map((c2) => c2.id));
447
+ const present = new Set(bundle.map((c) => c.id));
469
448
  for (const id of ids) {
470
449
  if (!present.has(id)) {
471
450
  throw new Error(
@@ -474,39 +453,7 @@ function suppressContributions(bundle, ids) {
474
453
  }
475
454
  }
476
455
  const drop = new Set(ids);
477
- return bundle.filter((c2) => !drop.has(c2.id));
478
- }
479
- function PaletteRegion({ contributions, ctx }) {
480
- const { ref, onKeyDown } = useRovingTabIndex("vertical");
481
- if (contributions.length === 0) return null;
482
- return /* @__PURE__ */ jsx(
483
- "div",
484
- {
485
- ref,
486
- className: "lk-palette-region",
487
- role: "toolbar",
488
- "aria-label": "Tools",
489
- "aria-orientation": "vertical",
490
- onKeyDown,
491
- children: /* @__PURE__ */ jsx(n6, { orientation: "vertical", children: contributions.map((c2) => {
492
- if (c2.render) return /* @__PURE__ */ jsx("span", { children: c2.render(ctx) }, c2.id);
493
- if (c2.region !== "palette" || !c2.item) return null;
494
- const { icon: Icon, label, shortcut, disabled } = c2.item;
495
- return /* @__PURE__ */ jsx(
496
- o3,
497
- {
498
- icon: /* @__PURE__ */ jsx(Icon, { size: 16 }),
499
- label,
500
- shortcut,
501
- active: ctx.activeToolId === c2.id,
502
- disabled,
503
- onClick: () => ctx.setActiveTool(c2.id)
504
- },
505
- c2.id
506
- );
507
- }) })
508
- }
509
- );
456
+ return bundle.filter((c) => !drop.has(c.id));
510
457
  }
511
458
  function Section({
512
459
  title,
@@ -542,83 +489,75 @@ function Section({
542
489
  collapsed ? null : /* @__PURE__ */ jsx("div", { className: "lk-sidebar-section__body", children })
543
490
  ] });
544
491
  }
545
- function SidebarRegion({ contributions, ctx }) {
492
+ function SidebarRegion({
493
+ contributions,
494
+ ctx,
495
+ region = "sidebar"
496
+ }) {
546
497
  if (contributions.length === 0) return null;
547
- return /* @__PURE__ */ jsx(Fragment, { children: contributions.map((c2) => {
548
- if (c2.render) return /* @__PURE__ */ jsx("div", { children: c2.render(ctx) }, c2.id);
549
- if (c2.region !== "sidebar" || !c2.item) return null;
550
- if (ctx.undockedPanels.includes(c2.id)) return null;
551
- const item = c2.item;
498
+ return /* @__PURE__ */ jsx(Fragment, { children: contributions.map((c) => {
499
+ if (c.render) return /* @__PURE__ */ jsx("div", { children: c.render(ctx) }, c.id);
500
+ if (c.region !== region || !c.item) return null;
501
+ if (ctx.undockedPanels?.includes(c.id)) return null;
502
+ const item = c.item;
552
503
  return /* @__PURE__ */ jsx(
553
504
  Section,
554
505
  {
555
506
  title: item.title,
556
- collapsed: ctx.collapsedSections[c2.id] ?? item.defaultCollapsed ?? false,
557
- onCollapsedChange: (next) => ctx.setSectionCollapsed(c2.id, next),
558
- onUndock: item.undockable === false ? void 0 : () => ctx.undockPanel(c2.id, item.undockAs ?? "tile"),
507
+ collapsed: ctx.collapsedSections[c.id] ?? item.defaultCollapsed ?? false,
508
+ onCollapsedChange: (next) => ctx.setSectionCollapsed(c.id, next),
509
+ onUndock: ctx.undockPanel && item.undockable !== false ? () => ctx.undockPanel?.(c.id, item.undockAs ?? "tile") : void 0,
559
510
  children: item.body
560
511
  },
561
- c2.id
512
+ c.id
562
513
  );
563
514
  }) });
564
515
  }
565
- function StatusRegion({ contributions, ctx }) {
516
+ function StatusRegion({
517
+ contributions,
518
+ ctx,
519
+ region = "status"
520
+ }) {
566
521
  if (contributions.length === 0) return null;
567
- return /* @__PURE__ */ jsx(StatusBar, { children: contributions.map((c2) => {
568
- if (c2.render)
569
- return /* @__PURE__ */ jsx(StatusBar.Section, { end: c2.end, children: c2.render(ctx) }, c2.id);
570
- if (c2.region !== "status" || !c2.item) return null;
571
- return /* @__PURE__ */ jsx(StatusBar.Section, { end: c2.end, children: /* @__PURE__ */ jsx("span", { title: c2.item.title, children: c2.item.text }) }, c2.id);
522
+ return /* @__PURE__ */ jsx(StatusBar, { children: contributions.map((c) => {
523
+ if (c.render)
524
+ return /* @__PURE__ */ jsx(StatusBar.Section, { end: c.end, children: c.render(ctx) }, c.id);
525
+ if (c.region !== region || !c.item) return null;
526
+ const item = c.item;
527
+ return /* @__PURE__ */ jsx(StatusBar.Section, { end: c.end, children: /* @__PURE__ */ jsx("span", { title: item.title, children: item.text }) }, c.id);
572
528
  }) });
573
529
  }
574
- function renderEntry(c2, ctx) {
575
- if (c2.render) return /* @__PURE__ */ jsx("span", { children: c2.render(ctx) }, c2.id);
576
- if (c2.region !== "titlebar" || !c2.item) return null;
577
- const { icon: Icon, label, shortcut, disabled, danger, onActivate } = c2.item;
578
- return /* @__PURE__ */ jsx(
579
- "button",
580
- {
581
- type: "button",
582
- className: `lk-titlebar-button${danger ? " lk-titlebar-button--danger" : ""}`,
583
- disabled,
584
- "aria-label": label,
585
- title: shortcut ? `${label} (${shortcut})` : label,
586
- onClick: () => onActivate(ctx),
587
- onPointerDown: (e) => e.stopPropagation(),
588
- onMouseDown: (e) => e.stopPropagation(),
589
- children: /* @__PURE__ */ jsx(Icon, { size: 14 })
590
- },
591
- c2.id
592
- );
593
- }
594
- function TitleBarRegion({ contributions, ctx, placement = "actions" }) {
595
- const wanted = placement === "actions";
596
- const mine = contributions.filter((c2) => (c2.end ?? false) === wanted);
597
- if (mine.length === 0) return null;
598
- return /* @__PURE__ */ jsx("span", { className: wanted ? "lk-trial__titlebar-actions" : "lk-trial__titlebar-lead", children: mine.map((c2) => renderEntry(c2, ctx)) });
599
- }
600
530
  function groupsOf(contributions) {
601
531
  const groups = [];
602
532
  const byKey = /* @__PURE__ */ new Map();
603
- for (const c2 of contributions) {
604
- if (c2.group == null) {
605
- groups.push({ key: c2.id, end: c2.end ?? false, entries: [c2] });
533
+ for (const c of contributions) {
534
+ if (c.group == null) {
535
+ groups.push({ key: c.id, end: c.end ?? false, entries: [c] });
606
536
  continue;
607
537
  }
608
- let g3 = byKey.get(c2.group);
609
- if (!g3) {
610
- g3 = { key: c2.group, end: c2.end ?? false, entries: [] };
611
- byKey.set(c2.group, g3);
612
- groups.push(g3);
538
+ let g2 = byKey.get(c.group);
539
+ if (!g2) {
540
+ g2 = { key: c.group, end: c.end ?? false, entries: [] };
541
+ byKey.set(c.group, g2);
542
+ groups.push(g2);
613
543
  }
614
- g3.entries.push(c2);
544
+ g2.entries.push(c);
615
545
  }
616
546
  return groups;
617
547
  }
618
- function renderEntry2(c2, ctx) {
619
- if (c2.render) return /* @__PURE__ */ jsx("span", { children: c2.render(ctx) }, c2.id);
620
- if (c2.region !== "toolbar" || !c2.item) return null;
621
- const { icon: Icon, label, shortcut, disabled, danger, showLabel, pressed, onActivate } = c2.item;
548
+ function renderEntry(c, ctx, region) {
549
+ if (c.render) return /* @__PURE__ */ jsx("span", { children: c.render(ctx) }, c.id);
550
+ if (c.region !== region || !c.item) return null;
551
+ const {
552
+ icon: Icon,
553
+ label,
554
+ shortcut,
555
+ disabled,
556
+ danger,
557
+ showLabel,
558
+ pressed,
559
+ onActivate
560
+ } = c.item;
622
561
  return /* @__PURE__ */ jsxs(
623
562
  Toolbar.Button,
624
563
  {
@@ -634,13 +573,164 @@ function renderEntry2(c2, ctx) {
634
573
  showLabel ? /* @__PURE__ */ jsx("span", { children: label }) : null
635
574
  ]
636
575
  },
637
- c2.id
576
+ c.id
638
577
  );
639
578
  }
640
- function ToolbarRegion({ contributions, ctx }) {
579
+ function ToolbarRegion({
580
+ contributions,
581
+ ctx,
582
+ region = "toolbar",
583
+ label = "Trial actions"
584
+ }) {
641
585
  if (contributions.length === 0) return null;
642
586
  const groups = groupsOf(contributions);
643
- return /* @__PURE__ */ jsx(Toolbar, { "aria-label": "Trial actions", children: groups.map((g3) => /* @__PURE__ */ jsx(Toolbar.Group, { end: g3.end, "aria-label": g3.key, children: g3.entries.map((c2) => renderEntry2(c2, ctx)) }, g3.key)) });
587
+ return /* @__PURE__ */ jsx(Toolbar, { "aria-label": label, children: groups.map((g2) => /* @__PURE__ */ jsx(Toolbar.Group, { end: g2.end, "aria-label": g2.key, children: g2.entries.map((c) => renderEntry(c, ctx, region)) }, g2.key)) });
588
+ }
589
+ function useLabChromeContext() {
590
+ const lab = useLabContext();
591
+ const storeCtx = useContext(LabStoreContext);
592
+ if (!storeCtx) throw new Error("[labkit] lab chrome requires <LabStoreProvider>");
593
+ const slot = useStore(storeCtx.store, (s) => s.activeToolId);
594
+ const storeInstruments = useStore(storeCtx.store, (s) => s.instruments);
595
+ const activeToolId = resolveLabTool(slot, storeInstruments ?? lab.instruments);
596
+ const setLabTool = useStore(storeCtx.store, (s) => s.setLabTool);
597
+ return useMemo(
598
+ () => ({ ...lab, activeToolId, setActiveTool: setLabTool }),
599
+ [lab, activeToolId, setLabTool]
600
+ );
601
+ }
602
+ function contributionsIn(contributions, region) {
603
+ return contributions.filter((c) => c.region === region);
604
+ }
605
+ function toolContributions(tools) {
606
+ return tools.map((t) => ({
607
+ id: t.id,
608
+ region: "palette",
609
+ ...t.group === void 0 ? {} : { group: t.group },
610
+ item: {
611
+ icon: t.icon,
612
+ label: t.label,
613
+ ...t.shortcut === void 0 ? {} : { shortcut: t.shortcut }
614
+ }
615
+ }));
616
+ }
617
+ function labContributions(tools, chrome) {
618
+ return mergeContributions(toolContributions(tools ?? []), [...chrome ?? []]);
619
+ }
620
+ function LabHeaderRegion({ contributions }) {
621
+ const ctx = useLabChromeContext();
622
+ return /* @__PURE__ */ jsx(
623
+ ToolbarRegion,
624
+ {
625
+ region: "header",
626
+ label: "Lab actions",
627
+ contributions: contributionsIn(contributions, "header"),
628
+ ctx
629
+ }
630
+ );
631
+ }
632
+ function LabSections({ contributions, region }) {
633
+ const lab = useLabChromeContext();
634
+ const [collapsedSections, setFolds] = usePersistedState(
635
+ `lk-lab-${region}-folds`,
636
+ {},
637
+ { scope: "lab" }
638
+ );
639
+ const ctx = useMemo(
640
+ () => ({
641
+ ...lab,
642
+ collapsedSections,
643
+ setSectionCollapsed: (key, collapsed) => setFolds((f) => ({ ...f, [key]: collapsed }))
644
+ }),
645
+ [lab, collapsedSections, setFolds]
646
+ );
647
+ return /* @__PURE__ */ jsx(
648
+ SidebarRegion,
649
+ {
650
+ contributions: contributionsIn(contributions, region),
651
+ ctx,
652
+ region
653
+ }
654
+ );
655
+ }
656
+ function LabSidebarRegion({ contributions }) {
657
+ return /* @__PURE__ */ jsx(LabSections, { contributions, region: "sidebar" });
658
+ }
659
+ function LabAsideRegion({ contributions }) {
660
+ return /* @__PURE__ */ jsx(LabSections, { contributions, region: "aside" });
661
+ }
662
+ function LabFooterRegion({ contributions }) {
663
+ const ctx = useLabChromeContext();
664
+ return /* @__PURE__ */ jsx(
665
+ StatusRegion,
666
+ {
667
+ region: "footer",
668
+ contributions: contributionsIn(contributions, "footer"),
669
+ ctx
670
+ }
671
+ );
672
+ }
673
+ function PaletteRegion({
674
+ contributions,
675
+ ctx,
676
+ region = "palette"
677
+ }) {
678
+ const { ref, onKeyDown } = useRovingTabIndex("vertical");
679
+ if (contributions.length === 0) return null;
680
+ return /* @__PURE__ */ jsx(
681
+ "div",
682
+ {
683
+ ref,
684
+ className: "lk-palette-region",
685
+ role: "toolbar",
686
+ "aria-label": "Tools",
687
+ "aria-orientation": "vertical",
688
+ onKeyDown,
689
+ children: /* @__PURE__ */ jsx(n7, { orientation: "vertical", children: contributions.map((c) => {
690
+ if (c.render) return /* @__PURE__ */ jsx("span", { children: c.render(ctx) }, c.id);
691
+ if (c.region !== region || !c.item) return null;
692
+ const { icon: Icon, label, shortcut, disabled } = c.item;
693
+ return /* @__PURE__ */ jsx(
694
+ o4,
695
+ {
696
+ icon: /* @__PURE__ */ jsx(Icon, { size: 16 }),
697
+ label,
698
+ shortcut,
699
+ active: ctx.activeToolId === c.id,
700
+ disabled,
701
+ onClick: () => ctx.setActiveTool(c.id)
702
+ },
703
+ c.id
704
+ );
705
+ }) })
706
+ }
707
+ );
708
+ }
709
+ function renderEntry2(c, ctx) {
710
+ if (c.render) return /* @__PURE__ */ jsx("span", { children: c.render(ctx) }, c.id);
711
+ if (c.region !== "titlebar" || !c.item) return null;
712
+ const { icon: Icon, label, shortcut, disabled, danger, onActivate } = c.item;
713
+ return /* @__PURE__ */ jsx(
714
+ "button",
715
+ {
716
+ type: "button",
717
+ className: `lk-titlebar-button${danger ? " lk-titlebar-button--danger" : ""}`,
718
+ disabled,
719
+ "aria-label": label,
720
+ title: shortcut ? `${label} (${shortcut})` : label,
721
+ onClick: () => onActivate(ctx),
722
+ onPointerDown: (e) => e.stopPropagation(),
723
+ onMouseDown: (e) => e.stopPropagation(),
724
+ children: /* @__PURE__ */ jsx(Icon, { size: 14 })
725
+ },
726
+ c.id
727
+ );
728
+ }
729
+ function TitleBarRegion({ contributions, ctx, placement = "actions" }) {
730
+ const wanted = placement === "actions";
731
+ const mine = contributions.filter((c) => (c.end ?? false) === wanted);
732
+ if (mine.length === 0) return null;
733
+ return /* @__PURE__ */ jsx("span", { className: wanted ? "lk-trial__titlebar-actions" : "lk-trial__titlebar-lead", children: mine.map((c) => renderEntry2(c, ctx)) });
644
734
  }
645
735
  function ViewportRegion({ contributions, ctx }) {
646
736
  const { ref, onKeyDown } = useRovingTabIndex();
@@ -653,10 +743,10 @@ function ViewportRegion({ contributions, ctx }) {
653
743
  role: "toolbar",
654
744
  "aria-label": "View",
655
745
  onKeyDown,
656
- children: contributions.map((c2) => {
657
- if (c2.render) return /* @__PURE__ */ jsx("span", { children: c2.render(ctx) }, c2.id);
658
- if (c2.region !== "viewport" || !c2.item) return null;
659
- const { icon: Icon, label, disabled, onActivate } = c2.item;
746
+ children: contributions.map((c) => {
747
+ if (c.render) return /* @__PURE__ */ jsx("span", { children: c.render(ctx) }, c.id);
748
+ if (c.region !== "viewport" || !c.item) return null;
749
+ const { icon: Icon, label, disabled, onActivate } = c.item;
660
750
  return /* @__PURE__ */ jsx(
661
751
  "button",
662
752
  {
@@ -668,13 +758,13 @@ function ViewportRegion({ contributions, ctx }) {
668
758
  onClick: () => onActivate(ctx),
669
759
  children: /* @__PURE__ */ jsx(Icon, { size: 16 })
670
760
  },
671
- c2.id
761
+ c.id
672
762
  );
673
763
  })
674
764
  }
675
765
  );
676
766
  }
677
767
 
678
- export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationsContext, ExportMenu, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, mergeContributions, suppressContributions, useAnnotations, useAnnotationsOptional };
679
- //# sourceMappingURL=chunk-64ZCN3DA.js.map
680
- //# sourceMappingURL=chunk-64ZCN3DA.js.map
768
+ export { AnnotationsContext, ExportMenu, LabAsideRegion, LabFooterRegion, LabHeaderRegion, LabSidebarRegion, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, contributionsIn, labContributions, mergeContributions, resolveLabTool, suppressContributions, toolContributions, useAnnotations, useAnnotationsOptional, useLabChromeContext };
769
+ //# sourceMappingURL=chunk-IHUVQ3TX.js.map
770
+ //# sourceMappingURL=chunk-IHUVQ3TX.js.map