@beweco/aurora-ui 1.0.0-beta.136 → 1.0.0-beta.138
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/css/styles.css +1 -1
- package/dist/index.cjs.js +332 -51
- package/dist/index.esm.js +334 -47
- package/dist/types/components/tabs/Tabs.d.ts +65 -0
- package/dist/types/components/tabs/Tabs.d.ts.map +1 -0
- package/dist/types/components/tabs/Tabs.types.d.ts +24 -0
- package/dist/types/components/tabs/Tabs.types.d.ts.map +1 -0
- package/dist/types/components/tabs/index.d.ts +3 -0
- package/dist/types/components/tabs/index.d.ts.map +1 -0
- package/dist/types/components/textarea/Textarea.d.ts.map +1 -1
- package/dist/types/components/textarea/Textarea.types.d.ts +14 -0
- package/dist/types/components/textarea/Textarea.types.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -518,7 +518,7 @@ const SHAPE_BY_VARIANT = {
|
|
|
518
518
|
// Por eso `SIZE_CLASS` vuelve al `px` del slot `base` de v2 y el sangrado del texto pasa a
|
|
519
519
|
// `CONTENT_PADDING` (abajo), con `gap-0` para anular el `gap-0.5` que v3 mete en `.chip` y que v2
|
|
520
520
|
// no tenía (en v2 TODA la separación salía de paddings).
|
|
521
|
-
const SIZE_CLASS$
|
|
521
|
+
const SIZE_CLASS$6 = {
|
|
522
522
|
sm: "h-6 px-1 gap-0 text-xs font-normal",
|
|
523
523
|
md: "h-7 px-1 gap-0 text-sm font-normal",
|
|
524
524
|
lg: "h-8 px-2 gap-0 text-base font-normal",
|
|
@@ -761,7 +761,7 @@ const Chip = ({ color = "default", variant = "solid", size = "md", radius = "ful
|
|
|
761
761
|
// Con una cadena suelta ambas clases llegan al DOM y gana la que Tailwind emita más
|
|
762
762
|
// tarde, no la del consumidor. Todas las clases de aquí son vocabulario v3 válido, así
|
|
763
763
|
// que tailwind-merge las resuelve bien (la trampa de F1 era con clases v2 muertas).
|
|
764
|
-
className: react.cn(SIZE_CLASS$
|
|
764
|
+
className: react.cn(SIZE_CLASS$6[size],
|
|
765
765
|
// Después de `SIZE_CLASS` a propósito: el cuadrado de un carácter ENCOGE la caja
|
|
766
766
|
// respecto al tamaño normal y tiene que ganar en tailwind-merge.
|
|
767
767
|
isSquare ? ONE_CHAR_CLASS[size] : "", RADIUS_CLASS$9[radius], outlineClass, flatDarkFgClass, customClass, isDisabled ? "opacity-50 pointer-events-none" : "", classNames?.base, className), style: style, "aria-disabled": isDisabled || undefined, children: [startContent, jsxRuntime.jsx("span", { className: react.cn("flex-1 text-inherit font-normal", startContent
|
|
@@ -1188,12 +1188,12 @@ exports.HolidayType = void 0;
|
|
|
1188
1188
|
// Mismo mecanismo que Input/Select (findings/campo-texto-responsive-sm-trap.md):
|
|
1189
1189
|
// `.date-input-group__input` fija su propio `text-base sm:text-sm` — se repite la clase de
|
|
1190
1190
|
// tamaño de TEXTO directo en `DateField.Input`, no solo en el `DateField.Group` contenedor.
|
|
1191
|
-
const SIZE_CLASS$
|
|
1191
|
+
const SIZE_CLASS$5 = {
|
|
1192
1192
|
sm: "min-h-8 h-8",
|
|
1193
1193
|
md: "min-h-10 h-10",
|
|
1194
1194
|
lg: "min-h-12 h-12",
|
|
1195
1195
|
};
|
|
1196
|
-
const SIZE_TEXT_CLASS$
|
|
1196
|
+
const SIZE_TEXT_CLASS$4 = {
|
|
1197
1197
|
sm: "text-sm",
|
|
1198
1198
|
md: "text-sm",
|
|
1199
1199
|
lg: "text-base",
|
|
@@ -1266,23 +1266,23 @@ function DatePicker({ label, description, errorMessage, id, size = "md", variant
|
|
|
1266
1266
|
return (jsxRuntime.jsxs(react.DatePicker, { ...props, id: autoId, "aria-label": ariaLabel, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, className: ["flex flex-col gap-1", fullWidth ? "w-full" : "", className]
|
|
1267
1267
|
.filter(Boolean)
|
|
1268
1268
|
.join(" "), children: [label && (jsxRuntime.jsx(react.Label, { className: "text-default-600 text-xs font-medium", children: label })), jsxRuntime.jsxs(react.DateField.Group, { fullWidth: fullWidth, className: [
|
|
1269
|
-
SIZE_CLASS$
|
|
1269
|
+
SIZE_CLASS$5[size],
|
|
1270
1270
|
RADIUS_CLASS$8[radius],
|
|
1271
1271
|
VARIANT_CLASS$5[variant],
|
|
1272
1272
|
FIELD_FOCUS_CLASS$5,
|
|
1273
1273
|
]
|
|
1274
1274
|
.filter(Boolean)
|
|
1275
|
-
.join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { className: SIZE_TEXT_CLASS$
|
|
1275
|
+
.join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { className: SIZE_TEXT_CLASS$4[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 })] }));
|
|
1276
1276
|
}
|
|
1277
1277
|
|
|
1278
1278
|
// Mismo mecanismo que DatePicker.tsx / Input.tsx / Select.tsx (findings/
|
|
1279
1279
|
// campo-texto-responsive-sm-trap.md).
|
|
1280
|
-
const SIZE_CLASS$
|
|
1280
|
+
const SIZE_CLASS$4 = {
|
|
1281
1281
|
sm: "min-h-8 h-8",
|
|
1282
1282
|
md: "min-h-10 h-10",
|
|
1283
1283
|
lg: "min-h-12 h-12",
|
|
1284
1284
|
};
|
|
1285
|
-
const SIZE_TEXT_CLASS$
|
|
1285
|
+
const SIZE_TEXT_CLASS$3 = {
|
|
1286
1286
|
sm: "text-sm",
|
|
1287
1287
|
md: "text-sm",
|
|
1288
1288
|
lg: "text-base",
|
|
@@ -1358,13 +1358,13 @@ function DateRangePicker({ label, description, errorMessage, id, size = "md", va
|
|
|
1358
1358
|
return (jsxRuntime.jsxs(react.DateRangePicker, { ...props, id: autoId, "aria-label": ariaLabel, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, className: ["flex flex-col gap-1", fullWidth ? "w-full" : "", className]
|
|
1359
1359
|
.filter(Boolean)
|
|
1360
1360
|
.join(" "), children: [label && (jsxRuntime.jsx(react.Label, { className: "text-default-600 text-xs font-medium", children: label })), jsxRuntime.jsxs(react.DateField.Group, { fullWidth: fullWidth, className: [
|
|
1361
|
-
SIZE_CLASS$
|
|
1361
|
+
SIZE_CLASS$4[size],
|
|
1362
1362
|
RADIUS_CLASS$7[radius],
|
|
1363
1363
|
VARIANT_CLASS$4[variant],
|
|
1364
1364
|
FIELD_FOCUS_CLASS$4,
|
|
1365
1365
|
]
|
|
1366
1366
|
.filter(Boolean)
|
|
1367
|
-
.join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { slot: "start", className: SIZE_TEXT_CLASS$
|
|
1367
|
+
.join(" "), children: [jsxRuntime.jsx(react.DateField.Input, { slot: "start", className: SIZE_TEXT_CLASS$3[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$3[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 })] }));
|
|
1368
1368
|
}
|
|
1369
1369
|
|
|
1370
1370
|
// TECH-2459 · F3.0 — v3 divide el `Input` monolítico de v2 en `TextField` (label/description/
|
|
@@ -1379,7 +1379,7 @@ function DateRangePicker({ label, description, errorMessage, id, size = "md", va
|
|
|
1379
1379
|
// `md: h-10 min-h-10` · `lg: h-12 min-h-12` (los dos últimos heredan el `px-3` de la base).
|
|
1380
1380
|
// Verificado además contra los PNG de v2: `input--small` 32px de alto y 10px del borde exterior al
|
|
1381
1381
|
// texto (2 de borde + 8 de padding) · `--medium` 40px y 14px (2 + 12) · `--large` 48px y 14px.
|
|
1382
|
-
const SIZE_CLASS$
|
|
1382
|
+
const SIZE_CLASS$3 = {
|
|
1383
1383
|
sm: "min-h-8 h-8",
|
|
1384
1384
|
md: "min-h-10 h-10",
|
|
1385
1385
|
lg: "min-h-12 h-12",
|
|
@@ -1416,7 +1416,7 @@ const PADDING_FULL_CLASS$1 = {
|
|
|
1416
1416
|
// medía 40px de alto en vez de 32, porque 20px de línea + 16 de padding no caben en `h-8`).
|
|
1417
1417
|
// El hueco entre el contenido de los extremos y el texto lo pone `ps-1.5`/`pe-1.5`, que es
|
|
1418
1418
|
// exactamente lo que hacía v2 (`data-[has-start-content=true]:ps-1.5`).
|
|
1419
|
-
const SIZE_TEXT_CLASS$
|
|
1419
|
+
const SIZE_TEXT_CLASS$2 = {
|
|
1420
1420
|
sm: "text-sm",
|
|
1421
1421
|
md: "text-sm",
|
|
1422
1422
|
lg: "text-base",
|
|
@@ -1734,11 +1734,11 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
|
|
|
1734
1734
|
return (jsxRuntime.jsxs(react.TextField, { id: inputId, name: name, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, isReadOnly: isReadOnly, className: react.cn(FIELD_STACK_CLASS$3[size], fullWidth ? "w-full" : "",
|
|
1735
1735
|
// El `className` del consumidor, en la raíz y en último lugar: el slot `base` de
|
|
1736
1736
|
// v2 y la posición que le deja ganar en tailwind-merge (ver bloque de arriba).
|
|
1737
|
-
className), children: [label && (jsxRuntime.jsx(react.Label, { className: react.cn(LABEL_CLASS$4, LABEL_LEFT_CLASS[variant], variant === "underlined" ? "top-0" : LABEL_OFFSET_CLASS$1[size], isInvalid ? INVALID_LABEL_CLASS$2 : "", labelFlotante ? LABEL_INSIDE_CLASS[size] : "", labelFlotante ? LABEL_FLOAT_CLASS : "", classNames?.label), children: label })), jsxRuntime.jsxs(react.InputGroup, { isInvalid: isInvalid, isDisabled: isDisabled, isReadOnly: isReadOnly, className: react.cn(SIZE_CLASS$
|
|
1737
|
+
className), children: [label && (jsxRuntime.jsx(react.Label, { className: react.cn(LABEL_CLASS$4, LABEL_LEFT_CLASS[variant], variant === "underlined" ? "top-0" : LABEL_OFFSET_CLASS$1[size], isInvalid ? INVALID_LABEL_CLASS$2 : "", labelFlotante ? LABEL_INSIDE_CLASS[size] : "", labelFlotante ? LABEL_FLOAT_CLASS : "", classNames?.label), children: label })), jsxRuntime.jsxs(react.InputGroup, { isInvalid: isInvalid, isDisabled: isDisabled, isReadOnly: isReadOnly, className: react.cn(SIZE_CLASS$3[size], radius === "full" ? PADDING_FULL_CLASS$1[size] : PADDING_CLASS$2[size], variant === "underlined" ? UNDERLINED_INNER_CLASS$1[size] : "", RADIUS_CLASS$6[radius], VARIANT_CLASS$3[variant], FIELD_FOCUS_CLASS$3, FIELD_SHADOW_CLASS$2,
|
|
1738
1738
|
// Incondicional, como el `inputWrapper` de v2: la caja del campo llena
|
|
1739
1739
|
// siempre su raíz, y es la raíz la que responde a `fullWidth` y al ancho que
|
|
1740
1740
|
// pase el consumidor.
|
|
1741
|
-
"w-full", classNames?.inputWrapper), 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: react.cn("bg-transparent p-0", SIZE_TEXT_CLASS$
|
|
1741
|
+
"w-full", classNames?.inputWrapper), 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: react.cn("bg-transparent p-0", SIZE_TEXT_CLASS$2[size], isInvalid ? INVALID_TEXT_CLASS$2 : "", startContent ? "ps-1.5" : "", endContent || showClear ? "pe-1.5" : "", classNames?.input) }), showClear && (jsxRuntime.jsx(react.CloseButton, { "aria-label": "Limpiar", className: "h-4 w-4 min-h-0 p-0.5 mr-1", onPress: handleClear })), endContent && (jsxRuntime.jsx(react.InputGroup.Suffix, { className: "border-none bg-transparent px-0", children: endContent }))] }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: react.cn(HELPER_CLASS$2, "text-left", classNames?.description), children: description })), isInvalid && errorMessage && (jsxRuntime.jsx(react.FieldError, { className: react.cn(HELPER_CLASS$2, "text-left", classNames?.errorMessage), children: errorMessage }))] }));
|
|
1742
1742
|
});
|
|
1743
1743
|
Input.displayName = "Input";
|
|
1744
1744
|
|
|
@@ -2285,7 +2285,7 @@ const OPCIONES_CLASS = [
|
|
|
2285
2285
|
* componente el label era propio de Aurora y llevaba un `mb-2` fijo (8px) para los tres. Por eso
|
|
2286
2286
|
* `FIELD_STACK_CLASS` es una constante y no un registro.
|
|
2287
2287
|
*/
|
|
2288
|
-
const SIZE_CLASS$
|
|
2288
|
+
const SIZE_CLASS$2 = {
|
|
2289
2289
|
sm: "min-h-8 h-8",
|
|
2290
2290
|
md: "min-h-10 h-10",
|
|
2291
2291
|
lg: "min-h-12 h-12",
|
|
@@ -2458,7 +2458,7 @@ isClearable = true, isReadOnly, inputValue, selectedKey, onInputChange, onSelect
|
|
|
2458
2458
|
inputRef.current?.focus();
|
|
2459
2459
|
};
|
|
2460
2460
|
return (jsxRuntime.jsxs(react.ComboBox, { id: autoId, isDisabled: isDisabled, isReadOnly: isReadOnly, inputValue: inputValue, selectedKey: selectedKey, onInputChange: onInputChange, onSelectionChange: onSelectionChange, className: [FIELD_STACK_CLASS$2, className].filter(Boolean).join(" "), ...props, children: [label && jsxRuntime.jsx(react.Label, { className: LABEL_CLASS$3, children: label }), jsxRuntime.jsxs(react.ComboBox.InputGroup, { className: [
|
|
2461
|
-
SIZE_CLASS$
|
|
2461
|
+
SIZE_CLASS$2[size],
|
|
2462
2462
|
PADDING_CLASS$1[size],
|
|
2463
2463
|
variant === "underlined" ? UNDERLINED_INNER_CLASS[size] : "",
|
|
2464
2464
|
FIELD_CLASS$1,
|
|
@@ -5301,7 +5301,7 @@ KanbanCard.displayName = "KanbanCard";
|
|
|
5301
5301
|
* `.button`/`.card`/`.chip`) y además arreglaría el Badge crudo de HeroUI que documenta la story
|
|
5302
5302
|
* `HeroUI Components/Badge`; queda reportado para ese lane.
|
|
5303
5303
|
*/
|
|
5304
|
-
const SIZE_CLASS$
|
|
5304
|
+
const SIZE_CLASS$1 = {
|
|
5305
5305
|
sm: "min-h-4 min-w-4", // v2: w-4 h-4 = 16px
|
|
5306
5306
|
md: "min-h-5 min-w-5", // v2: w-5 h-5 = 20px
|
|
5307
5307
|
lg: "min-h-6 min-w-6", // v2: w-6 h-6 = 24px
|
|
@@ -5359,7 +5359,7 @@ const DEFAULT_COLOR_STYLE = {
|
|
|
5359
5359
|
};
|
|
5360
5360
|
const BadgeRoot = ({ size = "md", color = "default", variant = "primary", className, style, content, isInvisible, children, ...props }) => {
|
|
5361
5361
|
const needsDefaultToken = color === "default" && variant === "primary";
|
|
5362
|
-
const badge = (jsxRuntime.jsx(react.Badge, { ...props, color: color, variant: variant, size: size, className: ["border-2", SIZE_CLASS$
|
|
5362
|
+
const badge = (jsxRuntime.jsx(react.Badge, { ...props, color: color, variant: variant, size: size, className: ["border-2", SIZE_CLASS$1[size], className]
|
|
5363
5363
|
.filter(Boolean)
|
|
5364
5364
|
.join(" "), style: needsDefaultToken ? { ...DEFAULT_COLOR_STYLE, ...style } : style, children: isV2Api(content, isInvisible) ? content : children }));
|
|
5365
5365
|
// API v3: los `children` SON el contenido del badge y el anclaje lo compone el consumidor con
|
|
@@ -8588,9 +8588,9 @@ const SearchInput = ({ searchPlaceholder = "Buscar...", searchIcon = "solar:magn
|
|
|
8588
8588
|
};
|
|
8589
8589
|
|
|
8590
8590
|
/** El indicador ya montado a mano por el consumidor: no se duplica. */
|
|
8591
|
-
function hasIndicator(children) {
|
|
8591
|
+
function hasIndicator$1(children) {
|
|
8592
8592
|
if (Array.isArray(children)) {
|
|
8593
|
-
return children.some(hasIndicator);
|
|
8593
|
+
return children.some(hasIndicator$1);
|
|
8594
8594
|
}
|
|
8595
8595
|
return $8WNJc$react.isValidElement(children) && children.type === react.ListBoxItem.Indicator;
|
|
8596
8596
|
}
|
|
@@ -8626,7 +8626,7 @@ function withItemIndicator(children) {
|
|
|
8626
8626
|
const next = (values) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [render(values), jsxRuntime.jsx(react.ListBoxItem.Indicator, {})] }));
|
|
8627
8627
|
return $8WNJc$react.cloneElement(element, { children: next });
|
|
8628
8628
|
}
|
|
8629
|
-
if (hasIndicator(original)) {
|
|
8629
|
+
if (hasIndicator$1(original)) {
|
|
8630
8630
|
return element;
|
|
8631
8631
|
}
|
|
8632
8632
|
const next = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [original, jsxRuntime.jsx(react.ListBoxItem.Indicator, {})] }));
|
|
@@ -8640,7 +8640,7 @@ function withItemIndicator(children) {
|
|
|
8640
8640
|
// min-h-10` · `lg: h-12 min-h-12` — las mismas medidas que el Input, como era de esperar.
|
|
8641
8641
|
// Verificado contra el PNG de v2: `select--medium` mide 40px de alto y 14px del borde exterior al
|
|
8642
8642
|
// texto (2 de borde + 12 de padding).
|
|
8643
|
-
const SIZE_CLASS
|
|
8643
|
+
const SIZE_CLASS = {
|
|
8644
8644
|
sm: "min-h-8 h-8 text-sm",
|
|
8645
8645
|
md: "min-h-10 h-10 text-sm",
|
|
8646
8646
|
lg: "min-h-12 h-12 text-base",
|
|
@@ -8668,7 +8668,7 @@ const TRIGGER_ALIGN_CLASS = "items-center py-0";
|
|
|
8668
8668
|
// `.input-group__input` (ver Input.tsx) — el tamaño de texto del trigger no llega al texto
|
|
8669
8669
|
// seleccionado por herencia. Se repite aquí, directo sobre `Select.Value` (comprobado con
|
|
8670
8670
|
// `className` computado en el DOM).
|
|
8671
|
-
const SIZE_TEXT_CLASS = {
|
|
8671
|
+
const SIZE_TEXT_CLASS$1 = {
|
|
8672
8672
|
sm: "text-sm",
|
|
8673
8673
|
md: "text-sm",
|
|
8674
8674
|
lg: "text-base",
|
|
@@ -9057,7 +9057,7 @@ fullWidth = true, isOpen, defaultOpen, onOpenChange, className, classNames, tran
|
|
|
9057
9057
|
// Mismo criterio que el `group-data-[has-helper=true]` de v2: cuenta como "con ayuda" el campo
|
|
9058
9058
|
// que efectivamente PINTA una descripción o un mensaje de error, no el que solo recibe la prop.
|
|
9059
9059
|
const hasHelper = Boolean((description && !isInvalid) || (isInvalid && errorMessage));
|
|
9060
|
-
const triggerClassName = react.cn(SIZE_CLASS
|
|
9060
|
+
const triggerClassName = react.cn(SIZE_CLASS[size], radius === "full" ? PADDING_FULL_CLASS[size] : PADDING_CLASS[size], TRIGGER_ALIGN_CLASS, RADIUS_CLASS$4[radius], VARIANT_CLASS$1[variant],
|
|
9061
9061
|
// En v2 el estado inválido MANDABA también con el campo enfocado
|
|
9062
9062
|
// (`group-data-[focus=true]:!border-danger`), así que el borde de foco no se aplica cuando
|
|
9063
9063
|
// el campo está en error: se queda el `danger`.
|
|
@@ -9070,7 +9070,7 @@ fullWidth = true, isOpen, defaultOpen, onOpenChange, className, classNames, tran
|
|
|
9070
9070
|
"w-full", classNames?.trigger);
|
|
9071
9071
|
const inner = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [label && (jsxRuntime.jsx(react.Label, { className: react.cn(LABEL_CLASS$1, hasHelper
|
|
9072
9072
|
? LABEL_OFFSET_HELPER_CLASS[size]
|
|
9073
|
-
: LABEL_OFFSET_CLASS[size], isInvalid ? INVALID_LABEL_CLASS$1 : "", classNames?.label), children: label })), jsxRuntime.jsxs(react.Select.Trigger, { className: triggerClassName, children: [jsxRuntime.jsx(react.Select.Value, { className: react.cn(SIZE_TEXT_CLASS[size], VALUE_ROOM_CLASS, isInvalid ? INVALID_TEXT_CLASS$1 : "") }), jsxRuntime.jsx(react.Select.Indicator, { className: "end-3" })] }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: `${HELPER_CLASS$1} text-left`, children: description })), jsxRuntime.jsx(react.Select.Popover, { className: classNames?.popoverContent, children: jsxRuntime.jsx(react.ListBox
|
|
9073
|
+
: LABEL_OFFSET_CLASS[size], isInvalid ? INVALID_LABEL_CLASS$1 : "", classNames?.label), children: label })), jsxRuntime.jsxs(react.Select.Trigger, { className: triggerClassName, children: [jsxRuntime.jsx(react.Select.Value, { className: react.cn(SIZE_TEXT_CLASS$1[size], VALUE_ROOM_CLASS, isInvalid ? INVALID_TEXT_CLASS$1 : "") }), jsxRuntime.jsx(react.Select.Indicator, { className: "end-3" })] }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: `${HELPER_CLASS$1} text-left`, children: description })), jsxRuntime.jsx(react.Select.Popover, { className: classNames?.popoverContent, children: jsxRuntime.jsx(react.ListBox
|
|
9074
9074
|
// El hueco que v2 llenaba con su `emptyContent` (ver el bloque de
|
|
9075
9075
|
// `DEFAULT_TRANSLATIONS`). `renderEmptyState` es la vía de v3: el `ListBox` de
|
|
9076
9076
|
// react-aria solo pinta algo con la colección vacía si se le pasa, y envuelve
|
|
@@ -9276,17 +9276,17 @@ const OWN_SCROLL = new Set([
|
|
|
9276
9276
|
react.Table.ResizableContainer,
|
|
9277
9277
|
]);
|
|
9278
9278
|
/** Identidad por `child.type` contra los objetos reales de HeroUI (mismo patrón que la fachada `Alert`). */
|
|
9279
|
-
function isPart$
|
|
9279
|
+
function isPart$2(node, parts) {
|
|
9280
9280
|
return $8WNJc$react.isValidElement(node) && parts.has(node.type);
|
|
9281
9281
|
}
|
|
9282
9282
|
const TableFacade = ({ children, ...props }) => {
|
|
9283
9283
|
const nodes = $8WNJc$react.Children.toArray(children);
|
|
9284
9284
|
// Sin hijos, o con un contenedor de scroll ya montado a mano: el root tal cual.
|
|
9285
|
-
if (nodes.length === 0 || nodes.some((node) => isPart$
|
|
9285
|
+
if (nodes.length === 0 || nodes.some((node) => isPart$2(node, OWN_SCROLL))) {
|
|
9286
9286
|
return jsxRuntime.jsx(react.Table, { ...props, children: children });
|
|
9287
9287
|
}
|
|
9288
|
-
const scrollable = nodes.filter((node) => !isPart$
|
|
9289
|
-
const outsideScroll = nodes.filter((node) => isPart$
|
|
9288
|
+
const scrollable = nodes.filter((node) => !isPart$2(node, OUTSIDE_SCROLL));
|
|
9289
|
+
const outsideScroll = nodes.filter((node) => isPart$2(node, OUTSIDE_SCROLL));
|
|
9290
9290
|
return (jsxRuntime.jsxs(react.Table, { ...props, children: [jsxRuntime.jsx(react.Table.ScrollContainer, { children: scrollable }), outsideScroll] }));
|
|
9291
9291
|
};
|
|
9292
9292
|
TableFacade.displayName = "Aurora.Table";
|
|
@@ -9378,18 +9378,70 @@ function AuraTable({ columns, items, renderCell, children, className, ...props }
|
|
|
9378
9378
|
// borde/fondo/tamaño de texto viven todos en el MISMO elemento — ver `textarea.css`). Por eso no
|
|
9379
9379
|
// hace falta repetir la clase de tamaño de texto en un hijo aparte (el hallazgo
|
|
9380
9380
|
// `campo-texto-responsive-sm-trap.md` no aplica: no hay wrapper distinto del elemento con texto).
|
|
9381
|
+
// El tamaño de TEXTO depende de `size`; el ALTO depende de `minRows` — por eso van en dos
|
|
9382
|
+
// constantes separadas y no en una sola clase con el alto a fuego (ver el bloque siguiente).
|
|
9383
|
+
const SIZE_TEXT_CLASS = {
|
|
9384
|
+
sm: "text-sm",
|
|
9385
|
+
md: "text-sm",
|
|
9386
|
+
lg: "text-base",
|
|
9387
|
+
};
|
|
9381
9388
|
// Alto mínimo con la fórmula de v2, no con un paso redondo de Tailwind: v2 no fijaba altura al
|
|
9382
9389
|
// multilínea (`isMultiline` → `inputWrapper: "!h-auto"`), la altura salía de `minRows` (3 por
|
|
9383
9390
|
// defecto) por el alto de línea, más el `py-2` que el compound `outside + isMultiline` añadía y los
|
|
9384
9391
|
// 2px de borde de cada lado:
|
|
9385
|
-
// sm/md (texto 14px, línea 20) →
|
|
9386
|
-
// lg (texto 16px, línea 24) →
|
|
9392
|
+
// sm/md (texto 14px, línea 20) → minRows·20 + 16 + 4 → 3 líneas = 80px
|
|
9393
|
+
// lg (texto 16px, línea 24) → minRows·24 + 16 + 4 → 3 líneas = 92px
|
|
9387
9394
|
// Comprobado contra el PNG de v2: `textarea--default` (que pasa `size="lg"`) mide exactamente 92px.
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9395
|
+
//
|
|
9396
|
+
// Hasta TECH-2459 esto eran dos clases fijas (`min-h-20` / `min-h-[92px]`) que ya llevaban el
|
|
9397
|
+
// `minRows = 3` metido dentro, así que el campo medía 80/92px pidiera el consumidor las líneas que
|
|
9398
|
+
// pidiera: en `beweossmbs` (la única app sin migrar) hay 27 usos de `minRows` reclamando SEIS
|
|
9399
|
+
// alturas distintas —1, 2, 3, 4, 6 y 8 líneas— y solo los 8 de "3 líneas" salían bien. Con la
|
|
9400
|
+
// fórmula, `minRows = 3` sigue dando 80/92px exactos: ninguna app que no pase la prop se mueve.
|
|
9401
|
+
const SIZE_LINE_HEIGHT = {
|
|
9402
|
+
sm: 20,
|
|
9403
|
+
md: 20,
|
|
9404
|
+
lg: 24,
|
|
9405
|
+
};
|
|
9406
|
+
// El `py-2` que `.textarea` de v3 se aplica a sí mismo: 8px arriba + 8 abajo (verificado en
|
|
9407
|
+
// `node_modules/@heroui/styles/dist/components/textarea.css`, no deducido del PNG).
|
|
9408
|
+
const FIELD_PADDING_Y = 16;
|
|
9409
|
+
// Los 2px de borde por lado del `bordered`/`faded` de v2 (`box-sizing: border-box`).
|
|
9410
|
+
const FIELD_BORDER_Y = 4;
|
|
9411
|
+
// El default de v2, literal: `({ minRows = 3, maxRows = 8, … })` en `@heroui/input@2.4.22`,
|
|
9412
|
+
// `dist/chunk-RIE4DNUQ.mjs`.
|
|
9413
|
+
const DEFAULT_MIN_ROWS = 3;
|
|
9414
|
+
// ── `minRows` gana al atributo nativo `rows` ─────────────────────────────────────────────────
|
|
9415
|
+
//
|
|
9416
|
+
// Las dos props dicen lo mismo —cuántas líneas de alto tiene la caja al aparecer— así que la
|
|
9417
|
+
// fachada las unifica en un solo número (`minRows ?? rows ?? 3`) y las trata igual. Cuando llegan
|
|
9418
|
+
// LAS DOS manda `minRows`, y eso no es un gusto: es lo que hacía v2, medido en el paquete v2
|
|
9419
|
+
// instalado (`beweossmbs/node_modules`), por dos caminos independientes.
|
|
9420
|
+
//
|
|
9421
|
+
// 1. v2 desestructuraba `minRows` y se lo pasaba a `TextareaAutosize`, que fija la altura con
|
|
9422
|
+
// `node.style.setProperty("height", height + "px", "important")` — un inline con
|
|
9423
|
+
// `!important` que ningún atributo `rows` puede discutir (`react-textarea-autosize@8.5.9`,
|
|
9424
|
+
// `calculateNodeHeight` + `resizeTextarea`).
|
|
9425
|
+
// 2. Y el `rows` del consumidor no llegaba ni al DOM: `useInput` filtraba las props ajenas con
|
|
9426
|
+
// `filterDOMProps(otherProps, { enabled: true, labelable: true })`, cuya lista blanca es
|
|
9427
|
+
// `id` + los cuatro `aria-*` etiquetables + `data-*` (`@react-aria/utils`,
|
|
9428
|
+
// `dist/filterDOMProps.mjs`), y `useTextField` tampoco lo emite. En v2 `rows` era INERTE.
|
|
9429
|
+
//
|
|
9430
|
+
// En v3 sí llega (viaja en `...rest` hasta el `<textarea>`), de modo que aquí se desestructura para
|
|
9431
|
+
// que no pelee con el alto mínimo: con `minRows={2} rows={8}`, el atributo daría 8 líneas de alto
|
|
9432
|
+
// intrínseco y ganaría a un `min-height` de 2. Se emite UN solo `rows`, el de la cuenta ya
|
|
9433
|
+
// resuelta, así el atributo nativo y el `min-height` nunca se contradicen (y el campo sale con su
|
|
9434
|
+
// alto incluso antes de que cargue la hoja de estilos: el intrínseco de N filas es
|
|
9435
|
+
// N·línea + 16 + 4 con borde, y menos sin él, así que jamás supera al `min-height`).
|
|
9436
|
+
//
|
|
9437
|
+
// `rows` se sigue aceptando —y con el mismo significado— porque hay 9 usos reales en las apps (3 en
|
|
9438
|
+
// `beweossmbs`, 1 en `beweosagency`, 5 en `backoffice-beweos`, verificados con el import de
|
|
9439
|
+
// `@beweco/aurora-ui` delante) y ninguno pasa las dos props a la vez.
|
|
9440
|
+
const resolveRows = (minRows, rows) =>
|
|
9441
|
+
// `Math.max(1, …)` y el redondeo son por el atributo: `rows` exige un entero ≥ 1 y el navegador
|
|
9442
|
+
// ignora cualquier otra cosa. v2 acababa igual de rebote (su altura era el máximo entre el
|
|
9443
|
+
// mínimo calculado y una línea de contenido).
|
|
9444
|
+
Math.max(1, Math.round(minRows ?? rows ?? DEFAULT_MIN_ROWS));
|
|
9393
9445
|
// v2 NO dejaba redimensionar el multilínea: su `tv` ponía `input: "resize-none …"` en la variante
|
|
9394
9446
|
// `isMultiline` (literal de `dist/components/input.js`). v3 deja el `<textarea>` con el
|
|
9395
9447
|
// comportamiento por defecto del navegador, que además de ser arrastrable PINTA el tirador en la
|
|
@@ -9511,7 +9563,10 @@ const INVALID_TEXT_CLASS = "text-danger";
|
|
|
9511
9563
|
* y acababa colgando el ref del contenedor y buscando el `<textarea>` con una query, y (b) era
|
|
9512
9564
|
* accidental: cualquier prop que se añadiese al destructuring lo habría cortado en silencio.
|
|
9513
9565
|
*/
|
|
9514
|
-
const Textarea = $8WNJc$react.forwardRef(({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md",
|
|
9566
|
+
const Textarea = $8WNJc$react.forwardRef(({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md",
|
|
9567
|
+
// Sin default en el destructuring a propósito: hace falta distinguir "no me la han pasado"
|
|
9568
|
+
// de un valor, para que `rows` solo se mire cuando `minRows` no viene (ver `resolveRows`).
|
|
9569
|
+
minRows, rows, placeholder, isInvalid = false, isRequired = false, isDisabled = false, isReadOnly = false,
|
|
9515
9570
|
// `fullWidth` por defecto a `true`: HeroUI v2 lo traía en sus `defaultVariants`
|
|
9516
9571
|
// (verificado en el paquete v2 compilado, `dist/components/input.js`:
|
|
9517
9572
|
// `defaultVariants: { variant:"flat", color:"default", size:"md", fullWidth:true, … }`, con
|
|
@@ -9519,9 +9574,18 @@ const Textarea = $8WNJc$react.forwardRef(({ label, description, errorMessage, id
|
|
|
9519
9574
|
// `undefined` y el campo dejaba de llenar su contenedor: en una fila flex se encogía al ancho
|
|
9520
9575
|
// de su contenido (medido por S2: 208px dentro de una fila de 592, 336px de hueco). En una
|
|
9521
9576
|
// columna no se notaba porque el `stretch` del flex lo tapaba — pero afecta a cualquier app.
|
|
9522
|
-
fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, name, ...rest }, ref) => {
|
|
9577
|
+
fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, name, style, ...rest }, ref) => {
|
|
9523
9578
|
const generatedId = $8WNJc$react.useId();
|
|
9524
9579
|
const textareaId = id || generatedId;
|
|
9580
|
+
const fieldRows = resolveRows(minRows, rows);
|
|
9581
|
+
// Inline y no una clase: el valor es un número arbitrario y Tailwind 4 solo emite las clases
|
|
9582
|
+
// que encuentra escritas en el fuente, así que `min-h-[${n}px]` no existiría en el CSS. El
|
|
9583
|
+
// `style` del consumidor va DESPUÉS para que pueda pisarlo (y una clase con `!` también gana,
|
|
9584
|
+
// que es el canal documentado en el README: `classNames={{ input: "min-h-40!" }}`).
|
|
9585
|
+
const fieldStyle = {
|
|
9586
|
+
minHeight: `${fieldRows * SIZE_LINE_HEIGHT[size] + FIELD_PADDING_Y + FIELD_BORDER_Y}px`,
|
|
9587
|
+
...style,
|
|
9588
|
+
};
|
|
9525
9589
|
const handleChange = (event) => {
|
|
9526
9590
|
onChange?.(event);
|
|
9527
9591
|
onValueChange?.(event.target.value);
|
|
@@ -9529,7 +9593,7 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
|
|
|
9529
9593
|
return (jsxRuntime.jsxs(react.TextField, { id: textareaId, name: name, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, isReadOnly: isReadOnly, className: react.cn(FIELD_STACK_CLASS, fullWidth ? "w-full" : "",
|
|
9530
9594
|
// El `className` del consumidor, en la raíz y en último lugar: el slot `base` de
|
|
9531
9595
|
// v2 y la posición que le deja ganar en tailwind-merge (ver bloque de arriba).
|
|
9532
|
-
className), children: [label && (jsxRuntime.jsx(react.Label, { className: react.cn(LABEL_CLASS, isInvalid ? INVALID_LABEL_CLASS : "", classNames?.label), children: label })), jsxRuntime.jsx(react.TextArea, { ...rest, ref: ref, placeholder: placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: react.cn(
|
|
9596
|
+
className), children: [label && (jsxRuntime.jsx(react.Label, { className: react.cn(LABEL_CLASS, isInvalid ? INVALID_LABEL_CLASS : "", classNames?.label), children: label })), jsxRuntime.jsx(react.TextArea, { ...rest, ref: ref, rows: fieldRows, style: fieldStyle, placeholder: placeholder, value: value, defaultValue: defaultValue, onChange: handleChange, className: react.cn(SIZE_TEXT_CLASS[size], RESIZE_CLASS, RADIUS_CLASS$3[radius], VARIANT_CLASS[variant], isInvalid ? INVALID_TEXT_CLASS : "", FIELD_FOCUS_CLASS, FIELD_SHADOW_CLASS,
|
|
9533
9597
|
// Incondicional, como el slot `input` de v2: el campo llena siempre su raíz,
|
|
9534
9598
|
// y es la raíz la que responde a `fullWidth` y al ancho del consumidor.
|
|
9535
9599
|
"w-full", classNames?.input ?? classNames?.inputWrapper) }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: react.cn(HELPER_CLASS, "text-left", classNames?.description), children: description })), isInvalid && errorMessage && (jsxRuntime.jsx(react.FieldError, { className: react.cn(HELPER_CLASS, "text-left", classNames?.errorMessage), children: errorMessage }))] }));
|
|
@@ -14675,18 +14739,18 @@ const OWN_POPOVER = new Set([
|
|
|
14675
14739
|
react.Dropdown.SubmenuTrigger,
|
|
14676
14740
|
]);
|
|
14677
14741
|
/** Identidad por `child.type` contra los objetos reales de HeroUI (patrón de la fachada `Table`). */
|
|
14678
|
-
function isPart(node, parts) {
|
|
14742
|
+
function isPart$1(node, parts) {
|
|
14679
14743
|
return $8WNJc$react.isValidElement(node) && parts.has(node.type);
|
|
14680
14744
|
}
|
|
14681
14745
|
const DropdownFacade = ({ children, ...props }) => {
|
|
14682
14746
|
const nodes = $8WNJc$react.Children.toArray(children);
|
|
14683
|
-
const menus = nodes.filter((node) => isPart(node, INSIDE_POPOVER));
|
|
14747
|
+
const menus = nodes.filter((node) => isPart$1(node, INSIDE_POPOVER));
|
|
14684
14748
|
// Nada que envolver (sin hijos, `children` como función, un popover ya montado a mano, o
|
|
14685
14749
|
// simplemente ningún menú suelto): el root tal cual, byte a byte como el crudo de v3.
|
|
14686
|
-
if (menus.length === 0 || nodes.some((node) => isPart(node, OWN_POPOVER))) {
|
|
14750
|
+
if (menus.length === 0 || nodes.some((node) => isPart$1(node, OWN_POPOVER))) {
|
|
14687
14751
|
return jsxRuntime.jsx(react.Dropdown, { ...props, children: children });
|
|
14688
14752
|
}
|
|
14689
|
-
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 })] }));
|
|
14753
|
+
return (jsxRuntime.jsxs(react.Dropdown, { ...props, children: [nodes.filter((node) => !isPart$1(node, INSIDE_POPOVER)), jsxRuntime.jsx(react.Dropdown.Popover, { offset: 7, placement: "bottom", children: menus })] }));
|
|
14690
14754
|
};
|
|
14691
14755
|
DropdownFacade.displayName = "Aurora.Dropdown";
|
|
14692
14756
|
/**
|
|
@@ -14717,6 +14781,229 @@ const Dropdown = Object.assign(DropdownFacade, {
|
|
|
14717
14781
|
Trigger: react.Dropdown.Trigger,
|
|
14718
14782
|
});
|
|
14719
14783
|
|
|
14784
|
+
// TECH-2459 — Fachada `Tabs` / `Tab`: monta las DOS piezas de la anatomía de v3 que, si la app
|
|
14785
|
+
// se las olvida, dejan la pestaña seleccionada sin distinguir. Hasta ahora `Tabs` y `Tab` eran
|
|
14786
|
+
// reexport crudo de v3 (`src/index.tsx`, bloque `from "@heroui/react"`) y no existía
|
|
14787
|
+
// `src/components/tabs/`: la anatomía entera quedaba a cargo de cada app.
|
|
14788
|
+
//
|
|
14789
|
+
// EL DEFECTO, medido por grep real en los repos de apps (no de memoria):
|
|
14790
|
+
//
|
|
14791
|
+
// | app | `<Tabs>` | `<Tabs.List>` | `<Tabs.ListContainer>` | tabs | `<Tabs.Indicator>` | resultado |
|
|
14792
|
+
// |-------------------|----------|---------------|------------------------|------|--------------------|-----------|
|
|
14793
|
+
// | beweosagency | 5 | 5 | 5 | 14 | **0** | la seleccionada sin píldora |
|
|
14794
|
+
// | backoffice-beweos | 5 | 5 | 5 | 18 | 18 (a mano) | bien |
|
|
14795
|
+
// | beweanalytics | 3 | 3 | 3 | 8 | 8 (a mano) | bien |
|
|
14796
|
+
// | beweossmbs / loginos / linda-business | 0 | 0 | 0 | 0 | 0 | no usan tabs |
|
|
14797
|
+
//
|
|
14798
|
+
// (conteo de tags de APERTURA; beweanalytics escribe `Tab` suelto en vez de `Tabs.Tab`.)
|
|
14799
|
+
// Dos lecturas que salen de esta tabla y que deciden el diseño:
|
|
14800
|
+
// · **26 indicadores montados a mano** contra 14 que faltan. La idempotencia no es un adorno:
|
|
14801
|
+
// sin ella esas 26 pestañas se quedarían con DOS indicadores.
|
|
14802
|
+
// · **`Tabs.List` y `Tabs.ListContainer` van 1:1 en las tres apps**, o sea que hoy NADIE usa la
|
|
14803
|
+
// forma delgada. Garantizar el carril es, para el código que existe hoy, un no-op medido; su
|
|
14804
|
+
// valor es que la próxima pantalla que se escriba no pueda caer en la forma delgada por
|
|
14805
|
+
// descuido.
|
|
14806
|
+
//
|
|
14807
|
+
// Las tres migraciones siguieron la misma guía; dos descubrieron que hacía falta el indicador y
|
|
14808
|
+
// una no, porque **nada en la API obliga a montarlo ni avisa**: compila en verde y se degrada en
|
|
14809
|
+
// silencio. Es el mismo patrón —y el mismo argumento— que ya justificó las fachadas `Table`
|
|
14810
|
+
// (`Table.ScrollContainer` ausente → columnas inalcanzables) y `Dropdown`
|
|
14811
|
+
// (`Dropdown.Popover` ausente → menú en línea).
|
|
14812
|
+
//
|
|
14813
|
+
// El criterio del usuario que lo convierte en trabajo de la librería y no de las apps:
|
|
14814
|
+
// «se supone que solo es llamar al componente dentro de la librería y ya se visualiza correcto;
|
|
14815
|
+
// asegúrate de que las apps no estén metiéndole fixes por separado».
|
|
14816
|
+
//
|
|
14817
|
+
// LAS DOS PIEZAS ESTÁN ACOPLADAS, y por eso la fachada monta las dos o ninguna:
|
|
14818
|
+
//
|
|
14819
|
+
// · `Tabs.Indicator` es quien pinta la píldora del seleccionado. Su CSS es
|
|
14820
|
+
// `.tabs__indicator { absolute start-0 top-0 size-full rounded-3xl bg-segment shadow-surface;
|
|
14821
|
+
// z-index:-1 }` (`@heroui/styles/dist/components/tabs.css:215-228`), y `--segment` es
|
|
14822
|
+
// `var(--white)` en claro y `oklch(39.64% .01 285.93)` (#46464c) en oscuro
|
|
14823
|
+
// (`@heroui/styles/dist/heroui.min.css`).
|
|
14824
|
+
// · `Tabs.ListContainer` es quien pinta el CARRIL sobre el que se ve esa píldora
|
|
14825
|
+
// (`.tabs__list-container { relative bg-default }`, `tabs.css:16-17`, que
|
|
14826
|
+
// `neutralize-v3.css` baja a `--color-default-100` = #f4f4f5 por contraste).
|
|
14827
|
+
// **Una píldora blanca sobre fondo blanco no se ve**, y el número: medido en Storybook, en
|
|
14828
|
+
// claro la píldora queda a **1.00:1** contra la página en la forma delgada y a **1.10:1**
|
|
14829
|
+
// contra el carril en la completa — sin carril lo único que sobrevive de ella es su sombra,
|
|
14830
|
+
// que en oscuro es transparente del todo. Garantizar solo el indicador cambiaría un defecto
|
|
14831
|
+
// por otro. La app que migró en la forma delgada ya lo documentó:
|
|
14832
|
+
// `beweanalytics/src/clientes/ui/pages/clientes.page.tsx:59-67`.
|
|
14833
|
+
//
|
|
14834
|
+
// Y `Tabs.Indicator` va DENTRO de cada `Tab`, nunca en la lista: `TabList` envuelve en
|
|
14835
|
+
// `SharedElementTransition` solo el `CollectionRoot`
|
|
14836
|
+
// (`react-aria-components/dist/private/Tabs.mjs:152`), así que un indicador suelto en la lista
|
|
14837
|
+
// lanza «<SharedElement> must be rendered inside a <SharedElementTransition>» y **la barra entera
|
|
14838
|
+
// desaparece del DOM**. De ahí que la inserción del indicador viva en la fachada del `Tab` y no
|
|
14839
|
+
// en la del root.
|
|
14840
|
+
//
|
|
14841
|
+
// LO QUE ESTA FACHADA NO HACE, y conste para que no se busque: no repone NADA del aspecto de v2
|
|
14842
|
+
// (radios, gap, padding, peso, la pastilla de v2). Eso se hizo en la `beta.132` y se retiró en la
|
|
14843
|
+
// `.133` por decisión del usuario (`.docs/migrate-heroui/DECISIONES.md` §9.1, «el objetivo NO es
|
|
14844
|
+
// identidad de píxel» y, sobre este componente, «a nivel visual debe verse como v3»); el mapa de
|
|
14845
|
+
// las 6 reglas retiradas sigue escrito al final de `src/styles/neutralize-v3.css`. La pieza que
|
|
14846
|
+
// aquí se monta es la de v3 —su propio `SelectionIndicator`, que además anima—, no una imitación
|
|
14847
|
+
// de v2 por CSS: es exactamente lo que la nota de esa retirada señala como la vía buena («la
|
|
14848
|
+
// pastilla de verdad, la que además anima, se tiene montando `Tabs.Indicator`, que es lo que v3
|
|
14849
|
+
// espera»). Lo que cambia es QUIÉN la monta: la librería en vez de cada app.
|
|
14850
|
+
/**
|
|
14851
|
+
* Identidad por `child.type` contra los objetos reales de HeroUI — mismo mecanismo que las
|
|
14852
|
+
* fachadas `Table` y `Dropdown`, y nunca por `displayName` ni por nombre de función (la
|
|
14853
|
+
* minificación los renombra y las piezas de v3 no declaran `displayName`).
|
|
14854
|
+
*
|
|
14855
|
+
* Es FIABLE para detectar lo que la app ya puso porque las apps tienen prohibido importar de
|
|
14856
|
+
* `@heroui/*` (regla de oro de la migración): su única vía para un `Tabs.List`/`Tabs.ListContainer`
|
|
14857
|
+
* es el estático de Aurora, que es **este mismo objeto** (los estáticos de abajo apuntan a los de
|
|
14858
|
+
* HeroUI, no a copias). El mismo argumento vale para el indicador, que tiene su propia función
|
|
14859
|
+
* (`hasIndicator`, más abajo) porque ahí además hay que descender por los Fragments.
|
|
14860
|
+
*
|
|
14861
|
+
* Se declara como predicado de tipo —y no `boolean` como en `Dropdown`— porque el mapeo en sitio
|
|
14862
|
+
* de la lista necesita la `key` del elemento.
|
|
14863
|
+
*/
|
|
14864
|
+
function isPart(node, parts) {
|
|
14865
|
+
return $8WNJc$react.isValidElement(node) && parts.has(node.type);
|
|
14866
|
+
}
|
|
14867
|
+
// ---------------------------------------------------------------------------------------------
|
|
14868
|
+
// Fachada del `Tab`: inserta el `Tabs.Indicator` que falte
|
|
14869
|
+
// ---------------------------------------------------------------------------------------------
|
|
14870
|
+
/**
|
|
14871
|
+
* ¿Hay ya un `Tabs.Indicator` entre los hijos? **Desciende por los Fragments**, que es lo único
|
|
14872
|
+
* que `Children.toArray` no aplana (los arrays sí — un `.map()` queda cubierto, medido).
|
|
14873
|
+
*
|
|
14874
|
+
* POR QUÉ AQUÍ SÍ SE DESCIENDE Y EN EL ROOT NO, que es la asimetría deliberada de esta fachada:
|
|
14875
|
+
* aquí solo hace falta DETECTAR (el indicador se añade al nivel del propio `Tab`, como hermano);
|
|
14876
|
+
* en el root haría falta INSERTAR dentro del Fragment del consumidor, o sea reescribir su árbol,
|
|
14877
|
+
* que es una intervención de otro orden. Y los modos de fallo también son distintos:
|
|
14878
|
+
* · sin esto, un indicador oculto en un Fragment daba DOS. Medido en el navegador: cajas y
|
|
14879
|
+
* estilos computados idénticos (85.7×32 en x=20, las dos se mueven juntas a x=165.9 al
|
|
14880
|
+
* pulsar), consola limpia, geometría de la tira sin cambio — pero la SOMBRA se compone dos
|
|
14881
|
+
* veces y el halo de 1-3 px alrededor de la píldora se oscurece: comparación de píxeles
|
|
14882
|
+
* contra la referencia sana, 608 px distintos de 39200 (1.55%) con delta máximo 17/255 en
|
|
14883
|
+
* claro (`rgb(225,225,226)` → `rgb(208,208,209)`), y 112 px con delta máximo 8/255 en oscuro
|
|
14884
|
+
* (ahí la sombra de v3 es transparente, así que solo es antialias del borde redondeado).
|
|
14885
|
+
* Cosmético, pero medible, y evitarlo cuesta esta función.
|
|
14886
|
+
* · sin descender en el root, una lista oculta en un Fragment deja la FORMA DELGADA, que es
|
|
14887
|
+
* una forma legítima de v3 y además el comportamiento de hoy: no hay regresión que evitar.
|
|
14888
|
+
*
|
|
14889
|
+
* No desciende por componentes del consumidor —solo por Fragments— porque los hijos de un
|
|
14890
|
+
* componente cualquiera todavía no se han renderizado y puede que no los renderice nunca.
|
|
14891
|
+
*/
|
|
14892
|
+
function hasIndicator(children) {
|
|
14893
|
+
return $8WNJc$react.Children.toArray(children).some((node) => {
|
|
14894
|
+
if (!$8WNJc$react.isValidElement(node)) {
|
|
14895
|
+
return false;
|
|
14896
|
+
}
|
|
14897
|
+
if (node.type === react.Tabs.Indicator) {
|
|
14898
|
+
return true;
|
|
14899
|
+
}
|
|
14900
|
+
return node.type === $8WNJc$react.Fragment && hasIndicator(node.props.children);
|
|
14901
|
+
});
|
|
14902
|
+
}
|
|
14903
|
+
const TabFacade = ({ children, ...props }) => {
|
|
14904
|
+
// `children` como función es la forma de render props de react-aria (`TabRenderProps`). No se
|
|
14905
|
+
// puede inspeccionar, y menos aún combinar con un hermano —React rechaza una función como
|
|
14906
|
+
// hijo junto a un elemento—, así que se pasa tal cual. Un consumidor que la use monta el
|
|
14907
|
+
// indicador él (es la vía de escape de este caso). Exposición hoy: 0 usos en los 6 repos.
|
|
14908
|
+
if (typeof children === "function") {
|
|
14909
|
+
return jsxRuntime.jsx(react.Tabs.Tab, { ...props, children: children });
|
|
14910
|
+
}
|
|
14911
|
+
if (hasIndicator(children)) {
|
|
14912
|
+
return jsxRuntime.jsx(react.Tabs.Tab, { ...props, children: children });
|
|
14913
|
+
}
|
|
14914
|
+
// El indicador va PRIMERO por legibilidad del marcado, no por efecto: es `position:absolute`
|
|
14915
|
+
// con `z-index:-1`, o sea fuera del flujo y detrás del texto, así que el orden no cambia el
|
|
14916
|
+
// render (las dos apps que lo montan a mano difieren —analytics lo pone antes de la etiqueta,
|
|
14917
|
+
// `AnalyticsCard.tsx:177` después— y se ven igual).
|
|
14918
|
+
//
|
|
14919
|
+
// `{children}` se pasa SIN normalizar (nada de `Children.toArray`) para no reescribir las
|
|
14920
|
+
// keys del consumidor: hacerlo cambiaría la reconciliación de una lista de pestañas
|
|
14921
|
+
// condicional. Verificado en el navegador que la anidación no produce aviso de key.
|
|
14922
|
+
return (jsxRuntime.jsxs(react.Tabs.Tab, { ...props, children: [jsxRuntime.jsx(react.Tabs.Indicator, {}), children] }));
|
|
14923
|
+
};
|
|
14924
|
+
TabFacade.displayName = "Aurora.Tab";
|
|
14925
|
+
/**
|
|
14926
|
+
* `Tab` de Aurora: el `Tabs.Tab` de v3 **con el `Tabs.Indicator` que faltaba**.
|
|
14927
|
+
*
|
|
14928
|
+
* Es el MISMO componente que `Tabs.Tab` (el estático de abajo apunta aquí). Las dos superficies
|
|
14929
|
+
* de entrada importan porque las apps usan las dos: beweanalytics importa `Tab` suelto
|
|
14930
|
+
* (`import { Tab, Tabs } from "@beweco/aurora-ui"`, 8 usos) y agency/backoffice escriben
|
|
14931
|
+
* `Tabs.Tab`. En v3 los dos nombres salen del mismo módulo y son el mismo objeto
|
|
14932
|
+
* (`@heroui/react/dist/components/tabs/index.js`: `Tabs = Object.assign(TabsRoot, { …, Tab })`,
|
|
14933
|
+
* y `dist/index.js:92-93` los exporta por separado), así que servir fachadas distintas por cada
|
|
14934
|
+
* nombre habría sido el «falso amigo» que ya costó rondas en Alert/Checkbox/Switch.
|
|
14935
|
+
*/
|
|
14936
|
+
const Tab = TabFacade;
|
|
14937
|
+
// ---------------------------------------------------------------------------------------------
|
|
14938
|
+
// Fachada del root: inserta el `Tabs.ListContainer` que falte
|
|
14939
|
+
// ---------------------------------------------------------------------------------------------
|
|
14940
|
+
/** Lo que va DENTRO del contenedor: la lista. */
|
|
14941
|
+
const INSIDE_CONTAINER = new Set([react.Tabs.List]);
|
|
14942
|
+
/** Si el consumidor ya monta el contenedor, la fachada no envuelve nada. */
|
|
14943
|
+
const OWN_CONTAINER = new Set([react.Tabs.ListContainer]);
|
|
14944
|
+
const TabsFacade = ({ children, ...props }) => {
|
|
14945
|
+
const nodes = $8WNJc$react.Children.toArray(children);
|
|
14946
|
+
const needsContainer = nodes.some((node) => isPart(node, INSIDE_CONTAINER)) &&
|
|
14947
|
+
!nodes.some((node) => isPart(node, OWN_CONTAINER));
|
|
14948
|
+
// Nada que envolver (sin hijos, `children` como función, un contenedor ya montado a mano, o
|
|
14949
|
+
// ninguna lista suelta): el root tal cual, byte a byte como el crudo de v3.
|
|
14950
|
+
if (!needsContainer) {
|
|
14951
|
+
return jsxRuntime.jsx(react.Tabs, { ...props, children: children });
|
|
14952
|
+
}
|
|
14953
|
+
// Se envuelve EN SITIO, no reagrupando como hace `Dropdown` —única desviación deliberada
|
|
14954
|
+
// respecto a ese precedente—: el popover del dropdown es `position:absolute`, así que allí da
|
|
14955
|
+
// igual en qué orden queden los hijos del root. Aquí `.tabs` es `flex` + `flex-col` en
|
|
14956
|
+
// horizontal (`tabs.css:2-8`), de modo que el ORDEN EN EL DOM es el orden visual; react-aria
|
|
14957
|
+
// lo vigila además por su cuenta (con el panel antes de la lista avisa por consola «There is
|
|
14958
|
+
// no tab id, please check if you have rendered the tab panel before the tab list»). O sea que
|
|
14959
|
+
// el orden de los hijos del root es observable, y reagrupar lo cambiaría sin ganar nada:
|
|
14960
|
+
// envolver en sitio es la intervención estrictamente menor y deja la geometría idéntica en
|
|
14961
|
+
// todos los casos.
|
|
14962
|
+
return (jsxRuntime.jsx(react.Tabs, { ...props, children: nodes.map((node) => isPart(node, INSIDE_CONTAINER) ? (jsxRuntime.jsx(react.Tabs.ListContainer, { children: node }, node.key)) : (node)) }));
|
|
14963
|
+
};
|
|
14964
|
+
TabsFacade.displayName = "Aurora.Tabs";
|
|
14965
|
+
/**
|
|
14966
|
+
* `Tabs` de Aurora: el root de v3 **más el `Tabs.ListContainer` que faltaba**, con el compound
|
|
14967
|
+
* completo colgado como estáticos y `Tabs.Tab` apuntando a la FACHADA del tab.
|
|
14968
|
+
*
|
|
14969
|
+
* ```tsx
|
|
14970
|
+
* // Mínimo: la fachada monta el carril y el indicador, y se ve correcto sin añadir nada.
|
|
14971
|
+
* <Tabs>
|
|
14972
|
+
* <Tabs.List aria-label="Vista">
|
|
14973
|
+
* <Tabs.Tab id="a">Alfa</Tabs.Tab>
|
|
14974
|
+
* </Tabs.List>
|
|
14975
|
+
* </Tabs>
|
|
14976
|
+
*
|
|
14977
|
+
* // Anatomía completa a mano: la fachada la respeta y no duplica nada.
|
|
14978
|
+
* <Tabs>
|
|
14979
|
+
* <Tabs.ListContainer>
|
|
14980
|
+
* <Tabs.List aria-label="Vista">
|
|
14981
|
+
* <Tabs.Tab id="a"><Tabs.Indicator />Alfa</Tabs.Tab>
|
|
14982
|
+
* </Tabs.List>
|
|
14983
|
+
* </Tabs.ListContainer>
|
|
14984
|
+
* </Tabs>
|
|
14985
|
+
* ```
|
|
14986
|
+
*
|
|
14987
|
+
* `Tabs.Root` queda deliberadamente crudo (el root pelado de v3, sin contenedor), igual que en
|
|
14988
|
+
* `Table` y `Dropdown`: vía de escape para la **forma delgada** de v3 (lista sin contenedor, sin
|
|
14989
|
+
* scroller ni chevrones), que sigue alcanzable y a la que `neutralize-v3.css` dedica su regla
|
|
14990
|
+
* `:not(:has(.tabs__list-container))`. Ojo: en la forma delgada el `variant="secondary"` de v3 no
|
|
14991
|
+
* pinta —todas sus reglas cuelgan de `> .tabs__list-container` (`tabs.css:234-282`)—, así que
|
|
14992
|
+
* pasar por la fachada es además lo que hace funcionar esa variante.
|
|
14993
|
+
*
|
|
14994
|
+
* `Tabs.Indicator` se conserva exportado (como estático y vía `Tab`) para quien quiera componerlo
|
|
14995
|
+
* a mano: es el objeto EXACTO de `@heroui/react`.
|
|
14996
|
+
*/
|
|
14997
|
+
const Tabs = Object.assign(TabsFacade, {
|
|
14998
|
+
Indicator: react.Tabs.Indicator,
|
|
14999
|
+
List: react.Tabs.List,
|
|
15000
|
+
ListContainer: react.Tabs.ListContainer,
|
|
15001
|
+
Panel: react.Tabs.Panel,
|
|
15002
|
+
Root: react.Tabs.Root,
|
|
15003
|
+
Separator: react.Tabs.Separator,
|
|
15004
|
+
Tab: TabFacade,
|
|
15005
|
+
});
|
|
15006
|
+
|
|
14720
15007
|
/**
|
|
14721
15008
|
* Tooltip - Componente BeweOS basado en HeroUI.
|
|
14722
15009
|
*
|
|
@@ -15617,10 +15904,6 @@ Object.defineProperty(exports, "Spinner", {
|
|
|
15617
15904
|
enumerable: true,
|
|
15618
15905
|
get: function () { return react.Spinner; }
|
|
15619
15906
|
});
|
|
15620
|
-
Object.defineProperty(exports, "Tab", {
|
|
15621
|
-
enumerable: true,
|
|
15622
|
-
get: function () { return react.Tab; }
|
|
15623
|
-
});
|
|
15624
15907
|
Object.defineProperty(exports, "TableBody", {
|
|
15625
15908
|
enumerable: true,
|
|
15626
15909
|
get: function () { return react.TableBody; }
|
|
@@ -15641,10 +15924,6 @@ Object.defineProperty(exports, "TableRow", {
|
|
|
15641
15924
|
enumerable: true,
|
|
15642
15925
|
get: function () { return react.TableRow; }
|
|
15643
15926
|
});
|
|
15644
|
-
Object.defineProperty(exports, "Tabs", {
|
|
15645
|
-
enumerable: true,
|
|
15646
|
-
get: function () { return react.Tabs; }
|
|
15647
|
-
});
|
|
15648
15927
|
Object.defineProperty(exports, "cn", {
|
|
15649
15928
|
enumerable: true,
|
|
15650
15929
|
get: function () { return react.cn; }
|
|
@@ -15746,7 +16025,9 @@ exports.StepIndicator = StepIndicator;
|
|
|
15746
16025
|
exports.Switch = Switch;
|
|
15747
16026
|
exports.SwitchComponent = Switch;
|
|
15748
16027
|
exports.THEME_COLOR_HEX_MAP = THEME_COLOR_HEX_MAP;
|
|
16028
|
+
exports.Tab = Tab;
|
|
15749
16029
|
exports.Table = Table;
|
|
16030
|
+
exports.Tabs = Tabs;
|
|
15750
16031
|
exports.TagsFilter = TagsFilter;
|
|
15751
16032
|
exports.Textarea = Textarea;
|
|
15752
16033
|
exports.ThemeContext = ThemeContext;
|