@weasel-js/labkit 1.5.2 → 1.6.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 (217) hide show
  1. package/README.md +3 -7
  2. package/dist/_dts/{CanvasStackContext-CMMo180l.d.ts → CanvasStackContext-Wo6OwIVM.d.ts} +1 -1
  3. package/dist/_dts/FloatingPanel-7j0IcXwz.d.ts +30 -0
  4. package/dist/_dts/LayerList.d-BoELAMsM.d.ts +83 -0
  5. package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
  6. package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +404 -0
  7. package/dist/_dts/{Select.d-ZTiwzYyT.d.ts → Select.d-Cr8-zoup.d.ts} +105 -15
  8. package/dist/_dts/{usePanZoom-SSTZe410.d.ts → Stage-DWBBi8IU.d.ts} +80 -35
  9. package/dist/_dts/{index-DlKolEIZ.d.ts → index-CKyX0ME_.d.ts} +12 -13
  10. package/dist/_dts/{frac-B4hFJMiN.d.ts → types-B7yBTTF9.d.ts} +709 -651
  11. package/dist/_dts/{types-Db-3NNk1.d.ts → types-DTuViBvc.d.ts} +21 -2
  12. package/dist/_dts/{useTrialState-pnAE-UBD.d.ts → useTrialState-CMaV6UD4.d.ts} +2 -3
  13. package/dist/canvas/index.d.ts +41 -8
  14. package/dist/canvas/index.js +5 -3
  15. package/dist/chrome/index.d.ts +6 -6
  16. package/dist/chrome/index.js +9 -7
  17. package/dist/chunk-24W5VEJW.js +18 -0
  18. package/dist/chunk-24W5VEJW.js.map +1 -0
  19. package/dist/chunk-2RVCB2PT.js +3 -0
  20. package/dist/chunk-2RVCB2PT.js.map +1 -0
  21. package/dist/chunk-3RY6WL5T.js +38 -0
  22. package/dist/chunk-3RY6WL5T.js.map +1 -0
  23. package/dist/{chunk-CKUKF72R.js → chunk-4TT3PNPR.js} +68 -55
  24. package/dist/chunk-4TT3PNPR.js.map +1 -0
  25. package/dist/{chunk-KJCUERQF.js → chunk-6FLXL3I7.js} +9 -164
  26. package/dist/chunk-6FLXL3I7.js.map +1 -0
  27. package/dist/chunk-ASOK76ZH.js +431 -0
  28. package/dist/chunk-ASOK76ZH.js.map +1 -0
  29. package/dist/chunk-AWQG7FCC.js +19 -0
  30. package/dist/chunk-AWQG7FCC.js.map +1 -0
  31. package/dist/chunk-CGHF6RZV.js +300 -0
  32. package/dist/chunk-CGHF6RZV.js.map +1 -0
  33. package/dist/chunk-DWMSB4CA.js +228 -0
  34. package/dist/chunk-DWMSB4CA.js.map +1 -0
  35. package/dist/chunk-GHGO52SO.js +92 -0
  36. package/dist/chunk-GHGO52SO.js.map +1 -0
  37. package/dist/{chunk-LRI3MBGR.js → chunk-HKV7LRHY.js} +4 -4
  38. package/dist/{chunk-LRI3MBGR.js.map → chunk-HKV7LRHY.js.map} +1 -1
  39. package/dist/{chunk-EMXAIRUJ.js → chunk-IRTGUQ5O.js} +5 -4
  40. package/dist/chunk-IRTGUQ5O.js.map +1 -0
  41. package/dist/{chunk-H6ZAOWNE.js → chunk-JVBYV6TL.js} +3 -3
  42. package/dist/{chunk-H6ZAOWNE.js.map → chunk-JVBYV6TL.js.map} +1 -1
  43. package/dist/chunk-KHK5FGER.js +145 -0
  44. package/dist/chunk-KHK5FGER.js.map +1 -0
  45. package/dist/chunk-NEXR37YJ.js +144 -0
  46. package/dist/chunk-NEXR37YJ.js.map +1 -0
  47. package/dist/{chunk-A2ACAGW6.js → chunk-O6FFFOHS.js} +32 -7
  48. package/dist/chunk-O6FFFOHS.js.map +1 -0
  49. package/dist/chunk-QGMOA2YE.js +731 -0
  50. package/dist/chunk-QGMOA2YE.js.map +1 -0
  51. package/dist/{chunk-ERFMC6WU.js → chunk-S4NCI32V.js} +19 -10
  52. package/dist/chunk-S4NCI32V.js.map +1 -0
  53. package/dist/{chunk-753Y6HE6.js → chunk-SLAQPUI4.js} +4 -4
  54. package/dist/chunk-SLAQPUI4.js.map +1 -0
  55. package/dist/{chunk-REOBGYMC.js → chunk-TJ77A4A3.js} +3 -5
  56. package/dist/chunk-TJ77A4A3.js.map +1 -0
  57. package/dist/chunk-TYN6MLXX.js +13864 -0
  58. package/dist/chunk-TYN6MLXX.js.map +1 -0
  59. package/dist/{chunk-RS3HRQWU.js → chunk-WPLAANH4.js} +4 -3
  60. package/dist/chunk-WPLAANH4.js.map +1 -0
  61. package/dist/config/index.d.ts +51 -7
  62. package/dist/config/index.js +4 -5
  63. package/dist/controls/index.d.ts +92 -5
  64. package/dist/controls/index.js +5 -4
  65. package/dist/dragdrop/index.d.ts +9 -6
  66. package/dist/dragdrop/index.js +3 -2
  67. package/dist/index.d.ts +108 -154
  68. package/dist/index.js +456 -600
  69. package/dist/index.js.map +1 -1
  70. package/dist/layers/index.d.ts +5 -35
  71. package/dist/layers/index.js +3 -3
  72. package/dist/loupe/index.d.ts +21 -17
  73. package/dist/loupe/index.js +5 -3
  74. package/dist/overview/index.d.ts +56 -0
  75. package/dist/overview/index.js +288 -0
  76. package/dist/overview/index.js.map +1 -0
  77. package/dist/passthrough/weasel-ui.d.ts +434 -231
  78. package/dist/passthrough/weasel-ui.js +2 -1
  79. package/dist/primitives/index.d.ts +19 -54
  80. package/dist/primitives/index.js +6 -4
  81. package/dist/state/index.d.ts +8 -7
  82. package/dist/state/index.js +4 -5
  83. package/dist/state/index.js.map +1 -1
  84. package/dist/styles.css +360 -174
  85. package/dist/undo/index.d.ts +5 -4
  86. package/package.json +13 -13
  87. package/src/annotations/frac.test.ts +7 -0
  88. package/src/annotations/index.ts +1 -0
  89. package/src/annotations/paint.test.ts +21 -0
  90. package/src/annotations/paint.ts +12 -0
  91. package/src/annotations/store.test.ts +57 -0
  92. package/src/annotations/store.ts +25 -6
  93. package/src/annotations/toolMap.test.ts +37 -2
  94. package/src/annotations/toolMap.ts +13 -0
  95. package/src/annotations/types.ts +30 -2
  96. package/src/canvas/AGENTS.md +8 -10
  97. package/src/canvas/CameraInput.test.tsx +136 -0
  98. package/src/canvas/CameraInput.tsx +311 -0
  99. package/src/canvas/CanvasStack.tsx +42 -58
  100. package/src/canvas/LinkedCursor.less +16 -0
  101. package/src/canvas/LinkedCursor.tsx +54 -0
  102. package/src/canvas/Stage.test.tsx +18 -0
  103. package/src/canvas/Stage.tsx +42 -37
  104. package/src/canvas/cameraView.test.ts +60 -0
  105. package/src/canvas/cameraView.ts +61 -0
  106. package/src/canvas/index.ts +11 -2
  107. package/src/chrome/regions/SidebarRegion.less +197 -0
  108. package/src/chrome/regions/SidebarRegion.test.tsx +27 -0
  109. package/src/chrome/regions/SidebarRegion.tsx +7 -2
  110. package/src/chrome/types.ts +5 -2
  111. package/src/config/autoConfig.ts +2 -2
  112. package/src/config/builder.ts +21 -2
  113. package/src/config/entry.test.ts +10 -0
  114. package/src/config/fromConfigField.ts +1 -0
  115. package/src/config/index.ts +5 -0
  116. package/src/config/resolve.ts +11 -1
  117. package/src/config/rules.ts +2 -0
  118. package/src/config/sectionTree.test.ts +152 -0
  119. package/src/config/sectionTree.ts +134 -0
  120. package/src/config/types.ts +21 -0
  121. package/src/controls/ControlPanel.less +4 -0
  122. package/src/controls/ControlPanel.stories.tsx +55 -2
  123. package/src/controls/ControlPanel.test.tsx +40 -3
  124. package/src/controls/ControlPanel.tsx +134 -336
  125. package/src/controls/inDialog.test.tsx +100 -0
  126. package/src/controls/inDialog.tsx +38 -0
  127. package/src/controls/index.ts +1 -0
  128. package/src/index.test.ts +1 -1
  129. package/src/index.ts +18 -29
  130. package/src/instrument/SineWave.smoke.test.tsx +2 -0
  131. package/src/instrument/types.ts +15 -3
  132. package/src/lab/Lab.nebula.test.tsx +40 -0
  133. package/src/lab/Lab.test.tsx +3 -1
  134. package/src/lab/Lab.tsx +42 -19
  135. package/src/lab/LabBoundary.test.tsx +66 -0
  136. package/src/lab/LabBoundary.tsx +56 -0
  137. package/src/lab/LabHeader.tsx +4 -23
  138. package/src/lab/LabRoot.tsx +2 -3
  139. package/src/lab/LabShell.less +0 -1
  140. package/src/lab/LabShell.stories.tsx +15 -0
  141. package/src/lab/LabShell.test.tsx +18 -0
  142. package/src/lab/LabShell.tsx +14 -1
  143. package/src/lab/LabSwitcher.less +1 -1
  144. package/src/lab/LabSwitcher.test.tsx +41 -0
  145. package/src/lab/LabSwitcher.tsx +30 -8
  146. package/src/lab/index.ts +1 -0
  147. package/src/layers/AGENTS.md +18 -74
  148. package/src/layers/index.ts +4 -2
  149. package/src/loupe/AGENTS.md +7 -6
  150. package/src/loupe/LoupeGestures.tsx +14 -9
  151. package/src/loupe/TrialLoupe.tsx +5 -5
  152. package/src/loupe/index.ts +1 -0
  153. package/src/loupe/loupeActions.ts +6 -2
  154. package/src/overview/AGENTS.md +38 -0
  155. package/src/overview/OverviewMarks.test.tsx +100 -0
  156. package/src/overview/OverviewMarks.tsx +93 -0
  157. package/src/overview/TrialOverview.less +53 -0
  158. package/src/overview/TrialOverview.stories.tsx +50 -0
  159. package/src/overview/TrialOverview.test.tsx +116 -0
  160. package/src/overview/TrialOverview.tsx +374 -0
  161. package/src/overview/index.ts +2 -0
  162. package/src/passthrough/weasel-ui.ts +32 -10
  163. package/src/primitives/index.ts +0 -2
  164. package/src/specimen/Specimen.tsx +59 -56
  165. package/src/state/labRecords.test.ts +4 -1
  166. package/src/state/store.test.ts +4 -4
  167. package/src/state/types.ts +2 -1
  168. package/src/state/useTrialState.test.tsx +1 -1
  169. package/src/styles.less +6 -2
  170. package/src/theme/Interstellar.stories.tsx +8 -13
  171. package/src/theme/base.less +3 -20
  172. package/src/theme/interstellar.test.ts +6 -3
  173. package/src/theme/interstellar.theme.json +0 -56
  174. package/src/theme/interstellar.ts +2 -2
  175. package/src/tools/labTool.ts +6 -2
  176. package/src/trial/Trial.annotations.test.tsx +16 -0
  177. package/src/trial/Trial.canvas.test.tsx +1 -1
  178. package/src/trial/Trial.loupe.test.tsx +73 -1
  179. package/src/trial/Trial.stories.tsx +2 -0
  180. package/src/trial/Trial.tsx +47 -9
  181. package/src/trial/trialOps.test.ts +4 -4
  182. package/dist/_dts/index-8LiKe3A-.d.ts +0 -410
  183. package/dist/chunk-2AYGEN57.js +0 -32
  184. package/dist/chunk-2AYGEN57.js.map +0 -1
  185. package/dist/chunk-6BUQ77ZV.js +0 -18
  186. package/dist/chunk-6BUQ77ZV.js.map +0 -1
  187. package/dist/chunk-753Y6HE6.js.map +0 -1
  188. package/dist/chunk-A2ACAGW6.js.map +0 -1
  189. package/dist/chunk-CKUKF72R.js.map +0 -1
  190. package/dist/chunk-D35PFTS7.js +0 -170
  191. package/dist/chunk-D35PFTS7.js.map +0 -1
  192. package/dist/chunk-EMXAIRUJ.js.map +0 -1
  193. package/dist/chunk-ERFMC6WU.js.map +0 -1
  194. package/dist/chunk-FKLT3ITC.js +0 -590
  195. package/dist/chunk-FKLT3ITC.js.map +0 -1
  196. package/dist/chunk-KJCUERQF.js.map +0 -1
  197. package/dist/chunk-LASCBWW7.js +0 -13456
  198. package/dist/chunk-LASCBWW7.js.map +0 -1
  199. package/dist/chunk-REOBGYMC.js.map +0 -1
  200. package/dist/chunk-RS3HRQWU.js.map +0 -1
  201. package/dist/chunk-TT5C5S6R.js +0 -368
  202. package/dist/chunk-TT5C5S6R.js.map +0 -1
  203. package/dist/ui/layers/index.d.ts +0 -66
  204. package/dist/ui/layers/index.js +0 -3
  205. package/dist/ui/layers/index.js.map +0 -1
  206. package/src/canvas/usePanZoom.test.ts +0 -244
  207. package/src/canvas/usePanZoom.ts +0 -147
  208. package/src/lab/useSystemMode.ts +0 -30
  209. package/src/layers/LayerList.less +0 -93
  210. package/src/layers/LayerList.stories.tsx +0 -66
  211. package/src/layers/LayerList.test.tsx +0 -232
  212. package/src/layers/LayerList.tsx +0 -268
  213. package/src/primitives/Sidebar.less +0 -112
  214. package/src/primitives/Sidebar.stories.tsx +0 -38
  215. package/src/primitives/Sidebar.test.tsx +0 -74
  216. package/src/primitives/Sidebar.tsx +0 -35
  217. package/src/ui/layers/index.ts +0 -5
package/dist/index.js CHANGED
@@ -1,141 +1,75 @@
1
- import { resolveLoupe, TrialLoupe } from './chunk-ERFMC6WU.js';
2
- export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LoupeBubble, LoupeGestures, TrialLoupe, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe } from './chunk-ERFMC6WU.js';
1
+ import { resolveLoupe, TrialLoupe } from './chunk-S4NCI32V.js';
2
+ export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LoupeBubble, LoupeGestures, TrialLoupe, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe } from './chunk-S4NCI32V.js';
3
3
  import { createEventBus, pushSnapshot, redo, undo } from './chunk-RL2LOLNI.js';
4
4
  export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-RL2LOLNI.js';
5
- import { useDragDrop, DragOverlay, Palette } from './chunk-RS3HRQWU.js';
5
+ import { useDragDrop, DragOverlay, Palette } from './chunk-WPLAANH4.js';
6
6
  import { useTiledSurface } from './chunk-IJJUK4FU.js';
7
7
  export { composeRects, rectsEqual, toDeviceRect, useTiledSurface } from './chunk-IJJUK4FU.js';
8
8
  import { useJob } from './chunk-HXXTULDN.js';
9
9
  export { useJob } from './chunk-HXXTULDN.js';
10
- import { suppressContributions, mergeContributions, builtinContributions, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, resolveLabTool, AnnotationsContext, useLabChromeContext, labContributions, LabHeaderRegion, LabFooterRegion, LabAsideRegion, LabSidebarRegion } from './chunk-CKUKF72R.js';
11
- export { AnnotationsContext, ExportMenu, LabAsideRegion, LabFooterRegion, LabHeaderRegion, LabSidebarRegion, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, contributionsIn, labContributions, mergeContributions, suppressContributions, toolContributions, useAnnotations, useAnnotationsOptional, useLabChromeContext } from './chunk-CKUKF72R.js';
12
- import { Split, JobProgress, Sidebar, Legend, FloatingPanel } from './chunk-KJCUERQF.js';
13
- export { FloatingPanel, JobProgress, Legend, Sidebar, Split } from './chunk-KJCUERQF.js';
14
- import { Toolbar, StatusBar, ScaleIndicator, ZoomControl } from './chunk-753Y6HE6.js';
15
- export { FpsMeter, ScaleIndicator, StatusBar, Toolbar, ZoomControl } from './chunk-753Y6HE6.js';
16
- import { unruledConfigSchema, createLabStore, openLabStore, panelKey } from './chunk-LRI3MBGR.js';
17
- export { CURRENT_DOCUMENT_VERSION, dockPanel, labDocumentKey, openLabStore, panelKey, quarantineKey, undockPanel, useTrialState } from './chunk-LRI3MBGR.js';
10
+ import { markCommands, markSvgNodes } from './chunk-KHK5FGER.js';
11
+ export { markCommands, markSvgNodes } from './chunk-KHK5FGER.js';
12
+ import { ANNOTATION_WEASEL_TOOLS, annotationToolInfo, suppressContributions, mergeContributions, builtinContributions, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, resolveLabTool, useLabChromeContext, labContributions, labAnnotationTools, LabHeaderRegion, LabFooterRegion, LabAsideRegion, LabSidebarRegion } from './chunk-4TT3PNPR.js';
13
+ export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, ExportMenu, LabAsideRegion, LabFooterRegion, LabHeaderRegion, LabSidebarRegion, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, contributionsIn, labContributions, mergeContributions, suppressContributions, toolContributions, useLabChromeContext } from './chunk-4TT3PNPR.js';
14
+ import { AnnotationsContext } from './chunk-3RY6WL5T.js';
15
+ export { AnnotationsContext, useAnnotations, useAnnotationsOptional } from './chunk-3RY6WL5T.js';
16
+ import { Split, JobProgress, Legend } from './chunk-6FLXL3I7.js';
17
+ export { JobProgress, Legend, Split } from './chunk-6FLXL3I7.js';
18
+ import { FloatingPanel } from './chunk-NEXR37YJ.js';
19
+ export { FloatingPanel } from './chunk-NEXR37YJ.js';
20
+ import { Toolbar, StatusBar, ScaleIndicator, ZoomControl } from './chunk-SLAQPUI4.js';
21
+ export { FpsMeter, ScaleIndicator, StatusBar, Toolbar, ZoomControl } from './chunk-SLAQPUI4.js';
22
+ import './chunk-SBXNQW4G.js';
23
+ import { unruledConfigSchema, createLabStore, openLabStore, panelKey } from './chunk-HKV7LRHY.js';
24
+ export { CURRENT_DOCUMENT_VERSION, dockPanel, labDocumentKey, openLabStore, panelKey, quarantineKey, undockPanel, useTrialState } from './chunk-HKV7LRHY.js';
18
25
  import { newId, useWarnIgnoredChange, useOpenOnce, PersistenceContext, createRecordCache, noneAdapter, defaultStorage, usePersistedState } from './chunk-RWNDDKOH.js';
19
26
  export { Persistence, createIndexedDbAdapter, createMemoryAdapter, indexedDbAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, usePersistedState } from './chunk-RWNDDKOH.js';
20
- export { ControlPanel } from './chunk-FKLT3ITC.js';
21
- import { useConfigSchema } from './chunk-6BUQ77ZV.js';
22
- export { useConfigSchema } from './chunk-6BUQ77ZV.js';
27
+ export { ControlPanel, inDialog, summarizeValue } from './chunk-ASOK76ZH.js';
28
+ import { useConfigSchema } from './chunk-GHGO52SO.js';
29
+ export { sectionTree, useConfigSchema } from './chunk-GHGO52SO.js';
23
30
  import { useLabContext, LabContext } from './chunk-Z76KEZAX.js';
24
31
  export { LabContext, useLabContext } from './chunk-Z76KEZAX.js';
25
- import { useResolvedConfig } from './chunk-A2ACAGW6.js';
26
- export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from './chunk-A2ACAGW6.js';
27
- export { fromConfigFields, isLeafVisible } from './chunk-EMXAIRUJ.js';
28
- import { hasConfigPath, schemaNodeAtPath, applyConfigWrite, resolveAutoConfig, isAuto, isRecord, autoPathsOf, fillConfigDefaults } from './chunk-REOBGYMC.js';
29
- export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from './chunk-REOBGYMC.js';
30
- import { CameraWheelContext, as2DView, DEFAULT_VIEW, CanvasStack, Stage, withZoom, fitStage } from './chunk-TT5C5S6R.js';
31
- export { CanvasStack, DEFAULT_VIEW, Stage, as2DView, fitStage, usePanZoom } from './chunk-TT5C5S6R.js';
32
- export { centerOn, zoomAt } from './chunk-H6ZAOWNE.js';
33
- import { applyCamera } from './chunk-2AYGEN57.js';
34
- export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from './chunk-2AYGEN57.js';
32
+ import { useResolvedConfig } from './chunk-O6FFFOHS.js';
33
+ export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from './chunk-O6FFFOHS.js';
34
+ export { fromConfigFields, isLeafVisible } from './chunk-IRTGUQ5O.js';
35
+ import { hasConfigPath, schemaNodeAtPath, applyConfigWrite, resolveAutoConfig, isAuto, isRecord, autoPathsOf, fillConfigDefaults } from './chunk-TJ77A4A3.js';
36
+ export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from './chunk-TJ77A4A3.js';
37
+ import { CanvasStack, Stage, fitStage } from './chunk-CGHF6RZV.js';
38
+ export { CanvasStack, Stage, fitStage } from './chunk-CGHF6RZV.js';
39
+ export { centerOn, zoomAt } from './chunk-JVBYV6TL.js';
40
+ export { screenToWorld, worldToScreen } from './chunk-AWQG7FCC.js';
35
41
  import { useSurfaceOptional, useSurfaceCanvas, useTileId, SurfaceContext, SurfaceCanvasContext } from './chunk-WIG6XHJ7.js';
36
42
  export { SurfaceCanvasContext, SurfaceContext, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId } from './chunk-WIG6XHJ7.js';
43
+ import { CameraWheelContext, as2DView, DEFAULT_VIEW, CameraScopeContext, withZoom } from './chunk-DWMSB4CA.js';
44
+ export { CameraContext, CameraInput, CameraScope, DEFAULT_VIEW, as2DView } from './chunk-DWMSB4CA.js';
45
+ import { applyCamera } from './chunk-24W5VEJW.js';
46
+ export { DEFAULT_FRAME, applyCamera, resolveFrame } from './chunk-24W5VEJW.js';
47
+ import { CanvasStackContext } from './chunk-CQLQPQ4P.js';
37
48
  export { CanvasStackContext } from './chunk-CQLQPQ4P.js';
38
- import { LabStoreContext, TrialIdProvider } from './chunk-2YILQ7Y5.js';
49
+ import { LabStoreContext, TrialIdProvider, TrialIdContext } from './chunk-2YILQ7Y5.js';
39
50
  export { LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, useLabStore, useTrialId } from './chunk-2YILQ7Y5.js';
40
- import { LayerList } from './chunk-D35PFTS7.js';
41
- export { LayerList } from './chunk-D35PFTS7.js';
42
- import './chunk-SBXNQW4G.js';
43
- import { E, w, T, a2, p, u, c, n, f, r, h, serializeSvg, C, l7, r5, a5, Lt, o2, a3, l3, u3, r7, r8, r6, o5, s5, c7, l6, c3, s3, u2, g, b2, y2, l4, b3, c8, r3, l2, C2, S, D, O, I2, z2, U, W, G2, H, B, X, A2, c4, n5, s4, m2, c2, l, g2, l5, S4, r9, n6, r10, i5, i4, s2, n7, o4, c5, c6, w2, L2, n8, k3, $2 } from './chunk-LASCBWW7.js';
44
- export { a5 as Button, B as CheckboxRow, y as CloseIcon, $ as CollapseIcon, z2 as ColorRow, S2 as CurveField, q as EffectCard, Y as EffectCardList, te as ExpandIcon, o as Icon, u2 as Input, l9 as Jog, c4 as LayerStack, U as NumberRow, I as PauseIcon, F as PlayIcon, X as PropertyGroup, O as PropertyList, D as PropertyPanel, j2 as PropertyRow, k2 as PropertySpan, v as ResetIcon, b2 as Select, W as SelectRow, I2 as SliderRow, R as StepBackIcon, z as StepForwardIcon, L as StopIcon, K as Subpanel, H as TextRow, r5 as ToggleBar, G2 as ToggleRow, oe as TokenPanel, H2 as inferTokenType, O2 as refitScale } from './chunk-LASCBWW7.js';
45
- import { textCommand, linePath, markerDrawCommands, ellipsePath, rectPath, createScene, asNodeId as asNodeId$1, WeaselProvider, SceneCanvas, sceneFromJSON, PathBuilder, renderSceneToPixels, useActiveToolContext } from '@weasel-js/core';
51
+ import './chunk-2RVCB2PT.js';
52
+ import { D, S2, G, d2, s3, c, Ht, o3, a6, l5, u5, a5, r3, a7, i2, o5, s6, c5, l7, p, f2, u4, g, T, y2, l8, y, c6, i3, l4, C2, S, ae2, oe, B2, b2, A2, n6, s5, m3, l2, u, g2, u3, S4, r4, n7, r5, i4, p2, f, n8, o4, c3, c4, w, L, n9, k2, $2 } from './chunk-TYN6MLXX.js';
53
+ export { c as Button, V as CloseIcon, xe as CollapseIcon, _ as CurveField, Se as ExpandIcon, l as Icon, u4 as Input, l9 as Jog, D as LayerList, re as PauseIcon, ne as PlayIcon, V2 as PropertyControl, B2 as PropertyField, b2 as PropertyGroup, oe as PropertyList, ae2 as PropertyPanel, L3 as PropertyRow, se as PropertySpan, B as ResetIcon, T as Select, ae as StepBackIcon, $ as StepForwardIcon, ie as StopIcon, x as Subpanel, a5 as ToggleBar, oe2 as TokenPanel, H2 as inferTokenType, S2 as moveLayers, O2 as refitScale } from './chunk-TYN6MLXX.js';
54
+ import { serializeSvg } from './chunk-QGMOA2YE.js';
55
+ import { createScene, asNodeId as asNodeId$1, WeaselProvider, SceneCanvas, createPointerStore, PointerContextProvider, sceneFromJSON, renderSceneToPixels, useActiveToolContext } from '@weasel-js/core';
46
56
  import { createContext, useState, useRef, useEffect, useCallback, useContext, useMemo, useId, Children, useLayoutEffect, useSyncExternalStore } from 'react';
47
57
  import { flushSync, createPortal } from 'react-dom';
48
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
49
- import { useThemeOptional, ThemeProvider } from '@weasel-js/theme/react';
58
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
59
+ import { defineTheme, weaselTheme, colorCount, resolveTheme, colorAt } from '@weasel-js/theme';
60
+ import { useResolvedColorMode, useThemeOptional, ThemeProvider, ThemeContext } from '@weasel-js/theme/react';
50
61
  import { useStore } from 'zustand/react';
51
- import { defineTheme, weaselTheme } from '@weasel-js/theme';
52
62
  import { Provider, StrategyRegistryProvider, DragProvider, Container, useDragHandle } from 'windease/react';
53
63
  import { asNodeId, Store, createNode, floatingStrategy, gridStrategy } from 'windease';
54
64
  import { Focusable } from 'react-aria-components';
55
65
 
56
- var MARK_COLOR = "#e5484d";
57
- var MARK_WIDTH = 2;
58
- var TEXT_SIZE = 14;
59
- var toWorld = (p2, content) => ({
60
- x: p2.x * content.w,
61
- y: p2.y * content.h
62
- });
63
- function vertices(m2, content) {
64
- const stored = m2.data.points;
65
- if (stored && stored.length >= 2) return stored.map((p2) => toWorld(p2, content));
66
- const { x, y: y3, width, height } = m2.pose;
67
- return [
68
- { x, y: y3 },
69
- { x: x + width, y: y3 + height }
70
- ];
71
- }
72
- function polyline(points) {
73
- const b3 = new PathBuilder();
74
- const first = points[0];
75
- if (!first) return rectPath(0, 0, 0, 0);
76
- b3.moveTo(first.x, first.y);
77
- for (const p2 of points.slice(1)) b3.lineTo(p2.x, p2.y);
78
- return b3.build();
79
- }
80
- function markCommands(m2, content, style = {}) {
81
- const color = style.color ?? MARK_COLOR;
82
- const stroke = {
83
- paint: { color },
84
- width: MARK_WIDTH,
85
- cap: "round",
86
- join: "round",
87
- ...style.stale ? { dash: [6, 4] } : {}
88
- };
89
- switch (m2.data.kind) {
90
- case "rect":
91
- return [
92
- { kind: "path", path: rectPath(m2.pose.x, m2.pose.y, m2.pose.width, m2.pose.height), stroke }
93
- ];
94
- case "ellipse":
95
- return [{ kind: "path", path: ellipsePath(m2.pose), stroke }];
96
- case "line": {
97
- const [a4, b3] = vertices(m2, content);
98
- return [{ kind: "path", path: linePath(a4, b3), stroke }];
99
- }
100
- case "arrow": {
101
- const [a4, b3] = vertices(m2, content);
102
- const marked = { ...stroke, markerEnd: "arrow" };
103
- const path = linePath(a4, b3);
104
- return [
105
- { kind: "path", path, stroke: marked },
106
- ...markerDrawCommands(path, marked, MARK_WIDTH, void 0)
107
- ];
108
- }
109
- case "stroke":
110
- return [{ kind: "path", path: polyline(vertices(m2, content)), stroke }];
111
- case "text": {
112
- const text = m2.data.title;
113
- if (!text) return [];
114
- return [
115
- textCommand(
116
- m2.pose.x,
117
- m2.pose.y,
118
- text,
119
- { fontSize: TEXT_SIZE },
120
- void 0,
121
- void 0,
122
- void 0,
123
- {
124
- fill: { color }
125
- }
126
- )
127
- ];
128
- }
129
- }
130
- }
131
-
132
66
  // src/annotations/staleness.ts
133
67
  function seenFrom(config, keys) {
134
68
  const out = {};
135
69
  if (config === null || typeof config !== "object") return out;
136
70
  const src = config;
137
- for (const k3 of keys) {
138
- if (k3 in src) out[k3] = src[k3];
71
+ for (const k2 of keys) {
72
+ if (k2 in src) out[k2] = src[k2];
139
73
  }
140
74
  return out;
141
75
  }
@@ -143,9 +77,9 @@ function isStale(seen, config, keys) {
143
77
  if (!seen || keys.length === 0) return false;
144
78
  if (config === null || typeof config !== "object") return false;
145
79
  const src = config;
146
- for (const k3 of keys) {
147
- if (!(k3 in seen)) continue;
148
- if (!Object.is(seen[k3], src[k3])) return true;
80
+ for (const k2 of keys) {
81
+ if (!(k2 in seen)) continue;
82
+ if (!Object.is(seen[k2], src[k2])) return true;
149
83
  }
150
84
  return false;
151
85
  }
@@ -156,71 +90,20 @@ function createMarkDrawOne(opts) {
156
90
  }
157
91
  function resolveMarkStyle(data, opts) {
158
92
  return {
159
- color: opts.meaning?.statuses?.find((s5) => s5.id === data.status)?.color,
93
+ color: opts.meaning?.statuses?.find((s4) => s4.id === data.status)?.color,
160
94
  // Read off the node rather than through the store's `isStale`, which
161
95
  // wants a projected Annotation this path does not have.
162
96
  stale: isStale(data.seen, opts.config, opts.positionDependsOn ?? [])
163
97
  };
164
98
  }
165
99
 
166
- // src/annotations/svgNodes.ts
167
- var NO_PAINT = { kind: "none" };
168
- function toSvgPaint(paint) {
169
- if (!paint) return NO_PAINT;
170
- if ("color" in paint && typeof paint.color === "string") {
171
- return {
172
- kind: "solid",
173
- color: paint.color,
174
- ...paint.opacity != null ? { opacity: paint.opacity } : {}
175
- };
176
- }
177
- return { kind: "gradient", paint };
178
- }
179
- function toSvgStroke(stroke) {
180
- return {
181
- paint: toSvgPaint(stroke.paint),
182
- width: stroke.width ?? 1,
183
- ...stroke.cap ? { cap: stroke.cap } : {},
184
- ...stroke.join ? { join: stroke.join } : {},
185
- ...stroke.dash ? { dash: [...stroke.dash] } : {},
186
- ...stroke.miterLimit != null ? { miterLimit: stroke.miterLimit } : {},
187
- ...stroke.align ? { align: stroke.align } : {}
188
- };
189
- }
190
- function toSvgNode(cmd, m2) {
191
- if (cmd.kind === "path") {
192
- return {
193
- kind: "path",
194
- path: cmd.path,
195
- fill: toSvgPaint(cmd.fill),
196
- ...cmd.stroke ? { stroke: toSvgStroke(cmd.stroke) } : {}
197
- };
198
- }
199
- if (cmd.kind === "text") {
200
- return {
201
- kind: "text",
202
- x: cmd.x,
203
- y: cmd.y,
204
- width: m2.pose.width,
205
- height: m2.pose.height,
206
- text: cmd.runs.map((run) => run.text).join(""),
207
- style: cmd.style,
208
- ...cmd.runs[0]?.fill ? { fill: cmd.runs[0].fill } : {}
209
- };
210
- }
211
- throw new Error(`[labkit] a mark drew a '${cmd.kind}' command, which has no vector form`);
212
- }
213
- function markSvgNodes(m2, content, style = {}) {
214
- return markCommands(m2, content, style).map((cmd) => toSvgNode(cmd, m2));
215
- }
216
-
217
100
  // src/annotations/capture.ts
218
101
  var SVG_NS = "http://www.w3.org/2000/svg";
219
102
  function capturePlan(base, format) {
220
103
  if (format === "svg") return "svg-document";
221
104
  return base?.kind === "svg" ? "svg-document" : "raster-stack";
222
105
  }
223
- function nestBaseSvg(markup, w3, h2) {
106
+ function nestBaseSvg(markup, w2, h) {
224
107
  const doc = new DOMParser().parseFromString(markup, "image/svg+xml");
225
108
  const root = doc.documentElement;
226
109
  if (doc.getElementsByTagName("parsererror").length > 0 || root.localName !== "svg") {
@@ -228,17 +111,17 @@ function nestBaseSvg(markup, w3, h2) {
228
111
  }
229
112
  root.setAttribute("x", "0");
230
113
  root.setAttribute("y", "0");
231
- root.setAttribute("width", String(w3));
232
- root.setAttribute("height", String(h2));
114
+ root.setAttribute("width", String(w2));
115
+ root.setAttribute("height", String(h));
233
116
  return new XMLSerializer().serializeToString(root);
234
117
  }
235
- function embedRasterBase(base, w3, h2, onWarn) {
118
+ function embedRasterBase(base, w2, h, onWarn) {
236
119
  const href = base.kind === "canvas" ? base.canvas.toDataURL() : base.kind === "image" ? base.src : "";
237
120
  if (base.kind === "image" && !href.startsWith("data:")) {
238
121
  onWarn?.(`base image '${href}' is a reference, so this SVG is not self-contained`);
239
122
  }
240
- return serializeSvg([{ kind: "image", href, x: 0, y: 0, width: w3, height: h2 }], {
241
- viewBox: { x: 0, y: 0, width: w3, height: h2 }
123
+ return serializeSvg([{ kind: "image", href, x: 0, y: 0, width: w2, height: h }], {
124
+ viewBox: { x: 0, y: 0, width: w2, height: h }
242
125
  });
243
126
  }
244
127
  function markNodesOf(scene, draw) {
@@ -254,15 +137,15 @@ function markNodesOf(scene, draw) {
254
137
  }
255
138
  function composeCaptureSvg(args) {
256
139
  const { base, scene, draw, scale, onWarn } = args;
257
- const { w: w3, h: h2 } = draw.content;
258
- const baseXml = base === void 0 ? "" : base.kind === "svg" ? nestBaseSvg(base.markup, w3, h2) : embedRasterBase(base, w3, h2, onWarn);
140
+ const { w: w2, h } = draw.content;
141
+ const baseXml = base === void 0 ? "" : base.kind === "svg" ? nestBaseSvg(base.markup, w2, h) : embedRasterBase(base, w2, h, onWarn);
259
142
  const marksXml = serializeSvg(markNodesOf(scene, draw), {
260
- viewBox: { x: 0, y: 0, width: w3, height: h2 },
143
+ viewBox: { x: 0, y: 0, width: w2, height: h },
261
144
  onWarn
262
145
  });
263
- const outW = Math.max(1, Math.round(w3 * scale));
264
- const outH = Math.max(1, Math.round(h2 * scale));
265
- return `<svg xmlns="${SVG_NS}" width="${outW}" height="${outH}" viewBox="0 0 ${w3} ${h2}">${baseXml}${marksXml}</svg>`;
146
+ const outW = Math.max(1, Math.round(w2 * scale));
147
+ const outH = Math.max(1, Math.round(h * scale));
148
+ return `<svg xmlns="${SVG_NS}" width="${outW}" height="${outH}" viewBox="0 0 ${w2} ${h}">${baseXml}${marksXml}</svg>`;
266
149
  }
267
150
  function context2d(width, height) {
268
151
  const canvas = document.createElement("canvas");
@@ -356,26 +239,26 @@ async function captureTarget(args, opts = {}) {
356
239
  }
357
240
 
358
241
  // src/annotations/frac.ts
359
- function fracToWorld(f3, content) {
242
+ function fracToWorld(f4, content) {
360
243
  return {
361
- x: f3.x * content.w,
362
- y: f3.y * content.h,
363
- width: f3.w * content.w,
364
- height: f3.h * content.h
244
+ x: f4.x * content.w,
245
+ y: f4.y * content.h,
246
+ width: f4.w * content.w,
247
+ height: f4.h * content.h
365
248
  };
366
249
  }
367
- function worldToFrac(r9, content) {
250
+ function worldToFrac(r4, content) {
368
251
  const sx = content.w === 0 ? 0 : 1 / content.w;
369
252
  const sy = content.h === 0 ? 0 : 1 / content.h;
370
- return { x: r9.x * sx, y: r9.y * sy, w: r9.width * sx, h: r9.height * sy };
253
+ return { x: r4.x * sx, y: r4.y * sy, w: r4.width * sx, h: r4.height * sy };
371
254
  }
372
255
  var DP = 1e4;
373
- function roundFrac(f3) {
256
+ function roundFrac(f4) {
374
257
  return {
375
- x: Math.round(f3.x * DP) / DP,
376
- y: Math.round(f3.y * DP) / DP,
377
- w: Math.round(f3.w * DP) / DP,
378
- h: Math.round(f3.h * DP) / DP
258
+ x: Math.round(f4.x * DP) / DP,
259
+ y: Math.round(f4.y * DP) / DP,
260
+ w: Math.round(f4.w * DP) / DP,
261
+ h: Math.round(f4.h * DP) / DP
379
262
  };
380
263
  }
381
264
  function fracContains(box, pt, tol = 0) {
@@ -417,8 +300,8 @@ var MarkHistory = class {
417
300
  /** The target `undo` would act on, skipping any whose scene has nothing
418
301
  * left — a scene can drop entries this ordering still lists. */
419
302
  next(stack, can, at) {
420
- for (let i3 = stack.length - 1; i3 >= 0; i3--) {
421
- const target = stack[i3];
303
+ for (let i4 = stack.length - 1; i4 >= 0; i4--) {
304
+ const target = stack[i4];
422
305
  if (target === void 0) continue;
423
306
  const scene = at(target);
424
307
  if (scene && can(scene)) return target;
@@ -426,13 +309,13 @@ var MarkHistory = class {
426
309
  return null;
427
310
  }
428
311
  canUndo(at) {
429
- return this.next(this.undoable, (s5) => s5.canUndo(), at) !== null;
312
+ return this.next(this.undoable, (s4) => s4.canUndo(), at) !== null;
430
313
  }
431
314
  canRedo(at) {
432
- return this.next(this.redoable, (s5) => s5.canRedo(), at) !== null;
315
+ return this.next(this.redoable, (s4) => s4.canRedo(), at) !== null;
433
316
  }
434
317
  undo(at) {
435
- const target = this.next(this.undoable, (s5) => s5.canUndo(), at);
318
+ const target = this.next(this.undoable, (s4) => s4.canUndo(), at);
436
319
  const scene = target === null ? void 0 : at(target);
437
320
  if (!scene) return false;
438
321
  this.replaying = "undo";
@@ -443,7 +326,7 @@ var MarkHistory = class {
443
326
  }
444
327
  }
445
328
  redo(at) {
446
- const target = this.next(this.redoable, (s5) => s5.canRedo(), at);
329
+ const target = this.next(this.redoable, (s4) => s4.canRedo(), at);
447
330
  const scene = target === null ? void 0 : at(target);
448
331
  if (!scene) return false;
449
332
  this.replaying = "redo";
@@ -455,9 +338,9 @@ var MarkHistory = class {
455
338
  }
456
339
  };
457
340
  function drop(stack, value) {
458
- for (let i3 = stack.length - 1; i3 >= 0; i3--) {
459
- if (stack[i3] === value) {
460
- stack.splice(i3, 1);
341
+ for (let i4 = stack.length - 1; i4 >= 0; i4--) {
342
+ if (stack[i4] === value) {
343
+ stack.splice(i4, 1);
461
344
  return;
462
345
  }
463
346
  }
@@ -498,6 +381,12 @@ function createAnnotationStore(opts) {
498
381
  for (const target of Object.keys(restore ?? {})) sceneFor(target);
499
382
  const targetOf = (id) => targets().find((t) => t.id === id);
500
383
  const contentOf = (id) => targetOf(id)?.content ?? NO_CONTENT;
384
+ const drawOptionsFor = (info) => ({
385
+ content: info.content,
386
+ positionDependsOn: info.positionDependsOn,
387
+ config: opts.config?.(),
388
+ meaning: typeof opts.meaning === "function" ? opts.meaning() : opts.meaning
389
+ });
501
390
  const project = (target, node) => {
502
391
  const found = scenes.get(target)?.get(asNodeId$1(node));
503
392
  if (!found) return void 0;
@@ -524,15 +413,15 @@ function createAnnotationStore(opts) {
524
413
  return out;
525
414
  };
526
415
  const all = () => liveTargets().flatMap(marksOn);
527
- const matches = (a4, q2) => {
528
- if (q2.target !== void 0 && a4.target !== q2.target) return false;
529
- if (q2.kind !== void 0 && a4.kind !== q2.kind) return false;
530
- if (q2.status !== void 0 && a4.status !== q2.status) return false;
531
- if (q2.tags !== void 0) {
416
+ const matches = (a4, q) => {
417
+ if (q.target !== void 0 && a4.target !== q.target) return false;
418
+ if (q.kind !== void 0 && a4.kind !== q.kind) return false;
419
+ if (q.status !== void 0 && a4.status !== q.status) return false;
420
+ if (q.tags !== void 0) {
532
421
  const have = a4.tags ?? [];
533
- for (const t of q2.tags) if (!have.includes(t)) return false;
422
+ for (const t of q.tags) if (!have.includes(t)) return false;
534
423
  }
535
- if (q2.where && !q2.where(a4)) return false;
424
+ if (q.where && !q.where(a4)) return false;
536
425
  return true;
537
426
  };
538
427
  const nodeOf = (id) => {
@@ -549,8 +438,8 @@ function createAnnotationStore(opts) {
549
438
  const parts = splitId(id);
550
439
  return parts ? project(parts.target, parts.node) : void 0;
551
440
  },
552
- query(q2) {
553
- return q2 ? all().filter((a4) => matches(a4, q2)) : all();
441
+ query(q) {
442
+ return q ? all().filter((a4) => matches(a4, q)) : all();
554
443
  },
555
444
  hitTest(target, pt, tol = 0) {
556
445
  return marksOn(target).filter((a4) => fracContains(a4.frac, pt, tol)).reverse();
@@ -598,7 +487,7 @@ function createAnnotationStore(opts) {
598
487
  for (const [target, scene] of scenes) {
599
488
  const next = wanted.get(target) ?? [];
600
489
  const now = scene.getSelection();
601
- if (now.length === next.length && next.every((n6, i3) => String(now[i3]) === n6)) continue;
490
+ if (now.length === next.length && next.every((n5, i4) => String(now[i4]) === n5)) continue;
602
491
  scene.setSelection(next.map(asNodeId$1));
603
492
  }
604
493
  },
@@ -649,6 +538,20 @@ function createAnnotationStore(opts) {
649
538
  const found = nodeOf(id);
650
539
  if (found) found.scene.remove(asNodeId$1(found.node.id));
651
540
  },
541
+ paintedMarks(target) {
542
+ const info = targetOf(target);
543
+ const scene = scenes.get(target);
544
+ if (!info || !scene) return [];
545
+ const draw = drawOptionsFor(info);
546
+ return [...scene.renderOrder()].flatMap((id) => {
547
+ const node = scene.get(asNodeId$1(String(id)));
548
+ if (!node) return [];
549
+ const data = node.data;
550
+ return [
551
+ { mark: { pose: node.pose, data }, style: resolveMarkStyle(data, draw) }
552
+ ];
553
+ });
554
+ },
652
555
  async capture(target, captureOpts) {
653
556
  const info = targetOf(target);
654
557
  if (!info) throw new Error(`[labkit] no annotation target called '${target}'`);
@@ -656,12 +559,7 @@ function createAnnotationStore(opts) {
656
559
  {
657
560
  target,
658
561
  scene: sceneFor(target),
659
- draw: {
660
- content: info.content,
661
- positionDependsOn: info.positionDependsOn,
662
- config: opts.config?.(),
663
- meaning: typeof opts.meaning === "function" ? opts.meaning() : opts.meaning
664
- },
562
+ draw: drawOptionsFor(info),
665
563
  base: info.base,
666
564
  onWarn: (message) => console.warn(`[labkit] capture: ${message}`)
667
565
  },
@@ -683,46 +581,18 @@ function annotationsFromJSON(raw, targets, rest = {}) {
683
581
  return createAnnotationStore({ targets, restore: doc.scenes, ...rest });
684
582
  }
685
583
 
686
- // src/annotations/toolMap.ts
687
- var TOOLS = {
688
- select: { weaselTool: "select" },
689
- stroke: { weaselTool: "pencil", kind: "stroke" },
690
- line: { weaselTool: "line", kind: "line" },
691
- arrow: { weaselTool: "line", kind: "arrow" },
692
- rect: { weaselTool: "rect", kind: "rect" },
693
- ellipse: { weaselTool: "ellipse", kind: "ellipse" },
694
- text: { weaselTool: "text", kind: "text" }
695
- };
696
- var ANNOTATION_TOOLS = [
697
- // Not in `TOOLS`: an id the map does not carry is what leaves the overlay idle.
698
- { id: "pointer", label: "Interact", icon: a2, group: "annotate" },
699
- { id: "select", label: "Select", icon: p, group: "annotate" },
700
- { id: "stroke", label: "Freehand", icon: u, group: "annotate" },
701
- { id: "line", label: "Line", icon: c, group: "annotate" },
702
- { id: "arrow", label: "Arrow", icon: n, group: "annotate" },
703
- { id: "rect", label: "Rectangle", icon: f, group: "annotate" },
704
- { id: "ellipse", label: "Ellipse", icon: r, group: "annotate" },
705
- { id: "text", label: "Text", icon: h, group: "annotate" }
706
- ];
707
- function annotationToolInfo(id) {
708
- return id === null ? void 0 : TOOLS[id];
709
- }
710
- var ANNOTATION_WEASEL_TOOLS = [
711
- ...new Set(Object.values(TOOLS).map((t) => t.weaselTool))
712
- ];
713
-
714
584
  // src/annotations/view.ts
715
- function toWeaselView(v2) {
716
- return { x: v2.pan.x, y: v2.pan.y, scale: { x: v2.zoom, y: v2.zoom } };
585
+ function toWeaselView(v) {
586
+ return { x: v.pan.x, y: v.pan.y, scale: { x: v.zoom, y: v.zoom } };
717
587
  }
718
- function fromWeaselView(v2) {
719
- return { zoom: v2.scale.x, pan: { x: v2.x, y: v2.y } };
588
+ function fromWeaselView(v) {
589
+ return { zoom: v.scale.x, pan: { x: v.x, y: v.y } };
720
590
  }
721
591
  function fitView(content, pane) {
722
592
  const zoom = content.w > 0 && content.h > 0 ? Math.min(pane.w / content.w, pane.h / content.h) : 1;
723
593
  return { zoom: Number.isFinite(zoom) && zoom > 0 ? zoom : 1, pan: { x: 0, y: 0 } };
724
594
  }
725
- var sameRect = (a4, b3) => a4 !== null && a4.x === b3.x && a4.y === b3.y && a4.w === b3.w && a4.h === b3.h;
595
+ var sameRect = (a4, b2) => a4 !== null && a4.x === b2.x && a4.y === b2.y && a4.w === b2.w && a4.h === b2.h;
726
596
  function ToolBridge({ toolId }) {
727
597
  const tools = useActiveToolContext();
728
598
  const setActive = tools.setActive;
@@ -732,9 +602,9 @@ function ToolBridge({ toolId }) {
732
602
  return null;
733
603
  }
734
604
  function pointsOf(extras, content) {
735
- const toFrac = (p2) => ({
736
- x: content.w === 0 ? 0 : p2.x / content.w,
737
- y: content.h === 0 ? 0 : p2.y / content.h
605
+ const toFrac = (p3) => ({
606
+ x: content.w === 0 ? 0 : p3.x / content.w,
607
+ y: content.h === 0 ? 0 : p3.y / content.h
738
608
  });
739
609
  if (extras.kind === "line") {
740
610
  return [toFrac(extras.a), toFrac(extras.b)];
@@ -997,10 +867,6 @@ var interstellar_theme_default = {
997
867
  dark: {
998
868
  value: "#0a0a14",
999
869
  type: "color"
1000
- },
1001
- light: {
1002
- value: "#fafaf7",
1003
- type: "color"
1004
870
  }
1005
871
  },
1006
872
  "surface-raised": {
@@ -1008,10 +874,6 @@ var interstellar_theme_default = {
1008
874
  dark: {
1009
875
  value: "rgba(20, 20, 36, 0.55)",
1010
876
  type: "color"
1011
- },
1012
- light: {
1013
- value: "#ffffff",
1014
- type: "color"
1015
877
  }
1016
878
  },
1017
879
  "surface-sunken": {
@@ -1019,10 +881,6 @@ var interstellar_theme_default = {
1019
881
  dark: {
1020
882
  value: "#02020a",
1021
883
  type: "color"
1022
- },
1023
- light: {
1024
- value: "#f0ebe2",
1025
- type: "color"
1026
884
  }
1027
885
  },
1028
886
  border: {
@@ -1030,10 +888,6 @@ var interstellar_theme_default = {
1030
888
  dark: {
1031
889
  value: "rgba(255, 255, 255, 0.14)",
1032
890
  type: "color"
1033
- },
1034
- light: {
1035
- value: "#c9bba5",
1036
- type: "color"
1037
891
  }
1038
892
  },
1039
893
  "line-subtle": {
@@ -1041,10 +895,6 @@ var interstellar_theme_default = {
1041
895
  dark: {
1042
896
  value: "rgba(255, 255, 255, 0.08)",
1043
897
  type: "color"
1044
- },
1045
- light: {
1046
- value: "rgba(0, 0, 0, 0.08)",
1047
- type: "color"
1048
898
  }
1049
899
  },
1050
900
  fg: {
@@ -1052,10 +902,6 @@ var interstellar_theme_default = {
1052
902
  dark: {
1053
903
  value: "#e8e8f0",
1054
904
  type: "color"
1055
- },
1056
- light: {
1057
- value: "#2a2018",
1058
- type: "color"
1059
905
  }
1060
906
  },
1061
907
  "fg-muted": {
@@ -1063,10 +909,6 @@ var interstellar_theme_default = {
1063
909
  dark: {
1064
910
  value: "#a8a8c0",
1065
911
  type: "color"
1066
- },
1067
- light: {
1068
- value: "#6b5c4a",
1069
- type: "color"
1070
912
  }
1071
913
  },
1072
914
  "fg-subtle": {
@@ -1074,10 +916,6 @@ var interstellar_theme_default = {
1074
916
  dark: {
1075
917
  value: "#5a5a78",
1076
918
  type: "color"
1077
- },
1078
- light: {
1079
- value: "#a89b85",
1080
- type: "color"
1081
919
  }
1082
920
  },
1083
921
  accent: {
@@ -1085,10 +923,6 @@ var interstellar_theme_default = {
1085
923
  dark: {
1086
924
  value: "#b08adb",
1087
925
  type: "color"
1088
- },
1089
- light: {
1090
- value: "#a86f3c",
1091
- type: "color"
1092
926
  }
1093
927
  },
1094
928
  "accent-hover": {
@@ -1096,10 +930,6 @@ var interstellar_theme_default = {
1096
930
  dark: {
1097
931
  value: "#c6a3ee",
1098
932
  type: "color"
1099
- },
1100
- light: {
1101
- value: "#c2854f",
1102
- type: "color"
1103
933
  }
1104
934
  },
1105
935
  "focus-ring": {
@@ -1107,10 +937,6 @@ var interstellar_theme_default = {
1107
937
  dark: {
1108
938
  value: "rgba(176, 138, 219, 0.45)",
1109
939
  type: "color"
1110
- },
1111
- light: {
1112
- value: "rgba(168, 111, 60, 0.35)",
1113
- type: "color"
1114
940
  }
1115
941
  },
1116
942
  shadow: {
@@ -1118,10 +944,6 @@ var interstellar_theme_default = {
1118
944
  dark: {
1119
945
  value: "rgba(0, 0, 0, 0.7)",
1120
946
  type: "color"
1121
- },
1122
- light: {
1123
- value: "rgba(80, 60, 40, 0.18)",
1124
- type: "color"
1125
947
  }
1126
948
  },
1127
949
  "border-strong": {
@@ -1129,10 +951,6 @@ var interstellar_theme_default = {
1129
951
  dark: {
1130
952
  value: "rgba(255, 255, 255, 0.36)",
1131
953
  type: "color"
1132
- },
1133
- light: {
1134
- value: "#9e8b71",
1135
- type: "color"
1136
954
  }
1137
955
  },
1138
956
  backdrop: {
@@ -1140,10 +958,6 @@ var interstellar_theme_default = {
1140
958
  dark: {
1141
959
  value: "radial-gradient(ellipse 60% 80% at 18% 30%, rgba(150, 80, 200, 0.22), transparent 70%), radial-gradient(ellipse 55% 90% at 78% 70%, rgba(220, 100, 140, 0.18), transparent 65%), radial-gradient(ellipse 50% 70% at 50% 50%, rgba(60, 110, 200, 0.18), transparent 75%), radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)",
1142
960
  type: "gradient"
1143
- },
1144
- light: {
1145
- value: "none",
1146
- type: "gradient"
1147
961
  }
1148
962
  }
1149
963
  }
@@ -1250,7 +1064,7 @@ function Portalled({
1250
1064
  }
1251
1065
  function UndockedSections({ trialId, sections, onDock }) {
1252
1066
  if (sections.length === 0) return null;
1253
- return /* @__PURE__ */ jsx(Fragment, { children: sections.map((c9) => /* @__PURE__ */ jsx(Portalled, { trialId, contribution: c9, onDock }, c9.id)) });
1067
+ return /* @__PURE__ */ jsx(Fragment, { children: sections.map((c6) => /* @__PURE__ */ jsx(Portalled, { trialId, contribution: c6, onDock }, c6.id)) });
1254
1068
  }
1255
1069
  var NO_OP = () => {
1256
1070
  };
@@ -1273,17 +1087,17 @@ function TrialChrome({
1273
1087
  const lab = useLabContext();
1274
1088
  const storeCtx = useContext(LabStoreContext);
1275
1089
  if (!storeCtx) throw new Error("[labkit] TrialChrome requires <LabStoreProvider>");
1276
- const updateTrialView = useStore(storeCtx.store, (s5) => s5.updateTrialView);
1277
- const updateTrialSidebarWidth = useStore(storeCtx.store, (s5) => s5.updateTrialSidebarWidth);
1278
- const setTrialTitle = useStore(storeCtx.store, (s5) => s5.setTrialTitle);
1279
- const setTrialSectionCollapsed = useStore(storeCtx.store, (s5) => s5.setTrialSectionCollapsed);
1280
- const updateTrialConfig = useStore(storeCtx.store, (s5) => s5.updateTrialConfig);
1281
- const updateTrialState = useStore(storeCtx.store, (s5) => s5.updateTrialState);
1282
- const undockPanelAction = useStore(storeCtx.store, (s5) => s5.undockPanel);
1283
- const dockPanelAction = useStore(storeCtx.store, (s5) => s5.dockPanel);
1284
- const undockedPanels = useStore(storeCtx.store, (s5) => s5.undockedPanels);
1090
+ const updateTrialView = useStore(storeCtx.store, (s4) => s4.updateTrialView);
1091
+ const updateTrialSidebarWidth = useStore(storeCtx.store, (s4) => s4.updateTrialSidebarWidth);
1092
+ const setTrialTitle = useStore(storeCtx.store, (s4) => s4.setTrialTitle);
1093
+ const setTrialSectionCollapsed = useStore(storeCtx.store, (s4) => s4.setTrialSectionCollapsed);
1094
+ const updateTrialConfig = useStore(storeCtx.store, (s4) => s4.updateTrialConfig);
1095
+ const updateTrialState = useStore(storeCtx.store, (s4) => s4.updateTrialState);
1096
+ const undockPanelAction = useStore(storeCtx.store, (s4) => s4.undockPanel);
1097
+ const dockPanelAction = useStore(storeCtx.store, (s4) => s4.dockPanel);
1098
+ const undockedPanels = useStore(storeCtx.store, (s4) => s4.undockedPanels);
1285
1099
  const undockedIds = useMemo(
1286
- () => Object.values(undockedPanels).filter((p2) => p2.trialId === trialId).map((p2) => p2.sectionId),
1100
+ () => Object.values(undockedPanels).filter((p3) => p3.trialId === trialId).map((p3) => p3.sectionId),
1287
1101
  [undockedPanels, trialId]
1288
1102
  );
1289
1103
  const view2d = as2DView(record.view);
@@ -1296,9 +1110,9 @@ function TrialChrome({
1296
1110
  const title = record.title ?? instrument.title ?? instrument.name;
1297
1111
  const collapsedSections = record.collapsedSections ?? NO_SECTIONS;
1298
1112
  const ctx = useMemo(() => {
1299
- const setZoom = (z3) => {
1113
+ const setZoom = (z) => {
1300
1114
  if (!view2d) return;
1301
- updateTrialView(trialId, withZoom(view2d, z3));
1115
+ updateTrialView(trialId, withZoom(view2d, z));
1302
1116
  };
1303
1117
  return {
1304
1118
  trialId,
@@ -1338,7 +1152,7 @@ function TrialChrome({
1338
1152
  undockedPanels: undockedIds,
1339
1153
  undockPanel: (sectionId, as) => undockPanelAction(trialId, sectionId, as),
1340
1154
  dockPanel: (sectionId) => dockPanelAction(trialId, sectionId),
1341
- savedSnapshots: lab.savedSnapshots.filter((s5) => s5.trialId === trialId),
1155
+ savedSnapshots: lab.savedSnapshots.filter((s4) => s4.trialId === trialId),
1342
1156
  saveSnapshot: (name) => lab.saveSnapshot(trialId, name),
1343
1157
  loadSnapshot: (snapshotId) => lab.loadSnapshot(trialId, snapshotId),
1344
1158
  clone: () => lab.cloneTrial(trialId),
@@ -1384,7 +1198,7 @@ function TrialChrome({
1384
1198
  ),
1385
1199
  [instrument, ctx, trialChrome, chrome, suppress, lab.controls]
1386
1200
  );
1387
- const inRegion = (region) => contributions.filter((c9) => c9.region === region);
1201
+ const inRegion = (region) => contributions.filter((c6) => c6.region === region);
1388
1202
  const handleKeyDown = (e) => {
1389
1203
  const mod = e.metaKey || e.ctrlKey;
1390
1204
  if (!mod) return;
@@ -1422,7 +1236,7 @@ function TrialChrome({
1422
1236
  TrialBody,
1423
1237
  {
1424
1238
  width: record.sidebarWidth,
1425
- onWidthChange: (w3) => updateTrialSidebarWidth(trialId, w3),
1239
+ onWidthChange: (w2) => updateTrialSidebarWidth(trialId, w2),
1426
1240
  contentClassName: instrument.canvas || instrument.stage ? "lk-trial__content--flush" : void 0,
1427
1241
  sidebar: /* @__PURE__ */ jsxs(Fragment, { children: [
1428
1242
  /* @__PURE__ */ jsx(SidebarRegion, { contributions: inRegion("sidebar"), ctx }),
@@ -1430,7 +1244,7 @@ function TrialChrome({
1430
1244
  UndockedSections,
1431
1245
  {
1432
1246
  trialId,
1433
- sections: inRegion("sidebar").filter((c9) => undockedIds.includes(c9.id)),
1247
+ sections: inRegion("sidebar").filter((c6) => undockedIds.includes(c6.id)),
1434
1248
  onDock: ctx.dockPanel
1435
1249
  }
1436
1250
  )
@@ -1454,9 +1268,9 @@ function Trial({ id, chrome, suppress }) {
1454
1268
  const lab = useLabContext();
1455
1269
  const storeCtx = useContext(LabStoreContext);
1456
1270
  if (!storeCtx) throw new Error("[labkit] <Trial> requires <LabStoreProvider>");
1457
- const instruments = useStore(storeCtx.store, (s5) => s5.instruments) ?? lab.instruments;
1458
- const record = useStore(storeCtx.store, (s5) => s5.trials.find((w3) => w3.id === id));
1459
- const instrument = record ? instruments.find((i3) => i3.name === record.instrumentName) : void 0;
1271
+ const instruments = useStore(storeCtx.store, (s4) => s4.instruments) ?? lab.instruments;
1272
+ const record = useStore(storeCtx.store, (s4) => s4.trials.find((w2) => w2.id === id));
1273
+ const instrument = record ? instruments.find((i4) => i4.name === record.instrumentName) : void 0;
1460
1274
  const kept = useKeptMarks(instrument?.annotations?.storage, id);
1461
1275
  if (!record) {
1462
1276
  return /* @__PURE__ */ jsxs("div", { className: "lk-trial lk-trial--unknown", children: [
@@ -1520,16 +1334,17 @@ function TrialRuntime({
1520
1334
  suppress
1521
1335
  }) {
1522
1336
  const wheelSlot = useRef(null);
1337
+ const [pointer] = useState(createPointerStore);
1523
1338
  const canvasContainerRef = useRef(null);
1524
1339
  const loupeHostRef = useRef(null);
1525
- const updateTrialState = useStore(store, (s5) => s5.updateTrialState);
1526
- const updateTrialConfig = useStore(store, (s5) => s5.updateTrialConfig);
1527
- const updateTrialView = useStore(store, (s5) => s5.updateTrialView);
1528
- const updateTrialUndoStack = useStore(store, (s5) => s5.updateTrialUndoStack);
1529
- const updateTrialAnnotations = useStore(store, (s5) => s5.updateTrialAnnotations);
1530
- const labToolId = useStore(store, (s5) => s5.activeToolId);
1531
- const setLabTool = useStore(store, (s5) => s5.setLabTool);
1532
- const setTrialTool = useStore(store, (s5) => s5.setTrialTool);
1340
+ const updateTrialState = useStore(store, (s4) => s4.updateTrialState);
1341
+ const updateTrialConfig = useStore(store, (s4) => s4.updateTrialConfig);
1342
+ const updateTrialView = useStore(store, (s4) => s4.updateTrialView);
1343
+ const updateTrialUndoStack = useStore(store, (s4) => s4.updateTrialUndoStack);
1344
+ const updateTrialAnnotations = useStore(store, (s4) => s4.updateTrialAnnotations);
1345
+ const labToolId = useStore(store, (s4) => s4.activeToolId);
1346
+ const setLabTool = useStore(store, (s4) => s4.setLabTool);
1347
+ const setTrialTool = useStore(store, (s4) => s4.setTrialTool);
1533
1348
  const schema = useConfigSchema(instrument);
1534
1349
  const { config } = useResolvedConfig(schema, record.config, record.auto);
1535
1350
  const busRef = useRef(null);
@@ -1539,7 +1354,7 @@ function TrialRuntime({
1539
1354
  const [layerOrder, setLayerOrder] = useState(null);
1540
1355
  const [loupeOn, setLoupeOn] = useState(false);
1541
1356
  const visibleLayers = useMemo(
1542
- () => (instrument.canvas?.layers ?? []).filter((l9) => layerVisibility[l9.id] !== false).map((l9) => l9.id),
1357
+ () => (instrument.canvas?.layers ?? []).filter((l8) => layerVisibility[l8.id] !== false).map((l8) => l8.id),
1543
1358
  [instrument.canvas, layerVisibility]
1544
1359
  );
1545
1360
  const undoCap = instrument.undo;
@@ -1547,12 +1362,12 @@ function TrialRuntime({
1547
1362
  const maxDepth = undoCap?.maxDepth ?? 50;
1548
1363
  const snapshotIfNeeded = (event) => {
1549
1364
  if (!undoCap || !undoEvents.has(event)) return;
1550
- const current = store.getState().trials.find((w3) => w3.id === record.id);
1365
+ const current = store.getState().trials.find((w2) => w2.id === record.id);
1551
1366
  if (!current) return;
1552
1367
  const snap = structuredClone(current.state);
1553
1368
  updateTrialUndoStack(record.id, (prev) => pushSnapshot(prev, snap, maxDepth));
1554
1369
  };
1555
- const setView = (v2) => updateTrialView(record.id, v2);
1370
+ const setView = (v) => updateTrialView(record.id, v);
1556
1371
  const stage = instrument.canvas ? void 0 : instrument.stage;
1557
1372
  const placeView = (size) => {
1558
1373
  const declared = instrument.canvas?.initialView ?? (stage ? stage.initialView ?? ((vp) => fitStage(stage.size, vp)) : void 0);
@@ -1654,12 +1469,13 @@ function TrialRuntime({
1654
1469
  view: record.view,
1655
1470
  setView,
1656
1471
  zoom: view2d?.zoom ?? 1,
1657
- setZoom: (z3) => {
1472
+ setZoom: (z) => {
1658
1473
  if (!view2d) return;
1659
- updateTrialView(record.id, withZoom(view2d, z3));
1474
+ updateTrialView(record.id, withZoom(view2d, z));
1660
1475
  },
1661
1476
  activeToolId: resolvedToolId,
1662
- visibleLayers
1477
+ visibleLayers,
1478
+ pointer
1663
1479
  },
1664
1480
  emit: (event) => {
1665
1481
  snapshotIfNeeded(event);
@@ -1696,11 +1512,11 @@ function TrialRuntime({
1696
1512
  if (declared == null) return null;
1697
1513
  return resolveLoupe(typeof declared === "function" ? declared(config) : declared);
1698
1514
  }, [instrument.loupe, config]);
1699
- const loupeBindings = loupeCap ? { on: loupeOn, toggle: () => setLoupeOn((v2) => !v2) } : void 0;
1515
+ const loupeBindings = loupeCap ? { on: loupeOn, toggle: () => setLoupeOn((v) => !v) } : void 0;
1700
1516
  const canvasLayers = useMemo(() => {
1701
1517
  if (!instrument.canvas) return [];
1702
1518
  const baseLayers = instrument.canvas.layers;
1703
- const ordered = layerOrder ? [...baseLayers].sort((a4, b3) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b3.id)) : baseLayers;
1519
+ const ordered = layerOrder ? [...baseLayers].sort((a4, b2) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b2.id)) : baseLayers;
1704
1520
  return ordered.map((layer) => ({
1705
1521
  id: layer.id,
1706
1522
  visible: layerVisibility[layer.id] !== false,
@@ -1712,10 +1528,23 @@ function TrialRuntime({
1712
1528
  }, [instrument.canvas, record.state, config, layerVisibility, layerOrder]);
1713
1529
  const layerDescriptors = useMemo(() => {
1714
1530
  if (!instrument.layers) return [];
1715
- return instrument.layers.ids.map((l9) => typeof l9 === "string" ? { id: l9, label: l9 } : l9);
1531
+ return instrument.layers.ids.map((l8) => typeof l8 === "string" ? { id: l8, label: l8 } : l8);
1716
1532
  }, [instrument.layers]);
1533
+ const layerItems = useMemo(() => {
1534
+ const ordered = layerOrder ? [...layerDescriptors].sort((a4, b2) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b2.id)) : layerDescriptors;
1535
+ const pinnedLast = [
1536
+ ...ordered.filter((l8) => !l8.alwaysOn),
1537
+ ...ordered.filter((l8) => l8.alwaysOn)
1538
+ ];
1539
+ return pinnedLast.map((l8) => ({
1540
+ id: l8.id,
1541
+ label: l8.label,
1542
+ locked: l8.alwaysOn === true,
1543
+ visible: l8.alwaysOn === true || layerVisibility[l8.id] !== false
1544
+ }));
1545
+ }, [layerDescriptors, layerOrder, layerVisibility]);
1717
1546
  const dragDropResult = useDragDrop({
1718
- capability: instrument.dragDrop ?? { palette: [], onDrop: (_p, _i, s5) => s5 },
1547
+ capability: instrument.dragDrop ?? { palette: [], onDrop: (_p, _i, s4) => s4 },
1719
1548
  canvasContainerRef,
1720
1549
  view: view2d ?? DEFAULT_VIEW,
1721
1550
  worldSpec: instrument.canvas?.worldSpec,
@@ -1732,8 +1561,8 @@ function TrialRuntime({
1732
1561
  });
1733
1562
  const paletteItems = useMemo(() => {
1734
1563
  if (!instrument.dragDrop) return [];
1735
- const p2 = instrument.dragDrop.palette;
1736
- return typeof p2 === "function" ? p2(record.state, config) : p2;
1564
+ const p3 = instrument.dragDrop.palette;
1565
+ return typeof p3 === "function" ? p3(record.state, config) : p3;
1737
1566
  }, [instrument.dragDrop, record.state, config]);
1738
1567
  const layersWithFeedback = useMemo(() => {
1739
1568
  if (!dragDropResult.drag?.feedback) return canvasLayers;
@@ -1747,12 +1576,12 @@ function TrialRuntime({
1747
1576
  render: (ctx) => {
1748
1577
  const el = canvasContainerRef.current;
1749
1578
  if (!el) return;
1750
- const r9 = el.getBoundingClientRect();
1579
+ const r4 = el.getBoundingClientRect();
1751
1580
  ctx.save();
1752
1581
  ctx.strokeStyle = fb.ok ? "#3a7" : "#c44";
1753
1582
  ctx.lineWidth = 2;
1754
1583
  ctx.beginPath();
1755
- ctx.arc(screen.x - r9.left, screen.y - r9.top, 16, 0, Math.PI * 2);
1584
+ ctx.arc(screen.x - r4.left, screen.y - r4.top, 16, 0, Math.PI * 2);
1756
1585
  ctx.stroke();
1757
1586
  ctx.restore();
1758
1587
  }
@@ -1803,7 +1632,10 @@ function TrialRuntime({
1803
1632
  minZoom: stage.minZoom,
1804
1633
  maxZoom: stage.maxZoom,
1805
1634
  hostRef: loupeHostRef,
1806
- overlay: lens,
1635
+ overlay: /* @__PURE__ */ jsxs(Fragment, { children: [
1636
+ stage.overlay?.(renderCtx),
1637
+ lens
1638
+ ] }),
1807
1639
  children: instrument.render(renderCtx)
1808
1640
  }
1809
1641
  );
@@ -1822,21 +1654,20 @@ function TrialRuntime({
1822
1654
  );
1823
1655
  const layerListNode = useMemo(
1824
1656
  () => instrument.layers && layerDescriptors.length > 0 ? /* @__PURE__ */ jsx(
1825
- LayerList,
1657
+ D,
1826
1658
  {
1827
- layers: layerDescriptors,
1828
- visibility: layerVisibility,
1829
- onReorder: (next) => {
1830
- setLayerOrder(next.map((l9) => l9.id));
1659
+ items: layerItems,
1660
+ onReorder: (move) => {
1661
+ setLayerOrder(S2(layerItems, move).map((l8) => l8.id));
1831
1662
  bus.emit("layers.reorder");
1832
1663
  },
1833
- onToggle: (lid, visible) => {
1664
+ onVisibilityChange: (lid, visible) => {
1834
1665
  setLayerVisibility((prev) => ({ ...prev, [lid]: visible }));
1835
1666
  bus.emit("layers.toggle");
1836
1667
  }
1837
1668
  }
1838
1669
  ) : null,
1839
- [instrument.layers, layerDescriptors, layerVisibility, bus]
1670
+ [instrument.layers, layerDescriptors, layerItems, bus]
1840
1671
  );
1841
1672
  const extraChrome = useMemo(() => {
1842
1673
  const out = [];
@@ -1867,6 +1698,7 @@ function TrialRuntime({
1867
1698
  activeToolId: labTool
1868
1699
  }
1869
1700
  ) : null;
1701
+ const scopedBody = /* @__PURE__ */ jsx(WeaselProvider, { isolate: true, children: /* @__PURE__ */ jsx(PointerContextProvider, { store: pointer, children: /* @__PURE__ */ jsx(CameraScopeContext.Provider, { value: true, children: body }) }) });
1870
1702
  return /* @__PURE__ */ jsx(TrialIdProvider, { trialId: record.id, children: /* @__PURE__ */ jsx(AnnotationsContext.Provider, { value: annotationsCap ? annotations : null, children: /* @__PURE__ */ jsx(CameraWheelContext.Provider, { value: wheelSlot, children: /* @__PURE__ */ jsxs(
1871
1703
  TrialChrome,
1872
1704
  {
@@ -1883,7 +1715,7 @@ function TrialRuntime({
1883
1715
  activeToolId: resolvedToolId,
1884
1716
  setActiveTool,
1885
1717
  children: [
1886
- body,
1718
+ scopedBody,
1887
1719
  annotationOverlays
1888
1720
  ]
1889
1721
  }
@@ -1893,7 +1725,7 @@ function TrialRuntime({
1893
1725
  // src/trial/trialOps.ts
1894
1726
  var DEFAULT_VIEW2 = { zoom: 1, pan: { x: 0, y: 0 } };
1895
1727
  function findInstrument(instruments, name) {
1896
- const found = instruments.find((i3) => i3.name === name);
1728
+ const found = instruments.find((i4) => i4.name === name);
1897
1729
  if (!found) {
1898
1730
  throw new Error(`[labkit] Unknown instrument: "${name}"`);
1899
1731
  }
@@ -1949,7 +1781,7 @@ function addTrial(trials, instruments, instrumentName, options = {}) {
1949
1781
  return [...trials, record];
1950
1782
  }
1951
1783
  function cloneTrial(trials, id) {
1952
- const sourceIdx = trials.findIndex((w3) => w3.id === id);
1784
+ const sourceIdx = trials.findIndex((w2) => w2.id === id);
1953
1785
  const source = trials[sourceIdx];
1954
1786
  if (!source) return trials;
1955
1787
  const clone = {
@@ -1964,11 +1796,11 @@ function cloneTrial(trials, id) {
1964
1796
  }
1965
1797
  function closeTrial(trials, id) {
1966
1798
  if (trials.length <= 1) return trials;
1967
- const next = trials.filter((w3) => w3.id !== id);
1799
+ const next = trials.filter((w2) => w2.id !== id);
1968
1800
  return next.length === trials.length ? trials : next;
1969
1801
  }
1970
1802
  function resetTrial(trials, id, instruments) {
1971
- const idx = trials.findIndex((w3) => w3.id === id);
1803
+ const idx = trials.findIndex((w2) => w2.id === id);
1972
1804
  const current = trials[idx];
1973
1805
  if (!current) return trials;
1974
1806
  const instrument = findInstrument(instruments, current.instrumentName);
@@ -1986,7 +1818,7 @@ function resetTrial(trials, id, instruments) {
1986
1818
  return [...trials.slice(0, idx), reset, ...trials.slice(idx + 1)];
1987
1819
  }
1988
1820
  function swapTrial(trials, instruments, id, instrumentName, options = {}) {
1989
- const idx = trials.findIndex((w3) => w3.id === id);
1821
+ const idx = trials.findIndex((w2) => w2.id === id);
1990
1822
  const current = trials[idx];
1991
1823
  if (!current) return trials;
1992
1824
  const [record] = addTrial([], instruments, instrumentName, options);
@@ -1994,25 +1826,25 @@ function swapTrial(trials, instruments, id, instrumentName, options = {}) {
1994
1826
  return [...trials.slice(0, idx), record, ...trials.slice(idx + 1)];
1995
1827
  }
1996
1828
  function reorderTrials(trials, ids) {
1997
- const byId = new Map(trials.map((w3) => [w3.id, w3]));
1998
- const named = ids.map((id) => byId.get(id)).filter((w3) => w3 !== void 0);
1999
- const seen = new Set(named.map((w3) => w3.id));
2000
- const rest = trials.filter((w3) => !seen.has(w3.id));
1829
+ const byId = new Map(trials.map((w2) => [w2.id, w2]));
1830
+ const named = ids.map((id) => byId.get(id)).filter((w2) => w2 !== void 0);
1831
+ const seen = new Set(named.map((w2) => w2.id));
1832
+ const rest = trials.filter((w2) => !seen.has(w2.id));
2001
1833
  return [...named, ...rest];
2002
1834
  }
2003
1835
  function findOvershoot(bound, items, tolerance = 1) {
2004
1836
  let worst = null;
2005
1837
  for (const { item, edges } of items) {
2006
1838
  const y3 = edges.bottom - bound.bottom;
2007
- const x = edges.right - bound.right;
2008
- const by = Math.max(x, y3);
1839
+ const x2 = edges.right - bound.right;
1840
+ const by = Math.max(x2, y3);
2009
1841
  if (by <= tolerance) continue;
2010
- if (!worst || by > worst.by) worst = { item, by, axis: y3 >= x ? "y" : "x" };
1842
+ if (!worst || by > worst.by) worst = { item, by, axis: y3 >= x2 ? "y" : "x" };
2011
1843
  }
2012
1844
  return worst;
2013
1845
  }
2014
1846
  function tagAndClasses(el) {
2015
- return el.tagName.toLowerCase() + [...el.classList].map((c9) => `.${c9}`).join("");
1847
+ return el.tagName.toLowerCase() + [...el.classList].map((c6) => `.${c6}`).join("");
2016
1848
  }
2017
1849
  function describeElement(el) {
2018
1850
  if (el.classList.length > 0) return tagAndClasses(el);
@@ -2021,8 +1853,8 @@ function describeElement(el) {
2021
1853
  return up ? `${tagAndClasses(el)} in ${tagAndClasses(up)}` : tagAndClasses(el);
2022
1854
  }
2023
1855
  function edgesOf(el) {
2024
- const r9 = el.getBoundingClientRect();
2025
- return { top: r9.top, left: r9.left, bottom: r9.bottom, right: r9.right };
1856
+ const r4 = el.getBoundingClientRect();
1857
+ return { top: r4.top, left: r4.left, bottom: r4.bottom, right: r4.right };
2026
1858
  }
2027
1859
  function* candidates(root) {
2028
1860
  yield { item: root, edges: edgesOf(root) };
@@ -2033,24 +1865,24 @@ function overflows(el) {
2033
1865
  }
2034
1866
  function explainLabScroll(lab, shellBody) {
2035
1867
  if (overflows(shellBody)) {
2036
- const r10 = shellBody.getBoundingClientRect();
1868
+ const r5 = shellBody.getBoundingClientRect();
2037
1869
  const bound2 = {
2038
- top: r10.top,
2039
- left: r10.left,
2040
- bottom: r10.top + shellBody.clientHeight,
2041
- right: r10.left + shellBody.clientWidth
1870
+ top: r5.top,
1871
+ left: r5.left,
1872
+ bottom: r5.top + shellBody.clientHeight,
1873
+ right: r5.left + shellBody.clientWidth
2042
1874
  };
2043
1875
  const hit2 = findOvershoot(bound2, candidates(shellBody));
2044
1876
  return hit2 ? `.lk-shell-body scrolls: ${describeElement(hit2.item)} reaches ${Math.round(hit2.by)}px past it (${hit2.axis})` : ".lk-shell-body scrolls";
2045
1877
  }
2046
1878
  const doc = document.scrollingElement ?? document.documentElement;
2047
1879
  if (!overflows(doc)) return null;
2048
- const r9 = lab.getBoundingClientRect();
1880
+ const r4 = lab.getBoundingClientRect();
2049
1881
  const bound = {
2050
- top: r9.top,
2051
- left: r9.left,
2052
- bottom: r9.top + Math.min(r9.height, doc.clientHeight),
2053
- right: r9.left + Math.min(r9.width, doc.clientWidth)
1882
+ top: r4.top,
1883
+ left: r4.left,
1884
+ bottom: r4.top + Math.min(r4.height, doc.clientHeight),
1885
+ right: r4.left + Math.min(r4.width, doc.clientWidth)
2054
1886
  };
2055
1887
  const hit = findOvershoot(bound, candidates(lab));
2056
1888
  return hit ? `the page scrolls: ${describeElement(hit.item)} reaches ${Math.round(hit.by)}px past the lab's box (${hit.axis})` : null;
@@ -2080,16 +1912,6 @@ function useLabFitWarning(labBody) {
2080
1912
  };
2081
1913
  }, [labBody]);
2082
1914
  }
2083
- var MODES = [
2084
- { value: "auto", label: "Auto", glyph: /* @__PURE__ */ jsx(E, { size: 14 }) },
2085
- { value: "light", label: "Light", glyph: /* @__PURE__ */ jsx(w, { size: 14 }) },
2086
- { value: "dark", label: "Dark", glyph: /* @__PURE__ */ jsx(T, { size: 14 }) }
2087
- ];
2088
- var MODE_ITEMS = MODES.map(({ value, label, glyph }) => ({
2089
- value,
2090
- label: glyph,
2091
- ariaLabel: label
2092
- }));
2093
1915
  function LabHeader({ addTrial: addTrial2 = true }) {
2094
1916
  const lab = useLabContext();
2095
1917
  const only = lab.instruments.length === 1 ? lab.instruments[0] : null;
@@ -2101,30 +1923,26 @@ function LabHeader({ addTrial: addTrial2 = true }) {
2101
1923
  className: "lk-lab-header__add",
2102
1924
  onClick: () => lab.addTrial(only.name),
2103
1925
  children: [
2104
- /* @__PURE__ */ jsx(C, { size: 16 }),
1926
+ /* @__PURE__ */ jsx(G, { size: 16 }),
2105
1927
  /* @__PURE__ */ jsx("span", { children: "Add trial" })
2106
1928
  ]
2107
1929
  }
2108
1930
  ) : /* @__PURE__ */ jsx(
2109
- l7,
1931
+ d2,
2110
1932
  {
2111
1933
  "aria-label": "Add trial",
2112
1934
  label: "Add trial\u2026",
2113
- items: lab.instruments.map((i3) => ({ value: i3.name, label: i3.title ?? i3.name })),
1935
+ items: lab.instruments.map((i4) => ({ value: i4.name, label: i4.title ?? i4.name })),
2114
1936
  onAction: (name) => lab.addTrial(name)
2115
1937
  }
2116
1938
  ),
2117
1939
  /* @__PURE__ */ jsx(
2118
- r5,
1940
+ s3,
2119
1941
  {
2120
1942
  className: "lk-lab-header__mode",
2121
- ariaLabel: "Color mode",
2122
1943
  variant: "flat",
2123
- items: MODE_ITEMS,
2124
1944
  value: lab.mode,
2125
- onChange: (next) => {
2126
- if (next) lab.setMode(next);
2127
- }
1945
+ onChange: lab.setMode
2128
1946
  }
2129
1947
  )
2130
1948
  ] });
@@ -2132,42 +1950,39 @@ function LabHeader({ addTrial: addTrial2 = true }) {
2132
1950
  function LabPalette({ tools, contributions }) {
2133
1951
  const ctx = useLabChromeContext();
2134
1952
  const all = labContributions(tools, contributions);
2135
- return /* @__PURE__ */ jsx(PaletteRegion, { contributions: all.filter((c9) => c9.region === "palette"), ctx });
2136
- }
2137
- function query() {
2138
- if (typeof window === "undefined" || !window.matchMedia) return null;
2139
- return window.matchMedia("(prefers-color-scheme: light)");
2140
- }
2141
- function useResolvedMode(mode) {
2142
- const [system, setSystem] = useState(
2143
- () => query()?.matches ? "light" : "dark"
2144
- );
2145
- useEffect(() => {
2146
- if (mode !== "auto") return;
2147
- const mq = query();
2148
- if (!mq) return;
2149
- const onChange = (e) => setSystem(e.matches ? "light" : "dark");
2150
- mq.addEventListener("change", onChange);
2151
- return () => mq.removeEventListener("change", onChange);
2152
- }, [mode]);
2153
- return mode === "auto" ? system : mode;
1953
+ return /* @__PURE__ */ jsx(PaletteRegion, { contributions: all.filter((c6) => c6.region === "palette"), ctx });
2154
1954
  }
2155
1955
  function LabRoot({ children, mode = "auto", className }) {
2156
- const resolved = useResolvedMode(mode);
1956
+ const resolved = useResolvedColorMode(mode);
2157
1957
  const outer = useThemeOptional();
2158
1958
  const root = /* @__PURE__ */ jsx("div", { className: className ? `lk-root ${className}` : "lk-root", "data-wzl-portal-host": "", children });
2159
1959
  return outer ? root : /* @__PURE__ */ jsx(ThemeProvider, { theme: interstellarTheme, selection: { mode: resolved }, children: root });
2160
1960
  }
1961
+ function locate(url) {
1962
+ const hash = url.indexOf("#");
1963
+ const trim = (part) => part.replace(/\?.*$/, "").replace(/\/$/, "");
1964
+ return {
1965
+ doc: trim(hash < 0 ? url : url.slice(0, hash)).replace(/\.html$/, ""),
1966
+ route: hash < 0 ? "" : trim(url.slice(hash + 1))
1967
+ };
1968
+ }
2161
1969
  function currentPage(path, pages) {
2162
- const here = path.replace(/[?#].*$/, "").replace(/\/$/, "").replace(/\.html$/, "");
2163
- return pages.findIndex((p2) => here.endsWith(p2.href.replace(/\.html$/, "")));
1970
+ const here = locate(path);
1971
+ const onDoc = (doc) => here.doc.endsWith(doc);
1972
+ const routed = pages.findIndex((p3) => {
1973
+ if (!p3.href.includes("#")) return false;
1974
+ const page = locate(p3.href);
1975
+ return onDoc(page.doc) && (here.route === page.route || here.route.startsWith(`${page.route}/`));
1976
+ });
1977
+ if (routed >= 0) return routed;
1978
+ return pages.findIndex((p3) => !p3.href.includes("#") && onDoc(locate(p3.href).doc));
2164
1979
  }
2165
1980
  function LabSwitcher({ title, pages, path, className }) {
2166
1981
  const [open, setOpen] = useState(false);
2167
1982
  const root = useRef(null);
2168
1983
  const menuId = useId();
2169
1984
  const here = currentPage(
2170
- path ?? (typeof window === "undefined" ? "" : window.location.pathname),
1985
+ path ?? (typeof window === "undefined" ? "" : window.location.pathname + window.location.hash),
2171
1986
  pages
2172
1987
  );
2173
1988
  const close = useCallback(() => setOpen(false), []);
@@ -2208,13 +2023,13 @@ function LabSwitcher({ title, pages, path, className }) {
2208
2023
  ]
2209
2024
  }
2210
2025
  ) }),
2211
- open && /* @__PURE__ */ jsx("div", { className: "lk-switcher-menu", id: menuId, role: "menu", children: pages.map((page, i3) => /* @__PURE__ */ jsx(
2026
+ open && /* @__PURE__ */ jsx("div", { className: "lk-switcher-menu", id: menuId, role: "menu", children: pages.map((page, i4) => /* @__PURE__ */ jsx(
2212
2027
  "a",
2213
2028
  {
2214
2029
  href: page.href,
2215
2030
  role: "menuitem",
2216
2031
  className: "lk-switcher-item",
2217
- "aria-current": i3 === here ? "page" : void 0,
2032
+ "aria-current": i4 === here ? "page" : void 0,
2218
2033
  onClick: close,
2219
2034
  children: page.label
2220
2035
  },
@@ -2229,8 +2044,17 @@ function LabShell({
2229
2044
  footer,
2230
2045
  mode = "auto",
2231
2046
  pages,
2232
- path
2047
+ path,
2048
+ documentTitle
2233
2049
  }) {
2050
+ useEffect(() => {
2051
+ if (documentTitle === void 0) return;
2052
+ const previous = document.title;
2053
+ document.title = documentTitle;
2054
+ return () => {
2055
+ document.title = previous;
2056
+ };
2057
+ }, [documentTitle]);
2234
2058
  return /* @__PURE__ */ jsxs(LabRoot, { mode, className: "lk-shell", children: [
2235
2059
  /* @__PURE__ */ jsxs("header", { className: "lk-shell-header", children: [
2236
2060
  pages && pages.length > 0 ? /* @__PURE__ */ jsx(LabSwitcher, { title, pages, path, className: "lk-shell-title" }) : /* @__PURE__ */ jsx("h1", { className: "lk-shell-title", children: title }),
@@ -2246,11 +2070,11 @@ var FLOAT_ZONE_ID = asNodeId("lk-workspace-floating");
2246
2070
  var PANEL_KIND = "panel";
2247
2071
  var KIND = "trial";
2248
2072
  function extentOf(store, id) {
2249
- const p2 = store.getNode(id)?.membership?.placement;
2250
- if (!p2) return null;
2073
+ const p3 = store.getNode(id)?.membership?.placement;
2074
+ if (!p3) return null;
2251
2075
  const out = {};
2252
- if (p2.size) out.size = p2.size;
2253
- if (p2.span) out.span = p2.span;
2076
+ if (p3.size) out.size = p3.size;
2077
+ if (p3.span) out.span = p3.span;
2254
2078
  return Object.keys(out).length > 0 ? out : null;
2255
2079
  }
2256
2080
  function PanelFrame({ panel, floating = false }) {
@@ -2271,11 +2095,11 @@ function Workspace({
2271
2095
  viewport
2272
2096
  }) {
2273
2097
  const items = Children.toArray(children);
2274
- const tilePanels = useMemo(() => (panels ?? []).filter((p2) => p2.as === "tile"), [panels]);
2275
- const floatPanels = useMemo(() => (panels ?? []).filter((p2) => p2.as === "floating"), [panels]);
2098
+ const tilePanels = useMemo(() => (panels ?? []).filter((p3) => p3.as === "tile"), [panels]);
2099
+ const floatPanels = useMemo(() => (panels ?? []).filter((p3) => p3.as === "floating"), [panels]);
2276
2100
  const wantedIds = [
2277
- ...items.map((_, i3) => ids?.[i3] ?? `lk-ws-${i3}`),
2278
- ...tilePanels.map((p2) => `lk-panel-${p2.key}`)
2101
+ ...items.map((_2, i4) => ids?.[i4] ?? `lk-ws-${i4}`),
2102
+ ...tilePanels.map((p3) => `lk-panel-${p3.key}`)
2279
2103
  ];
2280
2104
  const idKey = wantedIds.join(",");
2281
2105
  const idKeyRef = useRef(null);
@@ -2350,9 +2174,9 @@ function Workspace({
2350
2174
  [onReorder]
2351
2175
  );
2352
2176
  const chrome = useMemo(() => {
2353
- const byId = new Map(nodeIds.map((id, i3) => [id, items[i3]]));
2177
+ const byId = new Map(nodeIds.map((id, i4) => [id, items[i4]]));
2354
2178
  const panelByNode = new Map(
2355
- tilePanels.map((p2) => [`lk-panel-${p2.key}`, p2])
2179
+ tilePanels.map((p3) => [`lk-panel-${p3.key}`, p3])
2356
2180
  );
2357
2181
  return {
2358
2182
  [PANEL_KIND]: ({ node }) => {
@@ -2370,7 +2194,7 @@ function Workspace({
2370
2194
  }
2371
2195
  };
2372
2196
  }, [nodeIds, items, reorderable, tilePanels]);
2373
- const floatingLayer = floatPanels.length === 0 ? null : /* @__PURE__ */ jsx("div", { className: "lk-workspace__floating", children: floatPanels.map((p2) => /* @__PURE__ */ jsx(PanelFrame, { panel: p2, floating: true }, p2.key)) });
2197
+ const floatingLayer = floatPanels.length === 0 ? null : /* @__PURE__ */ jsx("div", { className: "lk-workspace__floating", children: floatPanels.map((p3) => /* @__PURE__ */ jsx(PanelFrame, { panel: p3, floating: true }, p3.key)) });
2374
2198
  const grid = /* @__PURE__ */ jsx(
2375
2199
  Container,
2376
2200
  {
@@ -2416,7 +2240,7 @@ async function openStoredLab({ instruments, defaultInstrument, mode }, storageKe
2416
2240
  const marks = /* @__PURE__ */ new Map();
2417
2241
  await Promise.all(
2418
2242
  opened.store.getState().trials.map(async (trial) => {
2419
- const kept = instruments.find((i3) => i3.name === trial.instrumentName)?.annotations?.storage;
2243
+ const kept = instruments.find((i4) => i4.name === trial.instrumentName)?.annotations?.storage;
2420
2244
  if (!kept) return;
2421
2245
  try {
2422
2246
  marks.set(trial.id, await kept.load());
@@ -2432,14 +2256,15 @@ function LabFallback({
2432
2256
  title,
2433
2257
  mode,
2434
2258
  density,
2259
+ theme = interstellarTheme,
2435
2260
  pages,
2436
2261
  path
2437
2262
  }) {
2438
- const resolvedMode = useResolvedMode(mode ?? "auto");
2263
+ const resolvedMode = useResolvedColorMode(mode ?? "auto");
2439
2264
  return /* @__PURE__ */ jsx(
2440
2265
  ThemeProvider,
2441
2266
  {
2442
- theme: interstellarTheme,
2267
+ theme,
2443
2268
  selection: { mode: resolvedMode, density: density ?? "comfortable" },
2444
2269
  className: "lk-lab",
2445
2270
  children: /* @__PURE__ */ jsx(
@@ -2462,10 +2287,13 @@ var NEBULA_SLOTS = [
2462
2287
  { cx: "12%", cy: "82%", sx: "50%", sy: "70%", stop: "70%" },
2463
2288
  { cx: "85%", cy: "18%", sx: "55%", sy: "80%", stop: "70%" }
2464
2289
  ];
2465
- function buildNebula(colors) {
2466
- const blobs = colors.map((c9, i3) => {
2467
- const p2 = NEBULA_SLOTS[i3 % NEBULA_SLOTS.length];
2468
- return `radial-gradient(ellipse ${p2.sx} ${p2.sy} at ${p2.cx} ${p2.cy}, color-mix(in srgb, ${c9} 22%, transparent), transparent ${p2.stop})`;
2290
+ function buildNebula(list, theme, mode, density) {
2291
+ const ctx = { theme, resolved: resolveTheme(theme, { mode, density }) };
2292
+ const n5 = colorCount(list, ctx) ?? NEBULA_SLOTS.length;
2293
+ const colors = Array.from({ length: n5 }, (_2, i4) => colorAt(list, i4, ctx));
2294
+ const blobs = colors.map((c6, i4) => {
2295
+ const p3 = NEBULA_SLOTS[i4 % NEBULA_SLOTS.length];
2296
+ return `radial-gradient(ellipse ${p3.sx} ${p3.sy} at ${p3.cx} ${p3.cy}, color-mix(in srgb, ${c6} 22%, transparent), transparent ${p3.stop})`;
2469
2297
  });
2470
2298
  blobs.push("radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)");
2471
2299
  return blobs.join(", ");
@@ -2485,7 +2313,7 @@ function LabPanes({
2485
2313
  void 0,
2486
2314
  { scope: "lab" }
2487
2315
  );
2488
- const main = contributions.some((c9) => c9.region === "aside") ? /* @__PURE__ */ jsx(
2316
+ const main = contributions.some((c6) => c6.region === "aside") ? /* @__PURE__ */ jsx(
2489
2317
  Split,
2490
2318
  {
2491
2319
  className: "lk-lab__panes",
@@ -2495,15 +2323,15 @@ function LabPanes({
2495
2323
  label: "Lab aside",
2496
2324
  defaultWidth: 320,
2497
2325
  width: asideWidth,
2498
- onWidthChange: (w3) => {
2499
- setAsideWidth(w3);
2326
+ onWidthChange: (w2) => {
2327
+ setAsideWidth(w2);
2500
2328
  surface?.invalidateRects();
2501
2329
  },
2502
2330
  sidebar: /* @__PURE__ */ jsx(LabAsideRegion, { contributions }),
2503
2331
  children
2504
2332
  }
2505
2333
  ) : children;
2506
- if (!contributions.some((c9) => c9.region === "sidebar")) return main;
2334
+ if (!contributions.some((c6) => c6.region === "sidebar")) return main;
2507
2335
  return /* @__PURE__ */ jsx(
2508
2336
  Split,
2509
2337
  {
@@ -2513,8 +2341,8 @@ function LabPanes({
2513
2341
  label: "Lab sidebar",
2514
2342
  defaultWidth: 260,
2515
2343
  width: sidebarWidth,
2516
- onWidthChange: (w3) => {
2517
- setSidebarWidth(w3);
2344
+ onWidthChange: (w2) => {
2345
+ setSidebarWidth(w2);
2518
2346
  surface?.invalidateRects();
2519
2347
  },
2520
2348
  sidebar: /* @__PURE__ */ jsx(LabSidebarRegion, { contributions }),
@@ -2539,6 +2367,7 @@ function Lab(props) {
2539
2367
  title: props.title,
2540
2368
  mode: props.mode,
2541
2369
  density: props.density,
2370
+ ...props.theme ? { theme: props.theme } : {},
2542
2371
  pages: props.pages,
2543
2372
  path: props.path
2544
2373
  }
@@ -2550,6 +2379,7 @@ function LabRuntime({
2550
2379
  instruments,
2551
2380
  mode,
2552
2381
  density,
2382
+ theme = interstellarTheme,
2553
2383
  nebula,
2554
2384
  title,
2555
2385
  pages,
@@ -2569,13 +2399,13 @@ function LabRuntime({
2569
2399
  useLayoutEffect(() => {
2570
2400
  store.getState().setInstruments(instruments);
2571
2401
  }, [instruments, store]);
2572
- const trials = useStore(store, (s5) => s5.trials);
2402
+ const trials = useStore(store, (s4) => s4.trials);
2573
2403
  const [focusPick, setFocusPick] = useState(null);
2574
2404
  const focusedTrialId = trials.some((t) => t.id === focusPick) ? focusPick : trials[0]?.id ?? null;
2575
- const savedSnapshots = useStore(store, (s5) => s5.savedSnapshots);
2576
- const modeValue = useStore(store, (s5) => s5.mode);
2577
- const layout = useStore(store, (s5) => s5.layout);
2578
- const undockedPanels = useStore(store, (s5) => s5.undockedPanels);
2405
+ const savedSnapshots = useStore(store, (s4) => s4.savedSnapshots);
2406
+ const modeValue = useStore(store, (s4) => s4.mode);
2407
+ const layout = useStore(store, (s4) => s4.layout);
2408
+ const undockedPanels = useStore(store, (s4) => s4.undockedPanels);
2579
2409
  const panelHostsRef = useRef(null);
2580
2410
  if (panelHostsRef.current === null) panelHostsRef.current = createPanelHostRegistry();
2581
2411
  const outerSurface = useSurfaceOptional();
@@ -2588,17 +2418,17 @@ function LabRuntime({
2588
2418
  const bufferRef = useRef({ w: 0, h: 0 });
2589
2419
  const surfaceRef = useRef(null);
2590
2420
  const onFrame = useCallback((frame) => {
2591
- const canvases = [ownUnderRef.current, ownOverRef.current].filter((c9) => c9 !== null);
2421
+ const canvases = [ownUnderRef.current, ownOverRef.current].filter((c6) => c6 !== null);
2592
2422
  if (canvases.length === 0) return;
2593
- const w3 = Math.round(frame.size.width * frame.dpr);
2594
- const h2 = Math.round(frame.size.height * frame.dpr);
2595
- if (bufferRef.current.w !== w3 || bufferRef.current.h !== h2) {
2596
- bufferRef.current = { w: w3, h: h2 };
2597
- for (const c9 of canvases) {
2598
- c9.width = w3;
2599
- c9.height = h2;
2600
- c9.style.width = `${frame.size.width}px`;
2601
- c9.style.height = `${frame.size.height}px`;
2423
+ const w2 = Math.round(frame.size.width * frame.dpr);
2424
+ const h = Math.round(frame.size.height * frame.dpr);
2425
+ if (bufferRef.current.w !== w2 || bufferRef.current.h !== h) {
2426
+ bufferRef.current = { w: w2, h };
2427
+ for (const c6 of canvases) {
2428
+ c6.width = w2;
2429
+ c6.height = h;
2430
+ c6.style.width = `${frame.size.width}px`;
2431
+ c6.style.height = `${frame.size.height}px`;
2602
2432
  }
2603
2433
  surfaceRef.current?.invalidateAll();
2604
2434
  return;
@@ -2656,14 +2486,14 @@ function LabRuntime({
2656
2486
  })),
2657
2487
  [undockedPanels]
2658
2488
  );
2659
- const resolvedMode = useResolvedMode(modeValue);
2660
- const annotates = instruments.some((i3) => i3.annotations != null);
2489
+ const resolvedMode = useResolvedColorMode(modeValue);
2490
+ const annotationTools = useMemo(() => labAnnotationTools(instruments), [instruments]);
2661
2491
  const labChromeAll = useMemo(
2662
- () => labContributions([...annotates ? ANNOTATION_TOOLS : [], ...tools ?? []], labChrome),
2663
- [annotates, tools, labChrome]
2492
+ () => labContributions([...annotationTools, ...tools ?? []], labChrome),
2493
+ [annotationTools, tools, labChrome]
2664
2494
  );
2665
- const hasFooterChrome = labChromeAll.some((c9) => c9.region === "footer");
2666
- const hasPaneChrome = labChromeAll.some((c9) => c9.region === "sidebar" || c9.region === "aside");
2495
+ const hasFooterChrome = labChromeAll.some((c6) => c6.region === "footer");
2496
+ const hasPaneChrome = labChromeAll.some((c6) => c6.region === "sidebar" || c6.region === "aside");
2667
2497
  useEffect(() => {
2668
2498
  if (mode && mode !== store.getState().mode) {
2669
2499
  store.getState().setMode(mode);
@@ -2671,14 +2501,14 @@ function LabRuntime({
2671
2501
  }, [mode, store]);
2672
2502
  const contextValue = useMemo(() => {
2673
2503
  const replaceTrials = (next) => {
2674
- const currentById = new Map(store.getState().trials.map((w3) => [w3.id, w3]));
2675
- const merged = next.map((w3) => currentById.get(w3.id) ?? w3);
2504
+ const currentById = new Map(store.getState().trials.map((w2) => [w2.id, w2]));
2505
+ const merged = next.map((w2) => currentById.get(w2.id) ?? w2);
2676
2506
  store.setState({ trials: merged });
2677
2507
  };
2678
2508
  const replaceAndFocusAdded = (next) => {
2679
- const before = new Set(store.getState().trials.map((w3) => w3.id));
2509
+ const before = new Set(store.getState().trials.map((w2) => w2.id));
2680
2510
  replaceTrials(next);
2681
- const added = next.find((w3) => !before.has(w3.id));
2511
+ const added = next.find((w2) => !before.has(w2.id));
2682
2512
  if (added) setFocusPick(added.id);
2683
2513
  };
2684
2514
  return {
@@ -2703,7 +2533,7 @@ function LabRuntime({
2703
2533
  const current = store.getState();
2704
2534
  const next = swapTrial(current.trials, instruments, id, instrumentName, options);
2705
2535
  if (next === current.trials) return;
2706
- const record = next[current.trials.findIndex((w3) => w3.id === id)];
2536
+ const record = next[current.trials.findIndex((w2) => w2.id === id)];
2707
2537
  const { [id]: extent, ...layoutRest } = current.layout;
2708
2538
  if (extent) current.setLayout({ ...layoutRest, [record.id]: extent });
2709
2539
  replaceTrials(next);
@@ -2713,17 +2543,17 @@ function LabRuntime({
2713
2543
  focusTrial: (id) => setFocusPick(id),
2714
2544
  resetTrial: (id) => {
2715
2545
  const next = resetTrial(store.getState().trials, id, instruments);
2716
- const record = next.find((w3) => w3.id === id);
2546
+ const record = next.find((w2) => w2.id === id);
2717
2547
  if (!record) return;
2718
- store.setState((s5) => ({
2719
- trials: s5.trials.map(
2720
- (w3) => w3.id === id ? { ...w3, config: record.config, state: record.state, view: record.view } : w3
2548
+ store.setState((s4) => ({
2549
+ trials: s4.trials.map(
2550
+ (w2) => w2.id === id ? { ...w2, config: record.config, state: record.state, view: record.view } : w2
2721
2551
  )
2722
2552
  }));
2723
2553
  },
2724
2554
  savedSnapshots,
2725
2555
  saveSnapshot: (trialId, name) => {
2726
- const taken = store.getState().savedSnapshots.filter((s5) => s5.trialId === trialId).length;
2556
+ const taken = store.getState().savedSnapshots.filter((s4) => s4.trialId === trialId).length;
2727
2557
  store.getState().saveSnapshot(trialId, name ?? `Snapshot ${taken + 1}`);
2728
2558
  },
2729
2559
  loadSnapshot: (trialId, snapshotId) => {
@@ -2749,24 +2579,31 @@ function LabRuntime({
2749
2579
  configRules,
2750
2580
  controls
2751
2581
  ]);
2752
- const backdropStyle = resolvedMode === "dark" && nebula && nebula.length > 0 ? { ["--wzl-backdrop"]: buildNebula(nebula) } : void 0;
2582
+ const backdropStyle = resolvedMode === "dark" && nebula && colorCount(nebula) !== 0 ? {
2583
+ ["--wzl-backdrop"]: buildNebula(
2584
+ nebula,
2585
+ theme,
2586
+ resolvedMode,
2587
+ density ?? "comfortable"
2588
+ )
2589
+ } : void 0;
2753
2590
  const workspace = /* @__PURE__ */ jsx(
2754
2591
  Workspace,
2755
2592
  {
2756
2593
  panels: workspacePanels,
2757
- ids: trials.map((w3) => w3.id),
2594
+ ids: trials.map((w2) => w2.id),
2758
2595
  resizable: true,
2759
2596
  reorderable: true,
2760
2597
  onReorder: (ids) => contextValue.reorderTrials(ids),
2761
2598
  layout,
2762
2599
  onLayoutChange: (next) => store.getState().setLayout(next),
2763
- children: trials.map((w3) => /* @__PURE__ */ jsx(Trial, { id: w3.id, chrome, suppress }, w3.id))
2600
+ children: trials.map((w2) => /* @__PURE__ */ jsx(Trial, { id: w2.id, chrome, suppress }, w2.id))
2764
2601
  }
2765
2602
  );
2766
2603
  return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: { store }, children: /* @__PURE__ */ jsx(PersistenceContext.Provider, { value: opened.records, children: /* @__PURE__ */ jsx(AnnotationPreloadContext.Provider, { value: opened.marks, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
2767
2604
  ThemeProvider,
2768
2605
  {
2769
- theme: interstellarTheme,
2606
+ theme,
2770
2607
  selection: { mode: resolvedMode, density: density ?? "comfortable" },
2771
2608
  className: "lk-lab",
2772
2609
  style: backdropStyle,
@@ -2829,6 +2666,9 @@ function LabRuntime({
2829
2666
  }
2830
2667
  ) }) }) }) });
2831
2668
  }
2669
+ function LabBoundary({ children }) {
2670
+ return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: null, children: /* @__PURE__ */ jsx(PersistenceContext.Provider, { value: null, children: /* @__PURE__ */ jsx(AnnotationPreloadContext.Provider, { value: null, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: null, children: /* @__PURE__ */ jsx(PanelHostContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SurfaceCanvasContext.Provider, { value: { over: null, under: null }, children: /* @__PURE__ */ jsx(TrialIdContext.Provider, { value: null, children: /* @__PURE__ */ jsx(AnnotationsContext.Provider, { value: null, children: /* @__PURE__ */ jsx(CameraWheelContext.Provider, { value: null, children: /* @__PURE__ */ jsx(CanvasStackContext.Provider, { value: null, children: /* @__PURE__ */ jsx(TrialDragContext.Provider, { value: null, children: /* @__PURE__ */ jsx(ThemeContext.Provider, { value: null, children }) }) }) }) }) }) }) }) }) }) }) }) });
2671
+ }
2832
2672
  var SPECIMEN_SECTIONS = [
2833
2673
  "Buttons & toggles",
2834
2674
  "Fields & pickers",
@@ -2922,32 +2762,32 @@ function ButtonsAndToggles() {
2922
2762
  const [open, setOpen] = useState(true);
2923
2763
  return /* @__PURE__ */ jsxs(Section, { title: "Buttons & toggles", children: [
2924
2764
  /* @__PURE__ */ jsx(Cell, { label: "Button", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2925
- /* @__PURE__ */ jsx(a5, { variant: "primary", children: "Save" }),
2926
- /* @__PURE__ */ jsx(a5, { variant: "secondary", children: "Cancel" }),
2927
- /* @__PURE__ */ jsx(a5, { variant: "ghost", children: "Ghost" }),
2928
- /* @__PURE__ */ jsx(a5, { variant: "secondary", disabled: true, children: "Disabled" }),
2929
- /* @__PURE__ */ jsx(a5, { variant: "secondary", iconOnly: true, ariaLabel: "Add", children: /* @__PURE__ */ jsx(Dot, {}) })
2765
+ /* @__PURE__ */ jsx(c, { variant: "primary", children: "Save" }),
2766
+ /* @__PURE__ */ jsx(c, { variant: "secondary", children: "Cancel" }),
2767
+ /* @__PURE__ */ jsx(c, { variant: "ghost", children: "Ghost" }),
2768
+ /* @__PURE__ */ jsx(c, { variant: "secondary", disabled: true, children: "Disabled" }),
2769
+ /* @__PURE__ */ jsx(c, { variant: "secondary", iconOnly: true, ariaLabel: "Add", children: /* @__PURE__ */ jsx(Dot, {}) })
2930
2770
  ] }) }),
2931
2771
  /* @__PURE__ */ jsx(Cell, { label: "Badge", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2932
- /* @__PURE__ */ jsx(Lt, { shape: "pill", tone: "accent", variant: "outline", size: "sm", children: "ACCENT" }),
2933
- /* @__PURE__ */ jsx(Lt, { tone: "info", variant: "subtle", children: "INFO" }),
2934
- /* @__PURE__ */ jsx(Lt, { tone: "warn", variant: "solid", children: "WARN" }),
2935
- /* @__PURE__ */ jsx(Lt, { tone: "danger", variant: "solid", children: "DANGER" }),
2936
- /* @__PURE__ */ jsx(Lt, { tone: "muted", children: "MUTED" })
2772
+ /* @__PURE__ */ jsx(Ht, { shape: "pill", status: "accent", variant: "outline", size: "sm", children: "ACCENT" }),
2773
+ /* @__PURE__ */ jsx(Ht, { status: "info", variant: "subtle", children: "INFO" }),
2774
+ /* @__PURE__ */ jsx(Ht, { status: "warn", variant: "solid", children: "WARN" }),
2775
+ /* @__PURE__ */ jsx(Ht, { status: "danger", variant: "solid", children: "DANGER" }),
2776
+ /* @__PURE__ */ jsx(Ht, { status: "muted", children: "MUTED" })
2937
2777
  ] }) }),
2938
2778
  /* @__PURE__ */ jsx(Cell, { label: "Checkbox, Switch", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2939
- /* @__PURE__ */ jsx(o2, { isSelected: snap, onChange: setSnap, children: "Snap to grid" }),
2940
- /* @__PURE__ */ jsx(o2, { isIndeterminate: true, children: "Mixed" }),
2941
- /* @__PURE__ */ jsx(a3, { isSelected: wifi, onChange: setWifi, children: "Wifi" })
2779
+ /* @__PURE__ */ jsx(o3, { isSelected: snap, onChange: setSnap, children: "Snap to grid" }),
2780
+ /* @__PURE__ */ jsx(o3, { isIndeterminate: true, children: "Mixed" }),
2781
+ /* @__PURE__ */ jsx(a6, { isSelected: wifi, onChange: setWifi, children: "Wifi" })
2942
2782
  ] }) }),
2943
- /* @__PURE__ */ jsx(Cell, { label: "RadioGroup", children: /* @__PURE__ */ jsxs(l3, { label: "Snap mode", orientation: "horizontal", defaultValue: "grid", children: [
2944
- /* @__PURE__ */ jsx(u3, { value: "off", children: "Off" }),
2945
- /* @__PURE__ */ jsx(u3, { value: "grid", children: "Grid" }),
2946
- /* @__PURE__ */ jsx(u3, { value: "pixel", children: "Pixel" })
2783
+ /* @__PURE__ */ jsx(Cell, { label: "RadioGroup", children: /* @__PURE__ */ jsxs(l5, { label: "Snap mode", orientation: "horizontal", defaultValue: "grid", children: [
2784
+ /* @__PURE__ */ jsx(u5, { value: "off", children: "Off" }),
2785
+ /* @__PURE__ */ jsx(u5, { value: "grid", children: "Grid" }),
2786
+ /* @__PURE__ */ jsx(u5, { value: "pixel", children: "Pixel" })
2947
2787
  ] }) }),
2948
2788
  /* @__PURE__ */ jsxs(Cell, { label: "ToggleBar", children: [
2949
2789
  /* @__PURE__ */ jsx(
2950
- r5,
2790
+ a5,
2951
2791
  {
2952
2792
  ariaLabel: "Align",
2953
2793
  value: align,
@@ -2960,7 +2800,7 @@ function ButtonsAndToggles() {
2960
2800
  }
2961
2801
  ),
2962
2802
  /* @__PURE__ */ jsx(
2963
- r5,
2803
+ a5,
2964
2804
  {
2965
2805
  ariaLabel: "Align, flat",
2966
2806
  variant: "flat",
@@ -2974,9 +2814,9 @@ function ButtonsAndToggles() {
2974
2814
  }
2975
2815
  )
2976
2816
  ] }),
2977
- /* @__PURE__ */ jsx(Cell, { label: "OptionsBar, ActionsBar", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2817
+ /* @__PURE__ */ jsx(Cell, { label: "OptionsBar, ButtonBar", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2978
2818
  /* @__PURE__ */ jsx(
2979
- r7,
2819
+ r3,
2980
2820
  {
2981
2821
  ariaLabel: "Text style",
2982
2822
  items: [
@@ -2986,7 +2826,7 @@ function ButtonsAndToggles() {
2986
2826
  }
2987
2827
  ),
2988
2828
  /* @__PURE__ */ jsx(
2989
- r8,
2829
+ a7,
2990
2830
  {
2991
2831
  items: [
2992
2832
  { value: "undo", label: "Undo", onAction: () => {
@@ -2999,7 +2839,7 @@ function ButtonsAndToggles() {
2999
2839
  ] }) }),
3000
2840
  /* @__PURE__ */ jsx(Cell, { label: "MenuButton, Disclosure", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
3001
2841
  /* @__PURE__ */ jsx(
3002
- l7,
2842
+ d2,
3003
2843
  {
3004
2844
  label: "Add trial\u2026",
3005
2845
  onAction: () => {
@@ -3010,24 +2850,22 @@ function ButtonsAndToggles() {
3010
2850
  ]
3011
2851
  }
3012
2852
  ),
3013
- /* @__PURE__ */ jsx(r6, { open, onToggle: () => setOpen((o5) => !o5), label: "Shapes" }),
3014
- /* @__PURE__ */ jsx(r6, { open: false, onToggle: () => {
3015
- }, label: "Down", direction: "down" })
2853
+ /* @__PURE__ */ jsx(i2, { open, onToggle: () => setOpen((o4) => !o4), label: "Shapes" })
3016
2854
  ] }) }),
3017
2855
  /* @__PURE__ */ jsx(Cell, { label: "Tabs", children: /* @__PURE__ */ jsxs(o5, { children: [
3018
- /* @__PURE__ */ jsxs(s5, { "aria-label": "Sections", children: [
3019
- /* @__PURE__ */ jsx(c7, { id: "props", children: "Props" }),
3020
- /* @__PURE__ */ jsx(c7, { id: "events", children: "Events" }),
3021
- /* @__PURE__ */ jsx(c7, { id: "snapshot", children: "Snapshot" })
2856
+ /* @__PURE__ */ jsxs(s6, { "aria-label": "Sections", children: [
2857
+ /* @__PURE__ */ jsx(c5, { id: "props", children: "Props" }),
2858
+ /* @__PURE__ */ jsx(c5, { id: "events", children: "Events" }),
2859
+ /* @__PURE__ */ jsx(c5, { id: "snapshot", children: "Snapshot" })
3022
2860
  ] }),
3023
- /* @__PURE__ */ jsx(l6, { id: "props", children: "Props panel." }),
3024
- /* @__PURE__ */ jsx(l6, { id: "events", children: "Events panel." }),
3025
- /* @__PURE__ */ jsx(l6, { id: "snapshot", children: "Snapshot panel." })
2861
+ /* @__PURE__ */ jsx(l7, { id: "props", children: "Props panel." }),
2862
+ /* @__PURE__ */ jsx(l7, { id: "events", children: "Events panel." }),
2863
+ /* @__PURE__ */ jsx(l7, { id: "snapshot", children: "Snapshot panel." })
3026
2864
  ] }) }),
3027
2865
  /* @__PURE__ */ jsx(Cell, { label: "Keycaps", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
3028
- /* @__PURE__ */ jsx(c3, { keys: [{ label: "\u2318" }, { label: "\u21E7" }, { label: "K" }], separator: "+" }),
3029
- /* @__PURE__ */ jsx(s3, { label: "K" }),
3030
- /* @__PURE__ */ jsx(s3, { label: "\u2325", variant: "minimal" })
2866
+ /* @__PURE__ */ jsx(p, { keys: [{ label: "\u2318" }, { label: "\u21E7" }, { label: "K" }], separator: "+" }),
2867
+ /* @__PURE__ */ jsx(f2, { label: "K" }),
2868
+ /* @__PURE__ */ jsx(f2, { label: "\u2325", variant: "minimal" })
3031
2869
  ] }) })
3032
2870
  ] });
3033
2871
  }
@@ -3048,9 +2886,9 @@ function FieldsAndPickers() {
3048
2886
  const [paint, setPaint] = useState({ fill: "solid", color: "#b08adb" });
3049
2887
  return /* @__PURE__ */ jsxs(Section, { title: "Fields & pickers", children: [
3050
2888
  /* @__PURE__ */ jsxs(Cell, { label: "Input", children: [
3051
- /* @__PURE__ */ jsx(u2, { label: "Name", placeholder: "e.g. Pico" }),
2889
+ /* @__PURE__ */ jsx(u4, { label: "Name", placeholder: "e.g. Pico" }),
3052
2890
  /* @__PURE__ */ jsx(
3053
- u2,
2891
+ u4,
3054
2892
  {
3055
2893
  label: "Size",
3056
2894
  leadingAdornment: /* @__PURE__ */ jsx("span", { children: "W" }),
@@ -3058,12 +2896,12 @@ function FieldsAndPickers() {
3058
2896
  defaultValue: "120"
3059
2897
  }
3060
2898
  ),
3061
- /* @__PURE__ */ jsx(u2, { label: "Required", isInvalid: true, errorMessage: "Name is required." })
2899
+ /* @__PURE__ */ jsx(u4, { label: "Required", isInvalid: true, errorMessage: "Name is required." })
3062
2900
  ] }),
3063
2901
  /* @__PURE__ */ jsxs(Cell, { label: "NumberField, Select, ComboBox", children: [
3064
2902
  /* @__PURE__ */ jsx(g, { label: "Opacity", minValue: 0, maxValue: 100, step: 5, defaultValue: 80 }),
3065
2903
  /* @__PURE__ */ jsx(
3066
- b2,
2904
+ T,
3067
2905
  {
3068
2906
  label: "Color",
3069
2907
  defaultSelectedKey: "g",
@@ -3087,19 +2925,19 @@ function FieldsAndPickers() {
3087
2925
  )
3088
2926
  ] }),
3089
2927
  /* @__PURE__ */ jsxs(Cell, { label: "RangeSlider, Slider", children: [
3090
- /* @__PURE__ */ jsx(l4, { label: "Range", defaultValue: [20, 80], minValue: 0, maxValue: 100 }),
2928
+ /* @__PURE__ */ jsx(l8, { label: "Range", defaultValue: [20, 80], minValue: 0, maxValue: 100 }),
3091
2929
  /* @__PURE__ */ jsx(
3092
- l4,
2930
+ l8,
3093
2931
  {
3094
2932
  label: "Opacity",
3095
2933
  defaultValue: 75,
3096
2934
  minValue: 0,
3097
2935
  maxValue: 100,
3098
- formatOutput: (v2) => `${v2}%`
2936
+ formatOutput: (v) => `${v}%`
3099
2937
  }
3100
2938
  ),
3101
2939
  /* @__PURE__ */ jsx(
3102
- b3,
2940
+ y,
3103
2941
  {
3104
2942
  ariaLabel: "Pair",
3105
2943
  min: 0,
@@ -3114,18 +2952,18 @@ function FieldsAndPickers() {
3114
2952
  ] }),
3115
2953
  /* @__PURE__ */ jsxs(Cell, { label: "DetentSlider, InlineRange", children: [
3116
2954
  /* @__PURE__ */ jsx(
3117
- c8,
2955
+ c6,
3118
2956
  {
3119
2957
  items: [0.25, 0.5, 1, 2, 4],
3120
2958
  value: rate,
3121
2959
  onChange: setRate,
3122
- formatLabel: (r9) => `${r9}\xD7`,
2960
+ formatLabel: (r4) => `${r4}\xD7`,
3123
2961
  labels: "all",
3124
2962
  ariaLabel: "Playback rate"
3125
2963
  }
3126
2964
  ),
3127
2965
  /* @__PURE__ */ jsx(
3128
- r3,
2966
+ i3,
3129
2967
  {
3130
2968
  "aria-label": "Width",
3131
2969
  min: 0,
@@ -3136,7 +2974,7 @@ function FieldsAndPickers() {
3136
2974
  )
3137
2975
  ] }),
3138
2976
  /* @__PURE__ */ jsxs(Cell, { label: "ColorField, GradientEditor", children: [
3139
- /* @__PURE__ */ jsx(l2, { value: color, alpha: true, onInput: setColor, onChange: setColor, "aria-label": "Color" }),
2977
+ /* @__PURE__ */ jsx(l4, { value: color, alpha: true, onInput: setColor, onChange: setColor, "aria-label": "Color" }),
3140
2978
  /* @__PURE__ */ jsx(C2, { value: gradient, onInput: setGradient, onChange: setGradient, kindSwitch: true })
3141
2979
  ] }),
3142
2980
  /* @__PURE__ */ jsx(Cell, { label: "PaintInput", children: /* @__PURE__ */ jsx(
@@ -3169,10 +3007,12 @@ function PanelsAndRows() {
3169
3007
  ]);
3170
3008
  const [panelCollapsed, setPanelCollapsed] = useState(false);
3171
3009
  return /* @__PURE__ */ jsxs(Section, { title: "Panels & property rows", children: [
3172
- /* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(D, { title: "Shape", children: /* @__PURE__ */ jsxs(O, { children: [
3010
+ /* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(ae2, { title: "Shape", children: /* @__PURE__ */ jsxs(oe, { children: [
3173
3011
  /* @__PURE__ */ jsx(
3174
- I2,
3012
+ B2,
3175
3013
  {
3014
+ kind: "number",
3015
+ control: "slider",
3176
3016
  label: "Opacity",
3177
3017
  value: opacity,
3178
3018
  min: 0,
@@ -3182,8 +3022,10 @@ function PanelsAndRows() {
3182
3022
  }
3183
3023
  ),
3184
3024
  /* @__PURE__ */ jsx(
3185
- I2,
3025
+ B2,
3186
3026
  {
3027
+ kind: "number",
3028
+ control: "slider",
3187
3029
  label: "Radius",
3188
3030
  value: radius,
3189
3031
  min: 0,
@@ -3193,8 +3035,9 @@ function PanelsAndRows() {
3193
3035
  }
3194
3036
  ),
3195
3037
  /* @__PURE__ */ jsx(
3196
- z2,
3038
+ B2,
3197
3039
  {
3040
+ kind: "color",
3198
3041
  label: "Fill",
3199
3042
  value: fill,
3200
3043
  onChange: setFill,
@@ -3202,11 +3045,23 @@ function PanelsAndRows() {
3202
3045
  onAlphaChange: setAlpha
3203
3046
  }
3204
3047
  ),
3205
- /* @__PURE__ */ jsx(z2, { label: "Stroke", value: stroke, onChange: setStroke }),
3206
- /* @__PURE__ */ jsx(U, { label: "Count", value: count, min: 0, max: 100, step: 1, onChange: setCount }),
3048
+ /* @__PURE__ */ jsx(B2, { kind: "color", label: "Stroke", value: stroke, onChange: setStroke }),
3207
3049
  /* @__PURE__ */ jsx(
3208
- W,
3050
+ B2,
3209
3051
  {
3052
+ kind: "number",
3053
+ label: "Count",
3054
+ value: count,
3055
+ min: 0,
3056
+ max: 100,
3057
+ step: 1,
3058
+ onChange: setCount
3059
+ }
3060
+ ),
3061
+ /* @__PURE__ */ jsx(
3062
+ B2,
3063
+ {
3064
+ kind: "enum",
3210
3065
  label: "Line cap",
3211
3066
  value: cap,
3212
3067
  onChange: setCap,
@@ -3217,8 +3072,10 @@ function PanelsAndRows() {
3217
3072
  }
3218
3073
  ),
3219
3074
  /* @__PURE__ */ jsx(
3220
- G2,
3075
+ B2,
3221
3076
  {
3077
+ kind: "enum",
3078
+ control: "toggle",
3222
3079
  label: "Align",
3223
3080
  value: side,
3224
3081
  onChange: setSide,
@@ -3229,10 +3086,22 @@ function PanelsAndRows() {
3229
3086
  ]
3230
3087
  }
3231
3088
  ),
3232
- /* @__PURE__ */ jsx(H, { label: "Label", value: label, onChange: setLabel }),
3233
- /* @__PURE__ */ jsx(B, { label: "Visible", value: visible, onChange: setVisible }),
3234
- /* @__PURE__ */ jsx(X, { title: "Bevel", defaultCollapsed: true, children: /* @__PURE__ */ jsx(I2, { label: "Rings", value: 32, min: 4, max: 96, step: 1, onChange: () => {
3235
- } }) })
3089
+ /* @__PURE__ */ jsx(B2, { kind: "string", label: "Label", value: label, onChange: setLabel }),
3090
+ /* @__PURE__ */ jsx(B2, { kind: "boolean", label: "Visible", value: visible, onChange: setVisible }),
3091
+ /* @__PURE__ */ jsx(b2, { title: "Bevel", defaultCollapsed: true, children: /* @__PURE__ */ jsx(
3092
+ B2,
3093
+ {
3094
+ kind: "number",
3095
+ control: "slider",
3096
+ label: "Rings",
3097
+ value: 32,
3098
+ min: 4,
3099
+ max: 96,
3100
+ step: 1,
3101
+ onChange: () => {
3102
+ }
3103
+ }
3104
+ ) })
3236
3105
  ] }) }) }),
3237
3106
  /* @__PURE__ */ jsx(Cell, { label: "PrefsForm", children: /* @__PURE__ */ jsx(
3238
3107
  A2,
@@ -3242,23 +3111,23 @@ function PanelsAndRows() {
3242
3111
  onChange: (path, value) => setPrefs((prev) => setAt(prev, path, value))
3243
3112
  }
3244
3113
  ) }),
3245
- /* @__PURE__ */ jsx(Cell, { label: "LayerStack", children: /* @__PURE__ */ jsx(
3246
- c4,
3114
+ /* @__PURE__ */ jsx(Cell, { label: "LayerList", children: /* @__PURE__ */ jsx(
3115
+ D,
3247
3116
  {
3248
3117
  items: layers,
3249
- onReorder: (ids) => setLayers(ids.flatMap((id) => layers.filter((item) => item.id === id))),
3118
+ onReorder: (move) => setLayers(S2(layers, move)),
3250
3119
  renderBody: (item) => /* @__PURE__ */ jsxs("div", { children: [
3251
3120
  "settings for ",
3252
3121
  item.label
3253
3122
  ] })
3254
3123
  }
3255
3124
  ) }),
3256
- /* @__PURE__ */ jsx(Cell, { label: "Sidebar, SidebarPanel", children: /* @__PURE__ */ jsx("div", { className: "lk-specimen__box", children: /* @__PURE__ */ jsx(n5, { side: "right", ariaLabel: "Specimen sidebar", children: /* @__PURE__ */ jsx(
3257
- s4,
3125
+ /* @__PURE__ */ jsx(Cell, { label: "Sidebar, SidebarPanel", children: /* @__PURE__ */ jsx("div", { className: "lk-specimen__box", children: /* @__PURE__ */ jsx(n6, { side: "right", ariaLabel: "Specimen sidebar", children: /* @__PURE__ */ jsx(
3126
+ s5,
3258
3127
  {
3259
3128
  title: "Selection",
3260
3129
  collapsed: panelCollapsed,
3261
- onToggleCollapse: () => setPanelCollapsed((v2) => !v2),
3130
+ onToggleCollapse: () => setPanelCollapsed((v) => !v),
3262
3131
  onHide: () => {
3263
3132
  },
3264
3133
  children: /* @__PURE__ */ jsx("div", { className: "lk-specimen__pad", children: "2 items selected" })
@@ -3270,12 +3139,12 @@ function OverlaysAndFeedback() {
3270
3139
  const calloutAnchor = useRef(null);
3271
3140
  const [calloutOpen, setCalloutOpen] = useState(false);
3272
3141
  const [dialogOpen, setDialogOpen] = useState(false);
3273
- const toasts = useMemo(() => m2(), []);
3142
+ const toasts = useMemo(() => m3(), []);
3274
3143
  return /* @__PURE__ */ jsxs(Section, { title: "Overlays & feedback", children: [
3275
3144
  /* @__PURE__ */ jsx(Cell, { label: "Tooltip, Callout, Dialog, Toast", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
3276
- /* @__PURE__ */ jsxs(c2, { children: [
3145
+ /* @__PURE__ */ jsxs(l2, { children: [
3277
3146
  /* @__PURE__ */ jsx(Focusable, { children: /* @__PURE__ */ jsx("button", { type: "button", children: "Hover me" }) }),
3278
- /* @__PURE__ */ jsx(l, { placement: "bottom", children: "Duplicates the selected layer" })
3147
+ /* @__PURE__ */ jsx(u, { placement: "bottom", children: "Duplicates the selected layer" })
3279
3148
  ] }),
3280
3149
  /* @__PURE__ */ jsx("button", { type: "button", ref: calloutAnchor, onClick: () => setCalloutOpen(true), children: "Callout" }),
3281
3150
  /* @__PURE__ */ jsx(
@@ -3284,24 +3153,24 @@ function OverlaysAndFeedback() {
3284
3153
  triggerRef: calloutAnchor,
3285
3154
  isOpen: calloutOpen,
3286
3155
  onOpenChange: setCalloutOpen,
3287
- tone: "info",
3288
- title: "Info",
3156
+ stance: "notice",
3157
+ title: "Notice",
3289
3158
  children: "Neutral guidance."
3290
3159
  }
3291
3160
  ),
3292
- /* @__PURE__ */ jsx(a5, { onClick: () => setDialogOpen(true), children: "Dialog" }),
3161
+ /* @__PURE__ */ jsx(c, { onClick: () => setDialogOpen(true), children: "Dialog" }),
3293
3162
  /* @__PURE__ */ jsx(
3294
- l5,
3163
+ u3,
3295
3164
  {
3296
3165
  isOpen: dialogOpen,
3297
3166
  onOpenChange: setDialogOpen,
3298
3167
  title: "Preferences",
3299
- footer: /* @__PURE__ */ jsx(a5, { variant: "primary", onClick: () => setDialogOpen(false), children: "OK" }),
3168
+ footer: /* @__PURE__ */ jsx(c, { variant: "primary", onClick: () => setDialogOpen(false), children: "OK" }),
3300
3169
  children: /* @__PURE__ */ jsx("p", { children: "Dialog body." })
3301
3170
  }
3302
3171
  ),
3303
3172
  /* @__PURE__ */ jsx(
3304
- a5,
3173
+ c,
3305
3174
  {
3306
3175
  onClick: () => toasts.add("success", "Saved", { description: "All changes stored.", ttlMs: null }),
3307
3176
  children: "Toast"
@@ -3310,29 +3179,29 @@ function OverlaysAndFeedback() {
3310
3179
  /* @__PURE__ */ jsx(S4, { queue: toasts, placement: "bottom-right" })
3311
3180
  ] }) }),
3312
3181
  /* @__PURE__ */ jsx(Cell, { label: "Powerline", children: /* @__PURE__ */ jsx(
3313
- r9,
3182
+ r4,
3314
3183
  {
3315
3184
  variant: "solid",
3316
3185
  size: "sm",
3317
3186
  segments: [
3318
- { text: "main", tone: "accent", endCap: "chevron" },
3319
- { text: "\u2713 12", tone: "info", endCap: "slant" },
3320
- { text: "~/proj", tone: "muted" }
3187
+ { text: "main", status: "accent", endCap: "chevron" },
3188
+ { text: "\u2713 12", status: "info", endCap: "slant" },
3189
+ { text: "~/proj", status: "muted" }
3321
3190
  ]
3322
3191
  }
3323
3192
  ) }),
3324
- /* @__PURE__ */ jsx(Cell, { label: "StatusBar", children: /* @__PURE__ */ jsxs(n6, { ariaLabel: "Editor status", children: [
3325
- /* @__PURE__ */ jsx(r10, { children: "tool: select" }),
3326
- /* @__PURE__ */ jsx(r10, { children: "sel: 3" }),
3327
- /* @__PURE__ */ jsx(i5, {}),
3328
- /* @__PURE__ */ jsx(r10, { muted: true, children: "0.7.0" })
3193
+ /* @__PURE__ */ jsx(Cell, { label: "StatusBar", children: /* @__PURE__ */ jsxs(n7, { ariaLabel: "Editor status", children: [
3194
+ /* @__PURE__ */ jsx(r5, { children: "tool: select" }),
3195
+ /* @__PURE__ */ jsx(r5, { children: "sel: 3" }),
3196
+ /* @__PURE__ */ jsx(i4, {}),
3197
+ /* @__PURE__ */ jsx(r5, { muted: true, children: "0.7.0" })
3329
3198
  ] }) })
3330
3199
  ] });
3331
3200
  }
3332
3201
  function ListsAndData() {
3333
3202
  return /* @__PURE__ */ jsxs(Section, { title: "Lists & data", children: [
3334
3203
  /* @__PURE__ */ jsx(Cell, { label: "ItemList", children: /* @__PURE__ */ jsx(
3335
- i4,
3204
+ p2,
3336
3205
  {
3337
3206
  rows: [
3338
3207
  { id: "a", label: "Draw rect" },
@@ -3343,7 +3212,7 @@ function ListsAndData() {
3343
3212
  }
3344
3213
  ) }),
3345
3214
  /* @__PURE__ */ jsx(Cell, { label: "DataGrid", children: /* @__PURE__ */ jsx(
3346
- s2,
3215
+ f,
3347
3216
  {
3348
3217
  rows: [
3349
3218
  { id: "1", name: "accent", count: 3 },
@@ -3351,8 +3220,8 @@ function ListsAndData() {
3351
3220
  { id: "3", name: "danger", count: 2 }
3352
3221
  ],
3353
3222
  columns: [
3354
- { id: "name", header: "name", accessor: (r9) => r9.name, sortable: true },
3355
- { id: "count", header: "count", accessor: (r9) => r9.count, sortable: true }
3223
+ { id: "name", header: "name", accessor: (r4) => r4.name, sortable: true },
3224
+ { id: "count", header: "count", accessor: (r4) => r4.count, sortable: true }
3356
3225
  ],
3357
3226
  defaultSort: { columnId: "name", direction: "asc" }
3358
3227
  }
@@ -3363,7 +3232,7 @@ function ToolChrome() {
3363
3232
  const [tool, setTool] = useState("select");
3364
3233
  const [paneWidth, setPaneWidth] = useState(160);
3365
3234
  return /* @__PURE__ */ jsxs(Section, { title: "Tool chrome", children: [
3366
- /* @__PURE__ */ jsx(Cell, { label: "ToolGroup, ToolButton", children: /* @__PURE__ */ jsx(n7, { orientation: "horizontal", ariaLabel: "Tools", children: ["select", "rect", "ellipse"].map((id) => /* @__PURE__ */ jsx(
3235
+ /* @__PURE__ */ jsx(Cell, { label: "ToolGroup, ToolButton", children: /* @__PURE__ */ jsx(n8, { orientation: "horizontal", ariaLabel: "Tools", children: ["select", "rect", "ellipse"].map((id) => /* @__PURE__ */ jsx(
3367
3236
  o4,
3368
3237
  {
3369
3238
  icon: /* @__PURE__ */ jsx(Dot, {}),
@@ -3375,14 +3244,14 @@ function ToolChrome() {
3375
3244
  },
3376
3245
  id
3377
3246
  )) }) }),
3378
- /* @__PURE__ */ jsx(Cell, { label: "ToolOptionsBar", children: /* @__PURE__ */ jsxs(c5, { label: "Text", children: [
3379
- /* @__PURE__ */ jsx(a5, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Bold", children: "B" }),
3380
- /* @__PURE__ */ jsx(a5, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Italic", children: "I" })
3247
+ /* @__PURE__ */ jsx(Cell, { label: "ToolOptionsBar", children: /* @__PURE__ */ jsxs(c3, { label: "Text", children: [
3248
+ /* @__PURE__ */ jsx(c, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Bold", children: "B" }),
3249
+ /* @__PURE__ */ jsx(c, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Italic", children: "I" })
3381
3250
  ] }) }),
3382
3251
  /* @__PURE__ */ jsx(Cell, { label: "ResizeHandle", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__box", children: [
3383
3252
  /* @__PURE__ */ jsx("div", { className: "lk-specimen__box-main", children: "content" }),
3384
3253
  /* @__PURE__ */ jsx(
3385
- c6,
3254
+ c4,
3386
3255
  {
3387
3256
  value: paneWidth,
3388
3257
  min: 100,
@@ -3451,7 +3320,7 @@ function EditorsAndPlots() {
3451
3320
  const [playhead, setPlayhead] = useState(0);
3452
3321
  return /* @__PURE__ */ jsxs(Section, { title: "Editors & plots", children: [
3453
3322
  /* @__PURE__ */ jsx(Cell, { label: "Plot2D", children: /* @__PURE__ */ jsx(
3454
- w2,
3323
+ w,
3455
3324
  {
3456
3325
  width: 260,
3457
3326
  height: 130,
@@ -3462,7 +3331,7 @@ function EditorsAndPlots() {
3462
3331
  }
3463
3332
  ) }),
3464
3333
  /* @__PURE__ */ jsx(Cell, { label: "CurveEditor", children: /* @__PURE__ */ jsx(
3465
- L2,
3334
+ L,
3466
3335
  {
3467
3336
  value: curve,
3468
3337
  onInput: setCurve,
@@ -3477,7 +3346,7 @@ function EditorsAndPlots() {
3477
3346
  }
3478
3347
  ) }),
3479
3348
  /* @__PURE__ */ jsx(Cell, { label: "PointPlotter", children: /* @__PURE__ */ jsx(
3480
- n8,
3349
+ n9,
3481
3350
  {
3482
3351
  value: points,
3483
3352
  onInput: setPoints,
@@ -3491,7 +3360,7 @@ function EditorsAndPlots() {
3491
3360
  }
3492
3361
  ) }),
3493
3362
  /* @__PURE__ */ jsx(Cell, { label: "BandEditor", wide: true, children: /* @__PURE__ */ jsx(
3494
- k3,
3363
+ k2,
3495
3364
  {
3496
3365
  min: 1 / 64,
3497
3366
  max: 1 / 2,
@@ -3501,7 +3370,7 @@ function EditorsAndPlots() {
3501
3370
  onChange: setBands,
3502
3371
  selectedIndex: band,
3503
3372
  onSelect: setBand,
3504
- renderBand: (b3) => b3.data.name,
3373
+ renderBand: (b2) => b2.data.name,
3505
3374
  ticks: [1 / 24, 1 / 12, 1 / 6].map((at) => ({ at, label: `1/${Math.round(1 / at)}` }))
3506
3375
  }
3507
3376
  ) }),
@@ -3518,7 +3387,6 @@ function EditorsAndPlots() {
3518
3387
  ] });
3519
3388
  }
3520
3389
  function LabChrome() {
3521
- const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
3522
3390
  const [zoom, setZoom] = useState(1);
3523
3391
  return /* @__PURE__ */ jsxs(Section, { title: "Lab chrome", children: [
3524
3392
  /* @__PURE__ */ jsx(Cell, { label: "Toolbar", wide: true, children: /* @__PURE__ */ jsxs(Toolbar, { "aria-label": "Trial actions", children: [
@@ -3536,18 +3404,6 @@ function LabChrome() {
3536
3404
  /* @__PURE__ */ jsx(StatusBar.Section, { children: "Items: 12" }),
3537
3405
  /* @__PURE__ */ jsx(StatusBar.Section, { children: "Zoom: 100%" })
3538
3406
  ] }) }),
3539
- /* @__PURE__ */ jsx(Cell, { label: "Sidebar", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__box", children: [
3540
- /* @__PURE__ */ jsx("div", { className: "lk-specimen__box-main", children: "main" }),
3541
- /* @__PURE__ */ jsx(
3542
- Sidebar,
3543
- {
3544
- title: "Controls",
3545
- collapsed: sidebarCollapsed,
3546
- onToggle: () => setSidebarCollapsed((v2) => !v2),
3547
- children: /* @__PURE__ */ jsx("p", { children: "One slider" })
3548
- }
3549
- )
3550
- ] }) }),
3551
3407
  /* @__PURE__ */ jsxs(Cell, { label: "Legend, JobProgress", children: [
3552
3408
  /* @__PURE__ */ jsx(Legend, { entries: LEGEND }),
3553
3409
  /* @__PURE__ */ jsx(JobProgress, { job: JOB })
@@ -3582,6 +3438,6 @@ function Specimen({ className }) {
3582
3438
  ] });
3583
3439
  }
3584
3440
 
3585
- export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationOverlay, AnnotationTargets, Lab, LabPalette, LabRoot, LabShell, LabSwitcher, SPECIMEN_SECTIONS, Specimen, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationToolInfo, annotationsFromJSON, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, currentPage, defineInstrument, fitView, fracContains, fracEncloses, fracToWorld, fromWeaselView, interstellarTheme, isStale, markCommands, markSvgNodes, reorderTrials, resetTrial, resolveMarkStyle, roundFrac, seenFrom, toWeaselView, validateConfigSchema, worldToFrac };
3441
+ export { AnnotationOverlay, AnnotationTargets, Lab, LabBoundary, LabPalette, LabRoot, LabShell, LabSwitcher, SPECIMEN_SECTIONS, Specimen, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationsFromJSON, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, currentPage, defineInstrument, fitView, fracContains, fracEncloses, fracToWorld, fromWeaselView, interstellarTheme, isStale, reorderTrials, resetTrial, resolveMarkStyle, roundFrac, seenFrom, toWeaselView, validateConfigSchema, worldToFrac };
3586
3442
  //# sourceMappingURL=index.js.map
3587
3443
  //# sourceMappingURL=index.js.map