@alpic-ai/ui 0.0.0-dev.g37dab1d → 0.0.0-dev.g380fab7

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 (109) hide show
  1. package/dist/components/accordion-card.d.mts +5 -5
  2. package/dist/components/accordion.d.mts +5 -5
  3. package/dist/components/alert.d.mts +8 -8
  4. package/dist/components/area-chart.d.mts +62 -0
  5. package/dist/components/area-chart.mjs +269 -0
  6. package/dist/components/attachment-tile.d.mts +1 -1
  7. package/dist/components/avatar.d.mts +7 -7
  8. package/dist/components/badge.d.mts +1 -1
  9. package/dist/components/bar-chart.d.mts +48 -0
  10. package/dist/components/bar-chart.mjs +245 -0
  11. package/dist/components/bar-list.d.mts +28 -0
  12. package/dist/components/bar-list.mjs +98 -0
  13. package/dist/components/breadcrumb.d.mts +10 -10
  14. package/dist/components/button.d.mts +5 -5
  15. package/dist/components/card.d.mts +9 -9
  16. package/dist/components/chart-card.d.mts +25 -0
  17. package/dist/components/chart-card.mjs +48 -0
  18. package/dist/components/chart-container.d.mts +20 -0
  19. package/dist/components/chart-container.mjs +37 -0
  20. package/dist/components/chart-legend.d.mts +16 -0
  21. package/dist/components/chart-legend.mjs +26 -0
  22. package/dist/components/chart-tooltip.d.mts +33 -0
  23. package/dist/components/chart-tooltip.mjs +52 -0
  24. package/dist/components/checkbox.d.mts +2 -2
  25. package/dist/components/collapsible.d.mts +4 -4
  26. package/dist/components/combobox.d.mts +10 -10
  27. package/dist/components/command.d.mts +9 -9
  28. package/dist/components/copyable.d.mts +2 -2
  29. package/dist/components/description-list.d.mts +5 -5
  30. package/dist/components/dialog.d.mts +13 -13
  31. package/dist/components/donut-chart.d.mts +46 -0
  32. package/dist/components/donut-chart.mjs +185 -0
  33. package/dist/components/dropdown-menu.d.mts +17 -17
  34. package/dist/components/form.d.mts +18 -18
  35. package/dist/components/form.mjs +6 -6
  36. package/dist/components/github-button.d.mts +1 -1
  37. package/dist/components/grid-fx.d.mts +13 -0
  38. package/dist/components/grid-fx.mjs +188 -0
  39. package/dist/components/heatmap-chart.d.mts +40 -0
  40. package/dist/components/heatmap-chart.mjs +198 -0
  41. package/dist/components/input-group.d.mts +4 -4
  42. package/dist/components/input.d.mts +4 -4
  43. package/dist/components/input.mjs +2 -2
  44. package/dist/components/label.d.mts +2 -2
  45. package/dist/components/line-chart.d.mts +55 -0
  46. package/dist/components/line-chart.mjs +211 -0
  47. package/dist/components/page-loader.d.mts +1 -1
  48. package/dist/components/pagination.d.mts +3 -3
  49. package/dist/components/popover.d.mts +5 -5
  50. package/dist/components/radio-group.d.mts +3 -3
  51. package/dist/components/scroll-area.d.mts +3 -3
  52. package/dist/components/select.d.mts +9 -9
  53. package/dist/components/separator.d.mts +2 -2
  54. package/dist/components/sheet.d.mts +11 -11
  55. package/dist/components/shimmer-text.d.mts +3 -1
  56. package/dist/components/sidebar.d.mts +33 -33
  57. package/dist/components/sidebar.mjs +10 -10
  58. package/dist/components/skeleton.d.mts +1 -1
  59. package/dist/components/sonner.d.mts +5 -5
  60. package/dist/components/spinner.d.mts +2 -2
  61. package/dist/components/stat.d.mts +30 -0
  62. package/dist/components/stat.mjs +107 -0
  63. package/dist/components/status-dot.d.mts +1 -1
  64. package/dist/components/switch.d.mts +2 -2
  65. package/dist/components/table.d.mts +10 -10
  66. package/dist/components/tabs.d.mts +10 -10
  67. package/dist/components/tag.d.mts +3 -3
  68. package/dist/components/task-progress.d.mts +1 -1
  69. package/dist/components/textarea.d.mts +3 -3
  70. package/dist/components/textarea.mjs +2 -2
  71. package/dist/components/toggle-group.d.mts +3 -3
  72. package/dist/components/toggle-group.mjs +3 -3
  73. package/dist/components/tooltip.d.mts +5 -5
  74. package/dist/components/typography.d.mts +4 -4
  75. package/dist/components/wizard.d.mts +4 -4
  76. package/dist/hooks/use-chart-theme.d.mts +18 -0
  77. package/dist/hooks/use-chart-theme.mjs +57 -0
  78. package/dist/hooks/use-mobile.mjs +3 -3
  79. package/dist/hooks/use-reduced-motion.d.mts +4 -0
  80. package/dist/hooks/use-reduced-motion.mjs +16 -0
  81. package/dist/lib/chart-palette.d.mts +4 -0
  82. package/dist/lib/chart-palette.mjs +95 -0
  83. package/dist/lib/chart.d.mts +14 -0
  84. package/dist/lib/chart.mjs +27 -0
  85. package/package.json +30 -29
  86. package/src/components/area-chart.tsx +339 -0
  87. package/src/components/bar-chart.tsx +300 -0
  88. package/src/components/bar-list.tsx +150 -0
  89. package/src/components/chart-card.tsx +63 -0
  90. package/src/components/chart-container.tsx +49 -0
  91. package/src/components/chart-legend.tsx +41 -0
  92. package/src/components/chart-tooltip.tsx +93 -0
  93. package/src/components/donut-chart.tsx +217 -0
  94. package/src/components/grid-fx.tsx +238 -0
  95. package/src/components/heatmap-chart.tsx +287 -0
  96. package/src/components/line-chart.tsx +264 -0
  97. package/src/components/stat.tsx +109 -0
  98. package/src/hooks/use-chart-theme.ts +75 -0
  99. package/src/hooks/use-reduced-motion.ts +17 -0
  100. package/src/lib/chart-palette.ts +110 -0
  101. package/src/lib/chart.ts +56 -0
  102. package/src/stories/area-chart.stories.tsx +200 -0
  103. package/src/stories/bar-chart.stories.tsx +169 -0
  104. package/src/stories/bar-list.stories.tsx +85 -0
  105. package/src/stories/donut-chart.stories.tsx +112 -0
  106. package/src/stories/heatmap-chart.stories.tsx +107 -0
  107. package/src/stories/line-chart.stories.tsx +146 -0
  108. package/src/stories/stat.stories.tsx +64 -0
  109. package/src/styles/tokens.css +63 -0
@@ -0,0 +1,198 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.mjs";
3
+ import { HEAT_EMPTY, heatColor, heatRamp } from "../lib/chart-palette.mjs";
4
+ import { useChartContext } from "./chart-container.mjs";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import * as React$1 from "react";
7
+ import { createPortal } from "react-dom";
8
+ //#region src/components/heatmap-chart.tsx
9
+ const PLACEHOLDER_HEIGHT = 168;
10
+ const CELL = 22;
11
+ const GAP = 3;
12
+ const PAD = {
13
+ left: 36,
14
+ top: 18,
15
+ right: 6,
16
+ bottom: 6
17
+ };
18
+ const MAX_X_TICKS = 13;
19
+ const DOT_MIN = .42;
20
+ const DOT_RANGE = .52;
21
+ const TOOLTIP_OFFSET = 14;
22
+ const TOOLTIP_WIDTH = 150;
23
+ const TOOLTIP_HEIGHT = 64;
24
+ const pairKey = (rowLabel, colLabel) => JSON.stringify([rowLabel, colLabel]);
25
+ const uniqueInOrder = (values) => {
26
+ const seen = /* @__PURE__ */ new Set();
27
+ const ordered = [];
28
+ for (const value of values) if (!seen.has(value)) {
29
+ seen.add(value);
30
+ ordered.push(value);
31
+ }
32
+ return ordered;
33
+ };
34
+ function HeatmapChart({ data, xKey, yKey, dataKey = "value", variant = "square", palette, xLabels, yLabels, highlightPeak = true, loading = false, valueFormatter = (value) => value.toLocaleString("en-US"), xTickFormatter, yTickFormatter, ariaLabel = "Activity heatmap", className }) {
35
+ const { paletteName, theme } = useChartContext(palette);
36
+ const [hovered, setHovered] = React$1.useState(null);
37
+ const [mounted, setMounted] = React$1.useState(false);
38
+ React$1.useEffect(() => {
39
+ setMounted(true);
40
+ }, []);
41
+ const { columns, rows, cells, maxValue, peakKey } = React$1.useMemo(() => {
42
+ const columns = xLabels ? [...xLabels] : uniqueInOrder(data.map((row) => String(row[xKey] ?? "")));
43
+ const rows = yLabels ? [...yLabels] : uniqueInOrder(data.map((row) => String(row[yKey] ?? "")));
44
+ const valueAt = /* @__PURE__ */ new Map();
45
+ for (const row of data) valueAt.set(pairKey(String(row[yKey] ?? ""), String(row[xKey] ?? "")), Number(row[dataKey]) || 0);
46
+ let maxValue = 0;
47
+ let peakKey = "";
48
+ return {
49
+ columns,
50
+ rows,
51
+ cells: rows.flatMap((rowLabel, rowIndex) => columns.map((colLabel, colIndex) => {
52
+ const value = valueAt.get(pairKey(rowLabel, colLabel)) ?? 0;
53
+ if (value > maxValue) {
54
+ maxValue = value;
55
+ peakKey = pairKey(rowLabel, colLabel);
56
+ }
57
+ return {
58
+ rowLabel,
59
+ colLabel,
60
+ rowIndex,
61
+ colIndex,
62
+ value
63
+ };
64
+ })),
65
+ maxValue,
66
+ peakKey
67
+ };
68
+ }, [
69
+ data,
70
+ xKey,
71
+ yKey,
72
+ dataKey,
73
+ xLabels,
74
+ yLabels
75
+ ]);
76
+ const isEmpty = columns.length === 0 || rows.length === 0 || maxValue <= 0;
77
+ if (loading) return /* @__PURE__ */ jsxs("div", {
78
+ className: cn("flex items-center justify-center gap-2.5 font-mono text-quaternary-foreground text-text-xs", className),
79
+ style: { minHeight: PLACEHOLDER_HEIGHT },
80
+ children: [/* @__PURE__ */ jsx("span", { className: "size-4 animate-spin rounded-full border-2 border-border border-t-foreground" }), "loading…"]
81
+ });
82
+ if (isEmpty) return /* @__PURE__ */ jsx("div", {
83
+ className: cn("flex items-center justify-center rounded-lg border border-border border-dashed font-mono text-quaternary-foreground text-text-xs", className),
84
+ style: { minHeight: PLACEHOLDER_HEIGHT },
85
+ children: "no data in range"
86
+ });
87
+ const ramp = heatRamp(paletteName, theme.isDark ? HEAT_EMPTY.dark : HEAT_EMPTY.light);
88
+ const totalWidth = PAD.left + columns.length * CELL + (columns.length - 1) * GAP + PAD.right;
89
+ const totalHeight = PAD.top + rows.length * CELL + (rows.length - 1) * GAP + PAD.bottom;
90
+ const xStride = Math.ceil(columns.length / MAX_X_TICKS);
91
+ const cellX = (col) => PAD.left + col * 25;
92
+ const cellY = (row) => PAD.top + row * 25;
93
+ const formatX = (label) => xTickFormatter ? xTickFormatter(label) : label;
94
+ const formatY = (label) => yTickFormatter ? yTickFormatter(label) : label;
95
+ const tooltipLeft = hovered && hovered.x + TOOLTIP_OFFSET + TOOLTIP_WIDTH > window.innerWidth ? hovered.x - TOOLTIP_OFFSET - TOOLTIP_WIDTH : (hovered?.x ?? 0) + TOOLTIP_OFFSET;
96
+ const tooltipTop = hovered && hovered.y + TOOLTIP_OFFSET + TOOLTIP_HEIGHT > window.innerHeight ? hovered.y - TOOLTIP_OFFSET - TOOLTIP_HEIGHT : (hovered?.y ?? 0) + TOOLTIP_OFFSET;
97
+ return /* @__PURE__ */ jsxs("div", {
98
+ "data-slot": "heatmap-chart",
99
+ className: cn("w-full", className),
100
+ children: [/* @__PURE__ */ jsx("div", {
101
+ className: "overflow-x-auto",
102
+ children: /* @__PURE__ */ jsxs("svg", {
103
+ viewBox: `0 0 ${totalWidth} ${totalHeight}`,
104
+ className: "block min-w-[480px]",
105
+ style: {
106
+ width: "100%",
107
+ height: "auto"
108
+ },
109
+ role: "img",
110
+ "aria-label": ariaLabel,
111
+ onMouseLeave: () => setHovered(null),
112
+ children: [
113
+ columns.map((label, col) => col % xStride === 0 ? /* @__PURE__ */ jsx("text", {
114
+ x: cellX(col) + CELL / 2,
115
+ y: PAD.top - 7,
116
+ textAnchor: "middle",
117
+ className: "fill-quaternary-foreground font-mono text-[8.5px]",
118
+ children: formatX(label)
119
+ }, `x-${label}`) : null),
120
+ rows.map((label, row) => /* @__PURE__ */ jsx("text", {
121
+ x: PAD.left - 8,
122
+ y: cellY(row) + CELL / 2 + 3,
123
+ textAnchor: "end",
124
+ className: "fill-quaternary-foreground font-mono text-[8.5px]",
125
+ children: formatY(label)
126
+ }, `y-${label}`)),
127
+ cells.map((cell) => {
128
+ const fraction = cell.value / maxValue;
129
+ const fill = heatColor(ramp, fraction);
130
+ const key = pairKey(cell.rowLabel, cell.colLabel);
131
+ const isPeak = highlightPeak && key === peakKey;
132
+ if (variant === "dot") return /* @__PURE__ */ jsx("circle", {
133
+ cx: cellX(cell.colIndex) + CELL / 2,
134
+ cy: cellY(cell.rowIndex) + CELL / 2,
135
+ r: CELL / 2 * (DOT_MIN + DOT_RANGE * fraction),
136
+ fill,
137
+ stroke: isPeak ? theme.foreground : void 0,
138
+ strokeWidth: isPeak ? 1.4 : void 0
139
+ }, key);
140
+ return /* @__PURE__ */ jsx("rect", {
141
+ x: cellX(cell.colIndex),
142
+ y: cellY(cell.rowIndex),
143
+ width: CELL,
144
+ height: CELL,
145
+ rx: 2.5,
146
+ fill,
147
+ stroke: isPeak ? theme.foreground : void 0,
148
+ strokeWidth: isPeak ? 1.4 : void 0
149
+ }, key);
150
+ }),
151
+ cells.map((cell) => /* @__PURE__ */ jsx("rect", {
152
+ x: cellX(cell.colIndex),
153
+ y: cellY(cell.rowIndex),
154
+ width: 25,
155
+ height: 25,
156
+ fill: "transparent",
157
+ onMouseMove: (event) => setHovered({
158
+ x: event.clientX,
159
+ y: event.clientY,
160
+ rowLabel: cell.rowLabel,
161
+ colLabel: cell.colLabel,
162
+ value: cell.value
163
+ })
164
+ }, `hit-${pairKey(cell.rowLabel, cell.colLabel)}`))
165
+ ]
166
+ })
167
+ }), mounted && hovered && createPortal(/* @__PURE__ */ jsxs("div", {
168
+ className: "pointer-events-none fixed z-50 min-w-[130px] rounded-lg border border-border bg-popover px-3 py-2.5 text-popover-foreground shadow-lg",
169
+ style: {
170
+ left: tooltipLeft,
171
+ top: tooltipTop
172
+ },
173
+ children: [/* @__PURE__ */ jsxs("p", {
174
+ className: "mb-1.5 font-mono text-[10px] text-quaternary-foreground uppercase tracking-wider",
175
+ children: [
176
+ formatY(hovered.rowLabel),
177
+ " · ",
178
+ formatX(hovered.colLabel)
179
+ ]
180
+ }), /* @__PURE__ */ jsxs("div", {
181
+ className: "flex items-center justify-between gap-4 text-text-xs",
182
+ children: [/* @__PURE__ */ jsxs("span", {
183
+ className: "inline-flex items-center gap-2 text-muted-foreground",
184
+ children: [/* @__PURE__ */ jsx("span", {
185
+ "aria-hidden": true,
186
+ className: "size-2 shrink-0 rounded-[2px]",
187
+ style: { background: heatColor(ramp, hovered.value / maxValue) }
188
+ }), "activity"]
189
+ }), /* @__PURE__ */ jsx("span", {
190
+ className: "font-mono font-semibold tabular-nums text-foreground",
191
+ children: valueFormatter(hovered.value)
192
+ })]
193
+ })]
194
+ }), document.body)]
195
+ });
196
+ }
197
+ //#endregion
198
+ export { HeatmapChart };
@@ -1,12 +1,12 @@
1
1
  import { VariantProps } from "class-variance-authority";
2
- import * as React from "react";
2
+ import * as React$1 from "react";
3
3
 
4
4
  //#region src/components/input-group.d.ts
5
5
  declare function InputGroup({
6
6
  className,
7
7
  children,
8
8
  ...props
9
- }: React.ComponentProps<"fieldset">): import("react/jsx-runtime").JSX.Element;
9
+ }: React$1.ComponentProps<"fieldset">): React$1.JSX.Element;
10
10
  declare const inputGroupAddonVariants: (props?: ({
11
11
  align?: "inline-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
12
12
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -14,10 +14,10 @@ declare function InputGroupAddon({
14
14
  className,
15
15
  align,
16
16
  ...props
17
- }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): import("react/jsx-runtime").JSX.Element;
17
+ }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): React$1.JSX.Element;
18
18
  declare function InputGroupTextarea({
19
19
  className,
20
20
  ...props
21
- }: React.ComponentProps<"textarea">): import("react/jsx-runtime").JSX.Element;
21
+ }: React$1.ComponentProps<"textarea">): React$1.JSX.Element;
22
22
  //#endregion
23
23
  export { InputGroup, InputGroupAddon, InputGroupTextarea };
@@ -1,14 +1,14 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
 
3
3
  //#region src/components/input.d.ts
4
- interface InputProps extends Omit<React.ComponentProps<"input">, "size"> {
4
+ interface InputProps extends Omit<React$1.ComponentProps<"input">, "size"> {
5
5
  label?: string;
6
6
  required?: boolean;
7
7
  hint?: string;
8
8
  error?: string;
9
9
  tooltip?: string;
10
10
  leadingText?: string;
11
- leadingIcon?: React.ReactNode;
11
+ leadingIcon?: React$1.ReactNode;
12
12
  size?: "sm" | "md";
13
13
  }
14
14
  declare function Input({
@@ -23,6 +23,6 @@ declare function Input({
23
23
  leadingIcon,
24
24
  size,
25
25
  ...props
26
- }: InputProps): import("react/jsx-runtime").JSX.Element;
26
+ }: InputProps): React$1.JSX.Element;
27
27
  //#endregion
28
28
  export { Input, type InputProps };
@@ -4,7 +4,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.mjs";
4
4
  import { Label } from "./label.mjs";
5
5
  import { Info } from "lucide-react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
- import * as React from "react";
7
+ import * as React$1 from "react";
8
8
  //#region src/components/input.tsx
9
9
  const inputSizeStyles = {
10
10
  sm: {
@@ -25,7 +25,7 @@ const inputSizeStyles = {
25
25
  }
26
26
  };
27
27
  function Input({ className, id, label, required, hint, error, tooltip, leadingText, leadingIcon, size = "md", ...props }) {
28
- const generatedId = React.useId();
28
+ const generatedId = React$1.useId();
29
29
  const fieldId = id ?? generatedId;
30
30
  const hasAddons = leadingText || leadingIcon;
31
31
  const sizes = inputSizeStyles[size];
@@ -1,10 +1,10 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
  import * as LabelPrimitive from "@radix-ui/react-label";
3
3
 
4
4
  //#region src/components/label.d.ts
5
5
  declare function Label({
6
6
  className,
7
7
  ...props
8
- }: React.ComponentProps<typeof LabelPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
8
+ }: React$1.ComponentProps<typeof LabelPrimitive.Root>): React$1.JSX.Element;
9
9
  //#endregion
10
10
  export { Label };
@@ -0,0 +1,55 @@
1
+ import { ChartSeries } from "../lib/chart.mjs";
2
+ import { ChartPaletteName } from "../lib/chart-palette.mjs";
3
+ import { ChartMarker } from "./area-chart.mjs";
4
+ import * as React$1 from "react";
5
+
6
+ //#region src/components/line-chart.d.ts
7
+ declare const CURVE_TYPE: {
8
+ readonly monotone: "monotone";
9
+ readonly linear: "linear";
10
+ readonly step: "stepAfter";
11
+ };
12
+ interface LineChartProps {
13
+ data: ReadonlyArray<Record<string, string | number | null | undefined>>;
14
+ index: string;
15
+ series: ChartSeries[];
16
+ curve?: keyof typeof CURVE_TYPE;
17
+ legend?: boolean;
18
+ valueFlags?: boolean;
19
+ dots?: boolean;
20
+ height?: number;
21
+ yAxisWidth?: number;
22
+ palette?: ChartPaletteName;
23
+ referenceLine?: {
24
+ y: number;
25
+ label?: string;
26
+ band?: boolean;
27
+ };
28
+ markers?: ChartMarker[];
29
+ lastValueLabel?: boolean;
30
+ loading?: boolean;
31
+ valueFormatter?: (value: number) => string;
32
+ labelFormatter?: (label: string | number) => string;
33
+ className?: string;
34
+ }
35
+ declare function LineChart({
36
+ data,
37
+ index,
38
+ series,
39
+ curve,
40
+ legend,
41
+ valueFlags,
42
+ dots,
43
+ height,
44
+ yAxisWidth,
45
+ palette,
46
+ referenceLine,
47
+ markers,
48
+ lastValueLabel,
49
+ loading,
50
+ valueFormatter,
51
+ labelFormatter,
52
+ className
53
+ }: LineChartProps): React$1.JSX.Element;
54
+ //#endregion
55
+ export { LineChart, LineChartProps };
@@ -0,0 +1,211 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.mjs";
3
+ import { useReducedMotion } from "../hooks/use-reduced-motion.mjs";
4
+ import { resolveSeries } from "../lib/chart.mjs";
5
+ import { useChartContext } from "./chart-container.mjs";
6
+ import { ChartLegend } from "./chart-legend.mjs";
7
+ import { ChartTooltipContent } from "./chart-tooltip.mjs";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import * as React$1 from "react";
10
+ import { CartesianGrid, LabelList, Line, LineChart as LineChart$1, ReferenceArea, ReferenceDot, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
11
+ //#region src/components/line-chart.tsx
12
+ const CURVE_TYPE = {
13
+ monotone: "monotone",
14
+ linear: "linear",
15
+ step: "stepAfter"
16
+ };
17
+ function LineChart({ data, index, series, curve = "monotone", legend = false, valueFlags = false, dots = false, height = 200, yAxisWidth = 48, palette, referenceLine, markers, lastValueLabel = false, loading = false, valueFormatter = (value) => value.toLocaleString("en-US"), labelFormatter, className }) {
18
+ const { palette: paletteColors, theme } = useChartContext(palette);
19
+ const animated = !useReducedMotion();
20
+ const resolved = resolveSeries(series, paletteColors, theme);
21
+ const numericMax = React$1.useMemo(() => {
22
+ let max = 0;
23
+ for (const row of data) for (const entry of series) {
24
+ const value = Number(row[entry.key]);
25
+ if (Number.isFinite(value) && value > max) max = value;
26
+ }
27
+ return max;
28
+ }, [data, series]);
29
+ const curveType = CURVE_TYPE[curve];
30
+ const margin = {
31
+ top: markers?.length ? 18 : 8,
32
+ right: lastValueLabel ? 56 : 8,
33
+ bottom: 2,
34
+ left: 0
35
+ };
36
+ const axis = {
37
+ stroke: theme.border,
38
+ tick: {
39
+ fill: theme.axisForeground,
40
+ fontSize: 10,
41
+ fontFamily: theme.fontMono
42
+ },
43
+ tickLine: false,
44
+ axisLine: {
45
+ stroke: theme.border,
46
+ strokeOpacity: .6
47
+ }
48
+ };
49
+ const legendItems = resolved.map((entry) => ({
50
+ name: entry.name,
51
+ color: entry.color,
52
+ dashed: entry.dashed
53
+ }));
54
+ const activeDotFor = (entry) => valueFlags ? (dotProps) => {
55
+ if (dotProps.cx == null || dotProps.cy == null) return /* @__PURE__ */ jsx("g", {});
56
+ return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("circle", {
57
+ cx: dotProps.cx,
58
+ cy: dotProps.cy,
59
+ r: 3.5,
60
+ fill: entry.color,
61
+ stroke: theme.card,
62
+ strokeWidth: 2
63
+ }), /* @__PURE__ */ jsx("text", {
64
+ x: dotProps.cx,
65
+ y: dotProps.cy - 8,
66
+ textAnchor: "middle",
67
+ fill: entry.color,
68
+ fontFamily: theme.fontMono,
69
+ fontSize: 10,
70
+ style: { fontVariantNumeric: "tabular-nums" },
71
+ children: valueFormatter(Number(dotProps.value ?? 0))
72
+ })] });
73
+ } : {
74
+ r: 3.5,
75
+ fill: entry.color,
76
+ stroke: theme.card,
77
+ strokeWidth: 2
78
+ };
79
+ const renderLastLabel = (color) => (props) => {
80
+ if (props.index !== data.length - 1 || props.x == null || props.y == null) return null;
81
+ return /* @__PURE__ */ jsx("text", {
82
+ x: Number(props.x) + 6,
83
+ y: Number(props.y),
84
+ dy: 3,
85
+ fill: color,
86
+ fontFamily: theme.fontMono,
87
+ fontSize: 10,
88
+ textAnchor: "start",
89
+ style: { fontVariantNumeric: "tabular-nums" },
90
+ children: valueFormatter(Number(props.value ?? 0))
91
+ });
92
+ };
93
+ const isEmpty = data.length === 0 || resolved.length === 0;
94
+ return /* @__PURE__ */ jsxs("div", {
95
+ "data-slot": "line-chart",
96
+ className: cn("flex w-full flex-col gap-3", className),
97
+ children: [/* @__PURE__ */ jsx("div", {
98
+ className: "w-full",
99
+ style: { height },
100
+ children: loading ? /* @__PURE__ */ jsxs("div", {
101
+ className: "flex h-full items-center justify-center gap-2.5 font-mono text-quaternary-foreground text-text-xs",
102
+ children: [/* @__PURE__ */ jsx("span", { className: "size-4 animate-spin rounded-full border-2 border-border border-t-foreground" }), "loading…"]
103
+ }) : isEmpty ? /* @__PURE__ */ jsx("div", {
104
+ className: "flex h-full items-center justify-center rounded-lg border border-border border-dashed font-mono text-quaternary-foreground text-text-xs",
105
+ children: "no data in range"
106
+ }) : /* @__PURE__ */ jsx(ResponsiveContainer, {
107
+ width: "100%",
108
+ height: "100%",
109
+ children: /* @__PURE__ */ jsxs(LineChart$1, {
110
+ data,
111
+ margin,
112
+ children: [
113
+ /* @__PURE__ */ jsx(CartesianGrid, {
114
+ vertical: false,
115
+ stroke: theme.grid,
116
+ strokeDasharray: "2 4"
117
+ }),
118
+ /* @__PURE__ */ jsx(XAxis, {
119
+ dataKey: index,
120
+ ...axis,
121
+ interval: "preserveStartEnd",
122
+ minTickGap: 44
123
+ }),
124
+ /* @__PURE__ */ jsx(YAxis, {
125
+ ...axis,
126
+ width: yAxisWidth,
127
+ tickFormatter: (value) => valueFormatter(value)
128
+ }),
129
+ /* @__PURE__ */ jsx(Tooltip, {
130
+ offset: 12,
131
+ allowEscapeViewBox: {
132
+ x: false,
133
+ y: false
134
+ },
135
+ cursor: {
136
+ stroke: theme.axisForeground,
137
+ strokeWidth: 1,
138
+ strokeDasharray: "3 3"
139
+ },
140
+ content: /* @__PURE__ */ jsx(ChartTooltipContent, {
141
+ valueFormatter,
142
+ labelFormatter
143
+ })
144
+ }),
145
+ referenceLine?.band && /* @__PURE__ */ jsx(ReferenceArea, {
146
+ y1: referenceLine.y,
147
+ y2: numericMax,
148
+ fill: theme.warning,
149
+ fillOpacity: .06,
150
+ ifOverflow: "extendDomain"
151
+ }),
152
+ referenceLine && /* @__PURE__ */ jsx(ReferenceLine, {
153
+ y: referenceLine.y,
154
+ stroke: theme.warning,
155
+ strokeDasharray: "4 4",
156
+ strokeOpacity: .6,
157
+ label: referenceLine.label ? {
158
+ value: referenceLine.label,
159
+ fill: theme.warning,
160
+ fontSize: 9,
161
+ fontFamily: theme.fontMono,
162
+ position: "insideBottomRight"
163
+ } : void 0
164
+ }),
165
+ resolved.map((entry) => /* @__PURE__ */ jsx(Line, {
166
+ type: curveType,
167
+ dataKey: entry.key,
168
+ name: entry.name,
169
+ stroke: entry.color,
170
+ strokeWidth: entry.dashed ? 2 : 1.8,
171
+ strokeDasharray: entry.dashed ? "5 3" : void 0,
172
+ dot: dots ? {
173
+ r: 2.5,
174
+ fill: entry.color,
175
+ strokeWidth: 0
176
+ } : false,
177
+ activeDot: activeDotFor(entry),
178
+ isAnimationActive: animated,
179
+ animationDuration: 650,
180
+ animationEasing: "ease-out",
181
+ children: lastValueLabel && /* @__PURE__ */ jsx(LabelList, {
182
+ dataKey: entry.key,
183
+ content: renderLastLabel(entry.color)
184
+ })
185
+ }, entry.key)),
186
+ markers?.map((marker) => /* @__PURE__ */ jsx(ReferenceDot, {
187
+ x: marker.x,
188
+ y: marker.y,
189
+ r: 3.5,
190
+ fill: marker.color ?? theme.foreground,
191
+ stroke: theme.card,
192
+ strokeWidth: 2,
193
+ label: marker.label ? {
194
+ value: marker.label,
195
+ fill: marker.color ?? theme.foreground,
196
+ fontSize: 9,
197
+ fontFamily: theme.fontMono,
198
+ position: "top"
199
+ } : void 0
200
+ }, `${marker.x}-${marker.y}`))
201
+ ]
202
+ })
203
+ })
204
+ }), legend && !isEmpty && /* @__PURE__ */ jsx(ChartLegend, {
205
+ items: legendItems,
206
+ style: { paddingLeft: yAxisWidth }
207
+ })]
208
+ });
209
+ }
210
+ //#endregion
211
+ export { LineChart };
@@ -4,6 +4,6 @@ interface PageLoaderProps {
4
4
  }
5
5
  declare function PageLoader({
6
6
  className
7
- }: PageLoaderProps): import("react/jsx-runtime").JSX.Element;
7
+ }: PageLoaderProps): import("react").JSX.Element;
8
8
  //#endregion
9
9
  export { PageLoader, type PageLoaderProps };
@@ -1,7 +1,7 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
 
3
3
  //#region src/components/pagination.d.ts
4
- interface PaginationProps extends React.ComponentProps<"nav"> {
4
+ interface PaginationProps extends React$1.ComponentProps<"nav"> {
5
5
  currentPage: number;
6
6
  totalPages: number;
7
7
  onPageChange: (page: number) => void;
@@ -12,6 +12,6 @@ declare function Pagination({
12
12
  onPageChange,
13
13
  className,
14
14
  ...props
15
- }: PaginationProps): import("react/jsx-runtime").JSX.Element | null;
15
+ }: PaginationProps): React$1.JSX.Element | null;
16
16
  //#endregion
17
17
  export { Pagination, type PaginationProps };
@@ -1,21 +1,21 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
  import * as PopoverPrimitive from "@radix-ui/react-popover";
3
3
 
4
4
  //#region src/components/popover.d.ts
5
5
  declare function Popover({
6
6
  ...props
7
- }: React.ComponentProps<typeof PopoverPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
7
+ }: React$1.ComponentProps<typeof PopoverPrimitive.Root>): React$1.JSX.Element;
8
8
  declare function PopoverTrigger({
9
9
  ...props
10
- }: React.ComponentProps<typeof PopoverPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
10
+ }: React$1.ComponentProps<typeof PopoverPrimitive.Trigger>): React$1.JSX.Element;
11
11
  declare function PopoverAnchor({
12
12
  ...props
13
- }: React.ComponentProps<typeof PopoverPrimitive.Anchor>): import("react/jsx-runtime").JSX.Element;
13
+ }: React$1.ComponentProps<typeof PopoverPrimitive.Anchor>): React$1.JSX.Element;
14
14
  declare function PopoverContent({
15
15
  className,
16
16
  align,
17
17
  sideOffset,
18
18
  ...props
19
- }: React.ComponentProps<typeof PopoverPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
19
+ }: React$1.ComponentProps<typeof PopoverPrimitive.Content>): React$1.JSX.Element;
20
20
  //#endregion
21
21
  export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -1,14 +1,14 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
3
3
 
4
4
  //#region src/components/radio-group.d.ts
5
5
  declare function RadioGroup({
6
6
  className,
7
7
  ...props
8
- }: React.ComponentProps<typeof RadioGroupPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
8
+ }: React$1.ComponentProps<typeof RadioGroupPrimitive.Root>): React$1.JSX.Element;
9
9
  declare function RadioGroupItem({
10
10
  className,
11
11
  ...props
12
- }: React.ComponentProps<typeof RadioGroupPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
12
+ }: React$1.ComponentProps<typeof RadioGroupPrimitive.Item>): React$1.JSX.Element;
13
13
  //#endregion
14
14
  export { RadioGroup, RadioGroupItem };
@@ -1,4 +1,4 @@
1
- import * as React from "react";
1
+ import * as React$1 from "react";
2
2
  import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3
3
 
4
4
  //#region src/components/scroll-area.d.ts
@@ -6,11 +6,11 @@ declare function ScrollArea({
6
6
  className,
7
7
  children,
8
8
  ...props
9
- }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
9
+ }: React$1.ComponentProps<typeof ScrollAreaPrimitive.Root>): React$1.JSX.Element;
10
10
  declare function ScrollBar({
11
11
  className,
12
12
  orientation,
13
13
  ...props
14
- }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): import("react/jsx-runtime").JSX.Element;
14
+ }: React$1.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): React$1.JSX.Element;
15
15
  //#endregion
16
16
  export { ScrollArea, ScrollBar };