@beweco/aurora-ui 1.0.0-beta.138 → 1.0.0-beta.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +520 -64
  3. package/dist/index.esm.js +519 -48
  4. package/dist/types/__smoke__/v2-api-surface.d.ts +5 -2
  5. package/dist/types/__smoke__/v2-api-surface.d.ts.map +1 -1
  6. package/dist/types/compat/heroui-v2-shims.d.ts +72 -7
  7. package/dist/types/compat/heroui-v2-shims.d.ts.map +1 -1
  8. package/dist/types/components/datepicker/DatePicker.d.ts +1 -1
  9. package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
  10. package/dist/types/components/datepicker/DatePicker.types.d.ts +74 -1
  11. package/dist/types/components/datepicker/DatePicker.types.d.ts.map +1 -1
  12. package/dist/types/components/datepicker/calendar-slots.d.ts +17 -0
  13. package/dist/types/components/datepicker/calendar-slots.d.ts.map +1 -0
  14. package/dist/types/components/datepicker/index.d.ts +1 -1
  15. package/dist/types/components/datepicker/index.d.ts.map +1 -1
  16. package/dist/types/components/daterangepicker/DateRangePicker.d.ts +1 -1
  17. package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -1
  18. package/dist/types/components/daterangepicker/DateRangePicker.types.d.ts +43 -1
  19. package/dist/types/components/daterangepicker/DateRangePicker.types.d.ts.map +1 -1
  20. package/dist/types/components/daterangepicker/index.d.ts +1 -1
  21. package/dist/types/components/daterangepicker/index.d.ts.map +1 -1
  22. package/dist/types/components/drawer/Drawer.d.ts +58 -0
  23. package/dist/types/components/drawer/Drawer.d.ts.map +1 -0
  24. package/dist/types/components/drawer/Drawer.types.d.ts +75 -0
  25. package/dist/types/components/drawer/Drawer.types.d.ts.map +1 -0
  26. package/dist/types/components/drawer/DrawerContext.d.ts +15 -0
  27. package/dist/types/components/drawer/DrawerContext.d.ts.map +1 -0
  28. package/dist/types/components/drawer/_internal/DrawerBody.d.ts +7 -0
  29. package/dist/types/components/drawer/_internal/DrawerBody.d.ts.map +1 -0
  30. package/dist/types/components/drawer/_internal/DrawerContent.d.ts +14 -0
  31. package/dist/types/components/drawer/_internal/DrawerContent.d.ts.map +1 -0
  32. package/dist/types/components/drawer/_internal/DrawerFooter.d.ts +13 -0
  33. package/dist/types/components/drawer/_internal/DrawerFooter.d.ts.map +1 -0
  34. package/dist/types/components/drawer/_internal/DrawerHeader.d.ts +20 -0
  35. package/dist/types/components/drawer/_internal/DrawerHeader.d.ts.map +1 -0
  36. package/dist/types/components/drawer/_internal/index.d.ts +5 -0
  37. package/dist/types/components/drawer/_internal/index.d.ts.map +1 -0
  38. package/dist/types/components/drawer/index.d.ts +4 -0
  39. package/dist/types/components/drawer/index.d.ts.map +1 -0
  40. package/dist/types/components/modal/Modal.d.ts +1 -1
  41. package/dist/types/components/modal/Modal.d.ts.map +1 -1
  42. package/dist/types/components/modal/Modal.types.d.ts +8 -0
  43. package/dist/types/components/modal/Modal.types.d.ts.map +1 -1
  44. package/dist/types/components/modal/_internal/ModalBody.d.ts +1 -1
  45. package/dist/types/components/tabs/Tabs.d.ts +5 -4
  46. package/dist/types/components/tabs/Tabs.d.ts.map +1 -1
  47. package/dist/types/components/tabs/Tabs.types.d.ts +90 -13
  48. package/dist/types/components/tabs/Tabs.types.d.ts.map +1 -1
  49. package/dist/types/components/time-input/TimeInput.d.ts +12 -8
  50. package/dist/types/components/time-input/TimeInput.d.ts.map +1 -1
  51. package/dist/types/components/time-input/TimeInput.types.d.ts +17 -3
  52. package/dist/types/components/time-input/TimeInput.types.d.ts.map +1 -1
  53. package/dist/types/components/time-input/index.d.ts +2 -2
  54. package/dist/types/components/time-input/index.d.ts.map +1 -1
  55. package/dist/types/index.d.ts +3 -2
  56. package/dist/types/index.d.ts.map +1 -1
  57. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -40,16 +40,24 @@ const Progress = react.ProgressBar;
40
40
  /** Divider → Separator. El uso INTERNO de la librería ya migró a `Separator` directo
41
41
  * (`TagsFilter.tsx`); este shim es solo para las apps, que siguen importando `Divider`. */
42
42
  const Divider = react.Separator;
43
- // ---------------------------------------------------------------------------
44
- // Eliminados
45
- // ---------------------------------------------------------------------------
46
43
  /**
47
- * `HeroUIProvider` ya no existe en v3 (los componentes no necesitan Provider). Shim no-op: pasa
48
- * los `children` tal cual para que el `<HeroUIProvider>` (aliased `AuroraProvider`) que envuelve
49
- * la raíz de las 4 apps siga compilando y renderizando sin cambios.
44
+ * `HeroUIProvider` ya no existe en v3 (los componentes no necesitan Provider para pintarse). Pero
45
+ * el de v2 hacía dos cosas que react-aria sí necesita y que las apps no pueden montar por su
46
+ * cuenta (todo pasa por aurora-ui): `locale` → `I18nProvider` y `navigate`/`useHref` →
47
+ * `RouterProvider`. Este shim las repone, cada una SOLO cuando se pasa; sin props pasa los
48
+ * `children` tal cual, como el no-op que era. El resto de props v2 se aceptan y se ignoran (ver
49
+ * `HeroUIProviderProps`). Orden de anidado idéntico al de v2: `I18nProvider` por fuera,
50
+ * `RouterProvider` por dentro.
50
51
  */
51
- function HeroUIProvider({ children }) {
52
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
52
+ function HeroUIProvider({ children, locale, navigate, useHref, }) {
53
+ let contents = children;
54
+ if (navigate) {
55
+ contents = (jsxRuntime.jsx(react.RouterProvider, { navigate: navigate, useHref: useHref, children: contents }));
56
+ }
57
+ if (locale) {
58
+ contents = jsxRuntime.jsx(react.I18nProvider, { locale: locale, children: contents });
59
+ }
60
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: contents });
53
61
  }
54
62
  /**
55
63
  * `Image` se elimina en v3 (usar `<img>` nativo, mismo criterio aplicado en
@@ -1185,6 +1193,33 @@ exports.HolidayType = void 0;
1185
1193
  HolidayType["DateRange"] = "dateRange";
1186
1194
  })(exports.HolidayType || (exports.HolidayType = {}));
1187
1195
 
1196
+ // Piezas compartidas por `DatePicker` y `DateRangePicker` para reponer `classNames` y
1197
+ // `calendarWidth` de v2 (TECH-2459). Interno: no se exporta desde el índice del paquete.
1198
+ /**
1199
+ * Fusiona las clases de la fachada con las del consumidor (`classNames.<slot>`), las del consumidor
1200
+ * DETRÁS para que ganen en tailwind-merge — como el `slots.x({ class })` de v2, cuyo `tv` llevaba
1201
+ * `twMerge: true`. Sin clase del consumidor la cadena de la fachada sale TAL CUAL (unida con
1202
+ * espacios, como antes de existir `classNames`): pasar la fachada por `cn` sin necesidad resolvería
1203
+ * sus conflictos internos (p. ej. `rounded-none` de `underlined` contra el radio) de otra forma que
1204
+ * la cascada de hoy, y cambiaría el píxel de quien no usa la prop.
1205
+ */
1206
+ function withConsumerClass(own, consumer) {
1207
+ const base = own.filter(Boolean).join(" ");
1208
+ return consumer ? react.cn(base, consumer) : base;
1209
+ }
1210
+ /**
1211
+ * `calendarWidth` de v2 → estilo en línea del `Calendar`. v3 fija `.calendar { w-63 max-w-63 }`
1212
+ * (`@heroui/styles/dist/components/calendar.css:11-13`), así que el `max-width` tiene que acompañar
1213
+ * al `width`: con solo `width: 300px` el tope de 252px lo seguiría recortando.
1214
+ */
1215
+ function calendarWidthStyle(calendarWidth, style) {
1216
+ if (calendarWidth === undefined) {
1217
+ return style;
1218
+ }
1219
+ const width = typeof calendarWidth === "number" ? `${calendarWidth}px` : calendarWidth;
1220
+ return { ...style, width, maxWidth: width };
1221
+ }
1222
+
1188
1223
  // Mismo mecanismo que Input/Select (findings/campo-texto-responsive-sm-trap.md):
1189
1224
  // `.date-input-group__input` fija su propio `text-base sm:text-sm` — se repite la clase de
1190
1225
  // tamaño de TEXTO directo en `DateField.Input`, no solo en el `DateField.Group` contenedor.
@@ -1259,20 +1294,25 @@ const CALENDAR_CELL_CLASS$1 = "size-8 place-self-center rounded-full " +
1259
1294
  * (grid) para que la API pública siga siendo un único componente con props planas, igual que en
1260
1295
  * v2 (label, description, errorMessage, endContent, variant, size, radius).
1261
1296
  */
1262
- function DatePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent, className, "aria-label": ariaLabel, ...props }) {
1297
+ function DatePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent: calendarBottomContentProp, CalendarBottomContent, calendarTopContent: calendarTopContentProp, CalendarTopContent, calendarWidth, calendarProps, classNames, className, "aria-label": ariaLabel, ...props }) {
1263
1298
  const generatedId = $8WNJc$react.useId();
1264
1299
  const autoId = id || generatedId;
1265
- const calendarLabel = (typeof label === "string" ? label : undefined) ?? ariaLabel ?? "Calendario";
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
- .filter(Boolean)
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: [
1300
+ const calendarLabel = (typeof label === "string" ? label : undefined) ??
1301
+ ariaLabel ??
1302
+ "Calendario";
1303
+ const calendarBottomContent = calendarBottomContentProp ?? CalendarBottomContent;
1304
+ const calendarTopContent = calendarTopContentProp ?? CalendarTopContent;
1305
+ const { className: calendarClassName, style: calendarStyle, ...restCalendarProps } = calendarProps ?? {};
1306
+ return (jsxRuntime.jsxs(react.DatePicker, { ...props, id: autoId, "aria-label": ariaLabel, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, className: withConsumerClass(["flex flex-col gap-1", fullWidth && "w-full", classNames?.base], className), children: [label && (jsxRuntime.jsx(react.Label, { className: withConsumerClass(["text-default-600 text-xs font-medium"], classNames?.label), children: label })), jsxRuntime.jsxs(react.DateField.Group, { fullWidth: fullWidth, className: withConsumerClass([
1269
1307
  SIZE_CLASS$5[size],
1270
1308
  RADIUS_CLASS$8[radius],
1271
1309
  VARIANT_CLASS$5[variant],
1272
1310
  FIELD_FOCUS_CLASS$5,
1273
- ]
1274
- .filter(Boolean)
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 })] }));
1311
+ ], classNames?.inputWrapper), children: [jsxRuntime.jsx(react.DateField.Input, { className: withConsumerClass([SIZE_TEXT_CLASS$4[size]], classNames?.input), children: (segment) => (jsxRuntime.jsx(react.DateField.Segment, { segment: segment, className: classNames?.segment })) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DatePicker.Trigger, { className: classNames?.selectorButton, children: endContent !== undefined ? (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, { className: classNames?.selectorIcon, children: endContent })) : (jsxRuntime.jsx(react.DatePicker.TriggerIndicator, { className: classNames?.selectorIcon })) }) })] }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: classNames?.description, children: description })), jsxRuntime.jsxs(react.DatePicker.Popover, { className: classNames?.popoverContent, children: [calendarTopContent, jsxRuntime.jsxs(react.Calendar, { "aria-label": calendarLabel, minValue: props.minValue, maxValue: props.maxValue, ...restCalendarProps, className: withConsumerClass([
1312
+ typeof calendarClassName === "string"
1313
+ ? calendarClassName
1314
+ : undefined,
1315
+ ], classNames?.calendar) || undefined, style: calendarWidthStyle(calendarWidth, typeof calendarStyle === "object" ? calendarStyle : undefined), 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, { className: classNames?.errorMessage, children: errorMessage }))] }));
1276
1316
  }
1277
1317
 
1278
1318
  // Mismo mecanismo que DatePicker.tsx / Input.tsx / Select.tsx (findings/
@@ -1351,20 +1391,25 @@ const CALENDAR_CELL_CLASS = "data-[today=true]:not-data-[selected=true]:[&_[data
1351
1391
  * `DatePicker`, migrado en tándem. Compone `DateRangePicker.Root/Trigger/TriggerIndicator/
1352
1392
  * RangeSeparator/Popover` + `DateField` (dos segmentos, start/end) + `RangeCalendar`.
1353
1393
  */
1354
- function DateRangePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent, className, "aria-label": ariaLabel, ...props }) {
1394
+ function DateRangePicker({ label, description, errorMessage, id, size = "md", variant = "bordered", radius = "md", isInvalid = false, isRequired = false, isDisabled = false, fullWidth, endContent, calendarBottomContent: calendarBottomContentProp, CalendarBottomContent, calendarTopContent: calendarTopContentProp, CalendarTopContent, calendarWidth, calendarProps, classNames, className, "aria-label": ariaLabel, ...props }) {
1355
1395
  const generatedId = $8WNJc$react.useId();
1356
1396
  const autoId = id || generatedId;
1357
- const calendarLabel = (typeof label === "string" ? label : undefined) ?? ariaLabel ?? "Rango de fechas";
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
- .filter(Boolean)
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: [
1397
+ const calendarLabel = (typeof label === "string" ? label : undefined) ??
1398
+ ariaLabel ??
1399
+ "Rango de fechas";
1400
+ const calendarBottomContent = calendarBottomContentProp ?? CalendarBottomContent;
1401
+ const calendarTopContent = calendarTopContentProp ?? CalendarTopContent;
1402
+ const { className: calendarClassName, style: calendarStyle, ...restCalendarProps } = calendarProps ?? {};
1403
+ return (jsxRuntime.jsxs(react.DateRangePicker, { ...props, id: autoId, "aria-label": ariaLabel, isInvalid: isInvalid, isRequired: isRequired, isDisabled: isDisabled, className: withConsumerClass(["flex flex-col gap-1", fullWidth && "w-full", classNames?.base], className), children: [label && (jsxRuntime.jsx(react.Label, { className: withConsumerClass(["text-default-600 text-xs font-medium"], classNames?.label), children: label })), jsxRuntime.jsxs(react.DateField.Group, { fullWidth: fullWidth, className: withConsumerClass([
1361
1404
  SIZE_CLASS$4[size],
1362
1405
  RADIUS_CLASS$7[radius],
1363
1406
  VARIANT_CLASS$4[variant],
1364
1407
  FIELD_FOCUS_CLASS$4,
1365
- ]
1366
- .filter(Boolean)
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 })] }));
1408
+ ], classNames?.inputWrapper), children: [jsxRuntime.jsx(react.DateField.Input, { slot: "start", className: withConsumerClass([SIZE_TEXT_CLASS$3[size]], classNames?.input), children: (segment) => (jsxRuntime.jsx(react.DateField.Segment, { segment: segment, className: classNames?.segment })) }), jsxRuntime.jsx(react.DateRangePicker.RangeSeparator, { className: classNames?.separator }), jsxRuntime.jsx(react.DateField.Input, { slot: "end", className: withConsumerClass([SIZE_TEXT_CLASS$3[size]], classNames?.input), children: (segment) => (jsxRuntime.jsx(react.DateField.Segment, { segment: segment, className: classNames?.segment })) }), jsxRuntime.jsx(react.DateField.Suffix, { children: jsxRuntime.jsx(react.DateRangePicker.Trigger, { className: classNames?.selectorButton, children: endContent !== undefined ? (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, { className: classNames?.selectorIcon, children: endContent })) : (jsxRuntime.jsx(react.DateRangePicker.TriggerIndicator, { className: classNames?.selectorIcon })) }) })] }), description && !isInvalid && (jsxRuntime.jsx(react.Description, { className: classNames?.description, children: description })), jsxRuntime.jsxs(react.DateRangePicker.Popover, { className: classNames?.popoverContent, children: [calendarTopContent, jsxRuntime.jsxs(react.RangeCalendar, { "aria-label": calendarLabel, minValue: props.minValue, maxValue: props.maxValue, ...restCalendarProps, className: withConsumerClass([
1409
+ typeof calendarClassName === "string"
1410
+ ? calendarClassName
1411
+ : undefined,
1412
+ ], classNames?.calendar) || undefined, style: calendarWidthStyle(calendarWidth, typeof calendarStyle === "object" ? calendarStyle : undefined), 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, { className: classNames?.errorMessage, children: errorMessage }))] }));
1368
1413
  }
1369
1414
 
1370
1415
  // TECH-2459 · F3.0 — v3 divide el `Input` monolítico de v2 en `TextField` (label/description/
@@ -8279,6 +8324,32 @@ const FIELD_BORDER_CLASS = "border-2 border-default-200 bg-background focus-with
8279
8324
  */
8280
8325
  const ROOT_INLINE_LABEL_CLASS = "flex-row items-center gap-x-2 flex-nowrap";
8281
8326
  const LABEL_CLASS$2 = "text-xs font-normal text-default-600";
8327
+ /*
8328
+ * TECH-2459 · hallazgo widgets 23-sep (`findings/app-widgets-timeinput-label-inline.md`) — la
8329
+ * etiqueta ENCIMA, para el nombre `TimeInput` a secas.
8330
+ *
8331
+ * En v2 (0.6.85, `dist/index.esm.js`) había DOS componentes bajo dos nombres: la fachada de arriba
8332
+ * (con `labelPlacement: "outside-left"`) se exportaba SOLO como `TimeInputComponent`
8333
+ * (`export { …, TimeInput as TimeInputComponent, … }`), y `TimeInput` a secas llegaba por el
8334
+ * `export * from '@heroui/react'`: el crudo de HeroUI 2.7.11, con la etiqueta encima. v1 había
8335
+ * apuntado los dos nombres a la fachada en línea, y el alta de agenda de widgets (que importa
8336
+ * `TimeInput` a secas junto a un `DatePicker`) quedó con «Hora» a la izquierda y «Fecha» encima.
8337
+ *
8338
+ * Las clases son las MISMAS que la fachada de `DatePicker` pone en su raíz y en su `Label`
8339
+ * (`DatePicker.tsx`: `"flex flex-col gap-1"` y `"text-default-600 text-xs font-medium"`), para que
8340
+ * en un formulario las dos etiquetas y los dos campos caigan en la misma línea. El grupo ya mide lo
8341
+ * mismo que el `size="md"` por defecto del `DatePicker` (`h-10 min-h-10`).
8342
+ */
8343
+ const ROOT_OUTSIDE_LABEL_CLASS = "flex flex-col gap-1";
8344
+ const OUTSIDE_LABEL_CLASS = "text-default-600 text-xs font-medium";
8345
+ const ROOT_CLASS = {
8346
+ outside: ROOT_OUTSIDE_LABEL_CLASS,
8347
+ "outside-left": ROOT_INLINE_LABEL_CLASS,
8348
+ };
8349
+ const LABEL_CLASS_BY_PLACEMENT = {
8350
+ outside: OUTSIDE_LABEL_CLASS,
8351
+ "outside-left": LABEL_CLASS$2,
8352
+ };
8282
8353
  const GROUP_SIZE_CLASS = "flex-1 h-10 min-h-10 shadow-xs";
8283
8354
  /*
8284
8355
  * TECH-2459 · F5 · R3 — Avance de los segmentos: se reproduce el de v2 MEDIDO en el PNG.
@@ -8339,16 +8410,11 @@ const DAY_PERIOD_SEGMENT_CLASS = "ms-0.5";
8339
8410
  */
8340
8411
  const FIELD_FOCUS_CLASS$2 = "ring-0 ring-offset-0";
8341
8412
  /**
8342
- * TimeInput genérico reutilizable, migrado al `TimeField` compound de HeroUI v3 (el `TimeInput`
8343
- * de v2 se elimina). Mantiene `label` + los props de estado de v2 (`value`, `onChange`,
8344
- * `isDisabled`, `isInvalid`, `isRequired`, `granularity`, `hourCycle`, `minValue`, `maxValue`…),
8345
- * que no cambiaron (son de React Aria, no de HeroUI).
8346
- *
8347
- * La etiqueta va en línea a la izquierda del campo, como en v2 (ver el bloque de arriba). v2 no
8348
- * exponía `labelPlacement` en su API pública (`Omit<HeroUITimeInputProps, "labelPlacement">`), así
8349
- * que aquí tampoco: la colocación es la del diseño de BeweOS y no se configura.
8413
+ * Implementación común de los dos nombres exportados. La única diferencia entre `TimeInput` y
8414
+ * `TimeInputComponent` es el valor por defecto de `labelPlacement`; una `labelPlacement` explícita
8415
+ * gana siempre.
8350
8416
  */
8351
- function TimeInput({ label, id, className,
8417
+ function TimeInputBase({ label, id, className, labelPlacement,
8352
8418
  // v2 lo forzaba a `true` en su propio hook (`@heroui/date-input@2.3.24` →
8353
8419
  // `dist/use-time-input.js:58`, `shouldForceLeadingZeros = true`), así que la referencia v2
8354
8420
  // muestra "09:00 AM"; React Aria por sí solo deja "9:00 AM". Es una prop de React Aria que v3
@@ -8360,10 +8426,29 @@ shouldForceLeadingZeros = true, ...props }) {
8360
8426
  // `cn` (tailwind-merge) y no una concatenación: el consumidor tiene que poder pisar la
8361
8427
  // colocación y el ancho (`ScheduleRow` pasa `w-full`). Todas las clases de aquí son
8362
8428
  // vocabulario v3 válido, así que tailwind-merge las resuelve bien.
8363
- className: react.cn(ROOT_INLINE_LABEL_CLASS, className), shouldForceLeadingZeros: shouldForceLeadingZeros, ...props, children: [label && jsxRuntime.jsx(react.Label, { className: LABEL_CLASS$2, children: label }), jsxRuntime.jsx(react.TimeField.Group, { className: react.cn(FIELD_BORDER_CLASS, GROUP_SIZE_CLASS, FIELD_FOCUS_CLASS$2), children: jsxRuntime.jsx(react.TimeField.Input, { className: INPUT_CLASS, children: (segment) => (jsxRuntime.jsx(react.TimeField.Segment, { segment: segment, className: segment.type === "dayPeriod"
8429
+ className: react.cn(ROOT_CLASS[labelPlacement], className), shouldForceLeadingZeros: shouldForceLeadingZeros, ...props, children: [label && (jsxRuntime.jsx(react.Label, { className: LABEL_CLASS_BY_PLACEMENT[labelPlacement], children: label })), jsxRuntime.jsx(react.TimeField.Group, { className: react.cn(FIELD_BORDER_CLASS, GROUP_SIZE_CLASS, FIELD_FOCUS_CLASS$2), children: jsxRuntime.jsx(react.TimeField.Input, { className: INPUT_CLASS, children: (segment) => (jsxRuntime.jsx(react.TimeField.Segment, { segment: segment, className: segment.type === "dayPeriod"
8364
8430
  ? DAY_PERIOD_SEGMENT_CLASS
8365
8431
  : undefined })) }) })] }));
8366
8432
  }
8433
+ /**
8434
+ * `TimeInput` — el nombre que en v2 era el crudo de HeroUI: etiqueta ENCIMA del campo
8435
+ * (`labelPlacement="outside"` por defecto), alineada con la de `DatePicker`. Migrado al
8436
+ * `TimeField` compound de v3; conserva `label` + los props de estado de v2 (`value`, `onChange`,
8437
+ * `isDisabled`, `isInvalid`, `isRequired`, `granularity`, `hourCycle`, `minValue`, `maxValue`…),
8438
+ * que son de React Aria y no cambiaron: `onChange` entrega un `TimeValue` de
8439
+ * `@internationalized/date` (o `null`), igual que el crudo de v2.
8440
+ */
8441
+ function TimeInput({ labelPlacement = "outside", ...props }) {
8442
+ return jsxRuntime.jsx(TimeInputBase, { ...props, labelPlacement: labelPlacement });
8443
+ }
8444
+ /**
8445
+ * `TimeInputComponent` — la fachada BeweOS de v2: etiqueta EN LÍNEA a la izquierda del campo
8446
+ * (`labelPlacement="outside-left"` por defecto, el `outside-left` que v2 fijaba sin exponerlo).
8447
+ * Es lo que usan `ScheduleRow`, beweossmbs y chatbot-claw.
8448
+ */
8449
+ function TimeInputComponent({ labelPlacement = "outside-left", ...props }) {
8450
+ return jsxRuntime.jsx(TimeInputBase, { ...props, labelPlacement: labelPlacement });
8451
+ }
8367
8452
 
8368
8453
  /**
8369
8454
  * @file schedule-row.constants.ts
@@ -8567,7 +8652,7 @@ const ScheduleRow = ({ day, daySchedule, translations = {}, showCopyToAll = fals
8567
8652
  const isLastSlot = index === slotsToDisplay.length - 1;
8568
8653
  const isSlotFilled = slot.from && slot.to;
8569
8654
  const canDelete = slotsToDisplay.length > 1;
8570
- return (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 w-full justify-between", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-1", children: [jsxRuntime.jsx(TimeInput, { label: t.from, className: "w-full", value: toTimeValue(slot.from), onChange: (value) => handleTimeChange(index, "from", value), isInvalid: !!slot.error }), jsxRuntime.jsx("span", { className: "text-default-900 xs:hidden xl:block", children: "-" }), jsxRuntime.jsx(TimeInput, { label: t.to, className: "w-full", value: toTimeValue(slot.to), onChange: (value) => handleTimeChange(index, "to", value), isInvalid: !!slot.error })] }), slot.error && (jsxRuntime.jsx("span", { className: "text-xs text-danger", children: slot.error }))] }), isLastSlot ? (jsxRuntime.jsx(Button, { isIconOnly: true, size: "sm", color: "primary", variant: "light", onPress: handleAddTimeSlot, isDisabled: !isSlotFilled, startContent: jsxRuntime.jsx(IconComponent, { icon: "solar:add-circle-bold" }) })) : (jsxRuntime.jsx(Button, { isIconOnly: true, size: "sm", color: "danger", variant: "light", onPress: () => handleRemoveTimeSlot(index), isDisabled: !canDelete, startContent: jsxRuntime.jsx(IconComponent, { icon: "solar:trash-bin-minimalistic-outline" }) }))] }, `${day}-timeslot-${index}`));
8655
+ return (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 w-full justify-between", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-1", children: [jsxRuntime.jsx(TimeInputComponent, { label: t.from, className: "w-full", value: toTimeValue(slot.from), onChange: (value) => handleTimeChange(index, "from", value), isInvalid: !!slot.error }), jsxRuntime.jsx("span", { className: "text-default-900 xs:hidden xl:block", children: "-" }), jsxRuntime.jsx(TimeInputComponent, { label: t.to, className: "w-full", value: toTimeValue(slot.to), onChange: (value) => handleTimeChange(index, "to", value), isInvalid: !!slot.error })] }), slot.error && (jsxRuntime.jsx("span", { className: "text-xs text-danger", children: slot.error }))] }), isLastSlot ? (jsxRuntime.jsx(Button, { isIconOnly: true, size: "sm", color: "primary", variant: "light", onPress: handleAddTimeSlot, isDisabled: !isSlotFilled, startContent: jsxRuntime.jsx(IconComponent, { icon: "solar:add-circle-bold" }) })) : (jsxRuntime.jsx(Button, { isIconOnly: true, size: "sm", color: "danger", variant: "light", onPress: () => handleRemoveTimeSlot(index), isDisabled: !canDelete, startContent: jsxRuntime.jsx(IconComponent, { icon: "solar:trash-bin-minimalistic-outline" }) }))] }, `${day}-timeslot-${index}`));
8571
8656
  }) }))] }, day));
8572
8657
  };
8573
8658
 
@@ -13922,7 +14007,7 @@ const ModalCloseContext = $8WNJc$react.createContext(() => { });
13922
14007
  * TECH-2459 · G2-overlays-nav — v3 convierte `Modal` en compound (`Modal.Backdrop/Container/
13923
14008
  * Dialog/Header/Body/Footer/CloseTrigger`, ver `upload-file/UploadFile.tsx` D-G1-7 y la guía
13924
14009
  * oficial `modal`). Esta fachada arma esa anatomía por dentro pero conserva la API PLANA de v2
13925
- * (`isOpen`/`onOpenChange`/`size`/`radius`/`backdrop`/`scrollBehavior`/`placement`/
14010
+ * (`isOpen`/`onOpenChange`/`onClose`/`size`/`radius`/`backdrop`/`scrollBehavior`/`placement`/
13926
14011
  * `isDismissable`/`hideCloseButton` + `<ModalContent>{(onClose) => ...}</ModalContent>`), para que
13927
14012
  * el código ya escrito en las 4 apps consumidoras siga funcionando sin cambios.
13928
14013
  *
@@ -13931,8 +14016,25 @@ const ModalCloseContext = $8WNJc$react.createContext(() => { });
13931
14016
  * foco vuelve al disparador al cerrar y la página no hace scroll por detrás — los cuatro los
13932
14017
  * gestiona react-aria-components internamente (`ModalOverlay`/`Dialog`), sin código propio.
13933
14018
  */
13934
- const Modal = ({ isOpen, defaultOpen, onOpenChange, size = "md", radius = "lg", backdrop = "opaque", scrollBehavior = "normal", placement, isDismissable = true, isKeyboardDismissDisabled = false, hideCloseButton = false, className, children, }) => {
13935
- return (jsxRuntime.jsx(react.Modal, { children: jsxRuntime.jsx(react.Modal.Backdrop, { isOpen: isOpen, defaultOpen: defaultOpen, onOpenChange: onOpenChange, variant: backdrop, isDismissable: isDismissable, isKeyboardDismissDisabled: isKeyboardDismissDisabled, children: jsxRuntime.jsx(react.Modal.Container, { size: SIZE_MAP[size], placement: placement, scroll: scrollBehavior === "inside" ? "inside" : undefined, children: jsxRuntime.jsx(react.Modal.Dialog, { className: react.cn(RADIUS_CLASS$2[radius], size !== "full" && MAX_WIDTH_CLASS[size], "px-6 py-9", className), children: ({ close }) => (jsxRuntime.jsxs(ModalCloseContext.Provider, { value: close, children: [!hideCloseButton && jsxRuntime.jsx(react.Modal.CloseTrigger, {}), children] })) }) }) }) }));
14019
+ const Modal = ({ isOpen, defaultOpen, onOpenChange, onClose, size = "md", radius = "lg", backdrop = "opaque", scrollBehavior = "normal", placement, isDismissable = true, isKeyboardDismissDisabled = false, hideCloseButton = false, className, children, }) => {
14020
+ // v2 aceptaba `onClose` además de `onOpenChange` y lo llamaba en cada cierre; v3 solo conoce
14021
+ // `onOpenChange`. Sin este puente, un modal controlado con `isOpen` + `onClose` (el patrón
14022
+ // v2 dominante en las apps: ~118 usos en beweossmbs frente a 8 de `onOpenChange`) no se
14023
+ // cerraba con la X, el backdrop ni Escape, porque nadie escuchaba `onOpenChange(false)`.
14024
+ //
14025
+ // Basta con engancharse aquí: TODAS las vías de cierre acaban en este `onOpenChange` del
14026
+ // `ModalOverlay`. La X (`Modal.CloseTrigger`, `slot="close"`) y el `close` del render-prop de
14027
+ // `Modal.Dialog` —el que `ModalCloseContext` pasa a `ModalContent`— llaman a `state.close()`
14028
+ // del estado del overlay, y Escape/backdrop también; ese estado (`useOverlayTriggerState` →
14029
+ // `useControlledState`) solo notifica cuando el valor cambia, así que `onClose` se dispara
14030
+ // una vez por cierre y ninguna al abrir.
14031
+ const handleOpenChange = (open) => {
14032
+ onOpenChange?.(open);
14033
+ if (!open) {
14034
+ onClose?.();
14035
+ }
14036
+ };
14037
+ return (jsxRuntime.jsx(react.Modal, { children: jsxRuntime.jsx(react.Modal.Backdrop, { isOpen: isOpen, defaultOpen: defaultOpen, onOpenChange: handleOpenChange, variant: backdrop, isDismissable: isDismissable, isKeyboardDismissDisabled: isKeyboardDismissDisabled, children: jsxRuntime.jsx(react.Modal.Container, { size: SIZE_MAP[size], placement: placement, scroll: scrollBehavior === "inside" ? "inside" : undefined, children: jsxRuntime.jsx(react.Modal.Dialog, { className: react.cn(RADIUS_CLASS$2[radius], size !== "full" && MAX_WIDTH_CLASS[size], "px-6 py-9", className), children: ({ close }) => (jsxRuntime.jsxs(ModalCloseContext.Provider, { value: close, children: [!hideCloseButton && jsxRuntime.jsx(react.Modal.CloseTrigger, {}), children] })) }) }) }) }));
13936
14038
  };
13937
14039
 
13938
14040
  /**
@@ -13978,7 +14080,7 @@ ModalHeader.displayName = "ModalHeader";
13978
14080
  * 24px de `px-6` ese margen negativo solo desalineaba el contenido 3px respecto al header.
13979
14081
  * `mt-0` anula el `.modal__header + .modal__body { mt-2 }` de v3, que v2 no tenía.
13980
14082
  */
13981
- const BODY_V2_GEOMETRY = "mx-0 mt-0 flex flex-1 flex-col gap-3 px-6 py-2";
14083
+ const BODY_V2_GEOMETRY$1 = "mx-0 mt-0 flex flex-1 flex-col gap-3 px-6 py-2";
13982
14084
  const ModalBody = $8WNJc$react.forwardRef(({ className, ...props }, forwardedRef) => {
13983
14085
  const nodeRef = $8WNJc$react.useRef(null);
13984
14086
  const callbackRef = $8WNJc$react.useCallback((node) => {
@@ -14125,7 +14227,7 @@ const ModalBody = $8WNJc$react.forwardRef(({ className, ...props }, forwardedRef
14125
14227
  track.remove();
14126
14228
  };
14127
14229
  }, []);
14128
- return (jsxRuntime.jsx(react.ModalBody, { ref: callbackRef, ...props, className: react.cn(BODY_V2_GEOMETRY, className) }));
14230
+ return (jsxRuntime.jsx(react.ModalBody, { ref: callbackRef, ...props, className: react.cn(BODY_V2_GEOMETRY$1, className) }));
14129
14231
  });
14130
14232
  ModalBody.displayName = "ModalBody";
14131
14233
 
@@ -14139,6 +14241,195 @@ ModalBody.displayName = "ModalBody";
14139
14241
  const ModalFooter = ({ className, ...props }) => (jsxRuntime.jsx(react.ModalFooter, { ...props, className: react.cn("mt-0 px-6 py-4", className) }));
14140
14242
  ModalFooter.displayName = "ModalFooter";
14141
14243
 
14244
+ const DrawerFacadeContext = $8WNJc$react.createContext({
14245
+ close: () => {
14246
+ // fuera de un `Drawer` no hay diálogo que cerrar
14247
+ },
14248
+ scrollBehavior: "inside",
14249
+ });
14250
+
14251
+ // Tope del lado corto del panel por tamaño, con los valores EXACTOS de v2 — leídos del oráculo,
14252
+ // no de memoria: `@heroui/theme@2.4.15`, `dist/chunk-EP7KPCL3.mjs` (tv `drawer`) aplica
14253
+ // `max-w-<size>` + `max-h-[<rem>]` al slot `base` (el panel), y el `placement` anula el eje que
14254
+ // no toca (`max-h-[none]` en left/right, `max-w-[none]` en top/bottom). La escala `maxWidth` de
14255
+ // Tailwind 3 resuelve `max-w-<size>` a los mismos rem que el `max-h` literal. Clases literales:
14256
+ // Tailwind solo genera lo que ve escrito entero en el fuente.
14257
+ //
14258
+ // left/right: v2 era `w-full` (slot `base` del modal) + `max-w-<size>`. v3 fija
14259
+ // `w-80 max-w-[85vw] sm:w-96` (320/384px) para cualquier tamaño: sin esto, `size="lg"` medía
14260
+ // 384px donde v2 medía 512px, y `size` no hacía nada. Ganan a `.drawer__dialog[data-placement]`
14261
+ // por capa (`@layer components` < `@layer utilities`), no por especificidad, igual que el
14262
+ // `MAX_WIDTH_CLASS` de `Modal`.
14263
+ const HORIZONTAL_SIZE_CLASS = {
14264
+ xs: "w-full max-w-[20rem]",
14265
+ sm: "w-full max-w-[24rem]",
14266
+ md: "w-full max-w-[28rem]",
14267
+ lg: "w-full max-w-[32rem]",
14268
+ xl: "w-full max-w-[36rem]",
14269
+ "2xl": "w-full max-w-[42rem]",
14270
+ "3xl": "w-full max-w-[48rem]",
14271
+ "4xl": "w-full max-w-[56rem]",
14272
+ "5xl": "w-full max-w-[64rem]",
14273
+ };
14274
+ // top/bottom: v3 ya es `w-full` y topa el alto a `max-h-[85vh]`; v2 lo topaba por tamaño.
14275
+ const VERTICAL_SIZE_CLASS = {
14276
+ xs: "max-h-[20rem]",
14277
+ sm: "max-h-[24rem]",
14278
+ md: "max-h-[28rem]",
14279
+ lg: "max-h-[32rem]",
14280
+ xl: "max-h-[36rem]",
14281
+ "2xl": "max-h-[42rem]",
14282
+ "3xl": "max-h-[48rem]",
14283
+ "4xl": "max-h-[56rem]",
14284
+ "5xl": "max-h-[64rem]",
14285
+ };
14286
+ // v2 `full`: `max-w-full max-h-full h-[100dvh] !rounded-none` en cualquier `placement`.
14287
+ const FULL_SIZE_CLASS = "w-full max-w-full h-[100dvh] max-h-full rounded-none";
14288
+ const sizeClass = (size, placement) => {
14289
+ if (size === "full") {
14290
+ return FULL_SIZE_CLASS;
14291
+ }
14292
+ return placement === "left" || placement === "right"
14293
+ ? HORIZONTAL_SIZE_CLASS[size]
14294
+ : VERTICAL_SIZE_CLASS[size];
14295
+ };
14296
+ /**
14297
+ * Drawer - fachada BeweOS sobre el `Drawer` compound de HeroUI v3.
14298
+ *
14299
+ * TECH-2459 — hasta el 23-sep `Drawer`/`DrawerContent`/`DrawerHeader`/`DrawerBody`/`DrawerFooter`
14300
+ * se servían CRUDOS de v3, que es compound y no entiende la API plana de v2: `isOpen`/`onClose`
14301
+ * no llegaban a ningún overlay, así que los drawers de las apps no montaban o no cerraban. Esta
14302
+ * fachada arma la anatomía de v3 por dentro (`Drawer` → `Backdrop` → `Content` → `Dialog`) y
14303
+ * conserva la API de v2 (`isOpen`/`defaultOpen`/`onOpenChange`/`onClose`/`placement`/`size`/
14304
+ * `backdrop`/`scrollBehavior`/`isDismissable`/`isKeyboardDismissDisabled`/`hideCloseButton` +
14305
+ * `<DrawerContent>{(onClose) => ...}</DrawerContent>`), con los defaults de v2 (`useDrawer` de
14306
+ * `@heroui/drawer@2.2.29`: `placement="right"`, `size="md"`, `scrollBehavior="inside"`).
14307
+ *
14308
+ * Lo que NO se repone a propósito (criterio de la migración: adaptarse a v3, no identidad de
14309
+ * píxel): fondo, sombra, radio y posición de la X son los de v3. Sí se repone la geometría de la
14310
+ * que depende el contenido de las apps: el ancho/alto por `size`, el padding de los slots
14311
+ * (`DrawerHeader`/`Body`/`Footer`) y el panel sin padding propio, porque las apps ya compensan
14312
+ * sobre esos valores (p. ej. `DrawerHeader className="pt-6"`).
14313
+ *
14314
+ * La anatomía v3 completa queda publicada como estáticos (`Drawer.Backdrop`, `Drawer.Content`,
14315
+ * `Drawer.Dialog`, …): son los MISMOS objetos que exporta `@heroui/react`.
14316
+ */
14317
+ const DrawerFacade = ({ isOpen, defaultOpen, onOpenChange, onClose, placement = "right", size = "md", backdrop = "opaque", scrollBehavior = "inside", isDismissable = true, isKeyboardDismissDisabled = false, hideCloseButton = false, className, children, }) => {
14318
+ // Mismo puente que `Modal` (f3ce18c): v3 solo conoce `onOpenChange`. Todas las vías de cierre
14319
+ // (la X —`Drawer.CloseTrigger`, `slot="close"`—, el `close` del render-prop de
14320
+ // `Drawer.Dialog`, Escape, backdrop y el arrastre de v3) acaban en `state.close()` del
14321
+ // overlay, que solo notifica cuando el valor cambia: `onClose` sale una vez por cierre y
14322
+ // ninguna al abrir.
14323
+ // v2 nombraba el diálogo con su cabecera (`ModalContent` → `aria-labelledby` = id del
14324
+ // `ModalHeader`). En v3 solo lo hace `Drawer.Heading`, que las apps no usan: sin esto el
14325
+ // panel quedaba sin nombre accesible y react-aria avisaba en consola en cada apertura («A
14326
+ // dialog must have a title for accessibility», medido en jsdom). `DrawerHeader` pone este id.
14327
+ const headerId = $8WNJc$react.useId();
14328
+ const handleOpenChange = (open) => {
14329
+ onOpenChange?.(open);
14330
+ if (!open) {
14331
+ onClose?.();
14332
+ }
14333
+ };
14334
+ // Sin `Drawer.Root` (el `DialogTrigger` de react-aria) a propósito: la fachada no tiene
14335
+ // disparador propio —lo abre el `isOpen` de la app— y un `DialogTrigger` sin hijo pulsable
14336
+ // avisa en consola en CADA montaje («A PressResponder was rendered without a pressable
14337
+ // child», medido en jsdom; `Modal` lo sigue emitiendo). `Drawer.Backdrop` (`ModalOverlay`)
14338
+ // ya crea y publica su propio estado de overlay con `isOpen`/`onOpenChange`, y trae todos los
14339
+ // slots de `drawerVariants()`, así que el root no aportaba nada.
14340
+ 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 })) }) }) }));
14341
+ };
14342
+ /** Aísla el `useMemo` del valor de contexto (el render-prop de `Dialog` no puede usar hooks). */
14343
+ const DrawerDialogBody = ({ close, headerId, scrollBehavior, hideCloseButton, children }) => {
14344
+ const value = $8WNJc$react.useMemo(() => ({ close, headerId, scrollBehavior }), [close, headerId, scrollBehavior]);
14345
+ return (jsxRuntime.jsxs(DrawerFacadeContext.Provider, { value: value, children: [!hideCloseButton && jsxRuntime.jsx(react.Drawer.CloseTrigger, {}), children] }));
14346
+ };
14347
+ DrawerFacade.displayName = "Aurora.Drawer";
14348
+ /**
14349
+ * `Drawer` de Aurora: fachada v2 + estáticos compound de v3 (los mismos objetos que exporta
14350
+ * `@heroui/react`), para quien quiera montar la anatomía de v3 a mano.
14351
+ *
14352
+ * ⚠️ `Drawer.Content`/`Drawer.Header`/`Drawer.Body`/`Drawer.Footer` son las piezas CRUDAS de v3
14353
+ * (sin la geometría v2 ni el render-prop): no son los `DrawerContent`/`DrawerHeader`/… planos de
14354
+ * esta librería. No se mezclan las dos formas en el mismo drawer.
14355
+ */
14356
+ const Drawer = Object.assign(DrawerFacade, {
14357
+ Root: react.Drawer.Root,
14358
+ Trigger: react.Drawer.Trigger,
14359
+ Backdrop: react.Drawer.Backdrop,
14360
+ Content: react.Drawer.Content,
14361
+ Dialog: react.Drawer.Dialog,
14362
+ Header: react.Drawer.Header,
14363
+ Heading: react.Drawer.Heading,
14364
+ Body: react.Drawer.Body,
14365
+ Footer: react.Drawer.Footer,
14366
+ Handle: react.Drawer.Handle,
14367
+ CloseTrigger: react.Drawer.CloseTrigger,
14368
+ });
14369
+
14370
+ /**
14371
+ * `DrawerContent` de v2 (en v2 era el mismo `ModalContent`). En v3 `Drawer.Content` es el
14372
+ * posicionador del overlay, que la fachada `Drawer` ya monta por dentro; este componente NO lo
14373
+ * envuelve: es azúcar de compatibilidad. Si `children` es una función, la invoca con el `close`
14374
+ * real del diálogo (vía contexto) para que el patrón v2 `{(onClose) => <>...</>}` siga
14375
+ * funcionando (6 de los 12 drawers de las apps lo usan, medido el 23-sep).
14376
+ */
14377
+ function DrawerContent({ children, className }) {
14378
+ const { close } = $8WNJc$react.useContext(DrawerFacadeContext);
14379
+ const content = typeof children === "function" ? children(close) : children;
14380
+ if (!className) {
14381
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
14382
+ }
14383
+ return jsxRuntime.jsx("div", { className: className, children: content });
14384
+ }
14385
+ DrawerContent.displayName = "Aurora.DrawerContent";
14386
+
14387
+ /**
14388
+ * Geometría v2 del slot `header`, reintroducida sobre `.drawer__header` de v3. v2 (el drawer
14389
+ * reusaba los slots del modal): `flex py-4 px-6 flex-initial text-large font-semibold`
14390
+ * (`@heroui/theme@2.4.15`, `chunk-YXVO2HGK.mjs`, slot `header`; `text-large` → `text-lg`).
14391
+ * `.drawer__header` de v3 no tiene padding ni tipografía y apila en columna con `gap-3`; mismo
14392
+ * arreglo que `ModalHeader`.
14393
+ *
14394
+ * El `className` del consumidor se mezcla con `cn` (tailwind-merge) en última posición, así que
14395
+ * sigue ganando: `className="flex flex-col gap-1"` mantiene su columna y `pt-6` pisa el `py-4`.
14396
+ *
14397
+ * Lleva el `id` que el panel usa como `aria-labelledby`: la cabecera NOMBRA el diálogo, como en
14398
+ * v2 (ver `Drawer.tsx`).
14399
+ */
14400
+ const DrawerHeader = ({ className, children }) => {
14401
+ const { headerId } = $8WNJc$react.useContext(DrawerFacadeContext);
14402
+ return (jsxRuntime.jsx(react.DrawerHeader, { id: headerId, className: react.cn("flex-initial flex-row gap-0 px-6 py-4 text-lg font-semibold", className), children: children }));
14403
+ };
14404
+ DrawerHeader.displayName = "Aurora.DrawerHeader";
14405
+
14406
+ /**
14407
+ * Geometría v2 del slot `body`: `flex flex-1 flex-col gap-3 px-6 py-2` (`@heroui/theme@2.4.15`,
14408
+ * `chunk-YXVO2HGK.mjs`, slot `body`). `.drawer__body` de v3 es un bloque sin padding ni gap
14409
+ * (`-m-[3px] my-0 p-[3px]`), así que los campos de un formulario quedarían pegados y a ras del
14410
+ * borde. `mx-0` anula el margen negativo de v3 y `mt-0` el `.drawer__header + .drawer__body
14411
+ * { mt-2 }`, que v2 no tenía (mismo arreglo que `ModalBody`).
14412
+ *
14413
+ * Scroll: con `scrollBehavior="inside"` (default v2 del drawer) el cuerpo hace scroll, que es lo
14414
+ * que ya trae `.drawer__body` de v3. Con `outside` el que hace scroll es el panel, así que el
14415
+ * cuerpo lo suelta (`overflow-visible`) y deja de encogerse (`flex-none`).
14416
+ */
14417
+ const BODY_V2_GEOMETRY = "mx-0 mt-0 flex flex-1 flex-col gap-3 px-6 py-2";
14418
+ const DrawerBody = ({ className, children }) => {
14419
+ const { scrollBehavior } = $8WNJc$react.useContext(DrawerFacadeContext);
14420
+ return (jsxRuntime.jsx(react.DrawerBody, { className: react.cn(BODY_V2_GEOMETRY, scrollBehavior === "outside" && "flex-none overflow-visible", className), children: children }));
14421
+ };
14422
+ DrawerBody.displayName = "Aurora.DrawerBody";
14423
+
14424
+ /**
14425
+ * Geometría v2 del slot `footer`: `flex flex-row gap-2 px-6 py-4 justify-end`
14426
+ * (`@heroui/theme@2.4.15`, slot `footer`). v3 conserva `flex-row justify-end gap-2` pero pierde
14427
+ * el padding y añade `.drawer__body + .drawer__footer { mt-5 }`, que v2 no tenía — de ahí el
14428
+ * `mt-0` (mismo arreglo que `ModalFooter`).
14429
+ */
14430
+ const DrawerFooter = ({ className, children }) => (jsxRuntime.jsx(react.DrawerFooter, { className: react.cn("mt-0 px-6 py-4", className), children: children }));
14431
+ DrawerFooter.displayName = "Aurora.DrawerFooter";
14432
+
14142
14433
  // TECH-2459 — Fachada `Alert` (hallazgo loginos 07-sep: `index.tsx` reexportaba el `Alert` CRUDO de
14143
14434
  // v3 y solo shimeaba el TIPO `AlertProps` v2 → el JSX v2 compilaba pero el componente era v3).
14144
14435
  //
@@ -14793,9 +15084,12 @@ const Dropdown = Object.assign(DropdownFacade, {
14793
15084
  // | beweosagency | 5 | 5 | 5 | 14 | **0** | la seleccionada sin píldora |
14794
15085
  // | backoffice-beweos | 5 | 5 | 5 | 18 | 18 (a mano) | bien |
14795
15086
  // | beweanalytics | 3 | 3 | 3 | 8 | 8 (a mano) | bien |
14796
- // | beweossmbs / loginos / linda-business | 0 | 0 | 0 | 0 | 0 | no usan tabs |
15087
+ // | beweossmbs / loginos / linda-business | 0 | 0 | 0 | 0 | 0 | no usan la forma v3 |
14797
15088
  //
14798
15089
  // (conteo de tags de APERTURA; beweanalytics escribe `Tab` suelto en vez de `Tabs.Tab`.)
15090
+ // Corrección del 23-sep: esa última fila solo contaba la forma v3. Las apps SIN migrar sí usan
15091
+ // tabs, y todas en la forma v2 (`<Tab key title>` suelto): beweossmbs 42 raíces, chatbot-claw 1,
15092
+ // linda-business 1. Esa forma la cubre la rama v2 del root, más abajo.
14799
15093
  // Dos lecturas que salen de esta tabla y que deciden el diseño:
14800
15094
  // · **26 indicadores montados a mano** contra 14 que faltan. La idempotencia no es un adorno:
14801
15095
  // sin ella esas 26 pestañas se quedarían con DOS indicadores.
@@ -14900,7 +15194,12 @@ function hasIndicator(children) {
14900
15194
  return node.type === $8WNJc$react.Fragment && hasIndicator(node.props.children);
14901
15195
  });
14902
15196
  }
14903
- const TabFacade = ({ children, ...props }) => {
15197
+ const TabFacade = ({ children: ownChildren, title,
15198
+ // `titleValue` es de v2 y no tiene destino en v3: se consume para que no llegue al DOM.
15199
+ titleValue: _titleValue, ...props }) => {
15200
+ // En la forma v3 la etiqueta son los `children`; si solo viene el `title` de v2 (un `Tab` con
15201
+ // `title` dentro de `Tabs.List`), hace de etiqueta. Con los dos, mandan los `children`.
15202
+ const children = ownChildren ?? title;
14904
15203
  // `children` como función es la forma de render props de react-aria (`TabRenderProps`). No se
14905
15204
  // puede inspeccionar, y menos aún combinar con un hermano —React rechaza una función como
14906
15205
  // hijo junto a un elemento—, así que se pasa tal cual. Un consumidor que la use monta el
@@ -14941,7 +15240,179 @@ const Tab = TabFacade;
14941
15240
  const INSIDE_CONTAINER = new Set([react.Tabs.List]);
14942
15241
  /** Si el consumidor ya monta el contenedor, la fachada no envuelve nada. */
14943
15242
  const OWN_CONTAINER = new Set([react.Tabs.ListContainer]);
14944
- const TabsFacade = ({ children, ...props }) => {
15243
+ // ---------------------------------------------------------------------------------------------
15244
+ // Forma v2: `<Tabs …><Tab key="x" title="X">panel</Tab></Tabs>`
15245
+ // ---------------------------------------------------------------------------------------------
15246
+ //
15247
+ // Las apps que faltan por migrar escriben SOLO esta forma (inventario con el parser de TypeScript
15248
+ // sobre `git show`, 23-sep: beweossmbs `origin/staging` 42 raíces, chatbot-claw
15249
+ // `origin/feat/TECH-3586/linda-claw` 1, linda-business `origin/staging` 1 — 44 raíces, 97 `Tab`,
15250
+ // todos con `key` y `title`, 39 con hijos = panel, 0 `Tabs.List`). En v3 esa forma no monta:
15251
+ // `Tab === Tabs.Tab` es un item de colección y fuera de `Tabs.List` react-aria lanza «cannot be
15252
+ // rendered outside a collection». La fachada la reescribe a la forma COMPLETA de v3:
15253
+ //
15254
+ // Tabs (root)
15255
+ // ├─ div data-slot="tabs-base" ← el `base` de v2: `classNames.base` + `className`
15256
+ // │ └─ Tabs.ListContainer ← el carril (sin él la píldora no se ve, ver arriba)
15257
+ // │ └─ Tabs.List aria-label del root ← `classNames.tabList`, `role="tablist"`
15258
+ // │ └─ Tabs.Tab id = key del Tab ← `classNames.tab` + `className` del Tab
15259
+ // │ ├─ Tabs.Indicator ← `classNames.cursor` (UNO por tab; v3 solo pinta el activo)
15260
+ // │ └─ title
15261
+ // └─ Tabs.Panel id = key (solo los Tab con hijos) ← `classNames.panel` + `className` del Tab
15262
+ //
15263
+ // Oráculo v2: `@heroui/tabs@2.2.29` `dist/tabs.js` y `@heroui/theme@2.4.15`
15264
+ // `dist/components/tabs.js` (npm pack, no de memoria). De ahí sale cada destino:
15265
+ // · `className` del root → `slots.base` junto a `classNames.base` (`tabs.js:88,114`), y `base`
15266
+ // envuelve SOLO la tira: los paneles son sus hermanos (`tabs.js:414-430`).
15267
+ // · `className` del Tab → la pestaña (`cn(classNames.tab, className)`, `tabs.js:207`) Y su panel
15268
+ // (`cn(classNames.panel, …, selectedItem.props.className)`, `tabs.js:282`).
15269
+ // · `classNames.cursor` → el `<span>` de la píldora (`tabs.js:145`), que en v3 es el indicador.
15270
+ // · Un Tab sin hijos NO genera panel (`if (!content) return null`, `tabs.js:284`).
15271
+ //
15272
+ // Las clases de la app van SIEMPRE en última posición de un `cn` (tailwind-merge): el `tv` de v2
15273
+ // corría con `twMerge: true`, así que su clase borraba la de la librería, y aquí igual — la
15274
+ // concatenación simple es el defecto ya medido en otras fachadas (la clase de la app perdía).
15275
+ /** Los dos nombres por los que una app llega a un `Tab`: la fachada y, por si acaso, el crudo. */
15276
+ const TAB_TYPES = new Set([TabFacade, react.Tabs.Tab]);
15277
+ /** Presencia de cualquiera de estas piezas = la app ya escribe la forma v3. */
15278
+ const V3_LIST_TYPES = new Set([
15279
+ react.Tabs.List,
15280
+ react.Tabs.ListContainer,
15281
+ ]);
15282
+ /**
15283
+ * Los `Tab` sueltos del root, en orden, **con su `key` original**.
15284
+ *
15285
+ * Se recorre con `Children.forEach` y no con `Children.toArray` a propósito: `toArray` REESCRIBE
15286
+ * las claves (`"all"` → `".$all"`) y la clave es justo lo que se necesita, porque en v2 es el
15287
+ * identificador que recibe `onSelectionChange` y que la app compara con su `selectedKey`.
15288
+ * `forEach` entrega cada hijo tal cual (comprobado: `key` intacta) y aplana arrays, o sea los
15289
+ * `.map()` y los `{cond && <Tab/>}` (los `false`/`null` se descartan). Los Fragments no los
15290
+ * aplana nadie, así que se desciende a mano — como en `hasIndicator`.
15291
+ */
15292
+ function collectV2Tabs(children, out = []) {
15293
+ $8WNJc$react.Children.forEach(children, (node) => {
15294
+ if (!$8WNJc$react.isValidElement(node)) {
15295
+ return;
15296
+ }
15297
+ if (node.type === $8WNJc$react.Fragment) {
15298
+ collectV2Tabs(node.props.children, out);
15299
+ }
15300
+ else if (TAB_TYPES.has(node.type)) {
15301
+ out.push(node);
15302
+ }
15303
+ });
15304
+ return out;
15305
+ }
15306
+ /** ¿Hay un `Tabs.List` / `Tabs.ListContainer` entre los hijos (descendiendo por Fragments)? */
15307
+ function hasV3List(children) {
15308
+ let found = false;
15309
+ $8WNJc$react.Children.forEach(children, (node) => {
15310
+ if (found || !$8WNJc$react.isValidElement(node)) {
15311
+ return;
15312
+ }
15313
+ found =
15314
+ V3_LIST_TYPES.has(node.type) ||
15315
+ (node.type === $8WNJc$react.Fragment && hasV3List(node.props.children));
15316
+ });
15317
+ return found;
15318
+ }
15319
+ /** v2 `underlined` es la línea inferior → `secondary` de v3; el resto de v2 → `primary` (default). */
15320
+ function toV3Variant(variant) {
15321
+ if (variant === "primary" || variant === "secondary") {
15322
+ return variant;
15323
+ }
15324
+ return variant === "underlined" ? "secondary" : undefined;
15325
+ }
15326
+ /** ¿El `Tab` de v2 trae contenido de panel? Mismo criterio que `if (!content)` de v2. */
15327
+ function hasPanelContent(children) {
15328
+ return typeof children === "function" || $8WNJc$react.Children.count(children) > 0;
15329
+ }
15330
+ const TabsFacade = (allProps) => {
15331
+ const { children, classNames, className, variant, fullWidth, items, isVertical, placement, orientation, destroyInactiveTabPanel = true,
15332
+ // Sin equivalente en v3: se consumen para que no lleguen al DOM (ver README, «Props v2»).
15333
+ size: _size, radius: _radius, color: _color, disableAnimation: _disableAnimation, disableCursorAnimation: _disableCursorAnimation, shouldSelectOnPressUp: _shouldSelectOnPressUp, ...rest } = allProps;
15334
+ const v3Variant = toV3Variant(variant);
15335
+ const v3Orientation = orientation ??
15336
+ (isVertical || placement === "start" || placement === "end"
15337
+ ? "vertical"
15338
+ : undefined);
15339
+ // Forma v2 dinámica: `items` + `children` como función `(item) => <Tab key=…/>`.
15340
+ const dynamic = typeof children === "function";
15341
+ const v2Tabs = dynamic
15342
+ ? Array.from(items ?? [], (item, index) => {
15343
+ const element = children(item);
15344
+ const fallback = item.key ?? item.id ?? index;
15345
+ return element.key == null
15346
+ ? { element, key: String(fallback) }
15347
+ : { element, key: element.key };
15348
+ })
15349
+ : hasV3List(children)
15350
+ ? []
15351
+ : collectV2Tabs(children).map((element, index) => ({
15352
+ element,
15353
+ key: element.key ?? String(index),
15354
+ }));
15355
+ if (v2Tabs.length > 0) {
15356
+ const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...rootProps } = rest;
15357
+ const tabs = v2Tabs.map(({ element, key }) => {
15358
+ const { id, title, titleValue: _titleValue, className: tabClassName, children: panel, ...tabProps } = element.props;
15359
+ return {
15360
+ id: id ?? key,
15361
+ title,
15362
+ tabClassName,
15363
+ panel,
15364
+ tabProps,
15365
+ };
15366
+ });
15367
+ // EL `base` DE v2: un div que envuelve SOLO la tira. Ahí van `className`, `classNames.base` y
15368
+ // el `w-full` de `fullWidth`, no al root. En v2 los paneles eran HERMANOS de `base`, fuera de
15369
+ // él (`tabs.js`: `<div {...getBaseProps()}><tabList/></div>` y luego los paneles), y en v3
15370
+ // el root envuelve tira + paneles. Mandarlas al root cambiaba dos pantallas de beweossmbs
15371
+ // sin que la app tocara nada: `service-detail.page.tsx` (`mb-4` debajo del bloque en vez de
15372
+ // entre tira y panel) y `whatsapp-campaign-full.page.tsx` (`flex justify-center` dejaba de
15373
+ // centrar la tira).
15374
+ //
15375
+ // Por qué un div propio y no el `Tabs.ListContainer`: el contenedor ES el carril gris, así
15376
+ // que un `w-full` o un `justify-center` de la app lo estirarían a todo el ancho. En v2 esa
15377
+ // clase caía en un envoltorio `inline-flex` y la tira (el carril de v2) seguía midiendo su
15378
+ // contenido. Este div es `flex`: el carril es un item de fila y mide su contenido, igual.
15379
+ // El scroller sigue funcionando por el `max-width: 100%` de `neutralize-v3.css`, que acota
15380
+ // el mínimo automático del item.
15381
+ //
15382
+ // El precio de meter un nodo entre el root y el carril: TODAS las reglas de la variante
15383
+ // `secondary` de v3 cuelgan de un combinador de hijo DIRECTO
15384
+ // (`.tabs--secondary > .tabs__list-container` y
15385
+ // `.tabs--secondary[data-orientation=…] > .tabs__list-container`, `tabs.css:234-282`), y
15386
+ // 5 pantallas de smbs llegan a ella por `variant="underlined"`. Por eso el div repite el
15387
+ // modificador y el `data-orientation` del root: esos selectores casan con div > carril (el
15388
+ // test lo comprueba con `matches()` sobre los selectores literales). `.tabs--secondary` no
15389
+ // tiene reglas propias, solo las de hijo directo, así que repetirlo no pinta nada en el div.
15390
+ // La única regla que deja de aplicarse es
15391
+ // `.tabs[data-orientation="horizontal"] > .tabs__list-container { align-self: start }` de
15392
+ // neutralize, que no hace falta: dentro de una fila el carril ya mide su contenido.
15393
+ const orientationAttr = v3Orientation ?? "horizontal";
15394
+ return (jsxRuntime.jsxs(react.Tabs, { ...rootProps, orientation: v3Orientation, variant: v3Variant, children: [jsxRuntime.jsx("div", { className: react.cn("flex", v3Variant === "secondary" && "tabs--secondary", fullWidth && "w-full", classNames?.base, className), "data-orientation": orientationAttr, "data-slot": "tabs-base", children: jsxRuntime.jsx(react.Tabs.ListContainer, { className: react.cn(fullWidth && "w-full"), children: jsxRuntime.jsx(react.Tabs.List, { "aria-describedby": ariaDescribedby, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, className: react.cn(classNames?.tabList), children: tabs.map(({ id, title, tabClassName, tabProps }) => ($8WNJc$react.createElement(react.Tabs.Tab, { ...tabProps, className: react.cn(classNames?.tab, tabClassName), id: id, key: id },
15395
+ jsxRuntime.jsx(react.Tabs.Indicator, { className: react.cn(classNames?.cursor) }),
15396
+ classNames?.tabContent ? (jsxRuntime.jsx("span", { className: classNames.tabContent, children: title })) : (title)))) }) }) }), tabs
15397
+ .filter(({ panel }) => hasPanelContent(panel))
15398
+ .map(({ id, panel, tabClassName }) => (jsxRuntime.jsx(react.Tabs.Panel, { className: react.cn(classNames?.panel, tabClassName), id: id, shouldForceMount: !destroyInactiveTabPanel || undefined, children: typeof panel === "function" ? null : panel }, id)))] }));
15399
+ }
15400
+ // Forma v3 (o nada que traducir): el camino de siempre. Solo se traducen las props de v2 que
15401
+ // tienen equivalente, para que una app a medio migrar no las pierda.
15402
+ // Sin `fullWidth` ni `classNames.base` el `className` pasa INTACTO (sin `cn`), igual que antes
15403
+ // de existir la forma v2: `cn` deduplica y reordena, y aquí no hay nada con qué fusionarlo.
15404
+ const v3Children = dynamic ? null : children;
15405
+ const v3Props = {
15406
+ ...rest,
15407
+ className: fullWidth || classNames?.base
15408
+ ? react.cn(fullWidth && "w-full", classNames?.base, className)
15409
+ : className,
15410
+ orientation: v3Orientation,
15411
+ variant: v3Variant,
15412
+ };
15413
+ return jsxRuntime.jsx(TabsV3, { ...v3Props, children: v3Children });
15414
+ };
15415
+ const TabsV3 = ({ children, ...props }) => {
14945
15416
  const nodes = $8WNJc$react.Children.toArray(children);
14946
15417
  const needsContainer = nodes.some((node) => isPart(node, INSIDE_CONTAINER)) &&
14947
15418
  !nodes.some((node) => isPart(node, OWN_CONTAINER));
@@ -15836,26 +16307,6 @@ Object.defineProperty(exports, "CloseButton", {
15836
16307
  enumerable: true,
15837
16308
  get: function () { return react.CloseButton; }
15838
16309
  });
15839
- Object.defineProperty(exports, "Drawer", {
15840
- enumerable: true,
15841
- get: function () { return react.Drawer; }
15842
- });
15843
- Object.defineProperty(exports, "DrawerBody", {
15844
- enumerable: true,
15845
- get: function () { return react.DrawerBody; }
15846
- });
15847
- Object.defineProperty(exports, "DrawerContent", {
15848
- enumerable: true,
15849
- get: function () { return react.DrawerContent; }
15850
- });
15851
- Object.defineProperty(exports, "DrawerFooter", {
15852
- enumerable: true,
15853
- get: function () { return react.DrawerFooter; }
15854
- });
15855
- Object.defineProperty(exports, "DrawerHeader", {
15856
- enumerable: true,
15857
- get: function () { return react.DrawerHeader; }
15858
- });
15859
16310
  Object.defineProperty(exports, "DropdownItem", {
15860
16311
  enumerable: true,
15861
16312
  get: function () { return react.DropdownItem; }
@@ -15968,7 +16419,12 @@ exports.DateRangePicker = DateRangePicker;
15968
16419
  exports.DateSelector = DateSelector;
15969
16420
  exports.Divider = Divider;
15970
16421
  exports.DonutChart = DonutChart;
16422
+ exports.Drawer = Drawer;
16423
+ exports.DrawerBody = DrawerBody;
16424
+ exports.DrawerContent = DrawerContent;
15971
16425
  exports.DrawerFilters = DrawerFilters;
16426
+ exports.DrawerFooter = DrawerFooter;
16427
+ exports.DrawerHeader = DrawerHeader;
15972
16428
  exports.Dropdown = Dropdown;
15973
16429
  exports.DropdownSection = DropdownSection;
15974
16430
  exports.EmailPreview = EmailPreview;
@@ -16034,7 +16490,7 @@ exports.ThemeContext = ThemeContext;
16034
16490
  exports.ThemePicker = ThemePicker;
16035
16491
  exports.ThemeProvider = ThemeProvider;
16036
16492
  exports.TimeInput = TimeInput;
16037
- exports.TimeInputComponent = TimeInput;
16493
+ exports.TimeInputComponent = TimeInputComponent;
16038
16494
  exports.ToastContext = ToastContext;
16039
16495
  exports.Tooltip = Tooltip;
16040
16496
  exports.TwoColumnLayoutAgent = TwoColumnLayoutAgent;