@weasel-js/labkit 1.6.1 → 1.7.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 (256) hide show
  1. package/README.md +3 -3
  2. package/dist/_dts/{CanvasStackContext-Wo6OwIVM.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
  3. package/dist/_dts/{Stage-DWBBi8IU.d.ts → Stage-D6t7o0pF.d.ts} +59 -18
  4. package/dist/_dts/{index-CKyX0ME_.d.ts → index-BTmaRy6a.d.ts} +10 -6
  5. package/dist/_dts/{types-B7yBTTF9.d.ts → index-DCMA4Fy1.d.ts} +59 -113
  6. package/dist/_dts/{types-DTuViBvc.d.ts → types-BUBSIZuV.d.ts} +18 -8
  7. package/dist/_dts/{useTrialState-CMaV6UD4.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
  8. package/dist/canvas/index.d.ts +8 -6
  9. package/dist/canvas/index.js +6 -6
  10. package/dist/chrome/index.d.ts +6 -4
  11. package/dist/chrome/index.js +11 -10
  12. package/dist/chunk-2ES4W47N.js +8 -0
  13. package/dist/chunk-2ES4W47N.js.map +1 -0
  14. package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
  15. package/dist/chunk-2N7UBSS2.js.map +1 -0
  16. package/dist/chunk-4KSC7NXL.js +15491 -0
  17. package/dist/chunk-4KSC7NXL.js.map +1 -0
  18. package/dist/{chunk-SLAQPUI4.js → chunk-CEGFXTBD.js} +10 -63
  19. package/dist/chunk-CEGFXTBD.js.map +1 -0
  20. package/dist/chunk-CZZPXUOU.js +3 -0
  21. package/dist/{chunk-SBXNQW4G.js.map → chunk-CZZPXUOU.js.map} +1 -1
  22. package/dist/{chunk-QGMOA2YE.js → chunk-E23Q6A3Y.js} +296 -104
  23. package/dist/chunk-E23Q6A3Y.js.map +1 -0
  24. package/dist/{chunk-GHGO52SO.js → chunk-E6NARGU7.js} +5 -5
  25. package/dist/{chunk-GHGO52SO.js.map → chunk-E6NARGU7.js.map} +1 -1
  26. package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
  27. package/dist/chunk-EESJUSYR.js.map +1 -0
  28. package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
  29. package/dist/chunk-EFXRM6XQ.js.map +1 -0
  30. package/dist/chunk-F4ACIK7Z.js +210 -0
  31. package/dist/chunk-F4ACIK7Z.js.map +1 -0
  32. package/dist/{chunk-6FLXL3I7.js → chunk-FB4MIZOO.js} +77 -45
  33. package/dist/chunk-FB4MIZOO.js.map +1 -0
  34. package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
  35. package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
  36. package/dist/{chunk-4TT3PNPR.js → chunk-GAHELLJT.js} +95 -95
  37. package/dist/chunk-GAHELLJT.js.map +1 -0
  38. package/dist/{chunk-HKV7LRHY.js → chunk-IBVRMHW5.js} +5 -5
  39. package/dist/{chunk-HKV7LRHY.js.map → chunk-IBVRMHW5.js.map} +1 -1
  40. package/dist/{chunk-ASOK76ZH.js → chunk-JFOJESJF.js} +72 -29
  41. package/dist/chunk-JFOJESJF.js.map +1 -0
  42. package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
  43. package/dist/chunk-PMLZP7RT.js.map +1 -0
  44. package/dist/{chunk-TJ77A4A3.js → chunk-READTDQX.js} +5 -9
  45. package/dist/chunk-READTDQX.js.map +1 -0
  46. package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
  47. package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
  48. package/dist/{chunk-CGHF6RZV.js → chunk-T6DLGEJB.js} +18 -18
  49. package/dist/chunk-T6DLGEJB.js.map +1 -0
  50. package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
  51. package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
  52. package/dist/{chunk-DWMSB4CA.js → chunk-VYVGVBGY.js} +95 -32
  53. package/dist/chunk-VYVGVBGY.js.map +1 -0
  54. package/dist/{chunk-IRTGUQ5O.js → chunk-WLMDTI2Q.js} +16 -6
  55. package/dist/chunk-WLMDTI2Q.js.map +1 -0
  56. package/dist/{chunk-NEXR37YJ.js → chunk-XE5HJOPL.js} +6 -8
  57. package/dist/chunk-XE5HJOPL.js.map +1 -0
  58. package/dist/chunk-XVUKDSYV.js +38 -0
  59. package/dist/chunk-XVUKDSYV.js.map +1 -0
  60. package/dist/{chunk-O6FFFOHS.js → chunk-YCFKW5RX.js} +16 -8
  61. package/dist/chunk-YCFKW5RX.js.map +1 -0
  62. package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
  63. package/dist/chunk-ZQIHJXP4.js.map +1 -0
  64. package/dist/config/index.d.ts +28 -13
  65. package/dist/config/index.js +4 -4
  66. package/dist/controls/index.d.ts +4 -7
  67. package/dist/controls/index.js +6 -5
  68. package/dist/dragdrop/index.d.ts +23 -3
  69. package/dist/dragdrop/index.js +4 -3
  70. package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
  71. package/dist/index.d.ts +72 -487
  72. package/dist/index.js +603 -441
  73. package/dist/index.js.map +1 -1
  74. package/dist/job/index.d.ts +8 -0
  75. package/dist/job/index.js +1 -1
  76. package/dist/layers/index.d.ts +6 -5
  77. package/dist/layers/index.js +3 -2
  78. package/dist/loupe/index.d.ts +100 -30
  79. package/dist/loupe/index.js +585 -6
  80. package/dist/loupe/index.js.map +1 -1
  81. package/dist/overview/index.d.ts +4 -2
  82. package/dist/overview/index.js +20 -18
  83. package/dist/overview/index.js.map +1 -1
  84. package/dist/passthrough/weasel-canvas.d.ts +2 -0
  85. package/dist/passthrough/weasel-ui.d.ts +2 -2701
  86. package/dist/passthrough/weasel-ui.js +4 -3
  87. package/dist/primitives/index.d.ts +37 -2
  88. package/dist/primitives/index.js +9 -8
  89. package/dist/state/index.d.ts +7 -5
  90. package/dist/state/index.js +6 -6
  91. package/dist/styles.css +150 -126
  92. package/dist/surface/index.d.ts +10 -2
  93. package/dist/surface/index.js +1 -1
  94. package/dist/undo/index.d.ts +5 -3
  95. package/package.json +14 -13
  96. package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
  97. package/src/annotations/AnnotationOverlay.tsx +52 -33
  98. package/src/annotations/Annotations.less +0 -10
  99. package/src/annotations/Annotations.overlay.test.tsx +31 -0
  100. package/src/annotations/MarkList.tsx +4 -8
  101. package/src/annotations/capture.browser.test.ts +41 -0
  102. package/src/annotations/capture.ts +14 -7
  103. package/src/annotations/drawOne.ts +2 -2
  104. package/src/annotations/frac.test.ts +44 -1
  105. package/src/annotations/frac.ts +46 -18
  106. package/src/annotations/index.ts +1 -0
  107. package/src/annotations/paint.test.ts +76 -46
  108. package/src/annotations/paint.ts +65 -43
  109. package/src/annotations/store.test.ts +212 -2
  110. package/src/annotations/store.ts +130 -27
  111. package/src/annotations/svgNodes.test.ts +28 -19
  112. package/src/annotations/svgNodes.ts +6 -6
  113. package/src/annotations/types.ts +29 -10
  114. package/src/canvas/AGENTS.md +1 -0
  115. package/src/canvas/CameraInput.test.tsx +30 -0
  116. package/src/canvas/CameraInput.tsx +60 -48
  117. package/src/canvas/CanvasStack.tsx +11 -6
  118. package/src/canvas/CanvasStackContext.ts +4 -1
  119. package/src/canvas/LinkedCursor.less +1 -1
  120. package/src/canvas/Stage.test.tsx +33 -4
  121. package/src/canvas/Stage.tsx +9 -4
  122. package/src/canvas/cameraRegistry.test.ts +55 -0
  123. package/src/canvas/cameraRegistry.ts +87 -0
  124. package/src/canvas/cameraZoom.test.ts +46 -0
  125. package/src/canvas/cameraZoom.ts +24 -0
  126. package/src/canvas/index.ts +14 -2
  127. package/src/canvas/sharedScope.test.tsx +94 -0
  128. package/src/canvas/worldSpec.ts +3 -1
  129. package/src/chrome/ChromeRegions.stories.tsx +1 -0
  130. package/src/chrome/builtins.test.ts +7 -6
  131. package/src/chrome/builtins.tsx +5 -1
  132. package/src/chrome/index.ts +1 -1
  133. package/src/chrome/merge.test.ts +5 -0
  134. package/src/chrome/merge.ts +4 -2
  135. package/src/chrome/regions/PaletteRegion.less +0 -7
  136. package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
  137. package/src/chrome/regions/PaletteRegion.tsx +3 -4
  138. package/src/chrome/regions/SidebarRegion.less +12 -2
  139. package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
  140. package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
  141. package/src/chrome/regions/ViewportRegion.less +6 -0
  142. package/src/chrome/regions/ViewportRegion.tsx +10 -4
  143. package/src/chrome/types.ts +4 -2
  144. package/src/config/auto.ts +1 -0
  145. package/src/config/builder.test.ts +2 -1
  146. package/src/config/builder.ts +18 -5
  147. package/src/config/fromConfigField.test.ts +14 -0
  148. package/src/config/fromConfigField.ts +18 -4
  149. package/src/config/path.ts +2 -5
  150. package/src/config/resolve.ts +4 -0
  151. package/src/config/types.ts +14 -9
  152. package/src/controls/ControlPanel.less +1 -1
  153. package/src/controls/ControlPanel.stories.tsx +3 -2
  154. package/src/controls/ControlPanel.test.tsx +98 -11
  155. package/src/controls/ControlPanel.tsx +61 -2
  156. package/src/dragdrop/DragDropRuntime.tsx +22 -13
  157. package/src/dragdrop/DragGhost.tsx +3 -0
  158. package/src/dragdrop/Palette.tsx +2 -0
  159. package/src/index.test.ts +5 -0
  160. package/src/index.ts +16 -2
  161. package/src/instrument/types.ts +0 -6
  162. package/src/job/useJob.ts +14 -9
  163. package/src/lab/Lab.tsx +88 -73
  164. package/src/lab/{LabFit.stories.less → LabFit.browser.test.less} +1 -1
  165. package/src/lab/{LabFit.stories.tsx → LabFit.browser.test.tsx} +41 -63
  166. package/src/lab/LabFullChrome.stories.tsx +1 -0
  167. package/src/lab/LabHeader.test.tsx +24 -14
  168. package/src/lab/LabHeader.tsx +11 -12
  169. package/src/lab/LabShell.less +9 -17
  170. package/src/lab/LabSwitcher.browser.test.tsx +27 -0
  171. package/src/lab/LabSwitcher.less +8 -6
  172. package/src/lab/LabZoom.test.tsx +223 -0
  173. package/src/lab/LabZoom.tsx +170 -0
  174. package/src/lab/Workspace.tsx +48 -52
  175. package/src/lab/index.ts +1 -0
  176. package/src/loupe/AGENTS.md +28 -15
  177. package/src/loupe/CanvasLoupe.tsx +2 -3
  178. package/src/loupe/DomLoupe.tsx +1 -7
  179. package/src/loupe/Loupe.less +16 -0
  180. package/src/loupe/LoupeGestures.tsx +1 -1
  181. package/src/loupe/TrialLoupe.tsx +120 -57
  182. package/src/loupe/index.ts +1 -6
  183. package/src/loupe/types.test.ts +3 -3
  184. package/src/loupe/types.ts +24 -27
  185. package/src/loupe/useLoupe.test.tsx +29 -4
  186. package/src/loupe/useLoupe.ts +20 -17
  187. package/src/overview/OverviewMarks.tsx +12 -4
  188. package/src/overview/TrialOverview.tsx +10 -8
  189. package/src/passthrough/weasel-ui.test.ts +2 -0
  190. package/src/passthrough/weasel-ui.ts +17 -5
  191. package/src/primitives/FloatingPanel.test.tsx +11 -0
  192. package/src/primitives/FloatingPanel.tsx +8 -7
  193. package/src/primitives/JobProgress.less +2 -1
  194. package/src/primitives/Legend.stories.tsx +1 -0
  195. package/src/primitives/Readout.browser.test.tsx +137 -0
  196. package/src/primitives/Readout.less +12 -0
  197. package/src/primitives/Readout.stories.tsx +58 -0
  198. package/src/primitives/Readout.test.tsx +93 -0
  199. package/src/primitives/Readout.tsx +56 -0
  200. package/src/primitives/Split.tsx +69 -41
  201. package/src/primitives/Toolbar.tsx +3 -3
  202. package/src/primitives/ZoomControl.less +1 -2
  203. package/src/primitives/index.ts +2 -0
  204. package/src/specimen/Specimen.stories.tsx +1 -0
  205. package/src/specimen/Specimen.tsx +2 -3
  206. package/src/state/Persistence.browser.test.tsx +47 -0
  207. package/src/state/store.test.ts +5 -1
  208. package/src/state/undock.ts +3 -0
  209. package/src/state/useOpenOnce.ts +20 -16
  210. package/src/state/usePersistedState.test.tsx +1 -1
  211. package/src/state/view.ts +1 -0
  212. package/src/styles.less +1 -0
  213. package/src/surface/index.ts +1 -1
  214. package/src/surface/useTiledSurface.test.tsx +14 -0
  215. package/src/surface/useTiledSurface.ts +11 -3
  216. package/src/theme/Interstellar.stories.tsx +3 -1
  217. package/src/theme/base.less +21 -47
  218. package/src/theme/interstellar.test.ts +1 -1
  219. package/src/theme/interstellar.theme.json +10 -3
  220. package/src/trial/Trial.annotations.test.tsx +73 -0
  221. package/src/trial/Trial.less +0 -29
  222. package/src/trial/Trial.loupe.test.tsx +28 -11
  223. package/src/trial/Trial.tsx +85 -67
  224. package/src/trial/TrialChrome.tsx +27 -6
  225. package/src/trial/index.ts +2 -0
  226. package/src/trial/loupeSwitch.ts +15 -0
  227. package/dist/_dts/LayerList.d-BoELAMsM.d.ts +0 -83
  228. package/dist/_dts/PrefsRow.d-DFpPIeIC.d.ts +0 -39
  229. package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +0 -404
  230. package/dist/_dts/Select.d-Cr8-zoup.d.ts +0 -569
  231. package/dist/chunk-4TT3PNPR.js.map +0 -1
  232. package/dist/chunk-6FLXL3I7.js.map +0 -1
  233. package/dist/chunk-ASOK76ZH.js.map +0 -1
  234. package/dist/chunk-CGHF6RZV.js.map +0 -1
  235. package/dist/chunk-CQLQPQ4P.js.map +0 -1
  236. package/dist/chunk-DWMSB4CA.js.map +0 -1
  237. package/dist/chunk-HXXTULDN.js.map +0 -1
  238. package/dist/chunk-IJJUK4FU.js.map +0 -1
  239. package/dist/chunk-IRTGUQ5O.js.map +0 -1
  240. package/dist/chunk-KHK5FGER.js +0 -145
  241. package/dist/chunk-KHK5FGER.js.map +0 -1
  242. package/dist/chunk-NEXR37YJ.js.map +0 -1
  243. package/dist/chunk-O6FFFOHS.js.map +0 -1
  244. package/dist/chunk-QGMOA2YE.js.map +0 -1
  245. package/dist/chunk-RWNDDKOH.js.map +0 -1
  246. package/dist/chunk-S4NCI32V.js +0 -549
  247. package/dist/chunk-S4NCI32V.js.map +0 -1
  248. package/dist/chunk-SBXNQW4G.js +0 -3
  249. package/dist/chunk-SLAQPUI4.js.map +0 -1
  250. package/dist/chunk-TJ77A4A3.js.map +0 -1
  251. package/dist/chunk-TYN6MLXX.js +0 -13864
  252. package/dist/chunk-TYN6MLXX.js.map +0 -1
  253. package/dist/chunk-WPLAANH4.js.map +0 -1
  254. package/src/primitives/useRovingTabIndex.test.ts +0 -48
  255. package/src/primitives/useRovingTabIndex.ts +0 -88
  256. package/src/state/Persistence.stories.tsx +0 -75
package/dist/index.d.ts CHANGED
@@ -1,251 +1,33 @@
1
+ export { Button, ButtonProps, ButtonSize, ButtonVariant, CloseIcon, CollapseIcon, CurveField, CurveFieldProps, CurveMark, DetailList, DetailListLayout, DetailListProps, DetailListValues, DetailRow, DetailRowProps, DetailRowStatus, ExpandIcon, Icon, IconProps, Input, InputProps, Jog, JogProps, LayerList, LayerListItem, LayerListProps, LayerMove, PauseIcon, PlayIcon, PropertyControl, PropertyControlProps, PropertyField, PropertyFieldProps, PropertyGroup, PropertyGroupProps, PropertyList, PropertyListPack, PropertyListProps, PropertyOption, PropertyPanel, PropertyPanelProps, PropertyRow, PropertyRowLayout, PropertyRowProps, PropertyRowVariant, PropertySpan, PropertySpanProps, ResetIcon, Select, SelectProps, StepBackIcon, StepForwardIcon, StopIcon, Subpanel, SubpanelProps, ToggleBar, ToggleBarItem, ToggleBarProps, ToggleBarSize, ToggleBarVariant, TokenCategory, TokenEntry, TokenPanel, TokenPanelProps, TokenScale, TokenScaleRule, inferTokenType, moveLayers, refitScale } from '@weasel-js/ui';
2
+ import { SceneNode, View, DrawCommand, BuiltinToolId } from '@weasel-js/core';
3
+ import { A as AnnotationMeaning, t as AnnotationData, v as WorldRect, w as MarkStyle, x as MarkScene, y as CaptureSource, z as CaptureOptions, B as CaptureResult, E as PaintableMark, F as AnnotationTarget, G as AnnotationsApi, H as AnnotationsCapability, J as TrialInfo, K as TrialTool, N as AnnotationKind, a as ViewTransform, O as Instrument, q as InstrumentList, o as LabMode, Q as LabDensity, R as TrialContribution, c as StorageAdapter, T as TrialRecord } from './_dts/index-DCMA4Fy1.js';
4
+ export { X as Annotation, Y as AnnotationInit, Z as AnnotationPatch, _ as AnnotationQuery, $ as AnnotationSelectionMode, a0 as AnnotationStatus, a1 as AnnotationStoreOptions, a2 as AnnotationTargetInfo, a3 as AnnotationToolId, a4 as Auto, a5 as CanvasCapability, a6 as CanvasLayer, a7 as CaptureDeps, a8 as ContributionBase, C as CreateLabStoreOptions, D as DEFAULT_FRAME, n as DragDropCapability, m as DragFeedback, a9 as FracPoint, aa as FracRect, ab as HitResult, ac as IconComponent, L as LabDocument, d as LabStoreState, ad as LayerCapability, ae as LayerDescriptor, l as PaletteItem, P as Point, af as RegionContribution, ag as RenderContext, e as SavedSnapshot, ah as SerializedAnnotations, S as SerializedTrial, ai as SidebarSection, aj as SidebarSlotContext, ak as StageCapability, al as StatusReadout, f as StorageChange, am as SystemEvent, an as ToolCapability, ao as ToolItem, ap as ToolSlotContext, aq as ToolbarItem, ar as TrialChromeContext, as as TrialRegion, g as TrialStateHandle, at as UndoCapability, U as UndoStack, h as UndockedPanel, i as UndockedPanels, au as ViewportControl, V as ViewportSize, W as WorldFrame, b as WorldSpec, av as annotationsFromJSON, k as applyCamera, aw as auto, ax as createAnnotationScene, ay as createAnnotationStore, j as dockPanel, az as fracContains, aA as fracEncloses, aB as fracToWorld, aC as isAuto, aD as markCommands, p as panelKey, r as resolveFrame, aE as roundFrac, u as undockPanel, aF as worldToFrac } from './_dts/index-DCMA4Fy1.js';
1
5
  import * as react from 'react';
2
6
  import { ReactNode } from 'react';
3
- import { I as IconProps } from './_dts/Select.d-Cr8-zoup.js';
4
- export { B as Button, a as ButtonProps, b as ButtonSize, c as ButtonVariant, d as Icon, e as Input, f as InputProps, S as Select, g as SelectProps, T as ToggleBar, h as ToggleBarItem, i as ToggleBarProps, j as ToggleBarSize, k as ToggleBarVariant } from './_dts/Select.d-Cr8-zoup.js';
5
- export { L as LayerList, a as LayerListItem, b as LayerListProps, c as LayerMove, m as moveLayers } from './_dts/LayerList.d-BoELAMsM.js';
6
- import { a as PropertyListPack } from './_dts/PropertyField.d-D0ndfIIt.js';
7
- import { PropertyMetricProps } from './passthrough/weasel-ui.js';
8
- export { b as PropertyControl, c as PropertyControlProps, d as PropertyField, e as PropertyFieldProps, f as PropertyList, g as PropertyListProps, h as PropertyOption, i as PropertyPanel, j as PropertyPanelProps, k as PropertyRow, l as PropertyRowLayout, m as PropertyRowProps, n as PropertyRowVariant, o as PropertySpan, p as PropertySpanProps } from './_dts/PropertyField.d-D0ndfIIt.js';
9
- import { StanceProps } from './passthrough/weasel-ui.js';
10
- import { SceneNode, View, DrawCommand, Path, FillStyle, ScreenLength, StrokeAlign, StyledRun, TextStyle, TextVerticalAlign, Stroke, BuiltinToolId } from '@weasel-js/core';
11
- import { A as AnnotationMeaning, w as AnnotationData, x as WorldRect, y as MarkStyle, z as MarkScene, B as CaptureSource, E as CaptureOptions, F as CaptureResult, G as PaintableMark, H as AnnotationTarget, J as AnnotationsApi, K as AnnotationsCapability, N as TrialInfo, O as TrialTool, Q as AnnotationKind, b as ViewTransform, R as Instrument, t as InstrumentList, s as LabMode, X as LabDensity, Y as TrialContribution, c as StorageAdapter, T as TrialRecord } from './_dts/types-B7yBTTF9.js';
12
- export { Z as Annotation, _ as AnnotationInit, $ as AnnotationPatch, a0 as AnnotationQuery, a1 as AnnotationStatus, a2 as AnnotationStoreOptions, a3 as AnnotationTargetInfo, a4 as AnnotationToolId, a5 as Auto, a6 as CanvasCapability, a7 as CanvasLayer, a8 as CaptureDeps, a9 as ContributionBase, C as CreateLabStoreOptions, D as DEFAULT_FRAME, q as DragDropCapability, o as DragFeedback, aa as FracPoint, ab as FracRect, ac as HitResult, ad as IconComponent, ae as LOUPE_DEFAULTS, d as LabDocument, e as LabStoreState, L as LayerCapability, a as LayerDescriptor, af as LoupeCapability, ag as LoupeDeclaration, ah as LoupeMode, ai as LoupePoint, aj as LoupeRenderArgs, n as PaletteItem, P as Point, ak as RegionContribution, al as RenderContext, am as ResolvedLoupe, f as SavedSnapshot, an as SerializedAnnotations, S as SerializedTrial, ao as SidebarSection, ap as SidebarSlotContext, aq as StageCapability, ar as StatusReadout, g as StorageChange, as as SystemEvent, at as ToolCapability, au as ToolItem, av as ToolSlotContext, aw as ToolbarItem, ax as TrialChromeContext, ay as TrialRegion, h as TrialStateHandle, az as UndoCapability, U as UndoStack, i as UndockedPanel, j as UndockedPanels, aA as ViewportControl, V as ViewportSize, W as WorldFrame, l as WorldSpec, aB as annotationsFromJSON, m as applyCamera, aC as auto, aD as createAnnotationScene, aE as createAnnotationStore, k as dockPanel, aF as fracContains, aG as fracEncloses, aH as fracToWorld, aI as isAuto, aJ as markCommands, p as panelKey, r as resolveFrame, aK as resolveLoupe, aL as roundFrac, u as undockPanel, aM as worldToFrac } from './_dts/types-B7yBTTF9.js';
13
- export { C as CameraContext, a as CameraContextValue, b as CameraInput, d as CameraScope, g as CanvasStack, h as CanvasStackProps, i as Stage, j as StageProps, Z as ZoomAtOptions, k as centerOn, l as fitStage, s as screenToWorld, w as worldToScreen, z as zoomAt } from './_dts/Stage-DWBBi8IU.js';
14
- export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-Wo6OwIVM.js';
15
- import { L as LabContribution } from './_dts/index-CKyX0ME_.js';
16
- export { A as AddTrialOptions, a as LabAsideRegion, b as LabChromeContext, c as LabContext, d as LabContextValue, e as LabFooterRegion, f as LabHeaderRegion, g as LabRegion, h as LabRegionProps, i as LabSidebarRegion, P as PaletteRegion, j as PaletteRegionProps, S as SidebarRegion, k as SidebarRegionProps, l as StatusRegion, m as StatusRegionProps, T as TitleBarPlacement, n as TitleBarRegion, o as TitleBarRegionProps, p as ToolbarRegion, q as ToolbarRegionProps, V as ViewportRegion, r as ViewportRegionProps, s as addTrial, t as builtinContributions, u as cloneTrial, v as closeTrial, w as contributionsIn, x as labContributions, y as mergeContributions, z as reorderTrials, B as resetTrial, C as suppressContributions, D as toolContributions, E as useLabChromeContext, F as useLabContext } from './_dts/index-CKyX0ME_.js';
7
+ import { SvgNode } from '@weasel-js/svg';
8
+ export { C as CameraContext, a as CameraContextValue, b as CameraInput, d as CameraPublishContext, e as CameraRegistry, f as CameraRegistryContext, g as CameraScope, h as CameraView, j as CanvasStack, k as CanvasStackProps, l as Stage, m as StageProps, Z as ZoomAtOptions, n as ZoomRange, o as centerOn, p as createCameraRegistry, q as fitStage, s as screenToWorld, r as usePublishCamera, w as worldToScreen, z as zoomAt } from './_dts/Stage-D6t7o0pF.js';
9
+ export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-Cjy6I-Iv.js';
10
+ import { L as LabContribution } from './_dts/index-BTmaRy6a.js';
11
+ export { A as AddTrialOptions, a as LabAsideRegion, b as LabChromeContext, c as LabContext, d as LabContextValue, e as LabFooterRegion, f as LabHeaderRegion, g as LabRegion, h as LabRegionProps, i as LabSidebarRegion, P as PaletteRegion, j as PaletteRegionProps, S as SidebarRegion, k as SidebarRegionProps, l as StatusRegion, m as StatusRegionProps, T as TRANSIENT_BUILTINS, n as TitleBarPlacement, o as TitleBarRegion, p as TitleBarRegionProps, q as ToolbarRegion, r as ToolbarRegionProps, V as ViewportRegion, s as ViewportRegionProps, t as addTrial, u as builtinContributions, v as cloneTrial, w as closeTrial, x as contributionsIn, y as labContributions, z as mergeContributions, B as reorderTrials, C as resetTrial, D as suppressContributions, E as toolContributions, F as useLabChromeContext, G as useLabContext } from './_dts/index-BTmaRy6a.js';
17
12
  export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, SectionTree, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, sectionTree, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath } from './config/index.js';
18
- import { b as ConfigSchema, a as ConfigField, c as ConfigRule, d as ControlRenderer } from './_dts/types-DTuViBvc.js';
19
- export { A as Annotations, B as BranchAnnotations, e as BranchOptions, f as CheckboxField, g as ColorField, h as ConfigBranch, i as ConfigEntry, j as ConfigFieldBase, k as ConfigFieldType, l as ConfigNode, m as ConfigOf, n as ConfigOption, C as ConfigPath, o as ConfigRuleContext, p as ConfigShape, D as DialogSpec, E as EntryValue, I as InDialogOptions, q as InferConfig, L as LeafPatch, N as NodeOptions, r as NodeValue, s as NumberField, R as ResolvedConfig, S as SectionOption, t as SectionSpec, u as SelectField, v as SelectOption, w as SliderField, T as TextField, V as ValueAtPath } from './_dts/types-DTuViBvc.js';
13
+ import { C as ConfigSchema, a as ConfigField, b as ConfigRule, c as ControlRenderer } from './_dts/types-BUBSIZuV.js';
14
+ export { A as Annotations, B as BranchAnnotations, d as BranchOptions, e as CheckboxField, f as ColorField, g as ConfigBranch, h as ConfigEntry, i as ConfigFieldBase, j as ConfigFieldType, k as ConfigNode, l as ConfigOf, m as ConfigOption, n as ConfigPath, o as ConfigRuleContext, p as ConfigShape, D as DialogSpec, E as EntryValue, I as InDialogOptions, q as InferConfig, L as LeafPatch, N as NodeOptions, r as NodeValue, s as NumberField, R as ResolvedConfig, S as SectionOption, t as SectionSpec, u as SelectField, v as SelectOption, w as SliderField, T as TextField, V as ValueAtPath } from './_dts/types-BUBSIZuV.js';
20
15
  export { ControlPanel, inDialog, summarizeValue } from './controls/index.js';
21
16
  import { J as JobHandle } from './_dts/types-DJ79Tg5J.js';
22
17
  export { a as JobCapability, b as JobEvent, c as JobFailure, d as JobStatus } from './_dts/types-DJ79Tg5J.js';
23
18
  export { UseJobOptions, useJob } from './job/index.js';
24
19
  import { Theme, ColorList } from '@weasel-js/theme';
25
- export { CanvasLoupe, CanvasLoupeProps, DomLoupe, DomLoupeProps, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LensCamera, LoupeBubble, LoupeBubbleProps, LoupeGestures, LoupeGesturesProps, LoupeInputApi, LoupeState, SourceRect, TrialLoupe, TrialLoupeProps, UseLoupeOptions, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, sampleStack, useLoupe } from './loupe/index.js';
26
20
  export { a as FloatingPanel, F as FloatingPanelProps } from './_dts/FloatingPanel-7j0IcXwz.js';
27
21
  import { SplitProps } from './primitives/index.js';
28
- export { FpsMeter, JobProgress, JobProgressProps, Legend, LegendEntry, LegendMark, LegendProps, ScaleIndicator, ScaleIndicatorProps, Split, StatusBar, StatusBarProps, StatusBarSectionProps, Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarProps, ZoomControl, ZoomControlProps } from './primitives/index.js';
29
- export { C as CURRENT_DOCUMENT_VERSION, I as IndexedDbAdapterOptions, b as LabStoreContext, c as LabStoreProvider, O as OpenLabStoreOptions, d as OpenedLabStore, P as PersistedStateOptions, e as Persistence, f as PersistenceProps, R as RecordCache, g as RecordChange, T as TrialIdContext, h as TrialIdProvider, i as createIndexedDbAdapter, k as createMemoryAdapter, l as indexedDbAdapter, m as labDocumentKey, n as localStorageAdapter, o as noneAdapter, p as openLabStore, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, r as useLabStore, t as usePersistedState, v as useTrialId, w as useTrialState } from './_dts/useTrialState-CMaV6UD4.js';
30
- export { Box, Rect, SurfaceCanvasContext, SurfaceCanvases, SurfaceClear, SurfaceContext, SurfaceFrame, SurfaceHandle, SurfaceLayer, TilePainter, UseTiledSurfaceOptions, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './surface/index.js';
22
+ export { FpsMeter, JobProgress, JobProgressProps, Legend, LegendEntry, LegendMark, LegendProps, Readout, ReadoutProps, ReadoutRow, ScaleIndicator, ScaleIndicatorProps, Split, StatusBar, StatusBarProps, StatusBarSectionProps, Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarProps, ZoomControl, ZoomControlProps } from './primitives/index.js';
23
+ export { C as CURRENT_DOCUMENT_VERSION, I as IndexedDbAdapterOptions, b as LabStoreContext, c as LabStoreProvider, O as OpenLabStoreOptions, d as OpenedLabStore, P as PersistedStateOptions, e as Persistence, f as PersistenceProps, R as RecordCache, g as RecordChange, T as TrialIdContext, h as TrialIdProvider, i as createIndexedDbAdapter, k as createMemoryAdapter, l as indexedDbAdapter, m as labDocumentKey, n as localStorageAdapter, o as noneAdapter, p as openLabStore, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, r as useLabStore, t as usePersistedState, v as useTrialId, w as useTrialState } from './_dts/useTrialState-Bh8bzFgE.js';
24
+ export { Box, Rect, SurfaceCanvasContext, SurfaceCanvases, SurfaceClear, SurfaceContext, SurfaceFrame, SurfaceHandle, SurfaceLayer, TilePainter, UseTiledSurfaceOptions, composeRects, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './surface/index.js';
31
25
  export { EventBus, EventListener, clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './undo/index.js';
32
- import 'react-aria-components';
26
+ import '@weasel-js/geom';
27
+ import '@weasel-js/quantity';
33
28
  import 'windease';
34
29
  import 'zustand/vanilla';
35
30
 
36
- declare const ResetIcon: (p: IconProps) => react.JSX.Element;
37
- declare const CloseIcon: (p: IconProps) => react.JSX.Element;
38
- declare const PlayIcon: (p: IconProps) => react.JSX.Element;
39
- declare const PauseIcon: (p: IconProps) => react.JSX.Element;
40
- declare const StopIcon: (p: IconProps) => react.JSX.Element;
41
- declare const StepBackIcon: (p: IconProps) => react.JSX.Element;
42
- declare const StepForwardIcon: (p: IconProps) => react.JSX.Element;
43
- declare const CollapseIcon: (p: IconProps) => react.JSX.Element;
44
- declare const ExpandIcon: (p: IconProps) => react.JSX.Element;
45
-
46
- /** An annotation drawn over a curve plot: a shaded band across a range of x,
47
- * or a vertical line at one x. */
48
- type CurveMark = {
49
- kind: 'band';
50
- x: [number, number];
51
- color?: string;
52
- } | {
53
- kind: 'line';
54
- x: number;
55
- color?: string;
56
- };
57
- /** Props for `<CurveField>`. */
58
- interface CurveFieldProps {
59
- /** Flat [x0, y0, x1, y1, …] — matches how curve-as-array configs
60
- * serialize in JSON snapshots. */
61
- values: number[];
62
- min: number;
63
- max: number;
64
- step: number;
65
- /** Plot width in CSS px. Caller sizes (typically uses a ResizeObserver). */
66
- width: number;
67
- /** Plot height in CSS px. Default 110. */
68
- height?: number;
69
- /** Flat default curve. When provided, a Reset button restores it. */
70
- defaults?: readonly number[];
71
- onChange: (next: number[]) => void;
72
- /** Optional vertical marks overlaid on the plot (e.g. landmarks). */
73
- marks?: readonly CurveMark[];
74
- }
75
- /**
76
- * A function-domain (y = f(x), x ∈ [0,1]) curve editor with per-stop
77
- * numeric readouts and flip buttons. Wraps weasel-ui's
78
- * `CurveEditor`; consumers wanting the raw editor (2D paths,
79
- * custom anchors) should import that instead.
80
- */
81
- declare function CurveField({ values, min, max, step, width, height, defaults, onChange, marks, }: CurveFieldProps): react.JSX.Element;
82
-
83
- /** Props for `<PropertyGroup>`. */
84
- interface PropertyGroupProps extends PropertyMetricProps, StanceProps {
85
- /** Title rendered between two rules at the top of the group. */
86
- title: ReactNode;
87
- /** Before the title: a drag handle, an ordinal. Clicks here do not fold the group. */
88
- leading?: ReactNode;
89
- /** After the title: a summary of the group's value, a remove button. Clicks here do not fold the group. */
90
- actions?: ReactNode;
91
- /** Help text for the whole group, drawn under the title and above the
92
- * rows. `<PropertyRow description>` covers the per-row case. */
93
- description?: ReactNode;
94
- /** When true the group renders nothing — useful for conditional sections. */
95
- hidden?: boolean;
96
- /**
97
- * Give the title a twisty that folds the rows away. Implied by any of the
98
- * three props below, so it is only needed for a group that starts open and
99
- * keeps its own state.
100
- */
101
- collapsible?: boolean;
102
- /** Start folded. Read once; the group owns the state from then on. */
103
- defaultCollapsed?: boolean;
104
- /**
105
- * Folded or not, as the consumer holds it. Given, the group keeps no state
106
- * of its own and every toggle arrives at `onCollapsedChange` instead — which
107
- * is what a panel that remembers its sections past a reload needs.
108
- */
109
- collapsed?: boolean;
110
- onCollapsedChange?: (next: boolean) => void;
111
- children: ReactNode;
112
- className?: string;
113
- /** Take the whole width of a packed grid, like `<PropertyRow span>`: a group
114
- * lays its own rows out, so half a column leaves them overlapping. */
115
- span?: boolean;
116
- /** How rows pack into the 2-column grid — see `<PropertyList pack>`. */
117
- pack?: PropertyListPack;
118
- }
119
- /**
120
- * Visually-bordered group inside a PropertyList. Use to scope a set of
121
- * related rows under a heading (e.g. "Aqua", "Bevel", "Dome" sections
122
- * inside a fill effect's controls).
123
- *
124
- * A collapsible group keeps its rows mounted and hides them, so a control's
125
- * local state survives being folded away. `stance` and `tone` work as on
126
- * `<PropertyPanel>`; a tone also draws the group's leading edge in it, which
127
- * is how a list of like groups — effects, tails — tells its members apart.
128
- * `leading` and `actions` put a handle and controls in the title row, and the
129
- * groups of a `<PropertyList>` reorder with `useReorderDragList`.
130
- */
131
- declare function PropertyGroup({ title, leading, actions, description, hidden, collapsible, defaultCollapsed, collapsed, onCollapsedChange, children, className, span, pack, density, align, stance, tone, }: PropertyGroupProps): react.JSX.Element | null;
132
-
133
- /** Props for `<Subpanel>`. */
134
- interface SubpanelProps extends PropertyMetricProps, StanceProps {
135
- title: ReactNode;
136
- children: ReactNode;
137
- className?: string;
138
- }
139
- /** A typographic divider inside a property list: a small title flanked by a
140
- * rule. Purely a heading — use `<PropertyGroup>` for a bordered section. A
141
- * stance or tone colors the title and rule. */
142
- declare function Subpanel({ title, children, className, density, align, stance, tone }: SubpanelProps): react.JSX.Element;
143
-
144
- /** A design token as `TokenPanel` edits it. */
145
- interface TokenEntry {
146
- /** The custom property, e.g. `--wzl-gray-50`. */
147
- name: string;
148
- /** A DTCG type name. A type the panel has no control for edits as text. */
149
- type: string;
150
- /** Tokens sharing a group sit together; a color group large enough draws as one row of swatches. */
151
- group: string;
152
- value: string;
153
- /** Whether `value` overrides the token's own, which offers Reset. */
154
- overridden?: boolean;
155
- description?: string;
156
- }
157
- /** How a scale's steps follow from its base: one multiplier per step, a constant ratio, or a constant step. */
158
- type TokenScaleRule = {
159
- kind: 'factors';
160
- factors: readonly number[];
161
- } | {
162
- kind: 'ratio';
163
- ratio: number;
164
- } | {
165
- kind: 'step';
166
- step: number;
167
- };
168
- /** A group whose steps are generated from a base, so the panel edits the base and the rule rather than each step. */
169
- interface TokenScale {
170
- /** The generated tokens, smallest first. Anything else in the group draws as an ordinary step. */
171
- tokens: readonly string[];
172
- base: number;
173
- rule: TokenScaleRule;
174
- }
175
- /**
176
- * The same scale under another rule, fitted to the amounts its steps have now.
177
- * A ratio or step counts from the first step, so switching to one moves the
178
- * base there.
179
- */
180
- declare function refitScale(scale: TokenScale, kind: TokenScaleRule['kind'], amounts: readonly number[]): TokenScale;
181
- type TokenCategory = 'color' | 'type' | 'size' | 'motion' | 'depth' | 'other';
182
- /** A DTCG type read off the shape of a value, for a token that arrives without one. `'string'` when nothing fits. */
183
- declare function inferTokenType(value: string): string;
184
-
185
- type OnChange = (name: string, value: string | null) => void;
186
- /** Props for `<TokenPanel>`. */
187
- interface TokenPanelProps {
188
- tokens: readonly TokenEntry[];
189
- /** A token's new value, or null to drop its override. Keep it stable: rows re-render only when it or their token changes. */
190
- onChange: OnChange;
191
- /** Sections held closed, by category. Omit to let the panel keep that state itself. */
192
- collapsed?: Readonly<Partial<Record<TokenCategory, boolean>>>;
193
- onCollapsedChange?: (category: TokenCategory, collapsed: boolean) => void;
194
- /** Groups generated from a base, by group name. Such a group edits its base and rule above its steps. */
195
- scales?: Readonly<Record<string, TokenScale>>;
196
- /** A scale's new base or rule. The panel does not regenerate the steps; the consumer does, through `onChange`. */
197
- onScaleChange?: (group: string, scale: TokenScale) => void;
198
- /** Files a token under a section. Defaults to `tokenCategory`. */
199
- categorize?: (token: TokenEntry) => TokenCategory;
200
- /** The fewest colors, or sizes, sharing a group that draw as one row of swatches or one grid of steps. Default 3. */
201
- familySize?: number;
202
- /**
203
- * Row layout. `tight` puts a token on one line — name, control, Reset — with the
204
- * names on a fixed rail so the values read down the panel as a column, and caps
205
- * the field rather than letting it span the panel. Default `normal` stacks the
206
- * control under its name.
207
- */
208
- density?: 'tight' | 'normal';
209
- className?: string;
210
- }
211
- /**
212
- * Edits a set of design tokens by type: collapsible sections by category, a
213
- * color group drawn as one row of swatches sized to fit, a group of sizes drawn
214
- * as one grid of numbers labeled by step — with its base and rule above it when
215
- * `scales` says how it is generated — and a control for each
216
- * type — a number with its unit for dimensions and durations, the nine weights
217
- * for a font weight, a curve beside a `cubic-bezier()`, a swatch beside a color,
218
- * and text for everything else.
219
- */
220
- declare function TokenPanel({ tokens, onChange, collapsed, onCollapsedChange, scales, onScaleChange, categorize, familySize, density, className, }: TokenPanelProps): react.JSX.Element;
221
-
222
- /** Props for {@link Jog}. */
223
- interface JogProps {
224
- /** Which step is showing, 0-based. */
225
- index: number;
226
- /** How many steps there are. */
227
- count: number;
228
- playing: boolean;
229
- onPlay: (playing: boolean) => void;
230
- /** Move one step, back or forward. */
231
- onStep: (by: -1 | 1) => void;
232
- /** Jump to a step. Left out, no scrubber is drawn. */
233
- onScrub?: (index: number) => void;
234
- /** What one step is called, for the spoken labels. Defaults to `Step`. */
235
- unit?: string;
236
- /** Drawn after the readout — a beat's caption, a snapshot's date. */
237
- caption?: ReactNode;
238
- className?: string;
239
- }
240
- /**
241
- * Transport for something counted rather than timed: beat 3 of 24, not 4.20s of 12.00s.
242
- * `<Transport>` is the continuous-time one, and wants a playhead in milliseconds, a rate and
243
- * a loop, none of which a list of steps has.
244
- *
245
- * Named for the jog of jog/shuttle — moving one frame at a time, as against running at speed.
246
- */
247
- declare function Jog(props: JogProps): react.JSX.Element;
248
-
249
31
  /** What resolving a mark's appearance needs beyond the mark itself. */
250
32
  interface MarkDrawOptions {
251
33
  /** The target's content box — the world a mark's geometry is in. */
@@ -285,6 +67,8 @@ type CapturePlan = 'svg-document' | 'raster-stack';
285
67
  * base.
286
68
  */
287
69
  declare function capturePlan(base: CaptureSource | undefined, format: 'png' | 'svg'): CapturePlan;
70
+ /** Inputs to `composeCaptureSvg`. `scale` is output pixels per content-box
71
+ * unit; `onWarn` receives non-fatal export warnings. */
288
72
  interface ComposeSvgArgs {
289
73
  base?: CaptureSource;
290
74
  scene: MarkScene;
@@ -298,7 +82,10 @@ interface ComposeSvgArgs {
298
82
  * The outer `viewBox` is the content box, so marks — which are already in it —
299
83
  * need no transform, and `width`/`height` carry the export scale. Both halves
300
84
  * nest as child `<svg>` elements, which each establish their own viewport and
301
- * so keep their own `viewBox` maths out of this function.
85
+ * so keep their own `viewBox` math out of this function.
86
+ *
87
+ * Synchronous with no `warmSvg`: marks export nothing that loads on demand,
88
+ * which `svgNodes.test.ts` pins.
302
89
  */
303
90
  declare function composeCaptureSvg(args: ComposeSvgArgs): string;
304
91
  /** What a capture needs about the target it is exporting. */
@@ -357,248 +144,6 @@ declare function seenFrom(config: unknown, keys: readonly string[]): Record<stri
357
144
  */
358
145
  declare function isStale(seen: Readonly<Record<string, unknown>> | undefined, config: unknown, keys: readonly string[]): boolean;
359
146
 
360
- type Mat3 = readonly [number, number, number, number, number, number];
361
-
362
- /**
363
- * Public types for `@weasel-js/svg`. The package exposes a flat,
364
- * discriminated-union node model (`SvgNode`) that mirrors the SVG element
365
- * tree but uses weasel-native leaf data (`Path`, `FillStyle`) for geometry and
366
- * paint.
367
- *
368
- * Parsing collapses every `transform="..."` onto its descendants' geometry,
369
- * so the `SvgNode` tree returned from `parseSvg` never has a non-identity
370
- * group transform. Consumers may still construct groups with explicit
371
- * transforms before serializing, in which case the serializer emits a
372
- * single `matrix(a b c d e f)` on the `<g>`.
373
- */
374
-
375
- /**
376
- * Opaque pass-through bag for namespaced XML content.
377
- *
378
- * weasel-svg does not interpret the contents — it only ensures that any
379
- * attributes or child elements in a *declared* XML namespace round-trip
380
- * losslessly through parse → serialize. Consumers (e.g. an app-specific
381
- * bridge layer) hang their domain semantics off this structure.
382
- *
383
- * Keyed by namespace prefix (the prefix is a write-time choice; the URI
384
- * is the canonical identifier and is supplied via `ParseOptions.namespaces`
385
- * / `SerializeOptions.namespaces`).
386
- */
387
- interface NamespaceMeta {
388
- [prefix: string]: {
389
- /** Local-name → string-value map for attributes in this namespace. */
390
- attrs?: Record<string, string>;
391
- /**
392
- * Child elements in this namespace, keyed by local name. Each entry
393
- * is an array because a namespace can host multiple sibling elements
394
- * with the same tag (e.g. `<wd:layer/><wd:layer/>`).
395
- */
396
- elements?: Record<string, NamespacedElement[]>;
397
- };
398
- }
399
- /** Opaque structured representation of a namespaced element. */
400
- interface NamespacedElement {
401
- /** Attribute local-name → string-value. */
402
- attrs: Record<string, string>;
403
- /** Text content, when the element contains only text (no child elements). */
404
- text?: string;
405
- /** Nested namespaced children, keyed by local name (recursive). */
406
- children?: Record<string, NamespacedElement[]>;
407
- }
408
- /**
409
- * 2x3 affine matrix in SVG's `matrix(a b c d e f)` order, mapping
410
- * `[x', y'] = [a*x + c*y + e, b*x + d*y + f]`.
411
- *
412
- * The same order the kernel's affine tier uses, so this is that type under
413
- * the name the SVG spec gives it — not a parallel one. An `SvgGroupNode`'s
414
- * transform and a geom `Mat3` are interchangeable without a conversion.
415
- */
416
- type Matrix = Mat3;
417
- /**
418
- * FillStyle description in the SVG sense — either explicit `none`, a solid
419
- * color, or a reference to a weasel-native gradient `FillStyle`. Solid colors
420
- * are normalized to `#rrggbb` strings; opacity is carried separately so
421
- * `fill-opacity` and `stroke-opacity` round-trip cleanly.
422
- */
423
- type SvgPaint = {
424
- kind: 'none';
425
- } | {
426
- kind: 'solid';
427
- color: string;
428
- opacity?: number;
429
- } | {
430
- kind: 'gradient';
431
- paint: FillStyle;
432
- };
433
- /** Stroke description: a paint plus structural line parameters. */
434
- interface SvgStroke {
435
- paint: SvgPaint;
436
- /** World units, or `{ px }` for a width that holds its rendered thickness
437
- * however the document is scaled — SVG's `vector-effect="non-scaling-stroke"`.
438
- * Literally the kit's own unit, not a second spelling of it. */
439
- width: ScreenLength;
440
- opacity?: number;
441
- /** `stroke-linecap`. Default per SVG spec is `'butt'`. */
442
- cap?: 'butt' | 'round' | 'square';
443
- /** `stroke-linejoin`. Default per SVG spec is `'miter'`. SVG's `arcs` / `miter-clip` map to `'miter'` with a warning. */
444
- join?: 'miter' | 'round' | 'bevel';
445
- /** `stroke-dasharray` as a flat number array. Odd-length inputs are doubled per SVG spec. */
446
- dash?: number[];
447
- /**
448
- * `stroke-miterlimit`. SVG's default is 4. Weasel's renderer defaults to
449
- * 10 (Canvas2D) when unset, so parsed strokes without an explicit
450
- * attribute may render with longer miters than the source SVG intended.
451
- */
452
- miterLimit?: number;
453
- /** The kit stroke's `align`. SVG has no stroke alignment, so the serializer
454
- * writes the stroke centered and says so through `onWarn`; the parser
455
- * never sets it. */
456
- align?: StrokeAlign;
457
- /** `marker-start` / `marker-mid` / `marker-end`, as the bare `url(#id)` key. */
458
- markerStart?: string;
459
- markerMid?: string;
460
- markerEnd?: string;
461
- }
462
- /**
463
- * Leaf node: a path geometry plus fill/stroke. All other v1 shapes
464
- * (`<rect>`, `<ellipse>`, etc.) are lowered to this representation on
465
- * parse — `<rect>` uses weasel's `RectPath` fast-path subtype when
466
- * possible, everything else becomes a `PolygonPath`.
467
- */
468
- interface SvgPathNode {
469
- kind: 'path';
470
- path: Path;
471
- fill: SvgPaint;
472
- stroke?: SvgStroke;
473
- /** Element-level opacity (`opacity="..."`), 0..1. */
474
- opacity?: number;
475
- /** Element-level rotation in **radians**, pivoting around the AABB
476
- * center of the underlying `path` geometry. Emitted as SVG
477
- * `transform="rotate(angleDegrees cx cy)"`. */
478
- rotation?: number;
479
- /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */
480
- meta?: NamespaceMeta;
481
- }
482
- /**
483
- * Group node: an SVG `<g>`. On parse, `transform` is always omitted (any
484
- * `transform` attribute is collapsed onto descendants' geometry). On
485
- * serialize, a non-identity `transform` is emitted as
486
- * `matrix(a b c d e f)`.
487
- */
488
- interface SvgGroupNode {
489
- kind: 'group';
490
- children: SvgNode[];
491
- transform?: Matrix;
492
- /** Clips the group's contents. Serializes to a `<clipPath>` def plus
493
- * `clip-path="url(#id)"`, and lives in the same space as `children` —
494
- * SVG applies the group's own `transform` to the clip as well.
495
- * A `<clipPath>` of more than one shape parses back as no clip: SVG
496
- * unions them and a `Path` holds one outline. */
497
- clip?: Path;
498
- opacity?: number;
499
- /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */
500
- meta?: NamespaceMeta;
501
- }
502
- /**
503
- * Text leaf node. Mirrors the kit's `TextPose` shape — a bounding box plus
504
- * text content, optional rich-text `runs` (per-range styling), and an
505
- * optional `TextStyle` for the node-wide defaults.
506
- *
507
- * Note on SVG text geometry: native `<text>` flows from a baseline; it
508
- * doesn't have width/height attributes. The serializer emits
509
- * `dominant-baseline="text-before-edge"` so `y` is the top of the text
510
- * box, plus `data-weasel-width` / `data-weasel-height` so weasel's
511
- * explicit box dimensions round-trip losslessly. External SVG text
512
- * (lacking the data-* attrs) imports with the width the kit's text layout
513
- * measures — an em-based estimate when no registered font can — and
514
- * `height = fontSize * lineHeight * (lineCount || 1)`.
515
- *
516
- * `x` here is always the box's left edge. In the SVG it is the
517
- * `text-anchor` point, and the parser and serializer convert between them.
518
- */
519
- interface SvgTextNode {
520
- kind: 'text';
521
- x: number;
522
- y: number;
523
- width: number;
524
- height: number;
525
- /** Plain text. When `runs` is set, `runsToPlainText(runs)` must equal `text`. */
526
- text: string;
527
- /** Optional per-range styling — same shape as `TextPose.runs`. */
528
- runs?: StyledRun[];
529
- /** Node-wide typography. Defaults applied at render time via `resolveTextStyle`. */
530
- style?: TextStyle;
531
- /** Where the laid-out text sits inside the box — `kit:text`'s
532
- * `data.verticalAlign`. SVG text has no box to align in, so this rides in
533
- * `data-weasel-vertical-align` and other readers draw the text top-aligned. */
534
- verticalAlign?: TextVerticalAlign;
535
- /**
536
- * Node-wide glyph paint, the `FillStyle` / `Stroke` a kit text node holds
537
- * in `data.fill` / `data.stroke`. Not `SvgPaint`, which is the path
538
- * nodes' shape — a text paint reaches the renderer through the runs, and
539
- * `StyledRun.fill` / `.stroke` override these per range.
540
- *
541
- * `null` is SVG's `fill="none"`: outline-only text, painted by its stroke
542
- * alone. Absent takes the default black.
543
- */
544
- fill?: FillStyle | null;
545
- stroke?: Stroke;
546
- /** Element-level opacity (`opacity="..."`), 0..1. */
547
- opacity?: number;
548
- /** Element-level rotation in **radians**, pivoting around the unrotated
549
- * AABB center `(x + width/2, y + height/2)`. Emitted as SVG
550
- * `transform="rotate(angleDegrees cx cy)"`. */
551
- rotation?: number;
552
- /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */
553
- meta?: NamespaceMeta;
554
- }
555
- /**
556
- * Raster-image leaf — an SVG `<image>`. `href` is the element's `href` (or
557
- * legacy `xlink:href`) verbatim: an external URL or a `data:` URI. The
558
- * package neither fetches nor decodes it, so an external URL round-trips as
559
- * a reference and only resolves when something downstream loads it.
560
- *
561
- * SVG's `preserveAspectRatio` is not modeled; the box is taken literally.
562
- *
563
- * With a `source` rect or a flip, the element is written as a `<g
564
- * data-weasel-image>` holding a nested `<svg>` viewport at the box, whose
565
- * `viewBox` is the source window over a unit-square `<image>` — plain SVG 1.1,
566
- * which any reader crops and mirrors the same way, and which `parseSvg` reads
567
- * back as one image node.
568
- */
569
- interface SvgImageNode {
570
- kind: 'image';
571
- href: string;
572
- x: number;
573
- y: number;
574
- width: number;
575
- height: number;
576
- /** The part of the bitmap drawn into the box, as fractions of the bitmap's
577
- * width and height from its top-left. Omitted draws the whole bitmap.
578
- * Fractions rather than bitmap pixels because this package never decodes
579
- * the image, so it cannot know its size. */
580
- source?: {
581
- x: number;
582
- y: number;
583
- width: number;
584
- height: number;
585
- };
586
- /** Mirror the drawn region within the box, as `ImageDrawCommand` does. The
587
- * box does not move. */
588
- flipX?: boolean;
589
- flipY?: boolean;
590
- /** Element-level opacity (`opacity="..."`), 0..1. */
591
- opacity?: number;
592
- /** Element-level rotation in **radians**, pivoting around the unrotated
593
- * AABB center `(x + width/2, y + height/2)`. Emitted as SVG
594
- * `transform="rotate(angleDegrees cx cy)"`. */
595
- rotation?: number;
596
- /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */
597
- meta?: NamespaceMeta;
598
- }
599
- /** Discriminated-union node — the leaf of the public tree. */
600
- type SvgNode = SvgPathNode | SvgGroupNode | SvgTextNode | SvgImageNode;
601
-
602
147
  /**
603
148
  * One mark as SVG nodes, converted from the very commands the pane paints.
604
149
  *
@@ -606,10 +151,7 @@ type SvgNode = SvgPathNode | SvgGroupNode | SvgTextNode | SvgImageNode;
606
151
  * and this is a translation of it. `serializeSvg` turns the result into a
607
152
  * document.
608
153
  */
609
- declare function markSvgNodes(m: PaintableMark, content: {
610
- w: number;
611
- h: number;
612
- }, style?: MarkStyle): SvgNode[];
154
+ declare function markSvgNodes(m: PaintableMark, style?: MarkStyle, scale?: View['scale']): SvgNode[];
613
155
 
614
156
  /** Props for `<AnnotationOverlay>`. */
615
157
  interface AnnotationOverlayProps {
@@ -826,6 +368,9 @@ interface LabBaseProps {
826
368
  /** Offer the header's add-trial control. Default `true`; a lab that opens
827
369
  * trials some other way passes `false`. */
828
370
  addTrial?: boolean;
371
+ /** Offer the header's zoom controls, which act on the focused trial's camera
372
+ * and answer Mod+=, Mod+- and Mod+0. Default `true`. */
373
+ zoom?: boolean;
829
374
  /** Tools offered lab-wide. A trial whose instrument declares none of its own
830
375
  * reflects and writes this slot. */
831
376
  tools?: readonly TrialTool[];
@@ -850,7 +395,7 @@ type LabProps = LabBaseProps & ({
850
395
  });
851
396
  /** The lab runtime: opens the store, provides it, and renders one trial
852
397
  * per record in a grid. Each trial runs one of `instruments`. */
853
- declare function Lab(props: LabProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react.JSX.Element | null;
398
+ declare function Lab(props: LabProps): string | number | bigint | boolean | react.JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null;
854
399
 
855
400
  /** Props for `<LabBoundary>`. */
856
401
  interface LabBoundaryProps {
@@ -924,6 +469,16 @@ interface LabShellProps {
924
469
  * the trial runtime is wanted too. */
925
470
  declare function LabShell({ title, children, header, footer, mode, pages, path, documentTitle, }: LabShellProps): react.JSX.Element;
926
471
 
472
+ /**
473
+ * Zoom out, the zoom as a percentage, and zoom in, for whichever trial has the
474
+ * focus. The percentage resets to actual size. They route through core's
475
+ * `viewport.zoom` action, on a dispatcher of their own that listens for its
476
+ * keys — Mod+=, Mod+- and Mod+0 — so the buttons and the keys are one path.
477
+ * Over a trial with no camera the group stays, disabled, so the header does not
478
+ * reflow as the focus moves.
479
+ */
480
+ declare function LabZoom(): react.JSX.Element;
481
+
927
482
  /** A tile's persisted extent, keyed by the id its caller gave it. Grid resizes
928
483
  * write `span`; `size` is here because a strategy swap would write that. */
929
484
  type TrialLayout = Record<string, {
@@ -936,6 +491,7 @@ type TrialLayout = Record<string, {
936
491
  rows?: number;
937
492
  };
938
493
  }>;
494
+ /** Props for `Workspace`. */
939
495
  interface WorkspaceProps {
940
496
  children: ReactNode;
941
497
  /**
@@ -964,7 +520,7 @@ interface WorkspaceProps {
964
520
  padding?: number;
965
521
  /** Undocked sidebar panels to render alongside the trials. A `'tile'` panel
966
522
  * joins the grid as a peer of the trials; a `'floating'` one goes into the
967
- * floating zone above it. The body is portalled in by the trial that owns
523
+ * floating zone above it. The body is portaled in by the trial that owns
968
524
  * it, so all this renders is the frame and the host. */
969
525
  panels?: readonly PanelDescriptor[];
970
526
  /**
@@ -984,6 +540,20 @@ interface PanelDescriptor {
984
540
  title: string;
985
541
  as: 'tile' | 'floating';
986
542
  }
543
+ /**
544
+ * Auto-balanced tiling of trials, `ceil(sqrt(n))` columns wide.
545
+ *
546
+ * Tiles are absolutely positioned at the rects `gridStrategy` computes, not
547
+ * laid out by CSS — `windease/styles.css` (folded into
548
+ * `@weasel-js/labkit/styles.css`) carries the rules that positioning depends on.
549
+ *
550
+ * `panels` are undocked sidebar sections. A `'tile'` panel is registered as a
551
+ * peer of the trials under `PANEL_KIND`, so the grid places and resizes it like
552
+ * one; a `'floating'` panel goes in the overlay above. Either way this renders
553
+ * only the frame and an empty host: the section's content is portaled in by
554
+ * the trial that owns it, which is what keeps a torn-out section inside its
555
+ * trial's React tree instead of rebuilding it as a sibling.
556
+ */
987
557
  declare function Workspace({ children, ids, panels, resizable, reorderable, onReorder, layout, onLayoutChange, gap, padding, viewport, }: WorkspaceProps): react.JSX.Element;
988
558
 
989
559
  /** The specimen's sections, in page order. */
@@ -1001,6 +571,7 @@ declare function Specimen({ className }: {
1001
571
  /** The 2D view labkit has always shipped, and what a trial gets when it names no
1002
572
  * other. Re-exported under its own name so a consumer can say which it means. */
1003
573
  type ViewTransform2D = ViewTransform;
574
+ /** Zoom 1, no pan. */
1004
575
  declare const DEFAULT_VIEW: ViewTransform2D;
1005
576
  /** A trial's view is opaque to labkit, so anything that needs the 2D shape — the
1006
577
  * zoom chrome, `CanvasStack` — asks for it and handles not getting it. */
@@ -1013,6 +584,19 @@ declare function as2DView(view: unknown): ViewTransform2D | null;
1013
584
  */
1014
585
  declare const interstellarTheme: Theme;
1015
586
 
587
+ /**
588
+ * A trial's loupe switch, as a lens mounted inside the trial finds it. The
589
+ * trial offers its toolbar toggle while at least one lens has called `mount`,
590
+ * and every lens reads `on` as whether it is turned on.
591
+ */
592
+ interface LoupeSwitch {
593
+ on: boolean;
594
+ /** Reports a lens mounted; the returned function reports it gone. */
595
+ mount: () => () => void;
596
+ }
597
+ /** The loupe switch of the trial around the caller, or `null` outside one. */
598
+ declare const LoupeSwitchContext: react.Context<LoupeSwitch | null>;
599
+
1016
600
  /** Props for `<Trial>`. */
1017
601
  interface TrialProps {
1018
602
  id: string;
@@ -1044,6 +628,7 @@ interface LoupeBindings {
1044
628
  on: boolean;
1045
629
  toggle: () => void;
1046
630
  }
631
+ /** The trial's undo history as its chrome sees it. */
1047
632
  interface UndoBindings {
1048
633
  canUndo: boolean;
1049
634
  canRedo: boolean;
@@ -1059,8 +644,8 @@ interface TrialChromeProps {
1059
644
  undoBindings?: UndoBindings;
1060
645
  /** Supplied when the instrument declares a `job`. */
1061
646
  job?: JobHandle;
1062
- /** Supplied when the instrument declares a `loupe`. The lens itself is the
1063
- * trial's to mount; the chrome only offers the switch. */
647
+ /** Supplied while a lens is mounted in the trial. The lens itself is the
648
+ * instrument's to mount; the chrome only offers the switch. */
1064
649
  loupe?: LoupeBindings;
1065
650
  /** Contributions the trial runtime itself adds — the drag palette and the
1066
651
  * layer list, which depend on runtime state the instrument cannot reach. */
@@ -1080,5 +665,5 @@ interface TrialChromeProps {
1080
665
  * each region its slice. */
1081
666
  declare function TrialChrome({ trialId, record, instrument, isLastTrial, undoBindings, job, loupe, trialChrome, chrome, suppress, activeToolId, setActiveTool, children, }: TrialChromeProps): react.JSX.Element;
1082
667
 
1083
- export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, CloseIcon, CollapseIcon, ConfigField, ConfigRule, ConfigSchema, ControlRenderer, CurveField, DEFAULT_VIEW, ExpandIcon, ExportMenu, IconProps, Instrument, InstrumentList, JobHandle, Jog, Lab, LabBoundary, LabContribution, LabDensity, LabMode, LabPalette, LabRoot, LabShell, LabSwitcher, MarkList, MarkScene, MarkStyle, PaintableMark, PauseIcon, PlayIcon, PropertyGroup, PropertyListPack, ResetIcon, SPECIMEN_SECTIONS, Specimen, SplitProps, StepBackIcon, StepForwardIcon, StopIcon, StorageAdapter, Subpanel, TokenPanel, Trial, TrialBody, TrialChrome, TrialContribution, TrialInfo, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, annotationToolInfo, as2DView, capturePlan, captureTarget, composeCaptureSvg, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, inferTokenType, interstellarTheme, isStale, markSvgNodes, refitScale, resolveMarkStyle, seenFrom, toWeaselView, useAnnotations, useAnnotationsOptional, validateConfigSchema };
1084
- export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, CurveFieldProps, CurveMark, InstrumentSpec, JogProps, LabBoundaryProps, LabPage, LabPaletteProps, LabProps, LabRootProps, LabShellProps, LabSwitcherProps, MarkDrawOptions, MarkListProps, PaneSize, PanelDescriptor, PropertyGroupProps, SubpanelProps, TokenCategory, TokenEntry, TokenPanelProps, TokenScale, TokenScaleRule, TrialBodyProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, ValidationResult, ViewTransform2D, WorkspaceProps };
668
+ export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, ConfigField, ConfigRule, ConfigSchema, ControlRenderer, DEFAULT_VIEW, ExportMenu, Instrument, InstrumentList, JobHandle, Lab, LabBoundary, LabContribution, LabDensity, LabMode, LabPalette, LabRoot, LabShell, LabSwitcher, LabZoom, LoupeSwitchContext, MarkList, MarkScene, MarkStyle, PaintableMark, SPECIMEN_SECTIONS, Specimen, SplitProps, StorageAdapter, Trial, TrialBody, TrialChrome, TrialContribution, TrialInfo, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, annotationToolInfo, as2DView, capturePlan, captureTarget, composeCaptureSvg, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, interstellarTheme, isStale, markSvgNodes, resolveMarkStyle, seenFrom, toWeaselView, useAnnotations, useAnnotationsOptional, validateConfigSchema };
669
+ export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, InstrumentSpec, LabBoundaryProps, LabPage, LabPaletteProps, LabProps, LabRootProps, LabShellProps, LabSwitcherProps, LoupeSwitch, MarkDrawOptions, MarkListProps, PaneSize, PanelDescriptor, TrialBodyProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, ValidationResult, ViewTransform2D, WorkspaceProps };