@tulipfarm/sprout 0.3.0 → 0.4.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 (349) hide show
  1. package/README.md +45 -40
  2. package/dist/components/accordion.d.ts +2 -2
  3. package/dist/components/accordion.js +9 -9
  4. package/dist/components/agent-fanout.d.ts +2 -2
  5. package/dist/components/agent-fanout.js +65 -87
  6. package/dist/components/alert-dialog.d.ts +6 -6
  7. package/dist/components/alert-dialog.js +20 -20
  8. package/dist/components/alert.d.ts +6 -6
  9. package/dist/components/alert.js +13 -13
  10. package/dist/components/aspect-ratio.d.ts +2 -2
  11. package/dist/components/aspect-ratio.js +2 -2
  12. package/dist/components/attachment.d.ts +17 -17
  13. package/dist/components/attachment.js +82 -115
  14. package/dist/components/avatar.d.ts +10 -10
  15. package/dist/components/avatar.js +14 -14
  16. package/dist/components/badge.d.ts +4 -4
  17. package/dist/components/badge.js +18 -18
  18. package/dist/components/board.d.ts +107 -0
  19. package/dist/components/board.js +640 -0
  20. package/dist/components/brand-icon.d.ts +6 -6
  21. package/dist/components/brand-icon.js +55 -63
  22. package/dist/components/breadcrumb.d.ts +11 -11
  23. package/dist/components/breadcrumb.js +16 -18
  24. package/dist/components/button-group.d.ts +6 -6
  25. package/dist/components/button-group.js +14 -14
  26. package/dist/components/button.d.ts +11 -11
  27. package/dist/components/button.js +46 -56
  28. package/dist/components/calendar.d.ts +5 -5
  29. package/dist/components/calendar.js +44 -53
  30. package/dist/components/canvas.d.ts +4 -4
  31. package/dist/components/canvas.js +39 -46
  32. package/dist/components/card.d.ts +6 -6
  33. package/dist/components/card.js +17 -17
  34. package/dist/components/carousel.d.ts +7 -7
  35. package/dist/components/carousel.js +57 -75
  36. package/dist/components/chart.d.ts +5 -112
  37. package/dist/components/chart.js +5 -172
  38. package/dist/components/chat-confirmation.d.ts +13 -11
  39. package/dist/components/chat-confirmation.js +32 -38
  40. package/dist/components/chat-input.d.ts +4 -4
  41. package/dist/components/chat-input.js +74 -81
  42. package/dist/components/chat-plan.d.ts +2 -2
  43. package/dist/components/chat-plan.js +15 -20
  44. package/dist/components/chat-sources.d.ts +8 -8
  45. package/dist/components/chat-sources.js +18 -27
  46. package/dist/components/checkbox.d.ts +1 -1
  47. package/dist/components/checkbox.js +9 -9
  48. package/dist/components/choice-list.d.ts +2 -2
  49. package/dist/components/choice-list.js +16 -18
  50. package/dist/components/code-block.d.ts +5 -5
  51. package/dist/components/code-block.js +26 -26
  52. package/dist/components/collapsible.d.ts +1 -1
  53. package/dist/components/collapsible.js +7 -11
  54. package/dist/components/combobox.d.ts +3 -3
  55. package/dist/components/combobox.js +24 -24
  56. package/dist/components/command.d.ts +13 -13
  57. package/dist/components/command.js +61 -73
  58. package/dist/components/context-menu.d.ts +5 -5
  59. package/dist/components/context-menu.js +22 -22
  60. package/dist/components/dialog.d.ts +6 -6
  61. package/dist/components/dialog.js +23 -28
  62. package/dist/components/direction.d.ts +1 -1
  63. package/dist/components/direction.js +1 -1
  64. package/dist/components/dropdown-menu.d.ts +5 -5
  65. package/dist/components/dropdown-menu.js +20 -20
  66. package/dist/components/field.d.ts +11 -11
  67. package/dist/components/field.js +41 -61
  68. package/dist/components/file-explorer.d.ts +2 -2
  69. package/dist/components/file-explorer.js +89 -105
  70. package/dist/components/file-viewer.d.ts +10 -10
  71. package/dist/components/file-viewer.js +112 -140
  72. package/dist/components/form.d.ts +7 -7
  73. package/dist/components/form.js +24 -28
  74. package/dist/components/glass-banner.d.ts +3 -3
  75. package/dist/components/glass-banner.js +21 -24
  76. package/dist/components/gradient-banner.d.ts +5 -5
  77. package/dist/components/gradient-banner.js +13 -22
  78. package/dist/components/hover-card.d.ts +4 -4
  79. package/dist/components/hover-card.js +6 -6
  80. package/dist/components/input-group.d.ts +11 -11
  81. package/dist/components/input-group.js +22 -36
  82. package/dist/components/input-otp.d.ts +10 -10
  83. package/dist/components/input-otp.js +13 -15
  84. package/dist/components/input.d.ts +1 -1
  85. package/dist/components/input.js +7 -7
  86. package/dist/components/kbd.d.ts +3 -3
  87. package/dist/components/kbd.js +5 -5
  88. package/dist/components/label.d.ts +2 -2
  89. package/dist/components/label.js +2 -2
  90. package/dist/components/mention-list.d.ts +3 -3
  91. package/dist/components/mention-list.js +10 -10
  92. package/dist/components/menubar.d.ts +6 -6
  93. package/dist/components/menubar.js +22 -22
  94. package/dist/components/message-actions.d.ts +2 -2
  95. package/dist/components/message-actions.js +29 -31
  96. package/dist/components/message-response.d.ts +3 -3
  97. package/dist/components/message-response.js +18 -18
  98. package/dist/components/message-scroller.d.ts +12 -12
  99. package/dist/components/message-scroller.js +44 -56
  100. package/dist/components/message.d.ts +11 -11
  101. package/dist/components/message.js +25 -25
  102. package/dist/components/navigation-menu.d.ts +2 -2
  103. package/dist/components/navigation-menu.js +15 -15
  104. package/dist/components/notice-banner.d.ts +2 -2
  105. package/dist/components/notice-banner.js +2 -2
  106. package/dist/components/page-content.d.ts +2 -2
  107. package/dist/components/page-content.js +2 -2
  108. package/dist/components/page-header.d.ts +1 -1
  109. package/dist/components/page-header.js +16 -16
  110. package/dist/components/pagination.d.ts +9 -9
  111. package/dist/components/pagination.js +17 -17
  112. package/dist/components/plan-outline.d.ts +2 -2
  113. package/dist/components/plan-outline.js +43 -60
  114. package/dist/components/popover.d.ts +6 -6
  115. package/dist/components/popover.js +15 -15
  116. package/dist/components/presence-cursor.d.ts +2 -2
  117. package/dist/components/presence-cursor.js +3 -3
  118. package/dist/components/progress.d.ts +1 -1
  119. package/dist/components/progress.js +8 -8
  120. package/dist/components/prompt-list.d.ts +3 -3
  121. package/dist/components/prompt-list.js +6 -6
  122. package/dist/components/questionnaire.d.ts +19 -19
  123. package/dist/components/questionnaire.js +183 -242
  124. package/dist/components/radio-group.d.ts +2 -2
  125. package/dist/components/radio-group.js +6 -6
  126. package/dist/components/reasoning-effort.d.ts +3 -3
  127. package/dist/components/reasoning-effort.js +9 -12
  128. package/dist/components/record-list.d.ts +66 -0
  129. package/dist/components/record-list.js +151 -0
  130. package/dist/components/resizable.d.ts +5 -5
  131. package/dist/components/resizable.js +76 -102
  132. package/dist/components/result-card.d.ts +10 -5
  133. package/dist/components/result-card.js +42 -53
  134. package/dist/components/result-notice.d.ts +18 -0
  135. package/dist/components/result-notice.js +29 -0
  136. package/dist/components/review-card.d.ts +6 -6
  137. package/dist/components/review-card.js +18 -18
  138. package/dist/components/rich-text-editor.d.ts +2 -2
  139. package/dist/components/rich-text-editor.js +56 -72
  140. package/dist/components/schema-diagram.d.ts +3 -3
  141. package/dist/components/schema-diagram.js +39 -53
  142. package/dist/components/scroll-area.d.ts +1 -1
  143. package/dist/components/scroll-area.js +10 -14
  144. package/dist/components/search-dialog.d.ts +6 -6
  145. package/dist/components/search-dialog.js +16 -16
  146. package/dist/components/search-field.d.ts +1 -1
  147. package/dist/components/search-field.js +11 -11
  148. package/dist/components/select.d.ts +3 -3
  149. package/dist/components/select.js +20 -20
  150. package/dist/components/selection-slot.d.ts +2 -2
  151. package/dist/components/selection-slot.js +6 -9
  152. package/dist/components/separator.d.ts +15 -15
  153. package/dist/components/separator.js +22 -27
  154. package/dist/components/settings-list.d.ts +3 -3
  155. package/dist/components/settings-list.js +5 -5
  156. package/dist/components/sheet.d.ts +6 -6
  157. package/dist/components/sheet.js +27 -27
  158. package/dist/components/sidebar.d.ts +22 -22
  159. package/dist/components/sidebar.js +57 -58
  160. package/dist/components/skeleton.d.ts +5 -5
  161. package/dist/components/skeleton.js +14 -21
  162. package/dist/components/slider.d.ts +2 -2
  163. package/dist/components/slider.js +6 -6
  164. package/dist/components/spinner.d.ts +5 -5
  165. package/dist/components/spinner.js +22 -26
  166. package/dist/components/sql-viewer.d.ts +14 -14
  167. package/dist/components/sql-viewer.js +99 -128
  168. package/dist/components/state-panel-samples.d.ts +2 -2
  169. package/dist/components/state-panel-samples.js +209 -245
  170. package/dist/components/state-panel.d.ts +2 -35
  171. package/dist/components/state-panel.js +2 -29
  172. package/dist/components/state-sample.d.ts +7 -7
  173. package/dist/components/state-sample.js +18 -31
  174. package/dist/components/switch.d.ts +1 -1
  175. package/dist/components/switch.js +7 -7
  176. package/dist/components/table-nuqs.d.ts +2 -2
  177. package/dist/components/table-nuqs.js +11 -12
  178. package/dist/components/table.d.ts +4 -4
  179. package/dist/components/table.js +166 -235
  180. package/dist/components/tabs.d.ts +2 -2
  181. package/dist/components/tabs.js +12 -12
  182. package/dist/components/textarea.d.ts +2 -2
  183. package/dist/components/textarea.js +6 -8
  184. package/dist/components/timeline.d.ts +3 -0
  185. package/dist/components/timeline.js +3 -0
  186. package/dist/components/toast.d.ts +2 -2
  187. package/dist/components/toast.js +19 -25
  188. package/dist/components/toggle-group.d.ts +2 -2
  189. package/dist/components/toggle-group.js +18 -20
  190. package/dist/components/toggle.d.ts +2 -2
  191. package/dist/components/toggle.js +8 -8
  192. package/dist/components/tool-activity.d.ts +1 -1
  193. package/dist/components/tool-activity.js +83 -110
  194. package/dist/components/toolbar-status.d.ts +2 -2
  195. package/dist/components/toolbar-status.js +7 -7
  196. package/dist/components/tooltip.d.ts +5 -5
  197. package/dist/components/tooltip.js +12 -11
  198. package/dist/components/typed-text.d.ts +2 -2
  199. package/dist/components/typed-text.js +10 -12
  200. package/dist/components/view-switcher.d.ts +51 -0
  201. package/dist/components/view-switcher.js +114 -0
  202. package/dist/index.d.ts +98 -93
  203. package/dist/index.js +98 -93
  204. package/dist/internal/chart-kit.d.ts +142 -0
  205. package/dist/internal/chart-kit.js +200 -0
  206. package/dist/internal/charts/bars.d.ts +61 -0
  207. package/dist/internal/charts/bars.js +86 -0
  208. package/dist/internal/charts/lines.d.ts +67 -0
  209. package/dist/internal/charts/lines.js +70 -0
  210. package/dist/internal/charts/more.d.ts +77 -0
  211. package/dist/internal/charts/more.js +68 -0
  212. package/dist/internal/charts/parts.d.ts +54 -0
  213. package/dist/internal/charts/parts.js +82 -0
  214. package/dist/internal/charts/timeline-dates.d.ts +38 -0
  215. package/dist/internal/charts/timeline-dates.js +113 -0
  216. package/dist/internal/charts/timeline-window.d.ts +31 -0
  217. package/dist/internal/charts/timeline-window.js +26 -0
  218. package/dist/internal/charts/timeline.d.ts +72 -0
  219. package/dist/internal/charts/timeline.js +287 -0
  220. package/dist/internal/classes.d.ts +1 -1
  221. package/dist/internal/classes.js +7 -9
  222. package/dist/internal/code-tokens.d.ts +2 -2
  223. package/dist/internal/code-tokens.js +12 -12
  224. package/dist/internal/fieldset.d.ts +1 -1
  225. package/dist/internal/fieldset.js +6 -6
  226. package/dist/internal/file-kind.d.ts +1 -1
  227. package/dist/internal/file-kind.js +43 -51
  228. package/dist/internal/flow.d.ts +4 -4
  229. package/dist/internal/flow.js +20 -23
  230. package/dist/internal/languages.js +999 -999
  231. package/dist/internal/message-scroller.d.ts +3 -3
  232. package/dist/internal/message-scroller.js +64 -112
  233. package/dist/internal/pressable.d.ts +1 -1
  234. package/dist/internal/pressable.js +7 -7
  235. package/dist/internal/state-panel.d.ts +35 -0
  236. package/dist/internal/state-panel.js +22 -0
  237. package/dist/internal/syntax.d.ts +2 -2
  238. package/dist/internal/syntax.js +36 -47
  239. package/dist/styles/accordion.css +3 -5
  240. package/dist/styles/agent-fanout.css +64 -60
  241. package/dist/styles/alert-dialog.css +12 -26
  242. package/dist/styles/alert.css +10 -15
  243. package/dist/styles/attachment.css +51 -93
  244. package/dist/styles/avatar.css +17 -24
  245. package/dist/styles/badge.css +11 -36
  246. package/dist/styles/board.css +571 -0
  247. package/dist/styles/brand-icon.css +7 -8
  248. package/dist/styles/breadcrumb.css +4 -7
  249. package/dist/styles/button-group.css +8 -14
  250. package/dist/styles/button.css +22 -27
  251. package/dist/styles/calendar.css +24 -36
  252. package/dist/styles/canvas.css +2 -3
  253. package/dist/styles/card.css +7 -23
  254. package/dist/styles/carousel.css +11 -12
  255. package/dist/styles/chart.css +215 -31
  256. package/dist/styles/chat-input.css +15 -39
  257. package/dist/styles/chat-plan.css +3 -4
  258. package/dist/styles/chat-sources.css +3 -6
  259. package/dist/styles/checkbox.css +11 -25
  260. package/dist/styles/choice-list.css +17 -31
  261. package/dist/styles/code-block.css +11 -25
  262. package/dist/styles/collapsible.css +10 -15
  263. package/dist/styles/combobox.css +11 -15
  264. package/dist/styles/command.css +5 -8
  265. package/dist/styles/context-menu.css +2 -2
  266. package/dist/styles/dialog.css +5 -16
  267. package/dist/styles/dropdown-menu.css +2 -2
  268. package/dist/styles/field.css +15 -21
  269. package/dist/styles/file-explorer.css +19 -33
  270. package/dist/styles/file-viewer.css +13 -17
  271. package/dist/styles/form.css +3 -3
  272. package/dist/styles/glass-banner.css +12 -47
  273. package/dist/styles/gradient-banner.css +17 -35
  274. package/dist/styles/hover-card.css +9 -15
  275. package/dist/styles/index.css +116 -108
  276. package/dist/styles/input-group.css +25 -41
  277. package/dist/styles/input-otp.css +5 -6
  278. package/dist/styles/input.css +5 -5
  279. package/dist/styles/kbd.css +1 -1
  280. package/dist/styles/label.css +9 -30
  281. package/dist/styles/mention-list.css +6 -8
  282. package/dist/styles/menubar.css +5 -6
  283. package/dist/styles/message-actions.css +1 -1
  284. package/dist/styles/message-response.css +3 -5
  285. package/dist/styles/message-scroller.css +14 -21
  286. package/dist/styles/message.css +23 -60
  287. package/dist/styles/navigation-menu.css +14 -29
  288. package/dist/styles/notice-banner.css +1 -2
  289. package/dist/styles/page-header.css +7 -10
  290. package/dist/styles/pagination.css +1 -4
  291. package/dist/styles/plan-outline.css +20 -37
  292. package/dist/styles/popover.css +10 -19
  293. package/dist/styles/presence-cursor.css +1 -2
  294. package/dist/styles/progress.css +2 -4
  295. package/dist/styles/prompt-list.css +6 -17
  296. package/dist/styles/questionnaire.css +16 -40
  297. package/dist/styles/radio-group.css +12 -23
  298. package/dist/styles/reasoning-effort.css +8 -15
  299. package/dist/styles/record-list.css +243 -0
  300. package/dist/styles/resizable.css +10 -11
  301. package/dist/styles/result-card.css +17 -3
  302. package/dist/styles/result-notice.css +80 -0
  303. package/dist/styles/review-card.css +2 -3
  304. package/dist/styles/rich-text-editor.css +1 -2
  305. package/dist/styles/schema-diagram.css +12 -17
  306. package/dist/styles/scroll-area.css +8 -10
  307. package/dist/styles/search-dialog.css +1 -5
  308. package/dist/styles/search-field.css +1 -2
  309. package/dist/styles/select.css +7 -7
  310. package/dist/styles/selection-slot.css +1 -2
  311. package/dist/styles/separator.css +7 -8
  312. package/dist/styles/settings-list.css +1 -2
  313. package/dist/styles/sheet.css +40 -73
  314. package/dist/styles/sidebar.css +17 -21
  315. package/dist/styles/skeleton.css +9 -11
  316. package/dist/styles/slider.css +11 -21
  317. package/dist/styles/spinner.css +2 -2
  318. package/dist/styles/sql-viewer.css +29 -29
  319. package/dist/styles/state-panel.css +8 -9
  320. package/dist/styles/state-sample.css +20 -33
  321. package/dist/styles/switch.css +11 -18
  322. package/dist/styles/table.css +51 -77
  323. package/dist/styles/tabs.css +12 -16
  324. package/dist/styles/textarea.css +3 -3
  325. package/dist/styles/themes/chatgpt.css +11 -23
  326. package/dist/styles/themes/claude.css +12 -24
  327. package/dist/styles/themes/cloudflare.css +11 -23
  328. package/dist/styles/themes/discord.css +11 -23
  329. package/dist/styles/themes/github.css +11 -23
  330. package/dist/styles/themes/grok.css +11 -23
  331. package/dist/styles/themes/linear.css +12 -25
  332. package/dist/styles/themes/neutral.css +11 -23
  333. package/dist/styles/themes/notion.css +11 -23
  334. package/dist/styles/themes/perplexity.css +11 -23
  335. package/dist/styles/themes/raycast.css +11 -23
  336. package/dist/styles/themes/spotify.css +11 -23
  337. package/dist/styles/themes/stripe.css +11 -23
  338. package/dist/styles/themes/supabase.css +11 -23
  339. package/dist/styles/themes/tulipfarm.css +9 -10
  340. package/dist/styles/themes/vercel.css +12 -25
  341. package/dist/styles/timeline.css +276 -0
  342. package/dist/styles/toast.css +13 -20
  343. package/dist/styles/toggle-group.css +17 -23
  344. package/dist/styles/toggle.css +8 -8
  345. package/dist/styles/tool-activity.css +7 -13
  346. package/dist/styles/toolbar-status.css +2 -7
  347. package/dist/styles/tooltip.css +15 -21
  348. package/dist/styles/view-switcher.css +279 -0
  349. package/package.json +21 -1
@@ -1,28 +1,28 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
2
  export declare const chatConfirmationStateNames: readonly ["pending", "submitting", "approved", "rejected", "expired", "cancelled", "error"];
3
- export type ChatConfirmationDecision = "approve" | "reject";
3
+ export type ChatConfirmationDecision = 'approve' | 'reject';
4
4
  export type ConfirmationState = {
5
- kind: "pending";
5
+ kind: 'pending';
6
6
  } | {
7
- kind: "submitting";
7
+ kind: 'submitting';
8
8
  decision: ChatConfirmationDecision;
9
9
  } | {
10
- kind: "approved";
10
+ kind: 'approved';
11
11
  } | {
12
- kind: "rejected";
12
+ kind: 'rejected';
13
13
  } | {
14
- kind: "expired";
14
+ kind: 'expired';
15
15
  } | {
16
- kind: "cancelled";
16
+ kind: 'cancelled';
17
17
  } | {
18
- kind: "error";
18
+ kind: 'error';
19
19
  message: string;
20
20
  };
21
21
  export type ChatConfirmationDetail = {
22
22
  label: string;
23
23
  value: string;
24
24
  };
25
- export interface ChatConfirmationProps extends Omit<ComponentProps<"div">, "title" | "children"> {
25
+ export interface ChatConfirmationProps extends Omit<ComponentProps<'div'>, 'title' | 'children'> {
26
26
  /** What the agent wants to do, such as “Remove the Notes field”. */
27
27
  title: string;
28
28
  /** One line above the facts, such as “Review these changes before approving.” */
@@ -33,10 +33,12 @@ export interface ChatConfirmationProps extends Omit<ComponentProps<"div">, "titl
33
33
  onDecision: (decision: ChatConfirmationDecision) => void;
34
34
  /** Locks both buttons, such as while the request is refreshing or cannot be verified. */
35
35
  disabled?: boolean | undefined;
36
+ /** Names the action on the approve button, such as “Approve 3 drafts”. */
37
+ approveLabel?: ReactNode;
36
38
  }
37
39
  /**
38
40
  * Asks someone in chat to approve or decline an action an agent proposed.
39
41
  * Built on `ReviewCard`: it folds once decided, and when the decision was
40
42
  * made from inside the card, focus moves to the outcome.
41
43
  */
42
- export declare function ChatConfirmation({ title, description, details, state, onDecision, disabled, className, ...props }: ChatConfirmationProps): import("react").JSX.Element;
44
+ export declare function ChatConfirmation({ title, description, details, state, onDecision, disabled, approveLabel, className, ...props }: ChatConfirmationProps): import("react").JSX.Element;
@@ -1,62 +1,56 @@
1
- "use client";
1
+ 'use client';
2
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";
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
9
  export const chatConfirmationStateNames = [
10
- "pending",
11
- "submitting",
12
- "approved",
13
- "rejected",
14
- "expired",
15
- "cancelled",
16
- "error",
10
+ 'pending',
11
+ 'submitting',
12
+ 'approved',
13
+ 'rejected',
14
+ 'expired',
15
+ 'cancelled',
16
+ 'error',
17
17
  ];
18
- const settledKinds = new Set([
19
- "approved",
20
- "rejected",
21
- "expired",
22
- "cancelled",
23
- ]);
18
+ const settledKinds = new Set(['approved', 'rejected', 'expired', 'cancelled']);
24
19
  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" },
20
+ pending: { label: 'Approval required', variant: 'warning' },
21
+ submitting: { label: 'Approval required', variant: 'warning' },
22
+ error: { label: 'Approval required', variant: 'warning' },
23
+ approved: { label: 'Approved', variant: 'info' },
24
+ rejected: { label: 'Declined', variant: 'secondary' },
25
+ expired: { label: 'Expired', variant: 'secondary' },
26
+ cancelled: { label: 'Cancelled', variant: 'secondary' },
32
27
  };
33
28
  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.",
29
+ approved: 'Approval recorded. This does not confirm the action has completed.',
30
+ rejected: 'The proposed action was declined.',
31
+ expired: 'This approval expired. No approval was granted.',
32
+ cancelled: 'This approval was cancelled. No approval was granted.',
38
33
  };
39
34
  /**
40
35
  * Asks someone in chat to approve or decline an action an agent proposed.
41
36
  * Built on `ReviewCard`: it folds once decided, and when the decision was
42
37
  * made from inside the card, focus moves to the outcome.
43
38
  */
44
- export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, className, ...props }) {
39
+ export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, approveLabel = 'Approve action', className, ...props }) {
45
40
  const done = settledKinds.has(state.kind);
46
41
  const section = useRef(null);
47
42
  const result = useRef(null);
48
43
  const submittedHere = useRef(false);
49
44
  useEffect(() => {
50
- if (state.kind === "submitting")
51
- submittedHere.current =
52
- section.current?.contains(document.activeElement) ?? false;
45
+ if (state.kind === 'submitting')
46
+ submittedHere.current = section.current?.contains(document.activeElement) ?? false;
53
47
  if (done && submittedHere.current) {
54
48
  result.current?.focus();
55
49
  submittedHere.current = false;
56
50
  }
57
51
  }, [done, state.kind]);
58
- const submitting = state.kind === "submitting";
59
- const busy = (decision) => state.kind === "submitting" && state.decision === decision;
52
+ const submitting = state.kind === 'submitting';
53
+ const busy = (decision) => state.kind === 'submitting' && state.decision === decision;
60
54
  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))) })] }) }));
55
+ 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" }), approveLabel] }), _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
56
  }
@@ -1,7 +1,7 @@
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";
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
5
  export declare const chatInputReferenceKindNames: readonly ["agent", "skill", "file"];
6
6
  export declare const chatInputStatusNames: readonly ["idle", "streaming"];
7
7
  export type ChatInputReferenceKind = (typeof chatInputReferenceKindNames)[number];
@@ -1,92 +1,92 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useId, useLayoutEffect, useMemo, useRef, useState, } from "react";
4
- import { Extension, Node, mergeAttributes, } from "@tiptap/core";
5
- import { PluginKey } from "@tiptap/pm/state";
6
- import Suggestion, { exitSuggestion, } from "@tiptap/suggestion";
7
- import { ArrowUp } from "reicon-react/icons/ArrowUp";
8
- import { ChevronDown } from "reicon-react/icons/ChevronDown";
9
- import { Folder } from "reicon-react/icons/Folder";
10
- import { Plus } from "reicon-react/icons/Plus";
11
- import { Sliders } from "reicon-react/icons/Sliders";
12
- import { X } from "reicon-react/icons/X";
13
- import { cn } from "../internal/classes.js";
14
- import { FileAttachment } from "./attachment.js";
15
- import { BrandIcon } from "./brand-icon.js";
16
- import { Button } from "./button.js";
17
- import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "./command.js";
18
- import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from "./dropdown-menu.js";
19
- import { InputGroup, InputGroupAddon, InputGroupButton, } from "./input-group.js";
20
- import { MentionList, MentionOption, MentionStatus } from "./mention-list.js";
21
- import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
22
- import { RichTextEditor, } from "./rich-text-editor.js";
23
- import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
24
- export const chatInputReferenceKindNames = ["agent", "skill", "file"];
25
- export const chatInputStatusNames = ["idle", "streaming"];
3
+ import { useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
4
+ import { Extension, Node, mergeAttributes } from '@tiptap/core';
5
+ import { PluginKey } from '@tiptap/pm/state';
6
+ import Suggestion, { exitSuggestion } from '@tiptap/suggestion';
7
+ import { ArrowUp } from 'reicon-react/icons/ArrowUp';
8
+ import { ChevronDown } from 'reicon-react/icons/ChevronDown';
9
+ import { Folder } from 'reicon-react/icons/Folder';
10
+ import { Plus } from 'reicon-react/icons/Plus';
11
+ import { Sliders } from 'reicon-react/icons/Sliders';
12
+ import { X } from 'reicon-react/icons/X';
13
+ import { cn } from '../internal/classes.js';
14
+ import { FileAttachment } from './attachment.js';
15
+ import { BrandIcon } from './brand-icon.js';
16
+ import { Button } from './button.js';
17
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from './command.js';
18
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from './dropdown-menu.js';
19
+ import { InputGroup, InputGroupAddon, InputGroupButton } from './input-group.js';
20
+ import { MentionList, MentionOption, MentionStatus } from './mention-list.js';
21
+ import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
22
+ import { RichTextEditor } from './rich-text-editor.js';
23
+ import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip.js';
24
+ export const chatInputReferenceKindNames = ['agent', 'skill', 'file'];
25
+ export const chatInputStatusNames = ['idle', 'streaming'];
26
26
  const triggers = {
27
- agent: { char: "@", label: "Agents", empty: "No agents match." },
28
- skill: { char: "/", label: "Skills", empty: "No skills match." },
29
- file: { char: "#", label: "Files", empty: "No files match." },
27
+ agent: { char: '@', label: 'Agents', empty: 'No agents match.' },
28
+ skill: { char: '/', label: 'Skills', empty: 'No skills match.' },
29
+ file: { char: '#', label: 'Files', empty: 'No files match.' },
30
30
  };
31
31
  const referenceNode = Node.create({
32
- name: "chatReference",
32
+ name: 'chatReference',
33
33
  inline: true,
34
- group: "inline",
34
+ group: 'inline',
35
35
  atom: true,
36
36
  selectable: true,
37
37
  addAttributes() {
38
38
  return {
39
39
  kind: {
40
- default: "file",
40
+ default: 'file',
41
41
  rendered: false,
42
- parseHTML: (el) => el.getAttribute("data-chat-reference"),
42
+ parseHTML: el => el.getAttribute('data-chat-reference'),
43
43
  },
44
44
  id: {
45
- default: "",
45
+ default: '',
46
46
  rendered: false,
47
- parseHTML: (el) => el.getAttribute("data-id"),
47
+ parseHTML: el => el.getAttribute('data-id'),
48
48
  },
49
49
  label: {
50
- default: "",
50
+ default: '',
51
51
  rendered: false,
52
- parseHTML: (el) => el.getAttribute("data-label"),
52
+ parseHTML: el => el.getAttribute('data-label'),
53
53
  },
54
54
  };
55
55
  },
56
56
  parseHTML() {
57
- return [{ tag: "span[data-chat-reference]" }];
57
+ return [{ tag: 'span[data-chat-reference]' }];
58
58
  },
59
59
  renderHTML({ node, HTMLAttributes }) {
60
60
  const kind = node.attrs.kind;
61
61
  return [
62
- "span",
62
+ 'span',
63
63
  mergeAttributes(HTMLAttributes, {
64
- "data-chat-reference": kind,
65
- "data-id": node.attrs.id,
66
- "data-label": node.attrs.label,
67
- class: "sprout-chat-input-reference",
64
+ 'data-chat-reference': kind,
65
+ 'data-id': node.attrs.id,
66
+ 'data-label': node.attrs.label,
67
+ class: 'sprout-chat-input-reference',
68
68
  }),
69
- `${triggers[kind]?.char ?? ""}${node.attrs.label}`,
69
+ `${triggers[kind]?.char ?? ''}${node.attrs.label}`,
70
70
  ];
71
71
  },
72
72
  renderText({ node }) {
73
73
  const kind = node.attrs.kind;
74
- return `${triggers[kind]?.char ?? ""}${node.attrs.label}`;
74
+ return `${triggers[kind]?.char ?? ''}${node.attrs.label}`;
75
75
  },
76
76
  });
77
77
  const linkShortcut = Extension.create({
78
- name: "chatInputLinkShortcut",
78
+ name: 'chatInputLinkShortcut',
79
79
  addKeyboardShortcuts() {
80
80
  return {
81
- "Mod-k": ({ editor }) => {
82
- if (editor.isActive("link"))
81
+ 'Mod-k': ({ editor }) => {
82
+ if (editor.isActive('link'))
83
83
  return editor.chain().focus().unsetLink().run();
84
84
  const { from, to } = editor.state.selection;
85
85
  const text = editor.state.doc.textBetween(from, to).trim();
86
86
  const href = /^\S+@\S+\.\S+$/.test(text)
87
87
  ? `mailto:${text}`
88
88
  : /^(https?:\/\/|www\.)\S+$/i.test(text)
89
- ? text.startsWith("www.")
89
+ ? text.startsWith('www.')
90
90
  ? `https://${text}`
91
91
  : text
92
92
  : null;
@@ -114,10 +114,10 @@ function triggerExtension(kind, source, onState) {
114
114
  .focus()
115
115
  .insertContentAt(range, [
116
116
  {
117
- type: "chatReference",
117
+ type: 'chatReference',
118
118
  attrs: { kind, id: props.id, label: props.label },
119
119
  },
120
- { type: "text", text: " " },
120
+ { type: 'text', text: ' ' },
121
121
  ])
122
122
  .run(),
123
123
  render: () => {
@@ -131,7 +131,7 @@ function triggerExtension(kind, source, onState) {
131
131
  kind,
132
132
  items,
133
133
  active: Math.min(active, Math.max(0, items.length - 1)),
134
- select: (index) => {
134
+ select: index => {
135
135
  const item = items[index];
136
136
  if (item)
137
137
  current?.command(item);
@@ -139,33 +139,30 @@ function triggerExtension(kind, source, onState) {
139
139
  });
140
140
  };
141
141
  return {
142
- onStart: (props) => {
142
+ onStart: props => {
143
143
  current = props;
144
144
  active = 0;
145
145
  publish();
146
146
  },
147
- onUpdate: (props) => {
147
+ onUpdate: props => {
148
148
  current = props;
149
149
  active = 0;
150
150
  publish();
151
151
  },
152
152
  onKeyDown: ({ event, view }) => {
153
- if (event.key === "Escape") {
153
+ if (event.key === 'Escape') {
154
154
  exitSuggestion(view, key);
155
155
  return true;
156
156
  }
157
157
  const count = current?.items.length ?? 0;
158
158
  if (!count)
159
159
  return false;
160
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
161
- active =
162
- (active + (event.key === "ArrowDown" ? 1 : count - 1)) %
163
- count;
160
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
161
+ active = (active + (event.key === 'ArrowDown' ? 1 : count - 1)) % count;
164
162
  publish();
165
163
  return true;
166
164
  }
167
- if ((event.key === "Enter" && !event.shiftKey) ||
168
- event.key === "Tab") {
165
+ if ((event.key === 'Enter' && !event.shiftKey) || event.key === 'Tab') {
169
166
  current.command(current.items[active]);
170
167
  return true;
171
168
  }
@@ -183,7 +180,7 @@ function triggerExtension(kind, source, onState) {
183
180
  });
184
181
  }
185
182
  function hasContent(node) {
186
- if (node.type === "chatReference")
183
+ if (node.type === 'chatReference')
187
184
  return true;
188
185
  if (node.text?.trim())
189
186
  return true;
@@ -191,8 +188,8 @@ function hasContent(node) {
191
188
  }
192
189
  function textDoc(text) {
193
190
  return {
194
- type: "doc",
195
- content: [{ type: "paragraph", content: [{ type: "text", text }] }],
191
+ type: 'doc',
192
+ content: [{ type: 'paragraph', content: [{ type: 'text', text }] }],
196
193
  };
197
194
  }
198
195
  function ModelMark({ model }) {
@@ -202,8 +199,8 @@ function ModelMark({ model }) {
202
199
  }
203
200
  function OptionPicker({ label, search, options, value, onChange, disabled, icon, align, }) {
204
201
  const [open, setOpen] = useState(false);
205
- const selected = options.find((option) => option.id === value);
206
- return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, { size: "sm", "aria-label": `${label}: ${selected?.label ?? "None"}`, disabled: disabled, className: "sprout-chat-input-picker" }), children: [icon(selected), _jsx("span", { className: "sprout-chat-input-picker-label", children: selected?.label ?? label }), _jsx(ChevronDown, { size: 12, "aria-hidden": "true" })] }), _jsx(PopoverContent, { size: "picker", side: "top", align: align, sideOffset: 8, className: "sprout-chat-input-menu", children: _jsxs(Command, { children: [_jsx(CommandInput, { "aria-label": search, placeholder: `${search}…` }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No matches." }), _jsx(CommandGroup, { heading: label, children: options.map((option) => (_jsxs(CommandItem, { value: `${option.label} ${option.description ?? ""}`, "data-checked": option.id === value, disabled: "disabled" in option && !!option.disabled, onSelect: () => {
202
+ const selected = options.find(option => option.id === value);
203
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, { size: "sm", "aria-label": `${label}: ${selected?.label ?? 'None'}`, disabled: disabled, className: "sprout-chat-input-picker" }), children: [icon(selected), _jsx("span", { className: "sprout-chat-input-picker-label", children: selected?.label ?? label }), _jsx(ChevronDown, { size: 12, "aria-hidden": "true" })] }), _jsx(PopoverContent, { size: "picker", side: "top", align: align, sideOffset: 8, className: "sprout-chat-input-menu", children: _jsxs(Command, { children: [_jsx(CommandInput, { "aria-label": search, placeholder: `${search}…` }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No matches." }), _jsx(CommandGroup, { heading: label, children: options.map(option => (_jsxs(CommandItem, { value: `${option.label} ${option.description ?? ''}`, "data-checked": option.id === value, disabled: 'disabled' in option && !!option.disabled, onSelect: () => {
207
204
  onChange(option.id);
208
205
  setOpen(false);
209
206
  }, children: [icon(option), _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] })] }) })] }));
@@ -213,7 +210,7 @@ function OptionPicker({ label, search, options, value, onChange, disabled, icon,
213
210
  * and `#` adds files. The bar holds attach and mode menus, a project picker,
214
211
  * a model picker, and send or stop. Starter prompts sit under an empty box.
215
212
  */
216
- export function ChatInput({ value, onValueChange, onSend, onStop, status = "idle", placeholder = "Ask anything, @agents, /skills, #files…", streamingPlaceholder = "Working on your request…", disabled = false, label = "Message", agents, skills, files, attachments = [], onRemoveAttachment, attachActions, modes, mode = null, onModeChange, projects, project, onProjectChange, models, model, onModelChange, prompts, onPromptSelect, className, }) {
213
+ export function ChatInput({ value, onValueChange, onSend, onStop, status = 'idle', placeholder = 'Ask anything, @agents, /skills, #files…', streamingPlaceholder = 'Working on your request…', disabled = false, label = 'Message', agents, skills, files, attachments = [], onRemoveAttachment, attachActions, modes, mode = null, onModeChange, projects, project, onProjectChange, models, model, onModelChange, prompts, onPromptSelect, className, }) {
217
214
  const editor = useRef(null);
218
215
  const form = useRef(null);
219
216
  const listId = useId();
@@ -232,15 +229,15 @@ export function ChatInput({ value, onValueChange, onSend, onStop, status = "idle
232
229
  referenceNode,
233
230
  linkShortcut,
234
231
  ...chatInputReferenceKindNames
235
- .filter((kind) => sources[kind].current)
236
- .map((kind) => triggerExtension(kind, sources[kind], setPanel)),
232
+ .filter(kind => sources[kind].current)
233
+ .map(kind => triggerExtension(kind, sources[kind], setPanel)),
237
234
  ],
238
235
  // Sources are refs, so only adding or removing a trigger rebuilds the editor.
239
236
  [enabled]);
240
- const streaming = status === "streaming";
237
+ const streaming = status === 'streaming';
241
238
  const filled = hasContent(value) || attachments.length > 0;
242
239
  const canSend = filled && !disabled && !streaming;
243
- const activeMode = modes?.find((option) => option.id === mode);
240
+ const activeMode = modes?.find(option => option.id === mode);
244
241
  const optionId = (index) => `${listId}-option-${index}`;
245
242
  const panelOpen = !!panel;
246
243
  useLayoutEffect(() => {
@@ -255,25 +252,21 @@ export function ChatInput({ value, onValueChange, onSend, onStop, status = "idle
255
252
  };
256
253
  const fill = (prompt) => {
257
254
  editor.current?.setContent(textDoc(prompt.prompt ?? prompt.label));
258
- editor.current?.editor()?.commands.focus("end");
255
+ editor.current?.editor()?.commands.focus('end');
259
256
  onPromptSelect?.(prompt);
260
257
  };
261
- return (_jsxs("div", { "data-slot": "chat-input", "data-status": status, "data-mode-color": activeMode?.color ? "" : undefined, style: activeMode?.color
258
+ return (_jsxs("div", { "data-slot": "chat-input", "data-status": status, "data-mode-color": activeMode?.color ? '' : undefined, style: activeMode?.color
262
259
  ? {
263
- "--sprout-chat-input-mode": activeMode.color,
260
+ '--sprout-chat-input-mode': activeMode.color,
264
261
  }
265
- : undefined, className: cn("sprout-chat-input", className), children: [_jsxs("form", { ref: form, "aria-label": label, className: "sprout-chat-input-form", onSubmit: (event) => {
262
+ : undefined, className: cn('sprout-chat-input', className), children: [_jsxs("form", { ref: form, "aria-label": label, className: "sprout-chat-input-form", onSubmit: event => {
266
263
  event.preventDefault();
267
264
  send();
268
- }, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map((file) => (_jsx(FileAttachment, { file: file, variant: "chip", viewable: true, preview: true, onRemove: onRemoveAttachment && !disabled
269
- ? () => onRemoveAttachment(file.id)
270
- : undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": "Add files and more", disabled: disabled }) }), children: _jsx(Plus, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Add files and more" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Add" }), attachActions.map((action) => (_jsxs(DropdownMenuItem, { onClick: action.onSelect, children: [action.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: action.label }), action.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: action.description }))] })] }, action.id)))] }) })] })), modes && modes.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": `Mode: ${activeMode?.label ?? "Default"}`, disabled: disabled }) }), children: _jsx(Sliders, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Modes" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Mode" }), _jsx(DropdownMenuRadioGroup, { value: mode ?? "", onValueChange: (next) => onModeChange?.(next === mode || !next ? null : String(next)), children: modes.map((option) => (_jsxs(DropdownMenuRadioItem, { value: option.id, closeOnClick: true, style: option.color
265
+ }, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map(file => (_jsx(FileAttachment, { file: file, variant: "chip", viewable: true, preview: true, onRemove: onRemoveAttachment && !disabled ? () => onRemoveAttachment(file.id) : undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": "Add files and more", disabled: disabled }) }), children: _jsx(Plus, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Add files and more" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Add" }), attachActions.map(action => (_jsxs(DropdownMenuItem, { onClick: action.onSelect, children: [action.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: action.label }), action.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: action.description }))] })] }, action.id)))] }) })] })), modes && modes.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": `Mode: ${activeMode?.label ?? 'Default'}`, disabled: disabled }) }), children: _jsx(Sliders, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Modes" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Mode" }), _jsx(DropdownMenuRadioGroup, { value: mode ?? '', onValueChange: next => onModeChange?.(next === mode || !next ? null : String(next)), children: modes.map(option => (_jsxs(DropdownMenuRadioItem, { value: option.id, closeOnClick: true, style: option.color
271
266
  ? {
272
- "--sprout-chat-input-mode": option.color,
267
+ '--sprout-chat-input-mode': option.color,
273
268
  }
274
- : undefined, className: option.color
275
- ? "sprout-chat-input-mode-option"
276
- : undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, { size: "sm", variant: "secondary", className: "sprout-chat-input-mode", "aria-label": `Turn off ${activeMode.label}`, disabled: disabled, onClick: () => onModeChange?.(null), children: [activeMode.icon, _jsx("span", { className: "sprout-chat-input-picker-label", children: activeMode.label }), _jsx(X, { size: 12, "aria-hidden": "true" })] })), projects && projects.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "sprout-chat-input-divider", "aria-hidden": "true" }), _jsx(OptionPicker, { label: "Project", search: "Search projects", options: projects, value: project, onChange: (id) => onProjectChange?.(id), disabled: disabled, icon: (option) => option?.icon ?? (_jsx(Folder, { size: 16, "aria-hidden": "true" })), align: "start" })] }))] }), _jsxs("div", { className: "sprout-chat-input-bar-end", children: [models && models.length > 0 && (_jsx(OptionPicker, { label: "Model", search: "Search models", options: models, value: model, onChange: (id) => onModelChange?.(id), disabled: disabled, icon: (option) => option && _jsx(ModelMark, { model: option }), align: "end" })), streaming ? (_jsx(InputGroupButton, { size: "icon-sm", variant: "default", className: "sprout-chat-input-send", "aria-label": "Stop", onClick: onStop, children: _jsx("span", { className: "sprout-chat-input-stop", "aria-hidden": "true" }) })) : (_jsx(InputGroupButton, { type: "submit", size: "icon-sm", variant: canSend ? "default" : "secondary", className: "sprout-chat-input-send", "aria-label": "Send message", disabled: !canSend, children: _jsx(ArrowUp, { size: 16, "aria-hidden": "true" }) }))] })] }) })] }), panel && (_jsx("div", { className: "sprout-chat-input-panel", "data-side": panelBelow ? "bottom" : "top", children: _jsx(MentionList, { id: listId, label: triggers[panel.kind].label, announcement: panel.items.length
269
+ : undefined, className: option.color ? 'sprout-chat-input-mode-option' : undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, { size: "sm", variant: "secondary", className: "sprout-chat-input-mode", "aria-label": `Turn off ${activeMode.label}`, disabled: disabled, onClick: () => onModeChange?.(null), children: [activeMode.icon, _jsx("span", { className: "sprout-chat-input-picker-label", children: activeMode.label }), _jsx(X, { size: 12, "aria-hidden": "true" })] })), projects && projects.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "sprout-chat-input-divider", "aria-hidden": "true" }), _jsx(OptionPicker, { label: "Project", search: "Search projects", options: projects, value: project, onChange: id => onProjectChange?.(id), disabled: disabled, icon: option => option?.icon ?? _jsx(Folder, { size: 16, "aria-hidden": "true" }), align: "start" })] }))] }), _jsxs("div", { className: "sprout-chat-input-bar-end", children: [models && models.length > 0 && (_jsx(OptionPicker, { label: "Model", search: "Search models", options: models, value: model, onChange: id => onModelChange?.(id), disabled: disabled, icon: option => option && _jsx(ModelMark, { model: option }), align: "end" })), streaming ? (_jsx(InputGroupButton, { size: "icon-sm", variant: "default", className: "sprout-chat-input-send", "aria-label": "Stop", onClick: onStop, children: _jsx("span", { className: "sprout-chat-input-stop", "aria-hidden": "true" }) })) : (_jsx(InputGroupButton, { type: "submit", size: "icon-sm", variant: canSend ? 'default' : 'secondary', className: "sprout-chat-input-send", "aria-label": "Send message", disabled: !canSend, children: _jsx(ArrowUp, { size: 16, "aria-hidden": "true" }) }))] })] }) })] }), panel && (_jsx("div", { className: "sprout-chat-input-panel", "data-side": panelBelow ? 'bottom' : 'top', children: _jsx(MentionList, { id: listId, label: triggers[panel.kind].label, announcement: panel.items.length
277
270
  ? `${panel.items.length} ${triggers[panel.kind].label.toLowerCase()}. Use Up and Down to choose, Enter to add, Escape to close.`
278
- : triggers[panel.kind].empty, status: panel.items.length ? undefined : (_jsx(MentionStatus, { tone: "empty", children: triggers[panel.kind].empty })), children: panel.items.map((item, index) => (_jsx(MentionOption, { id: optionId(index), active: index === panel.active, onSelect: () => panel.select(index), media: item.media, title: item.label, description: item.description }, item.id))) }) }))] }), prompts && prompts.length > 0 && !filled && !streaming && (_jsx("div", { role: "group", "aria-label": "Suggested prompts", className: "sprout-chat-input-prompts", children: prompts.map((prompt) => (_jsxs(Button, { size: "sm", variant: "outline", disabled: disabled, className: "sprout-chat-input-prompt", onClick: () => fill(prompt), children: [prompt.icon, prompt.label] }, prompt.id))) }))] }));
271
+ : triggers[panel.kind].empty, status: panel.items.length ? undefined : (_jsx(MentionStatus, { tone: "empty", children: triggers[panel.kind].empty })), children: panel.items.map((item, index) => (_jsx(MentionOption, { id: optionId(index), active: index === panel.active, onSelect: () => panel.select(index), media: item.media, title: item.label, description: item.description }, item.id))) }) }))] }), prompts && prompts.length > 0 && !filled && !streaming && (_jsx("div", { role: "group", "aria-label": "Suggested prompts", className: "sprout-chat-input-prompts", children: prompts.map(prompt => (_jsxs(Button, { size: "sm", variant: "outline", disabled: disabled, className: "sprout-chat-input-prompt", onClick: () => fill(prompt), children: [prompt.icon, prompt.label] }, prompt.id))) }))] }));
279
272
  }
@@ -1,4 +1,4 @@
1
- import type { ComponentProps } from "react";
1
+ import type { ComponentProps } from 'react';
2
2
  export declare const chatPlanStepStateNames: readonly ["pending", "running", "complete", "error"];
3
3
  export type ChatPlanStepState = (typeof chatPlanStepStateNames)[number];
4
4
  export type ChatPlanStep = {
@@ -8,7 +8,7 @@ export type ChatPlanStep = {
8
8
  detail?: string | undefined;
9
9
  state: ChatPlanStepState;
10
10
  };
11
- export interface ChatPlanProps extends Omit<ComponentProps<"section">, "title" | "children"> {
11
+ export interface ChatPlanProps extends Omit<ComponentProps<'section'>, 'title' | 'children'> {
12
12
  /** The plan name. It names the section and shows above the steps. */
13
13
  title: string;
14
14
  /** Steps in order. With none, the plan says no steps were proposed yet. */
@@ -1,27 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Check } from "reicon-react/icons/Check";
3
- import { Clock } from "reicon-react/icons/Clock";
4
- import { Warning } from "reicon-react/icons/Warning";
5
- import { cn } from "../internal/classes.js";
6
- import { Spinner } from "./spinner.js";
7
- export const chatPlanStepStateNames = [
8
- "pending",
9
- "running",
10
- "complete",
11
- "error",
12
- ];
2
+ import { Check } from 'reicon-react/icons/Check';
3
+ import { Clock } from 'reicon-react/icons/Clock';
4
+ import { Warning } from 'reicon-react/icons/Warning';
5
+ import { cn } from '../internal/classes.js';
6
+ import { Spinner } from './spinner.js';
7
+ export const chatPlanStepStateNames = ['pending', 'running', 'complete', 'error'];
13
8
  const stateLabels = {
14
- pending: "Not started",
15
- running: "In progress",
16
- complete: "Complete",
17
- error: "Failed",
9
+ pending: 'Not started',
10
+ running: 'In progress',
11
+ complete: 'Complete',
12
+ error: 'Failed',
18
13
  };
19
14
  function StepIcon({ state }) {
20
- if (state === "running")
15
+ if (state === 'running')
21
16
  return _jsx(Spinner, { "aria-hidden": "true" });
22
- if (state === "complete")
17
+ if (state === 'complete')
23
18
  return _jsx(Check, { size: 16, "aria-hidden": "true" });
24
- if (state === "error")
19
+ if (state === 'error')
25
20
  return _jsx(Warning, { size: 16, "aria-hidden": "true" });
26
21
  return _jsx(Clock, { size: 16, "aria-hidden": "true" });
27
22
  }
@@ -30,6 +25,6 @@ function StepIcon({ state }) {
30
25
  * in progress, complete, or failed. The header counts completed steps.
31
26
  */
32
27
  export function ChatPlan({ title, steps, className, ...props }) {
33
- const complete = steps.filter((step) => step.state === "complete").length;
34
- return (_jsxs("section", { "data-slot": "chat-plan", "aria-label": title, ...props, className: cn("sprout-chat-plan", className), children: [_jsxs("div", { className: "sprout-chat-plan-header", children: [_jsx("h4", { className: "sprout-chat-plan-title", children: title }), _jsxs("span", { className: "sprout-chat-plan-count", children: [complete, " of ", steps.length, " complete"] })] }), steps.length === 0 ? (_jsx("p", { className: "sprout-chat-plan-empty", children: "No steps have been proposed yet." })) : (_jsx("ol", { className: "sprout-chat-plan-steps", children: steps.map((step) => (_jsxs("li", { "data-slot": "chat-plan-step", "data-state": step.state, className: "sprout-chat-plan-step", children: [_jsx("span", { className: "sprout-chat-plan-icon", children: _jsx(StepIcon, { state: step.state }) }, step.state), _jsxs("div", { className: "sprout-chat-plan-text", children: [_jsxs("p", { className: "sprout-chat-plan-step-title", children: [step.title, _jsxs("span", { className: "sprout-chat-plan-sr-only", children: [" · ", stateLabels[step.state]] })] }), step.detail && (_jsx("p", { className: "sprout-chat-plan-detail", children: step.detail }))] })] }, step.id))) }))] }));
28
+ const complete = steps.filter(step => step.state === 'complete').length;
29
+ return (_jsxs("section", { "data-slot": "chat-plan", "aria-label": title, ...props, className: cn('sprout-chat-plan', className), children: [_jsxs("div", { className: "sprout-chat-plan-header", children: [_jsx("h4", { className: "sprout-chat-plan-title", children: title }), _jsxs("span", { className: "sprout-chat-plan-count", children: [complete, " of ", steps.length, " complete"] })] }), steps.length === 0 ? (_jsx("p", { className: "sprout-chat-plan-empty", children: "No steps have been proposed yet." })) : (_jsx("ol", { className: "sprout-chat-plan-steps", children: steps.map(step => (_jsxs("li", { "data-slot": "chat-plan-step", "data-state": step.state, className: "sprout-chat-plan-step", children: [_jsx("span", { className: "sprout-chat-plan-icon", children: _jsx(StepIcon, { state: step.state }) }, step.state), _jsxs("div", { className: "sprout-chat-plan-text", children: [_jsxs("p", { className: "sprout-chat-plan-step-title", children: [step.title, _jsxs("span", { className: "sprout-chat-plan-sr-only", children: [' · ', stateLabels[step.state]] })] }), step.detail && _jsx("p", { className: "sprout-chat-plan-detail", children: step.detail })] })] }, step.id))) }))] }));
35
30
  }
@@ -1,4 +1,4 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ComponentProps } from 'react';
2
2
  export type ChatSource = {
3
3
  id: string;
4
4
  title: string;
@@ -18,7 +18,7 @@ export interface InlineCitationProps {
18
18
  * Enter shows the cited passage and where it comes from.
19
19
  */
20
20
  export declare function InlineCitation({ source, number }: InlineCitationProps): import("react").JSX.Element;
21
- export interface ChatSourcesProps extends Omit<ComponentProps<"div">, "children"> {
21
+ export interface ChatSourcesProps extends Omit<ComponentProps<'div'>, 'children'> {
22
22
  /** Sources in citation order. With none, it says no sources were used. */
23
23
  sources: readonly ChatSource[];
24
24
  /** Start with the list open. */
@@ -32,19 +32,19 @@ export declare function ChatSources({ sources, defaultOpen, className, ...props
32
32
  export declare const citationStateKindNames: readonly ["idle", "loading", "ready", "unavailable", "error"];
33
33
  export type CitationStateKind = (typeof citationStateKindNames)[number];
34
34
  export type CitationState = {
35
- kind: "idle";
35
+ kind: 'idle';
36
36
  } | {
37
- kind: "loading";
37
+ kind: 'loading';
38
38
  } | {
39
- kind: "ready";
39
+ kind: 'ready';
40
40
  title: string;
41
41
  location: string;
42
42
  excerpt: string;
43
43
  } | {
44
- kind: "unavailable";
44
+ kind: 'unavailable';
45
45
  message: string;
46
46
  } | {
47
- kind: "error";
47
+ kind: 'error';
48
48
  message: string;
49
49
  };
50
50
  export interface CheckedCitationProps {
@@ -61,4 +61,4 @@ export interface CheckedCitationProps {
61
61
  * click. While checking it shows a spinner; an unavailable source never shows
62
62
  * an old passage.
63
63
  */
64
- export declare function CheckedCitation({ label, state, onOpen, onRetry, }: CheckedCitationProps): import("react").JSX.Element;
64
+ export declare function CheckedCitation({ label, state, onOpen, onRetry }: CheckedCitationProps): import("react").JSX.Element;