@tulipfarm/sprout 0.0.0-stage → 0.2.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 (314) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -2
  3. package/dist/components/accordion.d.ts +28 -0
  4. package/dist/components/accordion.js +26 -0
  5. package/dist/components/alert-dialog.d.ts +60 -0
  6. package/dist/components/alert-dialog.js +69 -0
  7. package/dist/components/alert.d.ts +30 -0
  8. package/dist/components/alert.js +35 -0
  9. package/dist/components/aspect-ratio.d.ts +7 -0
  10. package/dist/components/aspect-ratio.js +6 -0
  11. package/dist/components/attachment.d.ts +118 -0
  12. package/dist/components/attachment.js +285 -0
  13. package/dist/components/avatar.d.ts +32 -0
  14. package/dist/components/avatar.js +73 -0
  15. package/dist/components/badge.d.ts +21 -0
  16. package/dist/components/badge.js +27 -0
  17. package/dist/components/brand-icon.d.ts +28 -0
  18. package/dist/components/brand-icon.js +82 -0
  19. package/dist/components/breadcrumb.d.ts +29 -0
  20. package/dist/components/breadcrumb.js +44 -0
  21. package/dist/components/button-group.d.ts +28 -0
  22. package/dist/components/button-group.js +36 -0
  23. package/dist/components/button.d.ts +79 -0
  24. package/dist/components/button.js +93 -0
  25. package/dist/components/calendar.d.ts +27 -0
  26. package/dist/components/calendar.js +107 -0
  27. package/dist/components/canvas.d.ts +78 -0
  28. package/dist/components/canvas.js +180 -0
  29. package/dist/components/card.d.ts +43 -0
  30. package/dist/components/card.js +42 -0
  31. package/dist/components/carousel.d.ts +57 -0
  32. package/dist/components/carousel.js +422 -0
  33. package/dist/components/chart.d.ts +112 -0
  34. package/dist/components/chart.js +172 -0
  35. package/dist/components/chat-confirmation.d.ts +42 -0
  36. package/dist/components/chat-confirmation.js +62 -0
  37. package/dist/components/chat-input.d.ts +94 -0
  38. package/dist/components/chat-input.js +279 -0
  39. package/dist/components/chat-plan.d.ts +21 -0
  40. package/dist/components/chat-plan.js +35 -0
  41. package/dist/components/chat-sources.d.ts +64 -0
  42. package/dist/components/chat-sources.js +66 -0
  43. package/dist/components/checkbox.d.ts +16 -0
  44. package/dist/components/checkbox.js +17 -0
  45. package/dist/components/choice-list.d.ts +53 -0
  46. package/dist/components/choice-list.js +36 -0
  47. package/dist/components/code-block.d.ts +35 -0
  48. package/dist/components/code-block.js +64 -0
  49. package/dist/components/collapsible.d.ts +24 -0
  50. package/dist/components/collapsible.js +27 -0
  51. package/dist/components/combobox.d.ts +95 -0
  52. package/dist/components/combobox.js +106 -0
  53. package/dist/components/command.d.ts +94 -0
  54. package/dist/components/command.js +414 -0
  55. package/dist/components/context-menu.d.ts +57 -0
  56. package/dist/components/context-menu.js +60 -0
  57. package/dist/components/dialog.d.ts +60 -0
  58. package/dist/components/dialog.js +79 -0
  59. package/dist/components/direction.d.ts +6 -0
  60. package/dist/components/direction.js +6 -0
  61. package/dist/components/dropdown-menu.d.ts +62 -0
  62. package/dist/components/dropdown-menu.js +59 -0
  63. package/dist/components/field.d.ts +117 -0
  64. package/dist/components/field.js +150 -0
  65. package/dist/components/file-explorer.d.ts +27 -0
  66. package/dist/components/file-explorer.js +300 -0
  67. package/dist/components/file-viewer.d.ts +137 -0
  68. package/dist/components/file-viewer.js +400 -0
  69. package/dist/components/form.d.ts +87 -0
  70. package/dist/components/form.js +55 -0
  71. package/dist/components/glass-banner.d.ts +27 -0
  72. package/dist/components/glass-banner.js +116 -0
  73. package/dist/components/gradient-banner.d.ts +37 -0
  74. package/dist/components/gradient-banner.js +43 -0
  75. package/dist/components/hover-card.d.ts +27 -0
  76. package/dist/components/hover-card.js +26 -0
  77. package/dist/components/input-group.d.ts +68 -0
  78. package/dist/components/input-group.js +88 -0
  79. package/dist/components/input-otp.d.ts +38 -0
  80. package/dist/components/input-otp.js +43 -0
  81. package/dist/components/input.d.ts +16 -0
  82. package/dist/components/input.js +18 -0
  83. package/dist/components/kbd.d.ts +12 -0
  84. package/dist/components/kbd.js +11 -0
  85. package/dist/components/label.d.ts +8 -0
  86. package/dist/components/label.js +10 -0
  87. package/dist/components/mention-list.d.ts +54 -0
  88. package/dist/components/mention-list.js +31 -0
  89. package/dist/components/menubar.d.ts +64 -0
  90. package/dist/components/menubar.js +68 -0
  91. package/dist/components/message-actions.d.ts +34 -0
  92. package/dist/components/message-actions.js +68 -0
  93. package/dist/components/message-response.d.ts +20 -0
  94. package/dist/components/message-response.js +46 -0
  95. package/dist/components/message-scroller.d.ts +71 -0
  96. package/dist/components/message-scroller.js +217 -0
  97. package/dist/components/message.d.ts +49 -0
  98. package/dist/components/message.js +59 -0
  99. package/dist/components/navigation-menu.d.ts +45 -0
  100. package/dist/components/navigation-menu.js +54 -0
  101. package/dist/components/notice-banner.d.ts +14 -0
  102. package/dist/components/notice-banner.js +11 -0
  103. package/dist/components/page-content.d.ts +7 -0
  104. package/dist/components/page-content.js +9 -0
  105. package/dist/components/page-header.d.ts +37 -0
  106. package/dist/components/page-header.js +53 -0
  107. package/dist/components/pagination.d.ts +29 -0
  108. package/dist/components/pagination.js +29 -0
  109. package/dist/components/plan-outline.d.ts +60 -0
  110. package/dist/components/plan-outline.js +108 -0
  111. package/dist/components/popover.d.ts +34 -0
  112. package/dist/components/popover.js +35 -0
  113. package/dist/components/progress.d.ts +27 -0
  114. package/dist/components/progress.js +35 -0
  115. package/dist/components/prompt-list.d.ts +23 -0
  116. package/dist/components/prompt-list.js +11 -0
  117. package/dist/components/questionnaire.d.ts +148 -0
  118. package/dist/components/questionnaire.js +1002 -0
  119. package/dist/components/radio-group.d.ts +16 -0
  120. package/dist/components/radio-group.js +21 -0
  121. package/dist/components/reasoning-effort.d.ts +24 -0
  122. package/dist/components/reasoning-effort.js +269 -0
  123. package/dist/components/resizable.d.ts +67 -0
  124. package/dist/components/resizable.js +536 -0
  125. package/dist/components/result-card.d.ts +58 -0
  126. package/dist/components/result-card.js +88 -0
  127. package/dist/components/review-card.d.ts +62 -0
  128. package/dist/components/review-card.js +49 -0
  129. package/dist/components/rich-text-editor.d.ts +51 -0
  130. package/dist/components/rich-text-editor.js +248 -0
  131. package/dist/components/schema-diagram.d.ts +52 -0
  132. package/dist/components/schema-diagram.js +226 -0
  133. package/dist/components/scroll-area.d.ts +22 -0
  134. package/dist/components/scroll-area.js +19 -0
  135. package/dist/components/search-dialog.d.ts +103 -0
  136. package/dist/components/search-dialog.js +65 -0
  137. package/dist/components/search-field.d.ts +17 -0
  138. package/dist/components/search-field.js +27 -0
  139. package/dist/components/select.d.ts +57 -0
  140. package/dist/components/select.js +57 -0
  141. package/dist/components/selection-slot.d.ts +18 -0
  142. package/dist/components/selection-slot.js +53 -0
  143. package/dist/components/separator.d.ts +48 -0
  144. package/dist/components/separator.js +54 -0
  145. package/dist/components/settings-list.d.ts +26 -0
  146. package/dist/components/settings-list.js +17 -0
  147. package/dist/components/sheet.d.ts +70 -0
  148. package/dist/components/sheet.js +77 -0
  149. package/dist/components/sidebar.d.ts +70 -0
  150. package/dist/components/sidebar.js +187 -0
  151. package/dist/components/skeleton.d.ts +31 -0
  152. package/dist/components/skeleton.js +32 -0
  153. package/dist/components/slider.d.ts +17 -0
  154. package/dist/components/slider.js +24 -0
  155. package/dist/components/spinner.d.ts +37 -0
  156. package/dist/components/spinner.js +43 -0
  157. package/dist/components/state-panel-samples.d.ts +25 -0
  158. package/dist/components/state-panel-samples.js +423 -0
  159. package/dist/components/state-panel.d.ts +35 -0
  160. package/dist/components/state-panel.js +29 -0
  161. package/dist/components/state-sample.d.ts +63 -0
  162. package/dist/components/state-sample.js +42 -0
  163. package/dist/components/switch.d.ts +12 -0
  164. package/dist/components/switch.js +14 -0
  165. package/dist/components/table-nuqs.d.ts +16 -0
  166. package/dist/components/table-nuqs.js +59 -0
  167. package/dist/components/table.d.ts +120 -0
  168. package/dist/components/table.js +663 -0
  169. package/dist/components/tabs.d.ts +37 -0
  170. package/dist/components/tabs.js +36 -0
  171. package/dist/components/textarea.d.ts +18 -0
  172. package/dist/components/textarea.js +19 -0
  173. package/dist/components/toast.d.ts +45 -0
  174. package/dist/components/toast.js +83 -0
  175. package/dist/components/toggle-group.d.ts +30 -0
  176. package/dist/components/toggle-group.js +39 -0
  177. package/dist/components/toggle.d.ts +27 -0
  178. package/dist/components/toggle.js +21 -0
  179. package/dist/components/tool-activity.d.ts +79 -0
  180. package/dist/components/tool-activity.js +226 -0
  181. package/dist/components/toolbar-status.d.ts +21 -0
  182. package/dist/components/toolbar-status.js +14 -0
  183. package/dist/components/tooltip.d.ts +31 -0
  184. package/dist/components/tooltip.js +99 -0
  185. package/dist/components/typed-text.d.ts +17 -0
  186. package/dist/components/typed-text.js +56 -0
  187. package/dist/index.d.ts +90 -0
  188. package/dist/index.js +90 -0
  189. package/dist/internal/brand-glyphs.d.ts +370 -0
  190. package/dist/internal/brand-glyphs.js +262 -0
  191. package/dist/internal/classes.d.ts +3 -0
  192. package/dist/internal/classes.js +20 -0
  193. package/dist/internal/code-tokens.d.ts +4 -0
  194. package/dist/internal/code-tokens.js +34 -0
  195. package/dist/internal/fieldset.d.ts +6 -0
  196. package/dist/internal/fieldset.js +38 -0
  197. package/dist/internal/file-kind.d.ts +4 -0
  198. package/dist/internal/file-kind.js +62 -0
  199. package/dist/internal/languages.d.ts +7 -0
  200. package/dist/internal/languages.js +1010 -0
  201. package/dist/internal/message-scroller.d.ts +102 -0
  202. package/dist/internal/message-scroller.js +637 -0
  203. package/dist/internal/pressable.d.ts +2 -0
  204. package/dist/internal/pressable.js +29 -0
  205. package/dist/internal/syntax.d.ts +14 -0
  206. package/dist/internal/syntax.js +137 -0
  207. package/dist/styles/accordion.css +102 -0
  208. package/dist/styles/alert-dialog.css +198 -0
  209. package/dist/styles/alert.css +149 -0
  210. package/dist/styles/aspect-ratio.css +8 -0
  211. package/dist/styles/attachment.css +700 -0
  212. package/dist/styles/avatar.css +186 -0
  213. package/dist/styles/badge.css +178 -0
  214. package/dist/styles/brand-icon.css +104 -0
  215. package/dist/styles/breadcrumb.css +121 -0
  216. package/dist/styles/button-group.css +113 -0
  217. package/dist/styles/button.css +380 -0
  218. package/dist/styles/calendar.css +295 -0
  219. package/dist/styles/canvas.css +313 -0
  220. package/dist/styles/card.css +146 -0
  221. package/dist/styles/carousel.css +107 -0
  222. package/dist/styles/chart.css +227 -0
  223. package/dist/styles/chat-confirmation.css +29 -0
  224. package/dist/styles/chat-input.css +240 -0
  225. package/dist/styles/chat-plan.css +109 -0
  226. package/dist/styles/chat-sources.css +191 -0
  227. package/dist/styles/checkbox.css +122 -0
  228. package/dist/styles/choice-list.css +343 -0
  229. package/dist/styles/code-block.css +211 -0
  230. package/dist/styles/collapsible.css +72 -0
  231. package/dist/styles/combobox.css +347 -0
  232. package/dist/styles/command.css +233 -0
  233. package/dist/styles/context-menu.css +151 -0
  234. package/dist/styles/dialog.css +237 -0
  235. package/dist/styles/dropdown-menu.css +150 -0
  236. package/dist/styles/field.css +340 -0
  237. package/dist/styles/file-explorer.css +517 -0
  238. package/dist/styles/file-viewer.css +375 -0
  239. package/dist/styles/form.css +155 -0
  240. package/dist/styles/glass-banner.css +308 -0
  241. package/dist/styles/gradient-banner.css +256 -0
  242. package/dist/styles/hover-card.css +95 -0
  243. package/dist/styles/index.css +268 -0
  244. package/dist/styles/input-group.css +285 -0
  245. package/dist/styles/input-otp.css +138 -0
  246. package/dist/styles/input.css +98 -0
  247. package/dist/styles/kbd.css +59 -0
  248. package/dist/styles/label.css +89 -0
  249. package/dist/styles/mention-list.css +166 -0
  250. package/dist/styles/menubar.css +226 -0
  251. package/dist/styles/message-actions.css +83 -0
  252. package/dist/styles/message-response.css +176 -0
  253. package/dist/styles/message-scroller.css +136 -0
  254. package/dist/styles/message.css +310 -0
  255. package/dist/styles/navigation-menu.css +291 -0
  256. package/dist/styles/notice-banner.css +68 -0
  257. package/dist/styles/page-content.css +21 -0
  258. package/dist/styles/page-header.css +156 -0
  259. package/dist/styles/pagination.css +72 -0
  260. package/dist/styles/plan-outline.css +393 -0
  261. package/dist/styles/popover.css +140 -0
  262. package/dist/styles/progress.css +93 -0
  263. package/dist/styles/prompt-list.css +165 -0
  264. package/dist/styles/questionnaire.css +308 -0
  265. package/dist/styles/radio-group.css +119 -0
  266. package/dist/styles/reasoning-effort.css +157 -0
  267. package/dist/styles/resizable.css +108 -0
  268. package/dist/styles/result-card.css +215 -0
  269. package/dist/styles/review-card.css +235 -0
  270. package/dist/styles/rich-text-editor.css +169 -0
  271. package/dist/styles/schema-diagram.css +419 -0
  272. package/dist/styles/scroll-area.css +77 -0
  273. package/dist/styles/search-dialog.css +280 -0
  274. package/dist/styles/search-field.css +17 -0
  275. package/dist/styles/select.css +285 -0
  276. package/dist/styles/selection-slot.css +31 -0
  277. package/dist/styles/separator.css +206 -0
  278. package/dist/styles/settings-list.css +81 -0
  279. package/dist/styles/sheet.css +361 -0
  280. package/dist/styles/sidebar.css +363 -0
  281. package/dist/styles/skeleton.css +80 -0
  282. package/dist/styles/slider.css +142 -0
  283. package/dist/styles/spinner.css +39 -0
  284. package/dist/styles/state-panel-samples.css +41 -0
  285. package/dist/styles/state-panel.css +173 -0
  286. package/dist/styles/state-sample.css +285 -0
  287. package/dist/styles/switch.css +128 -0
  288. package/dist/styles/table.css +604 -0
  289. package/dist/styles/tabs.css +223 -0
  290. package/dist/styles/textarea.css +77 -0
  291. package/dist/styles/themes/chatgpt.css +125 -0
  292. package/dist/styles/themes/claude.css +125 -0
  293. package/dist/styles/themes/cloudflare.css +125 -0
  294. package/dist/styles/themes/discord.css +125 -0
  295. package/dist/styles/themes/github.css +125 -0
  296. package/dist/styles/themes/grok.css +125 -0
  297. package/dist/styles/themes/linear.css +126 -0
  298. package/dist/styles/themes/neutral.css +125 -0
  299. package/dist/styles/themes/notion.css +125 -0
  300. package/dist/styles/themes/perplexity.css +125 -0
  301. package/dist/styles/themes/raycast.css +125 -0
  302. package/dist/styles/themes/spotify.css +125 -0
  303. package/dist/styles/themes/stripe.css +125 -0
  304. package/dist/styles/themes/supabase.css +125 -0
  305. package/dist/styles/themes/tulipfarm.css +115 -0
  306. package/dist/styles/themes/vercel.css +126 -0
  307. package/dist/styles/toast.css +197 -0
  308. package/dist/styles/toggle-group.css +161 -0
  309. package/dist/styles/toggle.css +119 -0
  310. package/dist/styles/tool-activity.css +396 -0
  311. package/dist/styles/toolbar-status.css +52 -0
  312. package/dist/styles/tooltip.css +122 -0
  313. package/dist/styles/typed-text.css +17 -0
  314. package/package.json +452 -4
@@ -0,0 +1,62 @@
1
+ import { type ComponentProps, type ReactNode } from "react";
2
+ export declare const reviewCardBadgeVariantNames: readonly ["default", "success", "warning", "info", "secondary", "destructive", "outline"];
3
+ export type ReviewCardBadgeVariant = (typeof reviewCardBadgeVariantNames)[number];
4
+ export type ReviewCardBadge = {
5
+ label: string;
6
+ variant: ReviewCardBadgeVariant;
7
+ };
8
+ export interface ReviewCardProps extends Omit<ComponentProps<"section">, "title" | "children"> {
9
+ /** A 14–16px icon shown in a tile before the title. */
10
+ icon: ReactNode;
11
+ title: string;
12
+ badge: ReviewCardBadge;
13
+ /**
14
+ * A decided review. It folds to its header and footer, and folds again
15
+ * whenever `settled` turns true. People can still open it to read it.
16
+ */
17
+ settled?: boolean | undefined;
18
+ /** Footer content that stays visible when folded, such as the outcome. */
19
+ status?: ReactNode;
20
+ /** Decision buttons in the footer. Hidden while the card is folded. */
21
+ actions?: ReactNode;
22
+ /** The review itself: text, `ReviewRows`, `ReviewSteps`, and controls. */
23
+ children?: ReactNode;
24
+ /** Names the card, such as “Review row change”. Defaults to the title. */
25
+ label?: string | undefined;
26
+ }
27
+ /**
28
+ * A card that asks someone to review a proposed change before it happens:
29
+ * an approval, a draft, or a table edit. The header opens and closes the
30
+ * details; the footer holds the outcome and the decision buttons.
31
+ */
32
+ export declare function ReviewCard({ icon, title, badge, settled, status, actions, children, label, className, ...props }: ReviewCardProps): import("react").JSX.Element;
33
+ export type ReviewRowsProps = ComponentProps<"dl">;
34
+ /** A bordered list of labeled facts, such as Change, Table, and Trigger. */
35
+ export declare function ReviewRows({ className, ...props }: ReviewRowsProps): import("react").JSX.Element;
36
+ export interface ReviewRowProps extends Omit<ComponentProps<"div">, "children"> {
37
+ label: string;
38
+ /** The value: text, badges, or a stacked new and current value. */
39
+ children: ReactNode;
40
+ }
41
+ /** One fact: the label on the left and its value on the right. */
42
+ export declare function ReviewRow({ label, children, className, ...props }: ReviewRowProps): import("react").JSX.Element;
43
+ export type ReviewStep = {
44
+ summary: ReactNode;
45
+ detail?: ReactNode;
46
+ };
47
+ export interface ReviewStepsProps extends Omit<ComponentProps<"div">, "title" | "children"> {
48
+ /** Short heading, such as “3 steps”. */
49
+ title: string;
50
+ steps: readonly ReviewStep[];
51
+ }
52
+ /** A numbered list of what will happen, each with optional detail below. */
53
+ export declare function ReviewSteps({ title, steps, className, ...props }: ReviewStepsProps): import("react").JSX.Element;
54
+ export type ReviewValue = {
55
+ name: string;
56
+ value: string;
57
+ };
58
+ export interface ReviewValuesProps extends Omit<ComponentProps<"dl">, "children"> {
59
+ values: readonly ReviewValue[];
60
+ }
61
+ /** Exact names and values in monospace, such as headers or written fields. */
62
+ export declare function ReviewValues({ values, className, ...props }: ReviewValuesProps): import("react").JSX.Element;
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from "react";
4
+ import { ChevronDown } from "reicon-react/icons/ChevronDown";
5
+ import { cn } from "../internal/classes.js";
6
+ import { Badge } from "./badge.js";
7
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "./collapsible.js";
8
+ export const reviewCardBadgeVariantNames = [
9
+ "default",
10
+ "success",
11
+ "warning",
12
+ "info",
13
+ "secondary",
14
+ "destructive",
15
+ "outline",
16
+ ];
17
+ /**
18
+ * A card that asks someone to review a proposed change before it happens:
19
+ * an approval, a draft, or a table edit. The header opens and closes the
20
+ * details; the footer holds the outcome and the decision buttons.
21
+ */
22
+ export function ReviewCard({ icon, title, badge, settled = false, status, actions, children, label, className, ...props }) {
23
+ const titleId = useId();
24
+ const [open, setOpen] = useState(!settled);
25
+ const [wasSettled, setWasSettled] = useState(settled);
26
+ if (wasSettled !== settled) {
27
+ setWasSettled(settled);
28
+ setOpen(!settled);
29
+ }
30
+ const showActions = open && actions != null && actions !== false;
31
+ const showStatus = status != null && status !== false;
32
+ return (_jsxs("section", { "data-slot": "review-card", "data-settled": settled || undefined, "data-open": open || undefined, "aria-label": label, "aria-labelledby": label ? undefined : titleId, ...props, className: cn("sprout-review-card", className), children: [_jsxs(Collapsible, { open: open, onOpenChange: setOpen, children: [_jsxs("div", { className: "sprout-review-card-header", children: [_jsx("span", { "aria-hidden": "true", className: "sprout-review-card-icon", children: icon }), _jsx("h4", { id: titleId, className: "sprout-review-card-title", children: _jsx(CollapsibleTrigger, { className: "sprout-review-card-trigger", children: title }) }), _jsx(Badge, { variant: badge.variant, className: "sprout-review-card-badge", children: badge.label }), _jsx(ChevronDown, { size: 16, "aria-hidden": "true", "data-slot": "collapsible-indicator", className: "sprout-review-card-chevron" })] }), _jsx(CollapsibleContent, { variant: "card", children: _jsx("div", { className: "sprout-review-card-body", children: children }) })] }), (showStatus || showActions) && (_jsxs("div", { className: "sprout-review-card-footer", children: [status, showActions && (_jsx("div", { className: "sprout-review-card-actions", children: actions }))] }))] }));
33
+ }
34
+ /** A bordered list of labeled facts, such as Change, Table, and Trigger. */
35
+ export function ReviewRows({ className, ...props }) {
36
+ return (_jsx("dl", { "data-slot": "review-rows", ...props, className: cn("sprout-review-rows", className) }));
37
+ }
38
+ /** One fact: the label on the left and its value on the right. */
39
+ export function ReviewRow({ label, children, className, ...props }) {
40
+ return (_jsxs("div", { "data-slot": "review-row", ...props, className: cn("sprout-review-row", className), children: [_jsx("dt", { className: "sprout-review-row-label", children: label }), _jsx("dd", { className: "sprout-review-row-value", children: children })] }));
41
+ }
42
+ /** A numbered list of what will happen, each with optional detail below. */
43
+ export function ReviewSteps({ title, steps, className, ...props }) {
44
+ return (_jsxs("div", { "data-slot": "review-steps", ...props, className: cn("sprout-review-steps", className), children: [_jsx("h5", { className: "sprout-review-steps-title", children: title }), _jsx("ol", { className: "sprout-review-steps-list", children: steps.map((step, index) => (_jsxs("li", { className: "sprout-review-step", children: [_jsx("span", { "aria-hidden": "true", className: "sprout-review-step-number", children: index + 1 }), _jsxs("div", { className: "sprout-review-step-content", children: [_jsx("p", { className: "sprout-review-step-summary", children: step.summary }), step.detail] })] }, index))) })] }));
45
+ }
46
+ /** Exact names and values in monospace, such as headers or written fields. */
47
+ export function ReviewValues({ values, className, ...props }) {
48
+ return (_jsx("dl", { "data-slot": "review-values", ...props, className: cn("sprout-review-values", className), children: values.map(({ name, value }) => (_jsxs("div", { className: "sprout-review-value", children: [_jsx("dt", { className: "sprout-review-value-name", children: name }), _jsx("dd", { className: "sprout-review-value-text", children: value })] }, name))) }));
49
+ }
@@ -0,0 +1,51 @@
1
+ import { type ReactNode, type Ref } from "react";
2
+ import { type Editor, type Extensions, type JSONContent } from "@tiptap/core";
3
+ export declare const richTextEditorSizeNames: readonly ["default", "compact"];
4
+ export type RichTextEditorSize = (typeof richTextEditorSizeNames)[number];
5
+ /** A Tiptap JSON document, such as `{ type: "doc", content: [{ type: "paragraph" }] }`. */
6
+ export type RichTextValue = JSONContent;
7
+ export type RichTextEditorHandle = {
8
+ /** Puts the caret back in the editor. */
9
+ focus: () => void;
10
+ /** The Tiptap editor, or `null` before it mounts. Use it for formatting commands. */
11
+ editor: () => Editor | null;
12
+ /** Replaces the document and calls `onChange`. */
13
+ setContent: (content: RichTextValue) => void;
14
+ };
15
+ export interface RichTextEditorProps {
16
+ ref?: Ref<RichTextEditorHandle> | undefined;
17
+ /**
18
+ * `default` is an 80px to 256px box with 16px text and a toolbar row below.
19
+ * `compact` is a 40px to 128px box with 14px text and the toolbar inline at
20
+ * the end.
21
+ */
22
+ size?: RichTextEditorSize | null | undefined;
23
+ /** Shrinks a default editor to one compact row with an inline toolbar, such as while an agent question waits. */
24
+ condensed?: boolean | undefined;
25
+ value: RichTextValue;
26
+ onChange: (value: RichTextValue) => void;
27
+ /** Runs on Enter (outside lists and code) and on Cmd or Ctrl+Enter. */
28
+ onSend: () => void;
29
+ /** Extra Tiptap extensions, such as mention nodes and suggestion triggers. */
30
+ extensions?: Extensions | undefined;
31
+ placeholder?: string | undefined;
32
+ disabled?: boolean | undefined;
33
+ /** Accessible name of the textbox. Defaults to `Message`. */
34
+ ariaLabel?: string | undefined;
35
+ ariaInvalid?: boolean | undefined;
36
+ ariaDescribedBy?: string | undefined;
37
+ /** Set while a suggestion list is open; Enter then picks a suggestion instead of sending. */
38
+ ariaExpanded?: boolean | undefined;
39
+ ariaControls?: string | undefined;
40
+ ariaActiveDescendant?: string | undefined;
41
+ /** Buttons and pickers shown with the editor: a row below, or inline when compact or condensed. */
42
+ toolbarAddon?: ReactNode | undefined;
43
+ className?: string | undefined;
44
+ }
45
+ /**
46
+ * A chat message editor built on Tiptap. Enter sends, Shift+Enter adds a
47
+ * line, and lists, code fences, links, and headings work as you type. It marks
48
+ * itself `data-slot="input-group-control"`, so an `InputGroup` around it draws
49
+ * the border, focus, and invalid states.
50
+ */
51
+ export declare function RichTextEditor({ ref, size, condensed, value, onChange, onSend, extensions, placeholder, disabled, ariaLabel, ariaInvalid, ariaDescribedBy, ariaExpanded, ariaControls, ariaActiveDescendant, toolbarAddon, className, }: RichTextEditorProps): import("react").JSX.Element;
@@ -0,0 +1,248 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useImperativeHandle, useMemo, useRef, } from "react";
4
+ import { EditorContent, useEditor } from "@tiptap/react";
5
+ import { Extension, InputRule, } from "@tiptap/core";
6
+ import { Fragment, Slice, } from "@tiptap/pm/model";
7
+ import { Plugin, PluginKey, TextSelection, } from "@tiptap/pm/state";
8
+ import { canSplit } from "@tiptap/pm/transform";
9
+ import StarterKit from "@tiptap/starter-kit";
10
+ import Placeholder from "@tiptap/extension-placeholder";
11
+ import { cn } from "../internal/classes.js";
12
+ export const richTextEditorSizeNames = ["default", "compact"];
13
+ const fenceLanguage = /^[\w+#.-]{1,32}$/;
14
+ const typedFence = /```([\w+#.-]{1,32})?\s$/;
15
+ const fenceOnly = /^```([\w+#.-]{1,32})?$/;
16
+ const openingFence = /^ {0,3}(?:(`{3,})([^`]*)|(~{3,})(.*))$/;
17
+ function isFenceLine(state) {
18
+ const { $from, empty } = state.selection;
19
+ if (!empty ||
20
+ $from.parent.type.name !== "paragraph" ||
21
+ $from.parentOffset !== $from.parent.content.size)
22
+ return false;
23
+ return fenceOnly.test($from.parent
24
+ .textBetween(0, $from.parentOffset, undefined, "\n")
25
+ .split("\n")
26
+ .at(-1) ?? "");
27
+ }
28
+ function markdownBlocks(schema, text) {
29
+ const blocks = [];
30
+ const lines = text.replace(/\r\n?/g, "\n").split("\n");
31
+ while (lines.length) {
32
+ const line = lines.shift();
33
+ const open = openingFence.exec(line);
34
+ if (!open) {
35
+ if (line.trim())
36
+ blocks.push(schema.nodes.paragraph.create(null, schema.text(line)));
37
+ continue;
38
+ }
39
+ const fence = open[1] ?? open[3];
40
+ const info = (open[2] ?? open[4]).trim().split(/\s/)[0];
41
+ const closing = new RegExp(`^ {0,3}${fence[0]}{${fence.length},}\\s*$`);
42
+ const end = lines.findIndex((candidate) => closing.test(candidate));
43
+ const code = (end === -1 ? lines.splice(0) : lines.splice(0, end + 1).slice(0, -1)).join("\n");
44
+ blocks.push(schema.nodes.codeBlock.create({ language: fenceLanguage.test(info) ? info : null }, code ? schema.text(code) : null));
45
+ }
46
+ return blocks;
47
+ }
48
+ // StarterKit's fence rule only fires at the start of a paragraph, but Shift+Enter leaves the fence after a hard break.
49
+ const MarkdownCodeFence = Extension.create({
50
+ name: "markdownCodeFence",
51
+ priority: 1000,
52
+ addInputRules() {
53
+ return [
54
+ new InputRule({
55
+ find: typedFence,
56
+ handler: ({ state, range, match }) => {
57
+ const { tr, schema } = state;
58
+ const codeBlock = schema.nodes.codeBlock;
59
+ const $from = tr.doc.resolve(range.from);
60
+ if ($from.parent.type.name !== "paragraph" ||
61
+ range.to !== $from.end())
62
+ return null;
63
+ const before = $from.nodeBefore;
64
+ const attrs = { language: match[1] ?? null };
65
+ if (!before) {
66
+ if (!$from
67
+ .node(-1)
68
+ .canReplaceWith($from.index(-1), $from.indexAfter(-1), codeBlock))
69
+ return null;
70
+ tr.delete(range.from, range.to).setBlockType(range.from, range.from, codeBlock, attrs);
71
+ return;
72
+ }
73
+ if (before.type.name !== "hardBreak")
74
+ return null;
75
+ const splitAt = range.from - before.nodeSize;
76
+ tr.delete(splitAt, range.to);
77
+ if (!canSplit(tr.doc, splitAt, 1, [{ type: codeBlock, attrs }]))
78
+ return null;
79
+ tr.split(splitAt, 1, [{ type: codeBlock, attrs }]);
80
+ tr.setSelection(TextSelection.create(tr.doc, splitAt + 2));
81
+ },
82
+ }),
83
+ ];
84
+ },
85
+ addProseMirrorPlugins() {
86
+ return [
87
+ new Plugin({
88
+ key: new PluginKey("markdownCodeFencePaste"),
89
+ props: {
90
+ handlePaste: (view, event) => {
91
+ const text = event.clipboardData?.getData("text/plain") ?? "";
92
+ if (view.state.selection.$from.parent.type.spec.code ||
93
+ !text.split(/\r\n?|\n/).some((line) => openingFence.test(line)))
94
+ return false;
95
+ const blocks = markdownBlocks(view.state.schema, text);
96
+ const slice = new Slice(Fragment.from(blocks), blocks[0]?.type.name === "paragraph" ? 1 : 0, blocks.at(-1)?.type.name === "paragraph" ? 1 : 0);
97
+ view.dispatch(view.state.tr
98
+ .replaceSelection(slice)
99
+ .scrollIntoView()
100
+ .setMeta("paste", true));
101
+ return true;
102
+ },
103
+ },
104
+ }),
105
+ ];
106
+ },
107
+ });
108
+ const MessageFormatting = Extension.create({
109
+ name: "messageFormatting",
110
+ extendMarkSchema(extension) {
111
+ if (extension.name === "link")
112
+ return { inclusive: false };
113
+ return {};
114
+ },
115
+ addProseMirrorPlugins() {
116
+ return [
117
+ new Plugin({
118
+ key: new PluginKey("clearDeletedLink"),
119
+ appendTransaction(transactions, oldState, state) {
120
+ const link = state.schema.marks.link;
121
+ if (!link ||
122
+ !transactions.some((transaction) => transaction.docChanged) ||
123
+ state.doc.content.size >= oldState.doc.content.size ||
124
+ !state.selection.empty ||
125
+ !state.storedMarks?.some((mark) => mark.type === link))
126
+ return null;
127
+ if (state.selection.$from.parent.content.size &&
128
+ state.selection.$from.marks().some((mark) => mark.type === link))
129
+ return null;
130
+ return state.tr.removeStoredMark(link);
131
+ },
132
+ }),
133
+ ];
134
+ },
135
+ });
136
+ function within(state, name) {
137
+ const { $from } = state.selection;
138
+ for (let depth = $from.depth; depth > 0; depth -= 1)
139
+ if ($from.node(depth).type.name === name)
140
+ return true;
141
+ return false;
142
+ }
143
+ const allowedProtocols = ["http:", "https:", "mailto:"];
144
+ const baseExtensions = [
145
+ StarterKit.configure({
146
+ heading: { levels: [1, 2, 3] },
147
+ horizontalRule: false,
148
+ underline: false,
149
+ link: {
150
+ openOnClick: false,
151
+ isAllowedUri: (url, context) => {
152
+ const protocol = /^[a-z][a-z\d+.-]*:/i.exec(url)?.[0].toLowerCase();
153
+ return (context.defaultValidate(url) &&
154
+ (!protocol || allowedProtocols.includes(protocol)));
155
+ },
156
+ },
157
+ }),
158
+ MarkdownCodeFence,
159
+ MessageFormatting,
160
+ ];
161
+ /**
162
+ * A chat message editor built on Tiptap. Enter sends, Shift+Enter adds a
163
+ * line, and lists, code fences, links, and headings work as you type. It marks
164
+ * itself `data-slot="input-group-control"`, so an `InputGroup` around it draws
165
+ * the border, focus, and invalid states.
166
+ */
167
+ export function RichTextEditor({ ref, size, condensed = false, value, onChange, onSend, extensions = [], placeholder = "Ask anything…", disabled = false, ariaLabel = "Message", ariaInvalid = false, ariaDescribedBy, ariaExpanded, ariaControls, ariaActiveDescendant, toolbarAddon, className, }) {
168
+ const scale = size ?? "default";
169
+ const inline = condensed || scale === "compact";
170
+ const onSendRef = useRef(onSend);
171
+ const onChangeRef = useRef(onChange);
172
+ const placeholderRef = useRef(placeholder);
173
+ const suggestionOpenRef = useRef(ariaExpanded ?? false);
174
+ onSendRef.current = onSend;
175
+ onChangeRef.current = onChange;
176
+ placeholderRef.current = placeholder;
177
+ suggestionOpenRef.current = ariaExpanded ?? false;
178
+ const configured = useMemo(() => [
179
+ ...baseExtensions,
180
+ Placeholder.configure({ placeholder: () => placeholderRef.current }),
181
+ ...extensions,
182
+ ], [extensions]);
183
+ const editor = useEditor({
184
+ immediatelyRender: false,
185
+ extensions: configured,
186
+ content: value,
187
+ editable: !disabled,
188
+ editorProps: {
189
+ // useEditor re-applies editorProps on every render, so these stay current.
190
+ attributes: {
191
+ "data-slot": "input-group-control",
192
+ role: "textbox",
193
+ "aria-label": ariaLabel,
194
+ "aria-disabled": String(disabled),
195
+ "aria-multiline": "true",
196
+ "aria-autocomplete": "list",
197
+ "aria-invalid": ariaInvalid ? "true" : "false",
198
+ // ARIA forbids aria-expanded on a textbox; aria-controls and aria-activedescendant carry the open list.
199
+ ...(ariaDescribedBy && { "aria-describedby": ariaDescribedBy }),
200
+ ...(ariaControls && { "aria-controls": ariaControls }),
201
+ ...(ariaActiveDescendant && {
202
+ "aria-activedescendant": ariaActiveDescendant,
203
+ }),
204
+ class: "sprout-rich-text-editor-content",
205
+ },
206
+ handleKeyDown: (view, event) => {
207
+ if (event.isComposing)
208
+ return false;
209
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
210
+ event.preventDefault();
211
+ onSendRef.current();
212
+ return true;
213
+ }
214
+ if (event.key === "Enter" && suggestionOpenRef.current)
215
+ return false;
216
+ if (event.key === "Enter" && isFenceLine(view.state))
217
+ return false;
218
+ if (event.key === "Enter" &&
219
+ !event.shiftKey &&
220
+ !within(view.state, "listItem") &&
221
+ !within(view.state, "codeBlock")) {
222
+ event.preventDefault();
223
+ onSendRef.current();
224
+ return true;
225
+ }
226
+ return false;
227
+ },
228
+ },
229
+ onUpdate: ({ editor: current }) => onChangeRef.current(current.getJSON()),
230
+ });
231
+ useImperativeHandle(ref, () => ({
232
+ focus: () => editor?.commands.focus(),
233
+ editor: () => editor,
234
+ setContent: (content) => editor?.commands.setContent(content, { emitUpdate: true }),
235
+ }), [editor]);
236
+ useEffect(() => {
237
+ editor?.setEditable(!disabled, false);
238
+ }, [disabled, editor]);
239
+ useEffect(() => {
240
+ if (editor && !editor.isDestroyed)
241
+ editor.view.dispatch(editor.state.tr);
242
+ }, [editor, placeholder]);
243
+ useEffect(() => {
244
+ if (editor && !editor.state.doc.eq(editor.schema.nodeFromJSON(value)))
245
+ editor.commands.setContent(value, { emitUpdate: false });
246
+ }, [editor, value]);
247
+ return (_jsxs("div", { "data-slot": "rich-text-editor", "data-size": scale, "data-condensed": condensed || undefined, "data-disabled": disabled || undefined, className: cn("sprout-rich-text-editor", `sprout-rich-text-editor-size-${scale}`, condensed && "sprout-rich-text-editor-condensed", className), children: [_jsx("div", { className: "sprout-rich-text-editor-body", children: _jsx(EditorContent, { editor: editor }) }), toolbarAddon && (_jsx("div", { "data-slot": "rich-text-editor-toolbar", className: cn("sprout-rich-text-editor-toolbar", inline && "sprout-rich-text-editor-toolbar-inline"), children: toolbarAddon }))] }));
248
+ }
@@ -0,0 +1,52 @@
1
+ import { type HTMLAttributes } from "react";
2
+ export declare const schemaTableStateNames: readonly ["new", "changed", "unchanged", "linked"];
3
+ export declare const schemaChangeNames: readonly ["added", "changed", "removed"];
4
+ export declare const schemaDiagramLayoutNames: readonly ["auto", "horizontal", "vertical"];
5
+ export type SchemaTableState = (typeof schemaTableStateNames)[number];
6
+ export type SchemaChange = (typeof schemaChangeNames)[number];
7
+ export type SchemaDiagramLayout = (typeof schemaDiagramLayoutNames)[number];
8
+ export interface SchemaField {
9
+ id: string;
10
+ label: string;
11
+ type: string;
12
+ required: boolean;
13
+ unique?: boolean | undefined;
14
+ /** A second, muted line under the field, such as a relation target. */
15
+ detail?: string | undefined;
16
+ change?: SchemaChange | undefined;
17
+ }
18
+ export interface SchemaTable {
19
+ id: string;
20
+ label: string;
21
+ state: SchemaTableState;
22
+ fields: SchemaField[];
23
+ }
24
+ /** A link starts at a field row and ends at the target table header. */
25
+ export interface SchemaLink {
26
+ id: string;
27
+ /** The table that holds `field`. */
28
+ source: string;
29
+ field: string;
30
+ target: string;
31
+ label: string;
32
+ }
33
+ export interface SchemaDiagramProps extends Omit<HTMLAttributes<HTMLDivElement>, "role" | "children"> {
34
+ tables: readonly SchemaTable[];
35
+ links: readonly SchemaLink[];
36
+ /** Names the diagram for assistive tech, such as “Schema diagram for Launch tracker”. */
37
+ label: string;
38
+ /**
39
+ * `auto` stacks tables top to bottom on viewports under 768px and lays them
40
+ * out in columns otherwise.
41
+ */
42
+ layout?: SchemaDiagramLayout | undefined;
43
+ }
44
+ /**
45
+ * A pan-and-zoom diagram of tables, their fields, and the links between them,
46
+ * with proposed changes marked on each table and field.
47
+ */
48
+ export declare function SchemaDiagram({ tables, links, label, layout: layoutName, className, ...props }: SchemaDiagramProps): import("react").JSX.Element;
49
+ export interface SchemaLegendProps extends Omit<HTMLAttributes<HTMLUListElement>, "children"> {
50
+ }
51
+ /** Explains the change colors, the unique key, and the required mark. */
52
+ export declare function SchemaLegend({ className, ...props }: SchemaLegendProps): import("react").JSX.Element;