@beweco/aurora-ui 0.6.67 → 0.6.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -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";
@@ -3507,7 +3533,7 @@ var DEFAULT_TRANSLATIONS$6 = {
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
3539
  var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$6), translations);
@@ -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,7 @@ 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] }) })] }));
3690
3728
  });
3691
3729
 
3692
3730
  /**
@@ -3730,6 +3768,58 @@ var MenuClawHistoryPanel = React.memo(function MenuClawHistoryPanel(_a) {
3730
3768
  : "solar:alt-arrow-down-linear", size: "sm", "aria-hidden": true }), isExpanded ? showLessLabel : showMoreLabel] })) : null] })) : null] }));
3731
3769
  });
3732
3770
 
3771
+ /** ¿Está la key seleccionada en este ítem o en cualquiera de sus descendientes? */
3772
+ var containsKey = function (item, key) {
3773
+ var _a;
3774
+ if (!key) {
3775
+ return false;
3776
+ }
3777
+ if (item.key === key) {
3778
+ return true;
3779
+ }
3780
+ return ((_a = item.items) !== null && _a !== void 0 ? _a : []).some(function (child) { return containsKey(child, key); });
3781
+ };
3782
+ /**
3783
+ * Fila del menú. Si el ítem trae `items`, se pinta como grupo desplegable en vez
3784
+ * de como enlace.
3785
+ *
3786
+ * Existe porque `MenuClaw` no puede reutilizar `MenuNavList` (heredaría sus filas
3787
+ * de 44px) pero sí necesita el mismo dato jerárquico: los consumidores mandan
3788
+ * módulos con hijos —Catálogo › Productos/Servicios— y sin este render se
3789
+ * perderían en silencio, porque `MenuNavListItem.items` es opcional y no falla
3790
+ * al compilar.
3791
+ *
3792
+ * El grupo que contiene la ruta activa se despliega solo y no se puede plegar:
3793
+ * si se pudiera, el ítem activo quedaría oculto.
3794
+ */
3795
+ var MenuClawNavItem = function (_a) {
3796
+ var _b, _c;
3797
+ var item = _a.item, selectedKey = _a.selectedKey, isCollapsed = _a.isCollapsed, onSelect = _a.onSelect, _d = _a.depth, depth = _d === void 0 ? 0 : _d;
3798
+ var submenuId = React.useId();
3799
+ var _e = React.useState(false), isManuallyOpen = _e[0], setIsManuallyOpen = _e[1];
3800
+ var children = (_b = item.items) !== null && _b !== void 0 ? _b : [];
3801
+ // Comprimido no hay sitio para desplegables: la fila vuelve a ser navegable.
3802
+ var isGroup = children.length > 0 && !isCollapsed;
3803
+ var hasSelectedDescendant = React.useMemo(function () { return children.some(function (child) { return containsKey(child, selectedKey); }); }, [children, selectedKey]);
3804
+ var isOpen = hasSelectedDescendant || isManuallyOpen;
3805
+ var isActive = !!item.key && item.key === selectedKey;
3806
+ var handleClick = React.useCallback(function () {
3807
+ if (isGroup) {
3808
+ setIsManuallyOpen(function (prev) { return !prev; });
3809
+ return;
3810
+ }
3811
+ onSelect(item.key, item.href);
3812
+ }, [isGroup, onSelect, item.key, item.href]);
3813
+ var icon = 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;
3814
+ return (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsxs("button", { type: "button", title: isCollapsed ? item.title : undefined, onClick: handleClick, "aria-expanded": isGroup ? isOpen : undefined, "aria-controls": isGroup ? submenuId : undefined, className: react.cn("flex 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", depth === 0 ? "min-h-9" : "min-h-8", isCollapsed ? "justify-center" : "gap-3",
3815
+ // Sangría del hijo: alinea su texto con el del padre (px-2 + icono
3816
+ // de 20px + gap de 12px).
3817
+ !isCollapsed && depth > 0 && !icon ? "pl-10" : undefined, isActive
3818
+ ? "bg-default-100 font-medium text-foreground"
3819
+ : "text-default-600 hover:bg-default-100", item.className), children: [icon, !isCollapsed ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "menu-claw-collapsible flex-1 truncate", children: item.title }), (_c = item.endContent) !== null && _c !== void 0 ? _c : null, isGroup ? (jsxRuntime.jsx(IconComponent, { icon: "solar:alt-arrow-down-linear", size: "sm", "aria-hidden": true, className: react.cn("shrink-0 text-default-400 transition-transform", isOpen && "rotate-180") })) : null] })) : null] }), isGroup && isOpen ? (jsxRuntime.jsx("ul", { id: submenuId, className: "mt-0.5 flex flex-col gap-0.5", children: children.map(function (child) { return (jsxRuntime.jsx(MenuClawNavItem, { item: child, selectedKey: selectedKey, isCollapsed: isCollapsed, onSelect: onSelect, depth: depth + 1 }, child.key)); }) })) : null] }));
3820
+ };
3821
+ MenuClawNavItem.displayName = "MenuClawNavItem";
3822
+
3733
3823
  var DEFAULT_TRANSLATIONS$5 = {
3734
3824
  menuLabel: "Menú",
3735
3825
  closeSidebarAriaLabel: "Cerrar menú lateral",
@@ -3840,13 +3930,7 @@ var MenuClaw = React.memo(function MenuClaw(_a) {
3840
3930
  ? "solar:alt-arrow-right-linear"
3841
3931
  : "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) {
3842
3932
  var _a;
3843
- 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) {
3844
- var _a;
3845
- var isActive = !!item.key && item.key === selectedKey;
3846
- 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
3847
- ? "bg-default-100 font-medium text-foreground"
3848
- : "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));
3849
- }) })] }, group.key));
3933
+ 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) { return (jsxRuntime.jsx(MenuClawNavItem, { item: item, selectedKey: selectedKey, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, item.key)); }) })] }, group.key));
3850
3934
  }) }), 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] }) })] }));
3851
3935
  });
3852
3936
 
package/dist/index.esm.js CHANGED
@@ -3333,6 +3333,32 @@ function getSelectedKeyFromPath(pathname, items) {
3333
3333
  return undefined;
3334
3334
  }
3335
3335
 
3336
+ /**
3337
+ * Deriva las iniciales para el avatar del usuario a partir de su nombre completo.
3338
+ *
3339
+ * Muestra la inicial del nombre + la inicial del primer apellido (2 letras en
3340
+ * mayúsculas), p. ej. "Roser Ruiz" -> "RR". Si el usuario solo tiene un token
3341
+ * (nombre sin apellido) devuelve una sola inicial. Si no hay texto, devuelve "".
3342
+ *
3343
+ * TECH-1727: reemplaza el comportamiento por defecto de HeroUI (`safeText`), que
3344
+ * muestra las 3 primeras letras del nombre ("Roser Ruiz" -> "Ros").
3345
+ *
3346
+ * @param fullName Nombre completo del usuario (se usa el mismo valor que el label).
3347
+ * @returns Iniciales en mayúsculas (0, 1 o 2 letras).
3348
+ */
3349
+ var getUserInitials = function (fullName) {
3350
+ var tokens = fullName.trim().split(/\s+/).filter(Boolean);
3351
+ if (tokens.length === 0) {
3352
+ return "";
3353
+ }
3354
+ var firstInitial = tokens[0].charAt(0).toUpperCase();
3355
+ if (tokens.length === 1) {
3356
+ return firstInitial;
3357
+ }
3358
+ var secondInitial = tokens[1].charAt(0).toUpperCase();
3359
+ return "".concat(firstInitial).concat(secondInitial);
3360
+ };
3361
+
3336
3362
  var EnumMenuNavListItem;
3337
3363
  (function (EnumMenuNavListItem) {
3338
3364
  EnumMenuNavListItem["Nest"] = "nest";
@@ -3508,7 +3534,7 @@ var DEFAULT_TRANSLATIONS$6 = {
3508
3534
  */
3509
3535
  var MenuComponent = React.memo(function Menu(_a) {
3510
3536
  var _b, _c;
3511
- 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;
3537
+ 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;
3512
3538
  var _f = React.useState(false), isCollapsed = _f[0], setIsCollapsed = _f[1];
3513
3539
  var _g = React.useState(false), logoError = _g[0], setLogoError = _g[1];
3514
3540
  var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$6), translations);
@@ -3548,6 +3574,18 @@ var MenuComponent = React.memo(function Menu(_a) {
3548
3574
  var handleSidebarClose = useCallback(function () {
3549
3575
  onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(false);
3550
3576
  }, [onOpenSidebarChange]);
3577
+ // TECH-1784: clic en el bloque de usuario -> acción del consumidor (ej.
3578
+ // navegar a /profile) y cierre del sidebar en móvil, igual que los ítems.
3579
+ var handleUserInfoClick = useCallback(function () {
3580
+ onUserInfoClick === null || onUserInfoClick === void 0 ? void 0 : onUserInfoClick();
3581
+ handleSidebarClose();
3582
+ }, [onUserInfoClick, handleSidebarClose]);
3583
+ // Contenido del bloque de usuario (avatar + nombre + rol), reutilizado
3584
+ // tanto en la variante estática como en la interactiva (TECH-1784).
3585
+ var userInfoContent = (jsxs(Fragment, { children: [jsx(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,
3586
+ // TECH-1727: inicial de nombre + inicial de primer apellido
3587
+ // (p. ej. "Roser Ruiz" -> "RR") en vez de las 3 primeras letras.
3588
+ getInitials: getUserInitials, className: "shrink-0" }), jsxs("div", { className: "collapsible-item flex min-w-0 flex-col overflow-hidden", children: [jsx("p", { className: "text-small font-medium text-default-900 truncate", children: userName }), jsx("p", { className: "text-tiny text-default-400 truncate", children: userRole })] })] }));
3551
3589
  var handleSidebarOpen = useCallback(function () {
3552
3590
  onOpenSidebarChange === null || onOpenSidebarChange === void 0 ? void 0 : onOpenSidebarChange(true);
3553
3591
  }, [onOpenSidebarChange]);
@@ -3687,7 +3725,7 @@ var MenuComponent = React.memo(function Menu(_a) {
3687
3725
  flexDirection: isCollapsed ? "column-reverse" : "row",
3688
3726
  }, children: [jsxs("div", { className: "flex flex-row items-center justify-center ".concat(isCollapsed ? "gap-0" : "gap-2"), children: [jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-foreground text-background", children: hasValidLogo ? (jsx("img", { src: commerceInfo.logo, alt: "".concat(t.logoAlt, " ").concat(commerceName), className: "h-full w-full object-cover", onError: function () { return setLogoError(true); } })) : (jsx(IconComponent, { icon: "solar:buildings-2-outline", size: "sm", className: "shrink-0", "aria-hidden": true })) }), jsx("span", { className: "collapsible-item text-small font-bold truncate min-w-0", children: commerceName })] }), jsxs("div", { className: "flex items-center", children: [jsx(IconComponent, { icon: "material-symbols-light:close", size: "lg", className: "cursor-pointer block sm:hidden", onClick: handleSidebarClose }), jsx(IconComponent, { icon: isCollapsed
3689
3727
  ? "solar:alt-arrow-right-outline"
3690
- : "solar:alt-arrow-left-outline", size: "lg", className: "hidden sm:block cursor-pointer", onClick: handleCollapseToggle })] })] }), jsx(Spacer, { y: 6 }), jsxs("div", { className: "content__menu--user ".concat(isCollapsed ? "gap-0" : "gap-3"), children: [jsx(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" }), jsxs("div", { className: "collapsible-item flex min-w-0 flex-col overflow-hidden", children: [jsx("p", { className: "text-small font-medium text-default-900 truncate", children: userName }), jsx("p", { className: "text-tiny text-default-400 truncate", children: userRole })] })] }), jsxs("div", { className: "".concat(!isCollapsed ? "flex-1" : "h-full", " min-h-0 py-6 relative"), children: [!isCollapsed && showScrollArrows && (jsxs(Fragment, { children: [scrollState.canScrollUp && (jsxs(Fragment, { children: [jsx("div", { className: "menu-scroll-fade menu-scroll-fade--up", "aria-hidden": "true" }), jsx("button", { type: "button", "aria-label": t.scrollUpAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--up", onClick: handleScrollUp, children: jsx(IconComponent, { icon: "solar:alt-arrow-up-outline", size: "md", "aria-hidden": true }) })] })), scrollState.canScrollDown && (jsxs(Fragment, { children: [jsx("div", { className: "menu-scroll-fade menu-scroll-fade--down", "aria-hidden": "true" }), jsx("button", { type: "button", "aria-label": t.scrollDownAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--down", onClick: handleScrollDown, children: jsx(IconComponent, { icon: "solar:alt-arrow-down-outline", size: "md", "aria-hidden": true }) })] }))] })), 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: jsx(MenuNavList, { defaultSelectedKey: selectedKey, items: menuItems.items, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, selectedKey) })] }), helpSection ? (jsx("div", { className: "mt-auto flex flex-col justify-center items-center", children: jsx(Button$1, { fullWidth: true, className: " text-default-500 data-[hover=true]:text-default-600", startContent: jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed && (jsx("span", { className: "collapsible-item truncate", children: helpSection.title })) }) })) : null] }) })] }));
3728
+ : "solar:alt-arrow-left-outline", size: "lg", className: "hidden sm:block cursor-pointer", onClick: handleCollapseToggle })] })] }), jsx(Spacer, { y: 6 }), onUserInfoClick ? (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 })) : (jsx("div", { className: "content__menu--user ".concat(isCollapsed ? "gap-0" : "gap-3"), children: userInfoContent })), jsxs("div", { className: "".concat(!isCollapsed ? "flex-1" : "h-full", " min-h-0 py-6 relative"), children: [!isCollapsed && showScrollArrows && (jsxs(Fragment, { children: [scrollState.canScrollUp && (jsxs(Fragment, { children: [jsx("div", { className: "menu-scroll-fade menu-scroll-fade--up", "aria-hidden": "true" }), jsx("button", { type: "button", "aria-label": t.scrollUpAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--up", onClick: handleScrollUp, children: jsx(IconComponent, { icon: "solar:alt-arrow-up-outline", size: "md", "aria-hidden": true }) })] })), scrollState.canScrollDown && (jsxs(Fragment, { children: [jsx("div", { className: "menu-scroll-fade menu-scroll-fade--down", "aria-hidden": "true" }), jsx("button", { type: "button", "aria-label": t.scrollDownAriaLabel, className: "menu-scroll-chevron menu-scroll-chevron--down", onClick: handleScrollDown, children: jsx(IconComponent, { icon: "solar:alt-arrow-down-outline", size: "md", "aria-hidden": true }) })] }))] })), 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: jsx(MenuNavList, { defaultSelectedKey: selectedKey, items: menuItems.items, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, selectedKey) })] }), helpSection ? (jsx("div", { className: "mt-auto flex flex-col justify-center items-center", children: jsx(Button$1, { fullWidth: true, className: " text-default-500 data-[hover=true]:text-default-600", startContent: jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed && (jsx("span", { className: "collapsible-item truncate", children: helpSection.title })) }) })) : null] }) })] }));
3691
3729
  });
3692
3730
 
3693
3731
  /**
@@ -3731,6 +3769,58 @@ var MenuClawHistoryPanel = React.memo(function MenuClawHistoryPanel(_a) {
3731
3769
  : "solar:alt-arrow-down-linear", size: "sm", "aria-hidden": true }), isExpanded ? showLessLabel : showMoreLabel] })) : null] })) : null] }));
3732
3770
  });
3733
3771
 
3772
+ /** ¿Está la key seleccionada en este ítem o en cualquiera de sus descendientes? */
3773
+ var containsKey = function (item, key) {
3774
+ var _a;
3775
+ if (!key) {
3776
+ return false;
3777
+ }
3778
+ if (item.key === key) {
3779
+ return true;
3780
+ }
3781
+ return ((_a = item.items) !== null && _a !== void 0 ? _a : []).some(function (child) { return containsKey(child, key); });
3782
+ };
3783
+ /**
3784
+ * Fila del menú. Si el ítem trae `items`, se pinta como grupo desplegable en vez
3785
+ * de como enlace.
3786
+ *
3787
+ * Existe porque `MenuClaw` no puede reutilizar `MenuNavList` (heredaría sus filas
3788
+ * de 44px) pero sí necesita el mismo dato jerárquico: los consumidores mandan
3789
+ * módulos con hijos —Catálogo › Productos/Servicios— y sin este render se
3790
+ * perderían en silencio, porque `MenuNavListItem.items` es opcional y no falla
3791
+ * al compilar.
3792
+ *
3793
+ * El grupo que contiene la ruta activa se despliega solo y no se puede plegar:
3794
+ * si se pudiera, el ítem activo quedaría oculto.
3795
+ */
3796
+ var MenuClawNavItem = function (_a) {
3797
+ var _b, _c;
3798
+ var item = _a.item, selectedKey = _a.selectedKey, isCollapsed = _a.isCollapsed, onSelect = _a.onSelect, _d = _a.depth, depth = _d === void 0 ? 0 : _d;
3799
+ var submenuId = useId();
3800
+ var _e = useState(false), isManuallyOpen = _e[0], setIsManuallyOpen = _e[1];
3801
+ var children = (_b = item.items) !== null && _b !== void 0 ? _b : [];
3802
+ // Comprimido no hay sitio para desplegables: la fila vuelve a ser navegable.
3803
+ var isGroup = children.length > 0 && !isCollapsed;
3804
+ var hasSelectedDescendant = useMemo(function () { return children.some(function (child) { return containsKey(child, selectedKey); }); }, [children, selectedKey]);
3805
+ var isOpen = hasSelectedDescendant || isManuallyOpen;
3806
+ var isActive = !!item.key && item.key === selectedKey;
3807
+ var handleClick = useCallback(function () {
3808
+ if (isGroup) {
3809
+ setIsManuallyOpen(function (prev) { return !prev; });
3810
+ return;
3811
+ }
3812
+ onSelect(item.key, item.href);
3813
+ }, [isGroup, onSelect, item.key, item.href]);
3814
+ var icon = item.icon || item.startContent ? (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 ? (jsx(IconComponent, { icon: item.icon, size: "md", "aria-hidden": true })) : (item.startContent) })) : null;
3815
+ return (jsxs("li", { children: [jsxs("button", { type: "button", title: isCollapsed ? item.title : undefined, onClick: handleClick, "aria-expanded": isGroup ? isOpen : undefined, "aria-controls": isGroup ? submenuId : undefined, className: cn("flex 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", depth === 0 ? "min-h-9" : "min-h-8", isCollapsed ? "justify-center" : "gap-3",
3816
+ // Sangría del hijo: alinea su texto con el del padre (px-2 + icono
3817
+ // de 20px + gap de 12px).
3818
+ !isCollapsed && depth > 0 && !icon ? "pl-10" : undefined, isActive
3819
+ ? "bg-default-100 font-medium text-foreground"
3820
+ : "text-default-600 hover:bg-default-100", item.className), children: [icon, !isCollapsed ? (jsxs(Fragment, { children: [jsx("span", { className: "menu-claw-collapsible flex-1 truncate", children: item.title }), (_c = item.endContent) !== null && _c !== void 0 ? _c : null, isGroup ? (jsx(IconComponent, { icon: "solar:alt-arrow-down-linear", size: "sm", "aria-hidden": true, className: cn("shrink-0 text-default-400 transition-transform", isOpen && "rotate-180") })) : null] })) : null] }), isGroup && isOpen ? (jsx("ul", { id: submenuId, className: "mt-0.5 flex flex-col gap-0.5", children: children.map(function (child) { return (jsx(MenuClawNavItem, { item: child, selectedKey: selectedKey, isCollapsed: isCollapsed, onSelect: onSelect, depth: depth + 1 }, child.key)); }) })) : null] }));
3821
+ };
3822
+ MenuClawNavItem.displayName = "MenuClawNavItem";
3823
+
3734
3824
  var DEFAULT_TRANSLATIONS$5 = {
3735
3825
  menuLabel: "Menú",
3736
3826
  closeSidebarAriaLabel: "Cerrar menú lateral",
@@ -3841,13 +3931,7 @@ var MenuClaw = React.memo(function MenuClaw(_a) {
3841
3931
  ? "solar:alt-arrow-right-linear"
3842
3932
  : "solar:alt-arrow-left-linear", size: "md", "aria-hidden": true }) })] }), jsxs("div", { className: cn("flex items-center py-3", isCollapsed ? "justify-center gap-0" : "gap-3"), children: [jsx(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 ? (jsxs("div", { className: "menu-claw-collapsible flex min-w-0 flex-col overflow-hidden", children: [jsx("p", { className: "truncate text-small font-semibold text-foreground", children: userName }), jsx("p", { className: "truncate text-tiny text-default-400", children: userRole })] })) : null] }), 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 }), 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) {
3843
3933
  var _a;
3844
- return (jsxs("div", { className: "mb-2", children: [group.title && !isCollapsed ? (jsx("p", { className: "px-2 pb-1 pt-2 text-tiny font-medium uppercase tracking-wide text-default-400", children: group.title })) : null, jsx("ul", { className: "flex flex-col gap-0.5", children: ((_a = group.items) !== null && _a !== void 0 ? _a : []).map(function (item) {
3845
- var _a;
3846
- var isActive = !!item.key && item.key === selectedKey;
3847
- return (jsx("li", { children: jsxs("button", { type: "button", title: isCollapsed ? item.title : undefined, onClick: function () { return handleMenuSelect(item.key, item.href); }, className: 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
3848
- ? "bg-default-100 font-medium text-foreground"
3849
- : "text-default-600 hover:bg-default-100", item.className), children: [item.icon || item.startContent ? (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 ? (jsx(IconComponent, { icon: item.icon, size: "md", "aria-hidden": true })) : (item.startContent) })) : null, !isCollapsed ? (jsxs(Fragment, { children: [jsx("span", { className: "menu-claw-collapsible flex-1 truncate", children: item.title }), (_a = item.endContent) !== null && _a !== void 0 ? _a : null] })) : null] }) }, item.key));
3850
- }) })] }, group.key));
3934
+ return (jsxs("div", { className: "mb-2", children: [group.title && !isCollapsed ? (jsx("p", { className: "px-2 pb-1 pt-2 text-tiny font-medium uppercase tracking-wide text-default-400", children: group.title })) : null, jsx("ul", { className: "flex flex-col gap-0.5", children: ((_a = group.items) !== null && _a !== void 0 ? _a : []).map(function (item) { return (jsx(MenuClawNavItem, { item: item, selectedKey: selectedKey, isCollapsed: isCollapsed, onSelect: handleMenuSelect }, item.key)); }) })] }, group.key));
3851
3935
  }) }), helpSection ? (jsx("div", { className: "mt-auto flex flex-col items-center justify-center", children: jsx(Button$1, { fullWidth: true, className: "text-default-500 data-[hover=true]:text-default-600", startContent: jsx(IconComponent, { className: "text-default-500", icon: "solar:info-circle-line-duotone", size: "md" }), variant: "light", onPress: handleHelpClick, isIconOnly: isCollapsed, children: !isCollapsed ? (jsx("span", { className: "menu-claw-collapsible truncate", children: helpSection.title })) : null }) })) : null] }) })] }));
3852
3936
  });
3853
3937
 
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../../src/components/menu/Menu.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,aAAa,CAAC;AAIrB,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,cAAc,CAAC;AAgBtB;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA8ZtD,CAAC"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../../src/components/menu/Menu.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,aAAa,CAAC;AAKrB,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,cAAc,CAAC;AAgBtB;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA2btD,CAAC"}
@@ -66,6 +66,13 @@ export interface MenuComponentProps {
66
66
  * @default true
67
67
  */
68
68
  showNativeMenu?: boolean;
69
+ /**
70
+ * Se invoca al hacer clic (o Enter/Espacio) sobre el bloque de usuario
71
+ * (avatar + nombre + rol) del sidebar. Si se proporciona, el bloque se vuelve
72
+ * interactivo (cursor pointer + hover) — típicamente para navegar al perfil.
73
+ * Si se omite, el bloque se muestra como texto estático (sin acción).
74
+ */
75
+ onUserInfoClick?: () => void;
69
76
  /**
70
77
  * Traducciones i18n del componente.
71
78
  * Si no se proporciona, usa traducciones por defecto en español.
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.types.d.ts","sourceRoot":"","sources":["../../../../src/components/menu/Menu.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACvC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,kBAAkB;IAClC,YAAY,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF;;;OAGG;IACH,UAAU,CAAC,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACV,KAAK,EAAE,eAAe,EAAE,CAAC;QACzB;;;WAGG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,8FAA8F;QAC9F,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,KAAK,IAAI,CAAC;KAClF,CAAC;IACF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,yBAAyB,CAAC;CACzC"}
1
+ {"version":3,"file":"Menu.types.d.ts","sourceRoot":"","sources":["../../../../src/components/menu/Menu.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACvC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,kBAAkB;IAClC,YAAY,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF;;;OAGG;IACH,UAAU,CAAC,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACV,KAAK,EAAE,eAAe,EAAE,CAAC;QACzB;;;WAGG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,8FAA8F;QAC9F,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,KAAK,IAAI,CAAC;KAClF,CAAC;IACF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,yBAAyB,CAAC;CACzC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Deriva las iniciales para el avatar del usuario a partir de su nombre completo.
3
+ *
4
+ * Muestra la inicial del nombre + la inicial del primer apellido (2 letras en
5
+ * mayúsculas), p. ej. "Roser Ruiz" -> "RR". Si el usuario solo tiene un token
6
+ * (nombre sin apellido) devuelve una sola inicial. Si no hay texto, devuelve "".
7
+ *
8
+ * TECH-1727: reemplaza el comportamiento por defecto de HeroUI (`safeText`), que
9
+ * muestra las 3 primeras letras del nombre ("Roser Ruiz" -> "Ros").
10
+ *
11
+ * @param fullName Nombre completo del usuario (se usa el mismo valor que el label).
12
+ * @returns Iniciales en mayúsculas (0, 1 o 2 letras).
13
+ */
14
+ export declare const getUserInitials: (fullName: string) => string;
15
+ //# sourceMappingURL=get-user-initials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-user-initials.d.ts","sourceRoot":"","sources":["../../../../src/components/menu/get-user-initials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KAAG,MAWlD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"MenuClaw.d.ts","sourceRoot":"","sources":["../../../../src/components/menu-claw/MenuClaw.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAkB5E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA4S3C,CAAC"}
1
+ {"version":3,"file":"MenuClaw.d.ts","sourceRoot":"","sources":["../../../../src/components/menu-claw/MenuClaw.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAmB5E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA2Q3C,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type React from "react";
2
+ import type { MenuClawNavItemProps } from "./MenuClawNavItem.types";
3
+ /**
4
+ * Fila del menú. Si el ítem trae `items`, se pinta como grupo desplegable en vez
5
+ * de como enlace.
6
+ *
7
+ * Existe porque `MenuClaw` no puede reutilizar `MenuNavList` (heredaría sus filas
8
+ * de 44px) pero sí necesita el mismo dato jerárquico: los consumidores mandan
9
+ * módulos con hijos —Catálogo › Productos/Servicios— y sin este render se
10
+ * perderían en silencio, porque `MenuNavListItem.items` es opcional y no falla
11
+ * al compilar.
12
+ *
13
+ * El grupo que contiene la ruta activa se despliega solo y no se puede plegar:
14
+ * si se pudiera, el ítem activo quedaría oculto.
15
+ */
16
+ export declare const MenuClawNavItem: React.FC<MenuClawNavItemProps>;
17
+ //# sourceMappingURL=MenuClawNavItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuClawNavItem.d.ts","sourceRoot":"","sources":["../../../../../../src/components/menu-claw/_internal/menu-claw-nav/MenuClawNavItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAapE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAqG1D,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { MenuNavListItem } from "../../../menu/_internal/menu-nav-list/MenuNavList.types";
2
+ export type MenuClawNavItemProps = {
3
+ /** Ítem a pintar. Si trae `items`, se renderiza como grupo desplegable. */
4
+ item: MenuNavListItem;
5
+ /** Key del ítem activo, ya resuelta por el menú. */
6
+ selectedKey: string;
7
+ /** Lateral comprimido: solo iconos, sin desplegables. */
8
+ isCollapsed: boolean;
9
+ /** Se invoca al activar un ítem navegable (nunca en el padre desplegable). */
10
+ onSelect: (key: string, href?: string) => void;
11
+ /**
12
+ * Nivel de anidamiento. 0 = módulo, 1 = hijo. Solo afecta a la sangría y al
13
+ * alto de fila; el contrato de datos admite más niveles y se renderizan
14
+ * recursivamente.
15
+ */
16
+ depth?: number;
17
+ };
18
+ //# sourceMappingURL=MenuClawNavItem.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuClawNavItem.types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/menu-claw/_internal/menu-claw-nav/MenuClawNavItem.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yDAAyD,CAAC;AAE/F,MAAM,MAAM,oBAAoB,GAAG;IAClC,2EAA2E;IAC3E,IAAI,EAAE,eAAe,CAAC;IACtB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { MenuClawNavItem } from "./MenuClawNavItem";
2
+ export type { MenuClawNavItemProps } from "./MenuClawNavItem.types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/menu-claw/_internal/menu-claw-nav/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beweco/aurora-ui",
3
- "version": "0.6.67",
3
+ "version": "0.6.69",
4
4
  "description": "Bewe Aurora UI Component Library",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "module": "./dist/index.esm.js",