export function MetricCard({ item, loading = false, onClick }) {
const Icon = item.icon;
const UnitIcon = item.unitIcon;
const clickable = Boolean(onClick);
if (loading) {
return (
{Icon ?
: null}
);
}
return (
{
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
onClick();
}
} : undefined}
>
{Icon ? : null}
{item.label}
{UnitIcon ? : null}
{item.unit ? {item.unit} : null}
{Array.isArray(item.subMetrics) && item.subMetrics.length ?
:
}
);
}
function MetricMainValue({ item }) {
return (
<>
{item.value}
>
);
}
function MetricSubValues({ items }) {
return (
{items.map((subItem) => (
{subItem.label}
{subItem.value}
))}
);
}
function MetricDelta({ compact = false, item }) {
const tone = item.deltaTone || (String(item.delta || "").trim().startsWith("-") ? "down" : "up");
return (
{item.caption}
{item.delta ? `${tone === "down" ? "↓" : "↑"} ${item.delta.replace(/^[-+]/, "")}` : "--"}
);
}
function MetricSparkline({ series }) {
const lines = Array.isArray(series) ? series.filter((item) => Array.isArray(item.data) && item.data.length > 1) : [];
if (!lines.length) {
return ;
}
const values = lines.flatMap((line) => line.data.map((point) => Number(point.value) || 0));
const min = Math.min(...values);
const max = Math.max(...values);
return (
);
}
function sparklinePoints(points, min, max) {
const width = 100;
const height = 24;
const count = points.length;
return points.map((point, index) => {
const x = count <= 1 ? width : (index / (count - 1)) * width;
const normalized = max <= min ? 0.5 : ((Number(point.value) || 0) - min) / (max - min);
const y = height - normalized * 18 - 3;
return `${x.toFixed(2)},${y.toFixed(2)}`;
}).join(" ");
}