@weasel-js/labkit 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +3 -7
  2. package/dist/_dts/{CanvasStackContext-CJNMS6mz.d.ts → CanvasStackContext-DQgcH1ny.d.ts} +1 -1
  3. package/dist/_dts/LayerList.d-2c9yup5Y.d.ts +83 -0
  4. package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
  5. package/dist/_dts/{Select.d-Gwr8fLpK.d.ts → Select.d-BchGMC2Y.d.ts} +129 -12
  6. package/dist/_dts/{frac-B4okC2lX.d.ts → frac-DTRq7Xpb.d.ts} +31 -13
  7. package/dist/_dts/inDialog-D5ZKGjiD.d.ts +23 -0
  8. package/dist/_dts/{index-CSJoj4LC.d.ts → index-B0--8PEM.d.ts} +5 -4
  9. package/dist/_dts/index-DINmCuLA.d.ts +453 -0
  10. package/dist/_dts/number.d-OeQYQoUO.d.ts +28 -0
  11. package/dist/_dts/{types-DzoNY1pO.d.ts → types-B7y8hX1D.d.ts} +6 -6
  12. package/dist/_dts/{usePanZoom-Pzf9f2jh.d.ts → usePanZoom-Bq73pwFe.d.ts} +4 -47
  13. package/dist/_dts/{useTrialState-uLlmaccn.d.ts → useTrialState-CP4jfuKl.d.ts} +1 -1
  14. package/dist/canvas/index.d.ts +6 -5
  15. package/dist/canvas/index.js +1 -1
  16. package/dist/chrome/index.d.ts +5 -4
  17. package/dist/chrome/index.js +7 -7
  18. package/dist/chunk-2RVCB2PT.js +3 -0
  19. package/dist/chunk-2RVCB2PT.js.map +1 -0
  20. package/dist/{chunk-UN4U4P63.js → chunk-3FI7Y4R4.js} +9 -9
  21. package/dist/chunk-3FI7Y4R4.js.map +1 -0
  22. package/dist/{chunk-7PFH3CNM.js → chunk-AWH3SRPW.js} +31 -5
  23. package/dist/chunk-AWH3SRPW.js.map +1 -0
  24. package/dist/{chunk-ZDHY47EV.js → chunk-BVL7Y574.js} +25 -9
  25. package/dist/chunk-BVL7Y574.js.map +1 -0
  26. package/dist/{chunk-IHUVQ3TX.js → chunk-H5VIV7MQ.js} +31 -27
  27. package/dist/chunk-H5VIV7MQ.js.map +1 -0
  28. package/dist/chunk-HFRE4QQV.js +400 -0
  29. package/dist/chunk-HFRE4QQV.js.map +1 -0
  30. package/dist/{chunk-IXTQI7JX.js → chunk-MOLIUNVH.js} +4 -4
  31. package/dist/{chunk-IXTQI7JX.js.map → chunk-MOLIUNVH.js.map} +1 -1
  32. package/dist/{chunk-CEIUBPPW.js → chunk-TT5C5S6R.js} +3 -86
  33. package/dist/chunk-TT5C5S6R.js.map +1 -0
  34. package/dist/chunk-USO6TERP.js +90 -0
  35. package/dist/chunk-USO6TERP.js.map +1 -0
  36. package/dist/{chunk-PHK4W562.js → chunk-VQ47KWD5.js} +3 -3
  37. package/dist/{chunk-PHK4W562.js.map → chunk-VQ47KWD5.js.map} +1 -1
  38. package/dist/chunk-WUJXJC5O.js +14568 -0
  39. package/dist/chunk-WUJXJC5O.js.map +1 -0
  40. package/dist/{chunk-EHGVROVV.js → chunk-ZORVNOKX.js} +6 -25
  41. package/dist/chunk-ZORVNOKX.js.map +1 -0
  42. package/dist/config/index.d.ts +53 -11
  43. package/dist/config/index.js +5 -5
  44. package/dist/controls/index.d.ts +6 -3
  45. package/dist/controls/index.js +4 -4
  46. package/dist/dragdrop/index.d.ts +4 -3
  47. package/dist/index.d.ts +139 -114
  48. package/dist/index.js +470 -479
  49. package/dist/index.js.map +1 -1
  50. package/dist/layers/index.d.ts +6 -35
  51. package/dist/layers/index.js +2 -3
  52. package/dist/loupe/index.d.ts +6 -5
  53. package/dist/passthrough/weasel-ui.d.ts +421 -215
  54. package/dist/passthrough/weasel-ui.js +1 -1
  55. package/dist/primitives/index.d.ts +2 -13
  56. package/dist/primitives/index.js +4 -4
  57. package/dist/state/index.d.ts +6 -5
  58. package/dist/state/index.js +5 -5
  59. package/dist/styles.css +410 -190
  60. package/dist/undo/index.d.ts +4 -3
  61. package/package.json +9 -13
  62. package/src/annotations/frac.test.ts +7 -0
  63. package/src/annotations/paint.test.ts +21 -0
  64. package/src/annotations/paint.ts +12 -0
  65. package/src/annotations/store.test.ts +31 -0
  66. package/src/annotations/types.ts +3 -2
  67. package/src/canvas/Stage.test.tsx +18 -0
  68. package/src/canvas/index.ts +0 -9
  69. package/src/chrome/labTypes.ts +1 -1
  70. package/src/chrome/regions/PaletteRegion.test.tsx +18 -0
  71. package/src/chrome/regions/PaletteRegion.tsx +5 -4
  72. package/src/chrome/regions/SidebarRegion.less +197 -0
  73. package/src/chrome/regions/SidebarRegion.test.tsx +20 -0
  74. package/src/chrome/regions/SidebarRegion.tsx +7 -2
  75. package/src/chrome/regions/TitleBarRegion.tsx +1 -1
  76. package/src/chrome/types.ts +13 -4
  77. package/src/config/autoConfig.ts +2 -2
  78. package/src/config/builder.ts +23 -5
  79. package/src/config/entry.test.ts +8 -0
  80. package/src/config/index.ts +2 -0
  81. package/src/config/rules.ts +2 -0
  82. package/src/config/sectionTree.test.ts +146 -0
  83. package/src/config/sectionTree.ts +124 -0
  84. package/src/config/types.ts +4 -4
  85. package/src/controls/AutoControls.stories.tsx +6 -6
  86. package/src/controls/ControlPanel.less +27 -0
  87. package/src/controls/ControlPanel.stories.tsx +95 -1
  88. package/src/controls/ControlPanel.test.tsx +82 -112
  89. package/src/controls/ControlPanel.tsx +159 -396
  90. package/src/controls/inDialog.test.tsx +82 -0
  91. package/src/controls/inDialog.tsx +46 -0
  92. package/src/controls/index.ts +1 -0
  93. package/src/index.test.ts +0 -2
  94. package/src/index.ts +14 -35
  95. package/src/instrument/types.ts +5 -2
  96. package/src/lab/Lab.nebula.test.tsx +31 -0
  97. package/src/lab/Lab.tsx +57 -18
  98. package/src/lab/LabBoundary.test.tsx +66 -0
  99. package/src/lab/LabBoundary.tsx +56 -0
  100. package/src/lab/LabHeader.tsx +4 -23
  101. package/src/lab/LabRoot.tsx +2 -3
  102. package/src/lab/LabShell.less +0 -1
  103. package/src/lab/LabShell.stories.tsx +15 -0
  104. package/src/lab/LabShell.test.tsx +18 -0
  105. package/src/lab/LabShell.tsx +14 -1
  106. package/src/lab/LabSwitcher.less +1 -1
  107. package/src/lab/LabSwitcher.test.tsx +41 -0
  108. package/src/lab/LabSwitcher.tsx +30 -8
  109. package/src/lab/index.ts +1 -0
  110. package/src/layers/AGENTS.md +18 -74
  111. package/src/layers/index.ts +4 -2
  112. package/src/passthrough/weasel-ui.ts +25 -10
  113. package/src/primitives/FpsMeter.less +6 -1
  114. package/src/primitives/FpsMeter.test.tsx +12 -4
  115. package/src/primitives/FpsMeter.tsx +6 -1
  116. package/src/primitives/JobProgress.stories.tsx +1 -1
  117. package/src/primitives/StatusBar.less +6 -0
  118. package/src/primitives/index.ts +0 -2
  119. package/src/specimen/Specimen.tsx +42 -56
  120. package/src/state/types.ts +8 -2
  121. package/src/state/view.test.ts +4 -4
  122. package/src/styles.less +4 -2
  123. package/src/theme/Interstellar.stories.tsx +8 -9
  124. package/src/theme/base.less +3 -20
  125. package/src/theme/interstellar.test.ts +6 -3
  126. package/src/theme/interstellar.theme.json +0 -56
  127. package/src/theme/interstellar.ts +2 -2
  128. package/src/trial/Trial.canvas.test.tsx +9 -5
  129. package/src/trial/Trial.config.test.tsx +1 -1
  130. package/src/trial/Trial.tsx +30 -8
  131. package/dist/_dts/index-BNdz-tNd.d.ts +0 -423
  132. package/dist/chunk-7PFH3CNM.js.map +0 -1
  133. package/dist/chunk-CEIUBPPW.js.map +0 -1
  134. package/dist/chunk-EH7UEQV7.js +0 -590
  135. package/dist/chunk-EH7UEQV7.js.map +0 -1
  136. package/dist/chunk-EHGVROVV.js.map +0 -1
  137. package/dist/chunk-IHUVQ3TX.js.map +0 -1
  138. package/dist/chunk-MDVTK5U3.js +0 -170
  139. package/dist/chunk-MDVTK5U3.js.map +0 -1
  140. package/dist/chunk-PJ7WEQBJ.js +0 -18
  141. package/dist/chunk-PJ7WEQBJ.js.map +0 -1
  142. package/dist/chunk-T3EC2DXD.js +0 -12628
  143. package/dist/chunk-T3EC2DXD.js.map +0 -1
  144. package/dist/chunk-UN4U4P63.js.map +0 -1
  145. package/dist/chunk-ZDHY47EV.js.map +0 -1
  146. package/dist/ui/layers/index.d.ts +0 -66
  147. package/dist/ui/layers/index.js +0 -3
  148. package/dist/ui/layers/index.js.map +0 -1
  149. package/src/canvas/useOrbit.test.ts +0 -167
  150. package/src/canvas/useOrbit.ts +0 -156
  151. package/src/lab/useSystemMode.ts +0 -30
  152. package/src/layers/LayerList.less +0 -93
  153. package/src/layers/LayerList.stories.tsx +0 -66
  154. package/src/layers/LayerList.test.tsx +0 -232
  155. package/src/layers/LayerList.tsx +0 -268
  156. package/src/primitives/Sidebar.less +0 -112
  157. package/src/primitives/Sidebar.stories.tsx +0 -38
  158. package/src/primitives/Sidebar.test.tsx +0 -74
  159. package/src/primitives/Sidebar.tsx +0 -35
  160. package/src/ui/layers/index.ts +0 -5
@@ -1,12 +1,15 @@
1
- import { O as OverlayPortalProps, W as WithoutPortalTarget } from '../_dts/Select.d-Gwr8fLpK.js';
2
- export { B as Button, a as ButtonProps, b as ButtonSize, c as ButtonVariant, l as ICON_PATHS, d as Icon, m as IconName, I as IconProps, e as Input, f as InputProps, S as Select, n as SelectItem, o as SelectItemProps, p as SelectOption, g as SelectProps, T as ToggleBar, h as ToggleBarItem, i as ToggleBarProps, j as ToggleBarSize, k as ToggleBarVariant } from '../_dts/Select.d-Gwr8fLpK.js';
3
- import { ToolPrefLeaf, ToolPrefGroup, ToolsApi } from '@weasel-js/core';
1
+ import { j as ToggleBarSize, k as ToggleBarVariant, l as SegmentTooltipFields, F as FieldOrientation, O as OverlayPortalProps, W as WithoutPortalTarget } from '../_dts/Select.d-BchGMC2Y.js';
2
+ export { B as Button, a as ButtonProps, b as ButtonSize, c as ButtonVariant, m as Field, n as FieldProps, o as ICON_PATHS, d as Icon, p as IconName, I as IconProps, e as Input, f as InputProps, S as Select, q as SelectItem, r as SelectItemProps, s as SelectOption, g as SelectProps, T as ToggleBar, h as ToggleBarItem, i as ToggleBarProps, t as fieldClasses } from '../_dts/Select.d-BchGMC2Y.js';
3
+ import { ToolPrefLeaf, ToolPrefGroup, ToolsApi, oklchDegToHex } from '@weasel-js/core';
4
4
  export { ToolPref as BuiltinPref, ToolPrefBoolean as PrefBoolean, ToolPrefBooleanControl as PrefBooleanControl, ToolPrefColor as PrefColor, ToolPrefCustom as PrefCustom, ToolPrefEnum as PrefEnum, ToolPrefEnumControl as PrefEnumControl, ToolPrefEnumEncoding as PrefEnumEncoding, ToolPrefGroup as PrefGroup, ToolPrefKind as PrefKind, ToolPrefLeaf as PrefLeaf, ToolPrefNumber as PrefNumber, ToolPrefNumberControl as PrefNumberControl, ToolPrefNumberUnit as PrefNumberUnit, ToolPrefObject as PrefObject, ToolPrefPaint as PrefPaint, ToolPrefString as PrefString, ToolPrefStringControl as PrefStringControl } from '@weasel-js/core';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import * as react from 'react';
7
- import { ReactNode, CSSProperties, ReactElement, KeyboardEvent, RefObject, PointerEvent, RefCallback } from 'react';
8
- export { LayerStack, LayerStackItem, LayerStackProps } from '../ui/layers/index.js';
9
- export { a as PrefRenderContext, P as PrefRenderer } from '../_dts/PrefsForm.d-DPy9I8It.js';
7
+ import { ReactNode, CSSProperties, HTMLAttributes, ReactElement, PointerEvent, RefCallback, KeyboardEvent, RefObject } from 'react';
8
+ import { S as StanceProps, P as PrefRenderer } from '../_dts/PrefsRow.d-DFpPIeIC.js';
9
+ export { a as PrefRenderContext } from '../_dts/PrefsRow.d-DFpPIeIC.js';
10
+ export { L as LayerList, a as LayerListItem, b as LayerListProps, c as LayerMove, m as moveLayers } from '../_dts/LayerList.d-2c9yup5Y.js';
11
+ import { ColorModePreference } from '@weasel-js/theme';
12
+ export { M as MINUS_SIGN, f as formatNumber } from '../_dts/number.d-OeQYQoUO.js';
10
13
  import { CheckboxProps as CheckboxProps$1, SwitchProps as SwitchProps$1, TabProps as TabProps$1, TabListProps as TabListProps$1, TabPanelProps as TabPanelProps$1, TabsProps as TabsProps$1, RadioProps as RadioProps$1, RadioGroupProps as RadioGroupProps$1, ValidationResult, NumberFieldProps as NumberFieldProps$1, ComboBoxProps as ComboBoxProps$1, ListBoxItemProps, SliderProps as SliderProps$1, ModalOverlayProps, DialogProps as DialogProps$1, PopoverProps } from 'react-aria-components';
11
14
  export { DialogTrigger as CalloutTrigger } from 'react-aria-components';
12
15
 
@@ -50,15 +53,16 @@ interface ActionBarProps {
50
53
  /** Layout direction. Defaults to `'horizontal'`. */
51
54
  orientation?: 'horizontal' | 'vertical';
52
55
  /**
53
- * Per-id icon overrides — keyed by `action.id`. When an entry is provided
56
+ * Per-entry icon overrides, keyed by `ActionItem.key` — the action id, or
57
+ * `id:variant` for one variant of a parametric action. When an entry is provided
54
58
  * it replaces the action's own `icon` for this bar only. Mirrors
55
59
  * `PathfinderPanelProps.icons` so call sites that ship custom glyph sets
56
60
  * can swap them in without re-registering actions.
57
61
  */
58
62
  icons?: Record<string, ReactNode>;
59
63
  /**
60
- * Per-id label overrides — keyed by `action.id`. Drives both `aria-label`
61
- * and `title`. When omitted, the action's own `label` is used.
64
+ * Per-entry label overrides, keyed like `icons`. Drives both `aria-label`
65
+ * and `title`. When omitted, the entry's own `label` is used.
62
66
  */
63
67
  labels?: Record<string, string>;
64
68
  /** Additional class for the toolbar root. */
@@ -67,7 +71,8 @@ interface ActionBarProps {
67
71
  /**
68
72
  * Generic group-keyed action toolbar. Reads the parent `ActionsRegistry`,
69
73
  * filters to actions whose `group` matches `props.group`, and renders one
70
- * icon button per match. Disabled state is derived from each action's
74
+ * icon button per match — or per variant, for an action that declares
75
+ * `variants`. Disabled state is derived from each action's
71
76
  * `enabled` predicate via `evaluateEnabled` (so the button greys out and
72
77
  * swallows clicks while the keybinding — if any — still fires through the
73
78
  * registry's keydown listener; that's the registry's contract, not ours).
@@ -86,14 +91,15 @@ declare function ActionBar(props: ActionBarProps): react_jsx_runtime.JSX.Element
86
91
  */
87
92
  type BadgeShape = 'pill' | 'plain' | 'square' | 'notched' | 'perforated' | 'hexagon' | 'starburst' | 'scalloped' | 'shield' | 'ribbon' | 'beavis' | 'sparkler' | 'postage' | 'cloud' | 'house' | 'plaque' | 'crest' | 'urn' | 'coffin' | 'receipt' | 'wood' | 'quatrefoil';
88
93
  /**
89
- * Semantic color of a badge. `custom` paints from the `--badge-edge` custom
94
+ * Status color of a badge. `custom` paints from the `--badge-edge` custom
90
95
  * property instead of a theme token, so a call site can supply its own color.
91
96
  */
92
- type BadgeTone = 'accent' | 'info' | 'warn' | 'danger' | 'muted' | 'neutral' | 'custom';
93
- /** How a badge's tone is applied: outline only, filled, or a soft tinted fill. */
97
+ type BadgeStatus = 'accent' | 'info' | 'success' | 'warn' | 'danger' | 'muted' | 'neutral' | 'custom';
98
+ /** How a badge's color is applied: outline only, filled, or a soft tinted fill. */
94
99
  type BadgeVariant = 'outline' | 'solid' | 'subtle';
95
- /** Badge type scale and padding step. */
96
- type BadgeSize = 'sm' | 'md';
100
+ /** Badge type scale and padding step. `xs` is for counts and markers set
101
+ * inside a dense row, on the 2xs type step. */
102
+ type BadgeSize = 'xs' | 'sm' | 'md';
97
103
 
98
104
  interface SquareParams {
99
105
  /** 0..1 fraction of the maximum corner rounding (1 = full pill). */
@@ -648,7 +654,7 @@ interface SunbeamsEffectParams {
648
654
  * `backdrop-filter: blur(...)` on the host element via CSS.
649
655
  */
650
656
  interface AquaEffectParams {
651
- /** Body tint. Defaults to `var(--badge-edge)` so the badge's tone drives it. */
657
+ /** Body tint. Defaults to `var(--badge-edge)` so the badge's color drives it. */
652
658
  accent?: string;
653
659
  /** Stop opacities along the body gradient (0..1). */
654
660
  topAlpha?: number;
@@ -734,8 +740,9 @@ interface EffectSpec<E extends BadgeEffect = BadgeEffect> {
734
740
  params?: BadgeEffectParams[E];
735
741
  }
736
742
 
737
- interface BadgeBaseProps {
738
- tone?: BadgeTone;
743
+ interface BadgeBaseProps extends StanceProps {
744
+ /** The status the badge reports. A peer `tone`, or a stance's accent, paints over it. */
745
+ status?: BadgeStatus;
739
746
  variant?: BadgeVariant;
740
747
  size?: BadgeSize;
741
748
  /** "Edge bloat": offset every base perimeter sample outward by N CSS px along the normal
@@ -765,12 +772,22 @@ interface BadgeBaseProps {
765
772
  children: ReactNode;
766
773
  className?: string;
767
774
  /** Optional style overrides merged with the badge's own style. Useful for setting CSS
768
- * custom properties (e.g. `--badge-edge` to inject a custom tone color). */
775
+ * custom properties (e.g. `--badge-edge` to inject a `custom` status color). */
769
776
  style?: CSSProperties;
770
777
  'aria-label'?: string;
778
+ /**
779
+ * Tooltip content. Wraps the badge in a kit tooltip trigger. A tooltip
780
+ * trigger must be focusable and carry a role that announces its
781
+ * description, so a badge that is neither a button nor a link joins the tab
782
+ * order as `role="img"`, named by `aria-label` or else by string content.
783
+ */
784
+ tooltip?: ReactNode;
771
785
  }
786
+ /** DOM attributes a badge passes through to its root element, e.g. the ones
787
+ * `Focusable` supplies when a badge sits under a `TooltipTrigger`. */
788
+ type BadgeDomProps = Omit<HTMLAttributes<HTMLElement>, keyof BadgeBaseProps | 'onClick' | 'children' | 'className' | 'style'>;
772
789
  type BadgePropsByShape = {
773
- [S in BadgeShape]: BadgeBaseProps & {
790
+ [S in BadgeShape]: BadgeBaseProps & BadgeDomProps & {
774
791
  shape?: S;
775
792
  shapeParams?: BadgeShapeParams[S];
776
793
  };
@@ -789,8 +806,10 @@ type BadgeProps = BadgePropsByShape;
789
806
  * over it, which stack additively. `bloat` pushes the whole silhouette outward
790
807
  * along its normals before effects run, and `crawl` animates perimeter
791
808
  * patterns.
809
+ *
810
+ * `ref` and any other DOM attributes forward to the root element.
792
811
  */
793
- declare function Badge(props: BadgeProps): react_jsx_runtime.JSX.Element;
812
+ declare const Badge: react.ForwardRefExoticComponent<BadgePropsByShape & react.RefAttributes<HTMLElement>>;
794
813
 
795
814
  /**
796
815
  * One column of a {@link DataGrid}. `id` doubles as the default property name
@@ -825,6 +844,28 @@ interface DataGridProps<Row extends {
825
844
  /** Empty-state row text. Default `'—'`. */
826
845
  empty?: ReactNode;
827
846
  className?: string;
847
+ /** Extra class on a row's `<tr>`, for row-level state such as a verdict. */
848
+ rowClassName?: (row: Row) => string | undefined;
849
+ /**
850
+ * Activate a row. Makes each row focusable: a click anywhere in it, or
851
+ * Enter/Space while it has focus, calls this. Clicks and keys landing on a
852
+ * control inside a cell (button, link, input, …) are left to that control.
853
+ */
854
+ onRowClick?: (row: Row) => void;
855
+ /**
856
+ * Content for a full-width detail row under `row`, shown while the row is
857
+ * expanded. Setting it adds a leading disclosure column. Return `null` for
858
+ * no detail row.
859
+ */
860
+ renderDetail?: (row: Row) => ReactNode;
861
+ /** Which rows offer the disclosure. Default: every row. */
862
+ rowExpandable?: (row: Row) => boolean;
863
+ /** Expanded row ids, controlled. Pair with `onExpandedChange`. */
864
+ expandedIds?: ReadonlySet<string>;
865
+ /** Initially expanded row ids when uncontrolled. */
866
+ defaultExpandedIds?: Iterable<string>;
867
+ /** Called with the next expanded set when a disclosure toggles. */
868
+ onExpandedChange?: (ids: ReadonlySet<string>) => void;
828
869
  }
829
870
  /**
830
871
  * Sortable table for inspector-style data. Rows are keyed by `id`. Clicking a
@@ -837,8 +878,25 @@ declare function DataGrid<Row extends {
837
878
  id: string;
838
879
  }>(props: DataGridProps<Row>): react_jsx_runtime.JSX.Element;
839
880
 
840
- /** Which way the mark points when the section is closed. */
841
- type DisclosureDirection = 'right' | 'down';
881
+ /** Props for `<DisclosureMark>`. */
882
+ interface DisclosureMarkProps {
883
+ /** Whether the section it stands for is open: `−` when open, `+` when shut. */
884
+ open: boolean;
885
+ /** Mark size in px, square. Default 13. */
886
+ size?: number;
887
+ className?: string;
888
+ }
889
+ /**
890
+ * The fold mark alone: a dark violet rounded square holding a `+` while its section is
891
+ * shut and a `−` while it is open. Decorative — it carries no role or label —
892
+ * for a row that is itself the control, such as a tree item or a header
893
+ * button. Anywhere the mark has to be the control, use `<Disclosure>`.
894
+ *
895
+ * Deliberately not part of the icon register, on the same grounds as
896
+ * `DragHandleGlyph`: that register is outline strokes at a fixed weight, and
897
+ * this mark is filled.
898
+ */
899
+ declare function DisclosureMark({ open, size, className }: DisclosureMarkProps): react_jsx_runtime.JSX.Element;
842
900
  /** Props for `<Disclosure>`. */
843
901
  interface DisclosureProps {
844
902
  /** Whether the section it controls is open. The consumer owns this. */
@@ -854,17 +912,14 @@ interface DisclosureProps {
854
912
  * screen reader move to the revealed content.
855
913
  */
856
914
  controls?: string;
857
- /** Which way the closed mark points. `'right'` (default) rotates down when
858
- * open; `'down'` rotates up. */
859
- direction?: DisclosureDirection;
860
915
  /** Mark size in px. The hit target is at least 20px and grows with it.
861
- * Default 12. */
916
+ * Default 13. */
862
917
  size?: number;
863
918
  disabled?: boolean;
864
919
  className?: string;
865
920
  }
866
921
  /**
867
- * The twisty on a collapsible section: a triangle that turns as it opens.
922
+ * The twisty on a collapsible section: a `<DisclosureMark>` in a button.
868
923
  *
869
924
  * Presentational — it holds no open/closed state and renders no children.
870
925
  * The consumer owns the state and the panel; this is the control that toggles
@@ -873,17 +928,11 @@ interface DisclosureProps {
873
928
  * Three things it settles that a hand-rolled twisty keeps getting wrong. The
874
929
  * mark is drawn rather than typed, because `--wzl-font-ui` carries no ▸/▾ and
875
930
  * a text glyph falls back to whatever the system offers at whatever size that
876
- * font renders it — around 6px against 13px body text, which reads as dirt on
877
- * the screen. The hit target is larger than the mark. And it is a sibling of
878
- * the row's label rather than a child, so clicking to expand does not actuate
879
- * the label's own control.
880
- *
881
- * Deliberately not part of the icon register, on the same grounds as
882
- * `DragHandleGlyph`: that register is outline strokes at a fixed weight, and
883
- * `base.mjs` rejects a solid triangle in it by name. A disclosure mark is
884
- * filled.
931
+ * font renders it. The hit target is larger than the mark. And it is a sibling
932
+ * of the row's label rather than a child, so clicking to expand does not
933
+ * actuate the label's own control.
885
934
  */
886
- declare function Disclosure({ open, onToggle, label, controls, direction, size, disabled, className, }: DisclosureProps): react_jsx_runtime.JSX.Element;
935
+ declare function Disclosure({ open, onToggle, label, controls, size, disabled, className }: DisclosureProps): react_jsx_runtime.JSX.Element;
887
936
  /** Props for `<DisclosureRow>`. */
888
937
  interface DisclosureRowProps extends Omit<DisclosureProps, 'className'> {
889
938
  /** The row's own content — a label, a checkbox, a count. */
@@ -900,6 +949,26 @@ interface DisclosureRowProps extends Omit<DisclosureProps, 'className'> {
900
949
  */
901
950
  declare function DisclosureRow({ children, className, ...twisty }: DisclosureRowProps): react_jsx_runtime.JSX.Element;
902
951
 
952
+ /** Props for `<DragGhost>`. */
953
+ interface DragGhostProps {
954
+ /** The ghost's top-left in client space, and its width — `useReorderDragList`'s `state.ghost` is one. */
955
+ at: {
956
+ left: number;
957
+ top: number;
958
+ width: number;
959
+ };
960
+ /** An element inside the list being dragged from. The ghost portals to its nearest themed ancestor, so it resolves
961
+ * the list's tokens without being clipped by the list's panel. */
962
+ from: Element;
963
+ /** What to draw: copies of the dragged items, or any stand-in for them. */
964
+ children: ReactNode;
965
+ }
966
+ /**
967
+ * What follows the pointer during a drag while the dragged items hold their place: `children` on a raised surface at
968
+ * a client-space point. Hidden from assistive tech and from the pointer, so it never becomes the drop target.
969
+ */
970
+ declare function DragGhost({ at, from, children }: DragGhostProps): react.ReactPortal;
971
+
903
972
  /** Props for `<DragHandleGlyph>`. */
904
973
  interface DragHandleGlyphProps {
905
974
  /** Height in px; width scales with it. Default 16. */
@@ -1074,6 +1143,36 @@ declare function keySpecFromKey(raw: string, opts?: KeySpecsFromModsOptions & {
1074
1143
  optional?: boolean;
1075
1144
  }): KeySpec;
1076
1145
 
1146
+ interface ShortcutInput {
1147
+ key: string | readonly string[];
1148
+ mod?: boolean;
1149
+ alt?: boolean;
1150
+ shift?: boolean | 'optional';
1151
+ }
1152
+ /** Format a shortcut as an array of display chips, one per key — modifier
1153
+ * icons (⌘, ↑, ⌥) followed by the key glyph. UIs that want a boxed
1154
+ * per-key look render each chip in its own element. `shift: 'optional'` is
1155
+ * treated as falsy. */
1156
+ declare function formatShortcutParts(b: ShortcutInput | undefined): readonly string[] | undefined;
1157
+ /** Format a shortcut as a single display string. Order: mod, shift, alt,
1158
+ * key. Returns `undefined` for `undefined` input so callers can `??` a
1159
+ * fallback. When `key` is an array, the first element is used. `shift: 'optional'`
1160
+ * is treated as falsy. */
1161
+ declare function formatShortcut(b: ShortcutInput | undefined): string | undefined;
1162
+
1163
+ /**
1164
+ * A shortcut as `KeySequence` keys, one per key: mod, shift, alt, then the
1165
+ * key, each in the platform's own legend (`⌘` on macOS, `Ctrl` elsewhere).
1166
+ * The `KeySpec` counterpart of `formatShortcutParts`, which always prints
1167
+ * macOS glyphs. `shift: 'optional'` becomes an optional key; a key list
1168
+ * renders its first key. Returns `undefined` for no shortcut.
1169
+ *
1170
+ * ```tsx
1171
+ * <KeySequence keys={keySpecsFromShortcut({ key: 'z', mod: true, shift: true })} />
1172
+ * ```
1173
+ */
1174
+ declare function keySpecsFromShortcut(shortcut: ShortcutInput | undefined, opts?: KeySpecsFromModsOptions): readonly KeySpec[] | undefined;
1175
+
1077
1176
  /**
1078
1177
  * Passed to a custom thumb renderer: the thumb box in CSS px, and whether
1079
1178
  * this thumb is the one being dragged.
@@ -1198,6 +1297,146 @@ type SliderProps<T extends Thumb = Thumb> = {
1198
1297
  */
1199
1298
  declare function Slider<T extends Thumb = Thumb>(props: SliderProps<T>): ReactElement;
1200
1299
 
1300
+ /** One row in a reorderable list. */
1301
+ interface ReorderItem {
1302
+ id: string;
1303
+ label: ReactNode;
1304
+ /** Locked rows cannot be dragged, cannot be crossed by drops, and
1305
+ * never combine with other rows in a multi-selection. */
1306
+ locked?: boolean;
1307
+ }
1308
+ /**
1309
+ * Options for {@link useReorderDragList}. `onReorder` receives the dragged ids
1310
+ * and the index they were dropped at, measured against the pre-drag `items`.
1311
+ */
1312
+ interface UseReorderDragListOptions {
1313
+ items: ReorderItem[];
1314
+ selectedIds: string[];
1315
+ onReorder(ids: string[], targetIndex: number): void;
1316
+ /** A press that was released without ever engaging a drag — the click a
1317
+ * list row means by it. Fires for locked rows too, which can be selected
1318
+ * but not dragged. Modifiers are read at press, not at release. When this
1319
+ * is given, the DOM click that follows the press is dropped, so a row that
1320
+ * also handles `click` sees one press, not two. A press that starts on a
1321
+ * control inside the row (a toggle) is left to the control. */
1322
+ onPress?(id: string, mods: PressModifiers): void;
1323
+ /** Pointer-move distance (px) before pending drag engages. Default 4. */
1324
+ threshold?: number;
1325
+ /** Selector matching the container's children that are rows, for a list
1326
+ * that interleaves other elements (a table's detail rows). Default: every
1327
+ * child is a row. */
1328
+ rowSelector?: string;
1329
+ }
1330
+ /** Modifier keys held when a press began. */
1331
+ interface PressModifiers {
1332
+ shiftKey: boolean;
1333
+ ctrlKey: boolean;
1334
+ metaKey: boolean;
1335
+ altKey: boolean;
1336
+ }
1337
+ /**
1338
+ * Where a drag's ghost goes: the dragged rows, drawn again with their top-left
1339
+ * at a client-space point, so the row that was grabbed stays under the pointer
1340
+ * where it was picked up. `width` is the grabbed row's.
1341
+ */
1342
+ interface ReorderGhost {
1343
+ ids: readonly string[];
1344
+ left: number;
1345
+ top: number;
1346
+ width: number;
1347
+ }
1348
+ /**
1349
+ * Live drag state for rendering feedback: which ids are being dragged, the
1350
+ * insertion index the drop would use, and where their ghost goes. All `null`
1351
+ * when no drag is engaged.
1352
+ */
1353
+ interface ReorderDragState {
1354
+ draggedIds: string[] | null;
1355
+ targetIndex: number | null;
1356
+ ghost: ReorderGhost | null;
1357
+ }
1358
+ /**
1359
+ * A `ref` for the list container, an `onPointerDown` for each row, and the
1360
+ * live {@link ReorderDragState}. The container ref is required, not optional
1361
+ * decoration: it is what the drop index is measured against and what the
1362
+ * pointer session is opened on.
1363
+ */
1364
+ interface ReorderDragHandlers {
1365
+ rowProps(id: string, index: number): {
1366
+ onPointerDown(e: PointerEvent): void;
1367
+ };
1368
+ containerProps: {
1369
+ ref: RefCallback<HTMLElement>;
1370
+ };
1371
+ state: ReorderDragState;
1372
+ /**
1373
+ * Move the row at `index` one place up (`-1`) or down (`1`) — the keyboard
1374
+ * reorder. It moves what a drag of that row would: the whole selection if
1375
+ * the row is in it, else the row alone, never across a locked row. Calls
1376
+ * `onReorder` and returns `true`, or returns `false` when nothing can move.
1377
+ */
1378
+ nudge(id: string, index: number, delta: -1 | 1): boolean;
1379
+ }
1380
+ /**
1381
+ * Drag-to-reorder for a vertical list of rows. Dragging a row that is part of
1382
+ * the current selection drags the whole selection; dragging any other row
1383
+ * drags just that row. Locked rows can neither be dragged nor crossed by a
1384
+ * drop. A drop that would leave a contiguous block where it already is does
1385
+ * not call `onReorder`.
1386
+ *
1387
+ * The rows are the container's children, whatever they are: `ItemList` rows,
1388
+ * or the `PropertyGroup`s of a `PropertyList`. A row's `onPointerDown` can go
1389
+ * on the whole row or on a handle inside it.
1390
+ *
1391
+ * A press opens a `startThresholdDrag` on the *container*, which owns the
1392
+ * rest of the gesture: a drag that leaves the list still tracks, a release
1393
+ * anywhere still drops, and a release the window never delivered still ends
1394
+ * the drag. The container is the origin rather than the row because rows come
1395
+ * and go as the list re-renders, and a drag must outlive the row it grabbed.
1396
+ */
1397
+ declare function useReorderDragList(opts: UseReorderDragListOptions): ReorderDragHandlers;
1398
+
1399
+ /** Props for {@link ListEditor}. */
1400
+ interface ListEditorProps {
1401
+ value: readonly string[];
1402
+ /** Every edit, add and removal, with the whole list. Entries are written as
1403
+ * typed — an empty one stays until it is removed. */
1404
+ onChange: (next: string[]) => void;
1405
+ /** Shown in an empty entry. */
1406
+ placeholder?: string;
1407
+ /** Shown in place of the entries when there are none. */
1408
+ empty?: string;
1409
+ /** Text of the add button. */
1410
+ addLabel?: string;
1411
+ /** Names the list for assistive tech; each entry is named from it. */
1412
+ 'aria-label'?: string;
1413
+ className?: string;
1414
+ }
1415
+ /**
1416
+ * An editable list of strings: one field per entry, a remove button beside
1417
+ * each, and an add button under them. Enter in an entry adds one after it;
1418
+ * Backspace in an empty one removes it.
1419
+ */
1420
+ declare function ListEditor({ value, onChange, placeholder, empty, addLabel, 'aria-label': ariaLabel, className, }: ListEditorProps): react_jsx_runtime.JSX.Element;
1421
+
1422
+ /** Props for {@link ColorModeControl}. */
1423
+ interface ColorModeControlProps {
1424
+ value: ColorModePreference;
1425
+ onChange: (next: ColorModePreference) => void;
1426
+ /** Accessible name of the group. Defaults to `'Color mode'`. */
1427
+ ariaLabel?: string;
1428
+ size?: ToggleBarSize;
1429
+ variant?: ToggleBarVariant;
1430
+ className?: string;
1431
+ }
1432
+ /**
1433
+ * The Auto / Light / Dark choice, as a three-way radiogroup of mode glyphs.
1434
+ * Controlled: pair it with `useColorModePreference` from
1435
+ * `@weasel-js/theme/react` and put the hook's resolved `mode` in the
1436
+ * `ThemeProvider` selection.
1437
+ */
1438
+ declare function ColorModeControl({ value, onChange, ariaLabel, size, variant, className, }: ColorModeControlProps): ReactElement;
1439
+
1201
1440
  /**
1202
1441
  * One segment of an {@link OptionsBar}. Unlike `ToggleBar`, each item carries
1203
1442
  * its own selected state and its own `onChange`.
@@ -1235,28 +1474,28 @@ type OptionsBarProps<V extends string | number = string> = {
1235
1474
  declare function OptionsBar<V extends string | number = string>(props: OptionsBarProps<V>): ReactElement;
1236
1475
 
1237
1476
  /**
1238
- * One button in an {@link ActionsBar}. `value` is only a React key; the item
1477
+ * One button in an {@link ButtonBar}. `value` is only a React key; the item
1239
1478
  * carries no selected state.
1240
1479
  */
1241
- type ActionsBarItem<V extends string | number = string> = {
1480
+ type ButtonBarItem<V extends string | number = string> = {
1242
1481
  value: V;
1243
1482
  label?: ReactNode;
1244
1483
  ariaLabel?: string;
1245
1484
  disabled?: boolean;
1246
1485
  onAction: () => void;
1247
- };
1248
- /** Segment height and type scale for an {@link ActionsBar}. */
1249
- type ActionsBarSize = 'sm' | 'md';
1250
- /** Visual treatment of an {@link ActionsBar}. */
1251
- type ActionsBarVariant = 'default' | 'minimal';
1252
- /** Props for {@link ActionsBar}. */
1253
- type ActionsBarProps<V extends string | number = string> = {
1254
- items: readonly ActionsBarItem<V>[];
1486
+ } & SegmentTooltipFields;
1487
+ /** Segment height and type scale for an {@link ButtonBar}. */
1488
+ type ButtonBarSize = 'sm' | 'md';
1489
+ /** Visual treatment of an {@link ButtonBar}. */
1490
+ type ButtonBarVariant = 'default' | 'minimal';
1491
+ /** Props for {@link ButtonBar}. */
1492
+ type ButtonBarProps<V extends string | number = string> = {
1493
+ items: readonly ButtonBarItem<V>[];
1255
1494
  ariaLabel?: string;
1256
1495
  className?: string;
1257
1496
  height?: number;
1258
- size?: ActionsBarSize;
1259
- variant?: ActionsBarVariant;
1497
+ size?: ButtonBarSize;
1498
+ variant?: ButtonBarVariant;
1260
1499
  };
1261
1500
  /**
1262
1501
  * Segmented strip of momentary buttons — each press fires and nothing stays
@@ -1266,17 +1505,17 @@ type ActionsBarProps<V extends string | number = string> = {
1266
1505
  * This is a plain callback bar. For buttons driven by the kit's actions
1267
1506
  * registry, use `ActionBar` instead.
1268
1507
  */
1269
- declare function ActionsBar<V extends string | number = string>(props: ActionsBarProps<V>): ReactElement;
1508
+ declare function ButtonBar<V extends string | number = string>(props: ButtonBarProps<V>): ReactElement;
1270
1509
 
1271
1510
  /**
1272
1511
  * One segment of a {@link Powerline}. Giving it `onClick` or `href` makes it
1273
1512
  * interactive, the same way it does on a `Badge`.
1274
1513
  */
1275
- interface PowerlineSegment {
1514
+ interface PowerlineSegment extends StanceProps {
1276
1515
  text: ReactNode;
1277
1516
  /** Cap on this segment's right edge. Next segment's left edge adopts the same profile. */
1278
1517
  endCap?: EdgeCap;
1279
- tone?: BadgeTone;
1518
+ status?: BadgeStatus;
1280
1519
  variant?: BadgeVariant;
1281
1520
  size?: BadgeSize;
1282
1521
  onClick?: () => void;
@@ -1321,6 +1560,87 @@ declare function prefValueAtPath(values: unknown, path: string): unknown;
1321
1560
  */
1322
1561
  declare function visiblePrefSubtree<T extends ToolPrefLeaf | ToolPrefGroup>(node: T, showHidden: boolean): T | null;
1323
1562
 
1563
+ /** How a {@link PrefsForm} lays its groups out. */
1564
+ type PrefsLayout = 'columns' | 'rail';
1565
+ /** Props for {@link PrefsForm}. */
1566
+ interface PrefsFormProps {
1567
+ /** Root of the schema tree. Core `ToolPrefGroup`s assign structurally. */
1568
+ schema: ToolPrefGroup;
1569
+ /** Nested value tree (shape mirrors the schema). Sparse is fine —
1570
+ * missing leaves fall back to their schema `default`. */
1571
+ values?: unknown;
1572
+ /** Change callback with the leaf's dotted path. Values apply live;
1573
+ * there is no dirty/commit state. */
1574
+ onChange: (path: string, value: unknown) => void;
1575
+ /**
1576
+ * Per-kind renderers for app-defined kinds. Entries also override the
1577
+ * built-in kinds when keys collide. A renderer owns the control cell
1578
+ * (the label/tooltip row chrome stays with the form, unless the leaf
1579
+ * sets `block`); returning `null` collapses the row entirely. Unknown
1580
+ * kinds with no renderer show a labeled placeholder instead of
1581
+ * crashing.
1582
+ */
1583
+ renderers?: Record<string, PrefRenderer>;
1584
+ /** Reveal `hidden` leaves (dev tooling). Default false. */
1585
+ showHidden?: boolean;
1586
+ /**
1587
+ * `'columns'` (the default) wraps each top-level group into its own panel
1588
+ * column. `'rail'` puts a two-level navigation rail beside one group's
1589
+ * settings at a time — what a dialog-sized surface wants, since columns
1590
+ * overflow sideways once there are more than two.
1591
+ */
1592
+ layout?: PrefsLayout;
1593
+ /** Show a filter field that narrows the form to matching leaves. */
1594
+ filterable?: boolean;
1595
+ /** Rail layout: path of the open top-level group. Controlled. */
1596
+ section?: string;
1597
+ /** Rail layout: path of the group open before the reader picks one.
1598
+ * Defaults to the first in the schema. */
1599
+ defaultSection?: string;
1600
+ onSectionChange?: (path: string) => void;
1601
+ className?: string;
1602
+ }
1603
+ /**
1604
+ * Schema-driven preferences form. Leaves render as label + control rows;
1605
+ * how the groups around them are arranged is `layout`'s to say — columns of
1606
+ * panels, or a navigation rail beside one group at a time.
1607
+ *
1608
+ * Storage-agnostic: pair with `PrefsDialog` for the modal composition, and
1609
+ * persist however the app likes via `onChange`.
1610
+ */
1611
+ declare function PrefsForm(props: PrefsFormProps): react_jsx_runtime.JSX.Element;
1612
+
1613
+ /**
1614
+ * Props for {@link PrefsDialog} — everything {@link PrefsForm} takes, plus
1615
+ * the dialog's own open state and chrome.
1616
+ */
1617
+ interface PrefsDialogProps extends PrefsFormProps {
1618
+ isOpen: boolean;
1619
+ onOpenChange: (open: boolean) => void;
1620
+ /** Dialog heading. Defaults to the schema root's `name`. */
1621
+ title?: ReactNode;
1622
+ /** Extra chrome rendered at the end of the title row (e.g. a dev-mode
1623
+ * "Show hidden" switch). An action the reader acts on when they are done
1624
+ * — resetting, importing — belongs in `footer` instead, where a dialog's
1625
+ * actions live. */
1626
+ headerExtra?: ReactNode;
1627
+ /** Footer slot, passed through to `Dialog` — typically a reset or done
1628
+ * action. */
1629
+ footer?: ReactNode;
1630
+ /** Class applied to the dialog's modal box. */
1631
+ dialogClassName?: string;
1632
+ }
1633
+ /**
1634
+ * The kit's preferences dialog: `Dialog` + `PrefsForm`. Changes apply
1635
+ * live through `onChange` — there is no OK/Cancel staging. For custom
1636
+ * placement (sidebar, popover, inline page), compose `PrefsForm`
1637
+ * directly; this wrapper is intentionally thin.
1638
+ *
1639
+ * `layout="rail"` is what a dialog usually wants: the default columns wrap
1640
+ * sideways past two groups, and this box is 900px at its widest.
1641
+ */
1642
+ declare function PrefsDialog(props: PrefsDialogProps): react_jsx_runtime.JSX.Element;
1643
+
1324
1644
  /** Props for {@link Sidebar}. */
1325
1645
  interface SidebarProps {
1326
1646
  /**
@@ -1364,7 +1684,7 @@ interface SidebarPanelProps {
1364
1684
  collapsed?: boolean;
1365
1685
  /**
1366
1686
  * Click handler for the title row. When provided, the header renders
1367
- * as a button (chevron + label) and acts as the collapse toggle.
1687
+ * as a button (fold mark + label) and acts as the collapse toggle.
1368
1688
  * When omitted, the title is static text and the panel can't collapse.
1369
1689
  */
1370
1690
  onToggleCollapse?(): void;
@@ -1381,7 +1701,7 @@ interface SidebarPanelProps {
1381
1701
  * Generic collapsible panel section for sidebars. Pure presentation —
1382
1702
  * caller manages `collapsed`/`hidden` state externally (the pattern is
1383
1703
  * to drive it from app prefs so the Preferences modal and inline
1384
- * chevrons toggle the same map).
1704
+ * fold marks toggle the same map).
1385
1705
  *
1386
1706
  * Pair with `<Sidebar>` for the docked column layout.
1387
1707
  */
@@ -1484,6 +1804,11 @@ interface WorkspaceVisual {
1484
1804
  */
1485
1805
  interface ModeDefinition {
1486
1806
  id: string;
1807
+ /** Human-readable name for chrome — a breadcrumb, a status bar. Falls back
1808
+ * to `id`; read it through {@link modeLabel}. */
1809
+ label?: string;
1810
+ /** One sentence on what the mode is for, for a tooltip or a hint line. */
1811
+ description?: string;
1487
1812
  kind: 'soft' | 'strict';
1488
1813
  /** Capability tags this mode allows beyond IMPLICIT_TAGS. */
1489
1814
  allows: CapabilityTag[];
@@ -1517,23 +1842,6 @@ interface ModeRegistry {
1517
1842
  subscribe(listener: () => void): () => void;
1518
1843
  }
1519
1844
 
1520
- interface ShortcutInput {
1521
- key: string | readonly string[];
1522
- mod?: boolean;
1523
- alt?: boolean;
1524
- shift?: boolean | 'optional';
1525
- }
1526
- /** Format a shortcut as an array of display chips, one per key — modifier
1527
- * icons (⌘, ↑, ⌥) followed by the key glyph. UIs that want a boxed
1528
- * per-key look render each chip in its own element. `shift: 'optional'` is
1529
- * treated as falsy. */
1530
- declare function formatShortcutParts(b: ShortcutInput | undefined): readonly string[] | undefined;
1531
- /** Format a shortcut as a single display string. Order: mod, shift, alt,
1532
- * key. Returns `undefined` for `undefined` input so callers can `??` a
1533
- * fallback. When `key` is an array, the first element is used. `shift: 'optional'`
1534
- * is treated as falsy. */
1535
- declare function formatShortcut(b: ShortcutInput | undefined): string | undefined;
1536
-
1537
1845
  /** Props for {@link ToolPalette}. */
1538
1846
  interface ToolPaletteProps {
1539
1847
  tools: ToolsApi;
@@ -1544,10 +1852,11 @@ interface ToolPaletteProps {
1544
1852
  * omitted, falls back to `tool.keybinding` (legacy path). */
1545
1853
  lookupShortcut?: (toolId: string) => ShortcutInput | undefined;
1546
1854
  /**
1547
- * Optional mode registry. When provided, tools whose `capabilities` do not
1548
- * match the current mode are rendered greyed-out, aria-disabled, and their
1549
- * onClick is suppressed. When omitted, all tools are treated as eligible
1550
- * (preserves existing behaviour in consumers that haven't wired a registry).
1855
+ * Optional mode registry. When provided, tools whose
1856
+ * `eligibility.capabilities` do not match the current mode are rendered
1857
+ * greyed-out, aria-disabled, and their onClick is suppressed. When omitted,
1858
+ * all tools are treated as eligible (preserves existing behavior in
1859
+ * consumers that haven't wired a registry).
1551
1860
  */
1552
1861
  modeRegistry?: ModeRegistry;
1553
1862
  /**
@@ -1567,39 +1876,6 @@ interface ToolPaletteProps {
1567
1876
  */
1568
1877
  declare function ToolPalette(props: ToolPaletteProps): react_jsx_runtime.JSX.Element;
1569
1878
 
1570
- /**
1571
- * Whether a {@link Field} stacks its label above the control or sits them
1572
- * side by side.
1573
- */
1574
- type FieldOrientation = 'stacked' | 'row';
1575
- /** Props for {@link Field}. */
1576
- type FieldProps = {
1577
- orientation?: FieldOrientation;
1578
- className?: string;
1579
- children?: ReactNode;
1580
- };
1581
- /**
1582
- * Layout primitive that arranges a label, control, hint, and error in the
1583
- * canonical weasel-ui form-row shape. The control itself owns its semantics
1584
- * (RAC `TextField`, `Checkbox`, etc.); this just paints the layout.
1585
- *
1586
- * Most users will instead reach for `Input` / `Checkbox` / `Switch`, which
1587
- * compose Field internally. Use Field directly when you need a custom
1588
- * control to sit in the same visual rhythm.
1589
- */
1590
- declare function Field({ orientation, className, children }: FieldProps): react_jsx_runtime.JSX.Element;
1591
- /**
1592
- * The class names {@link Field} paints its slots with, so a control composing
1593
- * its own layout can match the same form-row rhythm.
1594
- */
1595
- declare const fieldClasses: {
1596
- root: string;
1597
- row: string;
1598
- label: string;
1599
- hint: string;
1600
- error: string;
1601
- };
1602
-
1603
1879
  /**
1604
1880
  * Props for {@link Checkbox}, on top of React Aria's `Checkbox` props. The
1605
1881
  * label is passed as children.
@@ -1693,6 +1969,12 @@ declare function Radio({ children, className, ...rest }: RadioProps): react_jsx_
1693
1969
  /** Props for {@link NumberField}, on top of React Aria's `NumberField` props. */
1694
1970
  type NumberFieldProps = Omit<NumberFieldProps$1, 'children' | 'className'> & {
1695
1971
  label?: ReactNode;
1972
+ /**
1973
+ * `'stacked'` (the default) puts the label above the field; `'row'` sets it
1974
+ * beside the field at its own width, with any description or error on a
1975
+ * line below. Same vocabulary as {@link Field}'s `orientation`.
1976
+ */
1977
+ orientation?: FieldOrientation;
1696
1978
  description?: ReactNode;
1697
1979
  errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
1698
1980
  /** Hide the up/down stepper buttons. Defaults to false. */
@@ -1721,6 +2003,12 @@ type NumberFieldProps = Omit<NumberFieldProps$1, 'children' | 'className'> & {
1721
2003
  */
1722
2004
  declare const NumberField: react.ForwardRefExoticComponent<Omit<NumberFieldProps$1, "className" | "children"> & {
1723
2005
  label?: ReactNode;
2006
+ /**
2007
+ * `'stacked'` (the default) puts the label above the field; `'row'` sets it
2008
+ * beside the field at its own width, with any description or error on a
2009
+ * line below. Same vocabulary as {@link Field}'s `orientation`.
2010
+ */
2011
+ orientation?: FieldOrientation;
1724
2012
  description?: ReactNode;
1725
2013
  errorMessage?: ReactNode | ((v: ValidationResult) => ReactNode);
1726
2014
  /** Hide the up/down stepper buttons. Defaults to false. */
@@ -1759,13 +2047,16 @@ type MenuButtonProps<T extends string = string> = {
1759
2047
  isDisabled?: boolean;
1760
2048
  className?: string;
1761
2049
  'aria-label'?: string;
1762
- } & OverlayPortalProps;
2050
+ } & SegmentTooltipFields & OverlayPortalProps;
1763
2051
  /**
1764
2052
  * A button that opens a list and acts on the row chosen — "Add trial…",
1765
2053
  * "Load…". Unlike a {@link Select} it holds no value, so it sizes to its own
1766
2054
  * label rather than to its widest row.
2055
+ *
2056
+ * `shortcut` adds a kit tooltip reading `Name (⌘N)`, named by `aria-label` or
2057
+ * a string `label`, as `Button` does; `tooltip` replaces that text.
1767
2058
  */
1768
- declare function MenuButton<T extends string = string>({ label, items, onAction, isDisabled, className, 'aria-label': ariaLabel, portalContainer, }: MenuButtonProps<T>): react_jsx_runtime.JSX.Element;
2059
+ declare function MenuButton<T extends string = string>({ label, items, onAction, isDisabled, className, 'aria-label': ariaLabel, portalContainer, shortcut, tooltip, }: MenuButtonProps<T>): react_jsx_runtime.JSX.Element;
1769
2060
 
1770
2061
  /**
1771
2062
  * One option in a {@link ComboBox}'s `options` list. `textValue` is the
@@ -1876,7 +2167,7 @@ type RangeSliderProps = Omit<SliderProps$1, 'children' | 'className'> & {
1876
2167
  declare function RangeSlider(props: RangeSliderProps): react_jsx_runtime.JSX.Element;
1877
2168
 
1878
2169
  /** Props for {@link Dialog}, on top of React Aria's `ModalOverlay` props. */
1879
- type DialogProps = Omit<WithoutPortalTarget<ModalOverlayProps>, 'children' | 'className'> & OverlayPortalProps & {
2170
+ type DialogProps = Omit<WithoutPortalTarget<ModalOverlayProps>, 'children' | 'className'> & OverlayPortalProps & StanceProps & {
1880
2171
  /** Heading rendered in the dialog's default header. Omit when supplying
1881
2172
  * a custom `header` slot via children. */
1882
2173
  title?: ReactNode;
@@ -1891,6 +2182,10 @@ type DialogProps = Omit<WithoutPortalTarget<ModalOverlayProps>, 'children' | 'cl
1891
2182
  role?: DialogProps$1['role'];
1892
2183
  /** Class applied to the modal box (inside the overlay). */
1893
2184
  className?: string;
2185
+ /** Class applied to the scrolling body. For content that owns its own
2186
+ * scrolling — a form with a fixed navigation rail beside a scrolling
2187
+ * pane — this is where the body's padding and overflow come off. */
2188
+ bodyClassName?: string;
1894
2189
  };
1895
2190
  /**
1896
2191
  * Modal dialog wrapping React Aria. Supplies a default header (title +
@@ -1899,23 +2194,19 @@ type DialogProps = Omit<WithoutPortalTarget<ModalOverlayProps>, 'children' | 'cl
1899
2194
  * `react-aria-components` upstream of this component.
1900
2195
  *
1901
2196
  * Escape, click-outside, focus trap, and scroll lock all come from the
1902
- * underlying primitives.
2197
+ * underlying primitives. `stance` and `tone` work as on `<PropertyPanel>` —
2198
+ * a destructive confirm is `stance="danger"`.
1903
2199
  */
1904
2200
  declare function Dialog(props: DialogProps): react_jsx_runtime.JSX.Element;
1905
2201
 
1906
- /** Accent color of a {@link Callout}'s border and arrow. */
1907
- type CalloutTone = 'info' | 'warning' | 'danger';
1908
-
1909
2202
  /** Props for {@link Callout}, on top of React Aria's `Popover` props. */
1910
- type CalloutProps = Omit<WithoutPortalTarget<PopoverProps>, 'children' | 'className' | 'isNonModal' | 'triggerRef'> & OverlayPortalProps & {
2203
+ type CalloutProps = Omit<WithoutPortalTarget<PopoverProps>, 'children' | 'className' | 'isNonModal' | 'triggerRef'> & OverlayPortalProps & StanceProps & {
1911
2204
  children?: ReactNode;
1912
2205
  className?: string;
1913
2206
  /** Optional heading rendered above the body. */
1914
2207
  title?: ReactNode;
1915
2208
  /** Footer slot — typically action buttons. */
1916
2209
  footer?: ReactNode;
1917
- /** Accent tone for border + arrow. Default `info`. */
1918
- tone?: CalloutTone;
1919
2210
  /**
1920
2211
  * `true` — blocks interaction with the rest of the app until dismissed;
1921
2212
  * inner dialog is `role="alertdialog"`. `false` (default) — non-blocking:
@@ -2308,7 +2599,7 @@ type ChromaCurvePoint = {
2308
2599
  * Converts an OKLCH color to a gamut-clipped `#rrggbb` string. Hue is in
2309
2600
  * degrees, unlike the kit's OKLab helpers which take radians.
2310
2601
  */
2311
- declare function oklchToHex(L: number, C: number, Hdeg: number): string;
2602
+ declare const oklchToHex: typeof oklchDegToHex;
2312
2603
  /** Evaluates a {@link ChromaCurve} at a lightness, clamping outside its range. */
2313
2604
  declare function chromaAt(L: number, curve: ChromaCurve): number;
2314
2605
 
@@ -2348,76 +2639,6 @@ type AsyncOptionsResult<T extends Key> = {
2348
2639
  */
2349
2640
  declare function useAsyncOptions<T extends Key = string>({ load, debounceMs, minLength, }: UseAsyncOptionsProps<T>): AsyncOptionsResult<T>;
2350
2641
 
2351
- /** One row in a reorderable list. */
2352
- interface LayerListItem {
2353
- id: string;
2354
- label: ReactNode;
2355
- /** Locked rows cannot be dragged, cannot be crossed by drops, and
2356
- * never combine with other rows in a multi-selection. */
2357
- locked?: boolean;
2358
- /** Optional color swatch rendered before the label. Any CSS color string. */
2359
- swatch?: string;
2360
- }
2361
- /**
2362
- * Options for {@link useReorderDragList}. `onReorder` receives the dragged ids
2363
- * and the index they were dropped at, measured against the pre-drag `items`.
2364
- */
2365
- interface UseReorderDragListOptions {
2366
- items: LayerListItem[];
2367
- selectedIds: string[];
2368
- onReorder(ids: string[], targetIndex: number): void;
2369
- /** A press that was released without ever engaging a drag — the click a
2370
- * list row means by it. Fires for locked rows too, which can be selected
2371
- * but not dragged. Modifiers are read at press, not at release. */
2372
- onPress?(id: string, mods: PressModifiers): void;
2373
- /** Pointer-move distance (px) before pending drag engages. Default 4. */
2374
- threshold?: number;
2375
- }
2376
- /** Modifier keys held when a press began. */
2377
- interface PressModifiers {
2378
- shiftKey: boolean;
2379
- ctrlKey: boolean;
2380
- metaKey: boolean;
2381
- altKey: boolean;
2382
- }
2383
- /**
2384
- * Live drag state for rendering feedback: which ids are being dragged and the
2385
- * insertion index the drop would use. Both `null` when no drag is engaged.
2386
- */
2387
- interface ReorderDragState {
2388
- draggedIds: string[] | null;
2389
- targetIndex: number | null;
2390
- }
2391
- /**
2392
- * A `ref` for the list container, an `onPointerDown` for each row, and the
2393
- * live {@link ReorderDragState}. The container ref is required, not optional
2394
- * decoration: it is what the drop index is measured against and what the
2395
- * pointer session is opened on.
2396
- */
2397
- interface ReorderDragHandlers {
2398
- rowProps(id: string, index: number): {
2399
- onPointerDown(e: PointerEvent): void;
2400
- };
2401
- containerProps: {
2402
- ref: RefCallback<HTMLElement>;
2403
- };
2404
- state: ReorderDragState;
2405
- }
2406
- /**
2407
- * Drag-to-reorder for a vertical list of rows. Dragging a row that is part of
2408
- * the current selection drags the whole selection; dragging any other row
2409
- * drags just that row. Locked rows can neither be dragged nor crossed by a
2410
- * drop. A drop that would leave a contiguous block where it already is does
2411
- * not call `onReorder`.
2412
- *
2413
- * A press opens a `startThresholdDrag` on the *container*, which owns the
2414
- * rest of the gesture: a drag that leaves the list still tracks, a release
2415
- * anywhere still drops, and a release the window never delivered still ends
2416
- * the drag. The container is the origin rather than the row because rows come
2417
- * and go as the list re-renders, and a drag must outlive the row it grabbed.
2418
- */
2419
- declare function useReorderDragList(opts: UseReorderDragListOptions): ReorderDragHandlers;
2420
-
2421
2642
  /** The only thing the hook needs to know about a bar's items: which are
2422
2643
  * skipped by arrow navigation. */
2423
2644
  type RovingItem = {
@@ -2459,37 +2680,22 @@ type RovingTabIndex<T extends HTMLElement = HTMLDivElement> = {
2459
2680
  * at both ends. Home and End go to the first and last enabled item. Both axes
2460
2681
  * navigate, so the same bar works laid out either way.
2461
2682
  *
2462
- * Backs `ActionsBar`, `OptionsBar`, and `ToggleBar`.
2683
+ * Backs `ButtonBar`, `OptionsBar`, and `ToggleBar`.
2463
2684
  *
2464
- * **When a bar should not use this.** Only when the bar owns its items. A
2465
- * container of arbitrary compound controls — a number field, a select, a
2685
+ * **When a bar should not use this.** What decides it is the items, not who
2686
+ * owns them. A container of compound controls — a number field, a select, a
2466
2687
  * color field — must leave the arrow keys alone, because those controls edit
2467
2688
  * their own value with them; taking the arrows over would break the control
2468
- * to navigate between controls. `ToolOptionsBar` is that case and keeps plain
2469
- * DOM tab order. A bar whose items are all simple buttons is the case this
2470
- * hook is for.
2689
+ * to navigate between controls. `ToolOptionsBar` is that case: it draws its
2690
+ * own controls from a tool's schema now rather than taking arbitrary
2691
+ * children, and a schema-drawn number field eats arrows exactly as a
2692
+ * hand-placed one did, so it keeps plain DOM tab order. A bar whose items are
2693
+ * all simple buttons is the case this hook is for.
2471
2694
  *
2472
2695
  * With every item disabled there is no tab stop and the bar drops out of the
2473
2696
  * tab order entirely.
2474
2697
  */
2475
2698
  declare function useRovingTabIndex<T extends HTMLElement = HTMLDivElement>(options: UseRovingTabIndexOptions): RovingTabIndex<T>;
2476
2699
 
2477
- /**
2478
- * Display-formatter for numbers. Use this anywhere a number is shown to
2479
- * a user. The whole point: negative values get prefixed with the real
2480
- * MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that
2481
- * `toLocaleString` and template literals produce by default.
2482
- *
2483
- * U+2212 is the same visual width as `+` and reads as a sign rather
2484
- * than a hyphen — columns of signed numbers align cleanly and the
2485
- * glyph doesn't get confused with a bullet or list dash.
2486
- */
2487
- declare const MINUS_SIGN = "\u2212";
2488
- /**
2489
- * Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII
2490
- * hyphen `toLocaleString` emits. Non-finite values stringify as-is.
2491
- */
2492
- declare function formatNumber(value: number, options?: Intl.NumberFormatOptions): string;
2493
-
2494
- export { ActionBar, ActionsBar, Badge, Callout, Checkbox, ComboBox, ComboBoxItem, CurveEditor, DataGrid, Dialog, Disclosure, DisclosureRow, DragHandleGlyph, EDGE_PROFILES, Field, KeyCap, KeySequence, MINUS_SIGN, MenuButton, NumberField, OptionsBar, Plot2D, PointPlotter, Powerline, Radio, RadioGroup, RangeSlider, Sidebar, SidebarPanel, Slider, Switch, Tab, TabList, TabPanel, Tabs, ToolButton, ToolGroup, ToolPalette, chromaAt, detectPlatform, dlog, fieldClasses, formatNumber, formatShortcut, formatShortcutParts, inferKeycapKind, isDebugEnabled, isPrefLeaf, keyGlyph, keySpecFromKey, keySpecsFromMods, oklchToHex, paintGradientTrack, prefValueAtPath, useAsyncOptions, useReorderDragList, useRovingTabIndex, visiblePrefSubtree };
2495
- export type { ActionBarProps, ActionsBarItem, ActionsBarProps, ActionsBarSize, ActionsBarVariant, AddPointMode, AnchorRenderProps, AsyncOption, AsyncOptionsResult, AxesSettings, BadgeProps, BadgeShape, BadgeSize, BadgeTone, BadgeVariant, BoundsCtx, BuiltInEdgeName, CalloutProps, CheckboxProps, ChromaCurve, ChromaCurvePoint, ComboBoxCommit, ComboBoxFilter, ComboBoxItemProps, ComboBoxOption, ComboBoxProps, ControlPoint, CurveDomain, CurveEditorProps, DataGridColumn, DataGridProps, DialogProps, DisclosureDirection, DisclosureProps, DisclosureRowProps, DragHandleGlyphProps, EdgeCap, EdgeProfile, EndpointMode, FieldOrientation, FieldProps, FillSettings, GradientTrackOpts, GridSettings, InterpolationMode, KeyCapProps, KeyCapVariant, KeySequenceProps, KeySpec, KeycapKind, LayerListItem, LogicalMod, LogicalModSpec, MenuButtonItem, MenuButtonProps, NumberFieldProps, OptionsBarItem, OptionsBarProps, OptionsBarSize, OptionsBarVariant, Platform, Plot2DCoords, Plot2DHandle, Plot2DProps, PointPlotterProps, PowerlineProps, PowerlineSegment, RadioGroupProps, RadioProps, RangeSliderProps, ReorderDragHandlers, ReorderDragState, RovingItem, RovingTabIndex, SidebarPanelProps, SidebarProps, SliderProps, SwitchProps, TabListProps, TabPanelProps, TabProps, TabsProps, Thumb, ThumbRenderCtx, ThumbShape, ToolButtonProps, ToolGroupProps, ToolPaletteProps, TrackCtx, UseAsyncOptionsProps, UseReorderDragListOptions, UseRovingTabIndexOptions };
2700
+ export { ActionBar, Badge, ButtonBar, Callout, Checkbox, ColorModeControl, ComboBox, ComboBoxItem, CurveEditor, DataGrid, Dialog, Disclosure, DisclosureMark, DisclosureRow, DragGhost, DragHandleGlyph, EDGE_PROFILES, FieldOrientation, KeyCap, KeySequence, ListEditor, MenuButton, NumberField, OptionsBar, Plot2D, PointPlotter, Powerline, PrefRenderer, PrefsDialog, PrefsForm, Radio, RadioGroup, RangeSlider, Sidebar, SidebarPanel, Slider, Switch, Tab, TabList, TabPanel, Tabs, ToggleBarSize, ToggleBarVariant, ToolButton, ToolGroup, ToolPalette, chromaAt, detectPlatform, dlog, formatShortcut, formatShortcutParts, inferKeycapKind, isDebugEnabled, isPrefLeaf, keyGlyph, keySpecFromKey, keySpecsFromMods, keySpecsFromShortcut, oklchToHex, paintGradientTrack, prefValueAtPath, useAsyncOptions, useReorderDragList, useRovingTabIndex, visiblePrefSubtree };
2701
+ export type { ActionBarProps, AddPointMode, AnchorRenderProps, AsyncOption, AsyncOptionsResult, AxesSettings, BadgeProps, BadgeShape, BadgeSize, BadgeStatus, BadgeVariant, BoundsCtx, BuiltInEdgeName, ButtonBarItem, ButtonBarProps, ButtonBarSize, ButtonBarVariant, CalloutProps, CheckboxProps, ChromaCurve, ChromaCurvePoint, ColorModeControlProps, ComboBoxCommit, ComboBoxFilter, ComboBoxItemProps, ComboBoxOption, ComboBoxProps, ControlPoint, CurveDomain, CurveEditorProps, DataGridColumn, DataGridProps, DialogProps, DisclosureMarkProps, DisclosureProps, DisclosureRowProps, DragGhostProps, DragHandleGlyphProps, EdgeCap, EdgeProfile, EndpointMode, FillSettings, GradientTrackOpts, GridSettings, InterpolationMode, KeyCapProps, KeyCapVariant, KeySequenceProps, KeySpec, KeycapKind, ListEditorProps, LogicalMod, LogicalModSpec, MenuButtonItem, MenuButtonProps, NumberFieldProps, OptionsBarItem, OptionsBarProps, OptionsBarSize, OptionsBarVariant, Platform, Plot2DCoords, Plot2DHandle, Plot2DProps, PointPlotterProps, PowerlineProps, PowerlineSegment, PrefsDialogProps, PrefsFormProps, PrefsLayout, RadioGroupProps, RadioProps, RangeSliderProps, ReorderDragHandlers, ReorderDragState, ReorderGhost, RovingItem, RovingTabIndex, SidebarPanelProps, SidebarProps, SliderProps, SwitchProps, TabListProps, TabPanelProps, TabProps, TabsProps, Thumb, ThumbRenderCtx, ThumbShape, ToolButtonProps, ToolGroupProps, ToolPaletteProps, TrackCtx, UseAsyncOptionsProps, UseReorderDragListOptions, UseRovingTabIndexOptions };