@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,63 +1,45 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
4
- import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from "@dnd-kit/core";
5
- import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
6
- import { CSS } from "@dnd-kit/utilities";
7
- import { aggregationFn_count, aggregationFn_max, aggregationFn_mean, aggregationFn_min, aggregationFn_sum, columnFilteringFeature, columnGroupingFeature, columnOrderingFeature, columnPinningFeature, columnResizingFeature, columnSizingFeature, columnVisibilityFeature, constructFilterFn, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_equals, filterFn_inDateRange, filterFn_inNumberRange, filterFn_includesString, functionalUpdate, globalFilteringFeature, rowAggregationFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from "@tanstack/react-table";
8
- import { useVirtualizer } from "@tanstack/react-virtual";
9
- import { ArrowDown } from "reicon-react/icons/ArrowDown";
10
- import { ArrowUp } from "reicon-react/icons/ArrowUp";
11
- import { ChevronDown } from "reicon-react/icons/ChevronDown";
12
- import { ChevronRight } from "reicon-react/icons/ChevronRight";
13
- import { InfoCircle } from "reicon-react/icons/InfoCircle";
14
- import { Plus } from "reicon-react/icons/Plus";
15
- import { Reorder } from "reicon-react/icons/Reorder";
16
- import { SortV } from "reicon-react/icons/SortV";
17
- import { X } from "reicon-react/icons/X";
18
- import { cn } from "../internal/classes.js";
19
- import { Button } from "./button.js";
20
- import { Checkbox } from "./checkbox.js";
21
- import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./dropdown-menu.js";
22
- import { Input } from "./input.js";
23
- import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
24
- import { ScrollArea } from "./scroll-area.js";
25
- import { SearchField } from "./search-field.js";
26
- import { Skeleton } from "./skeleton.js";
27
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./tooltip.js";
28
- export const tableVariantNames = ["plain", "grid"];
29
- export const tableNarrowNames = ["scroll", "stack"];
30
- export const tableAlignNames = ["left", "right"];
31
- export const tableFilterNames = [
32
- "text",
33
- "number",
34
- "select",
35
- "date",
36
- "boolean",
37
- ];
38
- export const tableEditNames = [
39
- "text",
40
- "number",
41
- "select",
42
- "date",
43
- "checkbox",
44
- ];
45
- export const tableAggregateNames = [
46
- "sum",
47
- "count",
48
- "min",
49
- "max",
50
- "mean",
51
- ];
3
+ import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
4
+ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from '@dnd-kit/core';
5
+ import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
6
+ import { CSS } from '@dnd-kit/utilities';
7
+ import { aggregationFn_count, aggregationFn_max, aggregationFn_mean, aggregationFn_min, aggregationFn_sum, columnFilteringFeature, columnGroupingFeature, columnOrderingFeature, columnPinningFeature, columnResizingFeature, columnSizingFeature, columnVisibilityFeature, constructFilterFn, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_equals, filterFn_inDateRange, filterFn_inNumberRange, filterFn_includesString, functionalUpdate, globalFilteringFeature, rowAggregationFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from '@tanstack/react-table';
8
+ import { useVirtualizer } from '@tanstack/react-virtual';
9
+ import { ArrowDown } from 'reicon-react/icons/ArrowDown';
10
+ import { ArrowUp } from 'reicon-react/icons/ArrowUp';
11
+ import { ChevronDown } from 'reicon-react/icons/ChevronDown';
12
+ import { ChevronRight } from 'reicon-react/icons/ChevronRight';
13
+ import { InfoCircle } from 'reicon-react/icons/InfoCircle';
14
+ import { Plus } from 'reicon-react/icons/Plus';
15
+ import { Reorder } from 'reicon-react/icons/Reorder';
16
+ import { SortV } from 'reicon-react/icons/SortV';
17
+ import { X } from 'reicon-react/icons/X';
18
+ import { cn } from '../internal/classes.js';
19
+ import { Button } from './button.js';
20
+ import { Checkbox } from './checkbox.js';
21
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from './dropdown-menu.js';
22
+ import { Input } from './input.js';
23
+ import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
24
+ import { ScrollArea } from './scroll-area.js';
25
+ import { SearchField } from './search-field.js';
26
+ import { Skeleton } from './skeleton.js';
27
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip.js';
28
+ export const tableVariantNames = ['plain', 'grid'];
29
+ export const tableNarrowNames = ['scroll', 'stack'];
30
+ export const tableAlignNames = ['left', 'right'];
31
+ export const tableFilterNames = ['text', 'number', 'select', 'date', 'boolean'];
32
+ export const tableEditNames = ['text', 'number', 'select', 'date', 'checkbox'];
33
+ export const tableAggregateNames = ['sum', 'count', 'min', 'max', 'mean'];
52
34
  export const tableLayoutKeys = [
53
- "columnSizing",
54
- "columnOrder",
55
- "columnPinning",
56
- "columnVisibility",
35
+ 'columnSizing',
36
+ 'columnOrder',
37
+ 'columnPinning',
38
+ 'columnVisibility',
57
39
  ];
58
40
  // dnd-kit's live region is a div; inside <table> it breaks the table roles.
59
41
  const dndAccessibility = {
60
- container: typeof document === "undefined" ? undefined : document.body,
42
+ container: typeof document === 'undefined' ? undefined : document.body,
61
43
  };
62
44
  const isAnyOf = constructFilterFn({
63
45
  filter: (dataValue, filterValue) => filterValue.includes(String(dataValue)),
@@ -104,34 +86,29 @@ const features = tableFeatures({
104
86
  },
105
87
  });
106
88
  const filterFnFor = {
107
- text: "includesString",
108
- number: "inNumberRange",
109
- select: "isAnyOf",
110
- date: "inDateRange",
111
- boolean: "equals",
89
+ text: 'includesString',
90
+ number: 'inNumberRange',
91
+ select: 'isAnyOf',
92
+ date: 'inDateRange',
93
+ boolean: 'equals',
112
94
  };
113
95
  const DEFAULT_PAGE_SIZE = 10;
114
- const pageResetKeys = new Set([
115
- "sorting",
116
- "columnFilters",
117
- "globalFilter",
118
- "grouping",
119
- ]);
96
+ const pageResetKeys = new Set(['sorting', 'columnFilters', 'globalFilter', 'grouping']);
120
97
  function initialState(columns, pageSize) {
121
98
  return {
122
99
  sorting: [],
123
100
  columnFilters: [],
124
- globalFilter: "",
101
+ globalFilter: '',
125
102
  grouping: [],
126
103
  expanded: true,
127
104
  pagination: { pageIndex: 0, pageSize: pageSize ?? DEFAULT_PAGE_SIZE },
128
105
  columnSizing: {},
129
106
  columnOrder: [],
130
107
  columnPinning: {
131
- start: columns.filter((c) => c.pin === "left").map((c) => c.key),
132
- end: columns.filter((c) => c.pin === "right").map((c) => c.key),
108
+ start: columns.filter(c => c.pin === 'left').map(c => c.key),
109
+ end: columns.filter(c => c.pin === 'right').map(c => c.key),
133
110
  },
134
- columnVisibility: Object.fromEntries(columns.filter((c) => c.hidden).map((c) => [c.key, false])),
111
+ columnVisibility: Object.fromEntries(columns.filter(c => c.hidden).map(c => [c.key, false])),
135
112
  };
136
113
  }
137
114
  const storageKey = (key) => `sprout-table:${key}`;
@@ -146,7 +123,7 @@ function readLayout(key) {
146
123
  }
147
124
  function writeLayout(key, state) {
148
125
  try {
149
- localStorage.setItem(storageKey(key), JSON.stringify(Object.fromEntries(tableLayoutKeys.map((k) => [k, state[k]]))));
126
+ localStorage.setItem(storageKey(key), JSON.stringify(Object.fromEntries(tableLayoutKeys.map(k => [k, state[k]]))));
150
127
  }
151
128
  catch {
152
129
  // Storage can be full or blocked; the Layout then lasts for this visit only.
@@ -158,8 +135,8 @@ function writeLayout(key, state) {
158
135
  * paging, Row edit, and Layout changes for you.
159
136
  */
160
137
  export function Table(props) {
161
- const { data, columns, getRowId, rowLabel = getRowId, variant = "plain", narrow = "scroll", caption, manual = false, rowCount, onStateChange, persistKey, searchable = false, columnMenu = false, resizable = false, reorderable = false, selectable = false, onSelectionChange, pageSize, virtual = false, onRowReorder, getSubRows, onRowSave, getRowHref, onRowClick, onRowDrop, actions, loading = false, empty, className, } = props;
162
- const label = props["aria-label"];
138
+ const { data, columns, getRowId, rowLabel = getRowId, variant = 'plain', narrow = 'scroll', caption, manual = false, rowCount, onStateChange, persistKey, searchable = false, columnMenu = false, resizable = false, reorderable = false, selectable = false, onSelectionChange, pageSize, virtual = false, onRowReorder, getSubRows, onRowSave, getRowHref, onRowClick, onRowDrop, actions, loading = false, empty, className, } = props;
139
+ const label = props['aria-label'];
163
140
  const [inner, setInner] = useState(() => initialState(columns, pageSize));
164
141
  const state = { ...inner, ...props.state };
165
142
  const stateRef = useRef(state);
@@ -175,7 +152,7 @@ export function Table(props) {
175
152
  return;
176
153
  const saved = readLayout(persistKey);
177
154
  if (Object.keys(saved).length)
178
- setInner((prev) => ({ ...prev, ...saved }));
155
+ setInner(prev => ({ ...prev, ...saved }));
179
156
  }, [persistKey]);
180
157
  const setSlice = (key) => (updater) => {
181
158
  const next = {
@@ -192,10 +169,10 @@ export function Table(props) {
192
169
  }
193
170
  onStateChange?.(next);
194
171
  };
195
- const byKey = useMemo(() => new Map(columns.map((c) => [c.key, c])), [columns]);
172
+ const byKey = useMemo(() => new Map(columns.map(c => [c.key, c])), [columns]);
196
173
  const columnDefs = useMemo(() => columns.map((c) => ({
197
174
  id: c.key,
198
- accessorFn: (row) => row[c.key],
175
+ accessorFn: row => row[c.key],
199
176
  header: c.header,
200
177
  enableSorting: c.sort ?? false,
201
178
  sortDescFirst: false,
@@ -212,28 +189,28 @@ export function Table(props) {
212
189
  getRowId,
213
190
  ...(getSubRows ? { getSubRows } : {}),
214
191
  state: { ...state, rowSelection },
215
- onSortingChange: setSlice("sorting"),
216
- onColumnFiltersChange: setSlice("columnFilters"),
217
- onGlobalFilterChange: setSlice("globalFilter"),
218
- onGroupingChange: setSlice("grouping"),
219
- onExpandedChange: setSlice("expanded"),
220
- onPaginationChange: setSlice("pagination"),
221
- onColumnSizingChange: setSlice("columnSizing"),
222
- onColumnOrderChange: setSlice("columnOrder"),
223
- onColumnPinningChange: setSlice("columnPinning"),
224
- onColumnVisibilityChange: setSlice("columnVisibility"),
225
- onRowSelectionChange: (updater) => {
192
+ onSortingChange: setSlice('sorting'),
193
+ onColumnFiltersChange: setSlice('columnFilters'),
194
+ onGlobalFilterChange: setSlice('globalFilter'),
195
+ onGroupingChange: setSlice('grouping'),
196
+ onExpandedChange: setSlice('expanded'),
197
+ onPaginationChange: setSlice('pagination'),
198
+ onColumnSizingChange: setSlice('columnSizing'),
199
+ onColumnOrderChange: setSlice('columnOrder'),
200
+ onColumnPinningChange: setSlice('columnPinning'),
201
+ onColumnVisibilityChange: setSlice('columnVisibility'),
202
+ onRowSelectionChange: updater => {
226
203
  const next = functionalUpdate(updater, rowSelection);
227
204
  setRowSelection(next);
228
- onSelectionChange?.(Object.keys(next).filter((id) => next[id]));
205
+ onSelectionChange?.(Object.keys(next).filter(id => next[id]));
229
206
  },
230
- globalFilterFn: "includesString",
231
- groupedColumnMode: "remove",
207
+ globalFilterFn: 'includesString',
208
+ groupedColumnMode: 'remove',
232
209
  // The reset would use TanStack's empty default, closing every group on each search.
233
210
  autoResetExpanded: false,
234
211
  // TanStack resets on every new state array (inline or URL state) and never in manual mode; setSlice resets instead.
235
212
  autoResetPageIndex: false,
236
- columnResizeMode: "onChange",
213
+ columnResizeMode: 'onChange',
237
214
  enableMultiSort: true,
238
215
  manualSorting: manual,
239
216
  manualFiltering: manual,
@@ -247,43 +224,38 @@ export function Table(props) {
247
224
  ...table.getCenterVisibleLeafColumns(),
248
225
  ...table.getEndVisibleLeafColumns(),
249
226
  ];
250
- const editable = !!onRowSave && columns.some((c) => c.edit);
227
+ const editable = !!onRowSave && columns.some(c => c.edit);
251
228
  const hasActions = !!actions || editable;
252
229
  const draggableRows = !!onRowReorder &&
253
230
  state.sorting.length === 0 &&
254
231
  state.grouping.length === 0 &&
255
232
  state.columnFilters.length === 0 &&
256
233
  !state.globalFilter;
257
- const totals = columns.some((c) => c.aggregate) && !loading && rows.length > 0;
258
- const colSpan = leafColumns.length +
259
- (selectable ? 1 : 0) +
260
- (onRowReorder ? 1 : 0) +
261
- (hasActions ? 1 : 0);
262
- const sized = resizable || columns.some((c) => c.width);
234
+ const totals = columns.some(c => c.aggregate) && !loading && rows.length > 0;
235
+ const colSpan = leafColumns.length + (selectable ? 1 : 0) + (onRowReorder ? 1 : 0) + (hasActions ? 1 : 0);
236
+ const sized = resizable || columns.some(c => c.width);
263
237
  const pinsStart = !!state.columnPinning.start?.length;
264
238
  const pinned = pinsStart || !!state.columnPinning.end?.length;
265
- const pinLayout = `${leafColumns.map((c) => `${c.id}:${c.getIsPinned()}`).join()}|${selectable}|${!!onRowReorder}|${hasActions}`;
239
+ const pinLayout = `${leafColumns.map(c => `${c.id}:${c.getIsPinned()}`).join()}|${selectable}|${!!onRowReorder}|${hasActions}`;
266
240
  useLayoutEffect(() => {
267
241
  const row = headRowRef.current;
268
242
  if (!pinned || !row)
269
243
  return;
270
244
  const observer = new ResizeObserver(() => {
271
245
  const next = measurePinOffsets(Array.from(row.children));
272
- setPinOffsets((prev) => JSON.stringify(prev) === JSON.stringify(next) ? prev : next);
246
+ setPinOffsets(prev => (JSON.stringify(prev) === JSON.stringify(next) ? prev : next));
273
247
  });
274
248
  for (const cell of row.children)
275
249
  observer.observe(cell);
276
250
  return () => observer.disconnect();
277
251
  }, [pinned, pinLayout]);
278
252
  const selectRow = (row, checked, range) => {
279
- const ids = rows
280
- .filter((r) => !r.getIsGrouped() && r.getCanSelect())
281
- .map((r) => r.id);
253
+ const ids = rows.filter(r => !r.getIsGrouped() && r.getCanSelect()).map(r => r.id);
282
254
  const from = anchorRef.current ? ids.indexOf(anchorRef.current) : -1;
283
255
  const to = ids.indexOf(row.id);
284
256
  if (range && from !== -1 && to !== -1) {
285
257
  const span = ids.slice(Math.min(from, to), Math.max(from, to) + 1);
286
- table.setRowSelection((prev) => {
258
+ table.setRowSelection(prev => {
287
259
  const next = { ...prev };
288
260
  for (const id of span) {
289
261
  if (checked)
@@ -311,16 +283,12 @@ export function Table(props) {
311
283
  initialRect: { width: 0, height: 600 },
312
284
  });
313
285
  const virtualItems = virtualizer.getVirtualItems();
314
- const visibleRows = virtual
315
- ? virtualItems.flatMap((item) => rows[item.index] ?? [])
316
- : rows;
286
+ const visibleRows = virtual ? virtualItems.flatMap(item => rows[item.index] ?? []) : rows;
317
287
  const paddingTop = virtual ? (virtualItems[0]?.start ?? 0) : 0;
318
- const paddingBottom = virtual
319
- ? virtualizer.getTotalSize() - (virtualItems.at(-1)?.end ?? 0)
320
- : 0;
288
+ const paddingBottom = virtual ? virtualizer.getTotalSize() - (virtualItems.at(-1)?.end ?? 0) : 0;
321
289
  const startEdit = (row) => setEditing({
322
290
  id: row.id,
323
- draft: Object.fromEntries(columns.filter((c) => c.edit).map((c) => [c.key, row.original[c.key]])),
291
+ draft: Object.fromEntries(columns.filter(c => c.edit).map(c => [c.key, row.original[c.key]])),
324
292
  });
325
293
  const saveEdit = async (row) => {
326
294
  if (!editing || !onRowSave)
@@ -342,9 +310,7 @@ export function Table(props) {
342
310
  const onColumnDragEnd = ({ active, over }) => {
343
311
  if (!over || active.id === over.id)
344
312
  return;
345
- const order = state.columnOrder.length
346
- ? state.columnOrder
347
- : table.getAllLeafColumns().map((c) => c.id);
313
+ const order = state.columnOrder.length ? state.columnOrder : table.getAllLeafColumns().map(c => c.id);
348
314
  table.setColumnOrder(arrayMove(order, order.indexOf(String(active.id)), order.indexOf(String(over.id))));
349
315
  };
350
316
  const onRowDragEnd = ({ active, over }) => {
@@ -353,44 +319,38 @@ export function Table(props) {
353
319
  const ids = data.map(getRowId);
354
320
  onRowReorder(ids.indexOf(String(active.id)), ids.indexOf(String(over.id)));
355
321
  };
356
- const toolbar = searchable || columns.some((c) => c.filter || c.group) || columnMenu;
322
+ const toolbar = searchable || columns.some(c => c.filter || c.group) || columnMenu;
357
323
  const allPageSelected = table.getIsAllPageRowsSelected();
358
324
  const somePageSelected = table.getIsSomePageRowsSelected();
359
- const stack = narrow === "stack";
325
+ const stack = narrow === 'stack';
360
326
  const role = (value) => (stack ? value : undefined);
361
- const header = (_jsx("thead", { "data-slot": "table-header", className: "sprout-table-header", role: role("rowgroup"), children: _jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onColumnDragEnd, children: _jsx(SortableContext, { items: leafColumns.map((c) => c.id), strategy: horizontalListSortingStrategy, children: _jsxs("tr", { ref: headRowRef, "data-slot": "table-row", className: "sprout-table-row", role: role("row"), children: [onRowReorder && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__reorder", role: role("columnheader"), children: _jsx("span", { className: "sprout-table-sr-only", children: "Reorder" }) })), selectable && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__select", role: role("columnheader"), children: _jsx(Checkbox, { "aria-label": "Select all rows", checked: allPageSelected, indeterminate: !allPageSelected && somePageSelected, onCheckedChange: (checked) => table.toggleAllPageRowsSelected(checked) }) })), table
327
+ const header = (_jsx("thead", { "data-slot": "table-header", className: "sprout-table-header", role: role('rowgroup'), children: _jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onColumnDragEnd, children: _jsx(SortableContext, { items: leafColumns.map(c => c.id), strategy: horizontalListSortingStrategy, children: _jsxs("tr", { ref: headRowRef, "data-slot": "table-row", className: "sprout-table-row", role: role('row'), children: [onRowReorder && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__reorder", role: role('columnheader'), children: _jsx("span", { className: "sprout-table-sr-only", children: "Reorder" }) })), selectable && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__select", role: role('columnheader'), children: _jsx(Checkbox, { "aria-label": "Select all rows", checked: allPageSelected, indeterminate: !allPageSelected && somePageSelected, onCheckedChange: checked => table.toggleAllPageRowsSelected(checked) }) })), table
362
328
  .getFlatHeaders()
363
- .map((h) => h.column.getIsVisible() ? (_jsx(HeadCell, { header: h, config: byKey.get(h.column.id), resizable: resizable, reorderable: reorderable, sized: sized, role: role("columnheader") }, h.id)) : null), hasActions && (_jsx("th", { className: "sprout-table-head", "data-sticky-end": "", "data-column-id": "__actions", role: role("columnheader"), children: _jsx("span", { className: "sprout-table-sr-only", children: "Actions" }) }))] }) }) }) }));
364
- const body = (_jsxs("tbody", { "data-slot": "table-body", className: "sprout-table-body", role: role("rowgroup"), children: [paddingTop > 0 && (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: colSpan, style: { height: paddingTop, padding: 0 } }) })), loading ? (Array.from({ length: 3 }, (_, i) => (_jsxs("tr", { className: "sprout-table-row", "data-loading-row": "", role: role("row"), children: [onRowReorder && (_jsx("td", { className: "sprout-table-cell", "data-selection": "" })), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", children: _jsx(Skeleton, { shape: "checkbox" }) })), leafColumns.map((c) => (_jsx("td", { className: "sprout-table-cell", role: role("cell"), children: _jsx(Skeleton, {}) }, c.id))), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", children: _jsx(Skeleton, { shape: "action" }) }))] }, i)))) : rows.length === 0 ? (_jsx("tr", { className: "sprout-table-row", role: role("row"), children: _jsx("td", { className: "sprout-table-cell sprout-table-empty", colSpan: colSpan, role: role("cell"), children: empty ?? "No results." }) })) : (_jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onRowDragEnd, children: _jsx(SortableContext, { items: rows.map((r) => r.id), strategy: verticalListSortingStrategy, children: visibleRows.map((row) => row.getIsGrouped() ? (_jsx(GroupRow, { row: row, columns: leafColumns, byKey: byKey, selectable: selectable, reorder: !!onRowReorder, hasActions: hasActions, rowIndex: virtual ? row.index + 2 : undefined, role: role }, row.id)) : (_jsx(BodyRow, { row: row, columns: leafColumns, byKey: byKey, label: rowLabel(row.original), selectable: selectable, onSelect: (checked, range) => selectRow(row, checked, range), reorder: onRowReorder ? draggableRows : undefined, editing: editing?.id === row.id ? editing : null, editable: editable, onEditChange: (key, value) => setEditing((prev) => prev && {
329
+ .map(h => h.column.getIsVisible() ? (_jsx(HeadCell, { header: h, config: byKey.get(h.column.id), resizable: resizable, reorderable: reorderable, sized: sized, role: role('columnheader') }, h.id)) : null), hasActions && (_jsx("th", { className: "sprout-table-head", "data-sticky-end": "", "data-column-id": "__actions", role: role('columnheader'), children: _jsx("span", { className: "sprout-table-sr-only", children: "Actions" }) }))] }) }) }) }));
330
+ const body = (_jsxs("tbody", { "data-slot": "table-body", className: "sprout-table-body", role: role('rowgroup'), children: [paddingTop > 0 && (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: colSpan, style: { height: paddingTop, padding: 0 } }) })), loading ? (Array.from({ length: 3 }, (_, i) => (_jsxs("tr", { className: "sprout-table-row", "data-loading-row": "", role: role('row'), children: [onRowReorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", children: _jsx(Skeleton, { shape: "checkbox" }) })), leafColumns.map(c => (_jsx("td", { className: "sprout-table-cell", role: role('cell'), children: _jsx(Skeleton, {}) }, c.id))), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", children: _jsx(Skeleton, { shape: "action" }) }))] }, i)))) : rows.length === 0 ? (_jsx("tr", { className: "sprout-table-row", role: role('row'), children: _jsx("td", { className: "sprout-table-cell sprout-table-empty", colSpan: colSpan, role: role('cell'), children: empty ?? 'No results.' }) })) : (_jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onRowDragEnd, children: _jsx(SortableContext, { items: rows.map(r => r.id), strategy: verticalListSortingStrategy, children: visibleRows.map(row => row.getIsGrouped() ? (_jsx(GroupRow, { row: row, columns: leafColumns, byKey: byKey, selectable: selectable, reorder: !!onRowReorder, hasActions: hasActions, rowIndex: virtual ? row.index + 2 : undefined, role: role }, row.id)) : (_jsx(BodyRow, { row: row, columns: leafColumns, byKey: byKey, label: rowLabel(row.original), selectable: selectable, onSelect: (checked, range) => selectRow(row, checked, range), reorder: onRowReorder ? draggableRows : undefined, editing: editing?.id === row.id ? editing : null, editable: editable, onEditChange: (key, value) => setEditing(prev => prev && {
365
331
  ...prev,
366
332
  draft: { ...prev.draft, [key]: value },
367
333
  }), onEdit: () => startEdit(row), onSave: () => void saveEdit(row), onCancel: () => setEditing(null), actions: actions, hasActions: hasActions, href: getRowHref?.(row.original), onOpen: onRowClick ? () => onRowClick(row.original) : undefined, drop: onRowDrop
368
334
  ? {
369
335
  active: dropTarget === row.id,
370
- set: (on) => setDropTarget(on ? row.id : null),
371
- onDrop: (files) => onRowDrop(row.original, files),
336
+ set: on => setDropTarget(on ? row.id : null),
337
+ onDrop: files => onRowDrop(row.original, files),
372
338
  }
373
339
  : undefined, colSpan: colSpan, rowIndex: virtual ? row.index + 2 : undefined, role: role }, row.id))) }) })), paddingBottom > 0 && (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: colSpan, style: { height: paddingBottom, padding: 0 } }) }))] }));
374
- const footer = totals && (_jsx("tfoot", { "data-slot": "table-footer", className: "sprout-table-footer", role: role("rowgroup"), children: _jsxs("tr", { className: "sprout-table-row", role: role("row"), children: [onRowReorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), leafColumns.map((c, index) => {
340
+ const footer = totals && (_jsx("tfoot", { "data-slot": "table-footer", className: "sprout-table-footer", role: role('rowgroup'), children: _jsxs("tr", { className: "sprout-table-row", role: role('row'), children: [onRowReorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), leafColumns.map((c, index) => {
375
341
  const config = byKey.get(c.id);
376
- return (_jsx("td", { className: "sprout-table-cell", "data-align": config?.align ?? "left", "data-label": config?.header, role: role("cell"), style: pinStyle(c, sized, pinOffsets), "data-pinned": c.getIsPinned() || undefined, children: config?.aggregate
377
- ? formatAggregate(config, c.getAggregationValue())
378
- : index === 0
379
- ? "Total"
380
- : null }, c.id));
342
+ return (_jsx("td", { className: "sprout-table-cell", "data-align": config?.align ?? 'left', "data-label": config?.header, role: role('cell'), style: pinStyle(c, sized, pinOffsets), "data-pinned": c.getIsPinned() || undefined, children: config?.aggregate ? formatAggregate(config, c.getAggregationValue()) : index === 0 ? 'Total' : null }, c.id));
381
343
  }), hasActions && _jsx("td", { className: "sprout-table-cell", "data-sticky-end": "" })] }) }));
382
- const tableElement = (_jsxs("table", { "data-slot": "table", "data-variant": variant, "data-narrow": narrow, "data-sized": sized || undefined, "data-pin-start": pinsStart || undefined, className: "sprout-table", "aria-label": label, "aria-rowcount": virtual ? rows.length + 1 : undefined, "aria-busy": loading || undefined, role: role("table"), style: {
344
+ const tableElement = (_jsxs("table", { "data-slot": "table", "data-variant": variant, "data-narrow": narrow, "data-sized": sized || undefined, "data-pin-start": pinsStart || undefined, className: "sprout-table", "aria-label": label, "aria-rowcount": virtual ? rows.length + 1 : undefined, "aria-busy": loading || undefined, role: role('table'), style: {
383
345
  ...(sized ? { minWidth: table.getTotalSize() } : {}),
384
- ...(pinOffsets.__select !== undefined
385
- ? { "--sprout-table-select-start": `${pinOffsets.__select}px` }
386
- : {}),
346
+ ...(pinOffsets.__select !== undefined ? { '--sprout-table-select-start': `${pinOffsets.__select}px` } : {}),
387
347
  }, children: [caption && (_jsx("caption", { "data-slot": "table-caption", className: "sprout-table-caption", children: caption })), _jsxs(PinOffsetsContext, { value: pinOffsets, children: [header, body] }), footer] }));
388
348
  const pageCount = table.getPageCount();
389
- return (_jsx(TooltipProvider, { children: _jsxs("div", { "data-slot": "table-root", className: cn("sprout-table-root", className), children: [toolbar && (_jsx(Toolbar, { table: table, columns: columns, label: label, searchable: searchable, columnMenu: columnMenu, onReset: () => {
349
+ return (_jsx(TooltipProvider, { children: _jsxs("div", { "data-slot": "table-root", className: cn('sprout-table-root', className), children: [toolbar && (_jsx(Toolbar, { table: table, columns: columns, label: label, searchable: searchable, columnMenu: columnMenu, onReset: () => {
390
350
  const reset = initialState(columns, pageSize);
391
351
  for (const key of tableLayoutKeys)
392
352
  setSlice(key)(reset[key]);
393
- } })), virtual ? (_jsx("div", { ref: scrollRef, "data-slot": "table-container", "data-virtual": "", className: "sprout-table-container", tabIndex: 0, role: "region", "aria-label": label, children: tableElement })) : variant === "grid" ? (_jsx(ScrollArea, { variant: "table", orientation: "both", viewportLabel: label, "data-slot": "table-container", children: tableElement })) : (_jsx(PlainContainer, { label: label, children: tableElement })), pageSize && pageCount > 1 && (_jsxs("nav", { className: "sprout-table-pages", "aria-label": `${label} pages`, children: [_jsxs("span", { "aria-live": "polite", children: ["Page ", state.pagination.pageIndex + 1, " of ", pageCount] }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanPreviousPage(), onClick: () => table.previousPage(), children: "Previous" }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanNextPage(), onClick: () => table.nextPage(), children: "Next" })] }))] }) }));
353
+ } })), virtual ? (_jsx("div", { ref: scrollRef, "data-slot": "table-container", "data-virtual": "", className: "sprout-table-container", tabIndex: 0, role: "region", "aria-label": label, children: tableElement })) : variant === 'grid' ? (_jsx(ScrollArea, { variant: "table", orientation: "both", viewportLabel: label, "data-slot": "table-container", children: tableElement })) : (_jsx(PlainContainer, { label: label, children: tableElement })), pageSize && pageCount > 1 && (_jsxs("nav", { className: "sprout-table-pages", "aria-label": `${label} pages`, children: [_jsxs("span", { "aria-live": "polite", children: ["Page ", state.pagination.pageIndex + 1, " of ", pageCount] }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanPreviousPage(), onClick: () => table.previousPage(), children: "Previous" }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanNextPage(), onClick: () => table.nextPage(), children: "Next" })] }))] }) }));
394
354
  }
395
355
  const PinOffsetsContext = createContext({});
396
356
  /** Sticky offsets from the real header cell widths, so columns without a set width pin in the right place. */
@@ -399,8 +359,7 @@ function measurePinOffsets(cells) {
399
359
  let start = 0;
400
360
  for (const cell of cells) {
401
361
  const id = cell.dataset.columnId;
402
- if (!id ||
403
- (cell.dataset.selection === undefined && cell.dataset.pinned !== "start"))
362
+ if (!id || (cell.dataset.selection === undefined && cell.dataset.pinned !== 'start'))
404
363
  continue;
405
364
  offsets[id] = start;
406
365
  start += cell.getBoundingClientRect().width;
@@ -408,8 +367,7 @@ function measurePinOffsets(cells) {
408
367
  let end = 0;
409
368
  for (const cell of [...cells].reverse()) {
410
369
  const id = cell.dataset.columnId;
411
- if (!id ||
412
- (cell.dataset.stickyEnd === undefined && cell.dataset.pinned !== "end"))
370
+ if (!id || (cell.dataset.stickyEnd === undefined && cell.dataset.pinned !== 'end'))
413
371
  continue;
414
372
  offsets[id] = end;
415
373
  end += cell.getBoundingClientRect().width;
@@ -421,27 +379,25 @@ function pinStyle(column, sized, offsets) {
421
379
  const width = sized ? column.getSize() : undefined;
422
380
  if (!pinned)
423
381
  return width ? { width } : undefined;
424
- return pinned === "start"
382
+ return pinned === 'start'
425
383
  ? {
426
384
  width,
427
- insetInlineStart: offsets[column.id] ?? column.getStart("start"),
385
+ insetInlineStart: offsets[column.id] ?? column.getStart('start'),
428
386
  }
429
- : { width, insetInlineEnd: offsets[column.id] ?? column.getAfter("end") };
387
+ : { width, insetInlineEnd: offsets[column.id] ?? column.getAfter('end') };
430
388
  }
431
389
  function formatAggregate(config, value) {
432
- if (typeof value !== "number")
390
+ if (typeof value !== 'number')
433
391
  return null;
434
- return config.formatAggregate
435
- ? config.formatAggregate(value)
436
- : value.toLocaleString();
392
+ return config.formatAggregate ? config.formatAggregate(value) : value.toLocaleString();
437
393
  }
438
394
  /** Joins the Tab order only while the table is wider than its container, so keyboard users can scroll it. */
439
- function PlainContainer({ label, children, }) {
395
+ function PlainContainer({ label, children }) {
440
396
  const ref = useRef(null);
441
397
  const [overflowing, setOverflowing] = useState(false);
442
398
  useEffect(() => {
443
399
  const element = ref.current;
444
- if (!element || typeof ResizeObserver === "undefined")
400
+ if (!element || typeof ResizeObserver === 'undefined')
445
401
  return;
446
402
  const measure = () => setOverflowing(element.scrollWidth > element.clientWidth);
447
403
  measure();
@@ -451,12 +407,12 @@ function PlainContainer({ label, children, }) {
451
407
  observer.observe(element.firstElementChild);
452
408
  return () => observer.disconnect();
453
409
  }, []);
454
- return (_jsx("div", { ref: ref, "data-slot": "table-container", "data-overflowing": overflowing || undefined, className: "sprout-table-container", tabIndex: overflowing ? 0 : undefined, role: overflowing ? "region" : undefined, "aria-label": overflowing ? label : undefined, children: children }));
410
+ return (_jsx("div", { ref: ref, "data-slot": "table-container", "data-overflowing": overflowing || undefined, className: "sprout-table-container", tabIndex: overflowing ? 0 : undefined, role: overflowing ? 'region' : undefined, "aria-label": overflowing ? label : undefined, children: children }));
455
411
  }
456
412
  function HeadCell({ header, config, resizable, reorderable, sized, role, }) {
457
413
  const column = header.column;
458
414
  const title = config?.header ?? column.id;
459
- const align = config?.align ?? "left";
415
+ const align = config?.align ?? 'left';
460
416
  const sorted = column.getIsSorted();
461
417
  const sortable = column.getCanSort();
462
418
  const sortable_ = useSortable({ id: column.id, disabled: !reorderable });
@@ -472,67 +428,62 @@ function HeadCell({ header, config, resizable, reorderable, sized, role, }) {
472
428
  : {}),
473
429
  };
474
430
  const next = column.getNextSortingOrder();
475
- const hint = sorted === "asc"
476
- ? `, ascending. ${next === "desc" ? "Select for descending" : "Select to clear"}`
477
- : sorted === "desc"
478
- ? `, descending. ${next === "asc" ? "Select for ascending" : "Select to clear"}`
479
- : "";
480
- const Icon = sorted === "asc" ? ArrowUp : sorted === "desc" ? ArrowDown : SortV;
431
+ const hint = sorted === 'asc'
432
+ ? `, ascending. ${next === 'desc' ? 'Select for descending' : 'Select to clear'}`
433
+ : sorted === 'desc'
434
+ ? `, descending. ${next === 'asc' ? 'Select for ascending' : 'Select to clear'}`
435
+ : '';
436
+ const Icon = sorted === 'asc' ? ArrowUp : sorted === 'desc' ? ArrowDown : SortV;
481
437
  const onResizeKey = (event) => {
482
438
  const step = event.shiftKey ? 40 : 10;
483
- const delta = event.key === "ArrowRight" ? step : event.key === "ArrowLeft" ? -step : 0;
439
+ const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
484
440
  if (!delta)
485
441
  return;
486
442
  event.preventDefault();
487
- column.table.setColumnSizing((prev) => ({
443
+ column.table.setColumnSizing(prev => ({
488
444
  ...prev,
489
445
  [column.id]: Math.max(48, column.getSize() + delta),
490
446
  }));
491
447
  };
492
- return (_jsxs("th", { ref: reorderable ? sortable_.setNodeRef : undefined, "data-slot": "table-head", "data-align": align, "data-pinned": pinned || undefined, "data-column-id": column.id, "data-dragging": sortable_.isDragging || undefined, className: "sprout-table-head", "aria-sort": sorted === "asc"
493
- ? "ascending"
494
- : sorted === "desc"
495
- ? "descending"
496
- : undefined, role: role, style: style, children: [_jsxs("span", { className: "sprout-table-head-inner", children: [reorderable && (_jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${title} column`, ...sortable_.attributes, ...sortable_.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) })), sortable ? (_jsxs(Button, { variant: sorted ? "secondary" : "ghost", size: align === "right" ? "column-header-end" : "column-header", "aria-label": `Sort by ${title}${hint}`, title: sorted ? undefined : "Sort ascending", onClick: column.getToggleSortingHandler(), children: [title, _jsx(Icon, { size: 14, "aria-hidden": "true" })] })) : (title), config?.hint && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx("button", { type: "button", "aria-label": `About ${title}`, className: "sprout-table-hint" }), children: _jsx(InfoCircle, { size: 14, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: config.hint })] }))] }), resizable && (_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": `Resize ${title} column`, "aria-valuenow": column.getSize(), "aria-valuemin": 48, tabIndex: 0, className: "sprout-table-resizer", "data-resizing": column.getIsResizing() || undefined, onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), onKeyDown: onResizeKey, onDoubleClick: () => column.resetSize() }))] }));
448
+ return (_jsxs("th", { ref: reorderable ? sortable_.setNodeRef : undefined, "data-slot": "table-head", "data-align": align, "data-pinned": pinned || undefined, "data-column-id": column.id, "data-dragging": sortable_.isDragging || undefined, className: "sprout-table-head", "aria-sort": sorted === 'asc' ? 'ascending' : sorted === 'desc' ? 'descending' : undefined, role: role, style: style, children: [_jsxs("span", { className: "sprout-table-head-inner", children: [reorderable && (_jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${title} column`, ...sortable_.attributes, ...sortable_.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) })), sortable ? (_jsxs(Button, { variant: sorted ? 'secondary' : 'ghost', size: align === 'right' ? 'column-header-end' : 'column-header', "aria-label": `Sort by ${title}${hint}`, title: sorted ? undefined : 'Sort ascending', onClick: column.getToggleSortingHandler(), children: [title, _jsx(Icon, { size: 14, "aria-hidden": "true" })] })) : (title), config?.hint && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx("button", { type: "button", "aria-label": `About ${title}`, className: "sprout-table-hint" }), children: _jsx(InfoCircle, { size: 14, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: config.hint })] }))] }), resizable && (_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": `Resize ${title} column`, "aria-valuenow": column.getSize(), "aria-valuemin": 48, tabIndex: 0, className: "sprout-table-resizer", "data-resizing": column.getIsResizing() || undefined, onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), onKeyDown: onResizeKey, onDoubleClick: () => column.resetSize() }))] }));
497
449
  }
498
450
  function GroupRow({ row, columns, byKey, selectable, reorder, hasActions, rowIndex, role, }) {
499
- const groupColumn = byKey.get(row.groupingColumnId ?? "");
451
+ const groupColumn = byKey.get(row.groupingColumnId ?? '');
500
452
  const value = row.groupingValue;
501
- const option = groupColumn?.options?.find((o) => o.value === String(value));
502
- const name = option?.label ?? (value == null || value === "" ? "None" : String(value));
453
+ const option = groupColumn?.options?.find(o => o.value === String(value));
454
+ const name = option?.label ?? (value == null || value === '' ? 'None' : String(value));
503
455
  const expanded = row.getIsExpanded();
504
- const leafRows = row.getLeafRows().filter((r) => !r.getIsGrouped());
456
+ const leafRows = row.getLeafRows().filter(r => !r.getIsGrouped());
505
457
  const offsets = useContext(PinOffsetsContext);
506
- return (_jsxs("tr", { "data-slot": "table-row", "data-group": "", className: "sprout-table-row", "aria-rowindex": rowIndex, role: role("row"), children: [reorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), columns.map((column, index) => {
458
+ return (_jsxs("tr", { "data-slot": "table-row", "data-group": "", className: "sprout-table-row", "aria-rowindex": rowIndex, role: role('row'), children: [reorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), columns.map((column, index) => {
507
459
  const config = byKey.get(column.id);
508
- return (_jsx("td", { className: "sprout-table-cell", "data-align": index === 0 ? "left" : (config?.align ?? "left"), "data-pinned": column.getIsPinned() || undefined, role: role("cell"), style: pinStyle(column, false, offsets), children: index === 0 ? (_jsxs("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": expanded, onClick: row.getToggleExpandedHandler(), style: { paddingInlineStart: row.depth * 16 }, children: [expanded ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })), _jsxs("span", { className: "sprout-table-group-name", children: [groupColumn?.header, ": ", name] }), _jsx("span", { className: "sprout-table-group-count", children: leafRows.length })] })) : config?.aggregate ? (formatAggregate(config, column.getAggregationValue({ rows: leafRows }))) : null }, column.id));
460
+ return (_jsx("td", { className: "sprout-table-cell", "data-align": index === 0 ? 'left' : (config?.align ?? 'left'), "data-pinned": column.getIsPinned() || undefined, role: role('cell'), style: pinStyle(column, false, offsets), children: index === 0 ? (_jsxs("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": expanded, onClick: row.getToggleExpandedHandler(), style: { paddingInlineStart: row.depth * 16 }, children: [expanded ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })), _jsxs("span", { className: "sprout-table-group-name", children: [groupColumn?.header, ": ", name] }), _jsx("span", { className: "sprout-table-group-count", children: leafRows.length })] })) : config?.aggregate ? (formatAggregate(config, column.getAggregationValue({ rows: leafRows }))) : null }, column.id));
509
461
  }), hasActions && _jsx("td", { className: "sprout-table-cell", "data-sticky-end": "" })] }));
510
462
  }
511
463
  function BodyRow({ row, columns, byKey, label, selectable, onSelect, reorder, editing, editable, onEditChange, onEdit, onSave, onCancel, actions, hasActions, href, onOpen, drop, colSpan, rowIndex, role, }) {
512
464
  const sortable = useSortable({ id: row.id, disabled: !reorder });
513
465
  const selected = row.getIsSelected();
514
466
  const offsets = useContext(PinOffsetsContext);
515
- const hasFiles = (event) => event.dataTransfer.types.includes("Files");
467
+ const hasFiles = (event) => event.dataTransfer.types.includes('Files');
516
468
  const onKeyDown = (event) => {
517
469
  if (!editing)
518
470
  return;
519
- if (event.key === "Escape") {
471
+ if (event.key === 'Escape') {
520
472
  event.preventDefault();
521
473
  onCancel();
522
474
  }
523
- else if (event.key === "Enter" &&
524
- event.target instanceof HTMLInputElement) {
475
+ else if (event.key === 'Enter' && event.target instanceof HTMLInputElement) {
525
476
  event.preventDefault();
526
477
  onSave();
527
478
  }
528
479
  };
529
- return (_jsxs(_Fragment, { children: [_jsxs("tr", { ref: reorder !== undefined ? sortable.setNodeRef : undefined, "data-slot": "table-row", "data-state": selected ? "selected" : undefined, "data-editing": editing ? "" : undefined, "data-drop-target": drop?.active || undefined, "data-linked": href || onOpen ? "" : undefined, "data-dragging": sortable.isDragging || undefined, className: "sprout-table-row", "aria-rowindex": rowIndex, "aria-selected": selectable ? selected : undefined, role: role("row"), style: sortable.transform
480
+ return (_jsxs(_Fragment, { children: [_jsxs("tr", { ref: reorder !== undefined ? sortable.setNodeRef : undefined, "data-slot": "table-row", "data-state": selected ? 'selected' : undefined, "data-editing": editing ? '' : undefined, "data-drop-target": drop?.active || undefined, "data-linked": href || onOpen ? '' : undefined, "data-dragging": sortable.isDragging || undefined, className: "sprout-table-row", "aria-rowindex": rowIndex, "aria-selected": selectable ? selected : undefined, role: role('row'), style: sortable.transform
530
481
  ? {
531
482
  transform: CSS.Translate.toString(sortable.transform),
532
483
  transition: sortable.transition,
533
484
  }
534
485
  : undefined, onKeyDown: onKeyDown, onDragOver: drop
535
- ? (event) => {
486
+ ? event => {
536
487
  if (!hasFiles(event))
537
488
  return;
538
489
  event.preventDefault();
@@ -540,124 +491,104 @@ function BodyRow({ row, columns, byKey, label, selectable, onSelect, reorder, ed
540
491
  drop.set(true);
541
492
  }
542
493
  : undefined, onDragLeave: drop
543
- ? (event) => {
494
+ ? event => {
544
495
  if (!event.currentTarget.contains(event.relatedTarget))
545
496
  drop.set(false);
546
497
  }
547
498
  : undefined, onDrop: drop
548
- ? (event) => {
499
+ ? event => {
549
500
  if (!hasFiles(event))
550
501
  return;
551
502
  event.preventDefault();
552
503
  drop.set(false);
553
504
  drop.onDrop(Array.from(event.dataTransfer.files));
554
505
  }
555
- : undefined, children: [reorder !== undefined && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role("cell"), children: _jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${label}`, disabled: !reorder, title: reorder
556
- ? undefined
557
- : "Clear sorting, filters, and grouping to reorder", ...sortable.attributes, ...sortable.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) }) })), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role("cell"), children: _jsx(Checkbox, { "aria-label": `Select ${label}`, checked: selected, disabled: !row.getCanSelect(), onCheckedChange: (checked, details) => onSelect(checked, details.event.shiftKey ===
558
- true) }) })), columns.map((column, index) => {
506
+ : undefined, children: [reorder !== undefined && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role('cell'), children: _jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${label}`, disabled: !reorder, title: reorder ? undefined : 'Clear sorting, filters, and grouping to reorder', ...sortable.attributes, ...sortable.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) }) })), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role('cell'), children: _jsx(Checkbox, { "aria-label": `Select ${label}`, checked: selected, disabled: !row.getCanSelect(), onCheckedChange: (checked, details) => onSelect(checked, details.event.shiftKey === true) }) })), columns.map((column, index) => {
559
507
  const config = byKey.get(column.id);
560
- const content = config?.cell
561
- ? config.cell(row.original)
562
- : row.getValue(column.id);
508
+ const content = config?.cell ? config.cell(row.original) : row.getValue(column.id);
563
509
  const first = index === 0;
564
510
  const canExpand = first && row.getCanExpand();
565
- return (_jsx("td", { "data-slot": "table-cell", "data-align": config?.align ?? "left", "data-pinned": column.getIsPinned() || undefined, "data-label": config?.header, className: "sprout-table-cell", role: role("cell"), style: pinStyle(column, false, offsets), children: editing && config?.edit ? (_jsx(Editor, { config: config, label: `${config.header} for ${label}`, value: editing.draft[column.id], onChange: (value) => onEditChange(column.id, value), autoFocus: first ||
566
- columns.findIndex((c) => byKey.get(c.id)?.edit) === index })) : first ? (_jsxs("span", { className: "sprout-table-first", style: row.depth
567
- ? { paddingInlineStart: row.depth * 16 }
568
- : undefined, children: [canExpand && (_jsx("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": row.getIsExpanded(), "aria-label": `${row.getIsExpanded() ? "Collapse" : "Expand"} ${label}`, onClick: row.getToggleExpandedHandler(), children: row.getIsExpanded() ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })) })), href ? (_jsx("a", { className: "sprout-table-link", href: href, children: content })) : onOpen ? (_jsx("button", { type: "button", className: "sprout-table-link", onClick: onOpen, children: content })) : (content)] })) : (content) }, column.id));
569
- }), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", role: role("cell"), children: _jsx("span", { className: "sprout-table-actions", children: editing ? (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", disabled: editing.saving, onClick: onSave, children: editing.saving ? "Saving" : "Save" }), _jsx(Button, { size: "sm", variant: "ghost", disabled: editing.saving, onClick: onCancel, children: "Cancel" })] })) : (_jsxs(_Fragment, { children: [editable && (_jsx(Button, { size: "sm", variant: "ghost", "aria-label": `Edit ${label}`, onClick: onEdit, children: "Edit" })), actions?.(row.original)] })) }) }))] }), editing?.error && (_jsx("tr", { className: "sprout-table-row", "data-error-row": "", role: role("row"), children: _jsx("td", { colSpan: colSpan, className: "sprout-table-cell sprout-table-error", role: "alert", children: editing.error }) }))] }));
511
+ return (_jsx("td", { "data-slot": "table-cell", "data-align": config?.align ?? 'left', "data-pinned": column.getIsPinned() || undefined, "data-label": config?.header, className: "sprout-table-cell", role: role('cell'), style: pinStyle(column, false, offsets), children: editing && config?.edit ? (_jsx(Editor, { config: config, label: `${config.header} for ${label}`, value: editing.draft[column.id], onChange: value => onEditChange(column.id, value), autoFocus: first || columns.findIndex(c => byKey.get(c.id)?.edit) === index })) : first ? (_jsxs("span", { className: "sprout-table-first", style: row.depth ? { paddingInlineStart: row.depth * 16 } : undefined, children: [canExpand && (_jsx("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": row.getIsExpanded(), "aria-label": `${row.getIsExpanded() ? 'Collapse' : 'Expand'} ${label}`, onClick: row.getToggleExpandedHandler(), children: row.getIsExpanded() ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })) })), href ? (_jsx("a", { className: "sprout-table-link", href: href, children: content })) : onOpen ? (_jsx("button", { type: "button", className: "sprout-table-link", onClick: onOpen, children: content })) : (content)] })) : (content) }, column.id));
512
+ }), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", role: role('cell'), children: _jsx("span", { className: "sprout-table-actions", children: editing ? (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", disabled: editing.saving, onClick: onSave, children: editing.saving ? 'Saving' : 'Save' }), _jsx(Button, { size: "sm", variant: "ghost", disabled: editing.saving, onClick: onCancel, children: "Cancel" })] })) : (_jsxs(_Fragment, { children: [editable && (_jsx(Button, { size: "sm", variant: "ghost", "aria-label": `Edit ${label}`, onClick: onEdit, children: "Edit" })), actions?.(row.original)] })) }) }))] }), editing?.error && (_jsx("tr", { className: "sprout-table-row", "data-error-row": "", role: role('row'), children: _jsx("td", { colSpan: colSpan, className: "sprout-table-cell sprout-table-error", role: "alert", children: editing.error }) }))] }));
570
513
  }
571
514
  function Editor({ config, label, value, onChange, autoFocus, }) {
572
- if (config.edit === "checkbox") {
573
- return (_jsx(Checkbox, { "aria-label": label, checked: Boolean(value), onCheckedChange: (checked) => onChange(checked), autoFocus: autoFocus }));
515
+ if (config.edit === 'checkbox') {
516
+ return (_jsx(Checkbox, { "aria-label": label, checked: Boolean(value), onCheckedChange: checked => onChange(checked), autoFocus: autoFocus }));
574
517
  }
575
- if (config.edit === "select") {
576
- return (_jsx("select", { "aria-label": label, className: "sprout-table-select", value: String(value ?? ""), onChange: (event) => onChange(event.target.value), autoFocus: autoFocus, children: config.options?.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) }));
518
+ if (config.edit === 'select') {
519
+ return (_jsx("select", { "aria-label": label, className: "sprout-table-select", value: String(value ?? ''), onChange: event => onChange(event.target.value), autoFocus: autoFocus, children: config.options?.map(o => (_jsx("option", { value: o.value, children: o.label }, o.value))) }));
577
520
  }
578
- return (_jsx(Input, { "aria-label": label, type: config.edit === "number"
579
- ? "number"
580
- : config.edit === "date"
581
- ? "date"
582
- : "text", value: value == null ? "" : String(value), onValueChange: (next) => onChange(config.edit === "number" ? (next === "" ? null : Number(next)) : next), autoFocus: autoFocus, className: "sprout-table-input" }));
521
+ return (_jsx(Input, { "aria-label": label, type: config.edit === 'number' ? 'number' : config.edit === 'date' ? 'date' : 'text', value: value == null ? '' : String(value), onValueChange: next => onChange(config.edit === 'number' ? (next === '' ? null : Number(next)) : next), autoFocus: autoFocus, className: "sprout-table-input" }));
583
522
  }
584
523
  function Toolbar({ table, columns, label, searchable, columnMenu, onReset, }) {
585
524
  const [pending, setPending] = useState([]);
586
525
  const [open, setOpen] = useState(null);
587
526
  const filters = table.state.columnFilters;
588
- const filterable = columns.filter((c) => c.filter);
589
- const groupable = columns.filter((c) => c.group);
527
+ const filterable = columns.filter(c => c.filter);
528
+ const groupable = columns.filter(c => c.group);
590
529
  const grouping = table.state.grouping;
591
- const chips = filterable.filter((c) => pending.includes(c.key) || filters.some((f) => f.id === c.key));
592
- return (_jsxs("div", { className: "sprout-table-toolbar", role: "toolbar", "aria-label": `${label} tools`, children: [searchable && (_jsx(SearchField, { label: `Search ${label}`, value: String(table.state.globalFilter ?? ""), onChange: (value) => table.setGlobalFilter(value) })), chips.map((c) => {
530
+ const chips = filterable.filter(c => pending.includes(c.key) || filters.some(f => f.id === c.key));
531
+ return (_jsxs("div", { className: "sprout-table-toolbar", role: "toolbar", "aria-label": `${label} tools`, children: [searchable && (_jsx(SearchField, { label: `Search ${label}`, value: String(table.state.globalFilter ?? ''), onChange: value => table.setGlobalFilter(value) })), chips.map(c => {
593
532
  const column = table.getColumn(c.key);
594
533
  if (!column)
595
534
  return null;
596
- return (_jsxs("span", { className: "sprout-table-chip", children: [_jsxs(Popover, { open: open === c.key, onOpenChange: (next) => setOpen(next ? c.key : null), children: [_jsxs(PopoverTrigger, { className: "sprout-table-chip-label", children: [c.header, describeFilter(c, column.getFilterValue())] }), _jsx(PopoverContent, { align: "start", children: _jsx(FilterEditor, { config: c, column: column }) })] }), _jsx("button", { type: "button", className: "sprout-table-chip-remove", "aria-label": `Remove ${c.header} filter`, onClick: () => {
535
+ return (_jsxs("span", { className: "sprout-table-chip", children: [_jsxs(Popover, { open: open === c.key, onOpenChange: next => setOpen(next ? c.key : null), children: [_jsxs(PopoverTrigger, { className: "sprout-table-chip-label", children: [c.header, describeFilter(c, column.getFilterValue())] }), _jsx(PopoverContent, { align: "start", children: _jsx(FilterEditor, { config: c, column: column }) })] }), _jsx("button", { type: "button", className: "sprout-table-chip-remove", "aria-label": `Remove ${c.header} filter`, onClick: () => {
597
536
  column.setFilterValue(undefined);
598
- setPending((p) => p.filter((k) => k !== c.key));
537
+ setPending(p => p.filter(k => k !== c.key));
599
538
  }, children: _jsx(X, { size: 12, "aria-hidden": "true" }) })] }, c.key));
600
539
  }), filterable.length > chips.length && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [_jsx(Plus, { size: 14, "aria-hidden": "true" }), "Filter"] }), _jsx(DropdownMenuContent, { align: "start", size: "menu", children: filterable
601
- .filter((c) => !chips.includes(c))
602
- .map((c) => (_jsx(DropdownMenuItem, { onClick: () => {
603
- setPending((p) => [...p, c.key]);
540
+ .filter(c => !chips.includes(c))
541
+ .map(c => (_jsx(DropdownMenuItem, { onClick: () => {
542
+ setPending(p => [...p, c.key]);
604
543
  setOpen(c.key);
605
- }, children: c.header }, c.key))) })] })), _jsxs("span", { className: "sprout-table-toolbar-end", children: [groupable.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [grouping.length ? `Group: ${grouping.length}` : "Group", _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsx(DropdownMenuContent, { align: "end", size: "menu", children: groupable.map((c) => (_jsx(DropdownMenuCheckboxItem, { checked: grouping.includes(c.key), onCheckedChange: () => table.getColumn(c.key)?.toggleGrouping(), children: c.header }, c.key))) })] })), columnMenu && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: ["Columns", _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsxs(DropdownMenuContent, { align: "end", size: "menu", children: [columns.map((c) => {
544
+ }, children: c.header }, c.key))) })] })), _jsxs("span", { className: "sprout-table-toolbar-end", children: [groupable.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [grouping.length ? `Group: ${grouping.length}` : 'Group', _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsx(DropdownMenuContent, { align: "end", size: "menu", children: groupable.map(c => (_jsx(DropdownMenuCheckboxItem, { checked: grouping.includes(c.key), onCheckedChange: () => table.getColumn(c.key)?.toggleGrouping(), children: c.header }, c.key))) })] })), columnMenu && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: ["Columns", _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsxs(DropdownMenuContent, { align: "end", size: "menu", children: [columns.map(c => {
606
545
  const column = table.getColumn(c.key);
607
546
  if (!column)
608
547
  return null;
609
- return (_jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: c.header }), _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: (checked) => column.toggleVisibility(checked), children: "Show" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuRadioGroup, { value: column.getIsPinned() || "none", onValueChange: (value) => column.pin(value === "none"
610
- ? false
611
- : value), children: [_jsx(DropdownMenuRadioItem, { value: "none", children: "Not pinned" }), _jsx(DropdownMenuRadioItem, { value: "start", children: "Pin to start" }), _jsx(DropdownMenuRadioItem, { value: "end", children: "Pin to end" })] })] })] }, c.key));
548
+ return (_jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: c.header }), _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: checked => column.toggleVisibility(checked), children: "Show" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuRadioGroup, { value: column.getIsPinned() || 'none', onValueChange: value => column.pin(value === 'none' ? false : value), children: [_jsx(DropdownMenuRadioItem, { value: "none", children: "Not pinned" }), _jsx(DropdownMenuRadioItem, { value: "start", children: "Pin to start" }), _jsx(DropdownMenuRadioItem, { value: "end", children: "Pin to end" })] })] })] }, c.key));
612
549
  }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { onClick: onReset, children: "Reset columns" })] })] }))] })] }));
613
550
  }
614
551
  function describeFilter(config, value) {
615
552
  if (value === undefined)
616
- return "";
617
- if (config.filter === "select" && Array.isArray(value)) {
618
- const labels = value.map((v) => config.options?.find((o) => o.value === v)?.label ?? String(v));
619
- return `: ${labels.join(", ")}`;
553
+ return '';
554
+ if (config.filter === 'select' && Array.isArray(value)) {
555
+ const labels = value.map(v => config.options?.find(o => o.value === v)?.label ?? String(v));
556
+ return `: ${labels.join(', ')}`;
620
557
  }
621
- if ((config.filter === "number" || config.filter === "date") &&
622
- Array.isArray(value)) {
558
+ if ((config.filter === 'number' || config.filter === 'date') && Array.isArray(value)) {
623
559
  const [min, max] = value;
624
- const has = (v) => v !== undefined && v !== null && v !== "";
560
+ const has = (v) => v !== undefined && v !== null && v !== '';
625
561
  if (has(min) && has(max))
626
562
  return `: ${min} – ${max}`;
627
563
  if (has(min))
628
564
  return `: ≥ ${min}`;
629
565
  if (has(max))
630
566
  return `: ≤ ${max}`;
631
- return "";
567
+ return '';
632
568
  }
633
- if (config.filter === "boolean")
634
- return `: ${value ? "Yes" : "No"}`;
569
+ if (config.filter === 'boolean')
570
+ return `: ${value ? 'Yes' : 'No'}`;
635
571
  return `: ${String(value)}`;
636
572
  }
637
- function FilterEditor({ config, column, }) {
573
+ function FilterEditor({ config, column }) {
638
574
  const value = column.getFilterValue();
639
575
  const name = config.header;
640
- if (config.filter === "select") {
576
+ if (config.filter === 'select') {
641
577
  const selected = value ?? [];
642
- return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), config.options?.map((o) => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx(Checkbox, { variant: "neutral", checked: selected.includes(o.value), onCheckedChange: (checked) => column.setFilterValue(checked
643
- ? [...selected, o.value]
644
- : selected.filter((v) => v !== o.value)) }), o.label] }, o.value)))] }));
578
+ return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), config.options?.map(o => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx(Checkbox, { variant: "neutral", checked: selected.includes(o.value), onCheckedChange: checked => column.setFilterValue(checked ? [...selected, o.value] : selected.filter(v => v !== o.value)) }), o.label] }, o.value)))] }));
645
579
  }
646
- if (config.filter === "boolean") {
647
- return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), [true, false].map((option) => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx("input", { type: "radio", name: `${column.id}-filter`, checked: value === option, onChange: () => column.setFilterValue(option) }), option ? "Yes" : "No"] }, String(option))))] }));
580
+ if (config.filter === 'boolean') {
581
+ return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), [true, false].map(option => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx("input", { type: "radio", name: `${column.id}-filter`, checked: value === option, onChange: () => column.setFilterValue(option) }), option ? 'Yes' : 'No'] }, String(option))))] }));
648
582
  }
649
- if (config.filter === "number" || config.filter === "date") {
650
- const [min, max] = value ?? [
651
- undefined,
652
- undefined,
653
- ];
654
- const type = config.filter === "number" ? "number" : "date";
583
+ if (config.filter === 'number' || config.filter === 'date') {
584
+ const [min, max] = value ?? [undefined, undefined];
585
+ const type = config.filter === 'number' ? 'number' : 'date';
655
586
  const set = (index, next) => {
656
- const parsed = next === "" ? undefined : type === "number" ? Number(next) : next;
587
+ const parsed = next === '' ? undefined : type === 'number' ? Number(next) : next;
657
588
  const range = index === 0 ? [parsed, max] : [min, parsed];
658
589
  column.setFilterValue(range[0] === undefined && range[1] === undefined ? undefined : range);
659
590
  };
660
- return (_jsxs("fieldset", { className: "sprout-table-filter", "data-range": "", children: [_jsx("legend", { children: name }), _jsx(Input, { "aria-label": `${name} from`, type: type, value: min == null ? "" : String(min), onValueChange: (next) => set(0, next) }), _jsx(Input, { "aria-label": `${name} to`, type: type, value: max == null ? "" : String(max), onValueChange: (next) => set(1, next) })] }));
591
+ return (_jsxs("fieldset", { className: "sprout-table-filter", "data-range": "", children: [_jsx("legend", { children: name }), _jsx(Input, { "aria-label": `${name} from`, type: type, value: min == null ? '' : String(min), onValueChange: next => set(0, next) }), _jsx(Input, { "aria-label": `${name} to`, type: type, value: max == null ? '' : String(max), onValueChange: next => set(1, next) })] }));
661
592
  }
662
- return (_jsx(Input, { "aria-label": `${name} contains`, autoFocus: true, value: String(value ?? ""), onValueChange: (next) => column.setFilterValue(next || undefined) }));
593
+ return (_jsx(Input, { "aria-label": `${name} contains`, autoFocus: true, value: String(value ?? ''), onValueChange: next => column.setFilterValue(next || undefined) }));
663
594
  }