@beweco/aurora-ui 0.6.66 → 0.6.68

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 (23) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +208 -8
  3. package/dist/index.esm.js +208 -9
  4. package/dist/types/components/menu/Menu.d.ts.map +1 -1
  5. package/dist/types/components/menu/Menu.types.d.ts +7 -0
  6. package/dist/types/components/menu/Menu.types.d.ts.map +1 -1
  7. package/dist/types/components/menu/get-user-initials.d.ts +15 -0
  8. package/dist/types/components/menu/get-user-initials.d.ts.map +1 -0
  9. package/dist/types/components/menu-claw/MenuClaw.d.ts +26 -0
  10. package/dist/types/components/menu-claw/MenuClaw.d.ts.map +1 -0
  11. package/dist/types/components/menu-claw/MenuClaw.types.d.ts +113 -0
  12. package/dist/types/components/menu-claw/MenuClaw.types.d.ts.map +1 -0
  13. package/dist/types/components/menu-claw/_internal/menu-claw-history/MenuClawHistoryPanel.d.ts +15 -0
  14. package/dist/types/components/menu-claw/_internal/menu-claw-history/MenuClawHistoryPanel.d.ts.map +1 -0
  15. package/dist/types/components/menu-claw/_internal/menu-claw-history/MenuClawHistoryPanel.types.d.ts +25 -0
  16. package/dist/types/components/menu-claw/_internal/menu-claw-history/MenuClawHistoryPanel.types.d.ts.map +1 -0
  17. package/dist/types/components/menu-claw/_internal/menu-claw-history/index.d.ts +3 -0
  18. package/dist/types/components/menu-claw/_internal/menu-claw-history/index.d.ts.map +1 -0
  19. package/dist/types/components/menu-claw/index.d.ts +3 -0
  20. package/dist/types/components/menu-claw/index.d.ts.map +1 -0
  21. package/dist/types/index.d.ts +1 -0
  22. package/dist/types/index.d.ts.map +1 -1
  23. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -3011,12 +3011,12 @@ var NotificationButton = function (_a) {
3011
3011
  };
3012
3012
  NotificationButton.displayName = "NotificationButton";
3013
3013
 
3014
- var DEFAULT_TRANSLATIONS$7 = {
3014
+ var DEFAULT_TRANSLATIONS$8 = {
3015
3015
  logout: "Cerrar sesión",
3016
3016
  };
3017
3017
  var HeaderComponent = function (_a) {
3018
3018
  var notificationCount = _a.notificationCount, options = _a.options, onMenuClick = _a.onMenuClick, onLogout = _a.onLogout, _b = _a.translations, translations = _b === void 0 ? {} : _b, breadcrumbs = _a.breadcrumbs, extraContent = _a.extraContent, _c = _a.showMenuButton, showMenuButton = _c === void 0 ? true : _c, onNotificationClick = _a.onNotificationClick, onOptionSelect = _a.onOptionSelect, onBreadcrumbClick = _a.onBreadcrumbClick;
3019
- var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$7), translations);
3019
+ var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$8), translations);
3020
3020
  return (jsxRuntime.jsx("header", { className: "header__container", children: jsxRuntime.jsxs("div", { className: "flex items-center justify-between w-full", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [showMenuButton && (jsxRuntime.jsx(react.Button, { className: "sm:hidden", isIconOnly: true, variant: "light", startContent: jsxRuntime.jsx(IconComponent, { icon: "solar:hamburger-menu-linear" }), onPress: onMenuClick })), breadcrumbs && breadcrumbs.length > 0 && (jsxRuntime.jsx(BreadcrumbsComponent, { items: breadcrumbs, onItemClick: onBreadcrumbClick }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [extraContent, jsxRuntime.jsx(NotificationButton, { notificationCount: notificationCount, onPress: onNotificationClick }), jsxRuntime.jsx(ConfigMenu, { options: options, onLogout: onLogout, onOptionSelect: onOptionSelect, translations: t })] })] }) }));
3021
3021
  };
3022
3022
  HeaderComponent.displayName = "Header";
@@ -3140,7 +3140,7 @@ KanbanColumn.displayName = "KanbanColumn";
3140
3140
  * Traducciones por defecto en español.
3141
3141
  * Se mezclan con las traducciones proporcionadas por el usuario.
3142
3142
  */
3143
- var DEFAULT_TRANSLATIONS$6 = {
3143
+ var DEFAULT_TRANSLATIONS$7 = {
3144
3144
  dropHere: "Soltar aquí",
3145
3145
  emptyMessage: "No hay elementos",
3146
3146
  };
@@ -3174,7 +3174,7 @@ var columnGapClasses = {
3174
3174
  var KanbanComponent = function (_a) {
3175
3175
  var columns = _a.columns, renderItem = _a.renderItem, onCardClick = _a.onCardClick, onItemMove = _a.onItemMove, isDraggable = _a.isDraggable, cardClassName = _a.cardClassName, isCardClickable = _a.isCardClickable, className = _a.className, _b = _a.columnWidth, columnWidth = _b === void 0 ? "280px" : _b, _c = _a.columnGap, columnGap = _c === void 0 ? "md" : _c, _d = _a.horizontalScroll, horizontalScroll = _d === void 0 ? true : _d, columnMaxHeight = _a.columnMaxHeight, renderColumnHeader = _a.renderColumnHeader, renderEmptyState = _a.renderEmptyState, _e = _a.translations, translations = _e === void 0 ? {} : _e, onLoadMore = _a.onLoadMore;
3176
3176
  // Mezclar traducciones del usuario con las por defecto
3177
- var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$6), translations);
3177
+ var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$7), translations);
3178
3178
  // Determinar si drag está habilitado
3179
3179
  var dragEnabled = isDraggable !== null && isDraggable !== void 0 ? isDraggable : !!onItemMove;
3180
3180
  // Estado del drag actual
@@ -3332,6 +3332,32 @@ function getSelectedKeyFromPath(pathname, items) {
3332
3332
  return undefined;
3333
3333
  }
3334
3334
 
3335
+ /**
3336
+ * Deriva las iniciales para el avatar del usuario a partir de su nombre completo.
3337
+ *
3338
+ * Muestra la inicial del nombre + la inicial del primer apellido (2 letras en
3339
+ * mayúsculas), p. ej. "Roser Ruiz" -> "RR". Si el usuario solo tiene un token
3340
+ * (nombre sin apellido) devuelve una sola inicial. Si no hay texto, devuelve "".
3341
+ *
3342
+ * TECH-1727: reemplaza el comportamiento por defecto de HeroUI (`safeText`), que
3343
+ * muestra las 3 primeras letras del nombre ("Roser Ruiz" -> "Ros").
3344
+ *
3345
+ * @param fullName Nombre completo del usuario (se usa el mismo valor que el label).
3346
+ * @returns Iniciales en mayúsculas (0, 1 o 2 letras).
3347
+ */
3348
+ var getUserInitials = function (fullName) {
3349
+ var tokens = fullName.trim().split(/\s+/).filter(Boolean);
3350
+ if (tokens.length === 0) {
3351
+ return "";
3352
+ }
3353
+ var firstInitial = tokens[0].charAt(0).toUpperCase();
3354
+ if (tokens.length === 1) {
3355
+ return firstInitial;
3356
+ }
3357
+ var secondInitial = tokens[1].charAt(0).toUpperCase();
3358
+ return "".concat(firstInitial).concat(secondInitial);
3359
+ };
3360
+
3335
3361
  exports.EnumMenuNavListItem = void 0;
3336
3362
  (function (EnumMenuNavListItem) {
3337
3363
  EnumMenuNavListItem["Nest"] = "nest";
@@ -3492,7 +3518,7 @@ var MenuNavList = React.forwardRef(function (_a, ref) {
3492
3518
  });
3493
3519
  MenuNavList.displayName = "MenuNavList";
3494
3520
 
3495
- var DEFAULT_TRANSLATIONS$5 = {
3521
+ var DEFAULT_TRANSLATIONS$6 = {
3496
3522
  menuLabel: "Menú",
3497
3523
  closeSidebarAriaLabel: "Cerrar menú lateral",
3498
3524
  mobileNavAriaLabel: "Navegación móvil",
@@ -3507,10 +3533,10 @@ var DEFAULT_TRANSLATIONS$5 = {
3507
3533
  */
3508
3534
  var MenuComponent = React.memo(function Menu(_a) {
3509
3535
  var _b, _c;
3510
- var commerceInfo = _a.commerceInfo, userInfo = _a.userInfo, helpButton = _a.helpButton, isOpenSidebar = _a.isOpenSidebar, onOpenSidebarChange = _a.onOpenSidebarChange, menuItems = _a.menuItems, mobileBottomBarGroupKey = _a.mobileBottomBarGroupKey, _d = _a.showNativeMenu, showNativeMenu = _d === void 0 ? true : _d, _e = _a.translations, translations = _e === void 0 ? {} : _e;
3536
+ var commerceInfo = _a.commerceInfo, userInfo = _a.userInfo, helpButton = _a.helpButton, isOpenSidebar = _a.isOpenSidebar, onOpenSidebarChange = _a.onOpenSidebarChange, menuItems = _a.menuItems, mobileBottomBarGroupKey = _a.mobileBottomBarGroupKey, _d = _a.showNativeMenu, showNativeMenu = _d === void 0 ? true : _d, onUserInfoClick = _a.onUserInfoClick, _e = _a.translations, translations = _e === void 0 ? {} : _e;
3511
3537
  var _f = React.useState(false), isCollapsed = _f[0], setIsCollapsed = _f[1];
3512
3538
  var _g = React.useState(false), logoError = _g[0], setLogoError = _g[1];
3513
- var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$5), translations);
3539
+ var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$6), translations);
3514
3540
  var selectedKey = React.useMemo(function () {
3515
3541
  var _a, _b, _c;
3516
3542
  if (menuItems.selectedPath) {
@@ -3547,6 +3573,18 @@ var MenuComponent = React.memo(function Menu(_a) {
3547
3573
  var handleSidebarClose = React.useCallback(function () {
3548
3574
  onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(false);
3549
3575
  }, [onOpenSidebarChange]);
3576
+ // TECH-1784: clic en el bloque de usuario -> acción del consumidor (ej.
3577
+ // navegar a /profile) y cierre del sidebar en móvil, igual que los ítems.
3578
+ var handleUserInfoClick = React.useCallback(function () {
3579
+ onUserInfoClick === null || onUserInfoClick === void 0 ? void 0 : onUserInfoClick();
3580
+ handleSidebarClose();
3581
+ }, [onUserInfoClick, handleSidebarClose]);
3582
+ // Contenido del bloque de usuario (avatar + nombre + rol), reutilizado
3583
+ // tanto en la variante estática como en la interactiva (TECH-1784).
3584
+ var userInfoContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(react.Avatar, { size: "md", src: ((_b = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, color: !((_c = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _c === void 0 ? void 0 : _c.trim()) ? "warning" : "default", name: userName,
3585
+ // TECH-1727: inicial de nombre + inicial de primer apellido
3586
+ // (p. ej. "Roser Ruiz" -> "RR") en vez de las 3 primeras letras.
3587
+ getInitials: getUserInitials, className: "shrink-0" }), jsxRuntime.jsxs("div", { className: "collapsible-item flex min-w-0 flex-col overflow-hidden", children: [jsxRuntime.jsx("p", { className: "text-small font-medium text-default-900 truncate", children: userName }), jsxRuntime.jsx("p", { className: "text-tiny text-default-400 truncate", children: userRole })] })] }));
3550
3588
  var handleSidebarOpen = React.useCallback(function () {
3551
3589
  onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(true);
3552
3590
  }, [onOpenSidebarChange]);
@@ -3686,7 +3724,168 @@ var MenuComponent = React.memo(function Menu(_a) {
3686
3724
  flexDirection: isCollapsed ? "column-reverse" : "row",
3687
3725
  }, children: [jsxRuntime.jsxs("div", { className: "flex flex-row items-center justify-center ".concat(isCollapsed ? "gap-0" : "gap-2"), children: [jsxRuntime.jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-foreground text-background", children: hasValidLogo ? (jsxRuntime.jsx("img", { src: commerceInfo.logo, alt: "".concat(t.logoAlt, " ").concat(commerceName), className: "h-full w-full object-cover", onError: function () { return setLogoError(true); } })) : (jsxRuntime.jsx(IconComponent, { icon: "solar:buildings-2-outline", size: "sm", className: "shrink-0", "aria-hidden": true })) }), jsxRuntime.jsx("span", { className: "collapsible-item text-small font-bold truncate min-w-0", children: commerceName })] }), jsxRuntime.jsxs("div", { className: "flex items-center", children: [jsxRuntime.jsx(IconComponent, { icon: "material-symbols-light:close", size: "lg", className: "cursor-pointer block sm:hidden", onClick: handleSidebarClose }), jsxRuntime.jsx(IconComponent, { icon: isCollapsed
3688
3726
  ? "solar:alt-arrow-right-outline"
3689
- : "solar:alt-arrow-left-outline", size: "lg", className: "hidden sm:block cursor-pointer", onClick: handleCollapseToggle })] })] }), jsxRuntime.jsx(react.Spacer, { y: 6 }), jsxRuntime.jsxs("div", { className: "content__menu--user ".concat(isCollapsed ? "gap-0" : "gap-3"), children: [jsxRuntime.jsx(react.Avatar, { size: "md", src: ((_b = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, color: !((_c = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _c === void 0 ? void 0 : _c.trim()) ? "warning" : "default", name: userName, className: "shrink-0" }), jsxRuntime.jsxs("div", { className: "collapsible-item flex min-w-0 flex-col overflow-hidden", children: [jsxRuntime.jsx("p", { className: "text-small font-medium text-default-900 truncate", children: userName }), jsxRuntime.jsx("p", { className: "text-tiny text-default-400 truncate", children: userRole })] })] }), jsxRuntime.jsxs("div", { className: "".concat(!isCollapsed ? "flex-1" : "h-full", " min-h-0 py-6 relative"), children: [!isCollapsed && showScrollArrows && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [scrollState.canScrollUp && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "menu-scroll-fade menu-scroll-fade--up", "aria-hidden": "true" }), jsxRuntime.jsx("button", { type: "button", "aria-label": t.scrollUpAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--up", onClick: handleScrollUp, children: jsxRuntime.jsx(IconComponent, { icon: "solar:alt-arrow-up-outline", size: "md", "aria-hidden": true }) })] })), scrollState.canScrollDown && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "menu-scroll-fade menu-scroll-fade--down", "aria-hidden": "true" }), jsxRuntime.jsx("button", { type: "button", "aria-label": t.scrollDownAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--down", onClick: handleScrollDown, children: jsxRuntime.jsx(IconComponent, { icon: "solar:alt-arrow-down-outline", size: "md", "aria-hidden": true }) })] }))] })), jsxRuntime.jsx("div", { ref: scrollContainerRef, className: "h-full overflow-y-auto pr-6 -mr-6 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none] select-none ".concat(isDraggingScroll ? "cursor-grabbing" : ""), onMouseDown: handleScrollAreaMouseDown, children: jsxRuntime.jsx(MenuNavList, { defaultSelectedKey: selectedKey, items: menuItems.items, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, selectedKey) })] }), helpSection ? (jsxRuntime.jsx("div", { className: "mt-auto flex flex-col justify-center items-center", children: jsxRuntime.jsx(react.Button, { fullWidth: true, className: " text-default-500 data-[hover=true]:text-default-600", startContent: jsxRuntime.jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed && (jsxRuntime.jsx("span", { className: "collapsible-item truncate", children: helpSection.title })) }) })) : null] }) })] }));
3727
+ : "solar:alt-arrow-left-outline", size: "lg", className: "hidden sm:block cursor-pointer", onClick: handleCollapseToggle })] })] }), jsxRuntime.jsx(react.Spacer, { y: 6 }), onUserInfoClick ? (jsxRuntime.jsx("button", { type: "button", onClick: handleUserInfoClick, className: "content__menu--user w-full text-left cursor-pointer rounded-large border-none bg-transparent transition-colors hover:bg-default/40 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus ".concat(isCollapsed ? "gap-0" : "gap-3"), children: userInfoContent })) : (jsxRuntime.jsx("div", { className: "content__menu--user ".concat(isCollapsed ? "gap-0" : "gap-3"), children: userInfoContent })), jsxRuntime.jsxs("div", { className: "".concat(!isCollapsed ? "flex-1" : "h-full", " min-h-0 py-6 relative"), children: [!isCollapsed && showScrollArrows && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [scrollState.canScrollUp && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "menu-scroll-fade menu-scroll-fade--up", "aria-hidden": "true" }), jsxRuntime.jsx("button", { type: "button", "aria-label": t.scrollUpAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--up", onClick: handleScrollUp, children: jsxRuntime.jsx(IconComponent, { icon: "solar:alt-arrow-up-outline", size: "md", "aria-hidden": true }) })] })), scrollState.canScrollDown && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "menu-scroll-fade menu-scroll-fade--down", "aria-hidden": "true" }), jsxRuntime.jsx("button", { type: "button", "aria-label": t.scrollDownAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--down", onClick: handleScrollDown, children: jsxRuntime.jsx(IconComponent, { icon: "solar:alt-arrow-down-outline", size: "md", "aria-hidden": true }) })] }))] })), jsxRuntime.jsx("div", { ref: scrollContainerRef, className: "h-full overflow-y-auto pr-6 -mr-6 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none] select-none ".concat(isDraggingScroll ? "cursor-grabbing" : ""), onMouseDown: handleScrollAreaMouseDown, children: jsxRuntime.jsx(MenuNavList, { defaultSelectedKey: selectedKey, items: menuItems.items, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, selectedKey) })] }), helpSection ? (jsxRuntime.jsx("div", { className: "mt-auto flex flex-col justify-center items-center", children: jsxRuntime.jsx(react.Button, { fullWidth: true, className: " text-default-500 data-[hover=true]:text-default-600", startContent: jsxRuntime.jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed && (jsxRuntime.jsx("span", { className: "collapsible-item truncate", children: helpSection.title })) }) })) : null] }) })] }));
3728
+ });
3729
+
3730
+ /**
3731
+ * Sección de historial de conversaciones: botón de nueva conversación + lista de
3732
+ * entradas recientes con "ver más".
3733
+ *
3734
+ * La lista tiene **scroll interno propio** (`flex-1 min-h-0 overflow-y-auto`) y
3735
+ * la sección está acotada en altura, para que crecer el historial no arrastre ni
3736
+ * recorte el área de navegación.
3737
+ *
3738
+ * Densidad de MenuClaw: fila de 36px, `px-2`, `text-small`/`text-tiny` y radios
3739
+ * `rounded-lg`/`rounded-xl` — que es justo lo que difiere del menú compartido.
3740
+ */
3741
+ var MenuClawHistoryPanel = React.memo(function MenuClawHistoryPanel(_a) {
3742
+ var items = _a.items, initialVisibleCount = _a.initialVisibleCount, onNewConversation = _a.onNewConversation, isCollapsed = _a.isCollapsed, title = _a.title, newLabel = _a.newLabel, showMoreLabel = _a.showMoreLabel, showLessLabel = _a.showLessLabel, onBeforeSelect = _a.onBeforeSelect;
3743
+ var _b = React.useState(false), isExpanded = _b[0], setIsExpanded = _b[1];
3744
+ var visibleItems = React.useMemo(function () { return (isExpanded ? items : items.slice(0, initialVisibleCount)); }, [isExpanded, items, initialVisibleCount]);
3745
+ var hasHiddenItems = items.length > initialVisibleCount;
3746
+ var handleToggleExpand = React.useCallback(function () {
3747
+ setIsExpanded(function (prev) { return !prev; });
3748
+ }, []);
3749
+ var handleItemPress = React.useCallback(function (item) {
3750
+ var _a;
3751
+ // `disabled` ya bloquea el botón; este guard cubre además el caso de
3752
+ // activación programática.
3753
+ if (item.disabled) {
3754
+ return;
3755
+ }
3756
+ onBeforeSelect === null || onBeforeSelect === void 0 ? void 0 : onBeforeSelect();
3757
+ (_a = item.onSelect) === null || _a === void 0 ? void 0 : _a.call(item);
3758
+ }, [onBeforeSelect]);
3759
+ // Comprimido no hay ancho para texto: solo el botón de nueva conversación,
3760
+ // en modo icono. Sin `onNewConversation` no hay nada que mostrar.
3761
+ if (isCollapsed && !onNewConversation) {
3762
+ return null;
3763
+ }
3764
+ return (jsxRuntime.jsxs("div", { className: "flex max-h-[40%] min-h-0 flex-col gap-2 pb-3", children: [onNewConversation ? (jsxRuntime.jsxs("button", { type: "button", title: newLabel, onClick: onNewConversation, className: react.cn("flex h-9 shrink-0 items-center gap-3 rounded-xl bg-foreground px-2 text-small font-medium text-background transition-opacity hover:opacity-90", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", isCollapsed && "justify-center"), children: [jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", children: jsxRuntime.jsx(IconComponent, { icon: "solar:pen-new-square-linear", size: "md", "aria-hidden": true }) }), !isCollapsed ? (jsxRuntime.jsx("span", { className: "menu-claw-collapsible truncate", children: newLabel })) : null] })) : null, !isCollapsed && items.length > 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("p", { className: "shrink-0 px-2 pb-1 pt-2 text-tiny font-medium uppercase tracking-wide text-default-400", children: title }), jsxRuntime.jsx("ul", { "aria-label": title, className: "flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: visibleItems.map(function (item) { return (jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("button", { type: "button", disabled: item.disabled, "aria-disabled": item.disabled, title: item.title, onClick: function () { return handleItemPress(item); }, className: react.cn("flex min-h-9 w-full items-center gap-3 rounded-lg px-2 py-1.5 text-left text-small text-default-600 transition-colors", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", item.disabled
3765
+ ? "cursor-not-allowed opacity-50"
3766
+ : "hover:bg-default-100"), children: [jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center text-default-400", children: jsxRuntime.jsx(IconComponent, { icon: "solar:chat-round-dots-linear", size: "md", "aria-hidden": true }) }), jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [jsxRuntime.jsx("span", { className: "truncate", children: item.title }), item.meta ? (jsxRuntime.jsx("span", { className: "truncate text-tiny text-default-400", children: item.meta })) : null] })] }) }, item.id)); }) }), hasHiddenItems ? (jsxRuntime.jsxs("button", { type: "button", onClick: handleToggleExpand, "aria-expanded": isExpanded, className: "flex w-full shrink-0 items-center gap-1.5 rounded-lg px-2 py-2 text-tiny font-medium text-default-500 transition-colors hover:bg-default-100 hover:text-default-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", children: [jsxRuntime.jsx(IconComponent, { icon: isExpanded
3767
+ ? "solar:alt-arrow-up-linear"
3768
+ : "solar:alt-arrow-down-linear", size: "sm", "aria-hidden": true }), isExpanded ? showLessLabel : showMoreLabel] })) : null] })) : null] }));
3769
+ });
3770
+
3771
+ var DEFAULT_TRANSLATIONS$5 = {
3772
+ menuLabel: "Menú",
3773
+ closeSidebarAriaLabel: "Cerrar menú lateral",
3774
+ mobileNavAriaLabel: "Navegación móvil",
3775
+ notDefinedLabel: "no definido",
3776
+ toggleSidebarAriaLabel: "Comprimir o expandir el menú",
3777
+ historyTitle: "Historial",
3778
+ historyNewLabel: "Nueva conversación",
3779
+ historyShowMoreLabel: "Ver más",
3780
+ historyShowLessLabel: "Ver menos",
3781
+ };
3782
+ /** Ítems del historial visibles antes de pulsar "ver más". */
3783
+ var DEFAULT_HISTORY_VISIBLE_COUNT = 5;
3784
+ /**
3785
+ * Menú lateral con historial de conversaciones integrado.
3786
+ *
3787
+ * Es un componente **aparte de `MenuComponent`**, no una extensión suya, y esa
3788
+ * es toda su razón de ser: el diseño no solo añade historial, cambia la
3789
+ * DENSIDAD del menú (fila de 36px en vez de 44, `px-2` en vez de `px-3`, dos
3790
+ * escalas tipográficas en vez de una, radios `lg`/`xl` en vez de `large`).
3791
+ * `MenuComponent` lo consumen varias plataformas —solo en beweossmbs hay 446
3792
+ * ficheros que importan el paquete— y no se puede cambiar su densidad base sin
3793
+ * regresionar a todas. Por eso aquí hay render propio y libertad visual, y por
3794
+ * eso **no** se reutiliza `MenuNavList`: heredaría los 44px que el diseño
3795
+ * cambia.
3796
+ *
3797
+ * Lo que sí se reutiliza es el **contrato de datos** (`MenuNavListItem`), para
3798
+ * que un consumidor pueda pasar exactamente la misma estructura de menú que ya
3799
+ * le da a `MenuComponent`. Mismo dato, render distinto.
3800
+ *
3801
+ * Preserva `helpButton` y la barra inferior móvil, que el menú hecho a mano del
3802
+ * diseño dejó caer. No pinta cabecera de comercio: en este diseño la identidad
3803
+ * del comercio vive fuera del lateral.
3804
+ */
3805
+ var MenuClaw = React.memo(function MenuClaw(_a) {
3806
+ var _b, _c;
3807
+ var userInfo = _a.userInfo, helpButton = _a.helpButton, menuItems = _a.menuItems, history = _a.history, isOpenSidebar = _a.isOpenSidebar, onOpenSidebarChange = _a.onOpenSidebarChange, mobileBottomBarGroupKey = _a.mobileBottomBarGroupKey, _d = _a.showNativeMenu, showNativeMenu = _d === void 0 ? true : _d, _e = _a.translations, translations = _e === void 0 ? {} : _e;
3808
+ var _f = React.useState(false), isCollapsed = _f[0], setIsCollapsed = _f[1];
3809
+ var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$5), translations);
3810
+ var selectedKey = React.useMemo(function () {
3811
+ var _a, _b, _c;
3812
+ if (menuItems.selectedPath) {
3813
+ return ((_b = (_a = getSelectedKeyFromPath(menuItems.selectedPath, menuItems.items)) !== null && _a !== void 0 ? _a : menuItems.selectedKey) !== null && _b !== void 0 ? _b : "");
3814
+ }
3815
+ return (_c = menuItems.selectedKey) !== null && _c !== void 0 ? _c : "";
3816
+ }, [menuItems.selectedPath, menuItems.selectedKey, menuItems.items]);
3817
+ var userName = (typeof (userInfo === null || userInfo === void 0 ? void 0 : userInfo.name) === "string" && userInfo.name.trim()) ||
3818
+ t.notDefinedLabel;
3819
+ var userRole = (typeof (userInfo === null || userInfo === void 0 ? void 0 : userInfo.role) === "string" && userInfo.role.trim()) ||
3820
+ t.notDefinedLabel;
3821
+ var helpSection = React.useMemo(function () {
3822
+ if (helpButton == null) {
3823
+ return null;
3824
+ }
3825
+ var title = typeof helpButton.title === "string" ? helpButton.title.trim() : "";
3826
+ var redirect = typeof helpButton.redirect === "string" ? helpButton.redirect.trim() : "";
3827
+ if (!(title && redirect)) {
3828
+ return null;
3829
+ }
3830
+ return { title: title, redirect: redirect };
3831
+ }, [helpButton]);
3832
+ var historyConfig = React.useMemo(function () {
3833
+ var items = Array.isArray(history === null || history === void 0 ? void 0 : history.items) ? history.items : [];
3834
+ var rawCount = history === null || history === void 0 ? void 0 : history.initialVisibleCount;
3835
+ var initialVisibleCount = typeof rawCount === "number" && Number.isFinite(rawCount) && rawCount > 0
3836
+ ? Math.floor(rawCount)
3837
+ : DEFAULT_HISTORY_VISIBLE_COUNT;
3838
+ return { items: items, initialVisibleCount: initialVisibleCount };
3839
+ }, [history]);
3840
+ var bottomBarItems = React.useMemo(function () {
3841
+ if (!mobileBottomBarGroupKey) {
3842
+ return [];
3843
+ }
3844
+ var group = menuItems.items.find(function (item) { return item.key === mobileBottomBarGroupKey; });
3845
+ if (!(group === null || group === void 0 ? void 0 : group.items)) {
3846
+ return [];
3847
+ }
3848
+ return group.items.filter(function (item) { return item.icon; });
3849
+ }, [mobileBottomBarGroupKey, menuItems.items]);
3850
+ var handleSidebarClose = React.useCallback(function () {
3851
+ onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(false);
3852
+ }, [onOpenSidebarChange]);
3853
+ var handleSidebarOpen = React.useCallback(function () {
3854
+ onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(true);
3855
+ }, [onOpenSidebarChange]);
3856
+ var handleCollapseToggle = React.useCallback(function () {
3857
+ setIsCollapsed(function (prev) { return !prev; });
3858
+ }, []);
3859
+ var handleHelpClick = React.useCallback(function () {
3860
+ if (helpSection) {
3861
+ window.open(helpSection.redirect, "_blank");
3862
+ }
3863
+ }, [helpSection]);
3864
+ var handleMenuSelect = React.useCallback(function (key, href) {
3865
+ var _a;
3866
+ onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(false);
3867
+ (_a = menuItems.onSelect) === null || _a === void 0 ? void 0 : _a.call(menuItems, key, href, "sidebar");
3868
+ }, [onOpenSidebarChange, menuItems.onSelect]);
3869
+ // Barra inferior: cerrar el lateral y avisar con source 'bottomBar' para que
3870
+ // la app no lo reabra al navegar.
3871
+ var handleBottomBarSelect = React.useCallback(function (key, href) {
3872
+ var _a;
3873
+ onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(false);
3874
+ (_a = menuItems.onSelect) === null || _a === void 0 ? void 0 : _a.call(menuItems, key, href, "bottomBar");
3875
+ }, [onOpenSidebarChange, menuItems.onSelect]);
3876
+ var showBottomBar = (mobileBottomBarGroupKey && bottomBarItems.length > 0) || showNativeMenu;
3877
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [showBottomBar ? (jsxRuntime.jsx(MenuMobileBottomBar, { items: bottomBarItems, selectedKey: selectedKey, onSelect: handleBottomBarSelect, onMenuPress: handleSidebarOpen, menuLabel: t.menuLabel, navAriaLabel: t.mobileNavAriaLabel, forceVisible: showNativeMenu && bottomBarItems.length === 0 })) : null, jsxRuntime.jsx("button", { type: "button", "aria-label": t.closeSidebarAriaLabel, className: "menu-claw-overlay ".concat(isOpenSidebar ? "menu-claw-overlay--open" : ""), onClick: handleSidebarClose, tabIndex: isOpenSidebar ? 0 : -1 }), jsxRuntime.jsx("div", { className: react.cn("menu-claw", isCollapsed ? "menu-claw--collapsed" : "menu-claw--expanded", isOpenSidebar && "menu-claw--mobile-open"), "aria-hidden": !isOpenSidebar, children: jsxRuntime.jsxs("div", { className: "menu-claw__content", children: [jsxRuntime.jsxs("div", { className: react.cn("flex items-center", isCollapsed ? "justify-center" : "justify-end"), children: [jsxRuntime.jsx(IconComponent, { icon: "material-symbols-light:close", size: "lg", className: "block cursor-pointer sm:hidden", onClick: handleSidebarClose }), jsxRuntime.jsx("button", { type: "button", "aria-label": t.toggleSidebarAriaLabel, onClick: handleCollapseToggle, className: "hidden h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-lg text-default-500 transition-colors hover:bg-default-100 sm:flex", children: jsxRuntime.jsx(IconComponent, { icon: isCollapsed
3878
+ ? "solar:alt-arrow-right-linear"
3879
+ : "solar:alt-arrow-left-linear", size: "md", "aria-hidden": true }) })] }), jsxRuntime.jsxs("div", { className: react.cn("flex items-center py-3", isCollapsed ? "justify-center gap-0" : "gap-3"), children: [jsxRuntime.jsx(react.Avatar, { size: "sm", src: ((_b = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, color: !((_c = userInfo === null || userInfo === void 0 ? void 0 : userInfo.avatar) === null || _c === void 0 ? void 0 : _c.trim()) ? "warning" : "default", name: userName, className: "shrink-0" }), !isCollapsed ? (jsxRuntime.jsxs("div", { className: "menu-claw-collapsible flex min-w-0 flex-col overflow-hidden", children: [jsxRuntime.jsx("p", { className: "truncate text-small font-semibold text-foreground", children: userName }), jsxRuntime.jsx("p", { className: "truncate text-tiny text-default-400", children: userRole })] })) : null] }), jsxRuntime.jsx(MenuClawHistoryPanel, { items: historyConfig.items, initialVisibleCount: historyConfig.initialVisibleCount, onNewConversation: history === null || history === void 0 ? void 0 : history.onNewConversation, isCollapsed: isCollapsed, title: t.historyTitle, newLabel: t.historyNewLabel, showMoreLabel: t.historyShowMoreLabel, showLessLabel: t.historyShowLessLabel, onBeforeSelect: handleSidebarClose }), jsxRuntime.jsx("nav", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: menuItems.items.map(function (group) {
3880
+ var _a;
3881
+ return (jsxRuntime.jsxs("div", { className: "mb-2", children: [group.title && !isCollapsed ? (jsxRuntime.jsx("p", { className: "px-2 pb-1 pt-2 text-tiny font-medium uppercase tracking-wide text-default-400", children: group.title })) : null, jsxRuntime.jsx("ul", { className: "flex flex-col gap-0.5", children: ((_a = group.items) !== null && _a !== void 0 ? _a : []).map(function (item) {
3882
+ var _a;
3883
+ var isActive = !!item.key && item.key === selectedKey;
3884
+ return (jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("button", { type: "button", title: isCollapsed ? item.title : undefined, onClick: function () { return handleMenuSelect(item.key, item.href); }, className: react.cn("flex min-h-9 w-full items-center rounded-lg px-2 py-1.5 text-left text-small transition-colors", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus", isCollapsed ? "justify-center" : "gap-3", isActive
3885
+ ? "bg-default-100 font-medium text-foreground"
3886
+ : "text-default-600 hover:bg-default-100", item.className), children: [item.icon || item.startContent ? (jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center text-default-500 [&_svg]:h-5 [&_svg]:w-5", children: item.icon ? (jsxRuntime.jsx(IconComponent, { icon: item.icon, size: "md", "aria-hidden": true })) : (item.startContent) })) : null, !isCollapsed ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "menu-claw-collapsible flex-1 truncate", children: item.title }), (_a = item.endContent) !== null && _a !== void 0 ? _a : null] })) : null] }) }, item.key));
3887
+ }) })] }, group.key));
3888
+ }) }), helpSection ? (jsxRuntime.jsx("div", { className: "mt-auto flex flex-col items-center justify-center", children: jsxRuntime.jsx(react.Button, { fullWidth: true, className: "text-default-500 data-[hover=true]:text-default-600", startContent: jsxRuntime.jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed ? (jsxRuntime.jsx("span", { className: "menu-claw-collapsible truncate", children: helpSection.title })) : null }) })) : null] }) })] }));
3690
3889
  });
3691
3890
 
3692
3891
  var StepIndicator = function (_a) {
@@ -9312,6 +9511,7 @@ exports.InputPassword = InputPassword;
9312
9511
  exports.Kanban = Kanban;
9313
9512
  exports.KanbanCard = KanbanCard;
9314
9513
  exports.KanbanColumn = KanbanColumn;
9514
+ exports.MenuClaw = MenuClaw;
9315
9515
  exports.MenuComponent = MenuComponent;
9316
9516
  exports.Modal = Modal;
9317
9517
  exports.ModalBody = ModalBody;