@unopsitg/ux 21.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/assets/_animations.scss +47 -0
- package/assets/_breadcrumb.scss +71 -0
- package/assets/_card.scss +11 -0
- package/assets/_config.scss +95 -0
- package/assets/_content.scss +55 -0
- package/assets/_fonts.scss +1 -0
- package/assets/_footer.scss +17 -0
- package/assets/_main.scss +38 -0
- package/assets/_mask.scss +7 -0
- package/assets/_paginator.scss +16 -0
- package/assets/_responsive.scss +203 -0
- package/assets/_sass_variables.scss +2 -0
- package/assets/_search.scss +35 -0
- package/assets/_tags.scss +90 -0
- package/assets/_topbar.scss +250 -0
- package/assets/_utils.scss +19 -0
- package/assets/fonts/InterDisplay-Black.otf +0 -0
- package/assets/fonts/InterDisplay-BlackItalic.otf +0 -0
- package/assets/fonts/InterDisplay-Bold.otf +0 -0
- package/assets/fonts/InterDisplay-BoldItalic.otf +0 -0
- package/assets/fonts/InterDisplay-ExtraBold.otf +0 -0
- package/assets/fonts/InterDisplay-ExtraBoldItalic.otf +0 -0
- package/assets/fonts/InterDisplay-ExtraLight.otf +0 -0
- package/assets/fonts/InterDisplay-ExtraLightItalic.otf +0 -0
- package/assets/fonts/InterDisplay-Italic.otf +0 -0
- package/assets/fonts/InterDisplay-Light.otf +0 -0
- package/assets/fonts/InterDisplay-LightItalic.otf +0 -0
- package/assets/fonts/InterDisplay-Medium.otf +0 -0
- package/assets/fonts/InterDisplay-MediumItalic.otf +0 -0
- package/assets/fonts/InterDisplay-Regular.otf +0 -0
- package/assets/fonts/InterDisplay-SemiBold.otf +0 -0
- package/assets/fonts/InterDisplay-SemiBoldItalic.otf +0 -0
- package/assets/fonts/InterDisplay-Thin.otf +0 -0
- package/assets/fonts/InterDisplay-ThinItalic.otf +0 -0
- package/assets/layout.scss +20 -0
- package/assets/opp/AppLogo/AppLogo-onDark_H.svg +55 -0
- package/assets/opp/AppLogo/AppLogo-onDark_V.svg +55 -0
- package/assets/opp/AppLogo/AppLogo-onDark_compact.svg +48 -0
- package/assets/opp/AppLogo/AppLogo-onLight_H.svg +55 -0
- package/assets/opp/AppLogo/AppLogo-onLight_V.svg +55 -0
- package/assets/opp/AppLogo-dark-vertical.svg +55 -0
- package/assets/opp/drive-download-20260421T141232Z-3-001.zip +0 -0
- package/assets/opp/favicon/apple-touch-icon.png +0 -0
- package/assets/opp/favicon/favicon-96x96.png +0 -0
- package/assets/opp/favicon/favicon.ico +0 -0
- package/assets/opp/favicon/favicon.svg +17 -0
- package/assets/opp/favicon/web-app-manifest-192x192.png +0 -0
- package/assets/opp/favicon/web-app-manifest-512x512.png +0 -0
- package/assets/opp/logo-dark-horizontal.svg +55 -0
- package/assets/opp/logo-light-horizontal.svg +55 -0
- package/assets/opp/unops-logo/UNOPS logo_vertical_RGB.png +0 -0
- package/assets/opp/unops-logo/UNOPS logo_vertical_RGB_black.png +0 -0
- package/assets/opp/unops-logo/UNOPS logo_vertical_RGB_white.png +0 -0
- package/assets/opp/unops-logo/unops-logo_ondark.svg +19 -0
- package/assets/opp/unops-logo/unops-logo_onlight.svg +10 -0
- package/assets/sidebar/_sidebar.scss +7 -0
- package/assets/sidebar/_sidebar_compact.scss +176 -0
- package/assets/sidebar/_sidebar_drawer.scss +200 -0
- package/assets/sidebar/_sidebar_horizontal.scss +220 -0
- package/assets/sidebar/_sidebar_reveal.scss +176 -0
- package/assets/sidebar/_sidebar_slim.scss +117 -0
- package/assets/sidebar/_sidebar_theme_core.scss +147 -0
- package/assets/sidebar/_sidebar_themes.scss +4 -0
- package/assets/sidebar/_sidebar_vertical.scss +392 -0
- package/assets/sidebar/themes/_dark.scss +31 -0
- package/assets/sidebar/themes/_light.scss +16 -0
- package/assets/sidebar/themes/_primary.scss +41 -0
- package/assets/styles.scss +1 -0
- package/assets/tailwind.css +679 -0
- package/assets/variables/_common.scss +21 -0
- package/assets/variables/_dark.scss +13 -0
- package/assets/variables/_light.scss +13 -0
- package/fesm2022/unopsitg-ux.mjs +2596 -0
- package/fesm2022/unopsitg-ux.mjs.map +1 -0
- package/package.json +46 -0
- package/types/unopsitg-ux.d.ts +878 -0
|
@@ -0,0 +1,2596 @@
|
|
|
1
|
+
import { definePreset, updatePreset, updateSurfacePalette, $t } from '@primeuix/themes';
|
|
2
|
+
import SoftBase from '@primeuix/themes/aura';
|
|
3
|
+
import CrispBase from '@primeuix/themes/lara';
|
|
4
|
+
import ContrastBase from '@primeuix/themes/nora';
|
|
5
|
+
import * as i0 from '@angular/core';
|
|
6
|
+
import { InjectionToken, signal, inject, computed, effect, Injectable, Component, PLATFORM_ID, model, booleanAttribute, Input, input, HostListener, ViewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core';
|
|
7
|
+
import * as i1 from '@angular/router';
|
|
8
|
+
import { Router, NavigationEnd, RouterModule } from '@angular/router';
|
|
9
|
+
import * as i1$1 from '@angular/common';
|
|
10
|
+
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
11
|
+
import { BehaviorSubject, filter, Subject, takeUntil } from 'rxjs';
|
|
12
|
+
import * as i5 from '@angular/forms';
|
|
13
|
+
import { FormsModule } from '@angular/forms';
|
|
14
|
+
import { PrimeNG } from 'primeng/config';
|
|
15
|
+
import * as i4 from 'primeng/drawer';
|
|
16
|
+
import { DrawerModule } from 'primeng/drawer';
|
|
17
|
+
import * as i5$1 from 'primeng/radiobutton';
|
|
18
|
+
import { RadioButtonModule } from 'primeng/radiobutton';
|
|
19
|
+
import * as i3 from 'primeng/selectbutton';
|
|
20
|
+
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
21
|
+
import { ToggleSwitchModule } from 'primeng/toggleswitch';
|
|
22
|
+
import * as i6 from 'primeng/button';
|
|
23
|
+
import { ButtonModule } from 'primeng/button';
|
|
24
|
+
import * as i2 from 'primeng/divider';
|
|
25
|
+
import { DividerModule } from 'primeng/divider';
|
|
26
|
+
import * as i4$1 from 'primeng/inputtext';
|
|
27
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
28
|
+
import * as i3$1 from 'primeng/select';
|
|
29
|
+
import { SelectModule } from 'primeng/select';
|
|
30
|
+
import * as i3$2 from 'primeng/autofocus';
|
|
31
|
+
import { AutoFocusModule } from 'primeng/autofocus';
|
|
32
|
+
import * as i1$2 from 'primeng/dialog';
|
|
33
|
+
import { DialogModule } from 'primeng/dialog';
|
|
34
|
+
import * as i4$2 from 'primeng/ripple';
|
|
35
|
+
import { RippleModule } from 'primeng/ripple';
|
|
36
|
+
import * as i3$3 from 'primeng/tooltip';
|
|
37
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
38
|
+
import * as i10 from 'primeng/avatar';
|
|
39
|
+
import { AvatarModule } from 'primeng/avatar';
|
|
40
|
+
import * as i8 from 'primeng/badge';
|
|
41
|
+
import { BadgeModule } from 'primeng/badge';
|
|
42
|
+
import * as i5$2 from 'primeng/iconfield';
|
|
43
|
+
import { IconFieldModule } from 'primeng/iconfield';
|
|
44
|
+
import * as i6$1 from 'primeng/inputicon';
|
|
45
|
+
import { InputIconModule } from 'primeng/inputicon';
|
|
46
|
+
import * as i9 from 'primeng/overlaybadge';
|
|
47
|
+
import { OverlayBadgeModule } from 'primeng/overlaybadge';
|
|
48
|
+
import * as i3$4 from 'primeng/styleclass';
|
|
49
|
+
import { StyleClassModule } from 'primeng/styleclass';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Brand theme presets built on top of PrimeUIX base presets.
|
|
53
|
+
*
|
|
54
|
+
* Upstream mapping (for PrimeNG docs, changelogs, and debugging):
|
|
55
|
+
* Soft <- @primeuix/themes/aura
|
|
56
|
+
* Crisp <- @primeuix/themes/lara
|
|
57
|
+
* Contrast <- @primeuix/themes/nora
|
|
58
|
+
*/
|
|
59
|
+
const brandPrimitives = {
|
|
60
|
+
deepsea: { 50: '#F1F5F9', 100: '#E2E8F0', 200: '#CBD5E1', 300: '#94A3B8', 400: '#64748B', 500: '#475569', 600: '#334155', 700: '#1E293B', 800: '#0F172A', 900: '#0A101D', 950: '#03080c' },
|
|
61
|
+
gray: { 50: '#f0f3f4', 100: '#ECF0F5', 200: '#d8dadf', 300: '#b9bac1', 400: '#858c99', 500: '#808393', 600: '#808284', 700: '#6a6b6d', 800: '#535455', 900: '#3c3d3e', 950: '#262627' },
|
|
62
|
+
red: { 50: '#f6cac6', 100: '#f0a9a4', 200: '#eb8982', 300: '#e56960', 400: '#e0493e', 500: '#da291c', 600: '#b92318', 700: '#991d14', 800: '#78170f', 900: '#57100b', 950: '#370a07' },
|
|
63
|
+
orange: { 50: '#f9d6c3', 100: '#f6be9f', 200: '#f2a57a', 300: '#ef8d56', 400: '#eb7432', 500: '#e85c0e', 600: '#c54e0c', 700: '#a2400a', 800: '#803308', 900: '#5d2506', 950: '#3a1704' },
|
|
64
|
+
yellow: { 50: '#fff0c5', 100: '#ffe7a1', 200: '#ffdd7e', 300: '#ffd45b', 400: '#ffcb38', 500: '#ffc215', 600: '#d9a512', 700: '#b3880f', 800: '#8c6b0c', 900: '#664e08', 950: '#403105' },
|
|
65
|
+
lemon: { 50: '#fdfad0', 100: '#fcf7b4', 200: '#fbf398', 300: '#faf07c', 400: '#f9ed60', 500: '#f8ea44', 600: '#d3c73a', 700: '#aea430', 800: '#888125', 900: '#635e1b', 950: '#3e3b11' },
|
|
66
|
+
lime: { 50: '#f0f5bf', 100: '#e7ef99', 200: '#dfe873', 300: '#d6e24d', 400: '#cddc26', 500: '#c4d600', 600: '#a7b600', 700: '#899600', 800: '#6c7600', 900: '#4e5600', 950: '#313600' },
|
|
67
|
+
babygreen: { 50: '#e5f2cf', 100: '#d5e9b1', 200: '#c5e194', 300: '#b6d977', 400: '#a6d15a', 500: '#96c93d', 600: '#80ab34', 700: '#698d2b', 800: '#536f22', 900: '#3c5018', 950: '#26320f' },
|
|
68
|
+
green: { 50: '#d2e7cd', 100: '#b7d9af', 200: '#9dca92', 300: '#82bc74', 400: '#67ad56', 500: '#4c9f38', 600: '#418730', 700: '#356f27', 800: '#2a571f', 900: '#1e4016', 950: '#13280e' },
|
|
69
|
+
olive: { 50: '#d1e0d5', 100: '#b5cdbc', 200: '#99baa3', 300: '#7da889', 400: '#619570', 500: '#458257', 600: '#3b6f4a', 700: '#305b3d', 800: '#264830', 900: '#1c3423', 950: '#112116' },
|
|
70
|
+
teal: { 50: '#bfeae5', 100: '#99ddd5', 200: '#73d0c6', 300: '#4dc3b6', 400: '#26b6a7', 500: '#00a997', 600: '#009080', 700: '#00766a', 800: '#005d53', 900: '#00443c', 950: '#002a26' },
|
|
71
|
+
ocean: { 50: '#d3f0f7', 100: '#b8e7f3', 200: '#9edeee', 300: '#83d5e9', 400: '#69cce5', 500: '#4ec3e0', 600: '#42a6be', 700: '#37899d', 800: '#2b6b7b', 900: '#1f4e5a', 950: '#143138' },
|
|
72
|
+
blue: { 50: '#DEEFFF', 100: '#C9E8FF', 150: '#99D3ED', 200: '#73c3e6', 300: '#4db3df', 400: '#26a2d8', 500: '#0092d1', 600: '#007cb2', 700: '#006692', 800: '#005073', 900: '#003a54', 950: '#002534' },
|
|
73
|
+
darkblue: { 50: '#D0EEFF', 100: '#B7E2F9', 200: '#73abc7', 300: '#4d94b8', 400: '#267da9', 500: '#00669a', 600: '#005783', 700: '#00476c', 800: '#003855', 900: '#00293e', 950: '#001a27' },
|
|
74
|
+
midnight: { 50: '#bfd2dd', 100: '#99b6c8', 200: '#739bb4', 300: '#4d809f', 400: '#26648b', 500: '#004976', 600: '#003e64', 700: '#003353', 800: '#002841', 850: '#001E31', 900: '#001d2f', 950: '#00121e' },
|
|
75
|
+
cherry: { 50: '#e6c7d9', 100: '#d6a5c2', 200: '#c783ab', 300: '#b86294', 400: '#a8407d', 500: '#991e66', 600: '#821a57', 700: '#6b1547', 800: '#541138', 900: '#3d0c29', 950: '#26081a' }
|
|
76
|
+
};
|
|
77
|
+
const brandOverrides = {
|
|
78
|
+
primitive: {
|
|
79
|
+
...brandPrimitives,
|
|
80
|
+
slate: brandPrimitives.gray,
|
|
81
|
+
zinc: brandPrimitives.deepsea,
|
|
82
|
+
neutral: brandPrimitives.gray,
|
|
83
|
+
stone: brandPrimitives.gray,
|
|
84
|
+
emerald: brandPrimitives.green,
|
|
85
|
+
amber: brandPrimitives.yellow,
|
|
86
|
+
cyan: brandPrimitives.ocean,
|
|
87
|
+
sky: brandPrimitives.blue,
|
|
88
|
+
indigo: brandPrimitives.darkblue,
|
|
89
|
+
violet: brandPrimitives.midnight,
|
|
90
|
+
purple: brandPrimitives.cherry,
|
|
91
|
+
fuchsia: brandPrimitives.cherry,
|
|
92
|
+
pink: brandPrimitives.cherry,
|
|
93
|
+
rose: brandPrimitives.red
|
|
94
|
+
},
|
|
95
|
+
semantic: {
|
|
96
|
+
fontFamily: '"Noto Sans", sans-serif',
|
|
97
|
+
primary: {
|
|
98
|
+
50: '{darkblue.50}',
|
|
99
|
+
100: '{darkblue.100}',
|
|
100
|
+
200: '{darkblue.200}',
|
|
101
|
+
300: '{darkblue.300}',
|
|
102
|
+
400: '{darkblue.400}',
|
|
103
|
+
500: '{darkblue.500}',
|
|
104
|
+
600: '{darkblue.600}',
|
|
105
|
+
700: '{darkblue.700}',
|
|
106
|
+
800: '{darkblue.800}',
|
|
107
|
+
900: '{darkblue.900}',
|
|
108
|
+
950: '{darkblue.950}'
|
|
109
|
+
},
|
|
110
|
+
colorScheme: {
|
|
111
|
+
light: {
|
|
112
|
+
surface: {
|
|
113
|
+
0: '#ffffff',
|
|
114
|
+
50: '{deepsea.50}',
|
|
115
|
+
100: '{deepsea.100}',
|
|
116
|
+
200: '{deepsea.200}',
|
|
117
|
+
300: '{deepsea.300}',
|
|
118
|
+
400: '{deepsea.400}',
|
|
119
|
+
500: '{deepsea.500}',
|
|
120
|
+
600: '{deepsea.600}',
|
|
121
|
+
700: '{deepsea.700}',
|
|
122
|
+
800: '{deepsea.800}',
|
|
123
|
+
900: '{deepsea.900}',
|
|
124
|
+
950: '{deepsea.950}'
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
dark: {
|
|
128
|
+
surface: {
|
|
129
|
+
0: '#ffffff',
|
|
130
|
+
50: '{darkblue.50}',
|
|
131
|
+
100: '{darkblue.100}',
|
|
132
|
+
200: '{darkblue.200}',
|
|
133
|
+
300: '{darkblue.200}',
|
|
134
|
+
400: '{darkblue.300}',
|
|
135
|
+
500: '{darkblue.400}',
|
|
136
|
+
600: '{darkblue.500}',
|
|
137
|
+
700: '{darkblue.600}',
|
|
138
|
+
800: '{darkblue.700}',
|
|
139
|
+
900: '{darkblue.900}',
|
|
140
|
+
950: '{darkblue.950}'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
components: {
|
|
146
|
+
button: {
|
|
147
|
+
colorScheme: {
|
|
148
|
+
light: {
|
|
149
|
+
root: {
|
|
150
|
+
primary: {
|
|
151
|
+
background: '{primary.600}',
|
|
152
|
+
borderColor: '{primary.600}'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
datatable: {
|
|
159
|
+
colorScheme: {
|
|
160
|
+
light: {
|
|
161
|
+
row: {
|
|
162
|
+
hoverBackground: '{surface.100}',
|
|
163
|
+
hoverColor: '{surface.950}'
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
dark: {
|
|
167
|
+
row: {
|
|
168
|
+
hoverBackground: '{surface.900}',
|
|
169
|
+
hoverColor: '{surface.0}'
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
paginator: {
|
|
175
|
+
root: {
|
|
176
|
+
background: 'transparent'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
tag: {
|
|
180
|
+
root: {
|
|
181
|
+
padding: '0.25rem 0.5rem',
|
|
182
|
+
fontWeight: '500'
|
|
183
|
+
},
|
|
184
|
+
colorScheme: {
|
|
185
|
+
light: {
|
|
186
|
+
secondary: { color: '{surface.800}' },
|
|
187
|
+
success: { color: '{green.800}' },
|
|
188
|
+
active: { color: '{green.800}' },
|
|
189
|
+
inactive: { color: '{gray.800}' },
|
|
190
|
+
info: { color: '{blue.800}' },
|
|
191
|
+
warn: { color: '{orange.800}' },
|
|
192
|
+
error: { color: '{red.800}' }
|
|
193
|
+
},
|
|
194
|
+
dark: {
|
|
195
|
+
secondary: { color: '{surface.100}' },
|
|
196
|
+
success: { color: '{green.100}' },
|
|
197
|
+
active: { color: '{green.100}' },
|
|
198
|
+
info: { color: '{blue.100}' },
|
|
199
|
+
inactive: { color: '{gray.100}' },
|
|
200
|
+
warn: { color: '{orange.100}' },
|
|
201
|
+
error: { color: '{red.100}' }
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const BrandSoft = definePreset(SoftBase, brandOverrides);
|
|
208
|
+
const BrandCrisp = definePreset(CrispBase, brandOverrides);
|
|
209
|
+
const BrandContrast = definePreset(ContrastBase, brandOverrides);
|
|
210
|
+
const brandPresets = {
|
|
211
|
+
Soft: BrandSoft,
|
|
212
|
+
Crisp: BrandCrisp,
|
|
213
|
+
Contrast: BrandContrast
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const MENU_MODEL = new InjectionToken('UNOPS_UX_MENU_MODEL', {
|
|
217
|
+
factory: () => {
|
|
218
|
+
throw new Error('MENU_MODEL is not provided. Add { provide: MENU_MODEL, useFactory: ... } or useValue to app.config.ts providers.');
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
const SIDEBAR_LOGO = new InjectionToken('UNOPS_UX_SIDEBAR_LOGO', {
|
|
222
|
+
factory: () => ({
|
|
223
|
+
expanded: 'assets/opp/AppLogo/AppLogo-onDark_H.svg',
|
|
224
|
+
compact: 'assets/opp/AppLogo/AppLogo-onDark_compact.svg',
|
|
225
|
+
alt: 'UNOPS'
|
|
226
|
+
})
|
|
227
|
+
});
|
|
228
|
+
const TOPBAR_MOBILE_LOGO = new InjectionToken('UNOPS_UX_TOPBAR_MOBILE_LOGO', {
|
|
229
|
+
factory: () => ({
|
|
230
|
+
dark: 'assets/opp/AppLogo/AppLogo-onDark_H.svg',
|
|
231
|
+
light: 'assets/opp/AppLogo/AppLogo-onLight_H.svg',
|
|
232
|
+
alt: 'UNOPS'
|
|
233
|
+
})
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
class LayoutService {
|
|
237
|
+
layoutConfig = signal({
|
|
238
|
+
preset: 'Soft',
|
|
239
|
+
primary: 'blue',
|
|
240
|
+
surface: null,
|
|
241
|
+
darkTheme: true,
|
|
242
|
+
menuMode: 'static',
|
|
243
|
+
menuTheme: 'primary',
|
|
244
|
+
cardStyle: 'transparent'
|
|
245
|
+
}, ...(ngDevMode ? [{ debugName: "layoutConfig" }] : []));
|
|
246
|
+
layoutState = signal({
|
|
247
|
+
staticMenuInactive: false,
|
|
248
|
+
overlayMenuActive: false,
|
|
249
|
+
rightMenuVisible: false,
|
|
250
|
+
configSidebarVisible: false,
|
|
251
|
+
mobileMenuActive: false,
|
|
252
|
+
searchBarActive: false,
|
|
253
|
+
sidebarExpanded: false,
|
|
254
|
+
sidebarPinned: true,
|
|
255
|
+
menuHoverActive: false,
|
|
256
|
+
activePath: null,
|
|
257
|
+
anchored: false
|
|
258
|
+
}, ...(ngDevMode ? [{ debugName: "layoutState" }] : []));
|
|
259
|
+
router = inject(Router);
|
|
260
|
+
currentUrl = signal('', ...(ngDevMode ? [{ debugName: "currentUrl" }] : []));
|
|
261
|
+
isDarkTheme = computed(() => this.layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
262
|
+
isSlim = computed(() => this.layoutConfig().menuMode === 'slim', ...(ngDevMode ? [{ debugName: "isSlim" }] : []));
|
|
263
|
+
isHorizontal = computed(() => this.layoutConfig().menuMode === 'horizontal', ...(ngDevMode ? [{ debugName: "isHorizontal" }] : []));
|
|
264
|
+
isOverlay = computed(() => this.layoutConfig().menuMode === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
|
|
265
|
+
isCompact = computed(() => this.layoutConfig().menuMode === 'compact', ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
|
|
266
|
+
isStatic = computed(() => this.layoutConfig().menuMode === 'static', ...(ngDevMode ? [{ debugName: "isStatic" }] : []));
|
|
267
|
+
isReveal = computed(() => this.layoutConfig().menuMode === 'reveal', ...(ngDevMode ? [{ debugName: "isReveal" }] : []));
|
|
268
|
+
isDrawer = computed(() => this.layoutConfig().menuMode === 'drawer', ...(ngDevMode ? [{ debugName: "isDrawer" }] : []));
|
|
269
|
+
isSidebarPinned = computed(() => this.layoutState().sidebarPinned, ...(ngDevMode ? [{ debugName: "isSidebarPinned" }] : []));
|
|
270
|
+
isRail = computed(() => !this.layoutState().sidebarPinned && this.isStatic(), ...(ngDevMode ? [{ debugName: "isRail" }] : []));
|
|
271
|
+
hasOverlaySubmenu = computed(() => this.isSlim() || this.isCompact() || this.isHorizontal(), ...(ngDevMode ? [{ debugName: "hasOverlaySubmenu" }] : []));
|
|
272
|
+
hasOpenOverlay = computed(() => this.layoutState().overlayMenuActive || this.hasOpenOverlaySubmenu(), ...(ngDevMode ? [{ debugName: "hasOpenOverlay" }] : []));
|
|
273
|
+
hasOpenOverlaySubmenu = computed(() => {
|
|
274
|
+
return this.hasOverlaySubmenu() && !!this.layoutState().activePath;
|
|
275
|
+
}, ...(ngDevMode ? [{ debugName: "hasOpenOverlaySubmenu" }] : []));
|
|
276
|
+
isSidebarStateChanged = computed(() => {
|
|
277
|
+
const layoutConfig = this.layoutConfig();
|
|
278
|
+
return layoutConfig.menuMode === 'horizontal' || layoutConfig.menuMode === 'slim' || layoutConfig.menuMode === 'slim-plus';
|
|
279
|
+
}, ...(ngDevMode ? [{ debugName: "isSidebarStateChanged" }] : []));
|
|
280
|
+
initialized = false;
|
|
281
|
+
previousMenuMode = undefined;
|
|
282
|
+
constructor() {
|
|
283
|
+
effect(() => {
|
|
284
|
+
const config = this.layoutConfig();
|
|
285
|
+
if (!this.initialized || !config) {
|
|
286
|
+
this.initialized = true;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
this.handleDarkModeTransition(config);
|
|
290
|
+
});
|
|
291
|
+
effect(() => {
|
|
292
|
+
this.updateMenuState();
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
updateMenuState() {
|
|
296
|
+
const menuMode = this.layoutConfig().menuMode;
|
|
297
|
+
if (this.previousMenuMode === undefined) {
|
|
298
|
+
this.previousMenuMode = menuMode;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (this.previousMenuMode === menuMode) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
this.previousMenuMode = menuMode;
|
|
305
|
+
const isOverlaySubmenu = menuMode === 'slim' || menuMode === 'slim-plus' || menuMode === 'horizontal' || menuMode === 'compact';
|
|
306
|
+
this.layoutState.update((prev) => ({
|
|
307
|
+
...prev,
|
|
308
|
+
staticMenuInactive: false,
|
|
309
|
+
overlayMenuActive: false,
|
|
310
|
+
mobileMenuActive: false,
|
|
311
|
+
sidebarExpanded: false,
|
|
312
|
+
menuHoverActive: false,
|
|
313
|
+
anchored: false,
|
|
314
|
+
activePath: this.isDesktop() ? (isOverlaySubmenu ? null : this.router.url) : prev.activePath
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
handleDarkModeTransition(config) {
|
|
318
|
+
const supportsViewTransition = 'startViewTransition' in document;
|
|
319
|
+
if (supportsViewTransition) {
|
|
320
|
+
this.startViewTransition(config);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
this.toggleDarkMode(config);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
startViewTransition(config) {
|
|
327
|
+
const transition = document.startViewTransition(() => {
|
|
328
|
+
this.toggleDarkMode(config);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
toggleDarkMode(config) {
|
|
332
|
+
const _config = config || this.layoutConfig();
|
|
333
|
+
if (_config.darkTheme) {
|
|
334
|
+
document.documentElement.classList.add('app-dark');
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
document.documentElement.classList.remove('app-dark');
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
toggleMenu() {
|
|
341
|
+
if (this.isDesktop()) {
|
|
342
|
+
this.toggleSidebarPin();
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
this.layoutState.update((prev) => ({ ...prev, mobileMenuActive: !prev.mobileMenuActive }));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
toggleSidebarPin() {
|
|
349
|
+
this.layoutState.update((prev) => ({
|
|
350
|
+
...prev,
|
|
351
|
+
sidebarPinned: !prev.sidebarPinned,
|
|
352
|
+
sidebarExpanded: false
|
|
353
|
+
}));
|
|
354
|
+
}
|
|
355
|
+
changeMenuMode(mode) {
|
|
356
|
+
this.layoutConfig.update((prev) => ({ ...prev, menuMode: mode }));
|
|
357
|
+
this.layoutState.update((prev) => ({ ...prev, staticMenuInactive: false, overlayMenuActive: false, mobileMenuActive: false, sidebarExpanded: false, sidebarPinned: true, menuHoverActive: false, anchored: false }));
|
|
358
|
+
if (this.isDesktop()) {
|
|
359
|
+
this.layoutState.update((prev) => ({ ...prev, activePath: this.hasOverlaySubmenu() ? null : this.router.url }));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
toggleRightMenu() {
|
|
363
|
+
this.layoutState.update((prev) => ({
|
|
364
|
+
...prev,
|
|
365
|
+
rightMenuVisible: !prev.rightMenuVisible
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
toggleConfigSidebar() {
|
|
369
|
+
this.layoutState.update((prev) => ({
|
|
370
|
+
...prev,
|
|
371
|
+
configSidebarVisible: !prev.configSidebarVisible
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
toggleSearchBar() {
|
|
375
|
+
this.layoutState.update((prev) => ({
|
|
376
|
+
...prev,
|
|
377
|
+
searchBarActive: !prev.searchBarActive
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
isDesktop() {
|
|
381
|
+
return window.innerWidth > 991;
|
|
382
|
+
}
|
|
383
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: LayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
384
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: LayoutService, providedIn: 'root' });
|
|
385
|
+
}
|
|
386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: LayoutService, decorators: [{
|
|
387
|
+
type: Injectable,
|
|
388
|
+
args: [{
|
|
389
|
+
providedIn: 'root'
|
|
390
|
+
}]
|
|
391
|
+
}], ctorParameters: () => [] });
|
|
392
|
+
|
|
393
|
+
class AppBreadcrumb {
|
|
394
|
+
router;
|
|
395
|
+
_breadcrumbs$ = new BehaviorSubject([]);
|
|
396
|
+
breadcrumbs$ = this._breadcrumbs$.asObservable();
|
|
397
|
+
constructor(router) {
|
|
398
|
+
this.router = router;
|
|
399
|
+
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((event) => {
|
|
400
|
+
const root = this.router.routerState.snapshot.root;
|
|
401
|
+
const breadcrumbs = [];
|
|
402
|
+
this.addBreadcrumb(root, [], breadcrumbs);
|
|
403
|
+
this._breadcrumbs$.next(breadcrumbs);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
addBreadcrumb(route, parentUrl, breadcrumbs) {
|
|
407
|
+
const routeUrl = parentUrl.concat(route.url.map((url) => url.path));
|
|
408
|
+
const breadcrumb = route.data['breadcrumb'];
|
|
409
|
+
const parentBreadcrumb = route.parent && route.parent.data ? route.parent.data['breadcrumb'] : null;
|
|
410
|
+
if (breadcrumb && breadcrumb !== parentBreadcrumb) {
|
|
411
|
+
breadcrumbs.push({
|
|
412
|
+
label: route.data['breadcrumb'],
|
|
413
|
+
url: '/' + routeUrl.join('/')
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
if (route.firstChild) {
|
|
417
|
+
this.addBreadcrumb(route.firstChild, routeUrl, breadcrumbs);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppBreadcrumb, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
|
|
421
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppBreadcrumb, isStandalone: true, selector: "[app-breadcrumb]", ngImport: i0, template: `<nav class="layout-breadcrumb" aria-label="Breadcrumb">
|
|
422
|
+
<ol>
|
|
423
|
+
@for (item of breadcrumbs$ | async; track item.url; let last = $last) {
|
|
424
|
+
<li class="text-sm font-medium text-surface-700 dark:text-surface-100">
|
|
425
|
+
@if (!last && item.url) {
|
|
426
|
+
<a [routerLink]="item.url" class="text-surface-700 dark:text-surface-100 cursor-pointer">{{ item.label }}</a>
|
|
427
|
+
} @else {
|
|
428
|
+
{{ item.label }}
|
|
429
|
+
}
|
|
430
|
+
</li>
|
|
431
|
+
@if (!last) {
|
|
432
|
+
<li class="text-sm font-medium text-surface-400 dark:text-surface-400">/</li>
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
</ol>
|
|
436
|
+
</nav> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] });
|
|
437
|
+
}
|
|
438
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppBreadcrumb, decorators: [{
|
|
439
|
+
type: Component,
|
|
440
|
+
args: [{
|
|
441
|
+
selector: '[app-breadcrumb]',
|
|
442
|
+
imports: [CommonModule, RouterModule],
|
|
443
|
+
template: `<nav class="layout-breadcrumb" aria-label="Breadcrumb">
|
|
444
|
+
<ol>
|
|
445
|
+
@for (item of breadcrumbs$ | async; track item.url; let last = $last) {
|
|
446
|
+
<li class="text-sm font-medium text-surface-700 dark:text-surface-100">
|
|
447
|
+
@if (!last && item.url) {
|
|
448
|
+
<a [routerLink]="item.url" class="text-surface-700 dark:text-surface-100 cursor-pointer">{{ item.label }}</a>
|
|
449
|
+
} @else {
|
|
450
|
+
{{ item.label }}
|
|
451
|
+
}
|
|
452
|
+
</li>
|
|
453
|
+
@if (!last) {
|
|
454
|
+
<li class="text-sm font-medium text-surface-400 dark:text-surface-400">/</li>
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
</ol>
|
|
458
|
+
</nav> `
|
|
459
|
+
}]
|
|
460
|
+
}], ctorParameters: () => [{ type: i1.Router }] });
|
|
461
|
+
|
|
462
|
+
class AppConfigurator {
|
|
463
|
+
simple = false;
|
|
464
|
+
location = 'app';
|
|
465
|
+
router = inject(Router);
|
|
466
|
+
config = inject(PrimeNG);
|
|
467
|
+
layoutService = inject(LayoutService);
|
|
468
|
+
platformId = inject(PLATFORM_ID);
|
|
469
|
+
primeng = inject(PrimeNG);
|
|
470
|
+
presetKeys = Object.keys(brandPresets);
|
|
471
|
+
themeOptions = [
|
|
472
|
+
{ name: 'Light', value: false },
|
|
473
|
+
{ name: 'Dark', value: true }
|
|
474
|
+
];
|
|
475
|
+
menuThemeOptions = [];
|
|
476
|
+
ngOnInit() {
|
|
477
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
478
|
+
this.onPresetChange(this.layoutService.layoutConfig().preset);
|
|
479
|
+
}
|
|
480
|
+
this.updateMenuThemeOptions();
|
|
481
|
+
}
|
|
482
|
+
updateMenuThemeOptions() {
|
|
483
|
+
if (this.darkTheme()) {
|
|
484
|
+
this.menuThemeOptions = [
|
|
485
|
+
{ name: 'Dark', value: 'dark' },
|
|
486
|
+
{ name: 'Primary', value: 'primary' }
|
|
487
|
+
];
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
this.menuThemeOptions = [
|
|
491
|
+
{ name: 'Light', value: 'light' },
|
|
492
|
+
{ name: 'Dark', value: 'dark' },
|
|
493
|
+
{ name: 'Primary', value: 'primary' }
|
|
494
|
+
];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
surfaces = [
|
|
498
|
+
{
|
|
499
|
+
name: 'gray',
|
|
500
|
+
palette: {
|
|
501
|
+
0: '#ffffff',
|
|
502
|
+
50: '#e5e6e6',
|
|
503
|
+
100: '#d5d6d7',
|
|
504
|
+
200: '#c6c7c8',
|
|
505
|
+
300: '#b6b8b9',
|
|
506
|
+
400: '#a7a8aa',
|
|
507
|
+
500: '#97999b',
|
|
508
|
+
600: '#808284',
|
|
509
|
+
700: '#6a6b6d',
|
|
510
|
+
800: '#535455',
|
|
511
|
+
900: '#3c3d3e',
|
|
512
|
+
950: '#262627'
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
name: 'darkblue',
|
|
517
|
+
palette: {
|
|
518
|
+
0: '#ffffff',
|
|
519
|
+
50: '#D0EEFF',
|
|
520
|
+
100: '#B7E2F9',
|
|
521
|
+
200: '#73abc7',
|
|
522
|
+
300: '#73abc7',
|
|
523
|
+
400: '#4d94b8',
|
|
524
|
+
500: '#267da9',
|
|
525
|
+
600: '#00669a',
|
|
526
|
+
700: '#005783',
|
|
527
|
+
800: '#00476c',
|
|
528
|
+
900: '#00293e',
|
|
529
|
+
950: '#001a27'
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
];
|
|
533
|
+
selectedPrimaryColor = computed(() => {
|
|
534
|
+
return this.layoutService.layoutConfig().primary;
|
|
535
|
+
}, ...(ngDevMode ? [{ debugName: "selectedPrimaryColor" }] : []));
|
|
536
|
+
selectedSurfaceColor = computed(() => this.layoutService.layoutConfig().surface, ...(ngDevMode ? [{ debugName: "selectedSurfaceColor" }] : []));
|
|
537
|
+
selectedPreset = computed(() => this.layoutService.layoutConfig().preset, ...(ngDevMode ? [{ debugName: "selectedPreset" }] : []));
|
|
538
|
+
menuMode = computed(() => {
|
|
539
|
+
const mode = this.layoutService.layoutConfig().menuMode;
|
|
540
|
+
const pinned = this.layoutService.layoutState().sidebarPinned;
|
|
541
|
+
return mode === 'static' && !pinned ? 'rail' : mode;
|
|
542
|
+
}, ...(ngDevMode ? [{ debugName: "menuMode" }] : []));
|
|
543
|
+
cardStyle = model(this.layoutService.layoutConfig().cardStyle, ...(ngDevMode ? [{ debugName: "cardStyle" }] : []));
|
|
544
|
+
get configSidebarVisible() {
|
|
545
|
+
return this.layoutService.layoutState().configSidebarVisible;
|
|
546
|
+
}
|
|
547
|
+
set configSidebarVisible(val) {
|
|
548
|
+
this.layoutService.layoutState.update((prev) => ({ ...prev, configSidebarVisible: val }));
|
|
549
|
+
}
|
|
550
|
+
darkTheme = computed(() => this.layoutService.layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "darkTheme" }] : []));
|
|
551
|
+
selectedSurface = computed(() => this.layoutService.layoutConfig().surface, ...(ngDevMode ? [{ debugName: "selectedSurface" }] : []));
|
|
552
|
+
cardStyleOptions = [
|
|
553
|
+
{ name: 'Transparent', value: 'transparent' },
|
|
554
|
+
{ name: 'Filled', value: 'filled' }
|
|
555
|
+
];
|
|
556
|
+
primaryColors = computed(() => {
|
|
557
|
+
const presetPalette = brandPresets[this.layoutService.layoutConfig().preset].primitive;
|
|
558
|
+
const colors = ['red', 'orange', 'yellow', 'lemon', 'lime', 'babygreen', 'green', 'olive', 'teal', 'ocean', 'blue', 'darkblue', 'midnight', 'cherry'];
|
|
559
|
+
const palettes = [{ name: 'noir', palette: {} }];
|
|
560
|
+
colors.forEach((color) => {
|
|
561
|
+
palettes.push({
|
|
562
|
+
name: color,
|
|
563
|
+
palette: presetPalette?.[color]
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
return palettes;
|
|
567
|
+
}, ...(ngDevMode ? [{ debugName: "primaryColors" }] : []));
|
|
568
|
+
menuTheme = computed(() => this.layoutService.layoutConfig().menuTheme, ...(ngDevMode ? [{ debugName: "menuTheme" }] : []));
|
|
569
|
+
getPresetExt() {
|
|
570
|
+
const color = this.primaryColors().find((c) => c.name === this.selectedPrimaryColor()) || {};
|
|
571
|
+
if (color.name === 'noir') {
|
|
572
|
+
return {
|
|
573
|
+
semantic: {
|
|
574
|
+
primary: {
|
|
575
|
+
50: '{surface.50}',
|
|
576
|
+
100: '{surface.100}',
|
|
577
|
+
200: '{surface.200}',
|
|
578
|
+
300: '{surface.300}',
|
|
579
|
+
400: '{surface.400}',
|
|
580
|
+
500: '{surface.500}',
|
|
581
|
+
600: '{surface.600}',
|
|
582
|
+
700: '{surface.700}',
|
|
583
|
+
800: '{surface.800}',
|
|
584
|
+
900: '{surface.900}',
|
|
585
|
+
950: '{surface.950}'
|
|
586
|
+
},
|
|
587
|
+
colorScheme: {
|
|
588
|
+
light: {
|
|
589
|
+
primary: {
|
|
590
|
+
color: '{primary.950}',
|
|
591
|
+
contrastColor: '#ffffff',
|
|
592
|
+
hoverColor: '{primary.800}',
|
|
593
|
+
activeColor: '{primary.700}'
|
|
594
|
+
},
|
|
595
|
+
highlight: {
|
|
596
|
+
background: '{primary.950}',
|
|
597
|
+
focusBackground: '{primary.700}',
|
|
598
|
+
color: '#ffffff',
|
|
599
|
+
focusColor: '#ffffff'
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
dark: {
|
|
603
|
+
primary: {
|
|
604
|
+
color: '{primary.50}',
|
|
605
|
+
contrastColor: '{primary.950}',
|
|
606
|
+
hoverColor: '{primary.200}',
|
|
607
|
+
activeColor: '{primary.300}'
|
|
608
|
+
},
|
|
609
|
+
highlight: {
|
|
610
|
+
background: '{primary.50}',
|
|
611
|
+
focusBackground: '{primary.300}',
|
|
612
|
+
color: '{primary.950}',
|
|
613
|
+
focusColor: '{primary.950}'
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
return {
|
|
622
|
+
semantic: {
|
|
623
|
+
primary: color.palette,
|
|
624
|
+
colorScheme: {
|
|
625
|
+
light: {
|
|
626
|
+
primary: {
|
|
627
|
+
color: '{primary.500}',
|
|
628
|
+
contrastColor: '#ffffff',
|
|
629
|
+
hoverColor: '{primary.600}',
|
|
630
|
+
activeColor: '{primary.700}'
|
|
631
|
+
},
|
|
632
|
+
highlight: {
|
|
633
|
+
background: '{primary.50}',
|
|
634
|
+
focusBackground: '{primary.100}',
|
|
635
|
+
color: '{primary.700}',
|
|
636
|
+
focusColor: '{primary.800}'
|
|
637
|
+
}
|
|
638
|
+
},
|
|
639
|
+
dark: {
|
|
640
|
+
primary: {
|
|
641
|
+
color: '{primary.400}',
|
|
642
|
+
contrastColor: '{surface.900}',
|
|
643
|
+
hoverColor: '{primary.300}',
|
|
644
|
+
activeColor: '{primary.200}'
|
|
645
|
+
},
|
|
646
|
+
highlight: {
|
|
647
|
+
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
|
|
648
|
+
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
|
|
649
|
+
color: 'rgba(255,255,255,.87)',
|
|
650
|
+
focusColor: 'rgba(255,255,255,.87)'
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
updateColors(event, type, color) {
|
|
659
|
+
if (type === 'primary') {
|
|
660
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
661
|
+
...state,
|
|
662
|
+
primary: color.name
|
|
663
|
+
}));
|
|
664
|
+
}
|
|
665
|
+
else if (type === 'surface') {
|
|
666
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
667
|
+
...state,
|
|
668
|
+
surface: color.name
|
|
669
|
+
}));
|
|
670
|
+
}
|
|
671
|
+
this.applyTheme(type, color);
|
|
672
|
+
event.stopPropagation();
|
|
673
|
+
}
|
|
674
|
+
applyTheme(type, color) {
|
|
675
|
+
if (type === 'primary') {
|
|
676
|
+
updatePreset(this.getPresetExt());
|
|
677
|
+
}
|
|
678
|
+
else if (type === 'surface') {
|
|
679
|
+
updateSurfacePalette(color.palette);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
onPresetChange(event) {
|
|
683
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
684
|
+
...state,
|
|
685
|
+
preset: event
|
|
686
|
+
}));
|
|
687
|
+
const preset = brandPresets[event];
|
|
688
|
+
const surfacePalette = this.surfaces.find((s) => s.name === this.selectedSurfaceColor())?.palette;
|
|
689
|
+
$t().preset(preset).preset(this.getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
|
|
690
|
+
}
|
|
691
|
+
onCardStyleChange(value) {
|
|
692
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
693
|
+
...state,
|
|
694
|
+
cardStyle: value
|
|
695
|
+
}));
|
|
696
|
+
}
|
|
697
|
+
onMenuThemeChange(value) {
|
|
698
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
699
|
+
...state,
|
|
700
|
+
menuTheme: value
|
|
701
|
+
}));
|
|
702
|
+
}
|
|
703
|
+
setMenuMode(mode) {
|
|
704
|
+
const isRail = mode === 'rail';
|
|
705
|
+
const actualMode = isRail ? 'static' : mode;
|
|
706
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
707
|
+
...state,
|
|
708
|
+
menuMode: actualMode
|
|
709
|
+
}));
|
|
710
|
+
this.layoutService.layoutState.update((state) => ({
|
|
711
|
+
...state,
|
|
712
|
+
staticMenuInactive: false,
|
|
713
|
+
overlayMenuActive: false,
|
|
714
|
+
mobileMenuActive: false,
|
|
715
|
+
sidebarExpanded: false,
|
|
716
|
+
sidebarPinned: !isRail,
|
|
717
|
+
menuHoverActive: false,
|
|
718
|
+
anchored: false
|
|
719
|
+
}));
|
|
720
|
+
}
|
|
721
|
+
toggleDarkMode() {
|
|
722
|
+
this.executeDarkModeToggle();
|
|
723
|
+
}
|
|
724
|
+
executeDarkModeToggle() {
|
|
725
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
726
|
+
...state,
|
|
727
|
+
darkTheme: !state.darkTheme
|
|
728
|
+
}));
|
|
729
|
+
if (this.darkTheme()) {
|
|
730
|
+
this.setMenuTheme('dark');
|
|
731
|
+
}
|
|
732
|
+
this.updateMenuThemeOptions();
|
|
733
|
+
}
|
|
734
|
+
toggleConfigSidebar() {
|
|
735
|
+
this.layoutService.layoutState.update((val) => ({ ...val, configSidebarVisible: !val.configSidebarVisible }));
|
|
736
|
+
}
|
|
737
|
+
setMenuTheme(theme) {
|
|
738
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
739
|
+
...state,
|
|
740
|
+
menuTheme: theme
|
|
741
|
+
}));
|
|
742
|
+
}
|
|
743
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppConfigurator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
744
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppConfigurator, isStandalone: true, selector: "app-configurator", inputs: { simple: { classPropertyName: "simple", publicName: "simple", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, location: { classPropertyName: "location", publicName: "location", isSignal: false, isRequired: false, transformFunction: null }, cardStyle: { classPropertyName: "cardStyle", publicName: "cardStyle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardStyle: "cardStyleChange" }, ngImport: i0, template: `
|
|
745
|
+
<p-drawer [(visible)]="configSidebarVisible" position="right" [transitionOptions]="'.3s cubic-bezier(0, 0, 0.2, 1)'" styleClass="layout-config-sidebar w-80" header="Settings" appendTo="body">
|
|
746
|
+
<div class="flex flex-col gap-6">
|
|
747
|
+
<div>
|
|
748
|
+
<span class="text-lg text-muted-color font-semibold">Primary</span>
|
|
749
|
+
<div class="pt-2 flex gap-2 flex-wrap">
|
|
750
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
751
|
+
<button
|
|
752
|
+
type="button"
|
|
753
|
+
[title]="primaryColor.name"
|
|
754
|
+
(click)="updateColors($event, 'primary', primaryColor)"
|
|
755
|
+
class="w-6 h-6 cursor-pointer hover:shadow-lg rounded duration-150 flex items-center justify-center"
|
|
756
|
+
[style]="{
|
|
757
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
758
|
+
}"
|
|
759
|
+
>
|
|
760
|
+
<i *ngIf="primaryColor.name === selectedPrimaryColor()" class="pi pi-check text-white"></i>
|
|
761
|
+
</button>
|
|
762
|
+
}
|
|
763
|
+
</div>
|
|
764
|
+
</div>
|
|
765
|
+
|
|
766
|
+
<div>
|
|
767
|
+
<span class="text-lg text-muted-color font-semibold">Surface</span>
|
|
768
|
+
<div class="pt-2 flex gap-2 flex-wrap">
|
|
769
|
+
@for (surface of surfaces; track surface.name) {
|
|
770
|
+
<button
|
|
771
|
+
type="button"
|
|
772
|
+
[title]="surface.name"
|
|
773
|
+
(click)="updateColors($event, 'surface', surface)"
|
|
774
|
+
class="w-6 h-6 cursor-pointer hover:shadow-lg rounded duration-150 flex items-center justify-center"
|
|
775
|
+
[style]="{
|
|
776
|
+
'background-color': surface?.palette?.['500']
|
|
777
|
+
}"
|
|
778
|
+
>
|
|
779
|
+
<i *ngIf="selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : darkTheme() ? surface.name === 'darkblue' : surface.name === 'gray'" class="pi pi-check text-white"></i>
|
|
780
|
+
</button>
|
|
781
|
+
}
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
<div>
|
|
785
|
+
<div class="flex flex-col gap-2">
|
|
786
|
+
<span class="text-lg text-muted-color font-semibold">Presets</span>
|
|
787
|
+
<p-selectbutton [options]="presetKeys" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false"></p-selectbutton>
|
|
788
|
+
</div>
|
|
789
|
+
</div>
|
|
790
|
+
<div>
|
|
791
|
+
<div class="flex flex-col gap-2">
|
|
792
|
+
<span class="text-lg text-muted-color font-semibold">Color Scheme</span>
|
|
793
|
+
<p-selectbutton [ngModel]="darkTheme()" (ngModelChange)="toggleDarkMode()" [options]="themeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"></p-selectbutton>
|
|
794
|
+
</div>
|
|
795
|
+
</div>
|
|
796
|
+
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
797
|
+
<span class="text-lg text-muted-color font-semibold">Card Style</span>
|
|
798
|
+
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" [allowEmpty]="false" />
|
|
799
|
+
</div>
|
|
800
|
+
|
|
801
|
+
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
802
|
+
<span class="text-lg text-muted-color font-semibold">Menu Theme</span>
|
|
803
|
+
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" [allowEmpty]="false" />
|
|
804
|
+
</div>
|
|
805
|
+
|
|
806
|
+
<div *ngIf="!simple && location === 'app'">
|
|
807
|
+
<div class="flex flex-col gap-2">
|
|
808
|
+
<span class="text-lg text-muted-color font-semibold">Menu Type</span>
|
|
809
|
+
<div class="flex flex-wrap flex-col gap-3">
|
|
810
|
+
<div class="flex">
|
|
811
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
812
|
+
<p-radiobutton name="menuMode" value="static" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('static')" inputId="static"></p-radiobutton>
|
|
813
|
+
<label for="static">Static</label>
|
|
814
|
+
</div>
|
|
815
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
816
|
+
<p-radiobutton name="menuMode" value="rail" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('rail')" inputId="rail"></p-radiobutton>
|
|
817
|
+
<label for="rail">Rail</label>
|
|
818
|
+
</div>
|
|
819
|
+
</div>
|
|
820
|
+
<div class="flex">
|
|
821
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
822
|
+
<p-radiobutton name="menuMode" value="overlay" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('overlay')" inputId="overlay"></p-radiobutton>
|
|
823
|
+
<label for="overlay">Overlay</label>
|
|
824
|
+
</div>
|
|
825
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
826
|
+
<p-radiobutton name="menuMode" value="slim" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('slim')" inputId="slim"></p-radiobutton>
|
|
827
|
+
<label for="slim">Slim</label>
|
|
828
|
+
</div>
|
|
829
|
+
</div>
|
|
830
|
+
<div class="flex">
|
|
831
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
832
|
+
<p-radiobutton name="menuMode" value="compact" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('compact')" inputId="compact"></p-radiobutton>
|
|
833
|
+
<label for="compact">Compact</label>
|
|
834
|
+
</div>
|
|
835
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
836
|
+
<p-radiobutton name="menuMode" value="reveal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('reveal')" inputId="reveal"></p-radiobutton>
|
|
837
|
+
<label for="reveal">Reveal</label>
|
|
838
|
+
</div>
|
|
839
|
+
</div>
|
|
840
|
+
<div class="flex">
|
|
841
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
842
|
+
<p-radiobutton name="menuMode" value="drawer" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('drawer')" inputId="drawer"></p-radiobutton>
|
|
843
|
+
<label for="drawer">Drawer</label>
|
|
844
|
+
</div>
|
|
845
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
846
|
+
<p-radiobutton name="menuMode" value="horizontal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('horizontal')" inputId="horizontal"></p-radiobutton>
|
|
847
|
+
<label for="horizontal">Horizontal</label>
|
|
848
|
+
</div>
|
|
849
|
+
</div>
|
|
850
|
+
</div>
|
|
851
|
+
</div>
|
|
852
|
+
</div>
|
|
853
|
+
</div>
|
|
854
|
+
</p-drawer>
|
|
855
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i5$1.RadioButton, selector: "p-radioButton, p-radiobutton, p-radio-button", inputs: ["value", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "styleClass", "autofocus", "binary", "variant", "size"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
856
|
+
}
|
|
857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppConfigurator, decorators: [{
|
|
858
|
+
type: Component,
|
|
859
|
+
args: [{
|
|
860
|
+
selector: 'app-configurator',
|
|
861
|
+
imports: [CommonModule, FormsModule, SelectButtonModule, DrawerModule, ToggleSwitchModule, RadioButtonModule],
|
|
862
|
+
template: `
|
|
863
|
+
<p-drawer [(visible)]="configSidebarVisible" position="right" [transitionOptions]="'.3s cubic-bezier(0, 0, 0.2, 1)'" styleClass="layout-config-sidebar w-80" header="Settings" appendTo="body">
|
|
864
|
+
<div class="flex flex-col gap-6">
|
|
865
|
+
<div>
|
|
866
|
+
<span class="text-lg text-muted-color font-semibold">Primary</span>
|
|
867
|
+
<div class="pt-2 flex gap-2 flex-wrap">
|
|
868
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
869
|
+
<button
|
|
870
|
+
type="button"
|
|
871
|
+
[title]="primaryColor.name"
|
|
872
|
+
(click)="updateColors($event, 'primary', primaryColor)"
|
|
873
|
+
class="w-6 h-6 cursor-pointer hover:shadow-lg rounded duration-150 flex items-center justify-center"
|
|
874
|
+
[style]="{
|
|
875
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
876
|
+
}"
|
|
877
|
+
>
|
|
878
|
+
<i *ngIf="primaryColor.name === selectedPrimaryColor()" class="pi pi-check text-white"></i>
|
|
879
|
+
</button>
|
|
880
|
+
}
|
|
881
|
+
</div>
|
|
882
|
+
</div>
|
|
883
|
+
|
|
884
|
+
<div>
|
|
885
|
+
<span class="text-lg text-muted-color font-semibold">Surface</span>
|
|
886
|
+
<div class="pt-2 flex gap-2 flex-wrap">
|
|
887
|
+
@for (surface of surfaces; track surface.name) {
|
|
888
|
+
<button
|
|
889
|
+
type="button"
|
|
890
|
+
[title]="surface.name"
|
|
891
|
+
(click)="updateColors($event, 'surface', surface)"
|
|
892
|
+
class="w-6 h-6 cursor-pointer hover:shadow-lg rounded duration-150 flex items-center justify-center"
|
|
893
|
+
[style]="{
|
|
894
|
+
'background-color': surface?.palette?.['500']
|
|
895
|
+
}"
|
|
896
|
+
>
|
|
897
|
+
<i *ngIf="selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : darkTheme() ? surface.name === 'darkblue' : surface.name === 'gray'" class="pi pi-check text-white"></i>
|
|
898
|
+
</button>
|
|
899
|
+
}
|
|
900
|
+
</div>
|
|
901
|
+
</div>
|
|
902
|
+
<div>
|
|
903
|
+
<div class="flex flex-col gap-2">
|
|
904
|
+
<span class="text-lg text-muted-color font-semibold">Presets</span>
|
|
905
|
+
<p-selectbutton [options]="presetKeys" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false"></p-selectbutton>
|
|
906
|
+
</div>
|
|
907
|
+
</div>
|
|
908
|
+
<div>
|
|
909
|
+
<div class="flex flex-col gap-2">
|
|
910
|
+
<span class="text-lg text-muted-color font-semibold">Color Scheme</span>
|
|
911
|
+
<p-selectbutton [ngModel]="darkTheme()" (ngModelChange)="toggleDarkMode()" [options]="themeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false"></p-selectbutton>
|
|
912
|
+
</div>
|
|
913
|
+
</div>
|
|
914
|
+
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
915
|
+
<span class="text-lg text-muted-color font-semibold">Card Style</span>
|
|
916
|
+
<p-selectbutton [ngModel]="cardStyle()" (ngModelChange)="onCardStyleChange($event)" [options]="cardStyleOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" [allowEmpty]="false" />
|
|
917
|
+
</div>
|
|
918
|
+
|
|
919
|
+
<div *ngIf="!simple && location === 'app'" class="flex flex-col gap-2">
|
|
920
|
+
<span class="text-lg text-muted-color font-semibold">Menu Theme</span>
|
|
921
|
+
<p-selectbutton [ngModel]="menuTheme()" (ngModelChange)="onMenuThemeChange($event)" [options]="menuThemeOptions" optionLabel="name" optionValue="value" [allowEmpty]="false" [allowEmpty]="false" />
|
|
922
|
+
</div>
|
|
923
|
+
|
|
924
|
+
<div *ngIf="!simple && location === 'app'">
|
|
925
|
+
<div class="flex flex-col gap-2">
|
|
926
|
+
<span class="text-lg text-muted-color font-semibold">Menu Type</span>
|
|
927
|
+
<div class="flex flex-wrap flex-col gap-3">
|
|
928
|
+
<div class="flex">
|
|
929
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
930
|
+
<p-radiobutton name="menuMode" value="static" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('static')" inputId="static"></p-radiobutton>
|
|
931
|
+
<label for="static">Static</label>
|
|
932
|
+
</div>
|
|
933
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
934
|
+
<p-radiobutton name="menuMode" value="rail" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('rail')" inputId="rail"></p-radiobutton>
|
|
935
|
+
<label for="rail">Rail</label>
|
|
936
|
+
</div>
|
|
937
|
+
</div>
|
|
938
|
+
<div class="flex">
|
|
939
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
940
|
+
<p-radiobutton name="menuMode" value="overlay" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('overlay')" inputId="overlay"></p-radiobutton>
|
|
941
|
+
<label for="overlay">Overlay</label>
|
|
942
|
+
</div>
|
|
943
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
944
|
+
<p-radiobutton name="menuMode" value="slim" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('slim')" inputId="slim"></p-radiobutton>
|
|
945
|
+
<label for="slim">Slim</label>
|
|
946
|
+
</div>
|
|
947
|
+
</div>
|
|
948
|
+
<div class="flex">
|
|
949
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
950
|
+
<p-radiobutton name="menuMode" value="compact" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('compact')" inputId="compact"></p-radiobutton>
|
|
951
|
+
<label for="compact">Compact</label>
|
|
952
|
+
</div>
|
|
953
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
954
|
+
<p-radiobutton name="menuMode" value="reveal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('reveal')" inputId="reveal"></p-radiobutton>
|
|
955
|
+
<label for="reveal">Reveal</label>
|
|
956
|
+
</div>
|
|
957
|
+
</div>
|
|
958
|
+
<div class="flex">
|
|
959
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
960
|
+
<p-radiobutton name="menuMode" value="drawer" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('drawer')" inputId="drawer"></p-radiobutton>
|
|
961
|
+
<label for="drawer">Drawer</label>
|
|
962
|
+
</div>
|
|
963
|
+
<div class="flex items-center gap-2 w-6/12">
|
|
964
|
+
<p-radiobutton name="menuMode" value="horizontal" [ngModel]="menuMode()" (ngModelChange)="setMenuMode('horizontal')" inputId="horizontal"></p-radiobutton>
|
|
965
|
+
<label for="horizontal">Horizontal</label>
|
|
966
|
+
</div>
|
|
967
|
+
</div>
|
|
968
|
+
</div>
|
|
969
|
+
</div>
|
|
970
|
+
</div>
|
|
971
|
+
</div>
|
|
972
|
+
</p-drawer>
|
|
973
|
+
`
|
|
974
|
+
}]
|
|
975
|
+
}], propDecorators: { simple: [{
|
|
976
|
+
type: Input,
|
|
977
|
+
args: [{ transform: booleanAttribute }]
|
|
978
|
+
}], location: [{
|
|
979
|
+
type: Input
|
|
980
|
+
}], cardStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardStyle", required: false }] }, { type: i0.Output, args: ["cardStyleChange"] }] } });
|
|
981
|
+
|
|
982
|
+
class AppFooter {
|
|
983
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
984
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppFooter, isStandalone: true, selector: "[app-footer]", ngImport: i0, template: `
|
|
985
|
+
<footer class="layout-footer">
|
|
986
|
+
<span class="footer-copyright">© UNOPS 2026</span>
|
|
987
|
+
</footer>
|
|
988
|
+
`, isInline: true });
|
|
989
|
+
}
|
|
990
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppFooter, decorators: [{
|
|
991
|
+
type: Component,
|
|
992
|
+
args: [{
|
|
993
|
+
selector: '[app-footer]',
|
|
994
|
+
template: `
|
|
995
|
+
<footer class="layout-footer">
|
|
996
|
+
<span class="footer-copyright">© UNOPS 2026</span>
|
|
997
|
+
</footer>
|
|
998
|
+
`
|
|
999
|
+
}]
|
|
1000
|
+
}] });
|
|
1001
|
+
|
|
1002
|
+
class AppRightMenu {
|
|
1003
|
+
layoutService = inject(LayoutService);
|
|
1004
|
+
cards = [
|
|
1005
|
+
{ label: '*****24', value: { id: 1, name: '*****24', code: 'A1' } },
|
|
1006
|
+
{ label: '*****75', value: { id: 2, name: '*****75', code: 'A2' } }
|
|
1007
|
+
];
|
|
1008
|
+
selectedCard;
|
|
1009
|
+
amountValue = '';
|
|
1010
|
+
get rightMenuVisible() {
|
|
1011
|
+
return this.layoutService.layoutState().rightMenuVisible;
|
|
1012
|
+
}
|
|
1013
|
+
set rightMenuVisible(_val) {
|
|
1014
|
+
this.layoutService.layoutState.update((prev) => ({ ...prev, rightMenuVisible: _val }));
|
|
1015
|
+
}
|
|
1016
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppRightMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1017
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppRightMenu, isStandalone: true, selector: "[app-rightmenu]", ngImport: i0, template: ` <p-drawer header="Menu" [(visible)]="rightMenuVisible" position="right" styleClass="layout-rightmenu w-full! sm:w-xl!">
|
|
1018
|
+
<div>
|
|
1019
|
+
<h2 class="title-h7 text-left">Activity</h2>
|
|
1020
|
+
<div class="flex flex-col mt-7">
|
|
1021
|
+
<div class="flex gap-6">
|
|
1022
|
+
<div class="flex flex-col items-center">
|
|
1023
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1024
|
+
<i class="pi pi-dollar text-blue-600 text-2xl!"></i>
|
|
1025
|
+
</span>
|
|
1026
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1027
|
+
</div>
|
|
1028
|
+
<div class="mt-2">
|
|
1029
|
+
<h5 class="label-large">New Sale</h5>
|
|
1030
|
+
<p class="md:label-small mt-1">Richard Jones has purchased a blue t-shirt for <b class="body-small text-surface-950 dark:text-surface-0">$79</b></p>
|
|
1031
|
+
</div>
|
|
1032
|
+
</div>
|
|
1033
|
+
<div class="flex gap-6">
|
|
1034
|
+
<div class="flex flex-col items-center">
|
|
1035
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1036
|
+
<i class="pi pi-download text-orange-600 text-2xl!"></i>
|
|
1037
|
+
</span>
|
|
1038
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1039
|
+
</div>
|
|
1040
|
+
<div class="mt-2">
|
|
1041
|
+
<h5 class="label-large">Withdrawal Initiated</h5>
|
|
1042
|
+
<p class="md:label-small mt-1">Your request for withdrawal of <b class="body-small text-surface-950 dark:text-surface-0">$2500</b> has been initiated.</p>
|
|
1043
|
+
</div>
|
|
1044
|
+
</div>
|
|
1045
|
+
<div class="flex gap-6">
|
|
1046
|
+
<div class="flex flex-col items-center">
|
|
1047
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1048
|
+
<i class="pi pi-question-circle text-violet-600 text-2xl!"></i>
|
|
1049
|
+
</span>
|
|
1050
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1051
|
+
</div>
|
|
1052
|
+
<div class="mt-2">
|
|
1053
|
+
<h5 class="label-large">Question Received</h5>
|
|
1054
|
+
<p class="md:label-small mt-1">Jane Davis has posted a <b class="body-small text-surface-950 dark:text-surface-0">new question</b> about your product.</p>
|
|
1055
|
+
</div>
|
|
1056
|
+
</div>
|
|
1057
|
+
<div class="flex gap-6">
|
|
1058
|
+
<div class="flex flex-col items-center">
|
|
1059
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1060
|
+
<i class="pi pi-comment text-blue-600 text-2xl!"></i>
|
|
1061
|
+
</span>
|
|
1062
|
+
</div>
|
|
1063
|
+
<div class="mt-2">
|
|
1064
|
+
<h5 class="label-large">Comment Received</h5>
|
|
1065
|
+
<p class="md:label-small mt-1">Claire Smith has upvoted your store along with a <b class="body-small text-surface-950 dark:text-surface-0">comment.</b></p>
|
|
1066
|
+
</div>
|
|
1067
|
+
</div>
|
|
1068
|
+
</div>
|
|
1069
|
+
</div>
|
|
1070
|
+
<p-divider class="my-10!" />
|
|
1071
|
+
<div>
|
|
1072
|
+
<h2 class="title-h7 text-left">Quick Withdraw</h2>
|
|
1073
|
+
<div class="flex flex-col gap-3.5 mt-7 mb-6">
|
|
1074
|
+
<input pInputText type="text" [(ngModel)]="amountValue" placeholder="Amount" />
|
|
1075
|
+
<p-select [(ngModel)]="selectedCard" [options]="cards" optionLabel="label" placeholder="Select a Card" class="w-full" />
|
|
1076
|
+
</div>
|
|
1077
|
+
<button pButton label="Confirm" severity="success" class="w-full!"></button>
|
|
1078
|
+
</div>
|
|
1079
|
+
<p-divider class="my-10!" />
|
|
1080
|
+
<div>
|
|
1081
|
+
<h2 class="title-h7 text-left">Shipment Tracking</h2>
|
|
1082
|
+
<p class="body-small mt-1 text-left">Track your ongoing shipments to customers.</p>
|
|
1083
|
+
<img class="w-full h-full max-h-60 object-cover border border-surface rounded-2xl mt-4" src="layout/images/sidebar-right/staticmap.png" alt="unops-ng_ux" />
|
|
1084
|
+
</div>
|
|
1085
|
+
</p-drawer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i4.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i2.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }] });
|
|
1086
|
+
}
|
|
1087
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppRightMenu, decorators: [{
|
|
1088
|
+
type: Component,
|
|
1089
|
+
args: [{
|
|
1090
|
+
selector: '[app-rightmenu]',
|
|
1091
|
+
imports: [DrawerModule, DividerModule, SelectModule, InputTextModule, FormsModule, ButtonModule],
|
|
1092
|
+
template: ` <p-drawer header="Menu" [(visible)]="rightMenuVisible" position="right" styleClass="layout-rightmenu w-full! sm:w-xl!">
|
|
1093
|
+
<div>
|
|
1094
|
+
<h2 class="title-h7 text-left">Activity</h2>
|
|
1095
|
+
<div class="flex flex-col mt-7">
|
|
1096
|
+
<div class="flex gap-6">
|
|
1097
|
+
<div class="flex flex-col items-center">
|
|
1098
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1099
|
+
<i class="pi pi-dollar text-blue-600 text-2xl!"></i>
|
|
1100
|
+
</span>
|
|
1101
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1102
|
+
</div>
|
|
1103
|
+
<div class="mt-2">
|
|
1104
|
+
<h5 class="label-large">New Sale</h5>
|
|
1105
|
+
<p class="md:label-small mt-1">Richard Jones has purchased a blue t-shirt for <b class="body-small text-surface-950 dark:text-surface-0">$79</b></p>
|
|
1106
|
+
</div>
|
|
1107
|
+
</div>
|
|
1108
|
+
<div class="flex gap-6">
|
|
1109
|
+
<div class="flex flex-col items-center">
|
|
1110
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1111
|
+
<i class="pi pi-download text-orange-600 text-2xl!"></i>
|
|
1112
|
+
</span>
|
|
1113
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1114
|
+
</div>
|
|
1115
|
+
<div class="mt-2">
|
|
1116
|
+
<h5 class="label-large">Withdrawal Initiated</h5>
|
|
1117
|
+
<p class="md:label-small mt-1">Your request for withdrawal of <b class="body-small text-surface-950 dark:text-surface-0">$2500</b> has been initiated.</p>
|
|
1118
|
+
</div>
|
|
1119
|
+
</div>
|
|
1120
|
+
<div class="flex gap-6">
|
|
1121
|
+
<div class="flex flex-col items-center">
|
|
1122
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1123
|
+
<i class="pi pi-question-circle text-violet-600 text-2xl!"></i>
|
|
1124
|
+
</span>
|
|
1125
|
+
<span class="min-h-14 w-px bg-(--surface-border)"></span>
|
|
1126
|
+
</div>
|
|
1127
|
+
<div class="mt-2">
|
|
1128
|
+
<h5 class="label-large">Question Received</h5>
|
|
1129
|
+
<p class="md:label-small mt-1">Jane Davis has posted a <b class="body-small text-surface-950 dark:text-surface-0">new question</b> about your product.</p>
|
|
1130
|
+
</div>
|
|
1131
|
+
</div>
|
|
1132
|
+
<div class="flex gap-6">
|
|
1133
|
+
<div class="flex flex-col items-center">
|
|
1134
|
+
<span class="w-14 h-14 flex items-center justify-center border border-surface rounded-xl shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05);]">
|
|
1135
|
+
<i class="pi pi-comment text-blue-600 text-2xl!"></i>
|
|
1136
|
+
</span>
|
|
1137
|
+
</div>
|
|
1138
|
+
<div class="mt-2">
|
|
1139
|
+
<h5 class="label-large">Comment Received</h5>
|
|
1140
|
+
<p class="md:label-small mt-1">Claire Smith has upvoted your store along with a <b class="body-small text-surface-950 dark:text-surface-0">comment.</b></p>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
</div>
|
|
1144
|
+
</div>
|
|
1145
|
+
<p-divider class="my-10!" />
|
|
1146
|
+
<div>
|
|
1147
|
+
<h2 class="title-h7 text-left">Quick Withdraw</h2>
|
|
1148
|
+
<div class="flex flex-col gap-3.5 mt-7 mb-6">
|
|
1149
|
+
<input pInputText type="text" [(ngModel)]="amountValue" placeholder="Amount" />
|
|
1150
|
+
<p-select [(ngModel)]="selectedCard" [options]="cards" optionLabel="label" placeholder="Select a Card" class="w-full" />
|
|
1151
|
+
</div>
|
|
1152
|
+
<button pButton label="Confirm" severity="success" class="w-full!"></button>
|
|
1153
|
+
</div>
|
|
1154
|
+
<p-divider class="my-10!" />
|
|
1155
|
+
<div>
|
|
1156
|
+
<h2 class="title-h7 text-left">Shipment Tracking</h2>
|
|
1157
|
+
<p class="body-small mt-1 text-left">Track your ongoing shipments to customers.</p>
|
|
1158
|
+
<img class="w-full h-full max-h-60 object-cover border border-surface rounded-2xl mt-4" src="layout/images/sidebar-right/staticmap.png" alt="unops-ng_ux" />
|
|
1159
|
+
</div>
|
|
1160
|
+
</p-drawer>`
|
|
1161
|
+
}]
|
|
1162
|
+
}] });
|
|
1163
|
+
|
|
1164
|
+
class AppSearch {
|
|
1165
|
+
layoutService = inject(LayoutService);
|
|
1166
|
+
toggleSearchBar() {
|
|
1167
|
+
this.layoutService.layoutState.update((value) => ({ ...value, searchBarActive: !value.searchBarActive }));
|
|
1168
|
+
}
|
|
1169
|
+
get searchBarActive() {
|
|
1170
|
+
return this.layoutService.layoutState().searchBarActive;
|
|
1171
|
+
}
|
|
1172
|
+
set searchBarActive(_val) {
|
|
1173
|
+
this.layoutService.layoutState.update((prev) => ({ ...prev, searchBarActive: _val }));
|
|
1174
|
+
}
|
|
1175
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSearch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1176
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppSearch, isStandalone: true, selector: "[app-search]", ngImport: i0, template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '992px': '75vw', '576px': '90vw' }" modal dismissableMask styleClass="w-1/2 search-container">
|
|
1177
|
+
<ng-template #headless>
|
|
1178
|
+
<div class="w-full">
|
|
1179
|
+
<i class="pi pi-search"></i>
|
|
1180
|
+
<input pInputText type="text" [pAutoFocus]="true" class="p-inputtext search-input" placeholder="Search" (keydown.enter)="toggleSearchBar()" />
|
|
1181
|
+
</div>
|
|
1182
|
+
</ng-template>
|
|
1183
|
+
</p-dialog>`, isInline: true, dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: AutoFocusModule }, { kind: "directive", type: i3$2.AutoFocus, selector: "[pAutoFocus]", inputs: ["pAutoFocus"] }] });
|
|
1184
|
+
}
|
|
1185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSearch, decorators: [{
|
|
1186
|
+
type: Component,
|
|
1187
|
+
args: [{
|
|
1188
|
+
selector: '[app-search]',
|
|
1189
|
+
imports: [DialogModule, InputTextModule, AutoFocusModule],
|
|
1190
|
+
template: ` <p-dialog [(visible)]="searchBarActive" [breakpoints]="{ '992px': '75vw', '576px': '90vw' }" modal dismissableMask styleClass="w-1/2 search-container">
|
|
1191
|
+
<ng-template #headless>
|
|
1192
|
+
<div class="w-full">
|
|
1193
|
+
<i class="pi pi-search"></i>
|
|
1194
|
+
<input pInputText type="text" [pAutoFocus]="true" class="p-inputtext search-input" placeholder="Search" (keydown.enter)="toggleSearchBar()" />
|
|
1195
|
+
</div>
|
|
1196
|
+
</ng-template>
|
|
1197
|
+
</p-dialog>`
|
|
1198
|
+
}]
|
|
1199
|
+
}] });
|
|
1200
|
+
|
|
1201
|
+
class AppMenuitem {
|
|
1202
|
+
layoutService = inject(LayoutService);
|
|
1203
|
+
router = inject(Router);
|
|
1204
|
+
hoverExpandTimer = null;
|
|
1205
|
+
item = input(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
1206
|
+
root = input(true, ...(ngDevMode ? [{ debugName: "root" }] : []));
|
|
1207
|
+
parentPath = input(null, ...(ngDevMode ? [{ debugName: "parentPath" }] : []));
|
|
1208
|
+
preventAutoActivate = input(false, ...(ngDevMode ? [{ debugName: "preventAutoActivate" }] : []));
|
|
1209
|
+
isDisabled = computed(() => this.item()?.disabled ?? false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
1210
|
+
isSlim = computed(() => this.layoutService.layoutConfig().menuMode === 'slim', ...(ngDevMode ? [{ debugName: "isSlim" }] : []));
|
|
1211
|
+
isHorizontal = computed(() => this.layoutService.layoutConfig().menuMode === 'horizontal', ...(ngDevMode ? [{ debugName: "isHorizontal" }] : []));
|
|
1212
|
+
isCompact = computed(() => this.layoutService.layoutConfig().menuMode === 'compact', ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
|
|
1213
|
+
isRailCollapsed = computed(() => this.layoutService.isRail() && !this.layoutService.layoutState().sidebarExpanded, ...(ngDevMode ? [{ debugName: "isRailCollapsed" }] : []));
|
|
1214
|
+
isVisible = computed(() => this.item()?.visible !== false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
1215
|
+
hasChildren = computed(() => !!this.item()?.items && (this.item()?.items?.length ?? 0) > 0, ...(ngDevMode ? [{ debugName: "hasChildren" }] : []));
|
|
1216
|
+
hasCommand = computed(() => typeof this.item()?.command === 'function', ...(ngDevMode ? [{ debugName: "hasCommand" }] : []));
|
|
1217
|
+
hasRouterLink = computed(() => !!this.item()?.routerLink, ...(ngDevMode ? [{ debugName: "hasRouterLink" }] : []));
|
|
1218
|
+
fullPath = computed(() => {
|
|
1219
|
+
const itemPath = this.item()?.path;
|
|
1220
|
+
if (!itemPath)
|
|
1221
|
+
return this.parentPath();
|
|
1222
|
+
const parent = this.parentPath();
|
|
1223
|
+
if (parent && !itemPath.startsWith(parent)) {
|
|
1224
|
+
return parent + itemPath;
|
|
1225
|
+
}
|
|
1226
|
+
return itemPath;
|
|
1227
|
+
}, ...(ngDevMode ? [{ debugName: "fullPath" }] : []));
|
|
1228
|
+
menuHoverActive = computed(() => this.layoutService.layoutState().menuHoverActive, ...(ngDevMode ? [{ debugName: "menuHoverActive" }] : []));
|
|
1229
|
+
isActive = computed(() => {
|
|
1230
|
+
const activePath = this.layoutService.layoutState().activePath;
|
|
1231
|
+
if (this.item()?.path) {
|
|
1232
|
+
return activePath?.startsWith(this.fullPath() ?? '') ?? false;
|
|
1233
|
+
}
|
|
1234
|
+
return false;
|
|
1235
|
+
}, ...(ngDevMode ? [{ debugName: "isActive" }] : []));
|
|
1236
|
+
isRouteWithin = computed(() => {
|
|
1237
|
+
this.layoutService.currentUrl();
|
|
1238
|
+
if (!this.root() || !this.hasChildren())
|
|
1239
|
+
return false;
|
|
1240
|
+
return this.hasMatchingChildRoute(this.item());
|
|
1241
|
+
}, ...(ngDevMode ? [{ debugName: "isRouteWithin" }] : []));
|
|
1242
|
+
initialized = signal(false, ...(ngDevMode ? [{ debugName: "initialized" }] : []));
|
|
1243
|
+
constructor() {
|
|
1244
|
+
effect(() => {
|
|
1245
|
+
this.updateActivePath();
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
defaultMatchOptions = {
|
|
1249
|
+
paths: 'exact',
|
|
1250
|
+
queryParams: 'ignored',
|
|
1251
|
+
matrixParams: 'ignored',
|
|
1252
|
+
fragment: 'ignored'
|
|
1253
|
+
};
|
|
1254
|
+
itemMatchOptions(item) {
|
|
1255
|
+
return item?.routerLinkActiveOptions ?? this.defaultMatchOptions;
|
|
1256
|
+
}
|
|
1257
|
+
updateActivePath() {
|
|
1258
|
+
if (this.layoutService.hasOverlaySubmenu() && this.layoutService.isDesktop()) {
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
if (this.preventAutoActivate()) {
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
const item = this.item();
|
|
1265
|
+
const parentPath = this.parentPath();
|
|
1266
|
+
if (item?.routerLink && !item?.items) {
|
|
1267
|
+
const isRouteActive = this.router.isActive(item.routerLink[0], this.itemMatchOptions(item));
|
|
1268
|
+
if (isRouteActive && parentPath) {
|
|
1269
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1270
|
+
...val,
|
|
1271
|
+
activePath: parentPath
|
|
1272
|
+
}));
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
ngAfterViewInit() {
|
|
1277
|
+
setTimeout(() => {
|
|
1278
|
+
this.initialized.set(true);
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
itemClick(event) {
|
|
1282
|
+
if (this.isDisabled()) {
|
|
1283
|
+
event.preventDefault();
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
if (this.hasCommand()) {
|
|
1287
|
+
this.item()?.command?.({ originalEvent: event, item: this.item() ?? undefined });
|
|
1288
|
+
}
|
|
1289
|
+
if (this.hasChildren()) {
|
|
1290
|
+
if (this.isActive()) {
|
|
1291
|
+
const deactivateHover = this.root() && this.layoutService.hasOverlaySubmenu() && this.layoutService.isDesktop();
|
|
1292
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1293
|
+
...val,
|
|
1294
|
+
activePath: this.parentPath(),
|
|
1295
|
+
menuHoverActive: deactivateHover ? false : val.menuHoverActive
|
|
1296
|
+
}));
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1300
|
+
...val,
|
|
1301
|
+
activePath: this.fullPath(),
|
|
1302
|
+
menuHoverActive: true
|
|
1303
|
+
}));
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
else {
|
|
1307
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1308
|
+
...val,
|
|
1309
|
+
overlayMenuActive: false,
|
|
1310
|
+
mobileMenuActive: false,
|
|
1311
|
+
menuHoverActive: false
|
|
1312
|
+
}));
|
|
1313
|
+
if (this.layoutService.hasOverlaySubmenu() && this.layoutService.isDesktop()) {
|
|
1314
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1315
|
+
...val,
|
|
1316
|
+
activePath: null
|
|
1317
|
+
}));
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (this.layoutService.isDesktop() && this.layoutService.isRail() && !this.layoutService.layoutState().sidebarExpanded) {
|
|
1321
|
+
this.layoutService.toggleSidebarPin();
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
onMouseEnter() {
|
|
1325
|
+
if (this.layoutService.isDesktop() && this.root() && this.hasChildren() && this.menuHoverActive() && !this.isActive()) {
|
|
1326
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1327
|
+
...val,
|
|
1328
|
+
activePath: this.fullPath(),
|
|
1329
|
+
menuHoverActive: true
|
|
1330
|
+
}));
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
onMouseLeave() { }
|
|
1334
|
+
ngOnDestroy() {
|
|
1335
|
+
this.clearHoverTimer();
|
|
1336
|
+
}
|
|
1337
|
+
scheduleRailExpand() {
|
|
1338
|
+
this.clearHoverTimer();
|
|
1339
|
+
this.hoverExpandTimer = setTimeout(() => {
|
|
1340
|
+
this.layoutService.layoutState.update((val) => ({
|
|
1341
|
+
...val,
|
|
1342
|
+
sidebarExpanded: true
|
|
1343
|
+
}));
|
|
1344
|
+
}, 500);
|
|
1345
|
+
}
|
|
1346
|
+
clearHoverTimer() {
|
|
1347
|
+
if (this.hoverExpandTimer !== null) {
|
|
1348
|
+
clearTimeout(this.hoverExpandTimer);
|
|
1349
|
+
this.hoverExpandTimer = null;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
hasMatchingChildRoute(item) {
|
|
1353
|
+
if (!item)
|
|
1354
|
+
return false;
|
|
1355
|
+
if (item.routerLink) {
|
|
1356
|
+
return this.router.isActive(item.routerLink[0], this.itemMatchOptions(item));
|
|
1357
|
+
}
|
|
1358
|
+
return item.items?.some((child) => this.hasMatchingChildRoute(child)) ?? false;
|
|
1359
|
+
}
|
|
1360
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppMenuitem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1361
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppMenuitem, isStandalone: true, selector: "[app-menuitem]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, root: { classPropertyName: "root", publicName: "root", isSignal: true, isRequired: false, transformFunction: null }, parentPath: { classPropertyName: "parentPath", publicName: "parentPath", isSignal: true, isRequired: false, transformFunction: null }, preventAutoActivate: { classPropertyName: "preventAutoActivate", publicName: "preventAutoActivate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.active-menuitem": "isActive()", "class.layout-root-menuitem": "root()", "class.route-active-within": "isRouteWithin()" } }, ngImport: i0, template: `
|
|
1362
|
+
@if (root() && isVisible() && hasChildren()) {
|
|
1363
|
+
<div class="layout-menuitem-root-text">{{ item()?.label }}</div>
|
|
1364
|
+
}
|
|
1365
|
+
@if ((!hasRouterLink() || hasChildren()) && isVisible()) {
|
|
1366
|
+
<a
|
|
1367
|
+
[attr.href]="item()?.url"
|
|
1368
|
+
(click)="itemClick($event)"
|
|
1369
|
+
(mouseenter)="onMouseEnter()"
|
|
1370
|
+
(mouseleave)="onMouseLeave()"
|
|
1371
|
+
[ngClass]="item()?.class"
|
|
1372
|
+
[attr.target]="item()?.target"
|
|
1373
|
+
tabindex="0"
|
|
1374
|
+
pRipple
|
|
1375
|
+
[pTooltip]="item()?.label"
|
|
1376
|
+
[tooltipDisabled]="!((isCompact() || isRailCollapsed()) && !isActive() && root())"
|
|
1377
|
+
>
|
|
1378
|
+
<i [ngClass]="item()?.icon" class="layout-menuitem-icon"></i>
|
|
1379
|
+
<span class="layout-menuitem-text label-small text-inherit">{{ item()?.label }}</span>
|
|
1380
|
+
@if (hasChildren()) {
|
|
1381
|
+
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
1382
|
+
}
|
|
1383
|
+
</a>
|
|
1384
|
+
}
|
|
1385
|
+
@if (hasRouterLink() && !hasChildren() && isVisible()) {
|
|
1386
|
+
<a
|
|
1387
|
+
(click)="itemClick($event)"
|
|
1388
|
+
(mouseenter)="onMouseEnter()"
|
|
1389
|
+
(mouseleave)="onMouseLeave()"
|
|
1390
|
+
[ngClass]="item()?.class"
|
|
1391
|
+
[routerLink]="item()?.routerLink"
|
|
1392
|
+
routerLinkActive="active-route"
|
|
1393
|
+
[routerLinkActiveOptions]="item()?.routerLinkActiveOptions || { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' }"
|
|
1394
|
+
[fragment]="item()?.fragment"
|
|
1395
|
+
[queryParamsHandling]="item()?.queryParamsHandling"
|
|
1396
|
+
[preserveFragment]="item()?.preserveFragment"
|
|
1397
|
+
[skipLocationChange]="item()?.skipLocationChange"
|
|
1398
|
+
[replaceUrl]="item()?.replaceUrl"
|
|
1399
|
+
[state]="item()?.state"
|
|
1400
|
+
[queryParams]="item()?.queryParams"
|
|
1401
|
+
[attr.target]="item()?.target"
|
|
1402
|
+
tabindex="0"
|
|
1403
|
+
[pTooltip]="item()?.label"
|
|
1404
|
+
[tooltipDisabled]="!((isCompact() || isRailCollapsed()) && !isActive() && root())"
|
|
1405
|
+
>
|
|
1406
|
+
<i [ngClass]="item()?.icon" class="layout-menuitem-icon"></i>
|
|
1407
|
+
<span class="layout-menuitem-text label-small text-inherit">{{ item()?.label }}</span>
|
|
1408
|
+
@if (hasChildren()) {
|
|
1409
|
+
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
1410
|
+
}
|
|
1411
|
+
</a>
|
|
1412
|
+
}
|
|
1413
|
+
@if (hasChildren() && isVisible()) {
|
|
1414
|
+
<ul [animate.enter]="initialized() ? 'p-submenu-enter' : null" [animate.leave]="'p-submenu-leave'" [class.layout-root-submenulist]="root()">
|
|
1415
|
+
@for (child of item()?.items; track child?.label) {
|
|
1416
|
+
<li app-menuitem [item]="child" [root]="false" [parentPath]="fullPath()" [preventAutoActivate]="preventAutoActivate() || !!item()?.preventAutoActivate" [class]="child?.['badgeClass']"></li>
|
|
1417
|
+
}
|
|
1418
|
+
</ul>
|
|
1419
|
+
}
|
|
1420
|
+
`, isInline: true, styles: [".p-submenu-enter{animation:p-animate-submenu-expand .15s cubic-bezier(.4,0,.2,1) forwards;overflow:hidden}.p-submenu-leave{animation:p-animate-submenu-collapse .15s cubic-bezier(.4,0,.2,1) forwards;overflow:hidden}@keyframes p-animate-submenu-expand{0%{max-height:0}to{max-height:1000px}}@keyframes p-animate-submenu-collapse{0%{max-height:1000px}to{max-height:0}}\n"], dependencies: [{ kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "root", "parentPath", "preventAutoActivate"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i4$2.Ripple, selector: "[pRipple]" }] });
|
|
1421
|
+
}
|
|
1422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppMenuitem, decorators: [{
|
|
1423
|
+
type: Component,
|
|
1424
|
+
args: [{ selector: '[app-menuitem]', imports: [CommonModule, RouterModule, TooltipModule, RippleModule], template: `
|
|
1425
|
+
@if (root() && isVisible() && hasChildren()) {
|
|
1426
|
+
<div class="layout-menuitem-root-text">{{ item()?.label }}</div>
|
|
1427
|
+
}
|
|
1428
|
+
@if ((!hasRouterLink() || hasChildren()) && isVisible()) {
|
|
1429
|
+
<a
|
|
1430
|
+
[attr.href]="item()?.url"
|
|
1431
|
+
(click)="itemClick($event)"
|
|
1432
|
+
(mouseenter)="onMouseEnter()"
|
|
1433
|
+
(mouseleave)="onMouseLeave()"
|
|
1434
|
+
[ngClass]="item()?.class"
|
|
1435
|
+
[attr.target]="item()?.target"
|
|
1436
|
+
tabindex="0"
|
|
1437
|
+
pRipple
|
|
1438
|
+
[pTooltip]="item()?.label"
|
|
1439
|
+
[tooltipDisabled]="!((isCompact() || isRailCollapsed()) && !isActive() && root())"
|
|
1440
|
+
>
|
|
1441
|
+
<i [ngClass]="item()?.icon" class="layout-menuitem-icon"></i>
|
|
1442
|
+
<span class="layout-menuitem-text label-small text-inherit">{{ item()?.label }}</span>
|
|
1443
|
+
@if (hasChildren()) {
|
|
1444
|
+
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
1445
|
+
}
|
|
1446
|
+
</a>
|
|
1447
|
+
}
|
|
1448
|
+
@if (hasRouterLink() && !hasChildren() && isVisible()) {
|
|
1449
|
+
<a
|
|
1450
|
+
(click)="itemClick($event)"
|
|
1451
|
+
(mouseenter)="onMouseEnter()"
|
|
1452
|
+
(mouseleave)="onMouseLeave()"
|
|
1453
|
+
[ngClass]="item()?.class"
|
|
1454
|
+
[routerLink]="item()?.routerLink"
|
|
1455
|
+
routerLinkActive="active-route"
|
|
1456
|
+
[routerLinkActiveOptions]="item()?.routerLinkActiveOptions || { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' }"
|
|
1457
|
+
[fragment]="item()?.fragment"
|
|
1458
|
+
[queryParamsHandling]="item()?.queryParamsHandling"
|
|
1459
|
+
[preserveFragment]="item()?.preserveFragment"
|
|
1460
|
+
[skipLocationChange]="item()?.skipLocationChange"
|
|
1461
|
+
[replaceUrl]="item()?.replaceUrl"
|
|
1462
|
+
[state]="item()?.state"
|
|
1463
|
+
[queryParams]="item()?.queryParams"
|
|
1464
|
+
[attr.target]="item()?.target"
|
|
1465
|
+
tabindex="0"
|
|
1466
|
+
[pTooltip]="item()?.label"
|
|
1467
|
+
[tooltipDisabled]="!((isCompact() || isRailCollapsed()) && !isActive() && root())"
|
|
1468
|
+
>
|
|
1469
|
+
<i [ngClass]="item()?.icon" class="layout-menuitem-icon"></i>
|
|
1470
|
+
<span class="layout-menuitem-text label-small text-inherit">{{ item()?.label }}</span>
|
|
1471
|
+
@if (hasChildren()) {
|
|
1472
|
+
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
|
1473
|
+
}
|
|
1474
|
+
</a>
|
|
1475
|
+
}
|
|
1476
|
+
@if (hasChildren() && isVisible()) {
|
|
1477
|
+
<ul [animate.enter]="initialized() ? 'p-submenu-enter' : null" [animate.leave]="'p-submenu-leave'" [class.layout-root-submenulist]="root()">
|
|
1478
|
+
@for (child of item()?.items; track child?.label) {
|
|
1479
|
+
<li app-menuitem [item]="child" [root]="false" [parentPath]="fullPath()" [preventAutoActivate]="preventAutoActivate() || !!item()?.preventAutoActivate" [class]="child?.['badgeClass']"></li>
|
|
1480
|
+
}
|
|
1481
|
+
</ul>
|
|
1482
|
+
}
|
|
1483
|
+
`, host: {
|
|
1484
|
+
'[class.active-menuitem]': 'isActive()',
|
|
1485
|
+
'[class.layout-root-menuitem]': 'root()',
|
|
1486
|
+
'[class.route-active-within]': 'isRouteWithin()'
|
|
1487
|
+
}, styles: [".p-submenu-enter{animation:p-animate-submenu-expand .15s cubic-bezier(.4,0,.2,1) forwards;overflow:hidden}.p-submenu-leave{animation:p-animate-submenu-collapse .15s cubic-bezier(.4,0,.2,1) forwards;overflow:hidden}@keyframes p-animate-submenu-expand{0%{max-height:0}to{max-height:1000px}}@keyframes p-animate-submenu-collapse{0%{max-height:1000px}to{max-height:0}}\n"] }]
|
|
1488
|
+
}], ctorParameters: () => [], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], root: [{ type: i0.Input, args: [{ isSignal: true, alias: "root", required: false }] }], parentPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentPath", required: false }] }], preventAutoActivate: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventAutoActivate", required: false }] }] } });
|
|
1489
|
+
|
|
1490
|
+
class AppMenu {
|
|
1491
|
+
/** Injected menu tree from the host application. */
|
|
1492
|
+
menuItems = inject(MENU_MODEL);
|
|
1493
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1494
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppMenu, isStandalone: true, selector: "[app-menu]", ngImport: i0, template: `<ul class="layout-menu">
|
|
1495
|
+
@for (item of menuItems; track $index) {
|
|
1496
|
+
@if (!item.separator) {
|
|
1497
|
+
<li app-menuitem [item]="item" [root]="true"></li>
|
|
1498
|
+
} @else {
|
|
1499
|
+
<li class="menu-separator"></li>
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
</ul> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AppMenuitem, selector: "[app-menuitem]", inputs: ["item", "root", "parentPath", "preventAutoActivate"] }, { kind: "ngmodule", type: RouterModule }] });
|
|
1503
|
+
}
|
|
1504
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppMenu, decorators: [{
|
|
1505
|
+
type: Component,
|
|
1506
|
+
args: [{
|
|
1507
|
+
selector: '[app-menu]',
|
|
1508
|
+
imports: [CommonModule, AppMenuitem, RouterModule],
|
|
1509
|
+
template: `<ul class="layout-menu">
|
|
1510
|
+
@for (item of menuItems; track $index) {
|
|
1511
|
+
@if (!item.separator) {
|
|
1512
|
+
<li app-menuitem [item]="item" [root]="true"></li>
|
|
1513
|
+
} @else {
|
|
1514
|
+
<li class="menu-separator"></li>
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
</ul> `
|
|
1518
|
+
}]
|
|
1519
|
+
}] });
|
|
1520
|
+
|
|
1521
|
+
class AppTopbar {
|
|
1522
|
+
layoutService = inject(LayoutService);
|
|
1523
|
+
mobileLogoConfig = inject(TOPBAR_MOBILE_LOGO);
|
|
1524
|
+
mobileLogo = computed(() => this.layoutService.isDarkTheme() ? this.mobileLogoConfig.dark : this.mobileLogoConfig.light, ...(ngDevMode ? [{ debugName: "mobileLogo" }] : []));
|
|
1525
|
+
desktopLogo = computed(() => this.layoutService.isDarkTheme() ? this.mobileLogoConfig.dark : this.mobileLogoConfig.light, ...(ngDevMode ? [{ debugName: "desktopLogo" }] : []));
|
|
1526
|
+
isDarkTheme = computed(() => this.layoutService.isDarkTheme(), ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
|
|
1527
|
+
isSidebarPinned = computed(() => this.layoutService.isSidebarPinned(), ...(ngDevMode ? [{ debugName: "isSidebarPinned" }] : []));
|
|
1528
|
+
searchActive = signal(false, ...(ngDevMode ? [{ debugName: "searchActive" }] : []));
|
|
1529
|
+
profileMenuOpen = signal(false, ...(ngDevMode ? [{ debugName: "profileMenuOpen" }] : []));
|
|
1530
|
+
shouldFocusSearch = false;
|
|
1531
|
+
menuButton;
|
|
1532
|
+
searchInput;
|
|
1533
|
+
profileItem;
|
|
1534
|
+
profilePanel;
|
|
1535
|
+
notificationsBars = signal([
|
|
1536
|
+
{
|
|
1537
|
+
id: 'inbox',
|
|
1538
|
+
label: 'Inbox',
|
|
1539
|
+
badge: '2'
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
id: 'general',
|
|
1543
|
+
label: 'General'
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
id: 'archived',
|
|
1547
|
+
label: 'Archived'
|
|
1548
|
+
}
|
|
1549
|
+
], ...(ngDevMode ? [{ debugName: "notificationsBars" }] : []));
|
|
1550
|
+
notifications = signal([
|
|
1551
|
+
{
|
|
1552
|
+
id: 'inbox',
|
|
1553
|
+
data: [
|
|
1554
|
+
{
|
|
1555
|
+
image: 'demo/images/avatar/avatar-square-m-2.jpg',
|
|
1556
|
+
name: 'Michael Lee',
|
|
1557
|
+
description: 'You have a new message from the support team regarding your recent inquiry.',
|
|
1558
|
+
time: '1 hour ago',
|
|
1559
|
+
new: true
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
image: 'demo/images/avatar/avatar-square-f-1.jpg',
|
|
1563
|
+
name: 'Alice Johnson',
|
|
1564
|
+
description: 'Your report has been successfully submitted and is under review.',
|
|
1565
|
+
time: '10 minutes ago',
|
|
1566
|
+
new: true
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
image: 'demo/images/avatar/avatar-square-f-2.jpg',
|
|
1570
|
+
name: 'Emily Davis',
|
|
1571
|
+
description: 'The project deadline has been updated to September 30th. Please check the details.',
|
|
1572
|
+
time: 'Yesterday at 4:35 PM',
|
|
1573
|
+
new: false
|
|
1574
|
+
}
|
|
1575
|
+
]
|
|
1576
|
+
},
|
|
1577
|
+
{
|
|
1578
|
+
id: 'general',
|
|
1579
|
+
data: [
|
|
1580
|
+
{
|
|
1581
|
+
image: 'demo/images/avatar/avatar-square-f-1.jpg',
|
|
1582
|
+
name: 'Alice Johnson',
|
|
1583
|
+
description: 'Reminder: Your subscription is about to expire in 3 days. Renew now to avoid interruption.',
|
|
1584
|
+
time: '30 minutes ago',
|
|
1585
|
+
new: true
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
image: 'demo/images/avatar/avatar-square-m-2.jpg',
|
|
1589
|
+
name: 'Michael Lee',
|
|
1590
|
+
description: 'The server maintenance has been completed successfully. No further downtime is expected.',
|
|
1591
|
+
time: 'Yesterday at 2:15 PM',
|
|
1592
|
+
new: false
|
|
1593
|
+
}
|
|
1594
|
+
]
|
|
1595
|
+
},
|
|
1596
|
+
{
|
|
1597
|
+
id: 'archived',
|
|
1598
|
+
data: [
|
|
1599
|
+
{
|
|
1600
|
+
image: 'demo/images/avatar/avatar-square-m-1.jpg',
|
|
1601
|
+
name: 'Lucas Brown',
|
|
1602
|
+
description: 'Your appointment with Dr. Anderson has been confirmed for October 12th at 10:00 AM.',
|
|
1603
|
+
time: '1 week ago',
|
|
1604
|
+
new: true
|
|
1605
|
+
},
|
|
1606
|
+
{
|
|
1607
|
+
image: 'demo/images/avatar/avatar-square-f-2.jpg',
|
|
1608
|
+
name: 'Emily Davis',
|
|
1609
|
+
description: 'The document you uploaded has been successfully archived for future reference.',
|
|
1610
|
+
time: '2 weeks ago',
|
|
1611
|
+
new: false
|
|
1612
|
+
}
|
|
1613
|
+
]
|
|
1614
|
+
}
|
|
1615
|
+
], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
|
|
1616
|
+
languages = signal([
|
|
1617
|
+
{ code: 'en', label: 'English', flag: '🇬🇧' },
|
|
1618
|
+
{ code: 'fr', label: 'French', flag: '🇫🇷' },
|
|
1619
|
+
{ code: 'es', label: 'Spanish', flag: '🇪🇸' }
|
|
1620
|
+
], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
1621
|
+
selectedLanguage = signal('en', ...(ngDevMode ? [{ debugName: "selectedLanguage" }] : []));
|
|
1622
|
+
selectedNotificationBar = model(this.notificationsBars()[0].id ?? 'inbox', ...(ngDevMode ? [{ debugName: "selectedNotificationBar" }] : []));
|
|
1623
|
+
selectedNotificationsBarData = computed(() => this.notifications().find((f) => f.id === this.selectedNotificationBar()).data, ...(ngDevMode ? [{ debugName: "selectedNotificationsBarData" }] : []));
|
|
1624
|
+
onMenuButtonClick() {
|
|
1625
|
+
this.layoutService.toggleMenu();
|
|
1626
|
+
}
|
|
1627
|
+
toggleSidebarPin() {
|
|
1628
|
+
this.layoutService.toggleSidebarPin();
|
|
1629
|
+
}
|
|
1630
|
+
toggleDarkMode() {
|
|
1631
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1632
|
+
...state,
|
|
1633
|
+
darkTheme: !state.darkTheme
|
|
1634
|
+
}));
|
|
1635
|
+
}
|
|
1636
|
+
showRightMenu() {
|
|
1637
|
+
this.layoutService.toggleRightMenu();
|
|
1638
|
+
}
|
|
1639
|
+
onConfigButtonClick() {
|
|
1640
|
+
this.layoutService.toggleConfigSidebar();
|
|
1641
|
+
}
|
|
1642
|
+
selectLanguage(code) {
|
|
1643
|
+
this.selectedLanguage.set(code);
|
|
1644
|
+
}
|
|
1645
|
+
toggleProfileMenu(event) {
|
|
1646
|
+
event.stopPropagation();
|
|
1647
|
+
this.profileMenuOpen.update((open) => !open);
|
|
1648
|
+
}
|
|
1649
|
+
onDocumentClick(event) {
|
|
1650
|
+
if (!this.profileMenuOpen())
|
|
1651
|
+
return;
|
|
1652
|
+
const target = event.target;
|
|
1653
|
+
const insideProfile = this.profileItem?.nativeElement?.contains(target);
|
|
1654
|
+
if (!insideProfile) {
|
|
1655
|
+
this.profileMenuOpen.set(false);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
openSearch() {
|
|
1659
|
+
this.searchActive.set(true);
|
|
1660
|
+
this.shouldFocusSearch = true;
|
|
1661
|
+
}
|
|
1662
|
+
closeSearch() {
|
|
1663
|
+
this.searchActive.set(false);
|
|
1664
|
+
}
|
|
1665
|
+
ngAfterViewChecked() {
|
|
1666
|
+
if (this.shouldFocusSearch && this.searchInput) {
|
|
1667
|
+
this.searchInput.nativeElement.focus();
|
|
1668
|
+
this.shouldFocusSearch = false;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
toggleSearchBar() {
|
|
1672
|
+
this.layoutService.toggleSearchBar();
|
|
1673
|
+
}
|
|
1674
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1675
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: AppTopbar, isStandalone: true, selector: "[app-topbar]", inputs: { selectedNotificationBar: { classPropertyName: "selectedNotificationBar", publicName: "selectedNotificationBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedNotificationBar: "selectedNotificationBarChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "menuButton", first: true, predicate: ["menubutton"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "profileItem", first: true, predicate: ["profileItem"], descendants: true }, { propertyName: "profilePanel", first: true, predicate: ["profilePanel"], descendants: true }], ngImport: i0, template: `<div class="layout-topbar">
|
|
1676
|
+
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="onMenuButtonClick()">
|
|
1677
|
+
<i class="pi pi-bars"></i>
|
|
1678
|
+
</button>
|
|
1679
|
+
<div class="topbar-left">
|
|
1680
|
+
<button
|
|
1681
|
+
type="button"
|
|
1682
|
+
class="topbar-menu-toggle"
|
|
1683
|
+
[class.active]="isSidebarPinned()"
|
|
1684
|
+
[attr.aria-label]="isSidebarPinned() ? 'Collapse sidebar' : 'Expand sidebar'"
|
|
1685
|
+
(click)="toggleSidebarPin()"
|
|
1686
|
+
>
|
|
1687
|
+
<i class="pi pi-bars"></i>
|
|
1688
|
+
</button>
|
|
1689
|
+
<a class="topbar-logo" [routerLink]="['/']">
|
|
1690
|
+
<img [src]="desktopLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1691
|
+
</a>
|
|
1692
|
+
<span class="topbar-logo-separator"></span>
|
|
1693
|
+
<div app-breadcrumb></div>
|
|
1694
|
+
@if (searchActive()) {
|
|
1695
|
+
<div class="flex items-center gap-2 ml-auto">
|
|
1696
|
+
<p-iconfield class="w-48 sm:w-80">
|
|
1697
|
+
<p-inputicon styleClass="pi pi-search" />
|
|
1698
|
+
<input #searchInput type="text" pInputText placeholder="Search..." aria-label="Search" class="w-full !py-2 !text-sm" (keydown.escape)="closeSearch()" />
|
|
1699
|
+
</p-iconfield>
|
|
1700
|
+
<button type="button" class="flex items-center justify-center w-8 h-8 rounded-md cursor-pointer hover:bg-emphasis transition-colors" aria-label="Close search" (click)="closeSearch()">
|
|
1701
|
+
<i class="pi pi-times text-sm"></i>
|
|
1702
|
+
</button>
|
|
1703
|
+
</div>
|
|
1704
|
+
}
|
|
1705
|
+
</div>
|
|
1706
|
+
|
|
1707
|
+
<a class="mobile-logo" [routerLink]="['/landing']">
|
|
1708
|
+
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1709
|
+
</a>
|
|
1710
|
+
|
|
1711
|
+
<div class="topbar-right">
|
|
1712
|
+
<ul class="topbar-menu">
|
|
1713
|
+
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1714
|
+
<a class="right-sidebar-button" aria-label="Open search" (click)="openSearch()">
|
|
1715
|
+
<i class="pi pi-search"></i>
|
|
1716
|
+
</a>
|
|
1717
|
+
</li>
|
|
1718
|
+
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1719
|
+
<a
|
|
1720
|
+
class="right-sidebar-button"
|
|
1721
|
+
[attr.aria-label]="isDarkTheme() ? 'Switch to light mode' : 'Switch to dark mode'"
|
|
1722
|
+
(click)="toggleDarkMode()"
|
|
1723
|
+
>
|
|
1724
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1725
|
+
</a>
|
|
1726
|
+
</li>
|
|
1727
|
+
<li class="right-sidebar-item static sm:relative z-50">
|
|
1728
|
+
<a class="right-sidebar-button" aria-label="Notifications" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveActiveClass="animate-fadeout" leaveToClass="hidden" [hideOnOutsideClick]="true">
|
|
1729
|
+
<span class="w-2 h-2 rounded-full bg-red-500 absolute top-2 right-2.5"></span>
|
|
1730
|
+
<i class="pi pi-bell"></i>
|
|
1731
|
+
</a>
|
|
1732
|
+
<div
|
|
1733
|
+
class="list-none m-0 rounded-2xl border border-surface fixed sm:absolute bg-surface-0 dark:bg-surface-900 overflow-hidden hidden origin-top w-[calc(100vw-2rem)] sm:w-88 mt-2 z-50 top-auto left-4 sm:left-auto sm:right-0 shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
1734
|
+
>
|
|
1735
|
+
<div class="p-4 flex items-center justify-between border-b border-surface">
|
|
1736
|
+
<span class="label-small text-surface-950 dark:text-surface-0">Notifications</span>
|
|
1737
|
+
<button pRipple class="py-1 px-2 text-surface-950 dark:text-surface-0 label-x-small hover:bg-emphasis border border-surface rounded-lg shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05)] transition-all">Mark all as read</button>
|
|
1738
|
+
</div>
|
|
1739
|
+
<div class="flex items-center border-b border-surface">
|
|
1740
|
+
@for (item of notificationsBars(); track item.id; let i = $index) {
|
|
1741
|
+
<button
|
|
1742
|
+
[ngClass]="{ 'border-surface-950 dark:border-surface-0': selectedNotificationBar() === item.id, 'border-transparent': selectedNotificationBar() !== item.id }"
|
|
1743
|
+
class="px-3.5 py-2 inline-flex items-center border-b gap-2"
|
|
1744
|
+
(click)="selectedNotificationBar.set(item.id)"
|
|
1745
|
+
>
|
|
1746
|
+
<span [ngClass]="{ 'text-surface-950 dark:text-surface-0': selectedNotificationBar() === item.id }" class="label-small">{{ item.label }}</span>
|
|
1747
|
+
<p-badge *ngIf="item?.badge" [value]="item.badge" severity="success" size="small" class="rounded-md!" />
|
|
1748
|
+
</button>
|
|
1749
|
+
}
|
|
1750
|
+
</div>
|
|
1751
|
+
<ul class="flex flex-col divide-y divide-(--surface-border) max-h-80 overflow-auto">
|
|
1752
|
+
@for (item of selectedNotificationsBarData(); track item.name; let i = $index) {
|
|
1753
|
+
<li>
|
|
1754
|
+
<div class="flex items-center gap-3 px-4 sm:px-6 py-3.5 cursor-pointer hover:bg-emphasis transition-all">
|
|
1755
|
+
<p-overlay-badge value="" severity="danger" class="inline-flex">
|
|
1756
|
+
<p-avatar size="large">
|
|
1757
|
+
<img [src]="item.image" [alt]="item.name" class="rounded-lg" />
|
|
1758
|
+
</p-avatar>
|
|
1759
|
+
</p-overlay-badge>
|
|
1760
|
+
<div class="flex items-center gap-3">
|
|
1761
|
+
<div class="flex flex-col">
|
|
1762
|
+
<span class="label-small text-left text-surface-950 dark:text-surface-0">{{ item.name }}</span>
|
|
1763
|
+
<span class="label-xsmall text-left line-clamp-1">{{ item.description }}</span>
|
|
1764
|
+
<span class="label-xsmall text-left">{{ item.time }}</span>
|
|
1765
|
+
</div>
|
|
1766
|
+
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
1767
|
+
</div>
|
|
1768
|
+
</div>
|
|
1769
|
+
<span *ngIf="i !== notifications().length - 1"></span>
|
|
1770
|
+
</li>
|
|
1771
|
+
}
|
|
1772
|
+
</ul>
|
|
1773
|
+
</div>
|
|
1774
|
+
</li>
|
|
1775
|
+
<li class="right-sidebar-item static sm:relative">
|
|
1776
|
+
<a class="right-sidebar-button relative z-50" aria-label="Change language" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveActiveClass="animate-fadeout" leaveToClass="hidden" [hideOnOutsideClick]="true">
|
|
1777
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
1778
|
+
<path d="m5 8 6 6"/>
|
|
1779
|
+
<path d="m4 14 6-6 2-3"/>
|
|
1780
|
+
<path d="M2 5h12"/>
|
|
1781
|
+
<path d="M7 2h1"/>
|
|
1782
|
+
<path d="m22 22-5-10-5 10"/>
|
|
1783
|
+
<path d="M14 18h6"/>
|
|
1784
|
+
</svg>
|
|
1785
|
+
</a>
|
|
1786
|
+
<div
|
|
1787
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 hidden origin-top w-44 mt-2 right-4 sm:right-0 z-999 top-auto shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
1788
|
+
>
|
|
1789
|
+
<ul class="flex flex-col gap-1">
|
|
1790
|
+
@for (lang of languages(); track lang.code) {
|
|
1791
|
+
<li>
|
|
1792
|
+
<a
|
|
1793
|
+
class="label-small dark:text-surface-400 flex gap-2.5 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
1794
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
1795
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
1796
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
1797
|
+
(click)="selectLanguage(lang.code)"
|
|
1798
|
+
>
|
|
1799
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
1800
|
+
<span>{{ lang.label }}</span>
|
|
1801
|
+
</a>
|
|
1802
|
+
</li>
|
|
1803
|
+
}
|
|
1804
|
+
</ul>
|
|
1805
|
+
</div>
|
|
1806
|
+
</li>
|
|
1807
|
+
<li class="profile-item static sm:relative" #profileItem>
|
|
1808
|
+
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="toggleProfileMenu($event)">
|
|
1809
|
+
<p-avatar icon="pi pi-user" styleClass="w-10! h-10!" />
|
|
1810
|
+
</a>
|
|
1811
|
+
<div
|
|
1812
|
+
#profilePanel
|
|
1813
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-52 mt-2 right-4 sm:right-0 z-999 top-auto shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
1814
|
+
[class.hidden]="!profileMenuOpen()"
|
|
1815
|
+
[class.animate-scalein]="profileMenuOpen()"
|
|
1816
|
+
>
|
|
1817
|
+
<ul class="flex flex-col gap-1">
|
|
1818
|
+
<div class="mobile-profile-actions">
|
|
1819
|
+
<li>
|
|
1820
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false); openSearch()">
|
|
1821
|
+
<i class="pi pi-search"></i>
|
|
1822
|
+
<span>Search</span>
|
|
1823
|
+
</a>
|
|
1824
|
+
</li>
|
|
1825
|
+
<li>
|
|
1826
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false); toggleDarkMode()">
|
|
1827
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1828
|
+
<span>{{ isDarkTheme() ? 'Light Mode' : 'Dark Mode' }}</span>
|
|
1829
|
+
</a>
|
|
1830
|
+
</li>
|
|
1831
|
+
<li>
|
|
1832
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer relative" (click)="profileMenuOpen.set(false)">
|
|
1833
|
+
<i class="pi pi-bell"></i>
|
|
1834
|
+
<span>Notifications</span>
|
|
1835
|
+
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
1836
|
+
</a>
|
|
1837
|
+
</li>
|
|
1838
|
+
<li class="border-b border-surface pb-1 mb-1">
|
|
1839
|
+
<span class="label-xsmall px-2.5 py-1 text-surface-400">Language</span>
|
|
1840
|
+
@for (lang of languages(); track lang.code) {
|
|
1841
|
+
<a
|
|
1842
|
+
class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
1843
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
1844
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
1845
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
1846
|
+
(click)="profileMenuOpen.set(false); selectLanguage(lang.code)"
|
|
1847
|
+
>
|
|
1848
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
1849
|
+
<span>{{ lang.label }}</span>
|
|
1850
|
+
@if (selectedLanguage() === lang.code) {
|
|
1851
|
+
<i class="pi pi-check ml-auto text-xs"></i>
|
|
1852
|
+
}
|
|
1853
|
+
</a>
|
|
1854
|
+
}
|
|
1855
|
+
</li>
|
|
1856
|
+
</div>
|
|
1857
|
+
<li>
|
|
1858
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1859
|
+
<i class="pi pi-user"></i>
|
|
1860
|
+
<span>Profile</span>
|
|
1861
|
+
</a>
|
|
1862
|
+
</li>
|
|
1863
|
+
<li>
|
|
1864
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1865
|
+
<i class="pi pi-cog"></i>
|
|
1866
|
+
<span>Settings</span>
|
|
1867
|
+
</a>
|
|
1868
|
+
</li>
|
|
1869
|
+
<li>
|
|
1870
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1871
|
+
<i class="pi pi-calendar"></i>
|
|
1872
|
+
<span>Calendar</span>
|
|
1873
|
+
</a>
|
|
1874
|
+
</li>
|
|
1875
|
+
<li>
|
|
1876
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1877
|
+
<i class="pi pi-inbox"></i>
|
|
1878
|
+
<span>Inbox</span>
|
|
1879
|
+
</a>
|
|
1880
|
+
</li>
|
|
1881
|
+
<li class="border-t border-surface mt-1 pt-1">
|
|
1882
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
1883
|
+
<i class="pi pi-power-off"></i>
|
|
1884
|
+
<span>Log out</span>
|
|
1885
|
+
</a>
|
|
1886
|
+
</li>
|
|
1887
|
+
</ul>
|
|
1888
|
+
</div>
|
|
1889
|
+
</li>
|
|
1890
|
+
</ul>
|
|
1891
|
+
</div>
|
|
1892
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$4.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppBreadcrumb, selector: "[app-breadcrumb]" }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i5$2.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i6$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i4$2.Ripple, selector: "[pRipple]" }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i8.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: OverlayBadgeModule }, { kind: "component", type: i9.OverlayBadge, selector: "p-overlayBadge, p-overlay-badge, p-overlaybadge", inputs: ["styleClass", "style", "badgeSize", "severity", "value", "badgeDisabled", "size"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i10.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }] });
|
|
1893
|
+
}
|
|
1894
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppTopbar, decorators: [{
|
|
1895
|
+
type: Component,
|
|
1896
|
+
args: [{
|
|
1897
|
+
selector: '[app-topbar]',
|
|
1898
|
+
imports: [RouterModule, CommonModule, StyleClassModule, AppBreadcrumb, InputTextModule, ButtonModule, IconFieldModule, InputIconModule, RippleModule, BadgeModule, OverlayBadgeModule, AvatarModule],
|
|
1899
|
+
template: `<div class="layout-topbar">
|
|
1900
|
+
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="onMenuButtonClick()">
|
|
1901
|
+
<i class="pi pi-bars"></i>
|
|
1902
|
+
</button>
|
|
1903
|
+
<div class="topbar-left">
|
|
1904
|
+
<button
|
|
1905
|
+
type="button"
|
|
1906
|
+
class="topbar-menu-toggle"
|
|
1907
|
+
[class.active]="isSidebarPinned()"
|
|
1908
|
+
[attr.aria-label]="isSidebarPinned() ? 'Collapse sidebar' : 'Expand sidebar'"
|
|
1909
|
+
(click)="toggleSidebarPin()"
|
|
1910
|
+
>
|
|
1911
|
+
<i class="pi pi-bars"></i>
|
|
1912
|
+
</button>
|
|
1913
|
+
<a class="topbar-logo" [routerLink]="['/']">
|
|
1914
|
+
<img [src]="desktopLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1915
|
+
</a>
|
|
1916
|
+
<span class="topbar-logo-separator"></span>
|
|
1917
|
+
<div app-breadcrumb></div>
|
|
1918
|
+
@if (searchActive()) {
|
|
1919
|
+
<div class="flex items-center gap-2 ml-auto">
|
|
1920
|
+
<p-iconfield class="w-48 sm:w-80">
|
|
1921
|
+
<p-inputicon styleClass="pi pi-search" />
|
|
1922
|
+
<input #searchInput type="text" pInputText placeholder="Search..." aria-label="Search" class="w-full !py-2 !text-sm" (keydown.escape)="closeSearch()" />
|
|
1923
|
+
</p-iconfield>
|
|
1924
|
+
<button type="button" class="flex items-center justify-center w-8 h-8 rounded-md cursor-pointer hover:bg-emphasis transition-colors" aria-label="Close search" (click)="closeSearch()">
|
|
1925
|
+
<i class="pi pi-times text-sm"></i>
|
|
1926
|
+
</button>
|
|
1927
|
+
</div>
|
|
1928
|
+
}
|
|
1929
|
+
</div>
|
|
1930
|
+
|
|
1931
|
+
<a class="mobile-logo" [routerLink]="['/landing']">
|
|
1932
|
+
<img [src]="mobileLogo()" [attr.alt]="mobileLogoConfig.alt" />
|
|
1933
|
+
</a>
|
|
1934
|
+
|
|
1935
|
+
<div class="topbar-right">
|
|
1936
|
+
<ul class="topbar-menu">
|
|
1937
|
+
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1938
|
+
<a class="right-sidebar-button" aria-label="Open search" (click)="openSearch()">
|
|
1939
|
+
<i class="pi pi-search"></i>
|
|
1940
|
+
</a>
|
|
1941
|
+
</li>
|
|
1942
|
+
<li class="right-sidebar-item" [class.hidden]="searchActive()">
|
|
1943
|
+
<a
|
|
1944
|
+
class="right-sidebar-button"
|
|
1945
|
+
[attr.aria-label]="isDarkTheme() ? 'Switch to light mode' : 'Switch to dark mode'"
|
|
1946
|
+
(click)="toggleDarkMode()"
|
|
1947
|
+
>
|
|
1948
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
1949
|
+
</a>
|
|
1950
|
+
</li>
|
|
1951
|
+
<li class="right-sidebar-item static sm:relative z-50">
|
|
1952
|
+
<a class="right-sidebar-button" aria-label="Notifications" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveActiveClass="animate-fadeout" leaveToClass="hidden" [hideOnOutsideClick]="true">
|
|
1953
|
+
<span class="w-2 h-2 rounded-full bg-red-500 absolute top-2 right-2.5"></span>
|
|
1954
|
+
<i class="pi pi-bell"></i>
|
|
1955
|
+
</a>
|
|
1956
|
+
<div
|
|
1957
|
+
class="list-none m-0 rounded-2xl border border-surface fixed sm:absolute bg-surface-0 dark:bg-surface-900 overflow-hidden hidden origin-top w-[calc(100vw-2rem)] sm:w-88 mt-2 z-50 top-auto left-4 sm:left-auto sm:right-0 shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
1958
|
+
>
|
|
1959
|
+
<div class="p-4 flex items-center justify-between border-b border-surface">
|
|
1960
|
+
<span class="label-small text-surface-950 dark:text-surface-0">Notifications</span>
|
|
1961
|
+
<button pRipple class="py-1 px-2 text-surface-950 dark:text-surface-0 label-x-small hover:bg-emphasis border border-surface rounded-lg shadow-[0px_1px_2px_0px_rgba(18,18,23,0.05)] transition-all">Mark all as read</button>
|
|
1962
|
+
</div>
|
|
1963
|
+
<div class="flex items-center border-b border-surface">
|
|
1964
|
+
@for (item of notificationsBars(); track item.id; let i = $index) {
|
|
1965
|
+
<button
|
|
1966
|
+
[ngClass]="{ 'border-surface-950 dark:border-surface-0': selectedNotificationBar() === item.id, 'border-transparent': selectedNotificationBar() !== item.id }"
|
|
1967
|
+
class="px-3.5 py-2 inline-flex items-center border-b gap-2"
|
|
1968
|
+
(click)="selectedNotificationBar.set(item.id)"
|
|
1969
|
+
>
|
|
1970
|
+
<span [ngClass]="{ 'text-surface-950 dark:text-surface-0': selectedNotificationBar() === item.id }" class="label-small">{{ item.label }}</span>
|
|
1971
|
+
<p-badge *ngIf="item?.badge" [value]="item.badge" severity="success" size="small" class="rounded-md!" />
|
|
1972
|
+
</button>
|
|
1973
|
+
}
|
|
1974
|
+
</div>
|
|
1975
|
+
<ul class="flex flex-col divide-y divide-(--surface-border) max-h-80 overflow-auto">
|
|
1976
|
+
@for (item of selectedNotificationsBarData(); track item.name; let i = $index) {
|
|
1977
|
+
<li>
|
|
1978
|
+
<div class="flex items-center gap-3 px-4 sm:px-6 py-3.5 cursor-pointer hover:bg-emphasis transition-all">
|
|
1979
|
+
<p-overlay-badge value="" severity="danger" class="inline-flex">
|
|
1980
|
+
<p-avatar size="large">
|
|
1981
|
+
<img [src]="item.image" [alt]="item.name" class="rounded-lg" />
|
|
1982
|
+
</p-avatar>
|
|
1983
|
+
</p-overlay-badge>
|
|
1984
|
+
<div class="flex items-center gap-3">
|
|
1985
|
+
<div class="flex flex-col">
|
|
1986
|
+
<span class="label-small text-left text-surface-950 dark:text-surface-0">{{ item.name }}</span>
|
|
1987
|
+
<span class="label-xsmall text-left line-clamp-1">{{ item.description }}</span>
|
|
1988
|
+
<span class="label-xsmall text-left">{{ item.time }}</span>
|
|
1989
|
+
</div>
|
|
1990
|
+
<p-badge *ngIf="item.new" value="" severity="success" />
|
|
1991
|
+
</div>
|
|
1992
|
+
</div>
|
|
1993
|
+
<span *ngIf="i !== notifications().length - 1"></span>
|
|
1994
|
+
</li>
|
|
1995
|
+
}
|
|
1996
|
+
</ul>
|
|
1997
|
+
</div>
|
|
1998
|
+
</li>
|
|
1999
|
+
<li class="right-sidebar-item static sm:relative">
|
|
2000
|
+
<a class="right-sidebar-button relative z-50" aria-label="Change language" pStyleClass="@next" enterFromClass="hidden" enterActiveClass="animate-scalein" leaveActiveClass="animate-fadeout" leaveToClass="hidden" [hideOnOutsideClick]="true">
|
|
2001
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
2002
|
+
<path d="m5 8 6 6"/>
|
|
2003
|
+
<path d="m4 14 6-6 2-3"/>
|
|
2004
|
+
<path d="M2 5h12"/>
|
|
2005
|
+
<path d="M7 2h1"/>
|
|
2006
|
+
<path d="m22 22-5-10-5 10"/>
|
|
2007
|
+
<path d="M14 18h6"/>
|
|
2008
|
+
</svg>
|
|
2009
|
+
</a>
|
|
2010
|
+
<div
|
|
2011
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 hidden origin-top w-44 mt-2 right-4 sm:right-0 z-999 top-auto shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
2012
|
+
>
|
|
2013
|
+
<ul class="flex flex-col gap-1">
|
|
2014
|
+
@for (lang of languages(); track lang.code) {
|
|
2015
|
+
<li>
|
|
2016
|
+
<a
|
|
2017
|
+
class="label-small dark:text-surface-400 flex gap-2.5 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
2018
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
2019
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
2020
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
2021
|
+
(click)="selectLanguage(lang.code)"
|
|
2022
|
+
>
|
|
2023
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
2024
|
+
<span>{{ lang.label }}</span>
|
|
2025
|
+
</a>
|
|
2026
|
+
</li>
|
|
2027
|
+
}
|
|
2028
|
+
</ul>
|
|
2029
|
+
</div>
|
|
2030
|
+
</li>
|
|
2031
|
+
<li class="profile-item static sm:relative" #profileItem>
|
|
2032
|
+
<a class="right-sidebar-button relative z-50" aria-label="User profile menu" (click)="toggleProfileMenu($event)">
|
|
2033
|
+
<p-avatar icon="pi pi-user" styleClass="w-10! h-10!" />
|
|
2034
|
+
</a>
|
|
2035
|
+
<div
|
|
2036
|
+
#profilePanel
|
|
2037
|
+
class="list-none p-2 m-0 rounded-2xl border border-surface overflow-hidden fixed sm:absolute bg-surface-0 dark:bg-surface-900 origin-top w-52 mt-2 right-4 sm:right-0 z-999 top-auto shadow-[0px_56px_16px_0px_rgba(0,0,0,0.00),0px_36px_14px_0px_rgba(0,0,0,0.01),0px_20px_12px_0px_rgba(0,0,0,0.02),0px_9px_9px_0px_rgba(0,0,0,0.03),0px_2px_5px_0px_rgba(0,0,0,0.04)]"
|
|
2038
|
+
[class.hidden]="!profileMenuOpen()"
|
|
2039
|
+
[class.animate-scalein]="profileMenuOpen()"
|
|
2040
|
+
>
|
|
2041
|
+
<ul class="flex flex-col gap-1">
|
|
2042
|
+
<div class="mobile-profile-actions">
|
|
2043
|
+
<li>
|
|
2044
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false); openSearch()">
|
|
2045
|
+
<i class="pi pi-search"></i>
|
|
2046
|
+
<span>Search</span>
|
|
2047
|
+
</a>
|
|
2048
|
+
</li>
|
|
2049
|
+
<li>
|
|
2050
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false); toggleDarkMode()">
|
|
2051
|
+
<i [class]="isDarkTheme() ? 'pi pi-sun' : 'pi pi-moon'"></i>
|
|
2052
|
+
<span>{{ isDarkTheme() ? 'Light Mode' : 'Dark Mode' }}</span>
|
|
2053
|
+
</a>
|
|
2054
|
+
</li>
|
|
2055
|
+
<li>
|
|
2056
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer relative" (click)="profileMenuOpen.set(false)">
|
|
2057
|
+
<i class="pi pi-bell"></i>
|
|
2058
|
+
<span>Notifications</span>
|
|
2059
|
+
<span class="w-2 h-2 rounded-full bg-red-500 ml-auto"></span>
|
|
2060
|
+
</a>
|
|
2061
|
+
</li>
|
|
2062
|
+
<li class="border-b border-surface pb-1 mb-1">
|
|
2063
|
+
<span class="label-xsmall px-2.5 py-1 text-surface-400">Language</span>
|
|
2064
|
+
@for (lang of languages(); track lang.code) {
|
|
2065
|
+
<a
|
|
2066
|
+
class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer"
|
|
2067
|
+
[class.text-surface-950]="selectedLanguage() === lang.code"
|
|
2068
|
+
[class.dark:text-surface-0]="selectedLanguage() === lang.code"
|
|
2069
|
+
[class.font-semibold]="selectedLanguage() === lang.code"
|
|
2070
|
+
(click)="profileMenuOpen.set(false); selectLanguage(lang.code)"
|
|
2071
|
+
>
|
|
2072
|
+
<span class="text-lg">{{ lang.flag }}</span>
|
|
2073
|
+
<span>{{ lang.label }}</span>
|
|
2074
|
+
@if (selectedLanguage() === lang.code) {
|
|
2075
|
+
<i class="pi pi-check ml-auto text-xs"></i>
|
|
2076
|
+
}
|
|
2077
|
+
</a>
|
|
2078
|
+
}
|
|
2079
|
+
</li>
|
|
2080
|
+
</div>
|
|
2081
|
+
<li>
|
|
2082
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2083
|
+
<i class="pi pi-user"></i>
|
|
2084
|
+
<span>Profile</span>
|
|
2085
|
+
</a>
|
|
2086
|
+
</li>
|
|
2087
|
+
<li>
|
|
2088
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2089
|
+
<i class="pi pi-cog"></i>
|
|
2090
|
+
<span>Settings</span>
|
|
2091
|
+
</a>
|
|
2092
|
+
</li>
|
|
2093
|
+
<li>
|
|
2094
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2095
|
+
<i class="pi pi-calendar"></i>
|
|
2096
|
+
<span>Calendar</span>
|
|
2097
|
+
</a>
|
|
2098
|
+
</li>
|
|
2099
|
+
<li>
|
|
2100
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2101
|
+
<i class="pi pi-inbox"></i>
|
|
2102
|
+
<span>Inbox</span>
|
|
2103
|
+
</a>
|
|
2104
|
+
</li>
|
|
2105
|
+
<li class="border-t border-surface mt-1 pt-1">
|
|
2106
|
+
<a class="label-small dark:text-surface-400 flex gap-2 py-2 px-2.5 rounded-lg items-center hover:bg-emphasis transition-colors duration-150 cursor-pointer" (click)="profileMenuOpen.set(false)">
|
|
2107
|
+
<i class="pi pi-power-off"></i>
|
|
2108
|
+
<span>Log out</span>
|
|
2109
|
+
</a>
|
|
2110
|
+
</li>
|
|
2111
|
+
</ul>
|
|
2112
|
+
</div>
|
|
2113
|
+
</li>
|
|
2114
|
+
</ul>
|
|
2115
|
+
</div>
|
|
2116
|
+
</div>`
|
|
2117
|
+
}]
|
|
2118
|
+
}], propDecorators: { menuButton: [{
|
|
2119
|
+
type: ViewChild,
|
|
2120
|
+
args: ['menubutton']
|
|
2121
|
+
}], searchInput: [{
|
|
2122
|
+
type: ViewChild,
|
|
2123
|
+
args: ['searchInput']
|
|
2124
|
+
}], profileItem: [{
|
|
2125
|
+
type: ViewChild,
|
|
2126
|
+
args: ['profileItem']
|
|
2127
|
+
}], profilePanel: [{
|
|
2128
|
+
type: ViewChild,
|
|
2129
|
+
args: ['profilePanel']
|
|
2130
|
+
}], selectedNotificationBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedNotificationBar", required: false }] }, { type: i0.Output, args: ["selectedNotificationBarChange"] }], onDocumentClick: [{
|
|
2131
|
+
type: HostListener,
|
|
2132
|
+
args: ['document:click', ['$event']]
|
|
2133
|
+
}] } });
|
|
2134
|
+
|
|
2135
|
+
const BREAKPOINT = 992;
|
|
2136
|
+
class AppSidebar {
|
|
2137
|
+
layoutService = inject(LayoutService);
|
|
2138
|
+
router = inject(Router);
|
|
2139
|
+
el = inject(ElementRef);
|
|
2140
|
+
menuContainer;
|
|
2141
|
+
sidebarRef;
|
|
2142
|
+
timeout = null;
|
|
2143
|
+
observer = null;
|
|
2144
|
+
outsideClickListener = null;
|
|
2145
|
+
mediaQuery = window.matchMedia(`(min-width: ${BREAKPOINT}px)`);
|
|
2146
|
+
destroy$ = new Subject();
|
|
2147
|
+
isHorizontal = computed(() => this.layoutService.isHorizontal(), ...(ngDevMode ? [{ debugName: "isHorizontal" }] : []));
|
|
2148
|
+
constructor() {
|
|
2149
|
+
effect(() => {
|
|
2150
|
+
const hasOpenOverlay = this.layoutService.hasOpenOverlay();
|
|
2151
|
+
const mobileMenuActive = this.layoutService.layoutState().mobileMenuActive;
|
|
2152
|
+
if (this.layoutService.isDesktop()) {
|
|
2153
|
+
if (hasOpenOverlay) {
|
|
2154
|
+
this.bindOutsideClickListener();
|
|
2155
|
+
}
|
|
2156
|
+
else {
|
|
2157
|
+
this.unbindOutsideClickListener();
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
else {
|
|
2161
|
+
if (mobileMenuActive) {
|
|
2162
|
+
this.bindOutsideClickListener();
|
|
2163
|
+
}
|
|
2164
|
+
else {
|
|
2165
|
+
this.unbindOutsideClickListener();
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
});
|
|
2169
|
+
effect(() => {
|
|
2170
|
+
const hasOpenOverlaySubmenu = this.layoutService.hasOpenOverlaySubmenu();
|
|
2171
|
+
if (this.layoutService.isDesktop()) {
|
|
2172
|
+
if (hasOpenOverlaySubmenu) {
|
|
2173
|
+
setTimeout(() => this.setupIntersectionObserver());
|
|
2174
|
+
}
|
|
2175
|
+
else {
|
|
2176
|
+
this.unbindObserver();
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
ngOnInit() {
|
|
2182
|
+
this.router.events
|
|
2183
|
+
.pipe(filter((event) => event instanceof NavigationEnd), takeUntil(this.destroy$))
|
|
2184
|
+
.subscribe((event) => {
|
|
2185
|
+
const navEvent = event;
|
|
2186
|
+
this.onRouteChange(navEvent.urlAfterRedirects);
|
|
2187
|
+
});
|
|
2188
|
+
this.onRouteChange(this.router.url);
|
|
2189
|
+
this.mediaQuery.addEventListener('change', this.screenChangeListener);
|
|
2190
|
+
}
|
|
2191
|
+
ngOnDestroy() {
|
|
2192
|
+
this.destroy$.next();
|
|
2193
|
+
this.destroy$.complete();
|
|
2194
|
+
this.unbindOutsideClickListener();
|
|
2195
|
+
this.unbindObserver();
|
|
2196
|
+
this.mediaQuery.removeEventListener('change', this.screenChangeListener);
|
|
2197
|
+
}
|
|
2198
|
+
onRouteChange(path) {
|
|
2199
|
+
this.layoutService.currentUrl.set(path);
|
|
2200
|
+
let newActivePath;
|
|
2201
|
+
if (this.layoutService.hasOverlaySubmenu() && this.layoutService.isDesktop()) {
|
|
2202
|
+
newActivePath = null;
|
|
2203
|
+
}
|
|
2204
|
+
else {
|
|
2205
|
+
newActivePath = path;
|
|
2206
|
+
}
|
|
2207
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2208
|
+
...val,
|
|
2209
|
+
activePath: newActivePath,
|
|
2210
|
+
overlayMenuActive: false,
|
|
2211
|
+
staticMenuMobileActive: false,
|
|
2212
|
+
menuHoverActive: false
|
|
2213
|
+
}));
|
|
2214
|
+
}
|
|
2215
|
+
screenChangeListener = () => {
|
|
2216
|
+
if (this.layoutService.hasOverlaySubmenu()) {
|
|
2217
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2218
|
+
...val,
|
|
2219
|
+
activePath: this.layoutService.isDesktop() ? null : this.router.url,
|
|
2220
|
+
menuHoverActive: false
|
|
2221
|
+
}));
|
|
2222
|
+
this.unbindOutsideClickListener();
|
|
2223
|
+
this.unbindObserver();
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
bindOutsideClickListener() {
|
|
2227
|
+
if (!this.outsideClickListener) {
|
|
2228
|
+
this.outsideClickListener = (event) => {
|
|
2229
|
+
if (this.isOutsideClicked(event)) {
|
|
2230
|
+
if (this.layoutService.isDesktop()) {
|
|
2231
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2232
|
+
...val,
|
|
2233
|
+
overlayMenuActive: false
|
|
2234
|
+
}));
|
|
2235
|
+
if (this.layoutService.hasOverlaySubmenu()) {
|
|
2236
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2237
|
+
...val,
|
|
2238
|
+
activePath: null,
|
|
2239
|
+
menuHoverActive: false
|
|
2240
|
+
}));
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
else {
|
|
2244
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2245
|
+
...val,
|
|
2246
|
+
mobileMenuActive: false
|
|
2247
|
+
}));
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
document.addEventListener('click', this.outsideClickListener);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
unbindOutsideClickListener() {
|
|
2255
|
+
if (this.outsideClickListener) {
|
|
2256
|
+
document.removeEventListener('click', this.outsideClickListener);
|
|
2257
|
+
this.outsideClickListener = null;
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
isOutsideClicked(event) {
|
|
2261
|
+
const topbarButtonEl = document.querySelector('.mobile-menu-button');
|
|
2262
|
+
const sidebarEl = this.el.nativeElement;
|
|
2263
|
+
return !(sidebarEl?.isSameNode(event.target) ||
|
|
2264
|
+
sidebarEl?.contains(event.target) ||
|
|
2265
|
+
topbarButtonEl?.isSameNode(event.target) ||
|
|
2266
|
+
topbarButtonEl?.contains(event.target));
|
|
2267
|
+
}
|
|
2268
|
+
onMouseEnter() { }
|
|
2269
|
+
onMouseLeave() {
|
|
2270
|
+
if (!this.layoutService.isDesktop() || !this.layoutService.isRail())
|
|
2271
|
+
return;
|
|
2272
|
+
if (this.layoutService.layoutState().sidebarPinned)
|
|
2273
|
+
return;
|
|
2274
|
+
if (this.timeout)
|
|
2275
|
+
clearTimeout(this.timeout);
|
|
2276
|
+
this.timeout = setTimeout(() => {
|
|
2277
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2278
|
+
...val,
|
|
2279
|
+
sidebarExpanded: false
|
|
2280
|
+
}));
|
|
2281
|
+
}, 300);
|
|
2282
|
+
}
|
|
2283
|
+
onAnchorToggle() {
|
|
2284
|
+
this.layoutService.layoutState.update((state) => ({
|
|
2285
|
+
...state,
|
|
2286
|
+
anchored: !state.anchored
|
|
2287
|
+
}));
|
|
2288
|
+
}
|
|
2289
|
+
onMenuScroll() {
|
|
2290
|
+
if (this.menuContainer?.nativeElement) {
|
|
2291
|
+
if (this.layoutService.isHorizontal()) {
|
|
2292
|
+
const scrollLeft = this.menuContainer.nativeElement.scrollLeft;
|
|
2293
|
+
this.menuContainer.nativeElement.style.setProperty('--menu-scroll-x', `-${scrollLeft}px`);
|
|
2294
|
+
}
|
|
2295
|
+
else {
|
|
2296
|
+
const scrollTop = this.menuContainer.nativeElement.scrollTop;
|
|
2297
|
+
this.menuContainer.nativeElement.style.setProperty('--menu-scroll-y', `-${scrollTop}px`);
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
if (this.layoutService.hasOverlaySubmenu() && this.layoutService.isDesktop()) {
|
|
2301
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2302
|
+
...val,
|
|
2303
|
+
activePath: null,
|
|
2304
|
+
menuHoverActive: false
|
|
2305
|
+
}));
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
setupIntersectionObserver() {
|
|
2309
|
+
if (!this.menuContainer?.nativeElement)
|
|
2310
|
+
return;
|
|
2311
|
+
if (this.observer) {
|
|
2312
|
+
this.observer.disconnect();
|
|
2313
|
+
}
|
|
2314
|
+
const activeMenuItem = this.menuContainer.nativeElement.querySelector('.layout-root-menuitem.active-menuitem');
|
|
2315
|
+
if (!activeMenuItem)
|
|
2316
|
+
return;
|
|
2317
|
+
this.observer = new IntersectionObserver((entries) => {
|
|
2318
|
+
entries.forEach((entry) => {
|
|
2319
|
+
if (this.layoutService.isDesktop() &&
|
|
2320
|
+
!entry.isIntersecting &&
|
|
2321
|
+
this.layoutService.hasOverlaySubmenu() &&
|
|
2322
|
+
this.layoutService.layoutState().activePath) {
|
|
2323
|
+
this.layoutService.layoutState.update((val) => ({
|
|
2324
|
+
...val,
|
|
2325
|
+
activePath: null
|
|
2326
|
+
}));
|
|
2327
|
+
}
|
|
2328
|
+
});
|
|
2329
|
+
}, {
|
|
2330
|
+
root: this.menuContainer.nativeElement,
|
|
2331
|
+
threshold: 0
|
|
2332
|
+
});
|
|
2333
|
+
this.observer.observe(activeMenuItem);
|
|
2334
|
+
}
|
|
2335
|
+
unbindObserver() {
|
|
2336
|
+
if (this.observer) {
|
|
2337
|
+
this.observer.disconnect();
|
|
2338
|
+
this.observer = null;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2342
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppSidebar, isStandalone: true, selector: "[app-sidebar]", viewQueries: [{ propertyName: "menuContainer", first: true, predicate: ["menuContainer"], descendants: true }, { propertyName: "sidebarRef", first: true, predicate: ["sidebarRef"], descendants: true }], ngImport: i0, template: `<nav class="layout-sidebar" aria-label="Main navigation" (mouseleave)="onMouseLeave()">
|
|
2343
|
+
<div #menuContainer class="layout-menu-container" (scroll)="onMenuScroll()">
|
|
2344
|
+
<div app-menu></div>
|
|
2345
|
+
</div>
|
|
2346
|
+
<div app-topbar *ngIf="isHorizontal()"></div>
|
|
2347
|
+
</nav>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AppMenu, selector: "[app-menu]" }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }] });
|
|
2348
|
+
}
|
|
2349
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppSidebar, decorators: [{
|
|
2350
|
+
type: Component,
|
|
2351
|
+
args: [{
|
|
2352
|
+
selector: '[app-sidebar]',
|
|
2353
|
+
imports: [CommonModule, AppMenu, RouterModule, AppTopbar],
|
|
2354
|
+
template: `<nav class="layout-sidebar" aria-label="Main navigation" (mouseleave)="onMouseLeave()">
|
|
2355
|
+
<div #menuContainer class="layout-menu-container" (scroll)="onMenuScroll()">
|
|
2356
|
+
<div app-menu></div>
|
|
2357
|
+
</div>
|
|
2358
|
+
<div app-topbar *ngIf="isHorizontal()"></div>
|
|
2359
|
+
</nav>`
|
|
2360
|
+
}]
|
|
2361
|
+
}], ctorParameters: () => [], propDecorators: { menuContainer: [{
|
|
2362
|
+
type: ViewChild,
|
|
2363
|
+
args: ['menuContainer']
|
|
2364
|
+
}], sidebarRef: [{
|
|
2365
|
+
type: ViewChild,
|
|
2366
|
+
args: ['sidebarRef']
|
|
2367
|
+
}] } });
|
|
2368
|
+
|
|
2369
|
+
class AppLayout {
|
|
2370
|
+
layoutService = inject(LayoutService);
|
|
2371
|
+
constructor() {
|
|
2372
|
+
effect(() => {
|
|
2373
|
+
const state = this.layoutService.layoutState();
|
|
2374
|
+
if (state.mobileMenuActive) {
|
|
2375
|
+
document.body.classList.add('blocked-scroll');
|
|
2376
|
+
}
|
|
2377
|
+
else {
|
|
2378
|
+
document.body.classList.remove('blocked-scroll');
|
|
2379
|
+
}
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
containerClass = computed(() => {
|
|
2383
|
+
const layoutConfig = this.layoutService.layoutConfig();
|
|
2384
|
+
const layoutState = this.layoutService.layoutState();
|
|
2385
|
+
return {
|
|
2386
|
+
'layout-overlay': layoutConfig.menuMode === 'overlay',
|
|
2387
|
+
'layout-static': layoutConfig.menuMode === 'static',
|
|
2388
|
+
'layout-slim': layoutConfig.menuMode === 'slim',
|
|
2389
|
+
'layout-horizontal': layoutConfig.menuMode === 'horizontal',
|
|
2390
|
+
'layout-compact': layoutConfig.menuMode === 'compact',
|
|
2391
|
+
'layout-reveal': layoutConfig.menuMode === 'reveal',
|
|
2392
|
+
'layout-drawer': layoutConfig.menuMode === 'drawer',
|
|
2393
|
+
'layout-overlay-active': layoutState.overlayMenuActive,
|
|
2394
|
+
'layout-mobile-active': layoutState.mobileMenuActive,
|
|
2395
|
+
'layout-sidebar-expanded': layoutState.sidebarExpanded,
|
|
2396
|
+
'layout-sidebar-rail': !layoutState.sidebarPinned && layoutConfig.menuMode === 'static',
|
|
2397
|
+
'layout-sidebar-anchored': layoutState.anchored,
|
|
2398
|
+
[`layout-card-${layoutConfig.cardStyle}`]: true,
|
|
2399
|
+
[`layout-sidebar-${layoutConfig.menuTheme}`]: true
|
|
2400
|
+
};
|
|
2401
|
+
}, ...(ngDevMode ? [{ debugName: "containerClass" }] : []));
|
|
2402
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2403
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AppLayout, isStandalone: true, selector: "app-layout", ngImport: i0, template: `<div class="layout-wrapper" [ngClass]="containerClass()">
|
|
2404
|
+
<div app-topbar></div>
|
|
2405
|
+
<div class="layout-body">
|
|
2406
|
+
<div app-sidebar></div>
|
|
2407
|
+
<div class="layout-content-wrapper">
|
|
2408
|
+
<div class="layout-content-wrapper-inside">
|
|
2409
|
+
<main class="layout-content">
|
|
2410
|
+
<div app-breadcrumb></div>
|
|
2411
|
+
<router-outlet></router-outlet>
|
|
2412
|
+
</main>
|
|
2413
|
+
<div app-footer></div>
|
|
2414
|
+
</div>
|
|
2415
|
+
</div>
|
|
2416
|
+
</div>
|
|
2417
|
+
<app-configurator />
|
|
2418
|
+
<div app-search></div>
|
|
2419
|
+
<div app-rightmenu></div>
|
|
2420
|
+
<div class="layout-mask"></div>
|
|
2421
|
+
</div> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "[app-topbar]", inputs: ["selectedNotificationBar"], outputs: ["selectedNotificationBarChange"] }, { kind: "component", type: AppSidebar, selector: "[app-sidebar]" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator", inputs: ["simple", "location", "cardStyle"], outputs: ["cardStyleChange"] }, { kind: "component", type: AppBreadcrumb, selector: "[app-breadcrumb]" }, { kind: "component", type: AppFooter, selector: "[app-footer]" }, { kind: "component", type: AppSearch, selector: "[app-search]" }, { kind: "component", type: AppRightMenu, selector: "[app-rightmenu]" }] });
|
|
2422
|
+
}
|
|
2423
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AppLayout, decorators: [{
|
|
2424
|
+
type: Component,
|
|
2425
|
+
args: [{
|
|
2426
|
+
selector: 'app-layout',
|
|
2427
|
+
imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppConfigurator, AppBreadcrumb, AppFooter, AppSearch, AppRightMenu],
|
|
2428
|
+
template: `<div class="layout-wrapper" [ngClass]="containerClass()">
|
|
2429
|
+
<div app-topbar></div>
|
|
2430
|
+
<div class="layout-body">
|
|
2431
|
+
<div app-sidebar></div>
|
|
2432
|
+
<div class="layout-content-wrapper">
|
|
2433
|
+
<div class="layout-content-wrapper-inside">
|
|
2434
|
+
<main class="layout-content">
|
|
2435
|
+
<div app-breadcrumb></div>
|
|
2436
|
+
<router-outlet></router-outlet>
|
|
2437
|
+
</main>
|
|
2438
|
+
<div app-footer></div>
|
|
2439
|
+
</div>
|
|
2440
|
+
</div>
|
|
2441
|
+
</div>
|
|
2442
|
+
<app-configurator />
|
|
2443
|
+
<div app-search></div>
|
|
2444
|
+
<div app-rightmenu></div>
|
|
2445
|
+
<div class="layout-mask"></div>
|
|
2446
|
+
</div> `
|
|
2447
|
+
}]
|
|
2448
|
+
}], ctorParameters: () => [] });
|
|
2449
|
+
|
|
2450
|
+
class AuthLayout {
|
|
2451
|
+
layoutService = inject(LayoutService);
|
|
2452
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AuthLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2453
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AuthLayout, isStandalone: true, selector: "auth-layout", ngImport: i0, template: `
|
|
2454
|
+
<main>
|
|
2455
|
+
<router-outlet></router-outlet>
|
|
2456
|
+
</main>
|
|
2457
|
+
<button class="layout-config-button config-link" (click)="layoutService.toggleConfigSidebar()">
|
|
2458
|
+
<i class="pi pi-cog"></i>
|
|
2459
|
+
</button>
|
|
2460
|
+
<app-configurator location="landing" />
|
|
2461
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AppConfigurator, selector: "app-configurator", inputs: ["simple", "location", "cardStyle"], outputs: ["cardStyleChange"] }] });
|
|
2462
|
+
}
|
|
2463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AuthLayout, decorators: [{
|
|
2464
|
+
type: Component,
|
|
2465
|
+
args: [{
|
|
2466
|
+
selector: 'auth-layout',
|
|
2467
|
+
imports: [RouterModule, AppConfigurator],
|
|
2468
|
+
template: `
|
|
2469
|
+
<main>
|
|
2470
|
+
<router-outlet></router-outlet>
|
|
2471
|
+
</main>
|
|
2472
|
+
<button class="layout-config-button config-link" (click)="layoutService.toggleConfigSidebar()">
|
|
2473
|
+
<i class="pi pi-cog"></i>
|
|
2474
|
+
</button>
|
|
2475
|
+
<app-configurator location="landing" />
|
|
2476
|
+
`
|
|
2477
|
+
}]
|
|
2478
|
+
}] });
|
|
2479
|
+
|
|
2480
|
+
let aiCardBgFilterId = 0;
|
|
2481
|
+
/**
|
|
2482
|
+
* Animated brand-tinted background for AI insight cards: shifting host background
|
|
2483
|
+
* plus soft blurred SVG blobs with staggered fill animation.
|
|
2484
|
+
*
|
|
2485
|
+
* Project card content with `<ng-content />` so it stacks above the SVG layer.
|
|
2486
|
+
*/
|
|
2487
|
+
class AiCardBgComponent {
|
|
2488
|
+
blurFilterId = `uxAiBlur_${++aiCardBgFilterId}`;
|
|
2489
|
+
get blurFilterUrl() {
|
|
2490
|
+
return `url(#${this.blurFilterId})`;
|
|
2491
|
+
}
|
|
2492
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AiCardBgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2493
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.8", type: AiCardBgComponent, isStandalone: true, selector: "ux-ai-card-bg", host: { properties: { "attr.data-ai-bg": "true" }, classAttribute: "ux-ai-card-bg block box-border" }, ngImport: i0, template: `
|
|
2494
|
+
<svg
|
|
2495
|
+
class="ux-ai-card-bg__svg"
|
|
2496
|
+
viewBox="0 0 400 300"
|
|
2497
|
+
fill="none"
|
|
2498
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
2499
|
+
aria-hidden="true"
|
|
2500
|
+
>
|
|
2501
|
+
<defs>
|
|
2502
|
+
<filter [attr.id]="blurFilterId" x="-50%" y="-50%" width="200%" height="200%">
|
|
2503
|
+
<feGaussianBlur stdDeviation="30" />
|
|
2504
|
+
</filter>
|
|
2505
|
+
</defs>
|
|
2506
|
+
<ellipse
|
|
2507
|
+
class="ux-ai-fg ux-ai-fg--1"
|
|
2508
|
+
cx="60"
|
|
2509
|
+
cy="50"
|
|
2510
|
+
rx="120"
|
|
2511
|
+
ry="100"
|
|
2512
|
+
opacity="0.35"
|
|
2513
|
+
[attr.filter]="blurFilterUrl"
|
|
2514
|
+
/>
|
|
2515
|
+
<ellipse
|
|
2516
|
+
class="ux-ai-fg ux-ai-fg--2"
|
|
2517
|
+
cx="320"
|
|
2518
|
+
cy="80"
|
|
2519
|
+
rx="100"
|
|
2520
|
+
ry="80"
|
|
2521
|
+
opacity="0.3"
|
|
2522
|
+
[attr.filter]="blurFilterUrl"
|
|
2523
|
+
/>
|
|
2524
|
+
<ellipse
|
|
2525
|
+
class="ux-ai-fg ux-ai-fg--3"
|
|
2526
|
+
cx="200"
|
|
2527
|
+
cy="240"
|
|
2528
|
+
rx="140"
|
|
2529
|
+
ry="90"
|
|
2530
|
+
opacity="0.25"
|
|
2531
|
+
[attr.filter]="blurFilterUrl"
|
|
2532
|
+
/>
|
|
2533
|
+
</svg>
|
|
2534
|
+
<ng-content />
|
|
2535
|
+
`, isInline: true, styles: [":host{--ux-ai-bg-from: #cce5ff;--ux-ai-bg-to:rgb(255, 236, 254);--ux-ai-fg-from:rgb(188, 214, 255);--ux-ai-fg-to:rgb(246, 216, 255);position:relative;overflow:hidden;isolation:isolate;contain:paint;animation:ux-ai-bg-move 5s ease-in-out infinite;will-change:background-color}:host-context([class*=\"app-dark\"]){--ux-ai-bg-from:rgb(0, 32, 69);--ux-ai-bg-to:rgb(47, 18, 116);--ux-ai-fg-from:rgb(0, 20, 47);--ux-ai-fg-to:rgb(76, 1, 71)}:host>:not(svg){position:relative;z-index:1}:host svg.ux-ai-card-bg__svg{position:absolute;inset:0;z-index:0;height:100%;width:100%;max-height:100%;overflow:hidden;pointer-events:none}.ux-ai-fg{will-change:fill;animation:ux-ai-fg-move 6s ease-in-out infinite}.ux-ai-fg--1{animation-delay:0s}.ux-ai-fg--2{animation-delay:2s}.ux-ai-fg--3{animation-delay:4s}@keyframes ux-ai-bg-move{0%,to{background-color:var(--ux-ai-bg-from)}50%{background-color:var(--ux-ai-bg-to)}}@keyframes ux-ai-fg-move{0%,to{fill:var(--ux-ai-fg-from)}50%{fill:var(--ux-ai-fg-to)}}@media(prefers-reduced-motion:reduce){:host{animation:none;background-color:var(--ux-ai-bg-from)}.ux-ai-fg{animation:none;fill:var(--ux-ai-fg-from)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2536
|
+
}
|
|
2537
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: AiCardBgComponent, decorators: [{
|
|
2538
|
+
type: Component,
|
|
2539
|
+
args: [{ selector: 'ux-ai-card-bg', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2540
|
+
class: 'ux-ai-card-bg block box-border',
|
|
2541
|
+
'[attr.data-ai-bg]': 'true'
|
|
2542
|
+
}, template: `
|
|
2543
|
+
<svg
|
|
2544
|
+
class="ux-ai-card-bg__svg"
|
|
2545
|
+
viewBox="0 0 400 300"
|
|
2546
|
+
fill="none"
|
|
2547
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
2548
|
+
aria-hidden="true"
|
|
2549
|
+
>
|
|
2550
|
+
<defs>
|
|
2551
|
+
<filter [attr.id]="blurFilterId" x="-50%" y="-50%" width="200%" height="200%">
|
|
2552
|
+
<feGaussianBlur stdDeviation="30" />
|
|
2553
|
+
</filter>
|
|
2554
|
+
</defs>
|
|
2555
|
+
<ellipse
|
|
2556
|
+
class="ux-ai-fg ux-ai-fg--1"
|
|
2557
|
+
cx="60"
|
|
2558
|
+
cy="50"
|
|
2559
|
+
rx="120"
|
|
2560
|
+
ry="100"
|
|
2561
|
+
opacity="0.35"
|
|
2562
|
+
[attr.filter]="blurFilterUrl"
|
|
2563
|
+
/>
|
|
2564
|
+
<ellipse
|
|
2565
|
+
class="ux-ai-fg ux-ai-fg--2"
|
|
2566
|
+
cx="320"
|
|
2567
|
+
cy="80"
|
|
2568
|
+
rx="100"
|
|
2569
|
+
ry="80"
|
|
2570
|
+
opacity="0.3"
|
|
2571
|
+
[attr.filter]="blurFilterUrl"
|
|
2572
|
+
/>
|
|
2573
|
+
<ellipse
|
|
2574
|
+
class="ux-ai-fg ux-ai-fg--3"
|
|
2575
|
+
cx="200"
|
|
2576
|
+
cy="240"
|
|
2577
|
+
rx="140"
|
|
2578
|
+
ry="90"
|
|
2579
|
+
opacity="0.25"
|
|
2580
|
+
[attr.filter]="blurFilterUrl"
|
|
2581
|
+
/>
|
|
2582
|
+
</svg>
|
|
2583
|
+
<ng-content />
|
|
2584
|
+
`, styles: [":host{--ux-ai-bg-from: #cce5ff;--ux-ai-bg-to:rgb(255, 236, 254);--ux-ai-fg-from:rgb(188, 214, 255);--ux-ai-fg-to:rgb(246, 216, 255);position:relative;overflow:hidden;isolation:isolate;contain:paint;animation:ux-ai-bg-move 5s ease-in-out infinite;will-change:background-color}:host-context([class*=\"app-dark\"]){--ux-ai-bg-from:rgb(0, 32, 69);--ux-ai-bg-to:rgb(47, 18, 116);--ux-ai-fg-from:rgb(0, 20, 47);--ux-ai-fg-to:rgb(76, 1, 71)}:host>:not(svg){position:relative;z-index:1}:host svg.ux-ai-card-bg__svg{position:absolute;inset:0;z-index:0;height:100%;width:100%;max-height:100%;overflow:hidden;pointer-events:none}.ux-ai-fg{will-change:fill;animation:ux-ai-fg-move 6s ease-in-out infinite}.ux-ai-fg--1{animation-delay:0s}.ux-ai-fg--2{animation-delay:2s}.ux-ai-fg--3{animation-delay:4s}@keyframes ux-ai-bg-move{0%,to{background-color:var(--ux-ai-bg-from)}50%{background-color:var(--ux-ai-bg-to)}}@keyframes ux-ai-fg-move{0%,to{fill:var(--ux-ai-fg-from)}50%{fill:var(--ux-ai-fg-to)}}@media(prefers-reduced-motion:reduce){:host{animation:none;background-color:var(--ux-ai-bg-from)}.ux-ai-fg{animation:none;fill:var(--ux-ai-fg-from)}}\n"] }]
|
|
2585
|
+
}] });
|
|
2586
|
+
|
|
2587
|
+
/*
|
|
2588
|
+
* Public API Surface of @unopsitg/ux
|
|
2589
|
+
*/
|
|
2590
|
+
|
|
2591
|
+
/**
|
|
2592
|
+
* Generated bundle index. Do not edit.
|
|
2593
|
+
*/
|
|
2594
|
+
|
|
2595
|
+
export { AiCardBgComponent, AppBreadcrumb, AppConfigurator, AppFooter, AppLayout, AppMenu, AppMenuitem, AppRightMenu, AppSearch, AppSidebar, AppTopbar, AuthLayout, BrandContrast, BrandCrisp, BrandSoft, LayoutService, MENU_MODEL, SIDEBAR_LOGO, TOPBAR_MOBILE_LOGO, brandPresets, brandPrimitives };
|
|
2596
|
+
//# sourceMappingURL=unopsitg-ux.mjs.map
|