@tulipfarm/sprout 0.3.1 → 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 +10 -10
  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 +4 -4
  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 +3 -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,40 +1,36 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useEffect, useLayoutEffect, useRef, useState, } from "react";
4
- import { Check } from "reicon-react/icons/Check";
5
- import { ChevronDown } from "reicon-react/icons/ChevronDown";
6
- import { Command } from "reicon-react/icons/Command";
7
- import { Danger } from "reicon-react/icons/Danger";
8
- import { Globe } from "reicon-react/icons/Globe";
9
- import { Stop3 } from "reicon-react/icons/Stop3";
10
- import { cn } from "../internal/classes.js";
11
- import { Button } from "./button.js";
12
- import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "./collapsible.js";
13
- import { Spinner } from "./spinner.js";
3
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
4
+ import { Check } from 'reicon-react/icons/Check';
5
+ import { ChevronDown } from 'reicon-react/icons/ChevronDown';
6
+ import { Command } from 'reicon-react/icons/Command';
7
+ import { Danger } from 'reicon-react/icons/Danger';
8
+ import { Globe } from 'reicon-react/icons/Globe';
9
+ import { Stop3 } from 'reicon-react/icons/Stop3';
10
+ import { cn } from '../internal/classes.js';
11
+ import { Button } from './button.js';
12
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './collapsible.js';
13
+ import { Spinner } from './spinner.js';
14
14
  export const toolActivityStatusNames = [
15
- "queued",
16
- "running",
17
- "waiting",
18
- "completed",
19
- "blocked",
20
- "failed",
21
- "cancelled",
22
- "unknown",
23
- ];
24
- export const toolActivityVariantNames = [
25
- "collapsible",
26
- "stepper",
27
- "transcript",
15
+ 'queued',
16
+ 'running',
17
+ 'waiting',
18
+ 'completed',
19
+ 'blocked',
20
+ 'failed',
21
+ 'cancelled',
22
+ 'unknown',
28
23
  ];
24
+ export const toolActivityVariantNames = ['collapsible', 'stepper', 'transcript'];
29
25
  const statusText = {
30
- queued: "Pending",
31
- running: "In progress",
32
- waiting: "Waiting",
33
- completed: "Completed",
34
- blocked: "Access denied",
35
- failed: "Failed",
36
- cancelled: "Cancelled",
37
- unknown: "Outcome unknown",
26
+ queued: 'Pending',
27
+ running: 'In progress',
28
+ waiting: 'Waiting',
29
+ completed: 'Completed',
30
+ blocked: 'Access denied',
31
+ failed: 'Failed',
32
+ cancelled: 'Cancelled',
33
+ unknown: 'Outcome unknown',
38
34
  };
39
35
  const visibleSourceCount = 4;
40
36
  /**
@@ -56,66 +52,60 @@ export function ActivityPanel({ working, activityLabel, hasResult = false, colla
56
52
  setOpen(false);
57
53
  }
58
54
  }, [working, collapseWhenDone]);
59
- return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "activity-panel", "data-has-result": hasResult || undefined, role: "region", "aria-label": "Chat activity", className: cn("sprout-activity-panel", className), children: [_jsxs(CollapsibleTrigger, { "aria-label": working
60
- ? `Working…${activityLabel ? ` ${activityLabel}` : ""}`
61
- : "Worked", className: "sprout-activity-panel-trigger", children: [working && _jsx(Spinner, { "aria-hidden": "true" }), _jsx("span", { role: "status", className: "sprout-activity-panel-status", children: working ? "Working…" : "Worked" }), working && activityLabel && (_jsx("span", { className: "sprout-activity-panel-label", children: activityLabel })), _jsx(ChevronDown, { size: 14, "aria-hidden": "true", "data-slot": "collapsible-indicator" })] }), _jsx(CollapsibleContent, { keepMounted: true, className: "sprout-activity-panel-content", children: _jsx("div", { className: "sprout-activity-panel-frame", "data-scrolled": scrolled || undefined, children: _jsx("div", { "data-slot": "activity-viewport", role: "region", "aria-label": "Activity timeline", tabIndex: 0, className: "sprout-activity-panel-viewport", onScroll: (event) => setScrolled(event.currentTarget.scrollTop > 0), children: children }) }) })] }));
55
+ return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "activity-panel", "data-has-result": hasResult || undefined, role: "region", "aria-label": "Chat activity", className: cn('sprout-activity-panel', className), children: [_jsxs(CollapsibleTrigger, { "aria-label": working ? `Working…${activityLabel ? ` ${activityLabel}` : ''}` : 'Worked', className: "sprout-activity-panel-trigger", children: [working && _jsx(Spinner, { "aria-hidden": "true" }), _jsx("span", { role: "status", className: "sprout-activity-panel-status", children: working ? 'Working…' : 'Worked' }), working && activityLabel && _jsx("span", { className: "sprout-activity-panel-label", children: activityLabel }), _jsx(ChevronDown, { size: 14, "aria-hidden": "true", "data-slot": "collapsible-indicator" })] }), _jsx(CollapsibleContent, { keepMounted: true, className: "sprout-activity-panel-content", children: _jsx("div", { className: "sprout-activity-panel-frame", "data-scrolled": scrolled || undefined, children: _jsx("div", { "data-slot": "activity-viewport", role: "region", "aria-label": "Activity timeline", tabIndex: 0, className: "sprout-activity-panel-viewport", onScroll: event => setScrolled(event.currentTarget.scrollTop > 0), children: children }) }) })] }));
62
56
  }
63
57
  function webUrl(url) {
64
58
  try {
65
59
  const parsed = new URL(url);
66
- return parsed.protocol === "https:" || parsed.protocol === "http:"
67
- ? parsed.href
68
- : null;
60
+ return parsed.protocol === 'https:' || parsed.protocol === 'http:' ? parsed.href : null;
69
61
  }
70
62
  catch {
71
63
  return null;
72
64
  }
73
65
  }
74
- function SourceFavicon({ url, sourceIcon, }) {
66
+ function SourceFavicon({ url, sourceIcon }) {
75
67
  const src = (webUrl(url) && sourceIcon?.(url)) || null;
76
- const [state, setState] = useState({ src, status: "loading" });
77
- const status = state.src === src ? state.status : "loading";
78
- return (_jsxs("span", { "data-slot": "source-favicon", "data-status": src ? status : "failed", "aria-hidden": "true", className: "sprout-tool-activity-favicon", children: [status !== "loaded" && _jsx(Globe, { size: 18 }), src && status !== "failed" && (_jsx("img", { src: src, alt: "", width: 20, height: 20, referrerPolicy: "no-referrer", onLoad: () => setState({ src, status: "loaded" }), onError: () => setState({ src, status: "failed" }) }))] }));
68
+ const [state, setState] = useState({ src, status: 'loading' });
69
+ const status = state.src === src ? state.status : 'loading';
70
+ return (_jsxs("span", { "data-slot": "source-favicon", "data-status": src ? status : 'failed', "aria-hidden": "true", className: "sprout-tool-activity-favicon", children: [status !== 'loaded' && _jsx(Globe, { size: 18 }), src && status !== 'failed' && (_jsx("img", { src: src, alt: "", width: 20, height: 20, referrerPolicy: "no-referrer", onLoad: () => setState({ src, status: 'loaded' }), onError: () => setState({ src, status: 'failed' }) }))] }));
79
71
  }
80
- function ToolSources({ item, sourceIcon, }) {
72
+ function ToolSources({ item, sourceIcon }) {
81
73
  const [expanded, setExpanded] = useState(false);
82
74
  const urls = [...new Set([...(item.urls ?? []), ...(item.failedUrls ?? [])])];
83
75
  if (!urls.length)
84
76
  return null;
85
- const titles = new Map(item.sources?.map((source) => [source.url, source.title.trim()]));
77
+ const titles = new Map(item.sources?.map(source => [source.url, source.title.trim()]));
86
78
  const visible = expanded ? urls : urls.slice(0, visibleSourceCount);
87
- return (_jsxs("div", { "data-slot": "tool-sources", className: "sprout-tool-activity-sources", children: [_jsx("ul", { "aria-label": "Web sources", className: "sprout-tool-activity-source-list", children: visible.map((url) => {
79
+ return (_jsxs("div", { "data-slot": "tool-sources", className: "sprout-tool-activity-sources", children: [_jsx("ul", { "aria-label": "Web sources", className: "sprout-tool-activity-source-list", children: visible.map(url => {
88
80
  const failed = item.failedUrls?.includes(url) ?? false;
89
- const title = titles.get(url) || url.replace(/^https?:\/\/(?:www\.)?/, "");
81
+ const title = titles.get(url) || url.replace(/^https?:\/\/(?:www\.)?/, '');
90
82
  const href = webUrl(url);
91
83
  const chip = (_jsxs(_Fragment, { children: [_jsx(SourceFavicon, { url: url, sourceIcon: sourceIcon }), _jsx("span", { className: "sprout-tool-activity-source-title", children: title }), failed && (_jsxs(_Fragment, { children: [_jsx(Danger, { size: 14, "aria-hidden": "true", className: "sprout-tool-activity-source-failed" }), _jsx("span", { className: "sprout-tool-activity-sr-only", children: "Page unavailable. Retry or paste the text." })] }))] }));
92
84
  return (_jsx("li", { className: "sprout-tool-activity-source", children: href ? (_jsx("a", { "data-slot": "source-chip", "data-failed": failed || undefined, href: href, title: `${title}\n${url}`, target: "_blank", rel: "noopener noreferrer", className: "sprout-tool-activity-source-chip", children: chip })) : (_jsx("span", { "data-slot": "source-chip", "data-failed": failed || undefined, title: `${title}\n${url}`, className: "sprout-tool-activity-source-chip", children: chip })) }, url));
93
- }) }), urls.length > visibleSourceCount && (_jsx(Button, { variant: "ghost", size: "sm", "aria-expanded": expanded, onClick: () => setExpanded((value) => !value), className: "sprout-tool-activity-more", children: expanded
94
- ? "Show fewer sources"
95
- : `${urls.length - visibleSourceCount} more` }))] }));
85
+ }) }), urls.length > visibleSourceCount && (_jsx(Button, { variant: "ghost", size: "sm", "aria-expanded": expanded, onClick: () => setExpanded(value => !value), className: "sprout-tool-activity-more", children: expanded ? 'Show fewer sources' : `${urls.length - visibleSourceCount} more` }))] }));
96
86
  }
97
87
  function StatusMark({ status }) {
98
- if (status === "running")
88
+ if (status === 'running')
99
89
  return (_jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 16 16", className: "sprout-tool-activity-mark-running", children: [_jsx("circle", { cx: "8", cy: "8", r: "6", className: "sprout-tool-activity-mark-track" }), _jsx("circle", { cx: "8", cy: "8", r: "6", strokeLinecap: "round", strokeDasharray: "14 24", className: "sprout-tool-activity-mark-arc" })] }));
100
- if (status === "completed")
90
+ if (status === 'completed')
101
91
  return (_jsx("span", { className: "sprout-tool-activity-mark-completed", children: _jsx(Check, { size: 12, "aria-hidden": "true" }) }));
102
- if (status === "waiting")
92
+ if (status === 'waiting')
103
93
  return (_jsx("svg", { "aria-hidden": "true", viewBox: "0 0 16 16", className: "sprout-tool-activity-mark-waiting", children: _jsx("circle", { cx: "8", cy: "8", r: "6", strokeDasharray: "3 2" }) }));
104
- if (status === "queued")
105
- return (_jsx("span", { "aria-hidden": "true", className: "sprout-tool-activity-mark-queued" }));
106
- if (status === "cancelled")
107
- return (_jsx(Stop3, { size: 14, "aria-hidden": "true", className: "sprout-tool-activity-mark-cancelled" }));
108
- return (_jsx(Danger, { size: 14, "aria-hidden": "true", className: "sprout-tool-activity-mark-problem" }));
94
+ if (status === 'queued')
95
+ return _jsx("span", { "aria-hidden": "true", className: "sprout-tool-activity-mark-queued" });
96
+ if (status === 'cancelled')
97
+ return _jsx(Stop3, { size: 14, "aria-hidden": "true", className: "sprout-tool-activity-mark-cancelled" });
98
+ return _jsx(Danger, { size: 14, "aria-hidden": "true", className: "sprout-tool-activity-mark-problem" });
109
99
  }
110
100
  /**
111
101
  * A timeline of the tools an agent used, with a status mark per row,
112
102
  * web sources, and a summary trigger that counts problems.
113
103
  */
114
- export function ToolActivity({ items, active = false, label = "Tool activity", activityLabel, onToggle, variant = "collapsible", onLoadOlder, onRetryOlder, hasOlder = false, loadingOlder = false, olderError = false, sourceIcon, className, }) {
115
- const visible = variant === "stepper" ? items.slice().reverse() : items;
104
+ export function ToolActivity({ items, active = false, label = 'Tool activity', activityLabel, onToggle, variant = 'collapsible', onLoadOlder, onRetryOlder, hasOlder = false, loadingOlder = false, olderError = false, sourceIcon, className, }) {
105
+ const visible = variant === 'stepper' ? items.slice().reverse() : items;
116
106
  const list = useRef(null);
117
107
  const olderSentinel = useRef(null);
118
- const latestId = variant === "stepper" ? visible.at(-1)?.id : undefined;
108
+ const latestId = variant === 'stepper' ? visible.at(-1)?.id : undefined;
119
109
  useLayoutEffect(() => {
120
110
  if (!latestId)
121
111
  return;
@@ -124,11 +114,7 @@ export function ToolActivity({ items, active = false, label = "Tool activity", a
124
114
  activity.scrollTop = activity.scrollHeight;
125
115
  }, [latestId]);
126
116
  useEffect(() => {
127
- if (variant !== "stepper" ||
128
- !hasOlder ||
129
- loadingOlder ||
130
- olderError ||
131
- !onLoadOlder)
117
+ if (variant !== 'stepper' || !hasOlder || loadingOlder || olderError || !onLoadOlder)
132
118
  return;
133
119
  const target = olderSentinel.current;
134
120
  if (!target)
@@ -139,21 +125,21 @@ export function ToolActivity({ items, active = false, label = "Tool activity", a
139
125
  const root = list.current?.closest('[data-slot="activity-viewport"]');
140
126
  if (!root)
141
127
  return false;
142
- if (typeof IntersectionObserver === "undefined") {
128
+ if (typeof IntersectionObserver === 'undefined') {
143
129
  const checkTop = () => {
144
130
  if (root.scrollTop <= 40)
145
131
  onLoadOlder();
146
132
  };
147
- root.addEventListener("scroll", checkTop, { passive: true });
148
- stopObserving = () => root.removeEventListener("scroll", checkTop);
133
+ root.addEventListener('scroll', checkTop, { passive: true });
134
+ stopObserving = () => root.removeEventListener('scroll', checkTop);
149
135
  }
150
136
  else {
151
- const observer = new IntersectionObserver((entries) => {
152
- if (entries.some((entry) => entry.isIntersecting)) {
137
+ const observer = new IntersectionObserver(entries => {
138
+ if (entries.some(entry => entry.isIntersecting)) {
153
139
  observer.disconnect();
154
140
  onLoadOlder();
155
141
  }
156
- }, { root, rootMargin: "40px 0px 0px" });
142
+ }, { root, rootMargin: '40px 0px 0px' });
157
143
  observer.observe(target);
158
144
  stopObserving = () => observer.disconnect();
159
145
  }
@@ -174,53 +160,40 @@ export function ToolActivity({ items, active = false, label = "Tool activity", a
174
160
  stopObserving?.();
175
161
  };
176
162
  }, [variant, hasOlder, loadingOlder, olderError, onLoadOlder, items.length]);
177
- const running = items.some((item) => item.status === "running");
163
+ const running = items.some(item => item.status === 'running');
178
164
  const working = active || running;
179
- const pending = working ||
180
- items.some((item) => item.status === "queued" ||
181
- item.status === "waiting" ||
182
- item.status === "unknown");
165
+ const pending = working || items.some(item => item.status === 'queued' || item.status === 'waiting' || item.status === 'unknown');
183
166
  const [expansion, setExpansion] = useState({
184
167
  pending,
185
- open: variant === "transcript" ? false : pending,
168
+ open: variant === 'transcript' ? false : pending,
186
169
  });
187
- if (variant !== "transcript" && expansion.pending !== pending)
170
+ if (variant !== 'transcript' && expansion.pending !== pending)
188
171
  setExpansion({ pending, open: pending });
189
- const open = variant === "transcript" || expansion.pending === pending
190
- ? expansion.open
191
- : pending;
172
+ const open = variant === 'transcript' || expansion.pending === pending ? expansion.open : pending;
192
173
  if (items.length === 0)
193
- return active && variant === "transcript" ? (_jsxs("div", { "data-slot": "reply-progress", role: "status", className: cn("sprout-tool-activity-progress", className), children: [_jsx(Spinner, { "aria-hidden": "true" }), activityLabel || "Thinking…"] })) : null;
194
- const problems = items.filter((item) => item.status === "blocked" ||
195
- item.status === "failed" ||
196
- item.status === "unknown").length;
197
- const count = `${items.length} ${items.length === 1 ? "tool" : "tools"}`;
198
- const attention = items.some((item) => item.status === "unknown")
199
- ? "Outcome unconfirmed"
200
- : items.some((item) => item.status === "failed")
201
- ? "Some work failed"
202
- : items.some((item) => item.status === "blocked")
203
- ? "Access denied"
204
- : items.some((item) => item.status === "waiting")
205
- ? "Waiting for input"
206
- : !working && items.some((item) => item.status === "cancelled")
207
- ? "Work cancelled"
174
+ return active && variant === 'transcript' ? (_jsxs("div", { "data-slot": "reply-progress", role: "status", className: cn('sprout-tool-activity-progress', className), children: [_jsx(Spinner, { "aria-hidden": "true" }), activityLabel || 'Thinking…'] })) : null;
175
+ const problems = items.filter(item => item.status === 'blocked' || item.status === 'failed' || item.status === 'unknown').length;
176
+ const count = `${items.length} ${items.length === 1 ? 'tool' : 'tools'}`;
177
+ const attention = items.some(item => item.status === 'unknown')
178
+ ? 'Outcome unconfirmed'
179
+ : items.some(item => item.status === 'failed')
180
+ ? 'Some work failed'
181
+ : items.some(item => item.status === 'blocked')
182
+ ? 'Access denied'
183
+ : items.some(item => item.status === 'waiting')
184
+ ? 'Waiting for input'
185
+ : !working && items.some(item => item.status === 'cancelled')
186
+ ? 'Work cancelled'
208
187
  : null;
209
- const title = variant === "transcript"
188
+ const title = variant === 'transcript'
210
189
  ? `${working
211
- ? `Working… ${activityLabel || items.find((item) => item.status === "running")?.label || ""}`.trim()
190
+ ? `Working… ${activityLabel || items.find(item => item.status === 'running')?.label || ''}`.trim()
212
191
  : pending
213
- ? "Work pending"
214
- : `Tool activity · ${count}`}${attention ? ` · ${attention}` : ""}`
215
- : `${working ? `Using ${count}` : pending ? `${count} waiting` : `Used ${count}`}${problems
216
- ? ` · ${problems} need${problems === 1 ? "s" : ""} attention`
217
- : ""}`;
218
- return (_jsxs(Collapsible, { "data-slot": "tool-activity", "data-variant": variant, open: variant === "stepper" || open, onOpenChange: (next) => {
192
+ ? 'Work pending'
193
+ : `Tool activity · ${count}`}${attention ? ` · ${attention}` : ''}`
194
+ : `${working ? `Using ${count}` : pending ? `${count} waiting` : `Used ${count}`}${problems ? ` · ${problems} need${problems === 1 ? 's' : ''} attention` : ''}`;
195
+ return (_jsxs(Collapsible, { "data-slot": "tool-activity", "data-variant": variant, open: variant === 'stepper' || open, onOpenChange: next => {
219
196
  onToggle?.();
220
197
  setExpansion({ pending, open: next });
221
- }, className: cn("sprout-tool-activity", className), children: [variant !== "stepper" && (_jsxs(CollapsibleTrigger, { "aria-label": title, className: "sprout-tool-activity-trigger", children: [working ? (_jsx(Spinner, { "aria-hidden": "true" })) : (_jsx(Command, { size: 14, "aria-hidden": "true" })), _jsx("span", { role: "status", className: "sprout-tool-activity-title", children: title }), _jsx(ChevronDown, { size: 14, "aria-hidden": "true", "data-slot": "collapsible-indicator" })] })), _jsxs(CollapsibleContent, { children: [variant === "stepper" && loadingOlder && (_jsxs("div", { role: "status", className: "sprout-tool-activity-older", children: [_jsx(Spinner, { "aria-hidden": "true" }), "Loading earlier activity\u2026"] })), variant === "stepper" && olderError && (_jsxs("div", { role: "alert", className: "sprout-tool-activity-older", "data-tone": "danger", children: [_jsx("span", { children: "Earlier activity didn\u2019t load." }), _jsx(Button, { variant: "link", size: "sm", disabled: !onRetryOlder, onClick: onRetryOlder, children: "Retry loading" })] })), _jsxs("ol", { ref: list, "aria-label": label, className: "sprout-tool-activity-list", children: [variant === "stepper" && hasOlder && (_jsx("li", { ref: olderSentinel, "aria-hidden": "true", className: "sprout-tool-activity-sentinel" })), visible.map((item, index) => (_jsxs("li", { "data-tool-id": item.id, "data-status": item.status, className: "sprout-tool-activity-row", children: [index < visible.length - 1 && (_jsx("span", { "data-slot": "timeline-connector", "aria-hidden": "true", className: "sprout-tool-activity-connector" })), _jsxs("div", { className: "sprout-tool-activity-head", children: [_jsx("span", { "data-slot": "tool-status-mark", className: "sprout-tool-activity-mark", children: _jsx(StatusMark, { status: item.status }) }), _jsx("span", { "aria-hidden": "true", className: "sprout-tool-activity-visual", children: item.visual }), _jsxs("span", { "data-slot": "tool-row-label", className: "sprout-tool-activity-label", children: [_jsx("span", { className: "sprout-tool-activity-label-text", children: item.label }), _jsx("span", { "data-slot": "tool-status-label", role: item.status === "running" && variant !== "transcript"
222
- ? "status"
223
- : undefined, className: "sprout-tool-activity-sr-only", children: statusText[item.status] })] })] }), item.query && (_jsx("p", { "data-slot": "web-search-query", className: "sprout-tool-activity-query", children: item.query })), item.detail && (_jsx("p", { "data-slot": "tool-detail", "data-tone": item.status === "failed" || item.status === "blocked"
224
- ? "danger"
225
- : undefined, className: "sprout-tool-activity-detail", children: item.detail })), item.details != null && item.details !== false && (_jsx("div", { "data-slot": "tool-details", className: "sprout-tool-activity-details", children: item.details })), _jsx(ToolSources, { item: item, sourceIcon: sourceIcon })] }, item.id)))] })] })] }));
198
+ }, className: cn('sprout-tool-activity', className), children: [variant !== 'stepper' && (_jsxs(CollapsibleTrigger, { "aria-label": title, className: "sprout-tool-activity-trigger", children: [working ? _jsx(Spinner, { "aria-hidden": "true" }) : _jsx(Command, { size: 14, "aria-hidden": "true" }), _jsx("span", { role: "status", className: "sprout-tool-activity-title", children: title }), _jsx(ChevronDown, { size: 14, "aria-hidden": "true", "data-slot": "collapsible-indicator" })] })), _jsxs(CollapsibleContent, { children: [variant === 'stepper' && loadingOlder && (_jsxs("div", { role: "status", className: "sprout-tool-activity-older", children: [_jsx(Spinner, { "aria-hidden": "true" }), "Loading earlier activity\u2026"] })), variant === 'stepper' && olderError && (_jsxs("div", { role: "alert", className: "sprout-tool-activity-older", "data-tone": "danger", children: [_jsx("span", { children: "Earlier activity didn\u2019t load." }), _jsx(Button, { variant: "link", size: "sm", disabled: !onRetryOlder, onClick: onRetryOlder, children: "Retry loading" })] })), _jsxs("ol", { ref: list, "aria-label": label, className: "sprout-tool-activity-list", children: [variant === 'stepper' && hasOlder && (_jsx("li", { ref: olderSentinel, "aria-hidden": "true", className: "sprout-tool-activity-sentinel" })), visible.map((item, index) => (_jsxs("li", { "data-tool-id": item.id, "data-status": item.status, className: "sprout-tool-activity-row", children: [index < visible.length - 1 && (_jsx("span", { "data-slot": "timeline-connector", "aria-hidden": "true", className: "sprout-tool-activity-connector" })), _jsxs("div", { className: "sprout-tool-activity-head", children: [_jsx("span", { "data-slot": "tool-status-mark", className: "sprout-tool-activity-mark", children: _jsx(StatusMark, { status: item.status }) }), _jsx("span", { "aria-hidden": "true", className: "sprout-tool-activity-visual", children: item.visual }), _jsxs("span", { "data-slot": "tool-row-label", className: "sprout-tool-activity-label", children: [_jsx("span", { className: "sprout-tool-activity-label-text", children: item.label }), _jsx("span", { "data-slot": "tool-status-label", role: item.status === 'running' && variant !== 'transcript' ? 'status' : undefined, className: "sprout-tool-activity-sr-only", children: statusText[item.status] })] })] }), item.query && (_jsx("p", { "data-slot": "web-search-query", className: "sprout-tool-activity-query", children: item.query })), item.detail && (_jsx("p", { "data-slot": "tool-detail", "data-tone": item.status === 'failed' || item.status === 'blocked' ? 'danger' : undefined, className: "sprout-tool-activity-detail", children: item.detail })), item.details != null && item.details !== false && (_jsx("div", { "data-slot": "tool-details", className: "sprout-tool-activity-details", children: item.details })), _jsx(ToolSources, { item: item, sourceIcon: sourceIcon })] }, item.id)))] })] })] }));
226
199
  }
@@ -1,4 +1,4 @@
1
- import { type ReactNode } from "react";
1
+ import { type ReactNode } from 'react';
2
2
  export interface ToolbarStatusProps {
3
3
  /** Short outcome on the trigger and the popover title, like "Exported". */
4
4
  label: string;
@@ -18,4 +18,4 @@ export interface ToolbarStatusProps {
18
18
  * A compact toolbar button that reports the result of an action and opens its
19
19
  * details. It replaces the action button until the person acts again.
20
20
  */
21
- export declare function ToolbarStatus({ label, message, error, children, defaultOpen, }: ToolbarStatusProps): import("react").JSX.Element;
21
+ export declare function ToolbarStatus({ label, message, error, children, defaultOpen }: ToolbarStatusProps): import("react").JSX.Element;
@@ -1,14 +1,14 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Children } from "react";
4
- import { Button } from "./button.js";
5
- import { Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, } from "./popover.js";
3
+ import { Children } from 'react';
4
+ import { Button } from './button.js';
5
+ import { Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from './popover.js';
6
6
  /**
7
7
  * A compact toolbar button that reports the result of an action and opens its
8
8
  * details. It replaces the action button until the person acts again.
9
9
  */
10
- export function ToolbarStatus({ label, message, error = false, children, defaultOpen = false, }) {
11
- const tone = error ? "error" : "success";
10
+ export function ToolbarStatus({ label, message, error = false, children, defaultOpen = false }) {
11
+ const tone = error ? 'error' : 'success';
12
12
  const hasActions = Children.toArray(children).length > 0;
13
- return (_jsxs(Popover, { defaultOpen: defaultOpen, children: [_jsx("span", { "data-slot": "toolbar-status-message", role: error ? "alert" : "status", className: "sprout-toolbar-status-message", children: message }), _jsx(PopoverTrigger, { "data-slot": "toolbar-status-trigger", "data-status": tone, className: "sprout-toolbar-status-trigger", render: _jsx(Button, { variant: error ? "destructive" : "outline", size: "sm" }), children: _jsx("span", { className: "sprout-toolbar-status-label", children: label }) }), _jsxs(PopoverContent, { "data-slot": "toolbar-status-content", "data-status": tone, align: "end", className: "sprout-toolbar-status-content", children: [_jsxs("div", { className: "sprout-toolbar-status-header", children: [_jsx(PopoverTitle, { className: "sprout-toolbar-status-title", children: label }), _jsx(PopoverDescription, { children: message })] }), hasActions && (_jsx("div", { "data-slot": "toolbar-status-actions", className: "sprout-toolbar-status-actions", children: children }))] })] }));
13
+ return (_jsxs(Popover, { defaultOpen: defaultOpen, children: [_jsx("span", { "data-slot": "toolbar-status-message", role: error ? 'alert' : 'status', className: "sprout-toolbar-status-message", children: message }), _jsx(PopoverTrigger, { "data-slot": "toolbar-status-trigger", "data-status": tone, className: "sprout-toolbar-status-trigger", render: _jsx(Button, { variant: error ? 'destructive' : 'outline', size: "sm" }), children: _jsx("span", { className: "sprout-toolbar-status-label", children: label }) }), _jsxs(PopoverContent, { "data-slot": "toolbar-status-content", "data-status": tone, align: "end", className: "sprout-toolbar-status-content", children: [_jsxs("div", { className: "sprout-toolbar-status-header", children: [_jsx(PopoverTitle, { className: "sprout-toolbar-status-title", children: label }), _jsx(PopoverDescription, { children: message })] }), hasActions && (_jsx("div", { "data-slot": "toolbar-status-actions", className: "sprout-toolbar-status-actions", children: children }))] })] }));
14
14
  }
@@ -1,4 +1,4 @@
1
- import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
1
+ import { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip';
2
2
  export type TooltipProviderProps = TooltipPrimitive.Provider.Props;
3
3
  /**
4
4
  * Shares one open delay across a group of tooltips. Once one tooltip is open,
@@ -13,13 +13,13 @@ export type TooltipTriggerProps = TooltipPrimitive.Trigger.Props;
13
13
  * `Button`, a link, or another component's trigger through `render`. While the
14
14
  * tooltip shows, the trigger is described by it.
15
15
  */
16
- export declare function TooltipTrigger({ render, "aria-describedby": ownDescribedBy, ...props }: TooltipTriggerProps): import("react").JSX.Element;
17
- type PositionerProps = Pick<TooltipPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "anchor" | "collisionPadding" | "collisionAvoidance" | "sticky" | "positionMethod">;
16
+ export declare function TooltipTrigger({ render, 'aria-describedby': ownDescribedBy, ...props }: TooltipTriggerProps): import("react").JSX.Element;
17
+ type PositionerProps = Pick<TooltipPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset' | 'anchor' | 'collisionPadding' | 'collisionAvoidance' | 'sticky' | 'positionMethod'>;
18
18
  export interface TooltipContentProps extends TooltipPrimitive.Popup.Props, PositionerProps {
19
19
  /** Keep the tooltip in the DOM while closed. */
20
- keepMounted?: TooltipPrimitive.Portal.Props["keepMounted"];
20
+ keepMounted?: TooltipPrimitive.Portal.Props['keepMounted'];
21
21
  /** Where the portal renders. Defaults to `document.body`. */
22
- container?: TooltipPrimitive.Portal.Props["container"];
22
+ container?: TooltipPrimitive.Portal.Props['container'];
23
23
  /** Render nothing, for example while a sidebar is expanded and its labels show. */
24
24
  hidden?: boolean;
25
25
  }
@@ -1,11 +1,11 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cloneElement, createContext, isValidElement, useContext, useEffect, useId, useImperativeHandle, useRef, useState, } from "react";
4
- import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
5
- import { stateClassName } from "../internal/classes.js";
3
+ import { cloneElement, createContext, isValidElement, useContext, useEffect, useId, useImperativeHandle, useRef, useState, } from 'react';
4
+ import { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip';
5
+ import { stateClassName } from '../internal/classes.js';
6
6
  const TooltipContext = createContext(null);
7
7
  function joinIds(...ids) {
8
- return ids.filter(Boolean).join(" ") || undefined;
8
+ return ids.filter(Boolean).join(' ') || undefined;
9
9
  }
10
10
  /**
11
11
  * Shares one open delay across a group of tooltips. Once one tooltip is open,
@@ -45,6 +45,7 @@ export function Tooltip({ onOpenChange, actionsRef, ...props }) {
45
45
  if (details.isCanceled)
46
46
  return;
47
47
  if (next) {
48
+ // oxlint-disable-next-line unicorn/no-useless-spread -- copy first: the loop deletes from the set.
48
49
  for (const other of [...openTooltips]) {
49
50
  if (other === actions)
50
51
  continue;
@@ -61,19 +62,19 @@ export function Tooltip({ onOpenChange, actionsRef, ...props }) {
61
62
  * `Button`, a link, or another component's trigger through `render`. While the
62
63
  * tooltip shows, the trigger is described by it.
63
64
  */
64
- export function TooltipTrigger({ render, "aria-describedby": ownDescribedBy, ...props }) {
65
+ export function TooltipTrigger({ render, 'aria-describedby': ownDescribedBy, ...props }) {
65
66
  const context = useContext(TooltipContext);
66
67
  const tooltipId = context?.describedBy;
67
68
  // Base UI lets props on the render element win, so merge the id into it.
68
69
  const element = render;
69
70
  const merged = tooltipId && isValidElement(element)
70
71
  ? cloneElement(element, {
71
- "aria-describedby": joinIds(element.props["aria-describedby"], ownDescribedBy, tooltipId),
72
+ 'aria-describedby': joinIds(element.props['aria-describedby'], ownDescribedBy, tooltipId),
72
73
  })
73
- : typeof render === "function" && tooltipId
74
+ : typeof render === 'function' && tooltipId
74
75
  ? ((renderProps, state) => render({
75
76
  ...renderProps,
76
- "aria-describedby": joinIds(renderProps["aria-describedby"], tooltipId),
77
+ 'aria-describedby': joinIds(renderProps['aria-describedby'], tooltipId),
77
78
  }, state))
78
79
  : render;
79
80
  return (_jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props, "aria-describedby": joinIds(ownDescribedBy, tooltipId), render: merged }));
@@ -90,10 +91,10 @@ function Describe({ id }) {
90
91
  * The tooltip label. It renders its own portal, positioner, and arrow, so
91
92
  * place it directly inside `Tooltip`.
92
93
  */
93
- export function TooltipContent({ side = "top", sideOffset = 4, align = "center", alignOffset = 0, collisionPadding = 8, collisionAvoidance, sticky, positionMethod, anchor, keepMounted = false, container, hidden = false, id, className, children, ...props }) {
94
+ export function TooltipContent({ side = 'top', sideOffset = 4, align = 'center', alignOffset = 0, collisionPadding = 8, collisionAvoidance, sticky, positionMethod, anchor, keepMounted = false, container, hidden = false, id, className, children, ...props }) {
94
95
  const context = useContext(TooltipContext);
95
96
  if (hidden)
96
97
  return null;
97
98
  const popupId = id ?? context?.id;
98
- return (_jsx(TooltipPrimitive.Portal, { keepMounted: keepMounted, container: container, children: _jsx(TooltipPrimitive.Positioner, { className: "sprout-tooltip-positioner", anchor: anchor, align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, collisionPadding: collisionPadding, collisionAvoidance: collisionAvoidance, sticky: sticky, positionMethod: positionMethod, children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", role: "tooltip", id: popupId, ...props, className: stateClassName("sprout-tooltip-content", className), children: [popupId && _jsx(Describe, { id: popupId }), children, _jsx(TooltipPrimitive.Arrow, { "data-slot": "tooltip-arrow", className: "sprout-tooltip-arrow" })] }) }) }));
99
+ return (_jsx(TooltipPrimitive.Portal, { keepMounted: keepMounted, container: container, children: _jsx(TooltipPrimitive.Positioner, { className: "sprout-tooltip-positioner", anchor: anchor, align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, collisionPadding: collisionPadding, collisionAvoidance: collisionAvoidance, sticky: sticky, positionMethod: positionMethod, children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", role: "tooltip", id: popupId, ...props, className: stateClassName('sprout-tooltip-content', className), children: [popupId && _jsx(Describe, { id: popupId }), children, _jsx(TooltipPrimitive.Arrow, { "data-slot": "tooltip-arrow", className: "sprout-tooltip-arrow" })] }) }) }));
99
100
  }
@@ -1,9 +1,9 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ComponentProps } from 'react';
2
2
  /** Milliseconds per character while typing. */
3
3
  export declare const typedTextCharacterDuration = 25;
4
4
  /** The longest a change takes to type, however long the text. */
5
5
  export declare const typedTextMaxDuration = 800;
6
- export interface TypedTextProps extends Omit<ComponentProps<"span">, "children"> {
6
+ export interface TypedTextProps extends Omit<ComponentProps<'span'>, 'children'> {
7
7
  /** The full text. A change types the new text in; the first render shows it at once. */
8
8
  text: string;
9
9
  /** Set `false` to show changes at once, such as a title someone renamed by hand. */
@@ -1,14 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useLayoutEffect, useRef, useState } from "react";
3
- import { cn } from "../internal/classes.js";
2
+ import { useLayoutEffect, useRef, useState } from 'react';
3
+ import { cn } from '../internal/classes.js';
4
4
  /** Milliseconds per character while typing. */
5
5
  export const typedTextCharacterDuration = 25;
6
6
  /** The longest a change takes to type, however long the text. */
7
7
  export const typedTextMaxDuration = 800;
8
8
  let segmenter;
9
9
  function graphemes(text) {
10
- segmenter ??= new Intl.Segmenter("und", { granularity: "grapheme" });
11
- return Array.from(segmenter.segment(text), (item) => item.segment);
10
+ segmenter ??= new Intl.Segmenter('und', { granularity: 'grapheme' });
11
+ return Array.from(segmenter.segment(text), item => item.segment);
12
12
  }
13
13
  /**
14
14
  * Text that types itself in when it changes, such as a chat title an agent
@@ -21,7 +21,7 @@ export function TypedText({ text, animate = true, className, ...rest }) {
21
21
  useLayoutEffect(() => {
22
22
  const changed = previous.current !== text;
23
23
  previous.current = text;
24
- const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
24
+ const motion = window.matchMedia('(prefers-reduced-motion: reduce)');
25
25
  if (!changed || !animate || motion.matches) {
26
26
  setVisible(text);
27
27
  return;
@@ -30,12 +30,10 @@ export function TypedText({ text, animate = true, className, ...rest }) {
30
30
  const start = performance.now();
31
31
  const duration = Math.min(typedTextMaxDuration, characters.length * typedTextCharacterDuration);
32
32
  let frame = 0;
33
- setVisible(characters[0] ?? "");
33
+ setVisible(characters[0] ?? '');
34
34
  function tick(now) {
35
35
  const progress = duration ? Math.min(1, (now - start) / duration) : 1;
36
- setVisible(characters
37
- .slice(0, Math.max(1, Math.ceil(progress * characters.length)))
38
- .join(""));
36
+ setVisible(characters.slice(0, Math.max(1, Math.ceil(progress * characters.length))).join(''));
39
37
  if (progress < 1)
40
38
  frame = requestAnimationFrame(tick);
41
39
  }
@@ -46,11 +44,11 @@ export function TypedText({ text, animate = true, className, ...rest }) {
46
44
  setVisible(text);
47
45
  }
48
46
  frame = requestAnimationFrame(tick);
49
- motion.addEventListener("change", reduceMotion);
47
+ motion.addEventListener('change', reduceMotion);
50
48
  return () => {
51
49
  cancelAnimationFrame(frame);
52
- motion.removeEventListener("change", reduceMotion);
50
+ motion.removeEventListener('change', reduceMotion);
53
51
  };
54
52
  }, [text, animate]);
55
- return (_jsxs("span", { "data-slot": "typed-text", "data-state": visible === text ? "idle" : "typing", className: cn("sprout-typed-text", className), ...rest, children: [_jsx("span", { className: "sprout-typed-text-sr-only", children: text }), _jsx("span", { "aria-hidden": "true", children: visible })] }));
53
+ return (_jsxs("span", { "data-slot": "typed-text", "data-state": visible === text ? 'idle' : 'typing', className: cn('sprout-typed-text', className), ...rest, children: [_jsx("span", { className: "sprout-typed-text-sr-only", children: text }), _jsx("span", { "aria-hidden": "true", children: visible })] }));
56
54
  }
@@ -0,0 +1,51 @@
1
+ import { type ComponentType, type ReactNode } from 'react';
2
+ export interface ViewSwitcherView {
3
+ /** Passed back in `onValueChange`, `onAdd`, and `onClose`. */
4
+ id: string;
5
+ label: string;
6
+ /** Drawn at 14px in the tab and 16px in the menu. */
7
+ icon: ComponentType<{
8
+ size?: number;
9
+ }>;
10
+ /** Shows a close control on the tab. The app decides. It needs `onClose`. */
11
+ closable?: boolean | undefined;
12
+ }
13
+ export interface ViewSwitcherOption extends ViewSwitcherView {
14
+ /** One line about what the view is for. */
15
+ description: string;
16
+ /** Why the view cannot be added. When set, the option is disabled and shows this instead of the description. */
17
+ unavailable?: string | undefined;
18
+ }
19
+ export interface ViewSwitcherProps {
20
+ /** The tabs in the bar, in order. Sprout shows exactly these. */
21
+ views: ViewSwitcherView[];
22
+ /** The `id` of the active view. */
23
+ value: string;
24
+ /** Called when a tab is chosen by click or arrow keys. */
25
+ onValueChange: (id: string) => void;
26
+ /** The views in the "Add view" menu, in order. Leave out to hide the menu. */
27
+ options?: ViewSwitcherOption[] | undefined;
28
+ /**
29
+ * Called with the chosen option. Options that are already in `views` show a
30
+ * check; the app decides what choosing one does, usually switching to it.
31
+ */
32
+ onAdd?: ((id: string) => void) | undefined;
33
+ /** Called by a tab's close control or the Delete key. The app removes the view from `views`. */
34
+ onClose?: ((id: string) => void) | undefined;
35
+ /** Accessible name of the tab list. Defaults to "Views". */
36
+ label?: string | undefined;
37
+ /** Text of the menu button. Defaults to "Add view". */
38
+ addLabel?: string | undefined;
39
+ /** Controls at the end of the bar, such as a settings button. */
40
+ actions?: ReactNode;
41
+ /** The `id` of the panel that shows the active view. Every tab points to it with `aria-controls`. */
42
+ panelId?: string | undefined;
43
+ className?: string | undefined;
44
+ }
45
+ /** The `id` of a view's tab, for the panel's `aria-labelledby`. Needs the same `panelId` as the switcher. */
46
+ export declare function viewSwitcherTabId(panelId: string, viewId: string): string;
47
+ /**
48
+ * The bar of a table's open views, with an "Add view" menu. It is fully
49
+ * controlled: the app owns which views exist, are open, or can close.
50
+ */
51
+ export declare function ViewSwitcher({ views, value, onValueChange, options, onAdd, onClose, label, addLabel, actions, panelId, className, }: ViewSwitcherProps): import("react").JSX.Element;