@beweco/aurora-ui 0.6.75 → 0.6.76-qa.102

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 (27) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +189 -12
  3. package/dist/index.esm.js +184 -13
  4. package/dist/types/components/area-line-chart/AreaLineChart.d.ts +1 -1
  5. package/dist/types/components/area-line-chart/AreaLineChart.d.ts.map +1 -1
  6. package/dist/types/components/area-line-chart/AreaLineChart.types.d.ts +12 -0
  7. package/dist/types/components/area-line-chart/AreaLineChart.types.d.ts.map +1 -1
  8. package/dist/types/components/button/Button.d.ts +1 -0
  9. package/dist/types/components/button/Button.d.ts.map +1 -1
  10. package/dist/types/components/button/Button.types.d.ts +15 -0
  11. package/dist/types/components/button/Button.types.d.ts.map +1 -1
  12. package/dist/types/components/donut-chart/DonutChart.d.ts.map +1 -1
  13. package/dist/types/components/donut-chart/DonutChart.types.d.ts +2 -0
  14. package/dist/types/components/donut-chart/DonutChart.types.d.ts.map +1 -1
  15. package/dist/types/components/donut-chart/donut-chart.utils.d.ts +7 -0
  16. package/dist/types/components/donut-chart/donut-chart.utils.d.ts.map +1 -1
  17. package/dist/types/components/donut-chart/index.d.ts +1 -1
  18. package/dist/types/components/donut-chart/index.d.ts.map +1 -1
  19. package/dist/types/components/phone/Phone.d.ts.map +1 -1
  20. package/dist/types/index.d.ts +1 -0
  21. package/dist/types/index.d.ts.map +1 -1
  22. package/dist/types/providers/theme/index.d.ts +1 -0
  23. package/dist/types/providers/theme/index.d.ts.map +1 -1
  24. package/dist/types/providers/theme/linda-tones.d.ts +53 -0
  25. package/dist/types/providers/theme/linda-tones.d.ts.map +1 -0
  26. package/dist/types/providers/theme/useThemeManager.d.ts.map +1 -1
  27. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -284,6 +284,10 @@ exports.HolidayType = void 0;
284
284
  HolidayType["DateRange"] = "dateRange";
285
285
  })(exports.HolidayType || (exports.HolidayType = {}));
286
286
 
287
+ var CLASE_AURA = {
288
+ ring: "linda-aura-ring",
289
+ surface: "linda-aura",
290
+ };
287
291
  /**
288
292
  * Botón genérico basado en HeroUI siguiendo las reglas de diseño BeweOS.
289
293
  *
@@ -294,10 +298,24 @@ exports.HolidayType = void 0;
294
298
  * - isLoading: On, Off
295
299
  * - Radius: md (por defecto)
296
300
  * - isIconOnly: True, False
301
+ * - ai: aura de Linda para las acciones que hace la IA (ver `Button.types.ts`)
297
302
  */
298
303
  var Button = function (_a) {
299
- var _b = _a.color, color = _b === void 0 ? "primary" : _b, _c = _a.size, size = _c === void 0 ? "md" : _c, _d = _a.variant, variant = _d === void 0 ? "solid" : _d, _e = _a.radius, radius = _e === void 0 ? "sm" : _e, startContent = _a.startContent, endContent = _a.endContent, _f = _a.isLoading, isLoading = _f === void 0 ? false : _f, _g = _a.isIconOnly, isIconOnly = _g === void 0 ? false : _g, props = __rest(_a, ["color", "size", "variant", "radius", "startContent", "endContent", "isLoading", "isIconOnly"]);
300
- return (jsxRuntime.jsx(react.Button, __assign({}, props, { color: color, size: size, variant: variant, radius: radius, startContent: startContent, endContent: endContent, isLoading: isLoading, isIconOnly: isIconOnly })));
304
+ var _b = _a.color, color = _b === void 0 ? "primary" : _b, _c = _a.size, size = _c === void 0 ? "md" : _c, _d = _a.variant, variant = _d === void 0 ? "solid" : _d, _e = _a.radius, radius = _e === void 0 ? "sm" : _e, startContent = _a.startContent, endContent = _a.endContent, _f = _a.isLoading, isLoading = _f === void 0 ? false : _f, _g = _a.isIconOnly, isIconOnly = _g === void 0 ? false : _g, ai = _a.ai, className = _a.className, children = _a.children, props = __rest(_a, ["color", "size", "variant", "radius", "startContent", "endContent", "isLoading", "isIconOnly", "ai", "className", "children"]);
305
+ /*
306
+ * El contenido se envuelve para poder subirlo por encima del aura.
307
+ *
308
+ * Y tiene que ser un elemento: `<Button>Crear campaña</Button>` pasa un NODO DE
309
+ * TEXTO, que no es posicionable, así que ningún selector puede sacarlo del fondo del
310
+ * apilado —el aura, que sí está posicionada, le pasaría por encima—. Con `ring` daría
311
+ * igual porque esa capa es solo el canto; con `surface` el texto se leería a través
312
+ * del degradado.
313
+ */
314
+ var contenido = ai ? (jsxRuntime.jsx("span", { className: "linda-aura-content", children: children })) : (children);
315
+ var clases = [ai ? CLASE_AURA[ai] : "", className]
316
+ .filter(Boolean)
317
+ .join(" ");
318
+ return (jsxRuntime.jsx(react.Button, __assign({}, props, { color: color, size: size, variant: variant, radius: radius, startContent: startContent, endContent: endContent, isLoading: isLoading, isIconOnly: isIconOnly, className: clases || undefined, children: contenido })));
301
319
  };
302
320
 
303
321
  var DatePicker = function (_a) {
@@ -581,9 +599,9 @@ function ChartTooltip(_a) {
581
599
  })] }));
582
600
  }
583
601
  function AreaLineChart(_a) {
584
- var data = _a.data, xAxisKey = _a.xAxisKey, series = _a.series, title = _a.title, value = _a.value, trend = _a.trend, _b = _a.height, height = _b === void 0 ? 200 : _b, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.wrappedInCard, wrappedInCard = _d === void 0 ? false : _d, formatTooltipValue = _a.formatTooltipValue, _e = _a.yAxisDomain, yAxisDomain = _e === void 0 ? [0, "dataMax + 100"] : _e;
602
+ var data = _a.data, xAxisKey = _a.xAxisKey, series = _a.series, title = _a.title, value = _a.value, trend = _a.trend, _b = _a.height, height = _b === void 0 ? 200 : _b, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.wrappedInCard, wrappedInCard = _d === void 0 ? false : _d, formatTooltipValue = _a.formatTooltipValue, _e = _a.yAxisDomain, yAxisDomain = _e === void 0 ? [0, "dataMax + 100"] : _e, _f = _a.xAxisInterval, xAxisInterval = _f === void 0 ? "preserveStartEnd" : _f;
585
603
  var hasHeader = title != null || value != null || trend != null || series.length > 0;
586
- var content = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasHeader && (jsxRuntime.jsxs("div", { className: "flex items-start justify-between mb-6", children: [jsxRuntime.jsxs("div", { children: [title != null && (jsxRuntime.jsx(H3, { className: "text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1", children: title })), value != null && (jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [jsxRuntime.jsx("span", { className: "text-2xl font-bold text-gray-900", children: value }), trend != null && (jsxRuntime.jsx("span", { className: "text-xs font-medium text-yellow-600 bg-yellow-50 px-2 py-1 rounded", children: trend }))] }))] }), series.length > 0 && (jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-4", children: series.map(function (s) { return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("svg", { width: "16", height: "2", viewBox: "0 0 16 2", fill: "none", children: jsxRuntime.jsx("line", { x1: "0", y1: "1", x2: "16", y2: "1", stroke: s.color, strokeWidth: "2" }) }), jsxRuntime.jsx("span", { className: "text-xs text-gray-600 font-medium", children: s.label })] }, s.dataKey)); }) }))] })), jsxRuntime.jsx("div", { className: "w-full", style: { height: "".concat(height, "px") }, children: jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: jsxRuntime.jsxs(recharts.LineChart, { data: data, margin: { top: 5, right: 5, left: 5, bottom: 5 }, children: [jsxRuntime.jsx("defs", { children: series.map(function (s) { return (jsxRuntime.jsxs("linearGradient", { id: "area-line-chart-".concat(s.dataKey), x1: "0", y1: "0", x2: "0", y2: "1", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: s.color, stopOpacity: 0.3 }), jsxRuntime.jsx("stop", { offset: "50%", stopColor: s.color, stopOpacity: 0.15 }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: s.color, stopOpacity: 0 })] }, s.dataKey)); }) }), jsxRuntime.jsx(recharts.XAxis, { dataKey: xAxisKey, axisLine: false, tickLine: false, tick: { fill: "#9ca3af", fontSize: 12 }, dy: 10 }), jsxRuntime.jsx(recharts.YAxis, { axisLine: false, tickLine: false, tick: { fill: "transparent", fontSize: 0 }, width: 0, tickCount: 6, domain: yAxisDomain, allowDecimals: false }), jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "#d1d5db", strokeOpacity: 0.5, vertical: false, horizontal: true }), jsxRuntime.jsx(recharts.Tooltip, { content: jsxRuntime.jsx(ChartTooltip, { series: series, formatValue: formatTooltipValue }) }), series.map(function (s) { return (jsxRuntime.jsx(recharts.Area, { type: "natural", dataKey: s.dataKey, stroke: "none", fill: "url(#area-line-chart-".concat(s.dataKey, ")"), animationDuration: 1500, animationEasing: "ease-in-out" }, "area-".concat(s.dataKey))); }), series.map(function (s) { return (jsxRuntime.jsx(recharts.Line, { type: "natural", dataKey: s.dataKey, name: s.dataKey, stroke: s.color, strokeWidth: 3, dot: false, activeDot: {
604
+ var content = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasHeader && (jsxRuntime.jsxs("div", { className: "flex items-start justify-between mb-6", children: [jsxRuntime.jsxs("div", { children: [title != null && (jsxRuntime.jsx(H3, { className: "text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1", children: title })), value != null && (jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [jsxRuntime.jsx("span", { className: "text-2xl font-bold text-gray-900", children: value }), trend != null && (jsxRuntime.jsx("span", { className: "text-xs font-medium text-yellow-600 bg-yellow-50 px-2 py-1 rounded", children: trend }))] }))] }), series.length > 0 && (jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-4", children: series.map(function (s) { return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("svg", { width: "16", height: "2", viewBox: "0 0 16 2", fill: "none", children: jsxRuntime.jsx("line", { x1: "0", y1: "1", x2: "16", y2: "1", stroke: s.color, strokeWidth: "2" }) }), jsxRuntime.jsx("span", { className: "text-xs text-gray-600 font-medium", children: s.label })] }, s.dataKey)); }) }))] })), jsxRuntime.jsx("div", { className: "w-full", style: { height: "".concat(height, "px") }, children: jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: jsxRuntime.jsxs(recharts.LineChart, { data: data, margin: { top: 5, right: 5, left: 5, bottom: 5 }, children: [jsxRuntime.jsx("defs", { children: series.map(function (s) { return (jsxRuntime.jsxs("linearGradient", { id: "area-line-chart-".concat(s.dataKey), x1: "0", y1: "0", x2: "0", y2: "1", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: s.color, stopOpacity: 0.3 }), jsxRuntime.jsx("stop", { offset: "50%", stopColor: s.color, stopOpacity: 0.15 }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: s.color, stopOpacity: 0 })] }, s.dataKey)); }) }), jsxRuntime.jsx(recharts.XAxis, { dataKey: xAxisKey, axisLine: false, tickLine: false, tick: { fill: "#9ca3af", fontSize: 12 }, dy: 10, interval: xAxisInterval }), jsxRuntime.jsx(recharts.YAxis, { axisLine: false, tickLine: false, tick: { fill: "transparent", fontSize: 0 }, width: 0, tickCount: 6, domain: yAxisDomain, allowDecimals: false }), jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "#d1d5db", strokeOpacity: 0.5, vertical: false, horizontal: true }), jsxRuntime.jsx(recharts.Tooltip, { content: jsxRuntime.jsx(ChartTooltip, { series: series, formatValue: formatTooltipValue }) }), series.map(function (s) { return (jsxRuntime.jsx(recharts.Area, { type: "natural", dataKey: s.dataKey, stroke: "none", fill: "url(#area-line-chart-".concat(s.dataKey, ")"), animationDuration: 1500, animationEasing: "ease-in-out" }, "area-".concat(s.dataKey))); }), series.map(function (s) { return (jsxRuntime.jsx(recharts.Line, { type: "natural", dataKey: s.dataKey, name: s.dataKey, stroke: s.color, strokeWidth: 3, dot: false, activeDot: {
587
605
  r: 6,
588
606
  fill: s.color,
589
607
  stroke: "#fff",
@@ -2967,6 +2985,20 @@ function computeTotal(data) {
2967
2985
  function isDonutEmpty(data) {
2968
2986
  return data.length === 0 || computeTotal(data) === 0;
2969
2987
  }
2988
+ /**
2989
+ * Formatea `percent` (0-1) como entero + "%", excepto cuando la porción es
2990
+ * real (>0) pero redondea a 0 — ahí muestra "<1%" en vez de "0%", que se lee
2991
+ * como "no hay nada" y confunde cuando sí hay dato (ej. 4 de 2357 = 0.17%).
2992
+ * `lessThanOneLabel` permite traducir el texto (ver `DonutChartTranslations`).
2993
+ */
2994
+ function formatDonutPercent(percent, lessThanOneLabel) {
2995
+ if (lessThanOneLabel === void 0) { lessThanOneLabel = "<1%"; }
2996
+ if (!Number.isFinite(percent) || percent <= 0) {
2997
+ return "0%";
2998
+ }
2999
+ var rounded = Math.round(percent * 100);
3000
+ return rounded === 0 ? lessThanOneLabel : "".concat(rounded, "%");
3001
+ }
2970
3002
  /**
2971
3003
  * Resuelve las proporciones y el color final de cada categoría.
2972
3004
  * El color propio de cada dato tiene prioridad; si falta, se cicla `palette` por índice.
@@ -2984,6 +3016,7 @@ function computeSlices(data, palette) {
2984
3016
  var DEFAULT_TRANSLATIONS$b = {
2985
3017
  emptyState: "Sin datos para mostrar",
2986
3018
  totalLabel: "Total",
3019
+ lessThanOnePercent: "<1%",
2987
3020
  };
2988
3021
  /**
2989
3022
  * DonutChart - Gráfico circular (pie o donut, según `innerRadiusRatio`) con
@@ -3002,7 +3035,7 @@ var DonutChart = function (_a) {
3002
3035
  return formatValue ? formatValue(value) : String(value);
3003
3036
  };
3004
3037
  var isDonut = innerRadiusRatio > 0;
3005
- return (jsxRuntime.jsxs("div", { className: className, children: [jsxRuntime.jsxs("div", { className: "relative w-full", style: { height: height }, children: [jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: jsxRuntime.jsxs(recharts.PieChart, { children: [jsxRuntime.jsx(recharts.Pie, { data: slices, dataKey: "value", nameKey: "name", innerRadius: isDonut ? "".concat(innerRadiusRatio * 100, "%") : 0, outerRadius: "90%", stroke: "none", children: slices.map(function (slice) { return (jsxRuntime.jsx(recharts.Cell, { fill: slice.color }, slice.name)); }) }), jsxRuntime.jsx(recharts.Tooltip, { formatter: function (value) { return format(value); } })] }) }), isDonut && showTotal && (jsxRuntime.jsxs("div", { className: "aurora-donut-total pointer-events-none absolute inset-0 flex flex-col items-center justify-center", "aria-hidden": "true", children: [jsxRuntime.jsx("span", { className: "text-xs text-foreground-500", children: t.totalLabel }), jsxRuntime.jsx("span", { className: "text-xl font-semibold", children: format(total) })] }))] }), showLegend && (jsxRuntime.jsx("ul", { className: "mt-3 flex flex-wrap gap-3", children: slices.map(function (slice) { return (jsxRuntime.jsxs("li", { className: "flex items-center gap-1.5 text-xs", children: [jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: slice.color }, "aria-hidden": "true" }), jsxRuntime.jsx("span", { children: slice.name }), jsxRuntime.jsxs("span", { className: "text-foreground-500", children: [Math.round(slice.percent * 100), "%"] })] }, slice.name)); }) }))] }));
3038
+ return (jsxRuntime.jsxs("div", { className: className, children: [jsxRuntime.jsxs("div", { className: "relative w-full", style: { height: height }, children: [jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: jsxRuntime.jsxs(recharts.PieChart, { children: [jsxRuntime.jsx(recharts.Pie, { data: slices, dataKey: "value", nameKey: "name", innerRadius: isDonut ? "".concat(innerRadiusRatio * 100, "%") : 0, outerRadius: "90%", stroke: "none", children: slices.map(function (slice) { return (jsxRuntime.jsx(recharts.Cell, { fill: slice.color }, slice.name)); }) }), jsxRuntime.jsx(recharts.Tooltip, { formatter: function (value) { return format(value); } })] }) }), isDonut && showTotal && (jsxRuntime.jsxs("div", { className: "aurora-donut-total pointer-events-none absolute inset-0 flex flex-col items-center justify-center", "aria-hidden": "true", children: [jsxRuntime.jsx("span", { className: "text-xs text-foreground-500", children: t.totalLabel }), jsxRuntime.jsx("span", { className: "text-xl font-semibold", children: format(total) })] }))] }), showLegend && (jsxRuntime.jsx("ul", { className: "mt-3 flex flex-wrap gap-3", children: slices.map(function (slice) { return (jsxRuntime.jsxs("li", { className: "flex items-center gap-1.5 text-xs", children: [jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: slice.color }, "aria-hidden": "true" }), jsxRuntime.jsx("span", { children: slice.name }), jsxRuntime.jsx("span", { className: "text-foreground-500", children: formatDonutPercent(slice.percent, t.lessThanOnePercent) })] }, slice.name)); }) }))] }));
3006
3039
  };
3007
3040
 
3008
3041
  var H1 = function (_a) {
@@ -4464,13 +4497,6 @@ var Phone = function (_a) {
4464
4497
  document.removeEventListener("mousedown", handleClickOutside);
4465
4498
  };
4466
4499
  }, [isDropdownOpen]);
4467
- // El dropdown se portea a `body` con posición absoluta fija; cerrarlo cuando
4468
- // un ancestro hace scroll para que no quede flotando fuera de lugar.
4469
- useCloseOnAncestorScroll({
4470
- isOpen: isDropdownOpen,
4471
- onClose: function () { return setIsDropdownOpen(false); },
4472
- contentRef: portalDropdownRef,
4473
- });
4474
4500
  var handleCountrySelect = function (country) {
4475
4501
  setSelectedCountry(country);
4476
4502
  setIsDropdownOpen(false);
@@ -9644,6 +9670,127 @@ function removeCustomPrimaryColor() {
9644
9670
  }
9645
9671
  }
9646
9672
 
9673
+ /**
9674
+ * Los tres tonos del aura de Linda, derivados del `primary` de la agencia.
9675
+ *
9676
+ * Linda no tiene color propio: es el `primary` que el negocio eligió en el onboarding,
9677
+ * y por eso aquí no hay ni un color escrito. Lo único que se fija es CUÁNTO se gira ese
9678
+ * tono y en qué banda de luz se pinta.
9679
+ */
9680
+ /**
9681
+ * Grados que se gira el `primary` para cada tono, en el orden en que se pintan.
9682
+ *
9683
+ * Son muchos grados a propósito. La gracia del aura es que haya MÁS DE UN COLOR: con
9684
+ * un giro discreto —del orden de 18°, el que usa un degradado de profundidad— salen
9685
+ * tres versiones del mismo tono y el resultado se lee como un plano. A ±55° el salto
9686
+ * se ve como otro color y sigue dentro de la familia del `primary`, que es lo que
9687
+ * permite que esto funcione con la agencia número siete sin tocar nada.
9688
+ *
9689
+ * El tono del medio va casi sin girar: es el que ancla el conjunto al color de la
9690
+ * agencia, para que el aura se lea como suya y no como una decoración pegada encima.
9691
+ */
9692
+ var GIROS = [-56, 8, 54];
9693
+ /**
9694
+ * Banda de luz en la que se pintan los tres tonos, en porcentaje HSL.
9695
+ *
9696
+ * Los tonos NO heredan la luz del `primary`, y esto es lo que más se nota: un primary
9697
+ * oscuro y poco saturado sobre una superficie clara se lee como una mancha gris —sucia,
9698
+ * no como color—, y uno casi blanco desaparece contra el fondo. Se llevan al paso medio
9699
+ * de la escala, que es el que funciona en los dos casos.
9700
+ */
9701
+ var BANDA_LUZ = { min: 52, max: 72 };
9702
+ /**
9703
+ * Banda de saturación de los tres tonos, en porcentaje HSL.
9704
+ *
9705
+ * El techo es lo que evita que el aura grite. A plena saturación los tonos dejan de ser
9706
+ * ambiente y pasan a ser tres focos de color encima de un control de 40 pt: bonito en
9707
+ * una captura, insoportable en una barra que se mira todo el día.
9708
+ *
9709
+ * ⚠️ **Y hay una razón que no es estética.** Girar el tono puede caer en un rojo vivo:
9710
+ * un `primary` amarillo —51°— girado −56° aterriza en 355°, que a saturación 100 se lee
9711
+ * como un estado de error alrededor de un botón que no ha fallado. Visto al renderizarlo,
9712
+ * no razonándolo. Bajado a 65 el mismo tono es un rosa apagado y vuelve a leerse como lo
9713
+ * que es: decoración.
9714
+ *
9715
+ * El suelo existe por lo contrario: un `primary` casi gris da tres tonos que no se
9716
+ * distinguen entre sí, y entonces no hay degradado que ver —el aura se lee como una
9717
+ * mancha plana—.
9718
+ */
9719
+ var BANDA_SATURACION = { min: 35, max: 65 };
9720
+ var VUELTA = 360;
9721
+ /** `H S% L%` — el formato exacto en el que HeroUI guarda sus variables de color. */
9722
+ var TRIPLETE = /^\s*(-?\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)%\s+(\d+(?:\.\d+)?)%\s*$/;
9723
+ /**
9724
+ * Lee el triplete que HeroUI deja en una variable de color.
9725
+ *
9726
+ * Devuelve `null` en vez de lanzar: esto corre en un efecto de tema y el valor puede
9727
+ * no estar todavía —la clase del tema aún no está en el `<html>`, o el consumidor no
9728
+ * cargó la hoja de estilos—. Un aura que no se pinta es un problema menor; una
9729
+ * excepción que tumba el provider de tema, no.
9730
+ */
9731
+ function parseHslTriplet(value) {
9732
+ var encontrado = TRIPLETE.exec(value);
9733
+ if (!encontrado) {
9734
+ return null;
9735
+ }
9736
+ var h = encontrado[1], s = encontrado[2], l = encontrado[3];
9737
+ return { h: Number(h), s: Number(s), l: Number(l) };
9738
+ }
9739
+ /** Deja un ángulo dentro de `[0, 360)`, venga de donde venga. */
9740
+ function normalizarTono(grados) {
9741
+ return ((grados % VUELTA) + VUELTA) % VUELTA;
9742
+ }
9743
+ function acotar(valor, min, max) {
9744
+ return Math.min(Math.max(valor, min), max);
9745
+ }
9746
+ /**
9747
+ * Los tres tonos del aura, listos para escribirse en una variable CSS.
9748
+ *
9749
+ * Se redondean a entero: es un degradado decorativo, y las décimas de grado solo
9750
+ * alargan la hoja de estilos.
9751
+ */
9752
+ function deriveLindaTones(primary) {
9753
+ var luz = Math.round(acotar(primary.l, BANDA_LUZ.min, BANDA_LUZ.max));
9754
+ var saturacion = Math.round(acotar(primary.s, BANDA_SATURACION.min, BANDA_SATURACION.max));
9755
+ var tonos = GIROS.map(function (giro) {
9756
+ return "".concat(Math.round(normalizarTono(primary.h + giro)), " ").concat(saturacion, "% ").concat(luz, "%");
9757
+ });
9758
+ return tonos;
9759
+ }
9760
+ /** Las variables que se escriben en el `<html>`, en el orden en que se pintan. */
9761
+ var LINDA_TONE_PROPERTIES = [
9762
+ "--linda-1",
9763
+ "--linda-2",
9764
+ "--linda-3",
9765
+ ];
9766
+ /**
9767
+ * Escribe los tres tonos del aura a partir del valor de `--heroui-primary`.
9768
+ *
9769
+ * Si el primary no se puede leer, **borra los que hubiera** y devuelve `false`. Es lo
9770
+ * contrario de dejarlos: unos tonos viejos son de otro tema, y un aura del color
9771
+ * anterior es peor que un aura que no se pinta —la CSS del efecto ya está escrita para
9772
+ * desaparecer sin sus variables—.
9773
+ */
9774
+ function applyLindaTones(style, primaryValue) {
9775
+ var primary = parseHslTriplet(primaryValue);
9776
+ if (!primary) {
9777
+ removeLindaTones(style);
9778
+ return false;
9779
+ }
9780
+ var tonos = deriveLindaTones(primary);
9781
+ LINDA_TONE_PROPERTIES.forEach(function (propiedad, indice) {
9782
+ style.setProperty(propiedad, tonos[indice]);
9783
+ });
9784
+ return true;
9785
+ }
9786
+ /** Quita los tres tonos del aura. */
9787
+ function removeLindaTones(style) {
9788
+ for (var _i = 0, LINDA_TONE_PROPERTIES_1 = LINDA_TONE_PROPERTIES; _i < LINDA_TONE_PROPERTIES_1.length; _i++) {
9789
+ var propiedad = LINDA_TONE_PROPERTIES_1[_i];
9790
+ style.removeProperty(propiedad);
9791
+ }
9792
+ }
9793
+
9647
9794
  /**
9648
9795
  * Custom hook to manage the theme state and side effects.
9649
9796
  * Supports both named ThemeColor values and arbitrary hex colors.
@@ -9689,6 +9836,30 @@ var useThemeManager = function () {
9689
9836
  removeCustomPrimaryColor();
9690
9837
  }
9691
9838
  }, [customHex, mode]);
9839
+ /*
9840
+ * Los tres tonos del aura de Linda, derivados del primary que acaba de quedar fijado.
9841
+ *
9842
+ * Va DESPUÉS de los dos efectos de arriba y depende de lo mismo que ellos, que es lo
9843
+ * que garantiza que lea el primary definitivo: React ejecuta los efectos en orden de
9844
+ * declaración, así que aquí la clase del tema ya está en el `<html>` y el hex a medida
9845
+ * ya está escrito o retirado.
9846
+ *
9847
+ * Se lee del estilo COMPUTADO y no de `customHex` a propósito: el primary llega por
9848
+ * dos caminos —el hex del negocio o la clase de una de las familias de tema— y el
9849
+ * computado es el único sitio donde los dos han convergido. Derivarlo solo de
9850
+ * `customHex` dejaría sin aura a toda agencia que use una familia tal cual.
9851
+ */
9852
+ /*
9853
+ * `customHex` y `rawTheme` están en la lista aunque el cuerpo no los lea: son la señal
9854
+ * de que el `<html>` acaba de cambiar. La entrada real de este efecto es el estilo
9855
+ * computado, que la regla no puede ver, y sin ellos el aura se quedaría con los tonos
9856
+ * del tema anterior.
9857
+ */
9858
+ // biome-ignore lint/correctness/useExhaustiveDependencies: ver el comentario de arriba
9859
+ React.useEffect(function () {
9860
+ var html = document.documentElement;
9861
+ applyLindaTones(html.style, getComputedStyle(html).getPropertyValue("--heroui-primary"));
9862
+ }, [customHex, rawTheme]);
9692
9863
  var setMode = React.useCallback(function (newMode) {
9693
9864
  var effectiveMode = newMode === "dark" ? "light" : newMode;
9694
9865
  var newTheme = color === "blue" ? effectiveMode : "".concat(color, "-").concat(effectiveMode);
@@ -9861,6 +10032,7 @@ exports.InputPassword = InputPassword;
9861
10032
  exports.Kanban = Kanban;
9862
10033
  exports.KanbanCard = KanbanCard;
9863
10034
  exports.KanbanColumn = KanbanColumn;
10035
+ exports.LINDA_TONE_PROPERTIES = LINDA_TONE_PROPERTIES;
9864
10036
  exports.LindaIcon = LindaIcon;
9865
10037
  exports.MenuClaw = MenuClaw;
9866
10038
  exports.MenuComponent = MenuComponent;
@@ -9911,6 +10083,7 @@ exports.Wizard = Wizard;
9911
10083
  exports.WizardNavigation = WizardNavigation;
9912
10084
  exports.WizardSidebar = WizardSidebar;
9913
10085
  exports.applyCustomPrimaryColor = applyCustomPrimaryColor;
10086
+ exports.applyLindaTones = applyLindaTones;
9914
10087
  exports.computeBars = computeBars;
9915
10088
  exports.computeMax = computeMax;
9916
10089
  exports.computeSlices = computeSlices;
@@ -9920,9 +10093,11 @@ exports.createCurrencyFormatter = createCurrencyFormatter;
9920
10093
  exports.defaultCountries = uniqueCountries;
9921
10094
  exports.defaultCurrencyOptions = defaultCurrencyOptions;
9922
10095
  exports.defaultTranslations = defaultTranslations$5;
10096
+ exports.deriveLindaTones = deriveLindaTones;
9923
10097
  exports.dismissControlProps = dismissControlProps;
9924
10098
  exports.forceLightOnlyThemeBeforeReact = forceLightOnlyThemeBeforeReact;
9925
10099
  exports.formatAuroraThemeTooltip = formatAuroraThemeTooltip;
10100
+ exports.formatDonutPercent = formatDonutPercent;
9926
10101
  exports.generateThemeColorScale = generateThemeColorScale;
9927
10102
  exports.getContrastForeground = getContrastForeground;
9928
10103
  exports.getRegisteredThemeColorBases = getRegisteredThemeColorBases;
@@ -9937,7 +10112,9 @@ exports.isGroupState = isGroupState;
9937
10112
  exports.isHexColor = isHexColor;
9938
10113
  exports.isRankedBarListEmpty = isRankedBarListEmpty;
9939
10114
  exports.isSegmentationGroup = isSegmentationGroup;
10115
+ exports.parseHslTriplet = parseHslTriplet;
9940
10116
  exports.removeCustomPrimaryColor = removeCustomPrimaryColor;
10117
+ exports.removeLindaTones = removeLindaTones;
9941
10118
  exports.shouldClosePopoverOnInteractOutside = shouldClosePopoverOnInteractOutside;
9942
10119
  exports.sizeMap = sizeMap;
9943
10120
  exports.themeColors = themeColors;
package/dist/index.esm.js CHANGED
@@ -285,6 +285,10 @@ var HolidayType;
285
285
  HolidayType["DateRange"] = "dateRange";
286
286
  })(HolidayType || (HolidayType = {}));
287
287
 
288
+ var CLASE_AURA = {
289
+ ring: "linda-aura-ring",
290
+ surface: "linda-aura",
291
+ };
288
292
  /**
289
293
  * Botón genérico basado en HeroUI siguiendo las reglas de diseño BeweOS.
290
294
  *
@@ -295,10 +299,24 @@ var HolidayType;
295
299
  * - isLoading: On, Off
296
300
  * - Radius: md (por defecto)
297
301
  * - isIconOnly: True, False
302
+ * - ai: aura de Linda para las acciones que hace la IA (ver `Button.types.ts`)
298
303
  */
299
304
  var Button = function (_a) {
300
- var _b = _a.color, color = _b === void 0 ? "primary" : _b, _c = _a.size, size = _c === void 0 ? "md" : _c, _d = _a.variant, variant = _d === void 0 ? "solid" : _d, _e = _a.radius, radius = _e === void 0 ? "sm" : _e, startContent = _a.startContent, endContent = _a.endContent, _f = _a.isLoading, isLoading = _f === void 0 ? false : _f, _g = _a.isIconOnly, isIconOnly = _g === void 0 ? false : _g, props = __rest(_a, ["color", "size", "variant", "radius", "startContent", "endContent", "isLoading", "isIconOnly"]);
301
- return (jsx(Button$1, __assign({}, props, { color: color, size: size, variant: variant, radius: radius, startContent: startContent, endContent: endContent, isLoading: isLoading, isIconOnly: isIconOnly })));
305
+ var _b = _a.color, color = _b === void 0 ? "primary" : _b, _c = _a.size, size = _c === void 0 ? "md" : _c, _d = _a.variant, variant = _d === void 0 ? "solid" : _d, _e = _a.radius, radius = _e === void 0 ? "sm" : _e, startContent = _a.startContent, endContent = _a.endContent, _f = _a.isLoading, isLoading = _f === void 0 ? false : _f, _g = _a.isIconOnly, isIconOnly = _g === void 0 ? false : _g, ai = _a.ai, className = _a.className, children = _a.children, props = __rest(_a, ["color", "size", "variant", "radius", "startContent", "endContent", "isLoading", "isIconOnly", "ai", "className", "children"]);
306
+ /*
307
+ * El contenido se envuelve para poder subirlo por encima del aura.
308
+ *
309
+ * Y tiene que ser un elemento: `<Button>Crear campaña</Button>` pasa un NODO DE
310
+ * TEXTO, que no es posicionable, así que ningún selector puede sacarlo del fondo del
311
+ * apilado —el aura, que sí está posicionada, le pasaría por encima—. Con `ring` daría
312
+ * igual porque esa capa es solo el canto; con `surface` el texto se leería a través
313
+ * del degradado.
314
+ */
315
+ var contenido = ai ? (jsx("span", { className: "linda-aura-content", children: children })) : (children);
316
+ var clases = [ai ? CLASE_AURA[ai] : "", className]
317
+ .filter(Boolean)
318
+ .join(" ");
319
+ return (jsx(Button$1, __assign({}, props, { color: color, size: size, variant: variant, radius: radius, startContent: startContent, endContent: endContent, isLoading: isLoading, isIconOnly: isIconOnly, className: clases || undefined, children: contenido })));
302
320
  };
303
321
 
304
322
  var DatePicker = function (_a) {
@@ -582,9 +600,9 @@ function ChartTooltip(_a) {
582
600
  })] }));
583
601
  }
584
602
  function AreaLineChart(_a) {
585
- var data = _a.data, xAxisKey = _a.xAxisKey, series = _a.series, title = _a.title, value = _a.value, trend = _a.trend, _b = _a.height, height = _b === void 0 ? 200 : _b, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.wrappedInCard, wrappedInCard = _d === void 0 ? false : _d, formatTooltipValue = _a.formatTooltipValue, _e = _a.yAxisDomain, yAxisDomain = _e === void 0 ? [0, "dataMax + 100"] : _e;
603
+ var data = _a.data, xAxisKey = _a.xAxisKey, series = _a.series, title = _a.title, value = _a.value, trend = _a.trend, _b = _a.height, height = _b === void 0 ? 200 : _b, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.wrappedInCard, wrappedInCard = _d === void 0 ? false : _d, formatTooltipValue = _a.formatTooltipValue, _e = _a.yAxisDomain, yAxisDomain = _e === void 0 ? [0, "dataMax + 100"] : _e, _f = _a.xAxisInterval, xAxisInterval = _f === void 0 ? "preserveStartEnd" : _f;
586
604
  var hasHeader = title != null || value != null || trend != null || series.length > 0;
587
- var content = (jsxs(Fragment, { children: [hasHeader && (jsxs("div", { className: "flex items-start justify-between mb-6", children: [jsxs("div", { children: [title != null && (jsx(H3, { className: "text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1", children: title })), value != null && (jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: "text-2xl font-bold text-gray-900", children: value }), trend != null && (jsx("span", { className: "text-xs font-medium text-yellow-600 bg-yellow-50 px-2 py-1 rounded", children: trend }))] }))] }), series.length > 0 && (jsx("div", { className: "flex flex-wrap items-center gap-4", children: series.map(function (s) { return (jsxs("div", { className: "flex items-center gap-2", children: [jsx("svg", { width: "16", height: "2", viewBox: "0 0 16 2", fill: "none", children: jsx("line", { x1: "0", y1: "1", x2: "16", y2: "1", stroke: s.color, strokeWidth: "2" }) }), jsx("span", { className: "text-xs text-gray-600 font-medium", children: s.label })] }, s.dataKey)); }) }))] })), jsx("div", { className: "w-full", style: { height: "".concat(height, "px") }, children: jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsxs(LineChart, { data: data, margin: { top: 5, right: 5, left: 5, bottom: 5 }, children: [jsx("defs", { children: series.map(function (s) { return (jsxs("linearGradient", { id: "area-line-chart-".concat(s.dataKey), x1: "0", y1: "0", x2: "0", y2: "1", children: [jsx("stop", { offset: "0%", stopColor: s.color, stopOpacity: 0.3 }), jsx("stop", { offset: "50%", stopColor: s.color, stopOpacity: 0.15 }), jsx("stop", { offset: "100%", stopColor: s.color, stopOpacity: 0 })] }, s.dataKey)); }) }), jsx(XAxis, { dataKey: xAxisKey, axisLine: false, tickLine: false, tick: { fill: "#9ca3af", fontSize: 12 }, dy: 10 }), jsx(YAxis, { axisLine: false, tickLine: false, tick: { fill: "transparent", fontSize: 0 }, width: 0, tickCount: 6, domain: yAxisDomain, allowDecimals: false }), jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#d1d5db", strokeOpacity: 0.5, vertical: false, horizontal: true }), jsx(Tooltip$1, { content: jsx(ChartTooltip, { series: series, formatValue: formatTooltipValue }) }), series.map(function (s) { return (jsx(Area, { type: "natural", dataKey: s.dataKey, stroke: "none", fill: "url(#area-line-chart-".concat(s.dataKey, ")"), animationDuration: 1500, animationEasing: "ease-in-out" }, "area-".concat(s.dataKey))); }), series.map(function (s) { return (jsx(Line, { type: "natural", dataKey: s.dataKey, name: s.dataKey, stroke: s.color, strokeWidth: 3, dot: false, activeDot: {
605
+ var content = (jsxs(Fragment, { children: [hasHeader && (jsxs("div", { className: "flex items-start justify-between mb-6", children: [jsxs("div", { children: [title != null && (jsx(H3, { className: "text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1", children: title })), value != null && (jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: "text-2xl font-bold text-gray-900", children: value }), trend != null && (jsx("span", { className: "text-xs font-medium text-yellow-600 bg-yellow-50 px-2 py-1 rounded", children: trend }))] }))] }), series.length > 0 && (jsx("div", { className: "flex flex-wrap items-center gap-4", children: series.map(function (s) { return (jsxs("div", { className: "flex items-center gap-2", children: [jsx("svg", { width: "16", height: "2", viewBox: "0 0 16 2", fill: "none", children: jsx("line", { x1: "0", y1: "1", x2: "16", y2: "1", stroke: s.color, strokeWidth: "2" }) }), jsx("span", { className: "text-xs text-gray-600 font-medium", children: s.label })] }, s.dataKey)); }) }))] })), jsx("div", { className: "w-full", style: { height: "".concat(height, "px") }, children: jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsxs(LineChart, { data: data, margin: { top: 5, right: 5, left: 5, bottom: 5 }, children: [jsx("defs", { children: series.map(function (s) { return (jsxs("linearGradient", { id: "area-line-chart-".concat(s.dataKey), x1: "0", y1: "0", x2: "0", y2: "1", children: [jsx("stop", { offset: "0%", stopColor: s.color, stopOpacity: 0.3 }), jsx("stop", { offset: "50%", stopColor: s.color, stopOpacity: 0.15 }), jsx("stop", { offset: "100%", stopColor: s.color, stopOpacity: 0 })] }, s.dataKey)); }) }), jsx(XAxis, { dataKey: xAxisKey, axisLine: false, tickLine: false, tick: { fill: "#9ca3af", fontSize: 12 }, dy: 10, interval: xAxisInterval }), jsx(YAxis, { axisLine: false, tickLine: false, tick: { fill: "transparent", fontSize: 0 }, width: 0, tickCount: 6, domain: yAxisDomain, allowDecimals: false }), jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#d1d5db", strokeOpacity: 0.5, vertical: false, horizontal: true }), jsx(Tooltip$1, { content: jsx(ChartTooltip, { series: series, formatValue: formatTooltipValue }) }), series.map(function (s) { return (jsx(Area, { type: "natural", dataKey: s.dataKey, stroke: "none", fill: "url(#area-line-chart-".concat(s.dataKey, ")"), animationDuration: 1500, animationEasing: "ease-in-out" }, "area-".concat(s.dataKey))); }), series.map(function (s) { return (jsx(Line, { type: "natural", dataKey: s.dataKey, name: s.dataKey, stroke: s.color, strokeWidth: 3, dot: false, activeDot: {
588
606
  r: 6,
589
607
  fill: s.color,
590
608
  stroke: "#fff",
@@ -2968,6 +2986,20 @@ function computeTotal(data) {
2968
2986
  function isDonutEmpty(data) {
2969
2987
  return data.length === 0 || computeTotal(data) === 0;
2970
2988
  }
2989
+ /**
2990
+ * Formatea `percent` (0-1) como entero + "%", excepto cuando la porción es
2991
+ * real (>0) pero redondea a 0 — ahí muestra "<1%" en vez de "0%", que se lee
2992
+ * como "no hay nada" y confunde cuando sí hay dato (ej. 4 de 2357 = 0.17%).
2993
+ * `lessThanOneLabel` permite traducir el texto (ver `DonutChartTranslations`).
2994
+ */
2995
+ function formatDonutPercent(percent, lessThanOneLabel) {
2996
+ if (lessThanOneLabel === void 0) { lessThanOneLabel = "<1%"; }
2997
+ if (!Number.isFinite(percent) || percent <= 0) {
2998
+ return "0%";
2999
+ }
3000
+ var rounded = Math.round(percent * 100);
3001
+ return rounded === 0 ? lessThanOneLabel : "".concat(rounded, "%");
3002
+ }
2971
3003
  /**
2972
3004
  * Resuelve las proporciones y el color final de cada categoría.
2973
3005
  * El color propio de cada dato tiene prioridad; si falta, se cicla `palette` por índice.
@@ -2985,6 +3017,7 @@ function computeSlices(data, palette) {
2985
3017
  var DEFAULT_TRANSLATIONS$b = {
2986
3018
  emptyState: "Sin datos para mostrar",
2987
3019
  totalLabel: "Total",
3020
+ lessThanOnePercent: "<1%",
2988
3021
  };
2989
3022
  /**
2990
3023
  * DonutChart - Gráfico circular (pie o donut, según `innerRadiusRatio`) con
@@ -3003,7 +3036,7 @@ var DonutChart = function (_a) {
3003
3036
  return formatValue ? formatValue(value) : String(value);
3004
3037
  };
3005
3038
  var isDonut = innerRadiusRatio > 0;
3006
- return (jsxs("div", { className: className, children: [jsxs("div", { className: "relative w-full", style: { height: height }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsxs(PieChart, { children: [jsx(Pie, { data: slices, dataKey: "value", nameKey: "name", innerRadius: isDonut ? "".concat(innerRadiusRatio * 100, "%") : 0, outerRadius: "90%", stroke: "none", children: slices.map(function (slice) { return (jsx(Cell, { fill: slice.color }, slice.name)); }) }), jsx(Tooltip$1, { formatter: function (value) { return format(value); } })] }) }), isDonut && showTotal && (jsxs("div", { className: "aurora-donut-total pointer-events-none absolute inset-0 flex flex-col items-center justify-center", "aria-hidden": "true", children: [jsx("span", { className: "text-xs text-foreground-500", children: t.totalLabel }), jsx("span", { className: "text-xl font-semibold", children: format(total) })] }))] }), showLegend && (jsx("ul", { className: "mt-3 flex flex-wrap gap-3", children: slices.map(function (slice) { return (jsxs("li", { className: "flex items-center gap-1.5 text-xs", children: [jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: slice.color }, "aria-hidden": "true" }), jsx("span", { children: slice.name }), jsxs("span", { className: "text-foreground-500", children: [Math.round(slice.percent * 100), "%"] })] }, slice.name)); }) }))] }));
3039
+ return (jsxs("div", { className: className, children: [jsxs("div", { className: "relative w-full", style: { height: height }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsxs(PieChart, { children: [jsx(Pie, { data: slices, dataKey: "value", nameKey: "name", innerRadius: isDonut ? "".concat(innerRadiusRatio * 100, "%") : 0, outerRadius: "90%", stroke: "none", children: slices.map(function (slice) { return (jsx(Cell, { fill: slice.color }, slice.name)); }) }), jsx(Tooltip$1, { formatter: function (value) { return format(value); } })] }) }), isDonut && showTotal && (jsxs("div", { className: "aurora-donut-total pointer-events-none absolute inset-0 flex flex-col items-center justify-center", "aria-hidden": "true", children: [jsx("span", { className: "text-xs text-foreground-500", children: t.totalLabel }), jsx("span", { className: "text-xl font-semibold", children: format(total) })] }))] }), showLegend && (jsx("ul", { className: "mt-3 flex flex-wrap gap-3", children: slices.map(function (slice) { return (jsxs("li", { className: "flex items-center gap-1.5 text-xs", children: [jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: slice.color }, "aria-hidden": "true" }), jsx("span", { children: slice.name }), jsx("span", { className: "text-foreground-500", children: formatDonutPercent(slice.percent, t.lessThanOnePercent) })] }, slice.name)); }) }))] }));
3007
3040
  };
3008
3041
 
3009
3042
  var H1 = function (_a) {
@@ -4465,13 +4498,6 @@ var Phone = function (_a) {
4465
4498
  document.removeEventListener("mousedown", handleClickOutside);
4466
4499
  };
4467
4500
  }, [isDropdownOpen]);
4468
- // El dropdown se portea a `body` con posición absoluta fija; cerrarlo cuando
4469
- // un ancestro hace scroll para que no quede flotando fuera de lugar.
4470
- useCloseOnAncestorScroll({
4471
- isOpen: isDropdownOpen,
4472
- onClose: function () { return setIsDropdownOpen(false); },
4473
- contentRef: portalDropdownRef,
4474
- });
4475
4501
  var handleCountrySelect = function (country) {
4476
4502
  setSelectedCountry(country);
4477
4503
  setIsDropdownOpen(false);
@@ -9645,6 +9671,127 @@ function removeCustomPrimaryColor() {
9645
9671
  }
9646
9672
  }
9647
9673
 
9674
+ /**
9675
+ * Los tres tonos del aura de Linda, derivados del `primary` de la agencia.
9676
+ *
9677
+ * Linda no tiene color propio: es el `primary` que el negocio eligió en el onboarding,
9678
+ * y por eso aquí no hay ni un color escrito. Lo único que se fija es CUÁNTO se gira ese
9679
+ * tono y en qué banda de luz se pinta.
9680
+ */
9681
+ /**
9682
+ * Grados que se gira el `primary` para cada tono, en el orden en que se pintan.
9683
+ *
9684
+ * Son muchos grados a propósito. La gracia del aura es que haya MÁS DE UN COLOR: con
9685
+ * un giro discreto —del orden de 18°, el que usa un degradado de profundidad— salen
9686
+ * tres versiones del mismo tono y el resultado se lee como un plano. A ±55° el salto
9687
+ * se ve como otro color y sigue dentro de la familia del `primary`, que es lo que
9688
+ * permite que esto funcione con la agencia número siete sin tocar nada.
9689
+ *
9690
+ * El tono del medio va casi sin girar: es el que ancla el conjunto al color de la
9691
+ * agencia, para que el aura se lea como suya y no como una decoración pegada encima.
9692
+ */
9693
+ var GIROS = [-56, 8, 54];
9694
+ /**
9695
+ * Banda de luz en la que se pintan los tres tonos, en porcentaje HSL.
9696
+ *
9697
+ * Los tonos NO heredan la luz del `primary`, y esto es lo que más se nota: un primary
9698
+ * oscuro y poco saturado sobre una superficie clara se lee como una mancha gris —sucia,
9699
+ * no como color—, y uno casi blanco desaparece contra el fondo. Se llevan al paso medio
9700
+ * de la escala, que es el que funciona en los dos casos.
9701
+ */
9702
+ var BANDA_LUZ = { min: 52, max: 72 };
9703
+ /**
9704
+ * Banda de saturación de los tres tonos, en porcentaje HSL.
9705
+ *
9706
+ * El techo es lo que evita que el aura grite. A plena saturación los tonos dejan de ser
9707
+ * ambiente y pasan a ser tres focos de color encima de un control de 40 pt: bonito en
9708
+ * una captura, insoportable en una barra que se mira todo el día.
9709
+ *
9710
+ * ⚠️ **Y hay una razón que no es estética.** Girar el tono puede caer en un rojo vivo:
9711
+ * un `primary` amarillo —51°— girado −56° aterriza en 355°, que a saturación 100 se lee
9712
+ * como un estado de error alrededor de un botón que no ha fallado. Visto al renderizarlo,
9713
+ * no razonándolo. Bajado a 65 el mismo tono es un rosa apagado y vuelve a leerse como lo
9714
+ * que es: decoración.
9715
+ *
9716
+ * El suelo existe por lo contrario: un `primary` casi gris da tres tonos que no se
9717
+ * distinguen entre sí, y entonces no hay degradado que ver —el aura se lee como una
9718
+ * mancha plana—.
9719
+ */
9720
+ var BANDA_SATURACION = { min: 35, max: 65 };
9721
+ var VUELTA = 360;
9722
+ /** `H S% L%` — el formato exacto en el que HeroUI guarda sus variables de color. */
9723
+ var TRIPLETE = /^\s*(-?\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)%\s+(\d+(?:\.\d+)?)%\s*$/;
9724
+ /**
9725
+ * Lee el triplete que HeroUI deja en una variable de color.
9726
+ *
9727
+ * Devuelve `null` en vez de lanzar: esto corre en un efecto de tema y el valor puede
9728
+ * no estar todavía —la clase del tema aún no está en el `<html>`, o el consumidor no
9729
+ * cargó la hoja de estilos—. Un aura que no se pinta es un problema menor; una
9730
+ * excepción que tumba el provider de tema, no.
9731
+ */
9732
+ function parseHslTriplet(value) {
9733
+ var encontrado = TRIPLETE.exec(value);
9734
+ if (!encontrado) {
9735
+ return null;
9736
+ }
9737
+ var h = encontrado[1], s = encontrado[2], l = encontrado[3];
9738
+ return { h: Number(h), s: Number(s), l: Number(l) };
9739
+ }
9740
+ /** Deja un ángulo dentro de `[0, 360)`, venga de donde venga. */
9741
+ function normalizarTono(grados) {
9742
+ return ((grados % VUELTA) + VUELTA) % VUELTA;
9743
+ }
9744
+ function acotar(valor, min, max) {
9745
+ return Math.min(Math.max(valor, min), max);
9746
+ }
9747
+ /**
9748
+ * Los tres tonos del aura, listos para escribirse en una variable CSS.
9749
+ *
9750
+ * Se redondean a entero: es un degradado decorativo, y las décimas de grado solo
9751
+ * alargan la hoja de estilos.
9752
+ */
9753
+ function deriveLindaTones(primary) {
9754
+ var luz = Math.round(acotar(primary.l, BANDA_LUZ.min, BANDA_LUZ.max));
9755
+ var saturacion = Math.round(acotar(primary.s, BANDA_SATURACION.min, BANDA_SATURACION.max));
9756
+ var tonos = GIROS.map(function (giro) {
9757
+ return "".concat(Math.round(normalizarTono(primary.h + giro)), " ").concat(saturacion, "% ").concat(luz, "%");
9758
+ });
9759
+ return tonos;
9760
+ }
9761
+ /** Las variables que se escriben en el `<html>`, en el orden en que se pintan. */
9762
+ var LINDA_TONE_PROPERTIES = [
9763
+ "--linda-1",
9764
+ "--linda-2",
9765
+ "--linda-3",
9766
+ ];
9767
+ /**
9768
+ * Escribe los tres tonos del aura a partir del valor de `--heroui-primary`.
9769
+ *
9770
+ * Si el primary no se puede leer, **borra los que hubiera** y devuelve `false`. Es lo
9771
+ * contrario de dejarlos: unos tonos viejos son de otro tema, y un aura del color
9772
+ * anterior es peor que un aura que no se pinta —la CSS del efecto ya está escrita para
9773
+ * desaparecer sin sus variables—.
9774
+ */
9775
+ function applyLindaTones(style, primaryValue) {
9776
+ var primary = parseHslTriplet(primaryValue);
9777
+ if (!primary) {
9778
+ removeLindaTones(style);
9779
+ return false;
9780
+ }
9781
+ var tonos = deriveLindaTones(primary);
9782
+ LINDA_TONE_PROPERTIES.forEach(function (propiedad, indice) {
9783
+ style.setProperty(propiedad, tonos[indice]);
9784
+ });
9785
+ return true;
9786
+ }
9787
+ /** Quita los tres tonos del aura. */
9788
+ function removeLindaTones(style) {
9789
+ for (var _i = 0, LINDA_TONE_PROPERTIES_1 = LINDA_TONE_PROPERTIES; _i < LINDA_TONE_PROPERTIES_1.length; _i++) {
9790
+ var propiedad = LINDA_TONE_PROPERTIES_1[_i];
9791
+ style.removeProperty(propiedad);
9792
+ }
9793
+ }
9794
+
9648
9795
  /**
9649
9796
  * Custom hook to manage the theme state and side effects.
9650
9797
  * Supports both named ThemeColor values and arbitrary hex colors.
@@ -9690,6 +9837,30 @@ var useThemeManager = function () {
9690
9837
  removeCustomPrimaryColor();
9691
9838
  }
9692
9839
  }, [customHex, mode]);
9840
+ /*
9841
+ * Los tres tonos del aura de Linda, derivados del primary que acaba de quedar fijado.
9842
+ *
9843
+ * Va DESPUÉS de los dos efectos de arriba y depende de lo mismo que ellos, que es lo
9844
+ * que garantiza que lea el primary definitivo: React ejecuta los efectos en orden de
9845
+ * declaración, así que aquí la clase del tema ya está en el `<html>` y el hex a medida
9846
+ * ya está escrito o retirado.
9847
+ *
9848
+ * Se lee del estilo COMPUTADO y no de `customHex` a propósito: el primary llega por
9849
+ * dos caminos —el hex del negocio o la clase de una de las familias de tema— y el
9850
+ * computado es el único sitio donde los dos han convergido. Derivarlo solo de
9851
+ * `customHex` dejaría sin aura a toda agencia que use una familia tal cual.
9852
+ */
9853
+ /*
9854
+ * `customHex` y `rawTheme` están en la lista aunque el cuerpo no los lea: son la señal
9855
+ * de que el `<html>` acaba de cambiar. La entrada real de este efecto es el estilo
9856
+ * computado, que la regla no puede ver, y sin ellos el aura se quedaría con los tonos
9857
+ * del tema anterior.
9858
+ */
9859
+ // biome-ignore lint/correctness/useExhaustiveDependencies: ver el comentario de arriba
9860
+ useEffect(function () {
9861
+ var html = document.documentElement;
9862
+ applyLindaTones(html.style, getComputedStyle(html).getPropertyValue("--heroui-primary"));
9863
+ }, [customHex, rawTheme]);
9693
9864
  var setMode = useCallback(function (newMode) {
9694
9865
  var effectiveMode = newMode === "dark" ? "light" : newMode;
9695
9866
  var newTheme = color === "blue" ? effectiveMode : "".concat(color, "-").concat(effectiveMode);
@@ -9811,4 +9982,4 @@ var NavigationLoadingProvider = function (_a) {
9811
9982
  return (jsxs(NavigationLoadingContext.Provider, { value: value, children: [children, jsx(NavigationLoadingOverlay, { isVisible: isVisible })] }));
9812
9983
  };
9813
9984
 
9814
- export { ALL_THEMES, AURORA_THEME_FAMILIES, AURORA_THEME_REGISTRY, AccordionList, AddHolidayForm, AnalyticsCard, AreaLineChart, AuraAutocomplete, AuraTable, AuraToastProvider, BEWEOS_THEME_MODE_COOKIE_NAME, BreadcrumbsComponent, Button, CONTAINER_ATTRIBUTE, Card, Chip, ColorPicker, ColorSelector, ContentCarousel, Currency, DEFAULT_DONUT_COLORS, DEFAULT_PREDEFINED_COLORS, DEFAULT_RANKED_BAR_COLORS, DISMISS_CONTROL_ATTRIBUTE, DatePicker, DateRangePicker, DateSelector, DonutChart, DrawerFilters, EmailPreview, EnumMenuNavListItem, GlobalToast, H1, H2, H3, H4, HeaderComponent, HolidayType, IconComponent, ImagePreview, Input, InputPassword, Kanban, KanbanCard, KanbanColumn, LindaIcon, MenuClaw, MenuComponent, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, MultiStepWizard, NavigationLoadingContext, NavigationLoadingOverlay, NavigationLoadingProvider, P, Pagination, Phone, PromotionalBanner, REGISTERED_THEME_COLORS, RangeFilter, RankedBarList, RowSteps, DEFAULT_TRANSLATIONS$1 as SEGMENTATION_DEFAULT_TRANSLATIONS, ScheduleRow, SearchInput, SegmentationBuilder, Select, SimpleLineChart, SocialMediaBar, SocialMediaCarousel, SocialMediaPreview, StatTile, StepIndicator, Switch as SwitchComponent, THEME_COLOR_HEX_MAP, TagsFilter, Textarea, ThemeContext, ThemePicker, ThemeProvider, TimeInput as TimeInputComponent, ToastContext, Tooltip, TwoColumnLayoutAgent, UploadFile, VerticalSteps, ViolinPlot, WhatsAppPreview, Wizard, WizardNavigation, WizardSidebar, applyCustomPrimaryColor, computeBars, computeMax, computeSlices, computeTotal, containerProps, createCurrencyFormatter, uniqueCountries as defaultCountries, defaultCurrencyOptions, defaultTranslations$5 as defaultTranslations, dismissControlProps, forceLightOnlyThemeBeforeReact, formatAuroraThemeTooltip, generateThemeColorScale, getContrastForeground, getRegisteredThemeColorBases, getSelectedKeyFromPath, hexToThemeColor, hslToCssValue, isAuroraFullThemeId, isDismissControl, isDonutEmpty, isExactThemeColor, isGroupState, isHexColor, isRankedBarListEmpty, isSegmentationGroup, removeCustomPrimaryColor, shouldClosePopoverOnInteractOutside, sizeMap, themeColors, useAuraToast, useCloseOnAncestorScroll, useMediaQuery, useNavigationLoading, useThemeContext };
9985
+ export { ALL_THEMES, AURORA_THEME_FAMILIES, AURORA_THEME_REGISTRY, AccordionList, AddHolidayForm, AnalyticsCard, AreaLineChart, AuraAutocomplete, AuraTable, AuraToastProvider, BEWEOS_THEME_MODE_COOKIE_NAME, BreadcrumbsComponent, Button, CONTAINER_ATTRIBUTE, Card, Chip, ColorPicker, ColorSelector, ContentCarousel, Currency, DEFAULT_DONUT_COLORS, DEFAULT_PREDEFINED_COLORS, DEFAULT_RANKED_BAR_COLORS, DISMISS_CONTROL_ATTRIBUTE, DatePicker, DateRangePicker, DateSelector, DonutChart, DrawerFilters, EmailPreview, EnumMenuNavListItem, GlobalToast, H1, H2, H3, H4, HeaderComponent, HolidayType, IconComponent, ImagePreview, Input, InputPassword, Kanban, KanbanCard, KanbanColumn, LINDA_TONE_PROPERTIES, LindaIcon, MenuClaw, MenuComponent, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, MultiStepWizard, NavigationLoadingContext, NavigationLoadingOverlay, NavigationLoadingProvider, P, Pagination, Phone, PromotionalBanner, REGISTERED_THEME_COLORS, RangeFilter, RankedBarList, RowSteps, DEFAULT_TRANSLATIONS$1 as SEGMENTATION_DEFAULT_TRANSLATIONS, ScheduleRow, SearchInput, SegmentationBuilder, Select, SimpleLineChart, SocialMediaBar, SocialMediaCarousel, SocialMediaPreview, StatTile, StepIndicator, Switch as SwitchComponent, THEME_COLOR_HEX_MAP, TagsFilter, Textarea, ThemeContext, ThemePicker, ThemeProvider, TimeInput as TimeInputComponent, ToastContext, Tooltip, TwoColumnLayoutAgent, UploadFile, VerticalSteps, ViolinPlot, WhatsAppPreview, Wizard, WizardNavigation, WizardSidebar, applyCustomPrimaryColor, applyLindaTones, computeBars, computeMax, computeSlices, computeTotal, containerProps, createCurrencyFormatter, uniqueCountries as defaultCountries, defaultCurrencyOptions, defaultTranslations$5 as defaultTranslations, deriveLindaTones, dismissControlProps, forceLightOnlyThemeBeforeReact, formatAuroraThemeTooltip, formatDonutPercent, generateThemeColorScale, getContrastForeground, getRegisteredThemeColorBases, getSelectedKeyFromPath, hexToThemeColor, hslToCssValue, isAuroraFullThemeId, isDismissControl, isDonutEmpty, isExactThemeColor, isGroupState, isHexColor, isRankedBarListEmpty, isSegmentationGroup, parseHslTriplet, removeCustomPrimaryColor, removeLindaTones, shouldClosePopoverOnInteractOutside, sizeMap, themeColors, useAuraToast, useCloseOnAncestorScroll, useMediaQuery, useNavigationLoading, useThemeContext };
@@ -1,3 +1,3 @@
1
1
  import type { AreaLineChartProps } from "./AreaLineChart.types";
2
- export declare function AreaLineChart<T extends Record<string, unknown>>({ data, xAxisKey, series, title, value, trend, height, className, wrappedInCard, formatTooltipValue, yAxisDomain, }: AreaLineChartProps<T>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function AreaLineChart<T extends Record<string, unknown>>({ data, xAxisKey, series, title, value, trend, height, className, wrappedInCard, formatTooltipValue, yAxisDomain, xAxisInterval, }: AreaLineChartProps<T>): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=AreaLineChart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AreaLineChart.d.ts","sourceRoot":"","sources":["../../../../src/components/area-line-chart/AreaLineChart.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,uBAAuB,CAAC;AAgD/B,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAChE,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAY,EACZ,SAAc,EACd,aAAqB,EACrB,kBAAkB,EAClB,WAAkC,GAClC,EAAE,kBAAkB,CAAC,CAAC,CAAC,2CAoJvB"}
1
+ {"version":3,"file":"AreaLineChart.d.ts","sourceRoot":"","sources":["../../../../src/components/area-line-chart/AreaLineChart.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,uBAAuB,CAAC;AAgD/B,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAChE,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAY,EACZ,SAAc,EACd,aAAqB,EACrB,kBAAkB,EAClB,WAAkC,EAClC,aAAkC,GAClC,EAAE,kBAAkB,CAAC,CAAC,CAAC,2CAqJvB"}
@@ -35,5 +35,17 @@ export interface AreaLineChartProps<T extends Record<string, unknown> = Record<s
35
35
  * corresponde a quien consume el componente, no a AreaLineChart.
36
36
  */
37
37
  yAxisDomain?: [number | string, number | string];
38
+ /**
39
+ * Estrategia de Recharts para decidir qué ticks del eje X pintar cuando no
40
+ * caben todos. `0` fuerza a pintar cada punto de `data` sin saltar
41
+ * ninguno — correcto para pocos puntos con labels cortos (ej. una
42
+ * tendencia mensual de 8-12 meses), pero con muchos puntos o labels
43
+ * largos los ticks se solapan (Recharts no rota ni elide con `interval={0}`,
44
+ * y `minTickGap` queda inoperante). Igual que `yAxisDomain`, esa
45
+ * decisión le corresponde a quien consume el componente según su dataset,
46
+ * no a `AreaLineChart`.
47
+ * @default "preserveStartEnd" — garantiza el primer y el último tick sin solapar
48
+ */
49
+ xAxisInterval?: number | "preserveStart" | "preserveEnd" | "preserveStartEnd";
38
50
  }
39
51
  //# sourceMappingURL=AreaLineChart.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AreaLineChart.types.d.ts","sourceRoot":"","sources":["../../../../src/components/area-line-chart/AreaLineChart.types.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,WAAW,yBAAyB;IACzC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB,CAClC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,gFAAgF;IAChF,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACpC,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAChE;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACjD"}
1
+ {"version":3,"file":"AreaLineChart.types.d.ts","sourceRoot":"","sources":["../../../../src/components/area-line-chart/AreaLineChart.types.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,WAAW,yBAAyB;IACzC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB,CAClC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,gFAAgF;IAChF,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACpC,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAChE;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACjD;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,aAAa,GAAG,kBAAkB,CAAC;CAC9E"}