@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,172 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { createContext, useContext, useId, useMemo, } from "react";
4
+ import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts";
5
+ import { cn } from "../internal/classes.js";
6
+ /** Theme names a `ChartConfig` entry can color, and the selector each one uses. */
7
+ const THEMES = { light: "", dark: ".dark" };
8
+ const INITIAL_DIMENSION = { width: 320, height: 200 };
9
+ export const chartIndicatorNames = ["dot", "line", "dashed"];
10
+ const cssKey = (key) => key.replace(/[^\w-]/g, "_");
11
+ /**
12
+ * The CSS variable a `ChartContainer` sets for one config key. Pass it as a
13
+ * series `fill` or `stroke`, for example `fill={chartColor("tasks")}`.
14
+ */
15
+ export function chartColor(key) {
16
+ return `var(--sprout-chart-color-${cssKey(key)})`;
17
+ }
18
+ const ChartContext = createContext(null);
19
+ function useChart() {
20
+ const context = useContext(ChartContext);
21
+ if (!context)
22
+ throw new Error("useChart must be used within a <ChartContainer />");
23
+ return context;
24
+ }
25
+ /**
26
+ * Sizes a Recharts chart to its box and turns `config` into series colors
27
+ * and labels for the tooltip and legend. The box is 16:9 unless `className`
28
+ * or `style` gives it a height.
29
+ */
30
+ export function ChartContainer({ id, className, children, config, initialDimension = INITIAL_DIMENSION, ...props }) {
31
+ const uniqueId = useId();
32
+ const chartId = `chart-${cssKey(id ?? uniqueId)}`;
33
+ const value = useMemo(() => ({ config }), [config]);
34
+ return (_jsx(ChartContext.Provider, { value: value, children: _jsxs("div", { "data-slot": "chart", "data-chart": chartId, className: cn("sprout-chart", className), ...props, children: [_jsx(ChartStyle, { id: chartId, config: config }), _jsx(ResponsiveContainer, { initialDimension: initialDimension, children: children })] }) }));
35
+ }
36
+ /**
37
+ * Writes `--sprout-chart-color-<key>` for every colored config entry, with a
38
+ * dark value for entries that pass `theme`. `ChartContainer` renders it.
39
+ */
40
+ export function ChartStyle({ id, config, }) {
41
+ const colorConfig = Object.entries(config).filter(([, item]) => item.theme ?? item.color);
42
+ if (!colorConfig.length)
43
+ return null;
44
+ const rules = (theme) => colorConfig
45
+ .map(([key, item]) => {
46
+ const color = item.theme?.[theme] ?? item.color;
47
+ return color
48
+ ? ` --sprout-chart-color-${cssKey(key)}: ${color};`
49
+ : null;
50
+ })
51
+ .filter(Boolean)
52
+ .join("\n");
53
+ const scope = `[data-chart="${cssKey(id)}"]`;
54
+ const themed = colorConfig.some(([, item]) => item.theme);
55
+ const css = [
56
+ `${scope} {\n${rules("light")}\n}`,
57
+ themed ? `${THEMES.dark} ${scope} {\n${rules("dark")}\n}` : "",
58
+ themed
59
+ ? `@media (prefers-color-scheme: dark) {\n:root:not(.light):not(.dark) ${scope} {\n${rules("dark")}\n}\n}`
60
+ : "",
61
+ ]
62
+ .filter(Boolean)
63
+ .join("\n");
64
+ return _jsx("style", { dangerouslySetInnerHTML: { __html: css } });
65
+ }
66
+ /**
67
+ * Recharts' `Tooltip`, moving in 160ms. Pass `content={<ChartTooltipContent />}`.
68
+ * It stays still when reduced motion is on.
69
+ */
70
+ export function ChartTooltip(props) {
71
+ return _jsx(Tooltip, { animationDuration: 160, ...props });
72
+ }
73
+ /**
74
+ * The tooltip card: a label, then one row per series with its indicator,
75
+ * config label, and value. Recharts passes `active`, `payload`, and `label`.
76
+ */
77
+ export function ChartTooltipContent({ active, payload, className, indicator = "dot", hideLabel = false, hideIndicator = false, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey, }) {
78
+ const { config } = useChart();
79
+ const tooltipLabel = useMemo(() => {
80
+ if (hideLabel || !payload?.length)
81
+ return null;
82
+ const [item] = payload;
83
+ const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`;
84
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
85
+ const value = !labelKey && typeof label === "string"
86
+ ? (config[label]?.label ?? label)
87
+ : itemConfig?.label;
88
+ if (labelFormatter)
89
+ return (_jsx("div", { className: cn("sprout-chart-tooltip-label", labelClassName), children: labelFormatter(value, payload) }));
90
+ if (!value)
91
+ return null;
92
+ return (_jsx("div", { className: cn("sprout-chart-tooltip-label", labelClassName), children: value }));
93
+ }, [
94
+ label,
95
+ labelFormatter,
96
+ payload,
97
+ hideLabel,
98
+ labelClassName,
99
+ config,
100
+ labelKey,
101
+ ]);
102
+ if (!active || !payload?.length)
103
+ return null;
104
+ const nestLabel = payload.length === 1 && indicator !== "dot";
105
+ return (_jsxs("div", { "data-slot": "chart-tooltip", "data-indicator": indicator, className: cn("sprout-chart-tooltip", className), children: [!nestLabel ? tooltipLabel : null, _jsx("div", { className: "sprout-chart-tooltip-items", children: payload
106
+ .filter((item) => item.type !== "none")
107
+ .map((item, index) => {
108
+ const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
109
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
110
+ const indicatorColor = color ??
111
+ item.payload?.fill ??
112
+ item.color;
113
+ return (_jsx("div", { "data-slot": "chart-tooltip-item", className: "sprout-chart-tooltip-item", children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (_jsxs(_Fragment, { children: [itemConfig?.icon ? (_jsx(itemConfig.icon, {})) : (!hideIndicator && (_jsx("span", { "aria-hidden": "true", "data-slot": "chart-tooltip-indicator", className: "sprout-chart-tooltip-indicator", style: {
114
+ "--sprout-chart-indicator": indicatorColor,
115
+ } }))), _jsxs("div", { className: "sprout-chart-tooltip-row", "data-nested": nestLabel || undefined, children: [_jsxs("div", { className: "sprout-chart-tooltip-name", children: [nestLabel ? tooltipLabel : null, _jsx("span", { children: itemConfig?.label ?? item.name })] }), item.value != null && (_jsx("span", { className: "sprout-chart-tooltip-value", children: typeof item.value === "number"
116
+ ? item.value.toLocaleString()
117
+ : String(item.value) }))] })] })) }, index));
118
+ }) })] }));
119
+ }
120
+ /** Recharts' `Legend`. Pass `content={<ChartLegendContent />}`. */
121
+ export const ChartLegend = Legend;
122
+ /** A centered row of swatches and config labels, one per series. */
123
+ export function ChartLegendContent({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey, }) {
124
+ const { config } = useChart();
125
+ if (!payload?.length)
126
+ return null;
127
+ return (_jsx("div", { "data-slot": "chart-legend", "data-align": verticalAlign === "top" ? "top" : "bottom", className: cn("sprout-chart-legend", className), children: payload
128
+ .filter((item) => item.type !== "none")
129
+ .map((item, index) => {
130
+ const key = `${nameKey ?? item.dataKey ?? "value"}`;
131
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
132
+ return (_jsxs("div", { "data-slot": "chart-legend-item", className: "sprout-chart-legend-item", children: [itemConfig?.icon && !hideIcon ? (_jsx(itemConfig.icon, {})) : (_jsx("span", { "aria-hidden": "true", className: "sprout-chart-legend-swatch", style: { backgroundColor: item.color } })), itemConfig?.label] }, index));
133
+ }) }));
134
+ }
135
+ function getPayloadConfigFromPayload(config, payload, key) {
136
+ if (typeof payload !== "object" || payload === null)
137
+ return undefined;
138
+ const inner = "payload" in payload &&
139
+ typeof payload.payload === "object" &&
140
+ payload.payload !== null
141
+ ? payload.payload
142
+ : undefined;
143
+ const outer = payload;
144
+ let configLabelKey = key;
145
+ if (typeof outer[key] === "string")
146
+ configLabelKey = outer[key];
147
+ else if (inner && typeof inner[key] === "string")
148
+ configLabelKey = inner[key];
149
+ return configLabelKey in config ? config[configLabelKey] : config[key];
150
+ }
151
+ const seriesConfig = (series) => Object.fromEntries(series.map((item) => [item.key, { label: item.label, color: item.color }]));
152
+ const tooltipCursor = { fill: "var(--sprout-hover)" };
153
+ /**
154
+ * Stacked daily bars, 256px tall. Days are rows keyed by series; a missing or
155
+ * null value keeps that series out of the day's tooltip. The top series gets
156
+ * rounded corners.
157
+ */
158
+ export function UsageChart({ days, series, title = "Usage by day", locale, className, }) {
159
+ const config = useMemo(() => seriesConfig(series), [series]);
160
+ const usageDay = (date) => new Date(`${String(date)}T00:00:00Z`).toLocaleDateString(locale, {
161
+ month: "short",
162
+ day: "numeric",
163
+ timeZone: "UTC",
164
+ });
165
+ return (_jsx(ChartContainer, { "data-variant": "usage", className: cn("sprout-chart-usage", className), config: config, children: _jsxs(BarChart, { data: days, accessibilityLayer: true, title: title, barCategoryGap: "20%", children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: "date", tickFormatter: usageDay, tickLine: false, axisLine: false, minTickGap: 24 }), _jsx(YAxis, { width: 40, tickLine: false, axisLine: false, allowDecimals: false }), _jsx(ChartTooltip, { cursor: tooltipCursor, content: _jsx(ChartTooltipContent, { labelFormatter: usageDay }) }), series.map((item, index) => (_jsx(Bar, { dataKey: item.key, stackId: "usage", fill: chartColor(item.key), radius: index === series.length - 1 ? [3, 3, 0, 0] : 0, isAnimationActive: false }, item.key)))] }) }));
166
+ }
167
+ /** Side-by-side bars per category with a legend in series order, 288px tall. */
168
+ export function CategoryChart({ rows, category, series, title, className, }) {
169
+ const config = useMemo(() => seriesConfig(series), [series]);
170
+ const name = title ?? `${series.map((item) => item.label).join(", ")} by ${category}`;
171
+ return (_jsx(ChartContainer, { "data-variant": "category", className: cn("sprout-chart-category", className), config: config, children: _jsxs(BarChart, { data: rows, accessibilityLayer: true, title: name, barCategoryGap: "24%", children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: category, tickLine: false, axisLine: false, minTickGap: 16 }), _jsx(YAxis, { width: 40, tickLine: false, axisLine: false, allowDecimals: false }), _jsx(ChartTooltip, { cursor: tooltipCursor, content: _jsx(ChartTooltipContent, {}) }), _jsx(ChartLegend, { itemSorter: null, content: _jsx(ChartLegendContent, {}) }), series.map((item) => (_jsx(Bar, { dataKey: item.key, fill: chartColor(item.key), radius: [3, 3, 0, 0], isAnimationActive: false }, item.key)))] }) }));
172
+ }
@@ -0,0 +1,42 @@
1
+ import { type ComponentProps } from "react";
2
+ export declare const chatConfirmationStateNames: readonly ["pending", "submitting", "approved", "rejected", "expired", "cancelled", "error"];
3
+ export type ChatConfirmationDecision = "approve" | "reject";
4
+ export type ConfirmationState = {
5
+ kind: "pending";
6
+ } | {
7
+ kind: "submitting";
8
+ decision: ChatConfirmationDecision;
9
+ } | {
10
+ kind: "approved";
11
+ } | {
12
+ kind: "rejected";
13
+ } | {
14
+ kind: "expired";
15
+ } | {
16
+ kind: "cancelled";
17
+ } | {
18
+ kind: "error";
19
+ message: string;
20
+ };
21
+ export type ChatConfirmationDetail = {
22
+ label: string;
23
+ value: string;
24
+ };
25
+ export interface ChatConfirmationProps extends Omit<ComponentProps<"div">, "title" | "children"> {
26
+ /** What the agent wants to do, such as “Remove the Notes field”. */
27
+ title: string;
28
+ /** One line above the facts, such as “Review these changes before approving.” */
29
+ description: string;
30
+ /** Labeled facts about the action, in order. */
31
+ details: readonly ChatConfirmationDetail[];
32
+ state: ConfirmationState;
33
+ onDecision: (decision: ChatConfirmationDecision) => void;
34
+ /** Locks both buttons, such as while the request is refreshing or cannot be verified. */
35
+ disabled?: boolean | undefined;
36
+ }
37
+ /**
38
+ * Asks someone in chat to approve or decline an action an agent proposed.
39
+ * Built on `ReviewCard`: it folds once decided, and when the decision was
40
+ * made from inside the card, focus moves to the outcome.
41
+ */
42
+ export declare function ChatConfirmation({ title, description, details, state, onDecision, disabled, className, ...props }: ChatConfirmationProps): import("react").JSX.Element;
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ import { ShieldUser } from "reicon-react/icons/ShieldUser";
5
+ import { cn } from "../internal/classes.js";
6
+ import { Button } from "./button.js";
7
+ import { ReviewCard, ReviewRow, ReviewRows, } from "./review-card.js";
8
+ import { Spinner } from "./spinner.js";
9
+ export const chatConfirmationStateNames = [
10
+ "pending",
11
+ "submitting",
12
+ "approved",
13
+ "rejected",
14
+ "expired",
15
+ "cancelled",
16
+ "error",
17
+ ];
18
+ const settledKinds = new Set([
19
+ "approved",
20
+ "rejected",
21
+ "expired",
22
+ "cancelled",
23
+ ]);
24
+ const badges = {
25
+ pending: { label: "Approval required", variant: "warning" },
26
+ submitting: { label: "Approval required", variant: "warning" },
27
+ error: { label: "Approval required", variant: "warning" },
28
+ approved: { label: "Approved", variant: "info" },
29
+ rejected: { label: "Declined", variant: "secondary" },
30
+ expired: { label: "Expired", variant: "secondary" },
31
+ cancelled: { label: "Cancelled", variant: "secondary" },
32
+ };
33
+ const outcomes = {
34
+ approved: "Approval recorded. This does not confirm the action has completed.",
35
+ rejected: "The proposed action was declined.",
36
+ expired: "This approval expired. No approval was granted.",
37
+ cancelled: "This approval was cancelled. No approval was granted.",
38
+ };
39
+ /**
40
+ * Asks someone in chat to approve or decline an action an agent proposed.
41
+ * Built on `ReviewCard`: it folds once decided, and when the decision was
42
+ * made from inside the card, focus moves to the outcome.
43
+ */
44
+ export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, className, ...props }) {
45
+ const done = settledKinds.has(state.kind);
46
+ const section = useRef(null);
47
+ const result = useRef(null);
48
+ const submittedHere = useRef(false);
49
+ useEffect(() => {
50
+ if (state.kind === "submitting")
51
+ submittedHere.current =
52
+ section.current?.contains(document.activeElement) ?? false;
53
+ if (done && submittedHere.current) {
54
+ result.current?.focus();
55
+ submittedHere.current = false;
56
+ }
57
+ }, [done, state.kind]);
58
+ const submitting = state.kind === "submitting";
59
+ const busy = (decision) => state.kind === "submitting" && state.decision === decision;
60
+ const outcome = outcomes[state.kind];
61
+ return (_jsx("div", { ref: section, "data-slot": "chat-confirmation", "data-state": state.kind, ...props, className: cn("sprout-chat-confirmation", className), children: _jsxs(ReviewCard, { icon: _jsx(ShieldUser, { size: 16 }), title: title, badge: badges[state.kind], settled: done, status: state.kind === "error" || outcome ? (_jsxs(_Fragment, { children: [state.kind === "error" && (_jsx("p", { role: "alert", className: "sprout-chat-confirmation-error", children: state.message })), outcome && (_jsx("p", { ref: result, tabIndex: -1, role: "status", className: "sprout-chat-confirmation-result", children: outcome }))] })) : undefined, actions: done ? undefined : (_jsxs(_Fragment, { children: [_jsxs(Button, { disabled: disabled || submitting, "aria-busy": busy("approve"), onClick: () => onDecision("approve"), children: [busy("approve") && _jsx(Spinner, { "aria-hidden": "true" }), "Approve action"] }), _jsxs(Button, { variant: "ghost", disabled: disabled || submitting, "aria-busy": busy("reject"), onClick: () => onDecision("reject"), children: [busy("reject") && _jsx(Spinner, { "aria-hidden": "true" }), "Decline"] })] })), children: [_jsx("p", { className: "sprout-chat-confirmation-description", children: description }), _jsx(ReviewRows, { children: details.map((detail) => (_jsx(ReviewRow, { label: detail.label, children: detail.value }, detail.label))) })] }) }));
62
+ }
@@ -0,0 +1,94 @@
1
+ import { type ReactNode } from "react";
2
+ import { type AttachmentFile } from "./attachment.js";
3
+ import { type Brand } from "./brand-icon.js";
4
+ import { type RichTextValue } from "./rich-text-editor.js";
5
+ export declare const chatInputReferenceKindNames: readonly ["agent", "skill", "file"];
6
+ export declare const chatInputStatusNames: readonly ["idle", "streaming"];
7
+ export type ChatInputReferenceKind = (typeof chatInputReferenceKindNames)[number];
8
+ export type ChatInputStatus = (typeof chatInputStatusNames)[number];
9
+ /** One row in the `@`, `/`, or `#` panel. Picking it drops a chip into the message. */
10
+ export interface ChatInputSuggestion {
11
+ id: string;
12
+ label: string;
13
+ description?: string | undefined;
14
+ /** A 16px icon, file icon, brand glyph, or small avatar. */
15
+ media?: ReactNode;
16
+ }
17
+ /** Returns the rows that match what follows the trigger. It may be async. */
18
+ export type ChatInputSource = (query: string) => ChatInputSuggestion[] | Promise<ChatInputSuggestion[]>;
19
+ export interface ChatInputAction {
20
+ id: string;
21
+ label: string;
22
+ description?: string | undefined;
23
+ icon?: ReactNode;
24
+ onSelect: () => void;
25
+ }
26
+ export interface ChatInputOption {
27
+ id: string;
28
+ label: string;
29
+ description?: string | undefined;
30
+ icon?: ReactNode;
31
+ /** Modes only. Any CSS color; tints the box border, chip, and menu icon while on. */
32
+ color?: string | undefined;
33
+ }
34
+ export interface ChatInputModel {
35
+ id: string;
36
+ label: string;
37
+ description?: string | undefined;
38
+ /** Draws the vendor logo. Use `icon` for a mark that isn't a `Brand`. */
39
+ brand?: Brand | undefined;
40
+ icon?: ReactNode;
41
+ disabled?: boolean | undefined;
42
+ }
43
+ export interface ChatInputPrompt {
44
+ id: string;
45
+ label: string;
46
+ icon?: ReactNode;
47
+ /** The text put in the message. Defaults to `label`. */
48
+ prompt?: string | undefined;
49
+ }
50
+ export interface ChatInputProps {
51
+ value: RichTextValue;
52
+ onValueChange: (value: RichTextValue) => void;
53
+ /** Runs on Enter, Cmd or Ctrl+Enter, and the send button, only when the message has content. */
54
+ onSend: () => void;
55
+ /** Shown in place of send while `status` is `streaming`. */
56
+ onStop?: (() => void) | undefined;
57
+ /** `streaming` swaps send for stop and shows `streamingPlaceholder`. */
58
+ status?: ChatInputStatus | undefined;
59
+ placeholder?: string | undefined;
60
+ streamingPlaceholder?: string | undefined;
61
+ disabled?: boolean | undefined;
62
+ /** Accessible name of the form. Defaults to `Message`. */
63
+ label?: string | undefined;
64
+ /** `@` opens these. Leave unset to turn the trigger off. */
65
+ agents?: ChatInputSource | undefined;
66
+ /** `/` opens these. */
67
+ skills?: ChatInputSource | undefined;
68
+ /** `#` opens these. */
69
+ files?: ChatInputSource | undefined;
70
+ attachments?: AttachmentFile[] | undefined;
71
+ onRemoveAttachment?: ((id: string) => void) | undefined;
72
+ /** The `+` menu, such as upload from computer, Google Drive, or a URL. */
73
+ attachActions?: ChatInputAction[] | undefined;
74
+ /** The modes menu, such as Plan, Deep research, or Learning. One mode at a time. */
75
+ modes?: ChatInputOption[] | undefined;
76
+ mode?: string | null | undefined;
77
+ onModeChange?: ((mode: string | null) => void) | undefined;
78
+ projects?: ChatInputOption[] | undefined;
79
+ project?: string | undefined;
80
+ onProjectChange?: ((project: string) => void) | undefined;
81
+ models?: ChatInputModel[] | undefined;
82
+ model?: string | undefined;
83
+ onModelChange?: ((model: string) => void) | undefined;
84
+ /** Starter chips under an empty message. A click fills the message. */
85
+ prompts?: ChatInputPrompt[] | undefined;
86
+ onPromptSelect?: ((prompt: ChatInputPrompt) => void) | undefined;
87
+ className?: string | undefined;
88
+ }
89
+ /**
90
+ * A chat message box on `RichTextEditor`. `@` tags agents, `/` adds skills,
91
+ * and `#` adds files. The bar holds attach and mode menus, a project picker,
92
+ * a model picker, and send or stop. Starter prompts sit under an empty box.
93
+ */
94
+ export declare function ChatInput({ value, onValueChange, onSend, onStop, status, placeholder, streamingPlaceholder, disabled, label, agents, skills, files, attachments, onRemoveAttachment, attachActions, modes, mode, onModeChange, projects, project, onProjectChange, models, model, onModelChange, prompts, onPromptSelect, className, }: ChatInputProps): import("react").JSX.Element;