@sd-angular/core 19.0.32 → 19.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/scss/core/_read-state-panel.scss +57 -0
- package/components/table/src/components/selector-action/selector-action.component.d.ts +1 -0
- package/components/table/src/models/table-option-selector.model.d.ts +2 -0
- package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +10 -9
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +5 -0
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +758 -17
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs +7 -43
- package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-notify.mjs +2 -2
- package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
- package/i18n/src/en.d.ts +1 -0
- package/modules/layout/components/layout-main/layout-main.component.d.ts +1 -1
- package/modules/layout/components/sidebar-mobile-v1/components/sidebar/sidebar.component.d.ts +2 -2
- package/modules/layout/components/sidebar-mobile-v1/main.component.d.ts +2 -2
- package/modules/layout/components/sidebar-v2/components/sidebar/sidebar.component.d.ts +56 -0
- package/modules/layout/components/sidebar-v2/components/user/user.component.d.ts +22 -0
- package/modules/layout/components/sidebar-v2/main.component.d.ts +25 -0
- package/modules/layout/configurations/layout.configuration.d.ts +5 -1
- package/modules/layout/services/layout.service.d.ts +2 -2
- package/package.json +1 -1
- package/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.d.ts +0 -4
- package/services/confirm/src/lib/confirm.service.d.ts +0 -6
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, input, booleanAttribute, effect, Component, Injectable, InjectionToken, signal, Pipe, output, DestroyRef, computed, untracked, viewChild, NgModule } from '@angular/core';
|
|
3
|
-
import * as i1$
|
|
2
|
+
import { inject, ElementRef, input, booleanAttribute, effect, Component, Injectable, InjectionToken, signal, Pipe, output, DestroyRef, computed, untracked, viewChild, ChangeDetectionStrategy, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1$3 from '@angular/common';
|
|
4
4
|
import { CommonModule, NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import * as i1$6 from '@angular/router';
|
|
6
6
|
import { Router, NavigationEnd, RouterModule, ActivatedRoute } from '@angular/router';
|
|
7
7
|
import { __decorate } from 'tslib';
|
|
8
|
-
import * as
|
|
8
|
+
import * as i3 from '@angular/material/icon';
|
|
9
9
|
import { MatIconModule } from '@angular/material/icon';
|
|
10
10
|
import { SdAvatar, SdTabComponent, SdButton } from '@sd-angular/core/components';
|
|
11
11
|
import { I18nService, I18N_STORAGE_KEY, I18N_MESSAGES, TranslatePipe } from '@sd-angular/core/i18n';
|
|
@@ -13,15 +13,16 @@ import * as i1 from '@sd-angular/core/services';
|
|
|
13
13
|
import { resolveMaybeAsync } from '@sdcorejs/utils/models';
|
|
14
14
|
import { Utilities, StringUtilities, BrowserUtilities } from '@sdcorejs/utils/fns';
|
|
15
15
|
import * as i1$1 from '@sd-angular/core/modules/permission';
|
|
16
|
-
import * as i1$
|
|
16
|
+
import * as i1$4 from '@angular/material/sidenav';
|
|
17
17
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
18
18
|
import { NestedTreeControl } from '@angular/cdk/tree';
|
|
19
19
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
20
|
+
import * as i1$5 from '@angular/forms';
|
|
20
21
|
import { FormsModule } from '@angular/forms';
|
|
21
22
|
import { MatInputModule } from '@angular/material/input';
|
|
22
23
|
import * as i4 from '@angular/material/tooltip';
|
|
23
24
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
24
|
-
import * as i3 from '@angular/material/tree';
|
|
25
|
+
import * as i3$1 from '@angular/material/tree';
|
|
25
26
|
import { MatTreeNestedDataSource, MatTreeModule } from '@angular/material/tree';
|
|
26
27
|
import { SdInput, SdSuffixDefDirective } from '@sd-angular/core/forms';
|
|
27
28
|
import { SdSafeHtmlPipe } from '@sd-angular/core/pipes';
|
|
@@ -484,11 +485,11 @@ let LayoutUserComponent$1 = class LayoutUserComponent {
|
|
|
484
485
|
this.toggleMenuLock.emit(event);
|
|
485
486
|
};
|
|
486
487
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
487
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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
|
|
488
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
488
489
|
};
|
|
489
490
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LayoutUserComponent$1, decorators: [{
|
|
490
491
|
type: Component,
|
|
491
|
-
args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar, TranslatePipe], standalone: true, template: "@let
|
|
492
|
+
args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar, TranslatePipe], standalone: true, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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"] }]
|
|
492
493
|
}] });
|
|
493
494
|
|
|
494
495
|
class SidebarComponent {
|
|
@@ -1031,7 +1032,7 @@ class SidebarComponent {
|
|
|
1031
1032
|
return count;
|
|
1032
1033
|
};
|
|
1033
1034
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1034
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let _sidebar = sidebar();\n@let _isShowSidebar = isShowSidebar();\n@let _searchText = searchText();\n@let _currentPath = currentPath();\n@let _activeMenuPath = activeMenuPath();\n@let _idMenuGroupActive = idMenuGroupActive();\n@let _pinnedMenuGroup = pinnedMenuGroup();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"wrapper\"\n [style.--sidebar-accent]=\"_sidebar.brandColor || 'var(--sd-primary, #005cbb)'\"\n [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!_isShowSidebar\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && _pinnedMenuGroup.children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, _pinnedMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, _pinnedMenuGroup)\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!_isShowSidebar\" [attr.inert]=\"!_isShowSidebar ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n hideInlineError\n [placeholder]=\"'core.module.layout.sidebar.search' | translate\"\n [model]=\"_searchText\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (_searchText) {\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\"\n >cancel</mat-icon\n >\n } @else {\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n [class.is-active]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!_isShowSidebar\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #252c38)',\n }\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: _currentPath | menuFocus: node : _activeMenuPath }\">\n <li>\n <div\n class=\"c-menu-node\"\n [class.is-ancestor]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!_isShowSidebar\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div class=\"c-menu-node-description-content\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"c-menu-node-group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"_isShowSidebar\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host{display:block;height:100%}.wrapper{--sidebar-surface: var(--sd-white, #fff);--sidebar-rail: color-mix(in srgb, var(--sd-surface-muted, #e7e8ed) 35%, var(--sidebar-surface));--sidebar-line: color-mix(in srgb, var(--sd-border, #c4c6d0) 45%, var(--sidebar-surface));--sidebar-ink: var(--sd-text, #252c38);--sidebar-muted: var(--sd-text-secondary, #6b7280);position:relative;display:flex;flex-direction:column;width:min(304px,100vw);color:var(--sidebar-ink);background:linear-gradient(to right,var(--sidebar-rail) 56px,var(--sidebar-surface) 56px)}.wrapper,.wrapper *{box-sizing:border-box}.wrapper:before{content:\"\";position:absolute;inset:0 auto 0 55px;width:1px;background:var(--sidebar-line);pointer-events:none}.c-header{flex:0 0 auto;display:grid;grid-template-columns:56px minmax(0,1fr);min-height:42px}.c-logo{grid-column:1;display:grid;place-items:center;height:42px}.c-logo a{display:grid;place-items:center;width:38px;height:40px;border-radius:9px;color:var(--sidebar-muted)}.c-logo img{width:30px;height:30px;object-fit:contain}.c-title-menu-group{grid-column:2;display:flex;align-items:center;min-width:0;padding:10px 14px 12px;color:var(--sidebar-ink);font-size:16px;font-weight:700;line-height:22px;letter-spacing:-.2px;overflow-wrap:anywhere}.c-body{flex:1;min-height:0;overflow:hidden}.c-menu{display:flex;height:100%}.c-menu-group{display:flex;flex:0 0 56px;flex-direction:column;align-items:center;gap:10px;width:56px;min-height:0;margin-bottom:86px;padding:5px 0 8px;overflow-y:auto;scrollbar-width:none}.c-menu-group>button{flex:0 0 auto;border-radius:9px}.c-menu-group .c-menu-group-icon{display:flex;align-items:center;justify-content:center;width:38px;height:40px;min-height:40px;border-radius:9px;font-size:22px}.c-menu-group .c-menu-group-icon img{width:22px;height:22px;object-fit:contain}.c-menu-tree{display:flex;flex:1;flex-direction:column;min-width:0;min-height:0}.c-menu-tree-search{flex:0 0 auto;padding:0 14px 12px;border-bottom:1px solid var(--sidebar-line)}.c-menu-tree-search .c-search-prefix-icon{width:18px;height:18px;padding:0;font-size:18px;color:var(--sidebar-muted)}.c-menu-tree-search .c-search-prefix-icon.cancel{cursor:pointer}.c-menu-tree-container{flex:1;min-height:0;padding:10px 8px 14px;overflow:auto;scrollbar-width:thin;scrollbar-color:var(--sidebar-line) transparent;overscroll-behavior:contain}.c-menu-node{position:relative;display:flex;align-items:center;width:100%;min-height:40px;margin:2px 0;padding:0;border-radius:7px;cursor:pointer;color:var(--sidebar-ink);font-size:13px;line-height:1.4}.c-menu-node-description{display:flex;flex:1;align-items:center;gap:6px;width:100%;min-width:0;min-height:40px;padding:0;border:0;border-radius:inherit;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.c-menu-node-description-content{display:flex;flex:1;align-items:center;align-self:stretch;gap:9px;min-width:0;padding:8px;color:inherit;font:inherit;font-weight:500;text-decoration:none}.c-menu-node-label{flex:1;min-width:0;white-space:normal;overflow-wrap:anywhere}.c-menu-node-icon{flex:0 0 20px;width:20px;height:20px;font-size:20px;object-fit:contain;color:var(--sidebar-muted)}.c-menu-node-description-icon-expand,.c-menu-node-description-icon-pin{display:flex;flex:0 0 20px;align-items:center;justify-content:center;width:20px;height:24px;margin-right:6px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);font-size:18px;cursor:pointer}.c-menu-node-description-icon-pin{opacity:0}.c-menu-node-description-icon-pin:focus-visible{opacity:1!important}.c-menu-node.is-ancestor{color:var(--sidebar-accent)}.c-menu-node.is-ancestor .c-menu-node-description-content,.c-menu-node.is-ancestor .c-menu-node-icon,.c-menu-node.is-ancestor .c-menu-node-description-icon-expand{color:inherit}.c-menu-node.is-active{color:var(--sidebar-accent)}.c-menu-node.is-active .c-menu-node-icon{color:inherit}.c-menu-node.is-active:before{content:\"\";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--sidebar-accent)}.c-menu-node-group{position:relative;margin:0 0 7px 19px;padding:1px 0 1px 16px;border-left:1px solid var(--sidebar-line)}.c-menu-node-group .c-menu-node{min-height:34px;border-radius:6px}.c-menu-node-group .c-menu-node-description-content{padding:7px 8px;font-weight:400}.c-menu-node-group .c-menu-node-description{min-height:34px}.c-menu-node-group .c-menu-node-icon{display:none}.c-menu-node-group .c-menu-node.is-active:before{left:-18px}.c-menu-node-group .c-menu-node.is-active .c-menu-node-description-content,.c-menu-node-group .c-menu-node.is-ancestor .c-menu-node-description-content{font-weight:500}.c-menu-node-group .c-menu-node-group{margin-left:8px;padding-left:7px}.c-menu-node-group .c-menu-node-group .c-menu-node.is-active:before{left:-9px}.c-footer{position:absolute;bottom:0;left:0;width:56px;height:86px;background:var(--sidebar-rail)}a:focus-visible,button:focus-visible{outline:2px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:-2px}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}@media(pointer:coarse){.c-menu-node,.c-menu-node-group .c-menu-node,.c-menu-node-description,.c-menu-node-group .c-menu-node-description{min-height:44px}}@media(prefers-reduced-motion:reduce){.c-menu-group-icon,.c-menu-node,.c-menu-node *{transition:none!important}}ul,li{margin-top:0;margin-bottom:0;list-style:none}\n"], dependencies: [{ kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "clearable", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i3.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i3.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i3.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i3.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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1035
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive() ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: isPinnedMenuGroupActive() ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | translate\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\n } @else {\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor: (currentPath() | menuFocus: node : activeMenuPath()) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color: (currentPath() | menuFocus: node : activeMenuPath()) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || '#2962FF' : null\"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node : activeMenuPath() }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <mat-icon class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\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{position:relative;display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{flex-shrink:0;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;min-height:0;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{margin-bottom:80px;display:flex;flex-direction:column;align-items:center;flex:0 0 60px;width:60px;min-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;min-height:0;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search{flex-shrink:0}.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;min-height:0;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{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:18px;opacity:0}.wrapper .c-footer{position:absolute;bottom:0;left:0;width:60px;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", "clearable", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1035
1036
|
}
|
|
1036
1037
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
1037
1038
|
type: Component,
|
|
@@ -1050,7 +1051,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
1050
1051
|
SdSuffixDefDirective,
|
|
1051
1052
|
LayoutUserComponent$1,
|
|
1052
1053
|
TranslatePipe,
|
|
1053
|
-
], template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n@let _isShowSidebar = isShowSidebar();\n@let _searchText = searchText();\n@let _currentPath = currentPath();\n@let _activeMenuPath = activeMenuPath();\n@let _idMenuGroupActive = idMenuGroupActive();\n@let _pinnedMenuGroup = pinnedMenuGroup();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"wrapper\"\n [style.--sidebar-accent]=\"_sidebar.brandColor || 'var(--sd-primary, #005cbb)'\"\n [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!_isShowSidebar\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && _pinnedMenuGroup.children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, _pinnedMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, _pinnedMenuGroup)\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!_isShowSidebar\" [attr.inert]=\"!_isShowSidebar ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n hideInlineError\n [placeholder]=\"'core.module.layout.sidebar.search' | translate\"\n [model]=\"_searchText\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (_searchText) {\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\"\n >cancel</mat-icon\n >\n } @else {\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n [class.is-active]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!_isShowSidebar\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #252c38)',\n }\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: _currentPath | menuFocus: node : _activeMenuPath }\">\n <li>\n <div\n class=\"c-menu-node\"\n [class.is-ancestor]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!_isShowSidebar\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div class=\"c-menu-node-description-content\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"c-menu-node-group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"_isShowSidebar\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host{display:block;height:100%}.wrapper{--sidebar-surface: var(--sd-white, #fff);--sidebar-rail: color-mix(in srgb, var(--sd-surface-muted, #e7e8ed) 35%, var(--sidebar-surface));--sidebar-line: color-mix(in srgb, var(--sd-border, #c4c6d0) 45%, var(--sidebar-surface));--sidebar-ink: var(--sd-text, #252c38);--sidebar-muted: var(--sd-text-secondary, #6b7280);position:relative;display:flex;flex-direction:column;width:min(304px,100vw);color:var(--sidebar-ink);background:linear-gradient(to right,var(--sidebar-rail) 56px,var(--sidebar-surface) 56px)}.wrapper,.wrapper *{box-sizing:border-box}.wrapper:before{content:\"\";position:absolute;inset:0 auto 0 55px;width:1px;background:var(--sidebar-line);pointer-events:none}.c-header{flex:0 0 auto;display:grid;grid-template-columns:56px minmax(0,1fr);min-height:42px}.c-logo{grid-column:1;display:grid;place-items:center;height:42px}.c-logo a{display:grid;place-items:center;width:38px;height:40px;border-radius:9px;color:var(--sidebar-muted)}.c-logo img{width:30px;height:30px;object-fit:contain}.c-title-menu-group{grid-column:2;display:flex;align-items:center;min-width:0;padding:10px 14px 12px;color:var(--sidebar-ink);font-size:16px;font-weight:700;line-height:22px;letter-spacing:-.2px;overflow-wrap:anywhere}.c-body{flex:1;min-height:0;overflow:hidden}.c-menu{display:flex;height:100%}.c-menu-group{display:flex;flex:0 0 56px;flex-direction:column;align-items:center;gap:10px;width:56px;min-height:0;margin-bottom:86px;padding:5px 0 8px;overflow-y:auto;scrollbar-width:none}.c-menu-group>button{flex:0 0 auto;border-radius:9px}.c-menu-group .c-menu-group-icon{display:flex;align-items:center;justify-content:center;width:38px;height:40px;min-height:40px;border-radius:9px;font-size:22px}.c-menu-group .c-menu-group-icon img{width:22px;height:22px;object-fit:contain}.c-menu-tree{display:flex;flex:1;flex-direction:column;min-width:0;min-height:0}.c-menu-tree-search{flex:0 0 auto;padding:0 14px 12px;border-bottom:1px solid var(--sidebar-line)}.c-menu-tree-search .c-search-prefix-icon{width:18px;height:18px;padding:0;font-size:18px;color:var(--sidebar-muted)}.c-menu-tree-search .c-search-prefix-icon.cancel{cursor:pointer}.c-menu-tree-container{flex:1;min-height:0;padding:10px 8px 14px;overflow:auto;scrollbar-width:thin;scrollbar-color:var(--sidebar-line) transparent;overscroll-behavior:contain}.c-menu-node{position:relative;display:flex;align-items:center;width:100%;min-height:40px;margin:2px 0;padding:0;border-radius:7px;cursor:pointer;color:var(--sidebar-ink);font-size:13px;line-height:1.4}.c-menu-node-description{display:flex;flex:1;align-items:center;gap:6px;width:100%;min-width:0;min-height:40px;padding:0;border:0;border-radius:inherit;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.c-menu-node-description-content{display:flex;flex:1;align-items:center;align-self:stretch;gap:9px;min-width:0;padding:8px;color:inherit;font:inherit;font-weight:500;text-decoration:none}.c-menu-node-label{flex:1;min-width:0;white-space:normal;overflow-wrap:anywhere}.c-menu-node-icon{flex:0 0 20px;width:20px;height:20px;font-size:20px;object-fit:contain;color:var(--sidebar-muted)}.c-menu-node-description-icon-expand,.c-menu-node-description-icon-pin{display:flex;flex:0 0 20px;align-items:center;justify-content:center;width:20px;height:24px;margin-right:6px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);font-size:18px;cursor:pointer}.c-menu-node-description-icon-pin{opacity:0}.c-menu-node-description-icon-pin:focus-visible{opacity:1!important}.c-menu-node.is-ancestor{color:var(--sidebar-accent)}.c-menu-node.is-ancestor .c-menu-node-description-content,.c-menu-node.is-ancestor .c-menu-node-icon,.c-menu-node.is-ancestor .c-menu-node-description-icon-expand{color:inherit}.c-menu-node.is-active{color:var(--sidebar-accent)}.c-menu-node.is-active .c-menu-node-icon{color:inherit}.c-menu-node.is-active:before{content:\"\";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--sidebar-accent)}.c-menu-node-group{position:relative;margin:0 0 7px 19px;padding:1px 0 1px 16px;border-left:1px solid var(--sidebar-line)}.c-menu-node-group .c-menu-node{min-height:34px;border-radius:6px}.c-menu-node-group .c-menu-node-description-content{padding:7px 8px;font-weight:400}.c-menu-node-group .c-menu-node-description{min-height:34px}.c-menu-node-group .c-menu-node-icon{display:none}.c-menu-node-group .c-menu-node.is-active:before{left:-18px}.c-menu-node-group .c-menu-node.is-active .c-menu-node-description-content,.c-menu-node-group .c-menu-node.is-ancestor .c-menu-node-description-content{font-weight:500}.c-menu-node-group .c-menu-node-group{margin-left:8px;padding-left:7px}.c-menu-node-group .c-menu-node-group .c-menu-node.is-active:before{left:-9px}.c-footer{position:absolute;bottom:0;left:0;width:56px;height:86px;background:var(--sidebar-rail)}a:focus-visible,button:focus-visible{outline:2px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:-2px}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}@media(pointer:coarse){.c-menu-node,.c-menu-node-group .c-menu-node,.c-menu-node-description,.c-menu-node-group .c-menu-node-description{min-height:44px}}@media(prefers-reduced-motion:reduce){.c-menu-group-icon,.c-menu-node,.c-menu-node *{transition:none!important}}ul,li{margin-top:0;margin-bottom:0;list-style:none}\n"] }]
|
|
1054
|
+
], template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive() ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: isPinnedMenuGroupActive() ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | translate\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\n } @else {\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor: (currentPath() | menuFocus: node : activeMenuPath()) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color: (currentPath() | menuFocus: node : activeMenuPath()) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || '#2962FF' : null\"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node : activeMenuPath() }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <mat-icon class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\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{position:relative;display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{flex-shrink:0;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;min-height:0;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{margin-bottom:80px;display:flex;flex-direction:column;align-items:center;flex:0 0 60px;width:60px;min-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;min-height:0;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search{flex-shrink:0}.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;min-height:0;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{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:18px;opacity:0}.wrapper .c-footer{position:absolute;bottom:0;left:0;width:60px;height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"] }]
|
|
1054
1055
|
}], ctorParameters: () => [] });
|
|
1055
1056
|
|
|
1056
1057
|
class SidebarV1Component {
|
|
@@ -1178,11 +1179,751 @@ class SidebarV1Component {
|
|
|
1178
1179
|
}
|
|
1179
1180
|
};
|
|
1180
1181
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1181
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.21", type: SidebarV1Component, isStandalone: true, selector: "sidebar-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 } }, viewQueries: [{ propertyName: "sidenav", first: true, predicate: ["sidenav"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:
|
|
1182
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.21", type: SidebarV1Component, isStandalone: true, selector: "sidebar-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 } }, viewQueries: [{ propertyName: "sidenav", first: true, predicate: ["sidenav"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", 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;overflow:clip!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.is-expanded{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"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$4.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i1$4.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i1$4.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$4.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$4.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarComponent, selector: "sidebar", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["expandSideBar", "popupUserMenuClosed", "popupUserMenuOpened", "showSideBar"] }] });
|
|
1182
1183
|
}
|
|
1183
1184
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV1Component, decorators: [{
|
|
1184
1185
|
type: Component,
|
|
1185
|
-
args: [{ selector: 'sidebar-v1', imports: [MatSidenavModule, CommonModule, SidebarComponent], standalone: true, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:
|
|
1186
|
+
args: [{ selector: 'sidebar-v1', imports: [MatSidenavModule, CommonModule, SidebarComponent], standalone: true, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", 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;overflow:clip!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.is-expanded{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"] }]
|
|
1187
|
+
}], ctorParameters: () => [] });
|
|
1188
|
+
|
|
1189
|
+
class SidebarV2UserComponent {
|
|
1190
|
+
// ==========================================
|
|
1191
|
+
// INJECT SERVICES
|
|
1192
|
+
// ==========================================
|
|
1193
|
+
#layoutConfiguration = inject(SD_LAYOUT_CONFIGURATION);
|
|
1194
|
+
// ==========================================
|
|
1195
|
+
// SIGNAL INPUTS & OUTPUTS
|
|
1196
|
+
// ==========================================
|
|
1197
|
+
isMobileOrTablet = input(false);
|
|
1198
|
+
isMenuLock = input(false);
|
|
1199
|
+
isShowSidebar = input(false);
|
|
1200
|
+
userInfo = input.required();
|
|
1201
|
+
// Chuyển thành void vì các hàm emit hiện tại không truyền data
|
|
1202
|
+
menuClosed = output();
|
|
1203
|
+
menuOpened = output();
|
|
1204
|
+
toggleMenuLock = output();
|
|
1205
|
+
// Config actions
|
|
1206
|
+
singoutLayoutConfig = this.#layoutConfiguration.signout;
|
|
1207
|
+
changePasswordLayoutConfig = this.#layoutConfiguration?.changePassword;
|
|
1208
|
+
// ==========================================
|
|
1209
|
+
// EVENT HANDLERS
|
|
1210
|
+
// ==========================================
|
|
1211
|
+
onMenuOpened = () => {
|
|
1212
|
+
this.menuOpened.emit();
|
|
1213
|
+
};
|
|
1214
|
+
onMenuClosed = () => {
|
|
1215
|
+
this.menuClosed.emit();
|
|
1216
|
+
};
|
|
1217
|
+
keepOpenWhenClickInsideMenu = (event) => {
|
|
1218
|
+
event.stopPropagation();
|
|
1219
|
+
};
|
|
1220
|
+
logout = () => {
|
|
1221
|
+
this.singoutLayoutConfig();
|
|
1222
|
+
};
|
|
1223
|
+
changePassword = () => {
|
|
1224
|
+
// Dùng Optional Chaining gọi hàm cực gọn
|
|
1225
|
+
this.changePasswordLayoutConfig?.();
|
|
1226
|
+
};
|
|
1227
|
+
onToggleMenuLock = (event) => {
|
|
1228
|
+
this.toggleMenuLock.emit(event);
|
|
1229
|
+
};
|
|
1230
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2UserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1231
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SidebarV2UserComponent, isStandalone: true, selector: "sd-sidebar-v2-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 _isShowSidebar = isShowSidebar();\n@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <button\n type=\"button\"\n class=\"c-layout-icon-toggle\"\n [attr.aria-label]=\"'core.component.preview-pdf.toggle-sidebar' | translate\"\n [attr.aria-expanded]=\"_isShowSidebar\"\n (click)=\"onToggleMenuLock($event)\">\n <mat-icon fontSet=\"material-icons-outlined\">\n {{ _isShowSidebar ? 'chevron_left' : 'chevron_right' }}\n </mat-icon>\n </button>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\n", 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;justify-content:flex-end;gap:4px;width:56px;height:86px;padding-bottom:6px;box-sizing:border-box}.c-layout-user-avatar{display:flex;align-items:center;justify-content:center;width:56px;height:40px;cursor:pointer}.c-layout-icon-toggle{display:flex;align-items:center;justify-content:center;width:32px;height:28px;min-height:28px;margin:0;padding:0;border:0;border-radius:6px;background:transparent;color:var(--sd-text-secondary, #6b7280);cursor:pointer}.c-layout-icon-toggle mat-icon{width:18px;height:18px;font-size:18px}.c-layout-icon-toggle:hover{background:color-mix(in srgb,var(--sd-text, #252c38) 5%,transparent);color:var(--sd-text, #252c38)}.c-layout-icon-toggle:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}@media(pointer:coarse){.c-layout-icon-toggle{width:44px;min-height:44px}}.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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1232
|
+
}
|
|
1233
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2UserComponent, decorators: [{
|
|
1234
|
+
type: Component,
|
|
1235
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sd-sidebar-v2-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar, TranslatePipe], standalone: true, template: "@let _isShowSidebar = isShowSidebar();\n@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <button\n type=\"button\"\n class=\"c-layout-icon-toggle\"\n [attr.aria-label]=\"'core.component.preview-pdf.toggle-sidebar' | translate\"\n [attr.aria-expanded]=\"_isShowSidebar\"\n (click)=\"onToggleMenuLock($event)\">\n <mat-icon fontSet=\"material-icons-outlined\">\n {{ _isShowSidebar ? 'chevron_left' : 'chevron_right' }}\n </mat-icon>\n </button>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\n", 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;justify-content:flex-end;gap:4px;width:56px;height:86px;padding-bottom:6px;box-sizing:border-box}.c-layout-user-avatar{display:flex;align-items:center;justify-content:center;width:56px;height:40px;cursor:pointer}.c-layout-icon-toggle{display:flex;align-items:center;justify-content:center;width:32px;height:28px;min-height:28px;margin:0;padding:0;border:0;border-radius:6px;background:transparent;color:var(--sd-text-secondary, #6b7280);cursor:pointer}.c-layout-icon-toggle mat-icon{width:18px;height:18px;font-size:18px}.c-layout-icon-toggle:hover{background:color-mix(in srgb,var(--sd-text, #252c38) 5%,transparent);color:var(--sd-text, #252c38)}.c-layout-icon-toggle:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}@media(pointer:coarse){.c-layout-icon-toggle{width:44px;min-height:44px}}.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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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"] }]
|
|
1236
|
+
}] });
|
|
1237
|
+
|
|
1238
|
+
class SidebarV2PanelComponent {
|
|
1239
|
+
// ==========================================
|
|
1240
|
+
// INJECT SERVICES (Thay thế Constructor rườm rà)
|
|
1241
|
+
// ==========================================
|
|
1242
|
+
#router = inject(Router);
|
|
1243
|
+
#layoutStorageService = inject(SdLayoutStorageService);
|
|
1244
|
+
#menuFocusPipe = inject(MenuFocusPipe);
|
|
1245
|
+
#destroyRef = inject(DestroyRef); // Dùng để unsubscribe RxJS tự động
|
|
1246
|
+
// ==========================================
|
|
1247
|
+
// SIGNAL INPUTS & OUTPUTS
|
|
1248
|
+
// ==========================================
|
|
1249
|
+
isShowSidebar = input.required();
|
|
1250
|
+
menus = input.required();
|
|
1251
|
+
userInfo = input.required();
|
|
1252
|
+
sidebar = input.required();
|
|
1253
|
+
expandSideBar = output();
|
|
1254
|
+
popupUserMenuClosed = output();
|
|
1255
|
+
popupUserMenuOpened = output();
|
|
1256
|
+
showSideBar = output();
|
|
1257
|
+
// ==========================================
|
|
1258
|
+
// STATE SIGNALS
|
|
1259
|
+
// ==========================================
|
|
1260
|
+
screenHeight = window.innerHeight;
|
|
1261
|
+
isMobileOrTablet = BrowserUtilities.isMobile();
|
|
1262
|
+
isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true);
|
|
1263
|
+
currentPath = signal(window.location.pathname);
|
|
1264
|
+
searchText = signal('');
|
|
1265
|
+
titleMenuGroup = signal('');
|
|
1266
|
+
idMenuGroupActive = signal('');
|
|
1267
|
+
menusByGroup = signal([]);
|
|
1268
|
+
#hoveredMenuNodeKey = signal(null);
|
|
1269
|
+
#pinIconHoverTimerId = signal(null);
|
|
1270
|
+
pinnedMenuGroup = signal(this.#layoutStorageService.pinnedMenuGroup.get() ?? {
|
|
1271
|
+
id: 'pinned-menu-group',
|
|
1272
|
+
title: 'Đã ghim',
|
|
1273
|
+
children: [],
|
|
1274
|
+
});
|
|
1275
|
+
// ==========================================
|
|
1276
|
+
// COMPUTED STATE
|
|
1277
|
+
// ==========================================
|
|
1278
|
+
totalMenuInMenusByGroup = computed(() => this.#getTotalMenus(this.menusByGroup()));
|
|
1279
|
+
pinnedNodeKeys = computed(() => new Set(this.pinnedMenuGroup().children?.map(m => this.#getMenuNodeKey(m)) ?? []));
|
|
1280
|
+
isPinnedMenuGroupActive = computed(() => this.idMenuGroupActive() === this.pinnedMenuGroup().id);
|
|
1281
|
+
// Path khớp sát nhất trong nhánh menu đang hiển thị. Nhờ nó '/appointment' hết sáng khi đang ở '/appointment/cs'.
|
|
1282
|
+
activeMenuPath = computed(() => resolveActiveMenuPath(this.menusByGroup(), this.currentPath()));
|
|
1283
|
+
// ==========================================
|
|
1284
|
+
// DATA STRUCTURES
|
|
1285
|
+
// ==========================================
|
|
1286
|
+
#pinIconHoverTimerDelay = 300;
|
|
1287
|
+
#isFirstBindingMenu = signal(true);
|
|
1288
|
+
dataSource = new MatTreeNestedDataSource();
|
|
1289
|
+
treeControl = new NestedTreeControl(node => ('children' in node && node.children?.length ? node.children : []));
|
|
1290
|
+
constructor() {
|
|
1291
|
+
this.#setupEffects();
|
|
1292
|
+
this.#setupSubscriptions();
|
|
1293
|
+
}
|
|
1294
|
+
#setupEffects() {
|
|
1295
|
+
effect(() => {
|
|
1296
|
+
const currentMenus = this.menus();
|
|
1297
|
+
untracked(() => {
|
|
1298
|
+
const lastActiveMenuGroupId = this.#layoutStorageService.lastActiveMenuGroupId.get();
|
|
1299
|
+
const pinnedGroup = this.pinnedMenuGroup();
|
|
1300
|
+
const isPinEnabled = this.sidebar()?.pin?.enabled;
|
|
1301
|
+
// Xử lý khi lần đầu vào web (nếu chưa có active group)
|
|
1302
|
+
if (!lastActiveMenuGroupId || (lastActiveMenuGroupId === pinnedGroup?.id && !isPinEnabled)) {
|
|
1303
|
+
// Ưu tiên pinnedGroup nếu đủ điều kiện, còn không lấy menu đầu tiền dev khai báo
|
|
1304
|
+
const targetId = isPinEnabled && pinnedGroup?.children?.length ? pinnedGroup?.id : currentMenus?.[0]?.id;
|
|
1305
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set(targetId ?? '');
|
|
1306
|
+
}
|
|
1307
|
+
this.#bindingMenuGroupByCurrentPath(currentMenus);
|
|
1308
|
+
this.#isFirstBindingMenu.set(false);
|
|
1309
|
+
});
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
#setupSubscriptions() {
|
|
1313
|
+
this.#router.events.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(event => {
|
|
1314
|
+
if (event instanceof NavigationEnd) {
|
|
1315
|
+
if (this.currentPath() !== window.location.pathname) {
|
|
1316
|
+
this.currentPath.set(window.location.pathname);
|
|
1317
|
+
this.#bindingMenuGroupByCurrentPath(this.menus());
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
// ==========================================
|
|
1323
|
+
// EVENT HANDLERS
|
|
1324
|
+
// ==========================================
|
|
1325
|
+
hasChild = (_, node) => 'children' in node && !!node.children?.length;
|
|
1326
|
+
onToggleMenuNode = (menu) => {
|
|
1327
|
+
this.treeControl.toggle(menu);
|
|
1328
|
+
};
|
|
1329
|
+
isPinnedNode = (node) => this.pinnedNodeKeys().has(this.#getMenuNodeKey(node));
|
|
1330
|
+
isHoveredNode = (node) => this.#hoveredMenuNodeKey() === this.#getMenuNodeKey(node);
|
|
1331
|
+
expandPinnedGroup = () => {
|
|
1332
|
+
const group = this.pinnedMenuGroup();
|
|
1333
|
+
this.idMenuGroupActive.set(group.id);
|
|
1334
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set(group.id || '');
|
|
1335
|
+
this.titleMenuGroup.set(group.title);
|
|
1336
|
+
this.#setMenusByGroup(group.children ?? []);
|
|
1337
|
+
this.searchText.set('');
|
|
1338
|
+
this.expandSideBar.emit();
|
|
1339
|
+
};
|
|
1340
|
+
onTogglePin = (event, node) => {
|
|
1341
|
+
event.stopPropagation();
|
|
1342
|
+
const key = this.#getMenuNodeKey(node);
|
|
1343
|
+
this.pinnedMenuGroup.update(group => {
|
|
1344
|
+
const children = group.children ?? [];
|
|
1345
|
+
const exists = children.some(m => this.#getMenuNodeKey(m) === key);
|
|
1346
|
+
const updatedChildren = exists ? children.filter(m => this.#getMenuNodeKey(m) !== key) : [...children, node];
|
|
1347
|
+
const updatedGroup = { id: 'pinned-menu-group', title: 'Đã ghim', children: updatedChildren };
|
|
1348
|
+
this.#layoutStorageService.pinnedMenuGroup.set(updatedGroup);
|
|
1349
|
+
return updatedGroup;
|
|
1350
|
+
});
|
|
1351
|
+
};
|
|
1352
|
+
#onExpandAllMenuNodes = (menus) => {
|
|
1353
|
+
menus?.forEach(menu => {
|
|
1354
|
+
this.treeControl.expand(menu);
|
|
1355
|
+
if ('children' in menu && menu.children?.length) {
|
|
1356
|
+
this.#onExpandAllMenuNodes(menu.children);
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
};
|
|
1360
|
+
#onCollapseAllMenuNodes = (menus) => {
|
|
1361
|
+
menus?.forEach(menu => {
|
|
1362
|
+
this.treeControl.collapse(menu);
|
|
1363
|
+
if ('children' in menu && menu.children?.length) {
|
|
1364
|
+
this.#onCollapseAllMenuNodes(menu.children);
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
};
|
|
1368
|
+
toggleMenuLock(event) {
|
|
1369
|
+
event.stopPropagation();
|
|
1370
|
+
this.isMenuLock.update(v => !v);
|
|
1371
|
+
this.#layoutStorageService.menuLockStatus?.set(this.isMenuLock());
|
|
1372
|
+
this.showSideBar.emit(this.isMenuLock());
|
|
1373
|
+
}
|
|
1374
|
+
openHomePage = () => {
|
|
1375
|
+
if (!this.isMobileOrTablet) {
|
|
1376
|
+
this.#router.navigateByUrl('/layout/home');
|
|
1377
|
+
}
|
|
1378
|
+
else {
|
|
1379
|
+
window.location.href = '/layout/home';
|
|
1380
|
+
}
|
|
1381
|
+
this.searchText.set('');
|
|
1382
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set('');
|
|
1383
|
+
};
|
|
1384
|
+
onUserMenuClosed = () => this.popupUserMenuClosed.emit();
|
|
1385
|
+
onUserMenuOpened = () => this.popupUserMenuOpened.emit();
|
|
1386
|
+
navigate = (args) => {
|
|
1387
|
+
const { path, queryParams } = args;
|
|
1388
|
+
if (path.includes('http')) {
|
|
1389
|
+
window.open(path);
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
this.#router.navigate([path.split('?')[0]], {
|
|
1393
|
+
queryParams,
|
|
1394
|
+
state: { switchTab: true },
|
|
1395
|
+
});
|
|
1396
|
+
if (this.isMobileOrTablet) {
|
|
1397
|
+
this.#closeMenu();
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
onFilterSearchText = (event) => {
|
|
1401
|
+
this.searchText.set(event);
|
|
1402
|
+
this.#filterMenuBySearchText(this.menusByGroup());
|
|
1403
|
+
};
|
|
1404
|
+
onClearSearchText = () => {
|
|
1405
|
+
this.searchText.set('');
|
|
1406
|
+
this.#filterMenuBySearchText(this.menusByGroup());
|
|
1407
|
+
};
|
|
1408
|
+
expandMenuGroup = (menuGroupNode) => {
|
|
1409
|
+
this.titleMenuGroup.set(menuGroupNode?.tooltipTitle || menuGroupNode?.title);
|
|
1410
|
+
// Case 1: Menu không có children
|
|
1411
|
+
if (!('children' in menuGroupNode && menuGroupNode.children?.length)) {
|
|
1412
|
+
if ('path' in menuGroupNode) {
|
|
1413
|
+
this.navigate({ path: menuGroupNode.path, queryParams: menuGroupNode?.queryParams ?? {} });
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
// Case 2: Menu có children
|
|
1418
|
+
if ('children' in menuGroupNode && menuGroupNode.children?.length) {
|
|
1419
|
+
this.#setMenusByGroup(menuGroupNode.children);
|
|
1420
|
+
this.searchText.set('');
|
|
1421
|
+
this.onFilterSearchText('');
|
|
1422
|
+
this.expandSideBar.emit();
|
|
1423
|
+
}
|
|
1424
|
+
this.idMenuGroupActive.set(menuGroupNode?.id);
|
|
1425
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set(menuGroupNode?.id || '');
|
|
1426
|
+
if (!this.currentPath()) {
|
|
1427
|
+
this.currentPath.set(window.location.pathname);
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
// ==========================================
|
|
1431
|
+
// CỤM HOVER MENU GROUP & NODE
|
|
1432
|
+
// ==========================================
|
|
1433
|
+
onMouseOverMenuGroupNode = (event, menuNode) => {
|
|
1434
|
+
if (this.idMenuGroupActive() !== menuNode?.id) {
|
|
1435
|
+
const menuGroup = event.currentTarget;
|
|
1436
|
+
const menuGroupIcon = menuGroup.querySelector('.c-menu-group-icon');
|
|
1437
|
+
const brandLightColorOpacity = this.#convertColor(this.sidebar()?.brandLightColor, 0.6);
|
|
1438
|
+
if (menuGroupIcon) {
|
|
1439
|
+
menuGroupIcon.style.transition = 'all 0.15s';
|
|
1440
|
+
menuGroupIcon.style.backgroundColor = brandLightColorOpacity || 'rgba(248, 249, 250, 0.6)';
|
|
1441
|
+
if (!(menuGroupIcon instanceof HTMLImageElement)) {
|
|
1442
|
+
menuGroupIcon.style.color = this.sidebar()?.brandColor || '#2962FF';
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
onMouseLeaveMenuGroupNode = (event, menuNode) => {
|
|
1448
|
+
if (this.idMenuGroupActive() !== menuNode?.id) {
|
|
1449
|
+
const menuGroup = event.currentTarget;
|
|
1450
|
+
const menuGroupIcon = menuGroup.querySelector('.c-menu-group-icon');
|
|
1451
|
+
if (menuGroupIcon) {
|
|
1452
|
+
menuGroupIcon.style.transition = 'all 0.15s';
|
|
1453
|
+
menuGroupIcon.style.backgroundColor = 'transparent';
|
|
1454
|
+
if (menuGroupIcon instanceof HTMLImageElement) {
|
|
1455
|
+
menuGroupIcon.style.opacity = '0.55';
|
|
1456
|
+
}
|
|
1457
|
+
else {
|
|
1458
|
+
menuGroupIcon.style.color = '#8C8C8C';
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
onMouseOverMenuNode = (event, menuItem) => {
|
|
1464
|
+
const menuNode = event.currentTarget;
|
|
1465
|
+
const brandColor = this.sidebar()?.brandColor || '#2962FF';
|
|
1466
|
+
// Nếu có bật config pin menu
|
|
1467
|
+
if (this.sidebar()?.pin?.enabled) {
|
|
1468
|
+
const iconPin = menuNode.querySelector('.c-menu-node-description-icon-pin');
|
|
1469
|
+
if (iconPin) {
|
|
1470
|
+
if (this.#pinIconHoverTimerId()) {
|
|
1471
|
+
clearTimeout(this.#pinIconHoverTimerId());
|
|
1472
|
+
this.#pinIconHoverTimerId.set(null);
|
|
1473
|
+
}
|
|
1474
|
+
this.#pinIconHoverTimerId.set(setTimeout(() => {
|
|
1475
|
+
this.#hoveredMenuNodeKey.set(this.#getMenuNodeKey(menuItem));
|
|
1476
|
+
iconPin.style.color = brandColor;
|
|
1477
|
+
iconPin.style.transition = 'all 0.15s';
|
|
1478
|
+
iconPin.style.opacity = '1';
|
|
1479
|
+
this.#pinIconHoverTimerId.set(null);
|
|
1480
|
+
}, this.#pinIconHoverTimerDelay));
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (!this.#menuFocusPipe.transform(this.currentPath(), menuItem, this.activeMenuPath())) {
|
|
1484
|
+
const iconMenu = menuNode.querySelector('.c-menu-node-icon');
|
|
1485
|
+
const content = menuNode.querySelector('.c-menu-node-description-content');
|
|
1486
|
+
const iconExpand = menuNode.querySelector('.c-menu-node-description-icon-expand');
|
|
1487
|
+
const brandLightColorOpacity = this.#convertColor(this.sidebar()?.brandLightColor, 0.6);
|
|
1488
|
+
if (menuNode) {
|
|
1489
|
+
menuNode.style.transition = 'all 0.15s';
|
|
1490
|
+
menuNode.style.backgroundColor = brandLightColorOpacity || 'rgba(248, 249, 250, 0.6)';
|
|
1491
|
+
if (iconMenu) {
|
|
1492
|
+
iconMenu.style.transition = 'all 0.15s';
|
|
1493
|
+
iconMenu.style.color = brandColor;
|
|
1494
|
+
}
|
|
1495
|
+
if (content) {
|
|
1496
|
+
content.style.transition = 'all 0.15s';
|
|
1497
|
+
content.style.color = brandColor;
|
|
1498
|
+
}
|
|
1499
|
+
if (iconExpand) {
|
|
1500
|
+
iconExpand.style.transition = 'all 0.15s';
|
|
1501
|
+
iconExpand.style.color = brandColor;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
onMouseLeaveMenuNode = (event, menuItem) => {
|
|
1507
|
+
const menuNode = event.currentTarget;
|
|
1508
|
+
// Nếu có bật config pin menu
|
|
1509
|
+
if (this.sidebar()?.pin?.enabled) {
|
|
1510
|
+
const iconPin = menuNode.querySelector('.c-menu-node-description-icon-pin');
|
|
1511
|
+
if (iconPin) {
|
|
1512
|
+
if (this.#pinIconHoverTimerId()) {
|
|
1513
|
+
clearTimeout(this.#pinIconHoverTimerId());
|
|
1514
|
+
this.#pinIconHoverTimerId.set(null);
|
|
1515
|
+
}
|
|
1516
|
+
this.#hoveredMenuNodeKey.set(null);
|
|
1517
|
+
iconPin.style.transition = 'all 0.15s';
|
|
1518
|
+
if (!this.isPinnedNode(menuItem)) {
|
|
1519
|
+
iconPin.style.color = '#8C8C8C';
|
|
1520
|
+
iconPin.style.opacity = '0';
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (!this.#menuFocusPipe.transform(this.currentPath(), menuItem, this.activeMenuPath())) {
|
|
1525
|
+
const iconMenu = menuNode.querySelector('.c-menu-node-icon');
|
|
1526
|
+
const content = menuNode.querySelector('.c-menu-node-description-content');
|
|
1527
|
+
const iconExpand = menuNode.querySelector('.c-menu-node-description-icon-expand');
|
|
1528
|
+
if (menuNode) {
|
|
1529
|
+
menuNode.style.transition = 'all 0.15s';
|
|
1530
|
+
menuNode.style.backgroundColor = 'transparent';
|
|
1531
|
+
if (iconMenu) {
|
|
1532
|
+
iconMenu.style.transition = 'all 0.15s';
|
|
1533
|
+
iconMenu.style.color = '#8C8C8C';
|
|
1534
|
+
}
|
|
1535
|
+
if (content) {
|
|
1536
|
+
content.style.transition = 'all 0.15s';
|
|
1537
|
+
content.style.color = '#1F1F1F';
|
|
1538
|
+
}
|
|
1539
|
+
if (iconExpand) {
|
|
1540
|
+
iconExpand.style.transition = 'all 0.15s';
|
|
1541
|
+
iconExpand.style.color = '#8C8C8C';
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1546
|
+
// ==========================================
|
|
1547
|
+
// PRIVATE LOGIC
|
|
1548
|
+
// ==========================================
|
|
1549
|
+
#setMenusByGroup = (menus) => {
|
|
1550
|
+
this.menusByGroup.set(menus);
|
|
1551
|
+
this.dataSource.data = menus;
|
|
1552
|
+
};
|
|
1553
|
+
#getMenuNodeKey = (node) => {
|
|
1554
|
+
if (node?.id) {
|
|
1555
|
+
return node.id;
|
|
1556
|
+
}
|
|
1557
|
+
if ('path' in node && node.path) {
|
|
1558
|
+
return node.path;
|
|
1559
|
+
}
|
|
1560
|
+
return node.title || '';
|
|
1561
|
+
};
|
|
1562
|
+
#getMenuGroupByCurrentPath = (menus) => {
|
|
1563
|
+
const activePath = resolveActiveMenuPath(menus, this.currentPath());
|
|
1564
|
+
if (!activePath) {
|
|
1565
|
+
return [];
|
|
1566
|
+
}
|
|
1567
|
+
const menuGroup = this.#findMenuGroupByPath(menus, activePath);
|
|
1568
|
+
return menuGroup ? [menuGroup] : [];
|
|
1569
|
+
};
|
|
1570
|
+
#findMenuGroupByPath = (menus, activePath, menuGroup) => {
|
|
1571
|
+
for (const menu of menus) {
|
|
1572
|
+
if ('path' in menu && menu.path === activePath) {
|
|
1573
|
+
return menuGroup ?? menu;
|
|
1574
|
+
}
|
|
1575
|
+
if ('children' in menu && menu.children?.length) {
|
|
1576
|
+
const result = this.#findMenuGroupByPath(menu.children, activePath, menuGroup ?? menu);
|
|
1577
|
+
if (result) {
|
|
1578
|
+
return result;
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
return null;
|
|
1583
|
+
};
|
|
1584
|
+
#bindingMenuGroupByCurrentPath = (menus) => {
|
|
1585
|
+
// Chỉ bindingGroup mới khi người dùng không searchText
|
|
1586
|
+
if (!this.#getValidSearchText()) {
|
|
1587
|
+
const pinnedChildren = this.pinnedMenuGroup()?.children ?? [];
|
|
1588
|
+
// Ưu tiên: Current path khớp với item trong pinMenuGroup thì lần đầu vào trang sẽ hiện pinnedMenuGroup
|
|
1589
|
+
const isPinnedPathMatchValid = this.sidebar()?.pin?.enabled &&
|
|
1590
|
+
pinnedChildren?.length &&
|
|
1591
|
+
this.#getMenuGroupByCurrentPath(pinnedChildren)?.length &&
|
|
1592
|
+
this.#isFirstBindingMenu() &&
|
|
1593
|
+
this.idMenuGroupActive() !== this.pinnedMenuGroup()?.id;
|
|
1594
|
+
if (isPinnedPathMatchValid) {
|
|
1595
|
+
const pinned = this.pinnedMenuGroup();
|
|
1596
|
+
this.idMenuGroupActive.set(pinned.id);
|
|
1597
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set(pinned.id ?? '');
|
|
1598
|
+
this.titleMenuGroup.set(pinned.title);
|
|
1599
|
+
this.#setMenusByGroup(pinnedChildren);
|
|
1600
|
+
this.#expandParentNodesByCurrentPath(pinnedChildren);
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
let menuGroupByPath = this.#getMenuGroupByCurrentPath(menus);
|
|
1604
|
+
// Nếu không tìm được path nào khớp với menu
|
|
1605
|
+
if (!menuGroupByPath?.length) {
|
|
1606
|
+
const lastActiveId = this.#layoutStorageService.lastActiveMenuGroupId.get() || '';
|
|
1607
|
+
// Nếu có pinned group thì hiện mậc định là pinnedMenuGroup
|
|
1608
|
+
if (this.sidebar()?.pin?.enabled && lastActiveId === this.pinnedMenuGroup()?.id && pinnedChildren?.length) {
|
|
1609
|
+
const pinned = this.pinnedMenuGroup();
|
|
1610
|
+
this.idMenuGroupActive.set(pinned.id);
|
|
1611
|
+
this.titleMenuGroup.set(pinned.title);
|
|
1612
|
+
this.#setMenusByGroup(pinnedChildren);
|
|
1613
|
+
this.#expandParentNodesByCurrentPath(pinnedChildren);
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
// Nếu không có pinnedMenuGroup thì menuGroup lấy từ thao tác cuối cùng của người dùng
|
|
1617
|
+
menuGroupByPath = this.menus()?.filter(menu => menu?.id === lastActiveId) || [];
|
|
1618
|
+
}
|
|
1619
|
+
// Kiểm tra lại menuGroupPath đã thực sự tìm được chưa?
|
|
1620
|
+
if (menuGroupByPath?.length) {
|
|
1621
|
+
// Nếu user đang ở pinedGroup và curentPath có chứa trong pinnedMenuGroup thì return luôn, không chuyển sang menuGroup mới
|
|
1622
|
+
if (this.sidebar()?.pin?.enabled &&
|
|
1623
|
+
this.idMenuGroupActive() === this.pinnedMenuGroup()?.id &&
|
|
1624
|
+
this.#getMenuGroupByCurrentPath(pinnedChildren)?.length) {
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
else {
|
|
1628
|
+
const matchedGroup = menuGroupByPath[0];
|
|
1629
|
+
this.idMenuGroupActive.set(matchedGroup?.id);
|
|
1630
|
+
this.#layoutStorageService.lastActiveMenuGroupId.set(matchedGroup?.id || '');
|
|
1631
|
+
this.titleMenuGroup.set(matchedGroup?.tooltipTitle || matchedGroup?.title);
|
|
1632
|
+
if ('children' in matchedGroup && matchedGroup.children?.length) {
|
|
1633
|
+
this.menusByGroup.set(matchedGroup.children);
|
|
1634
|
+
this.#expandParentNodesByCurrentPath(this.menusByGroup());
|
|
1635
|
+
}
|
|
1636
|
+
else {
|
|
1637
|
+
this.menusByGroup.set([]);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
this.idMenuGroupActive.set('');
|
|
1643
|
+
this.titleMenuGroup.set('');
|
|
1644
|
+
this.menusByGroup.set([]);
|
|
1645
|
+
}
|
|
1646
|
+
this.dataSource.data = this.menusByGroup();
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1649
|
+
#expandParentNodesByCurrentPath(menus) {
|
|
1650
|
+
const activePath = resolveActiveMenuPath(menus, this.currentPath());
|
|
1651
|
+
return activePath ? this.#expandParentNodesByPath(menus, activePath) : false;
|
|
1652
|
+
}
|
|
1653
|
+
#expandParentNodesByPath(menus, activePath) {
|
|
1654
|
+
let shouldPropagate = false;
|
|
1655
|
+
for (const menu of menus) {
|
|
1656
|
+
if ('path' in menu && menu.path === activePath) {
|
|
1657
|
+
shouldPropagate = true;
|
|
1658
|
+
}
|
|
1659
|
+
if ('children' in menu && menu.children?.length) {
|
|
1660
|
+
const childHasMatch = this.#expandParentNodesByPath(menu.children, activePath);
|
|
1661
|
+
if (childHasMatch) {
|
|
1662
|
+
this.treeControl.expand(menu);
|
|
1663
|
+
shouldPropagate = true;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
return shouldPropagate;
|
|
1668
|
+
}
|
|
1669
|
+
#filterMenuBySearchText = (menus) => {
|
|
1670
|
+
const validSearchText = this.#getValidSearchText();
|
|
1671
|
+
if (!validSearchText) {
|
|
1672
|
+
this.dataSource.data = menus;
|
|
1673
|
+
this.#onCollapseAllMenuNodes(menus);
|
|
1674
|
+
this.#expandParentNodesByCurrentPath(menus);
|
|
1675
|
+
}
|
|
1676
|
+
else {
|
|
1677
|
+
const aliasSearchText = StringUtilities.changeAliasLowerCase(validSearchText);
|
|
1678
|
+
this.dataSource.data = this.#getMenuByAliasSearchText(menus, aliasSearchText);
|
|
1679
|
+
if (this.dataSource.data?.length) {
|
|
1680
|
+
this.#onExpandAllMenuNodes(this.dataSource.data);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
#getMenuByAliasSearchText = (menus, aliasSearchText) => {
|
|
1685
|
+
const result = [];
|
|
1686
|
+
for (const menu of menus) {
|
|
1687
|
+
const aliasTitle = StringUtilities.changeAliasLowerCase(menu.title);
|
|
1688
|
+
// why: hỗ trợ search theo route (path) và search theo ký tự đầu (viết tắt) bên cạnh search theo tiêu đề
|
|
1689
|
+
const matchByRoutePath = 'path' in menu && !!menu.path && menu.path.toLowerCase().includes(aliasSearchText);
|
|
1690
|
+
const matchByInitials = this.#matchesTitleInitials(aliasTitle, aliasSearchText);
|
|
1691
|
+
if (aliasTitle.includes(aliasSearchText) || matchByRoutePath || matchByInitials) {
|
|
1692
|
+
result.push(menu);
|
|
1693
|
+
continue;
|
|
1694
|
+
}
|
|
1695
|
+
let matchedChildren = [];
|
|
1696
|
+
if ('children' in menu && menu.children?.length) {
|
|
1697
|
+
matchedChildren = this.#getMenuByAliasSearchText(menu.children, aliasSearchText);
|
|
1698
|
+
}
|
|
1699
|
+
if (matchedChildren?.length) {
|
|
1700
|
+
result.push({ ...menu, children: matchedChildren });
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
return result;
|
|
1704
|
+
};
|
|
1705
|
+
#matchesTitleInitials = (aliasTitle, aliasSearchText) => {
|
|
1706
|
+
const initials = aliasTitle
|
|
1707
|
+
.split(' ')
|
|
1708
|
+
.filter(word => word)
|
|
1709
|
+
.map(word => word[0])
|
|
1710
|
+
.join('');
|
|
1711
|
+
return this.#isOrderedSubsequence(aliasSearchText, initials);
|
|
1712
|
+
};
|
|
1713
|
+
#isOrderedSubsequence = (needle, haystack) => {
|
|
1714
|
+
let matchedCount = 0;
|
|
1715
|
+
for (const char of haystack) {
|
|
1716
|
+
if (char === needle[matchedCount]) {
|
|
1717
|
+
matchedCount++;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
return matchedCount === needle.length;
|
|
1721
|
+
};
|
|
1722
|
+
#closeMenu() {
|
|
1723
|
+
this.showSideBar.emit(null);
|
|
1724
|
+
}
|
|
1725
|
+
#convertColor = (input, opacity = 1) => {
|
|
1726
|
+
if (!input) {
|
|
1727
|
+
return '';
|
|
1728
|
+
}
|
|
1729
|
+
input = input.trim();
|
|
1730
|
+
const hexRegex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
1731
|
+
const rgbRegex = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
|
|
1732
|
+
if (hexRegex.test(input)) {
|
|
1733
|
+
let hex = input.slice(1);
|
|
1734
|
+
if (hex.length === 3) {
|
|
1735
|
+
hex = hex
|
|
1736
|
+
.split('')
|
|
1737
|
+
.map(c => c + c)
|
|
1738
|
+
.join('');
|
|
1739
|
+
}
|
|
1740
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
1741
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
1742
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
1743
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
1744
|
+
}
|
|
1745
|
+
const rgbMatch = input.match(rgbRegex);
|
|
1746
|
+
if (rgbMatch) {
|
|
1747
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1748
|
+
const [_, r, g, b] = rgbMatch;
|
|
1749
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
1750
|
+
}
|
|
1751
|
+
return input;
|
|
1752
|
+
};
|
|
1753
|
+
#getValidSearchText = () => {
|
|
1754
|
+
const normalized = this.#normalizeSearchText(this.searchText());
|
|
1755
|
+
return normalized && normalized.length >= 2 ? normalized : '';
|
|
1756
|
+
};
|
|
1757
|
+
#normalizeSearchText = (searchText) => {
|
|
1758
|
+
let str = searchText?.toString() ?? '';
|
|
1759
|
+
/* eslint-disable no-useless-escape */
|
|
1760
|
+
str = str.replace(/!|@|%|\^|\*|\(|\)|\+|\=|\<|\>|\?|\/|,|\.|\:|\;|\'|\"|\&|\#|\[|\]|~|\$|_|`|-|{|}|\||\\/g, '');
|
|
1761
|
+
str = str.replace(/ + /g, ' ');
|
|
1762
|
+
return str.trim();
|
|
1763
|
+
};
|
|
1764
|
+
#getTotalMenus = (menus) => {
|
|
1765
|
+
return menus.reduce((total, menu) => total + this.#countMenuChildrenNode(menu), 0);
|
|
1766
|
+
};
|
|
1767
|
+
#countMenuChildrenNode = (menu) => {
|
|
1768
|
+
if (!('children' in menu) || !menu.children?.length) {
|
|
1769
|
+
return 0;
|
|
1770
|
+
}
|
|
1771
|
+
let count = menu.children.length;
|
|
1772
|
+
for (const child of menu.children) {
|
|
1773
|
+
count += this.#countMenuChildrenNode(child);
|
|
1774
|
+
}
|
|
1775
|
+
return count;
|
|
1776
|
+
};
|
|
1777
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2PanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1778
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SidebarV2PanelComponent, isStandalone: true, selector: "sd-sidebar-v2-panel", 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();\n@let _sidebar = sidebar();\n@let _isShowSidebar = isShowSidebar();\n@let _searchText = searchText();\n@let _currentPath = currentPath();\n@let _activeMenuPath = activeMenuPath();\n@let _idMenuGroupActive = idMenuGroupActive();\n@let _pinnedMenuGroup = pinnedMenuGroup();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"wrapper\"\n [style.--sidebar-accent]=\"_sidebar.brandColor || 'var(--sd-primary, #005cbb)'\"\n [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!_isShowSidebar\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && _pinnedMenuGroup.children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, _pinnedMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, _pinnedMenuGroup)\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!_isShowSidebar\" [attr.inert]=\"!_isShowSidebar ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div class=\"c-menu-tree-search\">\n @let _searchLabel = 'core.module.layout.sidebar.search' | translate;\n <div class=\"c-menu-search-field\">\n <mat-icon class=\"c-menu-search-icon\" fontSet=\"material-icons-outlined\" aria-hidden=\"true\">search</mat-icon>\n <input\n #menuSearch\n class=\"c-menu-search-input\"\n type=\"search\"\n autocomplete=\"off\"\n [attr.aria-label]=\"_searchLabel\"\n [placeholder]=\"_searchLabel\"\n [ngModel]=\"_searchText\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onFilterSearchText($event)\" />\n @if (_searchText) {\n <button\n type=\"button\"\n class=\"c-menu-search-clear\"\n [attr.aria-label]=\"'core.module.layout.sidebar.clear-search' | translate\"\n (click)=\"onClearSearchText(); menuSearch.focus()\">\n <mat-icon fontSet=\"material-icons-outlined\" aria-hidden=\"true\">close</mat-icon>\n </button>\n }\n </div>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n [class.is-active]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!_isShowSidebar\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #252c38)',\n }\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: _currentPath | menuFocus: node : _activeMenuPath }\">\n <li>\n <div\n class=\"c-menu-node\"\n [class.is-ancestor]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!_isShowSidebar\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div class=\"c-menu-node-description-content\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"c-menu-node-group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <sd-sidebar-v2-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"_isShowSidebar\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </sd-sidebar-v2-user>\n </div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host{display:block;height:100%}.wrapper{--sidebar-surface: var(--sd-white, #fff);--sidebar-rail: color-mix(in srgb, var(--sd-surface-muted, #e7e8ed) 35%, var(--sidebar-surface));--sidebar-line: color-mix(in srgb, var(--sd-border, #c4c6d0) 45%, var(--sidebar-surface));--sidebar-ink: var(--sd-text, #252c38);--sidebar-muted: var(--sd-text-secondary, #6b7280);position:relative;display:flex;flex-direction:column;width:min(304px,100vw);color:var(--sidebar-ink);background:linear-gradient(to right,var(--sidebar-rail) 56px,var(--sidebar-surface) 56px)}.wrapper,.wrapper *{box-sizing:border-box}.wrapper:before{content:\"\";position:absolute;inset:0 auto 0 55px;width:1px;background:var(--sidebar-line);pointer-events:none}.c-header{flex:0 0 auto;display:grid;grid-template-columns:56px minmax(0,1fr);min-height:42px}.c-logo{grid-column:1;display:grid;place-items:center;height:42px}.c-logo a{display:grid;place-items:center;width:38px;height:40px;border-radius:9px;color:var(--sidebar-muted)}.c-logo img{width:30px;height:30px;object-fit:contain}.c-title-menu-group{grid-column:2;display:flex;align-items:center;min-width:0;padding:10px 14px 12px;color:var(--sidebar-ink);font-size:16px;font-weight:700;line-height:22px;letter-spacing:-.2px;overflow-wrap:anywhere}.c-body{flex:1;min-height:0;overflow:hidden}.c-menu{display:flex;height:100%}.c-menu-group{display:flex;flex:0 0 56px;flex-direction:column;align-items:center;gap:10px;width:56px;min-height:0;margin-bottom:86px;padding:5px 0 8px;overflow-y:auto;scrollbar-width:none}.c-menu-group>button{flex:0 0 auto;border-radius:9px}.c-menu-group .c-menu-group-icon{display:flex;align-items:center;justify-content:center;width:38px;height:40px;min-height:40px;border-radius:9px;font-size:22px}.c-menu-group .c-menu-group-icon img{width:22px;height:22px;object-fit:contain}.c-menu-tree{display:flex;flex:1;flex-direction:column;min-width:0;min-height:0}.c-menu-tree-search{flex:0 0 auto;padding:0 14px 12px;border-bottom:1px solid var(--sidebar-line)}.c-menu-search-field{display:flex;align-items:center;gap:8px;height:36px;padding:0 9px;border:1px solid var(--sidebar-line);border-radius:7px;background:var(--sidebar-rail);color:var(--sidebar-muted)}.c-menu-search-field:hover{border-color:color-mix(in srgb,var(--sidebar-muted) 35%,var(--sidebar-surface))}.c-menu-search-field:focus-within{border-color:color-mix(in srgb,var(--sidebar-accent, var(--sd-primary, #005cbb)) 75%,var(--sidebar-surface));background:var(--sidebar-surface)}.c-menu-search-icon{flex:0 0 18px;width:18px;height:18px;font-size:18px;pointer-events:none}.c-menu-search-input{flex:1 1 0;width:0;min-width:0;height:100%;margin:0;padding:0;border:0;border-radius:0;outline:none;box-shadow:none;appearance:none;background:transparent;color:var(--sidebar-ink);font:inherit;font-size:13px;line-height:20px}.c-menu-search-input:focus,.c-menu-search-input:focus-visible{outline:none;box-shadow:none}.c-menu-search-input::placeholder{color:var(--sidebar-muted);opacity:1}.c-menu-search-input::-webkit-search-decoration,.c-menu-search-input::-webkit-search-cancel-button{appearance:none}.c-menu-search-clear{display:grid;flex:0 0 24px;place-items:center;width:24px;min-width:24px;height:24px;margin:0;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);cursor:pointer}.c-menu-search-clear sd-icon,.c-menu-search-clear mat-icon{width:18px;height:18px;font-size:18px}.c-menu-search-clear:hover{background:color-mix(in srgb,var(--sidebar-ink) 7%,transparent);color:var(--sidebar-ink)}.c-menu-search-clear:focus-visible{outline:1px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:1px}.c-menu-tree-container{flex:1;min-height:0;padding:10px 8px 14px;overflow:auto;scrollbar-width:thin;scrollbar-color:var(--sidebar-line) transparent;overscroll-behavior:contain}.c-menu-node{position:relative;display:flex;align-items:center;width:100%;min-height:40px;margin:2px 0;padding:0;border-radius:7px;cursor:pointer;color:var(--sidebar-ink);font-size:13px;line-height:1.4}.c-menu-node-description{display:flex;flex:1;align-items:center;gap:6px;width:100%;min-width:0;min-height:40px;padding:0;border:0;border-radius:inherit;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.c-menu-node-description-content{display:flex;flex:1;align-items:center;align-self:stretch;gap:9px;min-width:0;padding:8px;color:inherit;font:inherit;font-weight:500;text-decoration:none}.c-menu-node-label{flex:1;min-width:0;white-space:normal;overflow-wrap:anywhere}.c-menu-node-icon{flex:0 0 20px;width:20px;height:20px;font-size:20px;object-fit:contain;color:var(--sidebar-muted)}.c-menu-node-description-icon-expand,.c-menu-node-description-icon-pin{display:flex;flex:0 0 20px;align-items:center;justify-content:center;width:20px;height:24px;margin-right:6px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);font-size:18px;cursor:pointer}.c-menu-node-description-icon-pin{opacity:0}.c-menu-node-description-icon-pin:focus-visible{opacity:1!important}.c-menu-node.is-ancestor{color:var(--sidebar-accent)}.c-menu-node.is-ancestor .c-menu-node-description-content,.c-menu-node.is-ancestor .c-menu-node-icon,.c-menu-node.is-ancestor .c-menu-node-description-icon-expand{color:inherit}.c-menu-node.is-active{color:var(--sidebar-accent)}.c-menu-node.is-active .c-menu-node-icon{color:inherit}.c-menu-node.is-active:before{content:\"\";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--sidebar-accent)}.c-menu-node-group{position:relative;margin:0 0 7px 19px;padding:1px 0 1px 16px;border-left:1px solid var(--sidebar-line)}.c-menu-node-group .c-menu-node{min-height:34px;border-radius:6px}.c-menu-node-group .c-menu-node-description-content{padding:7px 8px;font-weight:400}.c-menu-node-group .c-menu-node-description{min-height:34px}.c-menu-node-group .c-menu-node-icon{display:none}.c-menu-node-group .c-menu-node.is-active:before{left:-18px}.c-menu-node-group .c-menu-node.is-active .c-menu-node-description-content,.c-menu-node-group .c-menu-node.is-ancestor .c-menu-node-description-content{font-weight:500}.c-menu-node-group .c-menu-node-group{margin-left:8px;padding-left:7px}.c-menu-node-group .c-menu-node-group .c-menu-node.is-active:before{left:-9px}.c-footer{position:absolute;bottom:0;left:0;width:56px;height:86px;background:var(--sidebar-rail)}a:focus-visible,button:focus-visible{outline:2px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:-2px}@media(pointer:coarse){.c-menu-node,.c-menu-node-group .c-menu-node,.c-menu-node-description,.c-menu-node-group .c-menu-node-description{min-height:44px}}@media(prefers-reduced-motion:reduce){.c-menu-group-icon,.c-menu-node,.c-menu-node *{transition:none!important}}ul,li{margin-top:0;margin-bottom:0;list-style:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "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: "component", type: SidebarV2UserComponent, selector: "sd-sidebar-v2-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1779
|
+
}
|
|
1780
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2PanelComponent, decorators: [{
|
|
1781
|
+
type: Component,
|
|
1782
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sd-sidebar-v2-panel', standalone: true, imports: [
|
|
1783
|
+
FormsModule,
|
|
1784
|
+
CommonModule,
|
|
1785
|
+
RouterModule,
|
|
1786
|
+
MatIconModule,
|
|
1787
|
+
MatTreeModule,
|
|
1788
|
+
SdSafeHtmlPipe,
|
|
1789
|
+
MenuFocusPipe,
|
|
1790
|
+
MatTooltipModule,
|
|
1791
|
+
HighlightSearchPipe,
|
|
1792
|
+
SidebarV2UserComponent,
|
|
1793
|
+
TranslatePipe,
|
|
1794
|
+
], template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n@let _isShowSidebar = isShowSidebar();\n@let _searchText = searchText();\n@let _currentPath = currentPath();\n@let _activeMenuPath = activeMenuPath();\n@let _idMenuGroupActive = idMenuGroupActive();\n@let _pinnedMenuGroup = pinnedMenuGroup();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"wrapper\"\n [style.--sidebar-accent]=\"_sidebar.brandColor || 'var(--sd-primary, #005cbb)'\"\n [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\" [class.d-none]=\"!_isShowSidebar\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && _pinnedMenuGroup.children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, _pinnedMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, _pinnedMenuGroup)\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n fontSet=\"material-icons-outlined\"\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #6b7280)',\n backgroundColor:\n _idMenuGroupActive === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!_isShowSidebar\" [attr.inert]=\"!_isShowSidebar ? '' : null\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div class=\"c-menu-tree-search\">\n @let _searchLabel = 'core.module.layout.sidebar.search' | translate;\n <div class=\"c-menu-search-field\">\n <mat-icon class=\"c-menu-search-icon\" fontSet=\"material-icons-outlined\" aria-hidden=\"true\">search</mat-icon>\n <input\n #menuSearch\n class=\"c-menu-search-input\"\n type=\"search\"\n autocomplete=\"off\"\n [attr.aria-label]=\"_searchLabel\"\n [placeholder]=\"_searchLabel\"\n [ngModel]=\"_searchText\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onFilterSearchText($event)\" />\n @if (_searchText) {\n <button\n type=\"button\"\n class=\"c-menu-search-clear\"\n [attr.aria-label]=\"'core.module.layout.sidebar.clear-search' | translate\"\n (click)=\"onClearSearchText(); menuSearch.focus()\">\n <mat-icon fontSet=\"material-icons-outlined\" aria-hidden=\"true\">close</mat-icon>\n </button>\n }\n </div>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n [class.is-active]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!_isShowSidebar\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color:\n (_currentPath | menuFocus: node : _activeMenuPath)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #252c38)',\n }\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: _currentPath | menuFocus: node : _activeMenuPath }\">\n <li>\n <div\n class=\"c-menu-node\"\n [class.is-ancestor]=\"_currentPath | menuFocus: node : _activeMenuPath\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!_isShowSidebar\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div class=\"c-menu-node-description-content\">\n @if (node.iconUrl) {\n <img class=\"c-menu-node-icon\" [src]=\"node.iconUrl\" alt=\"\" />\n } @else if (node.icon) {\n <mat-icon class=\"c-menu-node-icon\" fontSet=\"material-icons-outlined\">{{ node.icon }}</mat-icon>\n }\n <span class=\"c-menu-node-label\" [innerHTML]=\"node.title | highLightSearch: _searchText | sdSafeHtml\"></span>\n </div>\n <mat-icon fontSet=\"material-icons-outlined\" class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"c-menu-node-group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <sd-sidebar-v2-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"_isShowSidebar\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </sd-sidebar-v2-user>\n </div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host{display:block;height:100%}.wrapper{--sidebar-surface: var(--sd-white, #fff);--sidebar-rail: color-mix(in srgb, var(--sd-surface-muted, #e7e8ed) 35%, var(--sidebar-surface));--sidebar-line: color-mix(in srgb, var(--sd-border, #c4c6d0) 45%, var(--sidebar-surface));--sidebar-ink: var(--sd-text, #252c38);--sidebar-muted: var(--sd-text-secondary, #6b7280);position:relative;display:flex;flex-direction:column;width:min(304px,100vw);color:var(--sidebar-ink);background:linear-gradient(to right,var(--sidebar-rail) 56px,var(--sidebar-surface) 56px)}.wrapper,.wrapper *{box-sizing:border-box}.wrapper:before{content:\"\";position:absolute;inset:0 auto 0 55px;width:1px;background:var(--sidebar-line);pointer-events:none}.c-header{flex:0 0 auto;display:grid;grid-template-columns:56px minmax(0,1fr);min-height:42px}.c-logo{grid-column:1;display:grid;place-items:center;height:42px}.c-logo a{display:grid;place-items:center;width:38px;height:40px;border-radius:9px;color:var(--sidebar-muted)}.c-logo img{width:30px;height:30px;object-fit:contain}.c-title-menu-group{grid-column:2;display:flex;align-items:center;min-width:0;padding:10px 14px 12px;color:var(--sidebar-ink);font-size:16px;font-weight:700;line-height:22px;letter-spacing:-.2px;overflow-wrap:anywhere}.c-body{flex:1;min-height:0;overflow:hidden}.c-menu{display:flex;height:100%}.c-menu-group{display:flex;flex:0 0 56px;flex-direction:column;align-items:center;gap:10px;width:56px;min-height:0;margin-bottom:86px;padding:5px 0 8px;overflow-y:auto;scrollbar-width:none}.c-menu-group>button{flex:0 0 auto;border-radius:9px}.c-menu-group .c-menu-group-icon{display:flex;align-items:center;justify-content:center;width:38px;height:40px;min-height:40px;border-radius:9px;font-size:22px}.c-menu-group .c-menu-group-icon img{width:22px;height:22px;object-fit:contain}.c-menu-tree{display:flex;flex:1;flex-direction:column;min-width:0;min-height:0}.c-menu-tree-search{flex:0 0 auto;padding:0 14px 12px;border-bottom:1px solid var(--sidebar-line)}.c-menu-search-field{display:flex;align-items:center;gap:8px;height:36px;padding:0 9px;border:1px solid var(--sidebar-line);border-radius:7px;background:var(--sidebar-rail);color:var(--sidebar-muted)}.c-menu-search-field:hover{border-color:color-mix(in srgb,var(--sidebar-muted) 35%,var(--sidebar-surface))}.c-menu-search-field:focus-within{border-color:color-mix(in srgb,var(--sidebar-accent, var(--sd-primary, #005cbb)) 75%,var(--sidebar-surface));background:var(--sidebar-surface)}.c-menu-search-icon{flex:0 0 18px;width:18px;height:18px;font-size:18px;pointer-events:none}.c-menu-search-input{flex:1 1 0;width:0;min-width:0;height:100%;margin:0;padding:0;border:0;border-radius:0;outline:none;box-shadow:none;appearance:none;background:transparent;color:var(--sidebar-ink);font:inherit;font-size:13px;line-height:20px}.c-menu-search-input:focus,.c-menu-search-input:focus-visible{outline:none;box-shadow:none}.c-menu-search-input::placeholder{color:var(--sidebar-muted);opacity:1}.c-menu-search-input::-webkit-search-decoration,.c-menu-search-input::-webkit-search-cancel-button{appearance:none}.c-menu-search-clear{display:grid;flex:0 0 24px;place-items:center;width:24px;min-width:24px;height:24px;margin:0;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);cursor:pointer}.c-menu-search-clear sd-icon,.c-menu-search-clear mat-icon{width:18px;height:18px;font-size:18px}.c-menu-search-clear:hover{background:color-mix(in srgb,var(--sidebar-ink) 7%,transparent);color:var(--sidebar-ink)}.c-menu-search-clear:focus-visible{outline:1px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:1px}.c-menu-tree-container{flex:1;min-height:0;padding:10px 8px 14px;overflow:auto;scrollbar-width:thin;scrollbar-color:var(--sidebar-line) transparent;overscroll-behavior:contain}.c-menu-node{position:relative;display:flex;align-items:center;width:100%;min-height:40px;margin:2px 0;padding:0;border-radius:7px;cursor:pointer;color:var(--sidebar-ink);font-size:13px;line-height:1.4}.c-menu-node-description{display:flex;flex:1;align-items:center;gap:6px;width:100%;min-width:0;min-height:40px;padding:0;border:0;border-radius:inherit;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.c-menu-node-description-content{display:flex;flex:1;align-items:center;align-self:stretch;gap:9px;min-width:0;padding:8px;color:inherit;font:inherit;font-weight:500;text-decoration:none}.c-menu-node-label{flex:1;min-width:0;white-space:normal;overflow-wrap:anywhere}.c-menu-node-icon{flex:0 0 20px;width:20px;height:20px;font-size:20px;object-fit:contain;color:var(--sidebar-muted)}.c-menu-node-description-icon-expand,.c-menu-node-description-icon-pin{display:flex;flex:0 0 20px;align-items:center;justify-content:center;width:20px;height:24px;margin-right:6px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--sidebar-muted);font-size:18px;cursor:pointer}.c-menu-node-description-icon-pin{opacity:0}.c-menu-node-description-icon-pin:focus-visible{opacity:1!important}.c-menu-node.is-ancestor{color:var(--sidebar-accent)}.c-menu-node.is-ancestor .c-menu-node-description-content,.c-menu-node.is-ancestor .c-menu-node-icon,.c-menu-node.is-ancestor .c-menu-node-description-icon-expand{color:inherit}.c-menu-node.is-active{color:var(--sidebar-accent)}.c-menu-node.is-active .c-menu-node-icon{color:inherit}.c-menu-node.is-active:before{content:\"\";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--sidebar-accent)}.c-menu-node-group{position:relative;margin:0 0 7px 19px;padding:1px 0 1px 16px;border-left:1px solid var(--sidebar-line)}.c-menu-node-group .c-menu-node{min-height:34px;border-radius:6px}.c-menu-node-group .c-menu-node-description-content{padding:7px 8px;font-weight:400}.c-menu-node-group .c-menu-node-description{min-height:34px}.c-menu-node-group .c-menu-node-icon{display:none}.c-menu-node-group .c-menu-node.is-active:before{left:-18px}.c-menu-node-group .c-menu-node.is-active .c-menu-node-description-content,.c-menu-node-group .c-menu-node.is-ancestor .c-menu-node-description-content{font-weight:500}.c-menu-node-group .c-menu-node-group{margin-left:8px;padding-left:7px}.c-menu-node-group .c-menu-node-group .c-menu-node.is-active:before{left:-9px}.c-footer{position:absolute;bottom:0;left:0;width:56px;height:86px;background:var(--sidebar-rail)}a:focus-visible,button:focus-visible{outline:2px solid var(--sidebar-accent, var(--sd-primary, #005cbb));outline-offset:-2px}@media(pointer:coarse){.c-menu-node,.c-menu-node-group .c-menu-node,.c-menu-node-description,.c-menu-node-group .c-menu-node-description{min-height:44px}}@media(prefers-reduced-motion:reduce){.c-menu-group-icon,.c-menu-node,.c-menu-node *{transition:none!important}}ul,li{margin-top:0;margin-bottom:0;list-style:none}\n"] }]
|
|
1795
|
+
}], ctorParameters: () => [] });
|
|
1796
|
+
|
|
1797
|
+
class SidebarV2Component {
|
|
1798
|
+
// ==========================================
|
|
1799
|
+
// INJECT SERVICES
|
|
1800
|
+
// ==========================================
|
|
1801
|
+
#layoutStorageService = inject(SdLayoutStorageService);
|
|
1802
|
+
// ==========================================
|
|
1803
|
+
// VIEW CHILD & INPUTS
|
|
1804
|
+
// ==========================================
|
|
1805
|
+
sidenav = viewChild.required('sidenav');
|
|
1806
|
+
menus = input([]);
|
|
1807
|
+
userInfo = input.required();
|
|
1808
|
+
sidebar = input.required();
|
|
1809
|
+
// ==========================================
|
|
1810
|
+
// STATE SIGNALS
|
|
1811
|
+
// ==========================================
|
|
1812
|
+
isMobileOrTablet = signal(BrowserUtilities.isMobile());
|
|
1813
|
+
// Trạng thái khóa menu (luôn mở rộng hay không)
|
|
1814
|
+
isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true);
|
|
1815
|
+
// Trạng thái hiển thị (mở/đóng) của Sidenav
|
|
1816
|
+
isShowSidebar = signal(BrowserUtilities.isMobile() ? false : (this.#layoutStorageService.menuLockStatus?.get() ?? true));
|
|
1817
|
+
onhover = signal(false);
|
|
1818
|
+
// ==========================================
|
|
1819
|
+
// PRIVATE TIMERS
|
|
1820
|
+
// ==========================================
|
|
1821
|
+
#timerMouseInMenu = null;
|
|
1822
|
+
constructor() {
|
|
1823
|
+
// EFFECT: Tự động đồng bộ isShowSidebar vào storage service mỗi khi nó thay đổi
|
|
1824
|
+
effect(() => {
|
|
1825
|
+
const isShow = this.isShowSidebar();
|
|
1826
|
+
untracked(() => {
|
|
1827
|
+
this.#layoutStorageService.isShowSidebar.set(isShow);
|
|
1828
|
+
});
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
// ==========================================
|
|
1832
|
+
// EVENT HANDLERS
|
|
1833
|
+
// ==========================================
|
|
1834
|
+
#mouseLeave = () => {
|
|
1835
|
+
if (this.#timerMouseInMenu) {
|
|
1836
|
+
clearTimeout(this.#timerMouseInMenu);
|
|
1837
|
+
}
|
|
1838
|
+
if (this.onhover() && this.isShowSidebar()) {
|
|
1839
|
+
this.isShowSidebar.set(false);
|
|
1840
|
+
this.onhover.set(false);
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
#handleMouseLeaveTransition = () => {
|
|
1844
|
+
if (!this.isShowSidebar()) {
|
|
1845
|
+
const delayTime = 400;
|
|
1846
|
+
if (this.#timerMouseInMenu) {
|
|
1847
|
+
clearTimeout(this.#timerMouseInMenu);
|
|
1848
|
+
}
|
|
1849
|
+
setTimeout(() => {
|
|
1850
|
+
this.#mouseLeave();
|
|
1851
|
+
}, delayTime);
|
|
1852
|
+
}
|
|
1853
|
+
else {
|
|
1854
|
+
this.#mouseLeave();
|
|
1855
|
+
}
|
|
1856
|
+
};
|
|
1857
|
+
openSidebar = () => {
|
|
1858
|
+
if (!this.isMobileOrTablet()) {
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
if (!this.isShowSidebar()) {
|
|
1862
|
+
this.isShowSidebar.set(true);
|
|
1863
|
+
this.onhover.set(true);
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
onPopupOfSideBarOpened = () => {
|
|
1867
|
+
this.onhover.set(false);
|
|
1868
|
+
this.isShowSidebar.set(true);
|
|
1869
|
+
};
|
|
1870
|
+
onPopupOfSideBarClosed = () => {
|
|
1871
|
+
const delayTime = 500;
|
|
1872
|
+
if (!this.isMenuLock()) {
|
|
1873
|
+
this.onhover.set(true);
|
|
1874
|
+
setTimeout(() => {
|
|
1875
|
+
this.#mouseLeave();
|
|
1876
|
+
}, delayTime);
|
|
1877
|
+
}
|
|
1878
|
+
};
|
|
1879
|
+
onExpandSideBar = () => {
|
|
1880
|
+
if (this.isMobileOrTablet()) {
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
if (!this.isShowSidebar()) {
|
|
1884
|
+
this.isShowSidebar.set(true);
|
|
1885
|
+
this.onhover.set(true);
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
onMouseleaveSideBar = () => {
|
|
1889
|
+
if (this.isMobileOrTablet()) {
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
this.#mouseLeave();
|
|
1893
|
+
};
|
|
1894
|
+
onSidenavOpenedChange = (opened) => {
|
|
1895
|
+
if (this.isMobileOrTablet()) {
|
|
1896
|
+
this.isShowSidebar.set(opened);
|
|
1897
|
+
}
|
|
1898
|
+
};
|
|
1899
|
+
onToggle = (data) => {
|
|
1900
|
+
if (data === null) {
|
|
1901
|
+
this.#handleMouseLeaveTransition();
|
|
1902
|
+
}
|
|
1903
|
+
else {
|
|
1904
|
+
this.#mouseLeave();
|
|
1905
|
+
this.isShowSidebar.set(data);
|
|
1906
|
+
this.isMenuLock.set(data);
|
|
1907
|
+
// Toggle component MatSidenav
|
|
1908
|
+
if (this.isMobileOrTablet()) {
|
|
1909
|
+
const sidenavComp = this.sidenav();
|
|
1910
|
+
if (sidenavComp) {
|
|
1911
|
+
if (data) {
|
|
1912
|
+
sidenavComp.open();
|
|
1913
|
+
}
|
|
1914
|
+
else {
|
|
1915
|
+
sidenavComp.close();
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1922
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.21", type: SidebarV2Component, isStandalone: true, selector: "sd-sidebar-v2", 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 } }, viewQueries: [{ propertyName: "sidenav", first: true, predicate: ["sidenav"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sd-sidebar-v2-panel\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sd-sidebar-v2-panel>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:56px;height:100vh!important;transform:none!important;overflow:hidden!important;overflow:clip!important;visibility:visible!important;transition:width .15s!important;box-shadow:none!important;border-right:1px solid color-mix(in srgb,var(--sd-border, #c4c6d0) 45%,white);border-radius:0;box-sizing:border-box}: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.is-expanded{width:min(304px,100vw);transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:56px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:min(304px,100vw)!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}@media(prefers-reduced-motion:reduce){:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{transition:none!important}}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$4.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i1$4.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i1$4.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$4.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$4.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarV2PanelComponent, selector: "sd-sidebar-v2-panel", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["expandSideBar", "popupUserMenuClosed", "popupUserMenuOpened", "showSideBar"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1923
|
+
}
|
|
1924
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarV2Component, decorators: [{
|
|
1925
|
+
type: Component,
|
|
1926
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sd-sidebar-v2', imports: [MatSidenavModule, CommonModule, SidebarV2PanelComponent], standalone: true, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"!isMobileOrTablet() || isShowSidebar()\"\n (openedChange)=\"onSidenavOpenedChange($event)\"\n class=\"c-layout-sidebar\"\n [class.is-expanded]=\"isShowSidebar()\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sd-sidebar-v2-panel\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sd-sidebar-v2-panel>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>\n", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:56px;height:100vh!important;transform:none!important;overflow:hidden!important;overflow:clip!important;visibility:visible!important;transition:width .15s!important;box-shadow:none!important;border-right:1px solid color-mix(in srgb,var(--sd-border, #c4c6d0) 45%,white);border-radius:0;box-sizing:border-box}: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.is-expanded{width:min(304px,100vw);transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:56px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:min(304px,100vw)!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}@media(prefers-reduced-motion:reduce){:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{transition:none!important}}\n"] }]
|
|
1186
1927
|
}], ctorParameters: () => [] });
|
|
1187
1928
|
|
|
1188
1929
|
class LayoutUserComponent {
|
|
@@ -1236,7 +1977,7 @@ class LayoutUserComponent {
|
|
|
1236
1977
|
this.toggleMenuLock.emit(event);
|
|
1237
1978
|
};
|
|
1238
1979
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1239
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n@if (isMobileOrTablet()) {\n <!-- Mobile: accordion inline expand -->\n <div class=\"m-user-card\">\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\n <div class=\"m-user-info\">\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n @if (_userInfo?.email) {\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\n }\n </div>\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\n keyboard_arrow_down\n </mat-icon>\n </button>\n\n @if (isExpanded()) {\n <div class=\"m-user-body\">\n @if (changePasswordLayoutConfig) {\n <button class=\"m-user-action\" (click)=\"changePassword()\">\n <mat-icon>lock_outline</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n }\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\n <mat-icon>logout</mat-icon>\n <span>{{ 'core.module.layout.user.logout' | translate }}</span>\n </button>\n </div>\n }\n </div>\n} @else {\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\n <div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n </div>\n}\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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:
|
|
1980
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n@if (isMobileOrTablet()) {\n <!-- Mobile: accordion inline expand -->\n <div class=\"m-user-card\">\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\n <div class=\"m-user-info\">\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n @if (_userInfo?.email) {\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\n }\n </div>\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\n keyboard_arrow_down\n </mat-icon>\n </button>\n\n @if (isExpanded()) {\n <div class=\"m-user-body\">\n @if (changePasswordLayoutConfig) {\n <button class=\"m-user-action\" (click)=\"changePassword()\">\n <mat-icon>lock_outline</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n }\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\n <mat-icon>logout</mat-icon>\n <span>{{ 'core.module.layout.user.logout' | translate }}</span>\n </button>\n </div>\n }\n </div>\n} @else {\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\n <div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n </div>\n}\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\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 mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1240
1981
|
}
|
|
1241
1982
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LayoutUserComponent, decorators: [{
|
|
1242
1983
|
type: Component,
|
|
@@ -1390,7 +2131,7 @@ class SidebarMobileOverlayComponent {
|
|
|
1390
2131
|
return null;
|
|
1391
2132
|
};
|
|
1392
2133
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarMobileOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1393
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"m-backdrop\"\n [class.m-backdrop--visible]=\"isShowSidebar()\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onClose()\"\n (keydown.escape)=\"onClose()\">\n </div>\n\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\n <div class=\"m-header\">\n <div class=\"m-title-group\">\n @if (_sidebar.logoUrl) {\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n }\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"m-close-btn\" (click)=\"onClose()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <div class=\"m-user-section\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"true\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\">\n </lib-layout-user>\n </div>\n\n <div class=\"m-menu-list\">\n @for (group of menus(); track group.id) {\n <div class=\"m-menu-card\">\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\n <div class=\"m-card-header-left\">\n @if (group.iconUrl) {\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\n } @else {\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\n }\n <span class=\"m-group-title\">{{ group.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\n <div class=\"m-card-body\">\n @for (child of getChildren(group); track child.id) {\n @if (hasChildren(child)) {\n <div class=\"m-sub-group\">\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n @if (expandedMobileGroups().has(child.id ?? '')) {\n @for (subChild of getChildren(child); track subChild.id) {\n <button class=\"m-menu-item m-menu-item--indented\"\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\n <div class=\"m-item-left\">\n @if (subChild.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ subChild.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n } @else {\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n}\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: i1$3.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"] }] });
|
|
2134
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"m-backdrop\"\n [class.m-backdrop--visible]=\"isShowSidebar()\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onClose()\"\n (keydown.escape)=\"onClose()\">\n </div>\n\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\n <div class=\"m-header\">\n <div class=\"m-title-group\">\n @if (_sidebar.logoUrl) {\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n }\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"m-close-btn\" (click)=\"onClose()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <div class=\"m-user-section\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"true\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\">\n </lib-layout-user>\n </div>\n\n <div class=\"m-menu-list\">\n @for (group of menus(); track group.id) {\n <div class=\"m-menu-card\">\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\n <div class=\"m-card-header-left\">\n @if (group.iconUrl) {\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\n } @else {\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\n }\n <span class=\"m-group-title\">{{ group.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\n <div class=\"m-card-body\">\n @for (child of getChildren(group); track child.id) {\n @if (hasChildren(child)) {\n <div class=\"m-sub-group\">\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n @if (expandedMobileGroups().has(child.id ?? '')) {\n @for (subChild of getChildren(child); track subChild.id) {\n <button class=\"m-menu-item m-menu-item--indented\"\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\n <div class=\"m-item-left\">\n @if (subChild.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ subChild.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n } @else {\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n}\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"] }] });
|
|
1394
2135
|
}
|
|
1395
2136
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarMobileOverlayComponent, decorators: [{
|
|
1396
2137
|
type: Component,
|
|
@@ -1432,7 +2173,7 @@ class SidebarMobileV1Component {
|
|
|
1432
2173
|
this.titleMenuGroup.set(title);
|
|
1433
2174
|
};
|
|
1434
2175
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarMobileV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1435
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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\">\n <div class=\"c-mobile-topbar\">\n <div class=\"c-topbar-brand\">\n @if (sidebar().logoUrl) {\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\n }\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\n <mat-icon>menu</mat-icon>\n </button>\n </div>\n\n <div class=\"c-mobile-content\">\n <ng-content></ng-content>\n </div>\n\n <sd-sidebar-mobile-overlay\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\n </sd-sidebar-mobile-overlay>\n</div>\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:
|
|
2176
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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\">\n <div class=\"c-mobile-topbar\">\n <div class=\"c-topbar-brand\">\n @if (sidebar().logoUrl) {\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\n }\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\n <mat-icon>menu</mat-icon>\n </button>\n </div>\n\n <div class=\"c-mobile-content\">\n <ng-content></ng-content>\n </div>\n\n <sd-sidebar-mobile-overlay\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\n </sd-sidebar-mobile-overlay>\n</div>\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"] }] });
|
|
1436
2177
|
}
|
|
1437
2178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SidebarMobileV1Component, decorators: [{
|
|
1438
2179
|
type: Component,
|
|
@@ -1457,11 +2198,11 @@ class SdLayoutComponent {
|
|
|
1457
2198
|
sidebar = this.#layoutService.sidebar;
|
|
1458
2199
|
isMobileOrTablet = signal(BrowserUtilities.isMobile());
|
|
1459
2200
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1460
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar
|
|
2201
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", 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>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n @let _menus = menus();\n @if (isMobileOrTablet()) {\n <sidebar-mobile-v1 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-mobile-v1>\n } @else {\n @switch (_sidebar.version) {\n @case (1) {\n <sidebar-v1 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-v1>\n }\n @case (2) {\n <sd-sidebar-v2 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sd-sidebar-v2>\n }\n }\n }\n}\n", styles: [""], dependencies: [{ kind: "component", type: SidebarV1Component, selector: "sidebar-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "component", type: SidebarV2Component, selector: "sd-sidebar-v2", 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"] }] });
|
|
1461
2202
|
}
|
|
1462
2203
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLayoutComponent, decorators: [{
|
|
1463
2204
|
type: Component,
|
|
1464
|
-
args: [{ selector: 'sd-layout', imports: [SidebarV1Component, SidebarMobileV1Component, NgTemplateOutlet], standalone: true, template: "<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar
|
|
2205
|
+
args: [{ selector: 'sd-layout', imports: [SidebarV1Component, SidebarV2Component, SidebarMobileV1Component, NgTemplateOutlet], standalone: true, template: "<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n @let _menus = menus();\n @if (isMobileOrTablet()) {\n <sidebar-mobile-v1 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-mobile-v1>\n } @else {\n @switch (_sidebar.version) {\n @case (1) {\n <sidebar-v1 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-v1>\n }\n @case (2) {\n <sd-sidebar-v2 [menus]=\"_menus\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sd-sidebar-v2>\n }\n }\n }\n}\n" }]
|
|
1465
2206
|
}] });
|
|
1466
2207
|
|
|
1467
2208
|
// End
|
|
@@ -1521,7 +2262,7 @@ let HomePageComponent = class HomePageComponent {
|
|
|
1521
2262
|
return `${formatted} (${this.#getTimezone()})`;
|
|
1522
2263
|
}
|
|
1523
2264
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HomePageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1524
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HomePageComponent, isStandalone: true, selector: "app-home-page", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">\n {{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}\n </div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"wrapper\">\n <div class=\"bento\">\n <!-- Hero -->\n <div class=\"card hero-card\">\n <div class=\"hero-ring ring-3\"></div>\n <div class=\"hero-ring ring-2\"></div>\n <div class=\"hero-ring ring-1\"></div>\n <div class=\"hero-core\">\n <mat-icon class=\"hero-icon\">space_dashboard</mat-icon>\n </div>\n <div class=\"hero-decoration\">\n <span class=\"dot d1\"></span>\n <span class=\"dot d2\"></span>\n <span class=\"dot d3\"></span>\n </div>\n </div>\n\n <!-- Features -->\n @for (feature of features; track feature.key; let i = $index) {\n <div\n class=\"card feature-card\"\n [class.feature-wide]=\"feature.area === 'audit' || feature.area === 'integ'\"\n [style.gridArea]=\"feature.area\"\n [style.animation-delay.ms]=\"(i + 1) * 80\"\n >\n <div class=\"feature-accent\"></div>\n <div class=\"feature-content\">\n <div class=\"feature-icon-wrap\">\n <mat-icon class=\"feature-icon\">{{ feature.icon }}</mat-icon>\n </div>\n <span class=\"feature-label\">{{ feature.key | translate }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n</sd-page>\n", styles: [":host{display:contents}.wrapper{display:flex;align-items:center;justify-content:center;padding:32px 24px;height:100%;width:100%;background:radial-gradient(circle at 15% 25%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 14%,transparent),transparent 55%),radial-gradient(circle at 85% 75%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 10%,transparent),transparent 55%),linear-gradient(135deg,#fafbfc,#f4f6fa);overflow:auto}.bento{display:grid;width:100%;max-width:1080px;gap:16px;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,minmax(140px,1fr));grid-template-areas:\"hero hero data report\" \"hero hero users flow\" \"audit audit integ integ\"}.card{position:relative;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:20px;overflow:hidden;opacity:0;transform:translateY(8px);animation:card-in .5s ease-out forwards;transition:transform .3s ease,box-shadow .3s ease}.card:hover{transform:translateY(-4px);box-shadow:0 16px 40px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,transparent),0 4px 12px #0000000f}.hero-card{grid-area:hero;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,white),#fff 60%),#fff;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 15%,transparent)}.hero-card .hero-ring{position:absolute;border-radius:50%;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 25%,transparent);animation:hero-pulse 3s ease-in-out infinite;pointer-events:none}.hero-card .hero-ring.ring-1{inset:calc(50% - 70px);animation-delay:0s}.hero-card .hero-ring.ring-2{inset:calc(50% - 105px);animation-delay:.6s}.hero-card .hero-ring.ring-3{inset:calc(50% - 140px);animation-delay:1.2s}.hero-card .hero-core{position:relative;z-index:1;width:140px;height:140px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 22%,white),#fff);box-shadow:0 0 60px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 30%,transparent),0 10px 30px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 20%,transparent)}.hero-card .hero-icon{font-size:72px;width:72px;height:72px;color:var(--mat-sys-primary, #1f49bf)}.hero-card .hero-decoration{position:absolute;inset:0;pointer-events:none}.hero-card .hero-decoration .dot{position:absolute;width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 50%,transparent);animation:dot-float 4s ease-in-out infinite}.hero-card .hero-decoration .d1{top:16%;left:12%;animation-delay:0s}.hero-card .hero-decoration .d2{bottom:20%;right:14%;animation-delay:1s}.hero-card .hero-decoration .d3{top:60%;left:80%;animation-delay:2s;width:5px;height:5px}.feature-card{display:flex;align-items:stretch;cursor:default}.feature-card .feature-accent{position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent),var(--mat-sys-primary, #1f49bf),color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent))}.feature-card .feature-content{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 18px;gap:10px}.feature-card .feature-icon-wrap{width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 12%,white);display:flex;align-items:center;justify-content:center}.feature-card .feature-icon{font-size:28px;width:28px;height:28px;color:var(--mat-sys-primary, #1f49bf)}.feature-card .feature-label{font-size:14px;font-weight:500;text-align:center;color:#000000c7;line-height:20px}.feature-card.feature-wide .feature-content{flex-direction:row;justify-content:flex-start;padding:18px 24px;gap:18px}.feature-card.feature-wide .feature-icon-wrap{width:64px;height:64px}.feature-card.feature-wide .feature-icon{font-size:32px;width:32px;height:32px}.feature-card.feature-wide .feature-label{text-align:left;font-size:16px}@keyframes card-in{to{opacity:1;transform:translateY(0)}}@keyframes hero-pulse{0%,to{transform:scale(1);opacity:.7}50%{transform:scale(1.06);opacity:.3}}@keyframes dot-float{0%,to{transform:translateY(0);opacity:.8}50%{transform:translateY(-8px);opacity:.4}}@media(max-width:1024px){.bento{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(4,minmax(120px,1fr));grid-template-areas:\"hero hero data\" \"hero hero report\" \"users flow audit\" \"integ integ integ\"}.hero-card .hero-core{width:120px;height:120px}.hero-card .hero-icon{font-size:60px;width:60px;height:60px}}@media(max-width:640px){.wrapper{padding:16px 12px}.bento{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:\"hero\" \"data\" \"report\" \"users\" \"flow\" \"audit\" \"integ\";gap:12px}.hero-card{min-height:220px}.hero-card .hero-core{width:100px;height:100px}.hero-card .hero-icon{font-size:52px;width:52px;height:52px}}@media(prefers-reduced-motion:reduce){.card{animation:none;opacity:1;transform:none}.hero-card .hero-ring{animation:none;opacity:.4}.hero-card .hero-decoration .dot{animation:none}}\n"], dependencies: [{ kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type:
|
|
2265
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HomePageComponent, isStandalone: true, selector: "app-home-page", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">\n {{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}\n </div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"wrapper\">\n <div class=\"bento\">\n <!-- Hero -->\n <div class=\"card hero-card\">\n <div class=\"hero-ring ring-3\"></div>\n <div class=\"hero-ring ring-2\"></div>\n <div class=\"hero-ring ring-1\"></div>\n <div class=\"hero-core\">\n <mat-icon class=\"hero-icon\">space_dashboard</mat-icon>\n </div>\n <div class=\"hero-decoration\">\n <span class=\"dot d1\"></span>\n <span class=\"dot d2\"></span>\n <span class=\"dot d3\"></span>\n </div>\n </div>\n\n <!-- Features -->\n @for (feature of features; track feature.key; let i = $index) {\n <div\n class=\"card feature-card\"\n [class.feature-wide]=\"feature.area === 'audit' || feature.area === 'integ'\"\n [style.gridArea]=\"feature.area\"\n [style.animation-delay.ms]=\"(i + 1) * 80\"\n >\n <div class=\"feature-accent\"></div>\n <div class=\"feature-content\">\n <div class=\"feature-icon-wrap\">\n <mat-icon class=\"feature-icon\">{{ feature.icon }}</mat-icon>\n </div>\n <span class=\"feature-label\">{{ feature.key | translate }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n</sd-page>\n", styles: [":host{display:contents}.wrapper{display:flex;align-items:center;justify-content:center;padding:32px 24px;height:100%;width:100%;background:radial-gradient(circle at 15% 25%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 14%,transparent),transparent 55%),radial-gradient(circle at 85% 75%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 10%,transparent),transparent 55%),linear-gradient(135deg,#fafbfc,#f4f6fa);overflow:auto}.bento{display:grid;width:100%;max-width:1080px;gap:16px;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,minmax(140px,1fr));grid-template-areas:\"hero hero data report\" \"hero hero users flow\" \"audit audit integ integ\"}.card{position:relative;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:20px;overflow:hidden;opacity:0;transform:translateY(8px);animation:card-in .5s ease-out forwards;transition:transform .3s ease,box-shadow .3s ease}.card:hover{transform:translateY(-4px);box-shadow:0 16px 40px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,transparent),0 4px 12px #0000000f}.hero-card{grid-area:hero;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,white),#fff 60%),#fff;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 15%,transparent)}.hero-card .hero-ring{position:absolute;border-radius:50%;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 25%,transparent);animation:hero-pulse 3s ease-in-out infinite;pointer-events:none}.hero-card .hero-ring.ring-1{inset:calc(50% - 70px);animation-delay:0s}.hero-card .hero-ring.ring-2{inset:calc(50% - 105px);animation-delay:.6s}.hero-card .hero-ring.ring-3{inset:calc(50% - 140px);animation-delay:1.2s}.hero-card .hero-core{position:relative;z-index:1;width:140px;height:140px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 22%,white),#fff);box-shadow:0 0 60px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 30%,transparent),0 10px 30px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 20%,transparent)}.hero-card .hero-icon{font-size:72px;width:72px;height:72px;color:var(--mat-sys-primary, #1f49bf)}.hero-card .hero-decoration{position:absolute;inset:0;pointer-events:none}.hero-card .hero-decoration .dot{position:absolute;width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 50%,transparent);animation:dot-float 4s ease-in-out infinite}.hero-card .hero-decoration .d1{top:16%;left:12%;animation-delay:0s}.hero-card .hero-decoration .d2{bottom:20%;right:14%;animation-delay:1s}.hero-card .hero-decoration .d3{top:60%;left:80%;animation-delay:2s;width:5px;height:5px}.feature-card{display:flex;align-items:stretch;cursor:default}.feature-card .feature-accent{position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent),var(--mat-sys-primary, #1f49bf),color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent))}.feature-card .feature-content{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 18px;gap:10px}.feature-card .feature-icon-wrap{width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 12%,white);display:flex;align-items:center;justify-content:center}.feature-card .feature-icon{font-size:28px;width:28px;height:28px;color:var(--mat-sys-primary, #1f49bf)}.feature-card .feature-label{font-size:14px;font-weight:500;text-align:center;color:#000000c7;line-height:20px}.feature-card.feature-wide .feature-content{flex-direction:row;justify-content:flex-start;padding:18px 24px;gap:18px}.feature-card.feature-wide .feature-icon-wrap{width:64px;height:64px}.feature-card.feature-wide .feature-icon{font-size:32px;width:32px;height:32px}.feature-card.feature-wide .feature-label{text-align:left;font-size:16px}@keyframes card-in{to{opacity:1;transform:translateY(0)}}@keyframes hero-pulse{0%,to{transform:scale(1);opacity:.7}50%{transform:scale(1.06);opacity:.3}}@keyframes dot-float{0%,to{transform:translateY(0);opacity:.8}50%{transform:translateY(-8px);opacity:.4}}@media(max-width:1024px){.bento{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(4,minmax(120px,1fr));grid-template-areas:\"hero hero data\" \"hero hero report\" \"users flow audit\" \"integ integ integ\"}.hero-card .hero-core{width:120px;height:120px}.hero-card .hero-icon{font-size:60px;width:60px;height:60px}}@media(max-width:640px){.wrapper{padding:16px 12px}.bento{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:\"hero\" \"data\" \"report\" \"users\" \"flow\" \"audit\" \"integ\";gap:12px}.hero-card{min-height:220px}.hero-card .hero-core{width:100px;height:100px}.hero-card .hero-icon{font-size:52px;width:52px;height:52px}}@media(prefers-reduced-motion:reduce){.card{animation:none;opacity:1;transform:none}.hero-card .hero-ring{animation:none;opacity:.4}.hero-card .hero-decoration .dot{animation:none}}\n"], dependencies: [{ kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
1525
2266
|
};
|
|
1526
2267
|
HomePageComponent = __decorate([
|
|
1527
2268
|
SdTabComponent({
|