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

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 (34) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +364 -109
  3. package/dist/index.esm.js +357 -110
  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/autocomplete/AutoComplete.d.ts +16 -0
  9. package/dist/types/components/autocomplete/AutoComplete.d.ts.map +1 -1
  10. package/dist/types/components/autocomplete/AutoComplete.types.d.ts +12 -0
  11. package/dist/types/components/autocomplete/AutoComplete.types.d.ts.map +1 -1
  12. package/dist/types/components/button/Button.d.ts +1 -0
  13. package/dist/types/components/button/Button.d.ts.map +1 -1
  14. package/dist/types/components/button/Button.types.d.ts +15 -0
  15. package/dist/types/components/button/Button.types.d.ts.map +1 -1
  16. package/dist/types/components/donut-chart/DonutChart.d.ts.map +1 -1
  17. package/dist/types/components/donut-chart/DonutChart.types.d.ts +2 -0
  18. package/dist/types/components/donut-chart/DonutChart.types.d.ts.map +1 -1
  19. package/dist/types/components/donut-chart/donut-chart.utils.d.ts +7 -0
  20. package/dist/types/components/donut-chart/donut-chart.utils.d.ts.map +1 -1
  21. package/dist/types/components/donut-chart/index.d.ts +1 -1
  22. package/dist/types/components/donut-chart/index.d.ts.map +1 -1
  23. package/dist/types/components/phone/Phone.d.ts.map +1 -1
  24. package/dist/types/components/tags-filter/TagsFilter.d.ts.map +1 -1
  25. package/dist/types/index.d.ts +1 -0
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/providers/theme/index.d.ts +1 -0
  28. package/dist/types/providers/theme/index.d.ts.map +1 -1
  29. package/dist/types/providers/theme/linda-tones.d.ts +53 -0
  30. package/dist/types/providers/theme/linda-tones.d.ts.map +1 -0
  31. package/dist/types/providers/theme/useThemeManager.d.ts.map +1 -1
  32. package/dist/types/utils/dismiss-control.d.ts +47 -1
  33. package/dist/types/utils/dismiss-control.d.ts.map +1 -1
  34. package/package.json +1 -1
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",
@@ -596,6 +614,139 @@ function AreaLineChart(_a) {
596
614
  return jsx("div", { className: className, children: content });
597
615
  }
598
616
 
617
+ /**
618
+ * Interacciones que un popover no-modal NO debe tratar como "clic fuera".
619
+ *
620
+ * El problema que resuelve: `useOverlay` de react-aria trata cualquier
621
+ * pulsación fuera del popover como interacción externa y, cuando el popover es
622
+ * el overlay visible más reciente, hace `stopPropagation()` + `preventDefault()`
623
+ * sobre el `pointerdown` **y** sobre el `click`
624
+ * (`@react-aria/overlays/useOverlay`). El evento nunca llega a su destino, así
625
+ * que `usePress` no registra la pulsación y `onPress` no se dispara: el primer
626
+ * clic solo cierra el desplegable.
627
+ *
628
+ * Para un clic en la página de fondo eso es lo correcto: descartar el
629
+ * desplegable sin activar nada por debajo. Dentro del mismo diálogo no: ahí el
630
+ * usuario está rellenando un formulario y espera que su clic llegue. Y como los
631
+ * buscadores se reabren al recuperar el foco, el clic siguiente se volvía a
632
+ * tragar — un callejón sin salida del que solo se salía vaciando el campo.
633
+ *
634
+ * La única palanca es `shouldCloseOnInteractOutside`: es el guardián de esos dos
635
+ * `preventDefault`. Devolviendo `false` para lo que no es realmente "fuera", la
636
+ * pulsación llega intacta. El desplegable sigue cerrándose igual, pero por
637
+ * pérdida de foco (`shouldCloseOnBlur`) en vez de por interacción externa.
638
+ */
639
+ var _a, _b;
640
+ /**
641
+ * Marca un botón como control de cierre de su contenedor. Los popovers de Aura
642
+ * no lo cuentan como interacción externa, así que su pulsación no se pierde.
643
+ */
644
+ var DISMISS_CONTROL_ATTRIBUTE = "data-aura-dismiss";
645
+ /** Props a esparcir en un control de cierre: `<Button {...dismissControlProps} />`. */
646
+ var dismissControlProps = (_a = {},
647
+ _a[DISMISS_CONTROL_ATTRIBUTE] = "true",
648
+ _a);
649
+ /**
650
+ * Marca el contenedor de una superficie modal propia (wizard, panel a medida).
651
+ * No hace falta en `Modal` ni `Drawer`: los diálogos de HeroUI ya traen
652
+ * `role="dialog"`, que cuenta igual.
653
+ */
654
+ var CONTAINER_ATTRIBUTE = "data-aura-container";
655
+ /** Props a esparcir en el contenedor: `<div {...containerProps}>`. */
656
+ var containerProps = (_b = {},
657
+ _b[CONTAINER_ATTRIBUTE] = "true",
658
+ _b);
659
+ /**
660
+ * Selector de controles de cierre. Incluye `[aria-label="Close"]` para cubrir
661
+ * los botones de cerrar internos de HeroUI (Modal, Drawer), que no admiten
662
+ * atributos propios.
663
+ */
664
+ var DISMISS_CONTROL_SELECTOR = "[".concat(DISMISS_CONTROL_ATTRIBUTE, "],[aria-label=\"Close\"]");
665
+ /** Selector del contenedor modal: el marcado de Aura o un diálogo estándar. */
666
+ var CONTAINER_SELECTOR = "[".concat(CONTAINER_ATTRIBUTE, "],[role=\"dialog\"],[role=\"alertdialog\"]");
667
+ var matchesAncestor = function (element, selector) {
668
+ if (!element || typeof element.closest !== "function") {
669
+ return false;
670
+ }
671
+ return element.closest(selector) != null;
672
+ };
673
+ /** `true` si el elemento es un control de cierre (o está dentro de uno). */
674
+ var isDismissControl = function (element) { return matchesAncestor(element, DISMISS_CONTROL_SELECTOR); };
675
+ /**
676
+ * `true` si el elemento vive dentro de una superficie modal: un diálogo estándar
677
+ * o un contenedor marcado con `containerProps`.
678
+ *
679
+ * Es la condición que decide si un componente con popover no-modal necesita el
680
+ * predicado de más abajo. Fuera de una superficie así, HeroUI ya resuelve el
681
+ * caso por su cuenta (`ariaShouldCloseOnInteractOutside` cierra el desplegable
682
+ * y devuelve `false`, de modo que la pulsación llega a su destino); solo falla
683
+ * cuando hay un diálogo de por medio, y ahí entra el nuestro.
684
+ */
685
+ var isInsideDismissContainer = function (element) { return matchesAncestor(element, CONTAINER_SELECTOR); };
686
+ /**
687
+ * Predicado listo para `popoverProps.shouldCloseOnInteractOutside` de un
688
+ * componente con popover no-modal.
689
+ *
690
+ * Devuelve `false` —no es interacción externa— en tres casos:
691
+ *
692
+ * 1. Dentro del propio componente: el popover vive en un portal, así que el
693
+ * campo de búsqueda queda fuera de él y una pulsación sobre el texto se
694
+ * contaba como externa.
695
+ * 2. Sobre un control de cierre del contenedor propio.
696
+ * 3. Dentro del mismo diálogo/contenedor que el componente: seguir rellenando
697
+ * el formulario no es descartar el desplegable.
698
+ *
699
+ * Las exenciones 2 y 3 se limitan al contenedor del propio componente. Un
700
+ * control de cierre suelto en la página —la X de un toast, la de un banner— no
701
+ * tiene nada que ver con este desplegable, así que sigue contando como externo
702
+ * y lo cierra.
703
+ *
704
+ * @param element Elemento donde ha empezado la interacción.
705
+ * @param root Raíz del componente.
706
+ */
707
+ var shouldClosePopoverOnInteractOutside = function (element, root) {
708
+ var _a;
709
+ if (root === null || root === void 0 ? void 0 : root.contains(element)) {
710
+ return false;
711
+ }
712
+ var container = (_a = root === null || root === void 0 ? void 0 : root.closest) === null || _a === void 0 ? void 0 : _a.call(root, CONTAINER_SELECTOR);
713
+ if (isDismissControl(element)) {
714
+ // Sin contenedor propio no hay a quién eximir: el control de cierre es
715
+ // de otra cosa y su pulsación descarta el desplegable como cualquier otra.
716
+ return container ? !container.contains(element) : true;
717
+ }
718
+ if (!matchesAncestor(element, CONTAINER_SELECTOR)) {
719
+ return true;
720
+ }
721
+ // Solo exime el contenedor propio: un diálogo distinto sigue siendo externo.
722
+ return !(container === null || container === void 0 ? void 0 : container.contains(element));
723
+ };
724
+ /**
725
+ * Mezcla las `popoverProps` de un consumidor con el predicado por defecto, para
726
+ * que un componente con popover no-modal no trate como "clic fuera" lo que no lo
727
+ * es (ver `shouldClosePopoverOnInteractOutside`).
728
+ *
729
+ * Llamar solo cuando el componente está dentro de una superficie modal
730
+ * (`isInsideDismissContainer`). Fuera de ella HeroUI trae su propio default y
731
+ * hay que dejárselo: instalar cualquier predicado lo desactiva, porque su mezcla
732
+ * es por truthiness (`@heroui/autocomplete` → `use-autocomplete`).
733
+ *
734
+ * El consumidor puede sustituir el predicado pasando el suyo — es la salida para
735
+ * casos a medida, no la puerta a `() => true`. Pasar `shouldCloseOnInteractOutside:
736
+ * undefined` NO desactiva el default: para eso hay que pasar un predicado propio.
737
+ *
738
+ * @param popoverProps Las que llegan del consumidor, si las hay.
739
+ * @param getRoot Lector de la raíz del componente. Es una función y no un
740
+ * valor porque el `ref` todavía es `null` en el primer
741
+ * render: hay que leerlo cuando ocurre la interacción.
742
+ */
743
+ var withPopoverDismissDefaults = function (popoverProps, getRoot) {
744
+ var _a;
745
+ return (__assign(__assign({}, popoverProps), { shouldCloseOnInteractOutside: (_a = popoverProps === null || popoverProps === void 0 ? void 0 : popoverProps.shouldCloseOnInteractOutside) !== null && _a !== void 0 ? _a : (function (element) {
746
+ return shouldClosePopoverOnInteractOutside(element, getRoot());
747
+ }) }));
748
+ };
749
+
599
750
  /** Clases del wrapper del icono: margen derecho y alineación igual para lupa e iconos custom */
600
751
  var ICON_WRAPPER_CLASSNAME = "mr-2 flex shrink-0 items-center [&_svg]:shrink-0";
601
752
  var DEFAULT_ICON = (jsx(IconComponent, { icon: "solar:magnifer-outline", className: "text-default-400 pointer-events-none shrink-0", size: "sm", "aria-hidden": true }));
@@ -608,15 +759,39 @@ var DEFAULT_ICON = (jsx(IconComponent, { icon: "solar:magnifer-outline", classNa
608
759
  * - labelPlacement: Outside
609
760
  * - Size: sm, md, lg (configurable)
610
761
  * - Icono: lupa por defecto; acepta prop icon para personalizar u ocultar (null).
762
+ *
763
+ * **Dentro de un modal, drawer o contenedor marcado con `containerProps`**, el
764
+ * desplegable deja de contar como "clic fuera" lo que ocurre dentro del propio
765
+ * componente, sobre un control de cierre del contenedor o dentro de ese mismo
766
+ * contenedor: react-aria hace `preventDefault()` sobre esas pulsaciones y el
767
+ * control de destino nunca llegaba a recibir su `onPress` (ver
768
+ * `shouldClosePopoverOnInteractOutside`). Sigue cerrándose, por la vía del
769
+ * `shouldCloseOnBlur` del combobox de HeroUI — no por `onBlurWithin` del
770
+ * overlay, que está gateado por el mismo predicado.
771
+ *
772
+ * **Fuera de un contenedor así no se instala nada**: HeroUI ya resuelve ese caso
773
+ * con `ariaShouldCloseOnInteractOutside`, y como su mezcla es por truthiness,
774
+ * poner un predicado propio lo desactivaría y volvería a tragarse la pulsación.
775
+ *
776
+ * Un consumidor puede sustituir el predicado con su propio
777
+ * `popoverProps.shouldCloseOnInteractOutside`; entonces manda el suyo siempre.
611
778
  */
612
779
  var AuraAutocomplete = function (_a) {
613
- var label = _a.label, id = _a.id, icon = _a.icon, _b = _a.size, size = _b === void 0 ? "md" : _b, _c = _a.variant, variant = _c === void 0 ? "bordered" : _c, _d = _a.radius, radius = _d === void 0 ? "md" : _d, props = __rest(_a, ["label", "id", "icon", "size", "variant", "radius"]);
780
+ var label = _a.label, id = _a.id, icon = _a.icon, _b = _a.size, size = _b === void 0 ? "md" : _b, _c = _a.variant, variant = _c === void 0 ? "bordered" : _c, _d = _a.radius, radius = _d === void 0 ? "md" : _d, popoverProps = _a.popoverProps, props = __rest(_a, ["label", "id", "icon", "size", "variant", "radius", "popoverProps"]);
614
781
  var generatedId = useId();
782
+ // El desplegable se renderiza en un portal, así que el campo de búsqueda
783
+ // queda fuera de él. Sin esta raíz el predicado no puede distinguir lo que
784
+ // pasa dentro del componente de un clic real de fuera. Se guarda en estado
785
+ // —y no en un ref— porque de ella depende SI se instala el predicado, y eso
786
+ // hay que decidirlo en render: un ref no dispara el re-render que hace falta.
787
+ var _e = useState(null), root = _e[0], setRoot = _e[1];
615
788
  var autoId = id || generatedId;
616
789
  var resolvedIcon = icon === undefined ? DEFAULT_ICON : icon;
617
790
  var hasIcon = resolvedIcon != null;
618
791
  var endContent = hasIcon ? (jsx("span", { className: ICON_WRAPPER_CLASSNAME, children: resolvedIcon })) : null;
619
- return (jsxs("div", { children: [label && (jsx("label", { htmlFor: autoId, className: "block mb-2 text-tiny text-default-600", children: label })), jsx(Autocomplete, __assign({}, props, { id: autoId, label: undefined, labelPlacement: "outside", variant: variant, size: size, radius: radius, endContent: endContent, classNames: __assign({ base: "[&_[data-slot=input-wrapper][data-focus=true]]:!border-primary-500", popoverContent: "aura-popover-content [&_li[data-hover=true]]:!bg-primary-50 [&_li[data-hover=true]]:!text-default-600 [&_li]:!text-default-500" }, (hasIcon && { selectorButton: "!hidden" })) }))] }));
792
+ return (jsxs("div", { ref: setRoot, children: [label && (jsx("label", { htmlFor: autoId, className: "block mb-2 text-tiny text-default-600", children: label })), jsx(Autocomplete, __assign({}, props, { id: autoId, label: undefined, labelPlacement: "outside", variant: variant, size: size, radius: radius, endContent: endContent, popoverProps: isInsideDismissContainer(root)
793
+ ? withPopoverDismissDefaults(popoverProps, function () { return root; })
794
+ : popoverProps, classNames: __assign({ base: "[&_[data-slot=input-wrapper][data-focus=true]]:!border-primary-500", popoverContent: "aura-popover-content [&_li[data-hover=true]]:!bg-primary-50 [&_li[data-hover=true]]:!text-default-600 [&_li]:!text-default-500" }, (hasIcon && { selectorButton: "!hidden" })) }))] }));
620
795
  };
621
796
 
622
797
  /**
@@ -2968,6 +3143,20 @@ function computeTotal(data) {
2968
3143
  function isDonutEmpty(data) {
2969
3144
  return data.length === 0 || computeTotal(data) === 0;
2970
3145
  }
3146
+ /**
3147
+ * Formatea `percent` (0-1) como entero + "%", excepto cuando la porción es
3148
+ * real (>0) pero redondea a 0 — ahí muestra "<1%" en vez de "0%", que se lee
3149
+ * como "no hay nada" y confunde cuando sí hay dato (ej. 4 de 2357 = 0.17%).
3150
+ * `lessThanOneLabel` permite traducir el texto (ver `DonutChartTranslations`).
3151
+ */
3152
+ function formatDonutPercent(percent, lessThanOneLabel) {
3153
+ if (lessThanOneLabel === void 0) { lessThanOneLabel = "<1%"; }
3154
+ if (!Number.isFinite(percent) || percent <= 0) {
3155
+ return "0%";
3156
+ }
3157
+ var rounded = Math.round(percent * 100);
3158
+ return rounded === 0 ? lessThanOneLabel : "".concat(rounded, "%");
3159
+ }
2971
3160
  /**
2972
3161
  * Resuelve las proporciones y el color final de cada categoría.
2973
3162
  * El color propio de cada dato tiene prioridad; si falta, se cicla `palette` por índice.
@@ -2985,6 +3174,7 @@ function computeSlices(data, palette) {
2985
3174
  var DEFAULT_TRANSLATIONS$b = {
2986
3175
  emptyState: "Sin datos para mostrar",
2987
3176
  totalLabel: "Total",
3177
+ lessThanOnePercent: "<1%",
2988
3178
  };
2989
3179
  /**
2990
3180
  * DonutChart - Gráfico circular (pie o donut, según `innerRadiusRatio`) con
@@ -3003,7 +3193,7 @@ var DonutChart = function (_a) {
3003
3193
  return formatValue ? formatValue(value) : String(value);
3004
3194
  };
3005
3195
  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)); }) }))] }));
3196
+ 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
3197
  };
3008
3198
 
3009
3199
  var H1 = function (_a) {
@@ -4021,96 +4211,6 @@ var MenuClaw = React.memo(function MenuClaw(_a) {
4021
4211
  }) }), helpSection ? (jsx("div", { className: "mt-auto flex flex-col items-center justify-center", children: jsx(Button$1, { fullWidth: true, className: "text-default-500 data-[hover=true]:text-default-600", startContent: jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: collapsed, children: !collapsed ? (jsx("span", { className: "menu-claw-collapsible truncate", children: helpSection.title })) : null }) })) : null] }) })] }));
4022
4212
  });
4023
4213
 
4024
- /**
4025
- * Interacciones que un popover no-modal NO debe tratar como "clic fuera".
4026
- *
4027
- * El problema que resuelve: `useOverlay` de react-aria trata cualquier
4028
- * pulsación fuera del popover como interacción externa y, cuando el popover es
4029
- * el overlay visible más reciente, hace `stopPropagation()` + `preventDefault()`
4030
- * sobre el `pointerdown` **y** sobre el `click`
4031
- * (`@react-aria/overlays/useOverlay`). El evento nunca llega a su destino, así
4032
- * que `usePress` no registra la pulsación y `onPress` no se dispara: el primer
4033
- * clic solo cierra el desplegable.
4034
- *
4035
- * Para un clic en la página de fondo eso es lo correcto: descartar el
4036
- * desplegable sin activar nada por debajo. Dentro del mismo diálogo no: ahí el
4037
- * usuario está rellenando un formulario y espera que su clic llegue. Y como los
4038
- * buscadores se reabren al recuperar el foco, el clic siguiente se volvía a
4039
- * tragar — un callejón sin salida del que solo se salía vaciando el campo.
4040
- *
4041
- * La única palanca es `shouldCloseOnInteractOutside`: es el guardián de esos dos
4042
- * `preventDefault`. Devolviendo `false` para lo que no es realmente "fuera", la
4043
- * pulsación llega intacta. El desplegable sigue cerrándose igual, pero por
4044
- * pérdida de foco (`shouldCloseOnBlur`) en vez de por interacción externa.
4045
- */
4046
- var _a, _b;
4047
- /**
4048
- * Marca un botón como control de cierre de su contenedor. Los popovers de Aura
4049
- * no lo cuentan como interacción externa, así que su pulsación no se pierde.
4050
- */
4051
- var DISMISS_CONTROL_ATTRIBUTE = "data-aura-dismiss";
4052
- /** Props a esparcir en un control de cierre: `<Button {...dismissControlProps} />`. */
4053
- var dismissControlProps = (_a = {},
4054
- _a[DISMISS_CONTROL_ATTRIBUTE] = "true",
4055
- _a);
4056
- /**
4057
- * Marca el contenedor de una superficie modal propia (wizard, panel a medida).
4058
- * No hace falta en `Modal` ni `Drawer`: los diálogos de HeroUI ya traen
4059
- * `role="dialog"`, que cuenta igual.
4060
- */
4061
- var CONTAINER_ATTRIBUTE = "data-aura-container";
4062
- /** Props a esparcir en el contenedor: `<div {...containerProps}>`. */
4063
- var containerProps = (_b = {},
4064
- _b[CONTAINER_ATTRIBUTE] = "true",
4065
- _b);
4066
- /**
4067
- * Selector de controles de cierre. Incluye `[aria-label="Close"]` para cubrir
4068
- * los botones de cerrar internos de HeroUI (Modal, Drawer), que no admiten
4069
- * atributos propios.
4070
- */
4071
- var DISMISS_CONTROL_SELECTOR = "[".concat(DISMISS_CONTROL_ATTRIBUTE, "],[aria-label=\"Close\"]");
4072
- /** Selector del contenedor modal: el marcado de Aura o un diálogo estándar. */
4073
- var CONTAINER_SELECTOR = "[".concat(CONTAINER_ATTRIBUTE, "],[role=\"dialog\"],[role=\"alertdialog\"]");
4074
- var matchesAncestor = function (element, selector) {
4075
- if (!element || typeof element.closest !== "function") {
4076
- return false;
4077
- }
4078
- return element.closest(selector) != null;
4079
- };
4080
- /** `true` si el elemento es un control de cierre (o está dentro de uno). */
4081
- var isDismissControl = function (element) { return matchesAncestor(element, DISMISS_CONTROL_SELECTOR); };
4082
- /**
4083
- * Predicado listo para `popoverProps.shouldCloseOnInteractOutside` de un
4084
- * componente con popover no-modal.
4085
- *
4086
- * Devuelve `false` —no es interacción externa— en tres casos:
4087
- *
4088
- * 1. Dentro del propio componente: el popover vive en un portal, así que el
4089
- * campo de búsqueda queda fuera de él y una pulsación sobre el texto se
4090
- * contaba como externa.
4091
- * 2. Sobre un control de cierre del contenedor.
4092
- * 3. Dentro del mismo diálogo/contenedor que el componente: seguir rellenando
4093
- * el formulario no es descartar el desplegable.
4094
- *
4095
- * @param element Elemento donde ha empezado la interacción.
4096
- * @param root Raíz del componente.
4097
- */
4098
- var shouldClosePopoverOnInteractOutside = function (element, root) {
4099
- var _a;
4100
- if (root === null || root === void 0 ? void 0 : root.contains(element)) {
4101
- return false;
4102
- }
4103
- if (isDismissControl(element)) {
4104
- return false;
4105
- }
4106
- if (!matchesAncestor(element, CONTAINER_SELECTOR)) {
4107
- return true;
4108
- }
4109
- // Solo exime el contenedor propio: un diálogo distinto sigue siendo externo.
4110
- var container = (_a = root === null || root === void 0 ? void 0 : root.closest) === null || _a === void 0 ? void 0 : _a.call(root, CONTAINER_SELECTOR);
4111
- return !(container === null || container === void 0 ? void 0 : container.contains(element));
4112
- };
4113
-
4114
4214
  var StepIndicator = function (_a) {
4115
4215
  var currentStep = _a.currentStep, totalSteps = _a.totalSteps, _b = _a.color, color = _b === void 0 ? "primary" : _b, _c = _a.showStepText, showStepText = _c === void 0 ? true : _c, stepTextFormatter = _a.stepTextFormatter, className = _a.className, props = __rest(_a, ["currentStep", "totalSteps", "color", "showStepText", "stepTextFormatter", "className"]);
4116
4216
  var progressPercentage = Math.min((currentStep / totalSteps) * 100, 100);
@@ -4465,13 +4565,6 @@ var Phone = function (_a) {
4465
4565
  document.removeEventListener("mousedown", handleClickOutside);
4466
4566
  };
4467
4567
  }, [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
4568
  var handleCountrySelect = function (country) {
4476
4569
  setSelectedCountry(country);
4477
4570
  setIsDropdownOpen(false);
@@ -8959,7 +9052,9 @@ function TagsFilter(_a) {
8959
9052
  var _m = useState(0), autocompleteKey = _m[0], setAutocompleteKey = _m[1];
8960
9053
  var selectedList = value !== null && value !== void 0 ? value : [];
8961
9054
  var _o = useState(null), sentinelNode = _o[0], setSentinelNode = _o[1];
8962
- var rootRef = useRef(null);
9055
+ // En estado y no en un ref: de la raíz depende SI se instala el predicado
9056
+ // (solo dentro de una superficie modal), y eso se decide en render.
9057
+ var _p = useState(null), root = _p[0], setRoot = _p[1];
8963
9058
  useEffect(function () {
8964
9059
  if (!onLoadMore || !sentinelNode || !hasMore) {
8965
9060
  return;
@@ -9031,7 +9126,7 @@ function TagsFilter(_a) {
9031
9126
  if (isLoading) {
9032
9127
  return (jsx("div", { className: "flex flex-col gap-4 ".concat(className), children: jsx("div", { className: "flex justify-center py-4", children: jsx(Spinner, { size: "sm" }) }) }));
9033
9128
  }
9034
- return (jsxs("div", { ref: rootRef, className: "flex flex-col gap-4 ".concat(className), children: [error && (jsxs("div", { className: "text-danger text-small py-2", children: [t.errorLoadingPrefix, ": ", error] })), !error && (jsxs(Fragment, { children: [jsxs("div", { className: "flex flex-col gap-3", children: [jsxs(H4, { className: "text-tiny text-left text-default-700", children: [t.labelSelect, required && jsx("span", { className: "text-danger ml-0.5", children: "*" })] }), jsx(AuraAutocomplete, { placeholder: t.placeholder, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : t.placeholder, inputValue: inputValue, onInputChange: function (v) {
9129
+ return (jsxs("div", { ref: setRoot, className: "flex flex-col gap-4 ".concat(className), children: [error && (jsxs("div", { className: "text-danger text-small py-2", children: [t.errorLoadingPrefix, ": ", error] })), !error && (jsxs(Fragment, { children: [jsxs("div", { className: "flex flex-col gap-3", children: [jsxs(H4, { className: "text-tiny text-left text-default-700", children: [t.labelSelect, required && jsx("span", { className: "text-danger ml-0.5", children: "*" })] }), jsx(AuraAutocomplete, { placeholder: t.placeholder, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : t.placeholder, inputValue: inputValue, onInputChange: function (v) {
9035
9130
  setInputValue(v);
9036
9131
  onInputChange === null || onInputChange === void 0 ? void 0 : onInputChange(v);
9037
9132
  }, selectedKey: null, items: itemsWithSentinel, onSelectionChange: handleAutocompleteSelection,
@@ -9065,9 +9160,16 @@ function TagsFilter(_a) {
9065
9160
  // click de toda interacción externa, así que su `onPress` no se
9066
9161
  // disparaba y el contenedor no se podía cerrar mientras el
9067
9162
  // desplegable estuviera abierto (ver `shouldClosePopoverOnInteractOutside`).
9068
- shouldCloseOnInteractOutside: function (element) {
9069
- return shouldClosePopoverOnInteractOutside(element, rootRef.current);
9070
- },
9163
+ //
9164
+ // Solo dentro de una superficie modal: fuera de ella HeroUI ya
9165
+ // resuelve el caso por su cuenta, y como su mezcla es por
9166
+ // truthiness, instalar cualquier predicado lo desactivaría y la
9167
+ // pulsación volvería a perderse.
9168
+ shouldCloseOnInteractOutside: isInsideDismissContainer(root)
9169
+ ? function (element) {
9170
+ return shouldClosePopoverOnInteractOutside(element, root);
9171
+ }
9172
+ : undefined,
9071
9173
  }, listboxProps: {
9072
9174
  className: "max-h-[200px] overflow-y-auto",
9073
9175
  }, className: "w-full", children: function (item) {
@@ -9645,6 +9747,127 @@ function removeCustomPrimaryColor() {
9645
9747
  }
9646
9748
  }
9647
9749
 
9750
+ /**
9751
+ * Los tres tonos del aura de Linda, derivados del `primary` de la agencia.
9752
+ *
9753
+ * Linda no tiene color propio: es el `primary` que el negocio eligió en el onboarding,
9754
+ * y por eso aquí no hay ni un color escrito. Lo único que se fija es CUÁNTO se gira ese
9755
+ * tono y en qué banda de luz se pinta.
9756
+ */
9757
+ /**
9758
+ * Grados que se gira el `primary` para cada tono, en el orden en que se pintan.
9759
+ *
9760
+ * Son muchos grados a propósito. La gracia del aura es que haya MÁS DE UN COLOR: con
9761
+ * un giro discreto —del orden de 18°, el que usa un degradado de profundidad— salen
9762
+ * tres versiones del mismo tono y el resultado se lee como un plano. A ±55° el salto
9763
+ * se ve como otro color y sigue dentro de la familia del `primary`, que es lo que
9764
+ * permite que esto funcione con la agencia número siete sin tocar nada.
9765
+ *
9766
+ * El tono del medio va casi sin girar: es el que ancla el conjunto al color de la
9767
+ * agencia, para que el aura se lea como suya y no como una decoración pegada encima.
9768
+ */
9769
+ var GIROS = [-56, 8, 54];
9770
+ /**
9771
+ * Banda de luz en la que se pintan los tres tonos, en porcentaje HSL.
9772
+ *
9773
+ * Los tonos NO heredan la luz del `primary`, y esto es lo que más se nota: un primary
9774
+ * oscuro y poco saturado sobre una superficie clara se lee como una mancha gris —sucia,
9775
+ * no como color—, y uno casi blanco desaparece contra el fondo. Se llevan al paso medio
9776
+ * de la escala, que es el que funciona en los dos casos.
9777
+ */
9778
+ var BANDA_LUZ = { min: 52, max: 72 };
9779
+ /**
9780
+ * Banda de saturación de los tres tonos, en porcentaje HSL.
9781
+ *
9782
+ * El techo es lo que evita que el aura grite. A plena saturación los tonos dejan de ser
9783
+ * ambiente y pasan a ser tres focos de color encima de un control de 40 pt: bonito en
9784
+ * una captura, insoportable en una barra que se mira todo el día.
9785
+ *
9786
+ * ⚠️ **Y hay una razón que no es estética.** Girar el tono puede caer en un rojo vivo:
9787
+ * un `primary` amarillo —51°— girado −56° aterriza en 355°, que a saturación 100 se lee
9788
+ * como un estado de error alrededor de un botón que no ha fallado. Visto al renderizarlo,
9789
+ * no razonándolo. Bajado a 65 el mismo tono es un rosa apagado y vuelve a leerse como lo
9790
+ * que es: decoración.
9791
+ *
9792
+ * El suelo existe por lo contrario: un `primary` casi gris da tres tonos que no se
9793
+ * distinguen entre sí, y entonces no hay degradado que ver —el aura se lee como una
9794
+ * mancha plana—.
9795
+ */
9796
+ var BANDA_SATURACION = { min: 35, max: 65 };
9797
+ var VUELTA = 360;
9798
+ /** `H S% L%` — el formato exacto en el que HeroUI guarda sus variables de color. */
9799
+ var TRIPLETE = /^\s*(-?\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)%\s+(\d+(?:\.\d+)?)%\s*$/;
9800
+ /**
9801
+ * Lee el triplete que HeroUI deja en una variable de color.
9802
+ *
9803
+ * Devuelve `null` en vez de lanzar: esto corre en un efecto de tema y el valor puede
9804
+ * no estar todavía —la clase del tema aún no está en el `<html>`, o el consumidor no
9805
+ * cargó la hoja de estilos—. Un aura que no se pinta es un problema menor; una
9806
+ * excepción que tumba el provider de tema, no.
9807
+ */
9808
+ function parseHslTriplet(value) {
9809
+ var encontrado = TRIPLETE.exec(value);
9810
+ if (!encontrado) {
9811
+ return null;
9812
+ }
9813
+ var h = encontrado[1], s = encontrado[2], l = encontrado[3];
9814
+ return { h: Number(h), s: Number(s), l: Number(l) };
9815
+ }
9816
+ /** Deja un ángulo dentro de `[0, 360)`, venga de donde venga. */
9817
+ function normalizarTono(grados) {
9818
+ return ((grados % VUELTA) + VUELTA) % VUELTA;
9819
+ }
9820
+ function acotar(valor, min, max) {
9821
+ return Math.min(Math.max(valor, min), max);
9822
+ }
9823
+ /**
9824
+ * Los tres tonos del aura, listos para escribirse en una variable CSS.
9825
+ *
9826
+ * Se redondean a entero: es un degradado decorativo, y las décimas de grado solo
9827
+ * alargan la hoja de estilos.
9828
+ */
9829
+ function deriveLindaTones(primary) {
9830
+ var luz = Math.round(acotar(primary.l, BANDA_LUZ.min, BANDA_LUZ.max));
9831
+ var saturacion = Math.round(acotar(primary.s, BANDA_SATURACION.min, BANDA_SATURACION.max));
9832
+ var tonos = GIROS.map(function (giro) {
9833
+ return "".concat(Math.round(normalizarTono(primary.h + giro)), " ").concat(saturacion, "% ").concat(luz, "%");
9834
+ });
9835
+ return tonos;
9836
+ }
9837
+ /** Las variables que se escriben en el `<html>`, en el orden en que se pintan. */
9838
+ var LINDA_TONE_PROPERTIES = [
9839
+ "--linda-1",
9840
+ "--linda-2",
9841
+ "--linda-3",
9842
+ ];
9843
+ /**
9844
+ * Escribe los tres tonos del aura a partir del valor de `--heroui-primary`.
9845
+ *
9846
+ * Si el primary no se puede leer, **borra los que hubiera** y devuelve `false`. Es lo
9847
+ * contrario de dejarlos: unos tonos viejos son de otro tema, y un aura del color
9848
+ * anterior es peor que un aura que no se pinta —la CSS del efecto ya está escrita para
9849
+ * desaparecer sin sus variables—.
9850
+ */
9851
+ function applyLindaTones(style, primaryValue) {
9852
+ var primary = parseHslTriplet(primaryValue);
9853
+ if (!primary) {
9854
+ removeLindaTones(style);
9855
+ return false;
9856
+ }
9857
+ var tonos = deriveLindaTones(primary);
9858
+ LINDA_TONE_PROPERTIES.forEach(function (propiedad, indice) {
9859
+ style.setProperty(propiedad, tonos[indice]);
9860
+ });
9861
+ return true;
9862
+ }
9863
+ /** Quita los tres tonos del aura. */
9864
+ function removeLindaTones(style) {
9865
+ for (var _i = 0, LINDA_TONE_PROPERTIES_1 = LINDA_TONE_PROPERTIES; _i < LINDA_TONE_PROPERTIES_1.length; _i++) {
9866
+ var propiedad = LINDA_TONE_PROPERTIES_1[_i];
9867
+ style.removeProperty(propiedad);
9868
+ }
9869
+ }
9870
+
9648
9871
  /**
9649
9872
  * Custom hook to manage the theme state and side effects.
9650
9873
  * Supports both named ThemeColor values and arbitrary hex colors.
@@ -9690,6 +9913,30 @@ var useThemeManager = function () {
9690
9913
  removeCustomPrimaryColor();
9691
9914
  }
9692
9915
  }, [customHex, mode]);
9916
+ /*
9917
+ * Los tres tonos del aura de Linda, derivados del primary que acaba de quedar fijado.
9918
+ *
9919
+ * Va DESPUÉS de los dos efectos de arriba y depende de lo mismo que ellos, que es lo
9920
+ * que garantiza que lea el primary definitivo: React ejecuta los efectos en orden de
9921
+ * declaración, así que aquí la clase del tema ya está en el `<html>` y el hex a medida
9922
+ * ya está escrito o retirado.
9923
+ *
9924
+ * Se lee del estilo COMPUTADO y no de `customHex` a propósito: el primary llega por
9925
+ * dos caminos —el hex del negocio o la clase de una de las familias de tema— y el
9926
+ * computado es el único sitio donde los dos han convergido. Derivarlo solo de
9927
+ * `customHex` dejaría sin aura a toda agencia que use una familia tal cual.
9928
+ */
9929
+ /*
9930
+ * `customHex` y `rawTheme` están en la lista aunque el cuerpo no los lea: son la señal
9931
+ * de que el `<html>` acaba de cambiar. La entrada real de este efecto es el estilo
9932
+ * computado, que la regla no puede ver, y sin ellos el aura se quedaría con los tonos
9933
+ * del tema anterior.
9934
+ */
9935
+ // biome-ignore lint/correctness/useExhaustiveDependencies: ver el comentario de arriba
9936
+ useEffect(function () {
9937
+ var html = document.documentElement;
9938
+ applyLindaTones(html.style, getComputedStyle(html).getPropertyValue("--heroui-primary"));
9939
+ }, [customHex, rawTheme]);
9693
9940
  var setMode = useCallback(function (newMode) {
9694
9941
  var effectiveMode = newMode === "dark" ? "light" : newMode;
9695
9942
  var newTheme = color === "blue" ? effectiveMode : "".concat(color, "-").concat(effectiveMode);
@@ -9811,4 +10058,4 @@ var NavigationLoadingProvider = function (_a) {
9811
10058
  return (jsxs(NavigationLoadingContext.Provider, { value: value, children: [children, jsx(NavigationLoadingOverlay, { isVisible: isVisible })] }));
9812
10059
  };
9813
10060
 
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 };
10061
+ 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, isInsideDismissContainer, isRankedBarListEmpty, isSegmentationGroup, parseHslTriplet, removeCustomPrimaryColor, removeLindaTones, shouldClosePopoverOnInteractOutside, sizeMap, themeColors, useAuraToast, useCloseOnAncestorScroll, useMediaQuery, useNavigationLoading, useThemeContext, withPopoverDismissDefaults };
@@ -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