@beweco/aurora-ui 1.0.0-beta.122 → 1.0.0-beta.124

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 (32) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +238 -31
  3. package/dist/index.esm.js +245 -32
  4. package/dist/types/__smoke__/field-ref-surface.d.ts +34 -0
  5. package/dist/types/__smoke__/field-ref-surface.d.ts.map +1 -0
  6. package/dist/types/__smoke__/v2-api-surface.d.ts +12 -1
  7. package/dist/types/__smoke__/v2-api-surface.d.ts.map +1 -1
  8. package/dist/types/components/autocomplete/AutoComplete.d.ts.map +1 -1
  9. package/dist/types/components/datepicker/DatePicker.d.ts +1 -1
  10. package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
  11. package/dist/types/components/datepicker/DatePicker.types.d.ts +38 -0
  12. package/dist/types/components/datepicker/DatePicker.types.d.ts.map +1 -1
  13. package/dist/types/components/daterangepicker/DateRangePicker.d.ts +1 -1
  14. package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -1
  15. package/dist/types/components/daterangepicker/DateRangePicker.types.d.ts +42 -0
  16. package/dist/types/components/daterangepicker/DateRangePicker.types.d.ts.map +1 -1
  17. package/dist/types/components/dropdown/Dropdown.d.ts +56 -0
  18. package/dist/types/components/dropdown/Dropdown.d.ts.map +1 -0
  19. package/dist/types/components/dropdown/Dropdown.types.d.ts +54 -0
  20. package/dist/types/components/dropdown/Dropdown.types.d.ts.map +1 -0
  21. package/dist/types/components/dropdown/index.d.ts +3 -0
  22. package/dist/types/components/dropdown/index.d.ts.map +1 -0
  23. package/dist/types/components/input/Input.d.ts +12 -1
  24. package/dist/types/components/input/Input.d.ts.map +1 -1
  25. package/dist/types/components/input-password/InputPassword.d.ts +10 -1
  26. package/dist/types/components/input-password/InputPassword.d.ts.map +1 -1
  27. package/dist/types/components/select/Select.d.ts.map +1 -1
  28. package/dist/types/components/textarea/Textarea.d.ts +12 -1
  29. package/dist/types/components/textarea/Textarea.d.ts.map +1 -1
  30. package/dist/types/index.d.ts +2 -1
  31. package/dist/types/index.d.ts.map +1 -1
  32. package/package.json +2 -1
package/dist/index.cjs.js CHANGED
@@ -1167,7 +1167,7 @@ const CALENDAR_CELL_CLASS$1 = "size-8 place-self-center rounded-full " +
1167
1167
  * (grid) para que la API pública siga siendo un único componente con props planas, igual que en
1168
1168
  * v2 (label, description, errorMessage, endContent, variant, size, radius).
1169
1169
  */
1170
- function DatePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, className, "aria-label": ariaLabel, ...props }) {
1170
+ function DatePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent, className, "aria-label": ariaLabel, ...props }) {
1171
1171
  const generatedId = $8WNJc$react.useId();
1172
1172
  const autoId = id || generatedId;
1173
1173
  const calendarLabel = (typeof label === "string" ? label : undefined) ?? ariaLabel ?? "Calendario";
@@ -1180,7 +1180,7 @@ function DatePicker({ label, description, errorMessage, id, size = "md", variant
1180
1180
  FIELD_FOCUS_CLASS$5,
1181
1181
  ]
1182
1182
  .filter(Boolean)
1183
- .join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { className: SIZE_TEXT_CLASS$3[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DatePicker.Trigger, { children: endContent !== undefined ? (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, { children: endContent })) : (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, {})) }) })] }), description && !isInvalid && jsxRuntime.jsx(react.Description, { children: description }), jsxRuntime.jsx(react.DatePicker.Popover, { children: jsxRuntime.jsxs(react.Calendar, { "aria-label": calendarLabel, children: [jsxRuntime.jsxs(react.Calendar.Header, { children: [jsxRuntime.jsxs(react.Calendar.YearPickerTrigger, { children: [jsxRuntime.jsx(react.Calendar.YearPickerTriggerHeading, {}), jsxRuntime.jsx(react.Calendar.YearPickerTriggerIndicator, {})] }), jsxRuntime.jsx(react.Calendar.NavButton, { slot: "previous" }), jsxRuntime.jsx(react.Calendar.NavButton, { slot: "next" })] }), jsxRuntime.jsxs(react.Calendar.Grid, { children: [jsxRuntime.jsx(react.Calendar.GridHeader, { children: (day) => jsxRuntime.jsx(react.Calendar.HeaderCell, { children: day }) }), jsxRuntime.jsx(react.Calendar.GridBody, { children: (date) => (jsxRuntime.jsx(react.Calendar.Cell, { date: date, className: CALENDAR_CELL_CLASS$1 })) })] })] }) }), isInvalid && errorMessage && jsxRuntime.jsx(react.FieldError, { children: errorMessage })] }));
1183
+ .join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { className: SIZE_TEXT_CLASS$3[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DatePicker.Trigger, { children: endContent !== undefined ? (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, { children: endContent })) : (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, {})) }) })] }), description && !isInvalid && jsxRuntime.jsx(react.Description, { children: description }), jsxRuntime.jsxs(react.DatePicker.Popover, { children: [jsxRuntime.jsxs(react.Calendar, { "aria-label": calendarLabel, children: [jsxRuntime.jsxs(react.Calendar.Header, { children: [jsxRuntime.jsxs(react.Calendar.YearPickerTrigger, { children: [jsxRuntime.jsx(react.Calendar.YearPickerTriggerHeading, {}), jsxRuntime.jsx(react.Calendar.YearPickerTriggerIndicator, {})] }), jsxRuntime.jsx(react.Calendar.NavButton, { slot: "previous" }), jsxRuntime.jsx(react.Calendar.NavButton, { slot: "next" })] }), jsxRuntime.jsxs(react.Calendar.Grid, { children: [jsxRuntime.jsx(react.Calendar.GridHeader, { children: (day) => jsxRuntime.jsx(react.Calendar.HeaderCell, { children: day }) }), jsxRuntime.jsx(react.Calendar.GridBody, { children: (date) => (jsxRuntime.jsx(react.Calendar.Cell, { date: date, className: CALENDAR_CELL_CLASS$1 })) })] })] }), calendarBottomContent] }), isInvalid && errorMessage && jsxRuntime.jsx(react.FieldError, { children: errorMessage })] }));
1184
1184
  }
1185
1185
 
1186
1186
  // Mismo mecanismo que DatePicker.tsx / Input.tsx / Select.tsx (findings/
@@ -1259,7 +1259,7 @@ const CALENDAR_CELL_CLASS = "data-[today=true]:not-data-[selected=true]:[&_[data
1259
1259
  * `DatePicker`, migrado en tándem. Compone `DateRangePicker.Root/Trigger/TriggerIndicator/
1260
1260
  * RangeSeparator/Popover` + `DateField` (dos segmentos, start/end) + `RangeCalendar`.
1261
1261
  */
1262
- function DateRangePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, className, "aria-label": ariaLabel, ...props }) {
1262
+ function DateRangePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent, className, "aria-label": ariaLabel, ...props }) {
1263
1263
  const generatedId = $8WNJc$react.useId();
1264
1264
  const autoId = id || generatedId;
1265
1265
  const calendarLabel = (typeof label === "string" ? label : undefined) ?? ariaLabel ?? "Rango de fechas";
@@ -1272,7 +1272,7 @@ function DateRangePicker({ label, description, errorMessage, id, size = "md", va
1272
1272
  FIELD_FOCUS_CLASS$4,
1273
1273
  ]
1274
1274
  .filter(Boolean)
1275
- .join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { slot: "start", className: SIZE_TEXT_CLASS$2[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateRangePicker.RangeSeparator, {}), jsxRuntime.jsx(react.DateField.Input, { slot: "end", className: SIZE_TEXT_CLASS$2[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DateRangePicker.Trigger, { children: endContent !== undefined ? (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, { children: endContent })) : (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, {})) }) })] }), description && !isInvalid && jsxRuntime.jsx(react.Description, { children: description }), jsxRuntime.jsx(react.DateRangePicker.Popover, { children: jsxRuntime.jsxs(react.RangeCalendar, { "aria-label": calendarLabel, children: [jsxRuntime.jsxs(react.RangeCalendar.Header, { children: [jsxRuntime.jsxs(react.RangeCalendar.YearPickerTrigger, { children: [jsxRuntime.jsx(react.RangeCalendar.YearPickerTriggerHeading, {}), jsxRuntime.jsx(react.RangeCalendar.YearPickerTriggerIndicator, {})] }), jsxRuntime.jsx(react.RangeCalendar.NavButton, { slot: "previous" }), jsxRuntime.jsx(react.RangeCalendar.NavButton, { slot: "next" })] }), jsxRuntime.jsxs(react.RangeCalendar.Grid, { children: [jsxRuntime.jsx(react.RangeCalendar.GridHeader, { children: (day) => jsxRuntime.jsx(react.RangeCalendar.HeaderCell, { children: day }) }), jsxRuntime.jsx(react.RangeCalendar.GridBody, { children: (date) => (jsxRuntime.jsx(react.RangeCalendar.Cell, { date: date, className: CALENDAR_CELL_CLASS })) })] })] }) }), isInvalid && errorMessage && jsxRuntime.jsx(react.FieldError, { children: errorMessage })] }));
1275
+ .join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { slot: "start", className: SIZE_TEXT_CLASS$2[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateRangePicker.RangeSeparator, {}), jsxRuntime.jsx(react.DateField.Input, { slot: "end", className: SIZE_TEXT_CLASS$2[size], children: (segment) => jsxRuntime.jsx(react.DateField.Segment, { segment: segment }) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DateRangePicker.Trigger, { children: endContent !== undefined ? (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, { children: endContent })) : (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, {})) }) })] }), description && !isInvalid && jsxRuntime.jsx(react.Description, { children: description }), jsxRuntime.jsxs(react.DateRangePicker.Popover, { children: [jsxRuntime.jsxs(react.RangeCalendar, { "aria-label": calendarLabel, children: [jsxRuntime.jsxs(react.RangeCalendar.Header, { children: [jsxRuntime.jsxs(react.RangeCalendar.YearPickerTrigger, { children: [jsxRuntime.jsx(react.RangeCalendar.YearPickerTriggerHeading, {}), jsxRuntime.jsx(react.RangeCalendar.YearPickerTriggerIndicator, {})] }), jsxRuntime.jsx(react.RangeCalendar.NavButton, { slot: "previous" }), jsxRuntime.jsx(react.RangeCalendar.NavButton, { slot: "next" })] }), jsxRuntime.jsxs(react.RangeCalendar.Grid, { children: [jsxRuntime.jsx(react.RangeCalendar.GridHeader, { children: (day) => jsxRuntime.jsx(react.RangeCalendar.HeaderCell, { children: day }) }), jsxRuntime.jsx(react.RangeCalendar.GridBody, { children: (date) => (jsxRuntime.jsx(react.RangeCalendar.Cell, { date: date, className: CALENDAR_CELL_CLASS })) })] })] }), calendarBottomContent] }), isInvalid && errorMessage && jsxRuntime.jsx(react.FieldError, { children: errorMessage })] }));
1276
1276
  }
1277
1277
 
1278
1278
  // TECH-2459 · F3.0 — v3 divide el `Input` monolítico de v2 en `TextField` (label/description/
@@ -1544,8 +1544,19 @@ const INVALID_TEXT_CLASS$2 = "text-danger";
1544
1544
  * - Radius configurable (v3 no tiene la prop).
1545
1545
  * - `startContent`/`endContent` → `InputGroup.Prefix`/`InputGroup.Suffix`.
1546
1546
  * - `isClearable` → botón de limpiar propio (`CloseButton`); solo en modo controlado (`value`).
1547
+ *
1548
+ * `ref` apunta al `<input>` REAL (`HTMLInputElement`), no al `InputGroup` ni al `TextField` que lo
1549
+ * envuelven: el consumidor que necesita el nodo —insertar texto en la posición del cursor con
1550
+ * `selectionStart`/`setSelectionRange`, enfocar, leer `validity`— lo alcanza directamente.
1551
+ *
1552
+ * ⚠️ Se reenvía con `forwardRef` (patrón de las 8 fachadas del repo que ya lo hacen) y NO
1553
+ * confiando en que React 19 pase `ref` dentro de `...rest`: medido, en React 19 eso ya funcionaba
1554
+ * de rebote —el `ref` viajaba en el spread hasta `InputGroup.Input`, que también hace spread— pero
1555
+ * (a) el tipo público lo rechazaba, así que el consumidor no podía escribirlo sin un `as any`, y
1556
+ * (b) era accidental: cualquier prop que se añadiese al destructuring lo habría cortado en
1557
+ * silencio.
1547
1558
  */
1548
- const Input = ({ label, description, errorMessage, id,
1559
+ const Input = $8WNJc$react.forwardRef(({ label, description, errorMessage, id,
1549
1560
  // ⚠️ El default de v2 era "md", no "lg" — verificado en el código de v2
1550
1561
  // (`git show b39d28f:src/components/input/Input.tsx`, `size = "md"`) y en su PNG congelado
1551
1562
  // (`input--default` mide exactamente lo mismo que `--medium`: 40px de alto, texto de 14px). El
@@ -1560,7 +1571,7 @@ size = "md", variant = "bordered", radius = "md", placeholder, startContent, end
1560
1571
  // `undefined` y el campo dejaba de llenar su contenedor: en una fila flex se encogía al ancho
1561
1572
  // de su contenido (medido por S2: 208px dentro de una fila de 592, 336px de hueco). En una
1562
1573
  // columna no se notaba porque el `stretch` del flex lo tapaba — pero afecta a cualquier app.
1563
- fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, required, name, type = "text", ...rest }) => {
1574
+ fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, required, name, type = "text", ...rest }, ref) => {
1564
1575
  const generatedId = $8WNJc$react.useId();
1565
1576
  const inputId = id || generatedId;
1566
1577
  // ⚠️ `isRequired` (prop de HeroUI, asterisco visual) y `required` (atributo HTML nativo, solo
@@ -1611,7 +1622,7 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
1611
1622
  className,
1612
1623
  ]
1613
1624
  .filter(Boolean)
1614
- .join(" "), children: [startContent && (jsxRuntime.jsx(react.InputGroup.Prefix, { className: "border-none bg-transparent px-0", children: startContent })), jsxRuntime.jsx(react.InputGroup.Input, { ...rest, required: required, type: type, placeholder: labelFlotante ? " " : placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: [
1625
+ .join(" "), children: [startContent && (jsxRuntime.jsx(react.InputGroup.Prefix, { className: "border-none bg-transparent px-0", children: startContent })), jsxRuntime.jsx(react.InputGroup.Input, { ...rest, ref: ref, required: required, type: type, placeholder: labelFlotante ? " " : placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: [
1615
1626
  "bg-transparent p-0",
1616
1627
  SIZE_TEXT_CLASS$1[size],
1617
1628
  isInvalid ? INVALID_TEXT_CLASS$2 : "",
@@ -1625,7 +1636,8 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
1625
1636
  .join(" "), children: description })), isInvalid && errorMessage && (jsxRuntime.jsx(react.FieldError, { className: [HELPER_CLASS$2, "text-left", classNames?.errorMessage]
1626
1637
  .filter(Boolean)
1627
1638
  .join(" "), children: errorMessage }))] }));
1628
- };
1639
+ });
1640
+ Input.displayName = "Input";
1629
1641
 
1630
1642
  const defaultTranslations$g = {
1631
1643
  addHolidayTitle: "Add holiday",
@@ -8788,17 +8800,17 @@ const OWN_SCROLL = new Set([
8788
8800
  react.Table.ResizableContainer,
8789
8801
  ]);
8790
8802
  /** Identidad por `child.type` contra los objetos reales de HeroUI (mismo patrón que la fachada `Alert`). */
8791
- function isPart(node, parts) {
8803
+ function isPart$1(node, parts) {
8792
8804
  return $8WNJc$react.isValidElement(node) && parts.has(node.type);
8793
8805
  }
8794
8806
  const TableFacade = ({ children, ...props }) => {
8795
8807
  const nodes = $8WNJc$react.Children.toArray(children);
8796
8808
  // Sin hijos, o con un contenedor de scroll ya montado a mano: el root tal cual.
8797
- if (nodes.length === 0 || nodes.some((node) => isPart(node, OWN_SCROLL))) {
8809
+ if (nodes.length === 0 || nodes.some((node) => isPart$1(node, OWN_SCROLL))) {
8798
8810
  return jsxRuntime.jsx(react.Table, { ...props, children: children });
8799
8811
  }
8800
- const scrollable = nodes.filter((node) => !isPart(node, OUTSIDE_SCROLL));
8801
- const outsideScroll = nodes.filter((node) => isPart(node, OUTSIDE_SCROLL));
8812
+ const scrollable = nodes.filter((node) => !isPart$1(node, OUTSIDE_SCROLL));
8813
+ const outsideScroll = nodes.filter((node) => isPart$1(node, OUTSIDE_SCROLL));
8802
8814
  return (jsxRuntime.jsxs(react.Table, { ...props, children: [jsxRuntime.jsx(react.Table.ScrollContainer, { children: scrollable }), outsideScroll] }));
8803
8815
  };
8804
8816
  TableFacade.displayName = "Aurora.Table";
@@ -8957,8 +8969,19 @@ const INVALID_TEXT_CLASS = "text-danger";
8957
8969
  * Textarea genérico reutilizable basado en HeroUI v3 (TextField + TextArea) siguiendo las reglas
8958
8970
  * de diseño BeweOS (TECH-2459 · F3 · G1-forms). La API pública v2 (label, description,
8959
8971
  * errorMessage, variant, size, radius, isClearable-less) se conserva sin cambios.
8972
+ *
8973
+ * `ref` apunta al `<textarea>` REAL (`HTMLTextAreaElement`), no al contenedor: el consumidor que
8974
+ * necesita el nodo —insertar texto en la posición del cursor con `selectionStart`/
8975
+ * `setSelectionRange`, enfocar, medir— lo alcanza directamente.
8976
+ *
8977
+ * ⚠️ Se reenvía con `forwardRef` (patrón de las 8 fachadas del repo que ya lo hacen) y NO
8978
+ * confiando en que React 19 pase `ref` dentro de `...rest`: medido, en React 19 eso ya funcionaba
8979
+ * de rebote —el `ref` viajaba en el spread hasta el `TextAreaRoot` de v3, que también hace spread—
8980
+ * pero (a) el tipo público lo rechazaba, así que el consumidor no podía escribirlo sin un `as any`
8981
+ * y acababa colgando el ref del contenedor y buscando el `<textarea>` con una query, y (b) era
8982
+ * accidental: cualquier prop que se añadiese al destructuring lo habría cortado en silencio.
8960
8983
  */
8961
- const Textarea = ({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", placeholder, isInvalid = false, isRequired = false, isDisabled = false, isReadOnly = false,
8984
+ const Textarea = $8WNJc$react.forwardRef(({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", placeholder, isInvalid = false, isRequired = false, isDisabled = false, isReadOnly = false,
8962
8985
  // `fullWidth` por defecto a `true`: HeroUI v2 lo traía en sus `defaultVariants`
8963
8986
  // (verificado en el paquete v2 compilado, `dist/components/input.js`:
8964
8987
  // `defaultVariants: { variant:"flat", color:"default", size:"md", fullWidth:true, … }`, con
@@ -8966,7 +8989,7 @@ const Textarea = ({ label, description, errorMessage, id, size = "md", variant =
8966
8989
  // `undefined` y el campo dejaba de llenar su contenedor: en una fila flex se encogía al ancho
8967
8990
  // de su contenido (medido por S2: 208px dentro de una fila de 592, 336px de hueco). En una
8968
8991
  // columna no se notaba porque el `stretch` del flex lo tapaba — pero afecta a cualquier app.
8969
- fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, name, ...rest }) => {
8992
+ fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, name, ...rest }, ref) => {
8970
8993
  const generatedId = $8WNJc$react.useId();
8971
8994
  const textareaId = id || generatedId;
8972
8995
  const handleChange = (event) => {
@@ -8981,7 +9004,7 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
8981
9004
  classNames?.label,
8982
9005
  ]
8983
9006
  .filter(Boolean)
8984
- .join(" "), children: label })), jsxRuntime.jsx(react.TextArea, { ...rest, placeholder: placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: [
9007
+ .join(" "), children: label })), jsxRuntime.jsx(react.TextArea, { ...rest, ref: ref, placeholder: placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: [
8985
9008
  SIZE_CLASS[size],
8986
9009
  RESIZE_CLASS,
8987
9010
  RADIUS_CLASS$3[radius],
@@ -8999,7 +9022,8 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
8999
9022
  .join(" "), children: description })), isInvalid && errorMessage && (jsxRuntime.jsx(react.FieldError, { className: [HELPER_CLASS, "text-left", classNames?.errorMessage]
9000
9023
  .filter(Boolean)
9001
9024
  .join(" "), children: errorMessage }))] }));
9002
- };
9025
+ });
9026
+ Textarea.displayName = "Textarea";
9003
9027
 
9004
9028
  // Traducciones por defecto en español según las reglas de diseño
9005
9029
  const defaultTranslations$3 = {
@@ -11570,14 +11594,23 @@ const EmailPreview = ({ htmlContent, subject, from, to, iframeHeight = 480, tran
11570
11594
  }) })] }), jsxRuntime.jsxs("span", { className: "text-xs text-gray-500", children: [t.toLabel, ": ", displayTo] })] })] })] })), jsxRuntime.jsx("div", { className: "w-full overflow-hidden", children: jsxRuntime.jsx("iframe", { title: t.iframeTitle, srcDoc: htmlContent, className: "w-full border-0", style: { height: `${iframeHeight}px` }, sandbox: "allow-same-origin" }) })] }), jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: jsxRuntime.jsx("div", { className: `w-32 h-1 rounded-full ${deviceColor === "black" ? "bg-gray-600" : "bg-gray-400"}` }) })] }) }));
11571
11595
  };
11572
11596
 
11573
- const InputPassword = ({ translations, showCriteria = false, criteria, isPristine = true, renderCriterionLabel, criteriaId = "password-criteria", ...inputProps }) => {
11597
+ /**
11598
+ * Campo de contraseña: la fachada `Input` con un botón de mostrar/ocultar y, opcionalmente, la
11599
+ * lista de criterios.
11600
+ *
11601
+ * `ref` apunta al `<input>` REAL (`HTMLInputElement`) — el mismo contrato que `Input`, no el `<div>`
11602
+ * que envuelve campo y criterios. Estaba afectado por el mismo defecto de tipos que `Input` y
11603
+ * `Textarea`: el `ref` llegaba al `<input>` en runtime (React 19 lo pasaba dentro de
11604
+ * `...inputProps`) pero `InputPasswordProps` no lo declaraba, así que TypeScript lo rechazaba.
11605
+ */
11606
+ const InputPassword = $8WNJc$react.forwardRef(({ translations, showCriteria = false, criteria, isPristine = true, renderCriterionLabel, criteriaId = "password-criteria", ...inputProps }, ref) => {
11574
11607
  const [showPassword, setShowPassword] = $8WNJc$react.useState(false);
11575
11608
  const togglePasswordVisibility = () => {
11576
11609
  setShowPassword((prev) => !prev);
11577
11610
  };
11578
11611
  const showLabel = translations?.showPassword ?? "Show password";
11579
11612
  const hideLabel = translations?.hidePassword ?? "Hide password";
11580
- return (jsxRuntime.jsxs("div", { className: "flex flex-col w-full", children: [jsxRuntime.jsx(Input, { ...inputProps, type: showPassword ? "text" : "password", "aria-describedby": showCriteria ? criteriaId : inputProps["aria-describedby"], endContent: jsxRuntime.jsx("button", { type: "button", tabIndex: -1, onClick: togglePasswordVisibility, className: "focus:outline-none", "aria-label": showPassword ? hideLabel : showLabel, children: showPassword ? (jsxRuntime.jsx(IconComponent, { icon: "lucide:eye-off", color: "gray" })) : (jsxRuntime.jsx(IconComponent, { icon: "lucide:eye", color: "gray" })) }) }), showCriteria && criteria && criteria.length > 0 && (jsxRuntime.jsx("fieldset", { id: criteriaId, className: "mt-2", children: jsxRuntime.jsx("ul", { className: "flex flex-col gap-2 list-none", children: criteria.map((criterion, idx) => {
11613
+ return (jsxRuntime.jsxs("div", { className: "flex flex-col w-full", children: [jsxRuntime.jsx(Input, { ...inputProps, ref: ref, type: showPassword ? "text" : "password", "aria-describedby": showCriteria ? criteriaId : inputProps["aria-describedby"], endContent: jsxRuntime.jsx("button", { type: "button", tabIndex: -1, onClick: togglePasswordVisibility, className: "focus:outline-none", "aria-label": showPassword ? hideLabel : showLabel, children: showPassword ? (jsxRuntime.jsx(IconComponent, { icon: "lucide:eye-off", color: "gray" })) : (jsxRuntime.jsx(IconComponent, { icon: "lucide:eye", color: "gray" })) }) }), showCriteria && criteria && criteria.length > 0 && (jsxRuntime.jsx("fieldset", { id: criteriaId, className: "mt-2", children: jsxRuntime.jsx("ul", { className: "flex flex-col gap-2 list-none", children: criteria.map((criterion, idx) => {
11581
11614
  const colorClass = criterion.passed
11582
11615
  ? "text-success"
11583
11616
  : isPristine
@@ -11587,7 +11620,8 @@ const InputPassword = ({ translations, showCriteria = false, criteria, isPristin
11587
11620
  ? renderCriterionLabel(criterion.label)
11588
11621
  : criterion.label] }, `${criteriaId}-${idx}`));
11589
11622
  }) }) }))] }));
11590
- };
11623
+ });
11624
+ InputPassword.displayName = "InputPassword";
11591
11625
 
11592
11626
  const SimpleLineChart = ({ data, title, height = 200, color = "#3b82f6", className = "", showTitle = true, emptyMessage = "No hay datos disponibles", onPointClick, }) => {
11593
11627
  if (data.length === 0) {
@@ -13718,7 +13752,7 @@ function hasCompoundChildren$1(children) {
13718
13752
  return $8WNJc$react.Children.toArray(children).some((child) => $8WNJc$react.isValidElement(child) && COMPOUND_PARTS$1.has(child.type));
13719
13753
  }
13720
13754
  /** `isEmpty` de v2 (`@heroui/shared-utils`): null/undefined/"" no cuentan como contenido. */
13721
- function hasValue(node) {
13755
+ function hasValue$1(node) {
13722
13756
  return node !== null && node !== undefined && node !== "" && node !== false;
13723
13757
  }
13724
13758
  /**
@@ -13756,10 +13790,10 @@ const AlertFacade = ({ color, status, variant = "flat", radius = "md", title, de
13756
13790
  onClose?.();
13757
13791
  };
13758
13792
  const slots = slotClasses(variant, effectiveColor);
13759
- const hasTitle = hasValue(title);
13760
- const hasDescription = hasValue(description);
13793
+ const hasTitle = hasValue$1(title);
13794
+ const hasDescription = hasValue$1(description);
13761
13795
  // `hasContent` de v2: sin descripción ni children, el título se centra verticalmente con el icono.
13762
- const hasContent = hasDescription || hasValue(children);
13796
+ const hasContent = hasDescription || hasValue$1(children);
13763
13797
  const showClose = isClosable || Boolean(onClose);
13764
13798
  return (jsxRuntime.jsxs(react.Alert, { role: "alert", "data-visible": "true", "data-closeable": showClose ? "true" : undefined, "data-has-title": hasTitle ? "true" : undefined, "data-has-description": hasDescription ? "true" : undefined, ...rest, status: effectiveStatus,
13765
13799
  // Base v2: `flex flex-grow flex-row w-full items-start py-3 px-4 gap-x-1`. v3 ya trae
@@ -13968,6 +14002,185 @@ const Checkbox = Object.assign(CheckboxFacade, {
13968
14002
  Content: react.Checkbox.Content,
13969
14003
  });
13970
14004
 
14005
+ // TECH-2459 — Fachada `Dropdown` / `DropdownSection`: repone la CABECERA DE SECCIÓN que la
14006
+ // migración a v3 dejó sin vía legal desde una app.
14007
+ //
14008
+ // EL DEFECTO (verificado en los tipos instalados, no deducido): el `DropdownSection` de v3 es
14009
+ // `interface DropdownSectionProps extends ComponentPropsWithRef<typeof MenuSectionRoot>`
14010
+ // (`@heroui/react/dist/components/dropdown/dropdown.d.ts`) y ahí NO hay `title` — react-aria lo
14011
+ // omite a mano en su base (`SectionProps<T> extends Omit<SharedSectionProps<T>, 'children' |
14012
+ // 'title'>`, `react-aria-components/dist/types/src/Collection.d.ts:79`). En v3 la cabecera es un
14013
+ // componente, el `Header` de react-aria, que `@heroui/react` SÍ reexporta
14014
+ // (`dist/index.js:128`, `export { Header } from './components/header/index.js'`) pero que la
14015
+ // fachada de Aurora no exponía. Con la regla de oro de la migración (0 imports directos de
14016
+ // `@heroui/*` ni de react-aria en las apps), desde una app no había NINGUNA forma de poner
14017
+ // cabecera a una sección: `title` compila como atributo global de HTML y sale como *tooltip*,
14018
+ // no como texto visible.
14019
+ //
14020
+ // Impacto medido: `beweossmbs/src/clients/ui/features/contact-list/components/column-manager/
14021
+ // column-manager.component.tsx:146` monta `<DropdownSection title={…} classNames={{heading}}>`
14022
+ // para su gestor de columnas — el único consumidor de secciones de dropdown en los repos de apps
14023
+ // (grep real de `DropdownSection|Dropdown.Section` en beweossmbs, beweosagency,
14024
+ // backoffice-beweos, loginos, linda-business y beweanalytics: 1 uso).
14025
+ //
14026
+ // POR QUÉ LA PROP `title` Y NO SOLO UN `Dropdown.SectionHeader` EXPORTADO: es la convención ya
14027
+ // establecida en este repo para esta MISMA forma de defecto (prop de v2 que v3 convierte en
14028
+ // pieza del compound) — la fachada `Alert` mantiene `title`/`description` como props y compone
14029
+ // `Alert.Title`/`Alert.Description` por dentro, y además publica esas piezas como estáticos;
14030
+ // `Checkbox`, `Switch` y `Table` siguen el mismo patrón (API v2 intacta + compound de v3 vía
14031
+ // estáticos). Exportar solo la pieza obligaría al consumidor a cambiar su marcado, que es
14032
+ // exactamente lo que la migración promete no pedir, y encima dejaría `classNames.heading` sin
14033
+ // destino. Se hacen las DOS cosas, igual que en `Alert`: la prop v2 y la pieza de v3
14034
+ // (`DropdownSection.Header`, alcanzable también como `Dropdown.Section.Header`).
14035
+ /**
14036
+ * Cabecera de sección con el aspecto de v2. Se repone UN literal, el único que difiere de la
14037
+ * clase `.header` de v3 — el resto ya coincide, MEDIDO en el navegador (Storybook, claro y
14038
+ * oscuro), no deducido de la hoja:
14039
+ *
14040
+ * | | v2 (`heading`) | v3 (`.header`) | ¿se repone? |
14041
+ * |---|---|---|---|
14042
+ * | tamaño | `text-tiny` = 12px | `text-xs` = 12px | no, idéntico |
14043
+ * | peso | sin clase → 400 | `font-medium` → 500 | **sí**, `font-normal` |
14044
+ * | color | `text-foreground-500` | `text-muted` | no: MISMO gris (ver abajo) |
14045
+ * | padding | `pl-1` (4px) | `px-2 pt-1.5 pb-1` | no, gana v3 (ver abajo) |
14046
+ *
14047
+ * Oráculo de v2 leído, no recordado: `@heroui/theme@2.4.15` →
14048
+ * `dist/chunk-VFBRSBM5.mjs:478`, `menuSection.heading = "pl-1 text-tiny text-foreground-500"`.
14049
+ * v3: `@heroui/styles/dist/components/header.css` → `.header { @apply w-full px-2 pt-1.5 pb-1
14050
+ * text-start text-xs font-medium text-muted }`.
14051
+ *
14052
+ * **El color NO se repone porque `text-muted` ya ES el gris de v2.** Medido en el navegador:
14053
+ * claro `--muted: oklch(55.17% .0138 285.94)` ≡ `--color-foreground-500: #71717a`; oscuro
14054
+ * `oklch(70.5% .015 286.067)` ≡ `#a1a1aa` (los dos son zinc-500 / zinc-400). Se descartó el
14055
+ * `text-foreground-500` redundante que tenía este constante en la primera versión: además de no
14056
+ * pintar nada distinto, habría desacoplado la cabecera del token de v3 para siempre.
14057
+ *
14058
+ * **El padding sí se deja en v3 a propósito**: los ítems también cambiaron de caja
14059
+ * (`.dropdown__popover [data-slot="menu-item"] { @apply px-2.5 }`), así que con el `px-2` de v3
14060
+ * el texto de la cabecera queda 2px a la izquierda del de sus ítems (medido dentro del popover
14061
+ * real: 605.9 vs 607.9); copiando el `pl-1` de v2 serían 6px.
14062
+ *
14063
+ * Va como utilidad (capa `utilities`), que gana a `.header` (capa `components`, ver
14064
+ * `@heroui/styles/dist/index.css:14`) — mismo mecanismo que las fachadas Alert/Badge/Card/Chip.
14065
+ * Ni una clase v2 muerta (`text-tiny` no existe sin el plugin `heroui()` y `cn` la BORRARÍA).
14066
+ */
14067
+ const SECTION_HEADING_CLASS = "font-normal";
14068
+ /** `isEmpty` de v2 (`@heroui/shared-utils`): null/undefined/""/false no cuentan como contenido. */
14069
+ function hasValue(node) {
14070
+ return node !== null && node !== undefined && node !== "" && node !== false;
14071
+ }
14072
+ /**
14073
+ * Sección de un `DropdownMenu` con la API de v2: `title` compone el `Header` de v3 por dentro y
14074
+ * `classNames.base`/`classNames.heading` apuntan a los dos slots que v3 conserva.
14075
+ *
14076
+ * La accesibilidad la cablea react-aria sola, y por eso la cabecera va DENTRO de la sección y no
14077
+ * como `<div>` hermano: `MenuSectionInner` llama a `useMenuSection({heading})` y publica los
14078
+ * `headingProps` (con su `id`) por `HeaderContext`, de modo que el `<section role="group">`
14079
+ * acaba con `aria-labelledby` apuntando a la cabecera
14080
+ * (`react-aria-components/dist/private/Menu.mjs:318-355`).
14081
+ */
14082
+ const DropdownSectionFacade = ({ title, classNames, className, children, ...props }) => {
14083
+ return (jsxRuntime.jsxs(react.Dropdown.Section, { ...props, className: react.cn(className, classNames?.base), children: [hasValue(title) ? (jsxRuntime.jsx(react.Header, { className: react.cn(SECTION_HEADING_CLASS, classNames?.heading), children: title })) : null, children] }));
14084
+ };
14085
+ DropdownSectionFacade.displayName = "Aurora.DropdownSection";
14086
+ /**
14087
+ * `DropdownSection` de Aurora: la sección de v3 con el `title` de v2, más el `Header` de v3 como
14088
+ * estático — la vía idiomática de v3 para quien escriba marcado nuevo:
14089
+ *
14090
+ * ```tsx
14091
+ * <DropdownSection title="Gestionar columnas">…</DropdownSection> // API v2
14092
+ * <DropdownSection><DropdownSection.Header>…</DropdownSection.Header>…</DropdownSection> // v3
14093
+ * ```
14094
+ *
14095
+ * `Header` es el objeto EXACTO que exporta `@heroui/react`, así que la pieza se comporta igual
14096
+ * que importándola de HeroUI (lo que las apps no pueden hacer).
14097
+ */
14098
+ const DropdownSection = Object.assign(DropdownSectionFacade, {
14099
+ Header: react.Header,
14100
+ });
14101
+ // ---------------------------------------------------------------------------------------------
14102
+ // Inserción automática del `Dropdown.Popover` que v3 exige (TECH-2459)
14103
+ // ---------------------------------------------------------------------------------------------
14104
+ //
14105
+ // EL DEFECTO: `MenuTrigger` (el root de v3) solo PROVEE el contexto del popover — no lo
14106
+ // renderiza. Se ve en su implementación: monta un `PressResponder` y devuelve `props.children`
14107
+ // tal cual (`react-aria-components/dist/private/Menu.mjs:76-108`). Así que el marcado v2
14108
+ // `<Dropdown><DropdownTrigger/><DropdownMenu/></Dropdown>` compila en verde y en ejecución pinta
14109
+ // el menú **en línea, dentro del flujo del documento**, siempre visible y sin posicionar. No hay
14110
+ // error, ni aviso en consola.
14111
+ //
14112
+ // Medido en los repos de apps (grep real de `<Dropdown` + `DropdownMenu`, no de memoria):
14113
+ // **13 ficheros / 23 tags** de `<Dropdown>` consumen esta fachada — 10 ficheros y 20 tags en
14114
+ // beweossmbs (9 de ellos en `campaigns/.../AudienceReachStep.tsx`), 3 y 3 en beweanalytics. De
14115
+ // esos 23 tags, **solo 2 montan el popover**: los que beweanalytics puso a mano al migrar
14116
+ // (`toolbar-column-manager.component.tsx:85` y `toolbar-saved-views.component.tsx:78`). Los
14117
+ // otros 21 pintan el menú en línea, y uno de ellos está en una app YA migrada
14118
+ // (`beweanalytics/.../toolbar-bulk-actions.component.tsx:51`), que es la prueba de que esto se
14119
+ // olvida: es invisible hasta que alguien abre el menú.
14120
+ // Los 3+3 ficheros que el inventario contaba en `linda-business` y `chatbot-claw` son FALSOS
14121
+ // POSITIVOS: su `DropdownMenu` es el de Radix (`@radix-ui/react-dropdown-menu` vía un
14122
+ // `shared/ui/components/ui/dropdown-menu.tsx` estilo shadcn) y no toca esta librería.
14123
+ //
14124
+ // La partición es por IDENTIDAD de `child.type` contra los objetos reales de HeroUI, igual que
14125
+ // en la fachada `Table` — no por `displayName` ni por nombre. Y es CONSERVADORA: solo viaja al
14126
+ // popover lo que sabemos que va dentro (el menú); todo lo demás (el trigger, cualquier envoltorio
14127
+ // propio del consumidor) se queda fuera. Un falso negativo deja el comportamiento de hoy (menú en
14128
+ // línea, que el consumidor arregla montando el popover a mano); un falso positivo metería el
14129
+ // trigger dentro del popover y ROMPERÍA un dropdown que funcionaba.
14130
+ /** Lo que va DENTRO del popover: el menú. */
14131
+ const INSIDE_POPOVER = new Set([react.Dropdown.Menu]);
14132
+ /**
14133
+ * Si el consumidor ya monta uno de estos, la fachada no envuelve nada: el árbol es suyo.
14134
+ * `SubmenuTrigger` entra aquí porque trae su propio `Popover` dentro (aunque en la práctica vive
14135
+ * dentro del menú, no como hijo del root).
14136
+ */
14137
+ const OWN_POPOVER = new Set([
14138
+ react.Dropdown.Popover,
14139
+ react.Dropdown.SubmenuTrigger,
14140
+ ]);
14141
+ /** Identidad por `child.type` contra los objetos reales de HeroUI (patrón de la fachada `Table`). */
14142
+ function isPart(node, parts) {
14143
+ return $8WNJc$react.isValidElement(node) && parts.has(node.type);
14144
+ }
14145
+ const DropdownFacade = ({ children, ...props }) => {
14146
+ const nodes = $8WNJc$react.Children.toArray(children);
14147
+ const menus = nodes.filter((node) => isPart(node, INSIDE_POPOVER));
14148
+ // Nada que envolver (sin hijos, `children` como función, un popover ya montado a mano, o
14149
+ // simplemente ningún menú suelto): el root tal cual, byte a byte como el crudo de v3.
14150
+ if (menus.length === 0 || nodes.some((node) => isPart(node, OWN_POPOVER))) {
14151
+ return jsxRuntime.jsx(react.Dropdown, { ...props, children: children });
14152
+ }
14153
+ return (jsxRuntime.jsxs(react.Dropdown, { ...props, children: [nodes.filter((node) => !isPart(node, INSIDE_POPOVER)), jsxRuntime.jsx(react.Dropdown.Popover, { offset: 7, placement: "bottom", children: menus })] }));
14154
+ };
14155
+ DropdownFacade.displayName = "Aurora.Dropdown";
14156
+ /**
14157
+ * `Dropdown` de Aurora: el root de v3 **más el `Dropdown.Popover` que faltaba**, con el compound
14158
+ * completo colgado como estáticos y `Dropdown.Section` apuntando a la FACHADA de la sección.
14159
+ *
14160
+ * Dos defectos de la migración en una pieza:
14161
+ * 1. **El popover que v3 exige** y v2 no pedía: sin él el menú se pinta en línea (ver el bloque
14162
+ * de comentarios de arriba). La fachada lo inserta si falta y respeta el del consumidor si ya
14163
+ * está.
14164
+ * 2. **La cabecera de sección**: si solo se pisara el `DropdownSection` plano,
14165
+ * `Dropdown.Section` seguiría siendo el crudo de v3 y la misma pieza aceptaría `title` o no
14166
+ * según por qué nombre se llegue — el "falso amigo" que ya costó rondas en
14167
+ * Alert/Checkbox/Switch (el tipo v2 compilaba pero el componente era el de v3).
14168
+ *
14169
+ * `Dropdown.Root` queda deliberadamente crudo (el `MenuTrigger` pelado de v3, sin popover),
14170
+ * igual que en `Table`: vía de escape para montar la anatomía a mano.
14171
+ */
14172
+ const Dropdown = Object.assign(DropdownFacade, {
14173
+ Item: react.Dropdown.Item,
14174
+ ItemIndicator: react.Dropdown.ItemIndicator,
14175
+ Menu: react.Dropdown.Menu,
14176
+ Popover: react.Dropdown.Popover,
14177
+ Root: react.Dropdown.Root,
14178
+ Section: DropdownSection,
14179
+ SubmenuIndicator: react.Dropdown.SubmenuIndicator,
14180
+ SubmenuTrigger: react.Dropdown.SubmenuTrigger,
14181
+ Trigger: react.Dropdown.Trigger,
14182
+ });
14183
+
13971
14184
  /**
13972
14185
  * Tooltip - Componente BeweOS basado en HeroUI.
13973
14186
  *
@@ -14820,10 +15033,6 @@ Object.defineProperty(exports, "DrawerHeader", {
14820
15033
  enumerable: true,
14821
15034
  get: function () { return react.DrawerHeader; }
14822
15035
  });
14823
- Object.defineProperty(exports, "Dropdown", {
14824
- enumerable: true,
14825
- get: function () { return react.Dropdown; }
14826
- });
14827
15036
  Object.defineProperty(exports, "DropdownItem", {
14828
15037
  enumerable: true,
14829
15038
  get: function () { return react.DropdownItem; }
@@ -14832,10 +15041,6 @@ Object.defineProperty(exports, "DropdownMenu", {
14832
15041
  enumerable: true,
14833
15042
  get: function () { return react.DropdownMenu; }
14834
15043
  });
14835
- Object.defineProperty(exports, "DropdownSection", {
14836
- enumerable: true,
14837
- get: function () { return react.DropdownSection; }
14838
- });
14839
15044
  Object.defineProperty(exports, "DropdownTrigger", {
14840
15045
  enumerable: true,
14841
15046
  get: function () { return react.DropdownTrigger; }
@@ -14949,6 +15154,8 @@ exports.DateSelector = DateSelector;
14949
15154
  exports.Divider = Divider;
14950
15155
  exports.DonutChart = DonutChart;
14951
15156
  exports.DrawerFilters = DrawerFilters;
15157
+ exports.Dropdown = Dropdown;
15158
+ exports.DropdownSection = DropdownSection;
14952
15159
  exports.EmailPreview = EmailPreview;
14953
15160
  exports.GlobalToast = GlobalToast;
14954
15161
  exports.H1 = H1;