cortena-ui 1.3.0 → 1.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 (280) hide show
  1. package/README.md +74 -3
  2. package/dist/a2ui/catalogue-doc.d.ts +44 -0
  3. package/dist/a2ui/catalogue-doc.js +169 -0
  4. package/dist/a2ui/catalogue-doc.js.map +1 -0
  5. package/dist/a2ui/catalogue.d.ts +44 -0
  6. package/dist/a2ui/catalogue.js +942 -0
  7. package/dist/a2ui/catalogue.js.map +1 -0
  8. package/dist/a2ui/index.d.ts +7 -0
  9. package/dist/a2ui/message.d.ts +232 -0
  10. package/dist/a2ui/message.js +365 -0
  11. package/dist/a2ui/message.js.map +1 -0
  12. package/dist/a2ui/renderer.d.ts +46 -0
  13. package/dist/a2ui/renderer.js +252 -0
  14. package/dist/a2ui/renderer.js.map +1 -0
  15. package/dist/a2ui/views.d.ts +80 -0
  16. package/dist/a2ui/views.js +596 -0
  17. package/dist/a2ui/views.js.map +1 -0
  18. package/dist/a2ui.d.ts +8 -0
  19. package/dist/a2ui.js +7 -0
  20. package/dist/chart.d.ts +9 -0
  21. package/dist/chart.js +9 -0
  22. package/dist/components/accordion.d.ts +22 -0
  23. package/dist/components/accordion.js +63 -0
  24. package/dist/components/accordion.js.map +1 -0
  25. package/dist/components/alert.d.ts +15 -0
  26. package/dist/components/alert.js +64 -0
  27. package/dist/components/alert.js.map +1 -0
  28. package/dist/components/avatar.d.ts +18 -0
  29. package/dist/components/avatar.js +40 -0
  30. package/dist/components/avatar.js.map +1 -0
  31. package/dist/components/badge.d.ts +12 -0
  32. package/dist/components/badge.js +47 -0
  33. package/dist/components/badge.js.map +1 -0
  34. package/dist/components/breadcrumb.d.ts +71 -0
  35. package/dist/components/breadcrumb.js +123 -0
  36. package/dist/components/breadcrumb.js.map +1 -0
  37. package/dist/components/button-link.d.ts +28 -0
  38. package/dist/components/button-link.js +24 -0
  39. package/dist/components/button-link.js.map +1 -0
  40. package/dist/components/button.d.ts +24 -0
  41. package/dist/components/button.js +65 -0
  42. package/dist/components/button.js.map +1 -0
  43. package/dist/components/calendar.d.ts +28 -0
  44. package/dist/components/calendar.js +123 -0
  45. package/dist/components/calendar.js.map +1 -0
  46. package/dist/components/card.d.ts +32 -0
  47. package/dist/components/card.js +57 -0
  48. package/dist/components/card.js.map +1 -0
  49. package/dist/components/chart/chart.d.ts +71 -0
  50. package/dist/components/chart/chart.js +167 -0
  51. package/dist/components/chart/chart.js.map +1 -0
  52. package/dist/components/chart/container.d.ts +88 -0
  53. package/dist/components/chart/container.js +189 -0
  54. package/dist/components/chart/container.js.map +1 -0
  55. package/dist/components/chart/data.js +128 -0
  56. package/dist/components/chart/data.js.map +1 -0
  57. package/dist/components/chart/index.d.ts +9 -0
  58. package/dist/components/chart/index.js +10 -0
  59. package/dist/components/chart/nivo-charts.js +225 -0
  60. package/dist/components/chart/nivo-charts.js.map +1 -0
  61. package/dist/components/chart/nivo-lazy.js +50 -0
  62. package/dist/components/chart/nivo-lazy.js.map +1 -0
  63. package/dist/components/chart/nivo-theme.d.ts +156 -0
  64. package/dist/components/chart/nivo-theme.js +161 -0
  65. package/dist/components/chart/nivo-theme.js.map +1 -0
  66. package/dist/components/chart/recharts-charts.js +276 -0
  67. package/dist/components/chart/recharts-charts.js.map +1 -0
  68. package/dist/components/chart/recharts-lazy.js +58 -0
  69. package/dist/components/chart/recharts-lazy.js.map +1 -0
  70. package/dist/components/chart/recharts-parts.d.ts +10 -0
  71. package/dist/components/chart/recharts-parts.js +25 -0
  72. package/dist/components/chart/recharts-parts.js.map +1 -0
  73. package/dist/components/chart/tokens.d.ts +62 -0
  74. package/dist/components/chart/tokens.js +192 -0
  75. package/dist/components/chart/tokens.js.map +1 -0
  76. package/dist/components/chart/types.d.ts +114 -0
  77. package/dist/components/chart/types.js +27 -0
  78. package/dist/components/chart/types.js.map +1 -0
  79. package/dist/components/checkbox.d.ts +20 -0
  80. package/dist/components/checkbox.js +24 -0
  81. package/dist/components/checkbox.js.map +1 -0
  82. package/dist/components/chip.d.ts +17 -0
  83. package/dist/components/chip.js +47 -0
  84. package/dist/components/chip.js.map +1 -0
  85. package/dist/components/combobox.d.ts +76 -0
  86. package/dist/components/combobox.js +201 -0
  87. package/dist/components/combobox.js.map +1 -0
  88. package/dist/components/command.d.ts +50 -0
  89. package/dist/components/command.js +117 -0
  90. package/dist/components/command.js.map +1 -0
  91. package/dist/components/data-table/data-table.d.ts +65 -0
  92. package/dist/components/data-table/data-table.js +588 -0
  93. package/dist/components/data-table/data-table.js.map +1 -0
  94. package/dist/components/data-table/export.d.ts +23 -0
  95. package/dist/components/data-table/export.js +95 -0
  96. package/dist/components/data-table/export.js.map +1 -0
  97. package/dist/components/data-table/features.d.ts +66 -0
  98. package/dist/components/data-table/features.js +103 -0
  99. package/dist/components/data-table/features.js.map +1 -0
  100. package/dist/components/data-table/index.d.ts +8 -0
  101. package/dist/components/data-table/parts.d.ts +79 -0
  102. package/dist/components/data-table/parts.js +400 -0
  103. package/dist/components/data-table/parts.js.map +1 -0
  104. package/dist/components/data-table/system-columns.js +84 -0
  105. package/dist/components/data-table/system-columns.js.map +1 -0
  106. package/dist/components/data-table/types.d.ts +172 -0
  107. package/dist/components/data-table/use-data-table.d.ts +19 -0
  108. package/dist/components/data-table/use-data-table.js +171 -0
  109. package/dist/components/data-table/use-data-table.js.map +1 -0
  110. package/dist/components/data-table/use-server-source.js +200 -0
  111. package/dist/components/data-table/use-server-source.js.map +1 -0
  112. package/dist/components/date-field.d.ts +54 -0
  113. package/dist/components/date-field.js +235 -0
  114. package/dist/components/date-field.js.map +1 -0
  115. package/dist/components/date-picker.d.ts +42 -0
  116. package/dist/components/date-picker.js +125 -0
  117. package/dist/components/date-picker.js.map +1 -0
  118. package/dist/components/dialog.d.ts +36 -0
  119. package/dist/components/dialog.js +97 -0
  120. package/dist/components/dialog.js.map +1 -0
  121. package/dist/components/dropdown-menu.d.ts +54 -0
  122. package/dist/components/dropdown-menu.js +191 -0
  123. package/dist/components/dropdown-menu.js.map +1 -0
  124. package/dist/components/dropzone.d.ts +48 -0
  125. package/dist/components/dropzone.js +185 -0
  126. package/dist/components/dropzone.js.map +1 -0
  127. package/dist/components/empty-state.d.ts +22 -0
  128. package/dist/components/empty-state.js +46 -0
  129. package/dist/components/empty-state.js.map +1 -0
  130. package/dist/components/error-banner.d.ts +17 -0
  131. package/dist/components/error-banner.js +52 -0
  132. package/dist/components/error-banner.js.map +1 -0
  133. package/dist/components/field.d.ts +64 -0
  134. package/dist/components/field.js +133 -0
  135. package/dist/components/field.js.map +1 -0
  136. package/dist/components/form.d.ts +37 -0
  137. package/dist/components/form.js +103 -0
  138. package/dist/components/form.js.map +1 -0
  139. package/dist/components/input.d.ts +17 -0
  140. package/dist/components/input.js +26 -0
  141. package/dist/components/input.js.map +1 -0
  142. package/dist/components/kbd.d.ts +11 -0
  143. package/dist/components/kbd.js +20 -0
  144. package/dist/components/kbd.js.map +1 -0
  145. package/dist/components/label.d.ts +14 -0
  146. package/dist/components/label.js +28 -0
  147. package/dist/components/label.js.map +1 -0
  148. package/dist/components/loading-skeleton.d.ts +22 -0
  149. package/dist/components/loading-skeleton.js +123 -0
  150. package/dist/components/loading-skeleton.js.map +1 -0
  151. package/dist/components/markdown.d.ts +44 -0
  152. package/dist/components/markdown.js +231 -0
  153. package/dist/components/markdown.js.map +1 -0
  154. package/dist/components/page-header.d.ts +26 -0
  155. package/dist/components/page-header.js +53 -0
  156. package/dist/components/page-header.js.map +1 -0
  157. package/dist/components/popover.d.ts +29 -0
  158. package/dist/components/popover.js +74 -0
  159. package/dist/components/popover.js.map +1 -0
  160. package/dist/components/progress.d.ts +22 -0
  161. package/dist/components/progress.js +49 -0
  162. package/dist/components/progress.js.map +1 -0
  163. package/dist/components/radio-group.d.ts +20 -0
  164. package/dist/components/radio-group.js +29 -0
  165. package/dist/components/radio-group.js.map +1 -0
  166. package/dist/components/scroll-area.d.ts +25 -0
  167. package/dist/components/scroll-area.js +39 -0
  168. package/dist/components/scroll-area.js.map +1 -0
  169. package/dist/components/section-card.d.ts +29 -0
  170. package/dist/components/section-card.js +55 -0
  171. package/dist/components/section-card.js.map +1 -0
  172. package/dist/components/segmented.d.ts +27 -0
  173. package/dist/components/segmented.js +32 -0
  174. package/dist/components/segmented.js.map +1 -0
  175. package/dist/components/select.d.ts +62 -0
  176. package/dist/components/select.js +97 -0
  177. package/dist/components/select.js.map +1 -0
  178. package/dist/components/separator.d.ts +19 -0
  179. package/dist/components/separator.js +23 -0
  180. package/dist/components/separator.js.map +1 -0
  181. package/dist/components/sheet.d.ts +35 -0
  182. package/dist/components/sheet.js +131 -0
  183. package/dist/components/sheet.js.map +1 -0
  184. package/dist/components/skeleton.d.ts +12 -0
  185. package/dist/components/skeleton.js +22 -0
  186. package/dist/components/skeleton.js.map +1 -0
  187. package/dist/components/sortable-list.d.ts +67 -0
  188. package/dist/components/sortable-list.js +206 -0
  189. package/dist/components/sortable-list.js.map +1 -0
  190. package/dist/components/spinner.d.ts +29 -0
  191. package/dist/components/spinner.js +34 -0
  192. package/dist/components/spinner.js.map +1 -0
  193. package/dist/components/status-dot.d.ts +26 -0
  194. package/dist/components/status-dot.js +47 -0
  195. package/dist/components/status-dot.js.map +1 -0
  196. package/dist/components/switch.d.ts +21 -0
  197. package/dist/components/switch.js +21 -0
  198. package/dist/components/switch.js.map +1 -0
  199. package/dist/components/tabs.d.ts +24 -0
  200. package/dist/components/tabs.js +60 -0
  201. package/dist/components/tabs.js.map +1 -0
  202. package/dist/components/textarea.d.ts +19 -0
  203. package/dist/components/textarea.js +47 -0
  204. package/dist/components/textarea.js.map +1 -0
  205. package/dist/components/toast.d.ts +47 -0
  206. package/dist/components/toast.js +106 -0
  207. package/dist/components/toast.js.map +1 -0
  208. package/dist/components/toolbar.d.ts +19 -0
  209. package/dist/components/toolbar.js +45 -0
  210. package/dist/components/toolbar.js.map +1 -0
  211. package/dist/components/tooltip.d.ts +28 -0
  212. package/dist/components/tooltip.js +59 -0
  213. package/dist/components/tooltip.js.map +1 -0
  214. package/dist/core.d.ts +44 -0
  215. package/dist/core.js +44 -0
  216. package/dist/data-table.d.ts +9 -0
  217. package/dist/data-table.js +7 -0
  218. package/dist/form.d.ts +7 -0
  219. package/dist/form.js +7 -0
  220. package/dist/hooks/use-cortena-theme.d.ts +98 -0
  221. package/dist/hooks/use-cortena-theme.js +145 -0
  222. package/dist/hooks/use-cortena-theme.js.map +1 -0
  223. package/dist/index.d.ts +75 -2678
  224. package/dist/index.js +66 -8598
  225. package/dist/lib/cn.d.ts +10 -0
  226. package/dist/lib/cn.js +15 -0
  227. package/dist/lib/cn.js.map +1 -0
  228. package/dist/lib/render.d.ts +23 -0
  229. package/dist/lib/render.js +20 -0
  230. package/dist/lib/render.js.map +1 -0
  231. package/dist/lib/shakeable.js +39 -0
  232. package/dist/lib/shakeable.js.map +1 -0
  233. package/dist/markdown.d.ts +3 -0
  234. package/dist/markdown.js +3 -0
  235. package/dist/sortable-list.d.ts +3 -0
  236. package/dist/sortable-list.js +3 -0
  237. package/package.json +37 -14
  238. package/src/a2ui/catalogue.ts +140 -103
  239. package/src/a2ui/views.tsx +5 -2
  240. package/src/components/alert.tsx +1 -1
  241. package/src/components/badge.tsx +1 -1
  242. package/src/components/button.tsx +1 -1
  243. package/src/components/chart/chart.tsx +72 -25
  244. package/src/components/chart/container.tsx +24 -39
  245. package/src/components/chart/index.tsx +4 -2
  246. package/src/components/chart/nivo-charts.tsx +41 -13
  247. package/src/components/chart/nivo-lazy.tsx +52 -0
  248. package/src/components/chart/recharts-charts.tsx +98 -3
  249. package/src/components/chart/recharts-lazy.tsx +72 -0
  250. package/src/components/chart/recharts-parts.tsx +34 -0
  251. package/src/components/chart/tokens.ts +1 -1
  252. package/src/components/chart/types.ts +14 -0
  253. package/src/components/chip.tsx +1 -1
  254. package/src/components/combobox.tsx +2 -2
  255. package/src/components/data-table/export.ts +18 -2
  256. package/src/components/data-table/features.ts +77 -45
  257. package/src/components/data-table/parts.tsx +15 -0
  258. package/src/components/data-table/use-data-table.ts +7 -2
  259. package/src/components/data-table/use-server-source.ts +17 -4
  260. package/src/components/date-field.tsx +1 -1
  261. package/src/components/error-banner.tsx +1 -1
  262. package/src/components/field.tsx +2 -2
  263. package/src/components/form.tsx +2 -2
  264. package/src/components/input.tsx +1 -1
  265. package/src/components/label.tsx +1 -1
  266. package/src/components/markdown.tsx +5 -4
  267. package/src/components/sheet.tsx +2 -2
  268. package/src/components/sortable-list.tsx +2 -2
  269. package/src/components/textarea.tsx +1 -1
  270. package/src/components/toast.tsx +1 -1
  271. package/src/entries/a2ui.ts +11 -0
  272. package/src/entries/chart.ts +10 -0
  273. package/src/entries/core.ts +91 -0
  274. package/src/entries/data-table.ts +9 -0
  275. package/src/entries/form.ts +24 -0
  276. package/src/entries/markdown.ts +9 -0
  277. package/src/entries/sortable-list.ts +13 -0
  278. package/src/index.ts +32 -98
  279. package/src/lib/shakeable.ts +33 -0
  280. package/dist/index.js.map +0 -1
@@ -25,7 +25,7 @@ export function vizVar(index: number): string {
25
25
  }
26
26
 
27
27
  /** The categorical palette as `var()` references, in series order. */
28
- export const vizSeriesVars: readonly string[] = Array.from({ length: VIZ_SERIES_COUNT }, (_, i) =>
28
+ export const vizSeriesVars: readonly string[] = /* @__PURE__ */ Array.from({ length: VIZ_SERIES_COUNT }, (_, i) =>
29
29
  vizVar(i),
30
30
  );
31
31
 
@@ -64,6 +64,20 @@ export interface ChartSeries {
64
64
  data: ChartPoint[];
65
65
  }
66
66
 
67
+ /**
68
+ * What to write on each arc of a pie or donut.
69
+ *
70
+ * `percent` is the default for both, because the question a reader asks of a
71
+ * pie is almost always "what share is that", and reading it off the legend
72
+ * slice by slice is the work the chart was supposed to do for them. `value`
73
+ * writes the number itself, through `valueFormatter` when one is given. `none`
74
+ * leaves the arcs bare for a chart that is decorative or has its own labelling.
75
+ *
76
+ * Arcs too thin to hold their text are left unlabelled whatever this says; see
77
+ * `ARC_LABEL_MIN_FRACTION` in recharts-charts.tsx.
78
+ */
79
+ export type ChartLabels = "none" | "value" | "percent";
80
+
67
81
  /** One slice of a pie, donut or funnel. */
68
82
  export interface ChartSlice {
69
83
  id: string | number;
@@ -8,7 +8,7 @@ import { cn } from "@/lib/cn";
8
8
  * Chip — a pill for filters, tags and selected values. Unlike Badge it keeps
9
9
  * sentence case and the body font.
10
10
  */
11
- const chipVariants = cva(
11
+ const chipVariants = /* @__PURE__ */ cva(
12
12
  [
13
13
  "inline-flex items-center gap-1.5 whitespace-nowrap border font-medium",
14
14
  "rounded-[var(--ds-radius-full)]",
@@ -34,9 +34,9 @@ function Combobox<Value, Multiple extends boolean | undefined = false, Item = Va
34
34
  return <ComboboxPrimitive.Root {...props} />;
35
35
  }
36
36
 
37
- const InsideChipsContext = createContext(false);
37
+ const InsideChipsContext = /* @__PURE__ */ createContext(false);
38
38
 
39
- const controlButtonClassName = cn(
39
+ const controlButtonClassName = /* @__PURE__ */ cn(
40
40
  "flex size-6 shrink-0 items-center justify-center rounded-[var(--ds-radius-sm)]",
41
41
  "text-[color:var(--ds-muted-foreground)] outline-none",
42
42
  "transition-[background-color,color] duration-[var(--ds-duration-fast)] ease-[var(--ds-ease-out)]",
@@ -54,13 +54,29 @@ export function toSheet<Row extends RowData>(
54
54
  };
55
55
  }
56
56
 
57
+ /**
58
+ * Text a spreadsheet would evaluate rather than display. Excel, Sheets and
59
+ * LibreOffice all treat a leading `=`, `+`, `-` or `@` as the start of a
60
+ * formula, and a leading tab or CR as whitespace they strip before looking
61
+ * again — so `\t=cmd|'/c calc'!A1` is a formula too. Only strings are checked:
62
+ * a number, boolean or Date cell cannot carry one, and prefixing `-5` would
63
+ * turn a number column into text.
64
+ */
65
+ const FORMULA_START = /^[=+\-@\t\r]/;
66
+
57
67
  function csvField(value: ExportCell): string {
58
68
  if (value == null) return "";
59
- const text = value instanceof Date ? value.toISOString() : String(value);
69
+ let text = value instanceof Date ? value.toISOString() : String(value);
70
+ // Prefix before quoting: the apostrophe is what makes the spreadsheet read
71
+ // the cell as text, and it has to sit inside the quotes to survive the parse.
72
+ if (typeof value === "string" && FORMULA_START.test(text)) text = `'${text}`;
60
73
  return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
61
74
  }
62
75
 
63
- /** RFC 4180 text: comma separated, CRLF lines, quotes doubled. */
76
+ /**
77
+ * RFC 4180 text: comma separated, CRLF lines, quotes doubled. A cell that a
78
+ * spreadsheet would read as a formula is prefixed with `'` so it stays text.
79
+ */
64
80
  export function toCsv<Row extends RowData>(
65
81
  table: DataTableTable<Row>,
66
82
  rows?: DataTableRow<Row>[],
@@ -36,6 +36,7 @@ import {
36
36
  type RowData,
37
37
  } from "@tanstack/react-table";
38
38
  import type { DataTableColumnMeta } from "./types";
39
+ import { shakeable } from "@/lib/shakeable";
39
40
 
40
41
  /**
41
42
  * TanStack Table v9 registers features explicitly; an API that is not in this
@@ -46,53 +47,84 @@ import type { DataTableColumnMeta } from "./types";
46
47
  * `filterFn: "auto"` resolves by the column's first non-null value to
47
48
  * `includesString` / `inNumberRange` / `equals` / `arrIncludes` /
48
49
  * `inDateRange` / `weakEquals`, so those built-ins are registered under their
49
- * conventional names. `oneOf` is ours: the faceted filter stores an array of
50
- * picked values and a row passes when its scalar value is one of them.
50
+ * conventional names. Two are ours: `oneOf`, where the faceted filter stores an
51
+ * array of picked values and a row passes when its scalar value is one of them,
52
+ * and `search`, the global filter.
51
53
  */
52
- const filterFn_oneOf = constructFilterFn({
53
- filter: (dataValue: unknown, filterValue: unknown) =>
54
- Array.isArray(filterValue) ? filterValue.includes(dataValue) : dataValue === filterValue,
55
- autoRemove: (value: unknown) =>
56
- value == null || value === "" || (Array.isArray(value) && value.length === 0),
57
- });
54
+ const filterFn_oneOf = /* @__PURE__ */ shakeable(() =>
55
+ constructFilterFn({
56
+ filter: (dataValue: unknown, filterValue: unknown) =>
57
+ Array.isArray(filterValue) ? filterValue.includes(dataValue) : dataValue === filterValue,
58
+ autoRemove: (value: unknown) =>
59
+ value == null || value === "" || (Array.isArray(value) && value.length === 0),
60
+ }),
61
+ );
58
62
 
59
- const baseFeatures = tableFeatures({
60
- columnFilteringFeature,
61
- globalFilteringFeature,
62
- columnFacetingFeature,
63
- rowSortingFeature,
64
- rowPaginationFeature,
65
- rowSelectionFeature,
66
- rowExpandingFeature,
67
- columnVisibilityFeature,
68
- columnPinningFeature,
69
- columnSizingFeature,
70
- columnResizingFeature,
71
- filteredRowModel: createFilteredRowModel(),
72
- sortedRowModel: createSortedRowModel(),
73
- paginatedRowModel: createPaginatedRowModel(),
74
- expandedRowModel: createExpandedRowModel(),
75
- facetedRowModel: createFacetedRowModel(),
76
- facetedUniqueValues: createFacetedUniqueValues(),
77
- filterFns: {
78
- includesString: filterFn_includesString,
79
- equals: filterFn_equals,
80
- equalsString: filterFn_equalsString,
81
- inNumberRange: filterFn_inNumberRange,
82
- arrIncludes: filterFn_arrIncludes,
83
- arrIncludesSome: filterFn_arrIncludesSome,
84
- inDateRange: filterFn_inDateRange,
85
- weakEquals: filterFn_weakEquals,
86
- oneOf: filterFn_oneOf,
87
- },
88
- sortFns: {
89
- alphanumeric: sortFn_alphanumeric,
90
- basic: sortFn_basic,
91
- datetime: sortFn_datetime,
92
- text: sortFn_text,
93
- },
94
- columnMeta: metaHelper<DataTableColumnMeta<any>>(),
95
- });
63
+ /**
64
+ * The global filter: `includesString` with the query trimmed first.
65
+ *
66
+ * A search box collects whatever the user types, and what they type includes
67
+ * whitespace — a space before the word arrives, a trailing one from a paste or
68
+ * an autocorrect. Untrimmed, `" "` is a real search term that matches no cell,
69
+ * so the grid empties and nothing explains why; users read that as the table
70
+ * being broken, and they are not wrong. A query that is only whitespace is the
71
+ * same as no query, and that is what this says.
72
+ *
73
+ * Both halves matter. `autoRemove` drops such a value from the table state, and
74
+ * `filter` returning true for it means a value that survives anyway — set
75
+ * through `initialState`, say — still shows every row rather than none.
76
+ */
77
+ const filterFn_search = /* @__PURE__ */ shakeable(() =>
78
+ constructFilterFn({
79
+ filter: (dataValue: unknown, filterValue: unknown) => {
80
+ const term = String(filterValue ?? "").trim().toLowerCase();
81
+ if (term === "") return true;
82
+ return String(dataValue ?? "").toLowerCase().includes(term);
83
+ },
84
+ autoRemove: (value: unknown) => typeof value !== "string" || value.trim() === "",
85
+ }),
86
+ );
87
+
88
+ const baseFeatures = /* @__PURE__ */ shakeable(() =>
89
+ tableFeatures({
90
+ columnFilteringFeature,
91
+ globalFilteringFeature,
92
+ columnFacetingFeature,
93
+ rowSortingFeature,
94
+ rowPaginationFeature,
95
+ rowSelectionFeature,
96
+ rowExpandingFeature,
97
+ columnVisibilityFeature,
98
+ columnPinningFeature,
99
+ columnSizingFeature,
100
+ columnResizingFeature,
101
+ filteredRowModel: createFilteredRowModel(),
102
+ sortedRowModel: createSortedRowModel(),
103
+ paginatedRowModel: createPaginatedRowModel(),
104
+ expandedRowModel: createExpandedRowModel(),
105
+ facetedRowModel: createFacetedRowModel(),
106
+ facetedUniqueValues: createFacetedUniqueValues(),
107
+ filterFns: {
108
+ includesString: filterFn_includesString,
109
+ equals: filterFn_equals,
110
+ equalsString: filterFn_equalsString,
111
+ inNumberRange: filterFn_inNumberRange,
112
+ arrIncludes: filterFn_arrIncludes,
113
+ arrIncludesSome: filterFn_arrIncludesSome,
114
+ inDateRange: filterFn_inDateRange,
115
+ weakEquals: filterFn_weakEquals,
116
+ oneOf: filterFn_oneOf,
117
+ search: filterFn_search,
118
+ },
119
+ sortFns: {
120
+ alphanumeric: sortFn_alphanumeric,
121
+ basic: sortFn_basic,
122
+ datetime: sortFn_datetime,
123
+ text: sortFn_text,
124
+ },
125
+ columnMeta: metaHelper<DataTableColumnMeta<any>>(),
126
+ }),
127
+ );
96
128
 
97
129
  /**
98
130
  * The registry type, re-keyed to the consumer's row type so `meta.onCommit`
@@ -92,6 +92,21 @@ function DataTableColumnHeader<Row extends RowData>({
92
92
  data-slot="data-table-sort"
93
93
  disabled={!canSort}
94
94
  onClick={canSort ? column.getToggleSortingHandler() : undefined}
95
+ // Without a name of its own the button announces as just the column
96
+ // title, which tells a screen-reader user the word "Name" and nothing
97
+ // about there being a control or what it would do. The `aria-sort` on
98
+ // the `<th>` (data-table.tsx) states the column's current order; this
99
+ // states the action, and repeats the order because a button reached by
100
+ // tabbing is not necessarily read with its header cell. Only when the
101
+ // column sorts: on a column that only hides or pins, the button is
102
+ // disabled and "Sort by" would be a lie.
103
+ aria-label={
104
+ canSort
105
+ ? sorted
106
+ ? `Sort by ${label}, sorted ${sorted === "asc" ? "ascending" : "descending"}`
107
+ : `Sort by ${label}`
108
+ : undefined
109
+ }
95
110
  className={cn(
96
111
  "inline-flex h-7 min-w-0 items-center gap-1 rounded-[var(--ds-radius-sm)] px-2 outline-none",
97
112
  "text-inherit transition-colors duration-[var(--ds-duration-fast)]",
@@ -104,7 +104,10 @@ export function useDataTable<Row extends RowData>(
104
104
 
105
105
  const query = React.useMemo<TableQuery>(
106
106
  () => ({
107
- q: searchQuery || undefined,
107
+ // Trimmed for the same reason the client filter trims (features.ts): a
108
+ // backend asked for `q: " "` returns nothing, and the user sees an empty
109
+ // table with no explanation. Whitespace-only means no search term.
110
+ q: searchQuery.trim() || undefined,
108
111
  filters: columnFilters.length ? columnFilters : undefined,
109
112
  sort: sorting.length ? sorting : undefined,
110
113
  page: pagination.pageIndex,
@@ -164,7 +167,9 @@ export function useDataTable<Row extends RowData>(
164
167
  enableColumnPinning,
165
168
  enableColumnResizing,
166
169
  columnResizeMode: "onChange",
167
- globalFilterFn: "includesString",
170
+ // `search`, not `includesString`: it trims the query, so a box holding only
171
+ // whitespace filters nothing rather than emptying the grid. See features.ts.
172
+ globalFilterFn: "search",
168
173
  });
169
174
 
170
175
  // Selection callback with original rows, for consumers that keep selection outside.
@@ -168,11 +168,23 @@ function useLocalStrategy<Row>(
168
168
  : !(state.scopeKey === scopeKey && state.page === query.page && state.pages.length > 0);
169
169
  const requestKey = `${scopeKey}|${targetPage}|${tick}`;
170
170
 
171
+ // The consumer's `fetch` is usually an inline arrow — `fetch: q => api.list(q)`
172
+ // is the documented call — so it is a new function on every parent render.
173
+ // Depending on it would abort and refire the request each time; the request's
174
+ // identity is `requestKey`, so the latest function is read from a ref instead.
175
+ const fetchRef = React.useRef(fetch);
171
176
  React.useEffect(() => {
172
- if (!fetch || !needs) return;
177
+ fetchRef.current = fetch;
178
+ });
179
+
180
+ const hasFetch = Boolean(fetch);
181
+
182
+ React.useEffect(() => {
183
+ const run = fetchRef.current;
184
+ if (!run || !needs) return;
173
185
  const controller = new AbortController();
174
186
  setState((s) => ({ ...s, isFetching: true }));
175
- fetch({ ...scope, page: targetPage }, controller.signal).then(
187
+ run({ ...scope, page: targetPage }, controller.signal).then(
176
188
  (result) => {
177
189
  if (controller.signal.aborted) return;
178
190
  setState((s) => ({
@@ -189,9 +201,10 @@ function useLocalStrategy<Row>(
189
201
  },
190
202
  );
191
203
  return () => controller.abort();
192
- // `requestKey` is the identity of the request; `scope` and `targetPage` derive from it.
204
+ // `requestKey` is the identity of the request; `scope` and `targetPage` derive
205
+ // from it. `fetch` itself is held in a ref, so only its presence is a dep.
193
206
  // eslint-disable-next-line react-hooks/exhaustive-deps
194
- }, [fetch, requestKey, needs]);
207
+ }, [hasFetch, requestKey, needs]);
195
208
 
196
209
  // Like keepPreviousData: the last result stays on screen while the next loads.
197
210
  const rows = React.useMemo(
@@ -39,7 +39,7 @@ const MONTHS_LONG = [
39
39
  "November",
40
40
  "December",
41
41
  ];
42
- const MONTHS_SHORT = MONTHS_LONG.map((m) => m.slice(0, 3));
42
+ const MONTHS_SHORT = /* @__PURE__ */ MONTHS_LONG.map((m) => m.slice(0, 3));
43
43
 
44
44
  const pad = (n: number) => String(n).padStart(2, "0");
45
45
 
@@ -10,7 +10,7 @@ export interface ErrorBannerProps extends Omit<React.ComponentProps<"div">, "chi
10
10
  onRetry?: () => void;
11
11
  }
12
12
 
13
- const actionClass = cn(
13
+ const actionClass = /* @__PURE__ */ cn(
14
14
  "inline-flex items-center justify-center rounded-[var(--ds-radius-sm)] p-1",
15
15
  "text-[color:var(--ds-destructive)] hover:bg-[var(--ds-destructive)]/10",
16
16
  "outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ds-destructive)]/40",
@@ -27,7 +27,7 @@ import { cn } from "@/lib/cn";
27
27
  * narrows that to one constraint. Given `errors` (a react-hook-form error
28
28
  * list) it renders whenever the list has a message.
29
29
  */
30
- const fieldVariants = cva("group/field flex w-full gap-2", {
30
+ const fieldVariants = /* @__PURE__ */ cva("group/field flex w-full gap-2", {
31
31
  variants: {
32
32
  orientation: {
33
33
  vertical: "flex-col [&>*]:w-full [&>.sr-only]:w-auto",
@@ -47,7 +47,7 @@ export interface FieldProps
47
47
  // Base UI's Field.Error reads the control's computed validity only; the
48
48
  // external `invalid` prop reaches the data attributes but not the error's
49
49
  // visibility. Carry it so FieldError can show its static message.
50
- const FieldInvalidContext = React.createContext(false);
50
+ const FieldInvalidContext = /* @__PURE__ */ React.createContext(false);
51
51
 
52
52
  function Field({ className, orientation = "vertical", invalid, ...props }: FieldProps) {
53
53
  return (
@@ -66,7 +66,7 @@ type FormFieldContextValue<
66
66
  name: TName;
67
67
  };
68
68
 
69
- const FormFieldContext = React.createContext<FormFieldContextValue | null>(null);
69
+ const FormFieldContext = /* @__PURE__ */ React.createContext<FormFieldContextValue | null>(null);
70
70
 
71
71
  function FormField<
72
72
  TFieldValues extends FieldValues = FieldValues,
@@ -84,7 +84,7 @@ type FormItemContextValue = {
84
84
  id: string;
85
85
  };
86
86
 
87
- const FormItemContext = React.createContext<FormItemContextValue | null>(null);
87
+ const FormItemContext = /* @__PURE__ */ React.createContext<FormItemContextValue | null>(null);
88
88
 
89
89
  function useFormFieldState() {
90
90
  const fieldContext = React.useContext(FormFieldContext);
@@ -11,7 +11,7 @@ import { cn } from "@/lib/cn";
11
11
  * and takes the ring colour on focus. `aria-invalid` swaps the border and ring
12
12
  * for the destructive pair so a Field can mark errors without extra classes.
13
13
  */
14
- const inputClassName = cn(
14
+ const inputClassName = /* @__PURE__ */ cn(
15
15
  "flex h-10 w-full min-w-0 rounded-[var(--ds-radius-md)] border border-[var(--ds-border)] bg-[var(--ds-muted)] px-3 py-2",
16
16
  "text-[length:var(--ds-text-caption-lg)] leading-[var(--ds-text-caption-lg--line-height)] text-[color:var(--ds-foreground)]",
17
17
  "placeholder:text-[color:var(--ds-text-tertiary)]",
@@ -8,7 +8,7 @@ import { cn } from "@/lib/cn";
8
8
  * Label — a plain `<label>`. Base UI's Label lives inside Field, so this is
9
9
  * the standalone form caption for anything that is not a Field.
10
10
  */
11
- const labelVariants = cva([
11
+ const labelVariants = /* @__PURE__ */ cva([
12
12
  "inline-flex items-center gap-2 select-none",
13
13
  "text-[length:var(--ds-text-body-sm)] font-medium leading-none",
14
14
  "text-[color:var(--ds-foreground)]",
@@ -6,6 +6,7 @@ import ReactMarkdown, { type Components, type ExtraProps, type Options } from "r
6
6
  import rehypeSanitize, { defaultSchema, type Options as SanitizeSchema } from "rehype-sanitize";
7
7
  import remarkGfm from "remark-gfm";
8
8
  import { cn } from "@/lib/cn";
9
+ import { shakeable } from "@/lib/shakeable";
9
10
 
10
11
  /**
11
12
  * Markdown.
@@ -32,14 +33,14 @@ function hastText(node: HastChild | HastNode): string {
32
33
  }
33
34
 
34
35
  /** The GitHub schema, plus `class="language-*"` on code and `checked` on task boxes. */
35
- const markdownSanitizeSchema: SanitizeSchema = {
36
+ const markdownSanitizeSchema: SanitizeSchema = /* @__PURE__ */ shakeable(() => ({
36
37
  ...defaultSchema,
37
38
  attributes: {
38
39
  ...defaultSchema.attributes,
39
40
  code: [...(defaultSchema.attributes?.code ?? []), ["className", /^language-./]],
40
41
  input: [...(defaultSchema.attributes?.input ?? []), "checked"],
41
42
  },
42
- };
43
+ }));
43
44
 
44
45
  export interface CodeRendererProps {
45
46
  /** The fenced block's text, without a trailing newline. */
@@ -56,11 +57,11 @@ function dom<T extends object>(props: T & ExtraProps): T {
56
57
 
57
58
  const block = "my-3 first:mt-0 last:mb-0 group-data-[compact]/markdown:my-1.5";
58
59
 
59
- const body = cn(
60
+ const body = /* @__PURE__ */ cn(
60
61
  "text-[length:var(--ds-text-body-sm)] leading-[var(--ds-text-body-sm--line-height)] text-[color:var(--ds-foreground)]",
61
62
  );
62
63
 
63
- const heading = cn(
64
+ const heading = /* @__PURE__ */ cn(
64
65
  "font-[family-name:var(--ds-font-display)] text-[color:var(--ds-foreground)]",
65
66
  "mt-6 mb-2 first:mt-0 group-data-[compact]/markdown:mt-3 group-data-[compact]/markdown:mb-1",
66
67
  );
@@ -32,7 +32,7 @@ import { cn } from "@/lib/cn";
32
32
  * until the user closes it. `modal` is on the Root because that is where Base
33
33
  * UI reads it; `SheetContent` picks the backdrop up from there through context.
34
34
  */
35
- const SheetModalContext = React.createContext<boolean | "trap-focus">(true);
35
+ const SheetModalContext = /* @__PURE__ */ React.createContext<boolean | "trap-focus">(true);
36
36
 
37
37
  export interface SheetProps extends SheetPrimitive.Root.Props {
38
38
  /**
@@ -79,7 +79,7 @@ function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
79
79
  );
80
80
  }
81
81
 
82
- const sheetVariants = cva(
82
+ const sheetVariants = /* @__PURE__ */ cva(
83
83
  [
84
84
  "fixed z-50 flex flex-col gap-4 p-6 outline-none",
85
85
  "bg-[var(--ds-popover)] text-[color:var(--ds-popover-foreground)] shadow-[var(--ds-shadow-lg)]",
@@ -135,13 +135,13 @@ interface ItemContextValue {
135
135
  const noopRef = () => {};
136
136
  const inertHandle: SortableHandleProps = { ref: noopRef };
137
137
 
138
- const SortableItemContext = React.createContext<ItemContextValue>({
138
+ const SortableItemContext = /* @__PURE__ */ React.createContext<ItemContextValue>({
139
139
  handleProps: inertHandle,
140
140
  isDragging: false,
141
141
  disabled: false,
142
142
  });
143
143
 
144
- const itemClassName = cn(
144
+ const itemClassName = /* @__PURE__ */ cn(
145
145
  "relative rounded-[var(--ds-radius-md)] outline-none",
146
146
  "focus-visible:ring-[3px] focus-visible:ring-[var(--ds-ring)]/40",
147
147
  "data-[dragging]:opacity-50 data-[dragging]:ring-2 data-[dragging]:ring-[var(--ds-ring)]",
@@ -10,7 +10,7 @@ import { cn } from "@/lib/cn";
10
10
  * together in a form. `autoGrow` resizes the element to its content on every
11
11
  * change (and on mount), which is how chat composers and note fields use it.
12
12
  */
13
- const textareaClassName = cn(
13
+ const textareaClassName = /* @__PURE__ */ cn(
14
14
  "flex min-h-20 w-full min-w-0 rounded-[var(--ds-radius-md)] border border-[var(--ds-border)] bg-[var(--ds-muted)] px-3 py-2",
15
15
  "text-[length:var(--ds-text-caption-lg)] leading-[var(--ds-text-caption-lg--line-height)] text-[color:var(--ds-foreground)]",
16
16
  "placeholder:text-[color:var(--ds-text-tertiary)]",
@@ -23,7 +23,7 @@ import { cn } from "@/lib/cn";
23
23
  * `createToastManager()` from `@base-ui/react/toast` and pass it as
24
24
  * `toastManager` to `Toaster` when you need to fire toasts outside React.
25
25
  */
26
- const toastVariants = cva(
26
+ const toastVariants = /* @__PURE__ */ cva(
27
27
  [
28
28
  "pointer-events-auto relative flex w-full items-start gap-3 p-4",
29
29
  "rounded-[var(--ds-radius-lg)] border shadow-[var(--ds-shadow-lg)]",
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `cortena-ui/a2ui` — the A2UI catalogue and renderer.
3
+ *
4
+ * Layer 1 of `cortenaUI&Design/05-agent-ui.md`. The catalogue names every view
5
+ * and every view names a component, so this entry reaches most of the package
6
+ * by design: it is the vocabulary an agent may draw with, and an agent may draw
7
+ * with all of it. That is why it is its own entry rather than something the
8
+ * root barrel forces on every consumer.
9
+ */
10
+
11
+ export * from "@/a2ui";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `cortena-ui/chart` — the Chart composite and the themed Recharts primitives.
3
+ *
4
+ * Importing this entry is what makes an app pay for a charting engine.
5
+ * Recharts is loaded on first render of a Recharts chart type and every
6
+ * `@nivo/*` package on first render of a Nivo one, so an app that imports
7
+ * `Chart` but renders none still ships no engine.
8
+ */
9
+
10
+ export * from "@/components/chart";
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `cortena-ui/core` — every component that carries no heavy dependency.
3
+ *
4
+ * The primitives, the overlays, the light form controls, the theme hook and
5
+ * `cn`. Nothing here reaches recharts, nivo, exceljs, dnd-kit, react-markdown,
6
+ * react-day-picker, react-dropzone, react-hook-form, zod or TanStack Table, so
7
+ * this is the entry to import from when a bundle's size is the constraint and
8
+ * you do not want to depend on tree-shaking working perfectly.
9
+ *
10
+ * Everything here is also exported from the root barrel; see README.md,
11
+ * "Entry points".
12
+ */
13
+
14
+ export type { AlertProps } from "@/components/alert";
15
+ export type { BadgeProps } from "@/components/badge";
16
+ export type { BreadcrumbLinkProps } from "@/components/breadcrumb";
17
+ export type { ButtonLinkProps } from "@/components/button-link";
18
+ export type { ButtonProps } from "@/components/button";
19
+ export type { CardProps } from "@/components/card";
20
+ export type { CheckboxProps } from "@/components/checkbox";
21
+ export type { ChipProps } from "@/components/chip";
22
+ export type { ComboboxChipProps, ComboboxChipsProps, ComboboxContentProps, ComboboxInputProps } from "@/components/combobox";
23
+ export type { CommandDialogProps, CommandItemProps } from "@/components/command";
24
+ export type { CortenaTheme, CortenaThemeMessage, ResolvedCortenaTheme, UseCortenaThemeOptions, UseCortenaThemeResult } from "@/hooks/use-cortena-theme";
25
+ export type { DialogContentProps } from "@/components/dialog";
26
+ export type { DropdownMenuContentProps, DropdownMenuItemProps, DropdownMenuLabelProps, DropdownMenuSubTriggerProps } from "@/components/dropdown-menu";
27
+ export type { EmptyStateProps } from "@/components/empty-state";
28
+ export type { ErrorBannerProps } from "@/components/error-banner";
29
+ export type { FieldControlProps, FieldDescriptionProps, FieldErrorItem, FieldErrorProps, FieldLabelProps, FieldProps, FieldsetLegendProps, FieldsetProps } from "@/components/field";
30
+ export type { InputProps } from "@/components/input";
31
+ export type { LabelProps } from "@/components/label";
32
+ export type { LoadingSkeletonPreset, LoadingSkeletonProps } from "@/components/loading-skeleton";
33
+ export type { PageHeaderProps } from "@/components/page-header";
34
+ export type { PopoverContentProps } from "@/components/popover";
35
+ export type { ProgressProps } from "@/components/progress";
36
+ export type { RadioGroupItemProps, RadioGroupProps } from "@/components/radio-group";
37
+ export type { ScrollAreaProps } from "@/components/scroll-area";
38
+ export type { SectionCardProps } from "@/components/section-card";
39
+ export type { SegmentedOption, SegmentedProps } from "@/components/segmented";
40
+ export type { SelectContentProps, SelectProps, SelectTriggerProps } from "@/components/select";
41
+ export type { SeparatorProps } from "@/components/separator";
42
+ export type { SheetContentProps, SheetProps } from "@/components/sheet";
43
+ export type { SpinnerProps } from "@/components/spinner";
44
+ export type { StatusDotProps, StatusDotTone } from "@/components/status-dot";
45
+ export type { SwitchProps } from "@/components/switch";
46
+ export type { TextareaProps } from "@/components/textarea";
47
+ export type { ToastProps, ToasterProps } from "@/components/toast";
48
+ export type { ToolbarProps } from "@/components/toolbar";
49
+ export type { TooltipContentProps } from "@/components/tooltip";
50
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/accordion";
51
+ export { Alert, AlertDescription, AlertIcon, AlertTitle, alertVariants } from "@/components/alert";
52
+ export { Avatar, AvatarFallback, AvatarImage } from "@/components/avatar";
53
+ export { Badge, badgeVariants } from "@/components/badge";
54
+ export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/breadcrumb";
55
+ export { Button, buttonVariants } from "@/components/button";
56
+ export { ButtonLink } from "@/components/button-link";
57
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/card";
58
+ export { Checkbox } from "@/components/checkbox";
59
+ export { Chip, chipVariants } from "@/components/chip";
60
+ export { Combobox, ComboboxChip, ComboboxChips, ComboboxClear, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, useComboboxFilter } from "@/components/combobox";
61
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut } from "@/components/command";
62
+ export { DEFAULT_THEME_STORAGE_KEY, THEME_MESSAGE_TYPE, applyStoredTheme, applyTheme, getThemeInitScript, readStoredTheme, themeFromBackground, themeFromMessage, themeInitScript, useCortenaTheme } from "@/hooks/use-cortena-theme";
63
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "@/components/dialog";
64
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/dropdown-menu";
65
+ export { EmptyState } from "@/components/empty-state";
66
+ export { ErrorBanner } from "@/components/error-banner";
67
+ export { Field, FieldContent, FieldControl, FieldDescription, FieldError, FieldGroup, FieldLabel, Fieldset, FieldsetLegend, fieldVariants } from "@/components/field";
68
+ export { Input, inputClassName } from "@/components/input";
69
+ export { Kbd } from "@/components/kbd";
70
+ export { Label, labelVariants } from "@/components/label";
71
+ export { LoadingSkeleton } from "@/components/loading-skeleton";
72
+ export { PageHeader } from "@/components/page-header";
73
+ export { Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "@/components/popover";
74
+ export { Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue } from "@/components/progress";
75
+ export { RadioGroup, RadioGroupItem } from "@/components/radio-group";
76
+ export { ScrollArea, ScrollBar } from "@/components/scroll-area";
77
+ export { SectionCard } from "@/components/section-card";
78
+ export { Segmented } from "@/components/segmented";
79
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from "@/components/select";
80
+ export { Separator } from "@/components/separator";
81
+ export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, sheetVariants } from "@/components/sheet";
82
+ export { Skeleton } from "@/components/skeleton";
83
+ export { Spinner } from "@/components/spinner";
84
+ export { StatusDot } from "@/components/status-dot";
85
+ export { Switch } from "@/components/switch";
86
+ export { Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger } from "@/components/tabs";
87
+ export { Textarea, textareaClassName } from "@/components/textarea";
88
+ export { Toast, Toaster, toastVariants, useToast } from "@/components/toast";
89
+ export { Toolbar, ToolbarEnd, ToolbarSeparator, ToolbarStart } from "@/components/toolbar";
90
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/tooltip";
91
+ export { cn } from "@/lib/cn";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `cortena-ui/data-table` — DataTable, its parts, and the export helpers.
3
+ *
4
+ * Brings `@tanstack/react-table` and `@tanstack/react-virtual`. exceljs is
5
+ * loaded on the first `downloadExcel` call and never before, so a table that is
6
+ * only ever read costs nothing for the workbook writer.
7
+ */
8
+
9
+ export * from "@/components/data-table";