@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
@@ -0,0 +1,287 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useMemo, useRef, useState, } from 'react';
4
+ import { Bar, BarChart, CartesianGrid, Rectangle, ReferenceArea, ReferenceLine, XAxis, YAxis } from 'recharts';
5
+ import { Badge } from '../../components/badge.js';
6
+ import { Button } from '../../components/button.js';
7
+ import { Skeleton } from '../../components/skeleton.js';
8
+ import { StatePanel } from '../state-panel.js';
9
+ import { cn } from '../classes.js';
10
+ import { ChartContainer, ChartLegend, ChartTooltip, ChartTooltipContent, chartColor, configLegend, dayLabel, quietAxis, seriesConfig, tooltipCursor, } from '../chart-kit.js';
11
+ import { DAY, dayTime, isCalendarDate, plainSpaces, wallClock } from './timeline-dates.js';
12
+ const AXIS = 40;
13
+ const read = (value) => {
14
+ if (typeof value === 'number')
15
+ return Number.isFinite(value) ? { time: value, date: false } : null;
16
+ if (typeof value !== 'string' || !value)
17
+ return null;
18
+ if (isCalendarDate(value))
19
+ return { time: dayTime(value), date: true };
20
+ const time = Date.parse(value);
21
+ return Number.isNaN(time) ? null : { time, date: false };
22
+ };
23
+ const clipText = {
24
+ start: 'Starts before window',
25
+ end: 'Ends after window',
26
+ both: 'Runs past window',
27
+ };
28
+ const dateFormat = (locale) => new Intl.DateTimeFormat(locale, { day: 'numeric', month: 'short', year: 'numeric', timeZone: 'UTC' });
29
+ const timeFormat = (locale, timeZone) => new Intl.DateTimeFormat(locale, {
30
+ day: 'numeric',
31
+ month: 'short',
32
+ year: 'numeric',
33
+ hour: 'numeric',
34
+ minute: '2-digit',
35
+ timeZone,
36
+ });
37
+ /** A mark's dates in words, like "1–9 Oct 2026". */
38
+ function datesText(mark, hasEnd, locale, timeZone) {
39
+ return plainSpaces(rawDatesText(mark, hasEnd, locale, timeZone));
40
+ }
41
+ function rawDatesText(mark, hasEnd, locale, timeZone) {
42
+ const format = mark.from.date ? dateFormat(locale) : timeFormat(locale, timeZone);
43
+ const start = format.format(mark.from.time);
44
+ if (mark.kind === 'reversed' && mark.to)
45
+ return `Starts ${start}, ends ${format.format(mark.to.time)}`;
46
+ if (!mark.to)
47
+ return hasEnd ? `${start}, no end` : start;
48
+ if (mark.to.time === mark.from.time)
49
+ return start;
50
+ return format.formatRange(mark.from.time, mark.to.time);
51
+ }
52
+ /** Saturdays and Sundays in a window of a month or less, as [from, to] times. */
53
+ function weekends(from, to) {
54
+ if (to - from > 31 * DAY)
55
+ return [];
56
+ const bands = [];
57
+ for (let day = from; day < to; day += DAY) {
58
+ const weekday = new Date(day).getUTCDay();
59
+ if (weekday === 6 || (weekday === 0 && day === from))
60
+ bands.push([day, Math.min(to, day + (weekday === 6 ? 2 : 1) * DAY)]);
61
+ }
62
+ return bands;
63
+ }
64
+ const weekLength = (from, to) => to - from <= 7 * DAY;
65
+ /** Tick times for a window: the middle of each day in a week, weekly in a month, twice a month in a quarter. */
66
+ function windowTicks(from, to) {
67
+ if (weekLength(from, to))
68
+ return Array.from({ length: Math.round((to - from) / DAY) }, (_, i) => from + (i + 0.5) * DAY);
69
+ const days = Math.round((to - from) / DAY);
70
+ const ticks = [];
71
+ for (let day = from; day <= to; day += DAY) {
72
+ const date = new Date(day).getUTCDate();
73
+ if (days <= 31 ? (date - 1) % 7 === 0 : date === 1 || date === 15)
74
+ ticks.push(day);
75
+ }
76
+ return ticks;
77
+ }
78
+ /** A week tick, like "Mon 12": weekday first in every locale so the days scan down one edge. */
79
+ function weekdayTick(value, locale) {
80
+ const parts = new Intl.DateTimeFormat(locale, { weekday: 'short', day: 'numeric', timeZone: 'UTC' }).formatToParts(value);
81
+ const part = (type) => parts.find(item => item.type === type)?.value ?? '';
82
+ return `${part('weekday')} ${part('day')}`;
83
+ }
84
+ const diamond = (cx, cy) => `M${cx} ${cy - 6}L${cx + 6} ${cy}L${cx} ${cy + 6}L${cx - 6} ${cy}Z`;
85
+ /** Bars for ranges, cut ends squared with a chevron; diamonds for points. */
86
+ function markShape(props) {
87
+ const mark = props.payload;
88
+ const { x = 0, y = 0, width = 0, height = 0 } = props;
89
+ const cy = y + height / 2;
90
+ if (mark.kind !== 'range')
91
+ return (_jsx("path", { className: "sprout-timeline-point", "data-kind": mark.kind, d: diamond(x, cy), fill: mark.kind === 'reversed' ? 'var(--sprout-surface)' : mark.fill, stroke: mark.kind === 'reversed' ? 'var(--sprout-warning)' : 'var(--sprout-surface)', strokeWidth: mark.kind === 'reversed' ? 2 : 1 }));
92
+ if (!mark.clip)
93
+ return _jsx(Rectangle, { ...props, fill: mark.fill });
94
+ const left = mark.clip !== 'end';
95
+ const right = mark.clip !== 'start';
96
+ const radius = [left ? 0 : 3, right ? 0 : 3, right ? 0 : 3, left ? 0 : 3];
97
+ const room = width >= 16;
98
+ return (_jsxs("g", { className: "sprout-timeline-clipped", "data-clip": mark.clip, children: [_jsx(Rectangle, { ...props, radius: radius, fill: mark.fill }), room && left ? (_jsx("path", { className: "sprout-timeline-chevron", d: `M${x + 8} ${cy - 4}L${x + 4} ${cy}L${x + 8} ${cy + 4}` })) : null, room && right ? (_jsx("path", { className: "sprout-timeline-chevron", d: `M${x + width - 8} ${cy - 4}L${x + width - 4} ${cy}L${x + width - 8} ${cy + 4}` })) : null] }));
99
+ }
100
+ function TodayLabel({ viewBox }) {
101
+ const x = viewBox?.x ?? 0;
102
+ const y = viewBox?.y ?? 0;
103
+ return (_jsxs("g", { className: "sprout-timeline-today", children: [_jsx("rect", { x: x - 21, y: y - AXIS + 2, width: 42, height: 16, rx: 8 }), _jsx("text", { x: x, y: y - AXIS + 10, textAnchor: "middle", dominantBaseline: "central", children: "Today" })] }));
104
+ }
105
+ const plural = (count) => (Number(String(count).replaceAll(',', '')) === 1 ? 'row' : 'rows');
106
+ const focusable = 'a[href], button, input, textarea, [tabindex]';
107
+ /**
108
+ * Gives only the active row's actions a place in the tab order, so the list
109
+ * is one tab stop and Tab from a row reaches its own actions.
110
+ */
111
+ function syncActions(list, active) {
112
+ list.querySelectorAll('[data-slot="timeline-row"]').forEach((row, index) => {
113
+ for (const element of row.querySelectorAll(`[data-slot="timeline-row-actions"] :is(${focusable})`)) {
114
+ const saved = element.dataset.sproutTabindex;
115
+ if (index === active) {
116
+ if (saved === undefined)
117
+ continue;
118
+ if (saved)
119
+ element.setAttribute('tabindex', saved);
120
+ else
121
+ element.removeAttribute('tabindex');
122
+ delete element.dataset.sproutTabindex;
123
+ }
124
+ else if (saved === undefined) {
125
+ element.dataset.sproutTabindex = element.getAttribute('tabindex') ?? '';
126
+ element.tabIndex = -1;
127
+ }
128
+ }
129
+ });
130
+ }
131
+ /**
132
+ * Rows as bars on a time axis, like a project plan. A row with only a start
133
+ * is a diamond. Give it a `window`, `renderLabel`, `renderActions`, or
134
+ * `onRowOpen` and it becomes a record timeline: a list of titles and dates
135
+ * in words beside the chart, in start order, with one tab stop and arrow
136
+ * keys. Without them it is a plain chart with names on the axis, one 32px
137
+ * row per task, colored by `seriesKey`.
138
+ */
139
+ export function TimelineChart({ rows, category, start, end, seriesKey, series = [], locale, window, today, timeZone, rowKey, renderLabel, renderActions, onRowOpen, undated, notice, status = 'ready', error, onRetry, empty, title = 'Timeline', className, }) {
140
+ const record = Boolean(window || renderLabel || renderActions || onRowOpen);
141
+ const zoned = record || timeZone !== undefined;
142
+ const config = useMemo(() => seriesConfig(series), [series]);
143
+ const domain = useMemo(() => (window ? [dayTime(window.start), dayTime(window.end) + DAY] : undefined), [window]);
144
+ const marks = useMemo(() => {
145
+ const at = (when) => (when.date || !zoned ? when.time : wallClock(when.time, timeZone));
146
+ const list = [];
147
+ rows.forEach((row, index) => {
148
+ const from = read(row[start]);
149
+ if (!from)
150
+ return;
151
+ const to = end ? read(row[end]) : null;
152
+ const key = seriesKey ? String(row[seriesKey] ?? '') : '';
153
+ const a = at(from);
154
+ const kind = !to ? 'point' : at(to) < a ? 'reversed' : 'range';
155
+ let range;
156
+ if (kind === 'range')
157
+ range = [a, at(to) + (record && to.date ? DAY : 0)];
158
+ else {
159
+ const point = a + (record && from.date ? DAY / 2 : 0);
160
+ range = [point, point];
161
+ }
162
+ let clip;
163
+ if (domain) {
164
+ const [low, high] = domain;
165
+ if (kind === 'range' ? range[1] <= low || range[0] >= high : range[0] < low || range[0] >= high)
166
+ return;
167
+ const cutStart = range[0] < low;
168
+ const cutEnd = range[1] > high;
169
+ clip = cutStart && cutEnd ? 'both' : cutStart ? 'start' : cutEnd ? 'end' : undefined;
170
+ range = [Math.max(range[0], low), Math.min(range[1], high)];
171
+ }
172
+ list.push({
173
+ row,
174
+ id: rowKey ? String(row[rowKey] ?? index) : String(index),
175
+ name: String(row[category] ?? ''),
176
+ key,
177
+ fill: series.some(item => item.key === key) ? chartColor(key) : 'var(--sprout-chart-1)',
178
+ kind,
179
+ range,
180
+ clip,
181
+ startsAt: a,
182
+ from,
183
+ to,
184
+ });
185
+ });
186
+ if (record)
187
+ list.sort((x, y) => x.startsAt - y.startsAt);
188
+ return list;
189
+ }, [rows, category, start, end, seriesKey, series, rowKey, domain, record, zoned, timeZone]);
190
+ const date = (value) => dayLabel(value, locale);
191
+ const todayAt = today && isCalendarDate(today) ? dayTime(today) + DAY / 2 : undefined;
192
+ if (!record)
193
+ return (_jsx(ChartContainer, { "data-variant": "timeline", className: cn('sprout-chart-timeline', className), style: { height: `${marks.length * 2 + (series.length ? 5 : 3)}rem` }, config: config, children: _jsxs(BarChart, { data: marks, accessibilityLayer: true, title: title, layout: "vertical", barCategoryGap: "28%", children: [_jsx(CartesianGrid, { horizontal: false }), _jsx(XAxis, { type: "number", scale: "time", domain: domain ?? ['dataMin', 'dataMax'], tickFormatter: date, ...quietAxis, minTickGap: 24 }), _jsx(YAxis, { type: "category", dataKey: "name", width: "auto", ...quietAxis, interval: 0 }), _jsx(ChartTooltip, { cursor: tooltipCursor, content: props => (_jsx(ChartTooltipContent, { active: props.active, label: props.label, nameKey: "key", payload: props.payload?.map(item => {
194
+ const [from, to] = item.payload.range;
195
+ return {
196
+ ...item,
197
+ name: item.payload.key,
198
+ value: from === to ? date(from) : `${date(from)} – ${date(to)}`,
199
+ };
200
+ }) })) }), series.length ? _jsx(ChartLegend, { content: configLegend(config) }) : null, todayAt === undefined ? null : (_jsx(ReferenceLine, { x: todayAt, stroke: "var(--sprout-chart-1)", strokeDasharray: "3 3" })), _jsx(Bar, { dataKey: "range", radius: 3, shape: markShape, isAnimationActive: false })] }) }));
201
+ return (_jsx(RecordTimeline, { marks: marks, config: config, series: series, hasEnd: Boolean(end), domain: domain, window: window, todayAt: todayAt, locale: locale, timeZone: timeZone, renderLabel: renderLabel, renderActions: renderActions, onRowOpen: onRowOpen, undated: undated, notice: notice, status: status, error: error, onRetry: onRetry, empty: empty, title: title, className: className }));
202
+ }
203
+ function RecordTimeline({ marks, config, series, hasEnd, domain, window, todayAt, locale, timeZone, renderLabel, renderActions, onRowOpen, undated, notice, status, error, onRetry, empty, title, className, }) {
204
+ const id = useId();
205
+ const listRef = useRef(null);
206
+ const [activeId, setActiveId] = useState(null);
207
+ const [hot, setHot] = useState(null);
208
+ const found = marks.findIndex(mark => mark.id === activeId);
209
+ const active = found === -1 ? 0 : found;
210
+ useEffect(() => {
211
+ if (listRef.current)
212
+ syncActions(listRef.current, active);
213
+ });
214
+ const date = (value) => dayLabel(value, locale);
215
+ const dates = marks.map(mark => datesText(mark, hasEnd, locale, timeZone));
216
+ const loading = status === 'loading';
217
+ const style = { '--sprout-timeline-count': Math.max(marks.length, 1) };
218
+ const focusRow = (index) => {
219
+ const next = marks[index];
220
+ if (!next)
221
+ return;
222
+ setActiveId(next.id);
223
+ listRef.current?.querySelectorAll('[data-slot="timeline-row"]')[index]?.focus();
224
+ };
225
+ const onKeyDown = (event, index) => {
226
+ if (event.target !== event.currentTarget)
227
+ return;
228
+ const moves = {
229
+ ArrowDown: index + 1,
230
+ ArrowUp: index - 1,
231
+ Home: 0,
232
+ End: marks.length - 1,
233
+ };
234
+ const next = moves[event.key];
235
+ if (next !== undefined) {
236
+ event.preventDefault();
237
+ focusRow(Math.min(Math.max(next, 0), marks.length - 1));
238
+ }
239
+ else if (event.key === 'Enter' && onRowOpen) {
240
+ event.preventDefault();
241
+ onRowOpen(marks[index].row);
242
+ }
243
+ };
244
+ const onRowClick = (event, index) => {
245
+ if (event.target.closest('[data-slot="timeline-row-actions"]'))
246
+ return;
247
+ onRowOpen?.(marks[index].row);
248
+ };
249
+ const windowText = () => {
250
+ if (!window)
251
+ return 'No rows to show.';
252
+ const format = dateFormat(locale);
253
+ return `Nothing between ${format.format(dayTime(window.start))} and ${format.format(dayTime(window.end))}.`;
254
+ };
255
+ let body;
256
+ if (status === 'error')
257
+ body = (_jsx(StatePanel, { kind: "error", heading: "h3", title: "Couldn't load the timeline", description: error ?? 'Something went wrong while reading these rows.', className: "sprout-timeline-state", children: onRetry ? (_jsx(Button, { variant: "outline", size: "sm", onClick: onRetry, children: "Try again" })) : null }));
258
+ else if (!marks.length && loading)
259
+ body = (_jsxs("div", { role: "status", "aria-label": "Loading timeline", className: "sprout-timeline-grid", "data-skeleton": "", children: [_jsx("div", { className: "sprout-timeline-labels", "aria-hidden": "true", children: [0, 1, 2, 3, 4].map(index => (_jsx("div", { className: "sprout-timeline-row", children: _jsxs("div", { className: "sprout-timeline-label", children: [_jsx(Skeleton, { style: { width: `${70 - index * 7}%` } }), _jsx(Skeleton, { style: { width: '45%', height: 10 } })] }) }, index))) }), _jsx("div", { className: "sprout-timeline-plot", "aria-hidden": "true", children: [0, 1, 2, 3, 4].map(index => (_jsx("div", { className: "sprout-timeline-skeleton-band", children: _jsx(Skeleton, { style: { marginLeft: `${(index * 17) % 60}%`, width: `${20 + ((index * 23) % 30)}%` } }) }, index))) })] }));
260
+ else if (!marks.length)
261
+ body = empty ?? (_jsx(StatePanel, { kind: "empty", heading: "h3", title: "Nothing in this window", description: windowText(), className: "sprout-timeline-state" }));
262
+ else
263
+ body = (_jsxs("div", { className: "sprout-timeline-grid", onMouseLeave: () => setHot(null), children: [_jsx("ol", { ref: listRef, "aria-label": title, className: "sprout-timeline-labels", onBlur: event => {
264
+ if (!event.currentTarget.contains(event.relatedTarget))
265
+ setHot(null);
266
+ }, children: marks.map((mark, index) => (_jsxs("li", { "data-slot": "timeline-row", "data-active": index === active || undefined, "data-hot": index === hot || undefined, "data-openable": onRowOpen ? '' : undefined, tabIndex: index === active ? 0 : -1, "aria-labelledby": `${id}-${index}`, className: "sprout-timeline-row", onKeyDown: event => onKeyDown(event, index), onClick: event => onRowClick(event, index), onFocus: () => {
267
+ setActiveId(mark.id);
268
+ setHot(index);
269
+ }, onMouseEnter: () => setHot(index), children: [_jsxs("div", { className: "sprout-timeline-label", id: `${id}-${index}`, children: [_jsxs("span", { className: "sprout-timeline-label-head", children: [_jsx("span", { className: "sprout-timeline-label-title", children: renderLabel ? renderLabel(mark.row) : mark.name }), mark.kind === 'reversed' ? (_jsx(Badge, { variant: "warning", size: "chip", className: "sprout-timeline-label-marker", children: "End before start" })) : null] }), _jsxs("span", { className: "sprout-timeline-label-dates", children: [mark.kind === 'reversed' ? (_jsx("span", { className: "sprout-timeline-label-warning", children: "End before start" })) : null, _jsx("span", { className: "sprout-timeline-label-text", children: dates[index] }), mark.clip ? _jsx("span", { className: "sprout-timeline-label-clip", children: clipText[mark.clip] }) : null] })] }), renderActions ? (_jsx("div", { "data-slot": "timeline-row-actions", className: "sprout-timeline-row-actions", children: renderActions(mark.row) })) : null] }, mark.id))) }), _jsxs("div", { className: "sprout-timeline-plot", "aria-hidden": "true", children: [hot === null ? null : (_jsx("div", { className: "sprout-timeline-band", style: { '--sprout-timeline-index': hot } })), _jsx(ChartContainer, { "data-variant": "timeline", className: "sprout-chart-timeline sprout-timeline-chart", config: config, initialDimension: { width: 640, height: AXIS + marks.length * 44 }, children: _jsxs(BarChart, { data: marks, layout: "vertical", margin: { top: 0, right: 16, bottom: 0, left: 16 }, barSize: 16, accessibilityLayer: false, onMouseMove: state => {
270
+ const index = Number(state.activeTooltipIndex);
271
+ setHot(Number.isInteger(index) && state.activeTooltipIndex != null ? index : null);
272
+ }, children: [_jsx(CartesianGrid, { horizontal: false, vertical: !(domain && weekLength(...domain)) }), domain
273
+ ? weekends(...domain).map(([x1, x2]) => (_jsx(ReferenceArea, { x1: x1, x2: x2, ifOverflow: "hidden", className: "sprout-timeline-weekend", fill: "var(--sprout-hover)", fillOpacity: 0.4, stroke: "none" }, x1)))
274
+ : null, _jsx(XAxis, { type: "number", scale: "time", orientation: "top", height: AXIS, domain: domain ?? ['dataMin', 'dataMax'], allowDataOverflow: true, ticks: domain ? windowTicks(...domain) : undefined, tickFormatter: domain && weekLength(...domain) ? (value) => weekdayTick(value, locale) : date, interval: "equidistantPreserveStart", ...quietAxis, tickMargin: 6, minTickGap: 32 }), _jsx(YAxis, { type: "category", dataKey: "id", hide: true }), _jsx(ChartTooltip, { cursor: false, content: props => (_jsx(ChartTooltipContent, { active: props.active, label: props.payload?.[0]?.payload?.name, nameKey: "key", hideIndicator: !series.length, payload: props.payload?.map(item => {
275
+ const mark = item.payload;
276
+ return {
277
+ ...item,
278
+ name: mark.key,
279
+ value: dates[marks.indexOf(mark)] ?? '',
280
+ };
281
+ }) })) }), todayAt === undefined ? null : (_jsx(ReferenceLine, { x: todayAt, stroke: "var(--sprout-chart-1)", strokeWidth: 1.5, ifOverflow: "discard", label: _jsx(TodayLabel, {}) })), _jsx(Bar, { dataKey: "range", radius: 3, shape: markShape, isAnimationActive: false, onClick: (_, index) => {
282
+ const mark = marks[index];
283
+ if (mark)
284
+ onRowOpen?.(mark.row);
285
+ } })] }) })] })] }));
286
+ return (_jsxs("div", { "data-slot": "timeline", "data-status": status, "aria-busy": loading || undefined, className: cn('sprout-timeline', className), style: style, children: [notice ? _jsx("div", { className: "sprout-timeline-notice", children: notice }) : null, body, series.length && marks.length && status !== 'error' ? (_jsx("div", { "data-slot": "chart-legend", className: "sprout-chart-legend sprout-timeline-legend", children: series.map(item => (_jsxs("div", { className: "sprout-chart-legend-item", children: [_jsx("span", { "aria-hidden": "true", className: "sprout-chart-legend-swatch", style: { backgroundColor: item.color } }), item.label] }, item.key))) })) : null, undated && status !== 'error' ? (_jsxs("div", { "data-slot": "timeline-undated", className: "sprout-timeline-undated", children: [_jsx("span", { children: `${undated.count} ${plural(undated.count)} without ${undated.field}` }), undated.action] })) : null] }));
287
+ }
@@ -1,3 +1,3 @@
1
- import { type ClassValue } from "clsx";
1
+ import { type ClassValue } from 'clsx';
2
2
  export declare function cn(...values: ClassValue[]): string;
3
3
  export declare function stateClassName<State>(base: string, className: string | ((state: State) => string | undefined) | undefined): string | ((state: State) => string);
@@ -1,12 +1,12 @@
1
- import { clsx } from "clsx";
2
- import { extendTailwindMerge } from "tailwind-merge";
1
+ import { clsx } from 'clsx';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
3
  const merge = extendTailwindMerge({
4
4
  extend: {
5
5
  theme: {
6
- text: ["sprout-xs", "sprout-sm", "sprout-base"],
7
- font: ["sprout"],
8
- radius: ["sprout-control", "sprout-panel"],
9
- shadow: ["sprout-control", "sprout-panel", "sprout-overlay"],
6
+ text: ['sprout-xs', 'sprout-sm', 'sprout-base'],
7
+ font: ['sprout'],
8
+ radius: ['sprout-control', 'sprout-panel'],
9
+ shadow: ['sprout-control', 'sprout-panel', 'sprout-overlay'],
10
10
  },
11
11
  },
12
12
  });
@@ -14,7 +14,5 @@ export function cn(...values) {
14
14
  return merge(clsx(values));
15
15
  }
16
16
  export function stateClassName(base, className) {
17
- return typeof className === "function"
18
- ? (state) => cn(base, className(state))
19
- : cn(base, className);
17
+ return typeof className === 'function' ? (state) => cn(base, className(state)) : cn(base, className);
20
18
  }
@@ -1,4 +1,4 @@
1
- import type { ThemedToken } from "shiki/core";
2
- import type { CodeLanguage } from "./languages.js";
1
+ import type { ThemedToken } from 'shiki/core';
2
+ import type { CodeLanguage } from './languages.js';
3
3
  export declare function useCodeTokens(code: string, language: CodeLanguage | null): ThemedToken[][] | null;
4
4
  export declare function tokenClass(token: ThemedToken): string | undefined;
@@ -1,16 +1,16 @@
1
- import { useEffect, useMemo, useState } from "react";
2
- import { codeTokens, embeddedLanguages, isLanguageReady, loadCodeLanguage, maxHighlightedLength, } from "./syntax.js";
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import { codeTokens, embeddedLanguages, isLanguageReady, loadCodeLanguage, maxHighlightedLength } from './syntax.js';
3
3
  export function useCodeTokens(code, language) {
4
4
  const [loaded, setLoaded] = useState(0);
5
5
  const highlightable = language !== null && code.length <= maxHighlightedLength;
6
- const needed = useMemo(() => highlightable ? [language, ...embeddedLanguages(code, language)] : [], [code, language, highlightable]);
7
- const missing = needed.filter((name) => !isLanguageReady(name));
8
- const key = missing.join(" ");
6
+ const needed = useMemo(() => (highlightable ? [language, ...embeddedLanguages(code, language)] : []), [code, language, highlightable]);
7
+ const missing = needed.filter(name => !isLanguageReady(name));
8
+ const key = missing.join(' ');
9
9
  useEffect(() => {
10
10
  if (!key)
11
11
  return;
12
12
  let live = true;
13
- void Promise.all(key.split(" ").map((name) => loadCodeLanguage(name))).then(() => live && setLoaded((value) => value + 1), () => undefined);
13
+ void Promise.all(key.split(' ').map(name => loadCodeLanguage(name))).then(() => live && setLoaded(value => value + 1), () => undefined);
14
14
  return () => {
15
15
  live = false;
16
16
  };
@@ -20,15 +20,15 @@ export function useCodeTokens(code, language) {
20
20
  [code, language, highlightable, loaded, key]);
21
21
  }
22
22
  const fontStyleClasses = [
23
- [1, "sprout-syntax-italic"],
24
- [2, "sprout-syntax-bold"],
25
- [4, "sprout-syntax-underline"],
23
+ [1, 'sprout-syntax-italic'],
24
+ [2, 'sprout-syntax-bold'],
25
+ [4, 'sprout-syntax-underline'],
26
26
  ];
27
27
  export function tokenClass(token) {
28
- const role = /--sprout-syntax-(?:token-)?([a-z-]+)/.exec(token.color ?? "")?.[1];
29
- const classes = role && role !== "foreground" ? [`sprout-syntax-${role}`] : [];
28
+ const role = /--sprout-syntax-(?:token-)?([a-z-]+)/.exec(token.color ?? '')?.[1];
29
+ const classes = role && role !== 'foreground' ? [`sprout-syntax-${role}`] : [];
30
30
  for (const [flag, name] of fontStyleClasses)
31
31
  if ((token.fontStyle ?? 0) & flag)
32
32
  classes.push(name);
33
- return classes.length ? classes.join(" ") : undefined;
33
+ return classes.length ? classes.join(' ') : undefined;
34
34
  }
@@ -1,4 +1,4 @@
1
- import { type Ref } from "react";
1
+ import { type Ref } from 'react';
2
2
  /**
3
3
  * Base UI roots are spans, which `<fieldset disabled>` does not disable. Track the
4
4
  * enclosing fieldsets so the control can pass a real `disabled` to Base UI.
@@ -1,4 +1,4 @@
1
- import { useCallback, useState } from "react";
1
+ import { useCallback, useState } from 'react';
2
2
  /**
3
3
  * Base UI roots are spans, which `<fieldset disabled>` does not disable. Track the
4
4
  * enclosing fieldsets so the control can pass a real `disabled` to Base UI.
@@ -6,29 +6,29 @@ import { useCallback, useState } from "react";
6
6
  export function useFieldsetDisabled(ref) {
7
7
  const [disabled, setDisabled] = useState(false);
8
8
  const mergedRef = useCallback((node) => {
9
- if (typeof ref === "function")
9
+ if (typeof ref === 'function')
10
10
  ref(node);
11
11
  else if (ref)
12
12
  ref.current = node;
13
13
  if (!node)
14
14
  return;
15
15
  const fieldsets = [];
16
- for (let fieldset = node.closest("fieldset"); fieldset; fieldset = fieldset.parentElement?.closest("fieldset") ?? null) {
16
+ for (let fieldset = node.closest('fieldset'); fieldset; fieldset = fieldset.parentElement?.closest('fieldset') ?? null) {
17
17
  fieldsets.push(fieldset);
18
18
  }
19
19
  if (fieldsets.length === 0)
20
20
  return;
21
- const sync = () => setDisabled(node.closest("fieldset:disabled") !== null);
21
+ const sync = () => setDisabled(node.closest('fieldset:disabled') !== null);
22
22
  sync();
23
23
  const observer = new MutationObserver(sync);
24
24
  for (const fieldset of fieldsets)
25
25
  observer.observe(fieldset, {
26
26
  attributes: true,
27
- attributeFilter: ["disabled"],
27
+ attributeFilter: ['disabled'],
28
28
  });
29
29
  return () => {
30
30
  observer.disconnect();
31
- if (typeof ref === "function")
31
+ if (typeof ref === 'function')
32
32
  ref(null);
33
33
  else if (ref)
34
34
  ref.current = null;
@@ -1,4 +1,4 @@
1
- export type FileKind = "image" | "pdf" | "json" | "text" | "markdown" | "code" | "sheet" | "document" | "slides" | "google" | "unsupported";
1
+ export type FileKind = 'image' | 'pdf' | 'json' | 'text' | 'markdown' | 'code' | 'sheet' | 'document' | 'slides' | 'google' | 'unsupported';
2
2
  export declare const defaultFileAccept: string;
3
3
  export declare function fileKind(name: string, mediaType: string): FileKind;
4
4
  export declare function formatFileSize(bytes: number): string;
@@ -1,62 +1,54 @@
1
- import { languageForFilename } from "./syntax.js";
2
- export const defaultFileAccept = ".docx,.xlsx,.xls,.csv,.tsv,.pptx,.ppt,.pdf,.json,.txt,.md,.markdown,.gdoc,.gsheet,.gslides,image/*," +
3
- ".js,.jsx,.ts,.tsx,.py,.rb,.go,.rs,.java,.kt,.swift,.c,.h,.cpp,.cs,.php,.sh,.sql,.yaml,.yml,.toml,.xml,.html,.css,.scss,.log";
1
+ import { languageForFilename } from './syntax.js';
2
+ export const defaultFileAccept = '.docx,.xlsx,.xls,.csv,.tsv,.pptx,.ppt,.pdf,.json,.txt,.md,.markdown,.gdoc,.gsheet,.gslides,image/*,' +
3
+ '.js,.jsx,.ts,.tsx,.py,.rb,.go,.rs,.java,.kt,.swift,.c,.h,.cpp,.cs,.php,.sh,.sql,.yaml,.yml,.toml,.xml,.html,.css,.scss,.log';
4
4
  const imageExtensions = [
5
- "png",
6
- "jpg",
7
- "jpeg",
8
- "gif",
9
- "webp",
10
- "avif",
11
- "svg",
12
- "bmp",
13
- "ico",
14
- "heic",
15
- "heif",
16
- "tif",
17
- "tiff",
5
+ 'png',
6
+ 'jpg',
7
+ 'jpeg',
8
+ 'gif',
9
+ 'webp',
10
+ 'avif',
11
+ 'svg',
12
+ 'bmp',
13
+ 'ico',
14
+ 'heic',
15
+ 'heif',
16
+ 'tif',
17
+ 'tiff',
18
18
  ];
19
19
  const sheetTypes = [
20
- "application/vnd.ms-excel",
21
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
22
- "text/csv",
20
+ 'application/vnd.ms-excel',
21
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
22
+ 'text/csv',
23
23
  ];
24
24
  export function fileKind(name, mediaType) {
25
- const extension = name.toLowerCase().split(".").at(-1) ?? "";
26
- if (mediaType.startsWith("image/") || imageExtensions.includes(extension))
27
- return "image";
28
- if (mediaType.startsWith("application/vnd.google-apps.") ||
29
- ["gdoc", "gsheet", "gslides"].includes(extension))
30
- return "google";
31
- if (extension === "pdf" || mediaType === "application/pdf")
32
- return "pdf";
33
- if (extension === "json" || mediaType === "application/json")
34
- return "json";
35
- if (["md", "markdown"].includes(extension) || mediaType === "text/markdown")
36
- return "markdown";
37
- if (["xls", "xlsx", "csv", "tsv"].includes(extension) ||
38
- sheetTypes.includes(mediaType))
39
- return "sheet";
40
- if (extension === "docx" ||
41
- mediaType ===
42
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
43
- return "document";
44
- if (extension === "pptx" ||
45
- mediaType ===
46
- "application/vnd.openxmlformats-officedocument.presentationml.presentation")
47
- return "slides";
25
+ const extension = name.toLowerCase().split('.').at(-1) ?? '';
26
+ if (mediaType.startsWith('image/') || imageExtensions.includes(extension))
27
+ return 'image';
28
+ if (mediaType.startsWith('application/vnd.google-apps.') || ['gdoc', 'gsheet', 'gslides'].includes(extension))
29
+ return 'google';
30
+ if (extension === 'pdf' || mediaType === 'application/pdf')
31
+ return 'pdf';
32
+ if (extension === 'json' || mediaType === 'application/json')
33
+ return 'json';
34
+ if (['md', 'markdown'].includes(extension) || mediaType === 'text/markdown')
35
+ return 'markdown';
36
+ if (['xls', 'xlsx', 'csv', 'tsv'].includes(extension) || sheetTypes.includes(mediaType))
37
+ return 'sheet';
38
+ if (extension === 'docx' || mediaType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')
39
+ return 'document';
40
+ if (extension === 'pptx' || mediaType === 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
41
+ return 'slides';
48
42
  if (languageForFilename(name))
49
- return "code";
50
- if (mediaType.startsWith("text/") || extension === "txt")
51
- return "text";
52
- return "unsupported";
43
+ return 'code';
44
+ if (mediaType.startsWith('text/') || extension === 'txt')
45
+ return 'text';
46
+ return 'unsupported';
53
47
  }
54
48
  export function formatFileSize(bytes) {
55
49
  if (bytes === 0)
56
- return "0 bytes";
50
+ return '0 bytes';
57
51
  if (bytes >= 1024 ** 3)
58
- return `${(bytes / 1024 ** 3).toFixed(1).replace(/\.0$/, "")} GB`;
59
- return bytes < 1024 * 1024
60
- ? `${Math.max(1, Math.round(bytes / 1024))} KB`
61
- : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
52
+ return `${(bytes / 1024 ** 3).toFixed(1).replace(/\.0$/, '')} GB`;
53
+ return bytes < 1024 * 1024 ? `${Math.max(1, Math.round(bytes / 1024))} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
62
54
  }
@@ -1,5 +1,5 @@
1
- import { type FitViewOptions, type Node } from "@xyflow/react";
2
- import { type KeyboardEvent } from "react";
1
+ import { type FitViewOptions, type Node } from '@xyflow/react';
2
+ import { type KeyboardEvent } from 'react';
3
3
  export declare const flowMinZoom = 0.2;
4
4
  export declare const flowMaxZoom = 1.5;
5
5
  export declare function useViewportMobile(): boolean;
@@ -8,12 +8,12 @@ export declare const motion: (ms: number) => number;
8
8
  * Refits whenever the pane resizes or the nodes change. The canvas panel
9
9
  * animates open, so the first fit sees a narrower pane than the final one.
10
10
  */
11
- export declare function FitOnResize({ nodes, fit, }: {
11
+ export declare function FitOnResize({ nodes, fit }: {
12
12
  nodes: readonly Node[];
13
13
  fit: FitViewOptions;
14
14
  }): null;
15
15
  export declare function ZoomControls({ position, fit, className, slot, }: {
16
- position: "top-right" | "bottom-right";
16
+ position: 'top-right' | 'bottom-right';
17
17
  fit: FitViewOptions;
18
18
  className: string;
19
19
  slot: string;