@weasel-js/labkit 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +3 -7
  2. package/dist/_dts/{CanvasStackContext-CMMo180l.d.ts → CanvasStackContext-Wo6OwIVM.d.ts} +1 -1
  3. package/dist/_dts/FloatingPanel-7j0IcXwz.d.ts +30 -0
  4. package/dist/_dts/LayerList.d-BoELAMsM.d.ts +83 -0
  5. package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
  6. package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +404 -0
  7. package/dist/_dts/{Select.d-ZTiwzYyT.d.ts → Select.d-Cr8-zoup.d.ts} +105 -15
  8. package/dist/_dts/{usePanZoom-SSTZe410.d.ts → Stage-DWBBi8IU.d.ts} +80 -35
  9. package/dist/_dts/{index-DlKolEIZ.d.ts → index-CKyX0ME_.d.ts} +12 -13
  10. package/dist/_dts/{frac-B4hFJMiN.d.ts → types-B7yBTTF9.d.ts} +709 -651
  11. package/dist/_dts/{types-Db-3NNk1.d.ts → types-DTuViBvc.d.ts} +21 -2
  12. package/dist/_dts/{useTrialState-pnAE-UBD.d.ts → useTrialState-CMaV6UD4.d.ts} +2 -3
  13. package/dist/canvas/index.d.ts +41 -8
  14. package/dist/canvas/index.js +5 -3
  15. package/dist/chrome/index.d.ts +6 -6
  16. package/dist/chrome/index.js +9 -7
  17. package/dist/chunk-24W5VEJW.js +18 -0
  18. package/dist/chunk-24W5VEJW.js.map +1 -0
  19. package/dist/chunk-2RVCB2PT.js +3 -0
  20. package/dist/chunk-2RVCB2PT.js.map +1 -0
  21. package/dist/chunk-3RY6WL5T.js +38 -0
  22. package/dist/chunk-3RY6WL5T.js.map +1 -0
  23. package/dist/{chunk-CKUKF72R.js → chunk-4TT3PNPR.js} +68 -55
  24. package/dist/chunk-4TT3PNPR.js.map +1 -0
  25. package/dist/{chunk-KJCUERQF.js → chunk-6FLXL3I7.js} +9 -164
  26. package/dist/chunk-6FLXL3I7.js.map +1 -0
  27. package/dist/chunk-ASOK76ZH.js +431 -0
  28. package/dist/chunk-ASOK76ZH.js.map +1 -0
  29. package/dist/chunk-AWQG7FCC.js +19 -0
  30. package/dist/chunk-AWQG7FCC.js.map +1 -0
  31. package/dist/chunk-CGHF6RZV.js +300 -0
  32. package/dist/chunk-CGHF6RZV.js.map +1 -0
  33. package/dist/chunk-DWMSB4CA.js +228 -0
  34. package/dist/chunk-DWMSB4CA.js.map +1 -0
  35. package/dist/chunk-GHGO52SO.js +92 -0
  36. package/dist/chunk-GHGO52SO.js.map +1 -0
  37. package/dist/{chunk-LRI3MBGR.js → chunk-HKV7LRHY.js} +4 -4
  38. package/dist/{chunk-LRI3MBGR.js.map → chunk-HKV7LRHY.js.map} +1 -1
  39. package/dist/{chunk-EMXAIRUJ.js → chunk-IRTGUQ5O.js} +5 -4
  40. package/dist/chunk-IRTGUQ5O.js.map +1 -0
  41. package/dist/{chunk-H6ZAOWNE.js → chunk-JVBYV6TL.js} +3 -3
  42. package/dist/{chunk-H6ZAOWNE.js.map → chunk-JVBYV6TL.js.map} +1 -1
  43. package/dist/chunk-KHK5FGER.js +145 -0
  44. package/dist/chunk-KHK5FGER.js.map +1 -0
  45. package/dist/chunk-NEXR37YJ.js +144 -0
  46. package/dist/chunk-NEXR37YJ.js.map +1 -0
  47. package/dist/{chunk-A2ACAGW6.js → chunk-O6FFFOHS.js} +32 -7
  48. package/dist/chunk-O6FFFOHS.js.map +1 -0
  49. package/dist/chunk-QGMOA2YE.js +731 -0
  50. package/dist/chunk-QGMOA2YE.js.map +1 -0
  51. package/dist/{chunk-ERFMC6WU.js → chunk-S4NCI32V.js} +19 -10
  52. package/dist/chunk-S4NCI32V.js.map +1 -0
  53. package/dist/{chunk-753Y6HE6.js → chunk-SLAQPUI4.js} +4 -4
  54. package/dist/chunk-SLAQPUI4.js.map +1 -0
  55. package/dist/{chunk-REOBGYMC.js → chunk-TJ77A4A3.js} +3 -5
  56. package/dist/chunk-TJ77A4A3.js.map +1 -0
  57. package/dist/chunk-TYN6MLXX.js +13864 -0
  58. package/dist/chunk-TYN6MLXX.js.map +1 -0
  59. package/dist/{chunk-RS3HRQWU.js → chunk-WPLAANH4.js} +4 -3
  60. package/dist/chunk-WPLAANH4.js.map +1 -0
  61. package/dist/config/index.d.ts +51 -7
  62. package/dist/config/index.js +4 -5
  63. package/dist/controls/index.d.ts +92 -5
  64. package/dist/controls/index.js +5 -4
  65. package/dist/dragdrop/index.d.ts +9 -6
  66. package/dist/dragdrop/index.js +3 -2
  67. package/dist/index.d.ts +108 -154
  68. package/dist/index.js +456 -600
  69. package/dist/index.js.map +1 -1
  70. package/dist/layers/index.d.ts +5 -35
  71. package/dist/layers/index.js +3 -3
  72. package/dist/loupe/index.d.ts +21 -17
  73. package/dist/loupe/index.js +5 -3
  74. package/dist/overview/index.d.ts +56 -0
  75. package/dist/overview/index.js +288 -0
  76. package/dist/overview/index.js.map +1 -0
  77. package/dist/passthrough/weasel-ui.d.ts +434 -231
  78. package/dist/passthrough/weasel-ui.js +2 -1
  79. package/dist/primitives/index.d.ts +19 -54
  80. package/dist/primitives/index.js +6 -4
  81. package/dist/state/index.d.ts +8 -7
  82. package/dist/state/index.js +4 -5
  83. package/dist/state/index.js.map +1 -1
  84. package/dist/styles.css +360 -174
  85. package/dist/undo/index.d.ts +5 -4
  86. package/package.json +13 -13
  87. package/src/annotations/frac.test.ts +7 -0
  88. package/src/annotations/index.ts +1 -0
  89. package/src/annotations/paint.test.ts +21 -0
  90. package/src/annotations/paint.ts +12 -0
  91. package/src/annotations/store.test.ts +57 -0
  92. package/src/annotations/store.ts +25 -6
  93. package/src/annotations/toolMap.test.ts +37 -2
  94. package/src/annotations/toolMap.ts +13 -0
  95. package/src/annotations/types.ts +30 -2
  96. package/src/canvas/AGENTS.md +8 -10
  97. package/src/canvas/CameraInput.test.tsx +136 -0
  98. package/src/canvas/CameraInput.tsx +311 -0
  99. package/src/canvas/CanvasStack.tsx +42 -58
  100. package/src/canvas/LinkedCursor.less +16 -0
  101. package/src/canvas/LinkedCursor.tsx +54 -0
  102. package/src/canvas/Stage.test.tsx +18 -0
  103. package/src/canvas/Stage.tsx +42 -37
  104. package/src/canvas/cameraView.test.ts +60 -0
  105. package/src/canvas/cameraView.ts +61 -0
  106. package/src/canvas/index.ts +11 -2
  107. package/src/chrome/regions/SidebarRegion.less +197 -0
  108. package/src/chrome/regions/SidebarRegion.test.tsx +27 -0
  109. package/src/chrome/regions/SidebarRegion.tsx +7 -2
  110. package/src/chrome/types.ts +5 -2
  111. package/src/config/autoConfig.ts +2 -2
  112. package/src/config/builder.ts +21 -2
  113. package/src/config/entry.test.ts +10 -0
  114. package/src/config/fromConfigField.ts +1 -0
  115. package/src/config/index.ts +5 -0
  116. package/src/config/resolve.ts +11 -1
  117. package/src/config/rules.ts +2 -0
  118. package/src/config/sectionTree.test.ts +152 -0
  119. package/src/config/sectionTree.ts +134 -0
  120. package/src/config/types.ts +21 -0
  121. package/src/controls/ControlPanel.less +4 -0
  122. package/src/controls/ControlPanel.stories.tsx +55 -2
  123. package/src/controls/ControlPanel.test.tsx +40 -3
  124. package/src/controls/ControlPanel.tsx +134 -336
  125. package/src/controls/inDialog.test.tsx +100 -0
  126. package/src/controls/inDialog.tsx +38 -0
  127. package/src/controls/index.ts +1 -0
  128. package/src/index.test.ts +1 -1
  129. package/src/index.ts +18 -29
  130. package/src/instrument/SineWave.smoke.test.tsx +2 -0
  131. package/src/instrument/types.ts +15 -3
  132. package/src/lab/Lab.nebula.test.tsx +40 -0
  133. package/src/lab/Lab.test.tsx +3 -1
  134. package/src/lab/Lab.tsx +42 -19
  135. package/src/lab/LabBoundary.test.tsx +66 -0
  136. package/src/lab/LabBoundary.tsx +56 -0
  137. package/src/lab/LabHeader.tsx +4 -23
  138. package/src/lab/LabRoot.tsx +2 -3
  139. package/src/lab/LabShell.less +0 -1
  140. package/src/lab/LabShell.stories.tsx +15 -0
  141. package/src/lab/LabShell.test.tsx +18 -0
  142. package/src/lab/LabShell.tsx +14 -1
  143. package/src/lab/LabSwitcher.less +1 -1
  144. package/src/lab/LabSwitcher.test.tsx +41 -0
  145. package/src/lab/LabSwitcher.tsx +30 -8
  146. package/src/lab/index.ts +1 -0
  147. package/src/layers/AGENTS.md +18 -74
  148. package/src/layers/index.ts +4 -2
  149. package/src/loupe/AGENTS.md +7 -6
  150. package/src/loupe/LoupeGestures.tsx +14 -9
  151. package/src/loupe/TrialLoupe.tsx +5 -5
  152. package/src/loupe/index.ts +1 -0
  153. package/src/loupe/loupeActions.ts +6 -2
  154. package/src/overview/AGENTS.md +38 -0
  155. package/src/overview/OverviewMarks.test.tsx +100 -0
  156. package/src/overview/OverviewMarks.tsx +93 -0
  157. package/src/overview/TrialOverview.less +53 -0
  158. package/src/overview/TrialOverview.stories.tsx +50 -0
  159. package/src/overview/TrialOverview.test.tsx +116 -0
  160. package/src/overview/TrialOverview.tsx +374 -0
  161. package/src/overview/index.ts +2 -0
  162. package/src/passthrough/weasel-ui.ts +32 -10
  163. package/src/primitives/index.ts +0 -2
  164. package/src/specimen/Specimen.tsx +59 -56
  165. package/src/state/labRecords.test.ts +4 -1
  166. package/src/state/store.test.ts +4 -4
  167. package/src/state/types.ts +2 -1
  168. package/src/state/useTrialState.test.tsx +1 -1
  169. package/src/styles.less +6 -2
  170. package/src/theme/Interstellar.stories.tsx +8 -13
  171. package/src/theme/base.less +3 -20
  172. package/src/theme/interstellar.test.ts +6 -3
  173. package/src/theme/interstellar.theme.json +0 -56
  174. package/src/theme/interstellar.ts +2 -2
  175. package/src/tools/labTool.ts +6 -2
  176. package/src/trial/Trial.annotations.test.tsx +16 -0
  177. package/src/trial/Trial.canvas.test.tsx +1 -1
  178. package/src/trial/Trial.loupe.test.tsx +73 -1
  179. package/src/trial/Trial.stories.tsx +2 -0
  180. package/src/trial/Trial.tsx +47 -9
  181. package/src/trial/trialOps.test.ts +4 -4
  182. package/dist/_dts/index-8LiKe3A-.d.ts +0 -410
  183. package/dist/chunk-2AYGEN57.js +0 -32
  184. package/dist/chunk-2AYGEN57.js.map +0 -1
  185. package/dist/chunk-6BUQ77ZV.js +0 -18
  186. package/dist/chunk-6BUQ77ZV.js.map +0 -1
  187. package/dist/chunk-753Y6HE6.js.map +0 -1
  188. package/dist/chunk-A2ACAGW6.js.map +0 -1
  189. package/dist/chunk-CKUKF72R.js.map +0 -1
  190. package/dist/chunk-D35PFTS7.js +0 -170
  191. package/dist/chunk-D35PFTS7.js.map +0 -1
  192. package/dist/chunk-EMXAIRUJ.js.map +0 -1
  193. package/dist/chunk-ERFMC6WU.js.map +0 -1
  194. package/dist/chunk-FKLT3ITC.js +0 -590
  195. package/dist/chunk-FKLT3ITC.js.map +0 -1
  196. package/dist/chunk-KJCUERQF.js.map +0 -1
  197. package/dist/chunk-LASCBWW7.js +0 -13456
  198. package/dist/chunk-LASCBWW7.js.map +0 -1
  199. package/dist/chunk-REOBGYMC.js.map +0 -1
  200. package/dist/chunk-RS3HRQWU.js.map +0 -1
  201. package/dist/chunk-TT5C5S6R.js +0 -368
  202. package/dist/chunk-TT5C5S6R.js.map +0 -1
  203. package/dist/ui/layers/index.d.ts +0 -66
  204. package/dist/ui/layers/index.js +0 -3
  205. package/dist/ui/layers/index.js.map +0 -1
  206. package/src/canvas/usePanZoom.test.ts +0 -244
  207. package/src/canvas/usePanZoom.ts +0 -147
  208. package/src/lab/useSystemMode.ts +0 -30
  209. package/src/layers/LayerList.less +0 -93
  210. package/src/layers/LayerList.stories.tsx +0 -66
  211. package/src/layers/LayerList.test.tsx +0 -232
  212. package/src/layers/LayerList.tsx +0 -268
  213. package/src/primitives/Sidebar.less +0 -112
  214. package/src/primitives/Sidebar.stories.tsx +0 -38
  215. package/src/primitives/Sidebar.test.tsx +0 -74
  216. package/src/primitives/Sidebar.tsx +0 -35
  217. package/src/ui/layers/index.ts +0 -5
@@ -1,6 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as react from 'react';
3
2
  import { ReactNode, ButtonHTMLAttributes, ReactElement } from 'react';
3
+ import { S as StanceProps } from './PrefsRow.d-DFpPIeIC.js';
4
4
  import { TextFieldProps, ValidationResult, SelectProps as SelectProps$1, ListBoxItemProps } from 'react-aria-components';
5
5
 
6
6
  declare const ICON_PATHS: {
@@ -42,6 +42,7 @@ declare const ICON_PATHS: {
42
42
  readonly warning: "<path d=\"M10 3.4 17.4 16.2H2.6z\"/><path d=\"M10 8.4v3.4\"/><path d=\"M10 14h0\"/>";
43
43
  readonly error: "<circle cx=\"10\" cy=\"10\" r=\"7\"/><path d=\"M7.6 7.6 12.4 12.4M12.4 7.6 7.6 12.4\"/>";
44
44
  readonly busy: "<path d=\"M10 3.2A6.8 6.8 0 1 1 3.2 10\"/>";
45
+ readonly check: "<path d=\"M4.35 10.56 8.03 14.24 15.66 5.77\"/>";
45
46
  readonly modeLight: "<circle cx=\"10\" cy=\"10\" r=\"3.5\"/><path d=\"M15.3 10L17.7 10M13.75 6.25L15.44 4.56M10 4.7L10 2.3M6.25 6.25L4.56 4.56M4.7 10L2.3 10M6.25 13.75L4.56 15.44M10 15.3L10 17.7M13.75 13.75L15.44 15.44\"/>";
46
47
  readonly modeDark: "<path d=\"M8.19 3.55A6.7 6.7 0 1 0 16.45 11.81A5.9 5.9 0 0 1 8.19 3.55Z\"/>";
47
48
  readonly modeAuto: "<path d=\"M10 2.6Q10 10 17.4 10Q10 10 10 17.4Q10 10 2.6 10Q10 10 10 2.6Z\"/>";
@@ -51,6 +52,7 @@ declare const ICON_PATHS: {
51
52
  readonly search: "<circle cx=\"9\" cy=\"9\" r=\"5.4\"/><path d=\"M12.82 12.82 16.9 16.9\"/>";
52
53
  readonly loupe: "<circle cx=\"9\" cy=\"9\" r=\"5.6\"/><path d=\"M12.96 12.96 17 17\"/><rect x=\"6\" y=\"6\" width=\"6\" height=\"6\" stroke-width=\"1\"/><path d=\"M9 6v6M6 9h6\" stroke-width=\"1\"/>";
53
54
  readonly layers: "<path d=\"M10 2.8 17.2 6.6 10 10.4 2.8 6.6z\"/><path d=\"M2.8 10 10 13.8 17.2 10\" stroke-width=\"1\"/><path d=\"M2.8 13.4 10 17.2 17.2 13.4\" stroke-width=\"1\"/>";
55
+ readonly page: "<path d=\"M4.6 2.8H11.6L15.4 6.6V17.2H4.6z\"/><path d=\"M11.6 2.8V6.6H15.4\"/>";
54
56
  readonly link: "<path d=\"M8.6 11.4a3.4 3.4 0 0 1 0-4.8l2.2-2.2a3.4 3.4 0 0 1 4.8 4.8l-1.1 1.1\"/><path d=\"M11.4 8.6a3.4 3.4 0 0 1 0 4.8l-2.2 2.2a3.4 3.4 0 0 1-4.8-4.8l1.1-1.1\"/>";
55
57
  readonly collapse: "<path d=\"M14.16 4.05 10 7.8 5.84 4.05M5.84 15.95 10 12.2 14.16 15.95\"/>";
56
58
  readonly expand: "<path d=\"M5.84 8.15 10 4.4 14.16 8.15M14.16 11.85 10 15.6 5.84 11.85\"/>";
@@ -236,15 +238,33 @@ interface IconProps {
236
238
  * in; reach for this when the glyph is chosen at runtime. */
237
239
  declare function Icon({ name, className, size, label, filled, fillOpacity, }: IconProps & {
238
240
  name: IconName;
239
- }): react_jsx_runtime.JSX.Element;
241
+ }): react.JSX.Element;
240
242
 
241
- /** Visual weight of a button. Defaults to `secondary`. */
242
- type ButtonVariant = 'primary' | 'secondary' | 'ghost';
243
+ /** The tooltip fields a segmented bar's item carries. */
244
+ interface SegmentTooltipFields {
245
+ /** Tooltip content. Overrides the name-plus-`shortcut` default. */
246
+ tooltip?: ReactNode;
247
+ /** Shortcut hint shown in the tooltip as `Name (⌘Z)`, the way `ToolButton`
248
+ * and `ActionBar` show theirs. The name is `ariaLabel`, else a string
249
+ * `label`. */
250
+ shortcut?: string;
251
+ }
252
+
253
+ /** Visual weight of a button. Defaults to `secondary`. `link` drops the
254
+ * control box entirely and reads as a hyperlink in running text -- for an
255
+ * in-page navigation that is still a button, not an `<a href>`. */
256
+ type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'link';
257
+ /** Text color of a `link` button — the same set as `Code`'s statuses. */
258
+ type ButtonStatus = 'neutral' | 'muted' | 'accent' | 'success' | 'warn' | 'danger';
243
259
  /** Button height and type scale. */
244
260
  type ButtonSize = 'sm' | 'md';
245
261
  type ButtonBase = {
246
262
  variant?: ButtonVariant;
247
263
  size?: ButtonSize;
264
+ /** Text color of the `link` variant, which is `accent` unless told
265
+ * otherwise. The boxed variants carry their weight in their fill and
266
+ * ignore it. A peer `tone`, or a stance's accent, paints over it. */
267
+ status?: ButtonStatus;
248
268
  /** A button that stays down: renders `aria-pressed` and holds the active
249
269
  * treatment while it is on. For a control that reports a state rather than
250
270
  * firing an action -- a panel toggle, a mode switch. Left off, the button
@@ -260,7 +280,7 @@ type ButtonBase = {
260
280
  style?: ButtonHTMLAttributes<HTMLButtonElement>['style'];
261
281
  children?: ReactNode;
262
282
  onClick?: ButtonHTMLAttributes<HTMLButtonElement>['onClick'];
263
- };
283
+ } & StanceProps & SegmentTooltipFields;
264
284
  type ButtonRegular = ButtonBase & {
265
285
  iconOnly?: false;
266
286
  ariaLabel?: string;
@@ -279,6 +299,10 @@ type ButtonProps = ButtonRegular | ButtonIconOnly;
279
299
  * button `aria-busy`, and leaves the label in place; it does not disable the
280
300
  * button, so pass `disabled` too if the click should be blocked.
281
301
  *
302
+ * `shortcut` adds a kit tooltip reading `Name (⌘S)`, named by `ariaLabel` or
303
+ * string children, the way `ToolButton` and `ButtonBar` items show theirs;
304
+ * `tooltip` replaces that text with any content.
305
+ *
282
306
  * `ref` forwards to the underlying `<button>`.
283
307
  */
284
308
  declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
@@ -289,7 +313,7 @@ type ToggleBarItem<V extends string | number = string> = {
289
313
  label?: ReactNode;
290
314
  ariaLabel?: string;
291
315
  disabled?: boolean;
292
- };
316
+ } & SegmentTooltipFields;
293
317
  /** Segment height and type scale for a {@link ToggleBar}. */
294
318
  type ToggleBarSize = 'sm' | 'md';
295
319
  /** Visual treatment of a {@link ToggleBar}. */
@@ -362,9 +386,48 @@ interface OverlayPortalProps {
362
386
  /** React Aria props minus the portal key a weasel overlay owns. */
363
387
  type WithoutPortalTarget<T> = Omit<T, 'UNSTABLE_portalContainer'>;
364
388
 
389
+ /**
390
+ * Whether a {@link Field} stacks its label above the control or sits them
391
+ * side by side.
392
+ */
393
+ type FieldOrientation = 'stacked' | 'row';
394
+ /** Props for {@link Field}. */
395
+ type FieldProps = {
396
+ orientation?: FieldOrientation;
397
+ className?: string;
398
+ children?: ReactNode;
399
+ };
400
+ /**
401
+ * Layout primitive that arranges a label, control, hint, and error in the
402
+ * canonical weasel-ui form-row shape. The control itself owns its semantics
403
+ * (RAC `TextField`, `Checkbox`, etc.); this just paints the layout.
404
+ *
405
+ * Most users will instead reach for `Input` / `Checkbox` / `Switch`, which
406
+ * compose Field internally. Use Field directly when you need a custom
407
+ * control to sit in the same visual rhythm.
408
+ */
409
+ declare function Field({ orientation, className, children }: FieldProps): react.JSX.Element;
410
+ /**
411
+ * The class names {@link Field} paints its slots with, so a control composing
412
+ * its own layout can match the same form-row rhythm.
413
+ */
414
+ declare const fieldClasses: {
415
+ root: string;
416
+ row: string;
417
+ label: string;
418
+ hint: string;
419
+ error: string;
420
+ };
421
+
365
422
  /** Props for {@link Input}, on top of React Aria's `TextField` props. */
366
423
  type InputProps = Omit<TextFieldProps, 'children' | 'className'> & {
367
424
  label?: ReactNode;
425
+ /**
426
+ * `'stacked'` (the default) puts the label above the field; `'row'` sets it
427
+ * beside the field at its own width, with any description or error on a
428
+ * line below. Same vocabulary as {@link Field}'s `orientation`.
429
+ */
430
+ orientation?: FieldOrientation;
368
431
  description?: ReactNode;
369
432
  errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
370
433
  placeholder?: string;
@@ -381,6 +444,12 @@ type InputProps = Omit<TextFieldProps, 'children' | 'className'> & {
381
444
  */
382
445
  declare const Input: react.ForwardRefExoticComponent<Omit<TextFieldProps, "className" | "children"> & {
383
446
  label?: ReactNode;
447
+ /**
448
+ * `'stacked'` (the default) puts the label above the field; `'row'` sets it
449
+ * beside the field at its own width, with any description or error on a
450
+ * line below. Same vocabulary as {@link Field}'s `orientation`.
451
+ */
452
+ orientation?: FieldOrientation;
384
453
  description?: ReactNode;
385
454
  errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
386
455
  placeholder?: string;
@@ -402,6 +471,13 @@ type SelectOption = {
402
471
  */
403
472
  textValue?: string;
404
473
  };
474
+ /** A titled group of options in a {@link Select}'s `options` list. */
475
+ type SelectOptionGroup<T extends Key = string> = {
476
+ title: ReactNode;
477
+ options: ReadonlyArray<SelectOption & {
478
+ value: T;
479
+ }>;
480
+ };
405
481
  type Key = string | number;
406
482
  /** How a {@link Select} trigger signals that it opens a list. */
407
483
  type SelectIndicator = 'chevron' | 'underline' | 'none';
@@ -413,13 +489,22 @@ type SelectPopup = 'over' | 'below';
413
489
  */
414
490
  type SelectProps<T extends Key = string> = Omit<SelectProps$1<object>, 'children' | 'className' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange'> & {
415
491
  label?: ReactNode;
492
+ /**
493
+ * `'stacked'` (the default) puts the label above the trigger; `'row'` sets it
494
+ * beside the trigger at its own width, with any description or error on a
495
+ * line below. Same vocabulary as {@link Field}'s `orientation`.
496
+ */
497
+ orientation?: FieldOrientation;
416
498
  description?: ReactNode;
417
499
  errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
418
500
  placeholder?: string;
419
- /** Either pass `options` for a quick render, or `children` for full control. */
420
- options?: ReadonlyArray<SelectOption & {
501
+ /**
502
+ * Either pass `options` for a quick render, or `children` for full control.
503
+ * An entry with `title` and `options` of its own is a titled section.
504
+ */
505
+ options?: ReadonlyArray<(SelectOption & {
421
506
  value: T;
422
- }>;
507
+ }) | SelectOptionGroup<T>>;
423
508
  children?: ReactNode;
424
509
  selectedKey?: T | null;
425
510
  defaultSelectedKey?: T;
@@ -453,16 +538,21 @@ type SelectProps<T extends Key = string> = Omit<SelectProps$1<object>, 'children
453
538
  */
454
539
  triggerId?: string;
455
540
  className?: string;
456
- } & OverlayPortalProps;
541
+ } & SegmentTooltipFields & OverlayPortalProps;
457
542
  /**
458
543
  * Form select wrapping React Aria's Select. Pass either `options` for a
459
544
  * quick declarative render or `children` of `<SelectItem>` for control over
460
- * each row.
545
+ * each row; `<SelectSection>` (or an `options` entry with a `title`) groups
546
+ * rows under a heading.
461
547
  *
462
548
  * The selection key type is parameterized so consumers with a string-literal
463
549
  * union for `value` (e.g. `'r' | 'g' | 'b'`) get a typed `onSelectionChange`.
550
+ *
551
+ * `shortcut` puts a kit tooltip on the trigger reading `Name (⌘K)`, named by
552
+ * `aria-label` or a string `label`, as `Button` does; `tooltip` replaces that
553
+ * text.
464
554
  */
465
- declare function Select<T extends Key = string>(props: SelectProps<T>): react_jsx_runtime.JSX.Element;
555
+ declare function Select<T extends Key = string>(props: SelectProps<T>): react.JSX.Element;
466
556
  /** Props for {@link SelectItem}, on top of React Aria's `ListBoxItem` props. */
467
557
  type SelectItemProps = Omit<ListBoxItemProps, 'className' | 'children'> & {
468
558
  children?: ReactNode;
@@ -473,7 +563,7 @@ type SelectItemProps = Omit<ListBoxItemProps, 'className' | 'children'> & {
473
563
  * selected. A string child supplies its own `textValue`; anything richer must
474
564
  * pass one so type-to-select and screen readers have something to read.
475
565
  */
476
- declare function SelectItem({ children, className, textValue, ...rest }: SelectItemProps): react_jsx_runtime.JSX.Element;
566
+ declare function SelectItem({ children, className, textValue, ...rest }: SelectItemProps): react.JSX.Element;
477
567
 
478
- export { Button as B, Select as S, ToggleBar as T, Icon as d, Input as e, ICON_PATHS as l, SelectItem as n };
479
- export type { IconProps as I, OverlayPortalProps as O, WithoutPortalTarget as W, ButtonProps as a, ButtonSize as b, ButtonVariant as c, InputProps as f, SelectProps as g, ToggleBarItem as h, ToggleBarProps as i, ToggleBarSize as j, ToggleBarVariant as k, IconName as m, SelectItemProps as o, SelectOption as p };
568
+ export { Button as B, Select as S, ToggleBar as T, Icon as d, Input as e, Field as m, ICON_PATHS as o, SelectItem as q, fieldClasses as t };
569
+ export type { FieldOrientation as F, IconProps as I, OverlayPortalProps as O, WithoutPortalTarget as W, ButtonProps as a, ButtonSize as b, ButtonVariant as c, InputProps as f, SelectProps as g, ToggleBarItem as h, ToggleBarProps as i, ToggleBarSize as j, ToggleBarVariant as k, SegmentTooltipFields as l, FieldProps as n, IconName as p, SelectItemProps as r, SelectOption as s };
@@ -1,7 +1,75 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode, WheelEvent, PointerEvent as PointerEvent$1 } from 'react';
3
- import { k as ViewTransform, a as WorldSpec, V as ViewportSize, l as Point, W as WorldFrame } from './frac-B4hFJMiN.js';
4
- import { C as CanvasLayerDescriptor } from './CanvasStackContext-CMMo180l.js';
1
+ import * as react from 'react';
2
+ import { RefObject, ReactNode } from 'react';
3
+ import { ViewApi } from '@weasel-js/core';
4
+ import { W as WorldFrame, P as Point, b as ViewTransform, l as WorldSpec, V as ViewportSize } from './types-B7yBTTF9.js';
5
+ import { C as CanvasLayerDescriptor } from './CanvasStackContext-Wo6OwIVM.js';
6
+
7
+ /** The view id the stage publishes its pointer under. */
8
+ declare const STAGE_VIEW_ID = "stage";
9
+ /**
10
+ * A camera, as the things that sit beside it read it: an overview, a loupe, a
11
+ * linked cursor. Points are *frame-local* — the world with `y` multiplied by
12
+ * `frame.yDir` — which is the space `view` works in.
13
+ */
14
+ interface CameraContextValue {
15
+ /** The camera as a weasel `ViewApi`, clamped to its zoom range. */
16
+ view: ViewApi;
17
+ frame: WorldFrame;
18
+ /** The element the camera's dispatcher listens on. */
19
+ element: () => HTMLElement | null;
20
+ /** The content's own rect, frame-local, when it has one — a `<Stage>`'s. */
21
+ content?: {
22
+ x: number;
23
+ y: number;
24
+ width: number;
25
+ height: number;
26
+ };
27
+ }
28
+ /** The camera around the caller, or `null` outside one. */
29
+ declare const CameraContext: react.Context<CameraContextValue | null>;
30
+ /** Set by a host that already provides one input scope for everything inside
31
+ * it — a trial — so the camera, the loupe and an overview share it. */
32
+ declare const CameraScopeContext: react.Context<boolean>;
33
+ /**
34
+ * The actions and deps a camera routes through: the ones a trial provides, or
35
+ * an isolated set of its own. Isolated, because an actions registry holds one
36
+ * dispatcher, and a camera must not take input from a canvas beside it. The
37
+ * pointer store is the exception — one already in scope is kept, since sharing
38
+ * it is the point.
39
+ */
40
+ declare function CameraScope({ children }: {
41
+ children: ReactNode;
42
+ }): react.JSX.Element;
43
+ /** Options for {@link useCameraView}. */
44
+ interface CameraViewOptions {
45
+ view: ViewTransform;
46
+ onViewChange: (v: ViewTransform) => void;
47
+ frame: WorldFrame;
48
+ hostRef: RefObject<HTMLElement | null>;
49
+ minZoom?: number;
50
+ maxZoom?: number;
51
+ }
52
+ /**
53
+ * A labkit camera as a stable `ViewApi`. Its zoom range is widened to keep the
54
+ * opening zoom reachable — captured once, so a zoom-out cannot shrink the
55
+ * range and strand the opening view behind it.
56
+ */
57
+ declare function useCameraView({ view, onViewChange, frame, hostRef, minZoom, maxZoom, }: CameraViewOptions): ViewApi;
58
+ /** Props for `<CameraInput>`. */
59
+ interface CameraInputProps {
60
+ hostRef: RefObject<HTMLElement | null>;
61
+ camera: ViewApi;
62
+ frame: WorldFrame;
63
+ /** A primary-button press released without crossing the drag threshold, at
64
+ * the world point it landed on. */
65
+ onTap?: (world: Point) => void;
66
+ }
67
+ /**
68
+ * Mounts the dispatcher on `hostRef` and routes the camera's gestures through
69
+ * it. Render it inside a `<CameraScope>`; with no actions registry in scope it
70
+ * renders nothing.
71
+ */
72
+ declare function CameraInput(props: CameraInputProps): react.JSX.Element | null;
5
73
 
6
74
  /** Props for `<CanvasStack>`. */
7
75
  interface CanvasStackProps {
@@ -24,8 +92,9 @@ interface CanvasStackProps {
24
92
  }
25
93
  /** Stacks one `<canvas>` per layer and drives them from a shared view, so a
26
94
  * layer that changes rarely is not redrawn with one that changes every frame.
27
- * Handles sizing, device pixel ratio, and pan/zoom. */
28
- declare function CanvasStack({ layers, view: viewProp, onViewChange, worldSpec, minZoom, maxZoom, width, height, className, onResize, onHitTest, children, }: CanvasStackProps): react_jsx_runtime.JSX.Element;
95
+ * Handles sizing and device pixel ratio; pan and zoom route through weasel's
96
+ * gesture dispatcher (`<CameraInput>`). */
97
+ declare function CanvasStack({ layers, view: viewProp, onViewChange, worldSpec, minZoom, maxZoom, width, height, className, onResize, onHitTest, children, }: CanvasStackProps): react.JSX.Element;
29
98
 
30
99
  /** Bounds and coordinate system a {@link zoomAt} works in. */
31
100
  interface ZoomAtOptions {
@@ -82,36 +151,12 @@ interface StageProps {
82
151
  declare function fitStage(size: ViewportSize, viewport: ViewportSize): ViewTransform;
83
152
  /**
84
153
  * DOM content of a fixed size, panned and zoomed by a camera — what
85
- * `<CanvasStack>` is for layers drawn to a canvas. The content is laid out at
154
+ * `<CanvasStack>` is for layers drawn to a canvas. Pan and zoom route through
155
+ * weasel's gesture dispatcher (`<CameraInput>`). The content is laid out at
86
156
  * its own size and transformed, so everything inside keeps its layout and a
87
157
  * measurement of any element in it reports where it is actually drawn.
88
158
  */
89
- declare function Stage({ size, view: viewProp, onViewChange, minZoom, maxZoom, onResize, hostRef, overlay, children, }: StageProps): react_jsx_runtime.JSX.Element;
90
-
91
- interface UsePanZoomOptions {
92
- view: ViewTransform;
93
- onViewChange: (v: ViewTransform) => void;
94
- /** The opening `view.zoom` always stays reachable, widening these past
95
- * whatever is passed here if it would otherwise exclude it. */
96
- minZoom?: number;
97
- maxZoom?: number;
98
- /** The instrument's coordinate system, resolved against the viewport. The
99
- * wheel anchors in this frame; omitting it anchors at the element's
100
- * top-left, which is what labkit did before a frame could be declared. */
101
- frame?: WorldFrame;
102
- /** A primary-button press released without ever crossing the drag
103
- * threshold. The pointer session owns the release, so the gesture's end is
104
- * reported here rather than left for a consumer's own `onPointerUp`. */
105
- onTap?: (e: PointerEvent) => void;
106
- }
107
- interface PanZoomHandlers {
108
- /** Zoom about the pointer. `anchor` is the element the pointer position is
109
- * measured against, for an event whose `currentTarget` is some other box. */
110
- onWheel: (e: WheelEvent<HTMLElement> | globalThis.WheelEvent, anchor?: Element) => void;
111
- onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
112
- isDragging: () => boolean;
113
- }
114
- declare function usePanZoom({ view, onViewChange, minZoom, maxZoom, frame, onTap, }: UsePanZoomOptions): PanZoomHandlers;
159
+ declare function Stage({ size, view: viewProp, onViewChange, minZoom, maxZoom, onResize, hostRef, overlay, children, }: StageProps): react.JSX.Element;
115
160
 
116
- export { CanvasStack as C, Stage as S, centerOn as c, fitStage as f, screenToWorld as s, usePanZoom as u, worldToScreen as w, zoomAt as z };
117
- export type { PanZoomHandlers as P, UsePanZoomOptions as U, ZoomAtOptions as Z, CanvasStackProps as a, StageProps as b };
161
+ export { CameraContext as C, STAGE_VIEW_ID as S, CameraInput as b, CameraScope as d, CameraScopeContext as e, CanvasStack as g, Stage as i, centerOn as k, fitStage as l, screenToWorld as s, useCameraView as u, worldToScreen as w, zoomAt as z };
162
+ export type { ZoomAtOptions as Z, CameraContextValue as a, CameraInputProps as c, CameraViewOptions as f, CanvasStackProps as h, StageProps as j };
@@ -1,6 +1,5 @@
1
- import { d as ControlRenderer, c as ConfigRule } from './types-Db-3NNk1.js';
2
- import { K as Instrument, as as TrialChromeContext, O as TrialContribution, T as TrialRecord, q as InstrumentList, e as SavedSnapshot, o as LabMode, aq as ToolSlotContext, a4 as ContributionBase, ar as ToolbarItem, ap as ToolItem, aj as SidebarSection, am as StatusReadout, H as TrialTool, af as RegionContribution, ak as SidebarSlotContext } from './frac-B4hFJMiN.js';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import { d as ControlRenderer, c as ConfigRule } from './types-DTuViBvc.js';
2
+ import { R as Instrument, ax as TrialChromeContext, Y as TrialContribution, T as TrialRecord, t as InstrumentList, f as SavedSnapshot, s as LabMode, av as ToolSlotContext, a9 as ContributionBase, aw as ToolbarItem, au as ToolItem, ao as SidebarSection, ar as StatusReadout, O as TrialTool, ak as RegionContribution, ap as SidebarSlotContext } from './types-B7yBTTF9.js';
4
3
  import * as react from 'react';
5
4
  import { ReactNode } from 'react';
6
5
 
@@ -142,15 +141,15 @@ interface LabRegionProps {
142
141
  contributions: readonly LabContribution[];
143
142
  }
144
143
  /** The lab's action bar, in the shell header beside the title. */
145
- declare function LabHeaderRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
144
+ declare function LabHeaderRegion({ contributions }: LabRegionProps): react.JSX.Element;
146
145
  /** The lab's sidebar sections. Fold state is a lab-scoped persisted value, so it
147
146
  * survives a reload in a stored lab and lasts the session in an unstored one. */
148
- declare function LabSidebarRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
147
+ declare function LabSidebarRegion({ contributions }: LabRegionProps): react.JSX.Element;
149
148
  /** The lab's aside sections, on the far side of the workspace from the sidebar.
150
149
  * Fold state persists the way the sidebar's does. */
151
- declare function LabAsideRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
150
+ declare function LabAsideRegion({ contributions }: LabRegionProps): react.JSX.Element;
152
151
  /** The lab's readouts, in the shell footer below the workspace. */
153
- declare function LabFooterRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
152
+ declare function LabFooterRegion({ contributions }: LabRegionProps): react.JSX.Element;
154
153
 
155
154
  /**
156
155
  * Concatenate contribution bundles into one list, preserving order — order
@@ -183,7 +182,7 @@ interface PaletteRegionProps<TCtx extends ToolSlotContext = TrialChromeContext>
183
182
  /** A tool strip: a trial's, or the lab's. Selection lives in whichever tool
184
183
  * slot the context carries; this region only reflects it. An item carrying
185
184
  * `onActivate` is a command instead — it presses, and never latches. */
186
- declare function PaletteRegion<TCtx extends ToolSlotContext = TrialChromeContext>({ contributions, ctx, region, }: PaletteRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
185
+ declare function PaletteRegion<TCtx extends ToolSlotContext = TrialChromeContext>({ contributions, ctx, region, }: PaletteRegionProps<TCtx>): react.JSX.Element | null;
187
186
 
188
187
  /** Props for `<SidebarRegion>`. */
189
188
  interface SidebarRegionProps<TCtx extends SidebarSlotContext = TrialChromeContext> {
@@ -196,7 +195,7 @@ interface SidebarRegionProps<TCtx extends SidebarSlotContext = TrialChromeContex
196
195
  * trial's, or the lab's. A section the trial has torn out is not rendered
197
196
  * here — `Trial` portals its body into the workspace instead. A context with
198
197
  * no `undockPanel` offers no tear-out. */
199
- declare function SidebarRegion<TCtx extends SidebarSlotContext = TrialChromeContext>({ contributions, ctx, region, }: SidebarRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
198
+ declare function SidebarRegion<TCtx extends SidebarSlotContext = TrialChromeContext>({ contributions, ctx, region, }: SidebarRegionProps<TCtx>): react.JSX.Element | null;
200
199
 
201
200
  /** Props for `<StatusRegion>`. */
202
201
  interface StatusRegionProps<TCtx = TrialChromeContext> {
@@ -206,7 +205,7 @@ interface StatusRegionProps<TCtx = TrialChromeContext> {
206
205
  region?: string;
207
206
  }
208
207
  /** Lays a bar's readouts out. */
209
- declare function StatusRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, }: StatusRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
208
+ declare function StatusRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, }: StatusRegionProps<TCtx>): react.JSX.Element | null;
210
209
 
211
210
  /** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders
212
211
  * the contributions that leave `end` unset, before the title; `'actions'`
@@ -220,7 +219,7 @@ interface TitleBarRegionProps {
220
219
  placement?: TitleBarPlacement;
221
220
  }
222
221
  /** Lays a trial's `titlebar` contributions out at one end of the bar. */
223
- declare function TitleBarRegion({ contributions, ctx, placement }: TitleBarRegionProps): react_jsx_runtime.JSX.Element | null;
222
+ declare function TitleBarRegion({ contributions, ctx, placement }: TitleBarRegionProps): react.JSX.Element | null;
224
223
 
225
224
  /** Props for `<ToolbarRegion>`. */
226
225
  interface ToolbarRegionProps<TCtx = TrialChromeContext> {
@@ -232,7 +231,7 @@ interface ToolbarRegionProps<TCtx = TrialChromeContext> {
232
231
  label?: string;
233
232
  }
234
233
  /** Lays a bar's contributions out, grouped by their `group`. */
235
- declare function ToolbarRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, label, }: ToolbarRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
234
+ declare function ToolbarRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, label, }: ToolbarRegionProps<TCtx>): react.JSX.Element | null;
236
235
 
237
236
  /** Props for `<ViewportRegion>`. */
238
237
  interface ViewportRegionProps {
@@ -243,7 +242,7 @@ interface ViewportRegionProps {
243
242
  * Controls acting on the view of a trial. Anchored inside the content well
244
243
  * rather than in the toolbar, which acts on the trial itself.
245
244
  */
246
- declare function ViewportRegion({ contributions, ctx }: ViewportRegionProps): react_jsx_runtime.JSX.Element | null;
245
+ declare function ViewportRegion({ contributions, ctx }: ViewportRegionProps): react.JSX.Element | null;
247
246
 
248
247
  export { resetTrial as B, suppressContributions as C, toolContributions as D, useLabChromeContext as E, useLabContext as F, PaletteRegion as P, SidebarRegion as S, ViewportRegion as V, LabAsideRegion as a, LabContext as c, LabFooterRegion as e, LabHeaderRegion as f, LabSidebarRegion as i, StatusRegion as l, TitleBarRegion as n, ToolbarRegion as p, addTrial as s, builtinContributions as t, cloneTrial as u, closeTrial as v, contributionsIn as w, labContributions as x, mergeContributions as y, reorderTrials as z };
249
248
  export type { AddTrialOptions as A, LabContribution as L, TitleBarPlacement as T, LabChromeContext as b, LabContextValue as d, LabRegion as g, LabRegionProps as h, PaletteRegionProps as j, SidebarRegionProps as k, StatusRegionProps as m, TitleBarRegionProps as o, ToolbarRegionProps as q, ViewportRegionProps as r };