@misael703/ui 1.57.0 → 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.
Files changed (134) hide show
  1. package/dist/{chunk-SZPUIQHI.js → chunk-2PNXLTEM.js} +4 -4
  2. package/dist/{chunk-SZPUIQHI.js.map → chunk-2PNXLTEM.js.map} +1 -1
  3. package/dist/chunk-2RBVHLG4.mjs +305 -0
  4. package/dist/chunk-2RBVHLG4.mjs.map +1 -0
  5. package/dist/{chunk-4WGXCRNN.js → chunk-3JRP3DGM.js} +3 -3
  6. package/dist/{chunk-4WGXCRNN.js.map → chunk-3JRP3DGM.js.map} +1 -1
  7. package/dist/{chunk-DYMX4R2B.js → chunk-3PYU6OHQ.js} +5 -5
  8. package/dist/{chunk-DYMX4R2B.js.map → chunk-3PYU6OHQ.js.map} +1 -1
  9. package/dist/{chunk-6E7VZNYQ.js → chunk-4G6NENVM.js} +4 -4
  10. package/dist/{chunk-6E7VZNYQ.js.map → chunk-4G6NENVM.js.map} +1 -1
  11. package/dist/{chunk-CZ6ODGWB.mjs → chunk-6JXGCU7F.mjs} +3 -3
  12. package/dist/{chunk-CZ6ODGWB.mjs.map → chunk-6JXGCU7F.mjs.map} +1 -1
  13. package/dist/{chunk-Z4SBVGSY.mjs → chunk-6OBFBETV.mjs} +3 -3
  14. package/dist/{chunk-Z4SBVGSY.mjs.map → chunk-6OBFBETV.mjs.map} +1 -1
  15. package/dist/{chunk-MURFESTG.js → chunk-AGMDYCGG.js} +4 -4
  16. package/dist/{chunk-MURFESTG.js.map → chunk-AGMDYCGG.js.map} +1 -1
  17. package/dist/chunk-BULIPFOG.js +313 -0
  18. package/dist/chunk-BULIPFOG.js.map +1 -0
  19. package/dist/{chunk-Z5RTA2MB.mjs → chunk-DH3IXJRJ.mjs} +4 -4
  20. package/dist/{chunk-Z5RTA2MB.mjs.map → chunk-DH3IXJRJ.mjs.map} +1 -1
  21. package/dist/{chunk-XA57BOHJ.mjs → chunk-ESU5UMEK.mjs} +5 -5
  22. package/dist/{chunk-XA57BOHJ.mjs.map → chunk-ESU5UMEK.mjs.map} +1 -1
  23. package/dist/{chunk-SE5E4GXH.js → chunk-F237OMT6.js} +4 -4
  24. package/dist/{chunk-SE5E4GXH.js.map → chunk-F237OMT6.js.map} +1 -1
  25. package/dist/{chunk-UINN3O5C.mjs → chunk-FR4JV3JA.mjs} +4 -4
  26. package/dist/{chunk-UINN3O5C.mjs.map → chunk-FR4JV3JA.mjs.map} +1 -1
  27. package/dist/{chunk-H4RFV2RM.mjs → chunk-G4OOD6AR.mjs} +5 -5
  28. package/dist/{chunk-H4RFV2RM.mjs.map → chunk-G4OOD6AR.mjs.map} +1 -1
  29. package/dist/{chunk-QMXU5WXD.js → chunk-HCTY5QYL.js} +4 -4
  30. package/dist/{chunk-QMXU5WXD.js.map → chunk-HCTY5QYL.js.map} +1 -1
  31. package/dist/{chunk-XSJSZL64.js → chunk-HKHGODQE.js} +4 -4
  32. package/dist/{chunk-XSJSZL64.js.map → chunk-HKHGODQE.js.map} +1 -1
  33. package/dist/{chunk-YFVY5X2Q.mjs → chunk-J2HHAZHV.mjs} +4 -4
  34. package/dist/{chunk-YFVY5X2Q.mjs.map → chunk-J2HHAZHV.mjs.map} +1 -1
  35. package/dist/{chunk-M4NNJ6HG.js → chunk-J2PQFMR5.js} +5 -5
  36. package/dist/{chunk-M4NNJ6HG.js.map → chunk-J2PQFMR5.js.map} +1 -1
  37. package/dist/{chunk-QR6X2UOT.mjs → chunk-JMFDIN5R.mjs} +3 -3
  38. package/dist/{chunk-QR6X2UOT.mjs.map → chunk-JMFDIN5R.mjs.map} +1 -1
  39. package/dist/{chunk-HZUB2LJI.js → chunk-MSDFMVIF.js} +5 -5
  40. package/dist/{chunk-HZUB2LJI.js.map → chunk-MSDFMVIF.js.map} +1 -1
  41. package/dist/{chunk-XJFGP7MK.js → chunk-MW7HQCFC.js} +4 -4
  42. package/dist/{chunk-XJFGP7MK.js.map → chunk-MW7HQCFC.js.map} +1 -1
  43. package/dist/{chunk-TYUTEYAK.mjs → chunk-NS6CI6RP.mjs} +4 -4
  44. package/dist/{chunk-TYUTEYAK.mjs.map → chunk-NS6CI6RP.mjs.map} +1 -1
  45. package/dist/{chunk-JZNUYA42.js → chunk-NU4GAGUV.js} +3 -3
  46. package/dist/{chunk-JZNUYA42.js.map → chunk-NU4GAGUV.js.map} +1 -1
  47. package/dist/{chunk-MD55OD7G.mjs → chunk-O3KM5SQB.mjs} +4 -4
  48. package/dist/{chunk-MD55OD7G.mjs.map → chunk-O3KM5SQB.mjs.map} +1 -1
  49. package/dist/{chunk-3WSB2R2K.mjs → chunk-OIYIWG53.mjs} +4 -4
  50. package/dist/{chunk-3WSB2R2K.mjs.map → chunk-OIYIWG53.mjs.map} +1 -1
  51. package/dist/{chunk-XNAYL6YM.mjs → chunk-Q4WPZJUS.mjs} +4 -4
  52. package/dist/{chunk-XNAYL6YM.mjs.map → chunk-Q4WPZJUS.mjs.map} +1 -1
  53. package/dist/{chunk-WBFVVOQW.mjs → chunk-RZQIZZKH.mjs} +3 -3
  54. package/dist/{chunk-WBFVVOQW.mjs.map → chunk-RZQIZZKH.mjs.map} +1 -1
  55. package/dist/{chunk-HCFIPNUU.js → chunk-S3DEFKS5.js} +5 -5
  56. package/dist/{chunk-HCFIPNUU.js.map → chunk-S3DEFKS5.js.map} +1 -1
  57. package/dist/{chunk-KROEMZNQ.js → chunk-S3MMU3LW.js} +5 -4
  58. package/dist/chunk-S3MMU3LW.js.map +1 -0
  59. package/dist/{chunk-WMRGTHJB.mjs → chunk-SCUHLOET.mjs} +5 -4
  60. package/dist/chunk-SCUHLOET.mjs.map +1 -0
  61. package/dist/{chunk-XP7P4Z6X.js → chunk-SHIQMHQP.js} +4 -4
  62. package/dist/{chunk-XP7P4Z6X.js.map → chunk-SHIQMHQP.js.map} +1 -1
  63. package/dist/{chunk-KPWOWFMT.js → chunk-SQJVGL7Y.js} +3 -3
  64. package/dist/{chunk-KPWOWFMT.js.map → chunk-SQJVGL7Y.js.map} +1 -1
  65. package/dist/{chunk-JZYPFPEA.mjs → chunk-T2DNEJR3.mjs} +3 -3
  66. package/dist/{chunk-JZYPFPEA.mjs.map → chunk-T2DNEJR3.mjs.map} +1 -1
  67. package/dist/{chunk-OSL35VGG.js → chunk-T46LLZHX.js} +5 -5
  68. package/dist/{chunk-OSL35VGG.js.map → chunk-T46LLZHX.js.map} +1 -1
  69. package/dist/{chunk-H7SJBODY.mjs → chunk-TGAAJCUZ.mjs} +3 -3
  70. package/dist/{chunk-H7SJBODY.mjs.map → chunk-TGAAJCUZ.mjs.map} +1 -1
  71. package/dist/{chunk-SDJHC7QY.js → chunk-TX4BUYX4.js} +4 -4
  72. package/dist/{chunk-SDJHC7QY.js.map → chunk-TX4BUYX4.js.map} +1 -1
  73. package/dist/{chunk-HFRMDYNW.mjs → chunk-X36H75RR.mjs} +3 -3
  74. package/dist/{chunk-HFRMDYNW.mjs.map → chunk-X36H75RR.mjs.map} +1 -1
  75. package/dist/{chunk-VTWO7TPC.js → chunk-XF445GS6.js} +5 -5
  76. package/dist/{chunk-VTWO7TPC.js.map → chunk-XF445GS6.js.map} +1 -1
  77. package/dist/{chunk-FAENPPKD.mjs → chunk-XJHK3RH5.mjs} +5 -5
  78. package/dist/{chunk-FAENPPKD.mjs.map → chunk-XJHK3RH5.mjs.map} +1 -1
  79. package/dist/{chunk-7RAQNHGB.mjs → chunk-YXUYWO2W.mjs} +4 -4
  80. package/dist/{chunk-7RAQNHGB.mjs.map → chunk-YXUYWO2W.mjs.map} +1 -1
  81. package/dist/components/AdvancedPickers.js +8 -8
  82. package/dist/components/AdvancedPickers.mjs +4 -4
  83. package/dist/components/AppShell.js +9 -9
  84. package/dist/components/AppShell.mjs +7 -7
  85. package/dist/components/Comments.js +7 -7
  86. package/dist/components/Comments.mjs +4 -4
  87. package/dist/components/Commerce.js +19 -19
  88. package/dist/components/Commerce.mjs +8 -8
  89. package/dist/components/ContextMenu.js +4 -4
  90. package/dist/components/ContextMenu.mjs +3 -3
  91. package/dist/components/DataTable.js +12 -12
  92. package/dist/components/DataTable.mjs +5 -5
  93. package/dist/components/Display2.js +7 -7
  94. package/dist/components/Display2.mjs +3 -3
  95. package/dist/components/Display3.js +11 -11
  96. package/dist/components/Display3.mjs +5 -5
  97. package/dist/components/Editing.js +14 -14
  98. package/dist/components/Editing.mjs +8 -8
  99. package/dist/components/HoverCard.js +3 -3
  100. package/dist/components/HoverCard.mjs +2 -2
  101. package/dist/components/InputsExtra.js +13 -13
  102. package/dist/components/InputsExtra.mjs +4 -4
  103. package/dist/components/Layout.js +21 -21
  104. package/dist/components/Layout.mjs +2 -2
  105. package/dist/components/Logo.js +3 -3
  106. package/dist/components/Logo.mjs +2 -2
  107. package/dist/components/Menubar.js +4 -4
  108. package/dist/components/Menubar.mjs +3 -3
  109. package/dist/components/Metrics.d.mts +130 -0
  110. package/dist/components/Metrics.d.ts +130 -0
  111. package/dist/components/Metrics.js +41 -0
  112. package/dist/components/Metrics.js.map +1 -0
  113. package/dist/components/Metrics.mjs +8 -0
  114. package/dist/components/Metrics.mjs.map +1 -0
  115. package/dist/components/NavigationMenu.js +4 -4
  116. package/dist/components/NavigationMenu.mjs +3 -3
  117. package/dist/components/Overlay.js +9 -9
  118. package/dist/components/Overlay.mjs +7 -7
  119. package/dist/components/Pickers.js +9 -9
  120. package/dist/components/Pickers.mjs +4 -4
  121. package/dist/components/Popover.js +4 -4
  122. package/dist/components/Popover.mjs +3 -3
  123. package/dist/components/TimeAgo.js +5 -5
  124. package/dist/components/TimeAgo.mjs +3 -3
  125. package/dist/hooks/index.js +15 -15
  126. package/dist/hooks/index.mjs +3 -3
  127. package/dist/index.d.mts +1 -0
  128. package/dist/index.d.ts +1 -0
  129. package/dist/index.js +207 -178
  130. package/dist/index.mjs +34 -33
  131. package/dist/styles.css +1 -1
  132. package/package.json +1 -1
  133. package/dist/chunk-KROEMZNQ.js.map +0 -1
  134. package/dist/chunk-WMRGTHJB.mjs.map +0 -1
@@ -0,0 +1,313 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var chunkCTOPKHEE_js = require('./chunk-CTOPKHEE.js');
5
+ var chunkC4AKMVDZ_js = require('./chunk-C4AKMVDZ.js');
6
+ var chunkPASF6T4H_js = require('./chunk-PASF6T4H.js');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ var SIGNED_PERCENT = (v) => {
10
+ const sign = v > 0 ? "+" : v < 0 ? "\u2212" : "";
11
+ return `${sign}${chunkCTOPKHEE_js.formatNumber(Math.abs(v), { maximumFractionDigits: 1 })}%`;
12
+ };
13
+ function DeltaBadge({
14
+ value,
15
+ format = SIGNED_PERCENT,
16
+ invert = false,
17
+ neutralThreshold = 0,
18
+ showIcon = true,
19
+ size = "md",
20
+ className,
21
+ ...rest
22
+ }) {
23
+ const dir = value > neutralThreshold ? "up" : value < -neutralThreshold ? "down" : "flat";
24
+ const tone = dir === "flat" ? "flat" : dir === "up" ? invert ? "neg" : "pos" : invert ? "pos" : "neg";
25
+ const Icon = dir === "up" ? chunkC4AKMVDZ_js.ArrowUp : dir === "down" ? chunkC4AKMVDZ_js.ArrowDown : chunkC4AKMVDZ_js.Minus;
26
+ const verb = dir === "up" ? "subi\xF3" : dir === "down" ? "baj\xF3" : "sin cambio";
27
+ const text = format(value);
28
+ return /* @__PURE__ */ jsxRuntime.jsxs(
29
+ "span",
30
+ {
31
+ className: chunkPASF6T4H_js.cx("delta-badge", `delta-badge--${tone}`, size === "sm" && "delta-badge--sm", className),
32
+ "aria-label": `${verb} ${text}`,
33
+ ...rest,
34
+ children: [
35
+ showIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: size === "sm" ? 11 : 13, "aria-hidden": true }),
36
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "delta-badge__text", children: text })
37
+ ]
38
+ }
39
+ );
40
+ }
41
+ function StatCard({
42
+ label,
43
+ value,
44
+ delta,
45
+ deltaFormat,
46
+ deltaInvert,
47
+ deltaNode,
48
+ caption,
49
+ icon,
50
+ accent,
51
+ chart,
52
+ className,
53
+ ...rest
54
+ }) {
55
+ const deltaEl = deltaNode ?? (delta !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(DeltaBadge, { value: delta, format: deltaFormat, invert: deltaInvert, size: "sm" }) : null);
56
+ return /* @__PURE__ */ jsxRuntime.jsxs(
57
+ "div",
58
+ {
59
+ className: chunkPASF6T4H_js.cx("metric-card", accent && `metric-card--${accent}`, className),
60
+ "data-accent": accent,
61
+ ...rest,
62
+ children: [
63
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "metric-card__head", children: [
64
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "metric-card__icon", "aria-hidden": true, children: icon }),
65
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "metric-card__label", children: label })
66
+ ] }),
67
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "metric-card__value", children: value }),
68
+ (deltaEl || caption) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "metric-card__foot", children: [
69
+ deltaEl,
70
+ caption && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "metric-card__caption", children: caption })
71
+ ] }),
72
+ chart && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "metric-card__chart", children: chart })
73
+ ]
74
+ }
75
+ );
76
+ }
77
+ function meterTone(value, low, high, optimum) {
78
+ if (low === void 0 && high === void 0) return "pos";
79
+ const lo = low ?? -Infinity;
80
+ const hi = high ?? Infinity;
81
+ if (optimum === "high") return value >= hi ? "pos" : value >= lo ? "warn" : "neg";
82
+ if (optimum === "low") return value <= lo ? "pos" : value <= hi ? "warn" : "neg";
83
+ return value >= lo && value <= hi ? "pos" : "warn";
84
+ }
85
+ function Meter({
86
+ value,
87
+ min = 0,
88
+ max = 100,
89
+ low,
90
+ high,
91
+ optimum = "high",
92
+ label,
93
+ valueLabel,
94
+ showValue = true,
95
+ size = "md",
96
+ className,
97
+ ...rest
98
+ }) {
99
+ const clamped = Math.min(Math.max(value, min), max);
100
+ const pct = max > min ? (clamped - min) / (max - min) * 100 : 0;
101
+ const tone = meterTone(value, low, high, optimum);
102
+ const hasThresholds = low !== void 0 || high !== void 0;
103
+ const caption = typeof valueLabel === "function" ? valueLabel(value, max) : valueLabel !== void 0 ? valueLabel : `${chunkCTOPKHEE_js.formatNumber(value)} / ${chunkCTOPKHEE_js.formatNumber(max)}`;
104
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("meter", size === "sm" && "meter--sm", className), ...rest, children: [
105
+ (label || showValue) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "meter__head", children: [
106
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "meter__label", children: label }),
107
+ showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "meter__value", children: caption })
108
+ ] }),
109
+ /* @__PURE__ */ jsxRuntime.jsx(
110
+ "div",
111
+ {
112
+ className: "meter__track",
113
+ role: "meter",
114
+ "aria-valuenow": value,
115
+ "aria-valuemin": min,
116
+ "aria-valuemax": max,
117
+ "aria-label": typeof label === "string" ? label : void 0,
118
+ children: /* @__PURE__ */ jsxRuntime.jsx(
119
+ "div",
120
+ {
121
+ className: chunkPASF6T4H_js.cx("meter__fill", hasThresholds ? `meter__fill--${tone}` : "meter__fill--primary"),
122
+ style: { width: `${pct}%` }
123
+ }
124
+ )
125
+ }
126
+ )
127
+ ] });
128
+ }
129
+ function Sparkbar({
130
+ data,
131
+ height = 32,
132
+ max,
133
+ color = "var(--color-primary)",
134
+ highlightLast = false,
135
+ gap = 2,
136
+ ariaLabel,
137
+ className,
138
+ style,
139
+ ...rest
140
+ }) {
141
+ const ceiling = max ?? Math.max(1, ...data.map((d) => Number.isFinite(d) ? d : 0));
142
+ return /* @__PURE__ */ jsxRuntime.jsx(
143
+ "div",
144
+ {
145
+ className: chunkPASF6T4H_js.cx("sparkbar", className),
146
+ role: "img",
147
+ "aria-label": ariaLabel,
148
+ style: { height, gap, ...style },
149
+ ...rest,
150
+ children: data.map((d, i) => {
151
+ const isLast = highlightLast && i === data.length - 1;
152
+ const h = ceiling > 0 ? Math.max(2, Math.max(0, d) / ceiling * 100) : 2;
153
+ return /* @__PURE__ */ jsxRuntime.jsx(
154
+ "span",
155
+ {
156
+ className: chunkPASF6T4H_js.cx("sparkbar__bar", isLast && "sparkbar__bar--last"),
157
+ style: { height: `${h}%`, background: isLast ? "var(--color-secondary)" : color }
158
+ },
159
+ i
160
+ );
161
+ })
162
+ }
163
+ );
164
+ }
165
+ var CAT_HUES = ["var(--cat-1)", "var(--cat-2)", "var(--cat-4)", "var(--cat-5)", "var(--cat-3)", "var(--cat-6)"];
166
+ function ProportionBar({
167
+ segments,
168
+ total,
169
+ showLegend = true,
170
+ showPercent = true,
171
+ height = 10,
172
+ ariaLabel,
173
+ className,
174
+ ...rest
175
+ }) {
176
+ const sum = total ?? segments.reduce((a, s) => a + Math.max(0, s.value), 0);
177
+ const pctOf = (v) => sum > 0 ? Math.max(0, v) / sum * 100 : 0;
178
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("proportion", className), ...rest, children: [
179
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "proportion__track", role: "img", "aria-label": ariaLabel, style: { height }, children: segments.map((s, i) => {
180
+ const pct = pctOf(s.value);
181
+ if (pct <= 0) return null;
182
+ return /* @__PURE__ */ jsxRuntime.jsx(
183
+ "span",
184
+ {
185
+ className: "proportion__seg",
186
+ style: { width: `${pct}%`, background: s.color ?? CAT_HUES[i % CAT_HUES.length] },
187
+ title: `${s.label}: ${chunkCTOPKHEE_js.formatNumber(s.value)}`
188
+ },
189
+ s.label
190
+ );
191
+ }) }),
192
+ showLegend && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "proportion__legend", children: segments.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "proportion__legend-item", children: [
193
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "proportion__swatch", style: { background: s.color ?? CAT_HUES[i % CAT_HUES.length] } }),
194
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "proportion__legend-label", children: s.label }),
195
+ showPercent && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "proportion__legend-pct", children: [
196
+ chunkCTOPKHEE_js.formatNumber(pctOf(s.value), { maximumFractionDigits: 0 }),
197
+ "%"
198
+ ] })
199
+ ] }, s.label)) })
200
+ ] });
201
+ }
202
+ function BulletChart({
203
+ value,
204
+ target,
205
+ min = 0,
206
+ max,
207
+ ranges = [],
208
+ label,
209
+ valueLabel,
210
+ tone = "primary",
211
+ height = 22,
212
+ ariaLabel,
213
+ className,
214
+ ...rest
215
+ }) {
216
+ const scaleMax = max ?? Math.max(value, target ?? 0, ...ranges, 1);
217
+ const span = scaleMax - min || 1;
218
+ const toPct = (v) => Math.min(100, Math.max(0, (v - min) / span * 100));
219
+ const sortedRanges = [...ranges].sort((a, b) => a - b);
220
+ const bands = sortedRanges.map((r, i) => ({ from: i === 0 ? min : sortedRanges[i - 1], to: r, level: i }));
221
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("bullet", className), ...rest, children: [
222
+ (label || valueLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bullet__head", children: [
223
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bullet__label", children: label }),
224
+ valueLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bullet__value", children: valueLabel })
225
+ ] }),
226
+ /* @__PURE__ */ jsxRuntime.jsxs(
227
+ "div",
228
+ {
229
+ className: "bullet__track",
230
+ role: "img",
231
+ "aria-label": ariaLabel ?? (typeof label === "string" ? `${label}: ${value}${target !== void 0 ? ` de ${target}` : ""}` : void 0),
232
+ style: { height },
233
+ children: [
234
+ bands.map((b) => /* @__PURE__ */ jsxRuntime.jsx(
235
+ "span",
236
+ {
237
+ className: "bullet__band",
238
+ style: { left: `${toPct(b.from)}%`, width: `${toPct(b.to) - toPct(b.from)}%`, opacity: 0.12 + b.level * 0.1 }
239
+ },
240
+ b.level
241
+ )),
242
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkPASF6T4H_js.cx("bullet__measure", `bullet__measure--${tone}`), style: { width: `${toPct(value)}%` } }),
243
+ target !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bullet__target", style: { left: `${toPct(target)}%` }, "aria-hidden": true })
244
+ ]
245
+ }
246
+ )
247
+ ] });
248
+ }
249
+ var LEVELS = 4;
250
+ function CalendarHeatmap({
251
+ data,
252
+ rows = 7,
253
+ max,
254
+ color = "var(--color-primary)",
255
+ cellSize = 13,
256
+ gap = 3,
257
+ legend = true,
258
+ ariaLabel,
259
+ className,
260
+ style,
261
+ ...rest
262
+ }) {
263
+ const ceiling = max ?? Math.max(1, ...data.map((d) => Number.isFinite(d.value) ? d.value : 0));
264
+ const bucket = (v) => {
265
+ if (v <= 0) return 0;
266
+ return Math.min(LEVELS, Math.ceil(v / ceiling * LEVELS));
267
+ };
268
+ const tint = (level) => level === 0 ? "var(--bg-muted)" : color;
269
+ const opacity = (level) => level === 0 ? 1 : 0.25 + level / LEVELS * 0.75;
270
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("heatmap", className), ...rest, children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx(
272
+ "div",
273
+ {
274
+ className: "heatmap__grid",
275
+ role: "img",
276
+ "aria-label": ariaLabel,
277
+ style: {
278
+ gridTemplateRows: `repeat(${rows}, ${cellSize}px)`,
279
+ gridAutoColumns: `${cellSize}px`,
280
+ gap,
281
+ ...style
282
+ },
283
+ children: data.map((d, i) => {
284
+ const level = bucket(d.value);
285
+ return /* @__PURE__ */ jsxRuntime.jsx(
286
+ "span",
287
+ {
288
+ className: "heatmap__cell",
289
+ style: { background: tint(level), opacity: opacity(level), borderRadius: "var(--radius-sm)" },
290
+ title: d.label != null ? String(d.label) : d.date ? `${d.date}: ${chunkCTOPKHEE_js.formatNumber(d.value)}` : chunkCTOPKHEE_js.formatNumber(d.value)
291
+ },
292
+ d.date ?? i
293
+ );
294
+ })
295
+ }
296
+ ),
297
+ legend && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "heatmap__legend", children: [
298
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "heatmap__legend-text", children: "menos" }),
299
+ Array.from({ length: LEVELS + 1 }, (_, l) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "heatmap__cell heatmap__legend-cell", style: { background: tint(l), opacity: opacity(l), borderRadius: "var(--radius-sm)" } }, l)),
300
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "heatmap__legend-text", children: "m\xE1s" })
301
+ ] })
302
+ ] });
303
+ }
304
+
305
+ exports.BulletChart = BulletChart;
306
+ exports.CalendarHeatmap = CalendarHeatmap;
307
+ exports.DeltaBadge = DeltaBadge;
308
+ exports.Meter = Meter;
309
+ exports.ProportionBar = ProportionBar;
310
+ exports.Sparkbar = Sparkbar;
311
+ exports.StatCard = StatCard;
312
+ //# sourceMappingURL=chunk-BULIPFOG.js.map
313
+ //# sourceMappingURL=chunk-BULIPFOG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Metrics.tsx"],"names":["formatNumber","ArrowUp","ArrowDown","Minus","jsxs","cx","jsx"],"mappings":"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","file":"chunk-BULIPFOG.js","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"]}
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
  import { Portal } from './chunk-FKBQYQQD.mjs';
3
+ import { useDismiss } from './chunk-6P2TKRTL.mjs';
4
+ import { usePopoverPosition } from './chunk-5XT2LX3I.mjs';
3
5
  import { ChevronUp, ChevronDown } from './chunk-BJGMROKL.mjs';
4
6
  import { cx } from './chunk-IEPCH3JB.mjs';
5
- import { usePopoverPosition } from './chunk-5XT2LX3I.mjs';
6
- import { useDismiss } from './chunk-6P2TKRTL.mjs';
7
7
  import * as React from 'react';
8
8
  import { jsxs, jsx } from 'react/jsx-runtime';
9
9
 
@@ -181,5 +181,5 @@ function Stat({ label, value, hint, trend, align = "start", className }) {
181
181
  }
182
182
 
183
183
  export { Avatar, AvatarGroup, Menu, Stat };
184
- //# sourceMappingURL=chunk-Z5RTA2MB.mjs.map
185
- //# sourceMappingURL=chunk-Z5RTA2MB.mjs.map
184
+ //# sourceMappingURL=chunk-DH3IXJRJ.mjs.map
185
+ //# sourceMappingURL=chunk-DH3IXJRJ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Display2.tsx"],"names":[],"mappings":"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","file":"chunk-Z5RTA2MB.mjs","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { ChevronUp, ChevronDown } from './Icons';\nimport { Portal } from './Portal';\nimport { usePopoverPosition } from '../hooks/usePopoverPosition';\nimport { useDismiss } from '../hooks/useDismiss';\n\n// ---------- Avatar ------------------------------------------------------\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n src?: string;\n alt?: string;\n name?: string; // for initials fallback\n size?: 24 | 32 | 40 | 48 | 64;\n shape?: 'circle' | 'square';\n status?: 'online' | 'offline' | 'busy';\n}\n\nfunction initials(name: string) {\n if (name.startsWith('+')) return name;\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return parts.slice(0, 2).map((p) => p[0]?.toUpperCase() ?? '').join('');\n}\n\nexport function Avatar({ src, alt, name, size = 32, shape = 'circle', status, className, style, ...rest }: AvatarProps) {\n return (\n <span\n className={cx('avatar', `avatar--${shape}`, className)}\n style={{ width: size, height: size, fontSize: size * 0.42, ...style }}\n {...rest}\n >\n {src ? (\n <img src={src} alt={alt ?? name ?? ''} />\n ) : (\n <span className=\"avatar__initials\">{name ? initials(name) : '?'}</span>\n )}\n {status && <span className={cx('avatar__status', `avatar__status--${status}`)} aria-label={status} />}\n </span>\n );\n}\n\nexport interface AvatarGroupProps {\n children: React.ReactNode;\n max?: number;\n size?: AvatarProps['size'];\n className?: string;\n}\n\nexport function AvatarGroup({ children, max = 4, size = 32, className }: AvatarGroupProps) {\n const arr = React.Children.toArray(children);\n const shown = arr.slice(0, max);\n const overflow = arr.length - shown.length;\n return (\n <div className={cx('avatar-group', className)}>\n {shown.map((c, i) => <span key={i} style={{ marginLeft: i === 0 ? 0 : -size * 0.3, zIndex: shown.length - i }}>{c}</span>)}\n {overflow > 0 && (\n <Avatar name={`+${overflow}`} size={size} className=\"avatar--overflow\" />\n )}\n </div>\n );\n}\n\n// ---------- Menu (dropdown) accesible -----------------------------------\nexport interface MenuItemProps {\n label: React.ReactNode;\n icon?: React.ReactNode;\n description?: React.ReactNode;\n onSelect?: () => void;\n disabled?: boolean;\n destructive?: boolean;\n shortcut?: string;\n}\n\nexport interface MenuProps {\n trigger: React.ReactElement;\n items: Array<MenuItemProps | { type: 'separator' } | { type: 'label'; label: React.ReactNode }>;\n align?: 'start' | 'end';\n className?: string;\n}\n\nexport function Menu({ trigger, items, align = 'start', className }: MenuProps) {\n const [open, setOpen] = React.useState(false);\n const [active, setActive] = React.useState(0);\n const wrapRef = React.useRef<HTMLSpanElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const itemRefs = React.useRef<Array<HTMLButtonElement | null>>([]);\n\n // Positions within `items` that are focusable menu items (no\n // separators/labels/disabled). `active` indexes into this list.\n const enabledIdx = items\n .map((it, i) => ('type' in it ? -1 : it.disabled ? -1 : i))\n .filter((i) => i >= 0);\n\n const pos = usePopoverPosition(wrapRef, panelRef, {\n open,\n side: 'bottom',\n align,\n offset: 6,\n });\n\n const focusTrigger = React.useCallback(() => {\n wrapRef.current?.querySelector<HTMLElement>('[aria-haspopup=\"menu\"]')?.focus();\n }, []);\n\n // Outside-click closes; Escape is handled on the panel so it can also\n // return focus to the trigger (WAI-ARIA menu button pattern).\n useDismiss({\n open,\n onDismiss: () => setOpen(false),\n refs: [wrapRef, panelRef],\n closeOnEscape: false,\n });\n\n React.useEffect(() => {\n if (open) setActive(0);\n }, [open]);\n\n React.useEffect(() => {\n if (!open) return;\n const realIdx = enabledIdx[active];\n if (realIdx != null) itemRefs.current[realIdx]?.focus();\n }, [open, active, enabledIdx]);\n\n const select = (i: number) => {\n const it = items[i];\n if (!it || 'type' in it || it.disabled) return;\n it.onSelect?.();\n setOpen(false);\n focusTrigger();\n };\n\n const onPanelKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n focusTrigger();\n } else if (e.key === 'Tab') {\n setOpen(false);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActive((a) => Math.min(a + 1, enabledIdx.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActive((a) => Math.max(a - 1, 0));\n } else if (e.key === 'Home') {\n e.preventDefault();\n setActive(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n setActive(Math.max(enabledIdx.length - 1, 0));\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const realIdx = enabledIdx[active];\n if (realIdx != null) select(realIdx);\n }\n };\n\n const triggerEl = React.cloneElement(trigger, {\n onClick: (e: React.MouseEvent) => {\n trigger.props.onClick?.(e);\n setOpen((o) => !o);\n },\n onKeyDown: (e: React.KeyboardEvent) => {\n trigger.props.onKeyDown?.(e);\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setOpen(true);\n }\n },\n 'aria-haspopup': 'menu',\n 'aria-expanded': open,\n });\n\n return (\n <span ref={wrapRef} className={cx('menu', className)} style={{ display: 'inline-block' }}>\n {triggerEl}\n {open && (\n <Portal>\n <div\n ref={panelRef}\n role=\"menu\"\n className=\"menu__panel\"\n onKeyDown={onPanelKeyDown}\n style={{\n position: 'fixed',\n top: pos.top,\n left: pos.left,\n visibility: pos.ready ? 'visible' : 'hidden',\n }}\n >\n {items.map((it, i) => {\n if ('type' in it && it.type === 'separator') return <div key={i} className=\"menu__sep\" role=\"separator\" />;\n if ('type' in it && it.type === 'label') return <div key={i} className=\"menu__label\">{it.label}</div>;\n const item = it as MenuItemProps;\n const isActive = enabledIdx[active] === i;\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el; }}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n className={cx('menu__item', isActive && 'is-active', item.destructive && 'is-destructive')}\n onMouseEnter={() => setActive(enabledIdx.indexOf(i))}\n onClick={() => select(i)}\n >\n {item.icon && <span className=\"menu__icon\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"menu__body\">\n <span className=\"menu__label-row\">\n <span>{item.label}</span>\n {item.shortcut && <kbd className=\"menu__kbd\">{item.shortcut}</kbd>}\n </span>\n {item.description && <span className=\"menu__desc\">{item.description}</span>}\n </span>\n </button>\n );\n })}\n </div>\n </Portal>\n )}\n </span>\n );\n}\n\n// ---------- Stat / MiniStat ---------------------------------------------\nexport interface StatProps {\n label: React.ReactNode;\n value: React.ReactNode;\n hint?: React.ReactNode;\n trend?: { dir: 'up' | 'down' | 'flat'; value: string };\n align?: 'start' | 'center';\n className?: string;\n}\n\nexport function Stat({ label, value, hint, trend, align = 'start', className }: StatProps) {\n return (\n <div className={cx('stat', `stat--${align}`, className)}>\n <span className=\"stat__label\">{label}</span>\n <span className=\"stat__value\">{value}</span>\n {(hint || trend) && (\n <span className=\"stat__foot\">\n {trend && (\n <span className={cx('stat__trend', `stat__trend--${trend.dir}`)}>\n {trend.dir === 'up' ? <ChevronUp size={12} /> : trend.dir === 'down' ? <ChevronDown size={12} /> : '–'} {trend.value}\n </span>\n )}\n {hint && <span className=\"stat__hint\">{hint}</span>}\n </span>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/Display2.tsx"],"names":[],"mappings":"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","file":"chunk-DH3IXJRJ.mjs","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { ChevronUp, ChevronDown } from './Icons';\nimport { Portal } from './Portal';\nimport { usePopoverPosition } from '../hooks/usePopoverPosition';\nimport { useDismiss } from '../hooks/useDismiss';\n\n// ---------- Avatar ------------------------------------------------------\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n src?: string;\n alt?: string;\n name?: string; // for initials fallback\n size?: 24 | 32 | 40 | 48 | 64;\n shape?: 'circle' | 'square';\n status?: 'online' | 'offline' | 'busy';\n}\n\nfunction initials(name: string) {\n if (name.startsWith('+')) return name;\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return parts.slice(0, 2).map((p) => p[0]?.toUpperCase() ?? '').join('');\n}\n\nexport function Avatar({ src, alt, name, size = 32, shape = 'circle', status, className, style, ...rest }: AvatarProps) {\n return (\n <span\n className={cx('avatar', `avatar--${shape}`, className)}\n style={{ width: size, height: size, fontSize: size * 0.42, ...style }}\n {...rest}\n >\n {src ? (\n <img src={src} alt={alt ?? name ?? ''} />\n ) : (\n <span className=\"avatar__initials\">{name ? initials(name) : '?'}</span>\n )}\n {status && <span className={cx('avatar__status', `avatar__status--${status}`)} aria-label={status} />}\n </span>\n );\n}\n\nexport interface AvatarGroupProps {\n children: React.ReactNode;\n max?: number;\n size?: AvatarProps['size'];\n className?: string;\n}\n\nexport function AvatarGroup({ children, max = 4, size = 32, className }: AvatarGroupProps) {\n const arr = React.Children.toArray(children);\n const shown = arr.slice(0, max);\n const overflow = arr.length - shown.length;\n return (\n <div className={cx('avatar-group', className)}>\n {shown.map((c, i) => <span key={i} style={{ marginLeft: i === 0 ? 0 : -size * 0.3, zIndex: shown.length - i }}>{c}</span>)}\n {overflow > 0 && (\n <Avatar name={`+${overflow}`} size={size} className=\"avatar--overflow\" />\n )}\n </div>\n );\n}\n\n// ---------- Menu (dropdown) accesible -----------------------------------\nexport interface MenuItemProps {\n label: React.ReactNode;\n icon?: React.ReactNode;\n description?: React.ReactNode;\n onSelect?: () => void;\n disabled?: boolean;\n destructive?: boolean;\n shortcut?: string;\n}\n\nexport interface MenuProps {\n trigger: React.ReactElement;\n items: Array<MenuItemProps | { type: 'separator' } | { type: 'label'; label: React.ReactNode }>;\n align?: 'start' | 'end';\n className?: string;\n}\n\nexport function Menu({ trigger, items, align = 'start', className }: MenuProps) {\n const [open, setOpen] = React.useState(false);\n const [active, setActive] = React.useState(0);\n const wrapRef = React.useRef<HTMLSpanElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const itemRefs = React.useRef<Array<HTMLButtonElement | null>>([]);\n\n // Positions within `items` that are focusable menu items (no\n // separators/labels/disabled). `active` indexes into this list.\n const enabledIdx = items\n .map((it, i) => ('type' in it ? -1 : it.disabled ? -1 : i))\n .filter((i) => i >= 0);\n\n const pos = usePopoverPosition(wrapRef, panelRef, {\n open,\n side: 'bottom',\n align,\n offset: 6,\n });\n\n const focusTrigger = React.useCallback(() => {\n wrapRef.current?.querySelector<HTMLElement>('[aria-haspopup=\"menu\"]')?.focus();\n }, []);\n\n // Outside-click closes; Escape is handled on the panel so it can also\n // return focus to the trigger (WAI-ARIA menu button pattern).\n useDismiss({\n open,\n onDismiss: () => setOpen(false),\n refs: [wrapRef, panelRef],\n closeOnEscape: false,\n });\n\n React.useEffect(() => {\n if (open) setActive(0);\n }, [open]);\n\n React.useEffect(() => {\n if (!open) return;\n const realIdx = enabledIdx[active];\n if (realIdx != null) itemRefs.current[realIdx]?.focus();\n }, [open, active, enabledIdx]);\n\n const select = (i: number) => {\n const it = items[i];\n if (!it || 'type' in it || it.disabled) return;\n it.onSelect?.();\n setOpen(false);\n focusTrigger();\n };\n\n const onPanelKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n focusTrigger();\n } else if (e.key === 'Tab') {\n setOpen(false);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActive((a) => Math.min(a + 1, enabledIdx.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActive((a) => Math.max(a - 1, 0));\n } else if (e.key === 'Home') {\n e.preventDefault();\n setActive(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n setActive(Math.max(enabledIdx.length - 1, 0));\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const realIdx = enabledIdx[active];\n if (realIdx != null) select(realIdx);\n }\n };\n\n const triggerEl = React.cloneElement(trigger, {\n onClick: (e: React.MouseEvent) => {\n trigger.props.onClick?.(e);\n setOpen((o) => !o);\n },\n onKeyDown: (e: React.KeyboardEvent) => {\n trigger.props.onKeyDown?.(e);\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setOpen(true);\n }\n },\n 'aria-haspopup': 'menu',\n 'aria-expanded': open,\n });\n\n return (\n <span ref={wrapRef} className={cx('menu', className)} style={{ display: 'inline-block' }}>\n {triggerEl}\n {open && (\n <Portal>\n <div\n ref={panelRef}\n role=\"menu\"\n className=\"menu__panel\"\n onKeyDown={onPanelKeyDown}\n style={{\n position: 'fixed',\n top: pos.top,\n left: pos.left,\n visibility: pos.ready ? 'visible' : 'hidden',\n }}\n >\n {items.map((it, i) => {\n if ('type' in it && it.type === 'separator') return <div key={i} className=\"menu__sep\" role=\"separator\" />;\n if ('type' in it && it.type === 'label') return <div key={i} className=\"menu__label\">{it.label}</div>;\n const item = it as MenuItemProps;\n const isActive = enabledIdx[active] === i;\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el; }}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n className={cx('menu__item', isActive && 'is-active', item.destructive && 'is-destructive')}\n onMouseEnter={() => setActive(enabledIdx.indexOf(i))}\n onClick={() => select(i)}\n >\n {item.icon && <span className=\"menu__icon\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"menu__body\">\n <span className=\"menu__label-row\">\n <span>{item.label}</span>\n {item.shortcut && <kbd className=\"menu__kbd\">{item.shortcut}</kbd>}\n </span>\n {item.description && <span className=\"menu__desc\">{item.description}</span>}\n </span>\n </button>\n );\n })}\n </div>\n </Portal>\n )}\n </span>\n );\n}\n\n// ---------- Stat / MiniStat ---------------------------------------------\nexport interface StatProps {\n label: React.ReactNode;\n value: React.ReactNode;\n hint?: React.ReactNode;\n trend?: { dir: 'up' | 'down' | 'flat'; value: string };\n align?: 'start' | 'center';\n className?: string;\n}\n\nexport function Stat({ label, value, hint, trend, align = 'start', className }: StatProps) {\n return (\n <div className={cx('stat', `stat--${align}`, className)}>\n <span className=\"stat__label\">{label}</span>\n <span className=\"stat__value\">{value}</span>\n {(hint || trend) && (\n <span className=\"stat__foot\">\n {trend && (\n <span className={cx('stat__trend', `stat__trend--${trend.dir}`)}>\n {trend.dir === 'up' ? <ChevronUp size={12} /> : trend.dir === 'down' ? <ChevronDown size={12} /> : '–'} {trend.value}\n </span>\n )}\n {hint && <span className=\"stat__hint\">{hint}</span>}\n </span>\n )}\n </div>\n );\n}\n"]}
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
  import { format } from './chunk-VGA7UT6T.mjs';
3
3
  import { Portal } from './chunk-FKBQYQQD.mjs';
4
+ import { getBrand } from './chunk-5GEWIK4T.mjs';
4
5
  import { useLocale } from './chunk-KYYRQNY7.mjs';
6
+ import { useDismiss } from './chunk-6P2TKRTL.mjs';
7
+ import { usePopoverPosition } from './chunk-5XT2LX3I.mjs';
5
8
  import { X, Clock } from './chunk-BJGMROKL.mjs';
6
9
  import { cx } from './chunk-IEPCH3JB.mjs';
7
- import { getBrand } from './chunk-5GEWIK4T.mjs';
8
- import { usePopoverPosition } from './chunk-5XT2LX3I.mjs';
9
- import { useDismiss } from './chunk-6P2TKRTL.mjs';
10
10
  import * as React from 'react';
11
11
  import { jsxs, jsx } from 'react/jsx-runtime';
12
12
 
@@ -362,5 +362,5 @@ function CheckboxGroup({ value, onChange, options, orientation = "vertical", cla
362
362
  }
363
363
 
364
364
  export { CheckboxGroup, MoneyInput, PhoneInput, Progress, ProgressCircle, RadioGroup, Slider, TagInput, TimePicker };
365
- //# sourceMappingURL=chunk-XA57BOHJ.mjs.map
366
- //# sourceMappingURL=chunk-XA57BOHJ.mjs.map
365
+ //# sourceMappingURL=chunk-ESU5UMEK.mjs.map
366
+ //# sourceMappingURL=chunk-ESU5UMEK.mjs.map