2026-06-01 01:51:39 +08:00

54 lines
1.4 KiB
JavaScript

export function MiniStat({ item }) {
const caption = parseCaption(item.caption);
const deltaTone = item.deltaTone || (caption.delta.startsWith("-") ? "down" : "up");
return (
<article className="mini-stat">
<span>{item.label}</span>
<strong>{item.value}</strong>
<small className={`mini-stat-delta mini-stat-delta--${deltaTone}`}>
<span>{caption.label}</span>
{caption.delta ? <b>{`${deltaTone === "down" ? "↓" : "↑"} ${caption.delta.replace(/^[-+]/, "")}`}</b> : null}
</small>
</article>
);
}
function parseCaption(caption = "") {
const normalized = String(caption).trim().replace(/\s+/g, " ");
const match = normalized.match(/^(.*)\s([+-][\d.]+(?:%|pp)?)$/);
if (!match) {
return { delta: "", label: normalized };
}
return { delta: match[2], label: match[1] };
}
export function TwoMetricRow({ items }) {
return (
<div className="two-metric-row">
{items.map((item) => (
<MiniStat item={item} key={item.label} />
))}
</div>
);
}
export function FourMetricRow({ items }) {
return (
<div className="four-metric-row">
{items.map((item) => (
<MiniStat item={item} key={item.label} />
))}
</div>
);
}
export function FiveMetricRow({ items }) {
return (
<div className="five-metric-row">
{items.map((item) => (
<MiniStat item={item} key={item.label} />
))}
</div>
);
}