@alpic-ai/ui 0.0.0-dev.g19c2d9f → 0.0.0-dev.g1a5d5ed
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.
- package/dist/components/accordion-card.d.mts +5 -6
- package/dist/components/accordion.d.mts +5 -6
- package/dist/components/alert.d.mts +9 -11
- package/dist/components/area-chart.d.mts +64 -0
- package/dist/components/area-chart.mjs +275 -0
- package/dist/components/attachment-tile.d.mts +1 -3
- package/dist/components/avatar.d.mts +8 -10
- package/dist/components/badge.d.mts +2 -4
- package/dist/components/bar-chart.d.mts +50 -0
- package/dist/components/bar-chart.mjs +262 -0
- package/dist/components/bar-list.d.mts +31 -0
- package/dist/components/bar-list.mjs +111 -0
- package/dist/components/breadcrumb.d.mts +10 -11
- package/dist/components/button.d.mts +6 -8
- package/dist/components/card.d.mts +9 -10
- package/dist/components/chart-card.d.mts +25 -0
- package/dist/components/chart-card.mjs +48 -0
- package/dist/components/chart-container.d.mts +20 -0
- package/dist/components/chart-container.mjs +37 -0
- package/dist/components/chart-legend.d.mts +21 -0
- package/dist/components/chart-legend.mjs +35 -0
- package/dist/components/chart-tooltip.d.mts +33 -0
- package/dist/components/chart-tooltip.mjs +52 -0
- package/dist/components/checkbox.d.mts +2 -3
- package/dist/components/collapsible.d.mts +4 -5
- package/dist/components/combobox.d.mts +12 -11
- package/dist/components/combobox.mjs +7 -4
- package/dist/components/command.d.mts +9 -10
- package/dist/components/copyable.d.mts +2 -3
- package/dist/components/description-list.d.mts +5 -6
- package/dist/components/dialog.d.mts +15 -17
- package/dist/components/donut-chart.d.mts +46 -0
- package/dist/components/donut-chart.mjs +189 -0
- package/dist/components/dropdown-menu.d.mts +18 -20
- package/dist/components/form.d.mts +38 -21
- package/dist/components/form.mjs +7 -7
- package/dist/components/github-button.d.mts +1 -2
- package/dist/components/heatmap-chart.d.mts +48 -0
- package/dist/components/heatmap-chart.mjs +229 -0
- package/dist/components/input-group.d.mts +5 -7
- package/dist/components/input.d.mts +4 -5
- package/dist/components/input.mjs +2 -2
- package/dist/components/label.d.mts +2 -3
- package/dist/components/line-chart.d.mts +57 -0
- package/dist/components/line-chart.mjs +218 -0
- package/dist/components/page-loader.d.mts +1 -3
- package/dist/components/pagination.d.mts +3 -4
- package/dist/components/popover.d.mts +5 -6
- package/dist/components/radio-group.d.mts +3 -4
- package/dist/components/scroll-area.d.mts +3 -4
- package/dist/components/select-trigger-variants.d.mts +1 -3
- package/dist/components/select.d.mts +9 -10
- package/dist/components/separator.d.mts +2 -3
- package/dist/components/sheet.d.mts +11 -12
- package/dist/components/shimmer-text.d.mts +2 -2
- package/dist/components/sidebar.d.mts +34 -36
- package/dist/components/sidebar.mjs +10 -10
- package/dist/components/skeleton.d.mts +2 -4
- package/dist/components/sonner.d.mts +5 -6
- package/dist/components/spinner.d.mts +3 -5
- package/dist/components/stat.d.mts +32 -0
- package/dist/components/stat.mjs +117 -0
- package/dist/components/status-dot.d.mts +2 -4
- package/dist/components/switch.d.mts +2 -3
- package/dist/components/table.d.mts +10 -11
- package/dist/components/tabs.d.mts +12 -14
- package/dist/components/tag.d.mts +3 -5
- package/dist/components/task-progress.d.mts +1 -3
- package/dist/components/textarea.d.mts +3 -4
- package/dist/components/textarea.mjs +3 -3
- package/dist/components/toggle-group.d.mts +4 -6
- package/dist/components/toggle-group.mjs +3 -3
- package/dist/components/tooltip-icon-button.d.mts +1 -2
- package/dist/components/tooltip.d.mts +5 -6
- package/dist/components/typography.d.mts +4 -5
- package/dist/components/wizard.d.mts +4 -23
- package/dist/components/wizard.mjs +1 -19
- package/dist/hooks/use-chart-theme.d.mts +18 -0
- package/dist/hooks/use-chart-theme.mjs +57 -0
- package/dist/hooks/use-mobile.mjs +3 -3
- package/dist/hooks/use-reduced-motion.d.mts +4 -0
- package/dist/hooks/use-reduced-motion.mjs +16 -0
- package/dist/lib/chart-palette.d.mts +4 -0
- package/dist/lib/chart-palette.mjs +95 -0
- package/dist/lib/chart.d.mts +14 -0
- package/dist/lib/chart.mjs +42 -0
- package/package.json +30 -29
- package/src/components/area-chart.tsx +347 -0
- package/src/components/bar-chart.tsx +317 -0
- package/src/components/bar-list.tsx +166 -0
- package/src/components/chart-card.tsx +65 -0
- package/src/components/chart-container.tsx +51 -0
- package/src/components/chart-legend.tsx +49 -0
- package/src/components/chart-tooltip.tsx +93 -0
- package/src/components/combobox.tsx +9 -2
- package/src/components/donut-chart.tsx +217 -0
- package/src/components/form.tsx +1 -1
- package/src/components/heatmap-chart.tsx +331 -0
- package/src/components/line-chart.tsx +277 -0
- package/src/components/stat.tsx +113 -0
- package/src/components/textarea.tsx +1 -1
- package/src/components/wizard.tsx +1 -35
- package/src/hooks/use-chart-theme.ts +75 -0
- package/src/hooks/use-reduced-motion.ts +17 -0
- package/src/lib/chart-palette.ts +110 -0
- package/src/lib/chart.ts +90 -0
- package/src/stories/area-chart.stories.tsx +198 -0
- package/src/stories/bar-chart.stories.tsx +167 -0
- package/src/stories/bar-list.stories.tsx +83 -0
- package/src/stories/donut-chart.stories.tsx +110 -0
- package/src/stories/heatmap-chart.stories.tsx +105 -0
- package/src/stories/line-chart.stories.tsx +144 -0
- package/src/stories/stat.stories.tsx +64 -0
- package/src/stories/textarea.stories.tsx +7 -0
- package/src/stories/wizard.stories.tsx +23 -5
- package/src/styles/tokens.css +18 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.mjs";
|
|
3
|
+
import { useReducedMotion } from "../hooks/use-reduced-motion.mjs";
|
|
4
|
+
import { makeXAxisTick, orderByLuminance, 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 { Bar, BarChart as BarChart$1, CartesianGrid, LabelList, ReferenceArea, ReferenceDot, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
|
|
11
|
+
//#region src/components/bar-chart.tsx
|
|
12
|
+
const BAR_RADIUS = 4;
|
|
13
|
+
const MAX_BAR_SIZE = 48;
|
|
14
|
+
function BarChart({ data, index, series, variant = "stacked", legend = false, legendAlign = "left", valueLabels = false, height = 200, yAxisWidth = 48, palette, referenceLine, markers, texture = false, loading = false, valueFormatter = (value) => value.toLocaleString("en-US"), labelFormatter, className }) {
|
|
15
|
+
const { palette: paletteColors, theme } = useChartContext(palette);
|
|
16
|
+
const reactId = React$1.useId().replace(/:/g, "");
|
|
17
|
+
const animated = !useReducedMotion();
|
|
18
|
+
const resolved = resolveSeries(series, paletteColors, theme);
|
|
19
|
+
const stacked = variant === "stacked" || variant === "expand";
|
|
20
|
+
const rendered = stacked ? orderByLuminance(resolved) : resolved;
|
|
21
|
+
const lead = resolved[0];
|
|
22
|
+
const withTotal = stacked && rendered.length > 1;
|
|
23
|
+
const numericMax = React$1.useMemo(() => {
|
|
24
|
+
let max = 0;
|
|
25
|
+
for (const row of data) {
|
|
26
|
+
let rowTotal = 0;
|
|
27
|
+
for (const entry of series) {
|
|
28
|
+
const value = Number(row[entry.key]);
|
|
29
|
+
if (Number.isFinite(value)) {
|
|
30
|
+
rowTotal += value;
|
|
31
|
+
if (!stacked && value > max) max = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (stacked && rowTotal > max) max = rowTotal;
|
|
35
|
+
}
|
|
36
|
+
return max;
|
|
37
|
+
}, [
|
|
38
|
+
data,
|
|
39
|
+
series,
|
|
40
|
+
stacked
|
|
41
|
+
]);
|
|
42
|
+
const margin = {
|
|
43
|
+
top: markers?.length || valueLabels ? 18 : 8,
|
|
44
|
+
right: 8,
|
|
45
|
+
bottom: 2,
|
|
46
|
+
left: 0
|
|
47
|
+
};
|
|
48
|
+
const axis = {
|
|
49
|
+
stroke: theme.border,
|
|
50
|
+
tick: {
|
|
51
|
+
fill: theme.axisForeground,
|
|
52
|
+
fontSize: 10,
|
|
53
|
+
fontFamily: theme.fontMono
|
|
54
|
+
},
|
|
55
|
+
tickLine: false,
|
|
56
|
+
axisLine: {
|
|
57
|
+
stroke: theme.border,
|
|
58
|
+
strokeOpacity: .6
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const legendItems = resolved.map((entry) => ({
|
|
62
|
+
name: entry.name,
|
|
63
|
+
color: entry.color,
|
|
64
|
+
dashed: entry.dashed
|
|
65
|
+
}));
|
|
66
|
+
const radiusFor = (slot) => {
|
|
67
|
+
if (!stacked || slot === rendered.length - 1) return [
|
|
68
|
+
BAR_RADIUS,
|
|
69
|
+
BAR_RADIUS,
|
|
70
|
+
0,
|
|
71
|
+
0
|
|
72
|
+
];
|
|
73
|
+
return [
|
|
74
|
+
0,
|
|
75
|
+
0,
|
|
76
|
+
0,
|
|
77
|
+
0
|
|
78
|
+
];
|
|
79
|
+
};
|
|
80
|
+
const fillFor = (entry, slot) => {
|
|
81
|
+
if (texture && lead && entry.key === lead.key) return `url(#bar-hatch-${reactId})`;
|
|
82
|
+
if (stacked) return entry.color;
|
|
83
|
+
return `url(#bar-${reactId}-${slot})`;
|
|
84
|
+
};
|
|
85
|
+
const renderValueLabel = (color) => (props) => {
|
|
86
|
+
if (props.x == null || props.y == null) return null;
|
|
87
|
+
return /* @__PURE__ */ jsx("text", {
|
|
88
|
+
x: Number(props.x) + Number(props.width ?? 0) / 2,
|
|
89
|
+
y: Number(props.y) - 5,
|
|
90
|
+
textAnchor: "middle",
|
|
91
|
+
fill: color,
|
|
92
|
+
fontFamily: theme.fontMono,
|
|
93
|
+
fontSize: 10,
|
|
94
|
+
style: { fontVariantNumeric: "tabular-nums" },
|
|
95
|
+
children: valueFormatter(Number(props.value ?? 0))
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const isEmpty = data.length === 0 || rendered.length === 0;
|
|
99
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
100
|
+
"data-slot": "bar-chart",
|
|
101
|
+
className: cn("flex w-full flex-col gap-3", className),
|
|
102
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
103
|
+
className: "w-full",
|
|
104
|
+
style: { height },
|
|
105
|
+
children: loading ? /* @__PURE__ */ jsxs("div", {
|
|
106
|
+
className: "flex h-full items-center justify-center gap-2.5 font-mono text-quaternary-foreground text-text-xs",
|
|
107
|
+
children: [/* @__PURE__ */ jsx("span", { className: "size-4 animate-spin rounded-full border-2 border-border border-t-foreground" }), "loading…"]
|
|
108
|
+
}) : isEmpty ? /* @__PURE__ */ jsx("div", {
|
|
109
|
+
className: "flex h-full items-center justify-center rounded-lg border border-border border-dashed font-mono text-quaternary-foreground text-text-xs",
|
|
110
|
+
children: "no data in range"
|
|
111
|
+
}) : /* @__PURE__ */ jsx(ResponsiveContainer, {
|
|
112
|
+
width: "100%",
|
|
113
|
+
height: "100%",
|
|
114
|
+
initialDimension: {
|
|
115
|
+
width: 0,
|
|
116
|
+
height
|
|
117
|
+
},
|
|
118
|
+
children: /* @__PURE__ */ jsxs(BarChart$1, {
|
|
119
|
+
data,
|
|
120
|
+
stackOffset: variant === "expand" ? "expand" : "none",
|
|
121
|
+
margin,
|
|
122
|
+
barCategoryGap: stacked ? "20%" : "16%",
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ jsxs("defs", { children: [!stacked && rendered.map((entry, slot) => /* @__PURE__ */ jsxs("linearGradient", {
|
|
125
|
+
id: `bar-${reactId}-${slot}`,
|
|
126
|
+
x1: "0",
|
|
127
|
+
y1: "0",
|
|
128
|
+
x2: "0",
|
|
129
|
+
y2: "1",
|
|
130
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
131
|
+
offset: "0%",
|
|
132
|
+
stopColor: entry.color,
|
|
133
|
+
stopOpacity: .95
|
|
134
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
135
|
+
offset: "100%",
|
|
136
|
+
stopColor: entry.color,
|
|
137
|
+
stopOpacity: .5
|
|
138
|
+
})]
|
|
139
|
+
}, entry.key)), texture && lead && /* @__PURE__ */ jsxs("pattern", {
|
|
140
|
+
id: `bar-hatch-${reactId}`,
|
|
141
|
+
patternUnits: "userSpaceOnUse",
|
|
142
|
+
width: 6,
|
|
143
|
+
height: 6,
|
|
144
|
+
patternTransform: "rotate(45)",
|
|
145
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
146
|
+
width: 6,
|
|
147
|
+
height: 6,
|
|
148
|
+
fill: lead.color,
|
|
149
|
+
fillOpacity: .22
|
|
150
|
+
}), /* @__PURE__ */ jsx("line", {
|
|
151
|
+
x1: 0,
|
|
152
|
+
y1: 0,
|
|
153
|
+
x2: 0,
|
|
154
|
+
y2: 6,
|
|
155
|
+
stroke: lead.color,
|
|
156
|
+
strokeWidth: 1.2,
|
|
157
|
+
strokeOpacity: .65
|
|
158
|
+
})]
|
|
159
|
+
})] }),
|
|
160
|
+
/* @__PURE__ */ jsx(CartesianGrid, {
|
|
161
|
+
vertical: false,
|
|
162
|
+
stroke: theme.grid,
|
|
163
|
+
strokeDasharray: "2 4"
|
|
164
|
+
}),
|
|
165
|
+
/* @__PURE__ */ jsx(XAxis, {
|
|
166
|
+
dataKey: index,
|
|
167
|
+
...axis,
|
|
168
|
+
tick: makeXAxisTick(theme),
|
|
169
|
+
interval: "preserveStartEnd",
|
|
170
|
+
minTickGap: 44
|
|
171
|
+
}),
|
|
172
|
+
/* @__PURE__ */ jsx(YAxis, {
|
|
173
|
+
...axis,
|
|
174
|
+
width: yAxisWidth,
|
|
175
|
+
domain: referenceLine && variant !== "expand" ? [0, Math.ceil(Math.max(numericMax, referenceLine.y) * 1.15)] : void 0,
|
|
176
|
+
tickFormatter: (value) => variant === "expand" ? `${Math.round(value * 100)}%` : valueFormatter(value)
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
179
|
+
offset: 12,
|
|
180
|
+
allowEscapeViewBox: {
|
|
181
|
+
x: false,
|
|
182
|
+
y: false
|
|
183
|
+
},
|
|
184
|
+
cursor: {
|
|
185
|
+
fill: lead?.color ?? theme.mutedForeground,
|
|
186
|
+
fillOpacity: theme.isDark ? .1 : .06
|
|
187
|
+
},
|
|
188
|
+
content: /* @__PURE__ */ jsx(ChartTooltipContent, {
|
|
189
|
+
valueFormatter,
|
|
190
|
+
labelFormatter,
|
|
191
|
+
showTotal: withTotal
|
|
192
|
+
})
|
|
193
|
+
}),
|
|
194
|
+
referenceLine?.band && /* @__PURE__ */ jsx(ReferenceArea, {
|
|
195
|
+
y1: referenceLine.y,
|
|
196
|
+
y2: numericMax,
|
|
197
|
+
fill: theme.warning,
|
|
198
|
+
fillOpacity: .06,
|
|
199
|
+
ifOverflow: "extendDomain"
|
|
200
|
+
}),
|
|
201
|
+
referenceLine && /* @__PURE__ */ jsx(ReferenceLine, {
|
|
202
|
+
y: referenceLine.y,
|
|
203
|
+
stroke: theme.warning,
|
|
204
|
+
strokeDasharray: "4 4",
|
|
205
|
+
strokeOpacity: .6,
|
|
206
|
+
label: referenceLine.label ? {
|
|
207
|
+
value: referenceLine.label,
|
|
208
|
+
fill: theme.warning,
|
|
209
|
+
fontSize: 9,
|
|
210
|
+
fontFamily: theme.fontMono,
|
|
211
|
+
position: "insideBottomRight"
|
|
212
|
+
} : void 0
|
|
213
|
+
}),
|
|
214
|
+
rendered.map((entry, slot) => /* @__PURE__ */ jsx(Bar, {
|
|
215
|
+
dataKey: entry.key,
|
|
216
|
+
name: entry.name,
|
|
217
|
+
stackId: stacked ? "stack" : void 0,
|
|
218
|
+
fill: fillFor(entry, slot),
|
|
219
|
+
stroke: entry.color,
|
|
220
|
+
strokeWidth: 0,
|
|
221
|
+
radius: radiusFor(slot),
|
|
222
|
+
maxBarSize: MAX_BAR_SIZE,
|
|
223
|
+
activeBar: {
|
|
224
|
+
fillOpacity: 1,
|
|
225
|
+
stroke: theme.card,
|
|
226
|
+
strokeWidth: 1
|
|
227
|
+
},
|
|
228
|
+
isAnimationActive: animated,
|
|
229
|
+
animationDuration: 650,
|
|
230
|
+
animationEasing: "ease-out",
|
|
231
|
+
children: valueLabels && (!stacked || rendered.length === 1) && /* @__PURE__ */ jsx(LabelList, {
|
|
232
|
+
dataKey: entry.key,
|
|
233
|
+
content: renderValueLabel(entry.color)
|
|
234
|
+
})
|
|
235
|
+
}, entry.key)),
|
|
236
|
+
markers?.map((marker) => /* @__PURE__ */ jsx(ReferenceDot, {
|
|
237
|
+
x: marker.x,
|
|
238
|
+
y: marker.y,
|
|
239
|
+
r: 3.5,
|
|
240
|
+
fill: marker.color ?? theme.foreground,
|
|
241
|
+
stroke: theme.card,
|
|
242
|
+
strokeWidth: 2,
|
|
243
|
+
label: marker.label ? {
|
|
244
|
+
value: marker.label,
|
|
245
|
+
fill: marker.color ?? theme.foreground,
|
|
246
|
+
fontSize: 9,
|
|
247
|
+
fontFamily: theme.fontMono,
|
|
248
|
+
position: "top"
|
|
249
|
+
} : void 0
|
|
250
|
+
}, `${marker.x}-${marker.y}`))
|
|
251
|
+
]
|
|
252
|
+
})
|
|
253
|
+
})
|
|
254
|
+
}), legend && !isEmpty && /* @__PURE__ */ jsx(ChartLegend, {
|
|
255
|
+
items: legendItems,
|
|
256
|
+
align: legendAlign,
|
|
257
|
+
insetLeft: yAxisWidth
|
|
258
|
+
})]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
export { BarChart };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ChartPaletteName } from "../lib/chart-palette.mjs";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/bar-list.d.ts
|
|
5
|
+
interface BarListProps {
|
|
6
|
+
data: ReadonlyArray<Record<string, string | number | null | undefined>>;
|
|
7
|
+
index: string;
|
|
8
|
+
dataKey?: string;
|
|
9
|
+
maxItems?: number;
|
|
10
|
+
palette?: ChartPaletteName;
|
|
11
|
+
/** Renders bars in a single semantic hue (e.g. red for errors) rather than the palette ramp. */
|
|
12
|
+
semantic?: "error" | "warning" | "success";
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
valueFormatter?: (value: number) => string;
|
|
15
|
+
labelFormatter?: (label: string | number) => string;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
declare function BarList({
|
|
19
|
+
data,
|
|
20
|
+
index,
|
|
21
|
+
dataKey,
|
|
22
|
+
maxItems,
|
|
23
|
+
palette,
|
|
24
|
+
semantic,
|
|
25
|
+
loading,
|
|
26
|
+
valueFormatter,
|
|
27
|
+
labelFormatter,
|
|
28
|
+
className
|
|
29
|
+
}: BarListProps): React$1.JSX.Element;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { BarList, BarListProps };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.mjs";
|
|
3
|
+
import { useReducedMotion } from "../hooks/use-reduced-motion.mjs";
|
|
4
|
+
import { rampColor } from "../lib/chart-palette.mjs";
|
|
5
|
+
import { formatShare } from "../lib/chart.mjs";
|
|
6
|
+
import { useChartContext } from "./chart-container.mjs";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import * as React$1 from "react";
|
|
9
|
+
//#region src/components/bar-list.tsx
|
|
10
|
+
const SEMANTIC_KEY = {
|
|
11
|
+
error: "destructive",
|
|
12
|
+
warning: "warning",
|
|
13
|
+
success: "success"
|
|
14
|
+
};
|
|
15
|
+
const PLACEHOLDER_HEIGHT = 168;
|
|
16
|
+
const RAMP_CEILING = .8;
|
|
17
|
+
const SEMANTIC_FLOOR = .62;
|
|
18
|
+
const IN_FILL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.28)";
|
|
19
|
+
function BarList({ data, index, dataKey = "value", maxItems, palette, semantic, loading = false, valueFormatter = (value) => value.toLocaleString("en-US"), labelFormatter, className }) {
|
|
20
|
+
const { paletteName, theme } = useChartContext(palette);
|
|
21
|
+
const accent = semantic ? theme[SEMANTIC_KEY[semantic]] : null;
|
|
22
|
+
const reducedMotion = useReducedMotion();
|
|
23
|
+
const [mounted, setMounted] = React$1.useState(false);
|
|
24
|
+
const [active, setActive] = React$1.useState(null);
|
|
25
|
+
React$1.useEffect(() => {
|
|
26
|
+
setMounted(true);
|
|
27
|
+
}, []);
|
|
28
|
+
const total = React$1.useMemo(() => data.reduce((sum, row) => sum + (Number(row[dataKey]) || 0), 0), [data, dataKey]);
|
|
29
|
+
const rows = React$1.useMemo(() => {
|
|
30
|
+
const mapped = data.map((row) => ({
|
|
31
|
+
name: String(row[index] ?? ""),
|
|
32
|
+
value: Number(row[dataKey]) || 0
|
|
33
|
+
}));
|
|
34
|
+
mapped.sort((lower, upper) => upper.value - lower.value);
|
|
35
|
+
const capped = maxItems ? mapped.slice(0, maxItems) : mapped;
|
|
36
|
+
return capped.map((row, rank) => {
|
|
37
|
+
const rankFraction = capped.length > 1 ? rank / (capped.length - 1) : 0;
|
|
38
|
+
const accentWeight = Math.round((1 - rankFraction * (1 - SEMANTIC_FLOOR)) * 100);
|
|
39
|
+
return {
|
|
40
|
+
...row,
|
|
41
|
+
color: accent ? `color-mix(in oklab, ${accent} ${accentWeight}%, white)` : rampColor(paletteName, rankFraction * RAMP_CEILING)
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}, [
|
|
45
|
+
data,
|
|
46
|
+
index,
|
|
47
|
+
dataKey,
|
|
48
|
+
maxItems,
|
|
49
|
+
paletteName,
|
|
50
|
+
accent
|
|
51
|
+
]);
|
|
52
|
+
const maxValue = rows.reduce((max, row) => row.value > max ? row.value : max, 0);
|
|
53
|
+
const isEmpty = rows.length === 0;
|
|
54
|
+
const formatName = (name) => labelFormatter ? labelFormatter(name) : name;
|
|
55
|
+
if (loading) return /* @__PURE__ */ jsxs("div", {
|
|
56
|
+
className: cn("flex items-center justify-center gap-2.5 font-mono text-quaternary-foreground text-text-xs", className),
|
|
57
|
+
style: { minHeight: PLACEHOLDER_HEIGHT },
|
|
58
|
+
children: [/* @__PURE__ */ jsx("span", { className: "size-4 animate-spin rounded-full border-2 border-border border-t-foreground" }), "loading…"]
|
|
59
|
+
});
|
|
60
|
+
if (isEmpty) return /* @__PURE__ */ jsx("div", {
|
|
61
|
+
className: cn("flex items-center justify-center rounded-lg border border-border border-dashed font-mono text-quaternary-foreground text-text-xs", className),
|
|
62
|
+
style: { minHeight: PLACEHOLDER_HEIGHT },
|
|
63
|
+
children: "no data in range"
|
|
64
|
+
});
|
|
65
|
+
return /* @__PURE__ */ jsx("div", {
|
|
66
|
+
"data-slot": "bar-list",
|
|
67
|
+
className: cn("flex w-full flex-col", className),
|
|
68
|
+
children: rows.map((row, slot) => {
|
|
69
|
+
const fraction = maxValue > 0 ? row.value / maxValue : 0;
|
|
70
|
+
const fillWidth = !reducedMotion && !mounted ? "0%" : `${fraction * 100}%`;
|
|
71
|
+
const dimmed = active !== null && active !== slot;
|
|
72
|
+
const isActive = active === slot;
|
|
73
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
74
|
+
onMouseEnter: () => setActive(slot),
|
|
75
|
+
onMouseLeave: () => setActive(null),
|
|
76
|
+
className: "flex items-center gap-3 py-1",
|
|
77
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
78
|
+
className: "relative h-[30px] flex-1 overflow-hidden rounded-md bg-muted",
|
|
79
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
80
|
+
className: "pointer-events-none absolute inset-x-3 top-1/2 z-0 -translate-y-1/2 truncate type-text-xs font-medium text-foreground",
|
|
81
|
+
children: formatName(row.name)
|
|
82
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
83
|
+
className: "absolute inset-y-0 left-0 z-10 overflow-hidden rounded-md",
|
|
84
|
+
style: {
|
|
85
|
+
width: fillWidth,
|
|
86
|
+
background: `linear-gradient(90deg, ${row.color}, color-mix(in oklab, ${row.color} 82%, transparent))`,
|
|
87
|
+
boxShadow: `inset 0 0 0 1px ${row.color}`,
|
|
88
|
+
opacity: dimmed ? .45 : 1,
|
|
89
|
+
transition: reducedMotion ? void 0 : "width 700ms ease-out"
|
|
90
|
+
},
|
|
91
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
92
|
+
className: "pointer-events-none absolute top-1/2 -translate-y-1/2 truncate type-text-xs font-medium text-white",
|
|
93
|
+
style: {
|
|
94
|
+
left: 12,
|
|
95
|
+
width: `calc(${100 / Math.max(fraction, 1e-4)}% - 24px)`,
|
|
96
|
+
textShadow: IN_FILL_SHADOW
|
|
97
|
+
},
|
|
98
|
+
children: formatName(row.name)
|
|
99
|
+
})
|
|
100
|
+
})]
|
|
101
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
102
|
+
className: "min-w-[4rem] shrink-0 whitespace-nowrap text-right font-mono text-text-xs tabular-nums motion-safe:transition-colors",
|
|
103
|
+
style: { color: isActive ? row.color : void 0 },
|
|
104
|
+
children: isActive ? formatShare(total > 0 ? row.value / total : 0) : valueFormatter(row.value)
|
|
105
|
+
})]
|
|
106
|
+
}, row.name);
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { BarList };
|
|
@@ -1,42 +1,41 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as React from "react";
|
|
1
|
+
import * as React$1 from "react";
|
|
3
2
|
|
|
4
3
|
//#region src/components/breadcrumb.d.ts
|
|
5
4
|
declare function Breadcrumb({
|
|
6
5
|
className,
|
|
7
6
|
...props
|
|
8
|
-
}: React.ComponentProps<"nav">):
|
|
7
|
+
}: React$1.ComponentProps<"nav">): React$1.JSX.Element;
|
|
9
8
|
declare function BreadcrumbList({
|
|
10
9
|
className,
|
|
11
10
|
...props
|
|
12
|
-
}: React.ComponentProps<"ol">):
|
|
11
|
+
}: React$1.ComponentProps<"ol">): React$1.JSX.Element;
|
|
13
12
|
declare function BreadcrumbItem({
|
|
14
13
|
className,
|
|
15
14
|
...props
|
|
16
|
-
}: React.ComponentProps<"li">):
|
|
15
|
+
}: React$1.ComponentProps<"li">): React$1.JSX.Element;
|
|
17
16
|
declare function BreadcrumbLink({
|
|
18
17
|
asChild,
|
|
19
18
|
className,
|
|
20
19
|
...props
|
|
21
|
-
}: React.ComponentProps<"a"> & {
|
|
20
|
+
}: React$1.ComponentProps<"a"> & {
|
|
22
21
|
asChild?: boolean;
|
|
23
|
-
}):
|
|
22
|
+
}): React$1.JSX.Element;
|
|
24
23
|
declare function BreadcrumbPage({
|
|
25
24
|
className,
|
|
26
25
|
...props
|
|
27
|
-
}: React.ComponentProps<"span">):
|
|
26
|
+
}: React$1.ComponentProps<"span">): React$1.JSX.Element;
|
|
28
27
|
declare function BreadcrumbSeparator({
|
|
29
28
|
children,
|
|
30
29
|
className,
|
|
31
30
|
...props
|
|
32
|
-
}: React.ComponentProps<"li">):
|
|
31
|
+
}: React$1.ComponentProps<"li">): React$1.JSX.Element;
|
|
33
32
|
declare function BreadcrumbChevron({
|
|
34
33
|
className,
|
|
35
34
|
...props
|
|
36
|
-
}: React.ComponentProps<"span">):
|
|
35
|
+
}: React$1.ComponentProps<"span">): React$1.JSX.Element;
|
|
37
36
|
declare function BreadcrumbEllipsis({
|
|
38
37
|
className,
|
|
39
38
|
...props
|
|
40
|
-
}: React.ComponentProps<"span">):
|
|
39
|
+
}: React$1.ComponentProps<"span">): React$1.JSX.Element;
|
|
41
40
|
//#endregion
|
|
42
41
|
export { Breadcrumb, BreadcrumbChevron, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator };
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { VariantProps } from "class-variance-authority";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import * as _$class_variance_authority_types0 from "class-variance-authority/types";
|
|
2
|
+
import * as React$1 from "react";
|
|
5
3
|
|
|
6
4
|
//#region src/components/button.d.ts
|
|
7
5
|
declare const buttonVariants: (props?: ({
|
|
8
6
|
variant?: "destructive" | "secondary" | "primary" | "tertiary" | "link" | "link-muted" | "cta" | null | undefined;
|
|
9
7
|
size?: "default" | "icon" | "icon-rounded" | "pill" | null | undefined;
|
|
10
|
-
} &
|
|
11
|
-
interface ButtonProps extends React.ComponentProps<"button">, VariantProps<typeof buttonVariants> {
|
|
8
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
9
|
+
interface ButtonProps extends React$1.ComponentProps<"button">, VariantProps<typeof buttonVariants> {
|
|
12
10
|
asChild?: boolean;
|
|
13
11
|
loading?: boolean;
|
|
14
|
-
icon?: React.ReactNode;
|
|
15
|
-
iconTrailing?: React.ReactNode;
|
|
12
|
+
icon?: React$1.ReactNode;
|
|
13
|
+
iconTrailing?: React$1.ReactNode;
|
|
16
14
|
}
|
|
17
15
|
declare function Button({
|
|
18
16
|
className,
|
|
@@ -26,6 +24,6 @@ declare function Button({
|
|
|
26
24
|
disabled,
|
|
27
25
|
children,
|
|
28
26
|
...props
|
|
29
|
-
}: ButtonProps):
|
|
27
|
+
}: ButtonProps): React$1.JSX.Element;
|
|
30
28
|
//#endregion
|
|
31
29
|
export { Button, type ButtonProps, buttonVariants };
|
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as React from "react";
|
|
1
|
+
import * as React$1 from "react";
|
|
3
2
|
|
|
4
3
|
//#region src/components/card.d.ts
|
|
5
4
|
declare function Card({
|
|
6
5
|
className,
|
|
7
6
|
hoverable,
|
|
8
7
|
...props
|
|
9
|
-
}: React.ComponentProps<"div"> & {
|
|
8
|
+
}: React$1.ComponentProps<"div"> & {
|
|
10
9
|
hoverable?: boolean;
|
|
11
|
-
}):
|
|
10
|
+
}): React$1.JSX.Element;
|
|
12
11
|
declare function CardHeader({
|
|
13
12
|
className,
|
|
14
13
|
...props
|
|
15
|
-
}: React.ComponentProps<"div">):
|
|
14
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
16
15
|
declare function CardTitle({
|
|
17
16
|
className,
|
|
18
17
|
...props
|
|
19
|
-
}: React.ComponentProps<"div">):
|
|
18
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
20
19
|
declare function CardDescription({
|
|
21
20
|
className,
|
|
22
21
|
...props
|
|
23
|
-
}: React.ComponentProps<"div">):
|
|
22
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
24
23
|
declare function CardAction({
|
|
25
24
|
className,
|
|
26
25
|
...props
|
|
27
|
-
}: React.ComponentProps<"div">):
|
|
26
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
28
27
|
declare function CardContent({
|
|
29
28
|
className,
|
|
30
29
|
...props
|
|
31
|
-
}: React.ComponentProps<"div">):
|
|
30
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
32
31
|
declare function CardFooter({
|
|
33
32
|
className,
|
|
34
33
|
...props
|
|
35
|
-
}: React.ComponentProps<"div">):
|
|
34
|
+
}: React$1.ComponentProps<"div">): React$1.JSX.Element;
|
|
36
35
|
//#endregion
|
|
37
36
|
export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ChartPaletteName } from "../lib/chart-palette.mjs";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/chart-card.d.ts
|
|
5
|
+
interface ChartCardProps extends Omit<React$1.ComponentProps<"section">, "title"> {
|
|
6
|
+
palette?: ChartPaletteName;
|
|
7
|
+
kicker?: React$1.ReactNode;
|
|
8
|
+
title?: React$1.ReactNode;
|
|
9
|
+
description?: React$1.ReactNode;
|
|
10
|
+
action?: React$1.ReactNode;
|
|
11
|
+
accent?: "top" | "left" | "none";
|
|
12
|
+
}
|
|
13
|
+
declare function ChartCard({
|
|
14
|
+
palette,
|
|
15
|
+
kicker,
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
action,
|
|
19
|
+
accent,
|
|
20
|
+
className,
|
|
21
|
+
children,
|
|
22
|
+
...props
|
|
23
|
+
}: ChartCardProps): React$1.JSX.Element;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ChartCard, ChartCardProps };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.mjs";
|
|
3
|
+
import { CHART_PALETTES } from "../lib/chart-palette.mjs";
|
|
4
|
+
import { ChartContainer } from "./chart-container.mjs";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/chart-card.tsx
|
|
7
|
+
function ChartCard({ palette = "magenta", kicker, title, description, action, accent = "top", className, children, ...props }) {
|
|
8
|
+
const lead = CHART_PALETTES[palette][0];
|
|
9
|
+
const isLeft = accent === "left";
|
|
10
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
11
|
+
"data-slot": "chart-card",
|
|
12
|
+
className: cn("chart-rise relative overflow-hidden rounded-xl border bg-card p-5 text-card-foreground shadow-shadow", isLeft && "pl-6", className),
|
|
13
|
+
...props,
|
|
14
|
+
children: [
|
|
15
|
+
accent !== "none" && /* @__PURE__ */ jsx("span", {
|
|
16
|
+
"aria-hidden": true,
|
|
17
|
+
className: cn("absolute", isLeft ? "inset-y-0 left-0 w-[3px]" : "inset-x-0 top-0 h-[3px]"),
|
|
18
|
+
style: { background: lead }
|
|
19
|
+
}),
|
|
20
|
+
(kicker || title || action) && /* @__PURE__ */ jsxs("header", {
|
|
21
|
+
className: "mb-4 flex items-start justify-between gap-4",
|
|
22
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
23
|
+
className: "flex flex-col gap-1",
|
|
24
|
+
children: [
|
|
25
|
+
kicker && /* @__PURE__ */ jsx("span", {
|
|
26
|
+
className: "font-mono text-[10px] text-primary uppercase tracking-[0.18em]",
|
|
27
|
+
children: kicker
|
|
28
|
+
}),
|
|
29
|
+
title && /* @__PURE__ */ jsx("h3", {
|
|
30
|
+
className: "type-text-md font-semibold leading-none tracking-tight",
|
|
31
|
+
children: title
|
|
32
|
+
}),
|
|
33
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
34
|
+
className: "type-text-xs text-muted-foreground",
|
|
35
|
+
children: description
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
}), action]
|
|
39
|
+
}),
|
|
40
|
+
/* @__PURE__ */ jsx(ChartContainer, {
|
|
41
|
+
palette,
|
|
42
|
+
children
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { ChartCard };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChartTheme } from "../hooks/use-chart-theme.mjs";
|
|
2
|
+
import { ChartPaletteName } from "../lib/chart-palette.mjs";
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/components/chart-container.d.ts
|
|
6
|
+
interface ChartContextValue {
|
|
7
|
+
palette: readonly string[];
|
|
8
|
+
paletteName: ChartPaletteName;
|
|
9
|
+
theme: ChartTheme;
|
|
10
|
+
}
|
|
11
|
+
declare function ChartContainer({
|
|
12
|
+
palette,
|
|
13
|
+
className,
|
|
14
|
+
...props
|
|
15
|
+
}: React$1.ComponentProps<"div"> & {
|
|
16
|
+
palette?: ChartPaletteName;
|
|
17
|
+
}): React$1.JSX.Element;
|
|
18
|
+
declare function useChartContext(paletteOverride?: ChartPaletteName): ChartContextValue;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { ChartContainer, type ChartContextValue, type ChartPaletteName, useChartContext };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.mjs";
|
|
3
|
+
import { CHART_PALETTES } from "../lib/chart-palette.mjs";
|
|
4
|
+
import { useChartTheme } from "../hooks/use-chart-theme.mjs";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import * as React$1 from "react";
|
|
7
|
+
//#region src/components/chart-container.tsx
|
|
8
|
+
const ChartContext = React$1.createContext(null);
|
|
9
|
+
function ChartContainer({ palette = "magenta", className, ...props }) {
|
|
10
|
+
const theme = useChartTheme();
|
|
11
|
+
const value = React$1.useMemo(() => ({
|
|
12
|
+
palette: CHART_PALETTES[palette],
|
|
13
|
+
paletteName: palette,
|
|
14
|
+
theme
|
|
15
|
+
}), [palette, theme]);
|
|
16
|
+
return /* @__PURE__ */ jsx(ChartContext.Provider, {
|
|
17
|
+
value,
|
|
18
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
19
|
+
"data-slot": "chart-container",
|
|
20
|
+
className: cn("flex flex-col gap-4", className),
|
|
21
|
+
...props
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function useChartContext(paletteOverride) {
|
|
26
|
+
const provided = React$1.useContext(ChartContext);
|
|
27
|
+
const fallbackTheme = useChartTheme();
|
|
28
|
+
if (provided && !paletteOverride) return provided;
|
|
29
|
+
const paletteName = paletteOverride ?? provided?.paletteName ?? "magenta";
|
|
30
|
+
return {
|
|
31
|
+
palette: CHART_PALETTES[paletteName],
|
|
32
|
+
paletteName,
|
|
33
|
+
theme: provided?.theme ?? fallbackTheme
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { ChartContainer, useChartContext };
|