@misael703/ui 1.57.1 → 1.58.0
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/chunk-2RBVHLG4.mjs +305 -0
- package/dist/chunk-2RBVHLG4.mjs.map +1 -0
- package/dist/chunk-BULIPFOG.js +313 -0
- package/dist/chunk-BULIPFOG.js.map +1 -0
- package/dist/components/Metrics.d.mts +130 -0
- package/dist/components/Metrics.d.ts +130 -0
- package/dist/components/Metrics.js +41 -0
- package/dist/components/Metrics.js.map +1 -0
- package/dist/components/Metrics.mjs +8 -0
- package/dist/components/Metrics.mjs.map +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +66 -37
- package/dist/index.mjs +6 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { formatNumber } from './chunk-WYOJ7YRQ.mjs';
|
|
3
|
+
import { ArrowUp, ArrowDown, Minus } from './chunk-BJGMROKL.mjs';
|
|
4
|
+
import { cx } from './chunk-IEPCH3JB.mjs';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var SIGNED_PERCENT = (v) => {
|
|
8
|
+
const sign = v > 0 ? "+" : v < 0 ? "\u2212" : "";
|
|
9
|
+
return `${sign}${formatNumber(Math.abs(v), { maximumFractionDigits: 1 })}%`;
|
|
10
|
+
};
|
|
11
|
+
function DeltaBadge({
|
|
12
|
+
value,
|
|
13
|
+
format = SIGNED_PERCENT,
|
|
14
|
+
invert = false,
|
|
15
|
+
neutralThreshold = 0,
|
|
16
|
+
showIcon = true,
|
|
17
|
+
size = "md",
|
|
18
|
+
className,
|
|
19
|
+
...rest
|
|
20
|
+
}) {
|
|
21
|
+
const dir = value > neutralThreshold ? "up" : value < -neutralThreshold ? "down" : "flat";
|
|
22
|
+
const tone = dir === "flat" ? "flat" : dir === "up" ? invert ? "neg" : "pos" : invert ? "pos" : "neg";
|
|
23
|
+
const Icon = dir === "up" ? ArrowUp : dir === "down" ? ArrowDown : Minus;
|
|
24
|
+
const verb = dir === "up" ? "subi\xF3" : dir === "down" ? "baj\xF3" : "sin cambio";
|
|
25
|
+
const text = format(value);
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"span",
|
|
28
|
+
{
|
|
29
|
+
className: cx("delta-badge", `delta-badge--${tone}`, size === "sm" && "delta-badge--sm", className),
|
|
30
|
+
"aria-label": `${verb} ${text}`,
|
|
31
|
+
...rest,
|
|
32
|
+
children: [
|
|
33
|
+
showIcon && /* @__PURE__ */ jsx(Icon, { size: size === "sm" ? 11 : 13, "aria-hidden": true }),
|
|
34
|
+
/* @__PURE__ */ jsx("span", { className: "delta-badge__text", children: text })
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function StatCard({
|
|
40
|
+
label,
|
|
41
|
+
value,
|
|
42
|
+
delta,
|
|
43
|
+
deltaFormat,
|
|
44
|
+
deltaInvert,
|
|
45
|
+
deltaNode,
|
|
46
|
+
caption,
|
|
47
|
+
icon,
|
|
48
|
+
accent,
|
|
49
|
+
chart,
|
|
50
|
+
className,
|
|
51
|
+
...rest
|
|
52
|
+
}) {
|
|
53
|
+
const deltaEl = deltaNode ?? (delta !== void 0 ? /* @__PURE__ */ jsx(DeltaBadge, { value: delta, format: deltaFormat, invert: deltaInvert, size: "sm" }) : null);
|
|
54
|
+
return /* @__PURE__ */ jsxs(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: cx("metric-card", accent && `metric-card--${accent}`, className),
|
|
58
|
+
"data-accent": accent,
|
|
59
|
+
...rest,
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ jsxs("div", { className: "metric-card__head", children: [
|
|
62
|
+
icon && /* @__PURE__ */ jsx("span", { className: "metric-card__icon", "aria-hidden": true, children: icon }),
|
|
63
|
+
/* @__PURE__ */ jsx("span", { className: "metric-card__label", children: label })
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ jsx("div", { className: "metric-card__value", children: value }),
|
|
66
|
+
(deltaEl || caption) && /* @__PURE__ */ jsxs("div", { className: "metric-card__foot", children: [
|
|
67
|
+
deltaEl,
|
|
68
|
+
caption && /* @__PURE__ */ jsx("span", { className: "metric-card__caption", children: caption })
|
|
69
|
+
] }),
|
|
70
|
+
chart && /* @__PURE__ */ jsx("div", { className: "metric-card__chart", children: chart })
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
function meterTone(value, low, high, optimum) {
|
|
76
|
+
if (low === void 0 && high === void 0) return "pos";
|
|
77
|
+
const lo = low ?? -Infinity;
|
|
78
|
+
const hi = high ?? Infinity;
|
|
79
|
+
if (optimum === "high") return value >= hi ? "pos" : value >= lo ? "warn" : "neg";
|
|
80
|
+
if (optimum === "low") return value <= lo ? "pos" : value <= hi ? "warn" : "neg";
|
|
81
|
+
return value >= lo && value <= hi ? "pos" : "warn";
|
|
82
|
+
}
|
|
83
|
+
function Meter({
|
|
84
|
+
value,
|
|
85
|
+
min = 0,
|
|
86
|
+
max = 100,
|
|
87
|
+
low,
|
|
88
|
+
high,
|
|
89
|
+
optimum = "high",
|
|
90
|
+
label,
|
|
91
|
+
valueLabel,
|
|
92
|
+
showValue = true,
|
|
93
|
+
size = "md",
|
|
94
|
+
className,
|
|
95
|
+
...rest
|
|
96
|
+
}) {
|
|
97
|
+
const clamped = Math.min(Math.max(value, min), max);
|
|
98
|
+
const pct = max > min ? (clamped - min) / (max - min) * 100 : 0;
|
|
99
|
+
const tone = meterTone(value, low, high, optimum);
|
|
100
|
+
const hasThresholds = low !== void 0 || high !== void 0;
|
|
101
|
+
const caption = typeof valueLabel === "function" ? valueLabel(value, max) : valueLabel !== void 0 ? valueLabel : `${formatNumber(value)} / ${formatNumber(max)}`;
|
|
102
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("meter", size === "sm" && "meter--sm", className), ...rest, children: [
|
|
103
|
+
(label || showValue) && /* @__PURE__ */ jsxs("div", { className: "meter__head", children: [
|
|
104
|
+
label && /* @__PURE__ */ jsx("span", { className: "meter__label", children: label }),
|
|
105
|
+
showValue && /* @__PURE__ */ jsx("span", { className: "meter__value", children: caption })
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
"div",
|
|
109
|
+
{
|
|
110
|
+
className: "meter__track",
|
|
111
|
+
role: "meter",
|
|
112
|
+
"aria-valuenow": value,
|
|
113
|
+
"aria-valuemin": min,
|
|
114
|
+
"aria-valuemax": max,
|
|
115
|
+
"aria-label": typeof label === "string" ? label : void 0,
|
|
116
|
+
children: /* @__PURE__ */ jsx(
|
|
117
|
+
"div",
|
|
118
|
+
{
|
|
119
|
+
className: cx("meter__fill", hasThresholds ? `meter__fill--${tone}` : "meter__fill--primary"),
|
|
120
|
+
style: { width: `${pct}%` }
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
127
|
+
function Sparkbar({
|
|
128
|
+
data,
|
|
129
|
+
height = 32,
|
|
130
|
+
max,
|
|
131
|
+
color = "var(--color-primary)",
|
|
132
|
+
highlightLast = false,
|
|
133
|
+
gap = 2,
|
|
134
|
+
ariaLabel,
|
|
135
|
+
className,
|
|
136
|
+
style,
|
|
137
|
+
...rest
|
|
138
|
+
}) {
|
|
139
|
+
const ceiling = max ?? Math.max(1, ...data.map((d) => Number.isFinite(d) ? d : 0));
|
|
140
|
+
return /* @__PURE__ */ jsx(
|
|
141
|
+
"div",
|
|
142
|
+
{
|
|
143
|
+
className: cx("sparkbar", className),
|
|
144
|
+
role: "img",
|
|
145
|
+
"aria-label": ariaLabel,
|
|
146
|
+
style: { height, gap, ...style },
|
|
147
|
+
...rest,
|
|
148
|
+
children: data.map((d, i) => {
|
|
149
|
+
const isLast = highlightLast && i === data.length - 1;
|
|
150
|
+
const h = ceiling > 0 ? Math.max(2, Math.max(0, d) / ceiling * 100) : 2;
|
|
151
|
+
return /* @__PURE__ */ jsx(
|
|
152
|
+
"span",
|
|
153
|
+
{
|
|
154
|
+
className: cx("sparkbar__bar", isLast && "sparkbar__bar--last"),
|
|
155
|
+
style: { height: `${h}%`, background: isLast ? "var(--color-secondary)" : color }
|
|
156
|
+
},
|
|
157
|
+
i
|
|
158
|
+
);
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
var CAT_HUES = ["var(--cat-1)", "var(--cat-2)", "var(--cat-4)", "var(--cat-5)", "var(--cat-3)", "var(--cat-6)"];
|
|
164
|
+
function ProportionBar({
|
|
165
|
+
segments,
|
|
166
|
+
total,
|
|
167
|
+
showLegend = true,
|
|
168
|
+
showPercent = true,
|
|
169
|
+
height = 10,
|
|
170
|
+
ariaLabel,
|
|
171
|
+
className,
|
|
172
|
+
...rest
|
|
173
|
+
}) {
|
|
174
|
+
const sum = total ?? segments.reduce((a, s) => a + Math.max(0, s.value), 0);
|
|
175
|
+
const pctOf = (v) => sum > 0 ? Math.max(0, v) / sum * 100 : 0;
|
|
176
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("proportion", className), ...rest, children: [
|
|
177
|
+
/* @__PURE__ */ jsx("div", { className: "proportion__track", role: "img", "aria-label": ariaLabel, style: { height }, children: segments.map((s, i) => {
|
|
178
|
+
const pct = pctOf(s.value);
|
|
179
|
+
if (pct <= 0) return null;
|
|
180
|
+
return /* @__PURE__ */ jsx(
|
|
181
|
+
"span",
|
|
182
|
+
{
|
|
183
|
+
className: "proportion__seg",
|
|
184
|
+
style: { width: `${pct}%`, background: s.color ?? CAT_HUES[i % CAT_HUES.length] },
|
|
185
|
+
title: `${s.label}: ${formatNumber(s.value)}`
|
|
186
|
+
},
|
|
187
|
+
s.label
|
|
188
|
+
);
|
|
189
|
+
}) }),
|
|
190
|
+
showLegend && /* @__PURE__ */ jsx("ul", { className: "proportion__legend", children: segments.map((s, i) => /* @__PURE__ */ jsxs("li", { className: "proportion__legend-item", children: [
|
|
191
|
+
/* @__PURE__ */ jsx("span", { className: "proportion__swatch", style: { background: s.color ?? CAT_HUES[i % CAT_HUES.length] } }),
|
|
192
|
+
/* @__PURE__ */ jsx("span", { className: "proportion__legend-label", children: s.label }),
|
|
193
|
+
showPercent && /* @__PURE__ */ jsxs("span", { className: "proportion__legend-pct", children: [
|
|
194
|
+
formatNumber(pctOf(s.value), { maximumFractionDigits: 0 }),
|
|
195
|
+
"%"
|
|
196
|
+
] })
|
|
197
|
+
] }, s.label)) })
|
|
198
|
+
] });
|
|
199
|
+
}
|
|
200
|
+
function BulletChart({
|
|
201
|
+
value,
|
|
202
|
+
target,
|
|
203
|
+
min = 0,
|
|
204
|
+
max,
|
|
205
|
+
ranges = [],
|
|
206
|
+
label,
|
|
207
|
+
valueLabel,
|
|
208
|
+
tone = "primary",
|
|
209
|
+
height = 22,
|
|
210
|
+
ariaLabel,
|
|
211
|
+
className,
|
|
212
|
+
...rest
|
|
213
|
+
}) {
|
|
214
|
+
const scaleMax = max ?? Math.max(value, target ?? 0, ...ranges, 1);
|
|
215
|
+
const span = scaleMax - min || 1;
|
|
216
|
+
const toPct = (v) => Math.min(100, Math.max(0, (v - min) / span * 100));
|
|
217
|
+
const sortedRanges = [...ranges].sort((a, b) => a - b);
|
|
218
|
+
const bands = sortedRanges.map((r, i) => ({ from: i === 0 ? min : sortedRanges[i - 1], to: r, level: i }));
|
|
219
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("bullet", className), ...rest, children: [
|
|
220
|
+
(label || valueLabel) && /* @__PURE__ */ jsxs("div", { className: "bullet__head", children: [
|
|
221
|
+
label && /* @__PURE__ */ jsx("span", { className: "bullet__label", children: label }),
|
|
222
|
+
valueLabel && /* @__PURE__ */ jsx("span", { className: "bullet__value", children: valueLabel })
|
|
223
|
+
] }),
|
|
224
|
+
/* @__PURE__ */ jsxs(
|
|
225
|
+
"div",
|
|
226
|
+
{
|
|
227
|
+
className: "bullet__track",
|
|
228
|
+
role: "img",
|
|
229
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? `${label}: ${value}${target !== void 0 ? ` de ${target}` : ""}` : void 0),
|
|
230
|
+
style: { height },
|
|
231
|
+
children: [
|
|
232
|
+
bands.map((b) => /* @__PURE__ */ jsx(
|
|
233
|
+
"span",
|
|
234
|
+
{
|
|
235
|
+
className: "bullet__band",
|
|
236
|
+
style: { left: `${toPct(b.from)}%`, width: `${toPct(b.to) - toPct(b.from)}%`, opacity: 0.12 + b.level * 0.1 }
|
|
237
|
+
},
|
|
238
|
+
b.level
|
|
239
|
+
)),
|
|
240
|
+
/* @__PURE__ */ jsx("span", { className: cx("bullet__measure", `bullet__measure--${tone}`), style: { width: `${toPct(value)}%` } }),
|
|
241
|
+
target !== void 0 && /* @__PURE__ */ jsx("span", { className: "bullet__target", style: { left: `${toPct(target)}%` }, "aria-hidden": true })
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
)
|
|
245
|
+
] });
|
|
246
|
+
}
|
|
247
|
+
var LEVELS = 4;
|
|
248
|
+
function CalendarHeatmap({
|
|
249
|
+
data,
|
|
250
|
+
rows = 7,
|
|
251
|
+
max,
|
|
252
|
+
color = "var(--color-primary)",
|
|
253
|
+
cellSize = 13,
|
|
254
|
+
gap = 3,
|
|
255
|
+
legend = true,
|
|
256
|
+
ariaLabel,
|
|
257
|
+
className,
|
|
258
|
+
style,
|
|
259
|
+
...rest
|
|
260
|
+
}) {
|
|
261
|
+
const ceiling = max ?? Math.max(1, ...data.map((d) => Number.isFinite(d.value) ? d.value : 0));
|
|
262
|
+
const bucket = (v) => {
|
|
263
|
+
if (v <= 0) return 0;
|
|
264
|
+
return Math.min(LEVELS, Math.ceil(v / ceiling * LEVELS));
|
|
265
|
+
};
|
|
266
|
+
const tint = (level) => level === 0 ? "var(--bg-muted)" : color;
|
|
267
|
+
const opacity = (level) => level === 0 ? 1 : 0.25 + level / LEVELS * 0.75;
|
|
268
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("heatmap", className), ...rest, children: [
|
|
269
|
+
/* @__PURE__ */ jsx(
|
|
270
|
+
"div",
|
|
271
|
+
{
|
|
272
|
+
className: "heatmap__grid",
|
|
273
|
+
role: "img",
|
|
274
|
+
"aria-label": ariaLabel,
|
|
275
|
+
style: {
|
|
276
|
+
gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,
|
|
277
|
+
gridAutoColumns: `${cellSize}px`,
|
|
278
|
+
gap,
|
|
279
|
+
...style
|
|
280
|
+
},
|
|
281
|
+
children: data.map((d, i) => {
|
|
282
|
+
const level = bucket(d.value);
|
|
283
|
+
return /* @__PURE__ */ jsx(
|
|
284
|
+
"span",
|
|
285
|
+
{
|
|
286
|
+
className: "heatmap__cell",
|
|
287
|
+
style: { background: tint(level), opacity: opacity(level), borderRadius: "var(--radius-sm)" },
|
|
288
|
+
title: d.label != null ? String(d.label) : d.date ? `${d.date}: ${formatNumber(d.value)}` : formatNumber(d.value)
|
|
289
|
+
},
|
|
290
|
+
d.date ?? i
|
|
291
|
+
);
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
),
|
|
295
|
+
legend && /* @__PURE__ */ jsxs("div", { className: "heatmap__legend", children: [
|
|
296
|
+
/* @__PURE__ */ jsx("span", { className: "heatmap__legend-text", children: "menos" }),
|
|
297
|
+
Array.from({ length: LEVELS + 1 }, (_, l) => /* @__PURE__ */ jsx("span", { className: "heatmap__cell heatmap__legend-cell", style: { background: tint(l), opacity: opacity(l), borderRadius: "var(--radius-sm)" } }, l)),
|
|
298
|
+
/* @__PURE__ */ jsx("span", { className: "heatmap__legend-text", children: "m\xE1s" })
|
|
299
|
+
] })
|
|
300
|
+
] });
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export { BulletChart, CalendarHeatmap, DeltaBadge, Meter, ProportionBar, Sparkbar, StatCard };
|
|
304
|
+
//# sourceMappingURL=chunk-2RBVHLG4.mjs.map
|
|
305
|
+
//# sourceMappingURL=chunk-2RBVHLG4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Metrics.tsx"],"names":[],"mappings":"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","file":"chunk-2RBVHLG4.mjs","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { formatNumber } from '../utils/format';\nimport { ArrowUp, ArrowDown, Minus } from './Icons';\nimport type { CategoryAccent } from './Display';\n\n/**\n * Dashboard data-communication primitives. Everything here is CSS-only — no\n * recharts dependency — so consumers can drop dense micro-viz into cards and\n * table cells without paying for a chart library. The heavyweight charts\n * (Line/Area/Bar/Donut) still live in Charts.tsx behind the BYO-recharts seam.\n */\n\n// ---------- DeltaBadge --------------------------------------------------\n// A sign-driven variation pill: ▲ +12,4% (good) / ▼ −3,1% (bad) / – 0% (flat).\n// Pulls the trend logic that used to be locked inside Stat into a reusable\n// atom for table cells, cards, anywhere. `invert` flips the tone (not the\n// arrow) for \"higher is worse\" metrics like error rate or cost.\nexport type DeltaTone = 'pos' | 'neg' | 'flat';\n\nexport interface DeltaBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** The variation. Sign drives direction + tone; magnitude is formatted. */\n value: number;\n /** Full-label formatter (incl. sign). Default: signed percent, e.g. `+12,4%`. */\n format?: (value: number) => string;\n /** Higher-is-worse: an increase shows ▲ but in red (cost, error rate, churn). */\n invert?: boolean;\n /** |value| ≤ this renders flat/neutral. Default 0. */\n neutralThreshold?: number;\n /** Hide the directional arrow, keep the colored number. */\n showIcon?: boolean;\n size?: 'sm' | 'md';\n}\n\nconst SIGNED_PERCENT = (v: number): string => {\n const sign = v > 0 ? '+' : v < 0 ? '−' : '';\n return `${sign}${formatNumber(Math.abs(v), { maximumFractionDigits: 1 })}%`;\n};\n\nexport function DeltaBadge({\n value, format = SIGNED_PERCENT, invert = false, neutralThreshold = 0,\n showIcon = true, size = 'md', className, ...rest\n}: DeltaBadgeProps) {\n const dir: 'up' | 'down' | 'flat' =\n value > neutralThreshold ? 'up' : value < -neutralThreshold ? 'down' : 'flat';\n const tone: DeltaTone =\n dir === 'flat' ? 'flat' : dir === 'up' ? (invert ? 'neg' : 'pos') : (invert ? 'pos' : 'neg');\n const Icon = dir === 'up' ? ArrowUp : dir === 'down' ? ArrowDown : Minus;\n const verb = dir === 'up' ? 'subió' : dir === 'down' ? 'bajó' : 'sin cambio';\n const text = format(value);\n\n return (\n <span\n className={cx('delta-badge', `delta-badge--${tone}`, size === 'sm' && 'delta-badge--sm', className)}\n aria-label={`${verb} ${text}`}\n {...rest}\n >\n {showIcon && <Icon size={size === 'sm' ? 11 : 13} aria-hidden />}\n <span className=\"delta-badge__text\">{text}</span>\n </span>\n );\n}\n\n// ---------- StatCard ----------------------------------------------------\n// The flagship KPI atom: leading icon + label, a large tabular value, a\n// DeltaBadge + comparison caption, and an optional chart slot (Sparkline /\n// Sparkbar). A standalone surface (does not depend on Card) so it composes in\n// any grid. `accent` tints the left edge with a category hue.\nexport interface StatCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n label: React.ReactNode;\n value: React.ReactNode;\n /** Convenience: renders a DeltaBadge. Omit and pass `deltaNode` for full control. */\n delta?: number;\n deltaFormat?: (value: number) => string;\n deltaInvert?: boolean;\n /** Escape hatch when `delta` isn't enough (custom node in the delta slot). */\n deltaNode?: React.ReactNode;\n /** Caption next to the delta, e.g. \"vs. mes anterior\". */\n caption?: React.ReactNode;\n /** Small leading glyph rendered in a tinted chip. */\n icon?: React.ReactNode;\n /** Left-edge accent hue. */\n accent?: CategoryAccent;\n /** Micro-viz slot (Sparkline / Sparkbar / ProportionBar). */\n chart?: React.ReactNode;\n}\n\nexport function StatCard({\n label, value, delta, deltaFormat, deltaInvert, deltaNode, caption, icon, accent, chart,\n className, ...rest\n}: StatCardProps) {\n const deltaEl =\n deltaNode ??\n (delta !== undefined ? <DeltaBadge value={delta} format={deltaFormat} invert={deltaInvert} size=\"sm\" /> : null);\n\n return (\n <div\n className={cx('metric-card', accent && `metric-card--${accent}`, className)}\n data-accent={accent}\n {...rest}\n >\n <div className=\"metric-card__head\">\n {icon && <span className=\"metric-card__icon\" aria-hidden>{icon}</span>}\n <span className=\"metric-card__label\">{label}</span>\n </div>\n <div className=\"metric-card__value\">{value}</div>\n {(deltaEl || caption) && (\n <div className=\"metric-card__foot\">\n {deltaEl}\n {caption && <span className=\"metric-card__caption\">{caption}</span>}\n </div>\n )}\n {chart && <div className=\"metric-card__chart\">{chart}</div>}\n </div>\n );\n}\n\n// ---------- Meter -------------------------------------------------------\n// A value within a range, with optional qualitative thresholds that drive the\n// fill tone. Distinct from Progress: `role=\"meter\"` is a static measurement\n// (stock level, budget used, capacity), not a task advancing to 100%.\nexport type MeterOptimum = 'low' | 'high' | 'middle';\n\nexport interface MeterProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n value: number;\n min?: number;\n max?: number;\n /** Lower threshold boundary (for tone zones). */\n low?: number;\n /** Upper threshold boundary (for tone zones). */\n high?: number;\n /** Where \"good\" lives. Default `high` (more is better). */\n optimum?: MeterOptimum;\n label?: React.ReactNode;\n /** Value caption. String or formatter; default shows `value/max`. */\n valueLabel?: React.ReactNode | ((value: number, max: number) => React.ReactNode);\n showValue?: boolean;\n size?: 'sm' | 'md';\n}\n\nfunction meterTone(value: number, low: number | undefined, high: number | undefined, optimum: MeterOptimum): DeltaTone | 'warn' {\n if (low === undefined && high === undefined) return 'pos'; // no thresholds → neutral-positive (primary)\n const lo = low ?? -Infinity;\n const hi = high ?? Infinity;\n if (optimum === 'high') return value >= hi ? 'pos' : value >= lo ? 'warn' : 'neg';\n if (optimum === 'low') return value <= lo ? 'pos' : value <= hi ? 'warn' : 'neg';\n return value >= lo && value <= hi ? 'pos' : 'warn'; // middle\n}\n\nexport function Meter({\n value, min = 0, max = 100, low, high, optimum = 'high',\n label, valueLabel, showValue = true, size = 'md', className, ...rest\n}: MeterProps) {\n const clamped = Math.min(Math.max(value, min), max);\n const pct = max > min ? ((clamped - min) / (max - min)) * 100 : 0;\n const tone = meterTone(value, low, high, optimum);\n const hasThresholds = low !== undefined || high !== undefined;\n const caption =\n typeof valueLabel === 'function' ? valueLabel(value, max)\n : valueLabel !== undefined ? valueLabel\n : `${formatNumber(value)} / ${formatNumber(max)}`;\n\n return (\n <div className={cx('meter', size === 'sm' && 'meter--sm', className)} {...rest}>\n {(label || showValue) && (\n <div className=\"meter__head\">\n {label && <span className=\"meter__label\">{label}</span>}\n {showValue && <span className=\"meter__value\">{caption}</span>}\n </div>\n )}\n <div\n className=\"meter__track\"\n role=\"meter\"\n aria-valuenow={value}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-label={typeof label === 'string' ? label : undefined}\n >\n <div\n className={cx('meter__fill', hasThresholds ? `meter__fill--${tone}` : 'meter__fill--primary')}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n\n// ---------- Sparkbar ----------------------------------------------------\n// Inline mini bars, CSS-only. The bar counterpart to Sparkline — drop a\n// distribution into a table cell or StatCard without recharts.\nexport interface SparkbarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n data: number[];\n height?: number;\n /** Scale ceiling. Default: max of `data`. */\n max?: number;\n color?: string;\n /** Emphasize the most recent bar (full opacity + secondary hue). */\n highlightLast?: boolean;\n /** Gap between bars in px. Default 2. */\n gap?: number;\n ariaLabel?: string;\n}\n\nexport function Sparkbar({\n data, height = 32, max, color = 'var(--color-primary)', highlightLast = false,\n gap = 2, ariaLabel, className, style, ...rest\n}: SparkbarProps) {\n const ceiling = max ?? Math.max(1, ...data.map((d) => (Number.isFinite(d) ? d : 0)));\n return (\n <div\n className={cx('sparkbar', className)}\n role=\"img\"\n aria-label={ariaLabel}\n style={{ height, gap, ...style }}\n {...rest}\n >\n {data.map((d, i) => {\n const isLast = highlightLast && i === data.length - 1;\n const h = ceiling > 0 ? Math.max(2, (Math.max(0, d) / ceiling) * 100) : 2;\n return (\n <span\n key={i}\n className={cx('sparkbar__bar', isLast && 'sparkbar__bar--last')}\n style={{ height: `${h}%`, background: isLast ? 'var(--color-secondary)' : color }}\n />\n );\n })}\n </div>\n );\n}\n\n// ---------- ProportionBar -----------------------------------------------\n// A single 100%-stacked bar for an inline category breakdown (paid / pending /\n// overdue) — the lightweight alternative to a donut when you just need shares.\nexport interface ProportionSegment {\n label: string;\n value: number;\n color?: string;\n}\n\nexport interface ProportionBarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n segments: ProportionSegment[];\n /** Denominator override (e.g. show partial fill against a known total). */\n total?: number;\n showLegend?: boolean;\n showPercent?: boolean;\n height?: number;\n ariaLabel?: string;\n}\n\nconst CAT_HUES = ['var(--cat-1)', 'var(--cat-2)', 'var(--cat-4)', 'var(--cat-5)', 'var(--cat-3)', 'var(--cat-6)'];\n\nexport function ProportionBar({\n segments, total, showLegend = true, showPercent = true, height = 10,\n ariaLabel, className, ...rest\n}: ProportionBarProps) {\n const sum = total ?? segments.reduce((a, s) => a + Math.max(0, s.value), 0);\n const pctOf = (v: number) => (sum > 0 ? (Math.max(0, v) / sum) * 100 : 0);\n\n return (\n <div className={cx('proportion', className)} {...rest}>\n <div className=\"proportion__track\" role=\"img\" aria-label={ariaLabel} style={{ height }}>\n {segments.map((s, i) => {\n const pct = pctOf(s.value);\n if (pct <= 0) return null;\n return (\n <span\n key={s.label}\n className=\"proportion__seg\"\n style={{ width: `${pct}%`, background: s.color ?? CAT_HUES[i % CAT_HUES.length] }}\n title={`${s.label}: ${formatNumber(s.value)}`}\n />\n );\n })}\n </div>\n {showLegend && (\n <ul className=\"proportion__legend\">\n {segments.map((s, i) => (\n <li key={s.label} className=\"proportion__legend-item\">\n <span className=\"proportion__swatch\" style={{ background: s.color ?? CAT_HUES[i % CAT_HUES.length] }} />\n <span className=\"proportion__legend-label\">{s.label}</span>\n {showPercent && <span className=\"proportion__legend-pct\">{formatNumber(pctOf(s.value), { maximumFractionDigits: 0 })}%</span>}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n\n// ---------- BulletChart -------------------------------------------------\n// Stephen Few's bullet graph (2006): a compact actual-vs-target bar over\n// qualitative ranges. Communicates more per pixel than a gauge — built for\n// dense KPI rows. CSS-only.\nexport type BulletTone = 'primary' | 'success' | 'warning' | 'danger';\n\nexport interface BulletChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n value: number;\n /** Comparative marker (the vertical tick). */\n target?: number;\n min?: number;\n /** Scale end. Default: max of value/target/ranges. */\n max?: number;\n /** Qualitative range boundaries (ascending). Shaded light→dark behind the bar. */\n ranges?: number[];\n label?: React.ReactNode;\n valueLabel?: React.ReactNode;\n tone?: BulletTone;\n height?: number;\n ariaLabel?: string;\n}\n\nexport function BulletChart({\n value, target, min = 0, max, ranges = [], label, valueLabel, tone = 'primary',\n height = 22, ariaLabel, className, ...rest\n}: BulletChartProps) {\n const scaleMax = max ?? Math.max(value, target ?? 0, ...ranges, 1);\n const span = scaleMax - min || 1;\n const toPct = (v: number) => Math.min(100, Math.max(0, ((v - min) / span) * 100));\n // Build cumulative band stops so each qualitative band has increasing tint.\n const sortedRanges = [...ranges].sort((a, b) => a - b);\n const bands = sortedRanges.map((r, i) => ({ from: i === 0 ? min : sortedRanges[i - 1], to: r, level: i }));\n\n return (\n <div className={cx('bullet', className)} {...rest}>\n {(label || valueLabel) && (\n <div className=\"bullet__head\">\n {label && <span className=\"bullet__label\">{label}</span>}\n {valueLabel && <span className=\"bullet__value\">{valueLabel}</span>}\n </div>\n )}\n <div\n className=\"bullet__track\"\n role=\"img\"\n aria-label={ariaLabel ?? (typeof label === 'string' ? `${label}: ${value}${target !== undefined ? ` de ${target}` : ''}` : undefined)}\n style={{ height }}\n >\n {bands.map((b) => (\n <span\n key={b.level}\n className=\"bullet__band\"\n style={{ left: `${toPct(b.from)}%`, width: `${toPct(b.to) - toPct(b.from)}%`, opacity: 0.12 + b.level * 0.1 }}\n />\n ))}\n <span className={cx('bullet__measure', `bullet__measure--${tone}`)} style={{ width: `${toPct(value)}%` }} />\n {target !== undefined && <span className=\"bullet__target\" style={{ left: `${toPct(target)}%` }} aria-hidden />}\n </div>\n </div>\n );\n}\n\n// ---------- CalendarHeatmap ---------------------------------------------\n// An intensity grid (GitHub-contributions style): cells tinted by value into\n// discrete buckets. Column-major fill (each column = a week, rows = weekdays).\nexport interface HeatmapCell {\n /** Optional key/date for accessibility + keys. */\n date?: string;\n label?: React.ReactNode;\n value: number;\n}\n\nexport interface CalendarHeatmapProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n data: HeatmapCell[];\n /** Rows in the grid (column-major flow). Default 7 (weekdays). */\n rows?: number;\n /** Intensity ceiling. Default: max of `data`. */\n max?: number;\n /** Base hue tinted by intensity. Default primary. */\n color?: string;\n cellSize?: number;\n gap?: number;\n legend?: boolean;\n ariaLabel?: string;\n}\n\nconst LEVELS = 4; // intensity buckets above zero\n\nexport function CalendarHeatmap({\n data, rows = 7, max, color = 'var(--color-primary)', cellSize = 13, gap = 3,\n legend = true, ariaLabel, className, style, ...rest\n}: CalendarHeatmapProps) {\n const ceiling = max ?? Math.max(1, ...data.map((d) => (Number.isFinite(d.value) ? d.value : 0)));\n const bucket = (v: number): number => {\n if (v <= 0) return 0;\n return Math.min(LEVELS, Math.ceil((v / ceiling) * LEVELS));\n };\n // opacity ramp per bucket so the base hue reads light→saturated.\n const tint = (level: number) => (level === 0 ? 'var(--bg-muted)' : color);\n const opacity = (level: number) => (level === 0 ? 1 : 0.25 + (level / LEVELS) * 0.75);\n\n return (\n <div className={cx('heatmap', className)} {...rest}>\n <div\n className=\"heatmap__grid\"\n role=\"img\"\n aria-label={ariaLabel}\n style={{\n gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,\n gridAutoColumns: `${cellSize}px`,\n gap,\n ...style,\n }}\n >\n {data.map((d, i) => {\n const level = bucket(d.value);\n return (\n <span\n key={d.date ?? i}\n className=\"heatmap__cell\"\n style={{ background: tint(level), opacity: opacity(level), borderRadius: 'var(--radius-sm)' }}\n title={d.label != null ? String(d.label) : d.date ? `${d.date}: ${formatNumber(d.value)}` : formatNumber(d.value)}\n />\n );\n })}\n </div>\n {legend && (\n <div className=\"heatmap__legend\">\n <span className=\"heatmap__legend-text\">menos</span>\n {Array.from({ length: LEVELS + 1 }, (_, l) => (\n <span key={l} className=\"heatmap__cell heatmap__legend-cell\" style={{ background: tint(l), opacity: opacity(l), borderRadius: 'var(--radius-sm)' }} />\n ))}\n <span className=\"heatmap__legend-text\">más</span>\n </div>\n )}\n </div>\n );\n}\n"]}
|