@mediusinc/mng-commons-layout 5.2.0 → 5.3.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/esm2022/index.mjs +5 -2
  2. package/esm2022/lib/components/footer.component.mjs +5 -3
  3. package/esm2022/lib/components/main-layout.component.mjs +11 -13
  4. package/esm2022/lib/components/menu-item.component.mjs +64 -144
  5. package/esm2022/lib/components/menu.component.mjs +10 -13
  6. package/esm2022/lib/components/pages/error/error.page.component.mjs +20 -0
  7. package/esm2022/lib/components/pages/not-found/not-found.page.component.mjs +20 -0
  8. package/esm2022/lib/components/settings.component.mjs +89 -0
  9. package/esm2022/lib/components/sidebar.component.mjs +11 -12
  10. package/esm2022/lib/components/topbar-user.component.mjs +23 -4
  11. package/esm2022/lib/components/topbar.component.mjs +4 -4
  12. package/esm2022/lib/helpers/menu-items.mjs +26 -0
  13. package/esm2022/lib/models/menu.model.mjs +1 -1
  14. package/esm2022/lib/provide.mjs +3 -1
  15. package/esm2022/lib/services/layout-feature-config.token.mjs +1 -1
  16. package/esm2022/lib/services/layout.service.mjs +166 -0
  17. package/esm2022/lib/services/menu.service.mjs +37 -37
  18. package/fesm2022/mediusinc-mng-commons-layout.mjs +437 -287
  19. package/fesm2022/mediusinc-mng-commons-layout.mjs.map +1 -1
  20. package/index.d.ts +4 -1
  21. package/lib/components/footer.component.d.ts +2 -0
  22. package/lib/components/main-layout.component.d.ts +2 -5
  23. package/lib/components/menu-item.component.d.ts +15 -27
  24. package/lib/components/menu.component.d.ts +3 -4
  25. package/lib/components/pages/error/error.page.component.d.ts +7 -0
  26. package/lib/components/pages/not-found/not-found.page.component.d.ts +7 -0
  27. package/lib/components/settings.component.d.ts +30 -0
  28. package/lib/components/sidebar.component.d.ts +2 -4
  29. package/lib/components/topbar-user.component.d.ts +5 -0
  30. package/lib/components/topbar.component.d.ts +2 -2
  31. package/lib/helpers/menu-items.d.ts +2 -0
  32. package/lib/models/menu.model.d.ts +2 -2
  33. package/lib/services/layout-feature-config.token.d.ts +73 -0
  34. package/lib/services/layout.service.d.ts +46 -0
  35. package/lib/services/menu.service.d.ts +7 -8
  36. package/package.json +2 -2
  37. package/scss/layout/mng/_mng_layout_styles.scss +1 -0
  38. package/scss/layout/mng/_mng_sidebar_vertical.scss +8 -0
  39. package/version-info.json +6 -6
  40. package/esm2022/lib/services/main-layout.component.service.mjs +0 -71
  41. package/lib/services/main-layout.component.service.d.ts +0 -17
@@ -1,31 +1,222 @@
1
- import { AsyncPipe, NgOptimizedImage, NgClass, NgTemplateOutlet } from '@angular/common';
2
1
  import * as i0 from '@angular/core';
3
- import { InjectionToken, inject, Injectable, DestroyRef, input, signal, computed, Component, ChangeDetectionStrategy, Injector, EventEmitter, effect, runInInjectionContext, Input, HostBinding, Output, ViewChild, ElementRef, Renderer2, viewChild } from '@angular/core';
2
+ import { InjectionToken, inject, PLATFORM_ID, signal, computed, afterNextRender, effect, Injectable, Component, ChangeDetectionStrategy, DestroyRef, input, output, viewChild, untracked, ElementRef, Injector, Renderer2 } from '@angular/core';
3
+ import * as i1$4 from '@angular/router';
4
+ import { RouterLink, Router, NavigationEnd, RouterModule, ActivatedRoute } from '@angular/router';
4
5
  import * as i1$1 from '@ngx-translate/core';
5
- import { TranslateModule } from '@ngx-translate/core';
6
+ import { TranslateModule, TranslateService } from '@ngx-translate/core';
7
+ import * as i1 from 'primeng/button';
8
+ import { ButtonModule, Button } from 'primeng/button';
9
+ import { DOCUMENT, AsyncPipe, NgOptimizedImage, NgClass, NgTemplateOutlet } from '@angular/common';
10
+ import { Subject, ReplaySubject, catchError, of, switchMap, take, startWith, distinctUntilChanged } from 'rxjs';
6
11
  import * as i2 from '@mediusinc/mng-commons/core';
7
- import { LoggerService, JsonPathPipe, CommonsService, ComponentDirective, CommonsRouterService, adjustRouteMenuLazyChildrenRouterLinks, doesUrlMatchRouterLink, PermissionService, EnumerateAsyncPipe, NotificationWrapperComponent, createRoute, CommonsFeatureTypeEnum } from '@mediusinc/mng-commons/core';
12
+ import { COMMONS_MODULE_CONFIG_IT, CommonsStorageService, LoggerService, JsonPathPipe, CommonsService, ComponentDirective, CommonsRouterService, adjustRouteMenuLazyChildrenRouterLinks, doesUrlMatchRouterLink, PermissionService, toObservable as toObservable$1, EnumerateAsyncPipe, NotificationWrapperComponent, createRoute, CommonsFeatureTypeEnum } from '@mediusinc/mng-commons/core';
8
13
  import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
9
- import { ReplaySubject, catchError, of, switchMap, take, Subject, Observable, BehaviorSubject, combineLatest, distinctUntilChanged } from 'rxjs';
10
14
  import { map, filter } from 'rxjs/operators';
11
- import * as i1 from '@angular/common/http';
12
- import * as i1$3 from '@angular/router';
13
- import { Router, NavigationEnd, RouterModule, ActivatedRoute } from '@angular/router';
14
- import * as i2$1 from '@angular/forms';
15
+ import * as i1$2 from '@angular/common/http';
16
+ import * as i3 from '@angular/forms';
15
17
  import { FormsModule } from '@angular/forms';
16
- import { ButtonModule } from 'primeng/button';
17
- import * as i1$4 from 'primeng/dropdown';
18
+ import * as i4 from 'primeng/dropdown';
18
19
  import { DropdownModule } from 'primeng/dropdown';
19
- import * as i1$2 from 'primeng/ripple';
20
+ import * as i1$3 from 'primeng/ripple';
20
21
  import { RippleModule } from 'primeng/ripple';
21
- import * as i3 from 'primeng/styleclass';
22
+ import * as i3$1 from 'primeng/styleclass';
22
23
  import { StyleClassModule } from 'primeng/styleclass';
23
24
  import { trigger, state, style, transition, animate } from '@angular/animations';
24
25
  import { TooltipModule } from 'primeng/tooltip';
25
26
  import { DomSanitizer } from '@angular/platform-browser';
27
+ import { DynamicDialogConfig, DynamicDialogRef, DialogService } from 'primeng/dynamicdialog';
28
+ import { InputSwitchModule } from 'primeng/inputswitch';
29
+ import * as i2$1 from 'primeng/radiobutton';
30
+ import { RadioButtonModule } from 'primeng/radiobutton';
31
+ import * as i5 from 'primeng/selectbutton';
32
+ import { SelectButtonModule } from 'primeng/selectbutton';
26
33
 
27
34
  const COMMONS_LAYOUT_FEATURE_CONFIG_IT = new InjectionToken('COMMONS_LAYOUT_FEATURE_CONFIG');
28
35
 
36
+ class LayoutService {
37
+ getInitColorScheme() {
38
+ let colorScheme = this.storageService.getItem(this.typeName, this.storageColorSchemeKey);
39
+ if (colorScheme == null || !['dark', 'light', 'auto'].includes(colorScheme)) {
40
+ colorScheme = this.getDefaultColorScheme();
41
+ }
42
+ return colorScheme;
43
+ }
44
+ getInitActualColorScheme(colorScheme) {
45
+ if (colorScheme === 'auto') {
46
+ return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
47
+ }
48
+ else {
49
+ return colorScheme;
50
+ }
51
+ }
52
+ getDefaultColorScheme() {
53
+ return this.config?.colorScheme ?? this.commonsConfig?.app?.colorScheme ?? 'auto';
54
+ }
55
+ setColorScheme(scheme) {
56
+ const defaultColorScheme = this.getDefaultColorScheme();
57
+ if (scheme === defaultColorScheme) {
58
+ this.storageService.removeItem(this.typeName, this.storageColorSchemeKey);
59
+ }
60
+ else {
61
+ this.storageService.setItem(this.typeName, this.storageColorSchemeKey, scheme);
62
+ }
63
+ this._colorSchemeSetting.set(scheme);
64
+ this._colorScheme.set(this.getInitActualColorScheme(scheme));
65
+ }
66
+ constructor() {
67
+ this.typeName = 'MainLayoutComponentService';
68
+ this.storageMenuModeKey = 'menuMode';
69
+ this.storageColorSchemeKey = 'colorScheme';
70
+ this.platformId = inject(PLATFORM_ID);
71
+ this.document = inject(DOCUMENT);
72
+ this.commonsConfig = inject(COMMONS_MODULE_CONFIG_IT, { optional: true });
73
+ this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
74
+ this.storageService = inject(CommonsStorageService);
75
+ this.state = signal({
76
+ staticMenuDesktopInactive: false,
77
+ overlayMenuActive: false,
78
+ rightMenuActive: false,
79
+ configSidebarVisible: false,
80
+ staticMenuMobileActive: false,
81
+ menuHoverActive: false,
82
+ sidebarActive: false,
83
+ anchored: false
84
+ });
85
+ this.overlayOpen = new Subject();
86
+ this.overlayOpen$ = this.overlayOpen.asObservable();
87
+ // color scheme
88
+ this._colorSchemeSetting = signal(this.getInitColorScheme());
89
+ this.colorSchemeSetting = this._colorSchemeSetting.asReadonly();
90
+ this._colorScheme = signal(this.getInitActualColorScheme(this.colorSchemeSetting()));
91
+ this.colorScheme = this._colorScheme.asReadonly();
92
+ this.colorSchemeIsLight = computed(() => this._colorScheme() === 'light');
93
+ // menu mode
94
+ this.menuModes = this.config?.menuModes ?? ['static', 'overlay', 'reveal', 'drawer', 'slim', 'slim-plus'];
95
+ this._menuMode = signal(this.initMenuMode());
96
+ this.menuMode = this._menuMode.asReadonly();
97
+ // logos
98
+ this.appLogoLight = signal(this.config?.logoPathLight ?? this.commonsConfig?.app?.logoPathLight ?? this.config?.logoPath ?? this.commonsConfig?.app?.logoPath ?? 'assets/layout/images/logo.png');
99
+ this.appLogoDark = signal(this.config?.logoPathLight ?? this.commonsConfig?.app?.logoPathDark ?? this.config?.logoPath ?? this.commonsConfig?.app?.logoPath ?? 'assets/layout/images/logo.png');
100
+ this.appLogo = computed(() => (this.colorSchemeIsLight() ? this.appLogoLight() : this.appLogoDark()));
101
+ this.appLogoNameLight = signal(this.config?.logoNamePathLight ??
102
+ this.commonsConfig?.app?.logoNamePathLight ??
103
+ this.config?.logoNamePath ??
104
+ this.commonsConfig?.app?.logoNamePath ??
105
+ 'assets/layout/images/logo-appname.png');
106
+ this.appLogoNameDark = signal(this.config?.logoNamePathDark ??
107
+ this.commonsConfig?.app?.logoNamePathDark ??
108
+ this.config?.logoNamePath ??
109
+ this.commonsConfig?.app?.logoNamePath ??
110
+ 'assets/layout/images/logo-appname.png');
111
+ this.appLogoName = computed(() => (this.colorSchemeIsLight() ? this.appLogoNameLight() : this.appLogoNameDark()));
112
+ // overlays
113
+ this.isOverlay = computed(() => this.menuMode() === 'overlay');
114
+ this.isSlim = computed(() => this.menuMode() === 'slim');
115
+ this.isSlimPlus = computed(() => this.menuMode() === 'slim-plus');
116
+ afterNextRender(() => {
117
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
118
+ if (this.colorSchemeSetting() === 'auto') {
119
+ const newColorScheme = event.matches ? 'dark' : 'light';
120
+ this._colorScheme.set(newColorScheme);
121
+ }
122
+ });
123
+ });
124
+ effect(() => {
125
+ const colorScheme = this._colorScheme();
126
+ const linkElement = this.document.getElementById('app-theme');
127
+ if (colorScheme === 'dark' && linkElement.href.includes('light')) {
128
+ linkElement.href = 'theme-dark.css';
129
+ }
130
+ else if (colorScheme === 'light' && linkElement.href.includes('dark')) {
131
+ linkElement.href = 'theme-light.css';
132
+ }
133
+ });
134
+ }
135
+ onMenuModeChange(mode) {
136
+ if (!this.menuModes.includes(mode)) {
137
+ return;
138
+ }
139
+ if (mode === this.config?.menuMode) {
140
+ this.storageService.removeItem(this.typeName, this.storageMenuModeKey);
141
+ }
142
+ else {
143
+ this.storageService.setItem(this.typeName, this.storageMenuModeKey, mode);
144
+ }
145
+ this._menuMode.set(mode);
146
+ }
147
+ onMenuToggle() {
148
+ if (this.isOverlay()) {
149
+ this.state.update(state => ({
150
+ ...state,
151
+ overlayMenuActive: !state.overlayMenuActive
152
+ }));
153
+ if (this.state().overlayMenuActive) {
154
+ this.overlayOpen.next(null);
155
+ }
156
+ }
157
+ if (this.isDesktop()) {
158
+ this.state.update(state => ({
159
+ ...state,
160
+ staticMenuDesktopInactive: !state.staticMenuDesktopInactive
161
+ }));
162
+ }
163
+ else {
164
+ this.state.update(state => ({
165
+ ...state,
166
+ staticMenuMobileActive: !state.staticMenuMobileActive
167
+ }));
168
+ if (this.state().staticMenuMobileActive) {
169
+ this.overlayOpen.next(null);
170
+ }
171
+ }
172
+ }
173
+ onOverlaySubmenuOpen() {
174
+ this.overlayOpen.next(null);
175
+ }
176
+ isDesktop() {
177
+ return window.innerWidth > 991;
178
+ }
179
+ isMobile() {
180
+ return !this.isDesktop();
181
+ }
182
+ initMenuMode() {
183
+ const lsMode = this.storageService.getItem(this.typeName, this.storageMenuModeKey);
184
+ if (lsMode && this.menuModes.includes(lsMode)) {
185
+ return lsMode;
186
+ }
187
+ return this.config?.menuMode ?? 'static';
188
+ }
189
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: LayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
190
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: LayoutService }); }
191
+ }
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: LayoutService, decorators: [{
193
+ type: Injectable
194
+ }], ctorParameters: () => [] });
195
+
196
+ class ErrorPageComponent {
197
+ constructor() {
198
+ this.layout = inject(LayoutService);
199
+ }
200
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: ErrorPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
201
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.5", type: ErrorPageComponent, isStandalone: true, selector: "mng-error-page", ngImport: i0, template: "<div [class]=\"'exception-body min-h-screen ' + (layout.colorSchemeIsLight() ? 'layout-light' : 'layout-dark')\">\n <div class=\"exception-container min-h-screen flex align-items-center justify-content-center flex-column bg-auto md:bg-contain bg-no-repeat\">\n <div class=\"exception-panel text-center flex align-items-center justify-content-center flex-column\">\n <h1 class=\"text-red-400 mb-0\">{{ 'pages.notFound.title' | translate }}</h1>\n <h3 class=\"text-red-300\">{{ 'pages.notFound.subtitle' | translate }}</h3>\n <button type=\"button\" pButton [label]=\"'general.returnHome' | translate\" [routerLink]=\"['/']\"></button>\n </div>\n <div class=\"exception-footer align-items-center flex\">\n <img [src]=\"layout.appLogo()\" class=\"exception-logo\" alt=\"App logo\" />\n <img [src]=\"layout.appLogoName()\" class=\"exception-appname ml-3\" alt=\"App name\" />\n </div>\n </div>\n</div>\n", styles: [".exception-body{background:var(--surface-ground)}.exception-body .exception-container{background:var(--exception-pages-image);background-repeat:no-repeat;background-size:contain;box-sizing:border-box}.exception-body .exception-container .exception-panel{box-sizing:border-box;flex-grow:1;margin-top:3rem;margin-bottom:3rem}.exception-body .exception-container .exception-panel h1{font-size:140px;font-weight:900;text-shadow:0 0 50px rgba(252,97,97,.2)}.exception-body .exception-container .exception-panel h3{font-size:80px;font-weight:900;margin-top:-90px;margin-bottom:50px}.exception-body .exception-container .exception-panel button{margin-top:50px}.exception-body .exception-container .exception-footer{margin-bottom:2rem}.exception-body .exception-container .exception-footer .exception-logo{width:34px}.exception-body .exception-container .exception-footer .exception-appname{width:72px}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
202
+ }
203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: ErrorPageComponent, decorators: [{
204
+ type: Component,
205
+ args: [{ standalone: true, selector: 'mng-error-page', imports: [ButtonModule, TranslateModule, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"'exception-body min-h-screen ' + (layout.colorSchemeIsLight() ? 'layout-light' : 'layout-dark')\">\n <div class=\"exception-container min-h-screen flex align-items-center justify-content-center flex-column bg-auto md:bg-contain bg-no-repeat\">\n <div class=\"exception-panel text-center flex align-items-center justify-content-center flex-column\">\n <h1 class=\"text-red-400 mb-0\">{{ 'pages.notFound.title' | translate }}</h1>\n <h3 class=\"text-red-300\">{{ 'pages.notFound.subtitle' | translate }}</h3>\n <button type=\"button\" pButton [label]=\"'general.returnHome' | translate\" [routerLink]=\"['/']\"></button>\n </div>\n <div class=\"exception-footer align-items-center flex\">\n <img [src]=\"layout.appLogo()\" class=\"exception-logo\" alt=\"App logo\" />\n <img [src]=\"layout.appLogoName()\" class=\"exception-appname ml-3\" alt=\"App name\" />\n </div>\n </div>\n</div>\n", styles: [".exception-body{background:var(--surface-ground)}.exception-body .exception-container{background:var(--exception-pages-image);background-repeat:no-repeat;background-size:contain;box-sizing:border-box}.exception-body .exception-container .exception-panel{box-sizing:border-box;flex-grow:1;margin-top:3rem;margin-bottom:3rem}.exception-body .exception-container .exception-panel h1{font-size:140px;font-weight:900;text-shadow:0 0 50px rgba(252,97,97,.2)}.exception-body .exception-container .exception-panel h3{font-size:80px;font-weight:900;margin-top:-90px;margin-bottom:50px}.exception-body .exception-container .exception-panel button{margin-top:50px}.exception-body .exception-container .exception-footer{margin-bottom:2rem}.exception-body .exception-container .exception-footer .exception-logo{width:34px}.exception-body .exception-container .exception-footer .exception-appname{width:72px}\n"] }]
206
+ }] });
207
+
208
+ class NotFoundPageComponent {
209
+ constructor() {
210
+ this.layout = inject(LayoutService);
211
+ }
212
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: NotFoundPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
213
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.5", type: NotFoundPageComponent, isStandalone: true, selector: "mng-not-found-page", ngImport: i0, template: "<div [class]=\"'exception-body min-h-screen ' + (layout.colorSchemeIsLight() ? 'layout-light' : 'layout-dark')\">\n <div class=\"exception-container min-h-screen flex align-items-center justify-content-center flex-column bg-auto md:bg-contain bg-no-repeat\">\n <div class=\"exception-panel text-center flex align-items-center justify-content-center flex-column\">\n <h1 class=\"text-red-400 mb-0\">{{ 'pages.notFound.title' | translate }}</h1>\n <h3 class=\"text-red-300\">{{ 'pages.notFound.subtitle' | translate }}</h3>\n <p>{{ 'pages.notFound.message' | translate }}</p>\n <button type=\"button\" pButton [label]=\"'general.returnHome' | translate\" [routerLink]=\"['/']\"></button>\n </div>\n <div class=\"exception-footer align-items-center flex\">\n <img [src]=\"layout.appLogo()\" class=\"exception-logo\" alt=\"App logo\" />\n <img [src]=\"layout.appLogoName()\" class=\"exception-appname ml-3\" alt=\"App name\" />\n </div>\n </div>\n</div>\n", styles: [".exception-body{background:var(--surface-ground)}.exception-body .exception-container{background:var(--exception-pages-image);background-repeat:no-repeat;background-size:contain;box-sizing:border-box}.exception-body .exception-container .exception-panel{box-sizing:border-box;flex-grow:1;margin-top:3rem;margin-bottom:3rem}.exception-body .exception-container .exception-panel h1{font-size:140px;font-weight:900;text-shadow:0 0 50px rgba(252,97,97,.2)}.exception-body .exception-container .exception-panel h3{font-size:80px;font-weight:900;margin-top:-90px;margin-bottom:50px}.exception-body .exception-container .exception-panel p{font-size:24px;font-weight:400;max-width:320px}.exception-body .exception-container .exception-panel button{margin-top:50px}.exception-body .exception-container .exception-footer{margin-bottom:2rem}.exception-body .exception-container .exception-footer .exception-logo{width:34px}.exception-body .exception-container .exception-footer .exception-appname{width:72px}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
214
+ }
215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: NotFoundPageComponent, decorators: [{
216
+ type: Component,
217
+ args: [{ standalone: true, selector: 'mng-not-found-page', imports: [ButtonModule, RouterLink, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"'exception-body min-h-screen ' + (layout.colorSchemeIsLight() ? 'layout-light' : 'layout-dark')\">\n <div class=\"exception-container min-h-screen flex align-items-center justify-content-center flex-column bg-auto md:bg-contain bg-no-repeat\">\n <div class=\"exception-panel text-center flex align-items-center justify-content-center flex-column\">\n <h1 class=\"text-red-400 mb-0\">{{ 'pages.notFound.title' | translate }}</h1>\n <h3 class=\"text-red-300\">{{ 'pages.notFound.subtitle' | translate }}</h3>\n <p>{{ 'pages.notFound.message' | translate }}</p>\n <button type=\"button\" pButton [label]=\"'general.returnHome' | translate\" [routerLink]=\"['/']\"></button>\n </div>\n <div class=\"exception-footer align-items-center flex\">\n <img [src]=\"layout.appLogo()\" class=\"exception-logo\" alt=\"App logo\" />\n <img [src]=\"layout.appLogoName()\" class=\"exception-appname ml-3\" alt=\"App name\" />\n </div>\n </div>\n</div>\n", styles: [".exception-body{background:var(--surface-ground)}.exception-body .exception-container{background:var(--exception-pages-image);background-repeat:no-repeat;background-size:contain;box-sizing:border-box}.exception-body .exception-container .exception-panel{box-sizing:border-box;flex-grow:1;margin-top:3rem;margin-bottom:3rem}.exception-body .exception-container .exception-panel h1{font-size:140px;font-weight:900;text-shadow:0 0 50px rgba(252,97,97,.2)}.exception-body .exception-container .exception-panel h3{font-size:80px;font-weight:900;margin-top:-90px;margin-bottom:50px}.exception-body .exception-container .exception-panel p{font-size:24px;font-weight:400;max-width:320px}.exception-body .exception-container .exception-panel button{margin-top:50px}.exception-body .exception-container .exception-footer{margin-bottom:2rem}.exception-body .exception-container .exception-footer .exception-logo{width:34px}.exception-body .exception-container .exception-footer .exception-appname{width:72px}\n"] }]
218
+ }] });
219
+
29
220
  class VersionService {
30
221
  constructor(http, configurationService) {
31
222
  this.http = http;
@@ -57,12 +248,12 @@ class VersionService {
57
248
  }
58
249
  return this.cache[url].asObservable();
59
250
  }
60
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: VersionService, deps: [{ token: i1.HttpClient }, { token: i2.CommonsConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
251
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: VersionService, deps: [{ token: i1$2.HttpClient }, { token: i2.CommonsConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
61
252
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: VersionService }); }
62
253
  }
63
254
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: VersionService, decorators: [{
64
255
  type: Injectable
65
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.CommonsConfigurationService }] });
256
+ }], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: i2.CommonsConfigurationService }] });
66
257
 
67
258
  class VersionComponent {
68
259
  constructor() {
@@ -146,16 +337,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
146
337
  class FooterComponent {
147
338
  constructor() {
148
339
  this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
340
+ this.layout = inject(LayoutService);
149
341
  this.commons = inject(CommonsService);
150
342
  this.currentYear = signal(new Date().getFullYear());
151
343
  this.versionComponent = signal(this.config?.components?.version === false ? undefined : this.config?.components?.version ?? VersionComponent);
152
344
  }
153
345
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
154
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: FooterComponent, isStandalone: true, selector: "mng-footer", ngImport: i0, template: "<div class=\"layout-footer\">\n <div class=\"footer-logo-container\">\n <img id=\"footer-logo\" [src]=\"commons.appLogo()\" alt=\"atlantis-layout\" />\n <span class=\"app-name\">{{ commons.appName() | translate }}</span>\n </div>\n <div class=\"flex flex-column\">\n <div>\n <span class=\"copyright\">&#169; {{ commons.appOwner() | translate }} - {{ currentYear() }}</span>\n </div>\n @if (versionComponent()) {\n <div class=\"version\" [mngComponent]=\"versionComponent()\" [inputs]=\"{version: commons.appVersion()}\" [attachToHost]=\"true\"></div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
346
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: FooterComponent, isStandalone: true, selector: "mng-footer", ngImport: i0, template: "<div class=\"layout-footer\">\n <div class=\"footer-logo-container\">\n <img id=\"footer-logo\" [src]=\"layout.appLogo()\" alt=\"atlantis-layout\" />\n <span class=\"app-name\">{{ commons.appName() | translate }}</span>\n </div>\n <div class=\"flex flex-column\">\n <div>\n <span class=\"copyright\">&#169; {{ commons.appOwner() | translate }} - {{ currentYear() }}</span>\n </div>\n @if (versionComponent()) {\n <div class=\"version\" [mngComponent]=\"versionComponent()\" [inputs]=\"{version: commons.appVersion()}\" [attachToHost]=\"true\"></div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
155
347
  }
156
348
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FooterComponent, decorators: [{
157
349
  type: Component,
158
- args: [{ standalone: true, selector: 'mng-footer', imports: [TranslateModule, NgOptimizedImage, VersionComponent, ComponentDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"layout-footer\">\n <div class=\"footer-logo-container\">\n <img id=\"footer-logo\" [src]=\"commons.appLogo()\" alt=\"atlantis-layout\" />\n <span class=\"app-name\">{{ commons.appName() | translate }}</span>\n </div>\n <div class=\"flex flex-column\">\n <div>\n <span class=\"copyright\">&#169; {{ commons.appOwner() | translate }} - {{ currentYear() }}</span>\n </div>\n @if (versionComponent()) {\n <div class=\"version\" [mngComponent]=\"versionComponent()\" [inputs]=\"{version: commons.appVersion()}\" [attachToHost]=\"true\"></div>\n }\n </div>\n</div>\n" }]
350
+ args: [{ standalone: true, selector: 'mng-footer', imports: [TranslateModule, NgOptimizedImage, VersionComponent, ComponentDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"layout-footer\">\n <div class=\"footer-logo-container\">\n <img id=\"footer-logo\" [src]=\"layout.appLogo()\" alt=\"atlantis-layout\" />\n <span class=\"app-name\">{{ commons.appName() | translate }}</span>\n </div>\n <div class=\"flex flex-column\">\n <div>\n <span class=\"copyright\">&#169; {{ commons.appOwner() | translate }} - {{ currentYear() }}</span>\n </div>\n @if (versionComponent()) {\n <div class=\"version\" [mngComponent]=\"versionComponent()\" [inputs]=\"{version: commons.appVersion()}\" [attachToHost]=\"true\"></div>\n }\n </div>\n</div>\n" }]
159
351
  }] });
160
352
 
161
353
  class BreadcrumbComponent {
@@ -182,72 +374,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
182
374
  args: [{ standalone: true, selector: 'mng-breadcrumb', imports: [TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"layout-breadcrumb flex align-items-center relative h-3rem\">\n <nav>\n <ol class=\"relative z-2\">\n @for (item of mappedBreadcrumbs(); track item.id; let last = $last) {\n <li>{{ item.label! | translate }}</li>\n @if (!last) {\n <li class=\"layout-breadcrumb-chevron\">/</li>\n }\n }\n </ol>\n </nav>\n</div>\n" }]
183
375
  }] });
184
376
 
185
- class MainLayoutComponentService {
186
- constructor() {
187
- this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
188
- this.state = signal({
189
- staticMenuDesktopInactive: false,
190
- overlayMenuActive: false,
191
- rightMenuActive: false,
192
- configSidebarVisible: false,
193
- staticMenuMobileActive: false,
194
- menuHoverActive: false,
195
- sidebarActive: false,
196
- anchored: false
197
- });
198
- this.overlayOpen = new Subject();
199
- this.overlayOpen$ = this.overlayOpen.asObservable();
200
- }
201
- onMenuToggle() {
202
- if (this.isOverlay()) {
203
- this.state.update(state => ({
204
- ...state,
205
- overlayMenuActive: !state.overlayMenuActive
206
- }));
207
- if (this.state().overlayMenuActive) {
208
- this.overlayOpen.next(null);
209
- }
210
- }
211
- if (this.isDesktop()) {
212
- this.state.update(state => ({
213
- ...state,
214
- staticMenuDesktopInactive: !state.staticMenuDesktopInactive
215
- }));
216
- }
217
- else {
218
- this.state.update(state => ({
219
- ...state,
220
- staticMenuMobileActive: !state.staticMenuMobileActive
221
- }));
222
- if (this.state().staticMenuMobileActive) {
223
- this.overlayOpen.next(null);
224
- }
377
+ function prepareMenuItemsToInternal(menuItems, parentKey = '') {
378
+ const newItems = menuItems.map((item, idx) => {
379
+ const itemsProp = signal([]);
380
+ const lazyChildrenProp = signal(item.lazyChildren ?? false);
381
+ const hasItemsProp = computed(() => itemsProp().length > 0);
382
+ const newItem = {
383
+ ...item,
384
+ isVisible: typeof item.isVisible !== 'undefined' ? item.isVisible : item.visible,
385
+ key: parentKey ? parentKey + '-' + idx : idx.toString(),
386
+ config: item,
387
+ items: itemsProp,
388
+ lazyChildren: lazyChildrenProp,
389
+ itemsVisibility: signal([]),
390
+ hasItems: hasItemsProp,
391
+ hasItemsOrLazyChildren: computed(() => lazyChildrenProp() || hasItemsProp())
392
+ };
393
+ if (Array.isArray(item.items) && item.items.length > 0) {
394
+ newItem.items.set(prepareMenuItemsToInternal(item.items, newItem.key));
395
+ newItem.itemsVisibility.set(newItem.items()?.map(i => signal(true)));
225
396
  }
226
- }
227
- onOverlaySubmenuOpen() {
228
- this.overlayOpen.next(null);
229
- }
230
- isOverlay() {
231
- return this.config?.menuMode === 'overlay';
232
- }
233
- isSlim() {
234
- return this.config?.menuMode === 'slim';
235
- }
236
- isSlimPlus() {
237
- return this.config?.menuMode === 'slim-plus';
238
- }
239
- isDesktop() {
240
- return window.innerWidth > 991;
241
- }
242
- isMobile() {
243
- return !this.isDesktop();
244
- }
245
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MainLayoutComponentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
246
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MainLayoutComponentService }); }
397
+ return newItem;
398
+ });
399
+ return newItems;
247
400
  }
248
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MainLayoutComponentService, decorators: [{
249
- type: Injectable
250
- }] });
251
401
 
252
402
  class MenuService {
253
403
  constructor() {
@@ -255,50 +405,45 @@ class MenuService {
255
405
  this.logger = LoggerService.create('MenuService');
256
406
  this.router = inject(Router);
257
407
  this.commonsRouter = inject(CommonsRouterService);
258
- this.menuSource = new ReplaySubject(1);
259
- this.resetSource = new Subject();
260
- this.menuSource$ = this.menuSource.asObservable();
261
- this.resetSource$ = this.resetSource.asObservable();
262
- this.menuItems = [];
408
+ this._menuItems = signal([]);
409
+ this.menuItems = this._menuItems.asReadonly();
410
+ this.menuChangeSubject = new ReplaySubject(1);
411
+ this.menuChange$ = this.menuChangeSubject.asObservable();
263
412
  this.routeLoadedChildrenSubscriptions = [];
264
413
  }
265
- initialize(menuItems) {
266
- this.menuItems = menuItems;
414
+ setItems(menuItems) {
267
415
  this.routeLoadedChildrenSubscriptions.forEach(s => s.unsubscribe());
268
416
  this.routeLoadedChildrenSubscriptions = [];
269
- this.generateMenuItemKeys(menuItems);
417
+ this._menuItems.set(prepareMenuItemsToInternal(menuItems));
418
+ this.appendListenersToLazyChildren(this._menuItems());
419
+ this.router.events;
270
420
  this.router.events
271
- .pipe(filter(event => event instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
421
+ .pipe(startWith(new NavigationEnd(0, this.router.url, this.router.url)), filter(event => event instanceof NavigationEnd), map(e => e), takeUntilDestroyed(this.destroyRef))
272
422
  .subscribe(e => {
273
423
  this.findAndSetActiveMenuItem(e.urlAfterRedirects);
274
424
  });
275
- this.findAndSetActiveMenuItem(this.router.url);
276
425
  }
277
- generateMenuItemKeys(menuItems, parentKey = '') {
278
- menuItems.forEach((item, idx) => {
279
- if (!item.index) {
280
- item.index = idx;
281
- item.key = parentKey ? parentKey + '-' + idx : idx.toString();
282
- }
283
- if (item.items) {
284
- this.generateMenuItemKeys(item.items, item.key);
285
- }
286
- else if (item.lazyChildren) {
426
+ appendListenersToLazyChildren(menuItems) {
427
+ menuItems.forEach(item => {
428
+ if (item.lazyChildren()) {
287
429
  this.listenToMenuItemLazyChildrenLoad(item);
288
430
  }
431
+ else if (item.items()) {
432
+ this.appendListenersToLazyChildren(item.items());
433
+ }
289
434
  });
290
435
  }
291
436
  findAndSetActiveMenuItem(url) {
292
- const matches = this.findActiveRouteMatches(this.menuItems, url);
437
+ const matches = this.findActiveRouteMatches(this.menuItems(), url);
293
438
  if (matches.length === 0) {
294
439
  this.reset();
295
440
  }
296
441
  else {
297
442
  const matchKey = matches[0][matches[0].length - 1].key;
298
443
  if (matchKey) {
299
- this.menuSource.next({
444
+ this.menuChangeSubject.next({
300
445
  key: matchKey,
301
- routeEvent: true
446
+ eventType: 'routeChange'
302
447
  });
303
448
  }
304
449
  else {
@@ -316,13 +461,14 @@ class MenuService {
316
461
  .pipe(take(1))
317
462
  .subscribe({
318
463
  next: routes => {
319
- let menuItems = routes
464
+ const menuItemsFromRoutes = routes
320
465
  .filter(r => Array.isArray(r.data?.menuItems))
321
466
  .flatMap(r => r.data.menuItems);
322
- menuItems = adjustRouteMenuLazyChildrenRouterLinks(menuItem, menuItems);
323
- menuItem.items = menuItems;
324
- menuItem.lazyChildren = false;
325
- this.generateMenuItemKeys(menuItem.items, menuItem.key);
467
+ const menuItems = adjustRouteMenuLazyChildrenRouterLinks(menuItem, menuItemsFromRoutes);
468
+ menuItem.items.set(prepareMenuItemsToInternal(menuItems, menuItem.key));
469
+ this.appendListenersToLazyChildren(menuItem.items());
470
+ menuItem.itemsVisibility.set(menuItem.items()?.map(i => signal(true)));
471
+ menuItem.lazyChildren.set(false);
326
472
  this.findAndSetActiveMenuItem(this.router.url);
327
473
  }
328
474
  }));
@@ -330,11 +476,12 @@ class MenuService {
330
476
  findActiveRouteMatches(menuItems, url) {
331
477
  const matches = [];
332
478
  for (const menuItem of menuItems) {
479
+ const chidldren = menuItem.items();
333
480
  if (menuItem.routerLink) {
334
481
  const isActive = doesUrlMatchRouterLink(menuItem.routerLink, url);
335
482
  if (isActive) {
336
- if (Array.isArray(menuItem.items)) {
337
- const itemsMatches = this.findActiveRouteMatches(menuItem.items, url);
483
+ if (Array.isArray(chidldren)) {
484
+ const itemsMatches = this.findActiveRouteMatches(chidldren, url);
338
485
  if (itemsMatches.length > 0) {
339
486
  matches.push(...itemsMatches.map(c => [menuItem, ...c]));
340
487
  }
@@ -347,8 +494,8 @@ class MenuService {
347
494
  }
348
495
  }
349
496
  }
350
- else if (Array.isArray(menuItem.items)) {
351
- const itemsMatches = this.findActiveRouteMatches(menuItem.items, url);
497
+ else if (Array.isArray(chidldren)) {
498
+ const itemsMatches = this.findActiveRouteMatches(chidldren, url);
352
499
  if (itemsMatches.length > 0) {
353
500
  matches.push(...itemsMatches.map(c => [menuItem, ...c]));
354
501
  }
@@ -357,7 +504,9 @@ class MenuService {
357
504
  return matches;
358
505
  }
359
506
  reset() {
360
- this.resetSource.next(true);
507
+ this.menuChangeSubject.next({
508
+ eventType: 'reset'
509
+ });
361
510
  }
362
511
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
363
512
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MenuService }); }
@@ -368,100 +517,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
368
517
 
369
518
  class MenuItemComponent {
370
519
  constructor() {
371
- this.router = inject(Router);
372
- this.injector = inject(Injector);
373
- this.destroyRef = inject(DestroyRef);
374
520
  this.menuService = inject(MenuService);
375
521
  this.permissionService = inject(PermissionService);
376
- this.layoutService = inject(MainLayoutComponentService);
377
- this.isPermitted = signal(true);
378
- this.childrenVisibilitySubject = [];
379
- this.root = false;
380
- this.visibleChangeEventEmitter = new EventEmitter();
381
- this.active = signal(false);
382
- this.visible = signal(false);
383
- this.menuService.menuSource$.pipe(takeUntilDestroyed()).subscribe(value => {
384
- setTimeout(() => {
385
- this.active.set(this.item.key === value.key || value.key.startsWith((this.item.key ?? '') + '-'));
386
- });
522
+ this.layout = inject(LayoutService);
523
+ this.item = input.required();
524
+ this.root = input(false);
525
+ this.visibleChange = output();
526
+ this.submenuElRef = viewChild('submenu');
527
+ this.isPermitted = toSignal(toObservable(this.item).pipe(switchMap(i => (i.permissions ? this.permissionService.isMenuItemVisible(i.permissions, i.config) : of(true)))));
528
+ this.isVisibleFromItemSettings = toSignal(toObservable(this.item).pipe(switchMap(i => (typeof i.isVisible === 'function' ? toObservable$1(i.isVisible(i.config)) : of(i.isVisible ?? true)))));
529
+ this.menuChangeEvents = toSignal(this.menuService.menuChange$.pipe(distinctUntilChanged((v1, v2) => v1.key === v2.key)));
530
+ this.active = computed(() => {
531
+ if (!this.isPermitted()) {
532
+ return false;
533
+ }
534
+ const menuChangeEvent = this.menuChangeEvents();
535
+ if (menuChangeEvent) {
536
+ return menuChangeEvent.eventType === 'reset' || !menuChangeEvent.key
537
+ ? false
538
+ : this.item().key === menuChangeEvent.key || menuChangeEvent.key.startsWith((this.item().key ?? '') + '-');
539
+ }
540
+ return false;
387
541
  });
388
- this.menuService.resetSource$.pipe(takeUntilDestroyed()).subscribe(() => {
389
- this.active.set(false);
390
- });
391
- this.router.events.pipe(takeUntilDestroyed()).subscribe(next => {
392
- if (next instanceof NavigationEnd) {
393
- if (!this.layoutService.isMobile()) {
394
- this.active.set(false);
395
- }
396
- else {
397
- this.updateActiveStateFromRoute();
398
- }
399
- }
542
+ this.visible = computed(() => {
543
+ const isPermitted = this.isPermitted();
544
+ if (!isPermitted) {
545
+ return false;
546
+ }
547
+ if (!this.isVisibleFromItemSettings()) {
548
+ return false;
549
+ }
550
+ const items = this.item().items();
551
+ if (Array.isArray(items) &&
552
+ items.length > 0 &&
553
+ this.item()
554
+ .itemsVisibility()
555
+ .every(v => !v())) {
556
+ return false;
557
+ }
558
+ return true;
400
559
  });
401
560
  effect(() => {
402
- if (this.isPermitted()) {
403
- this.active.set(false);
404
- this.visible.set(true);
561
+ if (this.root() && this.active() && this.layout.isDesktop() && (this.layout.isSlim() || this.layout.isSlimPlus())) {
562
+ this.calculatePosition(this.submenuElRef()?.nativeElement, this.submenuElRef()?.nativeElement.parentElement);
405
563
  }
406
- else {
407
- this.active.set(true);
408
- this.visible.set(false);
409
- }
410
- }, { allowSignalWrites: true });
411
- }
412
- ngOnInit() {
413
- if (this.item.routerLink) {
414
- if (typeof this.item.routerLink === 'string') {
415
- this.itemUrl = this.item.routerLink;
416
- }
417
- else {
418
- this.itemUrl = this.router.parseUrl(this.item.routerLink.join('/'));
419
- }
420
- }
421
- this.processItemVisibility();
422
- this.processItemChildrenVisibility();
423
- }
424
- ngAfterViewChecked() {
425
- if (this.root && this.active() && this.layoutService.isDesktop() && (this.layoutService.isSlim() || this.layoutService.isSlimPlus())) {
426
- this.calculatePosition(this.submenu?.nativeElement, this.submenu?.nativeElement.parentElement);
427
- }
428
- }
429
- ngOnDestroy() {
430
- this.isVisibleSubscription?.unsubscribe();
564
+ });
431
565
  }
432
566
  get submenuAnimation() {
433
- if (this.layoutService.isDesktop() && (this.layoutService.isSlim() || this.layoutService.isSlimPlus())) {
567
+ if (this.layout.isDesktop() && (this.layout.isSlim() || this.layout.isSlimPlus())) {
434
568
  return this.active() ? 'visible' : 'hidden';
435
569
  }
436
570
  else {
437
- return this.root ? 'expanded' : this.active() ? 'expanded' : 'collapsed';
571
+ return this.root() ? 'expanded' : this.active() ? 'expanded' : 'collapsed';
438
572
  }
439
573
  }
440
- get activeClass() {
441
- return this.active() && !this.root;
442
- }
443
574
  itemClick(event) {
575
+ const item = this.item();
444
576
  // avoid processing disabled items
445
- if (this.item.disabled) {
577
+ if (item.disabled) {
446
578
  event.preventDefault();
447
579
  return;
448
580
  }
449
581
  // toggle active state
450
- if (this.item.items || this.item.lazyChildren) {
451
- if ((this.root || this.active()) && (this.layoutService.isSlim() || this.layoutService.isSlimPlus())) {
452
- this.layoutService.onOverlaySubmenuOpen();
582
+ if (item.hasItemsOrLazyChildren()) {
583
+ if ((this.root() || this.active()) && (this.layout.isSlim() || this.layout.isSlimPlus())) {
584
+ this.layout.onOverlaySubmenuOpen();
453
585
  }
454
586
  }
455
587
  else {
456
- if (this.layoutService.isMobile()) {
457
- this.layoutService.state.update(state => ({
588
+ if (this.layout.isMobile()) {
589
+ this.layout.state.update(state => ({
458
590
  ...state,
459
591
  staticMenuMobileActive: false
460
592
  }));
461
593
  }
462
- if (this.layoutService.isSlim() || this.layoutService.isSlimPlus()) {
594
+ if (this.layout.isSlim() || this.layout.isSlimPlus()) {
463
595
  this.menuService.reset();
464
- this.layoutService.state.update(state => ({
596
+ this.layout.state.update(state => ({
465
597
  ...state,
466
598
  menuHoverActive: false
467
599
  }));
@@ -469,14 +601,14 @@ class MenuItemComponent {
469
601
  }
470
602
  }
471
603
  onSubmenuAnimated(event) {
472
- if (event.toState === 'visible' && this.layoutService.isDesktop() && (this.layoutService.isSlim() || this.layoutService.isSlimPlus())) {
604
+ if (event.toState === 'visible' && this.layout.isDesktop() && (this.layout.isSlim() || this.layout.isSlimPlus())) {
473
605
  const el = event.element;
474
606
  const elParent = el.parentElement;
475
607
  this.calculatePosition(el, elParent);
476
608
  }
477
609
  }
478
610
  onChildVisibleChange(visible, item, idx) {
479
- this.childrenVisibilitySubject[idx].next(visible);
611
+ this.item().itemsVisibility()[idx]?.set(visible);
480
612
  }
481
613
  calculatePosition(overlay, target) {
482
614
  if (overlay) {
@@ -486,63 +618,14 @@ class MenuItemComponent {
486
618
  // reset
487
619
  overlay.style.top = '';
488
620
  overlay.style.left = '';
489
- if (this.layoutService.isSlim() || this.layoutService.isSlimPlus()) {
621
+ if (this.layout.isSlim() || this.layout.isSlimPlus()) {
490
622
  const height = top + oHeight;
491
623
  overlay.style.top = vHeight < height ? `${top - (height - vHeight)}px` : `${top}px`;
492
624
  }
493
625
  }
494
626
  }
495
- processItemVisibility() {
496
- if (this.item.permissions) {
497
- this.permissionService
498
- .isMenuItemVisible(this.item.permissions, this.item)
499
- .pipe(takeUntilDestroyed(this.destroyRef))
500
- .subscribe({
501
- next: isPermitted => {
502
- this.isPermitted.set(isPermitted);
503
- }
504
- });
505
- }
506
- if (this.item.isVisible && typeof this.item.isVisible === 'function') {
507
- let isVisibleObs;
508
- runInInjectionContext(this.injector, () => {
509
- const isVisibleRes = this.item.isVisible(this.item);
510
- if (isVisibleRes instanceof Observable) {
511
- isVisibleObs = isVisibleRes;
512
- }
513
- else {
514
- isVisibleObs = of(isVisibleRes);
515
- }
516
- });
517
- this.isVisibleSubscription = isVisibleObs?.subscribe(isVisible => this.isPermitted.set(isVisible));
518
- }
519
- }
520
- updateActiveStateFromRoute() {
521
- if (this.itemUrl) {
522
- this.active.set(this.router.isActive(this.itemUrl, {
523
- matrixParams: 'ignored',
524
- queryParams: 'ignored',
525
- paths: this.item.items ? 'subset' : 'exact',
526
- fragment: 'ignored'
527
- }));
528
- }
529
- else {
530
- this.active.set(false);
531
- }
532
- }
533
- processItemChildrenVisibility() {
534
- if (this.item.items) {
535
- this.childrenVisibilitySubject = this.item.items.map(() => new BehaviorSubject(true));
536
- combineLatest(this.childrenVisibilitySubject.map(s => s.asObservable().pipe(distinctUntilChanged())))
537
- .pipe(takeUntilDestroyed(this.destroyRef))
538
- .subscribe(visible => {
539
- const anyChildVisible = visible.some(v => v === true);
540
- this.active.set(!anyChildVisible);
541
- });
542
- }
543
- }
544
627
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
545
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MenuItemComponent, isStandalone: true, selector: "[mng-menuitem]", inputs: { item: "item", root: "root" }, outputs: { visibleChangeEventEmitter: "visibleChange" }, host: { properties: { "class.layout-root-menuitem": "this.root", "class.active-menuitem": "this.activeClass" } }, providers: [PermissionService], viewQueries: [{ propertyName: "submenu", first: true, predicate: ["submenu"], descendants: true }], ngImport: i0, template: "@if (visible()) {\n @if (root) {\n <div class=\"layout-menuitem-root-text\">\n {{ item.label! | translate }}\n </div>\n }\n @if (!item.href) {\n @if (!item.routerLink || item.items) {\n <a\n [attr.href]=\"item.href\"\n (click)=\"itemClick($event)\"\n (keydown.enter)=\"itemClick($event)\"\n [routerLink]=\"item.routerLink\"\n [attr.target]=\"item.target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item.className ?? ''\"\n pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n } @else if (item.routerLink && !item.items) {\n <a\n (click)=\"itemClick($event)\"\n [routerLink]=\"item.routerLink\"\n [attr.target]=\"item.target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item.className ?? '' + (this.active() ? ' active-route' : '')\"\n [preserveFragment]=\"item.preserveFragment\"\n [skipLocationChange]=\"item.skipLocationChange\"\n [replaceUrl]=\"item.replaceUrl\"\n [queryParams]=\"item.queryParams\"\n pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n }\n } @else {\n @if (!item.items) {\n <a (click)=\"itemClick($event)\" [attr.href]=\"item.href\" [attr.target]=\"item.target\" [attr.tabindex]=\"0\" [ngClass]=\"item.className ?? ''\" pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n }\n }\n @if (item.items) {\n <ul #submenu [@children]=\"submenuAnimation\" (@children.done)=\"onSubmenuAnimated($event)\">\n @for (child of item.items; track child; let i = $index) {\n <li mng-menuitem [item]=\"child\" [class]=\"child.badgeClassName\" (visibleChange)=\"onChildVisibleChange($event, item, i)\"></li>\n }\n </ul>\n }\n}\n", dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[mng-menuitem]", inputs: ["item", "root"], outputs: ["visibleChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i1$2.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], animations: [
628
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MenuItemComponent, isStandalone: true, selector: "[mng-menuitem]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, root: { classPropertyName: "root", publicName: "root", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, host: { properties: { "class.active-menuitem": "!root() && active()", "class.layout-root-menuitem": "root()" } }, providers: [PermissionService], viewQueries: [{ propertyName: "submenuElRef", first: true, predicate: ["submenu"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (visible()) {\n @if (root()) {\n <div class=\"layout-menuitem-root-text\">\n {{ item().label! | translate }}\n </div>\n }\n @if (!item().href) {\n @if (!item().routerLink || item().hasItems()) {\n <a\n [attr.href]=\"item().href\"\n (click)=\"itemClick($event)\"\n (keydown.enter)=\"itemClick($event)\"\n [routerLink]=\"item().routerLink\"\n [attr.target]=\"item().target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item().className ?? ''\"\n pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n } @else if (item().routerLink && !item().hasItems()) {\n <a\n (click)=\"itemClick($event)\"\n [routerLink]=\"item().routerLink\"\n [attr.target]=\"item().target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item().className ?? '' + (this.active() ? ' active-route' : '')\"\n [preserveFragment]=\"item().preserveFragment\"\n [skipLocationChange]=\"item().skipLocationChange\"\n [replaceUrl]=\"item().replaceUrl\"\n [queryParams]=\"item().queryParams\"\n pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n }\n } @else {\n @if (!item().hasItems()) {\n <a (click)=\"itemClick($event)\" [attr.href]=\"item().href\" [attr.target]=\"item().target\" [attr.tabindex]=\"0\" [ngClass]=\"item().className ?? ''\" pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n }\n }\n @if (item().hasItems()) {\n <ul #submenu [@children]=\"submenuAnimation\" (@children.done)=\"onSubmenuAnimated($event)\">\n @for (child of item().items(); track child; let i = $index) {\n <li mng-menuitem [item]=\"child\" [class]=\"child.badgeClassName\" (visibleChange)=\"onChildVisibleChange($event, child, i)\"></li>\n }\n </ul>\n }\n}\n", dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[mng-menuitem]", inputs: ["item", "root"], outputs: ["visibleChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i1$3.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], animations: [
546
629
  trigger('children', [
547
630
  state('collapsed', style({
548
631
  height: '0'
@@ -578,34 +661,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
578
661
  })),
579
662
  transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
580
663
  ])
581
- ], providers: [PermissionService], template: "@if (visible()) {\n @if (root) {\n <div class=\"layout-menuitem-root-text\">\n {{ item.label! | translate }}\n </div>\n }\n @if (!item.href) {\n @if (!item.routerLink || item.items) {\n <a\n [attr.href]=\"item.href\"\n (click)=\"itemClick($event)\"\n (keydown.enter)=\"itemClick($event)\"\n [routerLink]=\"item.routerLink\"\n [attr.target]=\"item.target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item.className ?? ''\"\n pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n } @else if (item.routerLink && !item.items) {\n <a\n (click)=\"itemClick($event)\"\n [routerLink]=\"item.routerLink\"\n [attr.target]=\"item.target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item.className ?? '' + (this.active() ? ' active-route' : '')\"\n [preserveFragment]=\"item.preserveFragment\"\n [skipLocationChange]=\"item.skipLocationChange\"\n [replaceUrl]=\"item.replaceUrl\"\n [queryParams]=\"item.queryParams\"\n pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n }\n } @else {\n @if (!item.items) {\n <a (click)=\"itemClick($event)\" [attr.href]=\"item.href\" [attr.target]=\"item.target\" [attr.tabindex]=\"0\" [ngClass]=\"item.className ?? ''\" pRipple>\n <i [ngClass]=\"item.icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item.label! | translate }}</span>\n @if (item.items || item.lazyChildren) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item.badge) {\n <span class=\"menuitem-badge\">{{ item.badge }}</span>\n }\n </a>\n }\n }\n @if (item.items) {\n <ul #submenu [@children]=\"submenuAnimation\" (@children.done)=\"onSubmenuAnimated($event)\">\n @for (child of item.items; track child; let i = $index) {\n <li mng-menuitem [item]=\"child\" [class]=\"child.badgeClassName\" (visibleChange)=\"onChildVisibleChange($event, item, i)\"></li>\n }\n </ul>\n }\n}\n" }]
582
- }], ctorParameters: () => [], propDecorators: { item: [{
583
- type: Input,
584
- args: [{ required: true }]
585
- }], root: [{
586
- type: Input
587
- }, {
588
- type: HostBinding,
589
- args: ['class.layout-root-menuitem']
590
- }], visibleChangeEventEmitter: [{
591
- type: Output,
592
- args: ['visibleChange']
593
- }], submenu: [{
594
- type: ViewChild,
595
- args: ['submenu']
596
- }], activeClass: [{
597
- type: HostBinding,
598
- args: ['class.active-menuitem']
599
- }] } });
664
+ ], host: {
665
+ '[class.active-menuitem]': '!root() && active()',
666
+ '[class.layout-root-menuitem]': 'root()'
667
+ }, providers: [PermissionService], template: "@if (visible()) {\n @if (root()) {\n <div class=\"layout-menuitem-root-text\">\n {{ item().label! | translate }}\n </div>\n }\n @if (!item().href) {\n @if (!item().routerLink || item().hasItems()) {\n <a\n [attr.href]=\"item().href\"\n (click)=\"itemClick($event)\"\n (keydown.enter)=\"itemClick($event)\"\n [routerLink]=\"item().routerLink\"\n [attr.target]=\"item().target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item().className ?? ''\"\n pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n } @else if (item().routerLink && !item().hasItems()) {\n <a\n (click)=\"itemClick($event)\"\n [routerLink]=\"item().routerLink\"\n [attr.target]=\"item().target\"\n [attr.tabindex]=\"0\"\n [ngClass]=\"item().className ?? '' + (this.active() ? ' active-route' : '')\"\n [preserveFragment]=\"item().preserveFragment\"\n [skipLocationChange]=\"item().skipLocationChange\"\n [replaceUrl]=\"item().replaceUrl\"\n [queryParams]=\"item().queryParams\"\n pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n }\n } @else {\n @if (!item().hasItems()) {\n <a (click)=\"itemClick($event)\" [attr.href]=\"item().href\" [attr.target]=\"item().target\" [attr.tabindex]=\"0\" [ngClass]=\"item().className ?? ''\" pRipple>\n <i [ngClass]=\"item().icon ?? ''\" class=\"layout-menuitem-icon\"></i>\n <span class=\"layout-menuitem-text\">{{ item().label! | translate }}</span>\n @if (item().hasItemsOrLazyChildren()) {\n <i class=\"pi pi-fw pi-angle-down layout-submenu-toggler\"></i>\n }\n @if (item().badge) {\n <span class=\"menuitem-badge\">{{ item().badge }}</span>\n }\n </a>\n }\n }\n @if (item().hasItems()) {\n <ul #submenu [@children]=\"submenuAnimation\" (@children.done)=\"onSubmenuAnimated($event)\">\n @for (child of item().items(); track child; let i = $index) {\n <li mng-menuitem [item]=\"child\" [class]=\"child.badgeClassName\" (visibleChange)=\"onChildVisibleChange($event, child, i)\"></li>\n }\n </ul>\n }\n}\n" }]
668
+ }], ctorParameters: () => [] });
600
669
 
601
670
  class MenuComponent {
602
671
  constructor() {
603
672
  this.route = inject(ActivatedRoute);
604
- this.menuService = inject(MenuService);
605
673
  this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
606
- this.layoutService = inject(MainLayoutComponentService);
674
+ this.layout = inject(LayoutService);
675
+ this.menuService = inject(MenuService);
607
676
  this.routeData = toSignal(this.route.data);
608
- this.menuItems = computed(() => {
677
+ effect(() => {
609
678
  let items = [];
610
679
  if (this.config?.menuItems && Array.isArray(this.config.menuItems)) {
611
680
  items = this.config.menuItems;
@@ -614,48 +683,44 @@ class MenuComponent {
614
683
  items = this.routeData().menuItems;
615
684
  }
616
685
  // Wraps menu items
617
- if (!(this.layoutService.isSlim() || this.layoutService.isSlimPlus())) {
686
+ if (!(this.layout.isSlim() || this.layout.isSlimPlus())) {
618
687
  items = [{ items }];
619
688
  }
620
- return items;
621
- });
622
- effect(() => {
623
- this.menuService.initialize(this.menuItems());
689
+ untracked(() => this.menuService.setItems(items));
624
690
  });
625
691
  }
626
692
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
627
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MenuComponent, isStandalone: true, selector: "mng-menu", ngImport: i0, template: "<ul class=\"layout-menu\">\n @for (item of menuItems(); track item) {\n @if (!item.separator) {\n <li mng-menuitem [item]=\"item\" [root]=\"true\"></li>\n }\n @if (item.separator) {\n <li class=\"menu-separator\"></li>\n }\n }\n</ul>\n", dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[mng-menuitem]", inputs: ["item", "root"], outputs: ["visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
693
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MenuComponent, isStandalone: true, selector: "mng-menu", ngImport: i0, template: "<ul class=\"layout-menu\">\n @for (item of menuService.menuItems(); track item) {\n @if (!item.separator) {\n <li mng-menuitem [item]=\"item\" [root]=\"true\"></li>\n }\n @if (item.separator) {\n <li class=\"menu-separator\"></li>\n }\n }\n</ul>\n", dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[mng-menuitem]", inputs: ["item", "root"], outputs: ["visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
628
694
  }
629
695
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MenuComponent, decorators: [{
630
696
  type: Component,
631
- args: [{ standalone: true, selector: 'mng-menu', imports: [MenuItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"layout-menu\">\n @for (item of menuItems(); track item) {\n @if (!item.separator) {\n <li mng-menuitem [item]=\"item\" [root]=\"true\"></li>\n }\n @if (item.separator) {\n <li class=\"menu-separator\"></li>\n }\n }\n</ul>\n" }]
697
+ args: [{ standalone: true, selector: 'mng-menu', imports: [MenuItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"layout-menu\">\n @for (item of menuService.menuItems(); track item) {\n @if (!item.separator) {\n <li mng-menuitem [item]=\"item\" [root]=\"true\"></li>\n }\n @if (item.separator) {\n <li class=\"menu-separator\"></li>\n }\n }\n</ul>\n" }]
632
698
  }], ctorParameters: () => [] });
633
699
 
634
700
  class SidebarComponent {
635
701
  constructor() {
636
702
  this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
637
- this.commons = inject(CommonsService);
638
- this.layoutService = inject(MainLayoutComponentService);
703
+ this.layout = inject(LayoutService);
639
704
  this.el = inject(ElementRef);
640
705
  this.menuComponent = signal(this.config?.components?.menu === false ? undefined : this.config?.components?.menu ?? MenuComponent);
641
706
  this.timeout = null;
642
707
  }
643
708
  onMouseEnter() {
644
- if (!this.layoutService.state().anchored) {
709
+ if (!this.layout.state().anchored) {
645
710
  if (this.timeout) {
646
711
  clearTimeout(this.timeout);
647
712
  this.timeout = null;
648
713
  }
649
- this.layoutService.state.update(state => ({
714
+ this.layout.state.update(state => ({
650
715
  ...state,
651
716
  sidebarActive: true
652
717
  }));
653
718
  }
654
719
  }
655
720
  onMouseLeave() {
656
- if (!this.layoutService.state().anchored) {
721
+ if (!this.layout.state().anchored) {
657
722
  if (!this.timeout) {
658
- this.timeout = setTimeout(() => this.layoutService.state.update(state => ({
723
+ this.timeout = setTimeout(() => this.layout.state.update(state => ({
659
724
  ...state,
660
725
  sidebarActive: false
661
726
  })), 300);
@@ -663,25 +728,99 @@ class SidebarComponent {
663
728
  }
664
729
  }
665
730
  anchor() {
666
- this.layoutService.state.update(state => ({
731
+ this.layout.state.update(state => ({
667
732
  ...state,
668
733
  anchored: !state.anchored
669
734
  }));
670
735
  }
671
736
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
672
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: SidebarComponent, isStandalone: true, selector: "mng-sidebar", ngImport: i0, template: "<div class=\"layout-sidebar\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\n <div class=\"sidebar-header\">\n <a [routerLink]=\"['/']\" class=\"app-logo\">\n <div class=\"app-logo-small h-2rem\">\n <img [src]=\"commons.appLogo()\" [alt]=\"'App logo'\" />\n </div>\n <div class=\"app-logo-normal\">\n <img class=\"h-2rem\" [src]=\"commons.appLogo()\" [alt]=\"'App logo'\" />\n <img class=\"h-2rem ml-3\" [src]=\"commons.appLogoName()\" [alt]=\"'App name'\" />\n </div>\n </a>\n <button class=\"layout-sidebar-anchor p-link z-2\" type=\"button\" (click)=\"anchor()\"></button>\n </div>\n\n @if (menuComponent()) {\n <div #menuContainer class=\"layout-menu-container\">\n <div [mngComponent]=\"menuComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
737
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: SidebarComponent, isStandalone: true, selector: "mng-sidebar", ngImport: i0, template: "<div class=\"layout-sidebar\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\n <div class=\"sidebar-header\">\n <a [routerLink]=\"['/']\" class=\"app-logo\">\n <div class=\"app-logo-small h-2rem\">\n <img [src]=\"layout.appLogo()\" [alt]=\"'App logo'\" />\n </div>\n <div class=\"app-logo-normal\">\n <img class=\"h-2rem\" [src]=\"layout.appLogo()\" [alt]=\"'App logo'\" />\n <img class=\"h-2rem ml-3\" [src]=\"layout.appLogoName()\" [alt]=\"'App name'\" />\n </div>\n </a>\n <button class=\"layout-sidebar-anchor p-link z-2\" type=\"button\" (click)=\"anchor()\"></button>\n </div>\n\n @if (menuComponent()) {\n <div #menuContainer class=\"layout-menu-container\">\n <div [mngComponent]=\"menuComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
673
738
  }
674
739
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: SidebarComponent, decorators: [{
675
740
  type: Component,
676
- args: [{ standalone: true, selector: 'mng-sidebar', imports: [RouterModule, MenuComponent, ComponentDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"layout-sidebar\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\n <div class=\"sidebar-header\">\n <a [routerLink]=\"['/']\" class=\"app-logo\">\n <div class=\"app-logo-small h-2rem\">\n <img [src]=\"commons.appLogo()\" [alt]=\"'App logo'\" />\n </div>\n <div class=\"app-logo-normal\">\n <img class=\"h-2rem\" [src]=\"commons.appLogo()\" [alt]=\"'App logo'\" />\n <img class=\"h-2rem ml-3\" [src]=\"commons.appLogoName()\" [alt]=\"'App name'\" />\n </div>\n </a>\n <button class=\"layout-sidebar-anchor p-link z-2\" type=\"button\" (click)=\"anchor()\"></button>\n </div>\n\n @if (menuComponent()) {\n <div #menuContainer class=\"layout-menu-container\">\n <div [mngComponent]=\"menuComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n</div>\n" }]
741
+ args: [{ standalone: true, selector: 'mng-sidebar', imports: [RouterModule, MenuComponent, ComponentDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"layout-sidebar\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\n <div class=\"sidebar-header\">\n <a [routerLink]=\"['/']\" class=\"app-logo\">\n <div class=\"app-logo-small h-2rem\">\n <img [src]=\"layout.appLogo()\" [alt]=\"'App logo'\" />\n </div>\n <div class=\"app-logo-normal\">\n <img class=\"h-2rem\" [src]=\"layout.appLogo()\" [alt]=\"'App logo'\" />\n <img class=\"h-2rem ml-3\" [src]=\"layout.appLogoName()\" [alt]=\"'App name'\" />\n </div>\n </a>\n <button class=\"layout-sidebar-anchor p-link z-2\" type=\"button\" (click)=\"anchor()\"></button>\n </div>\n\n @if (menuComponent()) {\n <div #menuContainer class=\"layout-menu-container\">\n <div [mngComponent]=\"menuComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n</div>\n" }]
677
742
  }] });
678
743
 
744
+ const defaultColorSchemeOpts = [
745
+ {
746
+ value: 'auto',
747
+ label: 'system'
748
+ },
749
+ {
750
+ value: 'light',
751
+ label: 'light'
752
+ },
753
+ {
754
+ value: 'dark',
755
+ label: 'dark'
756
+ }
757
+ ];
758
+ class SettingsComponent {
759
+ constructor() {
760
+ this.document = inject(DOCUMENT);
761
+ this.dynamicDialogConfig = inject(DynamicDialogConfig);
762
+ this.dynamicDialogRef = inject(DynamicDialogRef);
763
+ this.colorSchemeOptions = signal(defaultColorSchemeOpts);
764
+ this.injector = this.dynamicDialogConfig.data.injector;
765
+ this.translate = this.injector.get(TranslateService);
766
+ this.commons = this.injector.get(CommonsService);
767
+ this.layout = this.injector.get(LayoutService);
768
+ this.menuModes = this.layout.menuModes;
769
+ this.translate
770
+ .stream('mngSettings.title')
771
+ .pipe(takeUntilDestroyed())
772
+ .subscribe(t => {
773
+ setTimeout(() => (this.dynamicDialogConfig.header = t));
774
+ });
775
+ const translateKey = 'mngSettings.colorScheme.options';
776
+ this.translate
777
+ .stream('mngSettings.colorScheme.options')
778
+ .pipe(takeUntilDestroyed())
779
+ .subscribe(t => {
780
+ if (t === translateKey) {
781
+ this.colorSchemeOptions.set(defaultColorSchemeOpts);
782
+ }
783
+ else {
784
+ this.colorSchemeOptions.update(options => options.map(o => ({
785
+ value: o.value,
786
+ label: `${t[o.value]}`
787
+ })));
788
+ }
789
+ });
790
+ }
791
+ switchLocale(language) {
792
+ this.commons.setAppLocale(language);
793
+ }
794
+ switchDataLocale(language) {
795
+ this.commons.setAppDataLocale(language);
796
+ }
797
+ onMenuModeChange(mode) {
798
+ this.layout.onMenuModeChange(mode);
799
+ }
800
+ onColorSchemeChange(scheme) {
801
+ this.layout.setColorScheme(scheme);
802
+ }
803
+ closeDialog() {
804
+ this.dynamicDialogRef.close();
805
+ }
806
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: SettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
807
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: SettingsComponent, isStandalone: true, selector: "mng-settings", ngImport: i0, template: "<div class=\"h-full flex flex-column\">\n <div class=\"flex-grow-1 mng-action-editor-form-container\">\n @if (commons.appLocales().length > 1 || commons.appDataLocales().length > 1) {\n <h5>{{ 'mngSettings.locales' | translate }}</h5>\n <div class=\"formgrid grid\">\n @if (commons.appLocales().length > 1) {\n <div class=\"field pr-4\">\n <i class=\"pi pi-fw pi-globe\"></i>\n <p-dropdown [ngModel]=\"commons.appLocale()\" [options]=\"commons.appLocales()\" (onChange)=\"switchLocale($event.value)\"></p-dropdown>\n </div>\n }\n @if (commons.appDataLocales().length > 1) {\n <div class=\"field pr-4\">\n <i class=\"pi pi-fw pi-database\"></i>\n <p-dropdown [ngModel]=\"commons.appDataLocale()\" [options]=\"commons.appDataLocales()\" (onChange)=\"switchDataLocale($event.value)\"></p-dropdown>\n </div>\n }\n </div>\n }\n\n <h5>{{ 'mngSettings.colorScheme.title' | translate }}</h5>\n <div class=\"formgrid grid\">\n <p-selectButton\n [options]=\"colorSchemeOptions()\"\n [ngModel]=\"layout.colorSchemeSetting()\"\n (ngModelChange)=\"onColorSchemeChange($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n allowEmpty=\"false\" />\n </div>\n\n @if (menuModes.length > 1) {\n <h5>{{ 'mngSettings.menuMode.title' | translate }}</h5>\n <div class=\"formgrid grid\">\n @for (mode of menuModes; track mode) {\n <div class=\"field-radiobutton col-6 md:col-4\">\n <p-radioButton name=\"category\" [value]=\"mode\" [ngModel]=\"layout.menuMode()\" (ngModelChange)=\"onMenuModeChange(mode)\" />\n <label [for]=\"mode\" class=\"ml-2\">\n {{ 'mngSettings.menuMode.' + mode | translate }}\n </label>\n </div>\n }\n </div>\n }\n\n <div class=\"flex flex-row justify-content-between mng-action-editor-footer-container\">\n <div></div>\n <div>\n <p-button (onClick)=\"closeDialog()\" [label]=\"'general.close' | translate\" icon=\"pi pi-times\" styleClass=\"p-button-primary p-button-text\" />\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i2$1.RadioButton, selector: "p-radioButton", inputs: ["value", "formControlName", "name", "disabled", "label", "variant", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "style", "styleClass", "labelStyleClass", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i4.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputSwitchModule }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i5.SelectButton, selector: "p-selectButton", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "style", "styleClass", "ariaLabelledBy", "disabled", "dataKey", "autofocus"], outputs: ["onOptionClick", "onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
808
+ }
809
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: SettingsComponent, decorators: [{
810
+ type: Component,
811
+ args: [{ standalone: true, selector: 'mng-settings', imports: [TranslateModule, RadioButtonModule, FormsModule, Button, DropdownModule, InputSwitchModule, SelectButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"h-full flex flex-column\">\n <div class=\"flex-grow-1 mng-action-editor-form-container\">\n @if (commons.appLocales().length > 1 || commons.appDataLocales().length > 1) {\n <h5>{{ 'mngSettings.locales' | translate }}</h5>\n <div class=\"formgrid grid\">\n @if (commons.appLocales().length > 1) {\n <div class=\"field pr-4\">\n <i class=\"pi pi-fw pi-globe\"></i>\n <p-dropdown [ngModel]=\"commons.appLocale()\" [options]=\"commons.appLocales()\" (onChange)=\"switchLocale($event.value)\"></p-dropdown>\n </div>\n }\n @if (commons.appDataLocales().length > 1) {\n <div class=\"field pr-4\">\n <i class=\"pi pi-fw pi-database\"></i>\n <p-dropdown [ngModel]=\"commons.appDataLocale()\" [options]=\"commons.appDataLocales()\" (onChange)=\"switchDataLocale($event.value)\"></p-dropdown>\n </div>\n }\n </div>\n }\n\n <h5>{{ 'mngSettings.colorScheme.title' | translate }}</h5>\n <div class=\"formgrid grid\">\n <p-selectButton\n [options]=\"colorSchemeOptions()\"\n [ngModel]=\"layout.colorSchemeSetting()\"\n (ngModelChange)=\"onColorSchemeChange($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n allowEmpty=\"false\" />\n </div>\n\n @if (menuModes.length > 1) {\n <h5>{{ 'mngSettings.menuMode.title' | translate }}</h5>\n <div class=\"formgrid grid\">\n @for (mode of menuModes; track mode) {\n <div class=\"field-radiobutton col-6 md:col-4\">\n <p-radioButton name=\"category\" [value]=\"mode\" [ngModel]=\"layout.menuMode()\" (ngModelChange)=\"onMenuModeChange(mode)\" />\n <label [for]=\"mode\" class=\"ml-2\">\n {{ 'mngSettings.menuMode.' + mode | translate }}\n </label>\n </div>\n }\n </div>\n }\n\n <div class=\"flex flex-row justify-content-between mng-action-editor-footer-container\">\n <div></div>\n <div>\n <p-button (onClick)=\"closeDialog()\" [label]=\"'general.close' | translate\" icon=\"pi pi-times\" styleClass=\"p-button-primary p-button-text\" />\n </div>\n </div>\n </div>\n</div>\n" }]
812
+ }], ctorParameters: () => [] });
813
+
679
814
  class TopbarUserComponent {
680
815
  constructor() {
816
+ this.injector = inject(Injector);
817
+ this.dialogService = inject(DialogService);
681
818
  this.commons = inject(CommonsService);
682
819
  this.hrefJsVoid = inject(DomSanitizer).bypassSecurityTrustUrl('javascript:void(0)');
820
+ this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
683
821
  this.user = computed(() => this.commons.user());
684
822
  this.userRoles = computed(() => this.commons.userRoles());
823
+ this.settingsDisabled = signal(this.config?.components?.settings === false);
685
824
  }
686
825
  logout(user, event) {
687
826
  if (typeof user?.logout === 'function') {
@@ -690,31 +829,43 @@ class TopbarUserComponent {
690
829
  user.logout();
691
830
  }
692
831
  }
832
+ openSettings() {
833
+ if (this.config?.components?.settings === false) {
834
+ return;
835
+ }
836
+ this.dialogService.open(this.config?.components?.settings ?? SettingsComponent, {
837
+ modal: true,
838
+ styleClass: 'mng-dialog mng-action-editor-dialog mng-dialog-xs',
839
+ data: {
840
+ injector: this.injector
841
+ }
842
+ });
843
+ }
693
844
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TopbarUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
694
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: TopbarUserComponent, isStandalone: true, selector: "mng-topbar-user-component", ngImport: i0, template: "<a\n class=\"cursor-pointer lg:pr-4\"\n pStyleClass=\"@next\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\"\n [hideOnOutsideClick]=\"true\"\n pRipple>\n <i class=\"pi pi-fw pi-user text-2xl\"></i>\n <span class=\"hidden sm:inline-block\">&nbsp; {{ user()?.displayName ?? user()?.username }}</span>\n</a>\n<ul class=\"topbar-menu active-topbar-menu w-15rem z-5 ng-hidden border-round\">\n <li role=\"menuitem\">\n <a\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-user text-base mr-2\"></i>\n <div>\n <strong>{{ user()?.displayName ?? user()?.username }}</strong>\n @if (userRoles().length > 0) {\n <small>\n <br />\n {{ userRoles() }}\n </small>\n }\n </div>\n </a>\n </li>\n @if (user()?.logout || user()?.logoutUrl) {\n <li role=\"menuitem\">\n <a\n [href]=\"user()?.logoutUrl ?? hrefJsVoid\"\n (click)=\"logout(user(), $event)\"\n class=\"flex align-items-center hover:text-primary-500 transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-sign-out text-base mr-2\"></i>\n <span>{{ 'mngTopbar.logout' | translate }}</span>\n </a>\n </li>\n }\n</ul>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i1$2.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
845
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: TopbarUserComponent, isStandalone: true, selector: "mng-topbar-user-component", ngImport: i0, template: "<a\n class=\"cursor-pointer lg:pr-4\"\n pStyleClass=\"@next\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\"\n [hideOnOutsideClick]=\"true\"\n pRipple>\n <i class=\"pi pi-fw pi-user text-2xl\"></i>\n <span class=\"hidden sm:inline-block\">&nbsp; {{ user()?.displayName ?? user()?.username }}</span>\n</a>\n<ul class=\"topbar-menu active-topbar-menu w-15rem z-5 ng-hidden border-round\">\n <li role=\"menuitem\">\n <a\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-user text-base mr-2\"></i>\n <div>\n <strong>{{ user()?.displayName ?? user()?.username }}</strong>\n @if (userRoles().length > 0) {\n <small>\n <br />\n {{ userRoles() }}\n </small>\n }\n </div>\n </a>\n </li>\n @if (!settingsDisabled()) {\n <li role=\"menuitem\">\n <a\n [href]=\"hrefJsVoid\"\n (click)=\"openSettings()\"\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-cog text-base mr-2\"></i>\n {{ 'mngSettings.title' | translate }}\n </a>\n </li>\n }\n @if (user()?.logout || user()?.logoutUrl) {\n <li role=\"menuitem\">\n <a\n [href]=\"user()?.logoutUrl ?? hrefJsVoid\"\n (click)=\"logout(user(), $event)\"\n class=\"flex align-items-center hover:text-primary-500 transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-sign-out text-base mr-2\"></i>\n <span>{{ 'mngTopbar.logout' | translate }}</span>\n </a>\n </li>\n }\n</ul>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i1$3.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
695
846
  }
696
847
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TopbarUserComponent, decorators: [{
697
848
  type: Component,
698
- args: [{ standalone: true, selector: 'mng-topbar-user-component', imports: [AsyncPipe, EnumerateAsyncPipe, TranslateModule, RippleModule, StyleClassModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a\n class=\"cursor-pointer lg:pr-4\"\n pStyleClass=\"@next\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\"\n [hideOnOutsideClick]=\"true\"\n pRipple>\n <i class=\"pi pi-fw pi-user text-2xl\"></i>\n <span class=\"hidden sm:inline-block\">&nbsp; {{ user()?.displayName ?? user()?.username }}</span>\n</a>\n<ul class=\"topbar-menu active-topbar-menu w-15rem z-5 ng-hidden border-round\">\n <li role=\"menuitem\">\n <a\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-user text-base mr-2\"></i>\n <div>\n <strong>{{ user()?.displayName ?? user()?.username }}</strong>\n @if (userRoles().length > 0) {\n <small>\n <br />\n {{ userRoles() }}\n </small>\n }\n </div>\n </a>\n </li>\n @if (user()?.logout || user()?.logoutUrl) {\n <li role=\"menuitem\">\n <a\n [href]=\"user()?.logoutUrl ?? hrefJsVoid\"\n (click)=\"logout(user(), $event)\"\n class=\"flex align-items-center hover:text-primary-500 transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-sign-out text-base mr-2\"></i>\n <span>{{ 'mngTopbar.logout' | translate }}</span>\n </a>\n </li>\n }\n</ul>\n" }]
849
+ args: [{ standalone: true, selector: 'mng-topbar-user-component', imports: [AsyncPipe, EnumerateAsyncPipe, TranslateModule, RippleModule, StyleClassModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a\n class=\"cursor-pointer lg:pr-4\"\n pStyleClass=\"@next\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\"\n [hideOnOutsideClick]=\"true\"\n pRipple>\n <i class=\"pi pi-fw pi-user text-2xl\"></i>\n <span class=\"hidden sm:inline-block\">&nbsp; {{ user()?.displayName ?? user()?.username }}</span>\n</a>\n<ul class=\"topbar-menu active-topbar-menu w-15rem z-5 ng-hidden border-round\">\n <li role=\"menuitem\">\n <a\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-user text-base mr-2\"></i>\n <div>\n <strong>{{ user()?.displayName ?? user()?.username }}</strong>\n @if (userRoles().length > 0) {\n <small>\n <br />\n {{ userRoles() }}\n </small>\n }\n </div>\n </a>\n </li>\n @if (!settingsDisabled()) {\n <li role=\"menuitem\">\n <a\n [href]=\"hrefJsVoid\"\n (click)=\"openSettings()\"\n class=\"flex align-items-center transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-cog text-base mr-2\"></i>\n {{ 'mngSettings.title' | translate }}\n </a>\n </li>\n }\n @if (user()?.logout || user()?.logoutUrl) {\n <li role=\"menuitem\">\n <a\n [href]=\"user()?.logoutUrl ?? hrefJsVoid\"\n (click)=\"logout(user(), $event)\"\n class=\"flex align-items-center hover:text-primary-500 transition-duration-200\"\n pStyleClass=\"@grandparent\"\n enterFromClass=\"ng-hidden\"\n enterActiveClass=\"px-scalein\"\n leaveToClass=\"ng-hidden\"\n leaveActiveClass=\"px-fadeout\">\n <i class=\"pi pi-fw pi-sign-out text-base mr-2\"></i>\n <span>{{ 'mngTopbar.logout' | translate }}</span>\n </a>\n </li>\n }\n</ul>\n" }]
699
850
  }] });
700
851
 
701
852
  class TopbarComponent {
702
853
  constructor() {
703
854
  this.el = inject(ElementRef);
704
855
  this.commons = inject(CommonsService);
705
- this.mainLayoutService = inject(MainLayoutComponentService);
856
+ this.layout = inject(LayoutService);
706
857
  this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
707
858
  this.topbarUserComponent = signal(this.config?.components?.topbarUser === false ? undefined : this.config?.components?.topbarUser ?? TopbarUserComponent);
708
859
  this.breadcrumbComponent = signal(this.config?.components?.breadcrumb === false ? undefined : this.config?.components?.breadcrumb ?? BreadcrumbComponent);
709
860
  }
710
861
  onMenuButtonClick() {
711
- this.mainLayoutService.onMenuToggle();
862
+ this.layout.onMenuToggle();
712
863
  }
713
864
  switchLocale(language) {
714
865
  this.commons.setAppLocale(language);
715
866
  }
716
867
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TopbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
717
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: TopbarComponent, isStandalone: true, selector: "mng-topbar", ngImport: i0, template: "<div class=\"layout-topbar\">\n <div class=\"topbar-start\">\n <button #menubutton type=\"button\" class=\"topbar-menubutton p-link p-trigger\" (click)=\"onMenuButtonClick()\">\n <i class=\"pi pi-bars\"></i>\n </button>\n\n @if (breadcrumbComponent()) {\n <div class=\"topbar-breadcrumb\">\n <div [mngComponent]=\"breadcrumbComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n </div>\n <div class=\"layout-topbar-menu-section\">\n <mng-sidebar></mng-sidebar>\n </div>\n <div class=\"topbar-end\">\n <ul class=\"topbar-menu\">\n @if (commons.appLocales().length > 1) {\n <li class=\"profile-item\">\n <i class=\"pi pi-fw pi-globe\"></i>\n <p-dropdown [ngModel]=\"commons.appLocale()\" [options]=\"commons.appLocales()\" (onChange)=\"switchLocale($event.value)\"></p-dropdown>\n </li>\n }\n @if (topbarUserComponent()) {\n <li #userMenuItem class=\"profile-item topbar-item mr-3\" [mngComponent]=\"topbarUserComponent()\" [attachToHost]=\"true\"></li>\n }\n </ul>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: SidebarComponent, selector: "mng-sidebar" }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: StyleClassModule }, { kind: "ngmodule", type: RippleModule }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i1$4.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
868
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: TopbarComponent, isStandalone: true, selector: "mng-topbar", ngImport: i0, template: "<div class=\"layout-topbar\">\n <div class=\"topbar-start\">\n <button #menubutton type=\"button\" class=\"topbar-menubutton p-link p-trigger\" (click)=\"onMenuButtonClick()\">\n <i class=\"pi pi-bars\"></i>\n </button>\n\n @if (breadcrumbComponent()) {\n <div class=\"topbar-breadcrumb\">\n <div [mngComponent]=\"breadcrumbComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n </div>\n <div class=\"layout-topbar-menu-section\">\n <mng-sidebar></mng-sidebar>\n </div>\n <div class=\"topbar-end\">\n <ul class=\"topbar-menu\">\n @if (commons.appLocales().length > 1) {\n <li class=\"profile-item\">\n <i class=\"pi pi-fw pi-globe\"></i>\n <p-dropdown [ngModel]=\"commons.appLocale()\" [options]=\"commons.appLocales()\" (onChange)=\"switchLocale($event.value)\"></p-dropdown>\n </li>\n }\n @if (topbarUserComponent()) {\n <li #userMenuItem class=\"profile-item topbar-item mr-3\" [mngComponent]=\"topbarUserComponent()\" [attachToHost]=\"true\"></li>\n }\n </ul>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: SidebarComponent, selector: "mng-sidebar" }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: StyleClassModule }, { kind: "ngmodule", type: RippleModule }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i4.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
718
869
  }
719
870
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: TopbarComponent, decorators: [{
720
871
  type: Component,
@@ -723,20 +874,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImpor
723
874
 
724
875
  class MainLayoutComponent {
725
876
  constructor() {
726
- this.commonsService = inject(CommonsService);
877
+ // private readonly commonsService = inject(CommonsService);
727
878
  this.config = inject(COMMONS_LAYOUT_FEATURE_CONFIG_IT, { optional: true });
728
- this.layoutService = inject(MainLayoutComponentService);
879
+ this.layout = inject(LayoutService);
729
880
  this.menuService = inject(MenuService);
730
881
  this.renderer = inject(Renderer2);
731
882
  this.appTopbar = viewChild('topbarCmp');
732
- this.colorScheme = computed(() => this.commonsService.colorScheme() ?? 'light');
733
- this.menuMode = signal(this.config?.menuMode ?? 'static');
734
883
  this.ripple = signal(this.config?.ripple ?? true);
735
884
  this.topbarComponent = signal(this.config?.components?.topbar === false ? undefined : this.config?.components?.topbar ?? TopbarComponent);
736
885
  this.breadcrumbsComponent = signal(this.config?.components?.breadcrumb === false ? undefined : this.config?.components?.breadcrumb ?? BreadcrumbComponent);
737
886
  this.footerComponent = signal(this.config?.components?.footer === false ? undefined : this.config?.components?.footer ?? FooterComponent);
738
887
  this.useNotificationWrapper = signal(!this.config?.disableNotificationWrapper);
739
- this.layoutService.overlayOpen$.pipe(takeUntilDestroyed()).subscribe(() => {
888
+ this.layout.overlayOpen$.pipe(takeUntilDestroyed()).subscribe(() => {
740
889
  if (!this.menuOutsideClickListener) {
741
890
  this.menuOutsideClickListener = this.renderer.listen('document', 'click', event => {
742
891
  const isOutsideClicked = !(this.appTopbar()?.nativeElement.isSameNode(event.target) || this.appTopbar()?.nativeElement.contains(event.target));
@@ -745,7 +894,7 @@ class MainLayoutComponent {
745
894
  }
746
895
  });
747
896
  }
748
- if (this.layoutService.state().staticMenuMobileActive) {
897
+ if (this.layout.state().staticMenuMobileActive) {
749
898
  this.blockBodyScroll();
750
899
  }
751
900
  });
@@ -767,7 +916,7 @@ class MainLayoutComponent {
767
916
  }
768
917
  }
769
918
  hideMenu() {
770
- this.layoutService.state.update(state => ({
919
+ this.layout.state.update(state => ({
771
920
  ...state,
772
921
  overlayMenuActive: false,
773
922
  staticMenuMobileActive: false,
@@ -786,11 +935,11 @@ class MainLayoutComponent {
786
935
  }
787
936
  }
788
937
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MainLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
789
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MainLayoutComponent, isStandalone: true, selector: "mng-main-layout", providers: [MainLayoutComponentService], viewQueries: [{ propertyName: "appTopbar", first: true, predicate: ["topbarCmp"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (useNotificationWrapper()) {\n <mng-notification-wrapper>\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n </mng-notification-wrapper>\n} @else {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n}\n\n<ng-template #content>\n <div\n class=\"layout-container\"\n [ngClass]=\"{\n 'layout-light': colorScheme() === 'light',\n 'layout-dark': colorScheme() === 'dark',\n 'layout-overlay': menuMode() === 'overlay',\n 'layout-static': menuMode() === 'static',\n 'layout-reveal': menuMode() === 'reveal',\n 'layout-drawer': menuMode() === 'drawer',\n 'layout-slim': menuMode() === 'slim',\n 'layout-slim-plus': menuMode() === 'slim-plus',\n 'layout-static-inactive': layoutService.state().staticMenuDesktopInactive && menuMode() === 'static',\n 'layout-overlay-active': layoutService.state().overlayMenuActive,\n 'layout-mobile-active': layoutService.state().staticMenuMobileActive,\n 'p-ripple-disabled': !ripple(),\n 'layout-sidebar-active': layoutService.state().sidebarActive,\n 'layout-sidebar-anchored': layoutService.state().anchored\n }\">\n <div class=\"layout-content-wrapper\">\n @if (topbarComponent()) {\n <div #topbarCmp class=\"layout-topbar-wrapper\" [mngComponent]=\"topbarComponent()\" [attachToHost]=\"true\"></div>\n }\n @if (breadcrumbsComponent()) {\n <div class=\"content-breadcrumb\">\n <div [mngComponent]=\"breadcrumbsComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n <div class=\"layout-content\">\n <router-outlet></router-outlet>\n </div>\n <div class=\"layout-mask\"></div>\n @if (footerComponent()) {\n <div [mngComponent]=\"footerComponent()\" [attachToHost]=\"true\"></div>\n }\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "component", type: NotificationWrapperComponent, selector: "mng-notification-wrapper" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
938
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: MainLayoutComponent, isStandalone: true, selector: "mng-main-layout", viewQueries: [{ propertyName: "appTopbar", first: true, predicate: ["topbarCmp"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (useNotificationWrapper()) {\n <mng-notification-wrapper>\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n </mng-notification-wrapper>\n} @else {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n}\n\n<ng-template #content>\n <div\n class=\"layout-container\"\n [ngClass]=\"{\n 'layout-light': layout.colorScheme() === 'light',\n 'layout-dark': layout.colorScheme() === 'dark',\n 'layout-overlay': layout.menuMode() === 'overlay',\n 'layout-static': layout.menuMode() === 'static',\n 'layout-reveal': layout.menuMode() === 'reveal',\n 'layout-drawer': layout.menuMode() === 'drawer',\n 'layout-slim': layout.menuMode() === 'slim',\n 'layout-slim-plus': layout.menuMode() === 'slim-plus',\n 'layout-static-inactive': layout.state().staticMenuDesktopInactive && layout.menuMode() === 'static',\n 'layout-overlay-active': layout.state().overlayMenuActive,\n 'layout-mobile-active': layout.state().staticMenuMobileActive,\n 'p-ripple-disabled': !ripple(),\n 'layout-sidebar-active': layout.state().sidebarActive,\n 'layout-sidebar-anchored': layout.state().anchored\n }\">\n <div class=\"layout-content-wrapper\">\n @if (topbarComponent()) {\n <div #topbarCmp class=\"layout-topbar-wrapper\" [mngComponent]=\"topbarComponent()\" [attachToHost]=\"true\"></div>\n }\n @if (breadcrumbsComponent()) {\n <div class=\"content-breadcrumb\">\n <div [mngComponent]=\"breadcrumbsComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n <div class=\"layout-content\">\n <router-outlet></router-outlet>\n </div>\n <div class=\"layout-mask\"></div>\n @if (footerComponent()) {\n <div [mngComponent]=\"footerComponent()\" [attachToHost]=\"true\"></div>\n }\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ComponentDirective, selector: "[mngComponent]", inputs: ["mngComponent", "injectionToken", "inputs", "attachToHost", "parentInjector"], outputs: ["instanceCreated"] }, { kind: "component", type: NotificationWrapperComponent, selector: "mng-notification-wrapper" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
790
939
  }
791
940
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: MainLayoutComponent, decorators: [{
792
941
  type: Component,
793
- args: [{ standalone: true, selector: 'mng-main-layout', imports: [NgClass, RouterModule, TopbarComponent, BreadcrumbComponent, ComponentDirective, AsyncPipe, NotificationWrapperComponent, NgTemplateOutlet], providers: [MainLayoutComponentService], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (useNotificationWrapper()) {\n <mng-notification-wrapper>\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n </mng-notification-wrapper>\n} @else {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n}\n\n<ng-template #content>\n <div\n class=\"layout-container\"\n [ngClass]=\"{\n 'layout-light': colorScheme() === 'light',\n 'layout-dark': colorScheme() === 'dark',\n 'layout-overlay': menuMode() === 'overlay',\n 'layout-static': menuMode() === 'static',\n 'layout-reveal': menuMode() === 'reveal',\n 'layout-drawer': menuMode() === 'drawer',\n 'layout-slim': menuMode() === 'slim',\n 'layout-slim-plus': menuMode() === 'slim-plus',\n 'layout-static-inactive': layoutService.state().staticMenuDesktopInactive && menuMode() === 'static',\n 'layout-overlay-active': layoutService.state().overlayMenuActive,\n 'layout-mobile-active': layoutService.state().staticMenuMobileActive,\n 'p-ripple-disabled': !ripple(),\n 'layout-sidebar-active': layoutService.state().sidebarActive,\n 'layout-sidebar-anchored': layoutService.state().anchored\n }\">\n <div class=\"layout-content-wrapper\">\n @if (topbarComponent()) {\n <div #topbarCmp class=\"layout-topbar-wrapper\" [mngComponent]=\"topbarComponent()\" [attachToHost]=\"true\"></div>\n }\n @if (breadcrumbsComponent()) {\n <div class=\"content-breadcrumb\">\n <div [mngComponent]=\"breadcrumbsComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n <div class=\"layout-content\">\n <router-outlet></router-outlet>\n </div>\n <div class=\"layout-mask\"></div>\n @if (footerComponent()) {\n <div [mngComponent]=\"footerComponent()\" [attachToHost]=\"true\"></div>\n }\n </div>\n </div>\n</ng-template>\n" }]
942
+ args: [{ standalone: true, selector: 'mng-main-layout', imports: [NgClass, RouterModule, TopbarComponent, BreadcrumbComponent, ComponentDirective, AsyncPipe, NotificationWrapperComponent, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (useNotificationWrapper()) {\n <mng-notification-wrapper>\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n </mng-notification-wrapper>\n} @else {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n}\n\n<ng-template #content>\n <div\n class=\"layout-container\"\n [ngClass]=\"{\n 'layout-light': layout.colorScheme() === 'light',\n 'layout-dark': layout.colorScheme() === 'dark',\n 'layout-overlay': layout.menuMode() === 'overlay',\n 'layout-static': layout.menuMode() === 'static',\n 'layout-reveal': layout.menuMode() === 'reveal',\n 'layout-drawer': layout.menuMode() === 'drawer',\n 'layout-slim': layout.menuMode() === 'slim',\n 'layout-slim-plus': layout.menuMode() === 'slim-plus',\n 'layout-static-inactive': layout.state().staticMenuDesktopInactive && layout.menuMode() === 'static',\n 'layout-overlay-active': layout.state().overlayMenuActive,\n 'layout-mobile-active': layout.state().staticMenuMobileActive,\n 'p-ripple-disabled': !ripple(),\n 'layout-sidebar-active': layout.state().sidebarActive,\n 'layout-sidebar-anchored': layout.state().anchored\n }\">\n <div class=\"layout-content-wrapper\">\n @if (topbarComponent()) {\n <div #topbarCmp class=\"layout-topbar-wrapper\" [mngComponent]=\"topbarComponent()\" [attachToHost]=\"true\"></div>\n }\n @if (breadcrumbsComponent()) {\n <div class=\"content-breadcrumb\">\n <div [mngComponent]=\"breadcrumbsComponent()\" [attachToHost]=\"true\"></div>\n </div>\n }\n <div class=\"layout-content\">\n <router-outlet></router-outlet>\n </div>\n <div class=\"layout-mask\"></div>\n @if (footerComponent()) {\n <div [mngComponent]=\"footerComponent()\" [attachToHost]=\"true\"></div>\n }\n </div>\n </div>\n</ng-template>\n" }]
794
943
  }], ctorParameters: () => [] });
795
944
 
796
945
  /**
@@ -814,6 +963,7 @@ function withLayout(config) {
814
963
  providers: [
815
964
  MenuService,
816
965
  VersionService,
966
+ LayoutService,
817
967
  {
818
968
  provide: COMMONS_LAYOUT_FEATURE_CONFIG_IT,
819
969
  useValue: config
@@ -828,5 +978,5 @@ function withLayout(config) {
828
978
  * Generated bundle index. Do not edit.
829
979
  */
830
980
 
831
- export { BreadcrumbComponent, COMMONS_LAYOUT_FEATURE_CONFIG_IT, FooterComponent, MainLayoutComponent, MainLayoutComponentService, MenuComponent, MenuItemComponent, MenuService, SidebarComponent, TopbarComponent, TopbarUserComponent, VersionComponent, VersionService, createLayoutRoute, withLayout };
981
+ export { BreadcrumbComponent, COMMONS_LAYOUT_FEATURE_CONFIG_IT, ErrorPageComponent, FooterComponent, LayoutService, MainLayoutComponent, MenuComponent, MenuItemComponent, MenuService, NotFoundPageComponent, SettingsComponent, SidebarComponent, TopbarComponent, TopbarUserComponent, VersionComponent, VersionService, createLayoutRoute, withLayout };
832
982
  //# sourceMappingURL=mediusinc-mng-commons-layout.mjs.map