@beweco/aurora-ui 1.0.0-beta.141 → 1.0.0-beta.142
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 +34 -3
- package/dist/index.cjs.js +339 -108
- package/dist/index.esm.js +340 -109
- package/dist/types/components/card/Card.d.ts.map +1 -1
- package/dist/types/components/chip/Chip.d.ts.map +1 -1
- package/dist/types/components/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
- package/dist/types/components/drawer/Drawer.d.ts.map +1 -1
- package/dist/types/components/drawer/_internal/DrawerFooter.d.ts +3 -1
- package/dist/types/components/drawer/_internal/DrawerFooter.d.ts.map +1 -1
- package/dist/types/components/drawer-filters/_internal/DayMonthPicker.d.ts +6 -0
- package/dist/types/components/drawer-filters/_internal/DayMonthPicker.d.ts.map +1 -1
- package/dist/types/components/drawer-filters/_internal/FilterSection.d.ts.map +1 -1
- package/dist/types/components/input/Input.d.ts.map +1 -1
- package/dist/types/components/menu/_internal/menu-nav-list/MenuNavList.d.ts.map +1 -1
- package/dist/types/components/modal/_internal/ModalFooter.d.ts +6 -0
- package/dist/types/components/modal/_internal/ModalFooter.d.ts.map +1 -1
- package/dist/types/components/pagination/Pagination.d.ts.map +1 -1
- package/dist/types/components/range-filter/RangeFilter.d.ts.map +1 -1
- package/dist/types/components/switch/Switch.d.ts.map +1 -1
- package/dist/types/components/switch/Switch.types.d.ts +22 -0
- package/dist/types/components/switch/Switch.types.d.ts.map +1 -1
- package/dist/types/components/switch/index.d.ts +1 -1
- package/dist/types/components/switch/index.d.ts.map +1 -1
- package/dist/types/components/table/Table.d.ts.map +1 -1
- package/dist/types/components/table/TableContent.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -756,7 +756,7 @@ const SHAPE_BY_VARIANT = {
|
|
|
756
756
|
light: "transparent",
|
|
757
757
|
flat: "soft",
|
|
758
758
|
bordered: "outline",
|
|
759
|
-
faded: "
|
|
759
|
+
faded: "faded",
|
|
760
760
|
// `shadow` de v2 es `solid` + sombra teñida (ver `SHADOW_CLASS`).
|
|
761
761
|
shadow: "solid",
|
|
762
762
|
// `dot` de v2: chip neutro con un punto de color (ver `DOT_BASE_CLASS`).
|
|
@@ -911,6 +911,7 @@ const V3_VARIANT_BY_SHAPE = {
|
|
|
911
911
|
soft: "soft",
|
|
912
912
|
transparent: "tertiary",
|
|
913
913
|
outline: "tertiary",
|
|
914
|
+
faded: "tertiary",
|
|
914
915
|
dot: "tertiary",
|
|
915
916
|
};
|
|
916
917
|
/**
|
|
@@ -1018,6 +1019,48 @@ const CLOSE_ICON_SIZE_CLASS = {
|
|
|
1018
1019
|
md: "size-[18px]",
|
|
1019
1020
|
lg: "size-5",
|
|
1020
1021
|
};
|
|
1022
|
+
// ── `bordered` y `faded` (TECH-2459, 24-sep: el usuario ve «muy negro» el `bordered default`) ──
|
|
1023
|
+
//
|
|
1024
|
+
// Antes las dos variantes pintaban borde y texto con `tintFg` (`default-700` = rgb(63,63,70) para
|
|
1025
|
+
// `default`): en el selector de tallas del `addon-card` de beweossmbs el chip sin elegir se leía
|
|
1026
|
+
// como un bloque casi negro al lado del `solid primary` elegido. Y el mismo `tintFg` dejaba el
|
|
1027
|
+
// texto por debajo de AA en otros colores. Medido en `Custom Components/Chip → BorderedColors`
|
|
1028
|
+
// (texto contra el fondo real, blanco / tarjeta `content1` oscura):
|
|
1029
|
+
//
|
|
1030
|
+
// | color | antes claro | antes oscuro | ahora claro | ahora oscuro |
|
|
1031
|
+
// |-----------|-------------|--------------|-------------|--------------|
|
|
1032
|
+
// | default | 10.44 (borde casi negro) | 13.96 (borde casi blanco) | 17.93 | 15.11 |
|
|
1033
|
+
// | primary | 4.66 | 3.80 ✗ | 6.38 | 7.33 |
|
|
1034
|
+
// | secondary | 9.50 | 5.77 | 9.50 | 5.77 |
|
|
1035
|
+
// | success | 2.19 ✗ | 8.08 | 5.50 | 8.08 |
|
|
1036
|
+
// | warning | 2.04 ✗ | 8.68 | 5.20 | 8.68 |
|
|
1037
|
+
// | danger | 4.14 ✗ | 4.27 ✗ | 6.06 | 5.02 |
|
|
1038
|
+
//
|
|
1039
|
+
// Criterio (no es volver a v2 por volver, es que se vea bien dentro de los tokens de Aurora):
|
|
1040
|
+
//
|
|
1041
|
+
// - **Borde**: el color a secas (`border-<color>`). Para `default`, el gris neutro que ya usa el
|
|
1042
|
+
// resto de la familia (`dot` lleva `border-default`, y v2 también en `bordered`/`faded`):
|
|
1043
|
+
// `--color-default`, rgb(212,212,216) en claro y rgb(63,63,70) en oscuro. Se distingue del fondo
|
|
1044
|
+
// (medido: 1.48:1 sobre blanco, 1.70:1 sobre la tarjeta oscura, 2.01:1 sobre el fondo negro) sin
|
|
1045
|
+
// competir con el texto. Input/Select reposan en `default-200`, un paso más claro, porque su borde
|
|
1046
|
+
// enmarca un campo; en un chip el borde ES la forma, y `default-200` (≈1.27:1 sobre blanco,
|
|
1047
|
+
// calculado) la dejaba casi invisible. En oscuro los dos pasos son el mismo rgb(63,63,70).
|
|
1048
|
+
// - **Texto**: el mismo paso legible que ya usa `flat` (`flatFg` + su `dark:`), que es el que la
|
|
1049
|
+
// librería ya validó para texto tintado; `default` usa `foreground`.
|
|
1050
|
+
// - Van como CLASES y no como `borderColor` inline: un estilo inline le ganaba a cualquier
|
|
1051
|
+
// `border-*` de la app, y así `cn` (tailwind-merge) deja ganar la clase del consumidor.
|
|
1052
|
+
// - `faded` conserva lo que lo distinguía en v2 (borde neutro en todos los colores + relleno
|
|
1053
|
+
// `default-100`); hasta ahora era idéntico a `bordered`. Su texto es el `flatFg` SIN el `dark:`
|
|
1054
|
+
// de `flat` (ver `flatDarkFgClass`). Medido: ≥ 4.73:1 en claro y ≥ 4.85:1 en oscuro en los 6
|
|
1055
|
+
// colores. 0 usos en las apps.
|
|
1056
|
+
const OUTLINE_BORDER_CLASS = {
|
|
1057
|
+
default: "border-default",
|
|
1058
|
+
primary: "border-primary",
|
|
1059
|
+
secondary: "border-secondary",
|
|
1060
|
+
success: "border-success",
|
|
1061
|
+
warning: "border-warning",
|
|
1062
|
+
danger: "border-danger",
|
|
1063
|
+
};
|
|
1021
1064
|
function colorStyle(color, shape) {
|
|
1022
1065
|
if (shape === "dot") {
|
|
1023
1066
|
// `dot`: el chip es neutro para cualquier color (el color va solo en el punto).
|
|
@@ -1034,7 +1077,14 @@ function colorStyle(color, shape) {
|
|
|
1034
1077
|
// `flat` de v2: pastilla translúcida + texto del paso -600/-700 (P-08d).
|
|
1035
1078
|
return { "--chip-bg": t.flatBg, "--chip-fg": t.flatFg };
|
|
1036
1079
|
}
|
|
1037
|
-
|
|
1080
|
+
if (shape === "outline" || shape === "faded") {
|
|
1081
|
+
// `bordered`/`faded`: texto del paso legible de `flat`; `default` en `foreground`.
|
|
1082
|
+
return {
|
|
1083
|
+
"--chip-bg": shape === "faded" ? "var(--color-default-100)" : "transparent",
|
|
1084
|
+
"--chip-fg": color === "default" ? "var(--color-foreground)" : t.flatFg,
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
// transparent (light): sin relleno, texto tinte del color.
|
|
1038
1088
|
return { "--chip-bg": "transparent", "--chip-fg": t.tintFg };
|
|
1039
1089
|
}
|
|
1040
1090
|
/**
|
|
@@ -1072,18 +1122,21 @@ const Chip = ({ color = "default", variant = "solid", size = "md", radius = "ful
|
|
|
1072
1122
|
: undefined;
|
|
1073
1123
|
// Con `dot` el color no tiñe el chip, tampoco el de los colores fijos.
|
|
1074
1124
|
const customClass = isStandard || isDot ? "" : CUSTOM_COLOR_CLASSES[color];
|
|
1075
|
-
const
|
|
1076
|
-
|
|
1077
|
-
|
|
1125
|
+
const hasBorder = shape === "outline" || shape === "faded";
|
|
1126
|
+
const outlineClass = hasBorder
|
|
1127
|
+
? react.cn("border-2", isStandard
|
|
1128
|
+
? OUTLINE_BORDER_CLASS[shape === "faded" ? "default" : color]
|
|
1129
|
+
: "")
|
|
1130
|
+
: "";
|
|
1131
|
+
// El `dark:text-*` que v2 declaraba para el texto de `flat` en success/warning/danger (P-08d),
|
|
1132
|
+
// reutilizado por `bordered`, que toma el mismo texto. `faded` NO: sobre su relleno
|
|
1133
|
+
// `default-100` oscuro el `danger-500` se quedaba en 4.22:1; con el paso `-600`/`-700` del
|
|
1134
|
+
// tema oscuro (más claro) todos los colores pasan AA. Va como clase porque `--chip-fg` es inline y no puede depender del tema; la capa
|
|
1078
1135
|
// `utilities` gana al `color: var(--chip-fg)` de `.chip`, que vive en `components`.
|
|
1079
|
-
const flatDarkFgClass = isStandard && shape === "soft"
|
|
1136
|
+
const flatDarkFgClass = isStandard && (shape === "soft" || shape === "outline")
|
|
1080
1137
|
? (COLOR_TOKENS[color].flatFgDarkClass ?? "")
|
|
1081
1138
|
: "";
|
|
1082
|
-
const baseStyle = vars
|
|
1083
|
-
? shape === "outline"
|
|
1084
|
-
? { ...vars, borderColor: vars["--chip-fg"] }
|
|
1085
|
-
: vars
|
|
1086
|
-
: undefined;
|
|
1139
|
+
const baseStyle = vars;
|
|
1087
1140
|
// El `style` del consumidor va DESPUÉS: pisa el relleno/texto calculados (uso real en
|
|
1088
1141
|
// beweossmbs: `style={{ backgroundColor, color }}` con el color del agente, 5 sitios).
|
|
1089
1142
|
const style = baseStyle || consumerStyle ? { ...baseStyle, ...consumerStyle } : undefined;
|
|
@@ -1202,6 +1255,20 @@ const STRIP_CLASS = "w-fit gap-0 rounded-[12px] shadow-xs";
|
|
|
1202
1255
|
const STRIP_LOOSE_CLASS = "w-fit gap-1";
|
|
1203
1256
|
/** Controles anterior/siguiente: celda cuadrada, sin el padding lateral de v3. */
|
|
1204
1257
|
const NAV_CLASS = "w-9 px-0";
|
|
1258
|
+
/**
|
|
1259
|
+
* TECH-2459 (beweossmbs, 24-sep) — anterior/siguiente deshabilitados por estar en un EXTREMO
|
|
1260
|
+
* (página 1 / última). v3 los apaga con `status-disabled` (`opacity: var(--disabled-opacity)`,
|
|
1261
|
+
* `@heroui/styles/dist/components/pagination.css:57`), que aquí deja el galón en el
|
|
1262
|
+
* `text-default-foreground` de `CELL_CLASS` al 50 %: medido `rgb(0,0,0)` a opacidad 0.5 sobre
|
|
1263
|
+
* `default-100`, que se lee como un control activo. Se pinta el galón en `default-300` y a
|
|
1264
|
+
* opacidad plena, el gris de «apagado» de la paleta (el mismo que usaba v2,
|
|
1265
|
+
* `data-[disabled=true]:text-default-300` de `@heroui/theme@2.4.15` `pagination.js:489`); el
|
|
1266
|
+
* cursor y el `pointer-events` de v3 se conservan.
|
|
1267
|
+
*
|
|
1268
|
+
* Solo en los extremos: con `isDisabled` en toda la paginación manda el apagado uniforme de v3
|
|
1269
|
+
* (todas las celdas al 50 %), y las flechas no deben verse distintas del resto.
|
|
1270
|
+
*/
|
|
1271
|
+
const NAV_AT_EDGE_CLASS = "disabled:text-default-300 disabled:opacity-100";
|
|
1205
1272
|
/**
|
|
1206
1273
|
* Radio de cada pieza según su posición en la tira.
|
|
1207
1274
|
*
|
|
@@ -1276,6 +1343,33 @@ const DEFAULT_TRANSLATIONS$g = {
|
|
|
1276
1343
|
jumpBackwardAriaLabel: "Retroceder {count} páginas",
|
|
1277
1344
|
jumpForwardAriaLabel: "Avanzar {count} páginas",
|
|
1278
1345
|
};
|
|
1346
|
+
/**
|
|
1347
|
+
* TECH-2459 (beweossmbs, 24-sep) — los mismos textos en inglés, para cuando el idioma de la app es
|
|
1348
|
+
* inglés. El defecto medido: con la interfaz en inglés, «anterior» se anunciaba «Página anterior».
|
|
1349
|
+
* La app SÍ comunica su idioma (`<HeroUIProvider locale="en-US">` → `I18nProvider` de react-aria,
|
|
1350
|
+
* `src/compat/heroui-v2-shims.tsx`), y es el mismo que ya siguen los textos propios de react-aria
|
|
1351
|
+
* (la casilla «Select all» de la tabla, los calendarios…); la fachada lo ignoraba porque solo
|
|
1352
|
+
* miraba `translations`. Ahora el idioma elige la base y `translations` sigue ganando encima.
|
|
1353
|
+
*/
|
|
1354
|
+
const EN_TRANSLATIONS = {
|
|
1355
|
+
previousPageAriaLabel: "Previous page",
|
|
1356
|
+
nextPageAriaLabel: "Next page",
|
|
1357
|
+
jumpBackwardAriaLabel: "Jump back {count} pages",
|
|
1358
|
+
jumpForwardAriaLabel: "Jump forward {count} pages",
|
|
1359
|
+
};
|
|
1360
|
+
/**
|
|
1361
|
+
* Base de textos según el idioma de react-aria (`useLocale`): inglés si el locale es `en*`,
|
|
1362
|
+
* español en cualquier otro caso (el default de la librería, regla `auraui-i18n`).
|
|
1363
|
+
*
|
|
1364
|
+
* Sin provider, react-aria resuelve el idioma del NAVEGADOR (`navigator.language`), igual que
|
|
1365
|
+
* para sus propios textos: una app que no declare `locale` sigue al navegador. Para fijarlo, la
|
|
1366
|
+
* app pasa `locale` a `HeroUIProvider` o los textos por `translations`.
|
|
1367
|
+
*/
|
|
1368
|
+
function baseTranslations(locale) {
|
|
1369
|
+
return locale.toLowerCase().startsWith("en")
|
|
1370
|
+
? EN_TRANSLATIONS
|
|
1371
|
+
: DEFAULT_TRANSLATIONS$g;
|
|
1372
|
+
}
|
|
1279
1373
|
/**
|
|
1280
1374
|
* TECH-2459 · elipsis navegable — páginas que salta la elipsis. Literal de v2:
|
|
1281
1375
|
* `dotsJump = 5`, default desestructurado en `@heroui/pagination@2.2.20`
|
|
@@ -1395,7 +1489,8 @@ function getPaginationRange(total, current) {
|
|
|
1395
1489
|
const Pagination = ({ total, page, initialPage = 1, onChange, size: _size = "sm", className, isDisabled, showControls = true, isCompact = true, showShadow = false, color = "primary", translations = {}, }) => {
|
|
1396
1490
|
const [internalPage, setInternalPage] = $8WNJc$react.useState(initialPage);
|
|
1397
1491
|
const currentPage = page ?? internalPage;
|
|
1398
|
-
const
|
|
1492
|
+
const { locale } = react.useLocale();
|
|
1493
|
+
const t = { ...baseTranslations(locale), ...translations };
|
|
1399
1494
|
const goTo = (next) => {
|
|
1400
1495
|
const clamped = Math.min(Math.max(next, 1), total);
|
|
1401
1496
|
if (page === undefined) {
|
|
@@ -1428,7 +1523,7 @@ const Pagination = ({ total, page, initialPage = 1, onChange, size: _size = "sm"
|
|
|
1428
1523
|
// lo nombraba ("previous page button", `use-pagination.js:213`), pero en
|
|
1429
1524
|
// inglés y hardcodeado; aquí va por `translations` (regla obligatoria de
|
|
1430
1525
|
// i18n del repo, skill `auraui-i18n`).
|
|
1431
|
-
, { "aria-label": t.previousPageAriaLabel, className: react.cn(CELL_CLASS, NAV_CLASS, cellRadius(isCompact, { isFirst: true, isLast: false })), isDisabled: isDisabled || currentPage <= 1, onPress: () => goTo(currentPage - 1), children: jsxRuntime.jsx(react.Pagination.PreviousIcon, {}) }) })), items.map((item, index) => {
|
|
1526
|
+
, { "aria-label": t.previousPageAriaLabel, className: react.cn(CELL_CLASS, NAV_CLASS, isDisabled ? "" : NAV_AT_EDGE_CLASS, cellRadius(isCompact, { isFirst: true, isLast: false })), isDisabled: isDisabled || currentPage <= 1, onPress: () => goTo(currentPage - 1), children: jsxRuntime.jsx(react.Pagination.PreviousIcon, {}) }) })), items.map((item, index) => {
|
|
1432
1527
|
if (item === "ellipsis") {
|
|
1433
1528
|
const isBefore = index < activeIndex;
|
|
1434
1529
|
const label = isBefore
|
|
@@ -1443,7 +1538,7 @@ const Pagination = ({ total, page, initialPage = 1, onChange, size: _size = "sm"
|
|
|
1443
1538
|
return (jsxRuntime.jsx(react.Pagination.Item, { children: jsxRuntime.jsx(react.Pagination.Link, { className: react.cn(CELL_CLASS, cellRadius(isCompact, itemPosition(index)), item === currentPage ? activeClass : ""), isActive: item === currentPage, isDisabled: isDisabled, onPress: () => goTo(item), children: item }) }, item));
|
|
1444
1539
|
}), showControls && (jsxRuntime.jsx(react.Pagination.Item, { children: jsxRuntime.jsx(react.Pagination.Next
|
|
1445
1540
|
/* Mismo motivo que en `Previous`: el galón es `aria-hidden`. */
|
|
1446
|
-
, { "aria-label": t.nextPageAriaLabel, className: react.cn(CELL_CLASS, NAV_CLASS, cellRadius(isCompact, { isFirst: false, isLast: true })), isDisabled: isDisabled || currentPage >= total, onPress: () => goTo(currentPage + 1), children: jsxRuntime.jsx(react.Pagination.NextIcon, {}) }) }))] }) }));
|
|
1541
|
+
, { "aria-label": t.nextPageAriaLabel, className: react.cn(CELL_CLASS, NAV_CLASS, isDisabled ? "" : NAV_AT_EDGE_CLASS, cellRadius(isCompact, { isFirst: false, isLast: true })), isDisabled: isDisabled || currentPage >= total, onPress: () => goTo(currentPage + 1), children: jsxRuntime.jsx(react.Pagination.NextIcon, {}) }) }))] }) }));
|
|
1447
1542
|
};
|
|
1448
1543
|
|
|
1449
1544
|
// TECH-2459 · F5 · P-01 — Valores tomados del tema v2 REAL (`@heroui/theme@2.4.15`,
|
|
@@ -1719,7 +1814,12 @@ const ROOT_HELPER_SPACE_CLASS = {
|
|
|
1719
1814
|
};
|
|
1720
1815
|
const GROUP_PLACEMENT_CLASS = {
|
|
1721
1816
|
outside: undefined,
|
|
1722
|
-
|
|
1817
|
+
// `min-w-min` (TECH-2459, beweossmbs QA 24-sep, barra de la agenda por debajo de 1440px):
|
|
1818
|
+
// `.date-input-group` de v3 lleva `overflow-hidden`, y un ítem flex con overflow distinto de
|
|
1819
|
+
// `visible` tiene `min-width: auto` = 0. Con `flex-1` el grupo se quedaba con el hueco sobrante
|
|
1820
|
+
// y recortaba su propio botón de calendario (104px con 140 de contenido a 1280px). En v2 el
|
|
1821
|
+
// overflow era visible: el grupo conservaba su contenido y era la etiqueta la que se partía.
|
|
1822
|
+
"outside-left": "relative flex-1 min-w-min",
|
|
1723
1823
|
};
|
|
1724
1824
|
const HELPER_PLACEMENT_CLASS = {
|
|
1725
1825
|
outside: undefined,
|
|
@@ -2221,7 +2321,9 @@ labelPlacement: _labelPlacement, isInvalid = false, isRequired = false, isDisabl
|
|
|
2221
2321
|
// `undefined` y el campo dejaba de llenar su contenedor: en una fila flex se encogía al ancho
|
|
2222
2322
|
// de su contenido (medido por S2: 208px dentro de una fila de 592, 336px de hueco). En una
|
|
2223
2323
|
// columna no se notaba porque el `stretch` del flex lo tapaba — pero afecta a cualquier app.
|
|
2224
|
-
fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, required, name, type = "text", onKeyDown,
|
|
2324
|
+
fullWidth = true, value, defaultValue, onChange, onValueChange, className, classNames, required, name, type = "text", onKeyDown,
|
|
2325
|
+
// Nombre y descripción accesibles: van al `TextField`, no al `<input>` (ver abajo).
|
|
2326
|
+
"aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...rest }, ref) => {
|
|
2225
2327
|
// El `<input>` real, también para la fachada: v2 devolvía el foco al campo al limpiar
|
|
2226
2328
|
// (`domRef.current?.focus()` en `handleClear`). Se combina con el `ref` del consumidor.
|
|
2227
2329
|
const inputRef = $8WNJc$react.useRef(null);
|
|
@@ -2264,6 +2366,19 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
|
|
|
2264
2366
|
// Solo flota cuando hay label y NO hay placeholder: con placeholder, v2 ya mostraba el label
|
|
2265
2367
|
// arriba desde el primer render (ver el bloque de arriba).
|
|
2266
2368
|
const labelFlotante = Boolean(label) && !placeholder;
|
|
2369
|
+
// ── Nombre accesible sin `label` visible ─────────────────────────────────────────────────
|
|
2370
|
+
//
|
|
2371
|
+
// Quien llama a `useLabel` (y avisa «If you do not provide a visible label, you must specify
|
|
2372
|
+
// an aria-label…») es el `TextField` de react-aria, que se los pasa al `<input>` por contexto.
|
|
2373
|
+
// Dejarlos en el spread del `<input>` hacía que avisara AUNQUE la app diera nombre (medido en
|
|
2374
|
+
// beweossmbs: 14/16 avisos al cargar `/clients/table`, del buscador con solo placeholder).
|
|
2375
|
+
// Y `aria-describedby` en el `<input>` pisaba el id de la `Description` propia. v2 no avisaba
|
|
2376
|
+
// nunca: `"aria-label": label ? aria-label : safeAriaLabel(aria-label, placeholder)`
|
|
2377
|
+
// (`@heroui/input@2.4.33`, `dist/use-input.js:119`). Con `aria-labelledby` no se añade el
|
|
2378
|
+
// placeholder: react-aria lo concatenaría al nombre del elemento referido.
|
|
2379
|
+
const accessibleLabel = label || ariaLabelledBy
|
|
2380
|
+
? ariaLabel
|
|
2381
|
+
: ariaLabel?.trim() || placeholder?.trim() || undefined;
|
|
2267
2382
|
const handleChange = (event) => {
|
|
2268
2383
|
onChange?.(event);
|
|
2269
2384
|
onValueChange?.(event.target.value);
|
|
@@ -2296,7 +2411,7 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
|
|
|
2296
2411
|
clearValue();
|
|
2297
2412
|
}
|
|
2298
2413
|
};
|
|
2299
|
-
return (jsxRuntime.jsxs(react.TextField, { id: inputId, value: currentValue,
|
|
2414
|
+
return (jsxRuntime.jsxs(react.TextField, { id: inputId, "aria-label": accessibleLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, value: currentValue,
|
|
2300
2415
|
// Solo el modo no controlado escribe aquí; en controlado manda el `value` del padre
|
|
2301
2416
|
// (que se entera por `onChange`/`onValueChange` del `<input>`).
|
|
2302
2417
|
onChange: isControlled ? undefined : setUncontrolledValue, name: name, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, isReadOnly: isReadOnly, className: react.cn(FIELD_STACK_CLASS$3[size], fullWidth ? "w-full" : "",
|
|
@@ -2313,7 +2428,15 @@ fullWidth = true, value, defaultValue, onChange, onValueChange, className, class
|
|
|
2313
2428
|
// pase el consumidor.
|
|
2314
2429
|
"w-full",
|
|
2315
2430
|
// v3 fusiona `innerWrapper` e `inputWrapper` de v2 en este único elemento.
|
|
2316
|
-
classNames?.innerWrapper, 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: setInputRef, onKeyDown: handleKeyDown, required: required, type: type, placeholder: labelFlotante ? " " : placeholder, onChange: handleChange, className: react.cn(
|
|
2431
|
+
classNames?.innerWrapper, 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: setInputRef, onKeyDown: handleKeyDown, required: required, type: type, placeholder: labelFlotante ? " " : placeholder, onChange: handleChange, className: react.cn(
|
|
2432
|
+
// `w-full min-w-0` (TECH-2459, beweossmbs QA 24-sep): `.input-group__input`
|
|
2433
|
+
// de v3 es `flex-1` sin ancho, así que el `<input>` aportaba su ancho
|
|
2434
|
+
// intrínseco (~151px) como min-content y el campo no encogía en una fila
|
|
2435
|
+
// flex estrecha (hex del color picker de Agenda → Colors: 180px y 35px
|
|
2436
|
+
// fuera de su fila; en v2, 132px). v2 ponía `w-full` en este slot
|
|
2437
|
+
// (`@heroui/theme@2.4.15`, `dist/components/input.js:111`), y un ancho
|
|
2438
|
+
// en porcentaje no cuenta para el min-content de un `<input>`.
|
|
2439
|
+
"w-full min-w-0 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: react.cn("h-4 w-4 min-h-0 p-0.5 mr-1", classNames?.clearButton), 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?.helperWrapper, classNames?.description), children: description })), isInvalid && errorMessage && (jsxRuntime.jsx(react.FieldError, { className: react.cn(HELPER_CLASS$2, "text-left", classNames?.helperWrapper, classNames?.errorMessage), children: errorMessage }))] }));
|
|
2317
2440
|
});
|
|
2318
2441
|
Input.displayName = "Input";
|
|
2319
2442
|
|
|
@@ -2435,18 +2558,36 @@ const SHADOW_CLASS = {
|
|
|
2435
2558
|
md: "shadow-[shadow:var(--aurora-shadow-medium)]",
|
|
2436
2559
|
lg: "shadow-[shadow:var(--aurora-shadow-large)]",
|
|
2437
2560
|
};
|
|
2561
|
+
// Geometría v2 de la raíz (slot `base` de `@heroui/theme@2.4.15`, `dist/components/card.js`):
|
|
2562
|
+
// `flex flex-col relative overflow-hidden`, SIN `gap`. v3 (`@heroui/styles/…/card.css:5`) pone
|
|
2563
|
+
// `gap-3 overflow-visible`, y eso ROMPE layouts de v2 (medido por beweossmbs con la .141): con
|
|
2564
|
+
// tres hijos la card crece 24px (Notificaciones automáticas: 220px frente a 192, y la última card
|
|
2565
|
+
// queda cortada por su contenedor), y el texto que no cabe se sale de la card en vez de
|
|
2566
|
+
// recortarse (cabecera de recurso de la agenda, vista Semana: 80px frente a 56 y los nombres
|
|
2567
|
+
// fuera). Va primero en el `cn`: un `gap-*`/`overflow-*` de la app lo retira por fusión.
|
|
2568
|
+
// `overflow-hidden` no quita nada que se viera: la onda ya se recorta en su propia capa
|
|
2569
|
+
// (`Card.css`), el anillo de foco es un `ring` (`box-shadow`, no lo recorta el `overflow` de su
|
|
2570
|
+
// propio nodo) y la sombra de la card se pinta fuera de su caja. Medido en la story `V2Geometry`: tres
|
|
2571
|
+
// hijos de 20px dan 108px (132 con el gap de v3) y el texto que desborda ya no asoma.
|
|
2572
|
+
const ROOT_V2_CLASS = "gap-0 overflow-hidden";
|
|
2438
2573
|
// Literales del `tv` de v2 (`@heroui/theme@2.4.15`, `dist/components/card.js`), con sus tokens
|
|
2439
2574
|
// traducidos a los que existen en Tailwind 4 + Aurora:
|
|
2440
2575
|
// isPressable → `cursor-pointer` + compound `data-[pressed=true]:scale-[0.97]
|
|
2441
2576
|
// tap-highlight-transparent` (el hundido lo hace aquí `:active`, que es lo que
|
|
2442
2577
|
// marcaba `data-pressed` en un botón nativo)
|
|
2443
2578
|
// disableAnimation=false → `transition-transform-background motion-reduce:transition-none`
|
|
2444
|
-
// foco → `dataFocusVisibleClasses` (`outline-2 outline-focus outline-offset-2`)
|
|
2579
|
+
// foco → `dataFocusVisibleClasses` (`outline-2 outline-focus outline-offset-2`). Aquí va con el
|
|
2580
|
+
// MISMO anillo que los botones de v3/Aurora (`status-focused` → `focus-ring`:
|
|
2581
|
+
// `ring-2 ring-focus ring-offset-background` + offset 2px), no con `outline`: en
|
|
2582
|
+
// Tailwind 4 `outline-none` fija `--tw-outline-style: none` y `focus-visible:outline-2`
|
|
2583
|
+
// hereda ese estilo, así que el anillo NO se pintaba (regresión de la .141, al pasar de
|
|
2584
|
+
// `<button>` a `<div role="button">`). El `ring` es `box-shadow` fuera de la caja: no lo
|
|
2585
|
+
// recorta el `overflow-hidden` de la raíz y se compone con la sombra de la card.
|
|
2445
2586
|
// isHoverable → `data-[hover=true]:bg-content2` (aquí `hover:`, react-aria ya no escribe
|
|
2446
2587
|
// `data-hover` — trampa 3 de la skill `auraui-components`)
|
|
2447
2588
|
// isDisabled → `opacity-disabled cursor-not-allowed` (`opacity-disabled` era 0.5 en v2)
|
|
2448
2589
|
// fullWidth → `w-full`
|
|
2449
|
-
const PRESSABLE_CLASS = "isolate cursor-pointer text-foreground outline-none focus-visible:z-10 focus-visible:
|
|
2590
|
+
const PRESSABLE_CLASS = "isolate cursor-pointer text-foreground outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background [-webkit-tap-highlight-color:transparent]";
|
|
2450
2591
|
const PRESS_ANIMATION_CLASS = "transition-[transform,background-color] motion-reduce:transition-none active:scale-[0.97]";
|
|
2451
2592
|
const HOVERABLE_CLASS = "hover:bg-content2";
|
|
2452
2593
|
const DISABLED_CLASS = "opacity-50 cursor-not-allowed";
|
|
@@ -2562,7 +2703,7 @@ const Card = $8WNJc$react.forwardRef(({ children, className, shadow = "sm", radi
|
|
|
2562
2703
|
event.preventDefault();
|
|
2563
2704
|
press(pressEventFromKey(event));
|
|
2564
2705
|
}, [onKeyUp, pulsable, press]);
|
|
2565
|
-
const combinedClassName = react.cn(paddingClasses[padding], RADIUS_CLASS$5[radius], SHADOW_CLASS[shadow], fullWidth ? "w-full" : "", isPressable ? PRESSABLE_CLASS : "", isPressable && !disableAnimation ? PRESS_ANIMATION_CLASS : "", isHoverable ? HOVERABLE_CLASS : "", isDisabled ? DISABLED_CLASS : "",
|
|
2706
|
+
const combinedClassName = react.cn(ROOT_V2_CLASS, paddingClasses[padding], RADIUS_CLASS$5[radius], SHADOW_CLASS[shadow], fullWidth ? "w-full" : "", isPressable ? PRESSABLE_CLASS : "", isPressable && !disableAnimation ? PRESS_ANIMATION_CLASS : "", isHoverable ? HOVERABLE_CLASS : "", isDisabled ? DISABLED_CLASS : "",
|
|
2566
2707
|
// El `className` de la app, último: gana por fusión (ver JSDoc).
|
|
2567
2708
|
className);
|
|
2568
2709
|
// v2 cambiaba el ELEMENTO a `<button>` con `isPressable`, y hasta la .140 esta fachada lo
|
|
@@ -3728,7 +3869,12 @@ const ColorPicker = $8WNJc$react.forwardRef(({ value, onChange, label, required
|
|
|
3728
3869
|
${error
|
|
3729
3870
|
? "border-danger dark:border-danger-400"
|
|
3730
3871
|
: "border-default-300 dark:border-default-700"}
|
|
3731
|
-
`, "aria-label": t.customColorLabel, title: t.customColorLabel }), jsxRuntime.jsx(Input, { type: "text", value: textValue, onValueChange: handleTextChange, onBlur: handleTextBlur, placeholder: t.placeholder, disabled: disabled, isDisabled: disabled, isInvalid: error || isInvalidFormat, size: "sm", variant: "bordered",
|
|
3872
|
+
`, "aria-label": t.customColorLabel, title: t.customColorLabel }), jsxRuntime.jsx(Input, { type: "text", value: textValue, onValueChange: handleTextChange, onBlur: handleTextBlur, placeholder: t.placeholder, disabled: disabled, isDisabled: disabled, isInvalid: error || isInvalidFormat, size: "sm", variant: "bordered",
|
|
3873
|
+
// `min-w-0` (TECH-2459, beweossmbs QA 24-sep): el campo es un ítem de la fila
|
|
3874
|
+
// flex de la muestra de color y tiene que poder encoger en huecos estrechos
|
|
3875
|
+
// (Agenda → Colors: 180px). El `w-full min-w-0` del `<input>` en la fachada
|
|
3876
|
+
// ya lo arregla; esto es el suelo explícito en la raíz del campo.
|
|
3877
|
+
className: "min-w-0", classNames: {
|
|
3732
3878
|
input: "uppercase font-mono text-sm",
|
|
3733
3879
|
inputWrapper: "min-h-8 h-8 focus-within:!border-primary-500",
|
|
3734
3880
|
}, startContent: textValue.startsWith("#") ? null : (jsxRuntime.jsx("span", { className: "text-default-400 text-sm", children: "#" })) })] }), (error || isInvalidFormat) && (jsxRuntime.jsx("p", { className: "text-xs text-danger", children: isInvalidFormat ? t.invalidColorFormat : errorText }))] }), showPredefinedColors && predefinedColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.predefinedColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: predefinedColors.map((color) => renderColorCircle(color.value, color.name, normalizeHexColor(value) === normalizeHexColor(color.value))) })] })), enableRecentColors && recentColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.recentColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: recentColors.map((color) => renderColorCircle(color, color, normalizeHexColor(value) === color)) })] }))] }));
|
|
@@ -6744,7 +6890,16 @@ const ITEM_COLLAPSED_CLASS = "w-11 h-11 gap-0 p-0 justify-center";
|
|
|
6744
6890
|
// `w-full flex-1`: el slot `title` de v2 era `flex-1 text-small font-normal w-full`, y su slot
|
|
6745
6891
|
// `wrapper` `w-full` — el título se comía el espacio libre y empujaba el `endContent` al borde.
|
|
6746
6892
|
// El `[data-slot="label"]` de v3 es `w-fit`, que es la otra mitad de P-14.
|
|
6747
|
-
|
|
6893
|
+
//
|
|
6894
|
+
// `min-w-0 truncate`: v2 le ponía `truncate` al slot `title` siempre que el título fuera texto
|
|
6895
|
+
// (`@heroui/theme@2.4.15`, `dist/components/listbox.js`, variante `hasTitleTextChild: { true:
|
|
6896
|
+
// { title: "truncate" } }`; en el menú el título es siempre un string). La migración copió el slot
|
|
6897
|
+
// base y se dejó la variante. Sin ella, una etiqueta que no cabe no se corta:
|
|
6898
|
+
// medido en beweossmbs y en la story `Menu › LongLabelTruncation`, «menu_automations» ocupaba sus
|
|
6899
|
+
// 126,8px enteros y empujaba la chip «AI» de x=204,7 a x=222,8, 6px FUERA del ítem. `truncate` solo
|
|
6900
|
+
// no basta: un flex item parte de `min-width: auto` (su ancho de contenido) y no encoge por debajo;
|
|
6901
|
+
// `min-w-0` es lo que le deja ceder el hueco a la chip, y entonces sí corta con elipsis.
|
|
6902
|
+
const ITEM_TITLE_CLASS = "w-full min-w-0 flex-1 truncate text-sm font-medium text-default-500 group-data-[selected=true]:text-default-600";
|
|
6748
6903
|
// TECH-2459 · G2 · fix de navegación — resolución de un ítem por su clave.
|
|
6749
6904
|
//
|
|
6750
6905
|
// `onSelectionChange` del `ListBox` entrega la CLAVE, no el ítem. v2 no necesitaba esto:
|
|
@@ -9086,52 +9241,23 @@ const COLOR_VAR = {
|
|
|
9086
9241
|
warning: "var(--warning)",
|
|
9087
9242
|
danger: "var(--danger)",
|
|
9088
9243
|
};
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
* pista v2 (`@heroui/theme@2.4.15`, `dist/components/toggle.js`, slot `wrapper`)
|
|
9107
|
-
* sm 40×24 · md 48×28 · lg 56×32, `rounded-full`, `bg-default-200`
|
|
9108
|
-
* v3 (`@heroui/styles/dist/components/switch.css`)
|
|
9109
|
-
* sm 32×16 · md 40×20 · lg 48×24, `rounded-lg`/`rounded-xl`, `--default`
|
|
9110
|
-
* thumb v2 círculo `bg-white` con `shadow-small`; sm 16 · md 20 · lg 24
|
|
9111
|
-
* v3 rectángulo redondeado; sm 16,5×12 · md 22×16 · lg 27,5×20
|
|
9112
|
-
*
|
|
9113
|
-
* Ya no se pisa NADA de eso: la pista, el thumb, su radio, su color y su desplazamiento salen de
|
|
9114
|
-
* v3. Por eso desaparecieron `TRACK_CLASS`, `THUMB_CLASS`, el `bg-white`/`shadow-small` del thumb
|
|
9115
|
-
* y el `--switch-control-bg` que forzaba el gris apagado de v2 — y con ellos la clase `group`,
|
|
9116
|
-
* que solo existía para que el thumb pudiera leer el `data-selected` de esta raíz.
|
|
9117
|
-
*
|
|
9118
|
-
* Lo que SÍ se conserva, y no es aspecto:
|
|
9119
|
-
*
|
|
9120
|
-
* · `--switch-control-bg-checked` (ver `COLOR_VAR`): sostiene la prop `color` de la API v2, que
|
|
9121
|
-
* v3 eliminó. Sin ella `color="success"` y compañía dejarían de pintar. El valor de
|
|
9122
|
-
* `primary` coincide con el de v3 (`--accent` = `--color-primary`), así que el aspecto por
|
|
9123
|
-
* defecto es el de v3 igualmente.
|
|
9124
|
-
* · `inline-flex flex-row items-center` en la raíz: es COLOCACIÓN, no aspecto del control. v3
|
|
9125
|
-
* usa `flex flex-col items-start` para poder apilar `description`/`field-error`, slots que
|
|
9126
|
-
* esta fachada no renderiza; al ser **inline**, la caja participa de la línea de texto, y eso
|
|
9127
|
-
* es lo que la sitúa donde la esperan los consumidores (medido: 1px de diferencia en un
|
|
9128
|
-
* contenedor de bloque, y `schedule-row` se apoya en ello). Dentro de un contenedor flex da
|
|
9129
|
-
* igual: un ítem flex se blockifica.
|
|
9130
|
-
*
|
|
9131
|
-
* Consecuencia asumida: la referencia v2 de las stories con Switch deja de coincidir. Declarado
|
|
9132
|
-
* como CAMBIO-V3 en `vrt/classification-overrides.json`, con las cifras en
|
|
9133
|
-
* `.bewe/epics/TECH-2459/findings/p6-switch-aspecto-v3.md`.
|
|
9134
|
-
*/
|
|
9244
|
+
// Literales COMPLETOS (sin interpolar): Tailwind de las apps los descubre escaneando `dist`.
|
|
9245
|
+
const SIZE_CLASSES = {
|
|
9246
|
+
sm: {
|
|
9247
|
+
control: "h-6 w-10 rounded-full",
|
|
9248
|
+
thumb: "h-4 w-5 ms-1 rounded-full group-data-[selected=true]/switch:ms-[calc(100%-1.5rem)]",
|
|
9249
|
+
},
|
|
9250
|
+
md: {
|
|
9251
|
+
control: "h-7 w-12 rounded-full",
|
|
9252
|
+
thumb: "h-5 w-6 ms-1 rounded-full group-data-[selected=true]/switch:ms-[calc(100%-1.75rem)]",
|
|
9253
|
+
},
|
|
9254
|
+
lg: {
|
|
9255
|
+
control: "h-8 w-14 rounded-full",
|
|
9256
|
+
thumb: "h-6 w-7 ms-1 rounded-full group-data-[selected=true]/switch:ms-[calc(100%-2rem)]",
|
|
9257
|
+
},
|
|
9258
|
+
};
|
|
9259
|
+
// Thumb ENCENDIDO blanco en cualquier pack y con cualquier `color` (defecto 1 del bloque de arriba).
|
|
9260
|
+
const THUMB_ON_CLASS = "group-data-[selected=true]/switch:bg-white";
|
|
9135
9261
|
// Los subcomponentes compound de v3, adjuntos como estáticos para que la API v3 siga funcionando a
|
|
9136
9262
|
// través de la fachada (`<Switch><Switch.Content><Switch.Control><Switch.Thumb/>…`). `Root` se deja
|
|
9137
9263
|
// FUERA a propósito (mismo criterio que `Alert` y `Checkbox`): la raíz de v3 es justo la pieza que
|
|
@@ -9158,12 +9284,32 @@ function hasCompoundChildren$2(children) {
|
|
|
9158
9284
|
*
|
|
9159
9285
|
* Dos modos, decididos por los `children`:
|
|
9160
9286
|
* - **API v2** (`children` como label, `isSelected`/`defaultSelected`, `onValueChange`, `color`,
|
|
9161
|
-
* `size`): la fachada compone `Switch.Content`/`Switch.Control`/`Switch.Thumb` por
|
|
9162
|
-
* repone `color` pisando `--switch-control-bg-checked
|
|
9287
|
+
* `size`, `classNames`): la fachada compone `Switch.Content`/`Switch.Control`/`Switch.Thumb` por
|
|
9288
|
+
* dentro, repone `color` pisando `--switch-control-bg-checked`, aplica su escala de tamaños y el
|
|
9289
|
+
* thumb encendido blanco (ver el bloque de la cabecera).
|
|
9163
9290
|
* - **API compound v3** (`<Switch><Switch.Content>…`): pasa los children tal cual a la raíz de
|
|
9164
|
-
* HeroUI, sin geometría ni colocación propias.
|
|
9165
|
-
|
|
9166
|
-
|
|
9291
|
+
* HeroUI, sin geometría ni colocación propias: ahí manda el JSX del consumidor.
|
|
9292
|
+
*
|
|
9293
|
+
* `classNames` (slots de v2 → nodo de v3; las clases de la app van al FINAL y ganan por `cn`):
|
|
9294
|
+
*
|
|
9295
|
+
* base → `Switch.Content`, la `<label>` que contiene la pista y la etiqueta: es el MISMO papel
|
|
9296
|
+
* que tenía `base` en v2 (una `<label>` con esos dos hijos directos, que la app
|
|
9297
|
+
* coloca con `flex-row-reverse justify-between`, y toda ella clicable). Pero la raíz
|
|
9298
|
+
* de v3 (`SwitchField`) la envuelve con una caja `inline-flex`, y un `w-full` de la
|
|
9299
|
+
* app se resolvería contra esa caja encogida. Así que con `base` la raíz pasa a
|
|
9300
|
+
* `display: contents` (se aparta de la maqueta) y `className` viaja con `base` a la
|
|
9301
|
+
* `<label>`, como en v2 (`cn(classNames.base, className)`). Lo único de la raíz que
|
|
9302
|
+
* `contents` pierde es la opacidad de `status-disabled` (el cursor y el
|
|
9303
|
+
* `pointer-events` se heredan; los tokens de color, también): se repone en la
|
|
9304
|
+
* `<label>` con su `data-disabled`. Medido en el navegador con el JSX de smbs: la
|
|
9305
|
+
* fila entera (390×52) conmuta, no solo el texto y la pista. Sin `base` no cambia
|
|
9306
|
+
* nada.
|
|
9307
|
+
* wrapper → la pista (`Switch.Control`).
|
|
9308
|
+
* thumb → el thumb (`Switch.Thumb`).
|
|
9309
|
+
* label → un `<span data-slot="label">` que envuelve los `children`; solo existe si se pasa
|
|
9310
|
+
* `classNames.label` (sin él los children siguen PELADOS, como hasta ahora).
|
|
9311
|
+
*/
|
|
9312
|
+
const SwitchFacade = ({ id, size = "md", color, children, onChange, onValueChange, className, classNames, style, ...props }) => {
|
|
9167
9313
|
const generatedId = $8WNJc$react.useId();
|
|
9168
9314
|
const autoId = id || generatedId;
|
|
9169
9315
|
const handleChange = (isSelected) => {
|
|
@@ -9183,6 +9329,10 @@ const SwitchFacade = ({ id, size = "md", color, children, onChange, onValueChang
|
|
|
9183
9329
|
// a `status` también en compound). Sin `color`, el encendido es el `--accent` de v3.
|
|
9184
9330
|
style: color === undefined ? style : colorStyle, onChange: handleChange, children: children }));
|
|
9185
9331
|
}
|
|
9332
|
+
const sizeClasses = SIZE_CLASSES[size] ?? SIZE_CLASSES.md;
|
|
9333
|
+
// Con `classNames.base`, la `<label>` (`Switch.Content`) hace de `base` de v2 y la raíz se
|
|
9334
|
+
// aparta de la maqueta (ver `classNames` en el JSDoc de arriba).
|
|
9335
|
+
const hasBase = Boolean(classNames?.base);
|
|
9186
9336
|
return (jsxRuntime.jsx(react.Switch, { ...props, id: autoId, size: size,
|
|
9187
9337
|
// COLOCACIÓN, no aspecto (ver el bloque de arriba): v3 usa `flex flex-col items-start`
|
|
9188
9338
|
// para poder apilar `description`/`field-error`, slots que esta fachada no renderiza.
|
|
@@ -9190,10 +9340,12 @@ const SwitchFacade = ({ id, size = "md", color, children, onChange, onValueChang
|
|
|
9190
9340
|
// (Storybook centra con `#storybook-root` en `display: block`): con `flex` el widget cae
|
|
9191
9341
|
// en y=346 y con `inline-flex` en y=345, donde lo esperan los consumidores. Dentro de un
|
|
9192
9342
|
// contenedor flex (el uso real, p. ej. `schedule-row`) da igual: un ítem flex se
|
|
9193
|
-
// blockifica.
|
|
9194
|
-
className:
|
|
9195
|
-
|
|
9196
|
-
.
|
|
9343
|
+
// blockifica. `group/switch`: de aquí lee el thumb el `data-selected`.
|
|
9344
|
+
className: hasBase
|
|
9345
|
+
? "group/switch contents"
|
|
9346
|
+
: react.cn("group/switch inline-flex flex-row items-center", className), style: colorStyle, onChange: handleChange, children: jsxRuntime.jsxs(react.Switch.Content, { className: hasBase
|
|
9347
|
+
? react.cn("data-[disabled=true]:opacity-(--disabled-opacity)", classNames?.base, className)
|
|
9348
|
+
: undefined, children: [jsxRuntime.jsx(react.Switch.Control, { className: react.cn(sizeClasses.control, classNames?.wrapper), children: jsxRuntime.jsx(react.Switch.Thumb, { className: react.cn(sizeClasses.thumb, THUMB_ON_CLASS, classNames?.thumb) }) }), classNames?.label && children != null ? (jsxRuntime.jsx("span", { "data-slot": "label", className: classNames.label, children: children })) : (children)] }) }));
|
|
9197
9349
|
};
|
|
9198
9350
|
SwitchFacade.displayName = "Aurora.Switch";
|
|
9199
9351
|
/**
|
|
@@ -10919,6 +11071,46 @@ function transformBody(body) {
|
|
|
10919
11071
|
return $8WNJc$react.cloneElement(body, undefined, ...spread(mapNodes(children, withSelectionCell)));
|
|
10920
11072
|
}
|
|
10921
11073
|
|
|
11074
|
+
/**
|
|
11075
|
+
* TECH-2459 (beweossmbs, 24-sep: «Sessions history» de finanzas) — la celda del ESTADO VACÍO.
|
|
11076
|
+
*
|
|
11077
|
+
* En v3 `renderEmptyState` es un render prop de react-aria que pinta lo que devuelva dentro de
|
|
11078
|
+
* `<tbody data-empty="true"><tr role="row"><td role="rowheader" colspan>`
|
|
11079
|
+
* (`react-aria-components/dist/private/Table.mjs:886-915`), y ese `<td>` NO lleva `.table__cell`:
|
|
11080
|
+
* se queda sin el `bg-surface`, el padding ni el color de las celdas. Medido en la story
|
|
11081
|
+
* `EmptyState` con la cadena pelada que devuelven 12 de las 13 tablas de beweossmbs: 20 px de
|
|
11082
|
+
* alto, `padding: 0`, `text-align: start` (el texto pegado arriba a la izquierda) y fondo
|
|
11083
|
+
* transparente, o sea el gris de la raíz `table-root--primary` asomando.
|
|
11084
|
+
*
|
|
11085
|
+
* No es una regresión de la librería: ni la fachada ni `Table.Content` pintaron nunca ese estado
|
|
11086
|
+
* (`git log -S renderEmptyState|data-empty|emptyContent -- src/components/table` → 0 commits); lo
|
|
11087
|
+
* que se había arreglado era backoffice, en su propia app (TECH-2298, `49f2b35`: cada
|
|
11088
|
+
* `renderEmptyState` devuelve `<div className="flex h-40 items-center justify-center
|
|
11089
|
+
* text-default-500">`). Aquí se resuelve para todas las apps, en la única pieza por la que pasan
|
|
11090
|
+
* todas las tablas.
|
|
11091
|
+
*
|
|
11092
|
+
* Qué se le da a la celda, con tokens de v3 (no se busca la métrica de v2):
|
|
11093
|
+
* - `h-40`: aire. En una celda de tabla `height` actúa de alto MÍNIMO, así que un nodo propio más
|
|
11094
|
+
* alto sigue mandando, y uno de `h-40` como el de backoffice mide lo mismo (no se suma: por
|
|
11095
|
+
* eso es alto y no padding vertical).
|
|
11096
|
+
* - `px-4 text-center align-middle`: centrado en los dos ejes; `px-4` es el lateral de `.table__cell`.
|
|
11097
|
+
* - `text-sm text-default-500`: el cuerpo de las celdas de v3 (`text-sm`) en el gris atenuado que
|
|
11098
|
+
* ya usan las apps para este texto (backoffice), legible sobre el blanco (contraste AA).
|
|
11099
|
+
* - `bg-surface`: el fondo del cuerpo (`.table__cell` de `table.css`), no el gris de la raíz. Las
|
|
11100
|
+
* esquinas redondeadas ya las pone `table.css` (primera/última celda de la primera/última fila).
|
|
11101
|
+
*
|
|
11102
|
+
* Selector por `data-empty`, que react-aria solo escribe con el cuerpo vacío. Cadenas literales
|
|
11103
|
+
* completas: Tailwind solo emite lo que encuentra escrito entero.
|
|
11104
|
+
*/
|
|
11105
|
+
const EMPTY_STATE_CLASS = [
|
|
11106
|
+
"[&>tbody[data-empty]>tr>td]:h-40",
|
|
11107
|
+
"[&>tbody[data-empty]>tr>td]:px-4",
|
|
11108
|
+
"[&>tbody[data-empty]>tr>td]:text-center",
|
|
11109
|
+
"[&>tbody[data-empty]>tr>td]:align-middle",
|
|
11110
|
+
"[&>tbody[data-empty]>tr>td]:text-sm",
|
|
11111
|
+
"[&>tbody[data-empty]>tr>td]:text-default-500",
|
|
11112
|
+
"[&>tbody[data-empty]>tr>td]:bg-surface",
|
|
11113
|
+
].join(" ");
|
|
10922
11114
|
/** Default de v2 (`use-table`, `@heroui/table@2.2.32`), sin reinterpretar. */
|
|
10923
11115
|
function defaultShowCheckboxes(props) {
|
|
10924
11116
|
const behavior = props.selectionBehavior ?? "toggle";
|
|
@@ -10961,7 +11153,8 @@ function TableContent({ children, isHeaderSticky, showSelectionCheckboxes, ...pr
|
|
|
10961
11153
|
return child;
|
|
10962
11154
|
});
|
|
10963
11155
|
// Esparcido y no `{content}`: ver `spread` (un array como hijo único exigiría claves).
|
|
10964
|
-
|
|
11156
|
+
// La clase del estado vacío va delante: la de la app, detrás, gana si pisa el mismo grupo.
|
|
11157
|
+
return $8WNJc$react.createElement(react.Table.Content, { ...props, className: react.cn(EMPTY_STATE_CLASS, props.className) }, ...spread(content));
|
|
10965
11158
|
}
|
|
10966
11159
|
TableContent.displayName = "Aurora.Table.Content";
|
|
10967
11160
|
|
|
@@ -10992,6 +11185,24 @@ function isPart$2(node, parts) {
|
|
|
10992
11185
|
function withSticky(isHeaderSticky, root) {
|
|
10993
11186
|
return isHeaderSticky === undefined ? (root) : (jsxRuntime.jsx(TableStickyContext.Provider, { value: isHeaderSticky, children: root }));
|
|
10994
11187
|
}
|
|
11188
|
+
/**
|
|
11189
|
+
* TECH-2459 (beweossmbs, 24-sep) — barra de scroll NATIVA en el contenedor que inserta la fachada.
|
|
11190
|
+
*
|
|
11191
|
+
* `table.css:20` le aplica a `.table__scroll-container` la utilidad `scrollbar` de v3, que con los
|
|
11192
|
+
* tokens de `@heroui/styles` resuelve a `scrollbar-width: thin` y un pulgar al 15 % de opacidad
|
|
11193
|
+
* sobre carril transparente (medido en la story `Overflow`:
|
|
11194
|
+
* `oklch(0.2103 0.0059 285.89 / 0.15) rgba(0,0,0,0)`). Con barras clásicas (Windows, o macOS con
|
|
11195
|
+
* «mostrar barras: siempre») casi no se ve, y el usuario concluye que la tabla no tiene scroll
|
|
11196
|
+
* horizontal aunque lo tenga: es affordance, no estética. `scrollbar-default` (utilidad de la
|
|
11197
|
+
* propia v3, `utilities/index.css:71`) devuelve la barra del sistema; al ser capa `utilities`
|
|
11198
|
+
* gana a la regla de `components` sin `!important`.
|
|
11199
|
+
*
|
|
11200
|
+
* Solo en el contenedor que monta la fachada. Si la app monta su propio `Table.ScrollContainer`
|
|
11201
|
+
* (o un `ResizableContainer`), la fachada no toca nada y manda lo que la app escriba; y una clase
|
|
11202
|
+
* de la app sobre el root dirigida al contenedor (`[&_.table__scroll-container]:scrollbar-thin`)
|
|
11203
|
+
* gana por especificidad.
|
|
11204
|
+
*/
|
|
11205
|
+
const SCROLL_CONTAINER_CLASS = "scrollbar-default";
|
|
10995
11206
|
const TableFacade = ({ children, isHeaderSticky, ...props }) => {
|
|
10996
11207
|
const nodes = $8WNJc$react.Children.toArray(children);
|
|
10997
11208
|
// Sin hijos, o con un contenedor de scroll ya montado a mano: el root tal cual.
|
|
@@ -11000,7 +11211,7 @@ const TableFacade = ({ children, isHeaderSticky, ...props }) => {
|
|
|
11000
11211
|
}
|
|
11001
11212
|
const scrollable = nodes.filter((node) => !isPart$2(node, OUTSIDE_SCROLL));
|
|
11002
11213
|
const outsideScroll = nodes.filter((node) => isPart$2(node, OUTSIDE_SCROLL));
|
|
11003
|
-
return withSticky(isHeaderSticky, jsxRuntime.jsxs(react.Table, { ...props, children: [jsxRuntime.jsx(react.Table.ScrollContainer, { children: scrollable }), outsideScroll] }));
|
|
11214
|
+
return withSticky(isHeaderSticky, jsxRuntime.jsxs(react.Table, { ...props, children: [jsxRuntime.jsx(react.Table.ScrollContainer, { className: SCROLL_CONTAINER_CLASS, children: scrollable }), outsideScroll] }));
|
|
11004
11215
|
};
|
|
11005
11216
|
TableFacade.displayName = "Aurora.Table";
|
|
11006
11217
|
/**
|
|
@@ -13431,7 +13642,7 @@ function readConfirmedMonthDay(container, monthSelector = '[data-type="month"]',
|
|
|
13431
13642
|
return { month, day };
|
|
13432
13643
|
return null;
|
|
13433
13644
|
}
|
|
13434
|
-
const DayMonthPicker = ({ value, onChange, translations, }) => {
|
|
13645
|
+
const DayMonthPicker = ({ value, onChange, translations, ariaLabelledBy, }) => {
|
|
13435
13646
|
const t = {
|
|
13436
13647
|
dayMonthAriaLabel: "Seleccionar mes y día",
|
|
13437
13648
|
dayMonthRangeAriaLabel: "Seleccionar rango de mes y día",
|
|
@@ -13507,7 +13718,7 @@ const DayMonthPicker = ({ value, onChange, translations, }) => {
|
|
|
13507
13718
|
});
|
|
13508
13719
|
}
|
|
13509
13720
|
};
|
|
13510
|
-
return (jsxRuntime.jsxs("div", { className: "w-full flex flex-wrap xs:gap-5 justify-between items-center", children: [jsxRuntime.jsxs(react.RadioGroup, { orientation: "horizontal", value: mode, onChange: handleModeChange, children: [jsxRuntime.jsx(react.Radio, { value: "single", children: jsxRuntime.jsxs(react.Radio.Content, { children: [jsxRuntime.jsx(react.Radio.Control, { children: jsxRuntime.jsx(react.Radio.Indicator, {}) }), t.dayMonthSingleOption] }) }), jsxRuntime.jsx(react.Radio, { value: "range", children: jsxRuntime.jsxs(react.Radio.Content, { children: [jsxRuntime.jsx(react.Radio.Control, { children: jsxRuntime.jsx(react.Radio.Indicator, {}) }), t.dayMonthRangeOption] }) })] }), mode === "single" ? (jsxRuntime.jsx("div", { ref: singleRef, children: jsxRuntime.jsx(DatePicker, { value: pickerValue, onChange: handleSingleChange, onFocusChange: handleSingleFocusChange, "aria-label": t.dayMonthAriaLabel, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:calendar-outline" }), className: `w-full md:w-auto md:max-w-40 ${NO_YEAR_CLASS}` }, "dmp") })) : (jsxRuntime.jsx("div", { ref: rangeRef, children: jsxRuntime.jsx(DateRangePicker, { value: rangeValue, onChange: handleRangeChange, onFocusChange: handleRangeFocusChange, "aria-label": t.dayMonthRangeAriaLabel, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:calendar-outline" }), className: `w-full md:w-auto md:max-w-xs ${NO_YEAR_CLASS}` }, "dmpr") }))] }));
|
|
13721
|
+
return (jsxRuntime.jsxs("div", { className: "w-full flex flex-wrap xs:gap-5 justify-between items-center", children: [jsxRuntime.jsxs(react.RadioGroup, { orientation: "horizontal", value: mode, onChange: handleModeChange, "aria-labelledby": ariaLabelledBy, children: [jsxRuntime.jsx(react.Radio, { value: "single", children: jsxRuntime.jsxs(react.Radio.Content, { children: [jsxRuntime.jsx(react.Radio.Control, { children: jsxRuntime.jsx(react.Radio.Indicator, {}) }), t.dayMonthSingleOption] }) }), jsxRuntime.jsx(react.Radio, { value: "range", children: jsxRuntime.jsxs(react.Radio.Content, { children: [jsxRuntime.jsx(react.Radio.Control, { children: jsxRuntime.jsx(react.Radio.Indicator, {}) }), t.dayMonthRangeOption] }) })] }), mode === "single" ? (jsxRuntime.jsx("div", { ref: singleRef, children: jsxRuntime.jsx(DatePicker, { value: pickerValue, onChange: handleSingleChange, onFocusChange: handleSingleFocusChange, "aria-label": t.dayMonthAriaLabel, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:calendar-outline" }), className: `w-full md:w-auto md:max-w-40 ${NO_YEAR_CLASS}` }, "dmp") })) : (jsxRuntime.jsx("div", { ref: rangeRef, children: jsxRuntime.jsx(DateRangePicker, { value: rangeValue, onChange: handleRangeChange, onFocusChange: handleRangeFocusChange, "aria-label": t.dayMonthRangeAriaLabel, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:calendar-outline" }), className: `w-full md:w-auto md:max-w-xs ${NO_YEAR_CLASS}` }, "dmpr") }))] }));
|
|
13511
13722
|
};
|
|
13512
13723
|
|
|
13513
13724
|
/**
|
|
@@ -13643,7 +13854,8 @@ const RangeFilter = ({ title, description, value, onChange, minValue, maxValue,
|
|
|
13643
13854
|
const [min, max] = newValue;
|
|
13644
13855
|
setCurrentValue([min, max]);
|
|
13645
13856
|
onChange([min, max]);
|
|
13646
|
-
}, className: "w-full", isDisabled: false,
|
|
13857
|
+
}, className: "w-full", isDisabled: false, "aria-label": restSliderProps["aria-label"] ??
|
|
13858
|
+
(restSliderProps["aria-labelledby"] ? undefined : t.title), ...restSliderProps, children: jsxRuntime.jsxs(react.Slider.Track, { children: [jsxRuntime.jsx(react.Slider.Fill, { className: fillClassName }), stepMarks.length > 0 ? (jsxRuntime.jsx(react.Slider.Marks, { children: stepMarks.map((left) => (jsxRuntime.jsx("span", { className: SLIDER_STEP_CLASS, style: { left: `${left}%` } }, left))) })) : null, jsxRuntime.jsx(react.Slider.Thumb, { index: 0, "aria-label": t.minLabel, className: thumbClassName }), jsxRuntime.jsx(react.Slider.Thumb, { index: 1, "aria-label": t.maxLabel, className: thumbClassName })] }) }) }), jsxRuntime.jsxs("div", { className: "flex justify-between items-center text-sm", children: [jsxRuntime.jsxs("div", { className: "flex flex-col items-start", children: [jsxRuntime.jsx("span", { className: "text-xs text-default-500", children: t.minLabel }), jsxRuntime.jsx("span", { className: "font-medium text-default-700", children: formatValue(currentValue[0]) })] }), jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [jsxRuntime.jsx("span", { className: "text-xs text-default-500", children: t.maxLabel }), jsxRuntime.jsx("span", { className: "font-medium text-default-700", children: formatValue(currentValue[1]) })] })] })] }));
|
|
13647
13859
|
};
|
|
13648
13860
|
|
|
13649
13861
|
/**
|
|
@@ -13682,6 +13894,13 @@ const resolveSelectPlaceholder = (translations, title) => (translations?.selectP
|
|
|
13682
13894
|
// =========================================================================
|
|
13683
13895
|
const FilterSection = ({ filter, translations, value, onChange, isExpanded = false, onToggleExpanded, }) => {
|
|
13684
13896
|
const isDisabled = filter.disabled === true;
|
|
13897
|
+
// TECH-2459 · El título visible de la sección es el NOMBRE ACCESIBLE de su control. Sin él,
|
|
13898
|
+
// react-aria (`useLabel`, vía `useSelect`/`useSlider`/`useListBox`) avisaba en dev «If you do
|
|
13899
|
+
// not provide a visible label, you must specify an aria-label or aria-labelledby» cada vez que
|
|
13900
|
+
// se desplegaba una sección (medido por beweossmbs en el drawer del catálogo con la .141), y el
|
|
13901
|
+
// lector de pantalla anunciaba solo el placeholder («Seleccionar categoría»). El control se
|
|
13902
|
+
// asocia por `aria-labelledby` a este id: sin cambio visual.
|
|
13903
|
+
const titleId = $8WNJc$react.useId();
|
|
13685
13904
|
const [internalExpanded, setInternalExpanded] = $8WNJc$react.useState(isDisabled ? false : isExpanded);
|
|
13686
13905
|
const handleToggleExpanded = () => {
|
|
13687
13906
|
if (isDisabled)
|
|
@@ -13778,17 +13997,17 @@ const FilterSection = ({ filter, translations, value, onChange, isExpanded = fal
|
|
|
13778
13997
|
const renderFilterContent = () => {
|
|
13779
13998
|
switch (filter.type) {
|
|
13780
13999
|
case "select":
|
|
13781
|
-
return (jsxRuntime.jsx(SelectFilter, { filter: filter, value: value, onChange: onChange, translations: translations }));
|
|
14000
|
+
return (jsxRuntime.jsx(SelectFilter, { filter: filter, value: value, onChange: onChange, translations: translations, titleId: titleId }));
|
|
13782
14001
|
case "multiselect":
|
|
13783
|
-
return (jsxRuntime.jsx(MultiSelectFilter, { filter: filter, value: value, onChange: onChange, translations: translations }));
|
|
14002
|
+
return (jsxRuntime.jsx(MultiSelectFilter, { filter: filter, value: value, onChange: onChange, translations: translations, titleId: titleId }));
|
|
13784
14003
|
case "range":
|
|
13785
|
-
return (jsxRuntime.jsx(RangeFilterComponent, { filter: filter, value: value, onChange: onChange }));
|
|
14004
|
+
return (jsxRuntime.jsx(RangeFilterComponent, { filter: filter, value: value, onChange: onChange, titleId: titleId }));
|
|
13786
14005
|
case "date":
|
|
13787
|
-
return (jsxRuntime.jsx(DateFilter, { filter: filter, value: value, onChange: onChange, translations: translations }));
|
|
14006
|
+
return (jsxRuntime.jsx(DateFilter, { filter: filter, value: value, onChange: onChange, translations: translations, titleId: titleId }));
|
|
13788
14007
|
case "text":
|
|
13789
|
-
return (jsxRuntime.jsx(TextFilter, { filter: filter, value: value, onChange: onChange }));
|
|
14008
|
+
return (jsxRuntime.jsx(TextFilter, { filter: filter, value: value, onChange: onChange, titleId: titleId }));
|
|
13790
14009
|
case "number":
|
|
13791
|
-
return (jsxRuntime.jsx(NumberFilter, { filter: filter, value: value, onChange: onChange }));
|
|
14010
|
+
return (jsxRuntime.jsx(NumberFilter, { filter: filter, value: value, onChange: onChange, titleId: titleId }));
|
|
13792
14011
|
default:
|
|
13793
14012
|
return null;
|
|
13794
14013
|
}
|
|
@@ -13798,7 +14017,7 @@ const FilterSection = ({ filter, translations, value, onChange, isExpanded = fal
|
|
|
13798
14017
|
boxShadow: "var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)",
|
|
13799
14018
|
"--tw-shadow": "var(--aurora-shadow-medium)",
|
|
13800
14019
|
"--tw-shadow-colored": "var(--aurora-shadow-medium)",
|
|
13801
|
-
}, children: [jsxRuntime.jsxs("button", { type: "button", className: react.cn("flex items-center justify-between w-full text-left p-4", isDisabled && "cursor-not-allowed"), onClick: handleToggleExpanded, children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx(H2, { className: "text-base font-normal text-foreground", children: filter.title }), !isDisabled && hasActiveFilter() && (jsxRuntime.jsx("span", { className: "text-xs px-2 py-1 rounded-full text-black dark:text-white", style: {
|
|
14020
|
+
}, children: [jsxRuntime.jsxs("button", { type: "button", className: react.cn("flex items-center justify-between w-full text-left p-4", isDisabled && "cursor-not-allowed"), onClick: handleToggleExpanded, children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx(H2, { id: titleId, className: "text-base font-normal text-foreground", children: filter.title }), !isDisabled && hasActiveFilter() && (jsxRuntime.jsx("span", { className: "text-xs px-2 py-1 rounded-full text-black dark:text-white", style: {
|
|
13802
14021
|
backgroundColor: "var(--color-default)",
|
|
13803
14022
|
}, children: getActiveFilterCount() }))] }), jsxRuntime.jsx(IconComponent, { icon: internalExpanded
|
|
13804
14023
|
? "solar:alt-arrow-down-outline"
|
|
@@ -13807,10 +14026,10 @@ const FilterSection = ({ filter, translations, value, onChange, isExpanded = fal
|
|
|
13807
14026
|
// =========================================================================
|
|
13808
14027
|
// SELECT FILTER
|
|
13809
14028
|
// =========================================================================
|
|
13810
|
-
const SelectFilter = ({ filter, value, onChange, translations }) => {
|
|
14029
|
+
const SelectFilter = ({ filter, value, onChange, translations, titleId }) => {
|
|
13811
14030
|
const currentValue = value?.value || "";
|
|
13812
14031
|
const triggerPlaceholder = resolveSelectPlaceholder(translations, filter.title);
|
|
13813
|
-
return (jsxRuntime.jsx(Select, { placeholder: triggerPlaceholder, selectedKeys: new Set(currentValue ? [currentValue] : []), onSelectionChange: (keys) => {
|
|
14032
|
+
return (jsxRuntime.jsx(Select, { "aria-labelledby": titleId, placeholder: triggerPlaceholder, selectedKeys: new Set(currentValue ? [currentValue] : []), onSelectionChange: (keys) => {
|
|
13814
14033
|
const selectedKey = Array.from(keys)[0];
|
|
13815
14034
|
onChange({ value: selectedKey || "" });
|
|
13816
14035
|
}, className: "w-full", children: filter.data.map((item) => (
|
|
@@ -13824,7 +14043,8 @@ const SelectFilter = ({ filter, value, onChange, translations }) => {
|
|
|
13824
14043
|
// =========================================================================
|
|
13825
14044
|
// MULTISELECT FILTER
|
|
13826
14045
|
// =========================================================================
|
|
13827
|
-
const MultiSelectFilter = ({ filter, value, onChange, translations }) => {
|
|
14046
|
+
const MultiSelectFilter = ({ filter, value, onChange, translations, titleId }) => {
|
|
14047
|
+
const valueId = $8WNJc$react.useId();
|
|
13828
14048
|
const triggerRef = $8WNJc$react.useRef(null);
|
|
13829
14049
|
const [triggerWidthPx, setTriggerWidthPx] = $8WNJc$react.useState(null);
|
|
13830
14050
|
const [isOpen, setIsOpen] = $8WNJc$react.useState(false);
|
|
@@ -13918,11 +14138,11 @@ const MultiSelectFilter = ({ filter, value, onChange, translations }) => {
|
|
|
13918
14138
|
maxWidth: Math.max(triggerWidthPx, 220),
|
|
13919
14139
|
}
|
|
13920
14140
|
: undefined;
|
|
13921
|
-
return (jsxRuntime.jsxs(react.Popover, { isOpen: isOpen, onOpenChange: handleOpenChange, children: [jsxRuntime.jsx(react.PopoverTrigger, { children: jsxRuntime.jsxs("button", { ref: triggerRef, type: "button", className: react.cn(
|
|
14141
|
+
return (jsxRuntime.jsxs(react.Popover, { isOpen: isOpen, onOpenChange: handleOpenChange, children: [jsxRuntime.jsx(react.PopoverTrigger, { "aria-labelledby": titleId, "aria-describedby": valueId, children: jsxRuntime.jsxs("button", { ref: triggerRef, type: "button", "aria-labelledby": titleId, "aria-describedby": valueId, className: react.cn(
|
|
13922
14142
|
// TECH-2459 · `bg-transparent` y no `bg-background`: este disparador tiene pinta de campo y vive
|
|
13923
14143
|
// DENTRO de un drawer, o sea el escenario del relleno negro sobre tarjeta gris. En oscuro
|
|
13924
14144
|
// `--color-background` es negro puro, y el `bordered` de v2 no llevaba ninguna clase `bg-*`.
|
|
13925
|
-
"flex w-full min-h-12 items-center justify-between gap-2 rounded-[12px] border border-default-200 bg-transparent px-3 py-2.5 text-left text-sm transition-colors", "hover:border-default-300 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background", isOpen && "border-primary"), "aria-expanded": isOpen, "aria-haspopup": "dialog", children: [jsxRuntime.jsx("span", { className: "line-clamp-2 min-w-0 flex-1 text-sm font-medium leading-snug text-foreground", title: triggerSelectionTitle, children: triggerSelection.visible.length > 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [triggerSelection.visible.map((item, index) => (jsxRuntime.jsxs($8WNJc$react.Fragment, { children: [index > 0 ? (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: ", " })) : null, jsxRuntime.jsx("span", { children: item.label })] }, item.value))), triggerSelection.overflow > 0 ? (jsxRuntime.jsxs("span", { className: "font-normal text-default-500", children: [" ", moreLabelTemplate.replace("{more}", String(triggerSelection.overflow))] })) : null] })) : (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: triggerPlaceholder })) }), jsxRuntime.jsx(IconComponent, { icon: isOpen
|
|
14145
|
+
"flex w-full min-h-12 items-center justify-between gap-2 rounded-[12px] border border-default-200 bg-transparent px-3 py-2.5 text-left text-sm transition-colors", "hover:border-default-300 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background", isOpen && "border-primary"), "aria-expanded": isOpen, "aria-haspopup": "dialog", children: [jsxRuntime.jsx("span", { id: valueId, className: "line-clamp-2 min-w-0 flex-1 text-sm font-medium leading-snug text-foreground", title: triggerSelectionTitle, children: triggerSelection.visible.length > 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [triggerSelection.visible.map((item, index) => (jsxRuntime.jsxs($8WNJc$react.Fragment, { children: [index > 0 ? (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: ", " })) : null, jsxRuntime.jsx("span", { children: item.label })] }, item.value))), triggerSelection.overflow > 0 ? (jsxRuntime.jsxs("span", { className: "font-normal text-default-500", children: [" ", moreLabelTemplate.replace("{more}", String(triggerSelection.overflow))] })) : null] })) : (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: triggerPlaceholder })) }), jsxRuntime.jsx(IconComponent, { icon: isOpen
|
|
13926
14146
|
? "solar:alt-arrow-up-outline"
|
|
13927
14147
|
: "solar:alt-arrow-down-outline", className: "shrink-0 text-default-400", size: "sm", "aria-hidden": true })] }) }), jsxRuntime.jsx(react.PopoverContent, { placement: "bottom start", offset: 6, className: "w-full min-w-0 max-w-none box-border border border-default-200 bg-content1 p-0 shadow-medium", style: popoverWidthStyle, children: jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-0 p-2", children: [searchable && (jsxRuntime.jsx("div", { className: "border-b border-default-100 px-1 pb-2", children: jsxRuntime.jsx(Input, { type: "search", placeholder: searchPlaceholder, value: searchQuery, onValueChange: setSearchQuery, className: "w-full", size: "sm", variant: "flat", radius: "full",
|
|
13928
14148
|
// `InputClassNames` de G1-forms ya no tiene slot `base` (v3 no
|
|
@@ -13936,7 +14156,7 @@ const MultiSelectFilter = ({ filter, value, onChange, translations }) => {
|
|
|
13936
14156
|
// =========================================================================
|
|
13937
14157
|
// RANGE FILTER
|
|
13938
14158
|
// =========================================================================
|
|
13939
|
-
const RangeFilterComponent = ({ filter, value, onChange }) => {
|
|
14159
|
+
const RangeFilterComponent = ({ filter, value, onChange, titleId }) => {
|
|
13940
14160
|
const currentValue = value || { min: filter.data.min, max: filter.data.max };
|
|
13941
14161
|
const rangeValue = [currentValue.min, currentValue.max];
|
|
13942
14162
|
const handleChange = (newValue) => {
|
|
@@ -13951,12 +14171,12 @@ const RangeFilterComponent = ({ filter, value, onChange }) => {
|
|
|
13951
14171
|
const data = Array.from({
|
|
13952
14172
|
length: Math.ceil((filter.data.max - filter.data.min) / (filter.data.step || 1)) + 1,
|
|
13953
14173
|
}, (_, i) => filter.data.min + i * (filter.data.step || 1));
|
|
13954
|
-
return (jsxRuntime.jsx(RangeFilter, { title: `Rango de ${filter.title.toLowerCase()}`, minValue: filter.data.min, maxValue: filter.data.max, step: filter.data.step || 1, data: data, value: rangeValue, onChange: handleChange, formatValue: formatter, className: "w-full", showHistogramCount: filter.data.showHistogramCount }));
|
|
14174
|
+
return (jsxRuntime.jsx(RangeFilter, { title: `Rango de ${filter.title.toLowerCase()}`, minValue: filter.data.min, maxValue: filter.data.max, step: filter.data.step || 1, data: data, value: rangeValue, onChange: handleChange, formatValue: formatter, className: "w-full", showHistogramCount: filter.data.showHistogramCount, sliderProps: { "aria-labelledby": titleId } }));
|
|
13955
14175
|
};
|
|
13956
14176
|
// =========================================================================
|
|
13957
14177
|
// DATE FILTER
|
|
13958
14178
|
// =========================================================================
|
|
13959
|
-
const DateFilter = ({ filter, value, onChange, translations }) => {
|
|
14179
|
+
const DateFilter = ({ filter, value, onChange, translations, titleId }) => {
|
|
13960
14180
|
if (filter.granularity === "dayMonth") {
|
|
13961
14181
|
const rawDayMonth = value?.type === "dayMonth" && value.dayMonth && typeof value.dayMonth !== "string"
|
|
13962
14182
|
? value.dayMonth
|
|
@@ -13975,7 +14195,7 @@ const DateFilter = ({ filter, value, onChange, translations }) => {
|
|
|
13975
14195
|
dayMonthRange: value.type === "dayMonthRange" ? rawDayMonthRange : null,
|
|
13976
14196
|
}
|
|
13977
14197
|
: null;
|
|
13978
|
-
return (jsxRuntime.jsx(DayMonthPicker, { value: dayMonthValue, onChange: (v) => onChange({ date: null, dateRange: null, ...v }), translations: translations }));
|
|
14198
|
+
return (jsxRuntime.jsx(DayMonthPicker, { value: dayMonthValue, onChange: (v) => onChange({ date: null, dateRange: null, ...v }), translations: translations, ariaLabelledBy: titleId }));
|
|
13979
14199
|
}
|
|
13980
14200
|
const handleDateSelectorChange = (dateSelectorValue) => {
|
|
13981
14201
|
onChange({
|
|
@@ -14047,23 +14267,25 @@ const DateFilter = ({ filter, value, onChange, translations }) => {
|
|
|
14047
14267
|
dateSelectorTranslations.selectDateRangeAriaLabel =
|
|
14048
14268
|
translations.selectDateRangeAriaLabel;
|
|
14049
14269
|
}
|
|
14050
|
-
return (jsxRuntime.jsx(DateSelector, { initialType: getInitialType(), initialDate: getInitialDate(), initialDateRange: getInitialDateRange(), onChange: handleDateSelectorChange, translations: dateSelectorTranslations,
|
|
14270
|
+
return (jsxRuntime.jsx(DateSelector, { initialType: getInitialType(), initialDate: getInitialDate(), initialDateRange: getInitialDateRange(), onChange: handleDateSelectorChange, translations: dateSelectorTranslations,
|
|
14271
|
+
// El grupo «Día / Rango» se nombra con el título de la sección (ver `titleId`).
|
|
14272
|
+
radioGroupProps: { "aria-labelledby": titleId }, className: "w-full" }));
|
|
14051
14273
|
};
|
|
14052
14274
|
// =========================================================================
|
|
14053
14275
|
// TEXT FILTER
|
|
14054
14276
|
// =========================================================================
|
|
14055
|
-
const TextFilter = ({ filter, value, onChange }) => {
|
|
14277
|
+
const TextFilter = ({ filter, value, onChange, titleId }) => {
|
|
14056
14278
|
const currentValue = value?.value || "";
|
|
14057
|
-
return (jsxRuntime.jsx(Input, { type: "text", placeholder: filter.data.placeholder || `Ingrese ${filter.title.toLowerCase()}`, value: currentValue, onValueChange: (newValue) => {
|
|
14279
|
+
return (jsxRuntime.jsx(Input, { "aria-labelledby": titleId, type: "text", placeholder: filter.data.placeholder || `Ingrese ${filter.title.toLowerCase()}`, value: currentValue, onValueChange: (newValue) => {
|
|
14058
14280
|
onChange({ value: newValue });
|
|
14059
14281
|
}, className: "w-full" }));
|
|
14060
14282
|
};
|
|
14061
14283
|
// =========================================================================
|
|
14062
14284
|
// NUMBER FILTER
|
|
14063
14285
|
// =========================================================================
|
|
14064
|
-
const NumberFilter = ({ filter, value, onChange }) => {
|
|
14286
|
+
const NumberFilter = ({ filter, value, onChange, titleId }) => {
|
|
14065
14287
|
const currentValue = value?.value?.toString() || "";
|
|
14066
|
-
return (jsxRuntime.jsx(Input, { type: "number", placeholder: filter.data.placeholder || `Ingrese ${filter.title.toLowerCase()}`, value: currentValue, onValueChange: (newValue) => {
|
|
14288
|
+
return (jsxRuntime.jsx(Input, { "aria-labelledby": titleId, type: "number", placeholder: filter.data.placeholder || `Ingrese ${filter.title.toLowerCase()}`, value: currentValue, onValueChange: (newValue) => {
|
|
14067
14289
|
const numValue = newValue === "" ? null : Number(newValue);
|
|
14068
14290
|
onChange({ value: numValue });
|
|
14069
14291
|
}, min: filter.data.min, max: filter.data.max, step: filter.data.step, className: "w-full" }));
|
|
@@ -16350,13 +16572,19 @@ ModalBody.displayName = "ModalBody";
|
|
|
16350
16572
|
* v3 conserva `flex-row justify-end gap-2` pero pierde el padding, y añade un
|
|
16351
16573
|
* `.modal__body + .modal__footer { mt-5 }` que v2 no tenía (v2 separaba los slots solo
|
|
16352
16574
|
* con su propio padding) — de ahí el `mt-0`.
|
|
16575
|
+
*
|
|
16576
|
+
* `items-stretch`: v2 no declaraba `items-*` (`align-items: normal`, que en flex estira), y v3
|
|
16577
|
+
* pone `items-center`. En un footer en columna (`className="flex flex-col"`, «Register payment»
|
|
16578
|
+
* de beweossmbs) eso encogía cada fila a su contenido: medido con la .141, Total 83px frente a
|
|
16579
|
+
* 464 y botones `flex-1` 108px frente a 226. En la fila por defecto no cambia nada visible
|
|
16580
|
+
* (los `Button` tienen alto propio). Un `items-*` de la app lo retira por fusión.
|
|
16353
16581
|
*/
|
|
16354
16582
|
const ModalFooter = ({ className, ...props }) => {
|
|
16355
16583
|
const { classNames } = $8WNJc$react.useContext(ModalFacadeContext);
|
|
16356
16584
|
return (jsxRuntime.jsx(react.ModalFooter, { ...props,
|
|
16357
16585
|
// v2 `classNames.footer` del `<Modal>` entre la fachada y el `className` propio, que
|
|
16358
16586
|
// gana (`clsx(classNames.footer, className)` en `@heroui/modal@2.2.19`).
|
|
16359
|
-
className: react.cn("mt-0 px-6 py-4", classNames?.footer, className) }));
|
|
16587
|
+
className: react.cn("mt-0 items-stretch px-6 py-4", classNames?.footer, className) }));
|
|
16360
16588
|
};
|
|
16361
16589
|
ModalFooter.displayName = "ModalFooter";
|
|
16362
16590
|
|
|
@@ -16453,7 +16681,8 @@ const DrawerFacade = ({ isOpen, defaultOpen, onOpenChange, onClose, placement =
|
|
|
16453
16681
|
// Sin `Drawer.Root` (el `DialogTrigger` de react-aria) a propósito: la fachada no tiene
|
|
16454
16682
|
// disparador propio —lo abre el `isOpen` de la app— y un `DialogTrigger` sin hijo pulsable
|
|
16455
16683
|
// avisa en consola en CADA montaje («A PressResponder was rendered without a pressable
|
|
16456
|
-
// child», medido en jsdom
|
|
16684
|
+
// child», medido en jsdom). `Modal` hace lo mismo desde 27958d2 (ya no monta `Modal.Root`) y
|
|
16685
|
+
// `Modal.v2.test.tsx` vigila 0 avisos con modales cerrados. `Drawer.Backdrop` (`ModalOverlay`)
|
|
16457
16686
|
// ya crea y publica su propio estado de overlay con `isOpen`/`onOpenChange`, y trae todos los
|
|
16458
16687
|
// slots de `drawerVariants()`, así que el root no aportaba nada.
|
|
16459
16688
|
return (jsxRuntime.jsx(react.Drawer.Backdrop, { isOpen: isOpen, defaultOpen: defaultOpen, onOpenChange: handleOpenChange, variant: backdrop, isDismissable: isDismissable, isKeyboardDismissDisabled: isKeyboardDismissDisabled, children: jsxRuntime.jsx(react.Drawer.Content, { placement: placement, children: jsxRuntime.jsx(react.Drawer.Dialog, { "aria-labelledby": headerId, className: react.cn(sizeClass(size, placement), "p-0", scrollBehavior === "outside" && "overflow-y-auto", className), children: ({ close }) => (jsxRuntime.jsx(DrawerDialogBody, { close: close, headerId: headerId, scrollBehavior: scrollBehavior, hideCloseButton: hideCloseButton, children: children })) }) }) }));
|
|
@@ -16544,9 +16773,11 @@ DrawerBody.displayName = "Aurora.DrawerBody";
|
|
|
16544
16773
|
* Geometría v2 del slot `footer`: `flex flex-row gap-2 px-6 py-4 justify-end`
|
|
16545
16774
|
* (`@heroui/theme@2.4.15`, slot `footer`). v3 conserva `flex-row justify-end gap-2` pero pierde
|
|
16546
16775
|
* el padding y añade `.drawer__body + .drawer__footer { mt-5 }`, que v2 no tenía — de ahí el
|
|
16547
|
-
* `mt-0` (mismo arreglo que `ModalFooter`).
|
|
16776
|
+
* `mt-0` (mismo arreglo que `ModalFooter`). Y `items-stretch` en lugar del `items-center` de
|
|
16777
|
+
* v3: v2 no declaraba `items-*`, así que un footer en columna estiraba sus filas (en «Register
|
|
16778
|
+
* payment» de beweossmbs, Total 83px frente a 464 con la .141; detalle en `ModalFooter`).
|
|
16548
16779
|
*/
|
|
16549
|
-
const DrawerFooter = ({ className, children }) => (jsxRuntime.jsx(react.DrawerFooter, { className: react.cn("mt-0 px-6 py-4", className), children: children }));
|
|
16780
|
+
const DrawerFooter = ({ className, children }) => (jsxRuntime.jsx(react.DrawerFooter, { className: react.cn("mt-0 items-stretch px-6 py-4", className), children: children }));
|
|
16550
16781
|
DrawerFooter.displayName = "Aurora.DrawerFooter";
|
|
16551
16782
|
|
|
16552
16783
|
// TECH-2459 — Fachada `Alert` (hallazgo loginos 07-sep: `index.tsx` reexportaba el `Alert` CRUDO de
|