@siyahi/ui 0.1.9-next.3 → 0.1.9-next.31

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 (254) hide show
  1. package/DESIGN.md +251 -0
  2. package/README.md +94 -177
  3. package/THIRD_PARTY_NOTICES.md +11 -11
  4. package/agents/examples/accordion.tsx +39 -0
  5. package/agents/examples/alert.tsx +24 -0
  6. package/agents/examples/app-sidebar.tsx +40 -0
  7. package/agents/examples/avatar.tsx +24 -0
  8. package/agents/examples/badge.tsx +26 -0
  9. package/agents/examples/bar-list-labels.tsx +22 -0
  10. package/agents/examples/bar-list-sides.tsx +40 -0
  11. package/agents/examples/bar-list.tsx +24 -0
  12. package/agents/examples/breadcrumb.tsx +28 -0
  13. package/agents/examples/button-states.tsx +23 -0
  14. package/agents/examples/button.tsx +21 -0
  15. package/agents/examples/calendar.tsx +11 -0
  16. package/agents/examples/callout.tsx +33 -0
  17. package/agents/examples/card.tsx +36 -0
  18. package/agents/examples/change-bar.tsx +104 -0
  19. package/agents/examples/change-grid-money.tsx +36 -0
  20. package/agents/examples/change-grid.tsx +43 -0
  21. package/agents/examples/chart-area-log.tsx +45 -0
  22. package/agents/examples/chart-area.tsx +39 -0
  23. package/agents/examples/chart-bar-flows.tsx +32 -0
  24. package/agents/examples/chart-bar-hourly.tsx +28 -0
  25. package/agents/examples/chart-bar-losses.tsx +29 -0
  26. package/agents/examples/chart-bar-teams.tsx +72 -0
  27. package/agents/examples/chart-bar-years.tsx +42 -0
  28. package/agents/examples/chart-bar.tsx +56 -0
  29. package/agents/examples/chart-category-ticks.tsx +50 -0
  30. package/agents/examples/chart-line-events.tsx +47 -0
  31. package/agents/examples/chart-line-forecast.tsx +36 -0
  32. package/agents/examples/chart-line-log.tsx +39 -0
  33. package/agents/examples/chart-line-quiet.tsx +114 -0
  34. package/agents/examples/chart-line-timeline.tsx +41 -0
  35. package/agents/examples/chart-line.tsx +57 -0
  36. package/agents/examples/chart-panels.tsx +94 -0
  37. package/agents/examples/code-block.tsx +40 -0
  38. package/agents/examples/collapsible.tsx +18 -0
  39. package/agents/examples/command.tsx +29 -0
  40. package/agents/examples/context-menu.tsx +17 -0
  41. package/agents/examples/copy-button.tsx +8 -0
  42. package/agents/examples/data-bar.tsx +114 -0
  43. package/agents/examples/data-table-compact.tsx +93 -0
  44. package/agents/examples/data-table-filters.tsx +103 -0
  45. package/agents/examples/data-table.tsx +96 -0
  46. package/agents/examples/delta.tsx +18 -0
  47. package/agents/examples/dialog.tsx +28 -0
  48. package/agents/examples/distribution-bar-budget.tsx +30 -0
  49. package/agents/examples/distribution-bar-tug.tsx +74 -0
  50. package/agents/examples/drawdown-chart.tsx +35 -0
  51. package/agents/examples/dropdown-menu.tsx +31 -0
  52. package/agents/examples/field.tsx +108 -0
  53. package/agents/examples/formatters.tsx +42 -0
  54. package/agents/examples/heatmap-calendar-signed.tsx +67 -0
  55. package/agents/examples/heatmap-calendar.tsx +62 -0
  56. package/agents/examples/heatmap-status.tsx +61 -0
  57. package/agents/examples/heatmap-weekday.tsx +72 -0
  58. package/agents/examples/histogram-chart.tsx +28 -0
  59. package/agents/examples/input-states.tsx +23 -0
  60. package/agents/examples/input.tsx +17 -0
  61. package/agents/examples/local-time.tsx +14 -0
  62. package/agents/examples/metric-strip.tsx +46 -0
  63. package/agents/examples/overview-dashboard.tsx +180 -0
  64. package/agents/examples/page-hero.tsx +38 -0
  65. package/agents/examples/page-section.tsx +52 -0
  66. package/agents/examples/popover.tsx +23 -0
  67. package/agents/examples/price-chart.tsx +32 -0
  68. package/agents/examples/progress-tone.tsx +29 -0
  69. package/agents/examples/progress.tsx +10 -0
  70. package/agents/examples/range-position-table.tsx +113 -0
  71. package/agents/examples/range-position.tsx +55 -0
  72. package/agents/examples/scatter-chart-quadrants.tsx +63 -0
  73. package/agents/examples/scatter-chart-scales.tsx +46 -0
  74. package/agents/examples/scatter-chart.tsx +78 -0
  75. package/agents/examples/scroll-area.tsx +22 -0
  76. package/agents/examples/section-cards-select.tsx +28 -0
  77. package/agents/examples/section-cards-trend.tsx +32 -0
  78. package/agents/examples/section-cards.tsx +48 -0
  79. package/agents/examples/select.tsx +27 -0
  80. package/agents/examples/separator.tsx +13 -0
  81. package/agents/examples/sheet.tsx +15 -0
  82. package/agents/examples/skeleton.tsx +11 -0
  83. package/agents/examples/slider.tsx +5 -0
  84. package/agents/examples/slope-chart-market.tsx +33 -0
  85. package/agents/examples/slope-chart.tsx +26 -0
  86. package/agents/examples/stale-blocks.tsx +56 -0
  87. package/agents/examples/surfaces.tsx +116 -0
  88. package/agents/examples/table.tsx +60 -0
  89. package/agents/examples/tabs.tsx +16 -0
  90. package/agents/examples/target-rows.tsx +74 -0
  91. package/agents/examples/toggle-group.tsx +12 -0
  92. package/agents/examples/toggle.tsx +11 -0
  93. package/agents/examples/tooltip.tsx +13 -0
  94. package/agents/examples/treemap.tsx +93 -0
  95. package/agents/examples/waterfall-chart-stores.tsx +27 -0
  96. package/agents/examples/waterfall-chart.tsx +37 -0
  97. package/agents/manifest.json +1391 -0
  98. package/agents/report-rules.json +7 -0
  99. package/dist/components/registry/charts/area-chart-card.d.ts +7 -3
  100. package/dist/components/registry/charts/area-chart-card.js +56 -10
  101. package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
  102. package/dist/components/registry/charts/bar-chart-card.js +20 -22
  103. package/dist/components/registry/charts/line-chart-card.d.ts +3 -3
  104. package/dist/components/registry/charts/line-chart-card.js +44 -9
  105. package/dist/components/registry/dashboard-01/section-cards.d.ts +6 -0
  106. package/dist/components/registry/dashboard-01/section-cards.js +51 -35
  107. package/dist/components/registry/dashboardcn/bar-list.js +17 -10
  108. package/dist/components/registry/dashboardcn/distribution-bar.js +6 -4
  109. package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
  110. package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
  111. package/dist/components/registry/dashboardcn/sparkline.d.ts +22 -0
  112. package/dist/components/registry/dashboardcn/sparkline.js +117 -0
  113. package/dist/components/registry/heatmap/calendar-heatmap.d.ts +11 -3
  114. package/dist/components/registry/heatmap/calendar-heatmap.js +164 -45
  115. package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
  116. package/dist/components/registry/heatmap/status-heatmap.js +115 -54
  117. package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
  118. package/dist/components/registry/heatmap/weekday-heatmap.js +83 -53
  119. package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
  120. package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
  121. package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
  122. package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
  123. package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
  124. package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
  125. package/dist/components/registry/niko-table/core/data-table.js +5 -1
  126. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +5 -5
  127. package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
  128. package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
  129. package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
  130. package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
  131. package/dist/components/registry/niko-table/lib/styles.js +3 -3
  132. package/dist/components/registry/niko-table/types/index.d.ts +9 -0
  133. package/dist/components/registry/niko-table/ui/table.js +2 -2
  134. package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
  135. package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
  136. package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
  137. package/dist/components/registry/sidebar-07/nav-main.js +16 -3
  138. package/dist/components/siyahi/callout.d.ts +17 -0
  139. package/dist/components/siyahi/callout.js +34 -0
  140. package/dist/components/siyahi/change-bar.d.ts +21 -0
  141. package/dist/components/siyahi/change-bar.js +35 -0
  142. package/dist/components/siyahi/change-grid.d.ts +31 -0
  143. package/dist/components/siyahi/change-grid.js +74 -0
  144. package/dist/components/siyahi/data-bar.d.ts +19 -0
  145. package/dist/components/siyahi/data-bar.js +29 -0
  146. package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
  147. package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
  148. package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
  149. package/dist/components/siyahi/data-table-footnote.js +35 -0
  150. package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
  151. package/dist/components/siyahi/default-sidebar-open.js +13 -0
  152. package/dist/components/siyahi/delta.d.ts +5 -1
  153. package/dist/components/siyahi/delta.js +14 -9
  154. package/dist/components/siyahi/drawdown-chart.d.ts +34 -0
  155. package/dist/components/siyahi/drawdown-chart.js +102 -0
  156. package/dist/components/siyahi/histogram-chart.d.ts +57 -0
  157. package/dist/components/siyahi/histogram-chart.js +134 -0
  158. package/dist/components/siyahi/page-hero.d.ts +23 -0
  159. package/dist/components/siyahi/page-hero.js +43 -0
  160. package/dist/components/siyahi/page-section.d.ts +4 -1
  161. package/dist/components/siyahi/page-section.js +6 -3
  162. package/dist/components/siyahi/page-toc.d.ts +20 -0
  163. package/dist/components/siyahi/page-toc.js +76 -0
  164. package/dist/components/siyahi/panel-grid.d.ts +24 -0
  165. package/dist/components/siyahi/panel-grid.js +37 -0
  166. package/dist/components/siyahi/quote.d.ts +12 -0
  167. package/dist/components/siyahi/quote.js +23 -0
  168. package/dist/components/siyahi/range-position.d.ts +24 -0
  169. package/dist/components/siyahi/range-position.js +105 -0
  170. package/dist/components/siyahi/scale-toggle.d.ts +32 -0
  171. package/dist/components/siyahi/scale-toggle.js +61 -0
  172. package/dist/components/siyahi/scatter-chart.d.ts +69 -0
  173. package/dist/components/siyahi/scatter-chart.js +395 -0
  174. package/dist/components/siyahi/siyahi-provider.d.ts +15 -2
  175. package/dist/components/siyahi/siyahi-provider.js +17 -4
  176. package/dist/components/siyahi/slope-chart.d.ts +35 -0
  177. package/dist/components/siyahi/slope-chart.js +159 -0
  178. package/dist/components/siyahi/stale-note.d.ts +9 -0
  179. package/dist/components/siyahi/stale-note.js +12 -0
  180. package/dist/components/siyahi/status-alert.d.ts +15 -0
  181. package/dist/components/siyahi/status-alert.js +29 -0
  182. package/dist/components/siyahi/status-badge.d.ts +15 -0
  183. package/dist/components/siyahi/status-badge.js +24 -0
  184. package/dist/components/siyahi/target-rows.d.ts +34 -0
  185. package/dist/components/siyahi/target-rows.js +97 -0
  186. package/dist/components/siyahi/tone-progress.d.ts +1 -1
  187. package/dist/components/siyahi/tone-progress.js +1 -1
  188. package/dist/components/siyahi/treemap.d.ts +8 -5
  189. package/dist/components/siyahi/treemap.js +80 -34
  190. package/dist/components/siyahi/waterfall-chart.d.ts +51 -0
  191. package/dist/components/siyahi/waterfall-chart.js +147 -0
  192. package/dist/components/ui/accordion.js +5 -5
  193. package/dist/components/ui/alert.js +2 -2
  194. package/dist/components/ui/badge.js +1 -1
  195. package/dist/components/ui/breadcrumb.js +2 -2
  196. package/dist/components/ui/button.js +10 -10
  197. package/dist/components/ui/calendar.js +1 -1
  198. package/dist/components/ui/card.js +4 -4
  199. package/dist/components/ui/chart.js +1 -1
  200. package/dist/components/ui/code-block.js +13 -12
  201. package/dist/components/ui/command.js +7 -6
  202. package/dist/components/ui/context-menu.js +7 -7
  203. package/dist/components/ui/dialog.js +5 -5
  204. package/dist/components/ui/dropdown-menu.js +8 -8
  205. package/dist/components/ui/field.d.ts +26 -0
  206. package/dist/components/ui/field.js +109 -0
  207. package/dist/components/ui/input-group.js +11 -11
  208. package/dist/components/ui/input.js +1 -1
  209. package/dist/components/ui/label.d.ts +5 -0
  210. package/dist/components/ui/label.js +13 -0
  211. package/dist/components/ui/popover.js +3 -3
  212. package/dist/components/ui/progress.js +1 -1
  213. package/dist/components/ui/select.js +6 -6
  214. package/dist/components/ui/sheet.js +5 -5
  215. package/dist/components/ui/sidebar.js +17 -18
  216. package/dist/components/ui/skeleton.js +1 -1
  217. package/dist/components/ui/slider.js +2 -2
  218. package/dist/components/ui/table.js +2 -2
  219. package/dist/components/ui/tabs.js +2 -2
  220. package/dist/components/ui/textarea.js +1 -1
  221. package/dist/components/ui/toggle-group.js +2 -2
  222. package/dist/components/ui/toggle.js +4 -4
  223. package/dist/components/ui/tooltip.js +2 -2
  224. package/dist/index.d.ts +35 -8
  225. package/dist/index.js +30 -4
  226. package/dist/lib/chart-frame.d.ts +51 -7
  227. package/dist/lib/chart-frame.js +390 -133
  228. package/dist/lib/chart-marks.d.ts +83 -0
  229. package/dist/lib/chart-marks.js +216 -0
  230. package/dist/lib/chart-series.d.ts +42 -10
  231. package/dist/lib/compact-columns.d.ts +19 -0
  232. package/dist/lib/compact-columns.js +55 -0
  233. package/dist/lib/fit-text.d.ts +6 -0
  234. package/dist/lib/fit-text.js +11 -0
  235. package/dist/lib/format.d.ts +8 -3
  236. package/dist/lib/format.js +55 -17
  237. package/dist/lib/heat.d.ts +7 -0
  238. package/dist/lib/heat.js +14 -0
  239. package/dist/lib/heatmap-navigation.d.ts +8 -0
  240. package/dist/lib/heatmap-navigation.js +49 -0
  241. package/dist/lib/scatter.d.ts +88 -0
  242. package/dist/lib/scatter.js +179 -0
  243. package/dist/lib/ticks.d.ts +27 -0
  244. package/dist/lib/ticks.js +67 -0
  245. package/dist/lib/tone.d.ts +36 -0
  246. package/dist/lib/tone.js +35 -0
  247. package/dist/lib/treemap.d.ts +0 -5
  248. package/dist/lib/treemap.js +1 -11
  249. package/dist/lib/use-element-width.d.ts +5 -0
  250. package/dist/lib/use-element-width.js +15 -0
  251. package/package.json +5 -1
  252. package/registry.lock.json +16 -0
  253. package/report.css +63 -47
  254. package/styles/siyahi.css +708 -55
@@ -0,0 +1,7 @@
1
+ [
2
+ "Never paint html or body beyond the base styles report.css sets.",
3
+ "Fluid width. No outer card and no banner title.",
4
+ "A panel with its own background gets 16px padding and var(--radius).",
5
+ "Charts get fixed pixel heights.",
6
+ "Never use 100vh."
7
+ ]
@@ -1,10 +1,14 @@
1
- import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
1
+ import { ChartCurve, LineMarksProps, NumericXProps, SeriesChartProps, ValueScaleProps } from "../../../lib/chart-series.js";
2
2
  //#region src/components/registry/charts/area-chart-card.d.ts
3
- export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
3
+ export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps, ValueScaleProps, LineMarksProps<T, K> {
4
4
  /** Stack the series into a total instead of overlapping them. */
5
5
  stacked?: boolean;
6
6
  curve?: ChartCurve;
7
7
  }
8
- /** Values over an ordered axis as filled areas: one series, or several overlapping or stacked. */
8
+ /**
9
+ * Values over an ordered axis: overlapping series drawn as lines, or stacked into a total as tinted bands. A
10
+ * stack keeps solid edges through a forecast stretch, since a dashed copy of a band would stack twice; the hatched
11
+ * band still marks it.
12
+ */
9
13
  export declare function AreaChartCard<T extends object, K extends keyof T>({ stacked, curve, ...props }: AreaChartCardProps<T, K>): import("react").JSX.Element;
10
14
  //#endregion
@@ -1,21 +1,67 @@
1
1
  "use client";
2
- import { ChartFrame } from "../../../lib/chart-frame.js";
3
- import { jsx } from "react/jsx-runtime";
2
+ import { QUIET, drawOrder } from "../../../lib/chart-marks.js";
3
+ import { ChartFrame, endDot } from "../../../lib/chart-frame.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Fragment as Fragment$1 } from "react";
4
6
  import { Area, AreaChart } from "recharts";
5
7
  //#region src/components/registry/charts/area-chart-card.tsx
6
- /** Values over an ordered axis as filled areas: one series, or several overlapping or stacked. */
8
+ /**
9
+ * Values over an ordered axis: overlapping series drawn as lines, or stacked into a total as tinted bands. A
10
+ * stack keeps solid edges through a forecast stretch, since a dashed copy of a band would stack twice; the hatched
11
+ * band still marks it.
12
+ */
7
13
  function AreaChartCard({ stacked = false, curve = "monotone", ...props }) {
8
- return /* @__PURE__ */ jsx(ChartFrame, {
14
+ const forecastEnd = props.forecastFrom !== void 0;
15
+ const forecast = !stacked && forecastEnd;
16
+ const count = props.data.length;
17
+ const series = stacked ? props.series : drawOrder(props.series);
18
+ return /* @__PURE__ */ jsxs(ChartFrame, {
9
19
  chart: AreaChart,
20
+ logBlocked: stacked ? "Log cannot show stacked areas" : void 0,
21
+ endLabels: !stacked,
22
+ forecastHatch: !stacked,
23
+ curve,
10
24
  ...props,
11
- children: props.series.map(({ key, color }) => /* @__PURE__ */ jsx(Area, {
25
+ children: [forecast && series.map(({ key }) => /* @__PURE__ */ jsx(Area, {
12
26
  dataKey: key,
13
27
  type: curve,
14
- fill: color,
15
- fillOpacity: stacked ? .4 : .2,
16
- stroke: color,
17
- stackId: stacked ? "stack" : void 0
18
- }, key))
28
+ fill: "none",
29
+ stroke: "var(--card)",
30
+ strokeWidth: 6,
31
+ dot: false,
32
+ activeDot: false,
33
+ tooltipType: "none",
34
+ legendType: "none",
35
+ className: "chart-forecast",
36
+ animationDuration: 1300
37
+ }, `halo-${key}`)), series.map(({ key, color }) => {
38
+ const quiet = color === QUIET;
39
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Area, {
40
+ dataKey: key,
41
+ type: curve,
42
+ fill: stacked ? color : "none",
43
+ fillOpacity: stacked ? .25 : void 0,
44
+ stroke: color,
45
+ strokeWidth: 2,
46
+ dot: quiet || forecast ? false : endDot(color, count, forecastEnd),
47
+ stackId: stacked ? "stack" : void 0,
48
+ className: forecast ? "chart-actual" : void 0,
49
+ animationDuration: 1300
50
+ }), forecast && /* @__PURE__ */ jsx(Area, {
51
+ dataKey: key,
52
+ type: curve,
53
+ fill: "none",
54
+ stroke: color,
55
+ strokeWidth: 2,
56
+ strokeDasharray: "5 4",
57
+ dot: quiet ? false : endDot(color, count, true),
58
+ activeDot: false,
59
+ tooltipType: "none",
60
+ legendType: "none",
61
+ className: "chart-forecast",
62
+ animationDuration: 1300
63
+ })] }, key);
64
+ })]
19
65
  });
20
66
  }
21
67
  //#endregion
@@ -3,7 +3,7 @@ import { SeriesChartProps } from "../../../lib/chart-series.js";
3
3
  export interface BarChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K> {
4
4
  /** Stack the series in one bar per point instead of side by side. */
5
5
  stacked?: boolean;
6
- /** Bars run sideways, categories down the left: for long names, such as sectors. */
6
+ /** Bars run sideways, categories down the left: for long names, such as product categories. */
7
7
  horizontal?: boolean;
8
8
  /** The picked category's x value: its bars stay solid and the rest fade. */
9
9
  selected?: T[K] | null;
@@ -1,41 +1,39 @@
1
1
  "use client";
2
- import { ChartFrame, seriesFill } from "../../../lib/chart-frame.js";
2
+ import { ChartFrame, barFill, seriesFill } from "../../../lib/chart-frame.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { Bar, BarChart, Cell } from "recharts";
5
5
  //#region src/components/registry/charts/bar-chart-card.tsx
6
+ const DOWN_FROM_ZERO = ["auto", 0];
6
7
  /** Values over an ordered axis as bars: one series, or several grouped or stacked. */
7
8
  function BarChartCard({ stacked = false, selected = null, onSelect, ...props }) {
8
9
  return /* @__PURE__ */ jsx(ChartFrame, {
9
10
  chart: BarChart,
10
11
  ...props,
12
+ yDomain: props.yDomain ?? (props.data.some((row) => props.series.some(({ key }) => Number(row[key]) > 0)) ? void 0 : DOWN_FROM_ZERO),
11
13
  stackOffset: stacked ? "sign" : void 0,
12
- children: props.series.map((item, index) => {
14
+ onClick: onSelect ? ({ activeTooltipIndex, isTooltipActive }) => {
15
+ if (!isTooltipActive || activeTooltipIndex == null) return;
16
+ const row = props.data[Number(activeTooltipIndex)];
17
+ if (row) onSelect(row[props.xKey] === selected ? null : row[props.xKey]);
18
+ } : void 0,
19
+ children: props.series.map((item) => {
13
20
  const { key, label, color, negativeColor } = item;
14
21
  return /* @__PURE__ */ jsx(Bar, {
15
22
  dataKey: key,
16
23
  name: label,
17
24
  fill: seriesFill(item, props.data),
25
+ maxBarSize: props.horizontal ? 24 : void 0,
18
26
  stackId: stacked ? "stack" : void 0,
19
- radius: !stacked ? 2 : index === props.series.length - 1 ? props.horizontal ? [
20
- 0,
21
- 2,
22
- 2,
23
- 0
24
- ] : [
25
- 2,
26
- 2,
27
- 0,
28
- 0
29
- ] : 0,
30
- className: onSelect ? "cursor-pointer" : void 0,
31
- onClick: onSelect && ((bar) => {
32
- const value = bar.payload?.[props.xKey];
33
- if (value !== void 0) onSelect(value === selected ? null : value);
34
- }),
35
- children: (negativeColor || selected !== null) && props.data.map((row, i) => /* @__PURE__ */ jsx(Cell, {
36
- fill: negativeColor && Number(row[key]) < 0 ? negativeColor : color,
37
- fillOpacity: selected === null || row[props.xKey] === selected ? 1 : .35
38
- }, i))
27
+ isAnimationActive: false,
28
+ children: props.data.map((row, i) => {
29
+ const tone = negativeColor && Number(row[key]) < 0 ? negativeColor : color;
30
+ const dim = selected !== null && row[props.xKey] !== selected;
31
+ return /* @__PURE__ */ jsx(Cell, {
32
+ fill: barFill(tone, dim),
33
+ stroke: tone,
34
+ strokeWidth: 1
35
+ }, i);
36
+ })
39
37
  }, key);
40
38
  })
41
39
  });
@@ -1,8 +1,8 @@
1
- import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
1
+ import { ChartCurve, LineMarksProps, NumericXProps, SeriesChartProps, ValueScaleProps } from "../../../lib/chart-series.js";
2
2
  //#region src/components/registry/charts/line-chart-card.d.ts
3
- export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
3
+ export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps, ValueScaleProps, LineMarksProps<T, K> {
4
4
  curve?: ChartCurve;
5
5
  }
6
- /** Values over an ordered axis as lines: one series, or several to compare, such as a portfolio against its index. */
6
+ /** Values over an ordered axis as lines: one series, or several to compare, such as sales against a target. */
7
7
  export declare function LineChartCard<T extends object, K extends keyof T>({ curve, ...props }: LineChartCardProps<T, K>): import("react").JSX.Element;
8
8
  //#endregion
@@ -1,20 +1,55 @@
1
1
  "use client";
2
- import { ChartFrame } from "../../../lib/chart-frame.js";
3
- import { jsx } from "react/jsx-runtime";
2
+ import { drawOrder } from "../../../lib/chart-marks.js";
3
+ import { ChartFrame, endDot } from "../../../lib/chart-frame.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Fragment as Fragment$1 } from "react";
4
6
  import { Line, LineChart } from "recharts";
5
7
  //#region src/components/registry/charts/line-chart-card.tsx
6
- /** Values over an ordered axis as lines: one series, or several to compare, such as a portfolio against its index. */
8
+ /** Values over an ordered axis as lines: one series, or several to compare, such as sales against a target. */
7
9
  function LineChartCard({ curve = "monotone", ...props }) {
8
- return /* @__PURE__ */ jsx(ChartFrame, {
10
+ const forecast = props.forecastFrom !== void 0;
11
+ const count = props.data.length;
12
+ const series = drawOrder(props.series);
13
+ return /* @__PURE__ */ jsxs(ChartFrame, {
9
14
  chart: LineChart,
15
+ endLabels: true,
16
+ curve,
10
17
  ...props,
11
- children: props.series.map(({ key, color }) => /* @__PURE__ */ jsx(Line, {
18
+ children: [forecast && series.map(({ key }) => /* @__PURE__ */ jsx(Line, {
12
19
  dataKey: key,
13
20
  type: curve,
14
- stroke: color,
15
- strokeWidth: 2,
16
- dot: false
17
- }, key))
21
+ stroke: "var(--card)",
22
+ strokeWidth: 6,
23
+ dot: false,
24
+ activeDot: false,
25
+ tooltipType: "none",
26
+ legendType: "none",
27
+ className: "chart-forecast",
28
+ animationDuration: 1300
29
+ }, `halo-${key}`)), series.map(({ key, color }) => {
30
+ const dot = color === "var(--muted-foreground)" || forecast ? false : endDot(color, count);
31
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Line, {
32
+ dataKey: key,
33
+ type: curve,
34
+ stroke: color,
35
+ strokeWidth: 2,
36
+ dot,
37
+ className: forecast ? "chart-actual" : void 0,
38
+ animationDuration: 1300
39
+ }), forecast && /* @__PURE__ */ jsx(Line, {
40
+ dataKey: key,
41
+ type: curve,
42
+ stroke: color,
43
+ strokeWidth: 2,
44
+ strokeDasharray: "5 4",
45
+ dot: color === "var(--muted-foreground)" ? false : endDot(color, count, true),
46
+ activeDot: false,
47
+ tooltipType: "none",
48
+ legendType: "none",
49
+ className: "chart-forecast",
50
+ animationDuration: 1300
51
+ })] }, key);
52
+ })]
18
53
  });
19
54
  }
20
55
  //#endregion
@@ -6,12 +6,18 @@ export interface SectionCard {
6
6
  value: React$1.ReactNode;
7
7
  /** Outline badge, top right; usually a <Delta />. */
8
8
  badge?: React$1.ReactNode;
9
+ /** A small chart under the value, usually a <Sparkline /> of the recent run. */
10
+ trend?: React$1.ReactNode;
9
11
  /** Bold first footer line. */
10
12
  headline?: React$1.ReactNode;
11
13
  /** Muted second footer line. */
12
14
  detail?: React$1.ReactNode;
13
15
  /** In a picker, a tile that cannot be picked, such as one with nothing in it: faded, and its button disabled. */
14
16
  disabled?: boolean;
17
+ /** Marks the tile as the exception on the page: a faint wash of the colour and an outline of it. */
18
+ tone?: "negative" | "warning";
19
+ /** Marks the tile's data as old, with since when, such as "3 Nov": the tile greys out and says so. */
20
+ stale?: React$1.ReactNode;
15
21
  }
16
22
  export interface SectionCardsProps {
17
23
  items: SectionCard[];
@@ -1,7 +1,9 @@
1
1
  "use client";
2
2
  import { Badge } from "../../ui/badge.js";
3
- import { Card, CardAction, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
3
+ import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
4
4
  import { cn } from "../../../lib/utils.js";
5
+ import { StaleNote } from "../../siyahi/stale-note.js";
6
+ import { useSurface } from "../../siyahi/siyahi-provider.js";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  import "react";
7
9
  //#region src/components/registry/dashboard-01/section-cards.tsx
@@ -13,43 +15,57 @@ const COLUMNS = {
13
15
  6: "@3xl/main:grid-cols-3"
14
16
  };
15
17
  function SectionCards({ items, selected, onSelect }) {
18
+ const surface = useSurface();
19
+ const ruled = surface === "ruled";
16
20
  return /* @__PURE__ */ jsx("div", {
17
- className: "@container/main",
21
+ "data-surface": surface,
22
+ className: cn("@container/main", ruled && "overflow-hidden border-y"),
18
23
  children: /* @__PURE__ */ jsx("div", {
19
- className: cn("grid grid-cols-1 gap-4", COLUMNS[items.length] ?? COLUMNS[4]),
20
- children: items.map((item) => /* @__PURE__ */ jsxs(Card, {
21
- className: cn("@container/card", onSelect && "relative", item.label === selected && "ring-2 ring-primary!", onSelect && item.disabled && "opacity-60"),
22
- children: [
23
- onSelect && /* @__PURE__ */ jsx("button", {
24
- type: "button",
25
- "aria-label": item.label,
26
- "aria-pressed": item.label === selected,
27
- disabled: item.disabled,
28
- onClick: () => onSelect(item.label),
29
- className: "absolute inset-0 z-10 rounded-4xl outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset"
30
- }),
31
- /* @__PURE__ */ jsxs(CardHeader, { children: [
32
- /* @__PURE__ */ jsx(CardDescription, { children: item.label }),
33
- /* @__PURE__ */ jsx(CardTitle, {
34
- className: "text-2xl font-semibold tabular-nums @[250px]/card:text-3xl",
35
- children: item.value
24
+ className: cn("grid grid-cols-1", ruled ? "-me-px -mb-px bg-card" : surface === "open" ? "gap-4" : "gap-2", COLUMNS[items.length] ?? COLUMNS[4]),
25
+ children: items.map((item) => /* @__PURE__ */ jsx("div", {
26
+ "data-slot": "section-card",
27
+ className: cn("min-w-0", ruled && "border-e border-b"),
28
+ children: /* @__PURE__ */ jsxs(Card, {
29
+ "data-tone": item.tone,
30
+ "data-stale": item.stale ? "" : void 0,
31
+ className: cn("@container/card h-full [--card-spacing:--spacing(3)]", onSelect && "relative", item.label === selected && "ring-2 ring-primary!", item.label === selected && ruled && "ring-inset", onSelect && item.disabled && "opacity-60"),
32
+ children: [
33
+ onSelect && /* @__PURE__ */ jsx("button", {
34
+ type: "button",
35
+ "aria-label": item.label,
36
+ "aria-pressed": item.label === selected,
37
+ disabled: item.disabled,
38
+ onClick: () => onSelect(item.label),
39
+ className: "absolute inset-0 z-10 rounded-[inherit] outline-none focus-visible:ring-3 focus-visible:ring-ring focus-visible:ring-inset"
36
40
  }),
37
- item.badge && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Badge, {
38
- variant: "outline",
39
- children: item.badge
40
- }) })
41
- ] }),
42
- (item.headline || item.detail) && /* @__PURE__ */ jsxs(CardFooter, {
43
- className: "flex-col items-start gap-1.5 text-sm",
44
- children: [item.headline && /* @__PURE__ */ jsx("div", {
45
- className: "flex flex-wrap gap-2 font-medium",
46
- children: item.headline
47
- }), item.detail && /* @__PURE__ */ jsx("div", {
48
- className: "text-muted-foreground",
49
- children: item.detail
50
- })]
51
- })
52
- ]
41
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
42
+ /* @__PURE__ */ jsx(CardDescription, {
43
+ className: "font-mono text-2xs tracking-wider uppercase",
44
+ children: item.label
45
+ }),
46
+ item.stale && /* @__PURE__ */ jsx(StaleNote, { since: item.stale }),
47
+ /* @__PURE__ */ jsx(CardTitle, {
48
+ className: "text-2xl font-semibold tabular-nums",
49
+ children: item.value
50
+ }),
51
+ item.badge && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Badge, {
52
+ variant: "outline",
53
+ children: item.badge
54
+ }) })
55
+ ] }),
56
+ item.trend && /* @__PURE__ */ jsx(CardContent, { children: item.trend }),
57
+ (item.headline || item.detail) && /* @__PURE__ */ jsxs(CardFooter, {
58
+ className: "flex-col items-start gap-1 font-mono text-2xs tracking-wider uppercase",
59
+ children: [item.headline && /* @__PURE__ */ jsx("div", {
60
+ className: "flex flex-wrap gap-2 font-medium",
61
+ children: item.headline
62
+ }), item.detail && /* @__PURE__ */ jsx("div", {
63
+ className: "text-muted-foreground",
64
+ children: item.detail
65
+ })]
66
+ })
67
+ ]
68
+ })
53
69
  }, item.label))
54
70
  })
55
71
  });
@@ -6,10 +6,11 @@ import * as React$1 from "react";
6
6
  //#region src/components/registry/dashboardcn/bar-list.tsx
7
7
  function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(--chart-1)", showPercentage = false, max: scale, onItemClick, className, ...props }) {
8
8
  const locale = useLocale();
9
- const format = valueFormatter ?? ((value) => new Intl.NumberFormat(locale.numberLocale, {
9
+ const defaultFormat = React$1.useMemo(() => new Intl.NumberFormat(locale.numberLocale, {
10
10
  notation: "compact",
11
11
  maximumFractionDigits: 1
12
- }).format(value));
12
+ }).format, [locale.numberLocale]);
13
+ const format = valueFormatter ?? defaultFormat;
13
14
  const items = React$1.useMemo(() => {
14
15
  if (sortOrder === "none") return data;
15
16
  const sorted = [...data].sort((a, b) => a.value - b.value);
@@ -19,7 +20,7 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
19
20
  const total = items.reduce((sum, item) => sum + item.value, 0);
20
21
  return /* @__PURE__ */ jsx("div", {
21
22
  "data-slot": "bar-list",
22
- className: cn("flex flex-col gap-1.5", className),
23
+ className: cn("@container/bar-list grid grid-cols-[minmax(0,1fr)_auto] gap-x-3 gap-y-1.5", className),
23
24
  ...props,
24
25
  children: items.map((item) => {
25
26
  const width = max > 0 ? item.value / max * 100 : 0;
@@ -28,16 +29,22 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
28
29
  const Label = item.href ? "a" : onItemClick ? "button" : "div";
29
30
  return /* @__PURE__ */ jsxs("div", {
30
31
  "data-slot": "bar-list-row",
31
- className: "flex items-center gap-3 text-sm",
32
+ className: "col-span-2 grid grid-cols-subgrid items-center text-sm @max-sm/bar-list:items-start",
32
33
  children: [/* @__PURE__ */ jsxs("div", {
33
- className: "relative flex h-8 min-w-0 flex-1 items-center",
34
+ className: "relative flex h-8 min-w-0 flex-1 items-center @max-sm/bar-list:h-auto @max-sm/bar-list:min-h-8 @max-sm/bar-list:items-start @max-sm/bar-list:pb-3",
34
35
  children: [
35
36
  /* @__PURE__ */ jsx("div", {
37
+ "data-slot": "bar-list-track",
36
38
  "aria-hidden": "true",
37
- className: "absolute inset-y-0 left-0 rounded-md transition-[width] duration-300",
39
+ className: "bg-muted/60 absolute inset-0 rounded-md @max-sm/bar-list:inset-y-auto @max-sm/bar-list:bottom-0 @max-sm/bar-list:h-1.5"
40
+ }),
41
+ /* @__PURE__ */ jsx("div", {
42
+ "data-slot": "bar-list-bar",
43
+ "aria-hidden": "true",
44
+ className: "absolute inset-y-0 left-0 rounded-md transition-[width] duration-300 @max-sm/bar-list:inset-y-auto @max-sm/bar-list:bottom-0 @max-sm/bar-list:h-1.5",
38
45
  style: {
39
46
  width: `${width}%`,
40
- backgroundColor: `color-mix(in oklab, ${color} 20%, transparent)`
47
+ backgroundColor: item.detail ? "color-mix(in oklab, var(--muted-foreground) 20%, transparent)" : `color-mix(in oklab, ${color} 32%, transparent)`
41
48
  }
42
49
  }),
43
50
  /* @__PURE__ */ jsxs(Label, {
@@ -46,12 +53,12 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
46
53
  type: "button",
47
54
  onClick: () => onItemClick(item)
48
55
  } : {},
49
- className: cn("relative flex min-w-0 items-center gap-2 px-2 text-left", interactive && "hover:underline"),
56
+ className: cn("text-foreground relative flex min-w-0 items-center gap-2 px-2 text-left", interactive && "hover:underline"),
50
57
  children: [item.icon ? /* @__PURE__ */ jsx("span", {
51
58
  className: "text-muted-foreground shrink-0 [&>svg]:size-4",
52
59
  children: item.icon
53
60
  }) : null, /* @__PURE__ */ jsx("span", {
54
- className: "truncate",
61
+ className: "truncate @max-sm/bar-list:whitespace-normal",
55
62
  children: item.name
56
63
  })]
57
64
  }),
@@ -62,7 +69,7 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
62
69
  }) : null
63
70
  ]
64
71
  }), /* @__PURE__ */ jsxs("div", {
65
- className: "flex shrink-0 items-center gap-2 tabular-nums",
72
+ className: "flex items-center justify-end gap-2 tabular-nums",
66
73
  children: [/* @__PURE__ */ jsx("span", {
67
74
  className: "font-medium",
68
75
  children: format(item.value)
@@ -62,16 +62,18 @@ function DistributionBar({ segments, valueFormatter, showLegend = true, showValu
62
62
  /* @__PURE__ */ jsx("div", {
63
63
  role: "img",
64
64
  "aria-label": ariaLabel ?? resolved.map((segment) => `${segment.name} ${figure(segment)}`).join(", "),
65
- className: "bg-muted relative h-2.5 w-full overflow-hidden rounded-full",
65
+ className: "bg-muted relative h-2.5 w-full overflow-hidden",
66
66
  onMouseLeave: onHover ? () => onHover(null) : void 0,
67
67
  children: resolved.map((segment) => segment.width > 0 ? /* @__PURE__ */ jsx("div", {
68
68
  "data-slot": "distribution-segment",
69
- className: "border-card absolute inset-y-0 border-x transition-[width,left,opacity] duration-300",
69
+ className: "border-card absolute inset-y-0 border-x transition-[width,left,background-color] duration-300",
70
70
  style: {
71
71
  left: `${segment.left}%`,
72
72
  width: `${segment.width}%`,
73
- backgroundColor: segment.color,
74
- opacity: highlighted === null || highlighted === segment.key ? 1 : .35
73
+ ...highlighted === null || highlighted === segment.key ? { backgroundColor: segment.color } : {
74
+ backgroundColor: `color-mix(in oklab, ${segment.color} 35%, var(--card))`,
75
+ boxShadow: `inset 0 0 0 1px ${segment.color}`
76
+ }
75
77
  },
76
78
  onMouseEnter: onHover ? () => onHover(segment) : void 0
77
79
  }, segment.key) : null)
@@ -0,0 +1,29 @@
1
+ import { Card } from "../../ui/card.js";
2
+ import * as React$1 from "react";
3
+ //#region src/components/registry/dashboardcn/kpi-row-card.d.ts
4
+ export interface MetricStripItem {
5
+ /** Muted label above the figure. */
6
+ label: string;
7
+ /** The figure, formatted by the page: money(4512300). */
8
+ value: React$1.ReactNode;
9
+ /** The signed change, drawn as a Delta under the figure; its sign colours the trend. For "pct", a fraction. */
10
+ change?: number;
11
+ changeFormat?: "pct" | "money";
12
+ /** Muted words after the change, such as "vs last month". */
13
+ note?: React$1.ReactNode;
14
+ /** Recent values, oldest first, drawn as a sparkline beside the figure. */
15
+ trend?: number[];
16
+ }
17
+ export interface MetricStripProps extends Omit<React$1.ComponentProps<typeof Card>, "title"> {
18
+ title?: React$1.ReactNode;
19
+ description?: React$1.ReactNode;
20
+ /** A range toggle, top right, that changes every figure. */
21
+ action?: React$1.ReactNode;
22
+ items: MetricStripItem[];
23
+ /** Lines under the strip, such as what the figures cover. */
24
+ footer?: React$1.ReactNode;
25
+ }
26
+ /** A card holding a row of small figures, each with its change and a sparkline: more numbers in less room than stat tiles. */
27
+ declare function MetricStrip({ title, description, action, items, footer, className, ...props }: MetricStripProps): React$1.JSX.Element;
28
+ //#endregion
29
+ export { MetricStrip };
@@ -0,0 +1,81 @@
1
+ import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
2
+ import { cn } from "../../../lib/utils.js";
3
+ import { Delta } from "../../siyahi/delta.js";
4
+ import { Sparkline } from "./sparkline.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import "react";
7
+ //#region src/components/registry/dashboardcn/kpi-row-card.tsx
8
+ const COLUMNS = {
9
+ 1: "basis-full",
10
+ 2: "basis-full @2xs/strip:basis-1/2",
11
+ 3: "basis-full @lg/strip:basis-1/3",
12
+ 4: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4",
13
+ 5: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/5",
14
+ 6: "basis-full @2xs/strip:basis-1/2 @xl/strip:basis-1/3 @5xl/strip:basis-1/6",
15
+ 8: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4 @7xl/strip:basis-1/8"
16
+ };
17
+ function trendColor(change) {
18
+ if (change === void 0) return "var(--chart-1)";
19
+ if (change > 0) return "var(--positive)";
20
+ if (change < 0) return "var(--negative)";
21
+ return "var(--muted-foreground)";
22
+ }
23
+ /** A card holding a row of small figures, each with its change and a sparkline: more numbers in less room than stat tiles. */
24
+ function MetricStrip({ title, description, action, items, footer, className, ...props }) {
25
+ const columns = COLUMNS[Math.min(items.length, 8)] ?? COLUMNS[8];
26
+ return /* @__PURE__ */ jsxs(Card, {
27
+ className: cn("gap-4", className),
28
+ ...props,
29
+ children: [
30
+ (title || description || action) && /* @__PURE__ */ jsxs(CardHeader, { children: [
31
+ title && /* @__PURE__ */ jsx(CardTitle, { children: title }),
32
+ description && /* @__PURE__ */ jsx(CardDescription, { children: description }),
33
+ action && /* @__PURE__ */ jsx(CardAction, { children: action })
34
+ ] }),
35
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", {
36
+ "data-slot": "metric-strip",
37
+ className: "@container/strip -mx-4 -my-3 overflow-hidden",
38
+ children: /* @__PURE__ */ jsx("div", {
39
+ className: "-me-px -mb-px flex flex-wrap",
40
+ children: items.map((item) => /* @__PURE__ */ jsxs("div", {
41
+ "data-slot": "metric-strip-item",
42
+ className: cn("flex min-w-0 flex-col gap-1.5 border-e border-b px-4 py-4", columns),
43
+ children: [/* @__PURE__ */ jsx("div", {
44
+ className: "truncate font-mono text-2xs tracking-wider text-muted-foreground uppercase",
45
+ children: item.label
46
+ }), /* @__PURE__ */ jsxs("div", {
47
+ className: "flex flex-wrap items-end justify-between gap-x-3 gap-y-1",
48
+ children: [/* @__PURE__ */ jsxs("div", {
49
+ className: "flex min-w-0 flex-col gap-0.5",
50
+ children: [/* @__PURE__ */ jsx("div", {
51
+ className: "text-xl font-semibold tracking-tight tabular-nums",
52
+ children: item.value
53
+ }), (item.change !== void 0 || item.note) && /* @__PURE__ */ jsxs("div", {
54
+ className: "flex flex-wrap items-center gap-x-1.5 text-xs",
55
+ children: [item.change !== void 0 && /* @__PURE__ */ jsx(Delta, {
56
+ value: item.change,
57
+ format: item.changeFormat
58
+ }), item.note && /* @__PURE__ */ jsx("span", {
59
+ className: "text-muted-foreground",
60
+ children: item.note
61
+ })]
62
+ })]
63
+ }), item.trend && item.trend.length > 1 && /* @__PURE__ */ jsx(Sparkline, {
64
+ data: item.trend,
65
+ variant: "line",
66
+ color: trendColor(item.change),
67
+ className: "h-9 w-20 shrink-0"
68
+ })]
69
+ })]
70
+ }, item.label))
71
+ })
72
+ }) }),
73
+ footer && /* @__PURE__ */ jsx(CardFooter, {
74
+ className: "flex-col items-start gap-2 text-sm",
75
+ children: footer
76
+ })
77
+ ]
78
+ });
79
+ }
80
+ //#endregion
81
+ export { MetricStrip };
@@ -0,0 +1,22 @@
1
+ import { ChartColor } from "../../../lib/chart-series.js";
2
+ import * as React$1 from "react";
3
+ //#region src/components/registry/dashboardcn/sparkline.d.ts
4
+ export interface SparklineProps extends React$1.ComponentProps<"div"> {
5
+ /** Series to plot, oldest first. */
6
+ data: number[];
7
+ variant?: "area" | "line";
8
+ /**
9
+ * The last step and the dot on the latest value: a chart slot, or var(--positive) or var(--negative) for a gain or
10
+ * a loss. Defaults to var(--chart-1). The run before it is muted.
11
+ */
12
+ color?: ChartColor;
13
+ curve?: "monotone" | "linear" | "step";
14
+ /** The run's line; the last step is 2px. */
15
+ strokeWidth?: number;
16
+ /** Animate after hydration and when data changes. Respects reduced motion. */
17
+ animate?: boolean;
18
+ animationDuration?: number;
19
+ }
20
+ declare function Sparkline({ data, variant, color, curve, strokeWidth, animate, animationDuration, className, ...props }: SparklineProps): React$1.JSX.Element;
21
+ //#endregion
22
+ export { Sparkline };