@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,50 +1,44 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useDeferredValue, useEffect, useId, useMemo, useRef, useState, } from "react";
4
- import { ChevronRight } from "reicon-react/icons/ChevronRight";
5
- import { FileText } from "reicon-react/icons/FileText";
6
- import { Folder } from "reicon-react/icons/Folder";
7
- import { FolderOpen } from "reicon-react/icons/FolderOpen";
8
- import { MinusSquare } from "reicon-react/icons/MinusSquare";
9
- import { X } from "reicon-react/icons/X";
10
- import { cn } from "../internal/classes.js";
11
- import { tokenClass, useCodeTokens } from "../internal/code-tokens.js";
12
- import { codeLanguageNames } from "../internal/languages.js";
13
- import { languageForFilename } from "../internal/syntax.js";
14
- import { SearchField } from "./search-field.js";
15
- import { StatePanel } from "./state-panel.js";
3
+ import { useDeferredValue, useEffect, useId, useMemo, useRef, useState, } from 'react';
4
+ import { ChevronRight } from 'reicon-react/icons/ChevronRight';
5
+ import { FileText } from 'reicon-react/icons/FileText';
6
+ import { Folder } from 'reicon-react/icons/Folder';
7
+ import { FolderOpen } from 'reicon-react/icons/FolderOpen';
8
+ import { MinusSquare } from 'reicon-react/icons/MinusSquare';
9
+ import { X } from 'reicon-react/icons/X';
10
+ import { cn } from '../internal/classes.js';
11
+ import { tokenClass, useCodeTokens } from '../internal/code-tokens.js';
12
+ import { codeLanguageNames } from '../internal/languages.js';
13
+ import { languageForFilename } from '../internal/syntax.js';
14
+ import { SearchField } from './search-field.js';
15
+ import { StatePanel } from '../internal/state-panel.js';
16
16
  /** Search stops after this many matching lines, so one common word cannot flood the list. */
17
17
  export const fileExplorerMaxMatches = 500;
18
- const nameOf = (path) => path.slice(path.lastIndexOf("/") + 1);
19
- const folderOf = (path) => path.slice(0, Math.max(0, path.lastIndexOf("/")));
20
- const order = (a, b) => a.kind === b.kind
21
- ? a.name.localeCompare(b.name, undefined, { numeric: true })
22
- : a.kind === "folder"
23
- ? -1
24
- : 1;
18
+ const nameOf = (path) => path.slice(path.lastIndexOf('/') + 1);
19
+ const folderOf = (path) => path.slice(0, Math.max(0, path.lastIndexOf('/')));
20
+ const order = (a, b) => a.kind === b.kind ? a.name.localeCompare(b.name, undefined, { numeric: true }) : a.kind === 'folder' ? -1 : 1;
25
21
  function ancestors(path) {
26
- const parts = path.split("/").slice(0, -1);
27
- return parts.map((_, index) => parts.slice(0, index + 1).join("/"));
22
+ const parts = path.split('/').slice(0, -1);
23
+ return parts.map((_, index) => parts.slice(0, index + 1).join('/'));
28
24
  }
29
25
  function buildTree(files) {
30
26
  const root = [];
31
- const folders = new Map([["", root]]);
27
+ const folders = new Map([['', root]]);
32
28
  for (const file of files) {
33
29
  for (const folder of ancestors(file.path)) {
34
30
  if (folders.has(folder))
35
31
  continue;
36
32
  const children = [];
37
33
  folders.get(folderOf(folder)).push({
38
- kind: "folder",
34
+ kind: 'folder',
39
35
  path: folder,
40
36
  name: nameOf(folder),
41
37
  children,
42
38
  });
43
39
  folders.set(folder, children);
44
40
  }
45
- folders
46
- .get(folderOf(file.path))
47
- .push({ kind: "file", path: file.path, name: nameOf(file.path), file });
41
+ folders.get(folderOf(file.path)).push({ kind: 'file', path: file.path, name: nameOf(file.path), file });
48
42
  }
49
43
  for (const children of folders.values())
50
44
  children.sort(order);
@@ -53,9 +47,7 @@ function buildTree(files) {
53
47
  function visibleRows(nodes, expanded, depth = 0) {
54
48
  return nodes.flatMap((node, index) => [
55
49
  { node, depth, size: nodes.length, position: index + 1 },
56
- ...(node.kind === "folder" && expanded.has(node.path)
57
- ? visibleRows(node.children, expanded, depth + 1)
58
- : []),
50
+ ...(node.kind === 'folder' && expanded.has(node.path) ? visibleRows(node.children, expanded, depth + 1) : []),
59
51
  ]);
60
52
  }
61
53
  function rangesIn(text, needle) {
@@ -68,14 +60,14 @@ function rangesIn(text, needle) {
68
60
  const excerptLead = 32;
69
61
  function searchFiles(files, query) {
70
62
  const needle = query.toLowerCase();
71
- const names = files.filter((file) => file.path.toLowerCase().includes(needle));
63
+ const names = files.filter(file => file.path.toLowerCase().includes(needle));
72
64
  const hits = [];
73
65
  let total = 0;
74
66
  for (const file of files) {
75
- if (!("content" in file) || total >= fileExplorerMaxMatches)
67
+ if (!('content' in file) || total >= fileExplorerMaxMatches)
76
68
  continue;
77
69
  const lines = [];
78
- file.content.split("\n").forEach((raw, index) => {
70
+ file.content.split('\n').forEach((raw, index) => {
79
71
  if (total >= fileExplorerMaxMatches)
80
72
  return;
81
73
  const ranges = rangesIn(raw, needle);
@@ -83,7 +75,7 @@ function searchFiles(files, query) {
83
75
  return;
84
76
  const indent = raw.length - raw.trimStart().length;
85
77
  const cut = Math.max(indent, ranges[0][0] - excerptLead);
86
- const prefix = cut > indent ? "…" : "";
78
+ const prefix = cut > indent ? '…' : '';
87
79
  const shift = cut - prefix.length;
88
80
  lines.push({
89
81
  line: index + 1,
@@ -120,59 +112,56 @@ function marked(pieces, ranges) {
120
112
  return out;
121
113
  }
122
114
  const glyphs = {
123
- typescript: ["TS", "info"],
124
- tsx: ["TSX", "info"],
125
- javascript: ["JS", "warning"],
126
- jsx: ["JSX", "warning"],
127
- json: ["{ }", "warning"],
128
- jsonc: ["{ }", "warning"],
129
- json5: ["{ }", "warning"],
130
- markdown: ["MD", "accent"],
131
- mdx: ["MDX", "accent"],
132
- python: ["PY", "info"],
133
- yaml: ["YML", "danger"],
134
- toml: ["TML", "danger"],
135
- css: ["CSS", "accent"],
136
- scss: ["SCS", "accent"],
137
- html: ["< >", "danger"],
138
- xml: ["< >", "warning"],
139
- shellscript: ["SH", "success"],
140
- dotenv: ["ENV", "success"],
141
- sql: ["SQL", "accent"],
142
- rust: ["RS", "danger"],
143
- go: ["GO", "info"],
144
- ruby: ["RB", "danger"],
115
+ typescript: ['TS', 'info'],
116
+ tsx: ['TSX', 'info'],
117
+ javascript: ['JS', 'warning'],
118
+ jsx: ['JSX', 'warning'],
119
+ json: ['{ }', 'warning'],
120
+ jsonc: ['{ }', 'warning'],
121
+ json5: ['{ }', 'warning'],
122
+ markdown: ['MD', 'accent'],
123
+ mdx: ['MDX', 'accent'],
124
+ python: ['PY', 'info'],
125
+ yaml: ['YML', 'danger'],
126
+ toml: ['TML', 'danger'],
127
+ css: ['CSS', 'accent'],
128
+ scss: ['SCS', 'accent'],
129
+ html: ['< >', 'danger'],
130
+ xml: ['< >', 'warning'],
131
+ shellscript: ['SH', 'success'],
132
+ dotenv: ['ENV', 'success'],
133
+ sql: ['SQL', 'accent'],
134
+ rust: ['RS', 'danger'],
135
+ go: ['GO', 'info'],
136
+ ruby: ['RB', 'danger'],
145
137
  };
146
138
  /** A 16px tile with a short language label, tinted by language. Decorative. */
147
139
  function FileGlyph({ name }) {
148
140
  const language = languageForFilename(name);
149
- const extension = name.includes(".") ? (name.split(".").at(-1) ?? "") : "";
150
- const [label, tone] = (language && glyphs[language]) ?? [
151
- extension.slice(0, 3).toUpperCase(),
152
- "muted",
153
- ];
141
+ const extension = name.includes('.') ? (name.split('.').at(-1) ?? '') : '';
142
+ const [label, tone] = (language && glyphs[language]) ?? [extension.slice(0, 3).toUpperCase(), 'muted'];
154
143
  if (!label)
155
- return (_jsx(FileText, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-glyph" }));
144
+ return _jsx(FileText, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-glyph" });
156
145
  return (_jsxs("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", "data-tone": tone, className: "sprout-file-explorer-glyph", children: [_jsx("rect", { x: "0.5", y: "1.5", width: "15", height: "13", rx: "3", className: "sprout-file-explorer-glyph-tile" }), _jsx("text", { x: "8", y: "10.8", textAnchor: "middle", fontSize: label.length > 2 ? 6 : 7.4, fontWeight: "700", className: "sprout-file-explorer-glyph-label", children: label })] }));
157
146
  }
158
- function CodeView({ file, query, line, }) {
147
+ function CodeView({ file, query, line }) {
159
148
  const language = languageForFilename(file.path);
160
149
  const tokens = useCodeTokens(file.content, language);
161
150
  const needle = query.toLowerCase();
162
151
  const current = useRef(null);
163
152
  useEffect(() => {
164
- current.current?.scrollIntoView({ block: "center" });
153
+ current.current?.scrollIntoView({ block: 'center' });
165
154
  }, [line, file.path]);
166
- const lines = useMemo(() => tokens?.map((row) => row.map((token) => ({
155
+ const lines = useMemo(() => tokens?.map(row => row.map(token => ({
167
156
  content: token.content,
168
157
  className: tokenClass(token),
169
- }))) ?? file.content.split("\n").map((content) => [{ content }]), [tokens, file.content]);
158
+ }))) ?? file.content.split('\n').map(content => [{ content }]), [tokens, file.content]);
170
159
  // ponytail: one DOM row per line; virtualize if files past ~20k lines matter.
171
- return (_jsx("div", { className: "sprout-file-explorer-code", tabIndex: 0, role: "region", "aria-label": file.path, "data-highlighted": tokens ? "" : undefined, children: _jsx("pre", { className: "sprout-file-explorer-pre", children: _jsx("code", { children: lines.map((pieces, index) => {
172
- const text = pieces.map((piece) => piece.content).join("");
173
- return (_jsxs("div", { ref: index + 1 === line ? current : undefined, "data-current": index + 1 === line ? "" : undefined, className: "sprout-file-explorer-line", children: [_jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-line-number", children: index + 1 }), _jsxs("span", { className: "sprout-file-explorer-line-text", children: [needle
160
+ return (_jsx("div", { className: "sprout-file-explorer-code", tabIndex: 0, role: "region", "aria-label": file.path, "data-highlighted": tokens ? '' : undefined, children: _jsx("pre", { className: "sprout-file-explorer-pre", children: _jsx("code", { children: lines.map((pieces, index) => {
161
+ const text = pieces.map(piece => piece.content).join('');
162
+ return (_jsxs("div", { ref: index + 1 === line ? current : undefined, "data-current": index + 1 === line ? '' : undefined, className: "sprout-file-explorer-line", children: [_jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-line-number", children: index + 1 }), _jsxs("span", { className: "sprout-file-explorer-line-text", children: [needle
174
163
  ? marked(pieces, rangesIn(text, needle))
175
- : pieces.map((piece, at) => (_jsx("span", { className: piece.className, children: piece.content }, at))), "\n"] })] }, index));
164
+ : pieces.map((piece, at) => (_jsx("span", { className: piece.className, children: piece.content }, at))), '\n'] })] }, index));
176
165
  }) }) }) }));
177
166
  }
178
167
  /**
@@ -180,21 +169,21 @@ function CodeView({ file, query, line, }) {
180
169
  * file pane. Search filters file names and lists matching lines across every
181
170
  * file; picking a line opens the file there.
182
171
  */
183
- export function FileExplorer({ files, label = "Files", defaultPath, className, ...props }) {
172
+ export function FileExplorer({ files, label = 'Files', defaultPath, className, ...props }) {
184
173
  const tree = useMemo(() => buildTree(files), [files]);
185
- const byPath = useMemo(() => new Map(files.map((file) => [file.path, file])), [files]);
174
+ const byPath = useMemo(() => new Map(files.map(file => [file.path, file])), [files]);
186
175
  const [expanded, setExpanded] = useState(() => new Set(defaultPath ? ancestors(defaultPath) : []));
187
176
  const [tabs, setTabs] = useState(defaultPath && byPath.has(defaultPath) ? [defaultPath] : []);
188
177
  const [active, setActive] = useState(tabs[0] ?? null);
189
178
  const [focused, setFocused] = useState(active);
190
179
  const [line, setLine] = useState(null);
191
- const [query, setQuery] = useState("");
180
+ const [query, setQuery] = useState('');
192
181
  const deferred = useDeferredValue(query.trim());
193
182
  const results = useMemo(() => (deferred ? searchFiles(files, deferred) : null), [files, deferred]);
194
183
  const rows = useMemo(() => visibleRows(tree, expanded), [tree, expanded]);
195
184
  const treeRef = useRef(null);
196
185
  const id = useId();
197
- const toggle = (path, open) => setExpanded((current) => {
186
+ const toggle = (path, open) => setExpanded(current => {
198
187
  const next = new Set(current);
199
188
  if (open ?? !next.has(path))
200
189
  next.add(path);
@@ -203,7 +192,7 @@ export function FileExplorer({ files, label = "Files", defaultPath, className, .
203
192
  return next;
204
193
  });
205
194
  const open = (path, at = null) => {
206
- setTabs((current) => {
195
+ setTabs(current => {
207
196
  if (current.includes(path))
208
197
  return current;
209
198
  const next = [...current];
@@ -213,11 +202,11 @@ export function FileExplorer({ files, label = "Files", defaultPath, className, .
213
202
  setActive(path);
214
203
  setFocused(path);
215
204
  setLine(at);
216
- setExpanded((current) => new Set([...current, ...ancestors(path)]));
205
+ setExpanded(current => new Set([...current, ...ancestors(path)]));
217
206
  };
218
207
  const close = (path) => {
219
208
  const index = tabs.indexOf(path);
220
- const next = tabs.filter((tab) => tab !== path);
209
+ const next = tabs.filter(tab => tab !== path);
221
210
  setTabs(next);
222
211
  if (active === path) {
223
212
  setActive(next[Math.min(index, next.length - 1)] ?? null);
@@ -228,47 +217,45 @@ export function FileExplorer({ files, label = "Files", defaultPath, className, .
228
217
  if (!path)
229
218
  return;
230
219
  setFocused(path);
231
- treeRef.current
232
- ?.querySelector(`[data-path="${CSS.escape(path)}"]`)
233
- ?.focus();
220
+ treeRef.current?.querySelector(`[data-path="${CSS.escape(path)}"]`)?.focus();
234
221
  };
235
222
  const onTreeKeyDown = (event) => {
236
- const index = rows.findIndex((row) => row.node.path === focused);
223
+ const index = rows.findIndex(row => row.node.path === focused);
237
224
  const row = rows[index];
238
225
  if (!row)
239
226
  return;
240
227
  const { node } = row;
241
- const isOpen = node.kind === "folder" && expanded.has(node.path);
228
+ const isOpen = node.kind === 'folder' && expanded.has(node.path);
242
229
  switch (event.key) {
243
- case "ArrowDown":
230
+ case 'ArrowDown':
244
231
  focusRow(rows[index + 1]?.node.path);
245
232
  break;
246
- case "ArrowUp":
233
+ case 'ArrowUp':
247
234
  focusRow(rows[index - 1]?.node.path);
248
235
  break;
249
- case "Home":
236
+ case 'Home':
250
237
  focusRow(rows[0]?.node.path);
251
238
  break;
252
- case "End":
239
+ case 'End':
253
240
  focusRow(rows.at(-1)?.node.path);
254
241
  break;
255
- case "ArrowRight":
256
- if (node.kind !== "folder")
242
+ case 'ArrowRight':
243
+ if (node.kind !== 'folder')
257
244
  return;
258
245
  if (isOpen)
259
246
  focusRow(rows[index + 1]?.node.path);
260
247
  else
261
248
  toggle(node.path, true);
262
249
  break;
263
- case "ArrowLeft":
250
+ case 'ArrowLeft':
264
251
  if (isOpen)
265
252
  toggle(node.path, false);
266
253
  else
267
254
  focusRow(folderOf(node.path) || undefined);
268
255
  break;
269
- case "Enter":
270
- case " ":
271
- if (node.kind === "folder")
256
+ case 'Enter':
257
+ case ' ':
258
+ if (node.kind === 'folder')
272
259
  toggle(node.path);
273
260
  else
274
261
  open(node.path);
@@ -280,21 +267,18 @@ export function FileExplorer({ files, label = "Files", defaultPath, className, .
280
267
  };
281
268
  const activeFile = active ? byPath.get(active) : undefined;
282
269
  const language = activeFile ? languageForFilename(activeFile.path) : null;
283
- const rovingPath = focused && rows.some((row) => row.node.path === focused)
284
- ? focused
285
- : rows[0]?.node.path;
286
- return (_jsxs("div", { "data-slot": "file-explorer", ...props, className: cn("sprout-file-explorer", className), children: [_jsxs("aside", { className: "sprout-file-explorer-sidebar", "aria-label": label, children: [_jsxs("div", { className: "sprout-file-explorer-sidebar-header", children: [_jsx("span", { className: "sprout-file-explorer-title", children: label }), _jsx("button", { type: "button", className: "sprout-file-explorer-icon-button", "aria-label": "Collapse all folders", title: "Collapse all folders", disabled: expanded.size === 0, onClick: () => setExpanded(new Set()), children: _jsx(MinusSquare, { size: 14, "aria-hidden": "true" }) })] }), _jsx("div", { className: "sprout-file-explorer-search", children: _jsx(SearchField, { label: `Search ${label.toLowerCase()}`, placeholder: "Search names and text", value: query, maxLength: 120, onChange: setQuery, className: "max-w-none" }) }), results ? (_jsxs("div", { className: "sprout-file-explorer-results", "aria-busy": deferred !== query.trim() || undefined, children: [_jsx("p", { role: "status", className: "sprout-file-explorer-summary", children: results.names.length || results.total
287
- ? `${results.names.length} ${results.names.length === 1 ? "file name" : "file names"}, ${results.capped ? `first ${results.total}` : results.total} ${results.total === 1 ? "line" : "lines"}`
288
- : `No files or lines match “${deferred}”.` }), results.names.length > 0 && (_jsxs("section", { "aria-labelledby": `${id}-names`, children: [_jsx("h3", { id: `${id}-names`, className: "sprout-file-explorer-group", children: "File names" }), _jsx("ul", { className: "sprout-file-explorer-list", children: results.names.map((file) => (_jsx("li", { children: _jsxs("button", { type: "button", className: "sprout-file-explorer-result", "aria-current": file.path === active || undefined, onClick: () => open(file.path), children: [_jsx(FileGlyph, { name: file.path }), _jsx("span", { className: "sprout-file-explorer-name", children: marked([{ content: nameOf(file.path) }], rangesIn(nameOf(file.path), deferred.toLowerCase())) }), _jsx("span", { className: "sprout-file-explorer-dir", children: folderOf(file.path) })] }) }, file.path))) })] })), results.hits.length > 0 && (_jsxs("section", { "aria-labelledby": `${id}-lines`, children: [_jsx("h3", { id: `${id}-lines`, className: "sprout-file-explorer-group", children: "Text in files" }), _jsx("ul", { className: "sprout-file-explorer-list", children: results.hits.map(({ file, lines }) => (_jsxs("li", { children: [_jsxs("button", { type: "button", className: "sprout-file-explorer-result", onClick: () => open(file.path, lines[0].line), children: [_jsx(FileGlyph, { name: file.path }), _jsx("span", { className: "sprout-file-explorer-name", children: nameOf(file.path) }), _jsx("span", { className: "sprout-file-explorer-dir", children: folderOf(file.path) }), _jsx("span", { className: "sprout-file-explorer-count", children: lines.length })] }), _jsx("ul", { className: "sprout-file-explorer-list", children: lines.map((hit) => (_jsx("li", { children: _jsxs("button", { type: "button", className: "sprout-file-explorer-hit", "aria-label": `${file.path}, line ${hit.line}: ${hit.text}`, "aria-current": (file.path === active && hit.line === line) ||
289
- undefined, onClick: () => open(file.path, hit.line), children: [_jsx("span", { className: "sprout-file-explorer-hit-line", children: hit.line }), _jsx("span", { className: "sprout-file-explorer-hit-text", children: marked([{ content: hit.text }], hit.ranges) })] }) }, hit.line))) })] }, file.path))) })] }))] })) : (_jsxs("div", { ref: treeRef, role: "tree", "aria-label": label, className: "sprout-file-explorer-tree", onKeyDown: onTreeKeyDown, children: [rows.length === 0 && (_jsx("p", { className: "sprout-file-explorer-summary", children: "No files yet." })), rows.map(({ node, depth, size, position }) => {
290
- const folder = node.kind === "folder";
270
+ const rovingPath = focused && rows.some(row => row.node.path === focused) ? focused : rows[0]?.node.path;
271
+ return (_jsxs("div", { "data-slot": "file-explorer", ...props, className: cn('sprout-file-explorer', className), children: [_jsxs("aside", { className: "sprout-file-explorer-sidebar", "aria-label": label, children: [_jsxs("div", { className: "sprout-file-explorer-sidebar-header", children: [_jsx("span", { className: "sprout-file-explorer-title", children: label }), _jsx("button", { type: "button", className: "sprout-file-explorer-icon-button", "aria-label": "Collapse all folders", title: "Collapse all folders", disabled: expanded.size === 0, onClick: () => setExpanded(new Set()), children: _jsx(MinusSquare, { size: 14, "aria-hidden": "true" }) })] }), _jsx("div", { className: "sprout-file-explorer-search", children: _jsx(SearchField, { label: `Search ${label.toLowerCase()}`, placeholder: "Search names and text", value: query, maxLength: 120, onChange: setQuery, className: "max-w-none" }) }), results ? (_jsxs("div", { className: "sprout-file-explorer-results", "aria-busy": deferred !== query.trim() || undefined, children: [_jsx("p", { role: "status", className: "sprout-file-explorer-summary", children: results.names.length || results.total
272
+ ? `${results.names.length} ${results.names.length === 1 ? 'file name' : 'file names'}, ${results.capped ? `first ${results.total}` : results.total} ${results.total === 1 ? 'line' : 'lines'}`
273
+ : `No files or lines match “${deferred}”.` }), results.names.length > 0 && (_jsxs("section", { "aria-labelledby": `${id}-names`, children: [_jsx("h3", { id: `${id}-names`, className: "sprout-file-explorer-group", children: "File names" }), _jsx("ul", { className: "sprout-file-explorer-list", children: results.names.map(file => (_jsx("li", { children: _jsxs("button", { type: "button", className: "sprout-file-explorer-result", "aria-current": file.path === active || undefined, onClick: () => open(file.path), children: [_jsx(FileGlyph, { name: file.path }), _jsx("span", { className: "sprout-file-explorer-name", children: marked([{ content: nameOf(file.path) }], rangesIn(nameOf(file.path), deferred.toLowerCase())) }), _jsx("span", { className: "sprout-file-explorer-dir", children: folderOf(file.path) })] }) }, file.path))) })] })), results.hits.length > 0 && (_jsxs("section", { "aria-labelledby": `${id}-lines`, children: [_jsx("h3", { id: `${id}-lines`, className: "sprout-file-explorer-group", children: "Text in files" }), _jsx("ul", { className: "sprout-file-explorer-list", children: results.hits.map(({ file, lines }) => (_jsxs("li", { children: [_jsxs("button", { type: "button", className: "sprout-file-explorer-result", onClick: () => open(file.path, lines[0].line), children: [_jsx(FileGlyph, { name: file.path }), _jsx("span", { className: "sprout-file-explorer-name", children: nameOf(file.path) }), _jsx("span", { className: "sprout-file-explorer-dir", children: folderOf(file.path) }), _jsx("span", { className: "sprout-file-explorer-count", children: lines.length })] }), _jsx("ul", { className: "sprout-file-explorer-list", children: lines.map(hit => (_jsx("li", { children: _jsxs("button", { type: "button", className: "sprout-file-explorer-hit", "aria-label": `${file.path}, line ${hit.line}: ${hit.text}`, "aria-current": (file.path === active && hit.line === line) || undefined, onClick: () => open(file.path, hit.line), children: [_jsx("span", { className: "sprout-file-explorer-hit-line", children: hit.line }), _jsx("span", { className: "sprout-file-explorer-hit-text", children: marked([{ content: hit.text }], hit.ranges) })] }) }, hit.line))) })] }, file.path))) })] }))] })) : (_jsxs("div", { ref: treeRef, role: "tree", "aria-label": label, className: "sprout-file-explorer-tree", onKeyDown: onTreeKeyDown, children: [rows.length === 0 && _jsx("p", { className: "sprout-file-explorer-summary", children: "No files yet." }), rows.map(({ node, depth, size, position }) => {
274
+ const folder = node.kind === 'folder';
291
275
  const isOpen = folder && expanded.has(node.path);
292
- return (_jsxs("div", { role: "treeitem", "data-path": node.path, "data-kind": node.kind, "aria-level": depth + 1, "aria-setsize": size, "aria-posinset": position, "aria-expanded": folder ? isOpen : undefined, "aria-selected": folder ? undefined : node.path === active, tabIndex: node.path === rovingPath ? 0 : -1, className: "sprout-file-explorer-row", style: { "--depth": depth }, onFocus: () => setFocused(node.path), onClick: () => (folder ? toggle(node.path) : open(node.path)), children: [Array.from({ length: depth }, (_, at) => (_jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-guide" }, at))), _jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-chevron", children: folder && _jsx(ChevronRight, { size: 12 }) }), folder ? (isOpen ? (_jsx(FolderOpen, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-folder" })) : (_jsx(Folder, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-folder" }))) : (_jsx(FileGlyph, { name: node.name })), _jsx("span", { className: "sprout-file-explorer-name", title: node.path, children: node.name })] }, node.path));
293
- })] }))] }), _jsxs("section", { className: "sprout-file-explorer-editor", "aria-label": "Editor", children: [tabs.length > 0 && (_jsx("div", { className: "sprout-file-explorer-tabs", "aria-label": "Open files", children: tabs.map((path) => (_jsxs("div", { className: "sprout-file-explorer-tab", "data-active": path === active ? "" : undefined, children: [_jsxs("button", { type: "button", className: "sprout-file-explorer-tab-open", "aria-current": path === active || undefined, title: path, onClick: () => {
276
+ return (_jsxs("div", { role: "treeitem", "data-path": node.path, "data-kind": node.kind, "aria-level": depth + 1, "aria-setsize": size, "aria-posinset": position, "aria-expanded": folder ? isOpen : undefined, "aria-selected": folder ? undefined : node.path === active, tabIndex: node.path === rovingPath ? 0 : -1, className: "sprout-file-explorer-row", style: { '--depth': depth }, onFocus: () => setFocused(node.path), onClick: () => (folder ? toggle(node.path) : open(node.path)), children: [Array.from({ length: depth }, (_, at) => (_jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-guide" }, at))), _jsx("span", { "aria-hidden": "true", className: "sprout-file-explorer-chevron", children: folder && _jsx(ChevronRight, { size: 12 }) }), folder ? (isOpen ? (_jsx(FolderOpen, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-folder" })) : (_jsx(Folder, { size: 16, "aria-hidden": "true", className: "sprout-file-explorer-folder" }))) : (_jsx(FileGlyph, { name: node.name })), _jsx("span", { className: "sprout-file-explorer-name", title: node.path, children: node.name })] }, node.path));
277
+ })] }))] }), _jsxs("section", { className: "sprout-file-explorer-editor", "aria-label": "Editor", children: [tabs.length > 0 && (_jsx("div", { className: "sprout-file-explorer-tabs", "aria-label": "Open files", children: tabs.map(path => (_jsxs("div", { className: "sprout-file-explorer-tab", "data-active": path === active ? '' : undefined, children: [_jsxs("button", { type: "button", className: "sprout-file-explorer-tab-open", "aria-current": path === active || undefined, title: path, onClick: () => {
294
278
  setActive(path);
295
279
  setLine(null);
296
- }, onAuxClick: (event) => {
280
+ }, onAuxClick: event => {
297
281
  if (event.button === 1)
298
282
  close(path);
299
- }, children: [_jsx(FileGlyph, { name: path }), nameOf(path)] }), _jsx("button", { type: "button", className: "sprout-file-explorer-tab-close", "aria-label": `Close ${nameOf(path)}`, onClick: () => close(path), children: _jsx(X, { size: 12, "aria-hidden": "true" }) })] }, path))) })), activeFile ? (_jsxs(_Fragment, { children: [_jsx("nav", { className: "sprout-file-explorer-crumbs", "aria-label": "File path", children: _jsx("ol", { children: activeFile.path.split("/").map((part, index, parts) => (_jsxs("li", { "aria-current": index === parts.length - 1 ? "page" : undefined, children: [index > 0 && (_jsx(ChevronRight, { size: 10, "aria-hidden": "true", className: "sprout-file-explorer-crumb-separator" })), part] }, index))) }) }), _jsx("div", { className: "sprout-file-explorer-body", children: "content" in activeFile ? (activeFile.content === "" ? (_jsx("p", { className: "sprout-file-explorer-summary", children: "This file is empty." })) : (_jsx(CodeView, { file: activeFile, query: results ? deferred : "", line: line }, activeFile.path))) : (_jsx(StatePanel, { kind: "unavailable", heading: "h3", title: "File cannot be displayed", description: activeFile.unavailable })) }), _jsxs("div", { className: "sprout-file-explorer-status", children: [_jsx("span", { children: language ? codeLanguageNames[language] : "Plain text" }), "content" in activeFile && (_jsxs("span", { children: [activeFile.content.split("\n").length.toLocaleString(), " lines"] })), line !== null && _jsxs("span", { children: ["Line ", line] }), _jsx("span", { className: "sprout-file-explorer-status-end", children: "Read only" })] })] })) : (_jsx(StatePanel, { kind: "empty", heading: "h3", title: "Open a file", description: "Choose a file in the tree, or search names and text.", icon: FileText }))] })] }));
283
+ }, children: [_jsx(FileGlyph, { name: path }), nameOf(path)] }), _jsx("button", { type: "button", className: "sprout-file-explorer-tab-close", "aria-label": `Close ${nameOf(path)}`, onClick: () => close(path), children: _jsx(X, { size: 12, "aria-hidden": "true" }) })] }, path))) })), activeFile ? (_jsxs(_Fragment, { children: [_jsx("nav", { className: "sprout-file-explorer-crumbs", "aria-label": "File path", children: _jsx("ol", { children: activeFile.path.split('/').map((part, index, parts) => (_jsxs("li", { "aria-current": index === parts.length - 1 ? 'page' : undefined, children: [index > 0 && (_jsx(ChevronRight, { size: 10, "aria-hidden": "true", className: "sprout-file-explorer-crumb-separator" })), part] }, index))) }) }), _jsx("div", { className: "sprout-file-explorer-body", children: 'content' in activeFile ? (activeFile.content === '' ? (_jsx("p", { className: "sprout-file-explorer-summary", children: "This file is empty." })) : (_jsx(CodeView, { file: activeFile, query: results ? deferred : '', line: line }, activeFile.path))) : (_jsx(StatePanel, { kind: "unavailable", heading: "h3", title: "File cannot be displayed", description: activeFile.unavailable })) }), _jsxs("div", { className: "sprout-file-explorer-status", children: [_jsx("span", { children: language ? codeLanguageNames[language] : 'Plain text' }), 'content' in activeFile && _jsxs("span", { children: [activeFile.content.split('\n').length.toLocaleString(), " lines"] }), line !== null && _jsxs("span", { children: ["Line ", line] }), _jsx("span", { className: "sprout-file-explorer-status-end", children: "Read only" })] })] })) : (_jsx(StatePanel, { kind: "empty", heading: "h3", title: "Open a file", description: "Choose a file in the tree, or search names and text.", icon: FileText }))] })] }));
300
284
  }
@@ -1,11 +1,11 @@
1
- import { type HTMLAttributes, type ReactNode } from "react";
2
- import { type FileKind } from "../internal/file-kind.js";
3
- import { type DialogContentProps } from "./dialog.js";
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type FileKind } from '../internal/file-kind.js';
3
+ import { type DialogContentProps } from './dialog.js';
4
4
  export type ViewableFileSource = {
5
- kind: "local";
5
+ kind: 'local';
6
6
  file: File;
7
7
  } | {
8
- kind: "remote";
8
+ kind: 'remote';
9
9
  url: string;
10
10
  };
11
11
  export interface ViewableFile {
@@ -20,7 +20,7 @@ export interface FileSheetRendererProps {
20
20
  onRetry: () => void;
21
21
  }
22
22
  export interface FileOfficeRendererProps extends FileSheetRendererProps {
23
- kind: "document" | "slides";
23
+ kind: 'document' | 'slides';
24
24
  }
25
25
  export interface FileMarkdownRendererProps {
26
26
  text: string;
@@ -41,7 +41,7 @@ export interface FileRenderersProviderProps {
41
41
  children?: ReactNode;
42
42
  }
43
43
  /** Registers file renderers once for every viewer below it. */
44
- export declare function FileRenderersProvider({ renderers, children, }: FileRenderersProviderProps): import("react").JSX.Element;
44
+ export declare function FileRenderersProvider({ renderers, children }: FileRenderersProviderProps): import("react").JSX.Element;
45
45
  export declare const maxViewableFileBytes: number;
46
46
  export declare function viewableFileKind(name: string, mediaType: string): ViewableFileKind;
47
47
  export interface GoogleDocumentLink {
@@ -64,7 +64,7 @@ interface FileViewerBaseProps {
64
64
  onOpenChange: (open: boolean) => void;
65
65
  renderers?: FileRenderers | undefined;
66
66
  /** Where focus goes on close. Defaults to the element that had focus when the viewer opened. */
67
- finalFocus?: DialogContentProps["finalFocus"];
67
+ finalFocus?: DialogContentProps['finalFocus'];
68
68
  /** Your header controls before Download, such as who is viewing and a Share button. */
69
69
  actions?: ReactNode;
70
70
  /** `DropdownMenuItem`s added to the More actions menu after Reload. */
@@ -115,10 +115,10 @@ export interface FileContentProps {
115
115
  renderers?: FileRenderers | undefined;
116
116
  }
117
117
  /** Shows bytes you already loaded: images, PDF, text, JSON, Markdown, Google shortcuts, and more. */
118
- export declare function FileContent({ name, mediaType, bytes, url, onRetry, renderers: own, }: FileContentProps): import("react").JSX.Element;
118
+ export declare function FileContent({ name, mediaType, bytes, url, onRetry, renderers: own }: FileContentProps): import("react").JSX.Element;
119
119
  export type LoadingFileProps = HTMLAttributes<HTMLDivElement>;
120
120
  export declare function LoadingFile({ className, ...props }: LoadingFileProps): import("react").JSX.Element;
121
- export interface FileErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
121
+ export interface FileErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
122
122
  message: ReactNode;
123
123
  onRetry: () => void;
124
124
  }