@sd-angular/core 19.0.0-beta.79 → 19.0.0-beta.80

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, ElementRef, input, booleanAttribute, effect, Component, Injectable, InjectionToken, signal, Pipe, output, DestroyRef, computed, untracked, viewChild, Inject, NgModule } from '@angular/core';
3
3
  import * as i1$3 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
4
+ import { CommonModule, NgTemplateOutlet } from '@angular/common';
5
5
  import * as i1$5 from '@angular/router';
6
6
  import { Router, NavigationEnd, RouterModule, ActivatedRoute } from '@angular/router';
7
7
  import { __decorate } from 'tslib';
@@ -296,7 +296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
296
296
  }]
297
297
  }] });
298
298
 
299
- class LayoutUserComponent {
299
+ let LayoutUserComponent$1 = class LayoutUserComponent {
300
300
  // ==========================================
301
301
  // INJECT SERVICES
302
302
  // ==========================================
@@ -339,8 +339,8 @@ class LayoutUserComponent {
339
339
  };
340
340
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
341
341
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\r\n\r\n<div class=\"c-layout-user-wrapper\">\r\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\r\n </div>\r\n\r\n @if (!isMobileOrTablet()) {\r\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\r\n <mat-icon style=\"color: #8c8c8c\">\r\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\r\n </mat-icon>\r\n </div>\r\n }\r\n</div>\r\n\r\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\r\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\r\n <div class=\"c-user-info-wrapper\">\r\n <div class=\"c-user-avatar\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\r\n </div>\r\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\r\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\r\n </div>\r\n\r\n @if (changePasswordLayoutConfig) {\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-account-options\" (click)=\"changePassword()\">\r\n <img alt=\"lock\" />\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">\u0110\u0103ng xu\u1EA5t</button>\r\n </div>\r\n </div>\r\n</mat-menu>", styles: ["::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options img{scale:.875;content:url('data:image/svg+xml,<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">%0D%0A <path%0D%0A d=\"M12 5.66667H11.3333V4.33333C11.3333 2.49333 9.83996 1 7.99996 1C6.15996 1 4.66663 2.49333 4.66663 4.33333V5.66667H3.99996C3.26663 5.66667 2.66663 6.26667 2.66663 7V13.6667C2.66663 14.4 3.26663 15 3.99996 15H12C12.7333 15 13.3333 14.4 13.3333 13.6667V7C13.3333 6.26667 12.7333 5.66667 12 5.66667ZM5.99996 4.33333C5.99996 3.22667 6.89329 2.33333 7.99996 2.33333C9.10663 2.33333 9.99996 3.22667 9.99996 4.33333V5.66667H5.99996V4.33333ZM12 13.6667H3.99996V7H12V13.6667ZM7.99996 11.6667C8.73329 11.6667 9.33329 11.0667 9.33329 10.3333C9.33329 9.6 8.73329 9 7.99996 9C7.26663 9 6.66663 9.6 6.66663 10.3333C6.66663 11.0667 7.26663 11.6667 7.99996 11.6667Z\"%0D%0A fill=\"%23757575\" />%0D%0A</svg>')}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }] });
342
- }
343
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutUserComponent, decorators: [{
342
+ };
343
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutUserComponent$1, decorators: [{
344
344
  type: Component,
345
345
  args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar], standalone: true, template: "@let _userInfo = userInfo();\r\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\r\n\r\n<div class=\"c-layout-user-wrapper\">\r\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\r\n </div>\r\n\r\n @if (!isMobileOrTablet()) {\r\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\r\n <mat-icon style=\"color: #8c8c8c\">\r\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\r\n </mat-icon>\r\n </div>\r\n }\r\n</div>\r\n\r\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\r\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\r\n <div class=\"c-user-info-wrapper\">\r\n <div class=\"c-user-avatar\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\r\n </div>\r\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\r\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\r\n </div>\r\n\r\n @if (changePasswordLayoutConfig) {\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-account-options\" (click)=\"changePassword()\">\r\n <img alt=\"lock\" />\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">\u0110\u0103ng xu\u1EA5t</button>\r\n </div>\r\n </div>\r\n</mat-menu>", styles: ["::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options img{scale:.875;content:url('data:image/svg+xml,<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">%0D%0A <path%0D%0A d=\"M12 5.66667H11.3333V4.33333C11.3333 2.49333 9.83996 1 7.99996 1C6.15996 1 4.66663 2.49333 4.66663 4.33333V5.66667H3.99996C3.26663 5.66667 2.66663 6.26667 2.66663 7V13.6667C2.66663 14.4 3.26663 15 3.99996 15H12C12.7333 15 13.3333 14.4 13.3333 13.6667V7C13.3333 6.26667 12.7333 5.66667 12 5.66667ZM5.99996 4.33333C5.99996 3.22667 6.89329 2.33333 7.99996 2.33333C9.10663 2.33333 9.99996 3.22667 9.99996 4.33333V5.66667H5.99996V4.33333ZM12 13.6667H3.99996V7H12V13.6667ZM7.99996 11.6667C8.73329 11.6667 9.33329 11.0667 9.33329 10.3333C9.33329 9.6 8.73329 9 7.99996 9C7.26663 9 6.66663 9.6 6.66663 10.3333C6.66663 11.0667 7.26663 11.6667 7.99996 11.6667Z\"%0D%0A fill=\"%23757575\" />%0D%0A</svg>')}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"] }]
346
346
  }] });
@@ -725,7 +725,7 @@ class SidebarComponent {
725
725
  return count;
726
726
  };
727
727
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar) {\r\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\r\n <div class=\"c-header\">\r\n @if (_sidebar.logoUrl) {\r\n <div class=\"c-logo\">\r\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\r\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\r\n </a>\r\n </div>\r\n }\r\n <div class=\"c-title-menu-group\">\r\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"c-body\">\r\n <div class=\"c-menu\">\r\n <div class=\"c-menu-group\">\r\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\r\n <button\r\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\r\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\r\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\r\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\r\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\r\n [matTooltipPosition]=\"'right'\"\r\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\r\n @if (nodeMenuGroup.iconUrl) {\r\n <span\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\r\n </span>\r\n } @else {\r\n <mat-icon\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n {{ nodeMenuGroup.icon || 'widgets' }}\r\n </mat-icon>\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"c-menu-tree\">\r\n @if (totalMenuInMenusByGroup() >= 10) {\r\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\r\n <sd-input size=\"sm\" placeholder=\"T\u00ECm ki\u1EBFm\" [model]=\"searchText()\" (sdChange)=\"onFilterSearchText($event)\">\r\n <ng-template sdSuffixDef>\r\n @if (searchText()) {\r\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\r\n } @else {\r\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\r\n }\r\n </ng-template>\r\n </sd-input>\r\n </div>\r\n }\r\n <div class=\"c-menu-tree-container\">\r\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\r\n <li\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\r\n [ngStyle]=\"{\r\n backgroundColor: (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [ngStyle]=\"{\r\n color: (currentPath() | menuFocus: node) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\r\n }\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n </div>\r\n </li>\r\n </mat-nested-tree-node>\r\n\r\n <mat-nested-tree-node\r\n *matTreeNodeDef=\"let node; when: hasChild\"\r\n aria-hidden=\"true\"\r\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\r\n <li>\r\n <div\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\r\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\r\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n <mat-icon class=\"c-menu-node-description-icon-expand\">\r\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n </mat-tree>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"c-footer\">\r\n <lib-layout-user\r\n [userInfo]=\"_userInfo\"\r\n [isMobileOrTablet]=\"isMobileOrTablet\"\r\n (menuOpened)=\"onUserMenuOpened()\"\r\n (menuClosed)=\"onUserMenuClosed()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (toggleMenuLock)=\"toggleMenuLock($event)\">\r\n </lib-layout-user>\r\n </div>\r\n\r\n <div class=\"c-vertical\"></div>\r\n </div>\r\n}", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:cover}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{text-align:left;background-color:transparent;border:none;font-size:20px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"], dependencies: [{ kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i3$1.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i3$1.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i3$1.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i3$1.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "ngmodule", type: MatInputModule }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }] });
728
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar) {\r\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\r\n <div class=\"c-header\">\r\n @if (_sidebar.logoUrl) {\r\n <div class=\"c-logo\">\r\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\r\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\r\n </a>\r\n </div>\r\n }\r\n <div class=\"c-title-menu-group\">\r\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"c-body\">\r\n <div class=\"c-menu\">\r\n <div class=\"c-menu-group\">\r\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\r\n <button\r\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\r\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\r\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\r\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\r\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\r\n [matTooltipPosition]=\"'right'\"\r\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\r\n @if (nodeMenuGroup.iconUrl) {\r\n <span\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\r\n </span>\r\n } @else {\r\n <mat-icon\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n {{ nodeMenuGroup.icon || 'widgets' }}\r\n </mat-icon>\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"c-menu-tree\">\r\n @if (totalMenuInMenusByGroup() >= 10) {\r\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\r\n <sd-input size=\"sm\" placeholder=\"T\u00ECm ki\u1EBFm\" [model]=\"searchText()\" (sdChange)=\"onFilterSearchText($event)\">\r\n <ng-template sdSuffixDef>\r\n @if (searchText()) {\r\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\r\n } @else {\r\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\r\n }\r\n </ng-template>\r\n </sd-input>\r\n </div>\r\n }\r\n <div class=\"c-menu-tree-container\">\r\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\r\n <li\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\r\n [ngStyle]=\"{\r\n backgroundColor: (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [ngStyle]=\"{\r\n color: (currentPath() | menuFocus: node) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\r\n }\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n </div>\r\n </li>\r\n </mat-nested-tree-node>\r\n\r\n <mat-nested-tree-node\r\n *matTreeNodeDef=\"let node; when: hasChild\"\r\n aria-hidden=\"true\"\r\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\r\n <li>\r\n <div\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\r\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\r\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n <mat-icon class=\"c-menu-node-description-icon-expand\">\r\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n </mat-tree>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"c-footer\">\r\n <lib-layout-user\r\n [userInfo]=\"_userInfo\"\r\n [isMobileOrTablet]=\"isMobileOrTablet\"\r\n (menuOpened)=\"onUserMenuOpened()\"\r\n (menuClosed)=\"onUserMenuClosed()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (toggleMenuLock)=\"toggleMenuLock($event)\">\r\n </lib-layout-user>\r\n </div>\r\n\r\n <div class=\"c-vertical\"></div>\r\n </div>\r\n}", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:cover}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{text-align:left;background-color:transparent;border:none;font-size:20px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"], dependencies: [{ kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i3$1.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i3$1.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i3$1.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i3$1.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "ngmodule", type: MatInputModule }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent$1, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }] });
729
729
  }
730
730
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarComponent, decorators: [{
731
731
  type: Component,
@@ -742,7 +742,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
742
742
  MatTooltipModule,
743
743
  HighlightSearchPipe,
744
744
  SdSuffixDefDirective,
745
- LayoutUserComponent,
745
+ LayoutUserComponent$1,
746
746
  ], template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar) {\r\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\r\n <div class=\"c-header\">\r\n @if (_sidebar.logoUrl) {\r\n <div class=\"c-logo\">\r\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\r\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\r\n </a>\r\n </div>\r\n }\r\n <div class=\"c-title-menu-group\">\r\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"c-body\">\r\n <div class=\"c-menu\">\r\n <div class=\"c-menu-group\">\r\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\r\n <button\r\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\r\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\r\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\r\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\r\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\r\n [matTooltipPosition]=\"'right'\"\r\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\r\n @if (nodeMenuGroup.iconUrl) {\r\n <span\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\r\n </span>\r\n } @else {\r\n <mat-icon\r\n class=\"c-menu-group-icon\"\r\n [ngStyle]=\"{\r\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\r\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n {{ nodeMenuGroup.icon || 'widgets' }}\r\n </mat-icon>\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"c-menu-tree\">\r\n @if (totalMenuInMenusByGroup() >= 10) {\r\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\r\n <sd-input size=\"sm\" placeholder=\"T\u00ECm ki\u1EBFm\" [model]=\"searchText()\" (sdChange)=\"onFilterSearchText($event)\">\r\n <ng-template sdSuffixDef>\r\n @if (searchText()) {\r\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\r\n } @else {\r\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\r\n }\r\n </ng-template>\r\n </sd-input>\r\n </div>\r\n }\r\n <div class=\"c-menu-tree-container\">\r\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\r\n <li\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\r\n [ngStyle]=\"{\r\n backgroundColor: (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\r\n }\">\r\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [ngStyle]=\"{\r\n color: (currentPath() | menuFocus: node) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\r\n }\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n </div>\r\n </li>\r\n </mat-nested-tree-node>\r\n\r\n <mat-nested-tree-node\r\n *matTreeNodeDef=\"let node; when: hasChild\"\r\n aria-hidden=\"true\"\r\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\r\n <li>\r\n <div\r\n class=\"c-menu-node\"\r\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\r\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\r\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\r\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\r\n <div\r\n class=\"c-menu-node-description-content\"\r\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\r\n <mat-icon class=\"c-menu-node-description-icon-expand\">\r\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n </mat-tree>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"c-footer\">\r\n <lib-layout-user\r\n [userInfo]=\"_userInfo\"\r\n [isMobileOrTablet]=\"isMobileOrTablet\"\r\n (menuOpened)=\"onUserMenuOpened()\"\r\n (menuClosed)=\"onUserMenuClosed()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (toggleMenuLock)=\"toggleMenuLock($event)\">\r\n </lib-layout-user>\r\n </div>\r\n\r\n <div class=\"c-vertical\"></div>\r\n </div>\r\n}", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:cover}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{text-align:left;background-color:transparent;border:none;font-size:20px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"] }]
747
747
  }], ctorParameters: () => [] });
748
748
 
@@ -866,30 +866,283 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
866
866
  args: [{ selector: 'sidebar-v1', imports: [MatSidenavModule, CommonModule, SidebarComponent], standalone: true, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\r\n <mat-sidenav\r\n #sidenav\r\n [opened]=\"isShowSidebar()\"\r\n (openedChange)=\"isShowSidebar.set($event)\"\r\n class=\"c-layout-sidebar\"\r\n (click)=\"openSidebar()\"\r\n (mouseleave)=\"onMouseleaveSideBar()\"\r\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\r\n [fixedInViewport]=\"isMobileOrTablet()\">\r\n <sidebar\r\n [menus]=\"menus()\"\r\n [userInfo]=\"userInfo()\"\r\n [sidebar]=\"sidebar()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (showSideBar)=\"onToggle($event)\"\r\n (expandSideBar)=\"onExpandSideBar()\"\r\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\r\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\r\n </sidebar>\r\n </mat-sidenav>\r\n\r\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\r\n <mat-drawer-container class=\"c-mat-drawer-container\">\r\n <mat-drawer-content>\r\n <ng-content></ng-content>\r\n </mat-drawer-content>\r\n </mat-drawer-container>\r\n </mat-sidenav-content>\r\n</mat-sidenav-container>", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:60px;height:100vh!important;transform:none!important;overflow:hidden!important;visibility:visible!important;transition:width .15s!important;box-shadow:0 0 6px #0003!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar .mat-drawer-inner-container{position:relative;overflow:visible;display:block!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar.mat-drawer-opened{width:290px;transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:60px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:290px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}\n"] }]
867
867
  }], ctorParameters: () => [] });
868
868
 
869
+ class LayoutUserComponent {
870
+ // ==========================================
871
+ // INJECT SERVICES
872
+ // ==========================================
873
+ #layoutConfiguration = inject(SD_LAYOUT_CONFIGURATION);
874
+ // ==========================================
875
+ // SIGNAL INPUTS & OUTPUTS
876
+ // ==========================================
877
+ isMobileOrTablet = input(false);
878
+ isMenuLock = input(false);
879
+ isShowSidebar = input(false);
880
+ userInfo = input.required();
881
+ menuClosed = output();
882
+ menuOpened = output();
883
+ toggleMenuLock = output();
884
+ // Config actions
885
+ singoutLayoutConfig = this.#layoutConfiguration.signout;
886
+ changePasswordLayoutConfig = this.#layoutConfiguration?.changePassword;
887
+ // Accordion state for mobile inline expand
888
+ isExpanded = signal(false);
889
+ // ==========================================
890
+ // EVENT HANDLERS
891
+ // ==========================================
892
+ onMenuOpened = () => {
893
+ this.menuOpened.emit();
894
+ };
895
+ onMenuClosed = () => {
896
+ this.menuClosed.emit();
897
+ };
898
+ keepOpenWhenClickInsideMenu = (event) => {
899
+ event.stopPropagation();
900
+ };
901
+ toggleExpanded = () => {
902
+ this.isExpanded.update(v => !v);
903
+ if (this.isExpanded()) {
904
+ this.menuOpened.emit();
905
+ }
906
+ else {
907
+ this.menuClosed.emit();
908
+ }
909
+ };
910
+ logout = () => {
911
+ this.singoutLayoutConfig();
912
+ };
913
+ changePassword = () => {
914
+ this.changePasswordLayoutConfig?.();
915
+ };
916
+ onToggleMenuLock = (event) => {
917
+ this.toggleMenuLock.emit(event);
918
+ };
919
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
920
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\r\n\r\n@if (isMobileOrTablet()) {\r\n <!-- Mobile: accordion inline expand -->\r\n <div class=\"m-user-card\">\r\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\r\n <div class=\"m-user-info\">\r\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\r\n @if (_userInfo?.email) {\r\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\r\n }\r\n </div>\r\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\r\n keyboard_arrow_down\r\n </mat-icon>\r\n </button>\r\n\r\n @if (isExpanded()) {\r\n <div class=\"m-user-body\">\r\n @if (changePasswordLayoutConfig) {\r\n <button class=\"m-user-action\" (click)=\"changePassword()\">\r\n <mat-icon>lock_outline</mat-icon>\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n }\r\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\r\n <mat-icon>logout</mat-icon>\r\n <span>\u0110\u0103ng xu\u1EA5t</span>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n} @else {\r\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\r\n <div class=\"c-layout-user-wrapper\">\r\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\r\n </div>\r\n\r\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\r\n <mat-icon style=\"color: #8c8c8c\">\r\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n}\r\n\r\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\r\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\r\n <div class=\"c-user-info-wrapper\">\r\n <div class=\"c-user-avatar\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\r\n </div>\r\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\r\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\r\n </div>\r\n\r\n @if (changePasswordLayoutConfig) {\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-account-options\" (click)=\"changePassword()\">\r\n <img alt=\"lock\" />\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">\u0110\u0103ng xu\u1EA5t</button>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n", styles: ["@media(min-width:1024px){::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}}.m-user-card{width:100%}.m-user-row{display:flex;align-items:center;gap:12px;width:100%;padding:0;border:none;background:transparent;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}.m-user-info{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden}.m-user-name{font-size:15px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-user-email{font-size:13px;color:#8c8c8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-expand-icon{color:#8c8c8c;flex-shrink:0;transition:transform .2s ease}.m-expand-icon--open{transform:rotate(180deg)}.m-user-body{margin-top:8px;border-top:1px solid #EBEBEB;padding-top:4px;display:flex;flex-direction:column}.m-user-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 4px;border:none;background:transparent;cursor:pointer;font-size:15px;color:#1f1f1f;-webkit-tap-highlight-color:transparent}.m-user-action mat-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-user-action:active{background-color:#f5f5f5}.m-user-action--logout{color:#e53935}.m-user-action--logout mat-icon{color:#e53935}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options img{scale:.875;content:url('data:image/svg+xml,<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">%0D%0A <path%0D%0A d=\"M12 5.66667H11.3333V4.33333C11.3333 2.49333 9.83996 1 7.99996 1C6.15996 1 4.66663 2.49333 4.66663 4.33333V5.66667H3.99996C3.26663 5.66667 2.66663 6.26667 2.66663 7V13.6667C2.66663 14.4 3.26663 15 3.99996 15H12C12.7333 15 13.3333 14.4 13.3333 13.6667V7C13.3333 6.26667 12.7333 5.66667 12 5.66667ZM5.99996 4.33333C5.99996 3.22667 6.89329 2.33333 7.99996 2.33333C9.10663 2.33333 9.99996 3.22667 9.99996 4.33333V5.66667H5.99996V4.33333ZM12 13.6667H3.99996V7H12V13.6667ZM7.99996 11.6667C8.73329 11.6667 9.33329 11.0667 9.33329 10.3333C9.33329 9.6 8.73329 9 7.99996 9C7.26663 9 6.66663 9.6 6.66663 10.3333C6.66663 11.0667 7.26663 11.6667 7.99996 11.6667Z\"%0D%0A fill=\"%23757575\" />%0D%0A</svg>')}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }] });
921
+ }
922
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutUserComponent, decorators: [{
923
+ type: Component,
924
+ args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar], standalone: true, template: "@let _userInfo = userInfo();\r\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\r\n\r\n@if (isMobileOrTablet()) {\r\n <!-- Mobile: accordion inline expand -->\r\n <div class=\"m-user-card\">\r\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\r\n <div class=\"m-user-info\">\r\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\r\n @if (_userInfo?.email) {\r\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\r\n }\r\n </div>\r\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\r\n keyboard_arrow_down\r\n </mat-icon>\r\n </button>\r\n\r\n @if (isExpanded()) {\r\n <div class=\"m-user-body\">\r\n @if (changePasswordLayoutConfig) {\r\n <button class=\"m-user-action\" (click)=\"changePassword()\">\r\n <mat-icon>lock_outline</mat-icon>\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n }\r\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\r\n <mat-icon>logout</mat-icon>\r\n <span>\u0110\u0103ng xu\u1EA5t</span>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n} @else {\r\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\r\n <div class=\"c-layout-user-wrapper\">\r\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\r\n </div>\r\n\r\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\r\n <mat-icon style=\"color: #8c8c8c\">\r\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n}\r\n\r\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\r\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\r\n <div class=\"c-user-info-wrapper\">\r\n <div class=\"c-user-avatar\">\r\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\r\n </div>\r\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\r\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\r\n </div>\r\n\r\n @if (changePasswordLayoutConfig) {\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-account-options\" (click)=\"changePassword()\">\r\n <img alt=\"lock\" />\r\n <span>\u0110\u1ED5i m\u1EADt kh\u1EA9u</span>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"c-sign-button-wrapper\">\r\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">\u0110\u0103ng xu\u1EA5t</button>\r\n </div>\r\n </div>\r\n</mat-menu>\r\n", styles: ["@media(min-width:1024px){::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}}.m-user-card{width:100%}.m-user-row{display:flex;align-items:center;gap:12px;width:100%;padding:0;border:none;background:transparent;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}.m-user-info{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden}.m-user-name{font-size:15px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-user-email{font-size:13px;color:#8c8c8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-expand-icon{color:#8c8c8c;flex-shrink:0;transition:transform .2s ease}.m-expand-icon--open{transform:rotate(180deg)}.m-user-body{margin-top:8px;border-top:1px solid #EBEBEB;padding-top:4px;display:flex;flex-direction:column}.m-user-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 4px;border:none;background:transparent;cursor:pointer;font-size:15px;color:#1f1f1f;-webkit-tap-highlight-color:transparent}.m-user-action mat-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-user-action:active{background-color:#f5f5f5}.m-user-action--logout{color:#e53935}.m-user-action--logout mat-icon{color:#e53935}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options img{scale:.875;content:url('data:image/svg+xml,<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">%0D%0A <path%0D%0A d=\"M12 5.66667H11.3333V4.33333C11.3333 2.49333 9.83996 1 7.99996 1C6.15996 1 4.66663 2.49333 4.66663 4.33333V5.66667H3.99996C3.26663 5.66667 2.66663 6.26667 2.66663 7V13.6667C2.66663 14.4 3.26663 15 3.99996 15H12C12.7333 15 13.3333 14.4 13.3333 13.6667V7C13.3333 6.26667 12.7333 5.66667 12 5.66667ZM5.99996 4.33333C5.99996 3.22667 6.89329 2.33333 7.99996 2.33333C9.10663 2.33333 9.99996 3.22667 9.99996 4.33333V5.66667H5.99996V4.33333ZM12 13.6667H3.99996V7H12V13.6667ZM7.99996 11.6667C8.73329 11.6667 9.33329 11.0667 9.33329 10.3333C9.33329 9.6 8.73329 9 7.99996 9C7.26663 9 6.66663 9.6 6.66663 10.3333C6.66663 11.0667 7.26663 11.6667 7.99996 11.6667Z\"%0D%0A fill=\"%23757575\" />%0D%0A</svg>')}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"] }]
925
+ }] });
926
+
927
+ class SidebarMobileOverlayComponent {
928
+ #router = inject(Router);
929
+ #destroyRef = inject(DestroyRef);
930
+ #layoutStorageService = inject(SdLayoutStorageService);
931
+ // ==========================================
932
+ // INPUTS & OUTPUTS
933
+ // ==========================================
934
+ isShowSidebar = input(false);
935
+ menus = input.required();
936
+ userInfo = input.required();
937
+ sidebar = input.required();
938
+ // showSideBar(null) = đóng sidebar (tương thích với onToggle của main component)
939
+ showSideBar = output();
940
+ expandSideBar = output();
941
+ popupUserMenuOpened = output();
942
+ popupUserMenuClosed = output();
943
+ titleMenuGroupChanged = output();
944
+ // ==========================================
945
+ // STATE SIGNALS
946
+ // ==========================================
947
+ titleMenuGroup = signal('');
948
+ currentPath = signal(window.location.pathname);
949
+ // Lưu danh sách ID các menu group đang được mở
950
+ expandedMobileGroups = signal(new Set());
951
+ constructor() {
952
+ // Bind title khi menus thay đổi
953
+ effect(() => {
954
+ const currentMenus = this.menus();
955
+ untracked(() => {
956
+ const lastActiveMenuGroupId = this.#layoutStorageService.lastActiveMenuGroupId.get();
957
+ if (!lastActiveMenuGroupId) {
958
+ this.#layoutStorageService.lastActiveMenuGroupId.set(currentMenus?.[0]?.id ?? '');
959
+ }
960
+ this.#bindingMenuGroupByCurrentPath(currentMenus);
961
+ });
962
+ });
963
+ // Bind title khi điều hướng
964
+ this.#router.events.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(event => {
965
+ if (event instanceof NavigationEnd) {
966
+ if (this.currentPath() !== window.location.pathname) {
967
+ this.currentPath.set(window.location.pathname);
968
+ this.#bindingMenuGroupByCurrentPath(this.menus());
969
+ }
970
+ }
971
+ });
972
+ }
973
+ // ==========================================
974
+ // EVENT HANDLERS
975
+ // ==========================================
976
+ toggleMobileGroup(groupId) {
977
+ if (!groupId)
978
+ return;
979
+ this.expandedMobileGroups.update(groups => {
980
+ const newGroups = new Set(groups);
981
+ if (newGroups.has(groupId)) {
982
+ newGroups.delete(groupId);
983
+ }
984
+ else {
985
+ newGroups.add(groupId);
986
+ }
987
+ return newGroups;
988
+ });
989
+ }
990
+ isExpanded(groupId) {
991
+ if (!groupId)
992
+ return false;
993
+ return this.expandedMobileGroups().has(groupId);
994
+ }
995
+ navigate(args) {
996
+ const { path, queryParams } = args;
997
+ if (!path)
998
+ return;
999
+ if (path.includes('http')) {
1000
+ window.open(path);
1001
+ return;
1002
+ }
1003
+ this.#router.navigate([path.split('?')[0]], {
1004
+ queryParams: queryParams ?? {},
1005
+ state: { switchTab: true },
1006
+ });
1007
+ // Sau khi điều hướng trên mobile, tự động đóng sidebar
1008
+ this.onClose();
1009
+ }
1010
+ onClose() {
1011
+ this.showSideBar.emit(null);
1012
+ }
1013
+ // Kiểm tra menu có children (là SdLayoutChildrenMenu)
1014
+ hasChildren(menu) {
1015
+ return 'children' in menu && !!menu.children?.length;
1016
+ }
1017
+ // Lấy danh sách children an toàn (type-safe)
1018
+ getChildren(menu) {
1019
+ return 'children' in menu ? (menu.children ?? []) : [];
1020
+ }
1021
+ // Lấy path an toàn từ leaf menu (SdLayoutRootMenu)
1022
+ getPath(menu) {
1023
+ return 'path' in menu ? menu.path : undefined;
1024
+ }
1025
+ // Lấy queryParams an toàn từ leaf menu
1026
+ getQueryParams(menu) {
1027
+ return ('queryParams' in menu ? menu.queryParams : undefined) ?? {};
1028
+ }
1029
+ onUserMenuOpened = () => this.popupUserMenuOpened.emit();
1030
+ onUserMenuClosed = () => this.popupUserMenuClosed.emit();
1031
+ // ==========================================
1032
+ // PRIVATE LOGIC
1033
+ // ==========================================
1034
+ #bindingMenuGroupByCurrentPath = (menus) => {
1035
+ let menuGroupByPath = this.#getMenuGroupByCurrentPath(menus);
1036
+ if (!menuGroupByPath?.length) {
1037
+ const lastActiveId = this.#layoutStorageService.lastActiveMenuGroupId.get() || '';
1038
+ menuGroupByPath = menus?.filter(menu => menu?.id === lastActiveId) || [];
1039
+ }
1040
+ if (menuGroupByPath?.length) {
1041
+ const matchedGroup = menuGroupByPath[0];
1042
+ this.#layoutStorageService.lastActiveMenuGroupId.set(matchedGroup?.id || '');
1043
+ const title = matchedGroup?.tooltipTitle || matchedGroup?.title;
1044
+ this.titleMenuGroup.set(title);
1045
+ this.titleMenuGroupChanged.emit(title);
1046
+ }
1047
+ else {
1048
+ this.titleMenuGroup.set('');
1049
+ this.titleMenuGroupChanged.emit('');
1050
+ }
1051
+ };
1052
+ #getMenuGroupByCurrentPath = (menus, menuGroup) => {
1053
+ for (const menu of menus) {
1054
+ if ('path' in menu && this.#isMenuPathMatchByCurrentPath(menu.path)) {
1055
+ return [menuGroup ?? menu];
1056
+ }
1057
+ if ('children' in menu && menu.children?.length) {
1058
+ const result = this.#getMenuGroupByCurrentPath(menu.children, menuGroup ?? menu);
1059
+ if (result?.length)
1060
+ return result;
1061
+ }
1062
+ }
1063
+ return [];
1064
+ };
1065
+ #isMenuPathMatchByCurrentPath = (path) => {
1066
+ if (!path)
1067
+ return false;
1068
+ if (this.currentPath() === path)
1069
+ return true;
1070
+ return this.#normalizePath(this.currentPath()).startsWith(this.#normalizePath(path));
1071
+ };
1072
+ #normalizePath = (p) => p.endsWith('/') ? p : p + '/';
1073
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarMobileOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1074
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SidebarMobileOverlayComponent, isStandalone: true, selector: "sd-sidebar-mobile-overlay", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { showSideBar: "showSideBar", expandSideBar: "expandSideBar", popupUserMenuOpened: "popupUserMenuOpened", popupUserMenuClosed: "popupUserMenuClosed", titleMenuGroupChanged: "titleMenuGroupChanged" }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar) {\r\n <div\r\n class=\"m-backdrop\"\r\n [class.m-backdrop--visible]=\"isShowSidebar()\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (click)=\"onClose()\"\r\n (keydown.escape)=\"onClose()\">\r\n </div>\r\n\r\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\r\n <div class=\"m-header\">\r\n <div class=\"m-title-group\">\r\n @if (_sidebar.logoUrl) {\r\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\r\n }\r\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n <button class=\"m-close-btn\" (click)=\"onClose()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"m-user-section\">\r\n <lib-layout-user\r\n [userInfo]=\"_userInfo\"\r\n [isMobileOrTablet]=\"true\"\r\n (menuOpened)=\"onUserMenuOpened()\"\r\n (menuClosed)=\"onUserMenuClosed()\">\r\n </lib-layout-user>\r\n </div>\r\n\r\n <div class=\"m-menu-list\">\r\n @for (group of menus(); track group.id) {\r\n <div class=\"m-menu-card\">\r\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\r\n <div class=\"m-card-header-left\">\r\n @if (group.iconUrl) {\r\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\r\n } @else {\r\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\r\n }\r\n <span class=\"m-group-title\">{{ group.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-expand-icon\">\r\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </button>\r\n\r\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\r\n <div class=\"m-card-body\">\r\n @for (child of getChildren(group); track child.id) {\r\n @if (hasChildren(child)) {\r\n <div class=\"m-sub-group\">\r\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\r\n <div class=\"m-item-left\">\r\n @if (child.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ child.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-expand-icon\">\r\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </button>\r\n @if (expandedMobileGroups().has(child.id ?? '')) {\r\n @for (subChild of getChildren(child); track subChild.id) {\r\n <button class=\"m-menu-item m-menu-item--indented\"\r\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\r\n <div class=\"m-item-left\">\r\n @if (subChild.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ subChild.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\r\n <div class=\"m-item-left\">\r\n @if (child.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ child.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block;position:fixed;inset:0;z-index:1000;pointer-events:none}.m-backdrop{position:absolute;inset:0;background:#0006;opacity:0;pointer-events:none;transition:opacity .3s ease;cursor:pointer;outline:none}.m-backdrop--visible{opacity:1;pointer-events:auto}.m-wrapper{display:flex;flex-direction:column;position:absolute;inset:0;background-color:#f2f2f6;padding:16px;box-sizing:border-box;overflow-y:auto;pointer-events:none;padding-top:max(16px,env(safe-area-inset-top));padding-bottom:max(16px,env(safe-area-inset-bottom));transform:translate(-100%);transition:transform .3s cubic-bezier(.4,0,.2,1)}.m-wrapper--open{transform:translate(0);pointer-events:auto}.m-wrapper .m-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px}.m-wrapper .m-header .m-title-group{display:flex;align-items:center;gap:12px}.m-wrapper .m-header .m-title-group .m-logo{width:32px;height:32px;object-fit:contain}.m-wrapper .m-header .m-title-group .m-title{font-size:18px;font-weight:600;color:#1f1f1f}.m-wrapper .m-header .m-close-btn{background:transparent;border:none;padding:0;color:#1f1f1f;display:flex;align-items:center;justify-content:center;cursor:pointer}.m-wrapper .m-header .m-close-btn mat-icon{font-size:28px;width:28px;height:28px}.m-wrapper .m-user-section{background-color:#fff;border-radius:12px;padding:12px 16px;margin-bottom:24px;box-shadow:0 1px 2px #00000005;border:1px solid #EBEBEB}.m-wrapper .m-user-section lib-layout-user{display:block;width:100%}.m-wrapper .m-menu-list{display:flex;flex-direction:column;gap:16px}.m-wrapper .m-menu-card{background-color:#fff;border-radius:12px;border:1px solid #EBEBEB;overflow:hidden}.m-wrapper .m-menu-card .m-card-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px;cursor:pointer;-webkit-user-select:none;user-select:none;border:none;background:transparent;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-header .m-card-header-left{display:flex;align-items:center;gap:16px}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-icon{font-size:24px;width:24px;height:24px;color:#1f1f1f;object-fit:contain}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-title{font-size:16px;font-weight:600;color:#1f1f1f}.m-wrapper .m-menu-card .m-card-header .m-expand-icon{color:#1f1f1f;transition:transform .2s ease}.m-wrapper .m-menu-card .m-card-body{display:flex;flex-direction:column;padding-bottom:8px}.m-wrapper .m-menu-card .m-card-body .m-menu-item{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:transparent;transition:background-color .2s;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-menu-item:active{background-color:#f5f5f5}.m-wrapper .m-menu-card .m-card-body .m-menu-item--indented{padding-left:48px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-title{font-size:15px;color:#333}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-nav-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-wrapper .m-menu-card .m-card-body .m-sub-group{border-top:1px solid #EBEBEB}.m-wrapper .m-menu-card .m-card-body .m-sub-group:first-child{border-top:none}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:#fafafa;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header:active{background-color:#f0f0f0}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-title{font-size:15px;font-weight:500;color:#333}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-expand-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: LayoutUserComponent, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }] });
1075
+ }
1076
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarMobileOverlayComponent, decorators: [{
1077
+ type: Component,
1078
+ args: [{ selector: 'sd-sidebar-mobile-overlay', standalone: true, imports: [
1079
+ CommonModule,
1080
+ RouterModule,
1081
+ MatIconModule,
1082
+ LayoutUserComponent,
1083
+ ], template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar) {\r\n <div\r\n class=\"m-backdrop\"\r\n [class.m-backdrop--visible]=\"isShowSidebar()\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (click)=\"onClose()\"\r\n (keydown.escape)=\"onClose()\">\r\n </div>\r\n\r\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\r\n <div class=\"m-header\">\r\n <div class=\"m-title-group\">\r\n @if (_sidebar.logoUrl) {\r\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\r\n }\r\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n <button class=\"m-close-btn\" (click)=\"onClose()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"m-user-section\">\r\n <lib-layout-user\r\n [userInfo]=\"_userInfo\"\r\n [isMobileOrTablet]=\"true\"\r\n (menuOpened)=\"onUserMenuOpened()\"\r\n (menuClosed)=\"onUserMenuClosed()\">\r\n </lib-layout-user>\r\n </div>\r\n\r\n <div class=\"m-menu-list\">\r\n @for (group of menus(); track group.id) {\r\n <div class=\"m-menu-card\">\r\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\r\n <div class=\"m-card-header-left\">\r\n @if (group.iconUrl) {\r\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\r\n } @else {\r\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\r\n }\r\n <span class=\"m-group-title\">{{ group.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-expand-icon\">\r\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </button>\r\n\r\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\r\n <div class=\"m-card-body\">\r\n @for (child of getChildren(group); track child.id) {\r\n @if (hasChildren(child)) {\r\n <div class=\"m-sub-group\">\r\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\r\n <div class=\"m-item-left\">\r\n @if (child.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ child.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-expand-icon\">\r\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </button>\r\n @if (expandedMobileGroups().has(child.id ?? '')) {\r\n @for (subChild of getChildren(child); track subChild.id) {\r\n <button class=\"m-menu-item m-menu-item--indented\"\r\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\r\n <div class=\"m-item-left\">\r\n @if (subChild.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ subChild.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\r\n <div class=\"m-item-left\">\r\n @if (child.iconUrl) {\r\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\r\n } @else {\r\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\r\n }\r\n <span class=\"m-item-title\">{{ child.title }}</span>\r\n </div>\r\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block;position:fixed;inset:0;z-index:1000;pointer-events:none}.m-backdrop{position:absolute;inset:0;background:#0006;opacity:0;pointer-events:none;transition:opacity .3s ease;cursor:pointer;outline:none}.m-backdrop--visible{opacity:1;pointer-events:auto}.m-wrapper{display:flex;flex-direction:column;position:absolute;inset:0;background-color:#f2f2f6;padding:16px;box-sizing:border-box;overflow-y:auto;pointer-events:none;padding-top:max(16px,env(safe-area-inset-top));padding-bottom:max(16px,env(safe-area-inset-bottom));transform:translate(-100%);transition:transform .3s cubic-bezier(.4,0,.2,1)}.m-wrapper--open{transform:translate(0);pointer-events:auto}.m-wrapper .m-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px}.m-wrapper .m-header .m-title-group{display:flex;align-items:center;gap:12px}.m-wrapper .m-header .m-title-group .m-logo{width:32px;height:32px;object-fit:contain}.m-wrapper .m-header .m-title-group .m-title{font-size:18px;font-weight:600;color:#1f1f1f}.m-wrapper .m-header .m-close-btn{background:transparent;border:none;padding:0;color:#1f1f1f;display:flex;align-items:center;justify-content:center;cursor:pointer}.m-wrapper .m-header .m-close-btn mat-icon{font-size:28px;width:28px;height:28px}.m-wrapper .m-user-section{background-color:#fff;border-radius:12px;padding:12px 16px;margin-bottom:24px;box-shadow:0 1px 2px #00000005;border:1px solid #EBEBEB}.m-wrapper .m-user-section lib-layout-user{display:block;width:100%}.m-wrapper .m-menu-list{display:flex;flex-direction:column;gap:16px}.m-wrapper .m-menu-card{background-color:#fff;border-radius:12px;border:1px solid #EBEBEB;overflow:hidden}.m-wrapper .m-menu-card .m-card-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px;cursor:pointer;-webkit-user-select:none;user-select:none;border:none;background:transparent;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-header .m-card-header-left{display:flex;align-items:center;gap:16px}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-icon{font-size:24px;width:24px;height:24px;color:#1f1f1f;object-fit:contain}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-title{font-size:16px;font-weight:600;color:#1f1f1f}.m-wrapper .m-menu-card .m-card-header .m-expand-icon{color:#1f1f1f;transition:transform .2s ease}.m-wrapper .m-menu-card .m-card-body{display:flex;flex-direction:column;padding-bottom:8px}.m-wrapper .m-menu-card .m-card-body .m-menu-item{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:transparent;transition:background-color .2s;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-menu-item:active{background-color:#f5f5f5}.m-wrapper .m-menu-card .m-card-body .m-menu-item--indented{padding-left:48px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-title{font-size:15px;color:#333}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-nav-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-wrapper .m-menu-card .m-card-body .m-sub-group{border-top:1px solid #EBEBEB}.m-wrapper .m-menu-card .m-card-body .m-sub-group:first-child{border-top:none}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:#fafafa;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header:active{background-color:#f0f0f0}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-title{font-size:15px;font-weight:500;color:#333}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-expand-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}\n"] }]
1084
+ }], ctorParameters: () => [] });
1085
+
1086
+ class SidebarMobileV1Component {
1087
+ #layoutStorageService = inject(SdLayoutStorageService);
1088
+ menus = input([]);
1089
+ userInfo = input.required();
1090
+ sidebar = input.required();
1091
+ // Sidebar luôn bắt đầu đóng trên mobile
1092
+ isShowSidebar = signal(false);
1093
+ titleMenuGroup = signal('');
1094
+ constructor() {
1095
+ effect(() => {
1096
+ const isShow = this.isShowSidebar();
1097
+ untracked(() => {
1098
+ this.#layoutStorageService.isShowSidebar.set(isShow);
1099
+ });
1100
+ });
1101
+ }
1102
+ openSidebar = () => {
1103
+ this.isShowSidebar.set(true);
1104
+ };
1105
+ onToggle = (_data) => {
1106
+ this.isShowSidebar.set(false);
1107
+ };
1108
+ onPopupOfSideBarOpened = () => { };
1109
+ onPopupOfSideBarClosed = () => { };
1110
+ onExpandSideBar = () => { };
1111
+ onMouseleaveSideBar = () => { };
1112
+ onTitleMenuGroupChanged = (title) => {
1113
+ this.titleMenuGroup.set(title);
1114
+ };
1115
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarMobileV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
1116
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SidebarMobileV1Component, isStandalone: true, selector: "sidebar-mobile-v1", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"c-mobile-layout\">\r\n <div class=\"c-mobile-topbar\">\r\n <div class=\"c-topbar-brand\">\r\n @if (sidebar().logoUrl) {\r\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\r\n }\r\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\r\n <mat-icon>menu</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"c-mobile-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <sd-sidebar-mobile-overlay\r\n [menus]=\"menus()\"\r\n [userInfo]=\"userInfo()\"\r\n [sidebar]=\"sidebar()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (showSideBar)=\"onToggle($event)\"\r\n (expandSideBar)=\"onExpandSideBar()\"\r\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\r\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\r\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\r\n </sd-sidebar-mobile-overlay>\r\n</div>\r\n", styles: [":host{display:block;height:100vh;position:relative;overflow:hidden}.c-mobile-layout{display:flex;flex-direction:column;height:100%;position:relative}.c-mobile-topbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background-color:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}.c-mobile-topbar .c-topbar-brand{display:flex;align-items:center;gap:10px;overflow:hidden}.c-mobile-topbar .c-topbar-brand .c-topbar-logo{width:28px;height:28px;object-fit:contain;flex-shrink:0}.c-mobile-topbar .c-topbar-brand .c-topbar-title{font-size:16px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c-mobile-topbar .c-hamburger-btn{display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;color:#333;flex-shrink:0}.c-mobile-topbar .c-hamburger-btn:hover{background-color:#0000000f}.c-mobile-content{flex:1;overflow-y:auto}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarMobileOverlayComponent, selector: "sd-sidebar-mobile-overlay", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["showSideBar", "expandSideBar", "popupUserMenuOpened", "popupUserMenuClosed", "titleMenuGroupChanged"] }] });
1117
+ }
1118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SidebarMobileV1Component, decorators: [{
1119
+ type: Component,
1120
+ args: [{ selector: 'sidebar-mobile-v1', imports: [MatIconModule, CommonModule, SidebarMobileOverlayComponent], standalone: true, template: "<div class=\"c-mobile-layout\">\r\n <div class=\"c-mobile-topbar\">\r\n <div class=\"c-topbar-brand\">\r\n @if (sidebar().logoUrl) {\r\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\r\n }\r\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\r\n </div>\r\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\r\n <mat-icon>menu</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"c-mobile-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <sd-sidebar-mobile-overlay\r\n [menus]=\"menus()\"\r\n [userInfo]=\"userInfo()\"\r\n [sidebar]=\"sidebar()\"\r\n [isShowSidebar]=\"isShowSidebar()\"\r\n (showSideBar)=\"onToggle($event)\"\r\n (expandSideBar)=\"onExpandSideBar()\"\r\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\r\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\r\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\r\n </sd-sidebar-mobile-overlay>\r\n</div>\r\n", styles: [":host{display:block;height:100vh;position:relative;overflow:hidden}.c-mobile-layout{display:flex;flex-direction:column;height:100%;position:relative}.c-mobile-topbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background-color:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}.c-mobile-topbar .c-topbar-brand{display:flex;align-items:center;gap:10px;overflow:hidden}.c-mobile-topbar .c-topbar-brand .c-topbar-logo{width:28px;height:28px;object-fit:contain;flex-shrink:0}.c-mobile-topbar .c-topbar-brand .c-topbar-title{font-size:16px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c-mobile-topbar .c-hamburger-btn{display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;color:#333;flex-shrink:0}.c-mobile-topbar .c-hamburger-btn:hover{background-color:#0000000f}.c-mobile-content{flex:1;overflow-y:auto}\n"] }]
1121
+ }], ctorParameters: () => [] });
1122
+
869
1123
  class SdLayoutComponent {
870
1124
  // ==========================================
871
1125
  // INJECT SERVICES
872
1126
  // ==========================================
873
1127
  #menuPipe = inject(MenuPipe);
874
- #layoutService = inject(SdLayoutService); // Inject LayoutService
1128
+ #layoutService = inject(SdLayoutService);
875
1129
  // ==========================================
876
1130
  // SIGNAL INPUTS
877
1131
  // ==========================================
878
1132
  menusInput = input([], { alias: 'menus' });
879
- // Tự động format qua MenuPipe mỗi khi menusInput từ component cha thay đổi
880
1133
  menus = computed(() => this.#menuPipe.transform(this.menusInput() || []));
881
1134
  // ==========================================
882
- // CONSUME SHARED STATE (Tuỳ chọn)
1135
+ // CONSUME SHARED STATE
883
1136
  // ==========================================
884
- // Bạn có thể gán biến ngắn gọn để xài trong HTML (ví dụ: userInfo() thay vì layoutService.userInfo())
885
1137
  userInfo = this.#layoutService.userInfo;
886
1138
  sidebar = this.#layoutService.sidebar;
1139
+ isMobileOrTablet = signal(SdUtilities.isMobile());
887
1140
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
888
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdLayoutComponent, isStandalone: true, selector: "sd-layout", inputs: { menusInput: { classPropertyName: "menusInput", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar?.version === 1) {\r\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-content></ng-content>\r\n </sidebar-v1>\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: SidebarV1Component, selector: "sidebar-v1", inputs: ["menus", "userInfo", "sidebar"] }] });
1141
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdLayoutComponent, isStandalone: true, selector: "sd-layout", inputs: { menusInput: { classPropertyName: "menusInput", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-template #projectedContent>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar?.version === 1) {\r\n @if (!isMobileOrTablet()) {\r\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\r\n </sidebar-v1>\r\n } @else {\r\n <sidebar-mobile-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\r\n </sidebar-mobile-v1>\r\n }\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: SidebarV1Component, selector: "sidebar-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "component", type: SidebarMobileV1Component, selector: "sidebar-mobile-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
889
1142
  }
890
1143
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdLayoutComponent, decorators: [{
891
1144
  type: Component,
892
- args: [{ selector: 'sd-layout', imports: [SidebarV1Component], standalone: true, template: "@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar?.version === 1) {\r\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-content></ng-content>\r\n </sidebar-v1>\r\n}\r\n" }]
1145
+ args: [{ selector: 'sd-layout', imports: [SidebarV1Component, SidebarMobileV1Component, NgTemplateOutlet], standalone: true, template: "<ng-template #projectedContent>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n@let _userInfo = userInfo();\r\n@let _sidebar = sidebar();\r\n\r\n@if (_userInfo && _sidebar?.version === 1) {\r\n @if (!isMobileOrTablet()) {\r\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\r\n </sidebar-v1>\r\n } @else {\r\n <sidebar-mobile-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\r\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\r\n </sidebar-mobile-v1>\r\n }\r\n}\r\n" }]
893
1146
  }] });
894
1147
 
895
1148
  // End
@@ -1188,5 +1441,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
1188
1441
  * Generated bundle index. Do not edit.
1189
1442
  */
1190
1443
 
1191
- export { ForbiddenModule, HomeModule, NotFoundModule, SD_LAYOUT_CONFIGURATION, SdLayoutComponent, SdLayoutModule, SdLayoutService, SdLayoutStorageService, SdPageComponent };
1444
+ export { ForbiddenModule, HomeModule, NotFoundModule, SD_LAYOUT_CONFIGURATION, SdLayoutComponent, SdLayoutModule, SdLayoutService, SdLayoutStorageService, SdPageComponent, SidebarMobileOverlayComponent, SidebarMobileV1Component };
1192
1445
  //# sourceMappingURL=sd-angular-core-modules-layout.mjs.map