@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,5 +1,5 @@
1
- import { Radio as BaseRadio } from "@base-ui/react/radio";
2
- import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
1
+ import { Radio as BaseRadio } from '@base-ui/react/radio';
2
+ import { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';
3
3
  export type RadioGroupProps<Value = string> = BaseRadioGroup.Props<Value>;
4
4
  export type RadioGroupItemProps<Value = string> = BaseRadio.Root.Props<Value>;
5
5
  /**
@@ -1,15 +1,15 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { Radio as BaseRadio } from "@base-ui/react/radio";
4
- import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
5
- import { stateClassName } from "../internal/classes.js";
3
+ import { Radio as BaseRadio } from '@base-ui/react/radio';
4
+ import { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';
5
+ import { stateClassName } from '../internal/classes.js';
6
6
  /**
7
7
  * A set of radios where one value is chosen. Arrow keys move between items
8
8
  * and select them. Name the group with `aria-label` or `aria-labelledby`.
9
9
  * Children may include a legend, helper, or error next to the items.
10
10
  */
11
11
  export function RadioGroup({ className, ...props }) {
12
- return (_jsx(BaseRadioGroup, { "data-slot": "radio-group", ...props, className: stateClassName("sprout-radio-group", className) }));
12
+ return (_jsx(BaseRadioGroup, { "data-slot": "radio-group", ...props, className: stateClassName('sprout-radio-group', className) }));
13
13
  }
14
14
  /**
15
15
  * A 16px radio with a larger hit area. Name it with a wrapping `Label`, a
@@ -17,5 +17,5 @@ export function RadioGroup({ className, ...props }) {
17
17
  * to draw a danger ring.
18
18
  */
19
19
  export function RadioGroupItem({ className, ...props }) {
20
- return (_jsx(BaseRadio.Root, { "data-slot": "radio-group-item", ...props, className: stateClassName("sprout-radio-group-item", className), children: _jsx(BaseRadio.Indicator, { "data-slot": "radio-group-indicator", className: "sprout-radio-group-indicator" }) }));
20
+ return (_jsx(BaseRadio.Root, { "data-slot": "radio-group-item", ...props, className: stateClassName('sprout-radio-group-item', className), children: _jsx(BaseRadio.Indicator, { "data-slot": "radio-group-indicator", className: "sprout-radio-group-indicator" }) }));
21
21
  }
@@ -11,9 +11,9 @@ export interface ReasoningEffortProps {
11
11
  */
12
12
  label?: string | undefined;
13
13
  /** Names the slider. Defaults to "Reasoning effort". */
14
- "aria-label"?: string | undefined;
14
+ 'aria-label'?: string | undefined;
15
15
  /** Points at visible text that names the slider, instead of `aria-label`. */
16
- "aria-labelledby"?: string | undefined;
16
+ 'aria-labelledby'?: string | undefined;
17
17
  className?: string | undefined;
18
18
  }
19
19
  /**
@@ -21,4 +21,4 @@ export interface ReasoningEffortProps {
21
21
  * a bubble grows out of the track and shows `label` and the level name.
22
22
  * Release snaps the thumb to the nearest level.
23
23
  */
24
- export declare function ReasoningEffort({ levels, value, onValueChange, label, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className, }: ReasoningEffortProps): import("react").JSX.Element;
24
+ export declare function ReasoningEffort({ levels, value, onValueChange, label, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, }: ReasoningEffortProps): import("react").JSX.Element;
@@ -1,7 +1,7 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useId, useLayoutEffect, useRef, useState, } from "react";
4
- import { cn } from "../internal/classes.js";
3
+ import { useEffect, useId, useLayoutEffect, useRef, useState } from 'react';
4
+ import { cn } from '../internal/classes.js';
5
5
  const TRACK = 256;
6
6
  const HEIGHT = 32;
7
7
  const RADIUS = HEIGHT / 2;
@@ -27,8 +27,7 @@ function smoothstep(t) {
27
27
  return x * x * (3 - 2 * x);
28
28
  }
29
29
  function reducedMotion() {
30
- return (typeof window !== "undefined" &&
31
- window.matchMedia?.("(prefers-reduced-motion: reduce)").matches);
30
+ return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
32
31
  }
33
32
  function plateauFor(textW) {
34
33
  return Math.max(8, textW + TEXT_SIDE * 2 - SHOULDER * 2);
@@ -136,7 +135,7 @@ function shellPath(cx, open, plateauW) {
136
135
  cmds.push(`A${RADIUS} ${RADIUS} 0 0 1 ${crownR} ${trackBot}`);
137
136
  }
138
137
  cmds.push(`H${crownL}Z`);
139
- return cmds.join("");
138
+ return cmds.join('');
140
139
  }
141
140
  function useTween(target, duration, delay = 0) {
142
141
  const ref = useRef(target);
@@ -171,7 +170,7 @@ function useTween(target, duration, delay = 0) {
171
170
  * a bubble grows out of the track and shows `label` and the level name.
172
171
  * Release snaps the thumb to the nearest level.
173
172
  */
174
- export function ReasoningEffort({ levels, value, onValueChange, label, "aria-label": ariaLabel = "Reasoning effort", "aria-labelledby": ariaLabelledBy, className, }) {
173
+ export function ReasoningEffort({ levels, value, onValueChange, label, 'aria-label': ariaLabel = 'Reasoning effort', 'aria-labelledby': ariaLabelledBy, className, }) {
175
174
  const max = Math.max(0, levels.length - 1);
176
175
  const current = clamp(Math.round(value), 0, max);
177
176
  const trackRef = useRef(null);
@@ -246,14 +245,12 @@ export function ReasoningEffort({ levels, value, onValueChange, label, "aria-lab
246
245
  if (w > 0 && Math.abs(w - textW) > 0.4)
247
246
  setTextW(w);
248
247
  }, [level, label, textW]);
249
- return (_jsxs("div", { "data-slot": "reasoning-effort", "data-dragging": dragging, className: cn("sprout-reasoning-effort", className), children: [_jsxs("svg", { className: "sprout-reasoning-effort-shell", viewBox: `0 0 ${TRACK} ${BUMP_H + HEIGHT}`, "aria-hidden": "true", children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0", className: "sprout-reasoning-effort-stop-top" }), _jsx("stop", { offset: "1", className: "sprout-reasoning-effort-stop-bottom" })] }) }), _jsx("path", { "data-slot": "reasoning-effort-shell", d: shellPath(center, open, plateauW), fill: `url(#${gradId})`, strokeWidth: "0.5", strokeLinejoin: "round", vectorEffect: "non-scaling-stroke" })] }), _jsx("div", { ref: labelRef, "data-slot": "reasoning-effort-bubble", "aria-hidden": "true", className: "sprout-reasoning-effort-bubble", style: {
248
+ return (_jsxs("div", { "data-slot": "reasoning-effort", "data-dragging": dragging, className: cn('sprout-reasoning-effort', className), children: [_jsxs("svg", { className: "sprout-reasoning-effort-shell", viewBox: `0 0 ${TRACK} ${BUMP_H + HEIGHT}`, "aria-hidden": "true", children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0", className: "sprout-reasoning-effort-stop-top" }), _jsx("stop", { offset: "1", className: "sprout-reasoning-effort-stop-bottom" })] }) }), _jsx("path", { "data-slot": "reasoning-effort-shell", d: shellPath(center, open, plateauW), fill: `url(#${gradId})`, strokeWidth: "0.5", strokeLinejoin: "round", vectorEffect: "non-scaling-stroke" })] }), _jsx("div", { ref: labelRef, "data-slot": "reasoning-effort-bubble", "aria-hidden": "true", className: "sprout-reasoning-effort-bubble", style: {
250
249
  left: labelX,
251
250
  opacity: reveal,
252
- filter: reveal > 0.98
253
- ? undefined
254
- : `blur(${((1 - reveal) * 3).toFixed(2)}px)`,
251
+ filter: reveal > 0.98 ? undefined : `blur(${((1 - reveal) * 3).toFixed(2)}px)`,
255
252
  transform: `translate(-50%, ${3 * (1 - open)}px)`,
256
- }, children: _jsxs("span", { className: "sprout-reasoning-effort-bubble-text", children: [label && (_jsx("span", { className: "sprout-reasoning-effort-bubble-label", children: label })), _jsx("span", { className: "sprout-reasoning-effort-bubble-level", children: level })] }, level) }), _jsxs("div", { ref: trackRef, role: "slider", tabIndex: 0, "data-slot": "reasoning-effort-track", "aria-label": ariaLabelledBy ? undefined : ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-orientation": "horizontal", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": current, "aria-valuetext": levels[current], className: "sprout-reasoning-effort-track", onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown, children: [_jsx("div", { "data-slot": "reasoning-effort-fill", className: "sprout-reasoning-effort-fill", style: { width: fillW } }), _jsx("div", { "data-slot": "reasoning-effort-thumb", className: "sprout-reasoning-effort-thumb", style: {
253
+ }, children: _jsxs("span", { className: "sprout-reasoning-effort-bubble-text", children: [label && _jsx("span", { className: "sprout-reasoning-effort-bubble-label", children: label }), _jsx("span", { className: "sprout-reasoning-effort-bubble-level", children: level })] }, level) }), _jsxs("div", { ref: trackRef, role: "slider", tabIndex: 0, "data-slot": "reasoning-effort-track", "aria-label": ariaLabelledBy ? undefined : ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-orientation": "horizontal", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": current, "aria-valuetext": levels[current], className: "sprout-reasoning-effort-track", onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown, children: [_jsx("div", { "data-slot": "reasoning-effort-fill", className: "sprout-reasoning-effort-fill", style: { width: fillW } }), _jsx("div", { "data-slot": "reasoning-effort-thumb", className: "sprout-reasoning-effort-thumb", style: {
257
254
  left: thumbLeft,
258
255
  width: thumbW,
259
256
  height: REST_H,
@@ -0,0 +1,66 @@
1
+ import { type ReactNode, type Ref } from 'react';
2
+ export declare const recordListStatusNames: readonly ["ready", "loading", "error"];
3
+ export declare const recordListDensityNames: readonly ["default", "compact"];
4
+ export type RecordListStatus = (typeof recordListStatusNames)[number];
5
+ export type RecordListDensity = (typeof recordListDensityNames)[number];
6
+ /** The most labelled values a row shows. Extra values are left out. */
7
+ export declare const recordListMaxValues = 4;
8
+ export interface RecordListItem {
9
+ id: string;
10
+ /** Plain text name of the record. Screen readers use it, and it shows in full on hover. */
11
+ title: string;
12
+ }
13
+ export interface RecordListValue {
14
+ /** The field name, such as "Assignee". */
15
+ label: string;
16
+ value: ReactNode;
17
+ /** Full text for the hover hint when `value` is not a string or number. */
18
+ text?: string | undefined;
19
+ }
20
+ export interface RecordListHandle {
21
+ /**
22
+ * Moves focus to the first row, or to the empty or error state when there
23
+ * are no rows. While `status` is `"loading"` it waits for the next render
24
+ * that is not loading. Call it after a page change.
25
+ */
26
+ focusFirst: () => void;
27
+ }
28
+ export interface RecordListProps<T extends RecordListItem> {
29
+ /** Rows on the current page, in order. */
30
+ items: T[];
31
+ /** Accessible name of the list, such as "Tickets". The row count is added to it. */
32
+ label: string;
33
+ /** Title content, such as an icon or key before the text. Screen readers still use `item.title`. */
34
+ renderTitle?: ((item: T) => ReactNode) | undefined;
35
+ /** Labelled values under the title. Only the first four show; leave out empty values. */
36
+ values?: ((item: T) => RecordListValue[]) | undefined;
37
+ /** Choice badges, such as status and tags. Leave out empty choices. */
38
+ badges?: ((item: T) => ReactNode) | undefined;
39
+ /** Row actions, such as an Edit button and a `DropdownMenu`. Clicks here do not open the row. */
40
+ renderActions?: ((item: T) => ReactNode) | undefined;
41
+ /** Click or Enter on a row. Open your own Sheet or Dialog here. */
42
+ onItemOpen?: ((item: T) => void) | undefined;
43
+ /** `"loading"` dims the current rows, or shows skeleton rows when there are none. Defaults to `"ready"`. */
44
+ status?: RecordListStatus | undefined;
45
+ /** Error description. Defaults to a short generic message. */
46
+ error?: ReactNode;
47
+ /** Shows a "Try again" button in the error state. */
48
+ onRetry?: (() => void) | undefined;
49
+ /** Shown when `items` is empty and ready. Pass a `StatePanel` or text. */
50
+ empty?: ReactNode;
51
+ /** Shown under the rows, inside the panel. Put the app's `Pagination` here. */
52
+ footer?: ReactNode;
53
+ /** `"compact"` uses less padding for dense pages. Defaults to `"default"`. */
54
+ density?: RecordListDensity | undefined;
55
+ /** Gets `focusFirst()` for moving focus after a page change. */
56
+ ref?: Ref<RecordListHandle> | undefined;
57
+ className?: string | undefined;
58
+ }
59
+ /**
60
+ * A reading and triage list of records: one row per record on the current
61
+ * page, with a title, up to four labelled values, choice badges, and row
62
+ * actions. The list is one tab stop. Arrow keys, Home, and End move between
63
+ * rows, Enter opens a row, and Tab reaches the focused row's actions. The app
64
+ * owns data, paging, and what the actions do.
65
+ */
66
+ export declare function RecordList<T extends RecordListItem>({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status, error, onRetry, empty, footer, density, ref, className, }: RecordListProps<T>): import("react").JSX.Element;
@@ -0,0 +1,151 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useCallback, useId, useImperativeHandle, useLayoutEffect, useRef, useState, } from 'react';
4
+ import { cn } from '../internal/classes.js';
5
+ import { Button } from './button.js';
6
+ import { Skeleton, SkeletonGroup } from './skeleton.js';
7
+ import { StatePanel } from '../internal/state-panel.js';
8
+ export const recordListStatusNames = ['ready', 'loading', 'error'];
9
+ export const recordListDensityNames = ['default', 'compact'];
10
+ /** The most labelled values a row shows. Extra values are left out. */
11
+ export const recordListMaxValues = 4;
12
+ const SKELETON_ROWS = 5;
13
+ const ROW = 'data-record-list-row';
14
+ const SAVED_TAB = 'data-record-list-tabindex';
15
+ const FOCUSABLE = 'a[href], area[href], button, input, select, textarea, iframe, summary, [contenteditable=""], [contenteditable="true"], [tabindex]';
16
+ const rowsName = (label, count) => `${label}, ${count} ${count === 1 ? 'row' : 'rows'}`;
17
+ const hint = (entry) => entry.text ?? (typeof entry.value === 'string' || typeof entry.value === 'number' ? String(entry.value) : undefined);
18
+ /** Keeps only the active row's own controls in the tab order, so Tab leaves the list after them. */
19
+ function syncTabStops(list) {
20
+ for (const row of list.querySelectorAll(`[${ROW}]`)) {
21
+ const active = row.tabIndex === 0;
22
+ for (const control of row.querySelectorAll(FOCUSABLE)) {
23
+ if (active) {
24
+ const saved = control.getAttribute(SAVED_TAB);
25
+ if (saved === null)
26
+ continue;
27
+ if (saved === '')
28
+ control.removeAttribute('tabindex');
29
+ else
30
+ control.setAttribute('tabindex', saved);
31
+ control.removeAttribute(SAVED_TAB);
32
+ }
33
+ else if (!control.hasAttribute(SAVED_TAB) && control.tabIndex >= 0) {
34
+ control.setAttribute(SAVED_TAB, control.getAttribute('tabindex') ?? '');
35
+ control.setAttribute('tabindex', '-1');
36
+ }
37
+ }
38
+ }
39
+ }
40
+ function SkeletonRows() {
41
+ return (_jsx(SkeletonGroup, { label: "Loading rows", gap: "sm", className: "sprout-record-list-skeleton", "data-slot": "record-list-skeleton", children: Array.from({ length: SKELETON_ROWS }, (_, index) => (_jsxs("div", { className: "sprout-record-list-skeleton-row", children: [_jsxs("div", { className: "sprout-record-list-skeleton-main", children: [_jsx(Skeleton, { className: "sprout-record-list-skeleton-title" }), _jsx(Skeleton, { className: "sprout-record-list-skeleton-values" })] }), _jsx(Skeleton, { shape: "action" })] }, index))) }));
42
+ }
43
+ /**
44
+ * A reading and triage list of records: one row per record on the current
45
+ * page, with a title, up to four labelled values, choice badges, and row
46
+ * actions. The list is one tab stop. Arrow keys, Home, and End move between
47
+ * rows, Enter opens a row, and Tab reaches the focused row's actions. The app
48
+ * owns data, paging, and what the actions do.
49
+ */
50
+ export function RecordList({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status = 'ready', error, onRetry, empty, footer, density = 'default', ref, className, }) {
51
+ const id = useId();
52
+ const listRef = useRef(null);
53
+ const stateRef = useRef(null);
54
+ const pendingFocus = useRef(false);
55
+ const [activeId, setActiveId] = useState(null);
56
+ const loading = status === 'loading';
57
+ const showRows = status !== 'error' && items.length > 0;
58
+ const current = items.some(item => item.id === activeId) ? activeId : (items[0]?.id ?? null);
59
+ const rowOf = useCallback((itemId) => [...(listRef.current?.querySelectorAll(`[${ROW}]`) ?? [])].find(row => row.dataset.recordListRow === itemId), []);
60
+ const flushFocus = useCallback(() => {
61
+ if (!pendingFocus.current || loading)
62
+ return;
63
+ pendingFocus.current = false;
64
+ if (showRows && items[0]) {
65
+ setActiveId(items[0].id);
66
+ rowOf(items[0].id)?.focus();
67
+ }
68
+ else
69
+ stateRef.current?.focus();
70
+ }, [items, loading, rowOf, showRows]);
71
+ const latestFlush = useRef(flushFocus);
72
+ useLayoutEffect(() => {
73
+ latestFlush.current = flushFocus;
74
+ flushFocus();
75
+ });
76
+ useImperativeHandle(ref, () => ({
77
+ focusFirst() {
78
+ pendingFocus.current = true;
79
+ // A task, not a microtask, so a switch to loading queued in the same handler commits first.
80
+ setTimeout(() => latestFlush.current());
81
+ },
82
+ }), []);
83
+ useLayoutEffect(() => {
84
+ const list = listRef.current;
85
+ if (!list)
86
+ return;
87
+ syncTabStops(list);
88
+ const observer = new MutationObserver(() => syncTabStops(list));
89
+ observer.observe(list, { childList: true, subtree: true });
90
+ return () => observer.disconnect();
91
+ });
92
+ const move = (event) => {
93
+ const row = event.target;
94
+ if (!row.hasAttribute(ROW) || event.altKey || event.ctrlKey || event.metaKey)
95
+ return;
96
+ const index = items.findIndex(item => item.id === row.dataset.recordListRow);
97
+ const item = items[index];
98
+ if (!item)
99
+ return;
100
+ if (event.key === 'Enter') {
101
+ if (!onItemOpen || event.repeat)
102
+ return;
103
+ event.preventDefault();
104
+ onItemOpen(item);
105
+ return;
106
+ }
107
+ const target = event.key === 'ArrowDown'
108
+ ? items[Math.min(index + 1, items.length - 1)]
109
+ : event.key === 'ArrowUp'
110
+ ? items[Math.max(index - 1, 0)]
111
+ : event.key === 'Home'
112
+ ? items[0]
113
+ : event.key === 'End'
114
+ ? items.at(-1)
115
+ : undefined;
116
+ if (!target || event.shiftKey)
117
+ return;
118
+ event.preventDefault();
119
+ setActiveId(target.id);
120
+ rowOf(target.id)?.focus();
121
+ };
122
+ const open = (event, item) => {
123
+ const target = event.target;
124
+ const row = event.currentTarget;
125
+ // Portaled menus bubble through React, so check the DOM too.
126
+ if (!onItemOpen || !row.contains(target))
127
+ return;
128
+ const control = target.closest(FOCUSABLE);
129
+ if (control && control !== row && row.contains(control))
130
+ return;
131
+ if (target.closest('[data-slot="record-list-actions"]'))
132
+ return;
133
+ if (window.getSelection()?.toString())
134
+ return;
135
+ onItemOpen(item);
136
+ };
137
+ const emptyContent = empty === undefined ? (_jsx(StatePanel, { kind: "empty", heading: "h3", title: "No rows to show", description: "Rows show here when they are added or match the search and filters." })) : typeof empty === 'string' ? (_jsx("p", { className: "sprout-record-list-empty-text", children: empty })) : (empty);
138
+ return (_jsxs("div", { "data-slot": "record-list", "data-density": density, "data-status": status, className: cn('sprout-record-list', className), children: [status === 'error' ? (_jsx("div", { ref: stateRef, tabIndex: -1, "data-slot": "record-list-state", className: "sprout-record-list-state", children: _jsx(StatePanel, { kind: "error", heading: "h3", title: "Rows did not load", description: error ?? 'Something went wrong while loading the rows.', children: onRetry ? (_jsx(Button, { variant: "outline", onClick: onRetry, children: "Try again" })) : null }) })) : showRows ? (_jsxs(_Fragment, { children: [_jsx("ul", { ref: listRef, "aria-label": rowsName(label, items.length), "aria-busy": loading || undefined, "data-slot": "record-list-items", className: "sprout-record-list-items", onKeyDown: move, children: items.map((item, index) => {
139
+ const shown = values?.(item).slice(0, recordListMaxValues) ?? [];
140
+ const badgeContent = badges?.(item);
141
+ const hasBadges = badgeContent != null && badgeContent !== false;
142
+ const actions = renderActions?.(item);
143
+ const valuesId = `${id}-${index}-values`;
144
+ const badgesId = `${id}-${index}-badges`;
145
+ const described = [shown.length > 0 && valuesId, hasBadges && badgesId].filter(Boolean).join(' ');
146
+ return (_jsxs("li", { "data-record-list-row": item.id, tabIndex: item.id === current ? 0 : -1, "aria-label": item.title, "aria-describedby": described || undefined, "data-slot": "record-list-item", "data-openable": onItemOpen ? '' : undefined, className: "sprout-record-list-item", onFocus: event => {
147
+ if (event.currentTarget.contains(event.target))
148
+ setActiveId(item.id);
149
+ }, onClick: event => open(event, item), children: [_jsx("div", { "data-slot": "record-list-title", className: "sprout-record-list-title", title: item.title, children: renderTitle ? renderTitle(item) : item.title }), shown.length > 0 && (_jsx("dl", { id: valuesId, "data-slot": "record-list-values", className: "sprout-record-list-values", children: shown.map((entry, position) => (_jsxs("div", { className: "sprout-record-list-value", children: [_jsx("dt", { children: entry.label }), _jsx("dd", { title: hint(entry), children: entry.value })] }, `${entry.label}-${position}`))) })), hasBadges && (_jsx("div", { id: badgesId, "data-slot": "record-list-badges", className: "sprout-record-list-badges", children: badgeContent })), actions != null && actions !== false && (_jsx("div", { "data-slot": "record-list-actions", className: "sprout-record-list-actions", children: actions }))] }, item.id));
150
+ }) }), _jsx("span", { role: "status", className: "sprout-record-list-sr-only", children: loading ? 'Loading rows…' : '' })] })) : (_jsx("div", { ref: stateRef, tabIndex: -1, "data-slot": "record-list-state", className: "sprout-record-list-state", children: loading ? _jsx(SkeletonRows, {}) : emptyContent })), footer != null && footer !== false && (_jsx("div", { "data-slot": "record-list-footer", className: "sprout-record-list-footer", children: footer }))] }));
151
+ }
@@ -1,4 +1,4 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ComponentProps } from 'react';
2
2
  export declare const resizableOrientationNames: readonly ["horizontal", "vertical"];
3
3
  /** `"horizontal"` places panels side by side. `"vertical"` stacks them. */
4
4
  export type ResizableOrientation = (typeof resizableOrientationNames)[number];
@@ -13,7 +13,7 @@ export interface ResizableLayoutChangeDetails {
13
13
  /** True for pointer and keyboard resizes. False for mount and container changes. */
14
14
  isUserInteraction: boolean;
15
15
  }
16
- export interface ResizablePanelGroupProps extends ComponentProps<"div"> {
16
+ export interface ResizablePanelGroupProps extends ComponentProps<'div'> {
17
17
  /** `"horizontal"` (default) places panels side by side. `"vertical"` stacks them. */
18
18
  orientation?: ResizableOrientation;
19
19
  /** Starting sizes by panel `id`, such as a layout saved by `useResizableLayout`. */
@@ -25,7 +25,7 @@ export interface ResizablePanelGroupProps extends ComponentProps<"div"> {
25
25
  }
26
26
  /** A row or column of resizable panels separated by `ResizableHandle`s. */
27
27
  export declare function ResizablePanelGroup({ orientation, defaultLayout, onLayoutChange, onLayoutChanged, className, children, ref, ...props }: ResizablePanelGroupProps): import("react").JSX.Element;
28
- export interface ResizablePanelProps extends Omit<ComponentProps<"div">, "id"> {
28
+ export interface ResizablePanelProps extends Omit<ComponentProps<'div'>, 'id'> {
29
29
  /** Key for this panel in layouts. Set it when saving layouts or showing panels conditionally. */
30
30
  id?: string;
31
31
  /** Starting size. Panels without one share the space that is left. */
@@ -37,7 +37,7 @@ export interface ResizablePanelProps extends Omit<ComponentProps<"div">, "id"> {
37
37
  }
38
38
  /** One resizable region. It must be a direct child of `ResizablePanelGroup`. */
39
39
  export declare function ResizablePanel({ id: idProp, defaultSize, minSize, maxSize, className, style, ref, ...props }: ResizablePanelProps): import("react").JSX.Element;
40
- export interface ResizableHandleProps extends ComponentProps<"div"> {
40
+ export interface ResizableHandleProps extends ComponentProps<'div'> {
41
41
  /** Shows a small grip on the line, for splits people resize often. */
42
42
  withHandle?: boolean;
43
43
  }
@@ -54,7 +54,7 @@ export interface UseResizableLayoutOptions {
54
54
  /** Only save sizes the person chose, not the starting layout. */
55
55
  onlySaveAfterUserInteractions?: boolean | undefined;
56
56
  /** Where to save. Defaults to `localStorage`. */
57
- storage?: Pick<Storage, "getItem" | "setItem"> | undefined;
57
+ storage?: Pick<Storage, 'getItem' | 'setItem'> | undefined;
58
58
  }
59
59
  export interface ResizableLayoutStore {
60
60
  defaultLayout: ResizableLayout | undefined;