@opendevstack/ngx-appshell 19.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +131 -0
  2. package/fesm2022/opendevstack-ngx-appshell.mjs +727 -0
  3. package/fesm2022/opendevstack-ngx-appshell.mjs.map +1 -0
  4. package/index.d.ts +5 -0
  5. package/lib/components/appshell-breadcrumb/appshell-breadcrumb.component.d.ts +7 -0
  6. package/lib/components/appshell-chip/appshell-chip.component.d.ts +6 -0
  7. package/lib/components/appshell-filters/appshell-filters.component.d.ts +12 -0
  8. package/lib/components/appshell-header/appshell-header.component.d.ts +24 -0
  9. package/lib/components/appshell-icon/appshell-icon.component.d.ts +12 -0
  10. package/lib/components/appshell-layout/appshell-layout.component.d.ts +25 -0
  11. package/lib/components/appshell-page-header/appshell-page-header.component.d.ts +18 -0
  12. package/lib/components/appshell-platform-header/appshell-platform-header.component.d.ts +37 -0
  13. package/lib/components/appshell-platform-layout/appshell-platform-layout.component.d.ts +30 -0
  14. package/lib/components/appshell-product-card/appshell-product-card.component.d.ts +23 -0
  15. package/lib/components/appshell-product-card-v2/appshell-product-card-v2.component.d.ts +16 -0
  16. package/lib/components/appshell-select/appshell-select.component.d.ts +9 -0
  17. package/lib/components/appshell-sidebar-menu/appshell-sidebar-menu.component.d.ts +12 -0
  18. package/lib/components/appshell-toast/appshell-toast.component.d.ts +9 -0
  19. package/lib/components/appshell-toasts/appshell-toasts.component.d.ts +14 -0
  20. package/lib/components/index.d.ts +15 -0
  21. package/lib/directives/appshell-link.directive.d.ts +15 -0
  22. package/lib/directives/index.d.ts +1 -0
  23. package/lib/models/appshell-button.d.ts +5 -0
  24. package/lib/models/appshell-filter.d.ts +4 -0
  25. package/lib/models/appshell-link.d.ts +6 -0
  26. package/lib/models/appshell-links-group.d.ts +5 -0
  27. package/lib/models/appshell-notification.d.ts +10 -0
  28. package/lib/models/appshell-picker.d.ts +9 -0
  29. package/lib/models/appshell-product.d.ts +12 -0
  30. package/lib/models/appshell-tag.d.ts +4 -0
  31. package/lib/models/appshell-toast.d.ts +6 -0
  32. package/lib/models/appshell-user.d.ts +5 -0
  33. package/lib/models/index.d.ts +10 -0
  34. package/lib/screens/appshell-notifications-screen/appshell-notifications-screen.component.d.ts +23 -0
  35. package/lib/screens/appshell-product-catalog-screen/appshell-product-catalog-screen.component.d.ts +16 -0
  36. package/lib/screens/appshell-product-view-screen/appshell-product-view-screen.component.d.ts +19 -0
  37. package/lib/screens/index.d.ts +3 -0
  38. package/lib/services/appshell-toast.service.d.ts +12 -0
  39. package/lib/services/icon-registry.service.d.ts +14 -0
  40. package/lib/services/index.d.ts +2 -0
  41. package/opendevstack-ngx-appshell-19.0.5.tgz +0 -0
  42. package/package.json +44 -0
  43. package/public-api.d.ts +5 -0
  44. package/schematics/azure-login/files/app-config/config.json.template +12 -0
  45. package/schematics/azure-login/files/app-config-service/app-config.service.spec.ts.template +48 -0
  46. package/schematics/azure-login/files/app-config-service/app-config.service.ts.template +39 -0
  47. package/schematics/azure-login/files/azure-config/azure.config.ts.template +94 -0
  48. package/schematics/azure-login/files/azure-service/azure.service.spec.ts.template +311 -0
  49. package/schematics/azure-login/files/azure-service/azure.service.ts.template +161 -0
  50. package/schematics/azure-login/index.d.ts +2 -0
  51. package/schematics/azure-login/index.js +325 -0
  52. package/schematics/azure-login/index.js.map +1 -0
  53. package/schematics/azure-login/schema.json +8 -0
  54. package/schematics/collection.json +19 -0
  55. package/schematics/nats-notifications/files/nats-service/nats.service.spec.ts.template +473 -0
  56. package/schematics/nats-notifications/files/nats-service/nats.service.ts.template +255 -0
  57. package/schematics/nats-notifications/files/notifications-screen/notifications-screen.component.html.template +7 -0
  58. package/schematics/nats-notifications/files/notifications-screen/notifications-screen.component.spec.ts.template +152 -0
  59. package/schematics/nats-notifications/files/notifications-screen/notifications-screen.component.ts.template +61 -0
  60. package/schematics/nats-notifications/index.d.ts +2 -0
  61. package/schematics/nats-notifications/index.js +502 -0
  62. package/schematics/nats-notifications/index.js.map +1 -0
  63. package/schematics/nats-notifications/schema.json +8 -0
  64. package/schematics/ng-add/files/_fonts.scss +85 -0
  65. package/schematics/ng-add/files/styles.scss +47 -0
  66. package/schematics/ng-add/index.d.ts +2 -0
  67. package/schematics/ng-add/index.js +442 -0
  68. package/schematics/ng-add/index.js.map +1 -0
  69. package/styles/appshell-typography-config.scss +19 -0
  70. package/styles/appshell.theme.scss +75 -0
  71. package/styles/palette.css +92 -0
@@ -0,0 +1,727 @@
1
+ import * as i0 from '@angular/core';
2
+ import { HostListener, Input, Directive, input, signal, effect, ViewEncapsulation, Component, output, ElementRef, ViewChild, Injectable, computed } from '@angular/core';
3
+ import * as i1 from '@angular/router';
4
+ import { RouterOutlet } from '@angular/router';
5
+ import * as i1$1 from '@angular/material/icon';
6
+ import { MatIconModule } from '@angular/material/icon';
7
+ import * as i1$2 from '@angular/material/chips';
8
+ import { MatChipsModule } from '@angular/material/chips';
9
+ import * as i1$3 from '@angular/material/button';
10
+ import { MatButtonModule } from '@angular/material/button';
11
+ import * as i3 from '@angular/material/menu';
12
+ import { MatMenuModule } from '@angular/material/menu';
13
+ import * as i2 from '@angular/material/tooltip';
14
+ import { MatTooltipModule } from '@angular/material/tooltip';
15
+ import * as i1$4 from '@angular/material/select';
16
+ import { MatSelectModule } from '@angular/material/select';
17
+ import { CommonModule, SlicePipe, DatePipe } from '@angular/common';
18
+ import * as i1$5 from '@angular/material/sidenav';
19
+ import { MatSidenavModule } from '@angular/material/sidenav';
20
+ import * as i4 from '@angular/forms';
21
+ import { FormsModule } from '@angular/forms';
22
+ import { MatFormFieldModule } from '@angular/material/form-field';
23
+ import * as i6 from '@angular/material/input';
24
+ import { MatInputModule } from '@angular/material/input';
25
+ import * as i2$1 from '@angular/material/card';
26
+ import { MatCardModule } from '@angular/material/card';
27
+ import { BehaviorSubject } from 'rxjs';
28
+ import * as i1$6 from 'ngx-markdown';
29
+ import { MarkdownComponent } from 'ngx-markdown';
30
+ import * as i1$7 from '@angular/common/http';
31
+ import { HttpClient } from '@angular/common/http';
32
+ import * as i3$1 from '@angular/platform-browser';
33
+
34
+ class AppShellLinkDirective {
35
+ el;
36
+ router;
37
+ renderer;
38
+ link;
39
+ constructor(el, router, renderer) {
40
+ this.el = el;
41
+ this.router = router;
42
+ this.renderer = renderer;
43
+ }
44
+ ngOnChanges(changes) {
45
+ if (changes['link']?.currentValue) {
46
+ this.renderer.setAttribute(this.el.nativeElement, 'href', this.link);
47
+ }
48
+ }
49
+ onClick(event) {
50
+ if (!this.isExternalLink()) {
51
+ event.preventDefault();
52
+ this.router.navigate([this.link]);
53
+ }
54
+ }
55
+ isExternalLink() {
56
+ return this.link.startsWith('http') || this.link.startsWith('www.');
57
+ }
58
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellLinkDirective, deps: [{ token: i0.ElementRef }, { token: i1.Router }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
59
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.11", type: AppShellLinkDirective, isStandalone: true, selector: "[appShellLink]", inputs: { link: ["appShellLink", "link"] }, host: { listeners: { "click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0 });
60
+ }
61
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellLinkDirective, decorators: [{
62
+ type: Directive,
63
+ args: [{
64
+ selector: '[appShellLink]',
65
+ standalone: true
66
+ }]
67
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.Router }, { type: i0.Renderer2 }], propDecorators: { link: [{
68
+ type: Input,
69
+ args: ['appShellLink']
70
+ }], onClick: [{
71
+ type: HostListener,
72
+ args: ['click', ['$event']]
73
+ }] } });
74
+
75
+ class AppShellIconComponent {
76
+ iconRegistry;
77
+ icon = input.required();
78
+ namespace = 'appshell';
79
+ // Resolved values for template rendering
80
+ resolvedSvgIcon = signal('');
81
+ resolvedFontIcon = signal('');
82
+ constructor(iconRegistry) {
83
+ this.iconRegistry = iconRegistry;
84
+ effect((onCleanup) => {
85
+ const iconName = this.icon();
86
+ // Try to resolve namespaced appshell icon; fall back to material font icon
87
+ // getNamedSvgIcon emits if the icon exists, errors if it doesn't.
88
+ let sub;
89
+ sub = this.iconRegistry.getNamedSvgIcon(iconName, this.namespace).subscribe({
90
+ next: () => {
91
+ this.resolvedSvgIcon.set(`${this.namespace}:${iconName}`);
92
+ this.resolvedFontIcon.set('');
93
+ },
94
+ error: () => {
95
+ this.resolvedSvgIcon.set('');
96
+ this.resolvedFontIcon.set(iconName);
97
+ }
98
+ });
99
+ onCleanup(() => sub?.unsubscribe());
100
+ });
101
+ }
102
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellIconComponent, deps: [{ token: i1$1.MatIconRegistry }], target: i0.ɵɵFactoryTarget.Component });
103
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellIconComponent, isStandalone: true, selector: "appshell-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (resolvedSvgIcon()) {\n <mat-icon [svgIcon]=\"resolvedSvgIcon()\"></mat-icon>\n} @else {\n <mat-icon>{{ resolvedFontIcon() }}</mat-icon>\n}", styles: ["appshell-icon{height:1.5rem;display:flex}mat-icon svg path{fill:currentColor!important}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], encapsulation: i0.ViewEncapsulation.None });
104
+ }
105
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellIconComponent, decorators: [{
106
+ type: Component,
107
+ args: [{ selector: 'appshell-icon', imports: [MatIconModule], encapsulation: ViewEncapsulation.None, template: "@if (resolvedSvgIcon()) {\n <mat-icon [svgIcon]=\"resolvedSvgIcon()\"></mat-icon>\n} @else {\n <mat-icon>{{ resolvedFontIcon() }}</mat-icon>\n}", styles: ["appshell-icon{height:1.5rem;display:flex}mat-icon svg path{fill:currentColor!important}\n"] }]
108
+ }], ctorParameters: () => [{ type: i1$1.MatIconRegistry }] });
109
+
110
+ class AppShellBreadcrumbComponent {
111
+ links = input();
112
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
113
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellBreadcrumbComponent, isStandalone: true, selector: "appshell-breadcrumb", inputs: { links: { classPropertyName: "links", publicName: "links", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<nav>\n @for (link of links(); track link.label) {\n @if ($index > 0) {\n <appshell-icon class=\"separator\" aria-hidden=\"true\" [icon]=\"'chevron_right'\" />\n }\n @if (link.icon) {\n @if (link.anchor !== '') {\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">\n <appshell-icon [icon]=\"link.icon\" />\n </a>\n } @else {\n <appshell-icon [icon]=\"link.icon\" />\n }\n } @else {\n @if (link.anchor !== '') {\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">{{ link.label }}</a>\n } @else {\n <span>{{ link.label }}</span>\n }\n }\n }\n</nav>", styles: ["nav{margin-bottom:.5rem;display:flex;align-items:center;gap:.25rem}nav a,nav span{color:var(--appshell-color-secondary-main);font-size:.875rem;text-decoration:none}nav .separator,nav .separator>mat-icon{height:1.25rem;width:1.25rem}nav a:hover{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: AppShellLinkDirective, selector: "[appShellLink]", inputs: ["appShellLink"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
114
+ }
115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellBreadcrumbComponent, decorators: [{
116
+ type: Component,
117
+ args: [{ selector: 'appshell-breadcrumb', imports: [AppShellLinkDirective, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<nav>\n @for (link of links(); track link.label) {\n @if ($index > 0) {\n <appshell-icon class=\"separator\" aria-hidden=\"true\" [icon]=\"'chevron_right'\" />\n }\n @if (link.icon) {\n @if (link.anchor !== '') {\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">\n <appshell-icon [icon]=\"link.icon\" />\n </a>\n } @else {\n <appshell-icon [icon]=\"link.icon\" />\n }\n } @else {\n @if (link.anchor !== '') {\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">{{ link.label }}</a>\n } @else {\n <span>{{ link.label }}</span>\n }\n }\n }\n</nav>", styles: ["nav{margin-bottom:.5rem;display:flex;align-items:center;gap:.25rem}nav a,nav span{color:var(--appshell-color-secondary-main);font-size:.875rem;text-decoration:none}nav .separator,nav .separator>mat-icon{height:1.25rem;width:1.25rem}nav a:hover{text-decoration:underline}\n"] }]
118
+ }] });
119
+
120
+ class AppShellChipComponent {
121
+ label = input.required();
122
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellChipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
123
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.11", type: AppShellChipComponent, isStandalone: true, selector: "appshell-chip", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<mat-chip class=\"appshell-chip\" disableRipple>{{label()}}</mat-chip>", styles: [".appshell-chip{--mdc-chip-disabled-label-text-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-elevated-container-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-elevated-disabled-container-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-disabled-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-selected-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-trailing-icon-trailing-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-focus-state-layer-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-focus-state-layer-opacity: 0;--mdc-chip-label-text-size: .875rem}.appshell-chip.mat-mdc-standard-chip{margin:0}.appshell-chip.mat-mdc-standard-chip .mdc-evolution-chip__action{cursor:unset}\n"], dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }], encapsulation: i0.ViewEncapsulation.None });
124
+ }
125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellChipComponent, decorators: [{
126
+ type: Component,
127
+ args: [{ selector: 'appshell-chip', imports: [MatChipsModule], encapsulation: ViewEncapsulation.None, template: "<mat-chip class=\"appshell-chip\" disableRipple>{{label()}}</mat-chip>", styles: [".appshell-chip{--mdc-chip-disabled-label-text-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-elevated-container-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-elevated-disabled-container-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-disabled-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-icon-selected-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-with-trailing-icon-trailing-icon-color: var(--appshell-color-sky-blue-contrast)!important;--mdc-chip-focus-state-layer-color: var(--appshell-color-sky-blue-light)!important;--mdc-chip-focus-state-layer-opacity: 0;--mdc-chip-label-text-size: .875rem}.appshell-chip.mat-mdc-standard-chip{margin:0}.appshell-chip.mat-mdc-standard-chip .mdc-evolution-chip__action{cursor:unset}\n"] }]
128
+ }] });
129
+
130
+ class AppShellPageHeaderComponent {
131
+ breadcrumbLinks = input();
132
+ title = input();
133
+ button = input();
134
+ buttonClicked = output();
135
+ secondaryButton = input();
136
+ secondaryButtonClicked = output();
137
+ picker = input();
138
+ pick = output();
139
+ clickButton() {
140
+ this.buttonClicked.emit();
141
+ }
142
+ clickSecondaryButton() {
143
+ this.secondaryButtonClicked.emit();
144
+ }
145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellPageHeaderComponent, isStandalone: true, selector: "appshell-page-header", inputs: { breadcrumbLinks: { classPropertyName: "breadcrumbLinks", publicName: "breadcrumbLinks", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null }, secondaryButton: { classPropertyName: "secondaryButton", publicName: "secondaryButton", isSignal: true, isRequired: false, transformFunction: null }, picker: { classPropertyName: "picker", publicName: "picker", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buttonClicked: "buttonClicked", secondaryButtonClicked: "secondaryButtonClicked", pick: "pick" }, ngImport: i0, template: "<div class=\"top-section\">\n <div class=\"left-ctn\">\n <appshell-breadcrumb [links]=\"breadcrumbLinks()\"></appshell-breadcrumb>\n <h2>{{title()}}</h2>\n </div>\n @if (picker() && picker()?.label && picker()?.options && picker()?.options!.length > 0) {\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\" mat-button class=\"action-picker-btn\">\n <span class=\"action-picker-label\">\n {{picker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </span>\n </button>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-picker-panel\">\n @for (opt of picker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"pick.emit(opt)\" (keypress)=\"pick.emit(opt)\" [class.active]=\"picker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n @if (secondaryButton()) {\n <div [matTooltip]=\"secondaryButton()?.tooltip || ''\" class=\"btn-ctn\">\n <button mat-flat-button color=\"secondary\" (click)=\"clickSecondaryButton()\" [disabled]=\"secondaryButton()?.disabled\">{{secondaryButton()?.label}}</button>\n </div>\n }\n @if (button()) {\n <div [matTooltip]=\"button()?.tooltip || ''\" class=\"btn-ctn\">\n <button mat-flat-button color=\"accent\" (click)=\"clickButton()\" [disabled]=\"button()?.disabled\">{{button()?.label}}</button>\n </div>\n }\n</div>", styles: [".top-section{display:flex;flex-direction:row;justify-content:space-between;align-items:end;padding:1.5rem;gap:2rem}.top-section>.left-ctn{flex:1}.top-section>.left-ctn h2{font-size:1.5rem;color:var(--appshell-color-secondary-main);line-height:150%;margin:0}.top-section>.btn-ctn>button,.top-section .action-picker-btn{--mdc-filled-button-container-height: unset!important;display:inline-flex;align-items:center;padding:.75rem 1.5rem;border-radius:.125rem;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;height:auto;color:var(--appshell-color-secondary-main)!important;text-decoration:none;font-family:AppShellTextFont;border:2px solid var(--mdc-filled-button-container-color)}.top-section>.btn-ctn>button:disabled,.top-section .action-picker-btn:disabled{border-color:transparent;color:var(--appshell-color-grey-main)!important}.top-section>.btn-ctn>button.mat-secondary,.top-section .action-picker-btn.mat-secondary{border:2px solid var(--appshell-color-secondary-main)}.top-section>.btn-ctn>button.mat-secondary:disabled,.top-section .action-picker-btn.mat-secondary:disabled{border-color:var(--mdc-filled-button-disabled-container-color);background-color:transparent;color:var(--appshell-color-grey-main)!important}.top-section>.btn-ctn>button.action-picker-btn,.top-section .action-picker-btn.action-picker-btn{border-bottom:2px solid var(--appshell-color-accent-green-main);padding:.5rem 1rem;min-width:10rem;--mat-text-button-hover-state-layer-opacity: 0;--mat-text-button-focus-state-layer-opacity: 0;--mat-text-button-pressed-state-layer-opacity: 0;--mat-text-button-ripple-color: transparent}.top-section>.btn-ctn>button.action-picker-btn>span,.top-section .action-picker-btn.action-picker-btn>span{width:100%}.top-section>.btn-ctn>button.action-picker-btn:hover,.top-section .action-picker-btn.action-picker-btn:hover{color:var(--appshell-color-secondary-medium);background-color:transparent;border-bottom:2px solid var(--appshell-color-accent-green-medium)}.top-section>.btn-ctn>button.action-picker-btn .action-picker-label,.top-section .action-picker-btn.action-picker-btn .action-picker-label{display:flex;gap:.5rem;justify-content:space-between}.appshell-picker-panel{padding:.75rem 0;margin-top:.4rem;border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important}.appshell-picker-panel>div{padding:0}.appshell-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: AppShellBreadcrumbComponent, selector: "appshell-breadcrumb", inputs: ["links"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
147
+ }
148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPageHeaderComponent, decorators: [{
149
+ type: Component,
150
+ args: [{ selector: 'appshell-page-header', imports: [MatButtonModule, AppShellBreadcrumbComponent, MatMenuModule, MatTooltipModule, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<div class=\"top-section\">\n <div class=\"left-ctn\">\n <appshell-breadcrumb [links]=\"breadcrumbLinks()\"></appshell-breadcrumb>\n <h2>{{title()}}</h2>\n </div>\n @if (picker() && picker()?.label && picker()?.options && picker()?.options!.length > 0) {\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\" mat-button class=\"action-picker-btn\">\n <span class=\"action-picker-label\">\n {{picker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </span>\n </button>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-picker-panel\">\n @for (opt of picker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"pick.emit(opt)\" (keypress)=\"pick.emit(opt)\" [class.active]=\"picker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n @if (secondaryButton()) {\n <div [matTooltip]=\"secondaryButton()?.tooltip || ''\" class=\"btn-ctn\">\n <button mat-flat-button color=\"secondary\" (click)=\"clickSecondaryButton()\" [disabled]=\"secondaryButton()?.disabled\">{{secondaryButton()?.label}}</button>\n </div>\n }\n @if (button()) {\n <div [matTooltip]=\"button()?.tooltip || ''\" class=\"btn-ctn\">\n <button mat-flat-button color=\"accent\" (click)=\"clickButton()\" [disabled]=\"button()?.disabled\">{{button()?.label}}</button>\n </div>\n }\n</div>", styles: [".top-section{display:flex;flex-direction:row;justify-content:space-between;align-items:end;padding:1.5rem;gap:2rem}.top-section>.left-ctn{flex:1}.top-section>.left-ctn h2{font-size:1.5rem;color:var(--appshell-color-secondary-main);line-height:150%;margin:0}.top-section>.btn-ctn>button,.top-section .action-picker-btn{--mdc-filled-button-container-height: unset!important;display:inline-flex;align-items:center;padding:.75rem 1.5rem;border-radius:.125rem;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;height:auto;color:var(--appshell-color-secondary-main)!important;text-decoration:none;font-family:AppShellTextFont;border:2px solid var(--mdc-filled-button-container-color)}.top-section>.btn-ctn>button:disabled,.top-section .action-picker-btn:disabled{border-color:transparent;color:var(--appshell-color-grey-main)!important}.top-section>.btn-ctn>button.mat-secondary,.top-section .action-picker-btn.mat-secondary{border:2px solid var(--appshell-color-secondary-main)}.top-section>.btn-ctn>button.mat-secondary:disabled,.top-section .action-picker-btn.mat-secondary:disabled{border-color:var(--mdc-filled-button-disabled-container-color);background-color:transparent;color:var(--appshell-color-grey-main)!important}.top-section>.btn-ctn>button.action-picker-btn,.top-section .action-picker-btn.action-picker-btn{border-bottom:2px solid var(--appshell-color-accent-green-main);padding:.5rem 1rem;min-width:10rem;--mat-text-button-hover-state-layer-opacity: 0;--mat-text-button-focus-state-layer-opacity: 0;--mat-text-button-pressed-state-layer-opacity: 0;--mat-text-button-ripple-color: transparent}.top-section>.btn-ctn>button.action-picker-btn>span,.top-section .action-picker-btn.action-picker-btn>span{width:100%}.top-section>.btn-ctn>button.action-picker-btn:hover,.top-section .action-picker-btn.action-picker-btn:hover{color:var(--appshell-color-secondary-medium);background-color:transparent;border-bottom:2px solid var(--appshell-color-accent-green-medium)}.top-section>.btn-ctn>button.action-picker-btn .action-picker-label,.top-section .action-picker-btn.action-picker-btn .action-picker-label{display:flex;gap:.5rem;justify-content:space-between}.appshell-picker-panel{padding:.75rem 0;margin-top:.4rem;border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important}.appshell-picker-panel>div{padding:0}.appshell-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"] }]
151
+ }] });
152
+
153
+ class AppShellSelectComponent {
154
+ label = input.required();
155
+ options = input.required();
156
+ placeholder = input.required();
157
+ selectValueChange = output();
158
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
159
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellSelectComponent, isStandalone: true, selector: "appshell-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { selectValueChange: "selectValueChange" }, ngImport: i0, template: "<mat-label>{{label()}}</mat-label>\n<mat-form-field appearance=\"outline\">\n <mat-select (selectionChange)=\"selectValueChange.emit($event.value)\" multiple [placeholder]=\"placeholder()\" panelClass=\"appshell-select-panel\" attr.aria-label=\"{{label()}}\">\n @for (option of options(); track option) {\n <mat-option value=\"{{option}}\">{{option}}</mat-option>\n }\n </mat-select>\n</mat-form-field>", styles: ["appshell-select{display:flex;flex-direction:column;--mat-select-enabled-trigger-text-color: var(--appshell-color-secondary-main);--mdc-outlined-text-field-focus-outline-color: var(--appshell-color-accent-green-main);--mat-form-field-subscript-text-line-height: 1.5rem;--mdc-outlined-text-field-container-shape: .125rem}appshell-select mat-label{margin-bottom:.5rem;color:var(--appshell-color-secondary-main);font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper{height:3rem}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex{height:100%}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper .mat-mdc-form-field-infix{height:100%;min-height:unset;padding:.75rem 0}.appshell-select-panel{border:1px solid var(--appshell-color-grey-dark);margin-top:.5rem;box-shadow:none!important;border-radius:.125rem!important;padding:.75rem 0!important;--mat-option-label-text-color: var(--appshell-color-secondary-main)}\n"], dependencies: [{ kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$4.MatLabel, selector: "mat-label" }, { kind: "component", type: i1$4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }], encapsulation: i0.ViewEncapsulation.None });
160
+ }
161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellSelectComponent, decorators: [{
162
+ type: Component,
163
+ args: [{ selector: 'appshell-select', imports: [MatSelectModule], encapsulation: ViewEncapsulation.None, template: "<mat-label>{{label()}}</mat-label>\n<mat-form-field appearance=\"outline\">\n <mat-select (selectionChange)=\"selectValueChange.emit($event.value)\" multiple [placeholder]=\"placeholder()\" panelClass=\"appshell-select-panel\" attr.aria-label=\"{{label()}}\">\n @for (option of options(); track option) {\n <mat-option value=\"{{option}}\">{{option}}</mat-option>\n }\n </mat-select>\n</mat-form-field>", styles: ["appshell-select{display:flex;flex-direction:column;--mat-select-enabled-trigger-text-color: var(--appshell-color-secondary-main);--mdc-outlined-text-field-focus-outline-color: var(--appshell-color-accent-green-main);--mat-form-field-subscript-text-line-height: 1.5rem;--mdc-outlined-text-field-container-shape: .125rem}appshell-select mat-label{margin-bottom:.5rem;color:var(--appshell-color-secondary-main);font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper{height:3rem}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex{height:100%}appshell-select .mat-mdc-form-field-type-mat-select .mat-mdc-text-field-wrapper .mat-mdc-form-field-infix{height:100%;min-height:unset;padding:.75rem 0}.appshell-select-panel{border:1px solid var(--appshell-color-grey-dark);margin-top:.5rem;box-shadow:none!important;border-radius:.125rem!important;padding:.75rem 0!important;--mat-option-label-text-color: var(--appshell-color-secondary-main)}\n"] }]
164
+ }] });
165
+
166
+ class AppShellFiltersComponent {
167
+ filters = input();
168
+ activeFilters = new Map();
169
+ activeFiltersChange = output();
170
+ ngOnChanges(changes) {
171
+ if (changes['filters']) {
172
+ this.activeFilters.clear();
173
+ }
174
+ }
175
+ onFilterChange(label, values) {
176
+ if (typeof values === 'string') {
177
+ if (values === '') {
178
+ this.activeFilters.delete(label);
179
+ }
180
+ else {
181
+ this.activeFilters.set(label, [values]);
182
+ }
183
+ }
184
+ else if (values.length === 0) {
185
+ this.activeFilters.delete(label);
186
+ }
187
+ else {
188
+ this.activeFilters.set(label, values);
189
+ }
190
+ this.activeFiltersChange.emit(this.activeFilters);
191
+ }
192
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
193
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellFiltersComponent, isStandalone: true, selector: "appshell-filters", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeFiltersChange: "activeFiltersChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"filters-ctn\">\n @for (filter of filters(); track filter.label) {\n <appshell-select [label]=\"filter.label\" \n [options]=\"filter.options\" \n [placeholder]=\"filter.placeholder\" \n (selectValueChange)=\"onFilterChange(filter.label, $event)\">\n </appshell-select>\n }\n</div>", styles: [".filters-ctn{padding:.5rem 1.5rem 0;display:flex;flex-direction:row;flex-wrap:wrap;column-gap:2.5rem}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: AppShellSelectComponent, selector: "appshell-select", inputs: ["label", "options", "placeholder"], outputs: ["selectValueChange"] }] });
194
+ }
195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellFiltersComponent, decorators: [{
196
+ type: Component,
197
+ args: [{ selector: 'appshell-filters', imports: [MatButtonModule, AppShellSelectComponent], template: "<div class=\"filters-ctn\">\n @for (filter of filters(); track filter.label) {\n <appshell-select [label]=\"filter.label\" \n [options]=\"filter.options\" \n [placeholder]=\"filter.placeholder\" \n (selectValueChange)=\"onFilterChange(filter.label, $event)\">\n </appshell-select>\n }\n</div>", styles: [".filters-ctn{padding:.5rem 1.5rem 0;display:flex;flex-direction:row;flex-wrap:wrap;column-gap:2.5rem}\n"] }]
198
+ }] });
199
+
200
+ class AppShellHeaderComponent {
201
+ router;
202
+ applicationName = input.required();
203
+ symbol = input();
204
+ applicationNameLink = input();
205
+ helpLink = input();
206
+ notificationsLink = input();
207
+ notificationsCount = input(0);
208
+ links = input.required();
209
+ picker = input();
210
+ loggedUser = input();
211
+ userLoggedIn = output();
212
+ userLoggedOut = output();
213
+ userPick = output();
214
+ constructor(router) {
215
+ this.router = router;
216
+ }
217
+ getCurrentUrlPath() {
218
+ return this.router.url;
219
+ }
220
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellHeaderComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
221
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellHeaderComponent, isStandalone: true, selector: "appshell-header", inputs: { applicationName: { classPropertyName: "applicationName", publicName: "applicationName", isSignal: true, isRequired: true, transformFunction: null }, symbol: { classPropertyName: "symbol", publicName: "symbol", isSignal: true, isRequired: false, transformFunction: null }, applicationNameLink: { classPropertyName: "applicationNameLink", publicName: "applicationNameLink", isSignal: true, isRequired: false, transformFunction: null }, helpLink: { classPropertyName: "helpLink", publicName: "helpLink", isSignal: true, isRequired: false, transformFunction: null }, notificationsLink: { classPropertyName: "notificationsLink", publicName: "notificationsLink", isSignal: true, isRequired: false, transformFunction: null }, notificationsCount: { classPropertyName: "notificationsCount", publicName: "notificationsCount", isSignal: true, isRequired: false, transformFunction: null }, links: { classPropertyName: "links", publicName: "links", isSignal: true, isRequired: true, transformFunction: null }, picker: { classPropertyName: "picker", publicName: "picker", isSignal: true, isRequired: false, transformFunction: null }, loggedUser: { classPropertyName: "loggedUser", publicName: "loggedUser", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userLoggedIn: "userLoggedIn", userLoggedOut: "userLoggedOut", userPick: "userPick" }, ngImport: i0, template: "<nav class=\"appshell-meta-navigation\" aria-label=\"Top of the header navigation\">\n @if (applicationNameLink() && applicationNameLink() !== '') {\n <a class=\"app-id-ctn\" [href]=\"applicationNameLink()\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" />\n }\n <h1>{{applicationName()}}</h1>\n </a>\n } @else {\n <div class=\"app-id-ctn\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" />\n }\n <h1>{{applicationName()}}</h1>\n </div>\n }\n <div class=\"header-space\"></div>\n @for (link of links(); track link.label; let index = $index) {\n <a class=\"header-link\" [appShellLink]=\"link.anchor\" [class.active]=\"getCurrentUrlPath() === link.anchor\" target=\"{{link!.target || '_self'}}\" [class.last]=\"index+1 === links().length\">\n {{link.label}}\n </a>\n }\n @if (picker() && picker()?.label && picker()?.options && picker()?.options!.length > 0) {\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\" class=\"header-picker\">\n {{picker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-picker-panel\">\n @for (opt of picker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"userPick.emit(opt)\" (keypress)=\"userPick.emit(opt)\" [class.active]=\"picker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n @if (helpLink() && helpLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"helpLink()!.anchor\" target=\"{{helpLink()!.target || '_self'}}\" [matTooltip]=\"helpLink()!.label\" aria-label=\"Visit the help page\">\n <appshell-icon [icon]=\"helpLink()!.icon!\" aria-label=\"Help icon\" />\n </a>\n }\n @if (notificationsLink() && notificationsLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"notificationsLink()!.anchor\" target=\"{{notificationsLink()!.target || '_self'}}\" [matTooltip]=\"notificationsLink()!.label\" aria-label=\"Visit the notifications page\">\n <appshell-icon [icon]=\"notificationsLink()!.icon!\" aria-label=\"Notifications icon\" />\n @if (notificationsCount() > 0) {\n <div class=\"notification-count\" aria-label=\"Number of notifications\">\n {{notificationsCount() > 9 ? '9+' : notificationsCount()}}\n </div>\n }\n </a>\n }\n <div class=\"separator\"></div>\n <div class=\"user-ctn\">\n @if (loggedUser() !== null) {\n <button [matMenuTriggerFor]=\"logoutMenu\">\n @if (loggedUser()!.avatarSrc) {\n <div class=\"header-profile-picture\" [style.backgroundImage]=\"'url('+loggedUser()!.avatarSrc+')'\"></div>\n } @else {\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n }\n <div class=\"user-text\">{{loggedUser()?.fullName}}</div>\n </button>\n <mat-menu #logoutMenu=\"matMenu\" xPosition=\"before\" class=\"appshell-logout-panel\">\n <button mat-menu-item (click)=\"userLoggedOut.emit()\" (keypress)=\"userLoggedOut.emit()\" aria-label=\"Logout\">Log Out</button>\n </mat-menu>\n } @else {\n <button (click)=\"userLoggedIn.emit()\" (keypress)=\"userLoggedIn.emit()\" aria-label=\"Login\">\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n <div class=\"user-text\">Login</div>\n </button>\n }\n </div>\n</nav>", styles: ["appshell-header{width:100%;--header-bg-color: var(--appshell-color-dark-green-main);--header-text-color: var(--text-color-on-main-color);--header-separator-color: var(--appshell-color-dark-green-light);--header-link-color: var(--appshell-color-dark-green-light);--header-link-hover-color: #ffffff;--header-link-selected-color: var(--appshell-color-accent-green-main);--header-border-bottom-color: var(--appshell-color-dark-green-main);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-header.theme-white{--header-bg-color: #ffffff;--header-text-color: var(--appshell-color-dark-green-main);--header-separator-color: var(--appshell-color-grey-strong);--header-link-color: var(--appshell-color-grey-strong);--header-link-hover-color: var(--appshell-color-dark-green-main);--header-link-selected-color: var(--appshell-color-dark-green-main);--header-border-bottom-color: var(--appshell-color-grey-warm);--header-app-name-color: var(--appshell-color-dark-green-main)}appshell-header.theme-purple{--header-bg-color: var(--appshell-color-violet-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-violet-light);--header-link-color: var(--appshell-color-violet-light);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-violet-dark);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-header.theme-blue{--header-bg-color: var(--appshell-color-sky-blue-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-sky-blue-medium);--header-link-color: var(--appshell-color-sky-blue-medium);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-sky-blue-dark);--header-app-name-color: var(--appshell-color-grey-medium)}.appshell-meta-navigation{width:100%;display:flex;flex-direction:row;align-items:center;height:3rem;background-color:var(--header-bg-color);color:var(--header-text-color);padding:0;box-sizing:border-box;font-size:.875rem;line-height:1.25rem;font-weight:400;font-style:normal;border-bottom:1px solid var(--header-border-bottom-color)}.appshell-meta-navigation .app-id-ctn{margin-left:2rem;box-sizing:border-box;display:flex;align-items:center;text-decoration:none}.appshell-meta-navigation .app-id-ctn img{height:1.5rem;width:1.5rem;margin-right:.5rem}.appshell-meta-navigation .app-id-ctn h1{color:var(--header-app-name-color);font-weight:500;margin:auto 0;font-size:1rem}.appshell-meta-navigation a.app-id-ctn:hover h1{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link{color:var(--header-link-color);margin-left:2rem;text-decoration:none;font-size:1rem;font-style:normal;font-weight:500}.appshell-meta-navigation .header-link.last{margin-right:1.25rem}.appshell-meta-navigation .header-link:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link.active{color:var(--header-link-selected-color);text-decoration:underline}.appshell-meta-navigation .separator{width:1px;height:70%;margin:auto 1rem;background-color:var(--header-separator-color)}.appshell-meta-navigation .header-picker{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;color:var(--header-link-color);font-size:1rem;font-style:normal;font-weight:500;font-family:AppShellTextFont;line-height:1.5rem;gap:.25rem;padding:0 1rem;height:85%;margin:auto 1.5rem}.appshell-meta-navigation .header-picker appshell-icon,.appshell-meta-navigation .header-picker mat-icon{width:1rem;height:1rem;display:flex;justify-content:center;align-items:center}.appshell-meta-navigation .header-picker:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon{border-radius:50%;display:flex;height:3rem;width:3rem;justify-content:center;align-items:center;color:var(--header-link-color);position:relative}.appshell-meta-navigation .header-icon:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon .notification-count{height:1.25rem;width:1.25rem;border-radius:50%;background-color:#e10a0a;color:#fff;font-family:AppShellTextFont;font-size:.75rem;font-style:normal;font-weight:400;line-height:1.5rem;text-decoration:none;display:flex;align-items:center;justify-content:center;position:absolute;top:.25rem;right:.25rem}.appshell-meta-navigation .user-ctn{padding-left:.5rem;padding-right:1.25rem;display:flex;flex-direction:row;align-items:center;height:100%}.appshell-meta-navigation .user-ctn button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;width:100%;gap:.5rem;color:var(--header-link-color)}.appshell-meta-navigation .user-ctn button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .user-ctn button .header-profile-picture{width:1.5rem;height:1.5rem;border-radius:50%;background-size:cover;background-position:center;border:1px solid var(--appshell-color-grey-warm);aspect-ratio:1}.appshell-meta-navigation .user-ctn button .user-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;width:10rem;line-height:1.25rem;text-align:start}.header-space{flex:1}.appshell-logout-panel,.appshell-picker-panel{border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important;width:13rem}.appshell-logout-panel>div,.appshell-picker-panel>div{padding:0}.appshell-logout-panel{margin-top:.7rem}.appshell-picker-panel{padding:.75rem 0;margin-top:.4rem}.appshell-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"], dependencies: [{ kind: "directive", type: AppShellLinkDirective, selector: "[appShellLink]", inputs: ["appShellLink"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
222
+ }
223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellHeaderComponent, decorators: [{
224
+ type: Component,
225
+ args: [{ selector: 'appshell-header', imports: [AppShellLinkDirective, MatTooltipModule, CommonModule, MatMenuModule, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<nav class=\"appshell-meta-navigation\" aria-label=\"Top of the header navigation\">\n @if (applicationNameLink() && applicationNameLink() !== '') {\n <a class=\"app-id-ctn\" [href]=\"applicationNameLink()\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" />\n }\n <h1>{{applicationName()}}</h1>\n </a>\n } @else {\n <div class=\"app-id-ctn\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" />\n }\n <h1>{{applicationName()}}</h1>\n </div>\n }\n <div class=\"header-space\"></div>\n @for (link of links(); track link.label; let index = $index) {\n <a class=\"header-link\" [appShellLink]=\"link.anchor\" [class.active]=\"getCurrentUrlPath() === link.anchor\" target=\"{{link!.target || '_self'}}\" [class.last]=\"index+1 === links().length\">\n {{link.label}}\n </a>\n }\n @if (picker() && picker()?.label && picker()?.options && picker()?.options!.length > 0) {\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\" class=\"header-picker\">\n {{picker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-picker-panel\">\n @for (opt of picker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"userPick.emit(opt)\" (keypress)=\"userPick.emit(opt)\" [class.active]=\"picker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n @if (helpLink() && helpLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"helpLink()!.anchor\" target=\"{{helpLink()!.target || '_self'}}\" [matTooltip]=\"helpLink()!.label\" aria-label=\"Visit the help page\">\n <appshell-icon [icon]=\"helpLink()!.icon!\" aria-label=\"Help icon\" />\n </a>\n }\n @if (notificationsLink() && notificationsLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"notificationsLink()!.anchor\" target=\"{{notificationsLink()!.target || '_self'}}\" [matTooltip]=\"notificationsLink()!.label\" aria-label=\"Visit the notifications page\">\n <appshell-icon [icon]=\"notificationsLink()!.icon!\" aria-label=\"Notifications icon\" />\n @if (notificationsCount() > 0) {\n <div class=\"notification-count\" aria-label=\"Number of notifications\">\n {{notificationsCount() > 9 ? '9+' : notificationsCount()}}\n </div>\n }\n </a>\n }\n <div class=\"separator\"></div>\n <div class=\"user-ctn\">\n @if (loggedUser() !== null) {\n <button [matMenuTriggerFor]=\"logoutMenu\">\n @if (loggedUser()!.avatarSrc) {\n <div class=\"header-profile-picture\" [style.backgroundImage]=\"'url('+loggedUser()!.avatarSrc+')'\"></div>\n } @else {\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n }\n <div class=\"user-text\">{{loggedUser()?.fullName}}</div>\n </button>\n <mat-menu #logoutMenu=\"matMenu\" xPosition=\"before\" class=\"appshell-logout-panel\">\n <button mat-menu-item (click)=\"userLoggedOut.emit()\" (keypress)=\"userLoggedOut.emit()\" aria-label=\"Logout\">Log Out</button>\n </mat-menu>\n } @else {\n <button (click)=\"userLoggedIn.emit()\" (keypress)=\"userLoggedIn.emit()\" aria-label=\"Login\">\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n <div class=\"user-text\">Login</div>\n </button>\n }\n </div>\n</nav>", styles: ["appshell-header{width:100%;--header-bg-color: var(--appshell-color-dark-green-main);--header-text-color: var(--text-color-on-main-color);--header-separator-color: var(--appshell-color-dark-green-light);--header-link-color: var(--appshell-color-dark-green-light);--header-link-hover-color: #ffffff;--header-link-selected-color: var(--appshell-color-accent-green-main);--header-border-bottom-color: var(--appshell-color-dark-green-main);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-header.theme-white{--header-bg-color: #ffffff;--header-text-color: var(--appshell-color-dark-green-main);--header-separator-color: var(--appshell-color-grey-strong);--header-link-color: var(--appshell-color-grey-strong);--header-link-hover-color: var(--appshell-color-dark-green-main);--header-link-selected-color: var(--appshell-color-dark-green-main);--header-border-bottom-color: var(--appshell-color-grey-warm);--header-app-name-color: var(--appshell-color-dark-green-main)}appshell-header.theme-purple{--header-bg-color: var(--appshell-color-violet-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-violet-light);--header-link-color: var(--appshell-color-violet-light);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-violet-dark);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-header.theme-blue{--header-bg-color: var(--appshell-color-sky-blue-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-sky-blue-medium);--header-link-color: var(--appshell-color-sky-blue-medium);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-sky-blue-dark);--header-app-name-color: var(--appshell-color-grey-medium)}.appshell-meta-navigation{width:100%;display:flex;flex-direction:row;align-items:center;height:3rem;background-color:var(--header-bg-color);color:var(--header-text-color);padding:0;box-sizing:border-box;font-size:.875rem;line-height:1.25rem;font-weight:400;font-style:normal;border-bottom:1px solid var(--header-border-bottom-color)}.appshell-meta-navigation .app-id-ctn{margin-left:2rem;box-sizing:border-box;display:flex;align-items:center;text-decoration:none}.appshell-meta-navigation .app-id-ctn img{height:1.5rem;width:1.5rem;margin-right:.5rem}.appshell-meta-navigation .app-id-ctn h1{color:var(--header-app-name-color);font-weight:500;margin:auto 0;font-size:1rem}.appshell-meta-navigation a.app-id-ctn:hover h1{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link{color:var(--header-link-color);margin-left:2rem;text-decoration:none;font-size:1rem;font-style:normal;font-weight:500}.appshell-meta-navigation .header-link.last{margin-right:1.25rem}.appshell-meta-navigation .header-link:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link.active{color:var(--header-link-selected-color);text-decoration:underline}.appshell-meta-navigation .separator{width:1px;height:70%;margin:auto 1rem;background-color:var(--header-separator-color)}.appshell-meta-navigation .header-picker{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;color:var(--header-link-color);font-size:1rem;font-style:normal;font-weight:500;font-family:AppShellTextFont;line-height:1.5rem;gap:.25rem;padding:0 1rem;height:85%;margin:auto 1.5rem}.appshell-meta-navigation .header-picker appshell-icon,.appshell-meta-navigation .header-picker mat-icon{width:1rem;height:1rem;display:flex;justify-content:center;align-items:center}.appshell-meta-navigation .header-picker:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon{border-radius:50%;display:flex;height:3rem;width:3rem;justify-content:center;align-items:center;color:var(--header-link-color);position:relative}.appshell-meta-navigation .header-icon:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon .notification-count{height:1.25rem;width:1.25rem;border-radius:50%;background-color:#e10a0a;color:#fff;font-family:AppShellTextFont;font-size:.75rem;font-style:normal;font-weight:400;line-height:1.5rem;text-decoration:none;display:flex;align-items:center;justify-content:center;position:absolute;top:.25rem;right:.25rem}.appshell-meta-navigation .user-ctn{padding-left:.5rem;padding-right:1.25rem;display:flex;flex-direction:row;align-items:center;height:100%}.appshell-meta-navigation .user-ctn button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;width:100%;gap:.5rem;color:var(--header-link-color)}.appshell-meta-navigation .user-ctn button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .user-ctn button .header-profile-picture{width:1.5rem;height:1.5rem;border-radius:50%;background-size:cover;background-position:center;border:1px solid var(--appshell-color-grey-warm);aspect-ratio:1}.appshell-meta-navigation .user-ctn button .user-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;width:10rem;line-height:1.25rem;text-align:start}.header-space{flex:1}.appshell-logout-panel,.appshell-picker-panel{border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important;width:13rem}.appshell-logout-panel>div,.appshell-picker-panel>div{padding:0}.appshell-logout-panel{margin-top:.7rem}.appshell-picker-panel{padding:.75rem 0;margin-top:.4rem}.appshell-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"] }]
226
+ }], ctorParameters: () => [{ type: i1.Router }] });
227
+
228
+ class AppShellSidebarMenuComponent {
229
+ router;
230
+ sections = input.required();
231
+ links = input();
232
+ constructor(router) {
233
+ this.router = router;
234
+ }
235
+ getCurrentUrlPath() {
236
+ return this.router.url;
237
+ }
238
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellSidebarMenuComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
239
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellSidebarMenuComponent, isStandalone: true, selector: "appshell-sidebar-menu", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null }, links: { classPropertyName: "links", publicName: "links", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"appshell-sidebar-menu-ctn\">\n @for (section of sections(); track $index) {\n <div class=\"link-group\">\n @if (section.label !== '') {\n <div class=\"menu-item link-group-header\">\n {{section.label}}\n </div>\n }\n <nav attr.aria-label=\"Sidebar menu for {{section.label}}\">\n @for (page of section.links; track $index) {\n <div class=\"menu-item link\" [class.active]=\"getCurrentUrlPath() === page.anchor\">\n <a [appShellLink]=\"page.anchor\" target=\"{{page.target || '_self'}}\">\n @if (page.icon) {\n <appshell-icon [icon]=\"page.icon\" aria-hidden=\"true\" />\n }\n {{page.label}}\n </a>\n </div>\n }\n </nav>\n </div>\n }\n @if (links() && links()!.links.length > 0) {\n <nav class=\"links\" aria-label=\"Links from sidebar menu\">\n <div class=\"links-separator\"></div>\n @if (links()!.label !== '') {\n <div class=\"links-header\">\n {{links()!.label}}\n </div>\n }\n @for (link of links()!.links; track $index) {\n <div class=\"menu-item link\">\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">\n @if (link.icon) {\n <appshell-icon [icon]=\"link.icon\" aria-hidden=\"true\" />\n }\n {{link.label}}\n </a>\n </div>\n }\n </nav>\n }\n</div>", styles: [".appshell-sidebar-menu-ctn{width:15rem;height:100%;background:var(--background-color);display:flex;box-sizing:border-box;padding:1.5rem 1rem;flex-direction:column;gap:.5rem;align-items:flex-start;color:var(--text-color-on-background)}.appshell-sidebar-menu-ctn .link-group{display:flex;flex-direction:column;align-items:flex-start;width:100%;gap:.5rem}.appshell-sidebar-menu-ctn .link-group nav{width:100%;display:flex;flex-direction:column;gap:.5rem}.appshell-sidebar-menu-ctn .link-group .appshell-sidebar-icon path{fill:var(--text-color-on-background)!important}.appshell-sidebar-menu-ctn .links{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:.5rem}.appshell-sidebar-menu-ctn .links .links-separator{height:.125rem;width:calc(100% - 2rem);margin:.5rem auto;background-color:var(--appshell-color-grey-medium)}.appshell-sidebar-menu-ctn .links .links-header{padding-left:1rem;font-size:.75rem;font-style:normal;font-weight:500;line-height:1.25rem}.appshell-sidebar-menu-ctn .menu-item{display:flex;flex-direction:row;box-sizing:border-box;align-items:center;gap:.75rem;align-self:stretch}.appshell-sidebar-menu-ctn .menu-item.link-group-header{font-size:1rem;line-height:1.25rem;height:2.25rem;padding:.5rem;font-family:AppShellHeadingFont;font-style:normal;font-weight:500}.appshell-sidebar-menu-ctn .link{font-weight:400;line-height:1.75rem}.appshell-sidebar-menu-ctn .link.active{border-radius:.125rem 0rem 0rem .125rem;background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-sidebar-menu-ctn .link:hover{background-color:var(--appshell-color-grey-light)}.appshell-sidebar-menu-ctn .link span{display:flex;width:1.5rem;height:1.5rem;justify-content:center;align-items:center}.appshell-sidebar-menu-ctn .link a{text-decoration:none;color:var(--text-color-on-background);display:flex;flex-direction:row;align-items:center;gap:.5rem;width:100%;padding:.5rem 1rem}\n"], dependencies: [{ kind: "directive", type: AppShellLinkDirective, selector: "[appShellLink]", inputs: ["appShellLink"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
240
+ }
241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellSidebarMenuComponent, decorators: [{
242
+ type: Component,
243
+ args: [{ selector: 'appshell-sidebar-menu', imports: [AppShellLinkDirective, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<div class=\"appshell-sidebar-menu-ctn\">\n @for (section of sections(); track $index) {\n <div class=\"link-group\">\n @if (section.label !== '') {\n <div class=\"menu-item link-group-header\">\n {{section.label}}\n </div>\n }\n <nav attr.aria-label=\"Sidebar menu for {{section.label}}\">\n @for (page of section.links; track $index) {\n <div class=\"menu-item link\" [class.active]=\"getCurrentUrlPath() === page.anchor\">\n <a [appShellLink]=\"page.anchor\" target=\"{{page.target || '_self'}}\">\n @if (page.icon) {\n <appshell-icon [icon]=\"page.icon\" aria-hidden=\"true\" />\n }\n {{page.label}}\n </a>\n </div>\n }\n </nav>\n </div>\n }\n @if (links() && links()!.links.length > 0) {\n <nav class=\"links\" aria-label=\"Links from sidebar menu\">\n <div class=\"links-separator\"></div>\n @if (links()!.label !== '') {\n <div class=\"links-header\">\n {{links()!.label}}\n </div>\n }\n @for (link of links()!.links; track $index) {\n <div class=\"menu-item link\">\n <a [appShellLink]=\"link.anchor\" target=\"{{link.target || '_self'}}\">\n @if (link.icon) {\n <appshell-icon [icon]=\"link.icon\" aria-hidden=\"true\" />\n }\n {{link.label}}\n </a>\n </div>\n }\n </nav>\n }\n</div>", styles: [".appshell-sidebar-menu-ctn{width:15rem;height:100%;background:var(--background-color);display:flex;box-sizing:border-box;padding:1.5rem 1rem;flex-direction:column;gap:.5rem;align-items:flex-start;color:var(--text-color-on-background)}.appshell-sidebar-menu-ctn .link-group{display:flex;flex-direction:column;align-items:flex-start;width:100%;gap:.5rem}.appshell-sidebar-menu-ctn .link-group nav{width:100%;display:flex;flex-direction:column;gap:.5rem}.appshell-sidebar-menu-ctn .link-group .appshell-sidebar-icon path{fill:var(--text-color-on-background)!important}.appshell-sidebar-menu-ctn .links{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:.5rem}.appshell-sidebar-menu-ctn .links .links-separator{height:.125rem;width:calc(100% - 2rem);margin:.5rem auto;background-color:var(--appshell-color-grey-medium)}.appshell-sidebar-menu-ctn .links .links-header{padding-left:1rem;font-size:.75rem;font-style:normal;font-weight:500;line-height:1.25rem}.appshell-sidebar-menu-ctn .menu-item{display:flex;flex-direction:row;box-sizing:border-box;align-items:center;gap:.75rem;align-self:stretch}.appshell-sidebar-menu-ctn .menu-item.link-group-header{font-size:1rem;line-height:1.25rem;height:2.25rem;padding:.5rem;font-family:AppShellHeadingFont;font-style:normal;font-weight:500}.appshell-sidebar-menu-ctn .link{font-weight:400;line-height:1.75rem}.appshell-sidebar-menu-ctn .link.active{border-radius:.125rem 0rem 0rem .125rem;background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-sidebar-menu-ctn .link:hover{background-color:var(--appshell-color-grey-light)}.appshell-sidebar-menu-ctn .link span{display:flex;width:1.5rem;height:1.5rem;justify-content:center;align-items:center}.appshell-sidebar-menu-ctn .link a{text-decoration:none;color:var(--text-color-on-background);display:flex;flex-direction:row;align-items:center;gap:.5rem;width:100%;padding:.5rem 1rem}\n"] }]
244
+ }], ctorParameters: () => [{ type: i1.Router }] });
245
+
246
+ class AppShellLayoutComponent {
247
+ headerVariant = input('');
248
+ applicationSymbol = input.required();
249
+ applicationName = input.required();
250
+ applicationNameLink = input();
251
+ appShellHelpLink = input();
252
+ appShellNotificationsLink = input();
253
+ appShellNotificationsCount = input(0);
254
+ headerLinks = input.required();
255
+ headerPicker = input();
256
+ sidenavSections = input.required();
257
+ sidenavLinks = input();
258
+ loggedUser = input.required();
259
+ userLoggedIn = output();
260
+ userLoggedOut = output();
261
+ userPick = output();
262
+ constructor() { }
263
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
264
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellLayoutComponent, isStandalone: true, selector: "appshell-layout", inputs: { headerVariant: { classPropertyName: "headerVariant", publicName: "headerVariant", isSignal: true, isRequired: false, transformFunction: null }, applicationSymbol: { classPropertyName: "applicationSymbol", publicName: "applicationSymbol", isSignal: true, isRequired: true, transformFunction: null }, applicationName: { classPropertyName: "applicationName", publicName: "applicationName", isSignal: true, isRequired: true, transformFunction: null }, applicationNameLink: { classPropertyName: "applicationNameLink", publicName: "applicationNameLink", isSignal: true, isRequired: false, transformFunction: null }, appShellHelpLink: { classPropertyName: "appShellHelpLink", publicName: "appShellHelpLink", isSignal: true, isRequired: false, transformFunction: null }, appShellNotificationsLink: { classPropertyName: "appShellNotificationsLink", publicName: "appShellNotificationsLink", isSignal: true, isRequired: false, transformFunction: null }, appShellNotificationsCount: { classPropertyName: "appShellNotificationsCount", publicName: "appShellNotificationsCount", isSignal: true, isRequired: false, transformFunction: null }, headerLinks: { classPropertyName: "headerLinks", publicName: "headerLinks", isSignal: true, isRequired: true, transformFunction: null }, headerPicker: { classPropertyName: "headerPicker", publicName: "headerPicker", isSignal: true, isRequired: false, transformFunction: null }, sidenavSections: { classPropertyName: "sidenavSections", publicName: "sidenavSections", isSignal: true, isRequired: true, transformFunction: null }, sidenavLinks: { classPropertyName: "sidenavLinks", publicName: "sidenavLinks", isSignal: true, isRequired: false, transformFunction: null }, loggedUser: { classPropertyName: "loggedUser", publicName: "loggedUser", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { userLoggedIn: "userLoggedIn", userLoggedOut: "userLoggedOut", userPick: "userPick" }, ngImport: i0, template: "<appshell-header\n [class]=\"headerVariant()\"\n [symbol]=\"applicationSymbol()\"\n [applicationName]=\"applicationName()\"\n [applicationNameLink]=\"applicationNameLink()\"\n [helpLink]=\"appShellHelpLink()\"\n [notificationsLink]=\"appShellNotificationsLink()\"\n [notificationsCount]=\"appShellNotificationsCount()\"\n [links]=\"headerLinks()\"\n [picker]=\"headerPicker()\"\n [loggedUser]=\"loggedUser()\"\n (userLoggedIn)=\"userLoggedIn.emit()\"\n (userLoggedOut)=\"userLoggedOut.emit()\"\n (userPick)=\"userPick.emit($event)\">\n</appshell-header>\n\n<section id=\"appshell-layout-content\">\n <mat-sidenav-container>\n @if (sidenavSections() && sidenavSections().length) {\n <mat-sidenav opened mode=\"side\" disableClose [fixedInViewport]=\"true\" [fixedTopGap]=\"48\">\n <appshell-sidebar-menu [sections]=\"sidenavSections()\" [links]=\"sidenavLinks()\"></appshell-sidebar-menu>\n </mat-sidenav>\n }\n <mat-sidenav-content>\n <main>\n <router-outlet></router-outlet>\n </main>\n </mat-sidenav-content>\n </mat-sidenav-container>\n</section>", styles: ["appshell-header{display:flex;position:fixed;z-index:99;width:100%}appshell-navigation{display:flex;flex-direction:row}#appshell-layout-content{flex-grow:1;display:flex;height:100%;padding-top:3rem}#appshell-layout-content mat-sidenav-container{width:100%}#appshell-layout-content appshell-sidebar-menu{display:flex;flex-direction:column;z-index:2}#appshell-layout-content mat-sidenav-content{box-sizing:border-box;background-color:var(--background-color)}#appshell-layout-content mat-sidenav-content main{display:flex;height:100%}\n"], dependencies: [{ kind: "component", type: AppShellSidebarMenuComponent, selector: "appshell-sidebar-menu", inputs: ["sections", "links"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "component", type: AppShellHeaderComponent, selector: "appshell-header", inputs: ["applicationName", "symbol", "applicationNameLink", "helpLink", "notificationsLink", "notificationsCount", "links", "picker", "loggedUser"], outputs: ["userLoggedIn", "userLoggedOut", "userPick"] }] });
265
+ }
266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellLayoutComponent, decorators: [{
267
+ type: Component,
268
+ args: [{ selector: 'appshell-layout', imports: [AppShellSidebarMenuComponent, RouterOutlet, MatSidenavModule, AppShellHeaderComponent], template: "<appshell-header\n [class]=\"headerVariant()\"\n [symbol]=\"applicationSymbol()\"\n [applicationName]=\"applicationName()\"\n [applicationNameLink]=\"applicationNameLink()\"\n [helpLink]=\"appShellHelpLink()\"\n [notificationsLink]=\"appShellNotificationsLink()\"\n [notificationsCount]=\"appShellNotificationsCount()\"\n [links]=\"headerLinks()\"\n [picker]=\"headerPicker()\"\n [loggedUser]=\"loggedUser()\"\n (userLoggedIn)=\"userLoggedIn.emit()\"\n (userLoggedOut)=\"userLoggedOut.emit()\"\n (userPick)=\"userPick.emit($event)\">\n</appshell-header>\n\n<section id=\"appshell-layout-content\">\n <mat-sidenav-container>\n @if (sidenavSections() && sidenavSections().length) {\n <mat-sidenav opened mode=\"side\" disableClose [fixedInViewport]=\"true\" [fixedTopGap]=\"48\">\n <appshell-sidebar-menu [sections]=\"sidenavSections()\" [links]=\"sidenavLinks()\"></appshell-sidebar-menu>\n </mat-sidenav>\n }\n <mat-sidenav-content>\n <main>\n <router-outlet></router-outlet>\n </main>\n </mat-sidenav-content>\n </mat-sidenav-container>\n</section>", styles: ["appshell-header{display:flex;position:fixed;z-index:99;width:100%}appshell-navigation{display:flex;flex-direction:row}#appshell-layout-content{flex-grow:1;display:flex;height:100%;padding-top:3rem}#appshell-layout-content mat-sidenav-container{width:100%}#appshell-layout-content appshell-sidebar-menu{display:flex;flex-direction:column;z-index:2}#appshell-layout-content mat-sidenav-content{box-sizing:border-box;background-color:var(--background-color)}#appshell-layout-content mat-sidenav-content main{display:flex;height:100%}\n"] }]
269
+ }], ctorParameters: () => [] });
270
+
271
+ class AppShellPlatformHeaderComponent {
272
+ router;
273
+ applicationName = input.required();
274
+ symbol = input();
275
+ logo = input();
276
+ applicationNameLink = input();
277
+ helpLink = input();
278
+ notificationsLink = input();
279
+ notificationsCount = input(0);
280
+ links = input.required();
281
+ projectPicker = input();
282
+ secondaryPicker = input();
283
+ loggedUser = input();
284
+ userLoggedIn = output();
285
+ userLoggedOut = output();
286
+ userProjectPick = output();
287
+ userProjectPickChoice = null;
288
+ userSecondaryPick = output();
289
+ userSecondaryPickChoice = null;
290
+ isPlatformPickerOpened = input(null);
291
+ platformPickerClick = output();
292
+ projectPickerSearch = '';
293
+ constructor(router) {
294
+ this.router = router;
295
+ effect(() => {
296
+ if (this.projectPicker()) {
297
+ this.userProjectPickChoice = this.projectPicker().selected ?? null;
298
+ }
299
+ });
300
+ effect(() => {
301
+ if (this.secondaryPicker()) {
302
+ this.userSecondaryPickChoice = this.secondaryPicker().selected ?? null;
303
+ }
304
+ });
305
+ }
306
+ getCurrentUrlPath() {
307
+ return this.router.url;
308
+ }
309
+ filteredProjectPickerOptions() {
310
+ const picker = this.projectPicker();
311
+ if (!picker?.options) {
312
+ return [];
313
+ }
314
+ if (!this.projectPickerSearch) {
315
+ return picker.options;
316
+ }
317
+ return picker.options.filter(opt => opt.toLowerCase().includes(this.projectPickerSearch.toLowerCase()));
318
+ }
319
+ pickProject(option) {
320
+ this.userProjectPickChoice = option;
321
+ this.userProjectPick.emit(option);
322
+ this.projectPickerSearch = '';
323
+ }
324
+ pickSecondChoice(option) {
325
+ this.userSecondaryPickChoice = option;
326
+ this.userSecondaryPick.emit(option);
327
+ }
328
+ openPlatformPicker() {
329
+ this.platformPickerClick.emit();
330
+ }
331
+ onSearchKeydown(event) {
332
+ // Prevent mat-menu's keyboard navigation from interfering
333
+ event.stopPropagation();
334
+ }
335
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPlatformHeaderComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
336
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellPlatformHeaderComponent, isStandalone: true, selector: "appshell-platform-header", inputs: { applicationName: { classPropertyName: "applicationName", publicName: "applicationName", isSignal: true, isRequired: true, transformFunction: null }, symbol: { classPropertyName: "symbol", publicName: "symbol", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, applicationNameLink: { classPropertyName: "applicationNameLink", publicName: "applicationNameLink", isSignal: true, isRequired: false, transformFunction: null }, helpLink: { classPropertyName: "helpLink", publicName: "helpLink", isSignal: true, isRequired: false, transformFunction: null }, notificationsLink: { classPropertyName: "notificationsLink", publicName: "notificationsLink", isSignal: true, isRequired: false, transformFunction: null }, notificationsCount: { classPropertyName: "notificationsCount", publicName: "notificationsCount", isSignal: true, isRequired: false, transformFunction: null }, links: { classPropertyName: "links", publicName: "links", isSignal: true, isRequired: true, transformFunction: null }, projectPicker: { classPropertyName: "projectPicker", publicName: "projectPicker", isSignal: true, isRequired: false, transformFunction: null }, secondaryPicker: { classPropertyName: "secondaryPicker", publicName: "secondaryPicker", isSignal: true, isRequired: false, transformFunction: null }, loggedUser: { classPropertyName: "loggedUser", publicName: "loggedUser", isSignal: true, isRequired: false, transformFunction: null }, isPlatformPickerOpened: { classPropertyName: "isPlatformPickerOpened", publicName: "isPlatformPickerOpened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userLoggedIn: "userLoggedIn", userLoggedOut: "userLoggedOut", userProjectPick: "userProjectPick", userSecondaryPick: "userSecondaryPick", platformPickerClick: "platformPickerClick" }, ngImport: i0, template: "<nav class=\"appshell-meta-navigation\" aria-label=\"Top of the header navigation\">\n @if(isPlatformPickerOpened() !== null) {\n <div class=\"platform-picker-trigger\" [class.opened-widget]=\"isPlatformPickerOpened()\" (click)=\"openPlatformPicker()\" (keypress)=\"openPlatformPicker()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"10\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"10\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"10\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/></svg>\n </div>\n }\n\n <div class=\"app-id-ctn\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" class=\"header-symbol\" />\n }\n @if (logo()) {\n <img src=\"assets/logo/{{logo()}}\" alt=\"App logo in the header\" class=\"header-logo\" />\n }\n <h1>{{applicationName()}}</h1>\n </div>\n @if (projectPicker() && projectPicker()?.label) {\n <div class=\"header-picker\">\n <button [matMenuTriggerFor]=\"projectPickerMenu\" #projectPickerTrigger=\"matMenuTrigger\" (menuOpened)=\"projectPickerSearchInput?.focus()\"\n [class.active]=\"projectPickerTrigger.menuOpen\">\n {{userProjectPickChoice && projectPicker()?.options && projectPicker()?.options!.length > 0 ? projectPicker()!.label + userProjectPickChoice : projectPicker()!.label}}\n <appshell-icon [icon]=\"projectPickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n </div>\n <mat-menu #projectPickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-platform-header-picker-panel\">\n <div class=\"picker-search-ctn\" \n (click)=\"$event.stopPropagation()\" \n (mousedown)=\"$event.stopPropagation()\" \n [hidden]=\"!projectPicker()?.options || projectPicker()?.options!.length === 0\">\n <mat-form-field>\n @if (!projectPickerSearch) {\n <appshell-icon matPrefix class=\"prefix-icon\" aria-label=\"Search icon\" [icon]=\"'search'\" />\n }\n <input matInput type=\"text\" placeholder=\"Search for ...\" aria-label=\"Search options\"\n [(ngModel)]=\"projectPickerSearch\" (keydown)=\"onSearchKeydown($event)\"\n #projectPickerSearchInput />\n @if (projectPickerSearch) {\n <button matSuffix aria-label=\"Clear\" (click)=\"projectPickerSearch=''\">\n <appshell-icon [icon]=\"'close'\" aria-hidden=\"true\" />\n </button>\n }\n </mat-form-field>\n </div>\n <div class=\"picker-options-ctn\">\n @for (opt of filteredProjectPickerOptions(); track opt; let index = $index) {\n <button mat-menu-item (click)=\"pickProject(opt)\" (keypress)=\"pickProject(opt)\" [class.active]=\"projectPicker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n @if (!projectPicker()?.options || projectPicker()?.options!.length === 0) {\n <div class=\"no-options-text\">\n @if(projectPicker()?.noOptionsTitle) {\n <b>{{ projectPicker()?.noOptionsTitle }}</b>\n }\n @if(projectPicker()?.noOptionsMessage) {\n <div [innerHTML]=\"projectPicker()?.noOptionsMessage\"></div>\n }\n </div>\n } @else if (filteredProjectPickerOptions().length === 0) {\n <div class=\"no-options-text\">\n @if(projectPicker()?.noFilteredOptionsTitle) {\n <b>{{ projectPicker()?.noFilteredOptionsTitle }}</b>\n }\n @if(projectPicker()?.noFilteredOptionsMessage) {\n <div [innerHTML]=\"projectPicker()?.noFilteredOptionsMessage\"></div>\n }\n </div>\n <button class=\"clear-search-btn\" mat-button (click)=\"projectPickerSearch=''; $event.stopPropagation()\" aria-label=\"Clear search\">Clear search</button>\n }\n </div>\n </mat-menu>\n }\n @if (secondaryPicker() && secondaryPicker()?.label && secondaryPicker()?.options && secondaryPicker()?.options!.length > 0) {\n <div class=\"header-picker\">\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\"\n [class.active]=\"pickerTrigger.menuOpen\">\n {{userSecondaryPickChoice ? secondaryPicker()!.label + userSecondaryPickChoice : secondaryPicker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n </div>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-platform-header-picker-panel\">\n @for (opt of secondaryPicker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"pickSecondChoice(opt)\" (keypress)=\"pickSecondChoice(opt)\" [class.active]=\"secondaryPicker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n <div class=\"header-space\"></div>\n @for (link of links(); track link.label; let index = $index) {\n <a class=\"header-link\" [appShellLink]=\"link.anchor\" [class.active]=\"getCurrentUrlPath() === link.anchor\" target=\"{{link!.target || '_self'}}\" [class.last]=\"index+1 === links().length\">\n {{link.label}}\n </a>\n }\n @if (helpLink() && helpLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"helpLink()!.anchor\" target=\"{{helpLink()!.target || '_self'}}\" [matTooltip]=\"helpLink()!.label\" aria-label=\"Visit the help page\">\n <appshell-icon [icon]=\"helpLink()!.icon!\" aria-label=\"Help icon\" />\n </a>\n }\n @if (notificationsLink() && notificationsLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"notificationsLink()!.anchor\" target=\"{{notificationsLink()!.target || '_self'}}\" [matTooltip]=\"notificationsLink()!.label\" aria-label=\"Visit the notifications page\">\n <appshell-icon [icon]=\"notificationsLink()!.icon!\" aria-label=\"Notifications icon\" />\n @if (notificationsCount() > 0) {\n <div class=\"notification-count\" aria-label=\"Number of notifications\">\n {{notificationsCount() > 9 ? '9+' : notificationsCount()}}\n </div>\n }\n </a>\n }\n <div class=\"separator\"></div>\n <div class=\"user-ctn\">\n @if (loggedUser() !== null) {\n <button [matMenuTriggerFor]=\"logoutMenu\">\n @if (loggedUser()!.avatarSrc) {\n <div class=\"header-profile-picture\" [style.backgroundImage]=\"'url('+loggedUser()!.avatarSrc+')'\"></div>\n } @else {\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n }\n <div class=\"user-text\">{{loggedUser()?.fullName}}</div>\n </button>\n <mat-menu #logoutMenu=\"matMenu\" xPosition=\"before\" class=\"appshell-logout-panel\">\n <button mat-menu-item (click)=\"userLoggedOut.emit()\" (keypress)=\"userLoggedOut.emit()\" aria-label=\"Logout\">Log Out</button>\n </mat-menu>\n } @else {\n <button (click)=\"userLoggedIn.emit()\" (keypress)=\"userLoggedIn.emit()\" aria-label=\"Login\">\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n <div class=\"user-text\">Login</div>\n </button>\n }\n </div>\n</nav>", styles: ["appshell-platform-header{width:100%;--header-bg-color: var(--appshell-color-dark-green-main);--header-text-color: var(--text-color-on-main-color);--header-separator-color: var(--appshell-color-dark-green-light);--header-link-color: var(--appshell-color-dark-green-light);--header-link-hover-color: #ffffff;--header-link-selected-color: var(--appshell-color-accent-green-main);--header-border-bottom-color: var(--appshell-color-dark-green-main);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-platform-header.theme-white{--header-bg-color: #ffffff;--header-text-color: var(--appshell-color-dark-green-main);--header-separator-color: var(--appshell-color-grey-strong);--header-link-color: var(--appshell-color-grey-strong);--header-link-hover-color: var(--appshell-color-dark-green-main);--header-link-selected-color: var(--appshell-color-dark-green-main);--header-border-bottom-color: var(--appshell-color-grey-warm);--header-app-name-color: var(--appshell-color-dark-green-main)}appshell-platform-header.theme-purple{--header-bg-color: var(--appshell-color-violet-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-violet-light);--header-link-color: var(--appshell-color-violet-light);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-violet-dark);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-platform-header.theme-blue{--header-bg-color: var(--appshell-color-sky-blue-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-sky-blue-medium);--header-link-color: var(--appshell-color-sky-blue-medium);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-sky-blue-dark);--header-app-name-color: var(--appshell-color-grey-medium)}.appshell-meta-navigation{width:100%;display:flex;flex-direction:row;align-items:center;height:4rem;background-color:var(--header-bg-color);color:var(--header-text-color);padding:0;box-sizing:border-box;font-size:.875rem;line-height:1.25rem;font-weight:400;font-style:normal;border-bottom:1px solid var(--header-border-bottom-color)}.appshell-meta-navigation .platform-picker-trigger{height:4rem;width:4rem;display:flex;justify-content:center;align-items:center;cursor:pointer}.appshell-meta-navigation .platform-picker-trigger:hover,.appshell-meta-navigation .platform-picker-trigger.opened-widget{background-color:var(--appshell-color-dark-green-dark)}.appshell-meta-navigation .app-id-ctn{margin-left:2.25rem;margin-right:4rem;box-sizing:border-box;display:flex;align-items:center;text-decoration:none}.appshell-meta-navigation .app-id-ctn img{margin-right:.5rem}.appshell-meta-navigation .app-id-ctn img.header-symbol{height:1.5rem;width:1.5rem}.appshell-meta-navigation .app-id-ctn img.header-logo{height:2rem;width:auto;max-width:6rem;margin-right:4rem}.appshell-meta-navigation .app-id-ctn h1{color:var(--header-app-name-color);font-weight:500;margin:auto 0;font-size:1rem}.appshell-meta-navigation .header-link{color:var(--header-link-color);margin-left:2rem;text-decoration:none;font-size:1rem;font-style:normal;font-weight:500}.appshell-meta-navigation .header-link.last{margin-right:1.25rem}.appshell-meta-navigation .header-link:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link.active{color:var(--header-link-selected-color);text-decoration:underline}.appshell-meta-navigation .separator{width:1px;height:2rem;margin:auto 1rem;background-color:var(--header-separator-color)}.appshell-meta-navigation .header-picker{min-width:13rem;margin-right:1.5rem}.appshell-meta-navigation .header-picker button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;color:var(--header-link-color);font-size:1rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;line-height:1.5rem;text-align:start;gap:.25rem;padding:.5rem;height:85%;border:1px solid transparent}.appshell-meta-navigation .header-picker button appshell-icon,.appshell-meta-navigation .header-picker button mat-icon{width:1rem;height:1rem;display:flex;justify-content:center;align-items:center}.appshell-meta-navigation .header-picker button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-picker button.active{color:var(--header-link-selected-color);border-bottom:1px solid var(--header-link-selected-color)}.appshell-meta-navigation .header-icon{border-radius:50%;display:flex;height:4rem;width:4rem;justify-content:center;align-items:center;color:var(--header-link-color);position:relative}.appshell-meta-navigation .header-icon:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon .notification-count{height:1.25rem;width:1.25rem;border-radius:50%;background-color:#e10a0a;color:#fff;font-family:AppShellTextFont;font-size:.75rem;font-style:normal;font-weight:400;line-height:1.5rem;text-decoration:none;display:flex;align-items:center;justify-content:center;position:absolute;top:.75rem;right:.75rem}.appshell-meta-navigation .user-ctn{padding-left:.5rem;padding-right:1.25rem;display:flex;flex-direction:row;align-items:center;height:100%}.appshell-meta-navigation .user-ctn button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;width:100%;gap:.5rem;color:var(--header-link-color)}.appshell-meta-navigation .user-ctn button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .user-ctn button .header-profile-picture{width:1.5rem;height:1.5rem;border-radius:50%;background-size:cover;background-position:center;border:1px solid var(--appshell-color-grey-warm);aspect-ratio:1}.appshell-meta-navigation .user-ctn button .user-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;width:10rem;line-height:1.25rem;text-align:start}.header-space{flex:1}.appshell-logout-panel,.appshell-platform-header-picker-panel{border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important;width:13rem}.appshell-logout-panel>div,.appshell-platform-header-picker-panel>div{padding:0}.appshell-logout-panel{margin-top:1.1rem}.appshell-platform-header-picker-panel{padding:.75rem 0;margin-top:.9rem;--mat-menu-item-label-text-color: var(--appshell-color-dark-green-main)}.appshell-platform-header-picker-panel .picker-search-ctn{height:3.75rem;width:100%;border-bottom:1px solid var(--appshell-color-grey-strong)}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field{width:86%;margin:0 7%;--mdc-filled-text-field-container-color: var(--appshell-color-grey-light);--mat-form-field-state-layer-color: transparent;--mdc-filled-text-field-active-indicator-color: var(--appshell-color-grey-main);--mdc-filled-text-field-hover-active-indicator-color: var(--appshell-color-grey-strong);--mdc-filled-text-field-focus-active-indicator-color: var(--appshell-color-accent-green-main);--mat-form-field-container-vertical-padding: .75rem;--mat-form-field-container-height: 2.75rem}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field .prefix-icon{margin:0 .5rem}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field button{background:transparent;border:none;cursor:pointer}.appshell-platform-header-picker-panel .picker-options-ctn{max-height:18rem;overflow-y:auto;color:var(--mat-menu-item-label-text-color)}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text{padding:1rem;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;text-align:center}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text b{display:block}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text a{color:#00e}.appshell-platform-header-picker-panel .picker-options-ctn .clear-search-btn{padding:.75rem;height:3rem;width:100%;background:none;border:none;text-decoration:underline;text-underline-offset:.4rem;text-decoration-color:var(--appshell-color-accent-green-main);color:var(--appshell-color-dark-green-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;text-decoration-thickness:2px;cursor:pointer}.appshell-platform-header-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-platform-header-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-platform-header-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"], dependencies: [{ kind: "directive", type: AppShellLinkDirective, selector: "[appShellLink]", inputs: ["appShellLink"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$4.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i1$4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
337
+ }
338
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPlatformHeaderComponent, decorators: [{
339
+ type: Component,
340
+ args: [{ selector: 'appshell-platform-header', imports: [AppShellLinkDirective, MatTooltipModule, CommonModule, MatMenuModule, FormsModule, MatFormFieldModule, MatInputModule, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<nav class=\"appshell-meta-navigation\" aria-label=\"Top of the header navigation\">\n @if(isPlatformPickerOpened() !== null) {\n <div class=\"platform-picker-trigger\" [class.opened-widget]=\"isPlatformPickerOpened()\" (click)=\"openPlatformPicker()\" (keypress)=\"openPlatformPicker()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"10\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"10\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"10\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"40\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"10\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"40\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/><rect x=\"70\" y=\"70\" width=\"20\" height=\"20\" fill=\"#FFFFFF\"/></svg>\n </div>\n }\n\n <div class=\"app-id-ctn\">\n @if (symbol()) {\n <img src=\"assets/logo/{{symbol()}}\" alt=\"App symbol in the header\" class=\"header-symbol\" />\n }\n @if (logo()) {\n <img src=\"assets/logo/{{logo()}}\" alt=\"App logo in the header\" class=\"header-logo\" />\n }\n <h1>{{applicationName()}}</h1>\n </div>\n @if (projectPicker() && projectPicker()?.label) {\n <div class=\"header-picker\">\n <button [matMenuTriggerFor]=\"projectPickerMenu\" #projectPickerTrigger=\"matMenuTrigger\" (menuOpened)=\"projectPickerSearchInput?.focus()\"\n [class.active]=\"projectPickerTrigger.menuOpen\">\n {{userProjectPickChoice && projectPicker()?.options && projectPicker()?.options!.length > 0 ? projectPicker()!.label + userProjectPickChoice : projectPicker()!.label}}\n <appshell-icon [icon]=\"projectPickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n </div>\n <mat-menu #projectPickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-platform-header-picker-panel\">\n <div class=\"picker-search-ctn\" \n (click)=\"$event.stopPropagation()\" \n (mousedown)=\"$event.stopPropagation()\" \n [hidden]=\"!projectPicker()?.options || projectPicker()?.options!.length === 0\">\n <mat-form-field>\n @if (!projectPickerSearch) {\n <appshell-icon matPrefix class=\"prefix-icon\" aria-label=\"Search icon\" [icon]=\"'search'\" />\n }\n <input matInput type=\"text\" placeholder=\"Search for ...\" aria-label=\"Search options\"\n [(ngModel)]=\"projectPickerSearch\" (keydown)=\"onSearchKeydown($event)\"\n #projectPickerSearchInput />\n @if (projectPickerSearch) {\n <button matSuffix aria-label=\"Clear\" (click)=\"projectPickerSearch=''\">\n <appshell-icon [icon]=\"'close'\" aria-hidden=\"true\" />\n </button>\n }\n </mat-form-field>\n </div>\n <div class=\"picker-options-ctn\">\n @for (opt of filteredProjectPickerOptions(); track opt; let index = $index) {\n <button mat-menu-item (click)=\"pickProject(opt)\" (keypress)=\"pickProject(opt)\" [class.active]=\"projectPicker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n @if (!projectPicker()?.options || projectPicker()?.options!.length === 0) {\n <div class=\"no-options-text\">\n @if(projectPicker()?.noOptionsTitle) {\n <b>{{ projectPicker()?.noOptionsTitle }}</b>\n }\n @if(projectPicker()?.noOptionsMessage) {\n <div [innerHTML]=\"projectPicker()?.noOptionsMessage\"></div>\n }\n </div>\n } @else if (filteredProjectPickerOptions().length === 0) {\n <div class=\"no-options-text\">\n @if(projectPicker()?.noFilteredOptionsTitle) {\n <b>{{ projectPicker()?.noFilteredOptionsTitle }}</b>\n }\n @if(projectPicker()?.noFilteredOptionsMessage) {\n <div [innerHTML]=\"projectPicker()?.noFilteredOptionsMessage\"></div>\n }\n </div>\n <button class=\"clear-search-btn\" mat-button (click)=\"projectPickerSearch=''; $event.stopPropagation()\" aria-label=\"Clear search\">Clear search</button>\n }\n </div>\n </mat-menu>\n }\n @if (secondaryPicker() && secondaryPicker()?.label && secondaryPicker()?.options && secondaryPicker()?.options!.length > 0) {\n <div class=\"header-picker\">\n <button [matMenuTriggerFor]=\"pickerMenu\" #pickerTrigger=\"matMenuTrigger\"\n [class.active]=\"pickerTrigger.menuOpen\">\n {{userSecondaryPickChoice ? secondaryPicker()!.label + userSecondaryPickChoice : secondaryPicker()!.label}}\n <appshell-icon [icon]=\"pickerTrigger.menuOpen ? 'expand_less' : 'expand_more'\" />\n </button>\n </div>\n <mat-menu #pickerMenu=\"matMenu\" xPosition=\"after\" class=\"appshell-platform-header-picker-panel\">\n @for (opt of secondaryPicker()!.options; track opt; let index = $index) {\n <button mat-menu-item (click)=\"pickSecondChoice(opt)\" (keypress)=\"pickSecondChoice(opt)\" [class.active]=\"secondaryPicker()?.selected === opt\" attr.aria-label=\"{{opt}}\">{{ opt }}</button>\n }\n </mat-menu>\n }\n <div class=\"header-space\"></div>\n @for (link of links(); track link.label; let index = $index) {\n <a class=\"header-link\" [appShellLink]=\"link.anchor\" [class.active]=\"getCurrentUrlPath() === link.anchor\" target=\"{{link!.target || '_self'}}\" [class.last]=\"index+1 === links().length\">\n {{link.label}}\n </a>\n }\n @if (helpLink() && helpLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"helpLink()!.anchor\" target=\"{{helpLink()!.target || '_self'}}\" [matTooltip]=\"helpLink()!.label\" aria-label=\"Visit the help page\">\n <appshell-icon [icon]=\"helpLink()!.icon!\" aria-label=\"Help icon\" />\n </a>\n }\n @if (notificationsLink() && notificationsLink()?.icon) {\n <a class=\"header-icon\" [appShellLink]=\"notificationsLink()!.anchor\" target=\"{{notificationsLink()!.target || '_self'}}\" [matTooltip]=\"notificationsLink()!.label\" aria-label=\"Visit the notifications page\">\n <appshell-icon [icon]=\"notificationsLink()!.icon!\" aria-label=\"Notifications icon\" />\n @if (notificationsCount() > 0) {\n <div class=\"notification-count\" aria-label=\"Number of notifications\">\n {{notificationsCount() > 9 ? '9+' : notificationsCount()}}\n </div>\n }\n </a>\n }\n <div class=\"separator\"></div>\n <div class=\"user-ctn\">\n @if (loggedUser() !== null) {\n <button [matMenuTriggerFor]=\"logoutMenu\">\n @if (loggedUser()!.avatarSrc) {\n <div class=\"header-profile-picture\" [style.backgroundImage]=\"'url('+loggedUser()!.avatarSrc+')'\"></div>\n } @else {\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n }\n <div class=\"user-text\">{{loggedUser()?.fullName}}</div>\n </button>\n <mat-menu #logoutMenu=\"matMenu\" xPosition=\"before\" class=\"appshell-logout-panel\">\n <button mat-menu-item (click)=\"userLoggedOut.emit()\" (keypress)=\"userLoggedOut.emit()\" aria-label=\"Logout\">Log Out</button>\n </mat-menu>\n } @else {\n <button (click)=\"userLoggedIn.emit()\" (keypress)=\"userLoggedIn.emit()\" aria-label=\"Login\">\n <appshell-icon [icon]=\"'person'\" aria-label=\"Guest user icon\" />\n <div class=\"user-text\">Login</div>\n </button>\n }\n </div>\n</nav>", styles: ["appshell-platform-header{width:100%;--header-bg-color: var(--appshell-color-dark-green-main);--header-text-color: var(--text-color-on-main-color);--header-separator-color: var(--appshell-color-dark-green-light);--header-link-color: var(--appshell-color-dark-green-light);--header-link-hover-color: #ffffff;--header-link-selected-color: var(--appshell-color-accent-green-main);--header-border-bottom-color: var(--appshell-color-dark-green-main);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-platform-header.theme-white{--header-bg-color: #ffffff;--header-text-color: var(--appshell-color-dark-green-main);--header-separator-color: var(--appshell-color-grey-strong);--header-link-color: var(--appshell-color-grey-strong);--header-link-hover-color: var(--appshell-color-dark-green-main);--header-link-selected-color: var(--appshell-color-dark-green-main);--header-border-bottom-color: var(--appshell-color-grey-warm);--header-app-name-color: var(--appshell-color-dark-green-main)}appshell-platform-header.theme-purple{--header-bg-color: var(--appshell-color-violet-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-violet-light);--header-link-color: var(--appshell-color-violet-light);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-violet-dark);--header-app-name-color: var(--appshell-color-grey-medium)}appshell-platform-header.theme-blue{--header-bg-color: var(--appshell-color-sky-blue-dark);--header-text-color: #ffffff;--header-separator-color: var(--appshell-color-sky-blue-medium);--header-link-color: var(--appshell-color-sky-blue-medium);--header-link-hover-color: #ffffff;--header-link-selected-color: #ffffff;--header-border-bottom-color: var(--appshell-color-sky-blue-dark);--header-app-name-color: var(--appshell-color-grey-medium)}.appshell-meta-navigation{width:100%;display:flex;flex-direction:row;align-items:center;height:4rem;background-color:var(--header-bg-color);color:var(--header-text-color);padding:0;box-sizing:border-box;font-size:.875rem;line-height:1.25rem;font-weight:400;font-style:normal;border-bottom:1px solid var(--header-border-bottom-color)}.appshell-meta-navigation .platform-picker-trigger{height:4rem;width:4rem;display:flex;justify-content:center;align-items:center;cursor:pointer}.appshell-meta-navigation .platform-picker-trigger:hover,.appshell-meta-navigation .platform-picker-trigger.opened-widget{background-color:var(--appshell-color-dark-green-dark)}.appshell-meta-navigation .app-id-ctn{margin-left:2.25rem;margin-right:4rem;box-sizing:border-box;display:flex;align-items:center;text-decoration:none}.appshell-meta-navigation .app-id-ctn img{margin-right:.5rem}.appshell-meta-navigation .app-id-ctn img.header-symbol{height:1.5rem;width:1.5rem}.appshell-meta-navigation .app-id-ctn img.header-logo{height:2rem;width:auto;max-width:6rem;margin-right:4rem}.appshell-meta-navigation .app-id-ctn h1{color:var(--header-app-name-color);font-weight:500;margin:auto 0;font-size:1rem}.appshell-meta-navigation .header-link{color:var(--header-link-color);margin-left:2rem;text-decoration:none;font-size:1rem;font-style:normal;font-weight:500}.appshell-meta-navigation .header-link.last{margin-right:1.25rem}.appshell-meta-navigation .header-link:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-link.active{color:var(--header-link-selected-color);text-decoration:underline}.appshell-meta-navigation .separator{width:1px;height:2rem;margin:auto 1rem;background-color:var(--header-separator-color)}.appshell-meta-navigation .header-picker{min-width:13rem;margin-right:1.5rem}.appshell-meta-navigation .header-picker button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;color:var(--header-link-color);font-size:1rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;line-height:1.5rem;text-align:start;gap:.25rem;padding:.5rem;height:85%;border:1px solid transparent}.appshell-meta-navigation .header-picker button appshell-icon,.appshell-meta-navigation .header-picker button mat-icon{width:1rem;height:1rem;display:flex;justify-content:center;align-items:center}.appshell-meta-navigation .header-picker button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-picker button.active{color:var(--header-link-selected-color);border-bottom:1px solid var(--header-link-selected-color)}.appshell-meta-navigation .header-icon{border-radius:50%;display:flex;height:4rem;width:4rem;justify-content:center;align-items:center;color:var(--header-link-color);position:relative}.appshell-meta-navigation .header-icon:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .header-icon .notification-count{height:1.25rem;width:1.25rem;border-radius:50%;background-color:#e10a0a;color:#fff;font-family:AppShellTextFont;font-size:.75rem;font-style:normal;font-weight:400;line-height:1.5rem;text-decoration:none;display:flex;align-items:center;justify-content:center;position:absolute;top:.75rem;right:.75rem}.appshell-meta-navigation .user-ctn{padding-left:.5rem;padding-right:1.25rem;display:flex;flex-direction:row;align-items:center;height:100%}.appshell-meta-navigation .user-ctn button{cursor:pointer;display:flex;flex-direction:row;align-items:center;background-color:transparent;border:none;width:100%;gap:.5rem;color:var(--header-link-color)}.appshell-meta-navigation .user-ctn button:hover{color:var(--header-link-hover-color)}.appshell-meta-navigation .user-ctn button .header-profile-picture{width:1.5rem;height:1.5rem;border-radius:50%;background-size:cover;background-position:center;border:1px solid var(--appshell-color-grey-warm);aspect-ratio:1}.appshell-meta-navigation .user-ctn button .user-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;font-family:AppShellTextFont;width:10rem;line-height:1.25rem;text-align:start}.header-space{flex:1}.appshell-logout-panel,.appshell-platform-header-picker-panel{border-radius:.125rem!important;border:1px solid var(--appshell-color-grey-main);box-shadow:none!important;width:13rem}.appshell-logout-panel>div,.appshell-platform-header-picker-panel>div{padding:0}.appshell-logout-panel{margin-top:1.1rem}.appshell-platform-header-picker-panel{padding:.75rem 0;margin-top:.9rem;--mat-menu-item-label-text-color: var(--appshell-color-dark-green-main)}.appshell-platform-header-picker-panel .picker-search-ctn{height:3.75rem;width:100%;border-bottom:1px solid var(--appshell-color-grey-strong)}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field{width:86%;margin:0 7%;--mdc-filled-text-field-container-color: var(--appshell-color-grey-light);--mat-form-field-state-layer-color: transparent;--mdc-filled-text-field-active-indicator-color: var(--appshell-color-grey-main);--mdc-filled-text-field-hover-active-indicator-color: var(--appshell-color-grey-strong);--mdc-filled-text-field-focus-active-indicator-color: var(--appshell-color-accent-green-main);--mat-form-field-container-vertical-padding: .75rem;--mat-form-field-container-height: 2.75rem}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field .prefix-icon{margin:0 .5rem}.appshell-platform-header-picker-panel .picker-search-ctn mat-form-field button{background:transparent;border:none;cursor:pointer}.appshell-platform-header-picker-panel .picker-options-ctn{max-height:18rem;overflow-y:auto;color:var(--mat-menu-item-label-text-color)}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text{padding:1rem;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;text-align:center}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text b{display:block}.appshell-platform-header-picker-panel .picker-options-ctn .no-options-text a{color:#00e}.appshell-platform-header-picker-panel .picker-options-ctn .clear-search-btn{padding:.75rem;height:3rem;width:100%;background:none;border:none;text-decoration:underline;text-underline-offset:.4rem;text-decoration-color:var(--appshell-color-accent-green-main);color:var(--appshell-color-dark-green-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;text-decoration-thickness:2px;cursor:pointer}.appshell-platform-header-picker-panel button.active{background-color:var(--appshell-color-grey-neutral);border-left:2px solid var(--appshell-color-accent-green-main)}.appshell-platform-header-picker-panel button:focus-visible{outline:2px solid #0069E5;outline-offset:-.1rem}.appshell-platform-header-picker-panel button:hover{background-color:var(--appshell-color-grey-light)}\n"] }]
341
+ }], ctorParameters: () => [{ type: i1.Router }] });
342
+
343
+ class AppShellPlatformLayoutComponent {
344
+ headerVariant = input('');
345
+ applicationSymbol = input();
346
+ applicationLogo = input();
347
+ applicationName = input.required();
348
+ applicationNameLink = input();
349
+ appShellHelpLink = input();
350
+ appShellNotificationsLink = input();
351
+ appShellNotificationsCount = input(0);
352
+ headerLinks = input.required();
353
+ headerProjectPicker = input();
354
+ headerSecondaryPicker = input();
355
+ sidenavSections = input.required();
356
+ sidenavLinks = input();
357
+ loggedUser = input.required();
358
+ isPlatformPickerOpened = input(null);
359
+ userLoggedIn = output();
360
+ userLoggedOut = output();
361
+ userProjectPick = output();
362
+ userSecondaryPick = output();
363
+ platformPickerClick = output();
364
+ constructor() { }
365
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPlatformLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
366
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellPlatformLayoutComponent, isStandalone: true, selector: "appshell-platform-layout", inputs: { headerVariant: { classPropertyName: "headerVariant", publicName: "headerVariant", isSignal: true, isRequired: false, transformFunction: null }, applicationSymbol: { classPropertyName: "applicationSymbol", publicName: "applicationSymbol", isSignal: true, isRequired: false, transformFunction: null }, applicationLogo: { classPropertyName: "applicationLogo", publicName: "applicationLogo", isSignal: true, isRequired: false, transformFunction: null }, applicationName: { classPropertyName: "applicationName", publicName: "applicationName", isSignal: true, isRequired: true, transformFunction: null }, applicationNameLink: { classPropertyName: "applicationNameLink", publicName: "applicationNameLink", isSignal: true, isRequired: false, transformFunction: null }, appShellHelpLink: { classPropertyName: "appShellHelpLink", publicName: "appShellHelpLink", isSignal: true, isRequired: false, transformFunction: null }, appShellNotificationsLink: { classPropertyName: "appShellNotificationsLink", publicName: "appShellNotificationsLink", isSignal: true, isRequired: false, transformFunction: null }, appShellNotificationsCount: { classPropertyName: "appShellNotificationsCount", publicName: "appShellNotificationsCount", isSignal: true, isRequired: false, transformFunction: null }, headerLinks: { classPropertyName: "headerLinks", publicName: "headerLinks", isSignal: true, isRequired: true, transformFunction: null }, headerProjectPicker: { classPropertyName: "headerProjectPicker", publicName: "headerProjectPicker", isSignal: true, isRequired: false, transformFunction: null }, headerSecondaryPicker: { classPropertyName: "headerSecondaryPicker", publicName: "headerSecondaryPicker", isSignal: true, isRequired: false, transformFunction: null }, sidenavSections: { classPropertyName: "sidenavSections", publicName: "sidenavSections", isSignal: true, isRequired: true, transformFunction: null }, sidenavLinks: { classPropertyName: "sidenavLinks", publicName: "sidenavLinks", isSignal: true, isRequired: false, transformFunction: null }, loggedUser: { classPropertyName: "loggedUser", publicName: "loggedUser", isSignal: true, isRequired: true, transformFunction: null }, isPlatformPickerOpened: { classPropertyName: "isPlatformPickerOpened", publicName: "isPlatformPickerOpened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userLoggedIn: "userLoggedIn", userLoggedOut: "userLoggedOut", userProjectPick: "userProjectPick", userSecondaryPick: "userSecondaryPick", platformPickerClick: "platformPickerClick" }, ngImport: i0, template: "<appshell-platform-header\n [class]=\"headerVariant()\"\n [symbol]=\"applicationSymbol()\"\n [logo]=\"applicationLogo()\"\n [applicationName]=\"applicationName()\"\n [applicationNameLink]=\"applicationNameLink()\"\n [helpLink]=\"appShellHelpLink()\"\n [notificationsLink]=\"appShellNotificationsLink()\"\n [notificationsCount]=\"appShellNotificationsCount()\"\n [links]=\"headerLinks()\"\n [projectPicker]=\"headerProjectPicker()\"\n [secondaryPicker]=\"headerSecondaryPicker()\"\n [loggedUser]=\"loggedUser()\"\n [isPlatformPickerOpened]=\"isPlatformPickerOpened()\"\n (userLoggedIn)=\"userLoggedIn.emit()\"\n (userLoggedOut)=\"userLoggedOut.emit()\"\n (platformPickerClick)=\"platformPickerClick.emit()\"\n (userProjectPick)=\"userProjectPick.emit($event)\"\n (userSecondaryPick)=\"userSecondaryPick.emit($event)\">\n</appshell-platform-header>\n\n<section id=\"appshell-layout-content\">\n <mat-sidenav-container>\n @if (sidenavSections() && sidenavSections().length) {\n <mat-sidenav opened mode=\"side\" disableClose [fixedInViewport]=\"true\" [fixedTopGap]=\"64\">\n <appshell-sidebar-menu [sections]=\"sidenavSections()\" [links]=\"sidenavLinks()\"></appshell-sidebar-menu>\n </mat-sidenav>\n }\n <mat-sidenav-content>\n <main>\n <router-outlet></router-outlet>\n </main>\n </mat-sidenav-content>\n </mat-sidenav-container>\n</section>", styles: ["appshell-platform-header{display:flex;position:fixed;z-index:99;width:100%}appshell-navigation{display:flex;flex-direction:row}#appshell-layout-content{flex-grow:1;display:flex;height:100%;padding-top:4rem}#appshell-layout-content mat-sidenav-container{width:100%}#appshell-layout-content appshell-sidebar-menu{display:flex;flex-direction:column;z-index:2}#appshell-layout-content mat-sidenav-content{box-sizing:border-box;background-color:var(--background-color)}#appshell-layout-content mat-sidenav-content main{display:flex;height:100%}\n"], dependencies: [{ kind: "component", type: AppShellSidebarMenuComponent, selector: "appshell-sidebar-menu", inputs: ["sections", "links"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "component", type: AppShellPlatformHeaderComponent, selector: "appshell-platform-header", inputs: ["applicationName", "symbol", "logo", "applicationNameLink", "helpLink", "notificationsLink", "notificationsCount", "links", "projectPicker", "secondaryPicker", "loggedUser", "isPlatformPickerOpened"], outputs: ["userLoggedIn", "userLoggedOut", "userProjectPick", "userSecondaryPick", "platformPickerClick"] }] });
367
+ }
368
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellPlatformLayoutComponent, decorators: [{
369
+ type: Component,
370
+ args: [{ selector: 'appshell-platform-layout', imports: [AppShellSidebarMenuComponent, RouterOutlet, MatSidenavModule, AppShellPlatformHeaderComponent], template: "<appshell-platform-header\n [class]=\"headerVariant()\"\n [symbol]=\"applicationSymbol()\"\n [logo]=\"applicationLogo()\"\n [applicationName]=\"applicationName()\"\n [applicationNameLink]=\"applicationNameLink()\"\n [helpLink]=\"appShellHelpLink()\"\n [notificationsLink]=\"appShellNotificationsLink()\"\n [notificationsCount]=\"appShellNotificationsCount()\"\n [links]=\"headerLinks()\"\n [projectPicker]=\"headerProjectPicker()\"\n [secondaryPicker]=\"headerSecondaryPicker()\"\n [loggedUser]=\"loggedUser()\"\n [isPlatformPickerOpened]=\"isPlatformPickerOpened()\"\n (userLoggedIn)=\"userLoggedIn.emit()\"\n (userLoggedOut)=\"userLoggedOut.emit()\"\n (platformPickerClick)=\"platformPickerClick.emit()\"\n (userProjectPick)=\"userProjectPick.emit($event)\"\n (userSecondaryPick)=\"userSecondaryPick.emit($event)\">\n</appshell-platform-header>\n\n<section id=\"appshell-layout-content\">\n <mat-sidenav-container>\n @if (sidenavSections() && sidenavSections().length) {\n <mat-sidenav opened mode=\"side\" disableClose [fixedInViewport]=\"true\" [fixedTopGap]=\"64\">\n <appshell-sidebar-menu [sections]=\"sidenavSections()\" [links]=\"sidenavLinks()\"></appshell-sidebar-menu>\n </mat-sidenav>\n }\n <mat-sidenav-content>\n <main>\n <router-outlet></router-outlet>\n </main>\n </mat-sidenav-content>\n </mat-sidenav-container>\n</section>", styles: ["appshell-platform-header{display:flex;position:fixed;z-index:99;width:100%}appshell-navigation{display:flex;flex-direction:row}#appshell-layout-content{flex-grow:1;display:flex;height:100%;padding-top:4rem}#appshell-layout-content mat-sidenav-container{width:100%}#appshell-layout-content appshell-sidebar-menu{display:flex;flex-direction:column;z-index:2}#appshell-layout-content mat-sidenav-content{box-sizing:border-box;background-color:var(--background-color)}#appshell-layout-content mat-sidenav-content main{display:flex;height:100%}\n"] }]
371
+ }], ctorParameters: () => [] });
372
+
373
+ class AppShellProductCardComponent {
374
+ router;
375
+ ngZone;
376
+ labelsChipSet;
377
+ title = input.required();
378
+ description = input.required();
379
+ image = input();
380
+ labels = input();
381
+ redirectTo = input();
382
+ resizeObserver = new ResizeObserver(this.debounce(() => {
383
+ this.ngZone.run(() => {
384
+ window.requestAnimationFrame(() => {
385
+ this.hideOverflowingLabels();
386
+ });
387
+ });
388
+ }, 100));
389
+ constructor(router, ngZone) {
390
+ this.router = router;
391
+ this.ngZone = ngZone;
392
+ }
393
+ debounce(func, wait) {
394
+ let timeout;
395
+ return (...args) => {
396
+ clearTimeout(timeout);
397
+ timeout = window.setTimeout(() => func.apply(this, args), wait);
398
+ };
399
+ }
400
+ ngAfterViewChecked() {
401
+ this.hideOverflowingLabels();
402
+ this.resizeObserver.observe(this.labelsChipSet.nativeElement);
403
+ }
404
+ onClick() {
405
+ this.router.navigate([this.redirectTo()]);
406
+ }
407
+ hideOverflowingLabels() {
408
+ const twoLinesHeight = 4.5 * 16; // Each label uses 2 rem with a gap of .5 rem where 1 rem = 16px
409
+ const labelsChipSetDiv = this.labelsChipSet.nativeElement.firstChild;
410
+ const chipsChildren = Array.from(labelsChipSetDiv.children).filter((child) => child.tagName.toLowerCase() === 'appshell-chip');
411
+ chipsChildren.forEach((child) => {
412
+ if (child.id === 'extra-labels') {
413
+ child.style.display = 'none';
414
+ }
415
+ else {
416
+ child.style.display = 'block';
417
+ }
418
+ });
419
+ if (chipsChildren.length <= 2) {
420
+ return;
421
+ }
422
+ let index = chipsChildren.length - 2; // Start from the second last child
423
+ const hiddenLabels = [];
424
+ const extraLabels = labelsChipSetDiv.querySelector('#extra-labels');
425
+ if (labelsChipSetDiv.scrollHeight > twoLinesHeight && extraLabels) {
426
+ extraLabels.style.display = 'block';
427
+ }
428
+ while (labelsChipSetDiv.scrollHeight > twoLinesHeight && index >= 0) {
429
+ const label = chipsChildren[index];
430
+ label.style.display = 'none';
431
+ const labelText = label.querySelector('.mdc-evolution-chip__text-label.mat-mdc-chip-action-label')?.textContent;
432
+ if (labelText) {
433
+ hiddenLabels.push(labelText);
434
+ index--;
435
+ }
436
+ }
437
+ if (hiddenLabels.length > 0 && extraLabels) {
438
+ this.changeExtraLabel(extraLabels, hiddenLabels);
439
+ }
440
+ }
441
+ changeExtraLabel(labelEl, removedLabels) {
442
+ labelEl.classList.add('tooltip-chip');
443
+ let existingSpan = labelEl.querySelector('.tooltip-text');
444
+ if (existingSpan) {
445
+ labelEl.removeChild(existingSpan);
446
+ }
447
+ existingSpan = document.createElement('span');
448
+ existingSpan.classList.add('tooltip-text');
449
+ existingSpan.textContent = `${[...removedLabels].reverse().join(', ')}`;
450
+ labelEl.appendChild(existingSpan);
451
+ const textLabel = labelEl?.querySelector('.mdc-evolution-chip__text-label.mat-mdc-chip-action-label');
452
+ if (textLabel) {
453
+ textLabel.textContent = `+${removedLabels.length}`;
454
+ }
455
+ }
456
+ ngOnDestroy() {
457
+ if (this.resizeObserver) {
458
+ this.resizeObserver.disconnect();
459
+ }
460
+ }
461
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCardComponent, deps: [{ token: i1.Router }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
462
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellProductCardComponent, isStandalone: true, selector: "appshell-product-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: true, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, redirectTo: { classPropertyName: "redirectTo", publicName: "redirectTo", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "labelsChipSet", first: true, predicate: ["labelsChipSet"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: "<mat-card class=\"appshell-product-card\" appearance=\"outlined\" tabindex=\"0\" (click)=\"onClick()\" (keydown.enter)=\"onClick()\" (keydown.space)=\"onClick()\">\n <mat-card-header>\n <mat-card-title-group>\n <mat-card-title>{{title()}}</mat-card-title>\n @if (image()) {\n <img mat-card-image [src]=\"image()\" alt=\"\">\n }\n </mat-card-title-group>\n </mat-card-header>\n <mat-card-content>\n {{description()}}\n </mat-card-content>\n <mat-card-actions>\n <mat-chip-set attr.aria-label=\"{{title()}} label\" class=\"appshell-product-card-labels\" #labelsChipSet>\n @for (label of labels(); track label) {\n <appshell-chip [label]=\"label\"></appshell-chip>\n }\n <appshell-chip id=\"extra-labels\" class=\"tooltip-chip\" label=\"+X\"></appshell-chip>\n </mat-chip-set>\n </mat-card-actions>\n</mat-card>", styles: [".appshell-product-card{padding:.5rem;border-radius:.15rem!important;border-width:1px!important;border-color:var(--appshell-color-grey-warm)!important;text-decoration:none;cursor:pointer;color:var(--appshell-color-secondary-main);height:100%;max-width:35rem}.appshell-product-card:hover{color:var(--appshell-color-secondary-medium)}.appshell-product-card mat-card-header{height:3rem;padding:1rem}.appshell-product-card mat-card-header mat-card-title-group{gap:1rem;align-items:center}.appshell-product-card mat-card-header mat-card-title-group mat-card-title{font-family:AppShellHeadingFont;font-size:1.25rem;font-style:normal;font-weight:500;line-height:120%;letter-spacing:.00625rem;overflow:hidden;display:-webkit-box;line-clamp:2;-webkit-line-clamp:2;-webkit-box-orient:vertical}.appshell-product-card mat-card-header mat-card-title-group img{width:2.5rem;height:2.5rem}.appshell-product-card mat-card-content{font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:120%;letter-spacing:.00625rem;overflow:hidden;display:-webkit-box;line-clamp:3;-webkit-line-clamp:3;-webkit-box-orient:vertical;height:3rem}.appshell-product-card mat-card-actions{padding:0 1rem;display:flex;flex-direction:column;align-items:start;gap:1rem;margin:1.5rem 0 1rem;min-height:unset}.appshell-product-card mat-card-actions .appshell-product-card-labels{max-height:4.5rem;width:100%}.appshell-product-card mat-card-actions .appshell-product-card-labels>div{row-gap:.5rem;column-gap:1rem}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip{position:relative}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip .tooltip-text{visibility:hidden;font-size:.875rem;width:10rem;background-color:#000;color:#fff;text-align:center;border-radius:6px;padding:.5rem;position:absolute;z-index:1;bottom:130%;left:50%;margin-left:-5.5rem}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip .tooltip-text:after{content:\"\";position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:black transparent transparent transparent}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip:hover .tooltip-text{visibility:visible}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2$1.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i2$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i2$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i2$1.MatCardImage, selector: "[mat-card-image], [matCardImage]" }, { kind: "directive", type: i2$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i2$1.MatCardTitleGroup, selector: "mat-card-title-group" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$2.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: AppShellChipComponent, selector: "appshell-chip", inputs: ["label"] }, { kind: "ngmodule", type: MatTooltipModule }], encapsulation: i0.ViewEncapsulation.None });
463
+ }
464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCardComponent, decorators: [{
465
+ type: Component,
466
+ args: [{ selector: 'appshell-product-card', imports: [MatCardModule, MatButtonModule, MatChipsModule, AppShellChipComponent, AppShellChipComponent, MatTooltipModule], encapsulation: ViewEncapsulation.None, template: "<mat-card class=\"appshell-product-card\" appearance=\"outlined\" tabindex=\"0\" (click)=\"onClick()\" (keydown.enter)=\"onClick()\" (keydown.space)=\"onClick()\">\n <mat-card-header>\n <mat-card-title-group>\n <mat-card-title>{{title()}}</mat-card-title>\n @if (image()) {\n <img mat-card-image [src]=\"image()\" alt=\"\">\n }\n </mat-card-title-group>\n </mat-card-header>\n <mat-card-content>\n {{description()}}\n </mat-card-content>\n <mat-card-actions>\n <mat-chip-set attr.aria-label=\"{{title()}} label\" class=\"appshell-product-card-labels\" #labelsChipSet>\n @for (label of labels(); track label) {\n <appshell-chip [label]=\"label\"></appshell-chip>\n }\n <appshell-chip id=\"extra-labels\" class=\"tooltip-chip\" label=\"+X\"></appshell-chip>\n </mat-chip-set>\n </mat-card-actions>\n</mat-card>", styles: [".appshell-product-card{padding:.5rem;border-radius:.15rem!important;border-width:1px!important;border-color:var(--appshell-color-grey-warm)!important;text-decoration:none;cursor:pointer;color:var(--appshell-color-secondary-main);height:100%;max-width:35rem}.appshell-product-card:hover{color:var(--appshell-color-secondary-medium)}.appshell-product-card mat-card-header{height:3rem;padding:1rem}.appshell-product-card mat-card-header mat-card-title-group{gap:1rem;align-items:center}.appshell-product-card mat-card-header mat-card-title-group mat-card-title{font-family:AppShellHeadingFont;font-size:1.25rem;font-style:normal;font-weight:500;line-height:120%;letter-spacing:.00625rem;overflow:hidden;display:-webkit-box;line-clamp:2;-webkit-line-clamp:2;-webkit-box-orient:vertical}.appshell-product-card mat-card-header mat-card-title-group img{width:2.5rem;height:2.5rem}.appshell-product-card mat-card-content{font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:120%;letter-spacing:.00625rem;overflow:hidden;display:-webkit-box;line-clamp:3;-webkit-line-clamp:3;-webkit-box-orient:vertical;height:3rem}.appshell-product-card mat-card-actions{padding:0 1rem;display:flex;flex-direction:column;align-items:start;gap:1rem;margin:1.5rem 0 1rem;min-height:unset}.appshell-product-card mat-card-actions .appshell-product-card-labels{max-height:4.5rem;width:100%}.appshell-product-card mat-card-actions .appshell-product-card-labels>div{row-gap:.5rem;column-gap:1rem}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip{position:relative}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip .tooltip-text{visibility:hidden;font-size:.875rem;width:10rem;background-color:#000;color:#fff;text-align:center;border-radius:6px;padding:.5rem;position:absolute;z-index:1;bottom:130%;left:50%;margin-left:-5.5rem}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip .tooltip-text:after{content:\"\";position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:black transparent transparent transparent}.appshell-product-card mat-card-actions .appshell-product-card-labels>div .tooltip-chip:hover .tooltip-text{visibility:visible}\n"] }]
467
+ }], ctorParameters: () => [{ type: i1.Router }, { type: i0.NgZone }], propDecorators: { labelsChipSet: [{
468
+ type: ViewChild,
469
+ args: ['labelsChipSet', { static: true, read: ElementRef }]
470
+ }] } });
471
+
472
+ class AppShellProductCardV2Component {
473
+ router;
474
+ title = input.required();
475
+ description = input.required();
476
+ image = input();
477
+ link = input();
478
+ buttonText = input();
479
+ labels = input();
480
+ redirectTo = input();
481
+ constructor(router) {
482
+ this.router = router;
483
+ }
484
+ onClick() {
485
+ this.router.navigate([this.redirectTo()]);
486
+ }
487
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCardV2Component, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
488
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellProductCardV2Component, isStandalone: true, selector: "appshell-product-card-v2", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: true, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, buttonText: { classPropertyName: "buttonText", publicName: "buttonText", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, redirectTo: { classPropertyName: "redirectTo", publicName: "redirectTo", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-card class=\"appshell-product-card-v2\" appearance=\"outlined\" tabindex=\"0\" (click)=\"onClick()\" (keydown.enter)=\"onClick()\" (keydown.space)=\"onClick()\">\n <mat-card-content>\n <div class=\"appshell-product-card-v2-img\">\n <img mat-card-image [src]=\"image()\" alt=\"\">\n </div>\n <div class=\"appshell-product-card-v2-data\">\n <div class=\"labels\">\n @for (label of labels(); track label; let index = $index) {\n <span>\n {{label}}\n </span>\n }\n </div>\n <span class=\"title\">{{title()}}</span>\n <div class=\"description\">{{description()}}</div>\n </div>\n </mat-card-content>\n</mat-card>", styles: [".appshell-product-card-v2{border-radius:.15rem!important;border-width:1px!important;border-color:var(--appshell-color-grey-warm)!important;gap:1rem;text-decoration:none;cursor:pointer}.appshell-product-card-v2 mat-card-content{color:var(--appshell-color-secondary-main);letter-spacing:.00625rem;display:flex;flex-direction:row;height:10rem;padding:0!important}.appshell-product-card-v2 mat-card-content:hover{color:var(--appshell-color-secondary-medium)}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-img{padding:1.5rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-img img{width:7rem;height:7rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data{display:flex;flex-direction:column;justify-content:start;padding:1rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;height:1.25rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span{display:inline-block;white-space:nowrap}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span:before{content:\"-\";margin-right:.1rem;margin-left:.1rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span:first-child:before{content:\"\";margin-right:0;margin-left:0}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .title{font-size:1.5rem;font-style:normal;font-weight:700;line-height:2.25rem;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;line-clamp:1;overflow:hidden;text-overflow:ellipsis}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .description{margin-top:.5rem;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2$1.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i2$1.MatCardImage, selector: "[mat-card-image], [matCardImage]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatChipsModule }], encapsulation: i0.ViewEncapsulation.None });
489
+ }
490
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCardV2Component, decorators: [{
491
+ type: Component,
492
+ args: [{ selector: 'appshell-product-card-v2', imports: [MatCardModule, MatButtonModule, MatChipsModule], encapsulation: ViewEncapsulation.None, template: "<mat-card class=\"appshell-product-card-v2\" appearance=\"outlined\" tabindex=\"0\" (click)=\"onClick()\" (keydown.enter)=\"onClick()\" (keydown.space)=\"onClick()\">\n <mat-card-content>\n <div class=\"appshell-product-card-v2-img\">\n <img mat-card-image [src]=\"image()\" alt=\"\">\n </div>\n <div class=\"appshell-product-card-v2-data\">\n <div class=\"labels\">\n @for (label of labels(); track label; let index = $index) {\n <span>\n {{label}}\n </span>\n }\n </div>\n <span class=\"title\">{{title()}}</span>\n <div class=\"description\">{{description()}}</div>\n </div>\n </mat-card-content>\n</mat-card>", styles: [".appshell-product-card-v2{border-radius:.15rem!important;border-width:1px!important;border-color:var(--appshell-color-grey-warm)!important;gap:1rem;text-decoration:none;cursor:pointer}.appshell-product-card-v2 mat-card-content{color:var(--appshell-color-secondary-main);letter-spacing:.00625rem;display:flex;flex-direction:row;height:10rem;padding:0!important}.appshell-product-card-v2 mat-card-content:hover{color:var(--appshell-color-secondary-medium)}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-img{padding:1.5rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-img img{width:7rem;height:7rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data{display:flex;flex-direction:column;justify-content:start;padding:1rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;height:1.25rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span{display:inline-block;white-space:nowrap}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span:before{content:\"-\";margin-right:.1rem;margin-left:.1rem}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .labels span:first-child:before{content:\"\";margin-right:0;margin-left:0}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .title{font-size:1.5rem;font-style:normal;font-weight:700;line-height:2.25rem;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;line-clamp:1;overflow:hidden;text-overflow:ellipsis}.appshell-product-card-v2 mat-card-content .appshell-product-card-v2-data .description{margin-top:.5rem;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3}\n"] }]
493
+ }], ctorParameters: () => [{ type: i1.Router }] });
494
+
495
+ class AppShellToastComponent {
496
+ notification = input();
497
+ closed = output();
498
+ closeToast() {
499
+ this.closed.emit(true);
500
+ }
501
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
502
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.11", type: AppShellToastComponent, isStandalone: true, selector: "appshell-toast", inputs: { notification: { classPropertyName: "notification", publicName: "notification", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<div class=\"appshell-toast\">\n <div class=\"appshell-toast-content\">\n <h4>{{ notification()?.title }}</h4>\n <p>{{ notification()?.message }}</p>\n </div>\n <button (click)=\"closeToast()\">\n <appshell-icon [icon]=\"'close'\"></appshell-icon>\n </button>\n</div>", styles: [".appshell-toast{display:flex;flex-direction:row;justify-content:space-between;width:17rem;padding:.75rem .5rem .75rem 1rem;align-items:center;gap:.5rem;flex-shrink:0;border-radius:.125rem;border:1px solid #EFEEEB;background:#fff;box-shadow:0 2px 12px #0000000d}.appshell-toast .appshell-toast-content{height:100%}.appshell-toast .appshell-toast-content h4{overflow:hidden;color:var(--black, #191919);text-overflow:ellipsis;margin:0;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:700;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;line-clamp:1;-webkit-line-clamp:1}.appshell-toast .appshell-toast-content p{margin:0;overflow:hidden;color:var(--appshell-color-grey-main);text-overflow:ellipsis;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;line-clamp:1;-webkit-line-clamp:1}.appshell-toast button{width:2rem;height:2rem;background:transparent;border:none;cursor:pointer}\n"], dependencies: [{ kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }] });
503
+ }
504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastComponent, decorators: [{
505
+ type: Component,
506
+ args: [{ selector: 'appshell-toast', imports: [AppShellIconComponent], template: "<div class=\"appshell-toast\">\n <div class=\"appshell-toast-content\">\n <h4>{{ notification()?.title }}</h4>\n <p>{{ notification()?.message }}</p>\n </div>\n <button (click)=\"closeToast()\">\n <appshell-icon [icon]=\"'close'\"></appshell-icon>\n </button>\n</div>", styles: [".appshell-toast{display:flex;flex-direction:row;justify-content:space-between;width:17rem;padding:.75rem .5rem .75rem 1rem;align-items:center;gap:.5rem;flex-shrink:0;border-radius:.125rem;border:1px solid #EFEEEB;background:#fff;box-shadow:0 2px 12px #0000000d}.appshell-toast .appshell-toast-content{height:100%}.appshell-toast .appshell-toast-content h4{overflow:hidden;color:var(--black, #191919);text-overflow:ellipsis;margin:0;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:700;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;line-clamp:1;-webkit-line-clamp:1}.appshell-toast .appshell-toast-content p{margin:0;overflow:hidden;color:var(--appshell-color-grey-main);text-overflow:ellipsis;font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.25rem;display:-webkit-box;-webkit-box-orient:vertical;line-clamp:1;-webkit-line-clamp:1}.appshell-toast button{width:2rem;height:2rem;background:transparent;border:none;cursor:pointer}\n"] }]
507
+ }] });
508
+
509
+ class AppShellToastService {
510
+ toastsSubject = new BehaviorSubject([]);
511
+ toasts$ = this.toastsSubject.asObservable();
512
+ currentId = 0;
513
+ showToast(notification, duration, closeFn) {
514
+ if (closeFn) {
515
+ const originalCloseFn = closeFn;
516
+ closeFn = () => {
517
+ originalCloseFn();
518
+ this.removeToast(this.currentId);
519
+ };
520
+ }
521
+ else {
522
+ closeFn = () => this.removeToast(this.currentId);
523
+ }
524
+ const toast = { id: this.currentId++, notification, closeFn: () => closeFn() };
525
+ this.toastsSubject.next([...this.toastsSubject.value, toast]);
526
+ if (duration) {
527
+ setTimeout(() => this.removeToast(toast.id), duration);
528
+ }
529
+ }
530
+ removeToast(id) {
531
+ this.toastsSubject.next(this.toastsSubject.value.filter(toast => toast.id !== id));
532
+ }
533
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
534
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastService, providedIn: 'root' });
535
+ }
536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastService, decorators: [{
537
+ type: Injectable,
538
+ args: [{
539
+ providedIn: 'root'
540
+ }]
541
+ }] });
542
+
543
+ class AppShellToastsComponent {
544
+ toastService;
545
+ toastsLimit = input(3);
546
+ toasts = [];
547
+ constructor(toastService) {
548
+ this.toastService = toastService;
549
+ }
550
+ ngOnInit() {
551
+ this.toastService.toasts$.subscribe((toasts) => this.toasts = toasts);
552
+ }
553
+ closeToast(id) {
554
+ this.toastService.removeToast(id);
555
+ }
556
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastsComponent, deps: [{ token: AppShellToastService }], target: i0.ɵɵFactoryTarget.Component });
557
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellToastsComponent, isStandalone: true, selector: "appshell-toasts", inputs: { toastsLimit: { classPropertyName: "toastsLimit", publicName: "toastsLimit", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"toast-container\">\n @for (toast of toasts | slice:0:toastsLimit(); track toast.id) {\n <appshell-toast [notification]=\"toast.notification\" (closed)=\"closeToast(toast.id)\"></appshell-toast>\n }\n</div>", styles: [".toast-container{position:fixed;top:4.5rem;right:1rem;display:flex;flex-direction:column-reverse;align-items:flex-end;z-index:9999}.toast-container appshell-toast{margin-bottom:1rem}\n"], dependencies: [{ kind: "component", type: AppShellToastComponent, selector: "appshell-toast", inputs: ["notification"], outputs: ["closed"] }, { kind: "pipe", type: SlicePipe, name: "slice" }] });
558
+ }
559
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellToastsComponent, decorators: [{
560
+ type: Component,
561
+ args: [{ selector: 'appshell-toasts', imports: [AppShellToastComponent, SlicePipe], template: "<div class=\"toast-container\">\n @for (toast of toasts | slice:0:toastsLimit(); track toast.id) {\n <appshell-toast [notification]=\"toast.notification\" (closed)=\"closeToast(toast.id)\"></appshell-toast>\n }\n</div>", styles: [".toast-container{position:fixed;top:4.5rem;right:1rem;display:flex;flex-direction:column-reverse;align-items:flex-end;z-index:9999}.toast-container appshell-toast{margin-bottom:1rem}\n"] }]
562
+ }], ctorParameters: () => [{ type: AppShellToastService }] });
563
+
564
+ class AppShellProductCatalogScreenComponent {
565
+ pageTitle = input.required();
566
+ breadcrumbLinks = input.required();
567
+ products = input.required();
568
+ filters = input.required();
569
+ noProductsIcon = input();
570
+ noProductsHtmlMessage = input();
571
+ activeFiltersChange = output();
572
+ getProductLabels(product) {
573
+ return product.tags?.flatMap(tag => tag.options) || [];
574
+ }
575
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCatalogScreenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
576
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellProductCatalogScreenComponent, isStandalone: true, selector: "appshell-product-catalog-screen", inputs: { pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: true, transformFunction: null }, breadcrumbLinks: { classPropertyName: "breadcrumbLinks", publicName: "breadcrumbLinks", isSignal: true, isRequired: true, transformFunction: null }, products: { classPropertyName: "products", publicName: "products", isSignal: true, isRequired: true, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: true, transformFunction: null }, noProductsIcon: { classPropertyName: "noProductsIcon", publicName: "noProductsIcon", isSignal: true, isRequired: false, transformFunction: null }, noProductsHtmlMessage: { classPropertyName: "noProductsHtmlMessage", publicName: "noProductsHtmlMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeFiltersChange: "activeFiltersChange" }, ngImport: i0, template: "<appshell-page-header \n [title]=\"pageTitle()\"\n [breadcrumbLinks]=\"breadcrumbLinks()\"></appshell-page-header>\n<appshell-filters\n [filters]=\"filters()\"\n (activeFiltersChange)=\"activeFiltersChange.emit($event)\"></appshell-filters>\n<section class=\"catalog-main\">\n @if(products().length > 0) {\n <div class=\"products-ctn\">\n @for (product of products(); track product.id) {\n <appshell-product-card\n [title]=\"product.title\"\n [description]=\"product.shortDescription\"\n [image]=\"product.image\"\n [labels]=\"getProductLabels(product)\"\n [redirectTo]=\"product.link\"\n ></appshell-product-card>\n }\n </div>\n }\n @if(products().length === 0 && (noProductsHtmlMessage() || noProductsIcon())) {\n <div class=\"no-results-ctn\" role=\"status\" aria-live=\"polite\" tabindex=\"0\">\n @if(noProductsIcon()) {\n <appshell-icon [class]=\"'no-results-icon'\" [icon]=\"noProductsIcon()!\" />\n }\n <div [innerHTML]=\"noProductsHtmlMessage()\"></div>\n </div>\n }\n</section>", styles: ["appshell-product-catalog-screen{display:flex;flex-direction:column;height:100%}.catalog-main{flex:1;background-color:var(--appshell-color-grey-light)}.catalog-main .products-ctn{display:grid;grid-template-columns:repeat(auto-fill,minmax(25rem,1fr));grid-auto-rows:1fr;gap:1.5rem;padding:1.5rem;box-sizing:border-box;max-width:127.5rem}.catalog-main .products-ctn>*{width:100%;min-width:25rem;max-width:35rem}.catalog-main .no-results-ctn{width:100%;height:100%;max-width:120rem;display:flex;flex-direction:column;align-items:center;padding-top:4.5rem;color:var(--appshell-color-secondary-main);text-align:center;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5rem}.catalog-main .no-results-ctn .no-results-icon{width:6rem;height:6rem;color:var(--appshell-color-secondary-light);margin-bottom:1.25rem}.catalog-main .no-results-ctn .no-results-icon mat-icon{height:6rem;width:6rem}\n"], dependencies: [{ kind: "component", type: AppShellProductCardComponent, selector: "appshell-product-card", inputs: ["title", "description", "image", "labels", "redirectTo"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: AppShellPageHeaderComponent, selector: "appshell-page-header", inputs: ["breadcrumbLinks", "title", "button", "secondaryButton", "picker"], outputs: ["buttonClicked", "secondaryButtonClicked", "pick"] }, { kind: "component", type: AppShellFiltersComponent, selector: "appshell-filters", inputs: ["filters"], outputs: ["activeFiltersChange"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }], encapsulation: i0.ViewEncapsulation.None });
577
+ }
578
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductCatalogScreenComponent, decorators: [{
579
+ type: Component,
580
+ args: [{ selector: 'appshell-product-catalog-screen', standalone: true, imports: [AppShellProductCardComponent, MatFormFieldModule, MatInputModule, MatButtonModule, MatChipsModule, AppShellPageHeaderComponent, AppShellFiltersComponent, AppShellIconComponent], encapsulation: ViewEncapsulation.None, template: "<appshell-page-header \n [title]=\"pageTitle()\"\n [breadcrumbLinks]=\"breadcrumbLinks()\"></appshell-page-header>\n<appshell-filters\n [filters]=\"filters()\"\n (activeFiltersChange)=\"activeFiltersChange.emit($event)\"></appshell-filters>\n<section class=\"catalog-main\">\n @if(products().length > 0) {\n <div class=\"products-ctn\">\n @for (product of products(); track product.id) {\n <appshell-product-card\n [title]=\"product.title\"\n [description]=\"product.shortDescription\"\n [image]=\"product.image\"\n [labels]=\"getProductLabels(product)\"\n [redirectTo]=\"product.link\"\n ></appshell-product-card>\n }\n </div>\n }\n @if(products().length === 0 && (noProductsHtmlMessage() || noProductsIcon())) {\n <div class=\"no-results-ctn\" role=\"status\" aria-live=\"polite\" tabindex=\"0\">\n @if(noProductsIcon()) {\n <appshell-icon [class]=\"'no-results-icon'\" [icon]=\"noProductsIcon()!\" />\n }\n <div [innerHTML]=\"noProductsHtmlMessage()\"></div>\n </div>\n }\n</section>", styles: ["appshell-product-catalog-screen{display:flex;flex-direction:column;height:100%}.catalog-main{flex:1;background-color:var(--appshell-color-grey-light)}.catalog-main .products-ctn{display:grid;grid-template-columns:repeat(auto-fill,minmax(25rem,1fr));grid-auto-rows:1fr;gap:1.5rem;padding:1.5rem;box-sizing:border-box;max-width:127.5rem}.catalog-main .products-ctn>*{width:100%;min-width:25rem;max-width:35rem}.catalog-main .no-results-ctn{width:100%;height:100%;max-width:120rem;display:flex;flex-direction:column;align-items:center;padding-top:4.5rem;color:var(--appshell-color-secondary-main);text-align:center;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5rem}.catalog-main .no-results-ctn .no-results-icon{width:6rem;height:6rem;color:var(--appshell-color-secondary-light);margin-bottom:1.25rem}.catalog-main .no-results-ctn .no-results-icon mat-icon{height:6rem;width:6rem}\n"] }]
581
+ }] });
582
+
583
+ class AppShellProductViewScreenComponent {
584
+ pageTitle = input.required();
585
+ breadcrumbLinks = input.required();
586
+ actionButton = input();
587
+ actionButtonClicked = output();
588
+ product = input.required();
589
+ secondaryButton = input();
590
+ secondaryButtonClicked = output();
591
+ actionPicker = input();
592
+ actionPick = output();
593
+ productLabels = computed(() => this.product().tags?.flatMap(tag => tag.options) || []);
594
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductViewScreenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
595
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellProductViewScreenComponent, isStandalone: true, selector: "appshell-product-view-screen", inputs: { pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: true, transformFunction: null }, breadcrumbLinks: { classPropertyName: "breadcrumbLinks", publicName: "breadcrumbLinks", isSignal: true, isRequired: true, transformFunction: null }, actionButton: { classPropertyName: "actionButton", publicName: "actionButton", isSignal: true, isRequired: false, transformFunction: null }, product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: true, transformFunction: null }, secondaryButton: { classPropertyName: "secondaryButton", publicName: "secondaryButton", isSignal: true, isRequired: false, transformFunction: null }, actionPicker: { classPropertyName: "actionPicker", publicName: "actionPicker", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionButtonClicked: "actionButtonClicked", secondaryButtonClicked: "secondaryButtonClicked", actionPick: "actionPick" }, ngImport: i0, template: "<appshell-page-header \n [breadcrumbLinks]=\"breadcrumbLinks()\"\n [title]=\"pageTitle()\"\n [button]=\"actionButton()\"\n (buttonClicked)=\"actionButtonClicked.emit()\"\n [secondaryButton]=\"secondaryButton()\"\n (secondaryButtonClicked)=\"secondaryButtonClicked.emit()\"\n [picker]=\"actionPicker()\"\n (pick)=\"actionPick.emit($event)\"></appshell-page-header>\n<div class=\"product-ctn\">\n @if (product().image) {\n <div class=\"product-img\">\n <img [src]=\"product().image\" [alt]=\"'Product image for ' + product().title\">\n </div>\n }\n <div class=\"product-metadata\">\n <h2>{{ product().title }}</h2>\n <div class=\"subheadline\">\n @if (product().authors && product().authors!.length > 0) {\n <span>{{ product().authors.join(', ') }}</span>\n }\n @if (product().authors && product().authors!.length > 0 && product().date) {\n <div class=\"row-separator\"></div>\n }\n @if (product().date) {\n <span>{{ product().date!.toJSON().slice(0,10) }}</span>\n }\n </div>\n @if (product().tags && product().tags!.length > 0) {\n <div class=\"tags-ctn\">\n <mat-chip-set aria-label=\"Product categories\">\n @for (tag of productLabels(); track tag) {\n <appshell-chip [label]=\"tag\"></appshell-chip>\n }\n </mat-chip-set>\n </div>\n }\n </div>\n <div class=\"description\">\n <markdown\n [data]=\"product().description\"\n [disableSanitizer]=\"true\">\n </markdown>\n </div>\n</div>", styles: [".product-ctn{padding:.5rem 1.5rem 1.5rem;display:flex;flex-direction:column;gap:1.5rem;max-width:50rem}.product-ctn .product-img img{max-height:7.5rem;max-width:7.5rem;aspect-ratio:1;height:fit-content;width:fit-content;min-height:4rem;min-width:4rem}.product-ctn .product-metadata{display:flex;flex-direction:column;gap:.5rem}.product-ctn .product-metadata h2{margin:0;overflow:hidden;color:var(--appshell-color-secondary-main);font-size:1.375rem;font-style:normal;font-weight:500;line-height:150%;letter-spacing:0rem}.product-ctn .product-metadata .subheadline{display:flex;flex-direction:row}.product-ctn .product-metadata .subheadline>span{color:var(--appshell-color-grey-strong);font-size:.875rem;font-style:normal;font-weight:500;line-height:150%;letter-spacing:0rem}.product-ctn .product-metadata .subheadline .row-separator{width:.0625rem;background-color:var(--appshell-color-accent-green-dark);margin:0 .5rem}.product-ctn .product-metadata mat-chip-set>div[role=presentation]{gap:.5rem}.product-ctn .description{line-height:150%;max-width:50rem;color:var(--appshell-color-secondary-main)}.product-ctn .description *{max-width:100%;text-wrap:auto;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: AppShellPageHeaderComponent, selector: "appshell-page-header", inputs: ["breadcrumbLinks", "title", "button", "secondaryButton", "picker"], outputs: ["buttonClicked", "secondaryButtonClicked", "pick"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$2.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: AppShellChipComponent, selector: "appshell-chip", inputs: ["label"] }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }], encapsulation: i0.ViewEncapsulation.None });
596
+ }
597
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellProductViewScreenComponent, decorators: [{
598
+ type: Component,
599
+ args: [{ selector: 'appshell-product-view-screen', standalone: true, imports: [AppShellPageHeaderComponent, MatButtonModule, MatChipsModule, AppShellChipComponent, MarkdownComponent], encapsulation: ViewEncapsulation.None, template: "<appshell-page-header \n [breadcrumbLinks]=\"breadcrumbLinks()\"\n [title]=\"pageTitle()\"\n [button]=\"actionButton()\"\n (buttonClicked)=\"actionButtonClicked.emit()\"\n [secondaryButton]=\"secondaryButton()\"\n (secondaryButtonClicked)=\"secondaryButtonClicked.emit()\"\n [picker]=\"actionPicker()\"\n (pick)=\"actionPick.emit($event)\"></appshell-page-header>\n<div class=\"product-ctn\">\n @if (product().image) {\n <div class=\"product-img\">\n <img [src]=\"product().image\" [alt]=\"'Product image for ' + product().title\">\n </div>\n }\n <div class=\"product-metadata\">\n <h2>{{ product().title }}</h2>\n <div class=\"subheadline\">\n @if (product().authors && product().authors!.length > 0) {\n <span>{{ product().authors.join(', ') }}</span>\n }\n @if (product().authors && product().authors!.length > 0 && product().date) {\n <div class=\"row-separator\"></div>\n }\n @if (product().date) {\n <span>{{ product().date!.toJSON().slice(0,10) }}</span>\n }\n </div>\n @if (product().tags && product().tags!.length > 0) {\n <div class=\"tags-ctn\">\n <mat-chip-set aria-label=\"Product categories\">\n @for (tag of productLabels(); track tag) {\n <appshell-chip [label]=\"tag\"></appshell-chip>\n }\n </mat-chip-set>\n </div>\n }\n </div>\n <div class=\"description\">\n <markdown\n [data]=\"product().description\"\n [disableSanitizer]=\"true\">\n </markdown>\n </div>\n</div>", styles: [".product-ctn{padding:.5rem 1.5rem 1.5rem;display:flex;flex-direction:column;gap:1.5rem;max-width:50rem}.product-ctn .product-img img{max-height:7.5rem;max-width:7.5rem;aspect-ratio:1;height:fit-content;width:fit-content;min-height:4rem;min-width:4rem}.product-ctn .product-metadata{display:flex;flex-direction:column;gap:.5rem}.product-ctn .product-metadata h2{margin:0;overflow:hidden;color:var(--appshell-color-secondary-main);font-size:1.375rem;font-style:normal;font-weight:500;line-height:150%;letter-spacing:0rem}.product-ctn .product-metadata .subheadline{display:flex;flex-direction:row}.product-ctn .product-metadata .subheadline>span{color:var(--appshell-color-grey-strong);font-size:.875rem;font-style:normal;font-weight:500;line-height:150%;letter-spacing:0rem}.product-ctn .product-metadata .subheadline .row-separator{width:.0625rem;background-color:var(--appshell-color-accent-green-dark);margin:0 .5rem}.product-ctn .product-metadata mat-chip-set>div[role=presentation]{gap:.5rem}.product-ctn .description{line-height:150%;max-width:50rem;color:var(--appshell-color-secondary-main)}.product-ctn .description *{max-width:100%;text-wrap:auto;overflow-wrap:anywhere}\n"] }]
600
+ }] });
601
+
602
+ class AppShellNotificationsScreenComponent {
603
+ markdownService;
604
+ pageTitle = input.required();
605
+ breadcrumbLinks = input.required();
606
+ notifications = input.required();
607
+ computedNotifications = computed(() => {
608
+ return this.notifications().map((notification) => {
609
+ notification.expanded = this.expandedNotifications.includes(notification.id);
610
+ if (notification.message) {
611
+ const parsed = this.markdownService.parse(notification.message.replace(/\\n/g, '\n'), { markedOptions: { gfm: true, breaks: false } });
612
+ notification.message = parsed;
613
+ }
614
+ return notification;
615
+ });
616
+ });
617
+ readNotification = output();
618
+ readAllNotifications = output();
619
+ expandedNotifications = [];
620
+ constructor(markdownService) {
621
+ this.markdownService = markdownService;
622
+ }
623
+ getIcon(notification) {
624
+ if (notification.type === 'success') {
625
+ return 'check_circle';
626
+ }
627
+ if (notification.type === 'error') {
628
+ return 'x_circle';
629
+ }
630
+ // Default to info
631
+ return 'info';
632
+ }
633
+ getIconClasses(notification) {
634
+ if (notification.type === 'success') {
635
+ return 'notification success';
636
+ }
637
+ if (notification.type === 'error') {
638
+ return 'notification error';
639
+ }
640
+ return 'notification';
641
+ }
642
+ expandNotification(notification) {
643
+ const index = this.expandedNotifications.indexOf(notification.id);
644
+ if (index === -1) {
645
+ this.expandedNotifications.push(notification.id);
646
+ }
647
+ else {
648
+ this.expandedNotifications.splice(index, 1);
649
+ }
650
+ }
651
+ isNotificationExpanded(notification) {
652
+ return this.expandedNotifications.includes(notification.id);
653
+ }
654
+ markAsRead(notification) {
655
+ this.readNotification.emit(notification);
656
+ }
657
+ markAllAsRead() {
658
+ this.readAllNotifications.emit();
659
+ }
660
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellNotificationsScreenComponent, deps: [{ token: i1$6.MarkdownService }], target: i0.ɵɵFactoryTarget.Component });
661
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.11", type: AppShellNotificationsScreenComponent, isStandalone: true, selector: "appshell-notifications-screen", inputs: { pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: true, transformFunction: null }, breadcrumbLinks: { classPropertyName: "breadcrumbLinks", publicName: "breadcrumbLinks", isSignal: true, isRequired: true, transformFunction: null }, notifications: { classPropertyName: "notifications", publicName: "notifications", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { readNotification: "readNotification", readAllNotifications: "readAllNotifications" }, ngImport: i0, template: "<appshell-page-header \n [breadcrumbLinks]=\"breadcrumbLinks()\"\n [title]=\"pageTitle()\"></appshell-page-header>\n<div class=\"notifications-ctn\">\n <button class=\"mark-all-read-btn\" mat-button (click)=\"markAllAsRead()\">Mark all as read</button>\n @for (notification of computedNotifications(); track notification.date) {\n <div class=\"notification-ctn\" [class.unread]=\"!notification.read\" (click)=\"markAsRead(notification)\">\n <div class=\"notification-icon\">\n <appshell-icon [icon]=\"getIcon(notification)\" [class]=\"getIconClasses(notification)\" />\n </div>\n <div class=\"notification-content\">\n <span class=\"notification-title\">{{ notification.title }}</span>\n <span class=\"notification-body\" [class.expanded]=\"notification.expanded\">\n @if (notification.message && notification.message.length > 80) {\n @if (notification.expanded) {\n <span [innerHTML]=\"notification.message\"></span>\n } @else {\n <span [innerHTML]=\"notification.message | slice:0:70\" class=\"sliced-message\"></span>...\n }\n <span class=\"read-more-less\" (click)=\"expandNotification(notification)\">{{ notification.expanded ? 'Show less' : 'Read more' }}</span>\n } @else {\n <span [innerHTML]=\"notification.message\"></span>\n }\n </span>\n </div>\n <span class=\"notification-date\">{{ notification.date | date:'dd/MM/YY' }}</span>\n </div>\n }\n</div>", styles: [".notifications-ctn{box-sizing:border-box;padding:0 1.5rem 1.5rem;width:50rem}.notifications-ctn .mark-all-read-btn{display:block;margin-left:auto;margin-bottom:1rem;color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;text-decoration-line:underline;text-decoration-color:var(--appshell-color-accent-green-main);text-decoration-thickness:3px;text-underline-offset:6px;--mat-text-button-hover-state-layer-opacity: 0;--mat-text-button-focus-state-layer-opacity: 0;--mat-text-button-pressed-state-layer-opacity: 0;--mat-text-button-ripple-color: transparent}.notifications-ctn .mark-all-read-btn:hover{color:var(--appshell-color-secondary-medium);background-color:transparent;text-decoration-color:var(--appshell-color-accent-green-medium)}.notifications-ctn .notification-ctn{border-top:1px solid #B7B6B2;padding:1rem;box-sizing:border-box;display:flex;flex-direction:row;gap:.75rem;background-color:transparent}.notifications-ctn .notification-ctn:hover{background-color:var(--appshell-color-tertiary-neutral)}.notifications-ctn .notification-ctn:last-of-type{border-bottom:1px solid #B7B6B2}.notifications-ctn .notification-ctn.unread{background-color:var(--appshell-color-sky-blue-light)}.notifications-ctn .notification-ctn.unread:hover{background-color:var(--appshell-color-sky-blue-medium)}.notifications-ctn .notification-ctn .notification-icon .notification{color:#0069e5}.notifications-ctn .notification-ctn .notification-icon .notification.success{color:#168215}.notifications-ctn .notification-ctn .notification-icon .notification.error{color:#e10a0a}.notifications-ctn .notification-ctn .notification-content{width:100%;display:flex;flex-direction:column;gap:.75rem}.notifications-ctn .notification-ctn .notification-content .notification-title{color:var(--appshell-color-secondary-main);font-family:AppShellHeadingFont;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5rem;word-break:break-word}.notifications-ctn .notification-ctn .notification-content .notification-body{color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.5rem;letter-spacing:.00625rem;word-break:break-word}.notifications-ctn .notification-ctn .notification-content .notification-body .sliced-message{display:inline-flex}.notifications-ctn .notification-ctn .notification-content .notification-body .read-more-less{color:#0069e5;margin-left:.2rem;display:inline}.notifications-ctn .notification-ctn .notification-content .notification-body .read-more-less:hover{cursor:pointer;text-decoration:underline}.notifications-ctn .notification-ctn .notification-content .notification-body.expanded .read-more-less{margin-left:0;display:block}.notifications-ctn .notification-ctn .notification-date{color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.5rem}\n"], dependencies: [{ kind: "component", type: AppShellPageHeaderComponent, selector: "appshell-page-header", inputs: ["breadcrumbLinks", "title", "button", "secondaryButton", "picker"], outputs: ["buttonClicked", "secondaryButtonClicked", "pick"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: SlicePipe, name: "slice" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: AppShellIconComponent, selector: "appshell-icon", inputs: ["icon"] }] });
662
+ }
663
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: AppShellNotificationsScreenComponent, decorators: [{
664
+ type: Component,
665
+ args: [{ selector: 'appshell-notifications-screen', standalone: true, imports: [AppShellPageHeaderComponent, DatePipe, SlicePipe, MatButtonModule, AppShellIconComponent], template: "<appshell-page-header \n [breadcrumbLinks]=\"breadcrumbLinks()\"\n [title]=\"pageTitle()\"></appshell-page-header>\n<div class=\"notifications-ctn\">\n <button class=\"mark-all-read-btn\" mat-button (click)=\"markAllAsRead()\">Mark all as read</button>\n @for (notification of computedNotifications(); track notification.date) {\n <div class=\"notification-ctn\" [class.unread]=\"!notification.read\" (click)=\"markAsRead(notification)\">\n <div class=\"notification-icon\">\n <appshell-icon [icon]=\"getIcon(notification)\" [class]=\"getIconClasses(notification)\" />\n </div>\n <div class=\"notification-content\">\n <span class=\"notification-title\">{{ notification.title }}</span>\n <span class=\"notification-body\" [class.expanded]=\"notification.expanded\">\n @if (notification.message && notification.message.length > 80) {\n @if (notification.expanded) {\n <span [innerHTML]=\"notification.message\"></span>\n } @else {\n <span [innerHTML]=\"notification.message | slice:0:70\" class=\"sliced-message\"></span>...\n }\n <span class=\"read-more-less\" (click)=\"expandNotification(notification)\">{{ notification.expanded ? 'Show less' : 'Read more' }}</span>\n } @else {\n <span [innerHTML]=\"notification.message\"></span>\n }\n </span>\n </div>\n <span class=\"notification-date\">{{ notification.date | date:'dd/MM/YY' }}</span>\n </div>\n }\n</div>", styles: [".notifications-ctn{box-sizing:border-box;padding:0 1.5rem 1.5rem;width:50rem}.notifications-ctn .mark-all-read-btn{display:block;margin-left:auto;margin-bottom:1rem;color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:500;line-height:1.25rem;text-decoration-line:underline;text-decoration-color:var(--appshell-color-accent-green-main);text-decoration-thickness:3px;text-underline-offset:6px;--mat-text-button-hover-state-layer-opacity: 0;--mat-text-button-focus-state-layer-opacity: 0;--mat-text-button-pressed-state-layer-opacity: 0;--mat-text-button-ripple-color: transparent}.notifications-ctn .mark-all-read-btn:hover{color:var(--appshell-color-secondary-medium);background-color:transparent;text-decoration-color:var(--appshell-color-accent-green-medium)}.notifications-ctn .notification-ctn{border-top:1px solid #B7B6B2;padding:1rem;box-sizing:border-box;display:flex;flex-direction:row;gap:.75rem;background-color:transparent}.notifications-ctn .notification-ctn:hover{background-color:var(--appshell-color-tertiary-neutral)}.notifications-ctn .notification-ctn:last-of-type{border-bottom:1px solid #B7B6B2}.notifications-ctn .notification-ctn.unread{background-color:var(--appshell-color-sky-blue-light)}.notifications-ctn .notification-ctn.unread:hover{background-color:var(--appshell-color-sky-blue-medium)}.notifications-ctn .notification-ctn .notification-icon .notification{color:#0069e5}.notifications-ctn .notification-ctn .notification-icon .notification.success{color:#168215}.notifications-ctn .notification-ctn .notification-icon .notification.error{color:#e10a0a}.notifications-ctn .notification-ctn .notification-content{width:100%;display:flex;flex-direction:column;gap:.75rem}.notifications-ctn .notification-ctn .notification-content .notification-title{color:var(--appshell-color-secondary-main);font-family:AppShellHeadingFont;font-size:1rem;font-style:normal;font-weight:400;line-height:1.5rem;word-break:break-word}.notifications-ctn .notification-ctn .notification-content .notification-body{color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.5rem;letter-spacing:.00625rem;word-break:break-word}.notifications-ctn .notification-ctn .notification-content .notification-body .sliced-message{display:inline-flex}.notifications-ctn .notification-ctn .notification-content .notification-body .read-more-less{color:#0069e5;margin-left:.2rem;display:inline}.notifications-ctn .notification-ctn .notification-content .notification-body .read-more-less:hover{cursor:pointer;text-decoration:underline}.notifications-ctn .notification-ctn .notification-content .notification-body.expanded .read-more-less{margin-left:0;display:block}.notifications-ctn .notification-ctn .notification-date{color:var(--appshell-color-secondary-main);font-family:AppShellTextFont;font-size:.875rem;font-style:normal;font-weight:400;line-height:1.5rem}\n"] }]
666
+ }], ctorParameters: () => [{ type: i1$6.MarkdownService }] });
667
+
668
+ class IconRegistryService {
669
+ matIconRegistry;
670
+ sanitizer;
671
+ namespace = 'appshell';
672
+ http;
673
+ constructor(httpBackend, matIconRegistry, sanitizer) {
674
+ this.matIconRegistry = matIconRegistry;
675
+ this.sanitizer = sanitizer;
676
+ this.http = new HttpClient(httpBackend);
677
+ }
678
+ registerIconsFromManifest(manifestUrl = 'assets/icons/icons.json') {
679
+ return new Promise((resolve) => {
680
+ this.http.get(manifestUrl).subscribe({
681
+ next: (manifest) => {
682
+ const basePath = manifestUrl.substring(0, manifestUrl.lastIndexOf('/') + 1);
683
+ if (Array.isArray(manifest)) {
684
+ manifest
685
+ .filter((f) => typeof f === 'string' && f.endsWith('.svg'))
686
+ .forEach((file) => {
687
+ const iconName = file.replace(/\.svg$/i, '');
688
+ const url = basePath + file;
689
+ this.matIconRegistry.addSvgIconInNamespace(this.namespace, iconName, this.sanitizer.bypassSecurityTrustResourceUrl(url));
690
+ });
691
+ }
692
+ else if (manifest && typeof manifest === 'object') {
693
+ Object.entries(manifest).forEach(([iconName, relativePath]) => {
694
+ if (typeof relativePath !== 'string' || !relativePath.endsWith('.svg')) {
695
+ return;
696
+ }
697
+ const isAbsolute = /^https?:\/\//i.test(relativePath);
698
+ const url = isAbsolute ? relativePath : basePath + relativePath;
699
+ this.matIconRegistry.addSvgIconInNamespace(this.namespace, iconName, this.sanitizer.bypassSecurityTrustResourceUrl(url));
700
+ });
701
+ }
702
+ resolve();
703
+ },
704
+ error: () => {
705
+ resolve();
706
+ },
707
+ });
708
+ });
709
+ }
710
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: IconRegistryService, deps: [{ token: i1$7.HttpBackend }, { token: i1$1.MatIconRegistry }, { token: i3$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Injectable });
711
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: IconRegistryService, providedIn: 'root' });
712
+ }
713
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: IconRegistryService, decorators: [{
714
+ type: Injectable,
715
+ args: [{ providedIn: 'root' }]
716
+ }], ctorParameters: () => [{ type: i1$7.HttpBackend }, { type: i1$1.MatIconRegistry }, { type: i3$1.DomSanitizer }] });
717
+
718
+ /*
719
+ * Public API Surface of ngx-appshell
720
+ */
721
+
722
+ /**
723
+ * Generated bundle index. Do not edit.
724
+ */
725
+
726
+ export { AppShellBreadcrumbComponent, AppShellChipComponent, AppShellFiltersComponent, AppShellHeaderComponent, AppShellIconComponent, AppShellLayoutComponent, AppShellLinkDirective, AppShellNotificationsScreenComponent, AppShellPageHeaderComponent, AppShellPlatformHeaderComponent, AppShellPlatformLayoutComponent, AppShellProductCardComponent, AppShellProductCardV2Component, AppShellProductCatalogScreenComponent, AppShellProductViewScreenComponent, AppShellSelectComponent, AppShellSidebarMenuComponent, AppShellToastComponent, AppShellToastService, AppShellToastsComponent, IconRegistryService };
727
+ //# sourceMappingURL=opendevstack-ngx-appshell.mjs.map