@elabs-ai/components-ui 4.0.0 → 4.1.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 (223) hide show
  1. package/README.md +10 -8
  2. package/dist/chunk-JKPPTL63.js +48 -0
  3. package/dist/chunk-JKPPTL63.js.map +1 -0
  4. package/dist/form.d.ts +28 -0
  5. package/dist/form.js +123 -0
  6. package/dist/form.js.map +1 -0
  7. package/dist/index.d.ts +2485 -167
  8. package/dist/index.js +10716 -2706
  9. package/dist/index.js.map +1 -1
  10. package/package.json +21 -7
  11. package/src/_peer-deps.test.ts +59 -0
  12. package/src/blocks-comparison-table.stories.tsx +2 -2
  13. package/src/components/accordion/accordion.tsx +1 -1
  14. package/src/components/advanced-group/advanced-group.tsx +1 -1
  15. package/src/components/alert/alert.tsx +4 -1
  16. package/src/components/app-shell/app-shell.stories.tsx +44 -2
  17. package/src/components/app-shell/app-shell.tsx +35 -2
  18. package/src/components/app-sidebar/app-sidebar.stories.tsx +9 -1
  19. package/src/components/attribution-panel/attribution-panel.tsx +1 -1
  20. package/src/components/attribution-panel/attributions.generated.ts +81 -77
  21. package/src/components/badge/badge.stories.tsx +8 -0
  22. package/src/components/badge/badge.tsx +1 -1
  23. package/src/components/bento-grid/bento-grid.test.tsx +1 -1
  24. package/src/components/bento-grid/bento-grid.tsx +1 -1
  25. package/src/components/breadcrumb/breadcrumb.stories.tsx +38 -0
  26. package/src/components/breadcrumb/breadcrumb.test.tsx +24 -1
  27. package/src/components/breadcrumb/breadcrumb.tsx +7 -2
  28. package/src/components/button/button.stories.tsx +116 -8
  29. package/src/components/button/button.tsx +1 -1
  30. package/src/components/card/card.stories.tsx +11 -6
  31. package/src/components/card/card.tsx +1 -1
  32. package/src/components/change-review/change-review.stories.tsx +145 -1
  33. package/src/components/change-review/change-review.test.tsx +143 -0
  34. package/src/components/change-review/change-review.tsx +185 -4
  35. package/src/components/checkbox/checkbox.tsx +1 -1
  36. package/src/components/color-picker/color-picker.tsx +6 -5
  37. package/src/components/command/command.stories.tsx +16 -6
  38. package/src/components/command/command.test.tsx +73 -0
  39. package/src/components/command/command.tsx +30 -7
  40. package/src/components/command/index.ts +1 -0
  41. package/src/components/command-trigger/command-trigger.stories.tsx +39 -0
  42. package/src/components/command-trigger/command-trigger.test.tsx +18 -0
  43. package/src/components/command-trigger/command-trigger.tsx +70 -0
  44. package/src/components/command-trigger/index.ts +1 -0
  45. package/src/components/context-rail/context-rail.stories.tsx +285 -0
  46. package/src/components/context-rail/context-rail.test.tsx +263 -0
  47. package/src/components/context-rail/context-rail.tsx +678 -0
  48. package/src/components/context-rail/index.ts +1 -0
  49. package/src/components/copyable-value/copyable-value.tsx +1 -1
  50. package/src/components/dialog/dialog.tsx +2 -2
  51. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +1 -1
  52. package/src/components/empty-state/empty-state.test.tsx +26 -0
  53. package/src/components/empty-state/empty-state.tsx +6 -1
  54. package/src/components/expand-dialog/expand-dialog.tsx +1 -2
  55. package/src/components/field/field-context.ts +59 -0
  56. package/src/components/field/field.stories.tsx +142 -0
  57. package/src/components/field/field.test.tsx +415 -0
  58. package/src/components/field/field.tsx +340 -0
  59. package/src/components/field/index.ts +9 -0
  60. package/src/components/field-row/field-row.stories.tsx +85 -1
  61. package/src/components/field-row/field-row.test.tsx +145 -0
  62. package/src/components/field-row/field-row.tsx +48 -6
  63. package/src/components/file-upload/file-upload.stories.tsx +16 -0
  64. package/src/components/file-upload/file-upload.test.tsx +7 -2
  65. package/src/components/file-upload/file-upload.tsx +15 -4
  66. package/src/components/form/form.tsx +5 -2
  67. package/src/components/icon-button/icon-button.test.tsx +1 -1
  68. package/src/components/icon-button/icon-button.tsx +2 -2
  69. package/src/components/input/input.stories.tsx +121 -0
  70. package/src/components/input/input.test.tsx +13 -0
  71. package/src/components/input/input.tsx +2 -2
  72. package/src/components/input-group/input-group.stories.tsx +74 -0
  73. package/src/components/input-group/input-group.tsx +13 -4
  74. package/src/components/input-otp/input-otp.tsx +5 -1
  75. package/src/components/keyboard-shortcuts/index.ts +6 -0
  76. package/src/components/keyboard-shortcuts/keyboard-shortcuts.stories.tsx +177 -0
  77. package/src/components/keyboard-shortcuts/keyboard-shortcuts.test.tsx +73 -0
  78. package/src/components/keyboard-shortcuts/keyboard-shortcuts.tsx +203 -0
  79. package/src/components/link-preview/link-preview.tsx +1 -1
  80. package/src/components/locale-provider/index.ts +6 -1
  81. package/src/components/locale-provider/locale-provider.stories.tsx +89 -1
  82. package/src/components/locale-provider/locale-provider.test.tsx +257 -1
  83. package/src/components/locale-provider/locale-provider.tsx +63 -8
  84. package/src/components/locale-provider/messages.ts +501 -2
  85. package/src/components/match-highlight/match-highlight.stories.tsx +1 -1
  86. package/src/components/mention-input/mention-input-mirror.stories.tsx +9 -1
  87. package/src/components/mention-input/mention-input.tsx +8 -38
  88. package/src/components/mention-input/mention-value.ts +8 -2
  89. package/src/components/metric-card/metric-card.stories.tsx +5 -3
  90. package/src/components/metric-card/metric-card.tsx +21 -2
  91. package/src/components/model-picker/model-picker.stories.tsx +63 -3
  92. package/src/components/model-picker/model-picker.test.tsx +63 -0
  93. package/src/components/model-picker/model-picker.tsx +62 -36
  94. package/src/components/nav-main/nav-main.tsx +1 -1
  95. package/src/components/nav-notifications/nav-notifications.stories.tsx +110 -0
  96. package/src/components/nav-notifications/nav-notifications.tsx +57 -5
  97. package/src/components/navigation-menu/navigation-menu.stories.tsx +22 -0
  98. package/src/components/navigation-menu/navigation-menu.test.tsx +174 -0
  99. package/src/components/navigation-menu/navigation-menu.tsx +189 -12
  100. package/src/components/page-shell/page-shell.stories.tsx +163 -0
  101. package/src/components/page-shell/page-shell.test.tsx +229 -0
  102. package/src/components/page-shell/page-shell.tsx +108 -25
  103. package/src/components/pagination/pagination.test.tsx +90 -0
  104. package/src/components/pagination/pagination.tsx +9 -5
  105. package/src/components/radio-group/radio-group.tsx +1 -1
  106. package/src/components/rating/rating.tsx +1 -1
  107. package/src/components/resizable/resizable.stories.tsx +114 -2
  108. package/src/components/resizable/resizable.tsx +1 -1
  109. package/src/components/revision-timeline/revision-timeline.stories.tsx +8 -1
  110. package/src/components/revision-timeline/revision-timeline.test.tsx +26 -0
  111. package/src/components/revision-timeline/revision-timeline.tsx +46 -3
  112. package/src/components/schema-form/from-json-schema.test.ts +390 -0
  113. package/src/components/schema-form/from-json-schema.ts +375 -0
  114. package/src/components/schema-form/index.ts +81 -0
  115. package/src/components/schema-form/schema-form-spec.ts +698 -0
  116. package/src/components/schema-form/schema-form.stories.tsx +566 -0
  117. package/src/components/schema-form/schema-form.test.tsx +900 -0
  118. package/src/components/schema-form/schema-form.tsx +1545 -0
  119. package/src/components/section-header/section-header.stories.tsx +37 -0
  120. package/src/components/section-header/section-header.tsx +12 -1
  121. package/src/components/select/select.tsx +6 -2
  122. package/src/components/sheet/sheet.tsx +1 -1
  123. package/src/components/side-dock/index.ts +1 -0
  124. package/src/components/side-dock/side-dock.stories.tsx +137 -0
  125. package/src/components/side-dock/side-dock.test.tsx +273 -0
  126. package/src/components/side-dock/side-dock.tsx +502 -0
  127. package/src/components/sidebar/index.ts +1 -0
  128. package/src/components/sidebar/sidebar-frame.test.tsx +162 -0
  129. package/src/components/sidebar/sidebar.stories.tsx +421 -1
  130. package/src/components/sidebar/sidebar.test.tsx +36 -1
  131. package/src/components/sidebar/sidebar.tsx +245 -33
  132. package/src/components/skip-link/index.ts +1 -0
  133. package/src/components/skip-link/skip-link.stories.tsx +106 -0
  134. package/src/components/skip-link/skip-link.test.tsx +20 -0
  135. package/src/components/skip-link/skip-link.tsx +34 -0
  136. package/src/components/slider/slider.tsx +1 -1
  137. package/src/components/split-panel/index.ts +6 -1
  138. package/src/components/split-panel/split-panel.stories.tsx +18 -2
  139. package/src/components/split-panel/split-panel.test.tsx +20 -0
  140. package/src/components/split-panel/split-panel.tsx +28 -8
  141. package/src/components/state-panel/state-panel.stories.tsx +52 -0
  142. package/src/components/state-panel/state-panel.test.tsx +125 -0
  143. package/src/components/state-panel/state-panel.tsx +96 -17
  144. package/src/components/status-badge/status-badge.stories.tsx +8 -0
  145. package/src/components/switch/switch.tsx +1 -1
  146. package/src/components/table/table.stories.tsx +62 -0
  147. package/src/components/table/table.test.tsx +142 -1
  148. package/src/components/table/table.tsx +60 -1
  149. package/src/components/tabs/tabs.tsx +8 -2
  150. package/src/components/tag-input/tag-input.tsx +3 -2
  151. package/src/components/team-switcher/team-switcher.tsx +34 -5
  152. package/src/components/textarea/textarea.tsx +1 -1
  153. package/src/components/theme-switcher/theme-switcher.tsx +6 -2
  154. package/src/components/theme-switcher/use-theme-transition.ts +2 -2
  155. package/src/components/timeline/timeline.stories.tsx +27 -0
  156. package/src/components/timeline/timeline.tsx +11 -1
  157. package/src/components/toggle/toggle.tsx +1 -1
  158. package/src/components/toolbar/toolbar.stories.tsx +10 -2
  159. package/src/components/tree/tree.stories.tsx +2 -2
  160. package/src/components/tree/tree.tsx +14 -9
  161. package/src/components/typography/prose.tsx +1 -1
  162. package/src/components/typography/typography.stories.tsx +228 -0
  163. package/src/components/view-toolbar/view-toolbar.stories.tsx +41 -1
  164. package/src/components/view-toolbar/view-toolbar.test.tsx +33 -0
  165. package/src/components/view-toolbar/view-toolbar.tsx +37 -4
  166. package/src/components/virtual-select/virtual-select.test.tsx +1 -1
  167. package/src/components/wizard/wizard.tsx +1 -1
  168. package/src/components/workspace-picker/index.ts +3 -0
  169. package/src/components/workspace-picker/workspace-picker-state.ts +50 -0
  170. package/src/components/workspace-picker/workspace-picker.stories.tsx +126 -0
  171. package/src/components/workspace-picker/workspace-picker.test.tsx +207 -0
  172. package/src/components/workspace-picker/workspace-picker.tsx +172 -0
  173. package/src/illustrations/empty-list-illustration.tsx +26 -0
  174. package/src/illustrations/error-illustration.tsx +60 -0
  175. package/src/illustrations/first-run-illustration.tsx +27 -0
  176. package/src/illustrations/illustration-base.tsx +108 -0
  177. package/src/illustrations/illustrations.stories.tsx +94 -0
  178. package/src/illustrations/illustrations.test.tsx +98 -0
  179. package/src/illustrations/index.ts +16 -0
  180. package/src/illustrations/no-access-illustration.tsx +45 -0
  181. package/src/illustrations/no-results-illustration.tsx +46 -0
  182. package/src/illustrations/offline-illustration.tsx +37 -0
  183. package/src/illustrations/success-illustration.tsx +40 -0
  184. package/src/index.ts +75 -2
  185. package/src/lib/agent-event-model.test.ts +12 -0
  186. package/src/lib/agent-event-model.ts +42 -0
  187. package/src/lib/approval-option.test.ts +17 -0
  188. package/src/lib/approval-option.ts +53 -0
  189. package/src/lib/check-result.ts +33 -0
  190. package/src/lib/diff-line.test.ts +36 -0
  191. package/src/lib/diff-line.ts +63 -0
  192. package/src/lib/diff-rows.test.ts +76 -0
  193. package/src/lib/diff-rows.ts +92 -0
  194. package/src/lib/format-duration.test.ts +22 -0
  195. package/src/lib/format-duration.ts +30 -0
  196. package/src/lib/has-renderable-content.test.ts +49 -0
  197. package/src/lib/has-renderable-content.ts +32 -0
  198. package/src/lib/operating-mode.test.ts +36 -0
  199. package/src/lib/operating-mode.ts +81 -0
  200. package/src/lib/optional-peer.ts +59 -0
  201. package/src/lib/session-launch.ts +37 -0
  202. package/src/lib/slash-command.test.ts +44 -0
  203. package/src/lib/slash-command.ts +45 -0
  204. package/src/lib/trigger-query.test.ts +94 -0
  205. package/src/lib/trigger-query.ts +88 -0
  206. package/src/lib/use-mobile.ts +12 -6
  207. package/src/motion.stories.tsx +6 -0
  208. package/src/templates-object-detail-hub.stories.tsx +2 -2
  209. package/src/templates-screen-states.stories.tsx +5 -5
  210. package/src/templates-settings.stories.tsx +1 -1
  211. package/src/blocks/sidebar-02/app-sidebar.tsx +0 -160
  212. package/src/blocks/sidebar-02/logo.tsx +0 -18
  213. package/src/blocks/sidebar-02/nav-main.tsx +0 -13
  214. package/src/blocks/sidebar-02/nav-notifications.tsx +0 -7
  215. package/src/blocks/sidebar-02/sidebar-02.stories.tsx +0 -23
  216. package/src/blocks/sidebar-02/team-switcher.tsx +0 -7
  217. package/src/blocks/sidebar-04/app-sidebar.tsx +0 -236
  218. package/src/blocks/sidebar-04/mail-context.tsx +0 -29
  219. package/src/blocks/sidebar-04/nav-user.tsx +0 -6
  220. package/src/blocks/sidebar-04/sidebar-04.stories.tsx +0 -150
  221. package/src/blocks/sidebar-05/app-sidebar.tsx +0 -375
  222. package/src/blocks/sidebar-05/sidebar-05.stories.tsx +0 -18
  223. package/src/blocks/sidebar-05/team-switcher.tsx +0 -6
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  import { LucideIcon, LucideProps } from 'lucide-react';
3
3
  import * as react from 'react';
4
- import react__default, { HTMLAttributes, ReactNode, InputHTMLAttributes, ButtonHTMLAttributes, ComponentProps, ComponentPropsWithoutRef, ReactElement, TextareaHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, LiHTMLAttributes, AnchorHTMLAttributes, OlHTMLAttributes } from 'react';
5
- import * as AccordionPrimitive from '@radix-ui/react-accordion';
4
+ import react__default, { ReactNode, HTMLAttributes, SVGProps, InputHTMLAttributes, ButtonHTMLAttributes, ComponentProps, ComponentPropsWithoutRef, ReactElement, TextareaHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, LiHTMLAttributes, AnchorHTMLAttributes, OlHTMLAttributes } from 'react';
6
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
7
- import * as _radix_ui_react_separator from '@radix-ui/react-separator';
8
6
  import { VariantProps } from 'class-variance-authority';
7
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
8
+ import * as _radix_ui_react_separator from '@radix-ui/react-separator';
9
9
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
10
10
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
11
11
  import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
@@ -21,10 +21,7 @@ import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
21
21
  import * as vaul from 'vaul';
22
22
  import { Drawer as Drawer$1 } from 'vaul';
23
23
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
24
- import * as _radix_ui_react_slot from '@radix-ui/react-slot';
25
24
  import * as _radix_ui_react_label from '@radix-ui/react-label';
26
- import * as react_hook_form from 'react-hook-form';
27
- import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
28
25
  import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
29
26
  import * as input_otp from 'input-otp';
30
27
  import * as PopoverPrimitive from '@radix-ui/react-popover';
@@ -34,6 +31,7 @@ import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
34
31
  import * as ProgressPrimitive from '@radix-ui/react-progress';
35
32
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
36
33
  import * as ResizablePrimitive from 'react-resizable-panels';
34
+ import { z } from 'zod';
37
35
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
38
36
  import * as SelectPrimitive from '@radix-ui/react-select';
39
37
  import * as SliderPrimitive from '@radix-ui/react-slider';
@@ -54,8 +52,14 @@ import { Virtualizer } from '@tanstack/react-virtual';
54
52
  */
55
53
  declare function cn(...inputs: ClassValue[]): string;
56
54
 
57
- /** Returns true when the viewport is below the mobile breakpoint (768px). */
58
- declare function useIsMobile(): boolean;
55
+ /**
56
+ * Returns true when the viewport is below `breakpoint` (default 768px, the
57
+ * mobile breakpoint). Additive optional argument (ADR 0035 §5) — every
58
+ * existing zero-arg call site is unchanged. A caller with its own threshold
59
+ * (e.g. `ContextRail`'s `overlayBreakpoint`) passes it directly instead of a
60
+ * second hook.
61
+ */
62
+ declare function useIsMobile(breakpoint?: number): boolean;
59
63
 
60
64
  /**
61
65
  * Browser file-download helpers — the single home for the
@@ -505,6 +509,642 @@ type StreamdownTranslationMap = Record<StreamdownTranslationKey, string>;
505
509
  */
506
510
  declare function useStreamdownTranslations(): StreamdownTranslationMap;
507
511
 
512
+ /**
513
+ * One verification verdict about an action — a linter, a type check, a test run,
514
+ * a policy hook. Shared vocabulary across packages: `ChangeReview` (#112) shows the
515
+ * checks a proposed edit already passed, `AgentEvent` (#109) shows the checks a
516
+ * runtime hook ran around a tool call. One runtime concept, one shape.
517
+ *
518
+ * Presentational only (D5): this type records a verdict someone else computed.
519
+ * Nothing in brand-ui ever runs a check.
520
+ *
521
+ * Rendering contract, binding on every consumer: `ok` must reach the user through
522
+ * an ICON and ACCESSIBLE TEXT, never through colour alone — the greyscale test in
523
+ * `.claude/rules/accessibility.md`.
524
+ */
525
+ interface CheckResult {
526
+ /** What ran, verbatim as the runtime names it: "eslint", "tsc", "pre_tool_use". */
527
+ label: string;
528
+ /** Did it pass? The verdict; the only required field besides `label`. */
529
+ ok: boolean;
530
+ /** One line of explanation. Renders as a secondary line, collapsed when long. */
531
+ detail?: string;
532
+ /** Wall-clock duration in milliseconds. Format with `formatElapsed`. */
533
+ durationMs?: number;
534
+ /** When it ran relative to the action it gates. Groups results into sections. */
535
+ phase?: "before" | "after";
536
+ }
537
+ /** A count summary, when the individual verdicts are not available. */
538
+ interface CheckSummary {
539
+ /** How many checks ran. */
540
+ ran: number;
541
+ /** How many of them passed. `passed <= ran`. */
542
+ passed: number;
543
+ }
544
+
545
+ /**
546
+ * Human-readable elapsed time — one formatter for every "how long did this take"
547
+ * surface in the system: `TurnStatus`'s running turn (#105), `ChangeReview`'s check
548
+ * rows (#112), `AgentEvent`'s hook durations (#109).
549
+ *
550
+ * Exported so a consumer's own elapsed-time surfaces agree with ours.
551
+ * Adapted from `brainless`'s turn-status elapsed formatter (MIT, see `ATTRIBUTION.md`).
552
+ *
553
+ * Rungs: sub-second → "420ms" · under ten seconds → "8.0s" · under a minute → "45s" ·
554
+ * beyond → "2m05s".
555
+ */
556
+ declare function formatElapsed(elapsedMs: number): string;
557
+
558
+ /** True when a raw error MESSAGE names a module the runtime could not load. */
559
+ declare function isModuleNotFoundMessage(message: string): boolean;
560
+ /**
561
+ * True when `value` is (or looks like) a failed dynamic `import()` of a
562
+ * missing optional peer. Accepts anything a `.catch()` or an error boundary
563
+ * might see: an `Error` instance (checked by `code` first, then message), or
564
+ * `undefined`/other for anything that clearly is not one.
565
+ */
566
+ declare function isOptionalPeerMissing(value: unknown): boolean;
567
+
568
+ /**
569
+ * The generic, component-agnostic half of a trigger-driven inline palette —
570
+ * "is the caret sitting inside a `trigger + query` run, and how do I splice a
571
+ * chosen result back in". Zero React, zero DOM, zero knowledge of mentions.
572
+ *
573
+ * Lifted out of `MentionInput`'s private `findQuery`/`isWordBoundary`
574
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 5) so a second
575
+ * trigger-driven surface (a slash-command palette) reuses the algorithm instead
576
+ * of re-implementing it. `MentionInput` consumes this module unchanged — see
577
+ * `mention-input.tsx`.
578
+ */
579
+ /**
580
+ * Where a trigger character is allowed to START a query.
581
+ *
582
+ * `"word"` — index 0, or preceded by whitespace / "(" / "[". (`MentionInput`'s
583
+ * behaviour, unchanged — an "@" inside an email address must not open a popup.)
584
+ * `"line-start"` — index 0, or preceded by "\n". (A slash palette: "/help" opens, "cd /usr" does not.)
585
+ */
586
+ type TriggerBoundary = "word" | "line-start";
587
+ /** An in-progress `trigger + query` run under the caret. */
588
+ interface TriggerQuery {
589
+ /** Offset of the trigger character in `text`. */
590
+ start: number;
591
+ /** The query WITHOUT the trigger character. */
592
+ query: string;
593
+ }
594
+ interface FindTriggerQueryOptions {
595
+ /** @default "word" */
596
+ boundary?: TriggerBoundary;
597
+ /**
598
+ * Veto a candidate whose trigger character has already been consumed by a
599
+ * committed token — `MentionInput` passes `mentionAt(...)` here so an
600
+ * inserted "@Ada Lovelace" cannot re-open the popup. Omit when there are no
601
+ * committed tokens (a slash palette has none).
602
+ */
603
+ isTriggerConsumed?: (start: number) => boolean;
604
+ }
605
+ /**
606
+ * Is the caret sitting inside a `trigger + query` run?
607
+ *
608
+ * DERIVED from committed text + caret, never intercepted at keydown — a
609
+ * keydown-driven trigger must `preventDefault()` every printable character and
610
+ * re-insert it by hand, which destroys IME composition, native undo, spellcheck
611
+ * and paste. Deriving means the popup opens identically whether the trigger
612
+ * arrived by typing, pasting, an IME commit, or a click that moved the caret
613
+ * back into a half-typed query.
614
+ */
615
+ declare function findTriggerQuery(text: string, caret: number, trigger: string, options?: FindTriggerQueryOptions): TriggerQuery | null;
616
+ /** The plain-text half of an insert: splice `insertText` over the run, and say where the caret lands. */
617
+ declare function replaceTriggerRun(text: string, queryStart: number, caret: number, insertText: string): {
618
+ text: string;
619
+ caret: number;
620
+ };
621
+
622
+ /**
623
+ * The command model behind a `/`-triggered slash-command palette
624
+ * (`PromptInputSlash` in `@elabs-ai/components-ai`, and the terminal CLI
625
+ * look-alike family's own palette — issue #117).
626
+ *
627
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
628
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
629
+ * each other — `ui` is upstream of both, so this is the one legal shared home
630
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4, the
631
+ * promotion rule: "a helper shared by two layer-2 siblings moves UP to `ui`,
632
+ * it is never duplicated sideways"). No DOM, no keyboard wiring, no rendering
633
+ * — the popover, the caret tracking and the row markup stay in each
634
+ * package's own presentational component.
635
+ */
636
+
637
+ /** One entry a slash palette offers. Ships no vocabulary — entirely prop-driven. */
638
+ interface SlashCommand {
639
+ /** Stable name, WITHOUT the leading "/" (e.g. `"help"`, not `"/help"`). */
640
+ name: string;
641
+ /** One line shown next to the name. */
642
+ description?: string;
643
+ /** Extra prefix-match aids beyond `name` (matched case-insensitively). */
644
+ keywords?: string[];
645
+ /** Leading glyph. Decorative — the row is identified by `name`. */
646
+ icon?: ReactNode;
647
+ }
648
+ /**
649
+ * Case-insensitive PREFIX match on `name`, falling back to a prefix match on
650
+ * any `keyword`. Prefix (not substring) is deliberate: `/hel` should surface
651
+ * `/help`, not e.g. a hypothetical `/channel`.
652
+ */
653
+ declare function defaultSlashCommandFilter(command: SlashCommand, query: string): boolean;
654
+ /** Next index in `[0, count)`, wrapping at both ends. `-1` when `count` is 0. */
655
+ declare function stepIndex(count: number, from: number, direction: 1 | -1): number;
656
+
657
+ /**
658
+ * The N-option, scoped-approval model behind `ApprovalCardOptions`
659
+ * (`@elabs-ai/components-ai`'s `confirmation.tsx`, #103) and the terminal CLI
660
+ * look-alike family's own permission row (issue #117) — a real coding-agent
661
+ * permission prompt is rarely a plain yes/no; it asks an N-option question
662
+ * whose options encode SCOPE ("Yes", "Yes, and don't ask again this
663
+ * session", "No, and tell the agent what to do instead").
664
+ *
665
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
666
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
667
+ * each other — `ui` is upstream of both
668
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). The
669
+ * SYMBOLS have zero SDK coupling; only their previous host module
670
+ * (`confirmation.tsx`) imports `ai`'s `ToolUIPart`, so only the vocabulary —
671
+ * never the component — moves.
672
+ */
673
+ /**
674
+ * How far a chosen option's permission reaches. Deliberately a closed,
675
+ * app-agnostic vocabulary (not a free string) so a consumer can derive an
676
+ * accessible fallback description per option (see
677
+ * `APPROVAL_SCOPE_DESCRIPTION_KEYS` below) — the one thing every option of a
678
+ * given scope always means, regardless of the agent-specific label wording.
679
+ */
680
+ type ApprovalScope = "once" | "session" | "always" | "deny";
681
+ interface ApprovalOption {
682
+ id: string;
683
+ label: string;
684
+ /**
685
+ * What choosing this option actually does. Optional: when omitted, the
686
+ * consumer renders a scope-derived sentence instead, so scope always
687
+ * reaches assistive tech through real text — never only through colour or
688
+ * a `data-*` attribute (WCAG 1.4.1).
689
+ */
690
+ description?: string;
691
+ scope: ApprovalScope;
692
+ /** Optional key hint shown beside the option, e.g. "1". */
693
+ keyHint?: string;
694
+ }
695
+ /**
696
+ * The locale-message KEY (not the translated text — `ui`'s locale catalogue,
697
+ * `components/locale-provider/messages.ts`, holds the English fallback and
698
+ * every other locale's translation) for the scope-derived sentence used only
699
+ * when `option.description` is omitted.
700
+ */
701
+ declare const APPROVAL_SCOPE_DESCRIPTION_KEYS: Record<ApprovalScope, string>;
702
+
703
+ /**
704
+ * The unified-diff line model behind `DiffView` (`@elabs-ai/components-ai`,
705
+ * #102) and the terminal CLI look-alike family's own diff hunk (issue #117).
706
+ *
707
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
708
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
709
+ * each other — `ui` is upstream of both
710
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). This
711
+ * module is the shiki-free half: the line shape, the marker glyph and the
712
+ * screen-reader polarity label. Intra-line syntax highlighting (Shiki) and
713
+ * the diff's presentational chrome stay in `@elabs-ai/components-ai`'s
714
+ * `diff-view.tsx` — `ui` does not depend on Shiki and never will for one
715
+ * component (see the decision doc § 3).
716
+ *
717
+ * The `DiffLine` model and the polarity-prefix technique are adapted from
718
+ * `theswerd/brainless` (MIT) — see `ATTRIBUTION.md`.
719
+ */
720
+ /** What role a line plays in the diff. */
721
+ type DiffLineType = "add" | "del" | "context" | "hunk" | "meta";
722
+ /** One line of a unified diff. Absent gutter numbers are load-bearing (see below). */
723
+ interface DiffLine {
724
+ type: DiffLineType;
725
+ /** Line number in the original file. Absent on `add` — there is no old line. */
726
+ oldNumber?: number;
727
+ /** Line number in the new file. Absent on `del` — there is no new line. */
728
+ newNumber?: number;
729
+ /** The line's text, without its leading `+` / `-` / ` ` marker. */
730
+ text: string;
731
+ }
732
+ /**
733
+ * The single-character marker glyph for a real source line (`add`/`del`/
734
+ * `context`). `hunk`/`meta` lines are diff headers, not source, and render
735
+ * through a full-width row instead — this returns `""` for them.
736
+ */
737
+ declare function diffLineMarker(type: DiffLineType): string;
738
+ /**
739
+ * The `ui` locale-message KEY (not the translated text) for the `sr-only`
740
+ * screen-reader polarity word an `add`/`del` row carries ALONGSIDE its marker
741
+ * glyph and its fill tint — colour is never the only channel (WCAG 1.4.1).
742
+ * `undefined` for `context`/`hunk`/`meta`, which carry no polarity.
743
+ */
744
+ declare function diffLineAccessibleLabel(type: DiffLineType): "ai.diffView.addedLine" | "ai.diffView.removedLine" | undefined;
745
+
746
+ /**
747
+ * One rendered row: either a real diff line, or a collapsed run of
748
+ * consecutive `context` lines longer than the caller's `contextLines`.
749
+ */
750
+ type DiffRow = {
751
+ kind: "line";
752
+ line: DiffLine;
753
+ index: number;
754
+ } | {
755
+ kind: "collapsed";
756
+ runStart: number;
757
+ hiddenCount: number;
758
+ };
759
+ /**
760
+ * Collapse long runs of consecutive `context` lines behind a single
761
+ * `"collapsed"` row, keeping `Math.ceil(contextLines / 2)` lines of context
762
+ * at the top of the run and `Math.floor(contextLines / 2)` at the bottom —
763
+ * so a reader always sees context on both sides of a hidden gap. A run
764
+ * already in `expanded` (by its start index) renders in full instead.
765
+ *
766
+ * Pure: no state, no effect. `useDiffRows` below is the stateful wrapper
767
+ * that owns the `expanded` set for a component.
768
+ */
769
+ declare function collapseDiffRows(lines: DiffLine[], contextLines: number | undefined, expanded?: ReadonlySet<number>): DiffRow[];
770
+ /**
771
+ * Stateful wrapper around `collapseDiffRows`: owns the set of run-start
772
+ * indices a caller has expanded via the "show more" control, and returns the
773
+ * current row list alongside an `expand` action.
774
+ */
775
+ declare function useDiffRows(lines: DiffLine[], contextLines: number | undefined): {
776
+ rows: DiffRow[];
777
+ expand: (runStart: number) => void;
778
+ };
779
+
780
+ /**
781
+ * The operating-mode and reasoning-effort vocabulary behind
782
+ * `PromptInputMode`/`PromptInputEffort` (`@elabs-ai/components-ai`, #104/#107)
783
+ * and the terminal CLI look-alike family's own composer chips (issue #117).
784
+ *
785
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
786
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
787
+ * each other — `ui` is upstream of both
788
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). Both
789
+ * types are caller-supplied vocabulary objects — never a vendor union — which
790
+ * #117 requires: no vendor mode/effort union may appear in a public type.
791
+ */
792
+
793
+ /**
794
+ * One app-defined operating mode — how autonomously the agent may act while
795
+ * this mode is active. `brand-ui` ships no vocabulary: `id`/`label` are
796
+ * entirely the consumer's (e.g. `"auto"`/`"Auto"`, `"plan"`/`"Plan first"`,
797
+ * or a completely different product's own terms).
798
+ */
799
+ interface OperatingMode {
800
+ /** Stable identifier — round-trips through `value`/`onValueChange`. */
801
+ id: string;
802
+ /** Visible + accessible name. */
803
+ label: string;
804
+ /** One line of guidance shown under the label in the menu. */
805
+ description?: string;
806
+ /** A shortcut hint rendered as a `Kbd` chip next to the label (e.g. `"⇧ Tab"`). */
807
+ keyHint?: string;
808
+ /** Leading glyph. Decorative — the mode is identified by `label`, not the icon. */
809
+ icon?: ReactNode;
810
+ }
811
+ /**
812
+ * One rung of an app-defined reasoning-effort scale. `brand-ui` ships no
813
+ * vocabulary: `id`/`label` are entirely the consumer's (e.g.
814
+ * `"low"`/`"Low"` … `"max"`/`"Max"`, or a completely different product's own
815
+ * terms and however many rungs it wants).
816
+ */
817
+ interface EffortLevel {
818
+ /** Stable identifier — round-trips through `value`/`onValueChange`. */
819
+ id: string;
820
+ /** Visible + accessible name for this rung. */
821
+ label: string;
822
+ }
823
+ /**
824
+ * Growing-square size rungs (Tailwind's own spacing scale — `size-2.5` through
825
+ * `size-6`), indexed by ordinal position so a caller never invents a raw
826
+ * pixel value. All in ONE `tailwind-merge` class group (`size`), so
827
+ * overriding a base size class is a guaranteed, order-independent swap
828
+ * rather than a `w-*`/`h-*` vs `size-*` conflict tailwind-merge can't see.
829
+ */
830
+ declare const EFFORT_SIZE_RUNGS: readonly ["size-2.5", "size-3", "size-3.5", "size-4", "size-4.5", "size-5", "size-5.5", "size-6"];
831
+ /**
832
+ * The size class for rung `index` of `count` evenly-spaced rungs — the
833
+ * growing-square ramp `PromptInputEffort` (and the terminal composer's own
834
+ * effort chips) render, low to high.
835
+ */
836
+ declare function effortRungForIndex(index: number, count: number): (typeof EFFORT_SIZE_RUNGS)[number];
837
+
838
+ /** The canonical, closed 7-state status enum (research 10 §B.1). */
839
+ declare const STATUSES: readonly ["pending", "running", "complete", "awaiting-approval", "denied", "failed", "skipped"];
840
+ type Status = (typeof STATUSES)[number];
841
+ /** Closed tone set for the out-of-vocabulary escape hatch (CALM treatments only). */
842
+ declare const STATUS_TONES: readonly ["neutral", "info", "success", "warning", "destructive"];
843
+ type StatusTone = (typeof STATUS_TONES)[number];
844
+ /**
845
+ * An out-of-vocabulary status. Prefer the canonical `Status` enum; reach for
846
+ * this only when the domain genuinely has a state the 7 do not express (e.g. a
847
+ * run engine's `stopped_guardrail`). Map it ONCE, near your domain — not per
848
+ * call site.
849
+ */
850
+ interface CustomStatus {
851
+ label: string;
852
+ tone: StatusTone;
853
+ /** Optional Lucide glyph. Omitted → label-only (no default glyph). */
854
+ icon?: LucideIcon;
855
+ }
856
+ /** Narrows `Status | CustomStatus` — the object form is always the escape hatch. */
857
+ declare function isCustomStatus(status: Status | CustomStatus): status is CustomStatus;
858
+ /**
859
+ * The canonical semantic ROLE per status — the single source of truth for
860
+ * status colour (#392). Any other status-keyed colour map in the repo
861
+ * (`Timeline`'s `NODE_STYLE`, or a future one) must be TESTED against this,
862
+ * not hand-authored — a second literal copy is exactly how `NODE_STYLE`
863
+ * drifted (`running` rendered `--primary` while this map said `--info`).
864
+ * Do NOT interpolate `bg-${STATUS_ROLE[status]}` into a class map: Tailwind
865
+ * scans source statically, so a template-literal class emits no CSS. Keep
866
+ * consuming maps as literal class strings, verified against this export by a
867
+ * test.
868
+ */
869
+ declare const STATUS_ROLE: {
870
+ readonly pending: "secondary";
871
+ readonly running: "info";
872
+ readonly complete: "success";
873
+ readonly "awaiting-approval": "warning";
874
+ readonly denied: "muted";
875
+ readonly failed: "destructive";
876
+ readonly skipped: "secondary";
877
+ };
878
+ /** Default human-readable label per status (override via `children`). */
879
+ declare const STATUS_LABELS: Record<Status, string>;
880
+ /**
881
+ * Lucide glyph per out-of-vocabulary TONE — the same five-tone escape hatch
882
+ * `CustomStatus` uses (`STATUS_TONES`). A consumer that encodes a bare TONE
883
+ * with no fuller `Status` semantics (e.g. `@elabs-ai/components-flow`'s `FlowNode.tone`,
884
+ * #387) derives its non-colour cue from here instead of inventing a second
885
+ * icon vocabulary — each entry reuses the SAME icon `STATUS_ICONS` already
886
+ * pairs with that tone's one canonical status (`success`→`complete`'s
887
+ * `CheckCircle2`, `warning`→`awaiting-approval`'s `Clock`,
888
+ * `destructive`→`failed`'s `AlertCircle`). `neutral`/`info` have no entry:
889
+ * nothing consumes them yet, and reaching for a glyph on every neutral/
890
+ * default-toned element would be assistive-tech noise on the common case —
891
+ * extend this map, don't fork a new one, the day something needs them.
892
+ */
893
+ declare const STATUS_TONE_ICONS: Partial<Record<StatusTone, LucideIcon>>;
894
+ interface StatusIconProps extends Omit<LucideProps, "ref"> {
895
+ /** The canonical execution status (closed enum). */
896
+ status: Status;
897
+ }
898
+ /**
899
+ * The icon + status-color atom `StatusBadge` itself composes — for tight rows
900
+ * (test-result rows, timeline/rail nodes) where a full badge is too heavy.
901
+ * Decorative by default (`aria-hidden`); the adjacent row text must carry the
902
+ * status name for AT users.
903
+ */
904
+ declare const StatusIcon: react.ForwardRefExoticComponent<StatusIconProps & react.RefAttributes<SVGSVGElement>>;
905
+ declare const statusBadgeVariants: (props?: ({
906
+ status?: "pending" | "running" | "complete" | "awaiting-approval" | "denied" | "failed" | "skipped" | null | undefined;
907
+ tone?: "success" | "warning" | "destructive" | "info" | "neutral" | null | undefined;
908
+ size?: "md" | "sm" | null | undefined;
909
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
910
+ interface StatusBadgeProps extends HTMLAttributes<HTMLSpanElement>, Omit<VariantProps<typeof statusBadgeVariants>, "status" | "tone"> {
911
+ /** The canonical execution status, or a mapped out-of-vocabulary one (#363). */
912
+ status: Status | CustomStatus;
913
+ /** Render label-only (no status icon). */
914
+ hideIcon?: boolean;
915
+ }
916
+ declare const StatusBadge: react.ForwardRefExoticComponent<StatusBadgeProps & react.RefAttributes<HTMLSpanElement>>;
917
+ /** The editor/markdown `Timeline` 3-state vocabulary (`@elabs-ai/components-editor`). */
918
+ type TimelineStatus = "done" | "active" | "pending";
919
+ /**
920
+ * Map the Timeline `done|active|pending` vocabulary onto the canonical
921
+ * `Status` (research 10 §B.1 mapping b — lossless; the timeline only
922
+ * expresses 3 of the 7 states). The AI-SDK `ToolUIPart` mapper lives in
923
+ * `@elabs-ai/components-ai` (`statusFromToolState`, tool.tsx) so `@elabs-ai/components-ui` stays free of
924
+ * the `ai` dependency (D6).
925
+ */
926
+ declare function fromTimelineStatus(status: TimelineStatus): Status;
927
+
928
+ /**
929
+ * The lifecycle/hook-event model behind `AgentEvent` (`@elabs-ai/components-ai`,
930
+ * #109) and the terminal CLI look-alike family's own event line (issue #117).
931
+ *
932
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
933
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
934
+ * each other — `ui` is upstream of both
935
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4).
936
+ * `agentEventOutcomeStatus` maps onto the existing closed 7-state `Status`
937
+ * (`components/status-badge/status-badge.tsx`), which already lives in
938
+ * `ui` — no eighth status is introduced.
939
+ */
940
+
941
+ /**
942
+ * When an event fired relative to the action it gates. A separate, WIDER
943
+ * vocabulary than `CheckResult.phase` (`"before" | "after"`, per-check): this
944
+ * one also admits `"lifecycle"` for events with no gated action (a turn's
945
+ * `user_prompt_submit`/`stop`). The two `phase` concepts answer different
946
+ * questions — "when did this event fire" vs "when did this check run" — and
947
+ * are never unified (§ 6.1 of the architecture decision above).
948
+ */
949
+ type AgentEventPhase = "before" | "after" | "lifecycle";
950
+ /** An event's verdict. Maps onto the existing closed `Status` — see `agentEventOutcomeStatus`. */
951
+ type AgentEventOutcome = "ok" | "blocked" | "failed";
952
+ /**
953
+ * `outcome` → the canonical 7-state `Status`. No new status value is added
954
+ * (issue #109 acceptance criteria); `blocked` maps to `denied` — a runtime
955
+ * hook refusing an action is the same shape as a human denying one.
956
+ */
957
+ declare function agentEventOutcomeStatus(outcome: AgentEventOutcome): Status;
958
+
959
+ /**
960
+ * The session-launch vocabulary behind `SessionHeader`
961
+ * (`@elabs-ai/components-ai`, #110) and the terminal CLI look-alike family's
962
+ * own launch banner (issue #117, T7 — the "Empty" and "First-run" states).
963
+ *
964
+ * Promoted here (not duplicated) because `@elabs-ai/components-ai` and
965
+ * `@elabs-ai/components-terminal` are layer-2 DAG SIBLINGS and may not import
966
+ * each other — `ui` is upstream of both
967
+ * (docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). Pure
968
+ * item types, no behaviour.
969
+ */
970
+
971
+ interface SessionCapability {
972
+ /** Short capability name, e.g. "Web search". */
973
+ label: string;
974
+ /** One-line detail rendered under the label. */
975
+ description?: string;
976
+ /** Decorative leading glyph — a Lucide icon element. */
977
+ icon?: ReactNode;
978
+ }
979
+ interface SessionWhatsNewItem {
980
+ /** What changed, e.g. "Faster file search". */
981
+ label: string;
982
+ /** Optional link to release notes / a changelog entry. */
983
+ href?: string;
984
+ }
985
+ interface SessionQuickAction {
986
+ /** Visible label, e.g. "New chat". */
987
+ label: string;
988
+ /** Shortcut hint, rendered with the `Kbd` primitive (e.g. "⌘N"). */
989
+ keyHint?: string;
990
+ /** Invoked when the action is chosen. */
991
+ onSelect?: () => void;
992
+ }
993
+
994
+ interface IllustrationProps extends SVGProps<SVGSVGElement> {
995
+ /**
996
+ * Rendered width & height (any CSS length — pass a `rem` value to stay
997
+ * density/zoom-aware). Illustrations are drawn to read clearly from about
998
+ * `4rem` (64px) up to `10rem` (160px).
999
+ * @default "7rem"
1000
+ */
1001
+ size?: string | number;
1002
+ }
1003
+ /**
1004
+ * Accent-semantics convention (#48 finding 1): an illustration draws at most
1005
+ * ONE accent mark (via `illustrationAccent()` below), and it exists ONLY
1006
+ * when it carries information the silhouette (the `currentColor`-stroked
1007
+ * subject) does not already supply on its own — never as ornamental
1008
+ * flourish wearing a meaning-bearing token. Applied across the seven
1009
+ * shipped illustrations:
1010
+ * - **Meaning-bearing (kept):** the "×" that turns a magnifying glass into
1011
+ * "no results" (`NoResultsIllustration`), the keyhole that turns a padlock
1012
+ * body into "restricted" (`NoAccessIllustration`), the checkmark that
1013
+ * turns a bare ring into "success" (`SuccessIllustration`), the
1014
+ * exclamation that turns a torn document into "warning" rather than
1015
+ * merely "broken" (`ErrorIllustration`).
1016
+ * - **Was decorative-only, removed (#48):** the "add" badge on
1017
+ * `EmptyListIllustration` (three rows already read as "empty list" on
1018
+ * their own), the sparkle on `FirstRunIllustration` (the planted flag
1019
+ * already reads as "start here"), and the broken-link fragments on
1020
+ * `OfflineIllustration` (a slashed cloud already reads as "disconnected" —
1021
+ * the universal "no signal" idiom). Their accent-free silhouettes carry
1022
+ * the full state alone, matching how `ErrorIllustration`'s silhouette
1023
+ * already did before this convention was written down.
1024
+ * Every illustration is `aria-hidden` regardless (the state's title/
1025
+ * description text is the ACCESSIBLE channel — see `illustrationSvgProps`
1026
+ * below), so this is a visual-consistency rule, not an a11y requirement on
1027
+ * its own; don't regress the silhouette-carries-meaning property while
1028
+ * redrawing any of the four kept accents above.
1029
+ */
1030
+ /**
1031
+ * The custom property every illustration's single meaning-bearing accent
1032
+ * reads through. `StatePanel` sets it on the illustration slot's wrapper for
1033
+ * `kind="error"` (`var(--destructive-text)`) so the accent follows the
1034
+ * panel's tint instead of staying pinned to one hue inside a re-colored slot
1035
+ * (#24 fix round 1, P0-2) — without this, an illustration whose accent
1036
+ * defaults to the brand hue renders a lime badge on a red error panel. Falls
1037
+ * back to each illustration's own default hue when no ambient override is
1038
+ * set.
1039
+ */
1040
+ declare const ILLUSTRATION_ACCENT_VAR = "--illustration-accent";
1041
+ /**
1042
+ * Build the `style` value for an illustration's accent ink: honors the
1043
+ * ambient `--illustration-accent` override when set, otherwise `fallback`.
1044
+ * `fallback` must be the correct **mark rung** for the accent's hue — e.g.
1045
+ * `var(--primary-text)` (NOT `var(--primary)`, a plate color that measures
1046
+ * 1.42:1 on `--card` in the `light` theme — #24 fix round 1, P0-1; see
1047
+ * `.claude/rules/styling-and-tokens.md` "Which status rung a graphical MARK
1048
+ * reaches for"), `var(--success-text)` for a positive-outcome accent, or
1049
+ * `var(--destructive-text)` for an error accent — the TEXT rung, deliberately
1050
+ * distinct from the FILL rung (`--destructive`) `StatePanel` puts the
1051
+ * SUBJECT on for `kind="error"`, so the two don't collapse onto one colour
1052
+ * (#48 finding 2).
1053
+ */
1054
+ declare function illustrationAccent(fallback: string): string;
1055
+
1056
+ /**
1057
+ * Empty list / zero-data-yet state. Three line-art rows read as "empty list"
1058
+ * on their own silhouette — no accent mark, per the accent-semantics
1059
+ * convention in `illustration-base.tsx` (#48 finding 1): a floating "add"
1060
+ * badge here would repeat information the rows already supply, not add any.
1061
+ */
1062
+ declare const EmptyListIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1063
+
1064
+ /**
1065
+ * Search / filter with zero matches. A line-art magnifying glass with a
1066
+ * `--primary-text` "×" inside the lens standing in for "nothing matched".
1067
+ * The "×" is meaning-bearing (per the accent-semantics convention in
1068
+ * `illustration-base.tsx`, #48 finding 1) — a bare magnifying glass alone
1069
+ * reads as "search", not "no results".
1070
+ */
1071
+ declare const NoResultsIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1072
+
1073
+ /**
1074
+ * Permission / access-denied state. A line-art padlock with a `--primary-text`
1075
+ * keyhole — reads as "restricted", not "broken". The keyhole is meaning-bearing
1076
+ * (per the accent-semantics convention in `illustration-base.tsx`, #48
1077
+ * finding 1) — it's what distinguishes a padlock from a generic rounded box.
1078
+ */
1079
+ declare const NoAccessIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1080
+
1081
+ /**
1082
+ * Recoverable-failure state. A line-art document split into two halves with a
1083
+ * visible gap between them — distinguishable from `NoAccessIllustration`/
1084
+ * `OfflineIllustration` by silhouette alone (a split document reads as
1085
+ * "broken" even in greyscale), per the WCAG 1.4.1 "never color-only" rule.
1086
+ * The exclamation mark IS meaning-bearing (per the accent-semantics
1087
+ * convention in `illustration-base.tsx`, #48 finding 1) — it turns "torn
1088
+ * document" into "warning", information the silhouette alone doesn't carry —
1089
+ * so it stays, in the upper-right quadrant of the right-hand half, clear of
1090
+ * both documents' outlines.
1091
+ *
1092
+ * Redrawn for #24 fix round 1 (P1-3) — the previous cracked-card + tiny alert
1093
+ * triangle read as a lightning bolt or a broken-image placeholder and the
1094
+ * triangle's exclamation collapsed to an illegible blob at 4rem.
1095
+ *
1096
+ * Redrawn again for #48 finding 3 — the mark previously sat at (76-84,
1097
+ * 54-95), exactly where the two document halves' torn edges converge, so it
1098
+ * read as a knot of overlapping lines rather than a "!". Moved to
1099
+ * (98-113, 44-85), 8-15 units clear of the nearest tear line at every
1100
+ * y-coordinate it spans.
1101
+ */
1102
+ declare const ErrorIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1103
+
1104
+ /**
1105
+ * Disconnected / no-network state. A line-art cloud crossed by a slash — the
1106
+ * universal "disabled/no signal" idiom — reads as "offline" on its own
1107
+ * silhouette. No accent mark, per the accent-semantics convention in
1108
+ * `illustration-base.tsx` (#48 finding 1).
1109
+ *
1110
+ * Redrawn for #24 fix round 1 (P1-4) — the previous cloud path's closing curve
1111
+ * left a visible hook/spur, and the dashed tether + falling node read as a
1112
+ * raindrop rather than a severed connection while pulling the ink centre 11.5
1113
+ * units below the shared stage centre.
1114
+ *
1115
+ * Redrawn again for #48 finding 4 — the two small rounded-rect "chain link"
1116
+ * fragments below the slash read as loose debris/dashes rather than a
1117
+ * "broken link" gesture. Removed rather than redrawn: the cloud+slash
1118
+ * silhouette already fully conveys "offline" without them (the same
1119
+ * reasoning that dropped the decorative accents from `EmptyListIllustration`/
1120
+ * `FirstRunIllustration`).
1121
+ */
1122
+ declare const OfflineIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1123
+
1124
+ /**
1125
+ * Completed / positive-outcome state. A line-art ring with a `--success-text`
1126
+ * checkmark — a ring + check needs no rays. The checkmark is meaning-bearing
1127
+ * (per the accent-semantics convention in `illustration-base.tsx`, #48
1128
+ * finding 1) — a bare ring alone carries no state at all.
1129
+ *
1130
+ * Redrawn for #24 fix round 1 (P0-1, P1-4) — the checkmark previously used
1131
+ * `--primary` (re-creating the "success chips read as primary" confusion #334
1132
+ * removed from the tokens) at `strokeWidth={6}` (off the shared accent-weight
1133
+ * rule), and the three radiating ticks straddled the now-removed dashed stage
1134
+ * (two crossed it, one didn't), reading as a clock/sun rather than a
1135
+ * celebration.
1136
+ */
1137
+ declare const SuccessIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1138
+
1139
+ /**
1140
+ * First-run / onboarding state. A line-art planted flag — reads as "start
1141
+ * here" on its own silhouette, distinct from `SuccessIllustration`. No
1142
+ * accent mark, per the accent-semantics convention in `illustration-base.tsx`
1143
+ * (#48 finding 1): a decorative sparkle here would repeat information the
1144
+ * flag already supplies, not add any.
1145
+ */
1146
+ declare const FirstRunIllustration: react.ForwardRefExoticComponent<Omit<IllustrationProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
1147
+
508
1148
  declare const Accordion: react.ForwardRefExoticComponent<(AccordionPrimitive.AccordionSingleProps | AccordionPrimitive.AccordionMultipleProps) & react.RefAttributes<HTMLDivElement>>;
509
1149
  declare const AccordionItem: react.ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionItemProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
510
1150
  declare const AccordionTrigger: react.ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionTriggerProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
@@ -552,7 +1192,7 @@ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttri
552
1192
 
553
1193
  declare const buttonVariants: (props?: ({
554
1194
  variant?: "link" | "default" | "secondary" | "outline" | "destructive" | "outline-subtle" | "ghost" | null | undefined;
555
- size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
1195
+ size?: "default" | "sm" | "icon" | "lg" | "icon-sm" | "icon-lg" | null | undefined;
556
1196
  } & class_variance_authority_types.ClassProp) | undefined) => string;
557
1197
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
558
1198
  /** Render the child element as the button (Radix Slot) instead of a <button>. */
@@ -579,6 +1219,28 @@ declare const SidebarProvider: react.ForwardRefExoticComponent<Omit<react.ClassA
579
1219
  defaultOpen?: boolean;
580
1220
  open?: boolean;
581
1221
  onOpenChange?: (open: boolean) => void;
1222
+ /**
1223
+ * Drives the frame's inset treatment from an ANCESTOR the whole frame can
1224
+ * see — `SidebarInset` (#342 fix) reads it as `data-variant` on this
1225
+ * wrapper via `group-data-[variant=inset]/sidebar-wrapper:`, which reaches
1226
+ * regardless of DOM order (unlike the legacy `peer-*` combinator, which
1227
+ * only matches a Sidebar that comes AFTER). Optional and unset by
1228
+ * default, so an existing caller that only sets `variant` on `Sidebar`
1229
+ * is unaffected.
1230
+ */
1231
+ variant?: "sidebar" | "floating" | "inset";
1232
+ /**
1233
+ * Default `"app"` — today's behaviour, byte-identical. `"nested"` is for
1234
+ * a `SidebarProvider` a compound component (e.g. `ContextRail`, ADR 0035
1235
+ * §4) mounts internally so `useSidebar()` reports ITS OWN state to its
1236
+ * own parts: it still provides `SidebarContext` and the two
1237
+ * `--sidebar-width*` custom properties (which survive `display:
1238
+ * contents`), but renders no frame box, no `data-slot`/`data-variant`/
1239
+ * `data-state`, registers no global `⌘B`/`Ctrl+B` listener, and writes no
1240
+ * `sidebar_state` cookie — so a nested rail can never be mistaken for a
1241
+ * second app frame. See the emission table in ADR 0035 §4.
1242
+ */
1243
+ frame?: "app" | "nested";
582
1244
  }, "ref"> & react.RefAttributes<HTMLDivElement>>;
583
1245
  declare const Sidebar: react.ForwardRefExoticComponent<Omit<react.ClassAttributes<HTMLDivElement> & react.HTMLAttributes<HTMLDivElement> & {
584
1246
  side?: "left" | "right";
@@ -587,7 +1249,41 @@ declare const Sidebar: react.ForwardRefExoticComponent<Omit<react.ClassAttribute
587
1249
  }, "ref"> & react.RefAttributes<HTMLDivElement>>;
588
1250
  declare const SidebarTrigger: react.ForwardRefExoticComponent<Omit<ButtonProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
589
1251
  declare const SidebarRail: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
590
- declare const SidebarInset: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
1252
+ /**
1253
+ * Which sides of the floating "inset" surface get a gutter, once an ancestor
1254
+ * drives the treatment (`SidebarProvider variant="inset"`, or the legacy
1255
+ * immediately-preceding `Sidebar variant="inset"`).
1256
+ *
1257
+ * - `"auto"` (default) — today's rule, unchanged: a gutter on every side
1258
+ * except the leading edge (`m-2 ms-0`, because the classic layout puts the
1259
+ * sidebar there), plus the leading edge's gutter returns (`ms-2`) once that
1260
+ * sidebar collapses and its own gap closes.
1261
+ * - `"none"` — no gutter margin (the unconditional radius/shadow below still
1262
+ * apply).
1263
+ * - An object — pick sides explicitly. `{ start: true, bottom: true }` is the
1264
+ * "flush rail" geometry: a leading + bottom gutter only, no top, no
1265
+ * trailing, because the trailing edge sits flush against a rail — a tab
1266
+ * must touch the page it belongs to.
1267
+ *
1268
+ * PRECEDENCE (fix round 1, #342): a caller composing BOTH mechanisms at once
1269
+ * — `SidebarProvider variant="inset"` AND a LEFT `Sidebar variant="inset"`,
1270
+ * the shape a left-hand shell (e.g. the sidebar-02 rebuild) uses — never hits
1271
+ * a class-order race, because the ancestor-scoped and legacy peer-scoped
1272
+ * margin classes are BOTH derived from this same `gutter` value, so whenever
1273
+ * both selectors match they emit identical declarations instead of competing
1274
+ * ones; the resolved geometry is always exactly what `gutter` says, decided
1275
+ * by this prop, never by the generated stylesheet's rule order.
1276
+ */
1277
+ type SidebarInsetGutter = "auto" | "none" | {
1278
+ top?: boolean;
1279
+ bottom?: boolean;
1280
+ start?: boolean;
1281
+ end?: boolean;
1282
+ };
1283
+ interface SidebarInsetProps extends ComponentProps<"main"> {
1284
+ gutter?: SidebarInsetGutter;
1285
+ }
1286
+ declare const SidebarInset: react.ForwardRefExoticComponent<Omit<SidebarInsetProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
591
1287
  declare const SidebarInput: react.ForwardRefExoticComponent<Omit<InputProps & react.RefAttributes<HTMLInputElement>, "ref"> & react.RefAttributes<HTMLInputElement>>;
592
1288
  declare const SidebarHeader: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
593
1289
  declare const SidebarFooter: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
@@ -715,12 +1411,18 @@ interface AppShellProps {
715
1411
  className?: string;
716
1412
  /** Class for the scrolling main content region. */
717
1413
  mainClassName?: string;
1414
+ /**
1415
+ * The `<main>` region's id, and the skip link's target. Override it when a
1416
+ * page mounts more than one shell — two elements sharing `main-content`
1417
+ * would make the skip link ambiguous. @default "main-content"
1418
+ */
1419
+ mainId?: string;
718
1420
  }
719
1421
  /**
720
1422
  * App-first layout: fixed-height viewport with an optional sidebar, a top bar,
721
1423
  * and a scrollable main region. Pure layout — bring your own nav components.
722
1424
  */
723
- declare function AppShell({ sidebar, topNav, children, className, mainClassName }: AppShellProps): react.JSX.Element;
1425
+ declare function AppShell({ sidebar, topNav, children, className, mainClassName, mainId, }: AppShellProps): react.JSX.Element;
724
1426
 
725
1427
  declare const AspectRatio: react.ForwardRefExoticComponent<AspectRatioPrimitive.AspectRatioProps & react.RefAttributes<HTMLDivElement>>;
726
1428
 
@@ -1097,6 +1799,13 @@ interface ChangeHunk {
1097
1799
  status?: ChangeHunkStatus;
1098
1800
  /** Per-hunk provenance override (overrides the review-level provenance). */
1099
1801
  provenance?: ChangeProvenance;
1802
+ /**
1803
+ * Verification results for this hunk (lint / types / tests / policy hooks).
1804
+ * Purely informational — a failing check never blocks approval, it only
1805
+ * informs the reviewer's decision. Grouped into "Before" / "After" sections
1806
+ * when both phases are present.
1807
+ */
1808
+ checks?: CheckResult[];
1100
1809
  }
1101
1810
  /** State surface exposed by the ChangeReview context. */
1102
1811
  interface ChangeReviewState {
@@ -1192,7 +1901,7 @@ interface ChangeReviewHunkProps extends Omit<HTMLAttributes<HTMLLIElement>, "chi
1192
1901
  * Approval state is signalled with TWO non-color cues:
1193
1902
  * - icon: Check (approved) vs plain toggle (pending)
1194
1903
  * - label: "Approved" badge vs "Approve" button text
1195
- * This ensures the state is clear in all three themes including the low-chroma
1904
+ * This ensures the state is clear in every theme including the low-chroma
1196
1905
  * monochrome surfaces (colorblind-safe).
1197
1906
  */
1198
1907
  declare const ChangeReviewHunk: react.ForwardRefExoticComponent<ChangeReviewHunkProps & react.RefAttributes<HTMLLIElement>>;
@@ -1569,10 +2278,29 @@ declare const Command: react.ForwardRefExoticComponent<CommandProps & react.RefA
1569
2278
  * external input above the tree).
1570
2279
  */
1571
2280
  declare function useCommandActiveItemId(): string | undefined;
1572
- declare function CommandDialog({ children, filter, ...props }: ComponentPropsWithoutRef<typeof Dialog> & {
2281
+ type CommandDialogProps = ComponentPropsWithoutRef<typeof Dialog> & {
1573
2282
  /** Custom cmdk ranking (e.g. strict substring instead of fuzzy). */
1574
2283
  filter?: ComponentPropsWithoutRef<typeof Command$1>["filter"];
1575
- }): react.JSX.Element;
2284
+ /**
2285
+ * The dialog's accessible name, rendered `sr-only`.
2286
+ *
2287
+ * OPTIONAL, and deliberately so: callers that already render their own
2288
+ * `DialogTitle` in `children` must not be forced to move it, and
2289
+ * `@elabs-ai/components-ai`'s `VoiceSelectorDialog` passes this whole prop
2290
+ * type straight through. Supply it when you have no visible title — a
2291
+ * `Dialog` with no accessible name is a Radix warning and an axe violation.
2292
+ */
2293
+ title?: ReactNode;
2294
+ };
2295
+ /**
2296
+ * A ⌘K command palette in a modal `Dialog`.
2297
+ *
2298
+ * This IS the palette presentation of `Command` — there is no separate
2299
+ * "selector" component. For an inline pill that opens the same grouped,
2300
+ * searchable list anchored under itself (a composer footer), reach for
2301
+ * `ModelPicker` instead.
2302
+ */
2303
+ declare function CommandDialog({ children, filter, title, ...props }: CommandDialogProps): react.JSX.Element;
1576
2304
  declare const CommandInput: react.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<react.DetailedHTMLProps<react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof react.InputHTMLAttributes<HTMLInputElement>> & {
1577
2305
  ref?: React.Ref<HTMLInputElement>;
1578
2306
  } & {
@@ -1630,6 +2358,31 @@ declare const CommandItem: react.ForwardRefExoticComponent<Omit<{
1630
2358
  } & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
1631
2359
  declare function CommandShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>): react.JSX.Element;
1632
2360
 
2361
+ interface CommandTriggerProps extends ComponentProps<"button"> {
2362
+ /** The visible and announced label. Defaults to "Search". */
2363
+ label?: string;
2364
+ /** The shortcut hint. Defaults to the platform-correct ⌘ K / Ctrl K. */
2365
+ shortcut?: string;
2366
+ }
2367
+ /**
2368
+ * The command-palette opener, shaped like a search field: label left, shortcut
2369
+ * pinned right, collapsing to the icon alone under `sm`.
2370
+ *
2371
+ * The button’s accessible name comes entirely from `aria-label` — that is what
2372
+ * stops the `Kbd`’s shortcut glyph from concatenating into it (#117); a
2373
+ * non-empty `aria-label` short-circuits accessible-name computation before the
2374
+ * DOM is ever consulted. The visible label and the `Kbd` are ALSO marked
2375
+ * `aria-hidden`, per `accessibility.md`, as defence in depth: if `aria-label`
2376
+ * is ever dropped, that turns a silent regression into a loud one — an empty
2377
+ * accessible name rather than a plausible wrong one. They do not do the work
2378
+ * themselves.
2379
+ *
2380
+ * `shortcut` reads `navigator` at render time when omitted, which can differ
2381
+ * between server and client — a consumer that server-renders this component
2382
+ * should pass `shortcut` explicitly to avoid a hydration mismatch.
2383
+ */
2384
+ declare const CommandTrigger: react.ForwardRefExoticComponent<Omit<CommandTriggerProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
2385
+
1633
2386
  interface ConfirmDialogProps {
1634
2387
  /** Controlled open state — the app owns it. */
1635
2388
  open: boolean;
@@ -1724,6 +2477,77 @@ declare const ContextMenuLabel: react.ForwardRefExoticComponent<Omit<ContextMenu
1724
2477
  declare const ContextMenuSeparator: react.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSeparatorProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
1725
2478
  declare function ContextMenuShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>): react.JSX.Element;
1726
2479
 
2480
+ /** One switchable section of a `ContextRail`. */
2481
+ interface ContextRailSection {
2482
+ /** Stable identifier — the switcher's `SidebarMenuButton` key and the
2483
+ * value reported to `activeSectionId`/`onActiveSectionChange`. */
2484
+ id: string;
2485
+ /** Visible label. Feeds the switcher entry's accessible name and the
2486
+ * body's heading — never rendered as visible text in the switcher
2487
+ * itself, which stays icon-only in every state. */
2488
+ label: string;
2489
+ /** Icon shown in the switcher, in both the expanded and collapsed
2490
+ * (48px icon strip) presentations. Decorative — wrapped `aria-hidden`. */
2491
+ icon: ReactNode;
2492
+ /** Optional count badge. Visible in BOTH states (unlike
2493
+ * `SidebarMenuBadge`, which hides under `collapsible="icon"`) and folded
2494
+ * into the switcher entry's accessible name, e.g. "Sources 3 items". */
2495
+ count?: number;
2496
+ /** Rendered only while this section is active — the rail mounts exactly
2497
+ * one section's content at a time. */
2498
+ content: ReactNode;
2499
+ /** Disables the switcher entry; clicking it is a no-op. */
2500
+ disabled?: boolean;
2501
+ }
2502
+ interface ContextRailProps extends Omit<ComponentProps<"div">, "onSelect" | "children"> {
2503
+ /** The sections the switcher can pick between. An empty array renders
2504
+ * the `empty` slot instead of a switcher. */
2505
+ sections: ContextRailSection[];
2506
+ /** Controlled active section id. */
2507
+ activeSectionId?: string;
2508
+ /** Initial active section id (uncontrolled). Defaults to `sections[0]`. */
2509
+ defaultActiveSectionId?: string;
2510
+ /** Fires with the clicked section's id — including a re-click of the
2511
+ * already-active section (open/close is a separate concern, see `open`). */
2512
+ onActiveSectionChange?: (sectionId: string) => void;
2513
+ /** Controlled expanded/collapsed state. Clicking the ACTIVE switcher
2514
+ * entry toggles this; clicking an INACTIVE entry sets it `true`. */
2515
+ open?: boolean;
2516
+ /** Initial expanded/collapsed state (uncontrolled). Defaults to `true`. */
2517
+ defaultOpen?: boolean;
2518
+ onOpenChange?: (open: boolean) => void;
2519
+ /** Expanded width, published as `--sidebar-width`. @default "20rem" */
2520
+ width?: string;
2521
+ /** Replaces the default localized empty state when `sections` is empty. */
2522
+ empty?: ReactNode;
2523
+ /**
2524
+ * Below this viewport width the rail renders its own 48px strip plus a
2525
+ * `Sheet` for the expanded body instead of mounting `Sidebar` — dev-only
2526
+ * warns if set below 768. @default 768
2527
+ */
2528
+ overlayBreakpoint?: number;
2529
+ }
2530
+ /**
2531
+ * A right-hand rail whose collapsed state is a 48px icon strip that doubles
2532
+ * as its own section switcher. Built on `Sidebar`/`SidebarProvider`
2533
+ * (`frame="nested"`, ADR 0035 §4) as an implementation detail — the public
2534
+ * seam is `sections` + `activeSectionId`/`onActiveSectionChange` (which
2535
+ * section) and `open`/`onOpenChange` (expanded or collapsed), both
2536
+ * controlled/uncontrolled. Below `overlayBreakpoint` it renders its own
2537
+ * strip plus a `Sheet` instead of mounting `Sidebar`. See
2538
+ * `docs/ADR/0035-context-rail-and-side-dock.md` §3.
2539
+ *
2540
+ * Known constraint (task-11f-brief.md Finding 5): below `overlayBreakpoint`
2541
+ * the expanded body is a `Sheet`, which always spans the full browser
2542
+ * viewport, while the persistent 48px strip is bounded by whatever container
2543
+ * the host gives the rail. In a host container shorter than the viewport
2544
+ * (any app shell with a toolbar above the rail), the strip stops mid-screen
2545
+ * while the sheet keeps going — the two read as unrelated surfaces. Give
2546
+ * `ContextRail` a full-viewport-height host container below the breakpoint
2547
+ * to avoid this seam.
2548
+ */
2549
+ declare const ContextRail: react.ForwardRefExoticComponent<Omit<ContextRailProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
2550
+
1727
2551
  interface CopyableValueProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "value" | "children"> {
1728
2552
  /**
1729
2553
  * The EXACT text written to the clipboard — the unrounded, un-abbreviated
@@ -1849,7 +2673,12 @@ declare function DropdownMenuShortcut({ className, ...props }: React.HTMLAttribu
1849
2673
  interface EmptyStateProps {
1850
2674
  title: ReactNode;
1851
2675
  description?: ReactNode;
1852
- /** Optional icon/illustration shown above the title. */
2676
+ /**
2677
+ * Optional icon shown above the title, clamped to a fixed 40×40 (this
2678
+ * wrapper only ever forwards `icon` to `StatePanel`, never `illustration`
2679
+ * — for a larger, unclamped illustration use
2680
+ * `StatePanel kind="empty" illustration={...}` directly).
2681
+ */
1853
2682
  icon?: ReactNode;
1854
2683
  /** Primary/secondary actions. */
1855
2684
  actions?: ReactNode;
@@ -1981,14 +2810,129 @@ interface ExpandDialogProps extends Omit<ExpandDialogContentProps, "title" | "ch
1981
2810
  */
1982
2811
  declare const ExpandDialog: react.ForwardRefExoticComponent<ExpandDialogProps & react.RefAttributes<HTMLDivElement>>;
1983
2812
 
2813
+ interface FieldRootProps extends HTMLAttributes<HTMLDivElement> {
2814
+ /**
2815
+ * Whether the field is currently invalid. Drives `aria-invalid` on every
2816
+ * `FieldControl` and error styling on `FieldLabel` — independent of
2817
+ * whether a `FieldError` with content is actually mounted, so a caller can
2818
+ * mark the control invalid before its message has settled.
2819
+ */
2820
+ invalid?: boolean;
2821
+ /** Whether the field is required. Drives `aria-required` on every `FieldControl`. */
2822
+ required?: boolean;
2823
+ }
2824
+ /**
2825
+ * Compound-anatomy field: `FieldRoot` owns id generation and `aria-describedby`
2826
+ * composition; `FieldLabel`/`FieldControl`/`FieldDescription`/`FieldError` read
2827
+ * that state from context and can be composed in ANY order/layout — including
2828
+ * more than one `FieldControl` in one row (e.g. first/last name) or a
2829
+ * `FieldDescription` placed before the control. Mirrors the same accessibility
2830
+ * wiring `FieldRow` (`../field-row`) already validated (id/`aria-describedby`/
2831
+ * `aria-invalid`/`role="alert"`), adapted to a shared lifted-state context so
2832
+ * it holds across independently-composed parts; `FieldRow` remains the
2833
+ * convenience wrapper for the common single-control case and is unaffected by
2834
+ * this addition (#43).
2835
+ *
2836
+ * @example
2837
+ * ```tsx
2838
+ * <FieldRoot invalid={!!error} required>
2839
+ * <FieldLabel>{label}</FieldLabel>
2840
+ * <FieldControl><Input /></FieldControl>
2841
+ * <FieldDescription>{helpText}</FieldDescription>
2842
+ * <FieldError>{error}</FieldError>
2843
+ * </FieldRoot>
2844
+ * ```
2845
+ */
2846
+ declare const FieldRoot: react.ForwardRefExoticComponent<FieldRootProps & react.RefAttributes<HTMLDivElement>>;
2847
+ declare const FieldLabel: react.ForwardRefExoticComponent<Omit<Omit<_radix_ui_react_label.LabelProps & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>>;
2848
+ interface FieldControlProps {
2849
+ /**
2850
+ * The single field control (`Input`, `Textarea`, `Select`, …). Receives
2851
+ * `id`/`aria-describedby`/`aria-invalid`/`aria-required` via a Radix
2852
+ * `Slot` — must be a single element that forwards those props to a real
2853
+ * form control. Compose more than one `FieldControl` inside one
2854
+ * `FieldRoot` for a multi-control row (each gets its own independent id;
2855
+ * give every control but the first its own explicit `id`, the same way
2856
+ * you would for any two form controls that must not collide). `FieldLabel`
2857
+ * can only associate with ONE control (the first to mount), so give every
2858
+ * OTHER control in the row its own `aria-label` — a shared visual label
2859
+ * plus a placeholder is not a real accessible name for the rest.
2860
+ */
2861
+ children: ReactElement<{
2862
+ id?: string;
2863
+ "aria-describedby"?: string;
2864
+ }>;
2865
+ }
2866
+ declare const FieldControl: react.ForwardRefExoticComponent<FieldControlProps & react.RefAttributes<HTMLElement>>;
2867
+ /**
2868
+ * Optional field help text. Renders nothing — and registers no
2869
+ * `aria-describedby` reference — when `children` is falsy (`false`/`0`/`""`/
2870
+ * `null`/`undefined`), an empty array, or an array containing only falsy
2871
+ * values (`{list.map(...)}` on an empty list; `[a && "x", b && "y"]` with
2872
+ * both false) — matching `FieldRow`'s `description ? … : null` convention:
2873
+ * `{hint && <FieldDescription>{hint}</FieldDescription>}` is the supported
2874
+ * way to express "no description".
2875
+ *
2876
+ * **Known limit:** a child that is itself a COMPONENT that renders nothing
2877
+ * (returns `null`/an empty fragment) is not knowable from the element
2878
+ * before render, so it still produces an empty paragraph that
2879
+ * `aria-describedby` points at. `FieldRow` and the wider React ecosystem
2880
+ * share this limit — pass a falsy child instead of a component that may
2881
+ * render nothing.
2882
+ */
2883
+ declare const FieldDescription: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
2884
+ /**
2885
+ * Validation error text, announced via `role="alert"`. Renders nothing —
2886
+ * and registers no `aria-describedby` reference — when `children` is falsy
2887
+ * (`false`/`0`/`""`/`null`/`undefined`), an empty array, or an array
2888
+ * containing only falsy values (`{errors.map(...)}` on an empty array is
2889
+ * exactly how a real form renders "no errors") — matching `FieldRow`'s
2890
+ * `error ? … : null` convention: `{error && <FieldError>{error}</FieldError>}`
2891
+ * is the supported way to express "no error".
2892
+ *
2893
+ * **Known limit:** a child that is itself a COMPONENT that renders nothing
2894
+ * (returns `null`/an empty fragment) is not knowable from the element
2895
+ * before render, so it still produces an empty `role="alert"` element that
2896
+ * `aria-describedby` points at (a screen reader announces an empty alert).
2897
+ * `FieldRow` and the wider React ecosystem share this limit — pass a falsy
2898
+ * child instead of a component that may render nothing.
2899
+ */
2900
+ declare const FieldError: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
2901
+
1984
2902
  interface FieldRowProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
1985
2903
  /** Field label — rendered as a real `<label>`, click-to-focus associated with the control. */
1986
2904
  label: ReactNode;
1987
- /** Optional help/description text, always visible (not gated by an error). */
2905
+ /**
2906
+ * Optional help/description text, always visible (not gated by an error).
2907
+ * Renders nothing — and contributes no id to `aria-describedby` — when
2908
+ * `description` is falsy (`false`/`0`/`""`/`null`/`undefined`), an empty
2909
+ * array, or an array containing only falsy values (`{list.map(...)}` on an
2910
+ * empty list; `[a && "x", b && "y"]` with both false).
2911
+ *
2912
+ * **Known limit:** a value that is itself a COMPONENT that renders nothing
2913
+ * (returns `null`/an empty fragment) is not knowable before render, so it
2914
+ * still produces an empty paragraph that `aria-describedby` points at.
2915
+ * `FieldDescription` and the wider React ecosystem share this limit — pass
2916
+ * a falsy value instead of a component that may render nothing, e.g.
2917
+ * `description={hasHint ? hintText : undefined}`, never
2918
+ * `description={<MaybeRendersNull />}`.
2919
+ */
1988
2920
  description?: ReactNode;
1989
2921
  /**
1990
2922
  * Validation error text. When present: sets `aria-invalid` on the control,
1991
2923
  * is appended to `aria-describedby`, and is announced via `role="alert"`.
2924
+ * Renders nothing — and leaves `aria-invalid="false"` — when `error` is
2925
+ * falsy (`false`/`0`/`""`/`null`/`undefined`), an empty array, or an array
2926
+ * containing only falsy values (`{errors.map(...)}` on an empty list — the
2927
+ * idiomatic "no errors" shape).
2928
+ *
2929
+ * **Known limit:** a value that is itself a COMPONENT that renders nothing
2930
+ * (returns `null`/an empty fragment) is not knowable before render, so it
2931
+ * still produces an empty `role="alert"` element that `aria-describedby`
2932
+ * points at. `FieldError` and the wider React ecosystem share this limit —
2933
+ * pass a falsy value instead of a component that may render nothing, e.g.
2934
+ * `error={hasError ? message : undefined}`, never
2935
+ * `error={<MaybeRendersNull />}`.
1992
2936
  */
1993
2937
  error?: ReactNode;
1994
2938
  /**
@@ -2104,26 +3048,6 @@ interface FileUploadItemProps extends HTMLAttributes<HTMLLIElement> {
2104
3048
  */
2105
3049
  declare const FileUploadItem: react.ForwardRefExoticComponent<FileUploadItemProps & react.RefAttributes<HTMLLIElement>>;
2106
3050
 
2107
- declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, }: react_hook_form.FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
2108
- declare function FormField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: ControllerProps<TFieldValues, TName>): react.JSX.Element;
2109
- declare function useFormField(): {
2110
- invalid: boolean;
2111
- isDirty: boolean;
2112
- isTouched: boolean;
2113
- isValidating: boolean;
2114
- error?: react_hook_form.FieldError;
2115
- id: string;
2116
- name: string;
2117
- formItemId: string;
2118
- formDescriptionId: string;
2119
- formMessageId: string;
2120
- };
2121
- declare const FormItem: react.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
2122
- declare const FormLabel: react.ForwardRefExoticComponent<Omit<Omit<_radix_ui_react_label.LabelProps & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>>;
2123
- declare const FormControl: react.ForwardRefExoticComponent<Omit<_radix_ui_react_slot.SlotProps & react.RefAttributes<HTMLElement>, "ref"> & react.RefAttributes<HTMLElement>>;
2124
- declare const FormDescription: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
2125
- declare const FormMessage: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
2126
-
2127
3051
  declare const HoverCard: react.FC<HoverCardPrimitive.HoverCardProps>;
2128
3052
  declare const HoverCardTrigger: react.ForwardRefExoticComponent<HoverCardPrimitive.HoverCardTriggerProps & react.RefAttributes<HTMLAnchorElement>>;
2129
3053
  declare const HoverCardContent: react.ForwardRefExoticComponent<Omit<HoverCardPrimitive.HoverCardContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
@@ -2200,6 +3124,43 @@ declare const InputOTPSeparator: react.ForwardRefExoticComponent<react.HTMLAttri
2200
3124
  /** Keyboard key hint, e.g. <Kbd>⌘K</Kbd>. */
2201
3125
  declare const Kbd: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & react.RefAttributes<HTMLElement>>;
2202
3126
 
3127
+ /** One keyboard shortcut: the action it performs and its ordered key tokens. */
3128
+ interface Shortcut {
3129
+ action: string;
3130
+ /** Ordered key tokens, e.g. `["⌘", "K"]`. Rendered via {@link Kbd}. */
3131
+ keys: string[];
3132
+ }
3133
+ /**
3134
+ * A named group of shortcuts. There is deliberately no `count` field — the
3135
+ * displayed count is always derived from `items.length`, never supplied by
3136
+ * the caller (see issue #113: brainless, the upstream this was adapted from,
3137
+ * shipped a `count` with no `items`, an honestly-unverifiable number).
3138
+ */
3139
+ interface ShortcutGroup {
3140
+ id: string;
3141
+ label: string;
3142
+ items: Shortcut[];
3143
+ /** Whether this group starts expanded when search is inactive. @default false */
3144
+ defaultOpen?: boolean;
3145
+ }
3146
+ interface KeyboardShortcutsProps extends Omit<ComponentProps<"div">, "onChange"> {
3147
+ groups: ShortcutGroup[];
3148
+ /** Show the built-in search field. @default true */
3149
+ searchable?: boolean;
3150
+ /** Controlled search query, if the app owns it. */
3151
+ query?: string;
3152
+ onQueryChange?: (query: string) => void;
3153
+ }
3154
+ /**
3155
+ * A grouped, searchable presentation of a shortcut set. Renders **content
3156
+ * only** — the app supplies the `Dialog`/`Sheet` shell, so the same
3157
+ * component works in a modal, a settings page or a sidebar.
3158
+ *
3159
+ * Group counts are always derived from `items.length` (or the number of
3160
+ * matching items while a search is active) — never a value passed in.
3161
+ */
3162
+ declare const KeyboardShortcuts: react.ForwardRefExoticComponent<Omit<KeyboardShortcutsProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
3163
+
2203
3164
  interface KeyValueRow {
2204
3165
  key: string;
2205
3166
  value: string;
@@ -2329,12 +3290,44 @@ interface ListEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange
2329
3290
  * keyboard-operable reorder (move-up/move-down buttons, not drag-and-drop —
2330
3291
  * no drag library exists in the monorepo and none should be added for this).
2331
3292
  *
2332
- * Controlled via `value`/`onValueChange`; uncontrolled via `defaultValue`.
3293
+ * Controlled via `value`/`onValueChange`; uncontrolled via `defaultValue`.
3294
+ */
3295
+ declare const ListEditor: react.ForwardRefExoticComponent<ListEditorProps & react.RefAttributes<HTMLDivElement>>;
3296
+
3297
+ /**
3298
+ * ICU cardinal-plural category, per `Intl.PluralRules` ("zero" | "one" | "two"
3299
+ * | "few" | "many" | "other"). Locales vary in which categories they use —
3300
+ * English has only "one"/"other"; Polish and Russian also use "few"/"many" —
3301
+ * so a `PluralMessage` may omit any category it doesn't need. `"other"` is the
3302
+ * universal fallback every locale defines.
3303
+ */
3304
+ type PluralCategory = Intl.LDMLPluralRule;
3305
+ /**
3306
+ * A per-count message: one string per plural category, selected at render
3307
+ * time via `Intl.PluralRules(locale).select(count)`. Each string still
3308
+ * supports the same `{name}`-style interpolation as a plain message.
3309
+ * Note: when passed to `t()`, `count` in `vars` must be a number, not a
3310
+ * numeric string, to select the correct plural category.
3311
+ */
3312
+ type PluralMessage = Partial<Record<PluralCategory, string>>;
3313
+ /** A single message value: a plain string, or a plural-form map. */
3314
+ type MessageValue = string | PluralMessage;
3315
+ /**
3316
+ * Shipped English (en-US) default microcopy bundle.
3317
+ *
3318
+ * Keys are intentionally terse, semantic, and framework-agnostic so they
3319
+ * translate cleanly into any target locale. Keep this list small and real —
3320
+ * only add a key here when a component actually needs it.
2333
3321
  */
2334
- declare const ListEditor: react.ForwardRefExoticComponent<ListEditorProps & react.RefAttributes<HTMLDivElement>>;
3322
+ declare const DEFAULT_MESSAGES: Record<string, MessageValue>;
2335
3323
 
2336
- /** A flat map of string keys to their translated values. */
2337
- type Messages = Record<string, string>;
3324
+ /**
3325
+ * A flat map of string keys to their translated values — a plain string, or a
3326
+ * `PluralMessage` (one string per ICU cardinal-plural category, e.g.
3327
+ * `{ one: "{count} item", other: "{count} items" }`) for microcopy whose
3328
+ * wording changes with a count. See `PluralMessage` in `./messages`.
3329
+ */
3330
+ type Messages = Record<string, MessageValue>;
2338
3331
  interface LocaleContextValue {
2339
3332
  /** BCP-47 locale tag, e.g. "en-US", "ar-EG", "de-DE". */
2340
3333
  locale: string;
@@ -2342,8 +3335,13 @@ interface LocaleContextValue {
2342
3335
  dir: "ltr" | "rtl";
2343
3336
  /**
2344
3337
  * Translate a key.
2345
- * Falls back to: consumer messages English default the key itself.
2346
- * Supports simple `{name}`-style variable interpolation.
3338
+ * Falls back to: an external `translate` resolver (if the provider was
3339
+ * given one) → consumer `messages` English default → the key itself.
3340
+ * Supports simple `{name}`-style variable interpolation, and ICU
3341
+ * cardinal-plural forms (`Intl.PluralRules`) when the resolved message is a
3342
+ * `PluralMessage` map and `vars.count` is a number. Note: `count` must be a
3343
+ * number, not a numeric string (e.g., `count: 3`, not `count: "3"`) to select
3344
+ * the correct plural category.
2347
3345
  */
2348
3346
  t: (key: string, vars?: Record<string, string | number>) => string;
2349
3347
  /** Format a number using the active locale. Memoized per locale+opts hash. */
@@ -2368,6 +3366,21 @@ interface LocaleProviderProps {
2368
3366
  * to the English bundle.
2369
3367
  */
2370
3368
  messages?: Messages;
3369
+ /**
3370
+ * Optional external resolver — hand brand-ui's microcopy off to an app's own
3371
+ * i18n runtime (next-intl, react-intl, i18next, …) instead of maintaining a
3372
+ * second, flattened message catalogue. Called with the raw key and vars
3373
+ * (not pre-interpolated), so a real ICU formatter gets real values and can
3374
+ * do its own pluralization/number/date formatting.
3375
+ *
3376
+ * Return a string to use it as-is (brand-ui does NOT re-run its own
3377
+ * `{name}` interpolation on it — the app's runtime already formatted it).
3378
+ * Return `undefined`/`null` to decline a key; brand-ui then falls back to
3379
+ * `messages` → `DEFAULT_MESSAGES` → the raw key, in that order — so a
3380
+ * resolver only needs to cover the keys it actually wants to override.
3381
+ * See `docs/I18N.md`.
3382
+ */
3383
+ translate?: (key: string, vars?: Record<string, string | number>) => string | undefined | null;
2371
3384
  children: ReactNode;
2372
3385
  }
2373
3386
  /**
@@ -2382,7 +3395,7 @@ interface LocaleProviderProps {
2382
3395
  * every Radix primitive reads via context regardless of DOM position (ADR-0014).
2383
3396
  * The `<div dir={dir}>` continues to carry direction for non-Radix content.
2384
3397
  */
2385
- declare function LocaleProvider({ locale, dir, messages, children, }: LocaleProviderProps): react.JSX.Element;
3398
+ declare function LocaleProvider({ locale, dir, messages, translate, children, }: LocaleProviderProps): react.JSX.Element;
2386
3399
  /**
2387
3400
  * Read the active locale, direction, `t`, `formatNumber`, and `formatDate`.
2388
3401
  *
@@ -2392,15 +3405,6 @@ declare function LocaleProvider({ locale, dir, messages, children, }: LocaleProv
2392
3405
  */
2393
3406
  declare function useLocale(): LocaleContextValue;
2394
3407
 
2395
- /**
2396
- * Shipped English (en-US) default microcopy bundle.
2397
- *
2398
- * Keys are intentionally terse, semantic, and framework-agnostic so they
2399
- * translate cleanly into any target locale. Keep this list small and real —
2400
- * only add a key here when a component actually needs it.
2401
- */
2402
- declare const DEFAULT_MESSAGES: Record<string, string>;
2403
-
2404
3408
  interface LoadingStateProps {
2405
3409
  /** Accessible status label. Defaults to "Loading…". */
2406
3410
  label?: ReactNode;
@@ -2806,14 +3810,22 @@ interface ModelPickerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelec
2806
3810
  open?: boolean;
2807
3811
  /** Fires whenever the popover would open/close — a trigger click, or a row select. */
2808
3812
  onOpenChange?: (open: boolean) => void;
3813
+ /**
3814
+ * Rendered inside the popover BELOW the list — a persistent action row that is
3815
+ * not one of the options (a free-text entry, a "browse…" affordance).
3816
+ * Outside `CommandList` on purpose: it must not be filtered by the search query
3817
+ * and must not participate in cmdk's roving selection.
3818
+ */
3819
+ footer?: ReactNode;
2809
3820
  }
2810
3821
  /**
2811
3822
  * A compact pill that opens a grouped, searchable target list anchored under
2812
3823
  * itself — sized to sit in a composer footer.
2813
3824
  *
2814
- * The inline sibling of `@elabs-ai/components-ai`'s `ModelSelector`,
2815
- * which is the same `Command` internals in a modal `Dialog`. Reach for that one
2816
- * for a full command palette; reach for this one for an in-place picker.
3825
+ * **Which one to reach for.** An inline pill in a composer footer, anchored
3826
+ * under itself this component. A full ⌘K palette compose `CommandDialog` +
3827
+ * `Command*` from this package directly; there is no separate "selector"
3828
+ * component wrapping them.
2817
3829
  *
2818
3830
  * **`Command` lives inside a `Popover`, never a `DropdownMenu`, and that is not
2819
3831
  * a stylistic choice.** `DropdownMenuContent` owns roving tabindex and its own
@@ -2950,12 +3962,45 @@ interface NavNotificationsProps {
2950
3962
  notifications: NavNotification[];
2951
3963
  /** Label for the "view all" footer item. @default "View all notifications" */
2952
3964
  viewAllLabel?: string;
3965
+ /**
3966
+ * Which side of the trigger the menu opens on.
3967
+ *
3968
+ * The default is `"right"`, which is right for the surface this component was
3969
+ * extracted from — a bell sitting in a left-hand nav rail. It is WRONG for a
3970
+ * trigger at the end of a top bar: Radix collision-handling then flips the
3971
+ * menu back across the trigger and it covers the controls beside it. Set
3972
+ * `side="bottom"` (usually with `align="end"`) for a top-bar bell.
3973
+ *
3974
+ * @default "right"
3975
+ */
3976
+ side?: ComponentProps<typeof DropdownMenuContent>["side"];
3977
+ /**
3978
+ * How the menu aligns along that side. Radix's own default is `"center"`;
3979
+ * pass `"end"` so a top-bar menu hangs from the trigger's outer edge instead
3980
+ * of straddling it.
3981
+ */
3982
+ align?: ComponentProps<typeof DropdownMenuContent>["align"];
3983
+ /**
3984
+ * Extra classes for the component ROOT — the bell trigger — merged last, so a
3985
+ * caller can override the shipped `rounded-full` (`component-api.md`).
3986
+ *
3987
+ * There is deliberately NO seam for the portalled menu surface: nothing needs
3988
+ * one today, and an unused prop is a worse API than a missing one. The one
3989
+ * thing a caller used to reach for it (dropping the rail's vertical inset for
3990
+ * a top-bar menu) is now derived from `side` instead — see below.
3991
+ */
3992
+ className?: string;
2953
3993
  }
2954
3994
  /**
2955
- * Sidebar notifications dropdown button. Shared primitive from sidebar-02 (issue #99).
2956
- * Renders a bell-icon ghost button that opens a dropdown listing recent notifications.
3995
+ * Notifications dropdown button. Shared primitive from sidebar-02 (issue #99).
3996
+ * Renders a bell-icon ghost button that opens a dropdown listing recent
3997
+ * notifications.
3998
+ *
3999
+ * Placement is caller-owned via `side`/`align`; the defaults are the original
4000
+ * rail placement, so every existing call site renders unchanged. `className`
4001
+ * styles the trigger, not the menu.
2957
4002
  */
2958
- declare function NavNotifications({ notifications, viewAllLabel, }: NavNotificationsProps): react.JSX.Element;
4003
+ declare function NavNotifications({ notifications, viewAllLabel, side, align, className, }: NavNotificationsProps): react.JSX.Element;
2959
4004
 
2960
4005
  interface NavUserUser {
2961
4006
  name: string;
@@ -2978,14 +4023,14 @@ declare function NavUser({ user }: NavUserProps): react.JSX.Element;
2978
4023
 
2979
4024
  declare const NavigationMenu: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuProps & react.RefAttributes<HTMLElement>, "ref"> & react.RefAttributes<HTMLElement>>;
2980
4025
  declare const NavigationMenuList: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuListProps & react.RefAttributes<HTMLUListElement>, "ref"> & react.RefAttributes<HTMLUListElement>>;
2981
- declare const NavigationMenuItem: react.ForwardRefExoticComponent<NavigationMenuPrimitive.NavigationMenuItemProps & react.RefAttributes<HTMLLIElement>>;
4026
+ declare const NavigationMenuItem: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuItemProps & react.RefAttributes<HTMLLIElement>, "ref"> & react.RefAttributes<HTMLLIElement>>;
2982
4027
  declare const navigationMenuTriggerStyle: (props?: class_variance_authority_types.ClassProp | undefined) => string;
2983
4028
  declare const NavigationMenuTrigger: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuTriggerProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
2984
4029
  declare const NavigationMenuContent: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
2985
4030
  declare const NavigationMenuLink: react.ForwardRefExoticComponent<NavigationMenuPrimitive.NavigationMenuLinkProps & react.RefAttributes<HTMLAnchorElement>>;
2986
4031
  declare const NavigationMenuViewport: react.ForwardRefExoticComponent<Omit<NavigationMenuPrimitive.NavigationMenuViewportProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
2987
4032
 
2988
- interface PageShellProps {
4033
+ interface PageShellProps extends ComponentProps<"div"> {
2989
4034
  children: ReactNode;
2990
4035
  /** Optional header row (often a <SectionHeader />, or a <ViewToolbar> — see headerVariant). */
2991
4036
  header?: ReactNode;
@@ -3004,11 +4049,42 @@ interface PageShellProps {
3004
4049
  headerVariant?: "default" | "toolbar";
3005
4050
  /** Constrain content width. Defaults to "xl". */
3006
4051
  width?: "md" | "lg" | "xl" | "full";
4052
+ /**
4053
+ * "body" (default) — the page scrolls with the document. Byte-identical to
4054
+ * the pre-#R6 behaviour; existing callers are unaffected.
4055
+ * "content" — this container is the scroll port. Use inside a `SidebarInset`
4056
+ * whose height is already bounded, so the top bar stays put. Defaults its own
4057
+ * `tabIndex` to `0` (a scroll container must be keyboard-operable — WCAG
4058
+ * 2.1.1, axe `scrollable-region-focusable`), following the `DialogBody`
4059
+ * precedent; pass `tabIndex={-1}` to opt out when the content already
4060
+ * supplies its own focusable child.
4061
+ * "fill" — fills its parent and scrolls nothing itself; a child (a table, a
4062
+ * canvas) owns the scrolling — and owns that child's keyboard reachability
4063
+ * too, the same way.
4064
+ */
4065
+ scroll?: "body" | "content" | "fill";
4066
+ /**
4067
+ * Reserve a fixed header row so a page title lands at identical coordinates
4068
+ * on every route, whether or not that route has a header. Default `false`.
4069
+ *
4070
+ * The row's height is a component-local CSS variable —
4071
+ * `--page-shell-header-gutter`, declared on the root, default `--spacing(12)`
4072
+ * (3rem / 48px at a 16px root — the height a one-line title already occupies
4073
+ * inside the `headerVariant="toolbar"` bar's own `py-3`). It is NOT a theme
4074
+ * token (`pnpm theme-parity:check` does not see it); retune it per surface the
4075
+ * same way `--focus-ring-color` is retargeted elsewhere in this package:
4076
+ * `<PageShell headerGutter className="[--page-shell-header-gutter:--spacing(16)]" />`.
4077
+ *
4078
+ * When `true` the header row renders **even if `header` is omitted** — that
4079
+ * empty row is the whole mechanism, and it is what `headerGutter={false}`
4080
+ * must never produce.
4081
+ */
4082
+ headerGutter?: boolean;
3007
4083
  className?: string;
3008
4084
  contentClassName?: string;
3009
4085
  }
3010
4086
  /** Page-level content container with consistent padding and max width. */
3011
- declare function PageShell({ children, header, headerVariant, width, className, contentClassName, }: PageShellProps): react.JSX.Element;
4087
+ declare const PageShell: react.ForwardRefExoticComponent<Omit<PageShellProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
3012
4088
 
3013
4089
  declare function Pagination({ className, ...props }: ComponentProps<"nav">): react.JSX.Element;
3014
4090
  declare const PaginationContent: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "ref"> & react.RefAttributes<HTMLUListElement>>;
@@ -3074,7 +4150,7 @@ interface RatingProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" |
3074
4150
  declare const Rating: react.ForwardRefExoticComponent<RatingProps & react.RefAttributes<HTMLDivElement>>;
3075
4151
 
3076
4152
  declare function ResizablePanelGroup({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>): react.JSX.Element;
3077
- declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<react.HTMLAttributes<HTMLAnchorElement | HTMLElement | HTMLDivElement | HTMLObjectElement | HTMLTitleElement | HTMLBodyElement | HTMLMetaElement | HTMLParagraphElement | HTMLSelectElement | HTMLLinkElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | HTMLQuoteElement | HTMLBRElement | HTMLButtonElement | HTMLCanvasElement | HTMLTableColElement | HTMLDataElement | HTMLDataListElement | HTMLModElement | HTMLDetailsElement | HTMLDialogElement | HTMLDListElement | HTMLEmbedElement | HTMLFieldSetElement | HTMLFormElement | HTMLHeadingElement | HTMLHeadElement | HTMLHRElement | HTMLHtmlElement | HTMLIFrameElement | HTMLImageElement | HTMLInputElement | HTMLLabelElement | HTMLLegendElement | HTMLLIElement | HTMLMapElement | HTMLMeterElement | HTMLOListElement | HTMLOptGroupElement | HTMLOptionElement | HTMLOutputElement | HTMLPreElement | HTMLProgressElement | HTMLScriptElement | HTMLSlotElement | HTMLSourceElement | HTMLSpanElement | HTMLStyleElement | HTMLTableElement | HTMLTableSectionElement | HTMLTableCellElement | HTMLTemplateElement | HTMLTextAreaElement | HTMLTimeElement | HTMLTableRowElement | HTMLTrackElement | HTMLUListElement | HTMLVideoElement | HTMLTableCaptionElement | HTMLMenuElement | HTMLPictureElement>, "id" | "onResize"> & {
4153
+ declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<react.HTMLAttributes<HTMLAnchorElement | HTMLElement | HTMLDivElement | HTMLSpanElement | HTMLObjectElement | HTMLTitleElement | HTMLBodyElement | HTMLMetaElement | HTMLParagraphElement | HTMLSelectElement | HTMLLinkElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | HTMLQuoteElement | HTMLBRElement | HTMLButtonElement | HTMLCanvasElement | HTMLTableColElement | HTMLDataElement | HTMLDataListElement | HTMLModElement | HTMLDetailsElement | HTMLDialogElement | HTMLDListElement | HTMLEmbedElement | HTMLFieldSetElement | HTMLFormElement | HTMLHeadingElement | HTMLHeadElement | HTMLHRElement | HTMLHtmlElement | HTMLIFrameElement | HTMLImageElement | HTMLInputElement | HTMLLabelElement | HTMLLegendElement | HTMLLIElement | HTMLMapElement | HTMLMeterElement | HTMLOListElement | HTMLOptGroupElement | HTMLOptionElement | HTMLOutputElement | HTMLPreElement | HTMLProgressElement | HTMLScriptElement | HTMLSlotElement | HTMLSourceElement | HTMLStyleElement | HTMLTableElement | HTMLTableSectionElement | HTMLTableCellElement | HTMLTemplateElement | HTMLTextAreaElement | HTMLTimeElement | HTMLTableRowElement | HTMLTrackElement | HTMLUListElement | HTMLVideoElement | HTMLTableCaptionElement | HTMLMenuElement | HTMLPictureElement>, "id" | "onResize"> & {
3078
4154
  className?: string | undefined;
3079
4155
  collapsedSize?: number | undefined;
3080
4156
  collapsible?: boolean | undefined;
@@ -3127,6 +4203,1112 @@ interface RevealGroupProps extends HTMLAttributes<HTMLDivElement>, VariantProps<
3127
4203
  */
3128
4204
  declare const RevealGroup: react.ForwardRefExoticComponent<RevealGroupProps & react.RefAttributes<HTMLDivElement>>;
3129
4205
 
4206
+ /**
4207
+ * schema-form-spec.ts — Serializable FormSpec for SchemaForm.
4208
+ *
4209
+ * SchemaForm is the GENERAL, app-UI spec-driven form renderer (issue #22):
4210
+ * describe a configuration form as data, render it. It is the sibling of
4211
+ * `@elabs-ai/components-ai`'s `MessageForm` / `fieldSpecSchema` — NOT a
4212
+ * generalization of it. The two are deliberately separate schemas because
4213
+ * they carry different trust models:
4214
+ *
4215
+ * - `MessageForm`'s `fieldSpecSchema` (`packages/ai/src/message-form-spec.ts`)
4216
+ * is what an LLM tool-call emits inside a chat message. Its vocabulary is
4217
+ * intentionally the SAFE subset — flat scalars only, no file input, no
4218
+ * password/credential format — so a model can never ask a user to hand it
4219
+ * a file or a secret through a chat-rendered form.
4220
+ * - `SchemaForm`'s `fieldSpecSchema` here is DEVELOPER-AUTHORED: a product
4221
+ * describes an integration/config form (connector settings, environment
4222
+ * variables, auth method) as data instead of hand-writing it. That is a
4223
+ * fundamentally different trust boundary, so it is allowed the fuller
4224
+ * vocabulary Onyx-style connector forms need: `list`, `key-value`, `file`,
4225
+ * and grouped alternative field sets (`group`, tabs or advanced-collapsed).
4226
+ *
4227
+ * Shares its overall shape (fields/values/validate/normalize) with
4228
+ * `message-form-spec.ts` by convention, not by import — merging them into one
4229
+ * union would either smuggle `file`/`group` into the chat-safe schema or
4230
+ * strip the safety comment from this one. See the issue-#22 result file for
4231
+ * the full reasoning.
4232
+ */
4233
+
4234
+ /** A single enum choice: a plain value, or a `{ const, title }` pair. */
4235
+ declare const enumOptionSchema: z.ZodUnion<[z.ZodString, z.ZodObject<{
4236
+ const: z.ZodString;
4237
+ title: z.ZodOptional<z.ZodString>;
4238
+ }, "strip", z.ZodTypeAny, {
4239
+ const: string;
4240
+ title?: string | undefined;
4241
+ }, {
4242
+ const: string;
4243
+ title?: string | undefined;
4244
+ }>]>;
4245
+ type EnumOption = z.infer<typeof enumOptionSchema>;
4246
+ /** The submitted value of an enum option. */
4247
+ declare function optionValue(option: EnumOption): string;
4248
+ /** The display label of an enum option (falls back to its value). */
4249
+ declare function optionLabel(option: EnumOption): string;
4250
+ declare const keyValueRowSchema: z.ZodObject<{
4251
+ key: z.ZodString;
4252
+ value: z.ZodString;
4253
+ /** Mask this row's value (rendered as `type="password"` with a reveal toggle). */
4254
+ secret: z.ZodOptional<z.ZodBoolean>;
4255
+ }, "strip", z.ZodTypeAny, {
4256
+ key: string;
4257
+ value: string;
4258
+ secret?: boolean | undefined;
4259
+ }, {
4260
+ key: string;
4261
+ value: string;
4262
+ secret?: boolean | undefined;
4263
+ }>;
4264
+ type FieldKeyValueRow = z.infer<typeof keyValueRowSchema>;
4265
+ /** A single-line or multi-line text field. */
4266
+ declare const stringFieldSchema: z.ZodObject<{
4267
+ default: z.ZodOptional<z.ZodString>;
4268
+ format: z.ZodOptional<z.ZodEnum<["email", "uri", "date", "date-time"]>>;
4269
+ minLength: z.ZodOptional<z.ZodNumber>;
4270
+ maxLength: z.ZodOptional<z.ZodNumber>;
4271
+ /** A serialized RegExp source string (client-enforced when present). */
4272
+ pattern: z.ZodOptional<z.ZodString>;
4273
+ /** Render a textarea instead of a single-line input. */
4274
+ multiline: z.ZodOptional<z.ZodBoolean>;
4275
+ /** Value key in the emitted form state (the `values` object key). */
4276
+ name: z.ZodString;
4277
+ /** Human label. Falls back to a humanized `name` when omitted. */
4278
+ label: z.ZodOptional<z.ZodString>;
4279
+ /** Helper text shown under the control. */
4280
+ description: z.ZodOptional<z.ZodString>;
4281
+ /** Whether a value is required before the form can submit. */
4282
+ required: z.ZodOptional<z.ZodBoolean>;
4283
+ /**
4284
+ * Conditional visibility: render (and validate/submit) this field only
4285
+ * when another field's current value equals `equals` — e.g. show a
4286
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4287
+ * by `isFieldVisible` against the form's current values; a hidden field is
4288
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4289
+ * a hidden `required` field never blocks submit.
4290
+ */
4291
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4292
+ /** Name of the controlling field. */
4293
+ field: z.ZodString;
4294
+ /** The controlling field's value that makes this field visible. */
4295
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4296
+ }, "strip", z.ZodTypeAny, {
4297
+ field: string;
4298
+ equals: string | number | boolean;
4299
+ }, {
4300
+ field: string;
4301
+ equals: string | number | boolean;
4302
+ }>>;
4303
+ type: z.ZodLiteral<"string">;
4304
+ }, "strip", z.ZodTypeAny, {
4305
+ name: string;
4306
+ type: "string";
4307
+ label?: string | undefined;
4308
+ default?: string | undefined;
4309
+ format?: "email" | "date" | "uri" | "date-time" | undefined;
4310
+ pattern?: string | undefined;
4311
+ maxLength?: number | undefined;
4312
+ minLength?: number | undefined;
4313
+ required?: boolean | undefined;
4314
+ description?: string | undefined;
4315
+ multiline?: boolean | undefined;
4316
+ visibleWhen?: {
4317
+ field: string;
4318
+ equals: string | number | boolean;
4319
+ } | undefined;
4320
+ }, {
4321
+ name: string;
4322
+ type: "string";
4323
+ label?: string | undefined;
4324
+ default?: string | undefined;
4325
+ format?: "email" | "date" | "uri" | "date-time" | undefined;
4326
+ pattern?: string | undefined;
4327
+ maxLength?: number | undefined;
4328
+ minLength?: number | undefined;
4329
+ required?: boolean | undefined;
4330
+ description?: string | undefined;
4331
+ multiline?: boolean | undefined;
4332
+ visibleWhen?: {
4333
+ field: string;
4334
+ equals: string | number | boolean;
4335
+ } | undefined;
4336
+ }>;
4337
+ type StringFieldSpec = z.infer<typeof stringFieldSchema>;
4338
+ /** A floating-point number field. */
4339
+ declare const numberFieldSchema: z.ZodObject<{
4340
+ default: z.ZodOptional<z.ZodNumber>;
4341
+ min: z.ZodOptional<z.ZodNumber>;
4342
+ max: z.ZodOptional<z.ZodNumber>;
4343
+ /** Value key in the emitted form state (the `values` object key). */
4344
+ name: z.ZodString;
4345
+ /** Human label. Falls back to a humanized `name` when omitted. */
4346
+ label: z.ZodOptional<z.ZodString>;
4347
+ /** Helper text shown under the control. */
4348
+ description: z.ZodOptional<z.ZodString>;
4349
+ /** Whether a value is required before the form can submit. */
4350
+ required: z.ZodOptional<z.ZodBoolean>;
4351
+ /**
4352
+ * Conditional visibility: render (and validate/submit) this field only
4353
+ * when another field's current value equals `equals` — e.g. show a
4354
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4355
+ * by `isFieldVisible` against the form's current values; a hidden field is
4356
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4357
+ * a hidden `required` field never blocks submit.
4358
+ */
4359
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4360
+ /** Name of the controlling field. */
4361
+ field: z.ZodString;
4362
+ /** The controlling field's value that makes this field visible. */
4363
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4364
+ }, "strip", z.ZodTypeAny, {
4365
+ field: string;
4366
+ equals: string | number | boolean;
4367
+ }, {
4368
+ field: string;
4369
+ equals: string | number | boolean;
4370
+ }>>;
4371
+ type: z.ZodLiteral<"number">;
4372
+ }, "strip", z.ZodTypeAny, {
4373
+ name: string;
4374
+ type: "number";
4375
+ label?: string | undefined;
4376
+ default?: number | undefined;
4377
+ max?: number | undefined;
4378
+ min?: number | undefined;
4379
+ required?: boolean | undefined;
4380
+ description?: string | undefined;
4381
+ visibleWhen?: {
4382
+ field: string;
4383
+ equals: string | number | boolean;
4384
+ } | undefined;
4385
+ }, {
4386
+ name: string;
4387
+ type: "number";
4388
+ label?: string | undefined;
4389
+ default?: number | undefined;
4390
+ max?: number | undefined;
4391
+ min?: number | undefined;
4392
+ required?: boolean | undefined;
4393
+ description?: string | undefined;
4394
+ visibleWhen?: {
4395
+ field: string;
4396
+ equals: string | number | boolean;
4397
+ } | undefined;
4398
+ }>;
4399
+ type NumberFieldSpec = z.infer<typeof numberFieldSchema>;
4400
+ /** A whole-number field. */
4401
+ declare const integerFieldSchema: z.ZodObject<{
4402
+ default: z.ZodOptional<z.ZodNumber>;
4403
+ min: z.ZodOptional<z.ZodNumber>;
4404
+ max: z.ZodOptional<z.ZodNumber>;
4405
+ /** Value key in the emitted form state (the `values` object key). */
4406
+ name: z.ZodString;
4407
+ /** Human label. Falls back to a humanized `name` when omitted. */
4408
+ label: z.ZodOptional<z.ZodString>;
4409
+ /** Helper text shown under the control. */
4410
+ description: z.ZodOptional<z.ZodString>;
4411
+ /** Whether a value is required before the form can submit. */
4412
+ required: z.ZodOptional<z.ZodBoolean>;
4413
+ /**
4414
+ * Conditional visibility: render (and validate/submit) this field only
4415
+ * when another field's current value equals `equals` — e.g. show a
4416
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4417
+ * by `isFieldVisible` against the form's current values; a hidden field is
4418
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4419
+ * a hidden `required` field never blocks submit.
4420
+ */
4421
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4422
+ /** Name of the controlling field. */
4423
+ field: z.ZodString;
4424
+ /** The controlling field's value that makes this field visible. */
4425
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4426
+ }, "strip", z.ZodTypeAny, {
4427
+ field: string;
4428
+ equals: string | number | boolean;
4429
+ }, {
4430
+ field: string;
4431
+ equals: string | number | boolean;
4432
+ }>>;
4433
+ type: z.ZodLiteral<"integer">;
4434
+ }, "strip", z.ZodTypeAny, {
4435
+ name: string;
4436
+ type: "integer";
4437
+ label?: string | undefined;
4438
+ default?: number | undefined;
4439
+ max?: number | undefined;
4440
+ min?: number | undefined;
4441
+ required?: boolean | undefined;
4442
+ description?: string | undefined;
4443
+ visibleWhen?: {
4444
+ field: string;
4445
+ equals: string | number | boolean;
4446
+ } | undefined;
4447
+ }, {
4448
+ name: string;
4449
+ type: "integer";
4450
+ label?: string | undefined;
4451
+ default?: number | undefined;
4452
+ max?: number | undefined;
4453
+ min?: number | undefined;
4454
+ required?: boolean | undefined;
4455
+ description?: string | undefined;
4456
+ visibleWhen?: {
4457
+ field: string;
4458
+ equals: string | number | boolean;
4459
+ } | undefined;
4460
+ }>;
4461
+ type IntegerFieldSpec = z.infer<typeof integerFieldSchema>;
4462
+ /** A boolean checkbox field. */
4463
+ declare const booleanFieldSchema: z.ZodObject<{
4464
+ default: z.ZodOptional<z.ZodBoolean>;
4465
+ /** Value key in the emitted form state (the `values` object key). */
4466
+ name: z.ZodString;
4467
+ /** Human label. Falls back to a humanized `name` when omitted. */
4468
+ label: z.ZodOptional<z.ZodString>;
4469
+ /** Helper text shown under the control. */
4470
+ description: z.ZodOptional<z.ZodString>;
4471
+ /** Whether a value is required before the form can submit. */
4472
+ required: z.ZodOptional<z.ZodBoolean>;
4473
+ /**
4474
+ * Conditional visibility: render (and validate/submit) this field only
4475
+ * when another field's current value equals `equals` — e.g. show a
4476
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4477
+ * by `isFieldVisible` against the form's current values; a hidden field is
4478
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4479
+ * a hidden `required` field never blocks submit.
4480
+ */
4481
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4482
+ /** Name of the controlling field. */
4483
+ field: z.ZodString;
4484
+ /** The controlling field's value that makes this field visible. */
4485
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4486
+ }, "strip", z.ZodTypeAny, {
4487
+ field: string;
4488
+ equals: string | number | boolean;
4489
+ }, {
4490
+ field: string;
4491
+ equals: string | number | boolean;
4492
+ }>>;
4493
+ type: z.ZodLiteral<"boolean">;
4494
+ }, "strip", z.ZodTypeAny, {
4495
+ name: string;
4496
+ type: "boolean";
4497
+ label?: string | undefined;
4498
+ default?: boolean | undefined;
4499
+ required?: boolean | undefined;
4500
+ description?: string | undefined;
4501
+ visibleWhen?: {
4502
+ field: string;
4503
+ equals: string | number | boolean;
4504
+ } | undefined;
4505
+ }, {
4506
+ name: string;
4507
+ type: "boolean";
4508
+ label?: string | undefined;
4509
+ default?: boolean | undefined;
4510
+ required?: boolean | undefined;
4511
+ description?: string | undefined;
4512
+ visibleWhen?: {
4513
+ field: string;
4514
+ equals: string | number | boolean;
4515
+ } | undefined;
4516
+ }>;
4517
+ type BooleanFieldSpec = z.infer<typeof booleanFieldSchema>;
4518
+ /** A single-select enum (one value from `options`). */
4519
+ declare const enumFieldSchema: z.ZodObject<{
4520
+ options: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
4521
+ const: z.ZodString;
4522
+ title: z.ZodOptional<z.ZodString>;
4523
+ }, "strip", z.ZodTypeAny, {
4524
+ const: string;
4525
+ title?: string | undefined;
4526
+ }, {
4527
+ const: string;
4528
+ title?: string | undefined;
4529
+ }>]>, "many">;
4530
+ default: z.ZodOptional<z.ZodString>;
4531
+ /** Value key in the emitted form state (the `values` object key). */
4532
+ name: z.ZodString;
4533
+ /** Human label. Falls back to a humanized `name` when omitted. */
4534
+ label: z.ZodOptional<z.ZodString>;
4535
+ /** Helper text shown under the control. */
4536
+ description: z.ZodOptional<z.ZodString>;
4537
+ /** Whether a value is required before the form can submit. */
4538
+ required: z.ZodOptional<z.ZodBoolean>;
4539
+ /**
4540
+ * Conditional visibility: render (and validate/submit) this field only
4541
+ * when another field's current value equals `equals` — e.g. show a
4542
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4543
+ * by `isFieldVisible` against the form's current values; a hidden field is
4544
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4545
+ * a hidden `required` field never blocks submit.
4546
+ */
4547
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4548
+ /** Name of the controlling field. */
4549
+ field: z.ZodString;
4550
+ /** The controlling field's value that makes this field visible. */
4551
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4552
+ }, "strip", z.ZodTypeAny, {
4553
+ field: string;
4554
+ equals: string | number | boolean;
4555
+ }, {
4556
+ field: string;
4557
+ equals: string | number | boolean;
4558
+ }>>;
4559
+ type: z.ZodLiteral<"enum">;
4560
+ }, "strip", z.ZodTypeAny, {
4561
+ name: string;
4562
+ type: "enum";
4563
+ options: (string | {
4564
+ const: string;
4565
+ title?: string | undefined;
4566
+ })[];
4567
+ label?: string | undefined;
4568
+ default?: string | undefined;
4569
+ required?: boolean | undefined;
4570
+ description?: string | undefined;
4571
+ visibleWhen?: {
4572
+ field: string;
4573
+ equals: string | number | boolean;
4574
+ } | undefined;
4575
+ }, {
4576
+ name: string;
4577
+ type: "enum";
4578
+ options: (string | {
4579
+ const: string;
4580
+ title?: string | undefined;
4581
+ })[];
4582
+ label?: string | undefined;
4583
+ default?: string | undefined;
4584
+ required?: boolean | undefined;
4585
+ description?: string | undefined;
4586
+ visibleWhen?: {
4587
+ field: string;
4588
+ equals: string | number | boolean;
4589
+ } | undefined;
4590
+ }>;
4591
+ type EnumFieldSpec = z.infer<typeof enumFieldSchema>;
4592
+ /** A multi-select enum (zero or more values from `options`). */
4593
+ declare const multiEnumFieldSchema: z.ZodObject<{
4594
+ options: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
4595
+ const: z.ZodString;
4596
+ title: z.ZodOptional<z.ZodString>;
4597
+ }, "strip", z.ZodTypeAny, {
4598
+ const: string;
4599
+ title?: string | undefined;
4600
+ }, {
4601
+ const: string;
4602
+ title?: string | undefined;
4603
+ }>]>, "many">;
4604
+ default: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
4605
+ /** Value key in the emitted form state (the `values` object key). */
4606
+ name: z.ZodString;
4607
+ /** Human label. Falls back to a humanized `name` when omitted. */
4608
+ label: z.ZodOptional<z.ZodString>;
4609
+ /** Helper text shown under the control. */
4610
+ description: z.ZodOptional<z.ZodString>;
4611
+ /** Whether a value is required before the form can submit. */
4612
+ required: z.ZodOptional<z.ZodBoolean>;
4613
+ /**
4614
+ * Conditional visibility: render (and validate/submit) this field only
4615
+ * when another field's current value equals `equals` — e.g. show a
4616
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4617
+ * by `isFieldVisible` against the form's current values; a hidden field is
4618
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4619
+ * a hidden `required` field never blocks submit.
4620
+ */
4621
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4622
+ /** Name of the controlling field. */
4623
+ field: z.ZodString;
4624
+ /** The controlling field's value that makes this field visible. */
4625
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4626
+ }, "strip", z.ZodTypeAny, {
4627
+ field: string;
4628
+ equals: string | number | boolean;
4629
+ }, {
4630
+ field: string;
4631
+ equals: string | number | boolean;
4632
+ }>>;
4633
+ type: z.ZodLiteral<"multi-enum">;
4634
+ }, "strip", z.ZodTypeAny, {
4635
+ name: string;
4636
+ type: "multi-enum";
4637
+ options: (string | {
4638
+ const: string;
4639
+ title?: string | undefined;
4640
+ })[];
4641
+ label?: string | undefined;
4642
+ default?: string[] | undefined;
4643
+ required?: boolean | undefined;
4644
+ description?: string | undefined;
4645
+ visibleWhen?: {
4646
+ field: string;
4647
+ equals: string | number | boolean;
4648
+ } | undefined;
4649
+ }, {
4650
+ name: string;
4651
+ type: "multi-enum";
4652
+ options: (string | {
4653
+ const: string;
4654
+ title?: string | undefined;
4655
+ })[];
4656
+ label?: string | undefined;
4657
+ default?: string[] | undefined;
4658
+ required?: boolean | undefined;
4659
+ description?: string | undefined;
4660
+ visibleWhen?: {
4661
+ field: string;
4662
+ equals: string | number | boolean;
4663
+ } | undefined;
4664
+ }>;
4665
+ type MultiEnumFieldSpec = z.infer<typeof multiEnumFieldSchema>;
4666
+ /** A repeating list of strings (Onyx's `list`) → renders `ListEditor`. */
4667
+ declare const listFieldSchema: z.ZodObject<{
4668
+ default: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
4669
+ minItems: z.ZodOptional<z.ZodNumber>;
4670
+ maxItems: z.ZodOptional<z.ZodNumber>;
4671
+ itemPlaceholder: z.ZodOptional<z.ZodString>;
4672
+ /** Value key in the emitted form state (the `values` object key). */
4673
+ name: z.ZodString;
4674
+ /** Human label. Falls back to a humanized `name` when omitted. */
4675
+ label: z.ZodOptional<z.ZodString>;
4676
+ /** Helper text shown under the control. */
4677
+ description: z.ZodOptional<z.ZodString>;
4678
+ /** Whether a value is required before the form can submit. */
4679
+ required: z.ZodOptional<z.ZodBoolean>;
4680
+ /**
4681
+ * Conditional visibility: render (and validate/submit) this field only
4682
+ * when another field's current value equals `equals` — e.g. show a
4683
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4684
+ * by `isFieldVisible` against the form's current values; a hidden field is
4685
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4686
+ * a hidden `required` field never blocks submit.
4687
+ */
4688
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4689
+ /** Name of the controlling field. */
4690
+ field: z.ZodString;
4691
+ /** The controlling field's value that makes this field visible. */
4692
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4693
+ }, "strip", z.ZodTypeAny, {
4694
+ field: string;
4695
+ equals: string | number | boolean;
4696
+ }, {
4697
+ field: string;
4698
+ equals: string | number | boolean;
4699
+ }>>;
4700
+ type: z.ZodLiteral<"list">;
4701
+ }, "strip", z.ZodTypeAny, {
4702
+ name: string;
4703
+ type: "list";
4704
+ label?: string | undefined;
4705
+ default?: string[] | undefined;
4706
+ required?: boolean | undefined;
4707
+ description?: string | undefined;
4708
+ visibleWhen?: {
4709
+ field: string;
4710
+ equals: string | number | boolean;
4711
+ } | undefined;
4712
+ minItems?: number | undefined;
4713
+ maxItems?: number | undefined;
4714
+ itemPlaceholder?: string | undefined;
4715
+ }, {
4716
+ name: string;
4717
+ type: "list";
4718
+ label?: string | undefined;
4719
+ default?: string[] | undefined;
4720
+ required?: boolean | undefined;
4721
+ description?: string | undefined;
4722
+ visibleWhen?: {
4723
+ field: string;
4724
+ equals: string | number | boolean;
4725
+ } | undefined;
4726
+ minItems?: number | undefined;
4727
+ maxItems?: number | undefined;
4728
+ itemPlaceholder?: string | undefined;
4729
+ }>;
4730
+ type ListFieldSpec = z.infer<typeof listFieldSchema>;
4731
+ /** A repeating key/value list, e.g. headers or env vars (Onyx's `string_pair_list`) → renders `KeyValueEditor`. */
4732
+ declare const keyValueFieldSchema: z.ZodObject<{
4733
+ default: z.ZodOptional<z.ZodArray<z.ZodObject<{
4734
+ key: z.ZodString;
4735
+ value: z.ZodString;
4736
+ /** Mask this row's value (rendered as `type="password"` with a reveal toggle). */
4737
+ secret: z.ZodOptional<z.ZodBoolean>;
4738
+ }, "strip", z.ZodTypeAny, {
4739
+ key: string;
4740
+ value: string;
4741
+ secret?: boolean | undefined;
4742
+ }, {
4743
+ key: string;
4744
+ value: string;
4745
+ secret?: boolean | undefined;
4746
+ }>, "many">>;
4747
+ keyPlaceholder: z.ZodOptional<z.ZodString>;
4748
+ valuePlaceholder: z.ZodOptional<z.ZodString>;
4749
+ /** Value key in the emitted form state (the `values` object key). */
4750
+ name: z.ZodString;
4751
+ /** Human label. Falls back to a humanized `name` when omitted. */
4752
+ label: z.ZodOptional<z.ZodString>;
4753
+ /** Helper text shown under the control. */
4754
+ description: z.ZodOptional<z.ZodString>;
4755
+ /** Whether a value is required before the form can submit. */
4756
+ required: z.ZodOptional<z.ZodBoolean>;
4757
+ /**
4758
+ * Conditional visibility: render (and validate/submit) this field only
4759
+ * when another field's current value equals `equals` — e.g. show a
4760
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4761
+ * by `isFieldVisible` against the form's current values; a hidden field is
4762
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4763
+ * a hidden `required` field never blocks submit.
4764
+ */
4765
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4766
+ /** Name of the controlling field. */
4767
+ field: z.ZodString;
4768
+ /** The controlling field's value that makes this field visible. */
4769
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4770
+ }, "strip", z.ZodTypeAny, {
4771
+ field: string;
4772
+ equals: string | number | boolean;
4773
+ }, {
4774
+ field: string;
4775
+ equals: string | number | boolean;
4776
+ }>>;
4777
+ type: z.ZodLiteral<"key-value">;
4778
+ }, "strip", z.ZodTypeAny, {
4779
+ name: string;
4780
+ type: "key-value";
4781
+ label?: string | undefined;
4782
+ default?: {
4783
+ key: string;
4784
+ value: string;
4785
+ secret?: boolean | undefined;
4786
+ }[] | undefined;
4787
+ required?: boolean | undefined;
4788
+ description?: string | undefined;
4789
+ keyPlaceholder?: string | undefined;
4790
+ valuePlaceholder?: string | undefined;
4791
+ visibleWhen?: {
4792
+ field: string;
4793
+ equals: string | number | boolean;
4794
+ } | undefined;
4795
+ }, {
4796
+ name: string;
4797
+ type: "key-value";
4798
+ label?: string | undefined;
4799
+ default?: {
4800
+ key: string;
4801
+ value: string;
4802
+ secret?: boolean | undefined;
4803
+ }[] | undefined;
4804
+ required?: boolean | undefined;
4805
+ description?: string | undefined;
4806
+ keyPlaceholder?: string | undefined;
4807
+ valuePlaceholder?: string | undefined;
4808
+ visibleWhen?: {
4809
+ field: string;
4810
+ equals: string | number | boolean;
4811
+ } | undefined;
4812
+ }>;
4813
+ type KeyValueFieldSpec = z.infer<typeof keyValueFieldSchema>;
4814
+ /** A file-upload field (Onyx's `file`) → renders `FileUpload`. No `default` — files cannot be defaulted. */
4815
+ declare const fileFieldSchema: z.ZodObject<{
4816
+ /** Forwarded to the native `<input accept>` (comma-separated extensions/MIME types). */
4817
+ accept: z.ZodOptional<z.ZodString>;
4818
+ multiple: z.ZodOptional<z.ZodBoolean>;
4819
+ /** Maximum individual file size, in bytes. */
4820
+ maxSize: z.ZodOptional<z.ZodNumber>;
4821
+ /** Maximum number of files (only meaningful when `multiple`). */
4822
+ maxFiles: z.ZodOptional<z.ZodNumber>;
4823
+ /** Value key in the emitted form state (the `values` object key). */
4824
+ name: z.ZodString;
4825
+ /** Human label. Falls back to a humanized `name` when omitted. */
4826
+ label: z.ZodOptional<z.ZodString>;
4827
+ /** Helper text shown under the control. */
4828
+ description: z.ZodOptional<z.ZodString>;
4829
+ /** Whether a value is required before the form can submit. */
4830
+ required: z.ZodOptional<z.ZodBoolean>;
4831
+ /**
4832
+ * Conditional visibility: render (and validate/submit) this field only
4833
+ * when another field's current value equals `equals` — e.g. show a
4834
+ * "client secret" field only once `authMethod` equals `"oauth"`. Evaluated
4835
+ * by `isFieldVisible` against the form's current values; a hidden field is
4836
+ * excluded from rendering, validation and the first-invalid-focus walk, so
4837
+ * a hidden `required` field never blocks submit.
4838
+ */
4839
+ visibleWhen: z.ZodOptional<z.ZodObject<{
4840
+ /** Name of the controlling field. */
4841
+ field: z.ZodString;
4842
+ /** The controlling field's value that makes this field visible. */
4843
+ equals: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>;
4844
+ }, "strip", z.ZodTypeAny, {
4845
+ field: string;
4846
+ equals: string | number | boolean;
4847
+ }, {
4848
+ field: string;
4849
+ equals: string | number | boolean;
4850
+ }>>;
4851
+ type: z.ZodLiteral<"file">;
4852
+ }, "strip", z.ZodTypeAny, {
4853
+ name: string;
4854
+ type: "file";
4855
+ label?: string | undefined;
4856
+ accept?: string | undefined;
4857
+ multiple?: boolean | undefined;
4858
+ required?: boolean | undefined;
4859
+ description?: string | undefined;
4860
+ maxSize?: number | undefined;
4861
+ maxFiles?: number | undefined;
4862
+ visibleWhen?: {
4863
+ field: string;
4864
+ equals: string | number | boolean;
4865
+ } | undefined;
4866
+ }, {
4867
+ name: string;
4868
+ type: "file";
4869
+ label?: string | undefined;
4870
+ accept?: string | undefined;
4871
+ multiple?: boolean | undefined;
4872
+ required?: boolean | undefined;
4873
+ description?: string | undefined;
4874
+ maxSize?: number | undefined;
4875
+ maxFiles?: number | undefined;
4876
+ visibleWhen?: {
4877
+ field: string;
4878
+ equals: string | number | boolean;
4879
+ } | undefined;
4880
+ }>;
4881
+ type FileFieldSpec = z.infer<typeof fileFieldSchema>;
4882
+ /**
4883
+ * Any one field in a FormSpec — pre-declared here (a plain TS union, not
4884
+ * `z.infer`) so `GroupItemSpec`/`GroupFieldSpec` below can reference it and
4885
+ * vice versa. TypeScript resolves mutual recursion between `type`/`interface`
4886
+ * declarations regardless of file order (no runtime value is involved); only
4887
+ * the `const` zod schemas further down need an explicit `z.ZodType<…>`
4888
+ * annotation to break the equivalent circular VALUE reference through
4889
+ * `z.lazy`.
4890
+ */
4891
+ type FieldSpec = StringFieldSpec | NumberFieldSpec | IntegerFieldSpec | BooleanFieldSpec | EnumFieldSpec | MultiEnumFieldSpec | ListFieldSpec | KeyValueFieldSpec | FileFieldSpec | GroupFieldSpec;
4892
+ /** One named branch of a `group` field's `groups` array. Recursive — a branch's `fields` are ordinary `FieldSpec`s, including nested groups. */
4893
+ interface GroupItemSpec {
4894
+ /** Stable key for this branch — also the value stored when `variant: "tabs"`. */
4895
+ key: string;
4896
+ label: string;
4897
+ description?: string;
4898
+ fields: FieldSpec[];
4899
+ }
4900
+ /**
4901
+ * Grouped alternative field sets (Onyx's `tab` / `string_tab`) → renders
4902
+ * `Tabs` (`variant: "tabs"`, mutually exclusive — e.g. "OAuth" vs "API key")
4903
+ * or a stack of `AdvancedGroup` disclosures (`variant: "advanced"` — always-
4904
+ * available secondary fields, not mutually exclusive).
4905
+ *
4906
+ * For `variant: "tabs"`, the field's OWN value (`values[field.name]`) is the
4907
+ * active branch's `key` — the group behaves like a single-select enum over
4908
+ * its branches. Only the active branch's fields are validated/required;
4909
+ * `variant: "advanced"` has no notion of an active branch, so every branch's
4910
+ * fields are always validated.
4911
+ */
4912
+ interface GroupFieldSpec {
4913
+ type: "group";
4914
+ name: string;
4915
+ label?: string;
4916
+ description?: string;
4917
+ required?: boolean;
4918
+ /** See `visibleWhen` on `baseField` — conditional visibility for the whole group (and its subtree). */
4919
+ visibleWhen?: {
4920
+ field: string;
4921
+ equals: string | number | boolean;
4922
+ };
4923
+ variant: "tabs" | "advanced";
4924
+ groups: GroupItemSpec[];
4925
+ /** Default active branch key. Only meaningful for `variant: "tabs"`. @default groups[0].key */
4926
+ default?: string;
4927
+ }
4928
+ declare const groupItemSchema: z.ZodType<GroupItemSpec>;
4929
+ declare const groupFieldSchema: z.ZodType<GroupFieldSpec>;
4930
+ /**
4931
+ * NOTE: cast through `unknown` — `z.discriminatedUnion`'s own inferred output
4932
+ * type is not assignable to the hand-declared `FieldSpec` union once one
4933
+ * member (`groupFieldSchema`) is itself hand-typed via `z.ZodType<…>` rather
4934
+ * than inferred; the runtime validator (discriminate on `type`, then run each
4935
+ * member's real `.parse`) is unaffected; only the static type is asserted.
4936
+ */
4937
+ declare const fieldSpecSchema: z.ZodType<FieldSpec>;
4938
+ /**
4939
+ * The serializable form specification SchemaForm reads, renders and submits
4940
+ * as `{ formName, values }`.
4941
+ */
4942
+ declare const formSpecSchema: z.ZodObject<{
4943
+ /** Stable identifier echoed back in the submit payload. */
4944
+ formName: z.ZodString;
4945
+ /** Heading rendered above the fields (also the accessible form name). */
4946
+ title: z.ZodOptional<z.ZodString>;
4947
+ /** Supplemental description under the title. */
4948
+ description: z.ZodOptional<z.ZodString>;
4949
+ /** The ordered fields to render. */
4950
+ fields: z.ZodArray<z.ZodType<FieldSpec, z.ZodTypeDef, FieldSpec>, "many">;
4951
+ /** Submit button label. @default "Submit" */
4952
+ submitLabel: z.ZodOptional<z.ZodString>;
4953
+ }, "strip", z.ZodTypeAny, {
4954
+ fields: FieldSpec[];
4955
+ formName: string;
4956
+ title?: string | undefined;
4957
+ description?: string | undefined;
4958
+ submitLabel?: string | undefined;
4959
+ }, {
4960
+ fields: FieldSpec[];
4961
+ formName: string;
4962
+ title?: string | undefined;
4963
+ description?: string | undefined;
4964
+ submitLabel?: string | undefined;
4965
+ }>;
4966
+ type FormSpec = Omit<z.infer<typeof formSpecSchema>, "fields"> & {
4967
+ fields: FieldSpec[];
4968
+ };
4969
+ /** A single field's value in the form state. */
4970
+ type FormValue = string | number | boolean | string[] | FieldKeyValueRow[] | File[] | undefined;
4971
+ /** The `values` object keyed by field `name`. */
4972
+ type FormValues = Record<string, FormValue>;
4973
+ /** The payload passed to `onSubmit`. */
4974
+ interface FormSubmitState {
4975
+ /** Echoes `spec.formName`. */
4976
+ formName: string;
4977
+ /** The current field values keyed by field name. */
4978
+ values: FormValues;
4979
+ }
4980
+ /** A validated, render-ready FormSpec. */
4981
+ interface NormalizedFormSpec {
4982
+ formName: string;
4983
+ title?: string;
4984
+ description?: string;
4985
+ submitLabel?: string;
4986
+ fields: FieldSpec[];
4987
+ }
4988
+ declare function normalizeFormSpec(spec: unknown): {
4989
+ ok: true;
4990
+ spec: NormalizedFormSpec;
4991
+ } | {
4992
+ ok: false;
4993
+ reason: string;
4994
+ };
4995
+ /** Find a field by name anywhere in the tree, including inside `group` branches. */
4996
+ declare function findFieldByName(fields: FieldSpec[], name: string): FieldSpec | undefined;
4997
+ /**
4998
+ * Does `field` currently satisfy its own `visibleWhen` (if it has one)? A
4999
+ * field with no `visibleWhen` is always visible. Shared by the render loops
5000
+ * (schema-form.tsx) and `collectValidatableFields` below, so what's shown and
5001
+ * what's validated/submitted never disagree.
5002
+ */
5003
+ declare function isFieldVisible(field: FieldSpec, values: FormValues): boolean;
5004
+ /**
5005
+ * The fields that currently participate in validation/submission: every
5006
+ * scalar field, plus — for a `group` field — either the ACTIVE branch's
5007
+ * fields (`variant: "tabs"`, keyed by `values[field.name]`) or ALL branches'
5008
+ * fields (`variant: "advanced"`, nothing is mutually exclusive there). A
5009
+ * field (or, for a hidden `group`, its whole subtree) whose `visibleWhen`
5010
+ * does not currently hold is excluded entirely — a hidden `required` field
5011
+ * must never block submit.
5012
+ */
5013
+ declare function collectValidatableFields(fields: FieldSpec[], values: FormValues): FieldSpec[];
5014
+ /** The label to show for a field (explicit `label`, else a humanized `name`). */
5015
+ declare function fieldLabel(field: FieldSpec): string;
5016
+ /** Seed the initial values from every field's `default` (+ sensible empties), recursively. */
5017
+ declare function initialFormValues(fields: FieldSpec[]): FormValues;
5018
+ /**
5019
+ * Validate one field's value against its declarative constraints.
5020
+ * Returns a short human error message, or `null` when the value is valid.
5021
+ * The vocabulary: required · email · url · min · max · minLength · maxLength ·
5022
+ * pattern · numeric (integer whole-number) · minItems/maxItems (list).
5023
+ */
5024
+ declare function validateField(field: FieldSpec, value: FormValue): string | null;
5025
+ /** Validate every VALIDATABLE field (see `collectValidatableFields`); returns a `{ [name]: error | null }` map. */
5026
+ declare function validateForm(fields: FieldSpec[], values: FormValues): Record<string, string | null>;
5027
+ /** Does `file` satisfy an `<input accept>`-style pattern (extensions, MIME types, or `type/*`)? */
5028
+ declare function fileMatchesAccept(file: File, accept: string | undefined): boolean;
5029
+ interface FileIssue {
5030
+ reason: "wrong-type" | "too-large";
5031
+ message: string;
5032
+ }
5033
+ /** Client-side per-file check for the designed `file` field states: wrong type, too large. */
5034
+ declare function checkFileIssue(file: File, field: FileFieldSpec): FileIssue | null;
5035
+
5036
+ interface SchemaFormProviderProps {
5037
+ /** A validated/normalized spec (a plain `FormSpec` also satisfies this). */
5038
+ spec: NormalizedFormSpec;
5039
+ /**
5040
+ * Controlled values. When provided the component is controlled and
5041
+ * `onChange` is the only way to update state.
5042
+ */
5043
+ values?: FormValues;
5044
+ /** Called with the next full values object on any field change. */
5045
+ onChange?: (values: FormValues) => void;
5046
+ /** Called with `{ formName, values }` when a valid form is submitted. */
5047
+ onSubmit?: (state: FormSubmitState) => void;
5048
+ /** Disable every control (form is read-only). A deliberate, durable state. */
5049
+ disabled?: boolean;
5050
+ /** Terminal submitted state: controls are inert, values visible, no submit. */
5051
+ submitted?: boolean;
5052
+ /** In-flight submit: controls transiently blocked, submit shows a spinner. */
5053
+ submitting?: boolean;
5054
+ /** No fields to render yet (e.g. the spec is still being fetched) → skeleton. */
5055
+ loading?: boolean;
5056
+ /** A terminal, form-level submission error rendered above the submit control. */
5057
+ error?: ReactNode;
5058
+ children: ReactNode;
5059
+ }
5060
+ /**
5061
+ * Lifts the form values. Controlled (pass `values`) or uncontrolled.
5062
+ * Derives `isControlled = values !== undefined` and never flips modes.
5063
+ */
5064
+ declare function SchemaFormProvider({ spec, values: valuesProp, onChange, onSubmit, disabled, submitted, submitting, loading, error, children, }: SchemaFormProviderProps): react.JSX.Element;
5065
+ interface SchemaFormFieldProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
5066
+ /** The field's `name` (its key in the spec + values). Resolved anywhere in the tree, including inside `group` branches. */
5067
+ name: string;
5068
+ }
5069
+ /**
5070
+ * Renders one field by name: label, control, description, inline error.
5071
+ * Boolean fields render their own inline label (checkbox + label); `group`
5072
+ * fields render their OWN label/description internally (a Tabs strip or a
5073
+ * stack of disclosures isn't a single labelled control), so the standalone
5074
+ * `<Label>` above is suppressed for both.
5075
+ *
5076
+ * Enforces its OWN `visibleWhen` (returns `null` when hidden) rather than
5077
+ * trusting the caller to have filtered it out first: the documented custom-
5078
+ * layout composition (`SchemaFormProvider` + the parts, see `SchemaForm`'s
5079
+ * own doc comment) lets a consumer place `<SchemaFormField name="…" />`
5080
+ * directly, bypassing `SchemaFormFields`'/`GroupTabsControl`'s/
5081
+ * `AdvancedGroupBranch`'s own `isFieldVisible` filters — without this check
5082
+ * the same spec would render a hidden field in a custom layout while
5083
+ * validation/submission (which always excludes it) disagree.
5084
+ */
5085
+ declare const SchemaFormField: react.ForwardRefExoticComponent<SchemaFormFieldProps & react.RefAttributes<HTMLDivElement>>;
5086
+ type SchemaFormFieldsProps = HTMLAttributes<HTMLDivElement>;
5087
+ /** Renders every top-level field in the spec, in order. A skeleton while `loading` with no fields. */
5088
+ declare const SchemaFormFields: react.ForwardRefExoticComponent<SchemaFormFieldsProps & react.RefAttributes<HTMLDivElement>>;
5089
+ type SchemaFormErrorProps = HTMLAttributes<HTMLDivElement>;
5090
+ /** A terminal, form-level submission error (e.g. "Couldn't save settings"). Renders nothing when absent. */
5091
+ declare const SchemaFormError: react.ForwardRefExoticComponent<SchemaFormErrorProps & react.RefAttributes<HTMLDivElement>>;
5092
+ interface SchemaFormSubmitProps extends Omit<HTMLAttributes<HTMLButtonElement>, "children"> {
5093
+ /** Submit button label (overrides `spec.submitLabel`). @default "Submit" */
5094
+ label?: string;
5095
+ }
5096
+ /**
5097
+ * The submit affordance. Enabled until the request starts (validation runs on
5098
+ * click), then transiently blocked. `submitting` uses `aria-disabled` + a
5099
+ * click-handler guard — NEVER the native `disabled` attribute — so a focused
5100
+ * button is never dropped from the tab order right after the user activates
5101
+ * it (see the module doc comment / interaction-guidelines.md). The explicit,
5102
+ * caller-set `disabled` (read-only form) stays native: that is a deliberate,
5103
+ * durable state, not a transient auto-flip. A submitted form shows an inert
5104
+ * "Submitted" note instead of a button.
5105
+ */
5106
+ declare const SchemaFormSubmit: react.ForwardRefExoticComponent<SchemaFormSubmitProps & react.RefAttributes<HTMLButtonElement>>;
5107
+ /**
5108
+ * `SchemaFormTestAction`'s lifecycle: `idle` → `pending` while `onTest` is in
5109
+ * flight → `success`/`failure` once it settles. Deliberately local component
5110
+ * state, NOT part of `SchemaFormContextValue` — so it can never affect field
5111
+ * validity or gate `submit()` (issue #22 maintainer ruling, 2026-09-01: a
5112
+ * form/group-level test-action slot, kept separate from field validity and
5113
+ * never gating submit — not per-field `validateAsync` in the validation
5114
+ * engine).
5115
+ */
5116
+ type SchemaFormTestActionStatus = "idle" | "pending" | "success" | "failure";
5117
+ interface SchemaFormTestActionProps extends Omit<HTMLAttributes<HTMLDivElement>, "onError"> {
5118
+ /**
5119
+ * Runs the test (e.g. calls an API with the fields typed so far). Receives
5120
+ * the form's CURRENT effective values — the same object `validateForm`
5121
+ * would resolve against — but this call is entirely independent of
5122
+ * validation: a field that is currently invalid, or an unrelated required
5123
+ * field left empty, never blocks a test run. Resolve to signal success;
5124
+ * reject (an `Error`, or throw) to signal failure — a rejected `Error`'s
5125
+ * `message` becomes the shown failure reason.
5126
+ */
5127
+ onTest: (values: FormValues) => void | Promise<void>;
5128
+ /** Button label. @default "Test connection" */
5129
+ label?: string;
5130
+ /** Label shown while pending. @default "Testing…" */
5131
+ pendingLabel?: string;
5132
+ /** Label shown on success. @default "Connected" */
5133
+ successLabel?: string;
5134
+ /** Fallback failure label when the rejection carries no message. @default "Test failed" */
5135
+ failureLabel?: string;
5136
+ }
5137
+ /**
5138
+ * A form- or group-level "Test connection" affordance: an async action the
5139
+ * user can run to verify the values typed so far (e.g. hit a connector's
5140
+ * `/ping` endpoint) BEFORE submitting. Place it anywhere inside a
5141
+ * `SchemaFormProvider` tree — directly under `SchemaFormRoot` for a
5142
+ * form-level test, or beside a `SchemaFormField` inside a `group` branch (a
5143
+ * `TabsContent`/`AdvancedGroup`) for a per-credential-set test. Not part of
5144
+ * `SchemaForm`'s default composition — an opt-in part a consumer places, the
5145
+ * same way a custom layout composes `SchemaFormField` directly.
5146
+ *
5147
+ * Deliberately NOT wired into `errors`/`validateForm`/`submit()` — its
5148
+ * pending/success/failure state is entirely local, so it can never block or
5149
+ * silently gate the form's own submit control.
5150
+ */
5151
+ declare const SchemaFormTestAction: react.ForwardRefExoticComponent<SchemaFormTestActionProps & react.RefAttributes<HTMLDivElement>>;
5152
+ type SchemaFormRootProps = Omit<HTMLAttributes<HTMLFormElement>, "onSubmit">;
5153
+ /**
5154
+ * The `<form>` element wired to the context's `submit`. Never nest inside
5155
+ * another `<form>` — compose it as its own top-level block.
5156
+ */
5157
+ declare const SchemaFormRoot: react.ForwardRefExoticComponent<SchemaFormRootProps & react.RefAttributes<HTMLFormElement>>;
5158
+ type SchemaFormTitleProps = HTMLAttributes<HTMLParagraphElement>;
5159
+ /** The form heading. Its id is the `<form>`'s `aria-labelledby` target. */
5160
+ declare const SchemaFormTitle: react.ForwardRefExoticComponent<SchemaFormTitleProps & react.RefAttributes<HTMLParagraphElement>>;
5161
+ type SchemaFormDescriptionProps = HTMLAttributes<HTMLParagraphElement>;
5162
+ /** Supplemental description under the title. */
5163
+ declare const SchemaFormDescription: react.ForwardRefExoticComponent<SchemaFormDescriptionProps & react.RefAttributes<HTMLParagraphElement>>;
5164
+ interface SchemaFormFallbackProps extends HTMLAttributes<HTMLDivElement> {
5165
+ /** Short human reason the form could not render. */
5166
+ message?: string;
5167
+ }
5168
+ /**
5169
+ * Shown when the spec is unusable. Mirrors `MessageFormFallback`: a calm,
5170
+ * bordered status box with a short reason — never a thrown error.
5171
+ */
5172
+ declare const SchemaFormFallback: react.ForwardRefExoticComponent<SchemaFormFallbackProps & react.RefAttributes<HTMLDivElement>>;
5173
+ interface SchemaFormProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSubmit" | "onChange" | "title"> {
5174
+ /** The serializable form specification. */
5175
+ spec: FormSpec | unknown;
5176
+ /** Controlled values (`{ [fieldName]: value }`). Omit for uncontrolled. */
5177
+ values?: FormValues;
5178
+ /** Called with the next full values object on any change. */
5179
+ onChange?: (values: FormValues) => void;
5180
+ /** Called with `{ formName, values }` on a valid submit. */
5181
+ onSubmit?: (state: FormSubmitState) => void;
5182
+ /** Submit button label (overrides `spec.submitLabel`). */
5183
+ submitLabel?: string;
5184
+ /** Disable every control (the whole form is read-only). */
5185
+ disabled?: boolean;
5186
+ /** Terminal submitted state: inert, values visible, submit replaced. */
5187
+ submitted?: boolean;
5188
+ /** In-flight submit: controls transiently blocked, spinner on submit. */
5189
+ submitting?: boolean;
5190
+ /** No fields to render yet (spec still loading) → skeleton. */
5191
+ loading?: boolean;
5192
+ /** A terminal, form-level submission error rendered above the submit control. */
5193
+ error?: ReactNode;
5194
+ }
5195
+ /**
5196
+ * Convenience composition: `Provider → Root(form) → title/description →
5197
+ * Fields → Error → Submit`. For a custom layout, compose `SchemaFormProvider`
5198
+ * + the parts. A malformed spec renders `SchemaFormFallback` (never throws).
5199
+ */
5200
+ declare const SchemaForm: react.ForwardRefExoticComponent<SchemaFormProps & react.RefAttributes<HTMLDivElement>>;
5201
+
5202
+ /**
5203
+ * from-json-schema.ts — `fromJsonSchema()`: the narrow, documented JSON
5204
+ * Schema → `FormSpec` adapter (issue #22, maintainer ruling 2026-09-01).
5205
+ *
5206
+ * Many consumers already have their config described as JSON Schema (an
5207
+ * OpenAPI request body, a connector manifest). This maps ONLY the common
5208
+ * subset such schemas actually use onto `SchemaForm`'s `FieldSpec`
5209
+ * vocabulary:
5210
+ *
5211
+ * { type: "string" } → StringFieldSpec
5212
+ * { type: "string", enum: [...] } → EnumFieldSpec
5213
+ * { type: "number" | "integer" } → NumberFieldSpec / IntegerFieldSpec
5214
+ * { type: "boolean" } → BooleanFieldSpec
5215
+ * { type: "array", items: { type: "string" } } → ListFieldSpec (free text)
5216
+ * { type: "array",
5217
+ * items: { type: "string", enum: [...] } } → MultiEnumFieldSpec
5218
+ * (a CONSTRAINED array
5219
+ * item schema maps onto
5220
+ * the field type that
5221
+ * actually enforces the
5222
+ * constraint — see
5223
+ * "Constraint keywords"
5224
+ * below for why this
5225
+ * one keyword IS read)
5226
+ * { type: "object", properties: {...} } → GroupFieldSpec
5227
+ * (variant: "advanced",
5228
+ * one always-open branch)
5229
+ *
5230
+ * `title`/`description` map to `label`/`description`; `required` (the
5231
+ * enclosing object schema's array of property names) maps to `required:
5232
+ * true`; `default` maps when it is type-compatible; `minLength`/`maxLength`/
5233
+ * `pattern`/`minimum`/`maximum`/`minItems`/`maxItems` map to their FieldSpec
5234
+ * equivalents. `format` maps only the four values `StringFieldSpec` itself
5235
+ * understands (`email`/`uri`/`date`/`date-time`) — any other `format` value
5236
+ * (`"binary"`, `"password"`, a custom one) is ignored predictably, the same
5237
+ * way an unknown JSON Schema `format` is defined to be advisory, not
5238
+ * validating.
5239
+ *
5240
+ * Deliberately NOT a general draft-07/2020-12 implementation (the maintainer
5241
+ * ruling's explicit narrow option) — this module does not resolve `$ref` and
5242
+ * does not implement the `allOf`/`oneOf`/`anyOf`/`not` combinators. Those
5243
+ * keywords change what a schema actually MEANS, and approximating them would
5244
+ * risk producing a field that looks plausible but is wrong (e.g. rendering a
5245
+ * `$ref`'d object as an empty string field) — silently wrong is exactly what
5246
+ * this adapter must never be. So `fromJsonSchema()` REFUSES: any of those
5247
+ * five keywords, found anywhere in the input (top-level or nested inside a
5248
+ * property/items schema), throws `UnsupportedJsonSchemaError` naming the
5249
+ * keyword and its JSON-Pointer-style path. Pre-resolve/inline that part of
5250
+ * the schema before calling `fromJsonSchema()`, or hand-write the affected
5251
+ * `FieldSpec`.
5252
+ *
5253
+ * A property whose `type` this subset does not cover (e.g. `"null"`, a
5254
+ * JSON-Schema-2020-12 array-of-types, an array of non-string items, an
5255
+ * object schema with no `properties`) is DROPPED from the result —
5256
+ * predictable and non-fatal, the same lenient-parse philosophy
5257
+ * `normalizeFormSpec` already uses for the render path, because omitting one
5258
+ * field is recoverable in a way a mis-mapped `$ref`/combinator is not.
5259
+ *
5260
+ * CONSTRAINT KEYWORDS this subset does not read: `const`, `if`/`then`/`else`,
5261
+ * `dependentSchemas`, `dependentRequired`, `additionalProperties`,
5262
+ * `patternProperties`, `propertyNames`, `contains`, `multipleOf`,
5263
+ * `exclusiveMinimum`/`exclusiveMaximum`, `uniqueItems`. These are
5264
+ * READ-IGNORED, not refused — unlike `$ref`/`allOf`/`oneOf`/`anyOf`/`not`,
5265
+ * none of them changes what TYPE a property maps to, so ignoring one never
5266
+ * produces a wrongly-shaped field. But ignoring one DOES widen what the
5267
+ * rendered form accepts relative to the source schema (a `const`-pinned
5268
+ * property renders as an ordinary editable field, not a fixed one; a
5269
+ * `multipleOf`-constrained number accepts any value in range). This is the
5270
+ * one place `fromJsonSchema()` is honestly silently-permissive rather than
5271
+ * silently-wrong or refusing — call it out in review when a schema leans on
5272
+ * one of these keywords for validation the mapped form will not enforce.
5273
+ * `items.enum` is the one exception among these: a constrained array-item
5274
+ * schema is common enough (and cheap enough to map faithfully) that it reads
5275
+ * `items.enum` and maps onto `MultiEnumFieldSpec` — see the table above —
5276
+ * rather than joining this ignore list and widening into a free-text
5277
+ * `ListFieldSpec`.
5278
+ *
5279
+ * Widening this subset later (more `format`s, `$ref` resolution) is an
5280
+ * additive, non-breaking change to this one function — see issue #22's
5281
+ * "worth having alongside" list.
5282
+ */
5283
+
5284
+ /**
5285
+ * Thrown by `fromJsonSchema()` when the input uses a JSON Schema keyword
5286
+ * outside its documented subset (see this module's doc comment) — never
5287
+ * silently mismapped.
5288
+ */
5289
+ declare class UnsupportedJsonSchemaError extends Error {
5290
+ constructor(keyword: string, path: string);
5291
+ }
5292
+ interface FromJsonSchemaOptions {
5293
+ /** `FormSpec.formName` — required; JSON Schema has no equivalent stable identifier. */
5294
+ formName: string;
5295
+ /** Overrides the mapped `schema.title`. */
5296
+ title?: string;
5297
+ /** Overrides the mapped `schema.description`. */
5298
+ description?: string;
5299
+ /** `FormSpec.submitLabel` — JSON Schema has no equivalent. */
5300
+ submitLabel?: string;
5301
+ }
5302
+ /**
5303
+ * Maps a JSON Schema OBJECT schema (an OpenAPI request body, a connector
5304
+ * manifest) onto a `FormSpec`, using only the documented subset described in
5305
+ * this module's doc comment. Throws `UnsupportedJsonSchemaError` if `schema`
5306
+ * (at any depth) uses `$ref`/`allOf`/`oneOf`/`anyOf`/`not`, or if the
5307
+ * top-level schema is not an object schema — never silently mismapped. A
5308
+ * property whose shape falls outside the subset is dropped, not thrown on.
5309
+ */
5310
+ declare function fromJsonSchema(schema: unknown, options: FromJsonSchemaOptions): FormSpec;
5311
+
3130
5312
  declare const ScrollArea: react.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
3131
5313
  declare const ScrollBar: react.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaScrollbarProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
3132
5314
 
@@ -3137,10 +5319,20 @@ interface SectionHeaderProps {
3137
5319
  actions?: ReactNode;
3138
5320
  /** Optional element rendered above the title (eyebrow / breadcrumbs). */
3139
5321
  eyebrow?: ReactNode;
5322
+ /**
5323
+ * The heading LEVEL the title contributes to the document outline. The
5324
+ * visual (`text-title`) is identical for every value — pick the level the
5325
+ * page's structure calls for, not the size you want (WCAG 1.3.1).
5326
+ *
5327
+ * Use `as="h1"` when this header titles the PAGE (a screen whose route it
5328
+ * names); leave it at the default when it titles a section INSIDE a page
5329
+ * that already has an `<h1>` elsewhere. @default "h2"
5330
+ */
5331
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
3140
5332
  className?: string;
3141
5333
  }
3142
5334
  /** A consistent page/section heading row with optional actions. */
3143
- declare function SectionHeader({ title, description, actions, eyebrow, className, }: SectionHeaderProps): react.JSX.Element;
5335
+ declare function SectionHeader({ title, description, actions, eyebrow, as: TitleTag, className, }: SectionHeaderProps): react.JSX.Element;
3144
5336
 
3145
5337
  interface SegmentedFieldOption {
3146
5338
  /** The option's value, reported to `onValueChange`. */
@@ -3265,10 +5457,79 @@ declare function SheetFooter({ className, ...props }: HTMLAttributes<HTMLDivElem
3265
5457
  declare const SheetTitle: react.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & react.RefAttributes<HTMLHeadingElement>, "ref"> & react.RefAttributes<HTMLHeadingElement>>;
3266
5458
  declare const SheetDescription: react.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & react.RefAttributes<HTMLParagraphElement>, "ref"> & react.RefAttributes<HTMLParagraphElement>>;
3267
5459
 
5460
+ interface SideDockProps extends Omit<ComponentProps<"aside">, "title"> {
5461
+ /**
5462
+ * The dock's name. Rendered as its header heading, and as the `SheetTitle`
5463
+ * of the overlay presentation. REQUIRED: the overlay cannot be accessible
5464
+ * without it, and an optional prop with a generic default would ship a
5465
+ * meaningless announced name into real apps.
5466
+ */
5467
+ title: ReactNode;
5468
+ /**
5469
+ * Optional longer description. Visible under the title in the column
5470
+ * presentation; `sr-only` in the overlay presentation (the compact sheet
5471
+ * header has no room for it, but it still reaches assistive tech).
5472
+ */
5473
+ description?: ReactNode;
5474
+ /** Optional controls placed in the header row beside the built-in close button. */
5475
+ headerActions?: ReactNode;
5476
+ /** Controlled open state. Closed means zero width (content stays mounted, inert). */
5477
+ open?: boolean;
5478
+ /** Uncontrolled initial open state. Default `false` — a dock is summoned. */
5479
+ defaultOpen?: boolean;
5480
+ /** Called with the next open state. */
5481
+ onOpenChange?: (open: boolean) => void;
5482
+ /** Which edge it docks to. Default `"right"`. */
5483
+ side?: "left" | "right";
5484
+ /**
5485
+ * `width`, `defaultWidth`, `minWidth`, `maxWidth`, `minContentWidth` and
5486
+ * `resizable` (below) govern the COLUMN presentation only — viewport at or
5487
+ * above `overlayBreakpoint`. Below that breakpoint the dock renders as an
5488
+ * overlay `Sheet` sized by the viewport (`Sheet`'s own `w-3/4 max-w-sm`),
5489
+ * so none of these props have any effect there.
5490
+ */
5491
+ /** Controlled width in px. */
5492
+ width?: number;
5493
+ /** Uncontrolled initial width in px. Default `400`. */
5494
+ defaultWidth?: number;
5495
+ /** Fires continuously during a resize — drive layout from this. */
5496
+ onWidthChange?: (width: number) => void;
5497
+ /** Fires once when an interaction ends — PERSIST from this. */
5498
+ onWidthCommit?: (width: number) => void;
5499
+ /** Lower bound in px. Default `320`. */
5500
+ minWidth?: number;
5501
+ /** Upper bound in px. Default `640`. */
5502
+ maxWidth?: number;
5503
+ /** Content width preserved when clamping against the live viewport, px. Default `480`. */
5504
+ minContentWidth?: number;
5505
+ /** Whether the resize handle renders. Default `true`. */
5506
+ resizable?: boolean;
5507
+ /**
5508
+ * Viewport width in px below which the dock renders as an overlay `Sheet`
5509
+ * instead of a column. Default `1100`. Deliberately ABOVE the library's
5510
+ * 768px mobile breakpoint: a 400px dock at 768px leaves ~360px of content.
5511
+ * This is the switch point for the column-only sizing props above — the
5512
+ * overlay presentation ignores them entirely.
5513
+ */
5514
+ overlayBreakpoint?: number;
5515
+ }
5516
+ declare const SideDock: react.ForwardRefExoticComponent<Omit<SideDockProps, "ref"> & react.RefAttributes<HTMLElement>>;
5517
+
3268
5518
  type SkeletonProps = HTMLAttributes<HTMLDivElement>;
3269
5519
  /** Loading placeholder. Compose with width/height utilities, e.g. `h-4 w-32`. */
3270
5520
  declare function Skeleton({ className, ...props }: SkeletonProps): react.JSX.Element;
3271
5521
 
5522
+ interface SkipLinkProps extends ComponentProps<"a"> {
5523
+ /** The id of the landmark to jump to. Defaults to "main-content". */
5524
+ targetId?: string;
5525
+ }
5526
+ /**
5527
+ * The first focusable element of an application: invisible until focused, then a
5528
+ * token-styled pill pinned to the top-start corner. Give the target element
5529
+ * `id={targetId}` and `tabIndex={-1}` so focus actually lands there.
5530
+ */
5531
+ declare const SkipLink: react.ForwardRefExoticComponent<Omit<SkipLinkProps, "ref"> & react.RefAttributes<HTMLAnchorElement>>;
5532
+
3272
5533
  /** Props for a single `SliderPrimitive.Thumb` — see `SliderProps["thumbProps"]`. */
3273
5534
  type SliderThumbProps = ComponentPropsWithoutRef<typeof SliderPrimitive.Thumb>;
3274
5535
  type SliderProps = ComponentPropsWithoutRef<typeof SliderPrimitive.Root> & {
@@ -3450,11 +5711,29 @@ interface StatePanelProps extends VariantProps<typeof statePanelVariants> {
3450
5711
  /** Supporting description below the title. */
3451
5712
  description?: ReactNode;
3452
5713
  /**
3453
- * Icon or illustration shown above the title.
3454
- * For `"error"` defaults to a built-in warning triangle.
3455
- * For `"loading"` defaults to an animated spinner.
5714
+ * Icon shown above the title, clamped to a uniform 40×40 so mismatched
5715
+ * glyphs stay tidy. For `"error"` defaults to a built-in warning triangle.
5716
+ * For `"loading"` defaults to an animated spinner. Ignored when
5717
+ * `illustration` is also provided — see `illustration`.
3456
5718
  */
3457
5719
  icon?: ReactNode;
5720
+ /**
5721
+ * A larger illustration (one of `@elabs-ai/components-ui`'s shipped
5722
+ * `*Illustration` components, or a consumer's own `ReactNode`) shown above
5723
+ * the title instead of `icon`. Unlike `icon`, it is **not** clamped to
5724
+ * 40×40 — an illustration governs its own size (see each illustration's
5725
+ * `size` prop, `rem`-based, ~64px–160px). Takes precedence over `icon`
5726
+ * when both are given.
5727
+ */
5728
+ illustration?: ReactNode;
5729
+ /**
5730
+ * Heading level for the panel's title (#328 convention). Set this to the
5731
+ * level that correctly follows whatever heading precedes this panel in
5732
+ * the document outline — e.g. `"h3"` inside a `ChartCard` whose own title
5733
+ * is an `<h2>`.
5734
+ * @default "h3"
5735
+ */
5736
+ titleAs?: "div" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
3458
5737
  /** Accessible label for the spinner in loading state. @default "Loading…" */
3459
5738
  loadingLabel?: string;
3460
5739
  /** Spinner size (loading kind only). @default "md" */
@@ -3468,113 +5747,28 @@ interface StatePanelProps extends VariantProps<typeof statePanelVariants> {
3468
5747
  * Replaces the three separate `EmptyState` / `ErrorState` / `LoadingState` components
3469
5748
  * while keeping those as back-compat thin wrappers.
3470
5749
  */
3471
- declare function StatePanel({ kind, title, description, icon, loadingLabel, size, actions, className, }: StatePanelProps): react.JSX.Element;
3472
-
3473
- /** The canonical, closed 7-state status enum (research 10 §B.1). */
3474
- declare const STATUSES: readonly ["pending", "running", "complete", "awaiting-approval", "denied", "failed", "skipped"];
3475
- type Status = (typeof STATUSES)[number];
3476
- /** Closed tone set for the out-of-vocabulary escape hatch (CALM treatments only). */
3477
- declare const STATUS_TONES: readonly ["neutral", "info", "success", "warning", "destructive"];
3478
- type StatusTone = (typeof STATUS_TONES)[number];
3479
- /**
3480
- * An out-of-vocabulary status. Prefer the canonical `Status` enum; reach for
3481
- * this only when the domain genuinely has a state the 7 do not express (e.g. a
3482
- * run engine's `stopped_guardrail`). Map it ONCE, near your domain — not per
3483
- * call site.
3484
- */
3485
- interface CustomStatus {
3486
- label: string;
3487
- tone: StatusTone;
3488
- /** Optional Lucide glyph. Omitted → label-only (no default glyph). */
3489
- icon?: LucideIcon;
3490
- }
3491
- /** Narrows `Status | CustomStatus` — the object form is always the escape hatch. */
3492
- declare function isCustomStatus(status: Status | CustomStatus): status is CustomStatus;
3493
- /**
3494
- * The canonical semantic ROLE per status — the single source of truth for
3495
- * status colour (#392). Any other status-keyed colour map in the repo
3496
- * (`Timeline`'s `NODE_STYLE`, or a future one) must be TESTED against this,
3497
- * not hand-authored — a second literal copy is exactly how `NODE_STYLE`
3498
- * drifted (`running` rendered `--primary` while this map said `--info`).
3499
- * Do NOT interpolate `bg-${STATUS_ROLE[status]}` into a class map: Tailwind
3500
- * scans source statically, so a template-literal class emits no CSS. Keep
3501
- * consuming maps as literal class strings, verified against this export by a
3502
- * test.
3503
- */
3504
- declare const STATUS_ROLE: {
3505
- readonly pending: "secondary";
3506
- readonly running: "info";
3507
- readonly complete: "success";
3508
- readonly "awaiting-approval": "warning";
3509
- readonly denied: "muted";
3510
- readonly failed: "destructive";
3511
- readonly skipped: "secondary";
3512
- };
3513
- /** Default human-readable label per status (override via `children`). */
3514
- declare const STATUS_LABELS: Record<Status, string>;
3515
- /**
3516
- * Lucide glyph per out-of-vocabulary TONE — the same five-tone escape hatch
3517
- * `CustomStatus` uses (`STATUS_TONES`). A consumer that encodes a bare TONE
3518
- * with no fuller `Status` semantics (e.g. `@elabs-ai/components-flow`'s `FlowNode.tone`,
3519
- * #387) derives its non-colour cue from here instead of inventing a second
3520
- * icon vocabulary — each entry reuses the SAME icon `STATUS_ICONS` already
3521
- * pairs with that tone's one canonical status (`success`→`complete`'s
3522
- * `CheckCircle2`, `warning`→`awaiting-approval`'s `Clock`,
3523
- * `destructive`→`failed`'s `AlertCircle`). `neutral`/`info` have no entry:
3524
- * nothing consumes them yet, and reaching for a glyph on every neutral/
3525
- * default-toned element would be assistive-tech noise on the common case —
3526
- * extend this map, don't fork a new one, the day something needs them.
3527
- */
3528
- declare const STATUS_TONE_ICONS: Partial<Record<StatusTone, LucideIcon>>;
3529
- interface StatusIconProps extends Omit<LucideProps, "ref"> {
3530
- /** The canonical execution status (closed enum). */
3531
- status: Status;
3532
- }
3533
- /**
3534
- * The icon + status-color atom `StatusBadge` itself composes — for tight rows
3535
- * (test-result rows, timeline/rail nodes) where a full badge is too heavy.
3536
- * Decorative by default (`aria-hidden`); the adjacent row text must carry the
3537
- * status name for AT users.
3538
- */
3539
- declare const StatusIcon: react.ForwardRefExoticComponent<StatusIconProps & react.RefAttributes<SVGSVGElement>>;
3540
- declare const statusBadgeVariants: (props?: ({
3541
- status?: "running" | "pending" | "complete" | "awaiting-approval" | "denied" | "failed" | "skipped" | null | undefined;
3542
- tone?: "success" | "warning" | "destructive" | "info" | "neutral" | null | undefined;
3543
- size?: "md" | "sm" | null | undefined;
3544
- } & class_variance_authority_types.ClassProp) | undefined) => string;
3545
- interface StatusBadgeProps extends HTMLAttributes<HTMLSpanElement>, Omit<VariantProps<typeof statusBadgeVariants>, "status" | "tone"> {
3546
- /** The canonical execution status, or a mapped out-of-vocabulary one (#363). */
3547
- status: Status | CustomStatus;
3548
- /** Render label-only (no status icon). */
3549
- hideIcon?: boolean;
3550
- }
3551
- declare const StatusBadge: react.ForwardRefExoticComponent<StatusBadgeProps & react.RefAttributes<HTMLSpanElement>>;
3552
- /** The editor/markdown `Timeline` 3-state vocabulary (`@elabs-ai/components-editor`). */
3553
- type TimelineStatus = "done" | "active" | "pending";
3554
- /**
3555
- * Map the Timeline `done|active|pending` vocabulary onto the canonical
3556
- * `Status` (research 10 §B.1 mapping b — lossless; the timeline only
3557
- * expresses 3 of the 7 states). The AI-SDK `ToolUIPart` mapper lives in
3558
- * `@elabs-ai/components-ai` (`statusFromToolState`, tool.tsx) so `@elabs-ai/components-ui` stays free of
3559
- * the `ai` dependency (D6).
3560
- */
3561
- declare function fromTimelineStatus(status: TimelineStatus): Status;
5750
+ declare function StatePanel({ kind, title, description, icon, illustration, titleAs: Tag, loadingLabel, size, actions, className, }: StatePanelProps): react.JSX.Element;
3562
5751
 
3563
5752
  /**
3564
5753
  * Per-pane surface tone — the ground-offset tiering axis (research 08 §H, #193).
3565
5754
  * `plain` keeps the ambient ground (default; non-breaking). `card` RAISES the pane as
3566
- * a white `bg-card` + `shadow-sm` and is robust across all three themes — a card is
5755
+ * a white `bg-card` + `shadow-sm` and is robust across every theme — a card is
3567
5756
  * lighter than the page ground in BOTH light and dark, so it always reads as raised.
3568
5757
  * `muted` (`bg-surface-muted`) reads as a recessed well ONLY in light themes; in dark
3569
5758
  * themes `--surface-muted` is lighter than `--card`, so a `muted` pane reads as a faint
3570
5759
  * raised tint, not a recess (dark-mode layering only goes UP — there is no surface below
3571
5760
  * the page ground). For a guaranteed cross-theme raise/recess contrast, raise the focus
3572
5761
  * pane with `card` and leave the other `plain`.
5762
+ *
5763
+ * Exported so the same tone system reaches a `Layout/Resizable` pane — a draggable
5764
+ * `ResizablePanel` composes `splitPaneVariants({ tone })` for the identical ground-offset
5765
+ * tiering `SplitPanel` gives its `startTone`/`endTone`, instead of a hand-rolled second
5766
+ * copy of these three classes. See `Layout/Resizable`'s `Tiered` story.
3573
5767
  */
3574
- declare const paneToneVariants: (props?: ({
3575
- tone?: "card" | "muted" | "plain" | null | undefined;
5768
+ declare const splitPaneVariants: (props?: ({
5769
+ tone?: "muted" | "card" | "plain" | null | undefined;
3576
5770
  } & class_variance_authority_types.ClassProp) | undefined) => string;
3577
- type SplitPanelTone = NonNullable<VariantProps<typeof paneToneVariants>["tone"]>;
5771
+ type SplitPanelTone = NonNullable<VariantProps<typeof splitPaneVariants>["tone"]>;
3578
5772
  interface SplitPanelProps {
3579
5773
  start: ReactNode;
3580
5774
  end: ReactNode;
@@ -3597,8 +5791,12 @@ interface SplitPanelProps {
3597
5791
  }
3598
5792
  /**
3599
5793
  * Two-pane layout for master/detail, editor/preview and inspector workflows.
3600
- * Static sizing by design (predictable in tests/SSR); for drag-to-resize wrap
3601
- * with a resize hook or compose `react-resizable-panels` at the app level.
5794
+ * Static sizing by design (predictable in tests/SSR) `startSize` is a CSS grid
5795
+ * track (`"320px"`, `"40%"`, `"1fr"`), not a percentage. For panes the user can
5796
+ * drag to resize, reach for `Layout/Resizable`'s `ResizablePanelGroup`/
5797
+ * `ResizablePanel`/`ResizableHandle` instead and apply `splitPaneVariants({ tone })`
5798
+ * to a panel for the same ground-offset tiering. See
5799
+ * [Choosing between similar components](?path=/docs/docs-choosing-between-similar-components--docs).
3602
5800
  *
3603
5801
  * For a master/detail surface where the detail should read as a raised card on a
3604
5802
  * recessed list, use `startTone="muted" endTone="card"` (ground-offset tiering).
@@ -3607,6 +5805,26 @@ declare function SplitPanel({ start, end, direction, startSize, divider, startTo
3607
5805
 
3608
5806
  declare const Switch: react.ForwardRefExoticComponent<Omit<SwitchPrimitive.SwitchProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
3609
5807
 
5808
+ /**
5809
+ * `Table`'s own scroll wrapper, gated on MEASURED overflow (#366).
5810
+ *
5811
+ * `className`/`ref`/`...props` all land on the `<table>` — unchanged, no new
5812
+ * prop — so this wrapper is internal plumbing, not a new public surface. It
5813
+ * follows `DataTable`'s non-virtualized branch verbatim
5814
+ * (`packages/data/src/data-table/data-table.tsx:1658-1695`, #330), the
5815
+ * closest precedent: a plain `overflow-auto` box with no pinned columns, no
5816
+ * loading overlay and no edge fade to carry along, just the keyboard
5817
+ * affordance itself.
5818
+ *
5819
+ * A table that FITS must stay a byte-identical no-op: no `tabIndex`, no
5820
+ * `aria-label`, no ring — an unconditional stop would announce "scrollable"
5821
+ * on content that never scrolls. Only a table that measurably overflows
5822
+ * gets the tab stop, its accessible name (WCAG 4.1.2) and the compound focus
5823
+ * ring (`focus-ring-inset` — the wrapper's own edge is the scroll clip, so an
5824
+ * outside ring would be cut, `.claude/rules/theming.md`). No `role="region"`:
5825
+ * both existing precedents (`DataTable`, `SheetTable`) decided against a
5826
+ * redundant landmark over a real `<table>`, and this wrapper adds none either.
5827
+ */
3610
5828
  declare const Table: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableElement> & react.RefAttributes<HTMLTableElement>>;
3611
5829
  declare const TableHeader: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & react.RefAttributes<HTMLTableSectionElement>>;
3612
5830
  declare const TableBody: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & react.RefAttributes<HTMLTableSectionElement>>;
@@ -3704,8 +5922,8 @@ type ThemeTransitionEffect = "polygon" | "circle" | "circle-blur" | "triangle";
3704
5922
  * Transitions API (the chanhdai.com "theme toggle effect", adapted to brand-ui).
3705
5923
  *
3706
5924
  * - Direction-aware: sets `data-vt="to-dark|to-light"` on `<html>` from the
3707
- * target theme's `dark` flag, so the clip-path wipes the right way for ANY of
3708
- * the three themes (not just light/dark).
5925
+ * target theme's `dark` flag, so the clip-path wipes the right way for ANY
5926
+ * theme (not just light/dark).
3709
5927
  * - `data-vt-effect` selects the reveal shape (default "polygon").
3710
5928
  * - Motion-aware: under `useReducedMotion()` (OS or in-app preference) — or when
3711
5929
  * the browser lacks `startViewTransition` — it falls back to an instant,
@@ -4223,7 +6441,7 @@ declare const TEXT_ROLE_REM: {
4223
6441
  type TextRole = keyof typeof TEXT_ROLE_REM;
4224
6442
  declare const textVariants: (props?: ({
4225
6443
  variant?: "body" | "caption" | "meta" | "kpi" | "code" | "lead" | null | undefined;
4226
- tone?: "default" | "primary" | "muted" | null | undefined;
6444
+ tone?: "default" | "muted" | "primary" | null | undefined;
4227
6445
  } & class_variance_authority_types.ClassProp) | undefined) => string;
4228
6446
  type TextVariant = NonNullable<VariantProps<typeof textVariants>["variant"]>;
4229
6447
  type TextTone = NonNullable<VariantProps<typeof textVariants>["tone"]>;
@@ -4334,6 +6552,22 @@ interface FilterChipProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>,
4334
6552
  * as a sentence fragment out of context (and in a screen reader).
4335
6553
  */
4336
6554
  label: string;
6555
+ /**
6556
+ * Short, non-shrinking secondary text — a count, a unit (`"excluded 1,204"`).
6557
+ * A second text slot rather than folding it into `label` (#284): `label` is
6558
+ * the shrinkable, safe-to-truncate part; `trailing` is short and fixed-width
6559
+ * and must never lose characters to the ellipsis. Same shape as
6560
+ * `TurnStatus`'s and `TerminalWorking`'s `trailing` slot — a fixed-width
6561
+ * companion beside a truncating label. Composed into the accessible name
6562
+ * after `label` (`"Remove filter: <label> · <trailing>"`), so the byte-
6563
+ * identical name from before this slot existed is unchanged.
6564
+ *
6565
+ * Trade-off: `trailing` is `shrink-0`, so an extremely narrow container now
6566
+ * truncates `label` down to nothing before it touches `trailing`. That is
6567
+ * the right default — the count is short and fixed, the label is the long,
6568
+ * prose-shaped part — but it is a choice, not a free win.
6569
+ */
6570
+ trailing?: string;
4337
6571
  /** Remove this filter. The WHOLE chip is the remove control — see below. */
4338
6572
  onRemove: () => void;
4339
6573
  }
@@ -4435,6 +6669,90 @@ interface VirtualSelectProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement
4435
6669
  */
4436
6670
  declare const VirtualSelect: react.ForwardRefExoticComponent<VirtualSelectProps & react.RefAttributes<HTMLButtonElement>>;
4437
6671
 
6672
+ /**
6673
+ * `WorkspacePicker`'s pure, directly-testable logic — kept out of the
6674
+ * component for the same reason `../model-picker/model-picker-state.ts` does
6675
+ * (see that file's header comment): an expression buried in JSX cannot be
6676
+ * unit-tested in isolation, and relative-time arithmetic in particular has
6677
+ * edge cases worth locking down on their own.
6678
+ */
6679
+ /**
6680
+ * One recent workspace. Deliberately a strict subset of `ModelPickerItem`'s
6681
+ * shape (`id` / `name` → `label` / `path` → `description` / `lastOpenedAt` →
6682
+ * a formatted `meta` entry) — see the reuse note in `workspace-picker.tsx`.
6683
+ */
6684
+ interface Workspace {
6685
+ id: string;
6686
+ /** Rendered as the row's primary label and, when current, the trigger text. */
6687
+ name: string;
6688
+ /**
6689
+ * The filesystem path. Long, user-supplied content — the row truncates it,
6690
+ * never wraps or overflows.
6691
+ */
6692
+ path: string;
6693
+ /**
6694
+ * When this workspace was last opened. Rendered as a relative time via
6695
+ * `Intl.RelativeTimeFormat` (`formatLastOpened`, below) — never a
6696
+ * pre-formatted string the caller hands over.
6697
+ */
6698
+ lastOpenedAt?: Date;
6699
+ }
6700
+ /**
6701
+ * "2 hours ago" / "in 3 minutes" / "yesterday" — `Intl.RelativeTimeFormat`
6702
+ * picks the coarsest unit (minutes → hours → days) that still reads
6703
+ * naturally, instead of e.g. "127 minutes ago".
6704
+ *
6705
+ * @param now - injection seam for tests; defaults to the real clock.
6706
+ */
6707
+ declare function formatLastOpened(date: Date, locale: string, now?: number): string;
6708
+
6709
+ interface WorkspacePickerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
6710
+ /** Recent workspaces, most-relevant first — the caller owns ordering. */
6711
+ workspaces: Workspace[];
6712
+ /** The currently open workspace's id. */
6713
+ currentId?: string;
6714
+ /** Fires with the chosen workspace; the popover closes first. */
6715
+ onSelect?: (workspace: Workspace) => void;
6716
+ /**
6717
+ * Free-text path entry, rendered in `ModelPicker`'s `footer` slot below the
6718
+ * list. Fires with the raw string the user typed once it validates as
6719
+ * non-empty — this component performs no filesystem access of any kind
6720
+ * (presentation layer, D5); resolving, normalizing or checking the path is
6721
+ * the caller's job.
6722
+ */
6723
+ onSubmitPath?: (path: string) => void;
6724
+ /**
6725
+ * Drives the same four-body state grid as `ModelPicker` — see
6726
+ * `ModelPickerStatus`. Default `"ready"`, inherited from `ModelPicker`.
6727
+ */
6728
+ status?: ModelPickerStatus;
6729
+ disabled?: boolean;
6730
+ /** Accessible name for the trigger and the popover — what the control is FOR. */
6731
+ "aria-label"?: string;
6732
+ /** Controlled popover open state — see `ModelPicker`'s controlled contract. */
6733
+ open?: boolean;
6734
+ onOpenChange?: (open: boolean) => void;
6735
+ }
6736
+ /**
6737
+ * Recent-workspace switcher — issue #111, decided in
6738
+ * `docs/decisions/2026-09-01-brainless-adoption-architecture.md` § 7.
6739
+ *
6740
+ * A `ModelPicker` PRESET, not a new picker: `ModelPickerItem`'s
6741
+ * `id`/`label`/`description`/`meta` shape is already a superset of what a
6742
+ * workspace needs, so this component only supplies workspace-shaped
6743
+ * defaults — it maps `path` into the truncating `description` slot, formats
6744
+ * `lastOpenedAt` with `Intl.RelativeTimeFormat`, marks the current workspace
6745
+ * in the row's TEXT (never colour alone — `ModelPicker`'s check glyph is
6746
+ * `aria-hidden` and cannot carry that on its own), and renders the free-text
6747
+ * path entry into `ModelPicker`'s `footer` slot so it sits below the list,
6748
+ * un-filtered by the search query.
6749
+ *
6750
+ * Unlike `TeamSwitcher`, this has no `Sidebar` dependency — it works anywhere
6751
+ * a picker is needed (a session launch card, a command palette), not only
6752
+ * inside a sidebar.
6753
+ */
6754
+ declare const WorkspacePicker: react.ForwardRefExoticComponent<WorkspacePickerProps & react.RefAttributes<HTMLDivElement>>;
6755
+
4438
6756
  interface WizardStepMeta {
4439
6757
  /** Stable id for the step. */
4440
6758
  id: string;
@@ -4494,4 +6812,4 @@ interface WizardNavProps extends HTMLAttributes<HTMLDivElement> {
4494
6812
  /** WizardNav — Back / Next (or Finish on the last step) controls. */
4495
6813
  declare const WizardNav: react.ForwardRefExoticComponent<WizardNavProps & react.RefAttributes<HTMLDivElement>>;
4496
6814
 
4497
- export { ATTRIBUTIONS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AdvancedGroup, type AdvancedGroupProps, Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, type AlertTitleProps, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, type Attribution, type AttributionCategory, AttributionPanel, type AttributionPanelProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BentoGrid, BentoGridItem, type BentoGridItemProps, type BentoGridItemVariants, type BentoGridProps, type BentoGridSize, BoundedNumber, type BoundedNumberProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, type ButtonProps, CATEGORY_LABEL, COLOR_TOKENS, COPY_FEEDBACK_MS, Calendar, type CalendarProps, Card, CardAction, CardContent, CardDescription, type CardDescriptionProps, CardFooter, CardHeader, type CardProps, CardTitle, type CardTitleProps, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChangeHunk, type ChangeHunkStatus, type ChangeProvenance, ChangeReview, type ChangeReviewActions, ChangeReviewHeader, type ChangeReviewHeaderProps, ChangeReviewHunk, type ChangeReviewHunkProps, ChangeReviewList, type ChangeReviewListProps, type ChangeReviewProps, ChangeReviewProvenance, type ChangeReviewProvenanceProps, ChangeReviewProvider, type ChangeReviewProviderProps, type ChangeReviewState, Checkbox, Collapsible, CollapsibleContent, type CollapsiblePanelAttrs, type CollapsiblePanelSide, type CollapsiblePanelState, CollapsibleTrigger, ColorPicker, type ColorPickerProps, type ColorToken, Combobox, type ComboboxOption, type ComboboxProps, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, type CommandProps, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, type CopyToClipboard, CopyableValue, type CopyableValueProps, type CustomStatus, DEFAULT_MESSAGES, DOCUMENT_ADDRESS_KINDS, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type DateRangePreset, Descriptions, DescriptionsItem, type DescriptionsItemProps, type DescriptionsProps, Dialog, DialogBody, type DialogBodyProps, DialogClose, DialogContent, DialogDescription, type DialogDismissGuard, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogSection, type DialogSectionProps, DialogTitle, DialogTrigger, type DocumentAddress, type DocumentAddressKind, type DocumentRect, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, ExpandDialog, ExpandDialogContent, type ExpandDialogContentProps, ExpandDialogHeader, type ExpandDialogHeaderProps, ExpandDialogPanes, type ExpandDialogPanesProps, type ExpandDialogProps, FILE_CATEGORY_ICONS, FieldRow, type FieldRowProps, type FileCategory, type FileKind, type FileSource, FileUpload, FileUploadDropzone, type FileUploadDropzoneProps, FileUploadItem, type FileUploadItemProps, FileUploadList, type FileUploadListProps, type FileUploadProps, type FileUploadStatus, FilterChip, type FilterChipProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Heading, type HeadingLevel, type HeadingProps, type HeadingSize, HoverCard, HoverCardContent, HoverCardTrigger, IconButton, type IconButtonProps, type IconButtonSize, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, type InputGroupProps, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, type InsertMentionResult, Kbd, KeyValueEditor, type KeyValueEditorProps, type KeyValueRow, Label, LinkPreview, LinkPreviewCard, type LinkPreviewCardProps, ListEditor, type ListEditorProps, LoadingState, type LoadingStateProps, type LocaleContextValue, LocaleProvider, type LocaleProviderProps, MatchHighlight, type MatchHighlightProps, type MatchRange, type Mention, MentionInput, MentionInputContent, type MentionInputContentProps, type MentionInputContextValue, MentionInputEmpty, type MentionInputEmptyProps, MentionInputItem, type MentionInputItemProps, MentionInputList, type MentionInputListProps, type MentionInputProps, MentionInputTextarea, type MentionInputTextareaProps, type MentionOption, type MentionValue, Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type Messages, MetricCard, type MetricCardEmphasis, type MetricCardProps, ModelPicker, type ModelPickerBody, type ModelPickerGroup, type ModelPickerItem, type ModelPickerProps, type ModelPickerStatus, NavMain, type NavMainProps, type NavMainRoute, type NavMainSubItem, type NavNotification, NavNotifications, type NavNotificationsProps, NavUser, type NavUserProps, type NavUserUser, NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NormalizedText, NumberInput, type NumberInputProps, PROSE_HEADING_REM, PROSE_HEADING_TRACKING, PROSE_HEADING_WEIGHT, PageShell, type PageShellProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, type ProgressProps, ProseBlockquote, ProseHeading, type ProseHeadingLevel, type ProseHeadingProps, ProseInlineCode, ProseLink, type ProseLinkProps, ProseList, ProseListItem, type ProseListProps, ProseText, type ProseTextProps, type QuoteAddress, RadioGroup, RadioGroupItem, type RangeAddress, Rating, type RatingProps, type RectAddress, ResizableHandle, ResizablePanel, ResizablePanelGroup, type ResolvedFileSource, ResultCount, type ResultCountProps, Reveal, RevealGroup, type RevealGroupProps, type RevealProps, type Revision, type RevisionBranch, type RevisionEdge, RevisionTimeline, type RevisionTimelineDensity, type RevisionTimelineProps, STATUSES, STATUS_LABELS, STATUS_ROLE, STATUS_TONES, STATUS_TONE_ICONS, STREAMDOWN_TRANSLATION_KEYS, ScrollArea, ScrollBar, SectionHeader, type SectionHeaderProps, SegmentedField, type SegmentedFieldOption, type SegmentedFieldProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, type SeparatorProps, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, type SkeletonProps, Slider, SliderNumber, type SliderNumberProps, type SliderProps, type SliderThumbProps, Spinner, type SpinnerProps, SplitPanel, type SplitPanelProps, type SplitPanelTone, StatePanel, type StatePanelProps, type Status, StatusBadge, type StatusBadgeProps, StatusIcon, type StatusIconProps, type StatusTone, type StreamdownTranslationKey, type StreamdownTranslationMap, Switch, TEXT_ROLE_REM, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagInput, type TagInputProps, TeamSwitcher, type TeamSwitcherProps, type TeamSwitcherTeam, Text, type TextProps, type TextRole, type TextTone, type TextVariant, Textarea, type TextareaProps, type ThemePreference, ThemeSwitcher, type ThemeSwitcherProps, type ThemeTransitionEffect, Timeline, type TimelineEntry, TimelineItem, type TimelineItemProps, type TimelineProps, TimelineRoot, type TimelineRootProps, type TimelineStatus, Toaster, type ToasterProps, Toggle, ToggleGroup, ToggleGroupItem, Toolbar, ToolbarButton, type ToolbarButtonProps, type ToolbarProps, ToolbarSeparator, type ToolbarSeparatorProps, ToolbarSlot, ToolbarToggleGroup, type ToolbarToggleGroupProps, ToolbarToggleItem, type ToolbarToggleItemProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNav, type TopNavProps, Transfer, type TransferItem, type TransferProps, Tree, type TreeNode, type TreeProps, TreeSelect, type TreeSelectProps, type UploadFile, type UseCollapsiblePanelOptions, type UseCollapsiblePanelReturn, type UseCopyToClipboardOptions, type UseDialogDismissGuardOptions, type UseTreeKeyboardOptions, type UseTreeKeyboardResult, ViewToolbar, ViewToolbarFilters, type ViewToolbarFiltersProps, type ViewToolbarProps, VirtualSelect, type VirtualSelectOption, type VirtualSelectProps, Wizard, WizardNav, type WizardNavProps, type WizardProps, WizardStep, type WizardStepMeta, type WizardStepProps, WizardSteps, type WizardStepsProps, type WizardValidator, alertVariants, badgeVariants, bentoGridItemVariants, buttonGroupVariants, buttonVariants, cardVariants, cn, countItems, defaultMentionFilter, dialogContentVariants, downloadBlob, downloadUrl, expandDialogPanesVariants, extensionOf, fileIconFor, fromTimelineStatus, headingVariants, hunkVariants, inputGroupAddonVariants, inputGroupVariants, insertMention, isCustomStatus, laneColor, mediaTypeFromName, mentionAt, mentionEnd, modelPickerBody, navigationMenuTriggerStyle, normalizeFileSource, normalizeQuoteText, normalizeQuoteTextWithOffsets, normalizeRanges, progressIndicatorVariants, queryToRanges, remapMentions, resolveFileKind, revealVariants, revisionTimelineVariants, serializeMentions, showsInlineError, sidebarMenuButtonVariants, statePanelVariants, statusBadgeVariants, textVariants, toggleVariants, toolbarVariants, useCollapsiblePanel, useCommandActiveItemId, useCopyToClipboard, useDialogDismissGuard, useFileUpload, useFormField, useIsMobile, useLocale, useMentionInput, useSidebar, useStreamdownTranslations, useThemeTransition, useTreeKeyboard, useVirtualListbox };
6815
+ export { APPROVAL_SCOPE_DESCRIPTION_KEYS, ATTRIBUTIONS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AdvancedGroup, type AdvancedGroupProps, type AgentEventOutcome, type AgentEventPhase, Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, type AlertTitleProps, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, type ApprovalOption, type ApprovalScope, AspectRatio, type Attribution, type AttributionCategory, AttributionPanel, type AttributionPanelProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BentoGrid, BentoGridItem, type BentoGridItemProps, type BentoGridItemVariants, type BentoGridProps, type BentoGridSize, type BooleanFieldSpec, BoundedNumber, type BoundedNumberProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, type ButtonProps, CATEGORY_LABEL, COLOR_TOKENS, COPY_FEEDBACK_MS, Calendar, type CalendarProps, Card, CardAction, CardContent, CardDescription, type CardDescriptionProps, CardFooter, CardHeader, type CardProps, CardTitle, type CardTitleProps, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChangeHunk, type ChangeHunkStatus, type ChangeProvenance, ChangeReview, type ChangeReviewActions, ChangeReviewHeader, type ChangeReviewHeaderProps, ChangeReviewHunk, type ChangeReviewHunkProps, ChangeReviewList, type ChangeReviewListProps, type ChangeReviewProps, ChangeReviewProvenance, type ChangeReviewProvenanceProps, ChangeReviewProvider, type ChangeReviewProviderProps, type ChangeReviewState, type CheckResult, type CheckSummary, Checkbox, Collapsible, CollapsibleContent, type CollapsiblePanelAttrs, type CollapsiblePanelSide, type CollapsiblePanelState, CollapsibleTrigger, ColorPicker, type ColorPickerProps, type ColorToken, Combobox, type ComboboxOption, type ComboboxProps, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, type CommandProps, CommandSeparator, CommandShortcut, CommandTrigger, type CommandTriggerProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextRail, type ContextRailProps, type ContextRailSection, type CopyToClipboard, CopyableValue, type CopyableValueProps, type CustomStatus, DEFAULT_MESSAGES, DOCUMENT_ADDRESS_KINDS, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type DateRangePreset, Descriptions, DescriptionsItem, type DescriptionsItemProps, type DescriptionsProps, Dialog, DialogBody, type DialogBodyProps, DialogClose, DialogContent, DialogDescription, type DialogDismissGuard, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogSection, type DialogSectionProps, DialogTitle, DialogTrigger, type DiffLine, type DiffLineType, type DiffRow, type DocumentAddress, type DocumentAddressKind, type DocumentRect, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type EffortLevel, EmptyListIllustration, EmptyState, type EmptyStateProps, type EnumFieldSpec, type EnumOption, ErrorIllustration, ErrorState, type ErrorStateProps, ExpandDialog, ExpandDialogContent, type ExpandDialogContentProps, ExpandDialogHeader, type ExpandDialogHeaderProps, ExpandDialogPanes, type ExpandDialogPanesProps, type ExpandDialogProps, FILE_CATEGORY_ICONS, FieldControl, type FieldControlProps, FieldDescription, FieldError, type FieldKeyValueRow, FieldLabel, FieldRoot, type FieldRootProps, FieldRow, type FieldRowProps, type FieldSpec, type FileCategory, type FileFieldSpec, type FileIssue, type FileKind, type FileSource, FileUpload, FileUploadDropzone, type FileUploadDropzoneProps, FileUploadItem, type FileUploadItemProps, FileUploadList, type FileUploadListProps, type FileUploadProps, type FileUploadStatus, FilterChip, type FilterChipProps, type FindTriggerQueryOptions, FirstRunIllustration, type FormSpec, type FormSubmitState, type FormValue, type FormValues, type FromJsonSchemaOptions, type GroupFieldSpec, type GroupItemSpec, Heading, type HeadingLevel, type HeadingProps, type HeadingSize, HoverCard, HoverCardContent, HoverCardTrigger, ILLUSTRATION_ACCENT_VAR, IconButton, type IconButtonProps, type IconButtonSize, type IllustrationProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, type InputGroupProps, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, type InsertMentionResult, type IntegerFieldSpec, Kbd, KeyValueEditor, type KeyValueEditorProps, type KeyValueFieldSpec, type KeyValueRow, KeyboardShortcuts, type KeyboardShortcutsProps, Label, LinkPreview, LinkPreviewCard, type LinkPreviewCardProps, ListEditor, type ListEditorProps, type ListFieldSpec, LoadingState, type LoadingStateProps, type LocaleContextValue, LocaleProvider, type LocaleProviderProps, MatchHighlight, type MatchHighlightProps, type MatchRange, type Mention, MentionInput, MentionInputContent, type MentionInputContentProps, type MentionInputContextValue, MentionInputEmpty, type MentionInputEmptyProps, MentionInputItem, type MentionInputItemProps, MentionInputList, type MentionInputListProps, type MentionInputProps, MentionInputTextarea, type MentionInputTextareaProps, type MentionOption, type MentionValue, Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type MessageValue, type Messages, MetricCard, type MetricCardEmphasis, type MetricCardProps, ModelPicker, type ModelPickerBody, type ModelPickerGroup, type ModelPickerItem, type ModelPickerProps, type ModelPickerStatus, type MultiEnumFieldSpec, NavMain, type NavMainProps, type NavMainRoute, type NavMainSubItem, type NavNotification, NavNotifications, type NavNotificationsProps, NavUser, type NavUserProps, type NavUserUser, NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NoAccessIllustration, NoResultsIllustration, type NormalizedFormSpec, type NormalizedText, type NumberFieldSpec, NumberInput, type NumberInputProps, OfflineIllustration, type OperatingMode, PROSE_HEADING_REM, PROSE_HEADING_TRACKING, PROSE_HEADING_WEIGHT, PageShell, type PageShellProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, type PluralCategory, type PluralMessage, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, type ProgressProps, ProseBlockquote, ProseHeading, type ProseHeadingLevel, type ProseHeadingProps, ProseInlineCode, ProseLink, type ProseLinkProps, ProseList, ProseListItem, type ProseListProps, ProseText, type ProseTextProps, type QuoteAddress, RadioGroup, RadioGroupItem, type RangeAddress, Rating, type RatingProps, type RectAddress, ResizableHandle, ResizablePanel, ResizablePanelGroup, type ResolvedFileSource, ResultCount, type ResultCountProps, Reveal, RevealGroup, type RevealGroupProps, type RevealProps, type Revision, type RevisionBranch, type RevisionEdge, RevisionTimeline, type RevisionTimelineDensity, type RevisionTimelineProps, STATUSES, STATUS_LABELS, STATUS_ROLE, STATUS_TONES, STATUS_TONE_ICONS, STREAMDOWN_TRANSLATION_KEYS, SchemaForm, SchemaFormDescription, type SchemaFormDescriptionProps, SchemaFormError, type SchemaFormErrorProps, SchemaFormFallback, type SchemaFormFallbackProps, SchemaFormField, type SchemaFormFieldProps, SchemaFormFields, type SchemaFormFieldsProps, type SchemaFormProps, SchemaFormProvider, type SchemaFormProviderProps, SchemaFormRoot, type SchemaFormRootProps, SchemaFormSubmit, type SchemaFormSubmitProps, SchemaFormTestAction, type SchemaFormTestActionProps, type SchemaFormTestActionStatus, SchemaFormTitle, type SchemaFormTitleProps, ScrollArea, ScrollBar, SectionHeader, type SectionHeaderProps, SegmentedField, type SegmentedFieldOption, type SegmentedFieldProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, type SeparatorProps, type SessionCapability, type SessionQuickAction, type SessionWhatsNewItem, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger, type Shortcut, type ShortcutGroup, SideDock, type SideDockProps, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, type SidebarInsetGutter, type SidebarInsetProps, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, type SkeletonProps, SkipLink, type SkipLinkProps, type SlashCommand, Slider, SliderNumber, type SliderNumberProps, type SliderProps, type SliderThumbProps, Spinner, type SpinnerProps, SplitPanel, type SplitPanelProps, type SplitPanelTone, StatePanel, type StatePanelProps, type Status, StatusBadge, type StatusBadgeProps, StatusIcon, type StatusIconProps, type StatusTone, type StreamdownTranslationKey, type StreamdownTranslationMap, type StringFieldSpec, SuccessIllustration, Switch, TEXT_ROLE_REM, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagInput, type TagInputProps, TeamSwitcher, type TeamSwitcherProps, type TeamSwitcherTeam, Text, type TextProps, type TextRole, type TextTone, type TextVariant, Textarea, type TextareaProps, type ThemePreference, ThemeSwitcher, type ThemeSwitcherProps, type ThemeTransitionEffect, Timeline, type TimelineEntry, TimelineItem, type TimelineItemProps, type TimelineProps, TimelineRoot, type TimelineRootProps, type TimelineStatus, Toaster, type ToasterProps, Toggle, ToggleGroup, ToggleGroupItem, Toolbar, ToolbarButton, type ToolbarButtonProps, type ToolbarProps, ToolbarSeparator, type ToolbarSeparatorProps, ToolbarSlot, ToolbarToggleGroup, type ToolbarToggleGroupProps, ToolbarToggleItem, type ToolbarToggleItemProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopNav, type TopNavProps, Transfer, type TransferItem, type TransferProps, Tree, type TreeNode, type TreeProps, TreeSelect, type TreeSelectProps, type TriggerBoundary, type TriggerQuery, UnsupportedJsonSchemaError, type UploadFile, type UseCollapsiblePanelOptions, type UseCollapsiblePanelReturn, type UseCopyToClipboardOptions, type UseDialogDismissGuardOptions, type UseTreeKeyboardOptions, type UseTreeKeyboardResult, ViewToolbar, ViewToolbarFilters, type ViewToolbarFiltersProps, type ViewToolbarProps, VirtualSelect, type VirtualSelectOption, type VirtualSelectProps, Wizard, WizardNav, type WizardNavProps, type WizardProps, WizardStep, type WizardStepMeta, type WizardStepProps, WizardSteps, type WizardStepsProps, type WizardValidator, type Workspace, WorkspacePicker, type WorkspacePickerProps, agentEventOutcomeStatus, alertVariants, badgeVariants, bentoGridItemVariants, booleanFieldSchema, buttonGroupVariants, buttonVariants, cardVariants, checkFileIssue, cn, collapseDiffRows, collectValidatableFields, countItems, defaultMentionFilter, defaultSlashCommandFilter, dialogContentVariants, diffLineAccessibleLabel, diffLineMarker, downloadBlob, downloadUrl, effortRungForIndex, enumFieldSchema, enumOptionSchema, expandDialogPanesVariants, extensionOf, fieldLabel, fieldSpecSchema, fileFieldSchema, fileIconFor, fileMatchesAccept, findFieldByName, findTriggerQuery, formSpecSchema, formatElapsed, formatLastOpened, fromJsonSchema, fromTimelineStatus, groupFieldSchema, groupItemSchema, headingVariants, hunkVariants, illustrationAccent, initialFormValues, inputGroupAddonVariants, inputGroupVariants, insertMention, integerFieldSchema, isCustomStatus, isFieldVisible, isModuleNotFoundMessage, isOptionalPeerMissing, keyValueFieldSchema, keyValueRowSchema, laneColor, listFieldSchema, mediaTypeFromName, mentionAt, mentionEnd, modelPickerBody, multiEnumFieldSchema, navigationMenuTriggerStyle, normalizeFileSource, normalizeFormSpec, normalizeQuoteText, normalizeQuoteTextWithOffsets, normalizeRanges, numberFieldSchema, optionLabel, optionValue, progressIndicatorVariants, queryToRanges, remapMentions, replaceTriggerRun, resolveFileKind, revealVariants, revisionTimelineVariants, serializeMentions, showsInlineError, sidebarMenuButtonVariants, splitPaneVariants, statePanelVariants, statusBadgeVariants, stepIndex, stringFieldSchema, textVariants, toggleVariants, toolbarVariants, useCollapsiblePanel, useCommandActiveItemId, useCopyToClipboard, useDialogDismissGuard, useDiffRows, useFileUpload, useIsMobile, useLocale, useMentionInput, useSidebar, useStreamdownTranslations, useThemeTransition, useTreeKeyboard, useVirtualListbox, validateField, validateForm };