@shival99/z-ui 2.1.32 → 2.2.0
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/fesm2022/shival99-z-ui-components-z-accordion.mjs +41 -25
- package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +176 -97
- package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-avatar.mjs +71 -40
- package/fesm2022/shival99-z-ui-components-z-avatar.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +26 -15
- package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-button-group.mjs +33 -21
- package/fesm2022/shival99-z-ui-components-z-button-group.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-button.mjs +32 -19
- package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs +289 -172
- package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-card.mjs +34 -24
- package/fesm2022/shival99-z-ui-components-z-card.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-chat.mjs +85 -47
- package/fesm2022/shival99-z-ui-components-z-chat.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +56 -31
- package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-code.mjs +29 -16
- package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-command.mjs +34 -19
- package/fesm2022/shival99-z-ui-components-z-command.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs +310 -88
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +32 -18
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-editor.mjs +118 -62
- package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-empty.mjs +31 -17
- package/fesm2022/shival99-z-ui-components-z-empty.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-filter.mjs +81 -54
- package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs +240 -132
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-icon.mjs +39 -21
- package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-input.mjs +173 -95
- package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs +88 -47
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-loading.mjs +31 -19
- package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs +42 -23
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-media-player.mjs +87 -45
- package/fesm2022/shival99-z-ui-components-z-media-player.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +126 -67
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-metric-card.mjs +42 -23
- package/fesm2022/shival99-z-ui-components-z-metric-card.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-modal.mjs +144 -80
- package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs +45 -24
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-popover.mjs +90 -57
- package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-qrcode.mjs +51 -29
- package/fesm2022/shival99-z-ui-components-z-qrcode.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-radio.mjs +36 -20
- package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs +27 -15
- package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-select.mjs +239 -138
- package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-show-more.mjs +38 -21
- package/fesm2022/shival99-z-ui-components-z-show-more.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs +42 -23
- package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +35 -19
- package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-steps.mjs +55 -31
- package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-switch.mjs +60 -33
- package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-table.mjs +10875 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs +534 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tags.mjs +72 -46
- package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs +254 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-toast.mjs +53 -31
- package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +133 -56
- package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-upload.mjs +63 -36
- package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-i18n.mjs +2 -0
- package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-pipes.mjs +18 -18
- package/fesm2022/shival99-z-ui-services.mjs +35 -31
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
- package/package.json +16 -16
- package/types/shival99-z-ui-components-z-autocomplete.d.ts +2 -2
- package/types/shival99-z-ui-components-z-card.d.ts +1 -2
- package/types/shival99-z-ui-components-z-drawer.d.ts +20 -2
- package/types/shival99-z-ui-components-z-gallery.d.ts +1 -2
- package/types/shival99-z-ui-components-z-select.d.ts +2 -2
- package/types/shival99-z-ui-components-z-table.d.ts +2293 -0
- package/types/shival99-z-ui-components-z-tabs.d.ts +92 -0
- package/types/shival99-z-ui-components-z-timeline.d.ts +71 -0
|
@@ -22,20 +22,34 @@ class ZMenuComponent {
|
|
|
22
22
|
zOnSelect = output();
|
|
23
23
|
zOnMenuAction = output();
|
|
24
24
|
zControl = output();
|
|
25
|
-
zLogo = input('assets/images/avatar.svg',
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
zLogo = input('assets/images/avatar.svg', /* @ts-ignore */
|
|
26
|
+
...(ngDevMode ? [{ debugName: "zLogo" }] : /* istanbul ignore next */ []));
|
|
27
|
+
zLogoMobile = input('', /* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [{ debugName: "zLogoMobile" }] : /* istanbul ignore next */ []));
|
|
29
|
+
zMenus = input([], /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "zMenus" }] : /* istanbul ignore next */ []));
|
|
31
|
+
zUser = input(null, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "zUser" }] : /* istanbul ignore next */ []));
|
|
33
|
+
zUserActions = input([], /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "zUserActions" }] : /* istanbul ignore next */ []));
|
|
35
|
+
zActionsTemplate = input(null, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "zActionsTemplate" }] : /* istanbul ignore next */ []));
|
|
37
|
+
zCurrentPath = input('', /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "zCurrentPath" }] : /* istanbul ignore next */ []));
|
|
39
|
+
zKey = input('z-menu', /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "zKey" }] : /* istanbul ignore next */ []));
|
|
41
|
+
selectedParent = signal(null, /* @ts-ignore */
|
|
42
|
+
...(ngDevMode ? [{ debugName: "selectedParent" }] : /* istanbul ignore next */ []));
|
|
43
|
+
selectedMenuItem = signal(null, /* @ts-ignore */
|
|
44
|
+
...(ngDevMode ? [{ debugName: "selectedMenuItem" }] : /* istanbul ignore next */ []));
|
|
45
|
+
mobileMenuOpen = signal(false, /* @ts-ignore */
|
|
46
|
+
...(ngDevMode ? [{ debugName: "mobileMenuOpen" }] : /* istanbul ignore next */ []));
|
|
47
|
+
mobileTemplateDrawerOpen = signal(false, /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "mobileTemplateDrawerOpen" }] : /* istanbul ignore next */ []));
|
|
49
|
+
sidebarCollapsed = signal(this._getStateMenuCollapsed(), /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
|
|
51
|
+
_templateDrawerParentId = signal(null, /* @ts-ignore */
|
|
52
|
+
...(ngDevMode ? [{ debugName: "_templateDrawerParentId" }] : /* istanbul ignore next */ []));
|
|
39
53
|
closeSidebarFn = () => this.sidebarCollapsed.set(true);
|
|
40
54
|
closeMobileDrawerFn = () => {
|
|
41
55
|
this.mobileTemplateDrawerOpen.set(false);
|
|
@@ -43,25 +57,31 @@ class ZMenuComponent {
|
|
|
43
57
|
};
|
|
44
58
|
_isMobile$ = this._breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.Small]).pipe(map(result => result.matches), takeUntilDestroyed(this._destroyRef));
|
|
45
59
|
isMobile = toSignal(this._isMobile$, { initialValue: false });
|
|
46
|
-
mobileLogo = computed(() => this.zLogoMobile() || this.zLogo(),
|
|
60
|
+
mobileLogo = computed(() => this.zLogoMobile() || this.zLogo(), /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "mobileLogo" }] : /* istanbul ignore next */ []));
|
|
47
62
|
_routerPath = toSignal(this._router.events.pipe(filter((e) => e instanceof NavigationEnd), map(e => e.urlAfterRedirects), startWith(this._router.url)), { initialValue: this._router.url });
|
|
48
|
-
_currentPath = computed(() => this.zCurrentPath() || this._routerPath(),
|
|
63
|
+
_currentPath = computed(() => this.zCurrentPath() || this._routerPath(), /* @ts-ignore */
|
|
64
|
+
...(ngDevMode ? [{ debugName: "_currentPath" }] : /* istanbul ignore next */ []));
|
|
49
65
|
overlayType = computed(() => {
|
|
50
66
|
if (!isPlatformBrowser(this._platformId)) {
|
|
51
67
|
return 'dark';
|
|
52
68
|
}
|
|
53
69
|
const browser = zDetectBrowser();
|
|
54
70
|
return browser.name === 'Chrome' ? 'dark' : 'blur';
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
}, /* @ts-ignore */
|
|
72
|
+
...(ngDevMode ? [{ debugName: "overlayType" }] : /* istanbul ignore next */ []));
|
|
73
|
+
menuProcessed = computed(() => this._processMenus(this.zMenus()), /* @ts-ignore */
|
|
74
|
+
...(ngDevMode ? [{ debugName: "menuProcessed" }] : /* istanbul ignore next */ []));
|
|
75
|
+
menuParents = computed(() => this.menuProcessed().tree.filter((item) => !item.parent || item.parent.length === 0), /* @ts-ignore */
|
|
76
|
+
...(ngDevMode ? [{ debugName: "menuParents" }] : /* istanbul ignore next */ []));
|
|
58
77
|
menuChildren = computed(() => {
|
|
59
78
|
const selected = this.selectedParent();
|
|
60
79
|
if (!selected) {
|
|
61
80
|
return [];
|
|
62
81
|
}
|
|
63
82
|
return selected.children ?? [];
|
|
64
|
-
},
|
|
83
|
+
}, /* @ts-ignore */
|
|
84
|
+
...(ngDevMode ? [{ debugName: "menuChildren" }] : /* istanbul ignore next */ []));
|
|
65
85
|
selectedParentHasNoChild = computed(() => {
|
|
66
86
|
const parent = this.selectedParent();
|
|
67
87
|
if (!parent) {
|
|
@@ -69,7 +89,8 @@ class ZMenuComponent {
|
|
|
69
89
|
}
|
|
70
90
|
const hasNoChildren = !parent.children || parent.children.length === 0;
|
|
71
91
|
return !parent.menuTemplate && hasNoChildren;
|
|
72
|
-
},
|
|
92
|
+
}, /* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [{ debugName: "selectedParentHasNoChild" }] : /* istanbul ignore next */ []));
|
|
73
94
|
parentWithActiveChild = computed(() => {
|
|
74
95
|
const activeItem = this.selectedMenuItem();
|
|
75
96
|
if (!activeItem) {
|
|
@@ -87,7 +108,8 @@ class ZMenuComponent {
|
|
|
87
108
|
return parents.find(p => p.id === topLevelParentId) || null;
|
|
88
109
|
}
|
|
89
110
|
return null;
|
|
90
|
-
},
|
|
111
|
+
}, /* @ts-ignore */
|
|
112
|
+
...(ngDevMode ? [{ debugName: "parentWithActiveChild" }] : /* istanbul ignore next */ []));
|
|
91
113
|
isParentOfActiveItem(item) {
|
|
92
114
|
const activeItem = this.selectedMenuItem();
|
|
93
115
|
if (!activeItem) {
|
|
@@ -98,14 +120,16 @@ class ZMenuComponent {
|
|
|
98
120
|
}
|
|
99
121
|
return false;
|
|
100
122
|
}
|
|
101
|
-
avatarSrc = computed(() => this.zUser()?.avatar || this.zLogo(),
|
|
123
|
+
avatarSrc = computed(() => this.zUser()?.avatar || this.zLogo(), /* @ts-ignore */
|
|
124
|
+
...(ngDevMode ? [{ debugName: "avatarSrc" }] : /* istanbul ignore next */ []));
|
|
102
125
|
customDrawerParent = computed(() => {
|
|
103
126
|
const parentId = this._templateDrawerParentId();
|
|
104
127
|
if (!parentId) {
|
|
105
128
|
return null;
|
|
106
129
|
}
|
|
107
130
|
return this.menuParents().find((p) => p.id === parentId) ?? null;
|
|
108
|
-
},
|
|
131
|
+
}, /* @ts-ignore */
|
|
132
|
+
...(ngDevMode ? [{ debugName: "customDrawerParent" }] : /* istanbul ignore next */ []));
|
|
109
133
|
_defaultSidebarChildWidth = 230;
|
|
110
134
|
_defaultMobileDrawerWidth = 280;
|
|
111
135
|
sidebarChildWidth = computed(() => {
|
|
@@ -114,14 +138,16 @@ class ZMenuComponent {
|
|
|
114
138
|
return parent.menuTemplateWidth;
|
|
115
139
|
}
|
|
116
140
|
return this._defaultSidebarChildWidth;
|
|
117
|
-
},
|
|
141
|
+
}, /* @ts-ignore */
|
|
142
|
+
...(ngDevMode ? [{ debugName: "sidebarChildWidth" }] : /* istanbul ignore next */ []));
|
|
118
143
|
mobileCustomDrawerWidth = computed(() => {
|
|
119
144
|
const parent = this.customDrawerParent();
|
|
120
145
|
if (parent?.menuTemplateWidth) {
|
|
121
146
|
return parent.menuTemplateWidth;
|
|
122
147
|
}
|
|
123
148
|
return this._defaultMobileDrawerWidth;
|
|
124
|
-
},
|
|
149
|
+
}, /* @ts-ignore */
|
|
150
|
+
...(ngDevMode ? [{ debugName: "mobileCustomDrawerWidth" }] : /* istanbul ignore next */ []));
|
|
125
151
|
constructor() {
|
|
126
152
|
effect(() => {
|
|
127
153
|
const parents = this.menuParents();
|
|
@@ -397,10 +423,10 @@ class ZMenuComponent {
|
|
|
397
423
|
_getStateMenuCollapsed() {
|
|
398
424
|
return ZCacheService.get(this.zKey(), false) ?? false;
|
|
399
425
|
}
|
|
400
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
401
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZMenuComponent, isStandalone: true, selector: "z-menu", inputs: { zLogo: { classPropertyName: "zLogo", publicName: "zLogo", isSignal: true, isRequired: false, transformFunction: null }, zLogoMobile: { classPropertyName: "zLogoMobile", publicName: "zLogoMobile", isSignal: true, isRequired: false, transformFunction: null }, zMenus: { classPropertyName: "zMenus", publicName: "zMenus", isSignal: true, isRequired: false, transformFunction: null }, zUser: { classPropertyName: "zUser", publicName: "zUser", isSignal: true, isRequired: false, transformFunction: null }, zUserActions: { classPropertyName: "zUserActions", publicName: "zUserActions", isSignal: true, isRequired: false, transformFunction: null }, zActionsTemplate: { classPropertyName: "zActionsTemplate", publicName: "zActionsTemplate", isSignal: true, isRequired: false, transformFunction: null }, zCurrentPath: { classPropertyName: "zCurrentPath", publicName: "zCurrentPath", isSignal: true, isRequired: false, transformFunction: null }, zKey: { classPropertyName: "zKey", publicName: "zKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnSelect: "zOnSelect", zOnMenuAction: "zOnMenuAction", zControl: "zControl" }, host: { properties: { "class.z-menu-collapsed": "sidebarCollapsed()", "class.z-menu-no-child": "selectedParentHasNoChild()", "class.z-menu-mobile": "isMobile()", "class.z-menu-mobile-open": "mobileMenuOpen()" }, classAttribute: "z-menu block" }, providers: [TranslatePipe], ngImport: i0, template: "<!-- DESKTOP LAYOUT - Hidden on mobile -->\n<div class=\"z-menu-desktop relative z-200 hidden h-full py-1 pl-1 md:block\" [class.collapsed]=\"sidebarCollapsed()\">\n <main class=\"z-menu-main relative flex h-full\">\n <div class=\"z-sidebar-main h-full w-[3.125rem]\">\n <div\n class=\"z-shadow-menu bg-sidebar border-border/40 dark:border-sidebar-border relative flex h-full w-full flex-col items-center gap-1.5 rounded-[0.375rem] border\"></div>\n\n <div class=\"bg-sidebar text-sidebar-foreground absolute inset-px z-20 flex flex-col rounded-[0.375rem]\">\n @if (zLogo()) {\n <div class=\"border-sidebar-border flex h-[3.25rem] items-center justify-center border-b px-2\">\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n </div>\n }\n\n <!-- Expand Button - Only show when collapsed -->\n @if (sidebarCollapsed() && selectedParent()) {\n <div\n class=\"z-expand-btn hover:bg-sidebar-accent mx-auto mt-2 flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem]\"\n (click)=\"toggleSidebar()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"20\" class=\"opacity-70\" />\n </div>\n }\n\n <div class=\"flex flex-1 flex-col items-center gap-2 p-2\">\n @for (item of menuParents(); track item.id) {\n @let hasActiveChild = parentWithActiveChild()?.id === item.id;\n @let isCurrentlySelected = selectedParent()?.id === item.id;\n @let showActiveIndicator = hasActiveChild && !isCurrentlySelected;\n <div\n zTooltip\n [zContent]=\"item.name | translate\"\n zPosition=\"right\"\n [zAlwaysShow]=\"true\"\n class=\"relative flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem] select-none\"\n [class.bg-sidebar-primary]=\"selectedParent()?.id === item.id\"\n [class.text-sidebar-primary-foreground]=\"selectedParent()?.id === item.id\"\n [class.hover:bg-sidebar-accent]=\"selectedParent()?.id !== item.id\"\n (click)=\"onDesktopParentClick(item)\">\n @if (item.icon) {\n <z-icon [zType]=\"item.icon\" zSize=\"20\" />\n } @else {\n <z-icon [zSvg]=\"item.iconSvg || ''\" zSize=\"20\" />\n }\n @if (showActiveIndicator) {\n <div\n class=\"bg-sidebar-primary absolute top-1/2 -left-[0.3125rem] h-4 w-1 -translate-y-1/2 rounded-full\"></div>\n }\n </div>\n }\n </div>\n\n <div class=\"border-sidebar-border flex items-center justify-center border-t p-2\">\n <div\n z-popover\n [zOffset]=\"11\"\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n class=\"aspect-square h-9 w-9 shrink-0 cursor-pointer overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n </div>\n </div>\n </div>\n\n <ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <!-- User Info Header - Always shown -->\n <div class=\"p-0 text-sm font-normal\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"truncate font-medium\">{{ zUser()?.name || 'User Name' }}</span>\n <span class=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n </div>\n\n @if (getVisibleUserActions().length > 0 || zActionsTemplate()) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <!-- Actions - Custom or from zUserActions -->\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n\n @if (selectedParent(); as parent) {\n @let hasChildrenOrTemplate = parent.menuTemplate || (parent.children && parent.children.length > 0);\n @if (hasChildrenOrTemplate) {\n <div\n class=\"z-sidebar-child-wrapper\"\n [class.collapsed]=\"sidebarCollapsed()\"\n [style.--sidebar-child-width.px]=\"sidebarChildWidth()\">\n <div\n class=\"z-sidebar-child z-shadow-menu bg-card text-card-foreground border-border/40 dark:border-sidebar-border flex h-full shrink-0 flex-col items-start overflow-hidden rounded-[0.375rem] border\"\n [style.width.px]=\"sidebarChildWidth()\"\n [class.collapsed]=\"sidebarCollapsed()\">\n <div\n #selectedParentHeaderTrigger\n class=\"border-border flex h-[3.25rem] w-full shrink-0 items-center border-b px-3\">\n @if (selectedParent()?.icon) {\n <z-icon [zType]=\"selectedParent()!.icon\" zSize=\"20\" class=\"mr-2 shrink-0\" />\n }\n <div\n class=\"mr-4 min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n zPosition=\"top-left\"\n [zContent]=\"selectedParent()?.name || '' | translate\"\n [zTriggerElement]=\"selectedParentHeaderTrigger\"\n [zOffset]=\"6\">\n {{ selectedParent()?.name | translate }}\n </div>\n\n <z-icon\n zType=\"lucidePanelRightOpen\"\n zSize=\"20\"\n class=\"shrink-0 cursor-pointer opacity-60 hover:opacity-100\"\n (click)=\"toggleSidebar()\" />\n </div>\n\n <!-- Show menuTemplate if available, otherwise show children -->\n @if (selectedParent()?.menuTemplate) {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1\" track=\"vertical\">\n <div class=\"flex w-full flex-col p-3 pr-2\">\n <ng-container\n *ngTemplateOutlet=\"\n selectedParent()!.menuTemplate!;\n context: { $implicit: selectedParent()!, close: closeSidebarFn }\n \" />\n </div>\n </ng-scrollbar>\n } @else {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1 overflow-hidden\" track=\"vertical\">\n <div class=\"flex w-full min-w-0 flex-col gap-1 overflow-hidden py-1 pr-2 pl-2\">\n <ng-container *ngTemplateOutlet=\"menuChildrenTpl; context: { $implicit: menuChildren() }\" />\n </div>\n </ng-scrollbar>\n }\n </div>\n </div>\n }\n }\n </main>\n</div>\n\n<!-- MOBILE LAYOUT - Visible only on mobile -->\n<div class=\"z-menu-mobile-wrapper hidden max-md:block\">\n <!-- Mobile Backdrop -->\n @if (mobileMenuOpen() || mobileTemplateDrawerOpen()) {\n <div\n class=\"z-menu-backdrop fixed inset-0 z-9998\"\n [class.z-menu-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onBackdropClick()\"></div>\n }\n\n <!-- Mobile Drawer -->\n <aside\n class=\"z-menu-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full w-70 flex-col rounded-r-lg border-r\"\n [class.open]=\"mobileMenuOpen()\">\n <!-- Drawer Header -->\n <div class=\"border-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"bg-accent h-9 w-9 shrink-0\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <!-- Drawer Content - Accordion Menu -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-3\">\n @for (parent of menuParents(); track parent.id) {\n <div class=\"mb-1\">\n <!-- Parent Item -->\n @let isParentActive =\n selectedMenuItem()?.id === parent.id && (!parent.children || parent.children.length === 0);\n @let hasActiveChild = parentWithActiveChild()?.id === parent.id && !isParentActive;\n @let isCurrentlyViewing = selectedParent()?.id === parent.id;\n <div\n #mobileParentTrigger\n class=\"relative flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\"\n [class.bg-primary/20]=\"isParentActive\"\n [class.text-primary]=\"isParentActive || hasActiveChild\"\n [class.hover:bg-accent]=\"!isParentActive\"\n (click)=\"onMobileParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"parent.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileParentTrigger\">\n {{ parent.name | translate }}\n </span>\n @if ((parent.children && parent.children.length > 0) || parent.menuTemplate) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"16\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"parent.expanded && isCurrentlyViewing\" />\n }\n </div>\n\n <!-- Children (Accordion) - Only render if NO menuTemplate -->\n @if (parent.children && parent.children.length > 0 && !parent.menuTemplate) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"parent.expanded && isCurrentlyViewing\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (child of parent.children; track child.id) {\n @let isChildActive =\n selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n\n <div>\n <div\n #mobileChildTrigger\n class=\"relative flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-accent]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1.5 w-1.5 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isChildActive\"\n [class.bg-gray-400]=\"!isChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileChildTrigger\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n <!-- Level 3 -->\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #mobileSubChildTrigger\n class=\"flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-accent]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileSubChildTrigger\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </ng-scrollbar>\n\n <!-- Drawer Footer - User Info -->\n <div class=\"border-border shrink-0 border-t p-3\">\n <div\n z-popover\n [zOffset]=\"6\"\n [zPopoverContent]=\"mobileActionsPopoverTpl\"\n zPosition=\"top-right\"\n zTrigger=\"click\"\n class=\"hover:bg-accent flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\">\n <div class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ zUser()?.name || 'User Name' }}</div>\n <div class=\"text-muted-foreground truncate text-xs\">{{ zUser()?.email || 'user@example.com' }}</div>\n </div>\n <div class=\"text-muted-foreground flex shrink-0 flex-col\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"-mt-1\" />\n </div>\n </div>\n </div>\n </aside>\n\n <!-- Mobile Custom Template Drawer -->\n <aside\n class=\"z-menu-custom-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full max-w-[calc(100vw-1rem)] flex-col rounded-r-lg border-r\"\n [style.width.px]=\"mobileCustomDrawerWidth()\"\n [class.open]=\"mobileTemplateDrawerOpen() && customDrawerParent()?.menuTemplate\">\n @if (customDrawerParent()?.menuTemplate) {\n <!-- Custom Drawer Header -->\n <div #customDrawerHeaderTrigger class=\"border-border flex h-14 shrink-0 items-center gap-3 border-b px-4\">\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"bg-accent h-9 w-9 shrink-0\"\n (click)=\"closeMobileTemplateDrawer()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"20\" />\n </button>\n <span\n class=\"min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n [zContent]=\"customDrawerParent()?.name || '' | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"customDrawerHeaderTrigger\">\n {{ customDrawerParent()?.name | translate }}\n </span>\n </div>\n\n <!-- Custom Template Content -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-4\">\n <ng-container\n *ngTemplateOutlet=\"\n customDrawerParent()!.menuTemplate!;\n context: { $implicit: customDrawerParent()!, close: closeMobileDrawerFn }\n \" />\n </div>\n </ng-scrollbar>\n }\n </aside>\n\n <ng-template #mobileActionsPopoverTpl let-close=\"close\">\n <div class=\"min-w-48 p-1\">\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n</div>\n\n<!-- Shared Template for Menu Children -->\n<ng-template #menuChildrenTpl let-children>\n @for (child of children; track child.id) {\n @let isChildActive = selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n @if (child.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ child.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"w-full min-w-0\">\n <div\n #divLevel1\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-gray-200]=\"!isChildActive\"\n [class.dark:hover:bg-input/50]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel1\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id; let isLast = $last) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #divLevel2\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-gray-200]=\"!isSubChildActive\"\n [class.dark:hover:bg-input/50]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel2\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".z-menu{display:block;flex-shrink:0;height:100%}.z-menu [class*=cursor-pointer]{-webkit-user-select:none;user-select:none}@media(min-width:48rem){.z-menu{contain:layout style;min-width:283px;transition:min-width .25s cubic-bezier(.4,0,.2,1);will-change:min-width}.z-menu.z-menu-collapsed,.z-menu.z-menu-no-child{min-width:53px}}.z-shadow-menu{box-shadow:0 0 10px #0000001f}@media(max-width:47.9375rem){.z-menu-desktop{display:none!important;pointer-events:none;visibility:hidden}}.z-sidebar-main{position:relative;z-index:20;flex-shrink:0}.z-sidebar-child-wrapper{--sidebar-child-width: 230px;position:absolute;left:0;top:0;width:calc(100% + -0px);height:100%;clip-path:inset(0 -100px 0 0);pointer-events:none;transition:clip-path .25s cubic-bezier(.4,0,.2,1);will-change:clip-path;contain:layout}.z-sidebar-child-wrapper.collapsed{clip-path:inset(0 -100px 0 53px)}.z-sidebar-child{flex-shrink:0;height:100%;margin-left:53px;transform:translate(0);transition:transform .25s cubic-bezier(.4,0,.2,1),width .25s cubic-bezier(.4,0,.2,1);pointer-events:auto;will-change:transform,width;overflow:hidden;max-width:100%}.z-sidebar-child *{max-width:100%}.z-sidebar-child.collapsed{transform:translate(calc(-1 * (var(--sidebar-child-width) + 50px + .3125rem)))}.z-menu-arrow.expanded{transform:rotate(90deg)}.z-menu-submenu{display:grid;grid-template-rows:0fr;transition:grid-template-rows .15s ease-out}.z-menu-submenu.expanded{grid-template-rows:1fr}.z-menu-submenu>.z-menu-submenu-inner{overflow:hidden;min-height:0}.z-menu-backdrop{animation:z-menu-backdrop-enter .2s ease-out forwards}.z-menu-backdrop-dark{background-color:#0009}.z-menu-backdrop-blur{background-color:#0000000d;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.z-menu-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a}.z-menu-drawer.open{transform:translate(0)}:host.z-menu-mobile-open .z-menu-drawer{transform:translate(0)}.z-menu-desktop.collapsed .z-sidebar-child-wrapper{pointer-events:none}.z-menu-custom-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-custom-drawer.open{transform:translate(0)}@keyframes z-menu-backdrop-enter{0%{opacity:0}to{opacity:1}}@keyframes z-expand-btn-enter{0%{opacity:0;transform:scale(.5) translateY(.625rem)}70%{transform:scale(1.1) translateY(-.125rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-expand-btn{animation:z-expand-btn-enter .25s cubic-bezier(.34,1.56,.64,1) forwards}.z-menu-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-scrollbar .ng-scroll-viewport,.z-menu-scrollbar .ng-scroll-content{max-width:100%}.z-menu-item{min-width:0;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zSticky", "zShowArrow", "zKeyboardSafe"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
426
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
427
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: ZMenuComponent, isStandalone: true, selector: "z-menu", inputs: { zLogo: { classPropertyName: "zLogo", publicName: "zLogo", isSignal: true, isRequired: false, transformFunction: null }, zLogoMobile: { classPropertyName: "zLogoMobile", publicName: "zLogoMobile", isSignal: true, isRequired: false, transformFunction: null }, zMenus: { classPropertyName: "zMenus", publicName: "zMenus", isSignal: true, isRequired: false, transformFunction: null }, zUser: { classPropertyName: "zUser", publicName: "zUser", isSignal: true, isRequired: false, transformFunction: null }, zUserActions: { classPropertyName: "zUserActions", publicName: "zUserActions", isSignal: true, isRequired: false, transformFunction: null }, zActionsTemplate: { classPropertyName: "zActionsTemplate", publicName: "zActionsTemplate", isSignal: true, isRequired: false, transformFunction: null }, zCurrentPath: { classPropertyName: "zCurrentPath", publicName: "zCurrentPath", isSignal: true, isRequired: false, transformFunction: null }, zKey: { classPropertyName: "zKey", publicName: "zKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnSelect: "zOnSelect", zOnMenuAction: "zOnMenuAction", zControl: "zControl" }, host: { properties: { "class.z-menu-collapsed": "sidebarCollapsed()", "class.z-menu-no-child": "selectedParentHasNoChild()", "class.z-menu-mobile": "isMobile()", "class.z-menu-mobile-open": "mobileMenuOpen()" }, classAttribute: "z-menu block" }, providers: [TranslatePipe], ngImport: i0, template: "<!-- DESKTOP LAYOUT - Hidden on mobile -->\n<div class=\"z-menu-desktop relative z-200 hidden h-full py-1 pl-1 md:block\" [class.collapsed]=\"sidebarCollapsed()\">\n <main class=\"z-menu-main relative flex h-full\">\n <div class=\"z-sidebar-main h-full w-[3.125rem]\">\n <div\n class=\"z-shadow-menu bg-sidebar border-border/40 dark:border-sidebar-border relative flex h-full w-full flex-col items-center gap-1.5 rounded-[0.375rem] border\"></div>\n\n <div class=\"bg-sidebar text-sidebar-foreground absolute inset-px z-20 flex flex-col rounded-[0.375rem]\">\n @if (zLogo()) {\n <div class=\"border-sidebar-border flex h-[3.25rem] items-center justify-center border-b px-2\">\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n </div>\n }\n\n <!-- Expand Button - Only show when collapsed -->\n @if (sidebarCollapsed() && selectedParent()) {\n <div\n class=\"z-expand-btn hover:bg-sidebar-accent mx-auto mt-2 flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem]\"\n (click)=\"toggleSidebar()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"20\" class=\"opacity-70\" />\n </div>\n }\n\n <div class=\"flex flex-1 flex-col items-center gap-2 p-2\">\n @for (item of menuParents(); track item.id) {\n @let hasActiveChild = parentWithActiveChild()?.id === item.id;\n @let isCurrentlySelected = selectedParent()?.id === item.id;\n @let showActiveIndicator = hasActiveChild && !isCurrentlySelected;\n <div\n zTooltip\n [zContent]=\"item.name | translate\"\n zPosition=\"right\"\n [zAlwaysShow]=\"true\"\n class=\"relative flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem] select-none\"\n [class.bg-sidebar-primary]=\"selectedParent()?.id === item.id\"\n [class.text-sidebar-primary-foreground]=\"selectedParent()?.id === item.id\"\n [class.hover:bg-sidebar-accent]=\"selectedParent()?.id !== item.id\"\n (click)=\"onDesktopParentClick(item)\">\n @if (item.icon) {\n <z-icon [zType]=\"item.icon\" zSize=\"20\" />\n } @else {\n <z-icon [zSvg]=\"item.iconSvg || ''\" zSize=\"20\" />\n }\n @if (showActiveIndicator) {\n <div\n class=\"bg-sidebar-primary absolute top-1/2 -left-[0.3125rem] h-4 w-1 -translate-y-1/2 rounded-full\"></div>\n }\n </div>\n }\n </div>\n\n <div class=\"border-sidebar-border flex items-center justify-center border-t p-2\">\n <div\n z-popover\n [zOffset]=\"11\"\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n class=\"aspect-square h-9 w-9 shrink-0 cursor-pointer overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n </div>\n </div>\n </div>\n\n <ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <!-- User Info Header - Always shown -->\n <div class=\"p-0 text-sm font-normal\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"truncate font-medium\">{{ zUser()?.name || 'User Name' }}</span>\n <span class=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n </div>\n\n @if (getVisibleUserActions().length > 0 || zActionsTemplate()) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <!-- Actions - Custom or from zUserActions -->\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n\n @if (selectedParent(); as parent) {\n @let hasChildrenOrTemplate = parent.menuTemplate || (parent.children && parent.children.length > 0);\n @if (hasChildrenOrTemplate) {\n <div\n class=\"z-sidebar-child-wrapper\"\n [class.collapsed]=\"sidebarCollapsed()\"\n [style.--sidebar-child-width.px]=\"sidebarChildWidth()\">\n <div\n class=\"z-sidebar-child z-shadow-menu bg-card text-card-foreground border-border/40 dark:border-sidebar-border flex h-full shrink-0 flex-col items-start overflow-hidden rounded-[0.375rem] border\"\n [style.width.px]=\"sidebarChildWidth()\"\n [class.collapsed]=\"sidebarCollapsed()\">\n <div\n #selectedParentHeaderTrigger\n class=\"border-border flex h-[3.25rem] w-full shrink-0 items-center border-b px-3\">\n @if (selectedParent()?.icon) {\n <z-icon [zType]=\"selectedParent()!.icon\" zSize=\"20\" class=\"mr-2 shrink-0\" />\n }\n <div\n class=\"mr-4 min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n zPosition=\"top-left\"\n [zContent]=\"selectedParent()?.name || '' | translate\"\n [zTriggerElement]=\"selectedParentHeaderTrigger\"\n [zOffset]=\"6\">\n {{ selectedParent()?.name | translate }}\n </div>\n\n <z-icon\n zType=\"lucidePanelRightOpen\"\n zSize=\"20\"\n class=\"shrink-0 cursor-pointer opacity-60 hover:opacity-100\"\n (click)=\"toggleSidebar()\" />\n </div>\n\n <!-- Show menuTemplate if available, otherwise show children -->\n @if (selectedParent()?.menuTemplate) {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1\" track=\"vertical\">\n <div class=\"flex w-full flex-col p-3 pr-2\">\n <ng-container\n *ngTemplateOutlet=\"\n selectedParent()!.menuTemplate!;\n context: { $implicit: selectedParent()!, close: closeSidebarFn }\n \" />\n </div>\n </ng-scrollbar>\n } @else {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1 overflow-hidden\" track=\"vertical\">\n <div class=\"flex w-full min-w-0 flex-col gap-1 overflow-hidden py-1 pr-2 pl-2\">\n <ng-container *ngTemplateOutlet=\"menuChildrenTpl; context: { $implicit: menuChildren() }\" />\n </div>\n </ng-scrollbar>\n }\n </div>\n </div>\n }\n }\n </main>\n</div>\n\n<!-- MOBILE LAYOUT - Visible only on mobile -->\n<div class=\"z-menu-mobile-wrapper hidden max-md:block\">\n <!-- Mobile Backdrop -->\n @if (mobileMenuOpen() || mobileTemplateDrawerOpen()) {\n <div\n class=\"z-menu-backdrop fixed inset-0 z-9998\"\n [class.z-menu-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onBackdropClick()\"></div>\n }\n\n <!-- Mobile Drawer -->\n <aside\n class=\"z-menu-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full w-70 flex-col rounded-r-lg border-r\"\n [class.open]=\"mobileMenuOpen()\">\n <!-- Drawer Header -->\n <div class=\"border-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"bg-accent h-9 w-9 shrink-0\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <!-- Drawer Content - Accordion Menu -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-3\">\n @for (parent of menuParents(); track parent.id) {\n <div class=\"mb-1\">\n <!-- Parent Item -->\n @let isParentActive =\n selectedMenuItem()?.id === parent.id && (!parent.children || parent.children.length === 0);\n @let hasActiveChild = parentWithActiveChild()?.id === parent.id && !isParentActive;\n @let isCurrentlyViewing = selectedParent()?.id === parent.id;\n <div\n #mobileParentTrigger\n class=\"relative flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\"\n [class.bg-primary/20]=\"isParentActive\"\n [class.text-primary]=\"isParentActive || hasActiveChild\"\n [class.hover:bg-accent]=\"!isParentActive\"\n (click)=\"onMobileParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"parent.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileParentTrigger\">\n {{ parent.name | translate }}\n </span>\n @if ((parent.children && parent.children.length > 0) || parent.menuTemplate) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"16\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"parent.expanded && isCurrentlyViewing\" />\n }\n </div>\n\n <!-- Children (Accordion) - Only render if NO menuTemplate -->\n @if (parent.children && parent.children.length > 0 && !parent.menuTemplate) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"parent.expanded && isCurrentlyViewing\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (child of parent.children; track child.id) {\n @let isChildActive =\n selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n\n <div>\n <div\n #mobileChildTrigger\n class=\"relative flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-accent]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1.5 w-1.5 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isChildActive\"\n [class.bg-gray-400]=\"!isChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileChildTrigger\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n <!-- Level 3 -->\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #mobileSubChildTrigger\n class=\"flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-accent]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileSubChildTrigger\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </ng-scrollbar>\n\n <!-- Drawer Footer - User Info -->\n <div class=\"border-border shrink-0 border-t p-3\">\n <div\n z-popover\n [zOffset]=\"6\"\n [zPopoverContent]=\"mobileActionsPopoverTpl\"\n zPosition=\"top-right\"\n zTrigger=\"click\"\n class=\"hover:bg-accent flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\">\n <div class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ zUser()?.name || 'User Name' }}</div>\n <div class=\"text-muted-foreground truncate text-xs\">{{ zUser()?.email || 'user@example.com' }}</div>\n </div>\n <div class=\"text-muted-foreground flex shrink-0 flex-col\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"-mt-1\" />\n </div>\n </div>\n </div>\n </aside>\n\n <!-- Mobile Custom Template Drawer -->\n <aside\n class=\"z-menu-custom-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full max-w-[calc(100vw-1rem)] flex-col rounded-r-lg border-r\"\n [style.width.px]=\"mobileCustomDrawerWidth()\"\n [class.open]=\"mobileTemplateDrawerOpen() && customDrawerParent()?.menuTemplate\">\n @if (customDrawerParent()?.menuTemplate) {\n <!-- Custom Drawer Header -->\n <div #customDrawerHeaderTrigger class=\"border-border flex h-14 shrink-0 items-center gap-3 border-b px-4\">\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"bg-accent h-9 w-9 shrink-0\"\n (click)=\"closeMobileTemplateDrawer()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"20\" />\n </button>\n <span\n class=\"min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n [zContent]=\"customDrawerParent()?.name || '' | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"customDrawerHeaderTrigger\">\n {{ customDrawerParent()?.name | translate }}\n </span>\n </div>\n\n <!-- Custom Template Content -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-4\">\n <ng-container\n *ngTemplateOutlet=\"\n customDrawerParent()!.menuTemplate!;\n context: { $implicit: customDrawerParent()!, close: closeMobileDrawerFn }\n \" />\n </div>\n </ng-scrollbar>\n }\n </aside>\n\n <ng-template #mobileActionsPopoverTpl let-close=\"close\">\n <div class=\"min-w-48 p-1\">\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n</div>\n\n<!-- Shared Template for Menu Children -->\n<ng-template #menuChildrenTpl let-children>\n @for (child of children; track child.id) {\n @let isChildActive = selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n @if (child.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ child.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"w-full min-w-0\">\n <div\n #divLevel1\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-gray-200]=\"!isChildActive\"\n [class.dark:hover:bg-input/50]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel1\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id; let isLast = $last) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #divLevel2\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-gray-200]=\"!isSubChildActive\"\n [class.dark:hover:bg-input/50]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel2\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".z-menu{display:block;flex-shrink:0;height:100%}.z-menu [class*=cursor-pointer]{-webkit-user-select:none;user-select:none}@media(min-width:48rem){.z-menu{contain:layout style;min-width:283px;transition:min-width .25s cubic-bezier(.4,0,.2,1);will-change:min-width}.z-menu.z-menu-collapsed,.z-menu.z-menu-no-child{min-width:53px}}.z-shadow-menu{box-shadow:0 0 10px #0000001f}@media(max-width:47.9375rem){.z-menu-desktop{display:none!important;pointer-events:none;visibility:hidden}}.z-sidebar-main{position:relative;z-index:20;flex-shrink:0}.z-sidebar-child-wrapper{--sidebar-child-width: 230px;position:absolute;left:0;top:0;width:calc(100% + -0px);height:100%;clip-path:inset(0 -100px 0 0);pointer-events:none;transition:clip-path .25s cubic-bezier(.4,0,.2,1);will-change:clip-path;contain:layout}.z-sidebar-child-wrapper.collapsed{clip-path:inset(0 -100px 0 53px)}.z-sidebar-child{flex-shrink:0;height:100%;margin-left:53px;transform:translate(0);transition:transform .25s cubic-bezier(.4,0,.2,1),width .25s cubic-bezier(.4,0,.2,1);pointer-events:auto;will-change:transform,width;overflow:hidden;max-width:100%}.z-sidebar-child *{max-width:100%}.z-sidebar-child.collapsed{transform:translate(calc(-1 * (var(--sidebar-child-width) + 50px + .3125rem)))}.z-menu-arrow.expanded{transform:rotate(90deg)}.z-menu-submenu{display:grid;grid-template-rows:0fr;transition:grid-template-rows .15s ease-out}.z-menu-submenu.expanded{grid-template-rows:1fr}.z-menu-submenu>.z-menu-submenu-inner{overflow:hidden;min-height:0}.z-menu-backdrop{animation:z-menu-backdrop-enter .2s ease-out forwards}.z-menu-backdrop-dark{background-color:#0009}.z-menu-backdrop-blur{background-color:#0000000d;backdrop-filter:blur(2px)}.z-menu-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a}.z-menu-drawer.open{transform:translate(0)}:host.z-menu-mobile-open .z-menu-drawer{transform:translate(0)}.z-menu-desktop.collapsed .z-sidebar-child-wrapper{pointer-events:none}.z-menu-custom-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-custom-drawer.open{transform:translate(0)}@keyframes z-menu-backdrop-enter{0%{opacity:0}to{opacity:1}}@keyframes z-expand-btn-enter{0%{opacity:0;transform:scale(.5) translateY(.625rem)}70%{transform:scale(1.1) translateY(-.125rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-expand-btn{animation:z-expand-btn-enter .25s cubic-bezier(.34,1.56,.64,1) forwards}.z-menu-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-scrollbar .ng-scroll-viewport,.z-menu-scrollbar .ng-scroll-content{max-width:100%}.z-menu-item{min-width:0;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zSticky", "zShowArrow", "zKeyboardSafe"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
402
428
|
}
|
|
403
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZMenuComponent, decorators: [{
|
|
404
430
|
type: Component,
|
|
405
431
|
args: [{ selector: 'z-menu', imports: [
|
|
406
432
|
NgTemplateOutlet,
|
|
@@ -416,7 +442,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
|
|
|
416
442
|
'[class.z-menu-no-child]': 'selectedParentHasNoChild()',
|
|
417
443
|
'[class.z-menu-mobile]': 'isMobile()',
|
|
418
444
|
'[class.z-menu-mobile-open]': 'mobileMenuOpen()',
|
|
419
|
-
}, template: "<!-- DESKTOP LAYOUT - Hidden on mobile -->\n<div class=\"z-menu-desktop relative z-200 hidden h-full py-1 pl-1 md:block\" [class.collapsed]=\"sidebarCollapsed()\">\n <main class=\"z-menu-main relative flex h-full\">\n <div class=\"z-sidebar-main h-full w-[3.125rem]\">\n <div\n class=\"z-shadow-menu bg-sidebar border-border/40 dark:border-sidebar-border relative flex h-full w-full flex-col items-center gap-1.5 rounded-[0.375rem] border\"></div>\n\n <div class=\"bg-sidebar text-sidebar-foreground absolute inset-px z-20 flex flex-col rounded-[0.375rem]\">\n @if (zLogo()) {\n <div class=\"border-sidebar-border flex h-[3.25rem] items-center justify-center border-b px-2\">\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n </div>\n }\n\n <!-- Expand Button - Only show when collapsed -->\n @if (sidebarCollapsed() && selectedParent()) {\n <div\n class=\"z-expand-btn hover:bg-sidebar-accent mx-auto mt-2 flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem]\"\n (click)=\"toggleSidebar()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"20\" class=\"opacity-70\" />\n </div>\n }\n\n <div class=\"flex flex-1 flex-col items-center gap-2 p-2\">\n @for (item of menuParents(); track item.id) {\n @let hasActiveChild = parentWithActiveChild()?.id === item.id;\n @let isCurrentlySelected = selectedParent()?.id === item.id;\n @let showActiveIndicator = hasActiveChild && !isCurrentlySelected;\n <div\n zTooltip\n [zContent]=\"item.name | translate\"\n zPosition=\"right\"\n [zAlwaysShow]=\"true\"\n class=\"relative flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem] select-none\"\n [class.bg-sidebar-primary]=\"selectedParent()?.id === item.id\"\n [class.text-sidebar-primary-foreground]=\"selectedParent()?.id === item.id\"\n [class.hover:bg-sidebar-accent]=\"selectedParent()?.id !== item.id\"\n (click)=\"onDesktopParentClick(item)\">\n @if (item.icon) {\n <z-icon [zType]=\"item.icon\" zSize=\"20\" />\n } @else {\n <z-icon [zSvg]=\"item.iconSvg || ''\" zSize=\"20\" />\n }\n @if (showActiveIndicator) {\n <div\n class=\"bg-sidebar-primary absolute top-1/2 -left-[0.3125rem] h-4 w-1 -translate-y-1/2 rounded-full\"></div>\n }\n </div>\n }\n </div>\n\n <div class=\"border-sidebar-border flex items-center justify-center border-t p-2\">\n <div\n z-popover\n [zOffset]=\"11\"\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n class=\"aspect-square h-9 w-9 shrink-0 cursor-pointer overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n </div>\n </div>\n </div>\n\n <ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <!-- User Info Header - Always shown -->\n <div class=\"p-0 text-sm font-normal\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"truncate font-medium\">{{ zUser()?.name || 'User Name' }}</span>\n <span class=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n </div>\n\n @if (getVisibleUserActions().length > 0 || zActionsTemplate()) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <!-- Actions - Custom or from zUserActions -->\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n\n @if (selectedParent(); as parent) {\n @let hasChildrenOrTemplate = parent.menuTemplate || (parent.children && parent.children.length > 0);\n @if (hasChildrenOrTemplate) {\n <div\n class=\"z-sidebar-child-wrapper\"\n [class.collapsed]=\"sidebarCollapsed()\"\n [style.--sidebar-child-width.px]=\"sidebarChildWidth()\">\n <div\n class=\"z-sidebar-child z-shadow-menu bg-card text-card-foreground border-border/40 dark:border-sidebar-border flex h-full shrink-0 flex-col items-start overflow-hidden rounded-[0.375rem] border\"\n [style.width.px]=\"sidebarChildWidth()\"\n [class.collapsed]=\"sidebarCollapsed()\">\n <div\n #selectedParentHeaderTrigger\n class=\"border-border flex h-[3.25rem] w-full shrink-0 items-center border-b px-3\">\n @if (selectedParent()?.icon) {\n <z-icon [zType]=\"selectedParent()!.icon\" zSize=\"20\" class=\"mr-2 shrink-0\" />\n }\n <div\n class=\"mr-4 min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n zPosition=\"top-left\"\n [zContent]=\"selectedParent()?.name || '' | translate\"\n [zTriggerElement]=\"selectedParentHeaderTrigger\"\n [zOffset]=\"6\">\n {{ selectedParent()?.name | translate }}\n </div>\n\n <z-icon\n zType=\"lucidePanelRightOpen\"\n zSize=\"20\"\n class=\"shrink-0 cursor-pointer opacity-60 hover:opacity-100\"\n (click)=\"toggleSidebar()\" />\n </div>\n\n <!-- Show menuTemplate if available, otherwise show children -->\n @if (selectedParent()?.menuTemplate) {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1\" track=\"vertical\">\n <div class=\"flex w-full flex-col p-3 pr-2\">\n <ng-container\n *ngTemplateOutlet=\"\n selectedParent()!.menuTemplate!;\n context: { $implicit: selectedParent()!, close: closeSidebarFn }\n \" />\n </div>\n </ng-scrollbar>\n } @else {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1 overflow-hidden\" track=\"vertical\">\n <div class=\"flex w-full min-w-0 flex-col gap-1 overflow-hidden py-1 pr-2 pl-2\">\n <ng-container *ngTemplateOutlet=\"menuChildrenTpl; context: { $implicit: menuChildren() }\" />\n </div>\n </ng-scrollbar>\n }\n </div>\n </div>\n }\n }\n </main>\n</div>\n\n<!-- MOBILE LAYOUT - Visible only on mobile -->\n<div class=\"z-menu-mobile-wrapper hidden max-md:block\">\n <!-- Mobile Backdrop -->\n @if (mobileMenuOpen() || mobileTemplateDrawerOpen()) {\n <div\n class=\"z-menu-backdrop fixed inset-0 z-9998\"\n [class.z-menu-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onBackdropClick()\"></div>\n }\n\n <!-- Mobile Drawer -->\n <aside\n class=\"z-menu-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full w-70 flex-col rounded-r-lg border-r\"\n [class.open]=\"mobileMenuOpen()\">\n <!-- Drawer Header -->\n <div class=\"border-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"bg-accent h-9 w-9 shrink-0\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <!-- Drawer Content - Accordion Menu -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-3\">\n @for (parent of menuParents(); track parent.id) {\n <div class=\"mb-1\">\n <!-- Parent Item -->\n @let isParentActive =\n selectedMenuItem()?.id === parent.id && (!parent.children || parent.children.length === 0);\n @let hasActiveChild = parentWithActiveChild()?.id === parent.id && !isParentActive;\n @let isCurrentlyViewing = selectedParent()?.id === parent.id;\n <div\n #mobileParentTrigger\n class=\"relative flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\"\n [class.bg-primary/20]=\"isParentActive\"\n [class.text-primary]=\"isParentActive || hasActiveChild\"\n [class.hover:bg-accent]=\"!isParentActive\"\n (click)=\"onMobileParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"parent.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileParentTrigger\">\n {{ parent.name | translate }}\n </span>\n @if ((parent.children && parent.children.length > 0) || parent.menuTemplate) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"16\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"parent.expanded && isCurrentlyViewing\" />\n }\n </div>\n\n <!-- Children (Accordion) - Only render if NO menuTemplate -->\n @if (parent.children && parent.children.length > 0 && !parent.menuTemplate) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"parent.expanded && isCurrentlyViewing\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (child of parent.children; track child.id) {\n @let isChildActive =\n selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n\n <div>\n <div\n #mobileChildTrigger\n class=\"relative flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-accent]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1.5 w-1.5 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isChildActive\"\n [class.bg-gray-400]=\"!isChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileChildTrigger\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n <!-- Level 3 -->\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #mobileSubChildTrigger\n class=\"flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-accent]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileSubChildTrigger\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </ng-scrollbar>\n\n <!-- Drawer Footer - User Info -->\n <div class=\"border-border shrink-0 border-t p-3\">\n <div\n z-popover\n [zOffset]=\"6\"\n [zPopoverContent]=\"mobileActionsPopoverTpl\"\n zPosition=\"top-right\"\n zTrigger=\"click\"\n class=\"hover:bg-accent flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\">\n <div class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ zUser()?.name || 'User Name' }}</div>\n <div class=\"text-muted-foreground truncate text-xs\">{{ zUser()?.email || 'user@example.com' }}</div>\n </div>\n <div class=\"text-muted-foreground flex shrink-0 flex-col\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"-mt-1\" />\n </div>\n </div>\n </div>\n </aside>\n\n <!-- Mobile Custom Template Drawer -->\n <aside\n class=\"z-menu-custom-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full max-w-[calc(100vw-1rem)] flex-col rounded-r-lg border-r\"\n [style.width.px]=\"mobileCustomDrawerWidth()\"\n [class.open]=\"mobileTemplateDrawerOpen() && customDrawerParent()?.menuTemplate\">\n @if (customDrawerParent()?.menuTemplate) {\n <!-- Custom Drawer Header -->\n <div #customDrawerHeaderTrigger class=\"border-border flex h-14 shrink-0 items-center gap-3 border-b px-4\">\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"bg-accent h-9 w-9 shrink-0\"\n (click)=\"closeMobileTemplateDrawer()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"20\" />\n </button>\n <span\n class=\"min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n [zContent]=\"customDrawerParent()?.name || '' | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"customDrawerHeaderTrigger\">\n {{ customDrawerParent()?.name | translate }}\n </span>\n </div>\n\n <!-- Custom Template Content -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-4\">\n <ng-container\n *ngTemplateOutlet=\"\n customDrawerParent()!.menuTemplate!;\n context: { $implicit: customDrawerParent()!, close: closeMobileDrawerFn }\n \" />\n </div>\n </ng-scrollbar>\n }\n </aside>\n\n <ng-template #mobileActionsPopoverTpl let-close=\"close\">\n <div class=\"min-w-48 p-1\">\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n</div>\n\n<!-- Shared Template for Menu Children -->\n<ng-template #menuChildrenTpl let-children>\n @for (child of children; track child.id) {\n @let isChildActive = selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n @if (child.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ child.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"w-full min-w-0\">\n <div\n #divLevel1\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-gray-200]=\"!isChildActive\"\n [class.dark:hover:bg-input/50]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel1\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id; let isLast = $last) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #divLevel2\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-gray-200]=\"!isSubChildActive\"\n [class.dark:hover:bg-input/50]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel2\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".z-menu{display:block;flex-shrink:0;height:100%}.z-menu [class*=cursor-pointer]{-webkit-user-select:none;user-select:none}@media(min-width:48rem){.z-menu{contain:layout style;min-width:283px;transition:min-width .25s cubic-bezier(.4,0,.2,1);will-change:min-width}.z-menu.z-menu-collapsed,.z-menu.z-menu-no-child{min-width:53px}}.z-shadow-menu{box-shadow:0 0 10px #0000001f}@media(max-width:47.9375rem){.z-menu-desktop{display:none!important;pointer-events:none;visibility:hidden}}.z-sidebar-main{position:relative;z-index:20;flex-shrink:0}.z-sidebar-child-wrapper{--sidebar-child-width: 230px;position:absolute;left:0;top:0;width:calc(100% + -0px);height:100%;clip-path:inset(0 -100px 0 0);pointer-events:none;transition:clip-path .25s cubic-bezier(.4,0,.2,1);will-change:clip-path;contain:layout}.z-sidebar-child-wrapper.collapsed{clip-path:inset(0 -100px 0 53px)}.z-sidebar-child{flex-shrink:0;height:100%;margin-left:53px;transform:translate(0);transition:transform .25s cubic-bezier(.4,0,.2,1),width .25s cubic-bezier(.4,0,.2,1);pointer-events:auto;will-change:transform,width;overflow:hidden;max-width:100%}.z-sidebar-child *{max-width:100%}.z-sidebar-child.collapsed{transform:translate(calc(-1 * (var(--sidebar-child-width) + 50px + .3125rem)))}.z-menu-arrow.expanded{transform:rotate(90deg)}.z-menu-submenu{display:grid;grid-template-rows:0fr;transition:grid-template-rows .15s ease-out}.z-menu-submenu.expanded{grid-template-rows:1fr}.z-menu-submenu>.z-menu-submenu-inner{overflow:hidden;min-height:0}.z-menu-backdrop{animation:z-menu-backdrop-enter .2s ease-out forwards}.z-menu-backdrop-dark{background-color:#0009}.z-menu-backdrop-blur{background-color:#0000000d;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.z-menu-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a}.z-menu-drawer.open{transform:translate(0)}:host.z-menu-mobile-open .z-menu-drawer{transform:translate(0)}.z-menu-desktop.collapsed .z-sidebar-child-wrapper{pointer-events:none}.z-menu-custom-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-custom-drawer.open{transform:translate(0)}@keyframes z-menu-backdrop-enter{0%{opacity:0}to{opacity:1}}@keyframes z-expand-btn-enter{0%{opacity:0;transform:scale(.5) translateY(.625rem)}70%{transform:scale(1.1) translateY(-.125rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-expand-btn{animation:z-expand-btn-enter .25s cubic-bezier(.34,1.56,.64,1) forwards}.z-menu-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-scrollbar .ng-scroll-viewport,.z-menu-scrollbar .ng-scroll-content{max-width:100%}.z-menu-item{min-width:0;overflow:hidden}\n"] }]
|
|
445
|
+
}, template: "<!-- DESKTOP LAYOUT - Hidden on mobile -->\n<div class=\"z-menu-desktop relative z-200 hidden h-full py-1 pl-1 md:block\" [class.collapsed]=\"sidebarCollapsed()\">\n <main class=\"z-menu-main relative flex h-full\">\n <div class=\"z-sidebar-main h-full w-[3.125rem]\">\n <div\n class=\"z-shadow-menu bg-sidebar border-border/40 dark:border-sidebar-border relative flex h-full w-full flex-col items-center gap-1.5 rounded-[0.375rem] border\"></div>\n\n <div class=\"bg-sidebar text-sidebar-foreground absolute inset-px z-20 flex flex-col rounded-[0.375rem]\">\n @if (zLogo()) {\n <div class=\"border-sidebar-border flex h-[3.25rem] items-center justify-center border-b px-2\">\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n </div>\n }\n\n <!-- Expand Button - Only show when collapsed -->\n @if (sidebarCollapsed() && selectedParent()) {\n <div\n class=\"z-expand-btn hover:bg-sidebar-accent mx-auto mt-2 flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem]\"\n (click)=\"toggleSidebar()\">\n <z-icon zType=\"lucideChevronsRight\" zSize=\"20\" class=\"opacity-70\" />\n </div>\n }\n\n <div class=\"flex flex-1 flex-col items-center gap-2 p-2\">\n @for (item of menuParents(); track item.id) {\n @let hasActiveChild = parentWithActiveChild()?.id === item.id;\n @let isCurrentlySelected = selectedParent()?.id === item.id;\n @let showActiveIndicator = hasActiveChild && !isCurrentlySelected;\n <div\n zTooltip\n [zContent]=\"item.name | translate\"\n zPosition=\"right\"\n [zAlwaysShow]=\"true\"\n class=\"relative flex h-9 w-9 cursor-pointer items-center justify-center rounded-[0.375rem] select-none\"\n [class.bg-sidebar-primary]=\"selectedParent()?.id === item.id\"\n [class.text-sidebar-primary-foreground]=\"selectedParent()?.id === item.id\"\n [class.hover:bg-sidebar-accent]=\"selectedParent()?.id !== item.id\"\n (click)=\"onDesktopParentClick(item)\">\n @if (item.icon) {\n <z-icon [zType]=\"item.icon\" zSize=\"20\" />\n } @else {\n <z-icon [zSvg]=\"item.iconSvg || ''\" zSize=\"20\" />\n }\n @if (showActiveIndicator) {\n <div\n class=\"bg-sidebar-primary absolute top-1/2 -left-[0.3125rem] h-4 w-1 -translate-y-1/2 rounded-full\"></div>\n }\n </div>\n }\n </div>\n\n <div class=\"border-sidebar-border flex items-center justify-center border-t p-2\">\n <div\n z-popover\n [zOffset]=\"11\"\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n class=\"aspect-square h-9 w-9 shrink-0 cursor-pointer overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n </div>\n </div>\n </div>\n\n <ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <!-- User Info Header - Always shown -->\n <div class=\"p-0 text-sm font-normal\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"truncate font-medium\">{{ zUser()?.name || 'User Name' }}</span>\n <span class=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n </div>\n\n @if (getVisibleUserActions().length > 0 || zActionsTemplate()) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <!-- Actions - Custom or from zUserActions -->\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n\n @if (selectedParent(); as parent) {\n @let hasChildrenOrTemplate = parent.menuTemplate || (parent.children && parent.children.length > 0);\n @if (hasChildrenOrTemplate) {\n <div\n class=\"z-sidebar-child-wrapper\"\n [class.collapsed]=\"sidebarCollapsed()\"\n [style.--sidebar-child-width.px]=\"sidebarChildWidth()\">\n <div\n class=\"z-sidebar-child z-shadow-menu bg-card text-card-foreground border-border/40 dark:border-sidebar-border flex h-full shrink-0 flex-col items-start overflow-hidden rounded-[0.375rem] border\"\n [style.width.px]=\"sidebarChildWidth()\"\n [class.collapsed]=\"sidebarCollapsed()\">\n <div\n #selectedParentHeaderTrigger\n class=\"border-border flex h-[3.25rem] w-full shrink-0 items-center border-b px-3\">\n @if (selectedParent()?.icon) {\n <z-icon [zType]=\"selectedParent()!.icon\" zSize=\"20\" class=\"mr-2 shrink-0\" />\n }\n <div\n class=\"mr-4 min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n zPosition=\"top-left\"\n [zContent]=\"selectedParent()?.name || '' | translate\"\n [zTriggerElement]=\"selectedParentHeaderTrigger\"\n [zOffset]=\"6\">\n {{ selectedParent()?.name | translate }}\n </div>\n\n <z-icon\n zType=\"lucidePanelRightOpen\"\n zSize=\"20\"\n class=\"shrink-0 cursor-pointer opacity-60 hover:opacity-100\"\n (click)=\"toggleSidebar()\" />\n </div>\n\n <!-- Show menuTemplate if available, otherwise show children -->\n @if (selectedParent()?.menuTemplate) {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1\" track=\"vertical\">\n <div class=\"flex w-full flex-col p-3 pr-2\">\n <ng-container\n *ngTemplateOutlet=\"\n selectedParent()!.menuTemplate!;\n context: { $implicit: selectedParent()!, close: closeSidebarFn }\n \" />\n </div>\n </ng-scrollbar>\n } @else {\n <ng-scrollbar class=\"z-menu-scrollbar min-h-0 w-full flex-1 overflow-hidden\" track=\"vertical\">\n <div class=\"flex w-full min-w-0 flex-col gap-1 overflow-hidden py-1 pr-2 pl-2\">\n <ng-container *ngTemplateOutlet=\"menuChildrenTpl; context: { $implicit: menuChildren() }\" />\n </div>\n </ng-scrollbar>\n }\n </div>\n </div>\n }\n }\n </main>\n</div>\n\n<!-- MOBILE LAYOUT - Visible only on mobile -->\n<div class=\"z-menu-mobile-wrapper hidden max-md:block\">\n <!-- Mobile Backdrop -->\n @if (mobileMenuOpen() || mobileTemplateDrawerOpen()) {\n <div\n class=\"z-menu-backdrop fixed inset-0 z-9998\"\n [class.z-menu-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onBackdropClick()\"></div>\n }\n\n <!-- Mobile Drawer -->\n <aside\n class=\"z-menu-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full w-70 flex-col rounded-r-lg border-r\"\n [class.open]=\"mobileMenuOpen()\">\n <!-- Drawer Header -->\n <div class=\"border-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"bg-accent h-9 w-9 shrink-0\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <!-- Drawer Content - Accordion Menu -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-3\">\n @for (parent of menuParents(); track parent.id) {\n <div class=\"mb-1\">\n <!-- Parent Item -->\n @let isParentActive =\n selectedMenuItem()?.id === parent.id && (!parent.children || parent.children.length === 0);\n @let hasActiveChild = parentWithActiveChild()?.id === parent.id && !isParentActive;\n @let isCurrentlyViewing = selectedParent()?.id === parent.id;\n <div\n #mobileParentTrigger\n class=\"relative flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\"\n [class.bg-primary/20]=\"isParentActive\"\n [class.text-primary]=\"isParentActive || hasActiveChild\"\n [class.hover:bg-accent]=\"!isParentActive\"\n (click)=\"onMobileParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"parent.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileParentTrigger\">\n {{ parent.name | translate }}\n </span>\n @if ((parent.children && parent.children.length > 0) || parent.menuTemplate) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"16\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"parent.expanded && isCurrentlyViewing\" />\n }\n </div>\n\n <!-- Children (Accordion) - Only render if NO menuTemplate -->\n @if (parent.children && parent.children.length > 0 && !parent.menuTemplate) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"parent.expanded && isCurrentlyViewing\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (child of parent.children; track child.id) {\n @let isChildActive =\n selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n\n <div>\n <div\n #mobileChildTrigger\n class=\"relative flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-accent]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1.5 w-1.5 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isChildActive\"\n [class.bg-gray-400]=\"!isChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileChildTrigger\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n <!-- Level 3 -->\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #mobileSubChildTrigger\n class=\"flex cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-accent]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"mobileSubChildTrigger\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </ng-scrollbar>\n\n <!-- Drawer Footer - User Info -->\n <div class=\"border-border shrink-0 border-t p-3\">\n <div\n z-popover\n [zOffset]=\"6\"\n [zPopoverContent]=\"mobileActionsPopoverTpl\"\n zPosition=\"top-right\"\n zTrigger=\"click\"\n class=\"hover:bg-accent flex cursor-pointer items-center gap-3 rounded-[0.375rem] p-2\">\n <div class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </div>\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ zUser()?.name || 'User Name' }}</div>\n <div class=\"text-muted-foreground truncate text-xs\">{{ zUser()?.email || 'user@example.com' }}</div>\n </div>\n <div class=\"text-muted-foreground flex shrink-0 flex-col\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"14\" />\n <z-icon zType=\"lucideChevronDown\" zSize=\"14\" class=\"-mt-1\" />\n </div>\n </div>\n </div>\n </aside>\n\n <!-- Mobile Custom Template Drawer -->\n <aside\n class=\"z-menu-custom-drawer bg-background border-border fixed top-0 left-0 z-9999 flex h-full max-w-[calc(100vw-1rem)] flex-col rounded-r-lg border-r\"\n [style.width.px]=\"mobileCustomDrawerWidth()\"\n [class.open]=\"mobileTemplateDrawerOpen() && customDrawerParent()?.menuTemplate\">\n @if (customDrawerParent()?.menuTemplate) {\n <!-- Custom Drawer Header -->\n <div #customDrawerHeaderTrigger class=\"border-border flex h-14 shrink-0 items-center gap-3 border-b px-4\">\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"bg-accent h-9 w-9 shrink-0\"\n (click)=\"closeMobileTemplateDrawer()\">\n <z-icon zType=\"lucideChevronLeft\" zSize=\"20\" />\n </button>\n <span\n class=\"min-w-0 flex-1 truncate text-base font-semibold\"\n zTooltip\n [zContent]=\"customDrawerParent()?.name || '' | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"top\"\n [zTriggerElement]=\"customDrawerHeaderTrigger\">\n {{ customDrawerParent()?.name | translate }}\n </span>\n </div>\n\n <!-- Custom Template Content -->\n <ng-scrollbar class=\"z-menu-scrollbar flex-1\" track=\"vertical\">\n <div class=\"p-4\">\n <ng-container\n *ngTemplateOutlet=\"\n customDrawerParent()!.menuTemplate!;\n context: { $implicit: customDrawerParent()!, close: closeMobileDrawerFn }\n \" />\n </div>\n </ng-scrollbar>\n }\n </aside>\n\n <ng-template #mobileActionsPopoverTpl let-close=\"close\">\n <div class=\"min-w-48 p-1\">\n @if (zActionsTemplate()) {\n <ng-container *ngTemplateOutlet=\"zActionsTemplate(); context: { close: close }\" />\n } @else if (getVisibleUserActions().length > 0) {\n @for (action of getVisibleUserActions(); track action.id; let idx = $index) {\n @if (shouldShowDividerBefore(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ action.label | translate }}</span>\n </button>\n\n @if (shouldShowDividerAfter(action, idx)) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n }\n </div>\n </ng-template>\n</div>\n\n<!-- Shared Template for Menu Children -->\n<ng-template #menuChildrenTpl let-children>\n @for (child of children; track child.id) {\n @let isChildActive = selectedMenuItem()?.id === child.id && (!child.children || child.children.length === 0);\n @let isChildParentOfActive = isParentOfActiveItem(child);\n @let hasChildren = child.children && child.children.length > 0;\n @if (child.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ child.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"w-full min-w-0\">\n <div\n #divLevel1\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isChildActive\"\n [class.text-primary-foreground]=\"isChildActive\"\n [class.text-primary]=\"isChildParentOfActive && !isChildActive\"\n [class.hover:bg-gray-200]=\"!isChildActive\"\n [class.dark:hover:bg-input/50]=\"!isChildActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"18\" class=\"shrink-0\" />\n } @else if (child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"child.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel1\">\n {{ child.name | translate }}\n </span>\n @if (hasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-arrow shrink-0 opacity-60 transition-transform\"\n [class.expanded]=\"child.expanded\" />\n }\n </div>\n\n @if (hasChildren) {\n <div class=\"z-menu-submenu\" [class.expanded]=\"child.expanded\">\n <div class=\"z-menu-submenu-inner\">\n <div class=\"z-menu-tree relative ml-4 flex flex-col gap-1 pt-1 pl-3\">\n <div class=\"absolute top-0 bottom-2 left-0 w-px bg-gray-300 dark:bg-gray-600\"></div>\n\n @for (subChild of child.children; track subChild.id; let isLast = $last) {\n @let isSubChildActive = selectedMenuItem()?.id === subChild.id;\n <div class=\"relative w-full min-w-0\">\n <div class=\"absolute top-1/2 -left-3 h-px w-3 bg-gray-300 dark:bg-gray-600\"></div>\n\n <div\n #divLevel2\n class=\"z-menu-item flex w-full cursor-pointer items-center gap-2 rounded-[0.375rem] p-2\"\n [class.bg-primary]=\"isSubChildActive\"\n [class.text-primary-foreground]=\"isSubChildActive\"\n [class.hover:bg-gray-200]=\"!isSubChildActive\"\n [class.dark:hover:bg-input/50]=\"!isSubChildActive\"\n (click)=\"onMenuItemClick(subChild)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"16\" class=\"shrink-0\" />\n } @else if (subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n } @else {\n <div\n class=\"h-1 w-1 shrink-0 rounded-full\"\n [class.bg-primary-foreground]=\"isSubChildActive\"\n [class.bg-gray-400]=\"!isSubChildActive\"></div>\n }\n <span\n class=\"min-w-0 flex-1 truncate text-[0.8125rem] font-[450]\"\n zTooltip\n [zContent]=\"subChild.name | translate\"\n [zOffset]=\"6\"\n zMaxWidth=\"200px\"\n zPosition=\"right\"\n [zTriggerElement]=\"divLevel2\">\n {{ subChild.name | translate }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".z-menu{display:block;flex-shrink:0;height:100%}.z-menu [class*=cursor-pointer]{-webkit-user-select:none;user-select:none}@media(min-width:48rem){.z-menu{contain:layout style;min-width:283px;transition:min-width .25s cubic-bezier(.4,0,.2,1);will-change:min-width}.z-menu.z-menu-collapsed,.z-menu.z-menu-no-child{min-width:53px}}.z-shadow-menu{box-shadow:0 0 10px #0000001f}@media(max-width:47.9375rem){.z-menu-desktop{display:none!important;pointer-events:none;visibility:hidden}}.z-sidebar-main{position:relative;z-index:20;flex-shrink:0}.z-sidebar-child-wrapper{--sidebar-child-width: 230px;position:absolute;left:0;top:0;width:calc(100% + -0px);height:100%;clip-path:inset(0 -100px 0 0);pointer-events:none;transition:clip-path .25s cubic-bezier(.4,0,.2,1);will-change:clip-path;contain:layout}.z-sidebar-child-wrapper.collapsed{clip-path:inset(0 -100px 0 53px)}.z-sidebar-child{flex-shrink:0;height:100%;margin-left:53px;transform:translate(0);transition:transform .25s cubic-bezier(.4,0,.2,1),width .25s cubic-bezier(.4,0,.2,1);pointer-events:auto;will-change:transform,width;overflow:hidden;max-width:100%}.z-sidebar-child *{max-width:100%}.z-sidebar-child.collapsed{transform:translate(calc(-1 * (var(--sidebar-child-width) + 50px + .3125rem)))}.z-menu-arrow.expanded{transform:rotate(90deg)}.z-menu-submenu{display:grid;grid-template-rows:0fr;transition:grid-template-rows .15s ease-out}.z-menu-submenu.expanded{grid-template-rows:1fr}.z-menu-submenu>.z-menu-submenu-inner{overflow:hidden;min-height:0}.z-menu-backdrop{animation:z-menu-backdrop-enter .2s ease-out forwards}.z-menu-backdrop-dark{background-color:#0009}.z-menu-backdrop-blur{background-color:#0000000d;backdrop-filter:blur(2px)}.z-menu-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a}.z-menu-drawer.open{transform:translate(0)}:host.z-menu-mobile-open .z-menu-drawer{transform:translate(0)}.z-menu-desktop.collapsed .z-sidebar-child-wrapper{pointer-events:none}.z-menu-custom-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-custom-drawer.open{transform:translate(0)}@keyframes z-menu-backdrop-enter{0%{opacity:0}to{opacity:1}}@keyframes z-expand-btn-enter{0%{opacity:0;transform:scale(.5) translateY(.625rem)}70%{transform:scale(1.1) translateY(-.125rem)}to{opacity:1;transform:scale(1) translateY(0)}}.z-expand-btn{animation:z-expand-btn-enter .25s cubic-bezier(.34,1.56,.64,1) forwards}.z-menu-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-scrollbar .ng-scroll-viewport,.z-menu-scrollbar .ng-scroll-content{max-width:100%}.z-menu-item{min-width:0;overflow:hidden}\n"] }]
|
|
420
446
|
}], ctorParameters: () => [], propDecorators: { zOnSelect: [{ type: i0.Output, args: ["zOnSelect"] }], zOnMenuAction: [{ type: i0.Output, args: ["zOnMenuAction"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zLogo: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLogo", required: false }] }], zLogoMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLogoMobile", required: false }] }], zMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMenus", required: false }] }], zUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "zUser", required: false }] }], zUserActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zUserActions", required: false }] }], zActionsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "zActionsTemplate", required: false }] }], zCurrentPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCurrentPath", required: false }] }], zKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "zKey", required: false }] }] } });
|
|
421
447
|
|
|
422
448
|
class ZMenuV2Component {
|
|
@@ -427,49 +453,81 @@ class ZMenuV2Component {
|
|
|
427
453
|
zOnSelect = output();
|
|
428
454
|
zOnMenuAction = output();
|
|
429
455
|
zControl = output();
|
|
430
|
-
zLogo = input('assets/images/avatar.svg',
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
456
|
+
zLogo = input('assets/images/avatar.svg', /* @ts-ignore */
|
|
457
|
+
...(ngDevMode ? [{ debugName: "zLogo" }] : /* istanbul ignore next */ []));
|
|
458
|
+
zLogoMobile = input('', /* @ts-ignore */
|
|
459
|
+
...(ngDevMode ? [{ debugName: "zLogoMobile" }] : /* istanbul ignore next */ []));
|
|
460
|
+
zMenus = input([], /* @ts-ignore */
|
|
461
|
+
...(ngDevMode ? [{ debugName: "zMenus" }] : /* istanbul ignore next */ []));
|
|
462
|
+
zUser = input(null, /* @ts-ignore */
|
|
463
|
+
...(ngDevMode ? [{ debugName: "zUser" }] : /* istanbul ignore next */ []));
|
|
464
|
+
zUserActions = input([], /* @ts-ignore */
|
|
465
|
+
...(ngDevMode ? [{ debugName: "zUserActions" }] : /* istanbul ignore next */ []));
|
|
466
|
+
zCurrentPath = input('', /* @ts-ignore */
|
|
467
|
+
...(ngDevMode ? [{ debugName: "zCurrentPath" }] : /* istanbul ignore next */ []));
|
|
468
|
+
zKey = input('z-menu-v2', /* @ts-ignore */
|
|
469
|
+
...(ngDevMode ? [{ debugName: "zKey" }] : /* istanbul ignore next */ []));
|
|
470
|
+
zClass = input('', /* @ts-ignore */
|
|
471
|
+
...(ngDevMode ? [{ debugName: "zClass" }] : /* istanbul ignore next */ []));
|
|
472
|
+
zTitle = input('', /* @ts-ignore */
|
|
473
|
+
...(ngDevMode ? [{ debugName: "zTitle" }] : /* istanbul ignore next */ []));
|
|
474
|
+
zCollapsedWidth = input(60, /* @ts-ignore */
|
|
475
|
+
...(ngDevMode ? [{ debugName: "zCollapsedWidth" }] : /* istanbul ignore next */ []));
|
|
476
|
+
zExpandedWidth = input(248, /* @ts-ignore */
|
|
477
|
+
...(ngDevMode ? [{ debugName: "zExpandedWidth" }] : /* istanbul ignore next */ []));
|
|
478
|
+
zExpandMode = input('multiple', /* @ts-ignore */
|
|
479
|
+
...(ngDevMode ? [{ debugName: "zExpandMode" }] : /* istanbul ignore next */ []));
|
|
480
|
+
zShowMobileBar = input(false, /* @ts-ignore */
|
|
481
|
+
...(ngDevMode ? [{ debugName: "zShowMobileBar" }] : /* istanbul ignore next */ []));
|
|
482
|
+
selectedParent = signal(null, /* @ts-ignore */
|
|
483
|
+
...(ngDevMode ? [{ debugName: "selectedParent" }] : /* istanbul ignore next */ []));
|
|
484
|
+
selectedMenuItem = signal(null, /* @ts-ignore */
|
|
485
|
+
...(ngDevMode ? [{ debugName: "selectedMenuItem" }] : /* istanbul ignore next */ []));
|
|
486
|
+
mobileMenuOpen = signal(false, /* @ts-ignore */
|
|
487
|
+
...(ngDevMode ? [{ debugName: "mobileMenuOpen" }] : /* istanbul ignore next */ []));
|
|
488
|
+
sidebarCollapsed = signal(false, /* @ts-ignore */
|
|
489
|
+
...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
|
|
490
|
+
_expandedIds = signal(new Set(), /* @ts-ignore */
|
|
491
|
+
...(ngDevMode ? [{ debugName: "_expandedIds" }] : /* istanbul ignore next */ []));
|
|
492
|
+
_collapsedIds = signal(new Set(), /* @ts-ignore */
|
|
493
|
+
...(ngDevMode ? [{ debugName: "_collapsedIds" }] : /* istanbul ignore next */ []));
|
|
494
|
+
_renderedOpeningIds = signal(new Set(), /* @ts-ignore */
|
|
495
|
+
...(ngDevMode ? [{ debugName: "_renderedOpeningIds" }] : /* istanbul ignore next */ []));
|
|
496
|
+
_renderedClosingIds = signal(new Set(), /* @ts-ignore */
|
|
497
|
+
...(ngDevMode ? [{ debugName: "_renderedClosingIds" }] : /* istanbul ignore next */ []));
|
|
498
|
+
_activeCacheKey = signal('', /* @ts-ignore */
|
|
499
|
+
...(ngDevMode ? [{ debugName: "_activeCacheKey" }] : /* istanbul ignore next */ []));
|
|
500
|
+
_hasSyncedInitialPath = signal(false, /* @ts-ignore */
|
|
501
|
+
...(ngDevMode ? [{ debugName: "_hasSyncedInitialPath" }] : /* istanbul ignore next */ []));
|
|
453
502
|
_openingRenderTimers = new Map();
|
|
454
503
|
_closingRenderTimers = new Map();
|
|
455
|
-
zClasses = computed(() => zMergeClasses('z-menu-v2-shell bg-sidebar text-sidebar-foreground border-sidebar-border', this.zClass()),
|
|
504
|
+
zClasses = computed(() => zMergeClasses('z-menu-v2-shell bg-sidebar text-sidebar-foreground border-sidebar-border', this.zClass()), /* @ts-ignore */
|
|
505
|
+
...(ngDevMode ? [{ debugName: "zClasses" }] : /* istanbul ignore next */ []));
|
|
456
506
|
_isMobile$ = this._breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.Small]).pipe(map(result => result.matches), takeUntilDestroyed(this._destroyRef));
|
|
457
507
|
isMobile = toSignal(this._isMobile$, { initialValue: false });
|
|
458
|
-
mobileLogo = computed(() => this.zLogoMobile() || this.zLogo(),
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
508
|
+
mobileLogo = computed(() => this.zLogoMobile() || this.zLogo(), /* @ts-ignore */
|
|
509
|
+
...(ngDevMode ? [{ debugName: "mobileLogo" }] : /* istanbul ignore next */ []));
|
|
510
|
+
effectiveTitle = computed(() => this.zTitle() || 'i18n_z_ui_menu_navigation', /* @ts-ignore */
|
|
511
|
+
...(ngDevMode ? [{ debugName: "effectiveTitle" }] : /* istanbul ignore next */ []));
|
|
512
|
+
avatarSrc = computed(() => this.zUser()?.avatar || this.zLogo(), /* @ts-ignore */
|
|
513
|
+
...(ngDevMode ? [{ debugName: "avatarSrc" }] : /* istanbul ignore next */ []));
|
|
514
|
+
visibleUserActions = computed(() => this.zUserActions().filter(action => !action.hidden), /* @ts-ignore */
|
|
515
|
+
...(ngDevMode ? [{ debugName: "visibleUserActions" }] : /* istanbul ignore next */ []));
|
|
462
516
|
_routerPath = toSignal(this._router.events.pipe(filter((e) => e instanceof NavigationEnd), map(e => e.urlAfterRedirects), startWith(this._router.url)), { initialValue: this._router.url });
|
|
463
|
-
_currentPath = computed(() => this.zCurrentPath() || this._routerPath(),
|
|
517
|
+
_currentPath = computed(() => this.zCurrentPath() || this._routerPath(), /* @ts-ignore */
|
|
518
|
+
...(ngDevMode ? [{ debugName: "_currentPath" }] : /* istanbul ignore next */ []));
|
|
464
519
|
overlayType = computed(() => {
|
|
465
520
|
if (!isPlatformBrowser(this._platformId)) {
|
|
466
521
|
return 'dark';
|
|
467
522
|
}
|
|
468
523
|
const browser = zDetectBrowser();
|
|
469
524
|
return browser.name === 'Chrome' ? 'dark' : 'blur';
|
|
470
|
-
},
|
|
471
|
-
|
|
472
|
-
|
|
525
|
+
}, /* @ts-ignore */
|
|
526
|
+
...(ngDevMode ? [{ debugName: "overlayType" }] : /* istanbul ignore next */ []));
|
|
527
|
+
menuProcessed = computed(() => this._processMenus(this.zMenus(), this._expandedIds(), this._collapsedIds(), this._renderedOpeningIds(), this._renderedClosingIds()), /* @ts-ignore */
|
|
528
|
+
...(ngDevMode ? [{ debugName: "menuProcessed" }] : /* istanbul ignore next */ []));
|
|
529
|
+
menuParents = computed(() => this.menuProcessed().tree.filter((item) => !item.parent || item.parent.length === 0), /* @ts-ignore */
|
|
530
|
+
...(ngDevMode ? [{ debugName: "menuParents" }] : /* istanbul ignore next */ []));
|
|
473
531
|
parentWithActiveChild = computed(() => {
|
|
474
532
|
const activeItem = this.selectedMenuItem();
|
|
475
533
|
if (!activeItem) {
|
|
@@ -480,7 +538,8 @@ class ZMenuV2Component {
|
|
|
480
538
|
}
|
|
481
539
|
const topLevelParentId = activeItem.parent[0];
|
|
482
540
|
return this.menuParents().find(parent => parent.id === topLevelParentId) ?? null;
|
|
483
|
-
},
|
|
541
|
+
}, /* @ts-ignore */
|
|
542
|
+
...(ngDevMode ? [{ debugName: "parentWithActiveChild" }] : /* istanbul ignore next */ []));
|
|
484
543
|
constructor() {
|
|
485
544
|
effect(() => {
|
|
486
545
|
if (this._hasSyncedInitialPath()) {
|
|
@@ -814,10 +873,10 @@ class ZMenuV2Component {
|
|
|
814
873
|
_getStateMenuCollapsed(key) {
|
|
815
874
|
return ZCacheService.get(key, false) ?? false;
|
|
816
875
|
}
|
|
817
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
818
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZMenuV2Component, isStandalone: true, selector: "z-menu-v2", inputs: { zLogo: { classPropertyName: "zLogo", publicName: "zLogo", isSignal: true, isRequired: false, transformFunction: null }, zLogoMobile: { classPropertyName: "zLogoMobile", publicName: "zLogoMobile", isSignal: true, isRequired: false, transformFunction: null }, zMenus: { classPropertyName: "zMenus", publicName: "zMenus", isSignal: true, isRequired: false, transformFunction: null }, zUser: { classPropertyName: "zUser", publicName: "zUser", isSignal: true, isRequired: false, transformFunction: null }, zUserActions: { classPropertyName: "zUserActions", publicName: "zUserActions", isSignal: true, isRequired: false, transformFunction: null }, zCurrentPath: { classPropertyName: "zCurrentPath", publicName: "zCurrentPath", isSignal: true, isRequired: false, transformFunction: null }, zKey: { classPropertyName: "zKey", publicName: "zKey", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zCollapsedWidth: { classPropertyName: "zCollapsedWidth", publicName: "zCollapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, zExpandedWidth: { classPropertyName: "zExpandedWidth", publicName: "zExpandedWidth", isSignal: true, isRequired: false, transformFunction: null }, zExpandMode: { classPropertyName: "zExpandMode", publicName: "zExpandMode", isSignal: true, isRequired: false, transformFunction: null }, zShowMobileBar: { classPropertyName: "zShowMobileBar", publicName: "zShowMobileBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnSelect: "zOnSelect", zOnMenuAction: "zOnMenuAction", zControl: "zControl" }, host: { properties: { "class.z-menu-v2-collapsed": "sidebarCollapsed()", "class.z-menu-v2-mobile-open": "mobileMenuOpen()", "class.z-menu-v2-mobile": "isMobile()" }, classAttribute: "z-menu-v2 block" }, providers: [TranslatePipe], ngImport: i0, template: "<aside\n class=\"hidden h-full min-h-0 flex-col overflow-hidden border-r shadow-sm md:flex\"\n [class]=\"zClasses()\"\n [style.--z-menu-v2-expanded-width.px]=\"zExpandedWidth()\"\n [style.--z-menu-v2-collapsed-width.px]=\"zCollapsedWidth()\">\n <div\n class=\"border-sidebar-border flex h-14 shrink-0 items-center gap-2 border-b px-3\"\n [class.justify-center]=\"sidebarCollapsed()\">\n @if (!sidebarCollapsed() && zLogo()) {\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto shrink-0 object-contain transition-opacity\" />\n }\n\n @if (!sidebarCollapsed()) {\n <div\n class=\"min-w-0 flex-1 overflow-hidden text-sm font-semibold text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"effectiveTitle() | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ effectiveTitle() | translate }}\n </div>\n }\n\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"z-menu-v2-toggle h-9 w-9 shrink-0\"\n [class.z-menu-v2-toggle-collapsed]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"\n (sidebarCollapsed() ? 'i18n_z_ui_menu_expand_sidebar' : 'i18n_z_ui_menu_collapse_sidebar') | translate\n \"\n (click)=\"toggleSidebar()\">\n <z-icon [zType]=\"sidebarCollapsed() ? 'lucidePanelLeftOpen' : 'lucidePanelLeftClose'\" zSize=\"18\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar min-h-0 flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-2\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n @if (parent.groupLabel && !sidebarCollapsed()) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n @if (sidebarCollapsed() && parentHasChildren) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"parentPopoverTpl\"\n [zPopoverWidth]=\"256\"\n zPosition=\"right-top\"\n [zOffset]=\"10\"\n class=\"z-menu-v2-icon-item\"\n [class.active]=\"parentActive || parentLeafActive\"\n [attr.aria-label]=\"parent.name | translate\"\n (click)=\"onCollapsedParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"20\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"20\" />\n }\n </button>\n\n <ng-template #parentPopoverTpl let-close=\"close\">\n <div class=\"z-menu-v2-popover w-64 max-w-64 min-w-0 pt-1 pl-1\">\n <div\n #parentPopoverHeaderTrigger\n class=\"text-muted-foreground flex items-center gap-2 px-2 py-2 text-xs font-medium\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"15\" />\n }\n <span\n class=\"overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentPopoverHeaderTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n </div>\n <ng-scrollbar class=\"z-menu-v2-popover-scrollbar\" orientation=\"vertical\" visibility=\"visible\">\n <div class=\"z-menu-v2-popover-scroll-content pr-2 pb-1\">\n <ng-container\n *ngTemplateOutlet=\"collapsedChildrenTpl; context: { $implicit: parent.children, close: close }\" />\n </div>\n </ng-scrollbar>\n </div>\n </ng-template>\n }\n @if (!(sidebarCollapsed() && parentHasChildren)) {\n <ng-container *ngTemplateOutlet=\"openParentTpl; context: { $implicit: parent }\" />\n }\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"userFooterTpl\" />\n</aside>\n\n<ng-template #openParentTpl let-parent>\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n <div class=\"z-menu-v2-menu-group\">\n <button\n #parentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n [class.icon-only]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? (parent.name | translate) : null\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\"\n [zDisabled]=\"!sidebarCollapsed()\"\n [zAlwaysShow]=\"sidebarCollapsed()\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n\n @if (!sidebarCollapsed()) {\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n }\n </button>\n\n @if (!sidebarCollapsed() && parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'right' }\" />\n </div>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #collapsedChildrenTpl let-children let-close=\"close\">\n <div class=\"z-menu-v2-submenu z-menu-v2-popover-tree\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #collapsedChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"childHasChildren ? onMenuItemClick(child) : onCollapsedLeafClick(child, close)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"collapsedChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel collapsed-popover\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <div class=\"z-menu-v2-submenu z-menu-v2-submenu-nested\">\n @for (subChild of child.children; track subChild.id) {\n @let subChildActive = selectedMenuItem()?.id === subChild.id;\n <button\n #collapsedSubChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"subChildActive\"\n (click)=\"onCollapsedLeafClick(subChild, close)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && !subChild.iconSvg) {\n <span class=\"z-menu-v2-dot small\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"subChild.name | translate\"\n [zTriggerElement]=\"collapsedSubChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ subChild.name | translate }}\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #userFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-2\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n [zOffset]=\"10\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\"\n [class.justify-center]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? zUser()?.name || 'User Name' : null\">\n <span class=\"h-9 w-9 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n @if (!sidebarCollapsed()) {\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n }\n </button>\n </div>\n</ng-template>\n\n<ng-template #mobileUserFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-3\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"top-right\"\n [zOffset]=\"6\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\">\n <span class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n </button>\n </div>\n</ng-template>\n\n<ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"overflow-hidden font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground mt-0.5 overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n\n @if (visibleUserActions().length > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n @for (action of visibleUserActions(); track action.id; let idx = $index) {\n @if (action.divide === 'before' && idx > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n #userActionTrigger\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span\n class=\"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"action.label | translate\"\n [zTriggerElement]=\"userActionTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ action.label | translate }}\n </span>\n </button>\n\n @if (action.divide === 'after' && idx < visibleUserActions().length - 1) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #openChildrenTpl let-children let-position=\"position\">\n <div class=\"z-menu-v2-submenu\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #openChildTrigger\n type=\"button\"\n class=\"z-menu-v2-item z-menu-v2-item-child\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"openChildTrigger\"\n [zPosition]=\"position\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: child.children, position: position }\" />\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n@if (zShowMobileBar()) {\n <div\n class=\"z-menu-v2-mobile-bar border-border bg-background flex h-14 items-center justify-between border-b px-4 md:hidden\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"openMobileMenu()\">\n <z-icon zType=\"lucideMenu\" zSize=\"20\" />\n </button>\n </div>\n}\n\n@if (mobileMenuOpen()) {\n <div\n class=\"z-menu-v2-backdrop fixed inset-0 z-9998 md:hidden\"\n [class.z-menu-v2-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-v2-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onMobileBackdropClick()\"></div>\n}\n\n<aside\n class=\"z-menu-v2-mobile-drawer bg-sidebar text-sidebar-foreground border-sidebar-border fixed top-0 left-0 z-9999 flex h-full w-72 max-w-[calc(100vw-1rem)] flex-col border-r md:hidden\"\n [class.open]=\"mobileMenuOpen()\">\n <div class=\"border-sidebar-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-3\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n @if (parent.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"z-menu-v2-menu-group\">\n <button\n #mobileParentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"mobileParentTrigger\"\n zPosition=\"top\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n </button>\n\n @if (parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'top' }\" />\n </div>\n </div>\n }\n </div>\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"mobileUserFooterTpl\" />\n</aside>\n", styles: [".z-menu-v2{display:block;flex-shrink:0;height:100%}.z-menu-v2 [class*=cursor-pointer],.z-menu-v2 button{-webkit-user-select:none;user-select:none}.z-menu-v2-shell{width:var(--z-menu-v2-expanded-width, 248px);transition:width .2s cubic-bezier(.4,0,.2,1);will-change:width}.z-menu-v2-collapsed .z-menu-v2-shell{width:var(--z-menu-v2-collapsed-width, 60px)}.z-menu-v2-toggle{position:relative;z-index:1}.z-menu-v2-toggle.z-menu-v2-toggle-collapsed{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.z-menu-v2-nav{gap:.25rem}.z-menu-v2-menu-group{display:flex;min-width:0;flex-direction:column}.z-menu-v2-item,.z-menu-v2-popover-item,.z-menu-v2-icon-item{min-width:0;border-radius:.375rem;outline:none;transition:background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.625rem;padding:.5rem .625rem;font-size:.8125rem;font-weight:450}.z-menu-v2-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-item.parent-active:not(.active){color:var(--sidebar-primary)}.z-menu-v2-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-item.active .z-menu-v2-dot,.z-menu-v2-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item.icon-only{justify-content:center;padding-inline:0;width:2.5rem;height:2.5rem;margin-inline:auto}.z-menu-v2-icon-item{display:flex;width:2.5rem;height:2.5rem;cursor:pointer;align-items:center;justify-content:center;margin-inline:auto}.z-menu-v2-icon-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-icon-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;padding:.45rem .5rem;font-size:.8125rem;font-weight:450}.z-menu-v2-popover-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-popover-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item.parent-active:not(.active){background-color:transparent;color:var(--sidebar-primary)}.z-menu-v2-popover-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-popover-item.active .z-menu-v2-dot,.z-menu-v2-popover-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item-child{position:relative;padding-left:.75rem}.z-menu-v2-item-sub-child{position:relative;padding-left:.75rem;font-size:.78125rem}.z-menu-v2-submenu-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .24s cubic-bezier(.16,1,.3,1)}.z-menu-v2-submenu-panel.expanded{grid-template-rows:1fr}.z-menu-v2-submenu-panel-inner{min-height:0;overflow:hidden}.z-menu-v2-submenu-panel-inner:before{content:\"\";display:block;height:.25rem}.z-menu-v2-submenu{position:relative;display:flex;min-width:0;min-height:0;flex-direction:column;gap:.25rem;margin:0 0 0 .875rem;padding-left:.875rem}.z-menu-v2-submenu:before{content:\"\";position:absolute;top:0;bottom:.75rem;left:0;width:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item,.z-menu-v2-submenu .z-menu-v2-popover-item{position:relative}.z-menu-v2-submenu .z-menu-v2-item:before,.z-menu-v2-submenu .z-menu-v2-popover-item:before{content:\"\";position:absolute;top:50%;left:-.875rem;width:.875rem;height:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item.active:before,.z-menu-v2-submenu .z-menu-v2-item.parent-active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.parent-active:before{background-color:color-mix(in oklab,var(--sidebar-primary) 72%,var(--sidebar-border))}.z-menu-v2-submenu-nested{margin-left:.75rem}.z-menu-v2-popover-tree{margin-top:0;margin-bottom:0}.z-menu-v2-popover-scrollbar{--scrollbar-padding: 0;--scrollbar-overscroll-behavior: contain;max-height:min(28rem,100vh - 8rem);min-height:0;overflow-x:hidden;overflow-y:auto}.z-menu-v2-popover-scroll-content{min-width:0}.z-menu-v2-arrow{transition:transform .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-arrow.expanded{transform:rotate(90deg)}.z-menu-v2-dot{display:inline-flex;width:.375rem;height:.375rem;flex-shrink:0;border-radius:9999px;background-color:color-mix(in oklab,var(--sidebar-foreground) 58%,transparent)}.z-menu-v2-dot.small{width:.25rem;height:.25rem}.z-menu-v2-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-v2-scrollbar .ng-scroll-viewport,.z-menu-v2-scrollbar .ng-scroll-content{max-width:100%}.z-menu-v2-backdrop{animation:z-menu-v2-backdrop-enter .2s ease-out forwards}.z-menu-v2-backdrop-dark{background-color:#0009}.z-menu-v2-backdrop-blur{background-color:#0000000d;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.z-menu-v2-mobile-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-v2-mobile-drawer.open{transform:translate(0)}@keyframes z-menu-v2-backdrop-enter{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zSticky", "zShowArrow", "zKeyboardSafe"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
876
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZMenuV2Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
877
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: ZMenuV2Component, isStandalone: true, selector: "z-menu-v2", inputs: { zLogo: { classPropertyName: "zLogo", publicName: "zLogo", isSignal: true, isRequired: false, transformFunction: null }, zLogoMobile: { classPropertyName: "zLogoMobile", publicName: "zLogoMobile", isSignal: true, isRequired: false, transformFunction: null }, zMenus: { classPropertyName: "zMenus", publicName: "zMenus", isSignal: true, isRequired: false, transformFunction: null }, zUser: { classPropertyName: "zUser", publicName: "zUser", isSignal: true, isRequired: false, transformFunction: null }, zUserActions: { classPropertyName: "zUserActions", publicName: "zUserActions", isSignal: true, isRequired: false, transformFunction: null }, zCurrentPath: { classPropertyName: "zCurrentPath", publicName: "zCurrentPath", isSignal: true, isRequired: false, transformFunction: null }, zKey: { classPropertyName: "zKey", publicName: "zKey", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zCollapsedWidth: { classPropertyName: "zCollapsedWidth", publicName: "zCollapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, zExpandedWidth: { classPropertyName: "zExpandedWidth", publicName: "zExpandedWidth", isSignal: true, isRequired: false, transformFunction: null }, zExpandMode: { classPropertyName: "zExpandMode", publicName: "zExpandMode", isSignal: true, isRequired: false, transformFunction: null }, zShowMobileBar: { classPropertyName: "zShowMobileBar", publicName: "zShowMobileBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnSelect: "zOnSelect", zOnMenuAction: "zOnMenuAction", zControl: "zControl" }, host: { properties: { "class.z-menu-v2-collapsed": "sidebarCollapsed()", "class.z-menu-v2-mobile-open": "mobileMenuOpen()", "class.z-menu-v2-mobile": "isMobile()" }, classAttribute: "z-menu-v2 block" }, providers: [TranslatePipe], ngImport: i0, template: "<aside\n class=\"hidden h-full min-h-0 flex-col overflow-hidden border-r shadow-sm md:flex\"\n [class]=\"zClasses()\"\n [style.--z-menu-v2-expanded-width.px]=\"zExpandedWidth()\"\n [style.--z-menu-v2-collapsed-width.px]=\"zCollapsedWidth()\">\n <div\n class=\"border-sidebar-border flex h-14 shrink-0 items-center gap-2 border-b px-3\"\n [class.justify-center]=\"sidebarCollapsed()\">\n @if (!sidebarCollapsed() && zLogo()) {\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto shrink-0 object-contain transition-opacity\" />\n }\n\n @if (!sidebarCollapsed()) {\n <div\n class=\"min-w-0 flex-1 overflow-hidden text-sm font-semibold text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"effectiveTitle() | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ effectiveTitle() | translate }}\n </div>\n }\n\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"z-menu-v2-toggle h-9 w-9 shrink-0\"\n [class.z-menu-v2-toggle-collapsed]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"\n (sidebarCollapsed() ? 'i18n_z_ui_menu_expand_sidebar' : 'i18n_z_ui_menu_collapse_sidebar') | translate\n \"\n (click)=\"toggleSidebar()\">\n <z-icon [zType]=\"sidebarCollapsed() ? 'lucidePanelLeftOpen' : 'lucidePanelLeftClose'\" zSize=\"18\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar min-h-0 flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-2\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n @if (parent.groupLabel && !sidebarCollapsed()) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n @if (sidebarCollapsed() && parentHasChildren) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"parentPopoverTpl\"\n [zPopoverWidth]=\"256\"\n zPosition=\"right-top\"\n [zOffset]=\"10\"\n class=\"z-menu-v2-icon-item\"\n [class.active]=\"parentActive || parentLeafActive\"\n [attr.aria-label]=\"parent.name | translate\"\n (click)=\"onCollapsedParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"20\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"20\" />\n }\n </button>\n\n <ng-template #parentPopoverTpl let-close=\"close\">\n <div class=\"z-menu-v2-popover w-64 max-w-64 min-w-0 pt-1 pl-1\">\n <div\n #parentPopoverHeaderTrigger\n class=\"text-muted-foreground flex items-center gap-2 px-2 py-2 text-xs font-medium\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"15\" />\n }\n <span\n class=\"overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentPopoverHeaderTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n </div>\n <ng-scrollbar class=\"z-menu-v2-popover-scrollbar\" orientation=\"vertical\" visibility=\"visible\">\n <div class=\"z-menu-v2-popover-scroll-content pr-2 pb-1\">\n <ng-container\n *ngTemplateOutlet=\"collapsedChildrenTpl; context: { $implicit: parent.children, close: close }\" />\n </div>\n </ng-scrollbar>\n </div>\n </ng-template>\n }\n @if (!(sidebarCollapsed() && parentHasChildren)) {\n <ng-container *ngTemplateOutlet=\"openParentTpl; context: { $implicit: parent }\" />\n }\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"userFooterTpl\" />\n</aside>\n\n<ng-template #openParentTpl let-parent>\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n <div class=\"z-menu-v2-menu-group\">\n <button\n #parentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n [class.icon-only]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? (parent.name | translate) : null\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\"\n [zDisabled]=\"!sidebarCollapsed()\"\n [zAlwaysShow]=\"sidebarCollapsed()\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n\n @if (!sidebarCollapsed()) {\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n }\n </button>\n\n @if (!sidebarCollapsed() && parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'right' }\" />\n </div>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #collapsedChildrenTpl let-children let-close=\"close\">\n <div class=\"z-menu-v2-submenu z-menu-v2-popover-tree\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #collapsedChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"childHasChildren ? onMenuItemClick(child) : onCollapsedLeafClick(child, close)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"collapsedChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel collapsed-popover\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <div class=\"z-menu-v2-submenu z-menu-v2-submenu-nested\">\n @for (subChild of child.children; track subChild.id) {\n @let subChildActive = selectedMenuItem()?.id === subChild.id;\n <button\n #collapsedSubChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"subChildActive\"\n (click)=\"onCollapsedLeafClick(subChild, close)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && !subChild.iconSvg) {\n <span class=\"z-menu-v2-dot small\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"subChild.name | translate\"\n [zTriggerElement]=\"collapsedSubChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ subChild.name | translate }}\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #userFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-2\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n [zOffset]=\"10\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\"\n [class.justify-center]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? zUser()?.name || 'User Name' : null\">\n <span class=\"h-9 w-9 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n @if (!sidebarCollapsed()) {\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n }\n </button>\n </div>\n</ng-template>\n\n<ng-template #mobileUserFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-3\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"top-right\"\n [zOffset]=\"6\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\">\n <span class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n </button>\n </div>\n</ng-template>\n\n<ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"overflow-hidden font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground mt-0.5 overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n\n @if (visibleUserActions().length > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n @for (action of visibleUserActions(); track action.id; let idx = $index) {\n @if (action.divide === 'before' && idx > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n #userActionTrigger\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span\n class=\"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"action.label | translate\"\n [zTriggerElement]=\"userActionTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ action.label | translate }}\n </span>\n </button>\n\n @if (action.divide === 'after' && idx < visibleUserActions().length - 1) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #openChildrenTpl let-children let-position=\"position\">\n <div class=\"z-menu-v2-submenu\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #openChildTrigger\n type=\"button\"\n class=\"z-menu-v2-item z-menu-v2-item-child\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"openChildTrigger\"\n [zPosition]=\"position\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: child.children, position: position }\" />\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n@if (zShowMobileBar()) {\n <div\n class=\"z-menu-v2-mobile-bar border-border bg-background flex h-14 items-center justify-between border-b px-4 md:hidden\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"openMobileMenu()\">\n <z-icon zType=\"lucideMenu\" zSize=\"20\" />\n </button>\n </div>\n}\n\n@if (mobileMenuOpen()) {\n <div\n class=\"z-menu-v2-backdrop fixed inset-0 z-9998 md:hidden\"\n [class.z-menu-v2-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-v2-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onMobileBackdropClick()\"></div>\n}\n\n<aside\n class=\"z-menu-v2-mobile-drawer bg-sidebar text-sidebar-foreground border-sidebar-border fixed top-0 left-0 z-9999 flex h-full w-72 max-w-[calc(100vw-1rem)] flex-col border-r md:hidden\"\n [class.open]=\"mobileMenuOpen()\">\n <div class=\"border-sidebar-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-3\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n @if (parent.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"z-menu-v2-menu-group\">\n <button\n #mobileParentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"mobileParentTrigger\"\n zPosition=\"top\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n </button>\n\n @if (parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'top' }\" />\n </div>\n </div>\n }\n </div>\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"mobileUserFooterTpl\" />\n</aside>\n", styles: [".z-menu-v2{display:block;flex-shrink:0;height:100%}.z-menu-v2 [class*=cursor-pointer],.z-menu-v2 button{-webkit-user-select:none;user-select:none}.z-menu-v2-shell{width:var(--z-menu-v2-expanded-width, 248px);transition:width .2s cubic-bezier(.4,0,.2,1);will-change:width}.z-menu-v2-collapsed .z-menu-v2-shell{width:var(--z-menu-v2-collapsed-width, 60px)}.z-menu-v2-toggle{position:relative;z-index:1}.z-menu-v2-toggle.z-menu-v2-toggle-collapsed{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.z-menu-v2-nav{gap:.25rem}.z-menu-v2-menu-group{display:flex;min-width:0;flex-direction:column}.z-menu-v2-item,.z-menu-v2-popover-item,.z-menu-v2-icon-item{min-width:0;border-radius:.375rem;outline:none;transition:background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.625rem;padding:.5rem .625rem;font-size:.8125rem;font-weight:450}.z-menu-v2-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-item.parent-active:not(.active){color:var(--sidebar-primary)}.z-menu-v2-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-item.active .z-menu-v2-dot,.z-menu-v2-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item.icon-only{justify-content:center;padding-inline:0;width:2.5rem;height:2.5rem;margin-inline:auto}.z-menu-v2-icon-item{display:flex;width:2.5rem;height:2.5rem;cursor:pointer;align-items:center;justify-content:center;margin-inline:auto}.z-menu-v2-icon-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-icon-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;padding:.45rem .5rem;font-size:.8125rem;font-weight:450}.z-menu-v2-popover-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-popover-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item.parent-active:not(.active){background-color:transparent;color:var(--sidebar-primary)}.z-menu-v2-popover-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-popover-item.active .z-menu-v2-dot,.z-menu-v2-popover-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item-child{position:relative;padding-left:.75rem}.z-menu-v2-item-sub-child{position:relative;padding-left:.75rem;font-size:.78125rem}.z-menu-v2-submenu-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .24s cubic-bezier(.16,1,.3,1)}.z-menu-v2-submenu-panel.expanded{grid-template-rows:1fr}.z-menu-v2-submenu-panel-inner{min-height:0;overflow:hidden}.z-menu-v2-submenu-panel-inner:before{content:\"\";display:block;height:.25rem}.z-menu-v2-submenu{position:relative;display:flex;min-width:0;min-height:0;flex-direction:column;gap:.25rem;margin:0 0 0 .875rem;padding-left:.875rem}.z-menu-v2-submenu:before{content:\"\";position:absolute;top:0;bottom:.75rem;left:0;width:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item,.z-menu-v2-submenu .z-menu-v2-popover-item{position:relative}.z-menu-v2-submenu .z-menu-v2-item:before,.z-menu-v2-submenu .z-menu-v2-popover-item:before{content:\"\";position:absolute;top:50%;left:-.875rem;width:.875rem;height:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item.active:before,.z-menu-v2-submenu .z-menu-v2-item.parent-active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.parent-active:before{background-color:color-mix(in oklab,var(--sidebar-primary) 72%,var(--sidebar-border))}.z-menu-v2-submenu-nested{margin-left:.75rem}.z-menu-v2-popover-tree{margin-top:0;margin-bottom:0}.z-menu-v2-popover-scrollbar{--scrollbar-padding: 0;--scrollbar-overscroll-behavior: contain;max-height:min(28rem,100vh - 8rem);min-height:0;overflow-x:hidden;overflow-y:auto}.z-menu-v2-popover-scroll-content{min-width:0}.z-menu-v2-arrow{transition:transform .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-arrow.expanded{transform:rotate(90deg)}.z-menu-v2-dot{display:inline-flex;width:.375rem;height:.375rem;flex-shrink:0;border-radius:9999px;background-color:color-mix(in oklab,var(--sidebar-foreground) 58%,transparent)}.z-menu-v2-dot.small{width:.25rem;height:.25rem}.z-menu-v2-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-v2-scrollbar .ng-scroll-viewport,.z-menu-v2-scrollbar .ng-scroll-content{max-width:100%}.z-menu-v2-backdrop{animation:z-menu-v2-backdrop-enter .2s ease-out forwards}.z-menu-v2-backdrop-dark{background-color:#0009}.z-menu-v2-backdrop-blur{background-color:#0000000d;backdrop-filter:blur(2px)}.z-menu-v2-mobile-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-v2-mobile-drawer.open{transform:translate(0)}@keyframes z-menu-v2-backdrop-enter{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zSticky", "zShowArrow", "zKeyboardSafe"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
819
878
|
}
|
|
820
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
879
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZMenuV2Component, decorators: [{
|
|
821
880
|
type: Component,
|
|
822
881
|
args: [{ selector: 'z-menu-v2', imports: [
|
|
823
882
|
NgTemplateOutlet,
|
|
@@ -832,7 +891,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
|
|
|
832
891
|
'[class.z-menu-v2-collapsed]': 'sidebarCollapsed()',
|
|
833
892
|
'[class.z-menu-v2-mobile-open]': 'mobileMenuOpen()',
|
|
834
893
|
'[class.z-menu-v2-mobile]': 'isMobile()',
|
|
835
|
-
}, template: "<aside\n class=\"hidden h-full min-h-0 flex-col overflow-hidden border-r shadow-sm md:flex\"\n [class]=\"zClasses()\"\n [style.--z-menu-v2-expanded-width.px]=\"zExpandedWidth()\"\n [style.--z-menu-v2-collapsed-width.px]=\"zCollapsedWidth()\">\n <div\n class=\"border-sidebar-border flex h-14 shrink-0 items-center gap-2 border-b px-3\"\n [class.justify-center]=\"sidebarCollapsed()\">\n @if (!sidebarCollapsed() && zLogo()) {\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto shrink-0 object-contain transition-opacity\" />\n }\n\n @if (!sidebarCollapsed()) {\n <div\n class=\"min-w-0 flex-1 overflow-hidden text-sm font-semibold text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"effectiveTitle() | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ effectiveTitle() | translate }}\n </div>\n }\n\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"z-menu-v2-toggle h-9 w-9 shrink-0\"\n [class.z-menu-v2-toggle-collapsed]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"\n (sidebarCollapsed() ? 'i18n_z_ui_menu_expand_sidebar' : 'i18n_z_ui_menu_collapse_sidebar') | translate\n \"\n (click)=\"toggleSidebar()\">\n <z-icon [zType]=\"sidebarCollapsed() ? 'lucidePanelLeftOpen' : 'lucidePanelLeftClose'\" zSize=\"18\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar min-h-0 flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-2\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n @if (parent.groupLabel && !sidebarCollapsed()) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n @if (sidebarCollapsed() && parentHasChildren) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"parentPopoverTpl\"\n [zPopoverWidth]=\"256\"\n zPosition=\"right-top\"\n [zOffset]=\"10\"\n class=\"z-menu-v2-icon-item\"\n [class.active]=\"parentActive || parentLeafActive\"\n [attr.aria-label]=\"parent.name | translate\"\n (click)=\"onCollapsedParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"20\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"20\" />\n }\n </button>\n\n <ng-template #parentPopoverTpl let-close=\"close\">\n <div class=\"z-menu-v2-popover w-64 max-w-64 min-w-0 pt-1 pl-1\">\n <div\n #parentPopoverHeaderTrigger\n class=\"text-muted-foreground flex items-center gap-2 px-2 py-2 text-xs font-medium\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"15\" />\n }\n <span\n class=\"overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentPopoverHeaderTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n </div>\n <ng-scrollbar class=\"z-menu-v2-popover-scrollbar\" orientation=\"vertical\" visibility=\"visible\">\n <div class=\"z-menu-v2-popover-scroll-content pr-2 pb-1\">\n <ng-container\n *ngTemplateOutlet=\"collapsedChildrenTpl; context: { $implicit: parent.children, close: close }\" />\n </div>\n </ng-scrollbar>\n </div>\n </ng-template>\n }\n @if (!(sidebarCollapsed() && parentHasChildren)) {\n <ng-container *ngTemplateOutlet=\"openParentTpl; context: { $implicit: parent }\" />\n }\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"userFooterTpl\" />\n</aside>\n\n<ng-template #openParentTpl let-parent>\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n <div class=\"z-menu-v2-menu-group\">\n <button\n #parentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n [class.icon-only]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? (parent.name | translate) : null\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\"\n [zDisabled]=\"!sidebarCollapsed()\"\n [zAlwaysShow]=\"sidebarCollapsed()\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n\n @if (!sidebarCollapsed()) {\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n }\n </button>\n\n @if (!sidebarCollapsed() && parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'right' }\" />\n </div>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #collapsedChildrenTpl let-children let-close=\"close\">\n <div class=\"z-menu-v2-submenu z-menu-v2-popover-tree\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #collapsedChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"childHasChildren ? onMenuItemClick(child) : onCollapsedLeafClick(child, close)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"collapsedChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel collapsed-popover\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <div class=\"z-menu-v2-submenu z-menu-v2-submenu-nested\">\n @for (subChild of child.children; track subChild.id) {\n @let subChildActive = selectedMenuItem()?.id === subChild.id;\n <button\n #collapsedSubChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"subChildActive\"\n (click)=\"onCollapsedLeafClick(subChild, close)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && !subChild.iconSvg) {\n <span class=\"z-menu-v2-dot small\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"subChild.name | translate\"\n [zTriggerElement]=\"collapsedSubChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ subChild.name | translate }}\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #userFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-2\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n [zOffset]=\"10\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\"\n [class.justify-center]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? zUser()?.name || 'User Name' : null\">\n <span class=\"h-9 w-9 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n @if (!sidebarCollapsed()) {\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n }\n </button>\n </div>\n</ng-template>\n\n<ng-template #mobileUserFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-3\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"top-right\"\n [zOffset]=\"6\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\">\n <span class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n </button>\n </div>\n</ng-template>\n\n<ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"overflow-hidden font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground mt-0.5 overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n\n @if (visibleUserActions().length > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n @for (action of visibleUserActions(); track action.id; let idx = $index) {\n @if (action.divide === 'before' && idx > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n #userActionTrigger\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span\n class=\"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"action.label | translate\"\n [zTriggerElement]=\"userActionTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ action.label | translate }}\n </span>\n </button>\n\n @if (action.divide === 'after' && idx < visibleUserActions().length - 1) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #openChildrenTpl let-children let-position=\"position\">\n <div class=\"z-menu-v2-submenu\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #openChildTrigger\n type=\"button\"\n class=\"z-menu-v2-item z-menu-v2-item-child\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"openChildTrigger\"\n [zPosition]=\"position\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: child.children, position: position }\" />\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n@if (zShowMobileBar()) {\n <div\n class=\"z-menu-v2-mobile-bar border-border bg-background flex h-14 items-center justify-between border-b px-4 md:hidden\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"openMobileMenu()\">\n <z-icon zType=\"lucideMenu\" zSize=\"20\" />\n </button>\n </div>\n}\n\n@if (mobileMenuOpen()) {\n <div\n class=\"z-menu-v2-backdrop fixed inset-0 z-9998 md:hidden\"\n [class.z-menu-v2-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-v2-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onMobileBackdropClick()\"></div>\n}\n\n<aside\n class=\"z-menu-v2-mobile-drawer bg-sidebar text-sidebar-foreground border-sidebar-border fixed top-0 left-0 z-9999 flex h-full w-72 max-w-[calc(100vw-1rem)] flex-col border-r md:hidden\"\n [class.open]=\"mobileMenuOpen()\">\n <div class=\"border-sidebar-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-3\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n @if (parent.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"z-menu-v2-menu-group\">\n <button\n #mobileParentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"mobileParentTrigger\"\n zPosition=\"top\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n </button>\n\n @if (parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'top' }\" />\n </div>\n </div>\n }\n </div>\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"mobileUserFooterTpl\" />\n</aside>\n", styles: [".z-menu-v2{display:block;flex-shrink:0;height:100%}.z-menu-v2 [class*=cursor-pointer],.z-menu-v2 button{-webkit-user-select:none;user-select:none}.z-menu-v2-shell{width:var(--z-menu-v2-expanded-width, 248px);transition:width .2s cubic-bezier(.4,0,.2,1);will-change:width}.z-menu-v2-collapsed .z-menu-v2-shell{width:var(--z-menu-v2-collapsed-width, 60px)}.z-menu-v2-toggle{position:relative;z-index:1}.z-menu-v2-toggle.z-menu-v2-toggle-collapsed{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.z-menu-v2-nav{gap:.25rem}.z-menu-v2-menu-group{display:flex;min-width:0;flex-direction:column}.z-menu-v2-item,.z-menu-v2-popover-item,.z-menu-v2-icon-item{min-width:0;border-radius:.375rem;outline:none;transition:background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.625rem;padding:.5rem .625rem;font-size:.8125rem;font-weight:450}.z-menu-v2-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-item.parent-active:not(.active){color:var(--sidebar-primary)}.z-menu-v2-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-item.active .z-menu-v2-dot,.z-menu-v2-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item.icon-only{justify-content:center;padding-inline:0;width:2.5rem;height:2.5rem;margin-inline:auto}.z-menu-v2-icon-item{display:flex;width:2.5rem;height:2.5rem;cursor:pointer;align-items:center;justify-content:center;margin-inline:auto}.z-menu-v2-icon-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-icon-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;padding:.45rem .5rem;font-size:.8125rem;font-weight:450}.z-menu-v2-popover-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-popover-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item.parent-active:not(.active){background-color:transparent;color:var(--sidebar-primary)}.z-menu-v2-popover-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-popover-item.active .z-menu-v2-dot,.z-menu-v2-popover-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item-child{position:relative;padding-left:.75rem}.z-menu-v2-item-sub-child{position:relative;padding-left:.75rem;font-size:.78125rem}.z-menu-v2-submenu-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .24s cubic-bezier(.16,1,.3,1)}.z-menu-v2-submenu-panel.expanded{grid-template-rows:1fr}.z-menu-v2-submenu-panel-inner{min-height:0;overflow:hidden}.z-menu-v2-submenu-panel-inner:before{content:\"\";display:block;height:.25rem}.z-menu-v2-submenu{position:relative;display:flex;min-width:0;min-height:0;flex-direction:column;gap:.25rem;margin:0 0 0 .875rem;padding-left:.875rem}.z-menu-v2-submenu:before{content:\"\";position:absolute;top:0;bottom:.75rem;left:0;width:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item,.z-menu-v2-submenu .z-menu-v2-popover-item{position:relative}.z-menu-v2-submenu .z-menu-v2-item:before,.z-menu-v2-submenu .z-menu-v2-popover-item:before{content:\"\";position:absolute;top:50%;left:-.875rem;width:.875rem;height:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item.active:before,.z-menu-v2-submenu .z-menu-v2-item.parent-active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.parent-active:before{background-color:color-mix(in oklab,var(--sidebar-primary) 72%,var(--sidebar-border))}.z-menu-v2-submenu-nested{margin-left:.75rem}.z-menu-v2-popover-tree{margin-top:0;margin-bottom:0}.z-menu-v2-popover-scrollbar{--scrollbar-padding: 0;--scrollbar-overscroll-behavior: contain;max-height:min(28rem,100vh - 8rem);min-height:0;overflow-x:hidden;overflow-y:auto}.z-menu-v2-popover-scroll-content{min-width:0}.z-menu-v2-arrow{transition:transform .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-arrow.expanded{transform:rotate(90deg)}.z-menu-v2-dot{display:inline-flex;width:.375rem;height:.375rem;flex-shrink:0;border-radius:9999px;background-color:color-mix(in oklab,var(--sidebar-foreground) 58%,transparent)}.z-menu-v2-dot.small{width:.25rem;height:.25rem}.z-menu-v2-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-v2-scrollbar .ng-scroll-viewport,.z-menu-v2-scrollbar .ng-scroll-content{max-width:100%}.z-menu-v2-backdrop{animation:z-menu-v2-backdrop-enter .2s ease-out forwards}.z-menu-v2-backdrop-dark{background-color:#0009}.z-menu-v2-backdrop-blur{background-color:#0000000d;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.z-menu-v2-mobile-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-v2-mobile-drawer.open{transform:translate(0)}@keyframes z-menu-v2-backdrop-enter{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
894
|
+
}, template: "<aside\n class=\"hidden h-full min-h-0 flex-col overflow-hidden border-r shadow-sm md:flex\"\n [class]=\"zClasses()\"\n [style.--z-menu-v2-expanded-width.px]=\"zExpandedWidth()\"\n [style.--z-menu-v2-collapsed-width.px]=\"zCollapsedWidth()\">\n <div\n class=\"border-sidebar-border flex h-14 shrink-0 items-center gap-2 border-b px-3\"\n [class.justify-center]=\"sidebarCollapsed()\">\n @if (!sidebarCollapsed() && zLogo()) {\n <img [src]=\"zLogo()\" alt=\"Logo\" class=\"h-8 w-auto shrink-0 object-contain transition-opacity\" />\n }\n\n @if (!sidebarCollapsed()) {\n <div\n class=\"min-w-0 flex-1 overflow-hidden text-sm font-semibold text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"effectiveTitle() | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ effectiveTitle() | translate }}\n </div>\n }\n\n <button\n z-button\n zType=\"ghost\"\n [zWave]=\"false\"\n class=\"z-menu-v2-toggle h-9 w-9 shrink-0\"\n [class.z-menu-v2-toggle-collapsed]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"\n (sidebarCollapsed() ? 'i18n_z_ui_menu_expand_sidebar' : 'i18n_z_ui_menu_collapse_sidebar') | translate\n \"\n (click)=\"toggleSidebar()\">\n <z-icon [zType]=\"sidebarCollapsed() ? 'lucidePanelLeftOpen' : 'lucidePanelLeftClose'\" zSize=\"18\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar min-h-0 flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-2\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n @if (parent.groupLabel && !sidebarCollapsed()) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n @if (sidebarCollapsed() && parentHasChildren) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"parentPopoverTpl\"\n [zPopoverWidth]=\"256\"\n zPosition=\"right-top\"\n [zOffset]=\"10\"\n class=\"z-menu-v2-icon-item\"\n [class.active]=\"parentActive || parentLeafActive\"\n [attr.aria-label]=\"parent.name | translate\"\n (click)=\"onCollapsedParentClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"20\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"20\" />\n }\n </button>\n\n <ng-template #parentPopoverTpl let-close=\"close\">\n <div class=\"z-menu-v2-popover w-64 max-w-64 min-w-0 pt-1 pl-1\">\n <div\n #parentPopoverHeaderTrigger\n class=\"text-muted-foreground flex items-center gap-2 px-2 py-2 text-xs font-medium\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"15\" />\n }\n <span\n class=\"overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentPopoverHeaderTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n </div>\n <ng-scrollbar class=\"z-menu-v2-popover-scrollbar\" orientation=\"vertical\" visibility=\"visible\">\n <div class=\"z-menu-v2-popover-scroll-content pr-2 pb-1\">\n <ng-container\n *ngTemplateOutlet=\"collapsedChildrenTpl; context: { $implicit: parent.children, close: close }\" />\n </div>\n </ng-scrollbar>\n </div>\n </ng-template>\n }\n @if (!(sidebarCollapsed() && parentHasChildren)) {\n <ng-container *ngTemplateOutlet=\"openParentTpl; context: { $implicit: parent }\" />\n }\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"userFooterTpl\" />\n</aside>\n\n<ng-template #openParentTpl let-parent>\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n\n <div class=\"z-menu-v2-menu-group\">\n <button\n #parentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n [class.icon-only]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? (parent.name | translate) : null\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n zPosition=\"right\"\n [zOffset]=\"6\"\n [zDisabled]=\"!sidebarCollapsed()\"\n [zAlwaysShow]=\"sidebarCollapsed()\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" [zSize]=\"sidebarCollapsed() ? '20' : '18'\" class=\"shrink-0\" />\n }\n\n @if (!sidebarCollapsed()) {\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"parentTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n }\n </button>\n\n @if (!sidebarCollapsed() && parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'right' }\" />\n </div>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #collapsedChildrenTpl let-children let-close=\"close\">\n <div class=\"z-menu-v2-submenu z-menu-v2-popover-tree\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #collapsedChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"childHasChildren ? onMenuItemClick(child) : onCollapsedLeafClick(child, close)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"collapsedChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel collapsed-popover\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <div class=\"z-menu-v2-submenu z-menu-v2-submenu-nested\">\n @for (subChild of child.children; track subChild.id) {\n @let subChildActive = selectedMenuItem()?.id === subChild.id;\n <button\n #collapsedSubChildTrigger\n type=\"button\"\n class=\"z-menu-v2-popover-item\"\n [class.active]=\"subChildActive\"\n (click)=\"onCollapsedLeafClick(subChild, close)\">\n @if (subChild.icon) {\n <z-icon [zType]=\"subChild.icon\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && subChild.iconSvg) {\n <z-icon [zSvg]=\"subChild.iconSvg\" zSize=\"15\" class=\"shrink-0\" />\n }\n @if (!subChild.icon && !subChild.iconSvg) {\n <span class=\"z-menu-v2-dot small\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"subChild.name | translate\"\n [zTriggerElement]=\"collapsedSubChildTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ subChild.name | translate }}\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #userFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-2\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"right-bottom\"\n [zOffset]=\"10\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\"\n [class.justify-center]=\"sidebarCollapsed()\"\n [attr.aria-label]=\"sidebarCollapsed() ? zUser()?.name || 'User Name' : null\">\n <span class=\"h-9 w-9 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n @if (!sidebarCollapsed()) {\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n }\n </button>\n </div>\n</ng-template>\n\n<ng-template #mobileUserFooterTpl>\n <div class=\"border-sidebar-border shrink-0 border-t p-3\">\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"userPopoverTpl\"\n zPosition=\"top-right\"\n [zOffset]=\"6\"\n class=\"hover:bg-sidebar-accent flex w-full cursor-pointer items-center gap-3 rounded-md p-2 text-left\">\n <span class=\"h-10 w-10 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"h-full w-full object-cover\" />\n </span>\n <span class=\"min-w-0 flex-1\">\n <span class=\"block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground block overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </span>\n <z-icon zType=\"lucideChevronsUpDown\" zSize=\"15\" class=\"text-muted-foreground shrink-0\" />\n </button>\n </div>\n</ng-template>\n\n<ng-template #userPopoverTpl let-close=\"close\">\n <div class=\"min-w-56 p-1\">\n <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <div class=\"h-8 w-8 shrink-0 overflow-hidden rounded-full\">\n <img [src]=\"avatarSrc()\" alt=\"User Avatar\" class=\"aspect-square size-full object-cover\" />\n </div>\n <div class=\"grid flex-1 text-left text-sm leading-tight\">\n <span class=\"overflow-hidden font-medium text-ellipsis whitespace-nowrap\">\n {{ zUser()?.name || 'User Name' }}\n </span>\n <span class=\"text-muted-foreground mt-0.5 overflow-hidden text-xs text-ellipsis whitespace-nowrap\">\n {{ zUser()?.email || 'user@example.com' }}\n </span>\n </div>\n </div>\n\n @if (visibleUserActions().length > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n @for (action of visibleUserActions(); track action.id; let idx = $index) {\n @if (action.divide === 'before' && idx > 0) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n\n <button\n #userActionTrigger\n type=\"button\"\n [disabled]=\"action.disabled\"\n [class]=\"action.class\"\n class=\"hover:bg-accent focus:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"onUserActionClick(action); close()\">\n @if (action.icon) {\n <z-icon [zType]=\"action.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span\n class=\"min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"action.label | translate\"\n [zTriggerElement]=\"userActionTrigger\"\n zPosition=\"right\"\n [zOffset]=\"6\">\n {{ action.label | translate }}\n </span>\n </button>\n\n @if (action.divide === 'after' && idx < visibleUserActions().length - 1) {\n <div class=\"bg-border -mx-1 my-1 h-px\"></div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #openChildrenTpl let-children let-position=\"position\">\n <div class=\"z-menu-v2-submenu\">\n @for (child of children; track child.id) {\n @let childActive = selectedMenuItem()?.id === child.id;\n @let childParentActive = selectedMenuItem()?.parent?.includes(child.id);\n @let childHasChildren = child.children && child.children.length > 0;\n <div class=\"z-menu-v2-menu-group\">\n <button\n #openChildTrigger\n type=\"button\"\n class=\"z-menu-v2-item z-menu-v2-item-child\"\n [class.active]=\"childActive\"\n [class.parent-active]=\"childParentActive\"\n (click)=\"onMenuItemClick(child)\">\n @if (child.icon) {\n <z-icon [zType]=\"child.icon\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && child.iconSvg) {\n <z-icon [zSvg]=\"child.iconSvg\" zSize=\"16\" class=\"shrink-0\" />\n }\n @if (!child.icon && !child.iconSvg) {\n <span class=\"z-menu-v2-dot\"></span>\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"child.name | translate\"\n [zTriggerElement]=\"openChildTrigger\"\n [zPosition]=\"position\"\n [zOffset]=\"6\">\n {{ child.name | translate }}\n </span>\n @if (childHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"14\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"child.expanded\" />\n }\n </button>\n\n @if (childHasChildren && child.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"child.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: child.children, position: position }\" />\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n@if (zShowMobileBar()) {\n <div\n class=\"z-menu-v2-mobile-bar border-border bg-background flex h-14 items-center justify-between border-b px-4 md:hidden\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"openMobileMenu()\">\n <z-icon zType=\"lucideMenu\" zSize=\"20\" />\n </button>\n </div>\n}\n\n@if (mobileMenuOpen()) {\n <div\n class=\"z-menu-v2-backdrop fixed inset-0 z-9998 md:hidden\"\n [class.z-menu-v2-backdrop-dark]=\"overlayType() === 'dark'\"\n [class.z-menu-v2-backdrop-blur]=\"overlayType() === 'blur'\"\n (click)=\"onMobileBackdropClick()\"></div>\n}\n\n<aside\n class=\"z-menu-v2-mobile-drawer bg-sidebar text-sidebar-foreground border-sidebar-border fixed top-0 left-0 z-9999 flex h-full w-72 max-w-[calc(100vw-1rem)] flex-col border-r md:hidden\"\n [class.open]=\"mobileMenuOpen()\">\n <div class=\"border-sidebar-border flex h-14 shrink-0 items-center justify-between border-b px-4\">\n @if (mobileLogo()) {\n <img [src]=\"mobileLogo()\" alt=\"Logo\" class=\"h-8 w-auto object-contain\" />\n }\n <button z-button zType=\"ghost\" [zWave]=\"false\" class=\"h-9 w-9\" (click)=\"closeMobileMenu()\">\n <z-icon zType=\"lucideX\" zSize=\"20\" />\n </button>\n </div>\n\n <ng-scrollbar class=\"z-menu-v2-scrollbar flex-1\" track=\"vertical\">\n <nav class=\"z-menu-v2-nav flex flex-col p-3\">\n @for (parent of menuParents(); track parent.id) {\n @let parentActive = parentWithActiveChild()?.id === parent.id;\n @let parentLeafActive = selectedMenuItem()?.id === parent.id;\n @let parentHasChildren = parent.children && parent.children.length > 0;\n @if (parent.groupLabel) {\n <div class=\"mt-1 first:mt-0\">\n <div class=\"border-sidebar-border mb-2.5 border-t\"></div>\n <div class=\"text-muted-foreground px-2 pb-0.5 text-[0.6875rem] font-semibold tracking-wider uppercase\">\n {{ parent.groupLabel | translate }}\n </div>\n </div>\n }\n <div class=\"z-menu-v2-menu-group\">\n <button\n #mobileParentTrigger\n type=\"button\"\n class=\"z-menu-v2-item\"\n [class.active]=\"parentLeafActive\"\n [class.parent-active]=\"parentActive && !parentLeafActive\"\n (click)=\"onMenuItemClick(parent)\">\n @if (parent.icon) {\n <z-icon [zType]=\"parent.icon\" zSize=\"18\" class=\"shrink-0\" />\n }\n @if (!parent.icon && parent.iconSvg) {\n <z-icon [zSvg]=\"parent.iconSvg\" zSize=\"18\" class=\"shrink-0\" />\n }\n <span\n class=\"min-w-0 flex-1 overflow-hidden text-left text-ellipsis whitespace-nowrap\"\n z-tooltip\n [zContent]=\"parent.name | translate\"\n [zTriggerElement]=\"mobileParentTrigger\"\n zPosition=\"top\"\n [zOffset]=\"6\">\n {{ parent.name | translate }}\n </span>\n @if (parentHasChildren) {\n <z-icon\n zType=\"lucideChevronRight\"\n zSize=\"15\"\n class=\"z-menu-v2-arrow shrink-0 opacity-60\"\n [class.expanded]=\"parent.expanded\" />\n }\n </button>\n\n @if (parentHasChildren && parent.renderChildren) {\n <div class=\"z-menu-v2-submenu-panel\" [class.expanded]=\"parent.renderExpanded\">\n <div class=\"z-menu-v2-submenu-panel-inner\">\n <ng-container\n *ngTemplateOutlet=\"openChildrenTpl; context: { $implicit: parent.children, position: 'top' }\" />\n </div>\n </div>\n }\n </div>\n }\n </nav>\n </ng-scrollbar>\n\n <ng-container *ngTemplateOutlet=\"mobileUserFooterTpl\" />\n</aside>\n", styles: [".z-menu-v2{display:block;flex-shrink:0;height:100%}.z-menu-v2 [class*=cursor-pointer],.z-menu-v2 button{-webkit-user-select:none;user-select:none}.z-menu-v2-shell{width:var(--z-menu-v2-expanded-width, 248px);transition:width .2s cubic-bezier(.4,0,.2,1);will-change:width}.z-menu-v2-collapsed .z-menu-v2-shell{width:var(--z-menu-v2-collapsed-width, 60px)}.z-menu-v2-toggle{position:relative;z-index:1}.z-menu-v2-toggle.z-menu-v2-toggle-collapsed{background-color:var(--sidebar-accent);color:var(--sidebar-accent-foreground)}.z-menu-v2-nav{gap:.25rem}.z-menu-v2-menu-group{display:flex;min-width:0;flex-direction:column}.z-menu-v2-item,.z-menu-v2-popover-item,.z-menu-v2-icon-item{min-width:0;border-radius:.375rem;outline:none;transition:background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.625rem;padding:.5rem .625rem;font-size:.8125rem;font-weight:450}.z-menu-v2-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-item.parent-active:not(.active){color:var(--sidebar-primary)}.z-menu-v2-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-item.active .z-menu-v2-dot,.z-menu-v2-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item.icon-only{justify-content:center;padding-inline:0;width:2.5rem;height:2.5rem;margin-inline:auto}.z-menu-v2-icon-item{display:flex;width:2.5rem;height:2.5rem;cursor:pointer;align-items:center;justify-content:center;margin-inline:auto}.z-menu-v2-icon-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-icon-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;padding:.45rem .5rem;font-size:.8125rem;font-weight:450}.z-menu-v2-popover-item:hover{background-color:var(--accent);color:var(--accent-foreground)}.z-menu-v2-popover-item.active{background-color:var(--sidebar-primary);color:var(--sidebar-primary-foreground)}.z-menu-v2-popover-item.parent-active:not(.active){background-color:transparent;color:var(--sidebar-primary)}.z-menu-v2-popover-item.parent-active:not(.active):hover{background-color:var(--accent);color:var(--sidebar-primary)}.z-menu-v2-popover-item.active .z-menu-v2-dot,.z-menu-v2-popover-item.parent-active .z-menu-v2-dot{background-color:currentColor}.z-menu-v2-item-child{position:relative;padding-left:.75rem}.z-menu-v2-item-sub-child{position:relative;padding-left:.75rem;font-size:.78125rem}.z-menu-v2-submenu-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .24s cubic-bezier(.16,1,.3,1)}.z-menu-v2-submenu-panel.expanded{grid-template-rows:1fr}.z-menu-v2-submenu-panel-inner{min-height:0;overflow:hidden}.z-menu-v2-submenu-panel-inner:before{content:\"\";display:block;height:.25rem}.z-menu-v2-submenu{position:relative;display:flex;min-width:0;min-height:0;flex-direction:column;gap:.25rem;margin:0 0 0 .875rem;padding-left:.875rem}.z-menu-v2-submenu:before{content:\"\";position:absolute;top:0;bottom:.75rem;left:0;width:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item,.z-menu-v2-submenu .z-menu-v2-popover-item{position:relative}.z-menu-v2-submenu .z-menu-v2-item:before,.z-menu-v2-submenu .z-menu-v2-popover-item:before{content:\"\";position:absolute;top:50%;left:-.875rem;width:.875rem;height:1px;background-color:color-mix(in oklab,var(--sidebar-border) 84%,transparent)}.z-menu-v2-submenu .z-menu-v2-item.active:before,.z-menu-v2-submenu .z-menu-v2-item.parent-active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.active:before,.z-menu-v2-submenu .z-menu-v2-popover-item.parent-active:before{background-color:color-mix(in oklab,var(--sidebar-primary) 72%,var(--sidebar-border))}.z-menu-v2-submenu-nested{margin-left:.75rem}.z-menu-v2-popover-tree{margin-top:0;margin-bottom:0}.z-menu-v2-popover-scrollbar{--scrollbar-padding: 0;--scrollbar-overscroll-behavior: contain;max-height:min(28rem,100vh - 8rem);min-height:0;overflow-x:hidden;overflow-y:auto}.z-menu-v2-popover-scroll-content{min-width:0}.z-menu-v2-arrow{transition:transform .2s cubic-bezier(.4,0,.2,1)}.z-menu-v2-arrow.expanded{transform:rotate(90deg)}.z-menu-v2-dot{display:inline-flex;width:.375rem;height:.375rem;flex-shrink:0;border-radius:9999px;background-color:color-mix(in oklab,var(--sidebar-foreground) 58%,transparent)}.z-menu-v2-dot.small{width:.25rem;height:.25rem}.z-menu-v2-scrollbar{--scrollbar-padding: 0;max-width:100%}.z-menu-v2-scrollbar .ng-scroll-viewport,.z-menu-v2-scrollbar .ng-scroll-content{max-width:100%}.z-menu-v2-backdrop{animation:z-menu-v2-backdrop-enter .2s ease-out forwards}.z-menu-v2-backdrop-dark{background-color:#0009}.z-menu-v2-backdrop-blur{background-color:#0000000d;backdrop-filter:blur(2px)}.z-menu-v2-mobile-drawer{transform:translate(-100%);transition:transform .3s cubic-bezier(.32,.72,0,1);box-shadow:4px 0 24px #0000001a;will-change:transform}.z-menu-v2-mobile-drawer.open{transform:translate(0)}@keyframes z-menu-v2-backdrop-enter{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
836
895
|
}], ctorParameters: () => [], propDecorators: { zOnSelect: [{ type: i0.Output, args: ["zOnSelect"] }], zOnMenuAction: [{ type: i0.Output, args: ["zOnMenuAction"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zLogo: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLogo", required: false }] }], zLogoMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLogoMobile", required: false }] }], zMenus: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMenus", required: false }] }], zUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "zUser", required: false }] }], zUserActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zUserActions", required: false }] }], zCurrentPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCurrentPath", required: false }] }], zKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "zKey", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTitle", required: false }] }], zCollapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCollapsedWidth", required: false }] }], zExpandedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zExpandedWidth", required: false }] }], zExpandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "zExpandMode", required: false }] }], zShowMobileBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowMobileBar", required: false }] }] } });
|
|
837
896
|
|
|
838
897
|
/**
|