@es.framework/ng.ui.theme 2.0.59 → 2.0.60

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.
@@ -4,12 +4,12 @@ import { Subject, Observable, lastValueFrom, BehaviorSubject, map, filter } from
4
4
  import * as i3$3 from '@es.framework/ng.core/services';
5
5
  import { ConfigStateService, SessionStateService, LocalizationService, LocalStorageService, NavItemsService, UserMenuService, RoutesService, SubscriptionService, ReplaceableComponentsService } from '@es.framework/ng.core/services';
6
6
  import { eLayoutType } from '@es.framework/ng.core/models';
7
- import * as i2$2 from '@angular/router';
7
+ import * as i2$1 from '@angular/router';
8
8
  import { Router, RouterModule, RouterOutlet, NavigationEnd } from '@angular/router';
9
9
  import * as i1$1 from '@angular/common';
10
10
  import { isPlatformBrowser, CommonModule } from '@angular/common';
11
11
  import { StyleClassModule } from 'primeng/styleclass';
12
- import * as i3$1 from 'primeng/avatar';
12
+ import * as i3$2 from 'primeng/avatar';
13
13
  import { AvatarModule } from 'primeng/avatar';
14
14
  import * as i5 from 'primeng/menu';
15
15
  import { MenuModule } from 'primeng/menu';
@@ -19,7 +19,7 @@ import { OverlayModule } from 'primeng/overlay';
19
19
  import { VisibleDirective, HasPermissionDirective, ReplaceableTemplateDirective } from '@es.framework/ng.core/directives';
20
20
  import { TranslatePipe, ToInjectorPipe } from '@es.framework/ng.core/pipes';
21
21
  import { toSignal } from '@angular/core/rxjs-interop';
22
- import * as i2$1 from '@angular/forms';
22
+ import * as i3 from '@angular/forms';
23
23
  import { FormsModule } from '@angular/forms';
24
24
  import { SelectModule } from 'primeng/select';
25
25
  import * as i1 from 'primeng/popover';
@@ -30,11 +30,11 @@ import Aura from '@primeng/themes/aura';
30
30
  import Lara from '@primeng/themes/lara';
31
31
  import Nora from '@primeng/themes/nora';
32
32
  import { PrimeNG } from 'primeng/config';
33
- import * as i3 from 'primeng/selectbutton';
33
+ import * as i3$1 from 'primeng/selectbutton';
34
34
  import { SelectButtonModule } from 'primeng/selectbutton';
35
35
  import { AuthService } from '@es.framework/ng.core/abstracts';
36
36
  import * as i4 from 'primeng/api';
37
- import * as i3$2 from 'primeng/tooltip';
37
+ import * as i4$1 from 'primeng/tooltip';
38
38
  import { TooltipModule } from 'primeng/tooltip';
39
39
  import Swal from 'sweetalert2';
40
40
  import { NAVIGATE_TO_MANAGE_PROFILE } from '@es.framework/ng.core/tokens';
@@ -210,36 +210,36 @@ class LanguagesComponent {
210
210
  }
211
211
  }
212
212
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LanguagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
213
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: LanguagesComponent, isStandalone: true, selector: "abp-languages", ngImport: i0, template: `
214
- @if (languages(); as langs) {
215
- <div>
216
- <!-- -->
217
- <button
218
- pButton
219
- type="button"
220
- icon="pi pi-globe"
221
- class="p-button-text"
222
- [title]="'اختر اللغة'"
223
- (click)="overlay.toggle($event)"
224
- ></button>
225
- <p-popover #overlay >
226
- <ul class="w-48">
227
- @for (lang of langs; track lang) {
228
- <li
229
- class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
230
- (click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
231
- >
232
- <span>{{ lang.displayName }}</span>
233
- @if (lang.cultureName === selectedLang()) {
234
- <i class="pi pi-check text-green-500"></i>
235
- }
236
- </li>
237
- }
238
- </ul>
239
- </p-popover>
240
- </div>
241
- }
242
-
213
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: LanguagesComponent, isStandalone: true, selector: "abp-languages", ngImport: i0, template: `
214
+ @if (languages(); as langs) {
215
+ <div>
216
+ <!-- -->
217
+ <button
218
+ pButton
219
+ type="button"
220
+ icon="pi pi-globe"
221
+ class="p-button-text"
222
+ [title]="'اختر اللغة'"
223
+ (click)="overlay.toggle($event)"
224
+ ></button>
225
+ <p-popover #overlay >
226
+ <ul class="w-48">
227
+ @for (lang of langs; track lang) {
228
+ <li
229
+ class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
230
+ (click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
231
+ >
232
+ <span>{{ lang.displayName }}</span>
233
+ @if (lang.cultureName === selectedLang()) {
234
+ <i class="pi pi-check text-green-500"></i>
235
+ }
236
+ </li>
237
+ }
238
+ </ul>
239
+ </p-popover>
240
+ </div>
241
+ }
242
+
243
243
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }] });
244
244
  }
245
245
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LanguagesComponent, decorators: [{
@@ -248,36 +248,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
248
248
  selector: 'abp-languages',
249
249
  standalone: true,
250
250
  imports: [SelectModule, FormsModule, PopoverModule, ButtonModule],
251
- template: `
252
- @if (languages(); as langs) {
253
- <div>
254
- <!-- -->
255
- <button
256
- pButton
257
- type="button"
258
- icon="pi pi-globe"
259
- class="p-button-text"
260
- [title]="'اختر اللغة'"
261
- (click)="overlay.toggle($event)"
262
- ></button>
263
- <p-popover #overlay >
264
- <ul class="w-48">
265
- @for (lang of langs; track lang) {
266
- <li
267
- class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
268
- (click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
269
- >
270
- <span>{{ lang.displayName }}</span>
271
- @if (lang.cultureName === selectedLang()) {
272
- <i class="pi pi-check text-green-500"></i>
273
- }
274
- </li>
275
- }
276
- </ul>
277
- </p-popover>
278
- </div>
279
- }
280
-
251
+ template: `
252
+ @if (languages(); as langs) {
253
+ <div>
254
+ <!-- -->
255
+ <button
256
+ pButton
257
+ type="button"
258
+ icon="pi pi-globe"
259
+ class="p-button-text"
260
+ [title]="'اختر اللغة'"
261
+ (click)="overlay.toggle($event)"
262
+ ></button>
263
+ <p-popover #overlay >
264
+ <ul class="w-48">
265
+ @for (lang of langs; track lang) {
266
+ <li
267
+ class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
268
+ (click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
269
+ >
270
+ <span>{{ lang.displayName }}</span>
271
+ @if (lang.cultureName === selectedLang()) {
272
+ <i class="pi pi-check text-green-500"></i>
273
+ }
274
+ </li>
275
+ }
276
+ </ul>
277
+ </p-popover>
278
+ </div>
279
+ }
280
+
281
281
  `
282
282
  }]
283
283
  }], ctorParameters: () => [] });
@@ -452,7 +452,45 @@ class AppConfigurator {
452
452
  primaryColors = computed(() => {
453
453
  const presetPalette = presets[this.layoutService.layoutConfig().preset].primitive;
454
454
  const colors = ['blue', 'green', 'lime', 'orange', 'amber', 'yellow', 'teal', 'cyan', 'sky', 'emerald', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose'];
455
- const palettes = [{ name: 'noir', palette: {} }];
455
+ const customColors = [
456
+ {
457
+ name: 'ghazali',
458
+ palette: {
459
+ 50: '#fbf7f2',
460
+ 100: '#f4eadf',
461
+ 200: '#e8d3bf',
462
+ 300: '#d8b596',
463
+ 400: '#c99572',
464
+ 500: '#b97855',
465
+ 600: '#a45f3f',
466
+ 700: '#884a34',
467
+ 800: '#713d2f',
468
+ 900: '#5e342b',
469
+ 950: '#351914'
470
+ }
471
+ },
472
+ {
473
+ name: 'brown',
474
+ palette: {
475
+ 50: '#faf6f3',
476
+ 100: '#f1e5dc',
477
+ 200: '#e2c9b8',
478
+ 300: '#cea58a',
479
+ 400: '#b97e5d',
480
+ 500: '#9f6244',
481
+ 600: '#814a34',
482
+ 700: '#6a3d2e',
483
+ 800: '#59342a',
484
+ 900: '#4c2e27',
485
+ 950: '#2b1712'
486
+ }
487
+ },
488
+ ];
489
+ // const palettes: SurfacesType[] = [{ name: 'noir', palette: {} }];
490
+ const palettes = [
491
+ { name: 'noir', palette: {} },
492
+ ...customColors
493
+ ];
456
494
  colors.forEach((color) => {
457
495
  palettes.push({
458
496
  name: color,
@@ -636,54 +674,54 @@ class AppConfigurator {
636
674
  this.layoutService.layoutConfig.update((prev) => ({ ...prev, menuMode: event }));
637
675
  }
638
676
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppConfigurator, deps: [], target: i0.ɵɵFactoryTarget.Component });
639
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AppConfigurator, isStandalone: true, selector: "app-configurator", ngImport: i0, template: `
640
- <div class="flex flex-col gap-4">
641
- <div>
642
- <span class="text-sm text-muted-color font-semibold">Primary</span>
643
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
644
- @for (primaryColor of primaryColors(); track primaryColor.name) {
645
- <button
646
- type="button"
647
- [title]="primaryColor.name"
648
- (click)="updateColors($event, 'primary', primaryColor)"
649
- [ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
650
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
651
- [style]="{
652
- 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
653
- }"
654
- ></button>
655
- }
656
- </div>
657
- </div>
658
- <div>
659
- <span class="text-sm text-muted-color font-semibold">Surface</span>
660
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
661
- @for (surface of surfaces; track surface.name) {
662
- <button
663
- type="button"
664
- [title]="surface.name"
665
- (click)="updateColors($event, 'surface', surface)"
666
- [ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
667
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
668
- [style]="{
669
- 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
670
- }"
671
- ></button>
672
- }
673
- </div>
674
- </div>
675
- <div class="flex flex-col gap-2">
676
- <span class="text-sm text-muted-color font-semibold">Presets</span>
677
- <p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
678
- </div>
679
- @if (showMenuModeButton()) {
680
- <div class="flex flex-col gap-2">
681
- <span class="text-sm text-muted-color font-semibold">Menu Mode</span>
682
- <p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
683
- </div>
684
- }
685
- </div>
686
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }] });
677
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AppConfigurator, isStandalone: true, selector: "app-configurator", ngImport: i0, template: `
678
+ <div class="flex flex-col gap-4">
679
+ <div>
680
+ <span class="text-sm text-muted-color font-semibold">Primary</span>
681
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
682
+ @for (primaryColor of primaryColors(); track primaryColor.name) {
683
+ <button
684
+ type="button"
685
+ [title]="primaryColor.name"
686
+ (click)="updateColors($event, 'primary', primaryColor)"
687
+ [ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
688
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
689
+ [style]="{
690
+ 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
691
+ }"
692
+ ></button>
693
+ }
694
+ </div>
695
+ </div>
696
+ <div>
697
+ <span class="text-sm text-muted-color font-semibold">Surface</span>
698
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
699
+ @for (surface of surfaces; track surface.name) {
700
+ <button
701
+ type="button"
702
+ [title]="surface.name"
703
+ (click)="updateColors($event, 'surface', surface)"
704
+ [ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
705
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
706
+ [style]="{
707
+ 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
708
+ }"
709
+ ></button>
710
+ }
711
+ </div>
712
+ </div>
713
+ <div class="flex flex-col gap-2">
714
+ <span class="text-sm text-muted-color font-semibold">Presets</span>
715
+ <p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
716
+ </div>
717
+ @if (showMenuModeButton()) {
718
+ <div class="flex flex-col gap-2">
719
+ <span class="text-sm text-muted-color font-semibold">Menu Mode</span>
720
+ <p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
721
+ </div>
722
+ }
723
+ </div>
724
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3$1.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }] });
687
725
  }
688
726
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppConfigurator, decorators: [{
689
727
  type: Component,
@@ -691,53 +729,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
691
729
  selector: 'app-configurator',
692
730
  standalone: true,
693
731
  imports: [CommonModule, FormsModule, SelectButtonModule],
694
- template: `
695
- <div class="flex flex-col gap-4">
696
- <div>
697
- <span class="text-sm text-muted-color font-semibold">Primary</span>
698
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
699
- @for (primaryColor of primaryColors(); track primaryColor.name) {
700
- <button
701
- type="button"
702
- [title]="primaryColor.name"
703
- (click)="updateColors($event, 'primary', primaryColor)"
704
- [ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
705
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
706
- [style]="{
707
- 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
708
- }"
709
- ></button>
710
- }
711
- </div>
712
- </div>
713
- <div>
714
- <span class="text-sm text-muted-color font-semibold">Surface</span>
715
- <div class="pt-2 flex gap-2 flex-wrap justify-start">
716
- @for (surface of surfaces; track surface.name) {
717
- <button
718
- type="button"
719
- [title]="surface.name"
720
- (click)="updateColors($event, 'surface', surface)"
721
- [ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
722
- class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
723
- [style]="{
724
- 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
725
- }"
726
- ></button>
727
- }
728
- </div>
729
- </div>
730
- <div class="flex flex-col gap-2">
731
- <span class="text-sm text-muted-color font-semibold">Presets</span>
732
- <p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
733
- </div>
734
- @if (showMenuModeButton()) {
735
- <div class="flex flex-col gap-2">
736
- <span class="text-sm text-muted-color font-semibold">Menu Mode</span>
737
- <p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
738
- </div>
739
- }
740
- </div>
732
+ template: `
733
+ <div class="flex flex-col gap-4">
734
+ <div>
735
+ <span class="text-sm text-muted-color font-semibold">Primary</span>
736
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
737
+ @for (primaryColor of primaryColors(); track primaryColor.name) {
738
+ <button
739
+ type="button"
740
+ [title]="primaryColor.name"
741
+ (click)="updateColors($event, 'primary', primaryColor)"
742
+ [ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
743
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
744
+ [style]="{
745
+ 'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
746
+ }"
747
+ ></button>
748
+ }
749
+ </div>
750
+ </div>
751
+ <div>
752
+ <span class="text-sm text-muted-color font-semibold">Surface</span>
753
+ <div class="pt-2 flex gap-2 flex-wrap justify-start">
754
+ @for (surface of surfaces; track surface.name) {
755
+ <button
756
+ type="button"
757
+ [title]="surface.name"
758
+ (click)="updateColors($event, 'surface', surface)"
759
+ [ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
760
+ class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
761
+ [style]="{
762
+ 'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
763
+ }"
764
+ ></button>
765
+ }
766
+ </div>
767
+ </div>
768
+ <div class="flex flex-col gap-2">
769
+ <span class="text-sm text-muted-color font-semibold">Presets</span>
770
+ <p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
771
+ </div>
772
+ @if (showMenuModeButton()) {
773
+ <div class="flex flex-col gap-2">
774
+ <span class="text-sm text-muted-color font-semibold">Menu Mode</span>
775
+ <p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
776
+ </div>
777
+ }
778
+ </div>
741
779
  `,
742
780
  }]
743
781
  }] });
@@ -868,168 +906,168 @@ class NavItemsComponent {
868
906
  this.authService.navigateToLogin();
869
907
  }
870
908
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NavItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
871
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: NavItemsComponent, isStandalone: true, selector: "app-nav-items", ngImport: i0, template: `
872
- <header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
873
- <!-- Left: Logo / Title -->
874
- <div class="flex items-center space-x-3 rtl:space-x-reverse">
875
- <img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
876
- <span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
877
- </div>
878
-
879
- <!-- Center: Nav Items -->
880
- <div class="flex items-center space-x-4 rtl:space-x-reverse">
881
- <ul class="flex space-x-4">
882
- @for (item of navItems.items$ | async; track item.id) {
883
- @if (!item.visible || item.visible(item)) {
884
- <ng-container *frameworkVisible="!item.visible || item.visible(item)">
885
- <li class="flex items-center">
886
- @if (item.component) {
887
- <ng-container
888
- [ngComponentOutlet]="item.component"
889
- [ngComponentOutletInjector]="item | toInjector"
890
- ></ng-container>
891
- } @else {
892
- <button
893
- pButton
894
- type="button"
895
- class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
896
- (click)="item.action?.()"
897
- >
898
- <span [innerHTML]="item.html"></span>
899
- </button>
900
- }
901
- </li>
902
- </ng-container>
903
- }
904
- }
905
- </ul>
906
- </div>
907
-
908
- <!-- Right: Actions -->
909
- <div class="flex items-center rtl:space-x-reverse">
910
- <!-- Configurator -->
911
-
912
- <div>
913
- <!-- -->
914
- <button
915
- pButton
916
- type="button"
917
- icon="pi pi-palette"
918
- class="p-button-text"
919
- [title]="''"
920
- (click)="overlay.toggle($event)"
921
- >
922
- </button>
923
-
924
- <p-popover #overlay >
925
- <app-configurator />
926
- </p-popover>
927
- </div>
928
-
929
-
930
- <!-- Dark Mode Toggle -->
931
- <button
932
- pButton
933
- type="button"
934
- [icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
935
- class="p-button-text"
936
- (click)="toggleDarkMode()">
937
- </button>
938
-
939
- <!-- Language Switcher -->
940
- <abp-languages></abp-languages>
941
-
942
- <!-- User Menu -->
943
- <div class="relative">
944
- <button
945
- class="p-link p-2"
946
- (click)="menu.toggle($event)"
947
- aria-label="User menu"
948
- >
949
- <p-avatar
950
- [label]="loading ? '' : userName"
951
- [icon]="loading ? 'pi pi-spinner' : ''"
952
- [class]="{'pi-spin': loading}"
953
- shape="circle"
954
- class="bg-blue-600 text-white cursor-pointer"
955
- [title]="(currentUser$ | async)?.name || ''"
956
- ></p-avatar>
957
- </button>
958
-
959
- <p-menu
960
- #menu
961
- [model]="userMenuItems"
962
- [popup]="true"
963
- [appendTo]="'body'"
964
- styleClass="w-64 sm:w-72 shadow-lg rounded-md"
965
- >
966
- <ng-template pTemplate="start">
967
- <div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
968
- <p-avatar
969
- [label]="userName"
970
- shape="circle"
971
- size="xlarge"
972
- styleClass="bg-blue-600 text-white mb-3 shadow-lg"
973
- [title]="(currentUser$ | async)?.name || ''"
974
- ></p-avatar>
975
- <h5 class="text-xl font-semibold text-gray-800 leading-tight">
976
- {{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
977
- </h5>
978
- <p class="text-sm text-gray-600 truncate max-w-full">
979
- {{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
980
- </p>
981
- @if ((selectedTenant$ | async); as tenant) {
982
- <span
983
- class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
984
- [ngClass]="{
985
- 'bg-green-100 text-green-800': true
986
- }"
987
- >
988
- {{ tenant?.name || '_' }}
989
- </span>
990
- }
991
- </div>
992
- </ng-template>
993
-
994
- <ng-template pTemplate="item" let-item>
995
- <!-- *frameworkVisible="!item.visible || item.visible(item)" -->
996
- <ng-container >
997
- <!-- *hasPermission="item.requiredPolicy" -->
998
- <a
999
-
1000
- class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
1001
- [ngClass]="item.styleClass || ''"
1002
- (click)="item.command ? item.command() : null"
1003
- [routerLink]="item.routerLink ? item.routerLink : null"
1004
- tabindex="0"
1005
- >
1006
- @if (item.component) {
1007
- <ng-container
1008
- [ngComponentOutlet]="item.component"
1009
- [ngComponentOutletInjector]="item | toInjector"
1010
- ></ng-container>
1011
- } @else {
1012
- <i [class]="item.icon + ' text-lg text-gray-600'"></i>
1013
- <span class="text-gray-700">{{ item.label | translate }}</span>
1014
- }
1015
- </a>
1016
- </ng-container>
1017
- </ng-template>
1018
- </p-menu>
1019
- </div>
1020
-
1021
- <!-- Logout Button (separate from menu) -->
1022
- <!-- <button
1023
- type="button"
1024
- class="layout-topbar-action"
1025
- (click)="logout()"
1026
- title="تسجيل الخروج"
1027
- >
1028
- <i class="pi pi-sign-out"></i>
1029
- </button> -->
1030
- </div>
1031
- </header>
1032
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }, { kind: "component", type: LanguagesComponent, selector: "abp-languages" }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i3$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i5.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: VisibleDirective, selector: "[frameworkVisible]", inputs: ["frameworkVisible"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: ToInjectorPipe, name: "toInjector" }] });
909
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: NavItemsComponent, isStandalone: true, selector: "app-nav-items", ngImport: i0, template: `
910
+ <header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
911
+ <!-- Left: Logo / Title -->
912
+ <div class="flex items-center space-x-3 rtl:space-x-reverse">
913
+ <img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
914
+ <span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
915
+ </div>
916
+
917
+ <!-- Center: Nav Items -->
918
+ <div class="flex items-center space-x-4 rtl:space-x-reverse">
919
+ <ul class="flex space-x-4">
920
+ @for (item of navItems.items$ | async; track item.id) {
921
+ @if (!item.visible || item.visible(item)) {
922
+ <ng-container *frameworkVisible="!item.visible || item.visible(item)">
923
+ <li class="flex items-center">
924
+ @if (item.component) {
925
+ <ng-container
926
+ [ngComponentOutlet]="item.component"
927
+ [ngComponentOutletInjector]="item | toInjector"
928
+ ></ng-container>
929
+ } @else {
930
+ <button
931
+ pButton
932
+ type="button"
933
+ class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
934
+ (click)="item.action?.()"
935
+ >
936
+ <span [innerHTML]="item.html"></span>
937
+ </button>
938
+ }
939
+ </li>
940
+ </ng-container>
941
+ }
942
+ }
943
+ </ul>
944
+ </div>
945
+
946
+ <!-- Right: Actions -->
947
+ <div class="flex items-center rtl:space-x-reverse">
948
+ <!-- Configurator -->
949
+
950
+ <div>
951
+ <!-- -->
952
+ <button
953
+ pButton
954
+ type="button"
955
+ icon="pi pi-palette"
956
+ class="p-button-text"
957
+ [title]="''"
958
+ (click)="overlay.toggle($event)"
959
+ >
960
+ </button>
961
+
962
+ <p-popover #overlay >
963
+ <app-configurator />
964
+ </p-popover>
965
+ </div>
966
+
967
+
968
+ <!-- Dark Mode Toggle -->
969
+ <button
970
+ pButton
971
+ type="button"
972
+ [icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
973
+ class="p-button-text"
974
+ (click)="toggleDarkMode()">
975
+ </button>
976
+
977
+ <!-- Language Switcher -->
978
+ <abp-languages></abp-languages>
979
+
980
+ <!-- User Menu -->
981
+ <div class="relative">
982
+ <button
983
+ class="p-link p-2"
984
+ (click)="menu.toggle($event)"
985
+ aria-label="User menu"
986
+ >
987
+ <p-avatar
988
+ [label]="loading ? '' : userName"
989
+ [icon]="loading ? 'pi pi-spinner' : ''"
990
+ [class]="{'pi-spin': loading}"
991
+ shape="circle"
992
+ class="bg-blue-600 text-white cursor-pointer"
993
+ [title]="(currentUser$ | async)?.name || ''"
994
+ ></p-avatar>
995
+ </button>
996
+
997
+ <p-menu
998
+ #menu
999
+ [model]="userMenuItems"
1000
+ [popup]="true"
1001
+ [appendTo]="'body'"
1002
+ styleClass="w-64 sm:w-72 shadow-lg rounded-md"
1003
+ >
1004
+ <ng-template pTemplate="start">
1005
+ <div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
1006
+ <p-avatar
1007
+ [label]="userName"
1008
+ shape="circle"
1009
+ size="xlarge"
1010
+ styleClass="bg-blue-600 text-white mb-3 shadow-lg"
1011
+ [title]="(currentUser$ | async)?.name || ''"
1012
+ ></p-avatar>
1013
+ <h5 class="text-xl font-semibold text-gray-800 leading-tight">
1014
+ {{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
1015
+ </h5>
1016
+ <p class="text-sm text-gray-600 truncate max-w-full">
1017
+ {{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
1018
+ </p>
1019
+ @if ((selectedTenant$ | async); as tenant) {
1020
+ <span
1021
+ class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
1022
+ [ngClass]="{
1023
+ 'bg-green-100 text-green-800': true
1024
+ }"
1025
+ >
1026
+ {{ tenant?.name || '_' }}
1027
+ </span>
1028
+ }
1029
+ </div>
1030
+ </ng-template>
1031
+
1032
+ <ng-template pTemplate="item" let-item>
1033
+ <!-- *frameworkVisible="!item.visible || item.visible(item)" -->
1034
+ <ng-container >
1035
+ <!-- *hasPermission="item.requiredPolicy" -->
1036
+ <a
1037
+
1038
+ class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
1039
+ [ngClass]="item.styleClass || ''"
1040
+ (click)="item.command ? item.command() : null"
1041
+ [routerLink]="item.routerLink ? item.routerLink : null"
1042
+ tabindex="0"
1043
+ >
1044
+ @if (item.component) {
1045
+ <ng-container
1046
+ [ngComponentOutlet]="item.component"
1047
+ [ngComponentOutletInjector]="item | toInjector"
1048
+ ></ng-container>
1049
+ } @else {
1050
+ <i [class]="item.icon + ' text-lg text-gray-600'"></i>
1051
+ <span class="text-gray-700">{{ item.label | translate }}</span>
1052
+ }
1053
+ </a>
1054
+ </ng-container>
1055
+ </ng-template>
1056
+ </p-menu>
1057
+ </div>
1058
+
1059
+ <!-- Logout Button (separate from menu) -->
1060
+ <!-- <button
1061
+ type="button"
1062
+ class="layout-topbar-action"
1063
+ (click)="logout()"
1064
+ title="تسجيل الخروج"
1065
+ >
1066
+ <i class="pi pi-sign-out"></i>
1067
+ </button> -->
1068
+ </div>
1069
+ </header>
1070
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }, { kind: "component", type: LanguagesComponent, selector: "abp-languages" }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i3$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i5.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: VisibleDirective, selector: "[frameworkVisible]", inputs: ["frameworkVisible"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: ToInjectorPipe, name: "toInjector" }] });
1033
1071
  }
1034
1072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NavItemsComponent, decorators: [{
1035
1073
  type: Component,
@@ -1052,167 +1090,167 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
1052
1090
  ToInjectorPipe,
1053
1091
  PopoverModule
1054
1092
  ],
1055
- template: `
1056
- <header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
1057
- <!-- Left: Logo / Title -->
1058
- <div class="flex items-center space-x-3 rtl:space-x-reverse">
1059
- <img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
1060
- <span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
1061
- </div>
1062
-
1063
- <!-- Center: Nav Items -->
1064
- <div class="flex items-center space-x-4 rtl:space-x-reverse">
1065
- <ul class="flex space-x-4">
1066
- @for (item of navItems.items$ | async; track item.id) {
1067
- @if (!item.visible || item.visible(item)) {
1068
- <ng-container *frameworkVisible="!item.visible || item.visible(item)">
1069
- <li class="flex items-center">
1070
- @if (item.component) {
1071
- <ng-container
1072
- [ngComponentOutlet]="item.component"
1073
- [ngComponentOutletInjector]="item | toInjector"
1074
- ></ng-container>
1075
- } @else {
1076
- <button
1077
- pButton
1078
- type="button"
1079
- class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
1080
- (click)="item.action?.()"
1081
- >
1082
- <span [innerHTML]="item.html"></span>
1083
- </button>
1084
- }
1085
- </li>
1086
- </ng-container>
1087
- }
1088
- }
1089
- </ul>
1090
- </div>
1091
-
1092
- <!-- Right: Actions -->
1093
- <div class="flex items-center rtl:space-x-reverse">
1094
- <!-- Configurator -->
1095
-
1096
- <div>
1097
- <!-- -->
1098
- <button
1099
- pButton
1100
- type="button"
1101
- icon="pi pi-palette"
1102
- class="p-button-text"
1103
- [title]="''"
1104
- (click)="overlay.toggle($event)"
1105
- >
1106
- </button>
1107
-
1108
- <p-popover #overlay >
1109
- <app-configurator />
1110
- </p-popover>
1111
- </div>
1112
-
1113
-
1114
- <!-- Dark Mode Toggle -->
1115
- <button
1116
- pButton
1117
- type="button"
1118
- [icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
1119
- class="p-button-text"
1120
- (click)="toggleDarkMode()">
1121
- </button>
1122
-
1123
- <!-- Language Switcher -->
1124
- <abp-languages></abp-languages>
1125
-
1126
- <!-- User Menu -->
1127
- <div class="relative">
1128
- <button
1129
- class="p-link p-2"
1130
- (click)="menu.toggle($event)"
1131
- aria-label="User menu"
1132
- >
1133
- <p-avatar
1134
- [label]="loading ? '' : userName"
1135
- [icon]="loading ? 'pi pi-spinner' : ''"
1136
- [class]="{'pi-spin': loading}"
1137
- shape="circle"
1138
- class="bg-blue-600 text-white cursor-pointer"
1139
- [title]="(currentUser$ | async)?.name || ''"
1140
- ></p-avatar>
1141
- </button>
1142
-
1143
- <p-menu
1144
- #menu
1145
- [model]="userMenuItems"
1146
- [popup]="true"
1147
- [appendTo]="'body'"
1148
- styleClass="w-64 sm:w-72 shadow-lg rounded-md"
1149
- >
1150
- <ng-template pTemplate="start">
1151
- <div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
1152
- <p-avatar
1153
- [label]="userName"
1154
- shape="circle"
1155
- size="xlarge"
1156
- styleClass="bg-blue-600 text-white mb-3 shadow-lg"
1157
- [title]="(currentUser$ | async)?.name || ''"
1158
- ></p-avatar>
1159
- <h5 class="text-xl font-semibold text-gray-800 leading-tight">
1160
- {{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
1161
- </h5>
1162
- <p class="text-sm text-gray-600 truncate max-w-full">
1163
- {{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
1164
- </p>
1165
- @if ((selectedTenant$ | async); as tenant) {
1166
- <span
1167
- class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
1168
- [ngClass]="{
1169
- 'bg-green-100 text-green-800': true
1170
- }"
1171
- >
1172
- {{ tenant?.name || '_' }}
1173
- </span>
1174
- }
1175
- </div>
1176
- </ng-template>
1177
-
1178
- <ng-template pTemplate="item" let-item>
1179
- <!-- *frameworkVisible="!item.visible || item.visible(item)" -->
1180
- <ng-container >
1181
- <!-- *hasPermission="item.requiredPolicy" -->
1182
- <a
1183
-
1184
- class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
1185
- [ngClass]="item.styleClass || ''"
1186
- (click)="item.command ? item.command() : null"
1187
- [routerLink]="item.routerLink ? item.routerLink : null"
1188
- tabindex="0"
1189
- >
1190
- @if (item.component) {
1191
- <ng-container
1192
- [ngComponentOutlet]="item.component"
1193
- [ngComponentOutletInjector]="item | toInjector"
1194
- ></ng-container>
1195
- } @else {
1196
- <i [class]="item.icon + ' text-lg text-gray-600'"></i>
1197
- <span class="text-gray-700">{{ item.label | translate }}</span>
1198
- }
1199
- </a>
1200
- </ng-container>
1201
- </ng-template>
1202
- </p-menu>
1203
- </div>
1204
-
1205
- <!-- Logout Button (separate from menu) -->
1206
- <!-- <button
1207
- type="button"
1208
- class="layout-topbar-action"
1209
- (click)="logout()"
1210
- title="تسجيل الخروج"
1211
- >
1212
- <i class="pi pi-sign-out"></i>
1213
- </button> -->
1214
- </div>
1215
- </header>
1093
+ template: `
1094
+ <header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
1095
+ <!-- Left: Logo / Title -->
1096
+ <div class="flex items-center space-x-3 rtl:space-x-reverse">
1097
+ <img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
1098
+ <span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
1099
+ </div>
1100
+
1101
+ <!-- Center: Nav Items -->
1102
+ <div class="flex items-center space-x-4 rtl:space-x-reverse">
1103
+ <ul class="flex space-x-4">
1104
+ @for (item of navItems.items$ | async; track item.id) {
1105
+ @if (!item.visible || item.visible(item)) {
1106
+ <ng-container *frameworkVisible="!item.visible || item.visible(item)">
1107
+ <li class="flex items-center">
1108
+ @if (item.component) {
1109
+ <ng-container
1110
+ [ngComponentOutlet]="item.component"
1111
+ [ngComponentOutletInjector]="item | toInjector"
1112
+ ></ng-container>
1113
+ } @else {
1114
+ <button
1115
+ pButton
1116
+ type="button"
1117
+ class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
1118
+ (click)="item.action?.()"
1119
+ >
1120
+ <span [innerHTML]="item.html"></span>
1121
+ </button>
1122
+ }
1123
+ </li>
1124
+ </ng-container>
1125
+ }
1126
+ }
1127
+ </ul>
1128
+ </div>
1129
+
1130
+ <!-- Right: Actions -->
1131
+ <div class="flex items-center rtl:space-x-reverse">
1132
+ <!-- Configurator -->
1133
+
1134
+ <div>
1135
+ <!-- -->
1136
+ <button
1137
+ pButton
1138
+ type="button"
1139
+ icon="pi pi-palette"
1140
+ class="p-button-text"
1141
+ [title]="''"
1142
+ (click)="overlay.toggle($event)"
1143
+ >
1144
+ </button>
1145
+
1146
+ <p-popover #overlay >
1147
+ <app-configurator />
1148
+ </p-popover>
1149
+ </div>
1150
+
1151
+
1152
+ <!-- Dark Mode Toggle -->
1153
+ <button
1154
+ pButton
1155
+ type="button"
1156
+ [icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
1157
+ class="p-button-text"
1158
+ (click)="toggleDarkMode()">
1159
+ </button>
1160
+
1161
+ <!-- Language Switcher -->
1162
+ <abp-languages></abp-languages>
1163
+
1164
+ <!-- User Menu -->
1165
+ <div class="relative">
1166
+ <button
1167
+ class="p-link p-2"
1168
+ (click)="menu.toggle($event)"
1169
+ aria-label="User menu"
1170
+ >
1171
+ <p-avatar
1172
+ [label]="loading ? '' : userName"
1173
+ [icon]="loading ? 'pi pi-spinner' : ''"
1174
+ [class]="{'pi-spin': loading}"
1175
+ shape="circle"
1176
+ class="bg-blue-600 text-white cursor-pointer"
1177
+ [title]="(currentUser$ | async)?.name || ''"
1178
+ ></p-avatar>
1179
+ </button>
1180
+
1181
+ <p-menu
1182
+ #menu
1183
+ [model]="userMenuItems"
1184
+ [popup]="true"
1185
+ [appendTo]="'body'"
1186
+ styleClass="w-64 sm:w-72 shadow-lg rounded-md"
1187
+ >
1188
+ <ng-template pTemplate="start">
1189
+ <div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
1190
+ <p-avatar
1191
+ [label]="userName"
1192
+ shape="circle"
1193
+ size="xlarge"
1194
+ styleClass="bg-blue-600 text-white mb-3 shadow-lg"
1195
+ [title]="(currentUser$ | async)?.name || ''"
1196
+ ></p-avatar>
1197
+ <h5 class="text-xl font-semibold text-gray-800 leading-tight">
1198
+ {{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
1199
+ </h5>
1200
+ <p class="text-sm text-gray-600 truncate max-w-full">
1201
+ {{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
1202
+ </p>
1203
+ @if ((selectedTenant$ | async); as tenant) {
1204
+ <span
1205
+ class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
1206
+ [ngClass]="{
1207
+ 'bg-green-100 text-green-800': true
1208
+ }"
1209
+ >
1210
+ {{ tenant?.name || '_' }}
1211
+ </span>
1212
+ }
1213
+ </div>
1214
+ </ng-template>
1215
+
1216
+ <ng-template pTemplate="item" let-item>
1217
+ <!-- *frameworkVisible="!item.visible || item.visible(item)" -->
1218
+ <ng-container >
1219
+ <!-- *hasPermission="item.requiredPolicy" -->
1220
+ <a
1221
+
1222
+ class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
1223
+ [ngClass]="item.styleClass || ''"
1224
+ (click)="item.command ? item.command() : null"
1225
+ [routerLink]="item.routerLink ? item.routerLink : null"
1226
+ tabindex="0"
1227
+ >
1228
+ @if (item.component) {
1229
+ <ng-container
1230
+ [ngComponentOutlet]="item.component"
1231
+ [ngComponentOutletInjector]="item | toInjector"
1232
+ ></ng-container>
1233
+ } @else {
1234
+ <i [class]="item.icon + ' text-lg text-gray-600'"></i>
1235
+ <span class="text-gray-700">{{ item.label | translate }}</span>
1236
+ }
1237
+ </a>
1238
+ </ng-container>
1239
+ </ng-template>
1240
+ </p-menu>
1241
+ </div>
1242
+
1243
+ <!-- Logout Button (separate from menu) -->
1244
+ <!-- <button
1245
+ type="button"
1246
+ class="layout-topbar-action"
1247
+ (click)="logout()"
1248
+ title="تسجيل الخروج"
1249
+ >
1250
+ <i class="pi pi-sign-out"></i>
1251
+ </button> -->
1252
+ </div>
1253
+ </header>
1216
1254
  `
1217
1255
  }]
1218
1256
  }], ctorParameters: () => [] });
@@ -1221,6 +1259,7 @@ class RoutesComponent {
1221
1259
  subSidebarVisible = false;
1222
1260
  sidebarVisible = true;
1223
1261
  isMobile = false;
1262
+ searchText = ''; // ✅ البحث
1224
1263
  router = inject(Router);
1225
1264
  localization = inject(LocalizationService);
1226
1265
  layoutService = inject(LayoutService);
@@ -1228,13 +1267,14 @@ class RoutesComponent {
1228
1267
  configState = inject(ConfigStateService);
1229
1268
  secondToLastLevel$;
1230
1269
  _menuItemsSubject = new BehaviorSubject([]);
1231
- // menuItems$!: Observable<MenuItem[]>;
1232
1270
  menuItems$ = this._menuItemsSubject.asObservable();
1233
1271
  constructor() {
1234
- // this.menuItems$ = this.routesService.visible$.pipe(
1235
- // map(routes => this.buildItems(routes).map(item => ({ ...item, expanded: true })))
1236
- // );
1237
- this.routesService.visible$.pipe(map(routes => this.buildItems(routes).map(item => ({ ...item, expanded: true })))).subscribe(items => this._menuItemsSubject.next(items));
1272
+ this.routesService.visible$.pipe(map(routes => {
1273
+ const items = this.buildItems(routes);
1274
+ // ✅ فتح الشجرة كاملة عند الدخول للنظام
1275
+ // this.setExpandedRecursive(items, true);
1276
+ return items;
1277
+ })).subscribe(items => this._menuItemsSubject.next(items));
1238
1278
  }
1239
1279
  ngOnInit() {
1240
1280
  this.checkViewport();
@@ -1242,25 +1282,87 @@ class RoutesComponent {
1242
1282
  const result = [];
1243
1283
  for (const item of items) {
1244
1284
  if (item.items && item.items.length > 0) {
1245
- // إضافة جميع الأبناء المباشرين (المستوى الثاني)
1246
1285
  result.push(...item.items);
1247
1286
  }
1248
1287
  }
1249
1288
  return result;
1250
1289
  }));
1251
- // this.secondToLastLevel$ = this.menuItems$.pipe(
1252
- // map(items => this.getSecondToLastLevel(items))
1253
- // );
1290
+ // إظهار الشجرة الفرعية مفتوحة في الديسكتوب عند الدخول
1291
+ if (!this.isMobile) {
1292
+ this.sidebarVisible = true;
1293
+ this.subSidebarVisible = true;
1294
+ }
1295
+ }
1296
+ setExpandedRecursive(items, expanded) {
1297
+ for (const item of items) {
1298
+ item.expanded = expanded;
1299
+ if (item.items?.length) {
1300
+ this.setExpandedRecursive(item.items, expanded);
1301
+ }
1302
+ }
1303
+ }
1304
+ expandAll() {
1305
+ const items = this._menuItemsSubject.value;
1306
+ this.setExpandedRecursive(items, true);
1307
+ this.subSidebarVisible = true;
1308
+ this._menuItemsSubject.next([...items]);
1309
+ }
1310
+ collapseAll() {
1311
+ const items = this._menuItemsSubject.value;
1312
+ this.setExpandedRecursive(items, false);
1313
+ this._menuItemsSubject.next([...items]);
1314
+ }
1315
+ onSearchChange() {
1316
+ const items = this._menuItemsSubject.value;
1317
+ if (!this.searchText.trim()) {
1318
+ // ✅ عند مسح البحث ترجع مغلقة مثل البداية
1319
+ this.setExpandedRecursive(items, false);
1320
+ this._menuItemsSubject.next([...items]);
1321
+ return;
1322
+ }
1323
+ // ✅ أثناء البحث يفتح فقط المسارات المطابقة
1324
+ this.expandMatchedParents(items, this.searchText);
1325
+ this._menuItemsSubject.next([...items]);
1326
+ }
1327
+ expandMatchedParents(items, keyword) {
1328
+ const term = keyword.trim().toLowerCase();
1329
+ let hasMatch = false;
1330
+ for (const item of items) {
1331
+ const label = String(item.label ?? '').toLowerCase();
1332
+ const title = String(item.title ?? '').toLowerCase();
1333
+ const selfMatch = label.includes(term) || title.includes(term);
1334
+ const childMatch = item.items?.length
1335
+ ? this.expandMatchedParents(item.items, keyword)
1336
+ : false;
1337
+ item.expanded = !!childMatch || !!selfMatch;
1338
+ if (selfMatch || childMatch) {
1339
+ hasMatch = true;
1340
+ }
1341
+ }
1342
+ return hasMatch;
1343
+ }
1344
+ isSearchMatch(item) {
1345
+ const term = this.searchText.trim().toLowerCase();
1346
+ if (!term)
1347
+ return false;
1348
+ const label = String(item.label ?? '').toLowerCase();
1349
+ const title = String(item.title ?? '').toLowerCase();
1350
+ return label.includes(term) || title.includes(term);
1351
+ }
1352
+ clearSearch() {
1353
+ this.searchText = '';
1354
+ const items = this._menuItemsSubject.value;
1355
+ // ✅ لا تفتح الكل عند مسح البحث
1356
+ this.setExpandedRecursive(items, false);
1357
+ this._menuItemsSubject.next([...items]);
1254
1358
  }
1255
1359
  getSecondToLastLevel(items) {
1256
1360
  const result = [];
1257
1361
  const traverse = (nodes) => {
1258
1362
  for (const node of nodes) {
1259
1363
  if (node.items && node.items.length > 0) {
1260
- // Check if any child has its own children
1261
1364
  const hasGrandChildren = node.items.some(c => c.items && c.items.length > 0);
1262
1365
  if (!hasGrandChildren) {
1263
- // Node is right before the last level
1264
1366
  result.push(node);
1265
1367
  }
1266
1368
  else {
@@ -1273,23 +1375,11 @@ class RoutesComponent {
1273
1375
  return result;
1274
1376
  }
1275
1377
  onParentClick(item) {
1276
- // toggle expand
1277
1378
  item.expanded = !item.expanded;
1278
- // TODO: Navigate to shell route if needed
1279
- // if (item.items?.length) {
1280
- // // Navigate to shell route
1281
- // // Split the path into segments for Angular
1282
- // const pathSegments = item.routerLink
1283
- // ? (Array.isArray(item.routerLink) ? item.routerLink : item.routerLink.split('/').filter(Boolean))
1284
- // : [];
1285
- // this.router.navigate(pathSegments);
1286
- // } else if (item.routerLink) {
1287
- // const pathSegments = Array.isArray(item.routerLink) ? item.routerLink : item.routerLink.split('/').filter(Boolean);
1288
- // this.router.navigate(pathSegments);
1289
- // }
1290
- // this.subSidebarVisible = true;
1291
- }
1292
- onResize() { this.checkViewport(); }
1379
+ }
1380
+ onResize() {
1381
+ this.checkViewport();
1382
+ }
1293
1383
  checkViewport() {
1294
1384
  this.isMobile = window.innerWidth < 1024;
1295
1385
  if (this.isMobile) {
@@ -1298,6 +1388,7 @@ class RoutesComponent {
1298
1388
  }
1299
1389
  else {
1300
1390
  this.sidebarVisible = true;
1391
+ // ✅ خلي الشجرة ظاهرة في الديسكتوب
1301
1392
  this.subSidebarVisible = true;
1302
1393
  }
1303
1394
  }
@@ -1321,7 +1412,7 @@ class RoutesComponent {
1321
1412
  if (item.items && item.items.length > 0) {
1322
1413
  const found = this.expandPath(item.items, target);
1323
1414
  if (found) {
1324
- item.expanded = true; // expand parent
1415
+ item.expanded = true;
1325
1416
  return true;
1326
1417
  }
1327
1418
  }
@@ -1365,14 +1456,7 @@ class RoutesComponent {
1365
1456
  closeMenu() {
1366
1457
  this.subSidebarVisible = false;
1367
1458
  this.sidebarVisible = false;
1368
- // this.menuItems$.subscribe(items => {
1369
- // items.forEach(item => item.expanded = false);
1370
- // });
1371
- }
1372
- // @HostListener('document:keydown.escape')
1373
- // onEsc() {
1374
- // this.closeMenu();
1375
- // }
1459
+ }
1376
1460
  onNavigate() {
1377
1461
  if (this.isMobile) {
1378
1462
  this.closeMenu();
@@ -1387,9 +1471,8 @@ class RoutesComponent {
1387
1471
  const item = {
1388
1472
  label: route.name,
1389
1473
  icon: route.iconClass,
1390
- // routerLink: route.path ? [route.path] : undefined,
1391
1474
  title: route.name,
1392
- expanded: false
1475
+ expanded: false // ✅ بدل false، افتح كل عنصر افتراضياً
1393
1476
  };
1394
1477
  if (route.isExternal) {
1395
1478
  item.url = route.path;
@@ -1403,25 +1486,9 @@ class RoutesComponent {
1403
1486
  if (this.routesService.hasChildren(route.name)) {
1404
1487
  item.items = this.buildItems(route.children ?? []);
1405
1488
  }
1406
- else {
1407
- // TODO: check if grant permission
1408
- // if(){
1409
- // item['actionButtons']= [
1410
- // {
1411
- // icon: 'pi pi-plus',
1412
- // tooltip: 'ADD',
1413
- // click: (item:any, event:any) => {
1414
- // this.router.navigate([route.path,'add']);
1415
- // },
1416
- // visible: (item:any) => true
1417
- // }
1418
- // ];
1419
- // }
1420
- }
1421
1489
  return item;
1422
1490
  }
1423
1491
  hasPermission(policy) {
1424
- // implement using permission service
1425
1492
  return true;
1426
1493
  }
1427
1494
  getLinkProps(item) {
@@ -1433,12 +1500,28 @@ class RoutesComponent {
1433
1500
  addRoute: item.addRoute ?? ''
1434
1501
  };
1435
1502
  }
1503
+ showTreeSearch = false;
1504
+ toggleTreeSearch() {
1505
+ this.showTreeSearch = !this.showTreeSearch;
1506
+ if (!this.showTreeSearch) {
1507
+ this.clearSearch();
1508
+ }
1509
+ }
1436
1510
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1437
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: RoutesComponent, isStandalone: true, selector: "app-routes", host: { listeners: { "window:resize": "onResize()" } }, ngImport: i0, template: "<aside class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\n [ngClass]=\"{ 'w-0 overflow-hidden': !sidebarVisible && isMobile }\">\n\n <!-- \uD83C\uDFA8 \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A \u0627\u0644\u0631\u0626\u064A\u0633\u064A -->\n <div\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl\n bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700\n text-white rounded-r-3xl\">\n\n <!-- \uD83D\uDD1D \u0627\u0644\u0623\u0639\u0644\u0649 -->\n <div class=\"flex flex-col items-center gap-4\">\n <img src=\"/assets/logo.png\" alt=\"Logo\"\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"/>\n\n <!-- \u0632\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 -->\n <!-- [pTooltip]=\"'TOGGLE_MENU' | translate\" -->\n <button (click)=\"toggleAll()\"\n tooltipPosition=\"right\"\n class=\"text-white hover:scale-110 transition-transform duration-200\">\n <i class=\"pi pi-bars text-lg\"></i>\n </button>\n\n <!-- \u0623\u064A\u0642\u0648\u0646\u0627\u062A -->\n @for (item of secondToLastLevel$ | async; track item) {\n <div class=\"relative flex flex-col items-center\">\n <!-- \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629 -->\n <div (click)=\"onMainClick(item)\"\n [pTooltip]=\"item.label | translate\"\n tooltipPosition=\"right\"\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer\n hover:bg-white/20 transition-all duration-200\"\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\">\n <i [class]=\"item.icon + ' text-xl'\"></i>\n </div>\n </div>\n }\n </div>\n\n <!-- \u2699\uFE0F \u0627\u0644\u0623\u0633\u0641\u0644 -->\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\n <i class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"></i>\n </div>\n </div>\n\n <!-- \uD83D\uDCCB \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0641\u0631\u0639\u064A\u0629 -->\n @if (subSidebarVisible) {\n <div\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn\n shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': isMobile }\">\n <!-- \u0632\u0631 \u0631\u062C\u0648\u0639 -->\n <button (click)=\"closeMenu()\"\n class=\"flex items-center gap-2 mb-4 text-gray-500 dark:text-gray-300 hover:text-primary-600 transition\">\n <i class=\"pi\" [ngClass]=\"isMobile ? 'pi-angle-right' : 'pi-angle-right'\"></i>\n <span>{{ 'back' | translate }}</span>\n </button>\n <!-- Recursive rendering -->\n @if (menuItems$ | async; as menuItems) {\n <ng-container *ngTemplateOutlet=\"renderMenu; context:{ $implicit: menuItems, level: 1 }\"></ng-container>\n}\n\n<ng-template #renderMenu let-items let-level=\"level\">\n @for (item of items; track item) {\n\n @if (!item.items?.length) {\n @let link = getLinkProps(item);\n <div class=\"mb-1\">\n @if (link.isExternal) {\n <a [href]=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">{{ item.label | translate }}</span>\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\n </a>\n } @else {\n <div class=\"flex items-center gap-2\">\n <a [routerLink]=\"link.routerLink\"\n (click)=\"onNavigate()\"\n routerLinkActive=\"active-link\"\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">\n {{ item.label | translate }}</span>\n </a>\n\n@if (link.addRoute) {\n <a\n [routerLink]=\"[link.addRoute]\"\n (click)=\"$event.stopPropagation(); onNavigate()\"\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\n [pTooltip]=\"'ADD' | translate\"\n tooltipPosition=\"top\">\n <i class=\"pi pi-plus text-xs\"></i>\n </a>\n}\n </div>\n }\n</div>\n}\n\n @if (item.items?.length) {\n <div class=\"mb-1\">\n\n <div\n (click)=\"onParentClick(item)\"\n [style.font-size.rem]=\"1.1 - (level * 0.05)\"\n [ngClass]=\"{\n 'font-bold': level === 1,\n 'font-semibold': level === 2,\n 'font-medium': level >= 3,\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500': item.expanded\n }\"\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\">\n\n <div class=\"flex items-center gap-2\">\n\n <i [class]=\"item.icon + ' text-base'\"></i>\n\n <span>\n {{ item.label | translate }}\n </span>\n\n </div>\n\n <i\n class=\"pi\"\n [ngClass]=\"item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\"\n style=\"font-size:0.6rem;\">\n </i>\n\n </div>\n\n @if (item.expanded) {\n <div class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\">\n\n <ng-container\n *ngTemplateOutlet=\"renderMenu; context:{ $implicit: item.items, level: level + 1 }\">\n </ng-container>\n\n </div>\n }\n\n </div>\n }\n\n }\n</ng-template>\n\n </div>\n}\n\n</aside>\n\n<!-- \uD83C\uDF1F \u0627\u0644\u0632\u0631 \u0627\u0644\u0639\u0627\u0626\u0645 \u0627\u0644\u062D\u062F\u064A\u062B -->\n@if (isMobile && !sidebarVisible) {\n <button\n class=\"floating-btn\"\n (click)=\"openMenu()\"\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\n tooltipPosition=\"top\">\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\n </button>\n}\n", styles: ["@charset \"UTF-8\";@keyframes slideIn{0%{transform:translate(60px);opacity:0}to{transform:translate(0);opacity:1}}.animate-slideIn{animation:slideIn .35s cubic-bezier(.25,1,.5,1)}.glass-bg{background:#ffffffbf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.25)}@media(max-width:1024px){aside{position:fixed;top:0;right:0;height:100vh;z-index:50}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700));box-shadow:0 4px 18px #00000040;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{width:28px;height:28px;border-radius:10px}.active-link{background-color:var(--p-primary-500)!important;color:#fff!important;font-weight:600;box-shadow:0 4px 6px -1px #0000001a;transform:translate(-3px)}.active-link i{color:#fff!important}.active-item-link{background:linear-gradient(to left,var(--p-primary-50),transparent);color:var(--p-primary-600)!important;position:relative;border-right:3px solid var(--p-primary-500);border-radius:0 12px 12px 0}.active-item-link i{color:var(--p-primary-500);filter:drop-shadow(0 0 5px rgba(var(--p-primary-500-rgb),.4))}.active-item-link span{font-weight:700}.animate-slideIn{animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{background:#0000001a;border-radius:10px}.active-link{background-color:var(--p-primary-50)!important;color:var(--p-primary-700)!important;border-right:4px solid var(--p-primary-500)!important;border-radius:4px 12px 12px 4px!important}.active-link span{font-weight:800!important}.active-link i{color:var(--p-primary-600)!important;transform:scale(1.1)}aside{-webkit-font-smoothing:antialiased;letter-spacing:-.01em}.dark .active-link{background-color:rgba(var(--p-primary-500-rgb),.15)!important;color:var(--p-primary-300)!important}.submenu{animation:menuOpen .25s ease}@keyframes menuOpen{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}aside{box-shadow:0 10px 40px #00000026}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1511
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: RoutesComponent, isStandalone: true, selector: "app-routes", host: { listeners: { "window:resize": "onResize()" } }, ngImport: i0, template: "<aside class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\r\n [ngClass]=\"{ 'w-0 overflow-hidden': !sidebarVisible && isMobile }\">\r\n\r\n <!-- \uD83C\uDFA8 \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A \u0627\u0644\u0631\u0626\u064A\u0633\u064A -->\r\n <div\r\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl\r\n bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700\r\n text-white rounded-r-3xl\">\r\n\r\n <!-- \uD83D\uDD1D \u0627\u0644\u0623\u0639\u0644\u0649 -->\r\n <div class=\"flex flex-col items-center gap-4\">\r\n <img src=\"/assets/logo.png\" alt=\"Logo\"\r\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"/>\r\n\r\n <!-- \u0632\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 -->\r\n <!-- [pTooltip]=\"'TOGGLE_MENU' | translate\" -->\r\n <button (click)=\"toggleAll()\"\r\n tooltipPosition=\"right\"\r\n class=\"text-white hover:scale-110 transition-transform duration-200\">\r\n <i class=\"pi pi-bars text-lg\"></i>\r\n </button>\r\n\r\n <!-- \u0623\u064A\u0642\u0648\u0646\u0627\u062A -->\r\n @for (item of secondToLastLevel$ | async; track item) {\r\n <div class=\"relative flex flex-col items-center\">\r\n <!-- \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629 -->\r\n <div (click)=\"onMainClick(item)\"\r\n [pTooltip]=\"item.label | translate\"\r\n tooltipPosition=\"right\"\r\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer\r\n hover:bg-white/20 transition-all duration-200\"\r\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\">\r\n <i [class]=\"item.icon + ' text-xl'\"></i>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- \u2699\uFE0F \u0627\u0644\u0623\u0633\u0641\u0644 -->\r\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\r\n <i class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"></i>\r\n </div>\r\n </div>\r\n\r\n <!-- \uD83D\uDCCB \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0641\u0631\u0639\u064A\u0629 -->\r\n @if (subSidebarVisible) {\r\n <div\r\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn\r\n shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\r\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': isMobile }\">\r\n <!-- \u0632\u0631 \u0631\u062C\u0648\u0639 -->\r\n <!-- \uD83D\uDD1D \u0631\u0623\u0633 \u0627\u0644\u0634\u062C\u0631\u0629 -->\r\n<!-- \uD83D\uDD1D \u0631\u0623\u0633 \u0627\u0644\u0634\u062C\u0631\u0629 -->\r\n<div class=\"tree-header mb-1\">\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"closeMenu()\"\r\n class=\"tree-back-btn\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n <span>{{ 'back' | translate }}</span>\r\n </button>\r\n\r\n <div class=\"tree-header-actions\">\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-mini-btn\"\r\n (click)=\"expandAll()\"\r\n pTooltip=\"\u0641\u062A\u062D \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-plus\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-mini-btn\"\r\n (click)=\"collapseAll()\"\r\n pTooltip=\"\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-minus\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-search-toggle\"\r\n [ngClass]=\"{ 'active': showTreeSearch }\"\r\n (click)=\"toggleTreeSearch()\"\r\n pTooltip=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-search\"></i>\r\n </button>\r\n\r\n </div>\r\n\r\n</div>\r\n\r\n@if (showTreeSearch) {\r\n <div class=\"tree-search-panel mb-4 animate-slideIn\">\r\n <div class=\"tree-search\">\r\n <i class=\"pi pi-search\"></i>\r\n\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"searchText\"\r\n (input)=\"onSearchChange()\"\r\n placeholder=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A...\"\r\n class=\"tree-search-input\" />\r\n\r\n @if (searchText) {\r\n <button\r\n type=\"button\"\r\n class=\"tree-search-clear\"\r\n (click)=\"clearSearch()\">\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n}\r\n\r\n\r\n <!-- Recursive rendering -->\r\n @if (menuItems$ | async; as menuItems) {\r\n <ng-container *ngTemplateOutlet=\"renderMenu; context:{ $implicit: menuItems, level: 1 }\"></ng-container>\r\n}\r\n\r\n<ng-template #renderMenu let-items let-level=\"level\">\r\n @for (item of items; track item) {\r\n\r\n @if (!item.items?.length) {\r\n @let link = getLinkProps(item);\r\n <div class=\"mb-1\">\r\n @if (link.isExternal) {\r\n <a [href]=\"link.href\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">{{ item.label | translate }}</span>\r\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\r\n </a>\r\n } @else {\r\n <div class=\"flex items-center gap-2\">\r\n <a [routerLink]=\"link.routerLink\"\r\n (click)=\"onNavigate()\"\r\n routerLinkActive=\"active-link\"\r\n [ngClass]=\"{ 'search-match': isSearchMatch(item) }\"\r\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">\r\n {{ item.label | translate }}</span>\r\n </a>\r\n\r\n@if (link.addRoute) {\r\n <a\r\n [routerLink]=\"[link.addRoute]\"\r\n (click)=\"$event.stopPropagation(); onNavigate()\"\r\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\r\n [pTooltip]=\"'ADD' | translate\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </a>\r\n}\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n @if (item.items?.length) {\r\n <div class=\"mb-1\">\r\n\r\n <div\r\n (click)=\"onParentClick(item)\"\r\n [style.font-size.rem]=\"1.1 - (level * 0.05)\"\r\n[ngClass]=\"{\r\n 'font-bold': level === 1,\r\n 'font-semibold': level === 2,\r\n 'font-medium': level >= 3,\r\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500': item.expanded,\r\n 'search-match': isSearchMatch(item)\r\n}\"\r\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\">\r\n\r\n <div class=\"flex items-center gap-2\">\r\n\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n\r\n <span>\r\n {{ item.label | translate }}\r\n </span>\r\n\r\n </div>\r\n\r\n <i\r\n class=\"pi\"\r\n [ngClass]=\"item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\"\r\n style=\"font-size:0.6rem;\">\r\n </i>\r\n\r\n </div>\r\n\r\n @if (item.expanded) {\r\n <div class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\">\r\n\r\n <ng-container\r\n *ngTemplateOutlet=\"renderMenu; context:{ $implicit: item.items, level: level + 1 }\">\r\n </ng-container>\r\n\r\n </div>\r\n }\r\n\r\n </div>\r\n }\r\n\r\n }\r\n</ng-template>\r\n\r\n </div>\r\n}\r\n\r\n</aside>\r\n\r\n<!-- \uD83C\uDF1F \u0627\u0644\u0632\u0631 \u0627\u0644\u0639\u0627\u0626\u0645 \u0627\u0644\u062D\u062F\u064A\u062B -->\r\n@if (isMobile && !sidebarVisible) {\r\n <button\r\n class=\"floating-btn\"\r\n (click)=\"openMenu()\"\r\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\r\n tooltipPosition=\"top\">\r\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";@keyframes slideIn{0%{transform:translate(60px);opacity:0}to{transform:translate(0);opacity:1}}.animate-slideIn{animation:slideIn .35s cubic-bezier(.25,1,.5,1)}.glass-bg{background:#ffffffbf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.25)}@media(max-width:1024px){aside{position:fixed;top:0;right:0;height:100vh;z-index:50}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700));box-shadow:0 4px 18px #00000040;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{width:28px;height:28px;border-radius:10px}.active-link{background-color:var(--p-primary-500)!important;color:#fff!important;font-weight:600;box-shadow:0 4px 6px -1px #0000001a;transform:translate(-3px)}.active-link i{color:#fff!important}.active-item-link{background:linear-gradient(to left,var(--p-primary-50),transparent);color:var(--p-primary-600)!important;position:relative;border-right:3px solid var(--p-primary-500);border-radius:0 12px 12px 0}.active-item-link i{color:var(--p-primary-500);filter:drop-shadow(0 0 5px rgba(var(--p-primary-500-rgb),.4))}.active-item-link span{font-weight:700}.animate-slideIn{animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{background:#0000001a;border-radius:10px}.active-link{background-color:var(--p-primary-50)!important;color:var(--p-primary-700)!important;border-right:4px solid var(--p-primary-500)!important;border-radius:4px 12px 12px 4px!important}.active-link span{font-weight:800!important}.active-link i{color:var(--p-primary-600)!important;transform:scale(1.1)}aside{-webkit-font-smoothing:antialiased;letter-spacing:-.01em}.dark .active-link{background-color:rgba(var(--p-primary-500-rgb),.15)!important;color:var(--p-primary-300)!important}.submenu{animation:menuOpen .25s ease}@keyframes menuOpen{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}aside{box-shadow:0 10px 40px #00000026}.tree-back-btn{height:2.25rem;padding:0 .35rem 0 .75rem;display:inline-flex;align-items:center;gap:.35rem;color:#64748b;font-weight:700;border-radius:999px;transition:all .2s ease}.tree-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.tree-back-btn{height:2.35rem;padding:0 .45rem 0 .85rem;display:inline-flex;align-items:center;gap:.4rem;color:#64748b;font-size:.86rem;font-weight:700;border-radius:999px;transition:all .22s ease}.tree-back-btn:hover{color:var(--p-primary-600);background:var(--p-primary-50)}.tree-back-btn i{font-size:.85rem}.tree-header-actions{display:inline-flex;align-items:center;gap:.3rem}.tree-mini-btn,.tree-search-toggle{width:2rem;height:2rem;border-radius:.8rem;display:inline-flex;align-items:center;justify-content:center;color:#64748b;background:#f8fafcd9;border:1px solid rgba(148,163,184,.24);transition:all .2s ease}.tree-mini-btn i,.tree-search-toggle i{font-size:.72rem}.tree-mini-btn:hover,.tree-search-toggle:hover{color:var(--p-primary-600);background:var(--p-primary-50);border-color:rgba(var(--p-primary-500-rgb),.25);transform:translateY(-1px)}.tree-search-toggle{color:var(--p-primary-600);background:rgba(var(--p-primary-500-rgb),.08);border-color:rgba(var(--p-primary-500-rgb),.18)}.tree-search-toggle.active{color:#fff;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-600));border-color:transparent;box-shadow:0 8px 18px rgba(var(--p-primary-500-rgb),.22)}.tree-search-panel{padding:.65rem;border-radius:1.15rem;background:#ffffff94;border:1px solid rgba(255,255,255,.45);box-shadow:0 10px 30px #0f172a14;backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%)}.tree-search{position:relative;display:flex;align-items:center}.tree-search i.pi-search{position:absolute;right:.85rem;color:var(--p-primary-500);font-size:.85rem;z-index:1}.tree-search-input{width:100%;height:2.45rem;padding:0 2.35rem 0 2.2rem;border-radius:999px;border:1px solid rgba(148,163,184,.35);background:#ffffffd1;color:#334155;font-size:.86rem;outline:none;transition:all .25s ease}.tree-search-input:focus{border-color:var(--p-primary-400);box-shadow:0 0 0 4px rgba(var(--p-primary-500-rgb),.12);background:#fff}.tree-search-clear{position:absolute;left:.55rem;width:1.75rem;height:1.75rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:#64748b;background:#f1f5f9e6;transition:all .2s ease}.tree-search-clear:hover{color:var(--p-primary-600);background:var(--p-primary-50);transform:scale(1.05)}.tree-search-icon{position:absolute;right:.85rem;color:#94a3b8;font-size:.85rem;pointer-events:none}.tree-search-input{width:100%;height:2.45rem;padding:0 2.35rem 0 2.2rem;border-radius:.95rem;border:1px solid rgba(148,163,184,.28);background:#f8fafcd1;color:#334155;font-size:.86rem;outline:none;transition:all .22s ease}.tree-search-input:focus{border-color:rgba(var(--p-primary-500-rgb),.45);background:#fff;box-shadow:0 0 0 3px rgba(var(--p-primary-500-rgb),.1)}.tree-search-input::placeholder{color:#94a3b8}.tree-search-clear{position:absolute;left:.55rem;width:1.65rem;height:1.65rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;transition:all .2s ease}.tree-search-clear:hover{color:var(--p-primary-600);background:var(--p-primary-50)}.tree-search-clear i{font-size:.7rem}.dark .tree-back-btn{color:#cbd5e1}.dark .tree-back-btn:hover{color:var(--p-primary-300);background:rgba(var(--p-primary-500-rgb),.12)}.dark .tree-header-actions{background:#1f2937b8;border-color:#94a3b824}.dark .tree-icon-btn{color:#cbd5e1}.dark .tree-icon-btn:hover{color:#fff;background:var(--p-primary-600)}.dark .tree-search-icon{color:#64748b}.dark .tree-search-input{background:#1f2937bd;border-color:#94a3b829;color:#e5e7eb}.dark .tree-search-input:focus{background:#111827eb;border-color:rgba(var(--p-primary-500-rgb),.48)}.dark .tree-search-input::placeholder{color:#64748b}.dark .tree-search-clear{color:#94a3b8}.dark .tree-search-clear:hover{color:var(--p-primary-300);background:rgba(var(--p-primary-500-rgb),.12)}.search-match{background:linear-gradient(to left,rgba(var(--p-primary-500-rgb),.16),transparent)!important;color:var(--p-primary-700)!important;border-right:3px solid var(--p-primary-500)!important;box-shadow:inset 0 0 0 1px rgba(var(--p-primary-500-rgb),.08)}.search-match span{font-weight:800!important}.search-match i{color:var(--p-primary-600)!important}.dark .tree-toolbar{background:#111827b8;border-color:#ffffff14}.dark .tree-search-input{background:#1f2937cc;border-color:#94a3b82e;color:#e5e7eb}.dark .tree-search-input:focus{background:#111827f2}.dark .tree-search-clear{background:#374151e6;color:#cbd5e1}.dark .tree-action-btn{background:rgba(var(--p-primary-500-rgb),.12);color:var(--p-primary-300);border-color:rgba(var(--p-primary-500-rgb),.22)}.dark .tree-action-btn:hover{background:var(--p-primary-600);color:#fff}.dark .search-match{background:rgba(var(--p-primary-500-rgb),.18)!important;color:var(--p-primary-300)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: 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: "ngmodule", type: // ✅ أضف هذا
1512
+ TooltipModule }, { kind: "directive", type: i4$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1438
1513
  }
1439
1514
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesComponent, decorators: [{
1440
1515
  type: Component,
1441
- args: [{ selector: 'app-routes', standalone: true, imports: [CommonModule, RouterModule, TooltipModule, TranslatePipe, StyleClassModule], template: "<aside class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\n [ngClass]=\"{ 'w-0 overflow-hidden': !sidebarVisible && isMobile }\">\n\n <!-- \uD83C\uDFA8 \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A \u0627\u0644\u0631\u0626\u064A\u0633\u064A -->\n <div\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl\n bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700\n text-white rounded-r-3xl\">\n\n <!-- \uD83D\uDD1D \u0627\u0644\u0623\u0639\u0644\u0649 -->\n <div class=\"flex flex-col items-center gap-4\">\n <img src=\"/assets/logo.png\" alt=\"Logo\"\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"/>\n\n <!-- \u0632\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 -->\n <!-- [pTooltip]=\"'TOGGLE_MENU' | translate\" -->\n <button (click)=\"toggleAll()\"\n tooltipPosition=\"right\"\n class=\"text-white hover:scale-110 transition-transform duration-200\">\n <i class=\"pi pi-bars text-lg\"></i>\n </button>\n\n <!-- \u0623\u064A\u0642\u0648\u0646\u0627\u062A -->\n @for (item of secondToLastLevel$ | async; track item) {\n <div class=\"relative flex flex-col items-center\">\n <!-- \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629 -->\n <div (click)=\"onMainClick(item)\"\n [pTooltip]=\"item.label | translate\"\n tooltipPosition=\"right\"\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer\n hover:bg-white/20 transition-all duration-200\"\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\">\n <i [class]=\"item.icon + ' text-xl'\"></i>\n </div>\n </div>\n }\n </div>\n\n <!-- \u2699\uFE0F \u0627\u0644\u0623\u0633\u0641\u0644 -->\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\n <i class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"></i>\n </div>\n </div>\n\n <!-- \uD83D\uDCCB \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0641\u0631\u0639\u064A\u0629 -->\n @if (subSidebarVisible) {\n <div\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn\n shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': isMobile }\">\n <!-- \u0632\u0631 \u0631\u062C\u0648\u0639 -->\n <button (click)=\"closeMenu()\"\n class=\"flex items-center gap-2 mb-4 text-gray-500 dark:text-gray-300 hover:text-primary-600 transition\">\n <i class=\"pi\" [ngClass]=\"isMobile ? 'pi-angle-right' : 'pi-angle-right'\"></i>\n <span>{{ 'back' | translate }}</span>\n </button>\n <!-- Recursive rendering -->\n @if (menuItems$ | async; as menuItems) {\n <ng-container *ngTemplateOutlet=\"renderMenu; context:{ $implicit: menuItems, level: 1 }\"></ng-container>\n}\n\n<ng-template #renderMenu let-items let-level=\"level\">\n @for (item of items; track item) {\n\n @if (!item.items?.length) {\n @let link = getLinkProps(item);\n <div class=\"mb-1\">\n @if (link.isExternal) {\n <a [href]=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">{{ item.label | translate }}</span>\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\n </a>\n } @else {\n <div class=\"flex items-center gap-2\">\n <a [routerLink]=\"link.routerLink\"\n (click)=\"onNavigate()\"\n routerLinkActive=\"active-link\"\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">\n {{ item.label | translate }}</span>\n </a>\n\n@if (link.addRoute) {\n <a\n [routerLink]=\"[link.addRoute]\"\n (click)=\"$event.stopPropagation(); onNavigate()\"\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\n [pTooltip]=\"'ADD' | translate\"\n tooltipPosition=\"top\">\n <i class=\"pi pi-plus text-xs\"></i>\n </a>\n}\n </div>\n }\n</div>\n}\n\n @if (item.items?.length) {\n <div class=\"mb-1\">\n\n <div\n (click)=\"onParentClick(item)\"\n [style.font-size.rem]=\"1.1 - (level * 0.05)\"\n [ngClass]=\"{\n 'font-bold': level === 1,\n 'font-semibold': level === 2,\n 'font-medium': level >= 3,\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500': item.expanded\n }\"\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\">\n\n <div class=\"flex items-center gap-2\">\n\n <i [class]=\"item.icon + ' text-base'\"></i>\n\n <span>\n {{ item.label | translate }}\n </span>\n\n </div>\n\n <i\n class=\"pi\"\n [ngClass]=\"item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\"\n style=\"font-size:0.6rem;\">\n </i>\n\n </div>\n\n @if (item.expanded) {\n <div class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\">\n\n <ng-container\n *ngTemplateOutlet=\"renderMenu; context:{ $implicit: item.items, level: level + 1 }\">\n </ng-container>\n\n </div>\n }\n\n </div>\n }\n\n }\n</ng-template>\n\n </div>\n}\n\n</aside>\n\n<!-- \uD83C\uDF1F \u0627\u0644\u0632\u0631 \u0627\u0644\u0639\u0627\u0626\u0645 \u0627\u0644\u062D\u062F\u064A\u062B -->\n@if (isMobile && !sidebarVisible) {\n <button\n class=\"floating-btn\"\n (click)=\"openMenu()\"\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\n tooltipPosition=\"top\">\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\n </button>\n}\n", styles: ["@charset \"UTF-8\";@keyframes slideIn{0%{transform:translate(60px);opacity:0}to{transform:translate(0);opacity:1}}.animate-slideIn{animation:slideIn .35s cubic-bezier(.25,1,.5,1)}.glass-bg{background:#ffffffbf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.25)}@media(max-width:1024px){aside{position:fixed;top:0;right:0;height:100vh;z-index:50}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700));box-shadow:0 4px 18px #00000040;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{width:28px;height:28px;border-radius:10px}.active-link{background-color:var(--p-primary-500)!important;color:#fff!important;font-weight:600;box-shadow:0 4px 6px -1px #0000001a;transform:translate(-3px)}.active-link i{color:#fff!important}.active-item-link{background:linear-gradient(to left,var(--p-primary-50),transparent);color:var(--p-primary-600)!important;position:relative;border-right:3px solid var(--p-primary-500);border-radius:0 12px 12px 0}.active-item-link i{color:var(--p-primary-500);filter:drop-shadow(0 0 5px rgba(var(--p-primary-500-rgb),.4))}.active-item-link span{font-weight:700}.animate-slideIn{animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{background:#0000001a;border-radius:10px}.active-link{background-color:var(--p-primary-50)!important;color:var(--p-primary-700)!important;border-right:4px solid var(--p-primary-500)!important;border-radius:4px 12px 12px 4px!important}.active-link span{font-weight:800!important}.active-link i{color:var(--p-primary-600)!important;transform:scale(1.1)}aside{-webkit-font-smoothing:antialiased;letter-spacing:-.01em}.dark .active-link{background-color:rgba(var(--p-primary-500-rgb),.15)!important;color:var(--p-primary-300)!important}.submenu{animation:menuOpen .25s ease}@keyframes menuOpen{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}aside{box-shadow:0 10px 40px #00000026}\n"] }]
1516
+ args: [{ selector: 'app-routes', standalone: true, imports: [
1517
+ CommonModule,
1518
+ RouterModule,
1519
+ FormsModule, // ✅ أضف هذا
1520
+ TooltipModule,
1521
+ TranslatePipe,
1522
+ StyleClassModule,
1523
+ ButtonModule
1524
+ ], template: "<aside class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\r\n [ngClass]=\"{ 'w-0 overflow-hidden': !sidebarVisible && isMobile }\">\r\n\r\n <!-- \uD83C\uDFA8 \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A \u0627\u0644\u0631\u0626\u064A\u0633\u064A -->\r\n <div\r\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl\r\n bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700\r\n text-white rounded-r-3xl\">\r\n\r\n <!-- \uD83D\uDD1D \u0627\u0644\u0623\u0639\u0644\u0649 -->\r\n <div class=\"flex flex-col items-center gap-4\">\r\n <img src=\"/assets/logo.png\" alt=\"Logo\"\r\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"/>\r\n\r\n <!-- \u0632\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 -->\r\n <!-- [pTooltip]=\"'TOGGLE_MENU' | translate\" -->\r\n <button (click)=\"toggleAll()\"\r\n tooltipPosition=\"right\"\r\n class=\"text-white hover:scale-110 transition-transform duration-200\">\r\n <i class=\"pi pi-bars text-lg\"></i>\r\n </button>\r\n\r\n <!-- \u0623\u064A\u0642\u0648\u0646\u0627\u062A -->\r\n @for (item of secondToLastLevel$ | async; track item) {\r\n <div class=\"relative flex flex-col items-center\">\r\n <!-- \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629 -->\r\n <div (click)=\"onMainClick(item)\"\r\n [pTooltip]=\"item.label | translate\"\r\n tooltipPosition=\"right\"\r\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer\r\n hover:bg-white/20 transition-all duration-200\"\r\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\">\r\n <i [class]=\"item.icon + ' text-xl'\"></i>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- \u2699\uFE0F \u0627\u0644\u0623\u0633\u0641\u0644 -->\r\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\r\n <i class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"></i>\r\n </div>\r\n </div>\r\n\r\n <!-- \uD83D\uDCCB \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0641\u0631\u0639\u064A\u0629 -->\r\n @if (subSidebarVisible) {\r\n <div\r\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn\r\n shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\r\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': isMobile }\">\r\n <!-- \u0632\u0631 \u0631\u062C\u0648\u0639 -->\r\n <!-- \uD83D\uDD1D \u0631\u0623\u0633 \u0627\u0644\u0634\u062C\u0631\u0629 -->\r\n<!-- \uD83D\uDD1D \u0631\u0623\u0633 \u0627\u0644\u0634\u062C\u0631\u0629 -->\r\n<div class=\"tree-header mb-1\">\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"closeMenu()\"\r\n class=\"tree-back-btn\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n <span>{{ 'back' | translate }}</span>\r\n </button>\r\n\r\n <div class=\"tree-header-actions\">\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-mini-btn\"\r\n (click)=\"expandAll()\"\r\n pTooltip=\"\u0641\u062A\u062D \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-plus\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-mini-btn\"\r\n (click)=\"collapseAll()\"\r\n pTooltip=\"\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-minus\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"tree-search-toggle\"\r\n [ngClass]=\"{ 'active': showTreeSearch }\"\r\n (click)=\"toggleTreeSearch()\"\r\n pTooltip=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-search\"></i>\r\n </button>\r\n\r\n </div>\r\n\r\n</div>\r\n\r\n@if (showTreeSearch) {\r\n <div class=\"tree-search-panel mb-4 animate-slideIn\">\r\n <div class=\"tree-search\">\r\n <i class=\"pi pi-search\"></i>\r\n\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"searchText\"\r\n (input)=\"onSearchChange()\"\r\n placeholder=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A...\"\r\n class=\"tree-search-input\" />\r\n\r\n @if (searchText) {\r\n <button\r\n type=\"button\"\r\n class=\"tree-search-clear\"\r\n (click)=\"clearSearch()\">\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n}\r\n\r\n\r\n <!-- Recursive rendering -->\r\n @if (menuItems$ | async; as menuItems) {\r\n <ng-container *ngTemplateOutlet=\"renderMenu; context:{ $implicit: menuItems, level: 1 }\"></ng-container>\r\n}\r\n\r\n<ng-template #renderMenu let-items let-level=\"level\">\r\n @for (item of items; track item) {\r\n\r\n @if (!item.items?.length) {\r\n @let link = getLinkProps(item);\r\n <div class=\"mb-1\">\r\n @if (link.isExternal) {\r\n <a [href]=\"link.href\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">{{ item.label | translate }}</span>\r\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\r\n </a>\r\n } @else {\r\n <div class=\"flex items-center gap-2\">\r\n <a [routerLink]=\"link.routerLink\"\r\n (click)=\"onNavigate()\"\r\n routerLinkActive=\"active-link\"\r\n [ngClass]=\"{ 'search-match': isSearchMatch(item) }\"\r\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">\r\n {{ item.label | translate }}</span>\r\n </a>\r\n\r\n@if (link.addRoute) {\r\n <a\r\n [routerLink]=\"[link.addRoute]\"\r\n (click)=\"$event.stopPropagation(); onNavigate()\"\r\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\r\n [pTooltip]=\"'ADD' | translate\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </a>\r\n}\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n @if (item.items?.length) {\r\n <div class=\"mb-1\">\r\n\r\n <div\r\n (click)=\"onParentClick(item)\"\r\n [style.font-size.rem]=\"1.1 - (level * 0.05)\"\r\n[ngClass]=\"{\r\n 'font-bold': level === 1,\r\n 'font-semibold': level === 2,\r\n 'font-medium': level >= 3,\r\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500': item.expanded,\r\n 'search-match': isSearchMatch(item)\r\n}\"\r\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\">\r\n\r\n <div class=\"flex items-center gap-2\">\r\n\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n\r\n <span>\r\n {{ item.label | translate }}\r\n </span>\r\n\r\n </div>\r\n\r\n <i\r\n class=\"pi\"\r\n [ngClass]=\"item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\"\r\n style=\"font-size:0.6rem;\">\r\n </i>\r\n\r\n </div>\r\n\r\n @if (item.expanded) {\r\n <div class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\">\r\n\r\n <ng-container\r\n *ngTemplateOutlet=\"renderMenu; context:{ $implicit: item.items, level: level + 1 }\">\r\n </ng-container>\r\n\r\n </div>\r\n }\r\n\r\n </div>\r\n }\r\n\r\n }\r\n</ng-template>\r\n\r\n </div>\r\n}\r\n\r\n</aside>\r\n\r\n<!-- \uD83C\uDF1F \u0627\u0644\u0632\u0631 \u0627\u0644\u0639\u0627\u0626\u0645 \u0627\u0644\u062D\u062F\u064A\u062B -->\r\n@if (isMobile && !sidebarVisible) {\r\n <button\r\n class=\"floating-btn\"\r\n (click)=\"openMenu()\"\r\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\r\n tooltipPosition=\"top\">\r\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";@keyframes slideIn{0%{transform:translate(60px);opacity:0}to{transform:translate(0);opacity:1}}.animate-slideIn{animation:slideIn .35s cubic-bezier(.25,1,.5,1)}.glass-bg{background:#ffffffbf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.25)}@media(max-width:1024px){aside{position:fixed;top:0;right:0;height:100vh;z-index:50}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700));box-shadow:0 4px 18px #00000040;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{width:28px;height:28px;border-radius:10px}.active-link{background-color:var(--p-primary-500)!important;color:#fff!important;font-weight:600;box-shadow:0 4px 6px -1px #0000001a;transform:translate(-3px)}.active-link i{color:#fff!important}.active-item-link{background:linear-gradient(to left,var(--p-primary-50),transparent);color:var(--p-primary-600)!important;position:relative;border-right:3px solid var(--p-primary-500);border-radius:0 12px 12px 0}.active-item-link i{color:var(--p-primary-500);filter:drop-shadow(0 0 5px rgba(var(--p-primary-500-rgb),.4))}.active-item-link span{font-weight:700}.animate-slideIn{animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{background:#0000001a;border-radius:10px}.active-link{background-color:var(--p-primary-50)!important;color:var(--p-primary-700)!important;border-right:4px solid var(--p-primary-500)!important;border-radius:4px 12px 12px 4px!important}.active-link span{font-weight:800!important}.active-link i{color:var(--p-primary-600)!important;transform:scale(1.1)}aside{-webkit-font-smoothing:antialiased;letter-spacing:-.01em}.dark .active-link{background-color:rgba(var(--p-primary-500-rgb),.15)!important;color:var(--p-primary-300)!important}.submenu{animation:menuOpen .25s ease}@keyframes menuOpen{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}aside{box-shadow:0 10px 40px #00000026}.tree-back-btn{height:2.25rem;padding:0 .35rem 0 .75rem;display:inline-flex;align-items:center;gap:.35rem;color:#64748b;font-weight:700;border-radius:999px;transition:all .2s ease}.tree-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem}.tree-back-btn{height:2.35rem;padding:0 .45rem 0 .85rem;display:inline-flex;align-items:center;gap:.4rem;color:#64748b;font-size:.86rem;font-weight:700;border-radius:999px;transition:all .22s ease}.tree-back-btn:hover{color:var(--p-primary-600);background:var(--p-primary-50)}.tree-back-btn i{font-size:.85rem}.tree-header-actions{display:inline-flex;align-items:center;gap:.3rem}.tree-mini-btn,.tree-search-toggle{width:2rem;height:2rem;border-radius:.8rem;display:inline-flex;align-items:center;justify-content:center;color:#64748b;background:#f8fafcd9;border:1px solid rgba(148,163,184,.24);transition:all .2s ease}.tree-mini-btn i,.tree-search-toggle i{font-size:.72rem}.tree-mini-btn:hover,.tree-search-toggle:hover{color:var(--p-primary-600);background:var(--p-primary-50);border-color:rgba(var(--p-primary-500-rgb),.25);transform:translateY(-1px)}.tree-search-toggle{color:var(--p-primary-600);background:rgba(var(--p-primary-500-rgb),.08);border-color:rgba(var(--p-primary-500-rgb),.18)}.tree-search-toggle.active{color:#fff;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-600));border-color:transparent;box-shadow:0 8px 18px rgba(var(--p-primary-500-rgb),.22)}.tree-search-panel{padding:.65rem;border-radius:1.15rem;background:#ffffff94;border:1px solid rgba(255,255,255,.45);box-shadow:0 10px 30px #0f172a14;backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%)}.tree-search{position:relative;display:flex;align-items:center}.tree-search i.pi-search{position:absolute;right:.85rem;color:var(--p-primary-500);font-size:.85rem;z-index:1}.tree-search-input{width:100%;height:2.45rem;padding:0 2.35rem 0 2.2rem;border-radius:999px;border:1px solid rgba(148,163,184,.35);background:#ffffffd1;color:#334155;font-size:.86rem;outline:none;transition:all .25s ease}.tree-search-input:focus{border-color:var(--p-primary-400);box-shadow:0 0 0 4px rgba(var(--p-primary-500-rgb),.12);background:#fff}.tree-search-clear{position:absolute;left:.55rem;width:1.75rem;height:1.75rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:#64748b;background:#f1f5f9e6;transition:all .2s ease}.tree-search-clear:hover{color:var(--p-primary-600);background:var(--p-primary-50);transform:scale(1.05)}.tree-search-icon{position:absolute;right:.85rem;color:#94a3b8;font-size:.85rem;pointer-events:none}.tree-search-input{width:100%;height:2.45rem;padding:0 2.35rem 0 2.2rem;border-radius:.95rem;border:1px solid rgba(148,163,184,.28);background:#f8fafcd1;color:#334155;font-size:.86rem;outline:none;transition:all .22s ease}.tree-search-input:focus{border-color:rgba(var(--p-primary-500-rgb),.45);background:#fff;box-shadow:0 0 0 3px rgba(var(--p-primary-500-rgb),.1)}.tree-search-input::placeholder{color:#94a3b8}.tree-search-clear{position:absolute;left:.55rem;width:1.65rem;height:1.65rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;color:#94a3b8;background:transparent;transition:all .2s ease}.tree-search-clear:hover{color:var(--p-primary-600);background:var(--p-primary-50)}.tree-search-clear i{font-size:.7rem}.dark .tree-back-btn{color:#cbd5e1}.dark .tree-back-btn:hover{color:var(--p-primary-300);background:rgba(var(--p-primary-500-rgb),.12)}.dark .tree-header-actions{background:#1f2937b8;border-color:#94a3b824}.dark .tree-icon-btn{color:#cbd5e1}.dark .tree-icon-btn:hover{color:#fff;background:var(--p-primary-600)}.dark .tree-search-icon{color:#64748b}.dark .tree-search-input{background:#1f2937bd;border-color:#94a3b829;color:#e5e7eb}.dark .tree-search-input:focus{background:#111827eb;border-color:rgba(var(--p-primary-500-rgb),.48)}.dark .tree-search-input::placeholder{color:#64748b}.dark .tree-search-clear{color:#94a3b8}.dark .tree-search-clear:hover{color:var(--p-primary-300);background:rgba(var(--p-primary-500-rgb),.12)}.search-match{background:linear-gradient(to left,rgba(var(--p-primary-500-rgb),.16),transparent)!important;color:var(--p-primary-700)!important;border-right:3px solid var(--p-primary-500)!important;box-shadow:inset 0 0 0 1px rgba(var(--p-primary-500-rgb),.08)}.search-match span{font-weight:800!important}.search-match i{color:var(--p-primary-600)!important}.dark .tree-toolbar{background:#111827b8;border-color:#ffffff14}.dark .tree-search-input{background:#1f2937cc;border-color:#94a3b82e;color:#e5e7eb}.dark .tree-search-input:focus{background:#111827f2}.dark .tree-search-clear{background:#374151e6;color:#cbd5e1}.dark .tree-action-btn{background:rgba(var(--p-primary-500-rgb),.12);color:var(--p-primary-300);border-color:rgba(var(--p-primary-500-rgb),.22)}.dark .tree-action-btn:hover{background:var(--p-primary-600);color:#fff}.dark .search-match{background:rgba(var(--p-primary-500-rgb),.18)!important;color:var(--p-primary-300)!important}\n"] }]
1442
1525
  }], ctorParameters: () => [], propDecorators: { onResize: [{
1443
1526
  type: HostListener,
1444
1527
  args: ['window:resize']
@@ -1447,11 +1530,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
1447
1530
  class AuthWrapperComponent {
1448
1531
  constructor() { }
1449
1532
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AuthWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1450
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AuthWrapperComponent, isStandalone: true, selector: "abp-auth-wrapper", ngImport: i0, template: " <ng-content></ng-content>\n\n\n<!-- <div class=\"row\">\n <div class=\"mx-auto col col-md-5\">\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\n <abp-tenant-box\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\n ></abp-tenant-box>\n }\n\n <div class=\"abp-account-container\">\n @if (service.enableLocalLogin$ | async) {\n <div class=\"card mt-3 shadow-sm rounded\">\n <div class=\"card-body p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n } @else {\n <div class=\"alert alert-warning\">\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\n </div>\n }\n </div>\n </div>\n</div> -->\n" });
1533
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AuthWrapperComponent, isStandalone: true, selector: "abp-auth-wrapper", ngImport: i0, template: " <ng-content></ng-content>\r\n\r\n\r\n<!-- <div class=\"row\">\r\n <div class=\"mx-auto col col-md-5\">\r\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\r\n <abp-tenant-box\r\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\r\n ></abp-tenant-box>\r\n }\r\n\r\n <div class=\"abp-account-container\">\r\n @if (service.enableLocalLogin$ | async) {\r\n <div class=\"card mt-3 shadow-sm rounded\">\r\n <div class=\"card-body p-5\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"alert alert-warning\">\r\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\r\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</div> -->\r\n" });
1451
1534
  }
1452
1535
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AuthWrapperComponent, decorators: [{
1453
1536
  type: Component,
1454
- args: [{ standalone: true, imports: [], selector: 'abp-auth-wrapper', template: " <ng-content></ng-content>\n\n\n<!-- <div class=\"row\">\n <div class=\"mx-auto col col-md-5\">\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\n <abp-tenant-box\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\n ></abp-tenant-box>\n }\n\n <div class=\"abp-account-container\">\n @if (service.enableLocalLogin$ | async) {\n <div class=\"card mt-3 shadow-sm rounded\">\n <div class=\"card-body p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n } @else {\n <div class=\"alert alert-warning\">\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\n </div>\n }\n </div>\n </div>\n</div> -->\n" }]
1537
+ args: [{ standalone: true, imports: [], selector: 'abp-auth-wrapper', template: " <ng-content></ng-content>\r\n\r\n\r\n<!-- <div class=\"row\">\r\n <div class=\"mx-auto col col-md-5\">\r\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\r\n <abp-tenant-box\r\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\r\n ></abp-tenant-box>\r\n }\r\n\r\n <div class=\"abp-account-container\">\r\n @if (service.enableLocalLogin$ | async) {\r\n <div class=\"card mt-3 shadow-sm rounded\">\r\n <div class=\"card-body p-5\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"alert alert-warning\">\r\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\r\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</div> -->\r\n" }]
1455
1538
  }], ctorParameters: () => [] });
1456
1539
 
1457
1540
  class AccountLayoutComponent {
@@ -1466,11 +1549,11 @@ class AccountLayoutComponent {
1466
1549
  // this.service.subscribeWindowSize();
1467
1550
  }
1468
1551
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AccountLayoutComponent, deps: [{ token: LayoutService }], target: i0.ɵɵFactoryTarget.Component });
1469
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AccountLayoutComponent, isStandalone: true, selector: "abp-layout-account", providers: [LayoutService, SubscriptionService], ngImport: i0, template: " <abp-auth-wrapper\n *abpReplaceableTemplate=\"{\n componentKey: authWrapperKey\n }\"\n >\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </abp-auth-wrapper>\n", dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AuthWrapperComponent, selector: "abp-auth-wrapper" }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }] });
1552
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AccountLayoutComponent, isStandalone: true, selector: "abp-layout-account", providers: [LayoutService, SubscriptionService], ngImport: i0, template: " <abp-auth-wrapper\r\n *abpReplaceableTemplate=\"{\r\n componentKey: authWrapperKey\r\n }\"\r\n >\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </abp-auth-wrapper>\r\n", dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AuthWrapperComponent, selector: "abp-auth-wrapper" }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }] });
1470
1553
  }
1471
1554
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AccountLayoutComponent, decorators: [{
1472
1555
  type: Component,
1473
- args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, AuthWrapperComponent, ReplaceableTemplateDirective], selector: 'abp-layout-account', providers: [LayoutService, SubscriptionService], template: " <abp-auth-wrapper\n *abpReplaceableTemplate=\"{\n componentKey: authWrapperKey\n }\"\n >\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </abp-auth-wrapper>\n" }]
1556
+ args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, AuthWrapperComponent, ReplaceableTemplateDirective], selector: 'abp-layout-account', providers: [LayoutService, SubscriptionService], template: " <abp-auth-wrapper\r\n *abpReplaceableTemplate=\"{\r\n componentKey: authWrapperKey\r\n }\"\r\n >\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </abp-auth-wrapper>\r\n" }]
1474
1557
  }], ctorParameters: () => [{ type: LayoutService }] });
1475
1558
 
1476
1559
  class ApplicationLayoutComponent {
@@ -1645,18 +1728,18 @@ class ApplicationLayoutComponent {
1645
1728
  catch (error) {
1646
1729
  }
1647
1730
  }
1648
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ApplicationLayoutComponent, deps: [{ token: LayoutService }, { token: i0.Renderer2 }, { token: i2$2.Router }, { token: i0.NgZone }, { token: i3$3.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1649
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ApplicationLayoutComponent, isStandalone: true, selector: "abp-layout-application", providers: [LayoutService, SubscriptionService], ngImport: i0, template: "\n\n<div class=\"flex h-screen overflow-hidden\">\n\n <!-- Sidebar stays fixed -->\n\n <app-routes\n *abpReplaceableTemplate=\"{\n componentKey: service.routesComponentKey,\n inputs: { smallScreen: { value: service.smallScreen } }\n }\"\n class=\"mb-2 md:mb-0\"\n ></app-routes>\n\n <!-- Main content scrolls -->\n <main class=\"flex-1 flex flex-col overflow-hidden\">\n\n <!-- Optional Topbar -->\n <!-- @if (showTopbar) { -->\n\n <app-nav-items\n *abpReplaceableTemplate=\"{\n componentKey: service.navItemsComponentKey\n }\"\n ></app-nav-items>\n\n <!-- p-6 space-y-6 -->\n <div class=\"flex-1 overflow-y-auto\">\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </div>\n\n <!-- <app-footer></app-footer> -->\n\n </main>\n\n </div>\n\n", dependencies: [{ kind: "component", type: RoutesComponent, selector: "app-routes" }, { kind: "component", type: NavItemsComponent, selector: "app-nav-items" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }], animations: [ /* slideFromBottom, */ /* appModuleAnimation() */] });
1731
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ApplicationLayoutComponent, deps: [{ token: LayoutService }, { token: i0.Renderer2 }, { token: i2$1.Router }, { token: i0.NgZone }, { token: i3$3.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1732
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ApplicationLayoutComponent, isStandalone: true, selector: "abp-layout-application", providers: [LayoutService, SubscriptionService], ngImport: i0, template: "\r\n\r\n<div class=\"flex h-screen overflow-hidden\">\r\n\r\n <!-- Sidebar stays fixed -->\r\n\r\n <app-routes\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.routesComponentKey,\r\n inputs: { smallScreen: { value: service.smallScreen } }\r\n }\"\r\n class=\"mb-2 md:mb-0\"\r\n ></app-routes>\r\n\r\n <!-- Main content scrolls -->\r\n <main class=\"flex-1 flex flex-col overflow-hidden\">\r\n\r\n <!-- Optional Topbar -->\r\n <!-- @if (showTopbar) { -->\r\n\r\n <app-nav-items\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.navItemsComponentKey\r\n }\"\r\n ></app-nav-items>\r\n\r\n <!-- p-6 space-y-6 -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </div>\r\n\r\n <!-- <app-footer></app-footer> -->\r\n\r\n </main>\r\n\r\n </div>\r\n\r\n", dependencies: [{ kind: "component", type: RoutesComponent, selector: "app-routes" }, { kind: "component", type: NavItemsComponent, selector: "app-nav-items" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }], animations: [ /* slideFromBottom, */ /* appModuleAnimation() */] });
1650
1733
  }
1651
1734
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ApplicationLayoutComponent, decorators: [{
1652
1735
  type: Component,
1653
- args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, ReplaceableTemplateDirective], selector: 'abp-layout-application', animations: [ /* slideFromBottom, */ /* appModuleAnimation() */], providers: [LayoutService, SubscriptionService], template: "\n\n<div class=\"flex h-screen overflow-hidden\">\n\n <!-- Sidebar stays fixed -->\n\n <app-routes\n *abpReplaceableTemplate=\"{\n componentKey: service.routesComponentKey,\n inputs: { smallScreen: { value: service.smallScreen } }\n }\"\n class=\"mb-2 md:mb-0\"\n ></app-routes>\n\n <!-- Main content scrolls -->\n <main class=\"flex-1 flex flex-col overflow-hidden\">\n\n <!-- Optional Topbar -->\n <!-- @if (showTopbar) { -->\n\n <app-nav-items\n *abpReplaceableTemplate=\"{\n componentKey: service.navItemsComponentKey\n }\"\n ></app-nav-items>\n\n <!-- p-6 space-y-6 -->\n <div class=\"flex-1 overflow-y-auto\">\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </div>\n\n <!-- <app-footer></app-footer> -->\n\n </main>\n\n </div>\n\n" }]
1654
- }], ctorParameters: () => [{ type: LayoutService }, { type: i0.Renderer2 }, { type: i2$2.Router }, { type: i0.NgZone }, { type: i3$3.LocalizationService }] });
1736
+ args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, ReplaceableTemplateDirective], selector: 'abp-layout-application', animations: [ /* slideFromBottom, */ /* appModuleAnimation() */], providers: [LayoutService, SubscriptionService], template: "\r\n\r\n<div class=\"flex h-screen overflow-hidden\">\r\n\r\n <!-- Sidebar stays fixed -->\r\n\r\n <app-routes\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.routesComponentKey,\r\n inputs: { smallScreen: { value: service.smallScreen } }\r\n }\"\r\n class=\"mb-2 md:mb-0\"\r\n ></app-routes>\r\n\r\n <!-- Main content scrolls -->\r\n <main class=\"flex-1 flex flex-col overflow-hidden\">\r\n\r\n <!-- Optional Topbar -->\r\n <!-- @if (showTopbar) { -->\r\n\r\n <app-nav-items\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.navItemsComponentKey\r\n }\"\r\n ></app-nav-items>\r\n\r\n <!-- p-6 space-y-6 -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </div>\r\n\r\n <!-- <app-footer></app-footer> -->\r\n\r\n </main>\r\n\r\n </div>\r\n\r\n" }]
1737
+ }], ctorParameters: () => [{ type: LayoutService }, { type: i0.Renderer2 }, { type: i2$1.Router }, { type: i0.NgZone }, { type: i3$3.LocalizationService }] });
1655
1738
 
1656
1739
  class EmptyLayoutComponent {
1657
1740
  static type = eLayoutType.empty;
1658
1741
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EmptyLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1659
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: EmptyLayoutComponent, isStandalone: true, selector: "abp-layout-empty", ngImport: i0, template: ` <router-outlet></router-outlet> `, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
1742
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: EmptyLayoutComponent, isStandalone: true, selector: "abp-layout-empty", ngImport: i0, template: ` <router-outlet></router-outlet> `, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
1660
1743
  }
1661
1744
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EmptyLayoutComponent, decorators: [{
1662
1745
  type: Component,