@weasel-js/labkit 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/_dts/{CanvasStackContext-Wo6OwIVM.d.ts → CanvasStackContext-D2jnIwfk.d.ts} +1 -1
  2. package/dist/_dts/{LayerList.d-BoELAMsM.d.ts → LayerList.d-DiuEArKq.d.ts} +2 -2
  3. package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +79 -0
  4. package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +141 -0
  5. package/dist/_dts/{Select.d-Cr8-zoup.d.ts → Select.d-Bensr_MT.d.ts} +11 -1
  6. package/dist/_dts/{Stage-DWBBi8IU.d.ts → Stage-CCWfQQWM.d.ts} +58 -18
  7. package/dist/_dts/index-B2Yj5aA0.d.ts +274 -0
  8. package/dist/_dts/{index-CKyX0ME_.d.ts → index-CsYqUHD3.d.ts} +2 -2
  9. package/dist/_dts/{types-DTuViBvc.d.ts → types-CRPSGFAp.d.ts} +13 -4
  10. package/dist/_dts/{types-B7yBTTF9.d.ts → types-CSm9jgol.d.ts} +2 -2
  11. package/dist/_dts/{useTrialState-CMaV6UD4.d.ts → useTrialState-CTZPgeZ7.d.ts} +1 -1
  12. package/dist/canvas/index.d.ts +6 -6
  13. package/dist/canvas/index.js +2 -2
  14. package/dist/chrome/index.d.ts +5 -5
  15. package/dist/chrome/index.js +8 -8
  16. package/dist/{chunk-QGMOA2YE.js → chunk-275JRRVD.js} +67 -70
  17. package/dist/chunk-275JRRVD.js.map +1 -0
  18. package/dist/{chunk-KHK5FGER.js → chunk-4LJSC7MB.js} +8 -10
  19. package/dist/chunk-4LJSC7MB.js.map +1 -0
  20. package/dist/{chunk-SLAQPUI4.js → chunk-7BO7HNGF.js} +5 -5
  21. package/dist/{chunk-SLAQPUI4.js.map → chunk-7BO7HNGF.js.map} +1 -1
  22. package/dist/chunk-CZZPXUOU.js +3 -0
  23. package/dist/{chunk-SBXNQW4G.js.map → chunk-CZZPXUOU.js.map} +1 -1
  24. package/dist/{chunk-6FLXL3I7.js → chunk-FMK7UQ6V.js} +19 -4
  25. package/dist/chunk-FMK7UQ6V.js.map +1 -0
  26. package/dist/{chunk-O6FFFOHS.js → chunk-FZ7YFQN7.js} +16 -8
  27. package/dist/chunk-FZ7YFQN7.js.map +1 -0
  28. package/dist/{chunk-GHGO52SO.js → chunk-GOZLNM4L.js} +5 -5
  29. package/dist/{chunk-GHGO52SO.js.map → chunk-GOZLNM4L.js.map} +1 -1
  30. package/dist/{chunk-4TT3PNPR.js → chunk-I5DUQ5HM.js} +33 -36
  31. package/dist/chunk-I5DUQ5HM.js.map +1 -0
  32. package/dist/{chunk-NEXR37YJ.js → chunk-J7OWWTCW.js} +4 -5
  33. package/dist/chunk-J7OWWTCW.js.map +1 -0
  34. package/dist/{chunk-IRTGUQ5O.js → chunk-KMJ7RWD3.js} +16 -6
  35. package/dist/chunk-KMJ7RWD3.js.map +1 -0
  36. package/dist/{chunk-S4NCI32V.js → chunk-M7HP3FTK.js} +4 -4
  37. package/dist/{chunk-S4NCI32V.js.map → chunk-M7HP3FTK.js.map} +1 -1
  38. package/dist/chunk-MIM5R4ZT.js +14972 -0
  39. package/dist/chunk-MIM5R4ZT.js.map +1 -0
  40. package/dist/{chunk-ASOK76ZH.js → chunk-T5IBSPAM.js} +59 -26
  41. package/dist/chunk-T5IBSPAM.js.map +1 -0
  42. package/dist/{chunk-DWMSB4CA.js → chunk-UNAZSLWE.js} +82 -16
  43. package/dist/chunk-UNAZSLWE.js.map +1 -0
  44. package/dist/{chunk-TJ77A4A3.js → chunk-Y23G2VZL.js} +5 -9
  45. package/dist/chunk-Y23G2VZL.js.map +1 -0
  46. package/dist/{chunk-HKV7LRHY.js → chunk-YT75VYRD.js} +4 -4
  47. package/dist/{chunk-HKV7LRHY.js.map → chunk-YT75VYRD.js.map} +1 -1
  48. package/dist/{chunk-CGHF6RZV.js → chunk-ZIFPHIWZ.js} +9 -7
  49. package/dist/chunk-ZIFPHIWZ.js.map +1 -0
  50. package/dist/config/index.d.ts +16 -9
  51. package/dist/config/index.js +4 -4
  52. package/dist/controls/index.d.ts +2 -2
  53. package/dist/controls/index.js +5 -5
  54. package/dist/dragdrop/index.d.ts +3 -3
  55. package/dist/index.d.ts +263 -24
  56. package/dist/index.js +376 -237
  57. package/dist/index.js.map +1 -1
  58. package/dist/layers/index.d.ts +4 -4
  59. package/dist/layers/index.js +2 -2
  60. package/dist/loupe/index.d.ts +4 -4
  61. package/dist/loupe/index.js +2 -2
  62. package/dist/overview/index.d.ts +2 -2
  63. package/dist/overview/index.js +9 -8
  64. package/dist/overview/index.js.map +1 -1
  65. package/dist/passthrough/weasel-ui.d.ts +208 -38
  66. package/dist/passthrough/weasel-ui.js +3 -3
  67. package/dist/primitives/index.d.ts +3 -178
  68. package/dist/primitives/index.js +6 -6
  69. package/dist/state/index.d.ts +5 -5
  70. package/dist/state/index.js +4 -4
  71. package/dist/styles.css +91 -83
  72. package/dist/undo/index.d.ts +3 -3
  73. package/package.json +13 -12
  74. package/src/annotations/AnnotationOverlay.tsx +2 -2
  75. package/src/annotations/Annotations.less +0 -10
  76. package/src/annotations/MarkList.tsx +4 -8
  77. package/src/annotations/paint.test.ts +3 -14
  78. package/src/annotations/paint.ts +3 -19
  79. package/src/annotations/svgNodes.test.ts +6 -9
  80. package/src/annotations/svgNodes.ts +3 -3
  81. package/src/canvas/AGENTS.md +1 -0
  82. package/src/canvas/CameraInput.tsx +44 -33
  83. package/src/canvas/CanvasStack.tsx +6 -1
  84. package/src/canvas/LinkedCursor.less +1 -1
  85. package/src/canvas/Stage.test.tsx +33 -4
  86. package/src/canvas/Stage.tsx +6 -1
  87. package/src/canvas/cameraRegistry.test.ts +55 -0
  88. package/src/canvas/cameraRegistry.ts +86 -0
  89. package/src/canvas/cameraZoom.test.ts +46 -0
  90. package/src/canvas/cameraZoom.ts +24 -0
  91. package/src/canvas/index.ts +14 -2
  92. package/src/canvas/sharedScope.test.tsx +94 -0
  93. package/src/chrome/ChromeRegions.stories.tsx +1 -0
  94. package/src/chrome/regions/PaletteRegion.less +0 -7
  95. package/src/chrome/regions/SidebarRegion.less +12 -2
  96. package/src/config/builder.test.ts +2 -1
  97. package/src/config/builder.ts +12 -5
  98. package/src/config/fromConfigField.test.ts +14 -0
  99. package/src/config/fromConfigField.ts +18 -4
  100. package/src/config/path.ts +2 -5
  101. package/src/config/resolve.ts +4 -0
  102. package/src/config/types.ts +13 -9
  103. package/src/controls/ControlPanel.less +1 -1
  104. package/src/controls/ControlPanel.stories.tsx +3 -2
  105. package/src/controls/ControlPanel.test.tsx +64 -11
  106. package/src/controls/ControlPanel.tsx +52 -2
  107. package/src/index.ts +15 -1
  108. package/src/lab/Lab.tsx +83 -72
  109. package/src/lab/{LabFit.stories.less → LabFit.browser.test.less} +1 -1
  110. package/src/lab/{LabFit.stories.tsx → LabFit.browser.test.tsx} +41 -63
  111. package/src/lab/LabFullChrome.stories.tsx +1 -0
  112. package/src/lab/LabHeader.test.tsx +24 -14
  113. package/src/lab/LabHeader.tsx +11 -12
  114. package/src/lab/LabShell.less +8 -17
  115. package/src/lab/LabSwitcher.less +6 -6
  116. package/src/lab/LabZoom.test.tsx +223 -0
  117. package/src/lab/LabZoom.tsx +170 -0
  118. package/src/lab/index.ts +1 -0
  119. package/src/loupe/LoupeGestures.tsx +1 -1
  120. package/src/overview/TrialOverview.tsx +7 -5
  121. package/src/passthrough/weasel-ui.test.ts +2 -0
  122. package/src/passthrough/weasel-ui.ts +16 -4
  123. package/src/primitives/FloatingPanel.test.tsx +11 -0
  124. package/src/primitives/FloatingPanel.tsx +2 -5
  125. package/src/primitives/JobProgress.less +1 -1
  126. package/src/primitives/Legend.stories.tsx +1 -0
  127. package/src/primitives/Readout.browser.test.tsx +137 -0
  128. package/src/primitives/Readout.less +12 -0
  129. package/src/primitives/Readout.stories.tsx +58 -0
  130. package/src/primitives/Readout.test.tsx +93 -0
  131. package/src/primitives/Readout.tsx +56 -0
  132. package/src/primitives/index.ts +2 -0
  133. package/src/specimen/Specimen.stories.tsx +1 -0
  134. package/src/specimen/Specimen.tsx +2 -2
  135. package/src/state/Persistence.browser.test.tsx +47 -0
  136. package/src/state/store.test.ts +5 -1
  137. package/src/state/usePersistedState.test.tsx +1 -1
  138. package/src/styles.less +1 -0
  139. package/src/theme/Interstellar.stories.tsx +3 -1
  140. package/src/theme/base.less +21 -47
  141. package/src/theme/interstellar.test.ts +1 -1
  142. package/src/theme/interstellar.theme.json +10 -3
  143. package/src/trial/Trial.less +0 -13
  144. package/src/trial/Trial.tsx +12 -6
  145. package/src/trial/TrialChrome.tsx +21 -3
  146. package/dist/_dts/PrefsRow.d-DFpPIeIC.d.ts +0 -39
  147. package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +0 -404
  148. package/dist/chunk-4TT3PNPR.js.map +0 -1
  149. package/dist/chunk-6FLXL3I7.js.map +0 -1
  150. package/dist/chunk-ASOK76ZH.js.map +0 -1
  151. package/dist/chunk-CGHF6RZV.js.map +0 -1
  152. package/dist/chunk-DWMSB4CA.js.map +0 -1
  153. package/dist/chunk-IRTGUQ5O.js.map +0 -1
  154. package/dist/chunk-KHK5FGER.js.map +0 -1
  155. package/dist/chunk-NEXR37YJ.js.map +0 -1
  156. package/dist/chunk-O6FFFOHS.js.map +0 -1
  157. package/dist/chunk-QGMOA2YE.js.map +0 -1
  158. package/dist/chunk-SBXNQW4G.js +0 -3
  159. package/dist/chunk-TJ77A4A3.js.map +0 -1
  160. package/dist/chunk-TYN6MLXX.js +0 -13864
  161. package/dist/chunk-TYN6MLXX.js.map +0 -1
  162. package/src/state/Persistence.stories.tsx +0 -75
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
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';
1
+ import { resolveLoupe, TrialLoupe } from './chunk-M7HP3FTK.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-M7HP3FTK.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
5
  import { useDragDrop, DragOverlay, Palette } from './chunk-WPLAANH4.js';
@@ -7,41 +7,41 @@ 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 { 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';
10
+ import { markCommands, markSvgNodes } from './chunk-4LJSC7MB.js';
11
+ export { markCommands, markSvgNodes } from './chunk-4LJSC7MB.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-I5DUQ5HM.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-I5DUQ5HM.js';
14
14
  import { AnnotationsContext } from './chunk-3RY6WL5T.js';
15
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';
16
+ import { Split, JobProgress, Legend } from './chunk-FMK7UQ6V.js';
17
+ export { JobProgress, Legend, Readout, Split } from './chunk-FMK7UQ6V.js';
18
+ import { FloatingPanel } from './chunk-J7OWWTCW.js';
19
+ export { FloatingPanel } from './chunk-J7OWWTCW.js';
20
+ import { Toolbar, StatusBar, ScaleIndicator, ZoomControl } from './chunk-7BO7HNGF.js';
21
+ export { FpsMeter, ScaleIndicator, StatusBar, Toolbar, ZoomControl } from './chunk-7BO7HNGF.js';
22
+ import './chunk-CZZPXUOU.js';
23
+ import { unruledConfigSchema, createLabStore, openLabStore, panelKey } from './chunk-YT75VYRD.js';
24
+ export { CURRENT_DOCUMENT_VERSION, dockPanel, labDocumentKey, openLabStore, panelKey, quarantineKey, undockPanel, useTrialState } from './chunk-YT75VYRD.js';
25
25
  import { newId, useWarnIgnoredChange, useOpenOnce, PersistenceContext, createRecordCache, noneAdapter, defaultStorage, usePersistedState } from './chunk-RWNDDKOH.js';
26
26
  export { Persistence, createIndexedDbAdapter, createMemoryAdapter, indexedDbAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, usePersistedState } from './chunk-RWNDDKOH.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';
27
+ export { ControlPanel, inDialog, summarizeValue } from './chunk-T5IBSPAM.js';
28
+ import { useConfigSchema } from './chunk-GOZLNM4L.js';
29
+ export { sectionTree, useConfigSchema } from './chunk-GOZLNM4L.js';
30
30
  import { useLabContext, LabContext } from './chunk-Z76KEZAX.js';
31
31
  export { LabContext, useLabContext } from './chunk-Z76KEZAX.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';
32
+ import { useResolvedConfig } from './chunk-FZ7YFQN7.js';
33
+ export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from './chunk-FZ7YFQN7.js';
34
+ export { fromConfigFields, isLeafVisible } from './chunk-KMJ7RWD3.js';
35
+ import { hasConfigPath, schemaNodeAtPath, applyConfigWrite, resolveAutoConfig, isAuto, isRecord, autoPathsOf, fillConfigDefaults } from './chunk-Y23G2VZL.js';
36
+ export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from './chunk-Y23G2VZL.js';
37
+ import { CanvasStack, Stage, fitStage } from './chunk-ZIFPHIWZ.js';
38
+ export { CanvasStack, Stage, fitStage } from './chunk-ZIFPHIWZ.js';
39
39
  export { centerOn, zoomAt } from './chunk-JVBYV6TL.js';
40
40
  export { screenToWorld, worldToScreen } from './chunk-AWQG7FCC.js';
41
41
  import { useSurfaceOptional, useSurfaceCanvas, useTileId, SurfaceContext, SurfaceCanvasContext } from './chunk-WIG6XHJ7.js';
42
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';
43
+ import { CameraWheelContext, as2DView, CameraRegistryContext, DEFAULT_VIEW, CameraPublishContext, createCameraRegistry, withZoom } from './chunk-UNAZSLWE.js';
44
+ export { CameraContext, CameraInput, CameraPublishContext, CameraRegistryContext, CameraScope, DEFAULT_VIEW, as2DView, createCameraRegistry, usePublishCamera } from './chunk-UNAZSLWE.js';
45
45
  import { applyCamera } from './chunk-24W5VEJW.js';
46
46
  export { DEFAULT_FRAME, applyCamera, resolveFrame } from './chunk-24W5VEJW.js';
47
47
  import { CanvasStackContext } from './chunk-CQLQPQ4P.js';
@@ -49,11 +49,11 @@ export { CanvasStackContext } from './chunk-CQLQPQ4P.js';
49
49
  import { LabStoreContext, TrialIdProvider, TrialIdContext } from './chunk-2YILQ7Y5.js';
50
50
  export { LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, useLabStore, useTrialId } from './chunk-2YILQ7Y5.js';
51
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';
56
- import { createContext, useState, useRef, useEffect, useCallback, useContext, useMemo, useId, Children, useLayoutEffect, useSyncExternalStore } from 'react';
52
+ import { E3, x3, X, U, G, d3, o3, c, Xt, o5, a8, l4, u4, a7, r3, a10, i2, o6, s4, c6, l6, p, f2, u3, y, E2, y2, l7, S, c7, i4, f3, D, T, re2, ie2, R, b2, j, n6, a11, m3, l2, u, _2, d2, S3, r4, n7, r5, i5, p2, f, n8, o4, c4, c5, w, L, n9, j2, ye, n2 } from './chunk-MIM5R4ZT.js';
53
+ export { c as Button, V as CloseIcon, xe as CollapseIcon, _ as CurveField, i3 as DetailList, a4 as DetailRow, Se as ExpandIcon, l as Icon, u3 as Input, l8 as Jog, E3 as LayerList, re as PauseIcon, ne as PlayIcon, z2 as PropertyControl, R as PropertyField, b2 as PropertyGroup, ie2 as PropertyList, re2 as PropertyPanel, I as PropertyRow, ae2 as PropertySpan, B as ResetIcon, E2 as Select, ae as StepBackIcon, $ as StepForwardIcon, ie as StopIcon, x2 as Subpanel, a7 as ToggleBar, oe as TokenPanel, H2 as inferTokenType, x3 as moveLayers, O2 as refitScale } from './chunk-MIM5R4ZT.js';
54
+ import { serializeSvg } from './chunk-275JRRVD.js';
55
+ import { makeViewportZoomAction, createScene, asNodeId as asNodeId$1, WeaselProvider, SceneCanvas, createPointerStore, PointerContextProvider, DepRegistryProvider, ActionsProvider, ActiveToolContextProvider, useActionsRegistry, useDepSource, ActionDisabledReason, useGestureDispatcher, sceneFromJSON, renderSceneToPixels, useActiveToolContext } from '@weasel-js/core';
56
+ import { createContext, useState, useRef, useEffect, useCallback, useContext, useMemo, useSyncExternalStore, useId, Children, useLayoutEffect } from 'react';
57
57
  import { flushSync, createPortal } from 'react-dom';
58
58
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
59
59
  import { defineTheme, weaselTheme, colorCount, resolveTheme, colorAt } from '@weasel-js/theme';
@@ -68,8 +68,8 @@ function seenFrom(config, keys) {
68
68
  const out = {};
69
69
  if (config === null || typeof config !== "object") return out;
70
70
  const src = config;
71
- for (const k2 of keys) {
72
- if (k2 in src) out[k2] = src[k2];
71
+ for (const k of keys) {
72
+ if (k in src) out[k] = src[k];
73
73
  }
74
74
  return out;
75
75
  }
@@ -77,9 +77,9 @@ function isStale(seen, config, keys) {
77
77
  if (!seen || keys.length === 0) return false;
78
78
  if (config === null || typeof config !== "object") return false;
79
79
  const src = config;
80
- for (const k2 of keys) {
81
- if (!(k2 in seen)) continue;
82
- if (!Object.is(seen[k2], src[k2])) return true;
80
+ for (const k of keys) {
81
+ if (!(k in seen)) continue;
82
+ if (!Object.is(seen[k], src[k])) return true;
83
83
  }
84
84
  return false;
85
85
  }
@@ -90,7 +90,7 @@ function createMarkDrawOne(opts) {
90
90
  }
91
91
  function resolveMarkStyle(data, opts) {
92
92
  return {
93
- color: opts.meaning?.statuses?.find((s4) => s4.id === data.status)?.color,
93
+ color: opts.meaning?.statuses?.find((s2) => s2.id === data.status)?.color,
94
94
  // Read off the node rather than through the store's `isStale`, which
95
95
  // wants a projected Annotation this path does not have.
96
96
  stale: isStale(data.seen, opts.config, opts.positionDependsOn ?? [])
@@ -239,12 +239,12 @@ async function captureTarget(args, opts = {}) {
239
239
  }
240
240
 
241
241
  // src/annotations/frac.ts
242
- function fracToWorld(f4, content) {
242
+ function fracToWorld(f5, content) {
243
243
  return {
244
- x: f4.x * content.w,
245
- y: f4.y * content.h,
246
- width: f4.w * content.w,
247
- height: f4.h * content.h
244
+ x: f5.x * content.w,
245
+ y: f5.y * content.h,
246
+ width: f5.w * content.w,
247
+ height: f5.h * content.h
248
248
  };
249
249
  }
250
250
  function worldToFrac(r4, content) {
@@ -253,12 +253,12 @@ function worldToFrac(r4, content) {
253
253
  return { x: r4.x * sx, y: r4.y * sy, w: r4.width * sx, h: r4.height * sy };
254
254
  }
255
255
  var DP = 1e4;
256
- function roundFrac(f4) {
256
+ function roundFrac(f5) {
257
257
  return {
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
258
+ x: Math.round(f5.x * DP) / DP,
259
+ y: Math.round(f5.y * DP) / DP,
260
+ w: Math.round(f5.w * DP) / DP,
261
+ h: Math.round(f5.h * DP) / DP
262
262
  };
263
263
  }
264
264
  function fracContains(box, pt, tol = 0) {
@@ -300,8 +300,8 @@ var MarkHistory = class {
300
300
  /** The target `undo` would act on, skipping any whose scene has nothing
301
301
  * left — a scene can drop entries this ordering still lists. */
302
302
  next(stack, can, at) {
303
- for (let i4 = stack.length - 1; i4 >= 0; i4--) {
304
- const target = stack[i4];
303
+ for (let i5 = stack.length - 1; i5 >= 0; i5--) {
304
+ const target = stack[i5];
305
305
  if (target === void 0) continue;
306
306
  const scene = at(target);
307
307
  if (scene && can(scene)) return target;
@@ -309,13 +309,13 @@ var MarkHistory = class {
309
309
  return null;
310
310
  }
311
311
  canUndo(at) {
312
- return this.next(this.undoable, (s4) => s4.canUndo(), at) !== null;
312
+ return this.next(this.undoable, (s2) => s2.canUndo(), at) !== null;
313
313
  }
314
314
  canRedo(at) {
315
- return this.next(this.redoable, (s4) => s4.canRedo(), at) !== null;
315
+ return this.next(this.redoable, (s2) => s2.canRedo(), at) !== null;
316
316
  }
317
317
  undo(at) {
318
- const target = this.next(this.undoable, (s4) => s4.canUndo(), at);
318
+ const target = this.next(this.undoable, (s2) => s2.canUndo(), at);
319
319
  const scene = target === null ? void 0 : at(target);
320
320
  if (!scene) return false;
321
321
  this.replaying = "undo";
@@ -326,7 +326,7 @@ var MarkHistory = class {
326
326
  }
327
327
  }
328
328
  redo(at) {
329
- const target = this.next(this.redoable, (s4) => s4.canRedo(), at);
329
+ const target = this.next(this.redoable, (s2) => s2.canRedo(), at);
330
330
  const scene = target === null ? void 0 : at(target);
331
331
  if (!scene) return false;
332
332
  this.replaying = "redo";
@@ -338,9 +338,9 @@ var MarkHistory = class {
338
338
  }
339
339
  };
340
340
  function drop(stack, value) {
341
- for (let i4 = stack.length - 1; i4 >= 0; i4--) {
342
- if (stack[i4] === value) {
343
- stack.splice(i4, 1);
341
+ for (let i5 = stack.length - 1; i5 >= 0; i5--) {
342
+ if (stack[i5] === value) {
343
+ stack.splice(i5, 1);
344
344
  return;
345
345
  }
346
346
  }
@@ -407,21 +407,21 @@ function createAnnotationStore(opts) {
407
407
  if (!scene) return [];
408
408
  const out = [];
409
409
  for (const id of scene.renderOrder()) {
410
- const a4 = project(target, String(id));
411
- if (a4) out.push(a4);
410
+ const a6 = project(target, String(id));
411
+ if (a6) out.push(a6);
412
412
  }
413
413
  return out;
414
414
  };
415
415
  const all = () => liveTargets().flatMap(marksOn);
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;
416
+ const matches = (a6, q) => {
417
+ if (q.target !== void 0 && a6.target !== q.target) return false;
418
+ if (q.kind !== void 0 && a6.kind !== q.kind) return false;
419
+ if (q.status !== void 0 && a6.status !== q.status) return false;
420
420
  if (q.tags !== void 0) {
421
- const have = a4.tags ?? [];
421
+ const have = a6.tags ?? [];
422
422
  for (const t of q.tags) if (!have.includes(t)) return false;
423
423
  }
424
- if (q.where && !q.where(a4)) return false;
424
+ if (q.where && !q.where(a6)) return false;
425
425
  return true;
426
426
  };
427
427
  const nodeOf = (id) => {
@@ -439,17 +439,17 @@ function createAnnotationStore(opts) {
439
439
  return parts ? project(parts.target, parts.node) : void 0;
440
440
  },
441
441
  query(q) {
442
- return q ? all().filter((a4) => matches(a4, q)) : all();
442
+ return q ? all().filter((a6) => matches(a6, q)) : all();
443
443
  },
444
444
  hitTest(target, pt, tol = 0) {
445
- return marksOn(target).filter((a4) => fracContains(a4.frac, pt, tol)).reverse();
445
+ return marksOn(target).filter((a6) => fracContains(a6.frac, pt, tol)).reverse();
446
446
  },
447
447
  within(target, box) {
448
- return marksOn(target).filter((a4) => fracEncloses(box, a4.frac));
448
+ return marksOn(target).filter((a6) => fracEncloses(box, a6.frac));
449
449
  },
450
- isStale(a4, config) {
451
- const keys = targetOf(a4.target)?.positionDependsOn ?? [];
452
- return isStale(a4.seen, config, keys);
450
+ isStale(a6, config) {
451
+ const keys = targetOf(a6.target)?.positionDependsOn ?? [];
452
+ return isStale(a6.seen, config, keys);
453
453
  },
454
454
  canUndo() {
455
455
  return history.canUndo(historySceneAt);
@@ -487,7 +487,7 @@ function createAnnotationStore(opts) {
487
487
  for (const [target, scene] of scenes) {
488
488
  const next = wanted.get(target) ?? [];
489
489
  const now = scene.getSelection();
490
- if (now.length === next.length && next.every((n5, i4) => String(now[i4]) === n5)) continue;
490
+ if (now.length === next.length && next.every((n6, i5) => String(now[i5]) === n6)) continue;
491
491
  scene.setSelection(next.map(asNodeId$1));
492
492
  }
493
493
  },
@@ -592,7 +592,7 @@ function fitView(content, pane) {
592
592
  const zoom = content.w > 0 && content.h > 0 ? Math.min(pane.w / content.w, pane.h / content.h) : 1;
593
593
  return { zoom: Number.isFinite(zoom) && zoom > 0 ? zoom : 1, pan: { x: 0, y: 0 } };
594
594
  }
595
- var sameRect = (a4, b2) => a4 !== null && a4.x === b2.x && a4.y === b2.y && a4.w === b2.w && a4.h === b2.h;
595
+ var sameRect = (a6, b2) => a6 !== null && a6.x === b2.x && a6.y === b2.y && a6.w === b2.w && a6.h === b2.h;
596
596
  function ToolBridge({ toolId }) {
597
597
  const tools = useActiveToolContext();
598
598
  const setActive = tools.setActive;
@@ -731,13 +731,13 @@ function AnnotationOverlay({
731
731
  }
732
732
  ),
733
733
  canvas && input ? (
734
- // One scope per pane: a shared <ActionsProvider> lets only the newest
735
- // canvas under it respond to input, and the rest go silently dead.
734
+ // Isolated so each pane keeps its own selection and tool.
736
735
  /* @__PURE__ */ jsxs(WeaselProvider, { isolate: true, children: [
737
736
  /* @__PURE__ */ jsx(ToolBridge, { toolId: annotationToolInfo(activeToolId)?.weaselTool ?? "select" }),
738
737
  /* @__PURE__ */ jsx(
739
738
  SceneCanvas,
740
739
  {
740
+ features: ["pick", "move", "transform", "edit"],
741
741
  ref: attachSceneCanvas,
742
742
  scene,
743
743
  width: rect.w,
@@ -921,21 +921,28 @@ var interstellar_theme_default = {
921
921
  accent: {
922
922
  by: "mode",
923
923
  dark: {
924
- value: "#b08adb",
924
+ value: "#4f46e5",
925
925
  type: "color"
926
926
  }
927
927
  },
928
928
  "accent-hover": {
929
929
  by: "mode",
930
930
  dark: {
931
- value: "#c6a3ee",
931
+ value: "#6d5dfc",
932
+ type: "color"
933
+ }
934
+ },
935
+ "accent-strong": {
936
+ by: "mode",
937
+ dark: {
938
+ value: "#7474fe",
932
939
  type: "color"
933
940
  }
934
941
  },
935
942
  "focus-ring": {
936
943
  by: "mode",
937
944
  dark: {
938
- value: "rgba(176, 138, 219, 0.45)",
945
+ value: "rgba(116, 116, 254, 0.5)",
939
946
  type: "color"
940
947
  }
941
948
  },
@@ -968,6 +975,24 @@ var interstellarTheme = defineTheme({
968
975
  ...interstellar_theme_default,
969
976
  extends: weaselTheme
970
977
  });
978
+
979
+ // src/canvas/cameraZoom.ts
980
+ function atScale(view, scale, at) {
981
+ return {
982
+ x: view.x + at.x / view.scale.x - at.x / scale,
983
+ y: view.y + at.y / view.scale.y - at.y / scale,
984
+ scale: { x: scale, y: scale }
985
+ };
986
+ }
987
+ function viewMiddle(camera) {
988
+ const size = camera.hostSize?.();
989
+ return size ? { x: size.width / 2, y: size.height / 2 } : { x: 0, y: 0 };
990
+ }
991
+ function zoomCameraTo(camera, zoom) {
992
+ const { min, max } = camera.zoomRange();
993
+ const scale = Math.min(max, Math.max(min, zoom));
994
+ camera.set(atScale(camera.get(), scale, viewMiddle(camera)));
995
+ }
971
996
  function TrialBody({ sidebar, children, contentClassName, ...rest }) {
972
997
  return /* @__PURE__ */ jsx(
973
998
  Split,
@@ -1069,6 +1094,7 @@ function UndockedSections({ trialId, sections, onDock }) {
1069
1094
  var NO_OP = () => {
1070
1095
  };
1071
1096
  var NO_SECTIONS = Object.freeze({});
1097
+ var noSubscribe = () => NO_OP;
1072
1098
  function TrialChrome({
1073
1099
  trialId,
1074
1100
  record,
@@ -1087,15 +1113,15 @@ function TrialChrome({
1087
1113
  const lab = useLabContext();
1088
1114
  const storeCtx = useContext(LabStoreContext);
1089
1115
  if (!storeCtx) throw new Error("[labkit] TrialChrome requires <LabStoreProvider>");
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);
1116
+ const updateTrialView = useStore(storeCtx.store, (s2) => s2.updateTrialView);
1117
+ const updateTrialSidebarWidth = useStore(storeCtx.store, (s2) => s2.updateTrialSidebarWidth);
1118
+ const setTrialTitle = useStore(storeCtx.store, (s2) => s2.setTrialTitle);
1119
+ const setTrialSectionCollapsed = useStore(storeCtx.store, (s2) => s2.setTrialSectionCollapsed);
1120
+ const updateTrialConfig = useStore(storeCtx.store, (s2) => s2.updateTrialConfig);
1121
+ const updateTrialState = useStore(storeCtx.store, (s2) => s2.updateTrialState);
1122
+ const undockPanelAction = useStore(storeCtx.store, (s2) => s2.undockPanel);
1123
+ const dockPanelAction = useStore(storeCtx.store, (s2) => s2.dockPanel);
1124
+ const undockedPanels = useStore(storeCtx.store, (s2) => s2.undockedPanels);
1099
1125
  const undockedIds = useMemo(
1100
1126
  () => Object.values(undockedPanels).filter((p3) => p3.trialId === trialId).map((p3) => p3.sectionId),
1101
1127
  [undockedPanels, trialId]
@@ -1109,10 +1135,15 @@ function TrialChrome({
1109
1135
  );
1110
1136
  const title = record.title ?? instrument.title ?? instrument.name;
1111
1137
  const collapsedSections = record.collapsedSections ?? NO_SECTIONS;
1138
+ const cameras = useContext(CameraRegistryContext);
1139
+ const camera = useSyncExternalStore(
1140
+ cameras?.subscribe ?? noSubscribe,
1141
+ () => cameras?.get(trialId) ?? null
1142
+ );
1112
1143
  const ctx = useMemo(() => {
1113
- const setZoom = (z) => {
1114
- if (!view2d) return;
1115
- updateTrialView(trialId, withZoom(view2d, z));
1144
+ const setZoom = (z2) => {
1145
+ if (camera) zoomCameraTo(camera, z2);
1146
+ else if (view2d) updateTrialView(trialId, withZoom(view2d, z2));
1116
1147
  };
1117
1148
  return {
1118
1149
  trialId,
@@ -1152,7 +1183,7 @@ function TrialChrome({
1152
1183
  undockedPanels: undockedIds,
1153
1184
  undockPanel: (sectionId, as) => undockPanelAction(trialId, sectionId, as),
1154
1185
  dockPanel: (sectionId) => dockPanelAction(trialId, sectionId),
1155
- savedSnapshots: lab.savedSnapshots.filter((s4) => s4.trialId === trialId),
1186
+ savedSnapshots: lab.savedSnapshots.filter((s2) => s2.trialId === trialId),
1156
1187
  saveSnapshot: (name) => lab.saveSnapshot(trialId, name),
1157
1188
  loadSnapshot: (snapshotId) => lab.loadSnapshot(trialId, snapshotId),
1158
1189
  clone: () => lab.cloneTrial(trialId),
@@ -1184,7 +1215,8 @@ function TrialChrome({
1184
1215
  dockPanelAction,
1185
1216
  setTrialTitle,
1186
1217
  setTrialSectionCollapsed,
1187
- collapsedSections
1218
+ collapsedSections,
1219
+ camera
1188
1220
  ]);
1189
1221
  const contributions = useMemo(
1190
1222
  () => suppressContributions(
@@ -1268,9 +1300,9 @@ function Trial({ id, chrome, suppress }) {
1268
1300
  const lab = useLabContext();
1269
1301
  const storeCtx = useContext(LabStoreContext);
1270
1302
  if (!storeCtx) throw new Error("[labkit] <Trial> requires <LabStoreProvider>");
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;
1303
+ const instruments = useStore(storeCtx.store, (s2) => s2.instruments) ?? lab.instruments;
1304
+ const record = useStore(storeCtx.store, (s2) => s2.trials.find((w2) => w2.id === id));
1305
+ const instrument = record ? instruments.find((i5) => i5.name === record.instrumentName) : void 0;
1274
1306
  const kept = useKeptMarks(instrument?.annotations?.storage, id);
1275
1307
  if (!record) {
1276
1308
  return /* @__PURE__ */ jsxs("div", { className: "lk-trial lk-trial--unknown", children: [
@@ -1334,17 +1366,23 @@ function TrialRuntime({
1334
1366
  suppress
1335
1367
  }) {
1336
1368
  const wheelSlot = useRef(null);
1369
+ const cameras = useContext(CameraRegistryContext);
1370
+ const trialId = record.id;
1371
+ const publishCamera = useMemo(
1372
+ () => cameras ? (camera) => cameras.register(trialId, camera) : null,
1373
+ [cameras, trialId]
1374
+ );
1337
1375
  const [pointer] = useState(createPointerStore);
1338
1376
  const canvasContainerRef = useRef(null);
1339
1377
  const loupeHostRef = useRef(null);
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);
1378
+ const updateTrialState = useStore(store, (s2) => s2.updateTrialState);
1379
+ const updateTrialConfig = useStore(store, (s2) => s2.updateTrialConfig);
1380
+ const updateTrialView = useStore(store, (s2) => s2.updateTrialView);
1381
+ const updateTrialUndoStack = useStore(store, (s2) => s2.updateTrialUndoStack);
1382
+ const updateTrialAnnotations = useStore(store, (s2) => s2.updateTrialAnnotations);
1383
+ const labToolId = useStore(store, (s2) => s2.activeToolId);
1384
+ const setLabTool = useStore(store, (s2) => s2.setLabTool);
1385
+ const setTrialTool = useStore(store, (s2) => s2.setTrialTool);
1348
1386
  const schema = useConfigSchema(instrument);
1349
1387
  const { config } = useResolvedConfig(schema, record.config, record.auto);
1350
1388
  const busRef = useRef(null);
@@ -1354,7 +1392,7 @@ function TrialRuntime({
1354
1392
  const [layerOrder, setLayerOrder] = useState(null);
1355
1393
  const [loupeOn, setLoupeOn] = useState(false);
1356
1394
  const visibleLayers = useMemo(
1357
- () => (instrument.canvas?.layers ?? []).filter((l8) => layerVisibility[l8.id] !== false).map((l8) => l8.id),
1395
+ () => (instrument.canvas?.layers ?? []).filter((l7) => layerVisibility[l7.id] !== false).map((l7) => l7.id),
1358
1396
  [instrument.canvas, layerVisibility]
1359
1397
  );
1360
1398
  const undoCap = instrument.undo;
@@ -1469,9 +1507,9 @@ function TrialRuntime({
1469
1507
  view: record.view,
1470
1508
  setView,
1471
1509
  zoom: view2d?.zoom ?? 1,
1472
- setZoom: (z) => {
1510
+ setZoom: (z2) => {
1473
1511
  if (!view2d) return;
1474
- updateTrialView(record.id, withZoom(view2d, z));
1512
+ updateTrialView(record.id, withZoom(view2d, z2));
1475
1513
  },
1476
1514
  activeToolId: resolvedToolId,
1477
1515
  visibleLayers,
@@ -1516,7 +1554,7 @@ function TrialRuntime({
1516
1554
  const canvasLayers = useMemo(() => {
1517
1555
  if (!instrument.canvas) return [];
1518
1556
  const baseLayers = instrument.canvas.layers;
1519
- const ordered = layerOrder ? [...baseLayers].sort((a4, b2) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b2.id)) : baseLayers;
1557
+ const ordered = layerOrder ? [...baseLayers].sort((a6, b2) => layerOrder.indexOf(a6.id) - layerOrder.indexOf(b2.id)) : baseLayers;
1520
1558
  return ordered.map((layer) => ({
1521
1559
  id: layer.id,
1522
1560
  visible: layerVisibility[layer.id] !== false,
@@ -1528,23 +1566,23 @@ function TrialRuntime({
1528
1566
  }, [instrument.canvas, record.state, config, layerVisibility, layerOrder]);
1529
1567
  const layerDescriptors = useMemo(() => {
1530
1568
  if (!instrument.layers) return [];
1531
- return instrument.layers.ids.map((l8) => typeof l8 === "string" ? { id: l8, label: l8 } : l8);
1569
+ return instrument.layers.ids.map((l7) => typeof l7 === "string" ? { id: l7, label: l7 } : l7);
1532
1570
  }, [instrument.layers]);
1533
1571
  const layerItems = useMemo(() => {
1534
- const ordered = layerOrder ? [...layerDescriptors].sort((a4, b2) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b2.id)) : layerDescriptors;
1572
+ const ordered = layerOrder ? [...layerDescriptors].sort((a6, b2) => layerOrder.indexOf(a6.id) - layerOrder.indexOf(b2.id)) : layerDescriptors;
1535
1573
  const pinnedLast = [
1536
- ...ordered.filter((l8) => !l8.alwaysOn),
1537
- ...ordered.filter((l8) => l8.alwaysOn)
1574
+ ...ordered.filter((l7) => !l7.alwaysOn),
1575
+ ...ordered.filter((l7) => l7.alwaysOn)
1538
1576
  ];
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
1577
+ return pinnedLast.map((l7) => ({
1578
+ id: l7.id,
1579
+ label: l7.label,
1580
+ locked: l7.alwaysOn === true,
1581
+ visible: l7.alwaysOn === true || layerVisibility[l7.id] !== false
1544
1582
  }));
1545
1583
  }, [layerDescriptors, layerOrder, layerVisibility]);
1546
1584
  const dragDropResult = useDragDrop({
1547
- capability: instrument.dragDrop ?? { palette: [], onDrop: (_p, _i, s4) => s4 },
1585
+ capability: instrument.dragDrop ?? { palette: [], onDrop: (_p, _i, s2) => s2 },
1548
1586
  canvasContainerRef,
1549
1587
  view: view2d ?? DEFAULT_VIEW,
1550
1588
  worldSpec: instrument.canvas?.worldSpec,
@@ -1654,11 +1692,11 @@ function TrialRuntime({
1654
1692
  );
1655
1693
  const layerListNode = useMemo(
1656
1694
  () => instrument.layers && layerDescriptors.length > 0 ? /* @__PURE__ */ jsx(
1657
- D,
1695
+ E3,
1658
1696
  {
1659
1697
  items: layerItems,
1660
1698
  onReorder: (move) => {
1661
- setLayerOrder(S2(layerItems, move).map((l8) => l8.id));
1699
+ setLayerOrder(x3(layerItems, move).map((l7) => l7.id));
1662
1700
  bus.emit("layers.reorder");
1663
1701
  },
1664
1702
  onVisibilityChange: (lid, visible) => {
@@ -1698,7 +1736,7 @@ function TrialRuntime({
1698
1736
  activeToolId: labTool
1699
1737
  }
1700
1738
  ) : null;
1701
- const scopedBody = /* @__PURE__ */ jsx(WeaselProvider, { isolate: true, children: /* @__PURE__ */ jsx(PointerContextProvider, { store: pointer, children: /* @__PURE__ */ jsx(CameraScopeContext.Provider, { value: true, children: body }) }) });
1739
+ const scopedBody = /* @__PURE__ */ jsx(WeaselProvider, { isolate: true, children: /* @__PURE__ */ jsx(PointerContextProvider, { store: pointer, children: /* @__PURE__ */ jsx(CameraPublishContext.Provider, { value: publishCamera, children: body }) }) });
1702
1740
  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(
1703
1741
  TrialChrome,
1704
1742
  {
@@ -1725,7 +1763,7 @@ function TrialRuntime({
1725
1763
  // src/trial/trialOps.ts
1726
1764
  var DEFAULT_VIEW2 = { zoom: 1, pan: { x: 0, y: 0 } };
1727
1765
  function findInstrument(instruments, name) {
1728
- const found = instruments.find((i4) => i4.name === name);
1766
+ const found = instruments.find((i5) => i5.name === name);
1729
1767
  if (!found) {
1730
1768
  throw new Error(`[labkit] Unknown instrument: "${name}"`);
1731
1769
  }
@@ -1836,10 +1874,10 @@ function findOvershoot(bound, items, tolerance = 1) {
1836
1874
  let worst = null;
1837
1875
  for (const { item, edges } of items) {
1838
1876
  const y3 = edges.bottom - bound.bottom;
1839
- const x2 = edges.right - bound.right;
1840
- const by = Math.max(x2, y3);
1877
+ const x3 = edges.right - bound.right;
1878
+ const by = Math.max(x3, y3);
1841
1879
  if (by <= tolerance) continue;
1842
- if (!worst || by > worst.by) worst = { item, by, axis: y3 >= x2 ? "y" : "x" };
1880
+ if (!worst || by > worst.by) worst = { item, by, axis: y3 >= x3 ? "y" : "x" };
1843
1881
  }
1844
1882
  return worst;
1845
1883
  }
@@ -1915,37 +1953,30 @@ function useLabFitWarning(labBody) {
1915
1953
  function LabHeader({ addTrial: addTrial2 = true }) {
1916
1954
  const lab = useLabContext();
1917
1955
  const only = lab.instruments.length === 1 ? lab.instruments[0] : null;
1918
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1919
- !addTrial2 ? null : only ? /* @__PURE__ */ jsxs(
1920
- "button",
1921
- {
1922
- type: "button",
1923
- className: "lk-lab-header__add",
1924
- onClick: () => lab.addTrial(only.name),
1925
- children: [
1926
- /* @__PURE__ */ jsx(G, { size: 16 }),
1927
- /* @__PURE__ */ jsx("span", { children: "Add trial" })
1928
- ]
1929
- }
1930
- ) : /* @__PURE__ */ jsx(
1931
- d2,
1932
- {
1933
- "aria-label": "Add trial",
1934
- label: "Add trial\u2026",
1935
- items: lab.instruments.map((i4) => ({ value: i4.name, label: i4.title ?? i4.name })),
1936
- onAction: (name) => lab.addTrial(name)
1937
- }
1938
- ),
1939
- /* @__PURE__ */ jsx(
1940
- s3,
1941
- {
1942
- className: "lk-lab-header__mode",
1943
- variant: "flat",
1944
- value: lab.mode,
1945
- onChange: lab.setMode
1946
- }
1947
- )
1948
- ] });
1956
+ return /* @__PURE__ */ jsx(Fragment, { children: !addTrial2 ? null : only ? /* @__PURE__ */ jsxs(
1957
+ "button",
1958
+ {
1959
+ type: "button",
1960
+ className: "lk-lab-header__add",
1961
+ onClick: () => lab.addTrial(only.name),
1962
+ children: [
1963
+ /* @__PURE__ */ jsx(G, { size: 16 }),
1964
+ /* @__PURE__ */ jsx("span", { children: "Add trial" })
1965
+ ]
1966
+ }
1967
+ ) : /* @__PURE__ */ jsx(
1968
+ d3,
1969
+ {
1970
+ "aria-label": "Add trial",
1971
+ label: "Add trial\u2026",
1972
+ items: lab.instruments.map((i5) => ({ value: i5.name, label: i5.title ?? i5.name })),
1973
+ onAction: (name) => lab.addTrial(name)
1974
+ }
1975
+ ) });
1976
+ }
1977
+ function LabThemeSwitcher() {
1978
+ const lab = useLabContext();
1979
+ return /* @__PURE__ */ jsx(o3, { value: lab.mode, onChange: lab.setMode });
1949
1980
  }
1950
1981
  function LabPalette({ tools, contributions }) {
1951
1982
  const ctx = useLabChromeContext();
@@ -2023,13 +2054,13 @@ function LabSwitcher({ title, pages, path, className }) {
2023
2054
  ]
2024
2055
  }
2025
2056
  ) }),
2026
- open && /* @__PURE__ */ jsx("div", { className: "lk-switcher-menu", id: menuId, role: "menu", children: pages.map((page, i4) => /* @__PURE__ */ jsx(
2057
+ open && /* @__PURE__ */ jsx("div", { className: "lk-switcher-menu", id: menuId, role: "menu", children: pages.map((page, i5) => /* @__PURE__ */ jsx(
2027
2058
  "a",
2028
2059
  {
2029
2060
  href: page.href,
2030
2061
  role: "menuitem",
2031
2062
  className: "lk-switcher-item",
2032
- "aria-current": i4 === here ? "page" : void 0,
2063
+ "aria-current": i5 === here ? "page" : void 0,
2033
2064
  onClick: close,
2034
2065
  children: page.label
2035
2066
  },
@@ -2064,6 +2095,110 @@ function LabShell({
2064
2095
  footer && /* @__PURE__ */ jsx("footer", { className: "lk-shell-footer", children: footer })
2065
2096
  ] });
2066
2097
  }
2098
+ var ZOOM_ID = "viewport.zoom";
2099
+ var NO_TOOLS = /* @__PURE__ */ new Map();
2100
+ var CHANNELS = { contextMenu: false, ingest: false };
2101
+ var NO_ELEMENT = { current: null };
2102
+ var BASE = makeViewportZoomAction({ min: 1e-9, max: Number.POSITIVE_INFINITY });
2103
+ var KEY_BINDINGS = BASE.defaultBinding.filter((b2) => b2.spec.kind === "key");
2104
+ function shortcutFor(kind) {
2105
+ const spec = KEY_BINDINGS.find((b2) => b2.opts?.params?.kind === kind)?.spec;
2106
+ return spec?.key ? n2({ key: spec.key, mod: spec.mods?.mod }) : void 0;
2107
+ }
2108
+ function forZoom(camera) {
2109
+ return {
2110
+ get: camera.get,
2111
+ set: camera.set,
2112
+ hostSize: camera.hostSize,
2113
+ recenter: () => atScale(camera.get(), 1, viewMiddle(camera))
2114
+ };
2115
+ }
2116
+ var percent = new Intl.NumberFormat(void 0, { style: "percent", maximumFractionDigits: 0 });
2117
+ function LabZoom() {
2118
+ return /* @__PURE__ */ jsx(DepRegistryProvider, { children: /* @__PURE__ */ jsx(ActionsProvider, { children: /* @__PURE__ */ jsx(ActiveToolContextProvider, { children: /* @__PURE__ */ jsx(LabZoomControls, {}) }) }) });
2119
+ }
2120
+ function LabZoomControls() {
2121
+ const registry = useActionsRegistry();
2122
+ const { focusedTrialId } = useLabContext();
2123
+ const cameras = useContext(CameraRegistryContext);
2124
+ const storeCtx = useContext(LabStoreContext);
2125
+ if (!storeCtx) throw new Error("[labkit] <LabZoom> requires <LabStoreProvider>");
2126
+ const camera = useSyncExternalStore(
2127
+ cameras?.subscribe ?? noSubscribe2,
2128
+ () => cameras && focusedTrialId ? cameras.get(focusedTrialId) : null
2129
+ );
2130
+ const zoom = useStore(storeCtx.store, (s2) => {
2131
+ const record = s2.trials.find((t) => t.id === focusedTrialId);
2132
+ return as2DView(record?.view)?.zoom ?? null;
2133
+ });
2134
+ const live = zoom !== null && camera !== null;
2135
+ const view = useMemo(() => camera ? forZoom(camera) : null, [camera]);
2136
+ const viewRef = useRef(view);
2137
+ viewRef.current = live ? view : null;
2138
+ useDepSource("view", () => viewRef.current);
2139
+ useEffect(() => {
2140
+ const action = {
2141
+ ...BASE,
2142
+ defaultBinding: KEY_BINDINGS,
2143
+ enabled: () => viewRef.current ? true : ActionDisabledReason.NotApplicable
2144
+ };
2145
+ return registry.register(action);
2146
+ }, [registry]);
2147
+ useGestureDispatcher({
2148
+ canvasRef: NO_ELEMENT,
2149
+ actions: registry,
2150
+ entriesById: NO_TOOLS,
2151
+ channels: CHANNELS,
2152
+ keyboard: "first"
2153
+ });
2154
+ const range = camera?.zoomRange();
2155
+ const canIn = zoom !== null && range !== void 0 && zoom < range.max * (1 - 1e-9);
2156
+ const canOut = zoom !== null && range !== void 0 && zoom > range.min * (1 + 1e-9);
2157
+ const run = (kind) => () => {
2158
+ registry.trigger(ZOOM_ID, { kind });
2159
+ };
2160
+ const hint = (label, kind) => {
2161
+ const keys = shortcutFor(kind);
2162
+ return keys ? `${label} (${keys})` : label;
2163
+ };
2164
+ const shown = live && zoom !== null ? percent.format(zoom) : null;
2165
+ return /* @__PURE__ */ jsx(Toolbar, { "aria-label": "Zoom", children: /* @__PURE__ */ jsxs(Toolbar.Group, { "aria-label": "Zoom", children: [
2166
+ /* @__PURE__ */ jsx(
2167
+ Toolbar.Button,
2168
+ {
2169
+ iconOnly: true,
2170
+ "aria-label": "Zoom out",
2171
+ title: hint("Zoom out", "out"),
2172
+ disabled: !canOut,
2173
+ onClick: run("out"),
2174
+ children: /* @__PURE__ */ jsx(X, { size: 16 })
2175
+ }
2176
+ ),
2177
+ /* @__PURE__ */ jsx(
2178
+ Toolbar.Button,
2179
+ {
2180
+ "aria-label": shown ? `Zoom ${shown} \u2014 reset to actual size` : "Zoom unavailable",
2181
+ title: live ? hint("Actual size", "reset") : "This trial has no camera",
2182
+ disabled: !live,
2183
+ onClick: run("reset"),
2184
+ children: /* @__PURE__ */ jsx("span", { className: "lk-lab-zoom__readout", children: shown ?? "\u2013" })
2185
+ }
2186
+ ),
2187
+ /* @__PURE__ */ jsx(
2188
+ Toolbar.Button,
2189
+ {
2190
+ iconOnly: true,
2191
+ "aria-label": "Zoom in",
2192
+ title: hint("Zoom in", "in"),
2193
+ disabled: !canIn,
2194
+ onClick: run("in"),
2195
+ children: /* @__PURE__ */ jsx(U, { size: 16 })
2196
+ }
2197
+ )
2198
+ ] }) });
2199
+ }
2200
+ var noSubscribe2 = () => () => {
2201
+ };
2067
2202
  var ZONE_ID = asNodeId("lk-workspace");
2068
2203
  var STRATEGIES = { grid: gridStrategy, floating: floatingStrategy };
2069
2204
  var FLOAT_ZONE_ID = asNodeId("lk-workspace-floating");
@@ -2098,7 +2233,7 @@ function Workspace({
2098
2233
  const tilePanels = useMemo(() => (panels ?? []).filter((p3) => p3.as === "tile"), [panels]);
2099
2234
  const floatPanels = useMemo(() => (panels ?? []).filter((p3) => p3.as === "floating"), [panels]);
2100
2235
  const wantedIds = [
2101
- ...items.map((_2, i4) => ids?.[i4] ?? `lk-ws-${i4}`),
2236
+ ...items.map((_3, i5) => ids?.[i5] ?? `lk-ws-${i5}`),
2102
2237
  ...tilePanels.map((p3) => `lk-panel-${p3.key}`)
2103
2238
  ];
2104
2239
  const idKey = wantedIds.join(",");
@@ -2174,7 +2309,7 @@ function Workspace({
2174
2309
  [onReorder]
2175
2310
  );
2176
2311
  const chrome = useMemo(() => {
2177
- const byId = new Map(nodeIds.map((id, i4) => [id, items[i4]]));
2312
+ const byId = new Map(nodeIds.map((id, i5) => [id, items[i5]]));
2178
2313
  const panelByNode = new Map(
2179
2314
  tilePanels.map((p3) => [`lk-panel-${p3.key}`, p3])
2180
2315
  );
@@ -2240,7 +2375,7 @@ async function openStoredLab({ instruments, defaultInstrument, mode }, storageKe
2240
2375
  const marks = /* @__PURE__ */ new Map();
2241
2376
  await Promise.all(
2242
2377
  opened.store.getState().trials.map(async (trial) => {
2243
- const kept = instruments.find((i4) => i4.name === trial.instrumentName)?.annotations?.storage;
2378
+ const kept = instruments.find((i5) => i5.name === trial.instrumentName)?.annotations?.storage;
2244
2379
  if (!kept) return;
2245
2380
  try {
2246
2381
  marks.set(trial.id, await kept.load());
@@ -2289,10 +2424,10 @@ var NEBULA_SLOTS = [
2289
2424
  ];
2290
2425
  function buildNebula(list, theme, mode, density) {
2291
2426
  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];
2427
+ const n6 = colorCount(list, ctx) ?? NEBULA_SLOTS.length;
2428
+ const colors = Array.from({ length: n6 }, (_3, i5) => colorAt(list, i5, ctx));
2429
+ const blobs = colors.map((c6, i5) => {
2430
+ const p3 = NEBULA_SLOTS[i5 % NEBULA_SLOTS.length];
2296
2431
  return `radial-gradient(ellipse ${p3.sx} ${p3.sy} at ${p3.cx} ${p3.cy}, color-mix(in srgb, ${c6} 22%, transparent), transparent ${p3.stop})`;
2297
2432
  });
2298
2433
  blobs.push("radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)");
@@ -2389,6 +2524,7 @@ function LabRuntime({
2389
2524
  labChrome,
2390
2525
  suppress,
2391
2526
  addTrial: addTrial2,
2527
+ zoom = true,
2392
2528
  tools,
2393
2529
  configRules,
2394
2530
  controls,
@@ -2399,13 +2535,14 @@ function LabRuntime({
2399
2535
  useLayoutEffect(() => {
2400
2536
  store.getState().setInstruments(instruments);
2401
2537
  }, [instruments, store]);
2402
- const trials = useStore(store, (s4) => s4.trials);
2538
+ const trials = useStore(store, (s2) => s2.trials);
2539
+ const [cameras] = useState(createCameraRegistry);
2403
2540
  const [focusPick, setFocusPick] = useState(null);
2404
2541
  const focusedTrialId = trials.some((t) => t.id === focusPick) ? focusPick : trials[0]?.id ?? null;
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);
2542
+ const savedSnapshots = useStore(store, (s2) => s2.savedSnapshots);
2543
+ const modeValue = useStore(store, (s2) => s2.mode);
2544
+ const layout = useStore(store, (s2) => s2.layout);
2545
+ const undockedPanels = useStore(store, (s2) => s2.undockedPanels);
2409
2546
  const panelHostsRef = useRef(null);
2410
2547
  if (panelHostsRef.current === null) panelHostsRef.current = createPanelHostRegistry();
2411
2548
  const outerSurface = useSurfaceOptional();
@@ -2545,15 +2682,15 @@ function LabRuntime({
2545
2682
  const next = resetTrial(store.getState().trials, id, instruments);
2546
2683
  const record = next.find((w2) => w2.id === id);
2547
2684
  if (!record) return;
2548
- store.setState((s4) => ({
2549
- trials: s4.trials.map(
2685
+ store.setState((s2) => ({
2686
+ trials: s2.trials.map(
2550
2687
  (w2) => w2.id === id ? { ...w2, config: record.config, state: record.state, view: record.view } : w2
2551
2688
  )
2552
2689
  }));
2553
2690
  },
2554
2691
  savedSnapshots,
2555
2692
  saveSnapshot: (trialId, name) => {
2556
- const taken = store.getState().savedSnapshots.filter((s4) => s4.trialId === trialId).length;
2693
+ const taken = store.getState().savedSnapshots.filter((s2) => s2.trialId === trialId).length;
2557
2694
  store.getState().saveSnapshot(trialId, name ?? `Snapshot ${taken + 1}`);
2558
2695
  },
2559
2696
  loadSnapshot: (trialId, snapshotId) => {
@@ -2600,7 +2737,7 @@ function LabRuntime({
2600
2737
  children: trials.map((w2) => /* @__PURE__ */ jsx(Trial, { id: w2.id, chrome, suppress }, w2.id))
2601
2738
  }
2602
2739
  );
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(
2740
+ 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(CameraRegistryContext.Provider, { value: cameras, children: /* @__PURE__ */ jsx(
2604
2741
  ThemeProvider,
2605
2742
  {
2606
2743
  theme,
@@ -2620,8 +2757,10 @@ function LabRuntime({
2620
2757
  ] }) : footer,
2621
2758
  header: /* @__PURE__ */ jsxs(Fragment, { children: [
2622
2759
  /* @__PURE__ */ jsx(LabHeader, { ...addTrial2 !== void 0 ? { addTrial: addTrial2 } : {} }),
2760
+ zoom ? /* @__PURE__ */ jsx(LabZoom, {}) : null,
2623
2761
  children,
2624
- /* @__PURE__ */ jsx(LabHeaderRegion, { contributions: labChromeAll })
2762
+ /* @__PURE__ */ jsx(LabHeaderRegion, { contributions: labChromeAll }),
2763
+ /* @__PURE__ */ jsx(LabThemeSwitcher, {})
2625
2764
  ] }),
2626
2765
  children: /* @__PURE__ */ jsx(PanelHostContext.Provider, { value: panelHostsRef.current, children: /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: surface, children: /* @__PURE__ */ jsx(SurfaceCanvasContext.Provider, { value: surfaceCanvases, children: /* @__PURE__ */ jsxs("div", { className: "lk-lab__body", ref: labBodyRef, children: [
2627
2766
  outerSurface ? null : (
@@ -2664,7 +2803,7 @@ function LabRuntime({
2664
2803
  }
2665
2804
  )
2666
2805
  }
2667
- ) }) }) }) });
2806
+ ) }) }) }) }) });
2668
2807
  }
2669
2808
  function LabBoundary({ children }) {
2670
2809
  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 }) }) }) }) }) }) }) }) }) }) }) }) });
@@ -2769,25 +2908,25 @@ function ButtonsAndToggles() {
2769
2908
  /* @__PURE__ */ jsx(c, { variant: "secondary", iconOnly: true, ariaLabel: "Add", children: /* @__PURE__ */ jsx(Dot, {}) })
2770
2909
  ] }) }),
2771
2910
  /* @__PURE__ */ jsx(Cell, { label: "Badge", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
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" })
2911
+ /* @__PURE__ */ jsx(Xt, { shape: "pill", status: "accent", variant: "outline", size: "sm", children: "ACCENT" }),
2912
+ /* @__PURE__ */ jsx(Xt, { status: "info", variant: "subtle", children: "INFO" }),
2913
+ /* @__PURE__ */ jsx(Xt, { status: "warn", variant: "solid", children: "WARN" }),
2914
+ /* @__PURE__ */ jsx(Xt, { status: "danger", variant: "solid", children: "DANGER" }),
2915
+ /* @__PURE__ */ jsx(Xt, { status: "muted", children: "MUTED" })
2777
2916
  ] }) }),
2778
2917
  /* @__PURE__ */ jsx(Cell, { label: "Checkbox, Switch", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
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" })
2918
+ /* @__PURE__ */ jsx(o5, { isSelected: snap, onChange: setSnap, children: "Snap to grid" }),
2919
+ /* @__PURE__ */ jsx(o5, { isIndeterminate: true, children: "Mixed" }),
2920
+ /* @__PURE__ */ jsx(a8, { isSelected: wifi, onChange: setWifi, children: "Wifi" })
2782
2921
  ] }) }),
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" })
2922
+ /* @__PURE__ */ jsx(Cell, { label: "RadioGroup", children: /* @__PURE__ */ jsxs(l4, { label: "Snap mode", orientation: "horizontal", defaultValue: "grid", children: [
2923
+ /* @__PURE__ */ jsx(u4, { value: "off", children: "Off" }),
2924
+ /* @__PURE__ */ jsx(u4, { value: "grid", children: "Grid" }),
2925
+ /* @__PURE__ */ jsx(u4, { value: "pixel", children: "Pixel" })
2787
2926
  ] }) }),
2788
2927
  /* @__PURE__ */ jsxs(Cell, { label: "ToggleBar", children: [
2789
2928
  /* @__PURE__ */ jsx(
2790
- a5,
2929
+ a7,
2791
2930
  {
2792
2931
  ariaLabel: "Align",
2793
2932
  value: align,
@@ -2800,7 +2939,7 @@ function ButtonsAndToggles() {
2800
2939
  }
2801
2940
  ),
2802
2941
  /* @__PURE__ */ jsx(
2803
- a5,
2942
+ a7,
2804
2943
  {
2805
2944
  ariaLabel: "Align, flat",
2806
2945
  variant: "flat",
@@ -2826,7 +2965,7 @@ function ButtonsAndToggles() {
2826
2965
  }
2827
2966
  ),
2828
2967
  /* @__PURE__ */ jsx(
2829
- a7,
2968
+ a10,
2830
2969
  {
2831
2970
  items: [
2832
2971
  { value: "undo", label: "Undo", onAction: () => {
@@ -2839,7 +2978,7 @@ function ButtonsAndToggles() {
2839
2978
  ] }) }),
2840
2979
  /* @__PURE__ */ jsx(Cell, { label: "MenuButton, Disclosure", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2841
2980
  /* @__PURE__ */ jsx(
2842
- d2,
2981
+ d3,
2843
2982
  {
2844
2983
  label: "Add trial\u2026",
2845
2984
  onAction: () => {
@@ -2850,17 +2989,17 @@ function ButtonsAndToggles() {
2850
2989
  ]
2851
2990
  }
2852
2991
  ),
2853
- /* @__PURE__ */ jsx(i2, { open, onToggle: () => setOpen((o4) => !o4), label: "Shapes" })
2992
+ /* @__PURE__ */ jsx(i2, { open, onToggle: () => setOpen((o5) => !o5), label: "Shapes" })
2854
2993
  ] }) }),
2855
- /* @__PURE__ */ jsx(Cell, { label: "Tabs", children: /* @__PURE__ */ jsxs(o5, { children: [
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" })
2994
+ /* @__PURE__ */ jsx(Cell, { label: "Tabs", children: /* @__PURE__ */ jsxs(o6, { children: [
2995
+ /* @__PURE__ */ jsxs(s4, { "aria-label": "Sections", children: [
2996
+ /* @__PURE__ */ jsx(c6, { id: "props", children: "Props" }),
2997
+ /* @__PURE__ */ jsx(c6, { id: "events", children: "Events" }),
2998
+ /* @__PURE__ */ jsx(c6, { id: "snapshot", children: "Snapshot" })
2860
2999
  ] }),
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." })
3000
+ /* @__PURE__ */ jsx(l6, { id: "props", children: "Props panel." }),
3001
+ /* @__PURE__ */ jsx(l6, { id: "events", children: "Events panel." }),
3002
+ /* @__PURE__ */ jsx(l6, { id: "snapshot", children: "Snapshot panel." })
2864
3003
  ] }) }),
2865
3004
  /* @__PURE__ */ jsx(Cell, { label: "Keycaps", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
2866
3005
  /* @__PURE__ */ jsx(p, { keys: [{ label: "\u2318" }, { label: "\u21E7" }, { label: "K" }], separator: "+" }),
@@ -2886,9 +3025,9 @@ function FieldsAndPickers() {
2886
3025
  const [paint, setPaint] = useState({ fill: "solid", color: "#b08adb" });
2887
3026
  return /* @__PURE__ */ jsxs(Section, { title: "Fields & pickers", children: [
2888
3027
  /* @__PURE__ */ jsxs(Cell, { label: "Input", children: [
2889
- /* @__PURE__ */ jsx(u4, { label: "Name", placeholder: "e.g. Pico" }),
3028
+ /* @__PURE__ */ jsx(u3, { label: "Name", placeholder: "e.g. Pico" }),
2890
3029
  /* @__PURE__ */ jsx(
2891
- u4,
3030
+ u3,
2892
3031
  {
2893
3032
  label: "Size",
2894
3033
  leadingAdornment: /* @__PURE__ */ jsx("span", { children: "W" }),
@@ -2896,12 +3035,12 @@ function FieldsAndPickers() {
2896
3035
  defaultValue: "120"
2897
3036
  }
2898
3037
  ),
2899
- /* @__PURE__ */ jsx(u4, { label: "Required", isInvalid: true, errorMessage: "Name is required." })
3038
+ /* @__PURE__ */ jsx(u3, { label: "Required", isInvalid: true, errorMessage: "Name is required." })
2900
3039
  ] }),
2901
3040
  /* @__PURE__ */ jsxs(Cell, { label: "NumberField, Select, ComboBox", children: [
2902
- /* @__PURE__ */ jsx(g, { label: "Opacity", minValue: 0, maxValue: 100, step: 5, defaultValue: 80 }),
3041
+ /* @__PURE__ */ jsx(y, { label: "Opacity", minValue: 0, maxValue: 100, step: 5, defaultValue: 80 }),
2903
3042
  /* @__PURE__ */ jsx(
2904
- T,
3043
+ E2,
2905
3044
  {
2906
3045
  label: "Color",
2907
3046
  defaultSelectedKey: "g",
@@ -2925,9 +3064,9 @@ function FieldsAndPickers() {
2925
3064
  )
2926
3065
  ] }),
2927
3066
  /* @__PURE__ */ jsxs(Cell, { label: "RangeSlider, Slider", children: [
2928
- /* @__PURE__ */ jsx(l8, { label: "Range", defaultValue: [20, 80], minValue: 0, maxValue: 100 }),
3067
+ /* @__PURE__ */ jsx(l7, { label: "Range", defaultValue: [20, 80], minValue: 0, maxValue: 100 }),
2929
3068
  /* @__PURE__ */ jsx(
2930
- l8,
3069
+ l7,
2931
3070
  {
2932
3071
  label: "Opacity",
2933
3072
  defaultValue: 75,
@@ -2937,7 +3076,7 @@ function FieldsAndPickers() {
2937
3076
  }
2938
3077
  ),
2939
3078
  /* @__PURE__ */ jsx(
2940
- y,
3079
+ S,
2941
3080
  {
2942
3081
  ariaLabel: "Pair",
2943
3082
  min: 0,
@@ -2952,7 +3091,7 @@ function FieldsAndPickers() {
2952
3091
  ] }),
2953
3092
  /* @__PURE__ */ jsxs(Cell, { label: "DetentSlider, InlineRange", children: [
2954
3093
  /* @__PURE__ */ jsx(
2955
- c6,
3094
+ c7,
2956
3095
  {
2957
3096
  items: [0.25, 0.5, 1, 2, 4],
2958
3097
  value: rate,
@@ -2963,7 +3102,7 @@ function FieldsAndPickers() {
2963
3102
  }
2964
3103
  ),
2965
3104
  /* @__PURE__ */ jsx(
2966
- i3,
3105
+ i4,
2967
3106
  {
2968
3107
  "aria-label": "Width",
2969
3108
  min: 0,
@@ -2974,11 +3113,11 @@ function FieldsAndPickers() {
2974
3113
  )
2975
3114
  ] }),
2976
3115
  /* @__PURE__ */ jsxs(Cell, { label: "ColorField, GradientEditor", children: [
2977
- /* @__PURE__ */ jsx(l4, { value: color, alpha: true, onInput: setColor, onChange: setColor, "aria-label": "Color" }),
2978
- /* @__PURE__ */ jsx(C2, { value: gradient, onInput: setGradient, onChange: setGradient, kindSwitch: true })
3116
+ /* @__PURE__ */ jsx(f3, { value: color, alpha: true, onInput: setColor, onChange: setColor, "aria-label": "Color" }),
3117
+ /* @__PURE__ */ jsx(D, { value: gradient, onInput: setGradient, onChange: setGradient, kindSwitch: true })
2979
3118
  ] }),
2980
3119
  /* @__PURE__ */ jsx(Cell, { label: "PaintInput", children: /* @__PURE__ */ jsx(
2981
- S,
3120
+ T,
2982
3121
  {
2983
3122
  value: paint,
2984
3123
  onInput: setPaint,
@@ -3007,9 +3146,9 @@ function PanelsAndRows() {
3007
3146
  ]);
3008
3147
  const [panelCollapsed, setPanelCollapsed] = useState(false);
3009
3148
  return /* @__PURE__ */ jsxs(Section, { title: "Panels & property rows", children: [
3010
- /* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(ae2, { title: "Shape", children: /* @__PURE__ */ jsxs(oe, { children: [
3149
+ /* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(re2, { title: "Shape", children: /* @__PURE__ */ jsxs(ie2, { children: [
3011
3150
  /* @__PURE__ */ jsx(
3012
- B2,
3151
+ R,
3013
3152
  {
3014
3153
  kind: "number",
3015
3154
  control: "slider",
@@ -3022,7 +3161,7 @@ function PanelsAndRows() {
3022
3161
  }
3023
3162
  ),
3024
3163
  /* @__PURE__ */ jsx(
3025
- B2,
3164
+ R,
3026
3165
  {
3027
3166
  kind: "number",
3028
3167
  control: "slider",
@@ -3035,7 +3174,7 @@ function PanelsAndRows() {
3035
3174
  }
3036
3175
  ),
3037
3176
  /* @__PURE__ */ jsx(
3038
- B2,
3177
+ R,
3039
3178
  {
3040
3179
  kind: "color",
3041
3180
  label: "Fill",
@@ -3045,9 +3184,9 @@ function PanelsAndRows() {
3045
3184
  onAlphaChange: setAlpha
3046
3185
  }
3047
3186
  ),
3048
- /* @__PURE__ */ jsx(B2, { kind: "color", label: "Stroke", value: stroke, onChange: setStroke }),
3187
+ /* @__PURE__ */ jsx(R, { kind: "color", label: "Stroke", value: stroke, onChange: setStroke }),
3049
3188
  /* @__PURE__ */ jsx(
3050
- B2,
3189
+ R,
3051
3190
  {
3052
3191
  kind: "number",
3053
3192
  label: "Count",
@@ -3059,7 +3198,7 @@ function PanelsAndRows() {
3059
3198
  }
3060
3199
  ),
3061
3200
  /* @__PURE__ */ jsx(
3062
- B2,
3201
+ R,
3063
3202
  {
3064
3203
  kind: "enum",
3065
3204
  label: "Line cap",
@@ -3072,7 +3211,7 @@ function PanelsAndRows() {
3072
3211
  }
3073
3212
  ),
3074
3213
  /* @__PURE__ */ jsx(
3075
- B2,
3214
+ R,
3076
3215
  {
3077
3216
  kind: "enum",
3078
3217
  control: "toggle",
@@ -3086,10 +3225,10 @@ function PanelsAndRows() {
3086
3225
  ]
3087
3226
  }
3088
3227
  ),
3089
- /* @__PURE__ */ jsx(B2, { kind: "string", label: "Label", value: label, onChange: setLabel }),
3090
- /* @__PURE__ */ jsx(B2, { kind: "boolean", label: "Visible", value: visible, onChange: setVisible }),
3228
+ /* @__PURE__ */ jsx(R, { kind: "string", label: "Label", value: label, onChange: setLabel }),
3229
+ /* @__PURE__ */ jsx(R, { kind: "boolean", label: "Visible", value: visible, onChange: setVisible }),
3091
3230
  /* @__PURE__ */ jsx(b2, { title: "Bevel", defaultCollapsed: true, children: /* @__PURE__ */ jsx(
3092
- B2,
3231
+ R,
3093
3232
  {
3094
3233
  kind: "number",
3095
3234
  control: "slider",
@@ -3104,7 +3243,7 @@ function PanelsAndRows() {
3104
3243
  ) })
3105
3244
  ] }) }) }),
3106
3245
  /* @__PURE__ */ jsx(Cell, { label: "PrefsForm", children: /* @__PURE__ */ jsx(
3107
- A2,
3246
+ j,
3108
3247
  {
3109
3248
  schema: PREFS,
3110
3249
  values: prefs,
@@ -3112,10 +3251,10 @@ function PanelsAndRows() {
3112
3251
  }
3113
3252
  ) }),
3114
3253
  /* @__PURE__ */ jsx(Cell, { label: "LayerList", children: /* @__PURE__ */ jsx(
3115
- D,
3254
+ E3,
3116
3255
  {
3117
3256
  items: layers,
3118
- onReorder: (move) => setLayers(S2(layers, move)),
3257
+ onReorder: (move) => setLayers(x3(layers, move)),
3119
3258
  renderBody: (item) => /* @__PURE__ */ jsxs("div", { children: [
3120
3259
  "settings for ",
3121
3260
  item.label
@@ -3123,7 +3262,7 @@ function PanelsAndRows() {
3123
3262
  }
3124
3263
  ) }),
3125
3264
  /* @__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,
3265
+ a11,
3127
3266
  {
3128
3267
  title: "Selection",
3129
3268
  collapsed: panelCollapsed,
@@ -3148,7 +3287,7 @@ function OverlaysAndFeedback() {
3148
3287
  ] }),
3149
3288
  /* @__PURE__ */ jsx("button", { type: "button", ref: calloutAnchor, onClick: () => setCalloutOpen(true), children: "Callout" }),
3150
3289
  /* @__PURE__ */ jsx(
3151
- g2,
3290
+ _2,
3152
3291
  {
3153
3292
  triggerRef: calloutAnchor,
3154
3293
  isOpen: calloutOpen,
@@ -3160,7 +3299,7 @@ function OverlaysAndFeedback() {
3160
3299
  ),
3161
3300
  /* @__PURE__ */ jsx(c, { onClick: () => setDialogOpen(true), children: "Dialog" }),
3162
3301
  /* @__PURE__ */ jsx(
3163
- u3,
3302
+ d2,
3164
3303
  {
3165
3304
  isOpen: dialogOpen,
3166
3305
  onOpenChange: setDialogOpen,
@@ -3176,7 +3315,7 @@ function OverlaysAndFeedback() {
3176
3315
  children: "Toast"
3177
3316
  }
3178
3317
  ),
3179
- /* @__PURE__ */ jsx(S4, { queue: toasts, placement: "bottom-right" })
3318
+ /* @__PURE__ */ jsx(S3, { queue: toasts, placement: "bottom-right" })
3180
3319
  ] }) }),
3181
3320
  /* @__PURE__ */ jsx(Cell, { label: "Powerline", children: /* @__PURE__ */ jsx(
3182
3321
  r4,
@@ -3193,7 +3332,7 @@ function OverlaysAndFeedback() {
3193
3332
  /* @__PURE__ */ jsx(Cell, { label: "StatusBar", children: /* @__PURE__ */ jsxs(n7, { ariaLabel: "Editor status", children: [
3194
3333
  /* @__PURE__ */ jsx(r5, { children: "tool: select" }),
3195
3334
  /* @__PURE__ */ jsx(r5, { children: "sel: 3" }),
3196
- /* @__PURE__ */ jsx(i4, {}),
3335
+ /* @__PURE__ */ jsx(i5, {}),
3197
3336
  /* @__PURE__ */ jsx(r5, { muted: true, children: "0.7.0" })
3198
3337
  ] }) })
3199
3338
  ] });
@@ -3244,14 +3383,14 @@ function ToolChrome() {
3244
3383
  },
3245
3384
  id
3246
3385
  )) }) }),
3247
- /* @__PURE__ */ jsx(Cell, { label: "ToolOptionsBar", children: /* @__PURE__ */ jsxs(c3, { label: "Text", children: [
3386
+ /* @__PURE__ */ jsx(Cell, { label: "ToolOptionsBar", children: /* @__PURE__ */ jsxs(c4, { label: "Text", children: [
3248
3387
  /* @__PURE__ */ jsx(c, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Bold", children: "B" }),
3249
3388
  /* @__PURE__ */ jsx(c, { size: "sm", variant: "ghost", iconOnly: true, ariaLabel: "Italic", children: "I" })
3250
3389
  ] }) }),
3251
3390
  /* @__PURE__ */ jsx(Cell, { label: "ResizeHandle", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__box", children: [
3252
3391
  /* @__PURE__ */ jsx("div", { className: "lk-specimen__box-main", children: "content" }),
3253
3392
  /* @__PURE__ */ jsx(
3254
- c4,
3393
+ c5,
3255
3394
  {
3256
3395
  value: paneWidth,
3257
3396
  min: 100,
@@ -3360,7 +3499,7 @@ function EditorsAndPlots() {
3360
3499
  }
3361
3500
  ) }),
3362
3501
  /* @__PURE__ */ jsx(Cell, { label: "BandEditor", wide: true, children: /* @__PURE__ */ jsx(
3363
- k2,
3502
+ j2,
3364
3503
  {
3365
3504
  min: 1 / 64,
3366
3505
  max: 1 / 2,
@@ -3375,7 +3514,7 @@ function EditorsAndPlots() {
3375
3514
  }
3376
3515
  ) }),
3377
3516
  /* @__PURE__ */ jsx(Cell, { label: "Timeline", wide: true, children: /* @__PURE__ */ jsx("div", { className: "lk-specimen__timeline", children: /* @__PURE__ */ jsx(
3378
- $2,
3517
+ ye,
3379
3518
  {
3380
3519
  tracks,
3381
3520
  duration: 2e3,
@@ -3438,6 +3577,6 @@ function Specimen({ className }) {
3438
3577
  ] });
3439
3578
  }
3440
3579
 
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 };
3580
+ export { AnnotationOverlay, AnnotationTargets, Lab, LabBoundary, LabPalette, LabRoot, LabShell, LabSwitcher, LabZoom, 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 };
3442
3581
  //# sourceMappingURL=index.js.map
3443
3582
  //# sourceMappingURL=index.js.map