@processpuzzle/auth 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,343 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Component, computed } from '@angular/core';
3
+ import { Router, ActivatedRoute, RouterLink } from '@angular/router';
4
+ import { MatSnackBar } from '@angular/material/snack-bar';
5
+ import { AUTHENTICATION_SERVICE, AUTHENTICATION_CONFIGURATION } from '@processpuzzle/auth/domain';
6
+ import * as i1 from '@angular/forms';
7
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
8
+ import { MatError, MatFormField, MatSuffix } from '@angular/material/form-field';
9
+ import { MatInput, MatLabel } from '@angular/material/input';
10
+ import * as i2 from '@angular/material/button';
11
+ import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button';
12
+ import * as i1$1 from '@angular/material/icon';
13
+ import { MatIcon, MatIconModule } from '@angular/material/icon';
14
+ import { MatDivider } from '@angular/material/divider';
15
+ import { TranslocoDirective, provideTranslocoScope } from '@jsverse/transloco';
16
+ import { NavigateBackService } from '@processpuzzle/widgets';
17
+ import { MatProgressBar } from '@angular/material/progress-bar';
18
+ import { MatDialogTitle, MatDialogContent, MatDialogActions } from '@angular/material/dialog';
19
+ import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
20
+ import { SubstringPipe } from '@processpuzzle/util';
21
+
22
+ const authGuard = async (route) => {
23
+ const authService = inject(AUTHENTICATION_SERVICE);
24
+ const isLoginRoute = route.routeConfig?.path === 'login';
25
+ const isLogoutRoute = route.routeConfig?.path === 'logout';
26
+ const router = inject(Router);
27
+ const snackBar = inject(MatSnackBar);
28
+ await authService.authenticate();
29
+ if (isLoginRoute) {
30
+ if (authService.isAuthenticated()) {
31
+ snackBar.open('You are already logged in', 'Close', { duration: 3000 });
32
+ await router.navigate(['/']);
33
+ return false;
34
+ }
35
+ else {
36
+ return true; // If not logged in, allow access to login page
37
+ }
38
+ }
39
+ else if (isLogoutRoute) {
40
+ if (authService.isAuthenticated()) {
41
+ return true; // If logged in, allow access to logout page
42
+ }
43
+ else {
44
+ snackBar.open('You are not already logged in', 'Close', { duration: 3000 });
45
+ await router.navigate(['/']);
46
+ return false;
47
+ }
48
+ }
49
+ else if (authService.isAuthenticated()) {
50
+ // For protected routes, check if user is logged in
51
+ return true;
52
+ }
53
+ else {
54
+ await router.navigate(['/auth/login']);
55
+ return false;
56
+ }
57
+ };
58
+
59
+ class LoginComponent {
60
+ errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
61
+ hidePassword = true;
62
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
63
+ loginForm;
64
+ authService = inject(AUTHENTICATION_SERVICE);
65
+ fb = inject(FormBuilder);
66
+ navigateBackService = inject(NavigateBackService);
67
+ route = inject(ActivatedRoute);
68
+ router = inject(Router);
69
+ // region public event handlers
70
+ ngOnInit() {
71
+ const user = this.route.snapshot.data['signedInUser'];
72
+ if (!user) {
73
+ this.loginForm = this.buildLoginForm();
74
+ }
75
+ }
76
+ async onSubmit() {
77
+ if (this.loginForm.invalid)
78
+ return;
79
+ this.errorMessage.set('');
80
+ this.isLoading.set(true);
81
+ try {
82
+ const { email, password } = this.loginForm.value;
83
+ await this.authService.login(this.navigateBackService.getRouteStack().pop(), email, password);
84
+ await this.router.navigate(['/']);
85
+ }
86
+ catch (error) {
87
+ const message = this.getErrorMessage(error.code || error.message || '');
88
+ this.errorMessage.set(message);
89
+ }
90
+ finally {
91
+ this.isLoading.set(false);
92
+ }
93
+ }
94
+ async signInWithGoogle() {
95
+ this.errorMessage.set('');
96
+ this.isLoading.set(true);
97
+ try {
98
+ // await signInWithPopup(this.authService, new GoogleAuthProvider());
99
+ await this.router.navigate(['/']);
100
+ }
101
+ catch (error) {
102
+ this.errorMessage.set(this.getErrorMessage(error.code || error.message || ''));
103
+ }
104
+ finally {
105
+ this.isLoading.set(false);
106
+ }
107
+ }
108
+ // endregion
109
+ // region protected, private helper methods
110
+ buildLoginForm() {
111
+ return this.fb.group({
112
+ email: ['', [Validators.required, Validators.email]],
113
+ password: ['', Validators.required],
114
+ });
115
+ }
116
+ getErrorMessage(errorCode) {
117
+ switch (errorCode) {
118
+ case 'auth/invalid-email':
119
+ return 'Invalid email address';
120
+ case 'auth/user-disabled':
121
+ return 'This account has been disabled';
122
+ case 'auth/user-not-found':
123
+ return 'No account found with this email';
124
+ case 'auth/wrong-password':
125
+ return 'Invalid password';
126
+ case 'auth/popup-closed-by-user':
127
+ return 'Sign-in popup was closed before completion';
128
+ default:
129
+ return 'An error occurred during sign in';
130
+ }
131
+ }
132
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
133
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LoginComponent, isStandalone: true, selector: "pp-login", providers: [], ngImport: i0, template: "<div class=\"login-container\">\n <ng-container *transloco=\"let t;\">\n <h2>{{t('auth.login_form.title')}}</h2>\n\n <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Login Form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" placeholder=\"Enter your email\">\n @if (loginForm.get('email')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.email_err_required')}}</mat-error>\n }\n @if (loginForm.get('email')?.hasError('email')) {\n <mat-error>{{t('auth.login_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\">\n <button mat-icon-button matSuffix type=\"button\" (click)=\"hidePassword = !hidePassword\" aria-label=\"Toggle Password Visibility\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (loginForm.get('password')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.password_err_required')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"actions\">\n <button mat-raised-button color=\"secondary\" routerLink=\"/auth/register\">{{t('auth.login_form.create_account_button')}}</button>\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"loginForm.invalid || isLoading()\">{{ isLoading() ? t('auth.login_form.signing_in_button') : t('auth.login_form.sign_in_button') }}</button>\n </div>\n </form>\n\n <mat-divider class=\"divider\">OR</mat-divider>\n\n <button mat-stroked-button (click)=\"signInWithGoogle()\" [disabled]=\"isLoading()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\">\n <path fill=\"#FFC107\" d=\"M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12\ts5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20\ts20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z\"/>\n <path fill=\"#FF3D00\" d=\"M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039\tl5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z\"/>\n <path fill=\"#4CAF50\" d=\"M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36\tc-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z\"/>\n <path fill=\"#1976D2\" d=\"M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571\tc0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z\"/>\n </svg>\n {{t('auth.login_form.google_button')}}\n </button>\n @if (errorMessage()) {\n <div class=\"error-message\">{{ errorMessage() }}</div>\n }\n </ng-container>\n</div>\n", styles: [".login-container{max-width:400px;margin:2rem auto;padding:2rem;border-radius:8px;box-shadow:0 2px 4px #0000001a}h2{text-align:center;margin-bottom:2rem}form{display:flex;flex-direction:column;gap:1rem}mat-form-field{width:100%}.actions{display:flex;justify-content:center;margin-top:1rem;gap:10px}.divider{margin:2rem 0;text-align:center}button[mat-stroked-button]{width:100%;margin-top:1rem;display:flex;align-items:center;justify-content:center;gap:.5rem}.google-icon{width:18px;height:18px}.error-message{color:red;text-align:center;margin-top:1rem}.mat-form-field-suffix{visibility:visible!important;opacity:1!important;display:flex!important}.mat-form-field-suffix button{z-index:10}\n"], dependencies: [{ kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }] });
134
+ }
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LoginComponent, decorators: [{
136
+ type: Component,
137
+ args: [{ selector: 'pp-login', imports: [MatButton, MatDivider, MatError, MatFormField, MatIcon, MatIconButton, MatInput, MatLabel, MatSuffix, ReactiveFormsModule, RouterLink, TranslocoDirective], providers: [], template: "<div class=\"login-container\">\n <ng-container *transloco=\"let t;\">\n <h2>{{t('auth.login_form.title')}}</h2>\n\n <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Login Form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" placeholder=\"Enter your email\">\n @if (loginForm.get('email')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.email_err_required')}}</mat-error>\n }\n @if (loginForm.get('email')?.hasError('email')) {\n <mat-error>{{t('auth.login_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\">\n <button mat-icon-button matSuffix type=\"button\" (click)=\"hidePassword = !hidePassword\" aria-label=\"Toggle Password Visibility\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (loginForm.get('password')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.password_err_required')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"actions\">\n <button mat-raised-button color=\"secondary\" routerLink=\"/auth/register\">{{t('auth.login_form.create_account_button')}}</button>\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"loginForm.invalid || isLoading()\">{{ isLoading() ? t('auth.login_form.signing_in_button') : t('auth.login_form.sign_in_button') }}</button>\n </div>\n </form>\n\n <mat-divider class=\"divider\">OR</mat-divider>\n\n <button mat-stroked-button (click)=\"signInWithGoogle()\" [disabled]=\"isLoading()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\">\n <path fill=\"#FFC107\" d=\"M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12\ts5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20\ts20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z\"/>\n <path fill=\"#FF3D00\" d=\"M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039\tl5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z\"/>\n <path fill=\"#4CAF50\" d=\"M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36\tc-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z\"/>\n <path fill=\"#1976D2\" d=\"M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571\tc0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z\"/>\n </svg>\n {{t('auth.login_form.google_button')}}\n </button>\n @if (errorMessage()) {\n <div class=\"error-message\">{{ errorMessage() }}</div>\n }\n </ng-container>\n</div>\n", styles: [".login-container{max-width:400px;margin:2rem auto;padding:2rem;border-radius:8px;box-shadow:0 2px 4px #0000001a}h2{text-align:center;margin-bottom:2rem}form{display:flex;flex-direction:column;gap:1rem}mat-form-field{width:100%}.actions{display:flex;justify-content:center;margin-top:1rem;gap:10px}.divider{margin:2rem 0;text-align:center}button[mat-stroked-button]{width:100%;margin-top:1rem;display:flex;align-items:center;justify-content:center;gap:.5rem}.google-icon{width:18px;height:18px}.error-message{color:red;text-align:center;margin-top:1rem}.mat-form-field-suffix{visibility:visible!important;opacity:1!important;display:flex!important}.mat-form-field-suffix button{z-index:10}\n"] }]
138
+ }] });
139
+
140
+ class MyProfileComponent {
141
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MyProfileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: MyProfileComponent, isStandalone: true, selector: "pp-my-profile", providers: [provideTranslocoScope('auth')], ngImport: i0, template: "<h1>My profile</h1>\n", styles: [""] });
143
+ }
144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MyProfileComponent, decorators: [{
145
+ type: Component,
146
+ args: [{ selector: 'pp-my-profile', imports: [], providers: [provideTranslocoScope('auth')], template: "<h1>My profile</h1>\n" }]
147
+ }] });
148
+
149
+ class RegistrationComponent {
150
+ authService = inject(AUTHENTICATION_SERVICE);
151
+ fb = inject(FormBuilder);
152
+ navigateBack = inject(NavigateBackService);
153
+ snackBar = inject(MatSnackBar);
154
+ registerForm;
155
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
156
+ errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
157
+ hidePassword = true;
158
+ hideConfirmPassword = true;
159
+ constructor() {
160
+ this.registerForm = this.fb.group({
161
+ email: ['', [Validators.required, Validators.email]],
162
+ password: ['', [Validators.required, Validators.minLength(6)]],
163
+ confirmPassword: ['', Validators.required],
164
+ }, {
165
+ validators: [this.passwordMatchValidator],
166
+ });
167
+ }
168
+ passwordMatchValidator() {
169
+ return (form) => {
170
+ const password = form.get('password')?.value;
171
+ const confirmPassword = form.get('confirmPassword')?.value;
172
+ if (password !== confirmPassword) {
173
+ return { passwordMismatch: true };
174
+ }
175
+ return null;
176
+ };
177
+ }
178
+ async onSubmit() {
179
+ if (this.registerForm.invalid)
180
+ return;
181
+ this.isLoading.set(true);
182
+ try {
183
+ const { email, password } = this.registerForm.value;
184
+ await this.authService.login('', email, password);
185
+ }
186
+ catch (error) {
187
+ const errorCode = error.code || error.message || 'unknown';
188
+ this.snackBar.open(this.getErrorMessage(errorCode), 'Close', {
189
+ duration: 5000,
190
+ panelClass: ['error-snackbar'],
191
+ });
192
+ }
193
+ finally {
194
+ this.isLoading.set(false);
195
+ this.errorMessage.set('');
196
+ this.navigateBack.goBack();
197
+ }
198
+ }
199
+ getErrorMessage(errorCode) {
200
+ switch (errorCode) {
201
+ case 'auth/email-already-in-use':
202
+ return 'This email address is already registered';
203
+ case 'auth/invalid-email':
204
+ return 'Please enter a valid email address';
205
+ case 'auth/operation-not-allowed':
206
+ return 'Email/password registration is not enabled';
207
+ case 'auth/weak-password':
208
+ return 'Please choose a stronger password';
209
+ default:
210
+ return 'An error occurred during registration. Please try again.';
211
+ }
212
+ }
213
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: RegistrationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
214
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: RegistrationComponent, isStandalone: true, selector: "pp-registration", providers: [provideTranslocoScope({ scope: 'auth' })], ngImport: i0, template: "<div class=\"registration-container\">\n <ng-container *transloco=\"let t;\">\n <h1>{{t('auth.registration_form.title')}}</h1>\n\n <form [formGroup]=\"registerForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Registration Form\">\n @if (isLoading()) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" [placeholder]=\"t('auth.registration_form.email_placeholder')\">\n @if (registerForm.get('email')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.email_err_required')}}</mat-error>\n }\n @if (registerForm.get('email')?.errors?.['email']) {\n <mat-error>{{t('auth.registration_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\" [placeholder]=\"t('auth.registration_form.password_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hidePassword = !hidePassword\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.get('password')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.password_err_required')}}</mat-error>\n }\n @if (registerForm.get('password')?.errors?.['minlength']) {\n <mat-error>{{t('auth.registration_form.password_err_min_length')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_confirm_label')}}</mat-label>\n <input matInput [type]=\"hideConfirmPassword ? 'password' : 'text'\" formControlName=\"confirmPassword\" [placeholder]=\"t('auth.registration_form.password_confirm_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hideConfirmPassword = !hideConfirmPassword\">\n <mat-icon>{{hideConfirmPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.errors?.['passwordMismatch']) {\n <mat-error>{{t('auth.registration_form.password_confirm_err_mismatch')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"form-actions\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"registerForm.invalid || isLoading()\">{{t('auth.registration_form.create_button')}}</button>\n <button mat-button type=\"button\" routerLink=\"/auth/login\" [disabled]=\"isLoading()\">{{t('auth.registration_form.sign_in_button')}}</button>\n </div>\n\n @if (errorMessage() !== '') {\n <mat-error class=\"server-error\">{{ errorMessage() }}</mat-error>\n }\n </form>\n </ng-container>\n</div>\n", styles: [".registration-container{max-width:400px;margin:2rem auto;padding:2rem}form{display:flex;flex-direction:column;gap:1rem}.form-actions{display:flex;flex-direction:column;gap:.5rem;margin-top:1rem}.server-error{margin-top:1rem;text-align:center}h1{text-align:center;margin-bottom:2rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }] });
215
+ }
216
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: RegistrationComponent, decorators: [{
217
+ type: Component,
218
+ args: [{ selector: 'pp-registration', imports: [ReactiveFormsModule, MatProgressBar, MatFormField, MatInput, MatIconButton, MatIcon, MatLabel, MatButton, RouterLink, MatError, TranslocoDirective], providers: [provideTranslocoScope({ scope: 'auth' })], template: "<div class=\"registration-container\">\n <ng-container *transloco=\"let t;\">\n <h1>{{t('auth.registration_form.title')}}</h1>\n\n <form [formGroup]=\"registerForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Registration Form\">\n @if (isLoading()) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" [placeholder]=\"t('auth.registration_form.email_placeholder')\">\n @if (registerForm.get('email')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.email_err_required')}}</mat-error>\n }\n @if (registerForm.get('email')?.errors?.['email']) {\n <mat-error>{{t('auth.registration_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\" [placeholder]=\"t('auth.registration_form.password_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hidePassword = !hidePassword\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.get('password')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.password_err_required')}}</mat-error>\n }\n @if (registerForm.get('password')?.errors?.['minlength']) {\n <mat-error>{{t('auth.registration_form.password_err_min_length')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_confirm_label')}}</mat-label>\n <input matInput [type]=\"hideConfirmPassword ? 'password' : 'text'\" formControlName=\"confirmPassword\" [placeholder]=\"t('auth.registration_form.password_confirm_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hideConfirmPassword = !hideConfirmPassword\">\n <mat-icon>{{hideConfirmPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.errors?.['passwordMismatch']) {\n <mat-error>{{t('auth.registration_form.password_confirm_err_mismatch')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"form-actions\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"registerForm.invalid || isLoading()\">{{t('auth.registration_form.create_button')}}</button>\n <button mat-button type=\"button\" routerLink=\"/auth/login\" [disabled]=\"isLoading()\">{{t('auth.registration_form.sign_in_button')}}</button>\n </div>\n\n @if (errorMessage() !== '') {\n <mat-error class=\"server-error\">{{ errorMessage() }}</mat-error>\n }\n </form>\n </ng-container>\n</div>\n", styles: [".registration-container{max-width:400px;margin:2rem auto;padding:2rem}form{display:flex;flex-direction:column;gap:1rem}.form-actions{display:flex;flex-direction:column;gap:.5rem;margin-top:1rem}.server-error{margin-top:1rem;text-align:center}h1{text-align:center;margin-bottom:2rem}\n"] }]
219
+ }], ctorParameters: () => [] });
220
+
221
+ class LogoutComponent {
222
+ authService = inject(AUTHENTICATION_SERVICE);
223
+ navigateBackService = inject(NavigateBackService);
224
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
225
+ onCancel() {
226
+ this.navigateBackService.goBack();
227
+ }
228
+ async onLogout() {
229
+ try {
230
+ this.isLoading.set(true);
231
+ this.navigateBackService.getRouteStack().pop();
232
+ await this.authService.logout(this.navigateBackService.getRouteStack().pop());
233
+ this.navigateBackService.goBack();
234
+ }
235
+ catch (error) {
236
+ console.error('Error during logout:', error);
237
+ }
238
+ finally {
239
+ this.isLoading.set(false);
240
+ }
241
+ }
242
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LogoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
243
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LogoutComponent, isStandalone: true, selector: "pp-logout", providers: [provideTranslocoScope('auth')], ngImport: i0, template: `
244
+ <div class="logout-dialog">
245
+ <ng-container *transloco="let t">
246
+ <h2 mat-dialog-title>{{ t('auth.logout_dialog.title') }}</h2>
247
+ <mat-dialog-content>{{ t('auth.logout_dialog.content') }}</mat-dialog-content>
248
+ <mat-dialog-actions align="end">
249
+ <button mat-button (click)="onCancel()">{{ t('auth.logout_dialog.cancel_button') }}</button>
250
+ <button mat-raised-button color="primary" (click)="onLogout()" [disabled]="isLoading()">{{ t('auth.logout_dialog.logout_button') }}</button>
251
+ </mat-dialog-actions>
252
+ </ng-container>
253
+ </div>
254
+ `, isInline: true, styles: ["mat-dialog-actions{gap:.5rem}mat-dialog-content{margin:1rem 0}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }] });
255
+ }
256
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LogoutComponent, decorators: [{
257
+ type: Component,
258
+ args: [{ selector: 'pp-logout', template: `
259
+ <div class="logout-dialog">
260
+ <ng-container *transloco="let t">
261
+ <h2 mat-dialog-title>{{ t('auth.logout_dialog.title') }}</h2>
262
+ <mat-dialog-content>{{ t('auth.logout_dialog.content') }}</mat-dialog-content>
263
+ <mat-dialog-actions align="end">
264
+ <button mat-button (click)="onCancel()">{{ t('auth.logout_dialog.cancel_button') }}</button>
265
+ <button mat-raised-button color="primary" (click)="onLogout()" [disabled]="isLoading()">{{ t('auth.logout_dialog.logout_button') }}</button>
266
+ </mat-dialog-actions>
267
+ </ng-container>
268
+ </div>
269
+ `, imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButton, TranslocoDirective], providers: [provideTranslocoScope('auth')], styles: ["mat-dialog-actions{gap:.5rem}mat-dialog-content{margin:1rem 0}\n"] }]
270
+ }] });
271
+
272
+ const loginResolver = async () => {
273
+ const authConfig = inject(AUTHENTICATION_CONFIGURATION);
274
+ const authService = inject(AUTHENTICATION_SERVICE);
275
+ const navigateBackService = inject(NavigateBackService);
276
+ if (authConfig.AUTHENTICATION_PROVIDER === 'firebase-auth')
277
+ return undefined;
278
+ else
279
+ return await authService.login(navigateBackService.getRouteStack().pop());
280
+ };
281
+
282
+ const authRoutes = [
283
+ { path: '', redirectTo: 'login', pathMatch: 'full', providers: [provideTranslocoScope('auth')] },
284
+ { path: 'login', component: LoginComponent, title: 'login', data: { icon: 'login', authToggle: true }, resolve: { signedInUser: loginResolver }, canActivate: [authGuard] },
285
+ { path: 'logout', component: LogoutComponent, title: 'logout', data: { icon: 'logout', authToggle: false }, canActivate: [authGuard] },
286
+ { path: 'register', component: RegistrationComponent, title: 'register', data: { icon: 'person_add', authToggle: true } },
287
+ { path: 'my-profile', component: MyProfileComponent, title: 'my_profile', data: { icon: 'person', authToggle: false } },
288
+ ];
289
+
290
+ class AuthButtonComponent {
291
+ authService = inject(AUTHENTICATION_SERVICE);
292
+ isAuthenticated = computed(() => this.authService.isAuthenticated(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
293
+ routes = authRoutes.filter((item) => item.title !== null && item.title !== undefined);
294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AuthButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
295
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: AuthButtonComponent, isStandalone: true, selector: "pp-auth-button", providers: [provideTranslocoScope('auth')], ngImport: i0, template: `
296
+ <div class="auth-button">
297
+ <ng-container *transloco="let t">
298
+ <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Auth Button">
299
+ <mat-icon>person</mat-icon>
300
+ </button>
301
+ <mat-menu #menu="matMenu">
302
+ @for (item of routes; track item) {
303
+ @if ((isAuthenticated() && !item.data?.['authToggle']) || (!isAuthenticated() && item.data?.['authToggle'])) {
304
+ <button mat-menu-item [routerLink]="'auth/' + item.path">
305
+ <mat-icon>{{ item.data?.['icon'] }}</mat-icon>
306
+ <span>&nbsp;{{ t('auth.button.' + item.title | substring: 0) }}</span>
307
+ </button>
308
+ }
309
+ }
310
+ </mat-menu>
311
+ </ng-container>
312
+ </div>
313
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "pipe", type: SubstringPipe, name: "substring" }] });
314
+ }
315
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AuthButtonComponent, decorators: [{
316
+ type: Component,
317
+ args: [{ selector: 'pp-auth-button', template: `
318
+ <div class="auth-button">
319
+ <ng-container *transloco="let t">
320
+ <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Auth Button">
321
+ <mat-icon>person</mat-icon>
322
+ </button>
323
+ <mat-menu #menu="matMenu">
324
+ @for (item of routes; track item) {
325
+ @if ((isAuthenticated() && !item.data?.['authToggle']) || (!isAuthenticated() && item.data?.['authToggle'])) {
326
+ <button mat-menu-item [routerLink]="'auth/' + item.path">
327
+ <mat-icon>{{ item.data?.['icon'] }}</mat-icon>
328
+ <span>&nbsp;{{ t('auth.button.' + item.title | substring: 0) }}</span>
329
+ </button>
330
+ }
331
+ }
332
+ </mat-menu>
333
+ </ng-container>
334
+ </div>
335
+ `, imports: [MatIconModule, MatButtonModule, MatMenu, MatMenuItem, RouterLink, MatMenuTrigger, SubstringPipe, TranslocoDirective], providers: [provideTranslocoScope('auth')] }]
336
+ }] });
337
+
338
+ /**
339
+ * Generated bundle index. Do not edit.
340
+ */
341
+
342
+ export { AuthButtonComponent, authGuard, authRoutes };
343
+ //# sourceMappingURL=processpuzzle-auth-feature.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processpuzzle-auth-feature.mjs","sources":["../../../../libs/auth/feature/auth.guard.ts","../../../../libs/auth/feature/login/login.component.ts","../../../../libs/auth/feature/login/login.component.html","../../../../libs/auth/feature/my-profile/my-profile.component.ts","../../../../libs/auth/feature/my-profile/my-profile.component.html","../../../../libs/auth/feature/registration/registration.component.ts","../../../../libs/auth/feature/registration/registration.component.html","../../../../libs/auth/feature/logout/logout.component.ts","../../../../libs/auth/feature/login/login.resolver.ts","../../../../libs/auth/feature/auth.routes.ts","../../../../libs/auth/feature/auth-button/auth-button.component.ts","../../../../libs/auth/feature/processpuzzle-auth-feature.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { ActivatedRouteSnapshot, Router } from '@angular/router';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { AUTHENTICATION_SERVICE } from '@processpuzzle/auth/domain';\n\nexport const authGuard = async (route: ActivatedRouteSnapshot) => {\n const authService = inject(AUTHENTICATION_SERVICE);\n const isLoginRoute = route.routeConfig?.path === 'login';\n const isLogoutRoute = route.routeConfig?.path === 'logout';\n const router = inject(Router);\n const snackBar = inject(MatSnackBar);\n\n await authService.authenticate();\n\n if (isLoginRoute) {\n if (authService.isAuthenticated()) {\n snackBar.open('You are already logged in', 'Close', { duration: 3000 });\n await router.navigate(['/']);\n return false;\n } else {\n return true; // If not logged in, allow access to login page\n }\n } else if (isLogoutRoute) {\n if (authService.isAuthenticated()) {\n return true; // If logged in, allow access to logout page\n } else {\n snackBar.open('You are not already logged in', 'Close', { duration: 3000 });\n await router.navigate(['/']);\n return false;\n }\n } else if (authService.isAuthenticated()) {\n // For protected routes, check if user is logged in\n return true;\n } else {\n await router.navigate(['/auth/login']);\n return false;\n }\n};\n","import { Component, inject, OnInit, signal } from '@angular/core';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';\nimport { MatError, MatFormField, MatSuffix } from '@angular/material/form-field';\nimport { MatInput, MatLabel } from '@angular/material/input';\nimport { MatButton, MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatDivider } from '@angular/material/divider';\nimport { TranslocoDirective } from '@jsverse/transloco';\nimport { AUTHENTICATION_SERVICE, AuthService } from '@processpuzzle/auth/domain';\nimport { NavigateBackService } from '@processpuzzle/widgets';\n\n@Component({\n selector: 'pp-login',\n templateUrl: 'login.component.html',\n styleUrls: ['login.component.css'],\n imports: [MatButton, MatDivider, MatError, MatFormField, MatIcon, MatIconButton, MatInput, MatLabel, MatSuffix, ReactiveFormsModule, RouterLink, TranslocoDirective],\n providers: [],\n})\nexport class LoginComponent implements OnInit {\n errorMessage = signal('');\n hidePassword = true;\n isLoading = signal(false);\n loginForm!: FormGroup;\n private readonly authService: AuthService = inject(AUTHENTICATION_SERVICE);\n private readonly fb = inject(FormBuilder);\n private readonly navigateBackService = inject(NavigateBackService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n // region public event handlers\n ngOnInit(): void {\n const user = this.route.snapshot.data['signedInUser'];\n if (!user) {\n this.loginForm = this.buildLoginForm();\n }\n }\n\n async onSubmit() {\n if (this.loginForm.invalid) return;\n this.errorMessage.set('');\n this.isLoading.set(true);\n\n try {\n const { email, password } = this.loginForm.value;\n await this.authService.login(this.navigateBackService.getRouteStack().pop(), email, password);\n await this.router.navigate(['/']);\n } catch (error: unknown) {\n const message = this.getErrorMessage((error as { code?: string; message?: string }).code || (error as { code?: string; message?: string }).message || '');\n this.errorMessage.set(message);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n protected async signInWithGoogle() {\n this.errorMessage.set('');\n this.isLoading.set(true);\n try {\n // await signInWithPopup(this.authService, new GoogleAuthProvider());\n await this.router.navigate(['/']);\n } catch (error: unknown) {\n this.errorMessage.set(this.getErrorMessage((error as { code?: string; message?: string }).code || (error as { code?: string; message?: string }).message || ''));\n } finally {\n this.isLoading.set(false);\n }\n }\n // endregion\n\n // region protected, private helper methods\n private buildLoginForm() {\n return this.fb.group({\n email: ['', [Validators.required, Validators.email]],\n password: ['', Validators.required],\n });\n }\n\n private getErrorMessage(errorCode: string): string {\n switch (errorCode) {\n case 'auth/invalid-email':\n return 'Invalid email address';\n case 'auth/user-disabled':\n return 'This account has been disabled';\n case 'auth/user-not-found':\n return 'No account found with this email';\n case 'auth/wrong-password':\n return 'Invalid password';\n case 'auth/popup-closed-by-user':\n return 'Sign-in popup was closed before completion';\n default:\n return 'An error occurred during sign in';\n }\n }\n // endregion\n}\n","<div class=\"login-container\">\n <ng-container *transloco=\"let t;\">\n <h2>{{t('auth.login_form.title')}}</h2>\n\n <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Login Form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" placeholder=\"Enter your email\">\n @if (loginForm.get('email')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.email_err_required')}}</mat-error>\n }\n @if (loginForm.get('email')?.hasError('email')) {\n <mat-error>{{t('auth.login_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.login_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\">\n <button mat-icon-button matSuffix type=\"button\" (click)=\"hidePassword = !hidePassword\" aria-label=\"Toggle Password Visibility\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (loginForm.get('password')?.hasError('required')) {\n <mat-error>{{t('auth.login_form.password_err_required')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"actions\">\n <button mat-raised-button color=\"secondary\" routerLink=\"/auth/register\">{{t('auth.login_form.create_account_button')}}</button>\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"loginForm.invalid || isLoading()\">{{ isLoading() ? t('auth.login_form.signing_in_button') : t('auth.login_form.sign_in_button') }}</button>\n </div>\n </form>\n\n <mat-divider class=\"divider\">OR</mat-divider>\n\n <button mat-stroked-button (click)=\"signInWithGoogle()\" [disabled]=\"isLoading()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\">\n <path fill=\"#FFC107\" d=\"M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12\ts5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20\ts20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z\"/>\n <path fill=\"#FF3D00\" d=\"M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039\tl5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z\"/>\n <path fill=\"#4CAF50\" d=\"M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36\tc-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z\"/>\n <path fill=\"#1976D2\" d=\"M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571\tc0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z\"/>\n </svg>\n {{t('auth.login_form.google_button')}}\n </button>\n @if (errorMessage()) {\n <div class=\"error-message\">{{ errorMessage() }}</div>\n }\n </ng-container>\n</div>\n","import { Component } from '@angular/core';\nimport { provideTranslocoScope } from '@jsverse/transloco';\n\n@Component({\n selector: 'pp-my-profile',\n templateUrl: 'my-profile.component.html',\n styles: ``,\n imports: [],\n providers: [provideTranslocoScope('auth')],\n})\nexport class MyProfileComponent {}\n","<h1>My profile</h1>\n","import { Component, inject, signal } from '@angular/core';\nimport { AbstractControl, FormBuilder, FormGroup, ReactiveFormsModule, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';\nimport { RouterLink } from '@angular/router';\nimport { MatProgressBar } from '@angular/material/progress-bar';\nimport { MatError, MatFormField } from '@angular/material/form-field';\nimport { MatInput, MatLabel } from '@angular/material/input';\nimport { MatButton, MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { NavigateBackService } from '@processpuzzle/widgets';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { provideTranslocoScope, TranslocoDirective } from '@jsverse/transloco';\nimport { AUTHENTICATION_SERVICE, AuthService } from '@processpuzzle/auth/domain';\n\n@Component({\n selector: 'pp-registration',\n templateUrl: './registration.component.html',\n styleUrls: ['./registration.component.css'],\n imports: [ReactiveFormsModule, MatProgressBar, MatFormField, MatInput, MatIconButton, MatIcon, MatLabel, MatButton, RouterLink, MatError, TranslocoDirective],\n providers: [provideTranslocoScope({ scope: 'auth' })],\n})\nexport class RegistrationComponent {\n private readonly authService: AuthService = inject(AUTHENTICATION_SERVICE);\n private readonly fb = inject(FormBuilder);\n private readonly navigateBack = inject(NavigateBackService);\n private readonly snackBar = inject<MatSnackBar>(MatSnackBar);\n public registerForm: FormGroup;\n public isLoading = signal<boolean>(false);\n public errorMessage = signal<string>('');\n public hidePassword = true;\n public hideConfirmPassword = true;\n\n constructor() {\n this.registerForm = this.fb.group(\n {\n email: ['', [Validators.required, Validators.email]],\n password: ['', [Validators.required, Validators.minLength(6)]],\n confirmPassword: ['', Validators.required],\n },\n {\n validators: [this.passwordMatchValidator],\n },\n );\n }\n\n private passwordMatchValidator(): ValidatorFn {\n return (form: AbstractControl): ValidationErrors | null => {\n const password = form.get('password')?.value;\n const confirmPassword = form.get('confirmPassword')?.value;\n\n if (password !== confirmPassword) {\n return { passwordMismatch: true };\n }\n return null;\n };\n }\n\n async onSubmit(): Promise<void> {\n if (this.registerForm.invalid) return;\n\n this.isLoading.set(true);\n\n try {\n const { email, password } = this.registerForm.value;\n await this.authService.login('', email, password);\n } catch (error: unknown) {\n const errorCode = (error as { code?: string; message?: string }).code || (error as { code?: string; message?: string }).message || 'unknown';\n this.snackBar.open(this.getErrorMessage(errorCode), 'Close', {\n duration: 5000,\n panelClass: ['error-snackbar'],\n });\n } finally {\n this.isLoading.set(false);\n this.errorMessage.set('');\n this.navigateBack.goBack();\n }\n }\n\n private getErrorMessage(errorCode: string): string {\n switch (errorCode) {\n case 'auth/email-already-in-use':\n return 'This email address is already registered';\n case 'auth/invalid-email':\n return 'Please enter a valid email address';\n case 'auth/operation-not-allowed':\n return 'Email/password registration is not enabled';\n case 'auth/weak-password':\n return 'Please choose a stronger password';\n default:\n return 'An error occurred during registration. Please try again.';\n }\n }\n}\n","<div class=\"registration-container\">\n <ng-container *transloco=\"let t;\">\n <h1>{{t('auth.registration_form.title')}}</h1>\n\n <form [formGroup]=\"registerForm\" (ngSubmit)=\"onSubmit()\" aria-label=\"Registration Form\">\n @if (isLoading()) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.email_label')}}</mat-label>\n <input matInput type=\"email\" formControlName=\"email\" [placeholder]=\"t('auth.registration_form.email_placeholder')\">\n @if (registerForm.get('email')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.email_err_required')}}</mat-error>\n }\n @if (registerForm.get('email')?.errors?.['email']) {\n <mat-error>{{t('auth.registration_form.email_err_invalid')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_label')}}</mat-label>\n <input matInput [type]=\"hidePassword ? 'password' : 'text'\" formControlName=\"password\" [placeholder]=\"t('auth.registration_form.password_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hidePassword = !hidePassword\">\n <mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.get('password')?.errors?.['required']) {\n <mat-error>{{t('auth.registration_form.password_err_required')}}</mat-error>\n }\n @if (registerForm.get('password')?.errors?.['minlength']) {\n <mat-error>{{t('auth.registration_form.password_err_min_length')}}</mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{t('auth.registration_form.password_confirm_label')}}</mat-label>\n <input matInput [type]=\"hideConfirmPassword ? 'password' : 'text'\" formControlName=\"confirmPassword\" [placeholder]=\"t('auth.registration_form.password_confirm_placeholder')\">\n <button mat-icon-button type=\"button\" matSuffix (click)=\"hideConfirmPassword = !hideConfirmPassword\">\n <mat-icon>{{hideConfirmPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n @if (registerForm.errors?.['passwordMismatch']) {\n <mat-error>{{t('auth.registration_form.password_confirm_err_mismatch')}}</mat-error>\n }\n </mat-form-field>\n\n <div class=\"form-actions\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"registerForm.invalid || isLoading()\">{{t('auth.registration_form.create_button')}}</button>\n <button mat-button type=\"button\" routerLink=\"/auth/login\" [disabled]=\"isLoading()\">{{t('auth.registration_form.sign_in_button')}}</button>\n </div>\n\n @if (errorMessage() !== '') {\n <mat-error class=\"server-error\">{{ errorMessage() }}</mat-error>\n }\n </form>\n </ng-container>\n</div>\n","import { Component, inject, signal } from '@angular/core';\nimport { MatDialogActions, MatDialogContent, MatDialogTitle } from '@angular/material/dialog';\nimport { MatButton } from '@angular/material/button';\nimport { NavigateBackService } from '@processpuzzle/widgets';\nimport { provideTranslocoScope, TranslocoDirective } from '@jsverse/transloco';\nimport { AUTHENTICATION_SERVICE } from '@processpuzzle/auth/domain';\n\n@Component({\n selector: 'pp-logout',\n template: `\n <div class=\"logout-dialog\">\n <ng-container *transloco=\"let t\">\n <h2 mat-dialog-title>{{ t('auth.logout_dialog.title') }}</h2>\n <mat-dialog-content>{{ t('auth.logout_dialog.content') }}</mat-dialog-content>\n <mat-dialog-actions align=\"end\">\n <button mat-button (click)=\"onCancel()\">{{ t('auth.logout_dialog.cancel_button') }}</button>\n <button mat-raised-button color=\"primary\" (click)=\"onLogout()\" [disabled]=\"isLoading()\">{{ t('auth.logout_dialog.logout_button') }}</button>\n </mat-dialog-actions>\n </ng-container>\n </div>\n `,\n styles: [\n `\n mat-dialog-actions {\n gap: 0.5rem;\n }\n\n mat-dialog-content {\n margin: 1rem 0;\n }\n `,\n ],\n imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButton, TranslocoDirective],\n providers: [provideTranslocoScope('auth')],\n})\nexport class LogoutComponent {\n private readonly authService = inject(AUTHENTICATION_SERVICE);\n private readonly navigateBackService = inject(NavigateBackService);\n protected isLoading = signal(false);\n\n onCancel() {\n this.navigateBackService.goBack();\n }\n\n async onLogout(): Promise<void> {\n try {\n this.isLoading.set(true);\n this.navigateBackService.getRouteStack().pop();\n await this.authService.logout(this.navigateBackService.getRouteStack().pop());\n this.navigateBackService.goBack();\n } catch (error) {\n console.error('Error during logout:', error);\n } finally {\n this.isLoading.set(false);\n }\n }\n}\n","import { inject } from '@angular/core';\nimport { ResolveFn } from '@angular/router';\nimport { AUTHENTICATION_CONFIGURATION, AUTHENTICATION_SERVICE, AuthenticationConfiguration, User } from '@processpuzzle/auth/domain';\nimport { NavigateBackService } from '@processpuzzle/widgets';\n\nexport const loginResolver: ResolveFn<User | undefined> = async () => {\n const authConfig: AuthenticationConfiguration = inject(AUTHENTICATION_CONFIGURATION);\n const authService = inject(AUTHENTICATION_SERVICE);\n const navigateBackService = inject(NavigateBackService);\n\n if (authConfig.AUTHENTICATION_PROVIDER === 'firebase-auth') return undefined;\n else return await authService.login(navigateBackService.getRouteStack().pop());\n};\n","import { Routes } from '@angular/router';\nimport { LoginComponent } from './login/login.component';\nimport { MyProfileComponent } from './my-profile/my-profile.component';\nimport { RegistrationComponent } from './registration/registration.component';\nimport { LogoutComponent } from './logout/logout.component';\nimport { authGuard } from './auth.guard';\nimport { loginResolver } from './login/login.resolver';\nimport { provideTranslocoScope } from '@jsverse/transloco';\n\nexport const authRoutes: Routes = [\n { path: '', redirectTo: 'login', pathMatch: 'full', providers: [provideTranslocoScope('auth')] },\n { path: 'login', component: LoginComponent, title: 'login', data: { icon: 'login', authToggle: true }, resolve: { signedInUser: loginResolver }, canActivate: [authGuard] },\n { path: 'logout', component: LogoutComponent, title: 'logout', data: { icon: 'logout', authToggle: false }, canActivate: [authGuard] },\n { path: 'register', component: RegistrationComponent, title: 'register', data: { icon: 'person_add', authToggle: true } },\n { path: 'my-profile', component: MyProfileComponent, title: 'my_profile', data: { icon: 'person', authToggle: false } },\n];\n","import { Component, computed, inject } from '@angular/core';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { RouterLink } from '@angular/router';\nimport { authRoutes } from '../auth.routes';\nimport { SubstringPipe } from '@processpuzzle/util';\nimport { provideTranslocoScope, TranslocoDirective } from '@jsverse/transloco';\nimport { AUTHENTICATION_SERVICE } from '@processpuzzle/auth/domain';\n\n@Component({\n selector: 'pp-auth-button',\n template: `\n <div class=\"auth-button\">\n <ng-container *transloco=\"let t\">\n <button mat-icon-button [matMenuTriggerFor]=\"menu\" aria-label=\"Auth Button\">\n <mat-icon>person</mat-icon>\n </button>\n <mat-menu #menu=\"matMenu\">\n @for (item of routes; track item) {\n @if ((isAuthenticated() && !item.data?.['authToggle']) || (!isAuthenticated() && item.data?.['authToggle'])) {\n <button mat-menu-item [routerLink]=\"'auth/' + item.path\">\n <mat-icon>{{ item.data?.['icon'] }}</mat-icon>\n <span>&nbsp;{{ t('auth.button.' + item.title | substring: 0) }}</span>\n </button>\n }\n }\n </mat-menu>\n </ng-container>\n </div>\n `,\n imports: [MatIconModule, MatButtonModule, MatMenu, MatMenuItem, RouterLink, MatMenuTrigger, SubstringPipe, TranslocoDirective],\n styles: [],\n providers: [provideTranslocoScope('auth')],\n})\nexport class AuthButtonComponent {\n private readonly authService = inject(AUTHENTICATION_SERVICE);\n isAuthenticated = computed(() => this.authService.isAuthenticated());\n readonly routes = authRoutes.filter((item) => item.title !== null && item.title !== undefined);\n\n // region event handling methods\n // endregion\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":";;;;;;;;;;;;;;;;;;;;;MAKa,SAAS,GAAG,OAAO,KAA6B,KAAI;AAC/D,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,sBAAsB,CAAC;IAClD,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,OAAO;IACxD,MAAM,aAAa,GAAG,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,QAAQ;AAC1D,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;AAEpC,IAAA,MAAM,WAAW,CAAC,YAAY,EAAE;IAEhC,IAAI,YAAY,EAAE;AAChB,QAAA,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE;AACjC,YAAA,QAAQ,CAAC,IAAI,CAAC,2BAA2B,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACvE,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;AAC5B,YAAA,OAAO,KAAK;QACd;aAAO;YACL,OAAO,IAAI,CAAC;QACd;IACF;SAAO,IAAI,aAAa,EAAE;AACxB,QAAA,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE;YACjC,OAAO,IAAI,CAAC;QACd;aAAO;AACL,YAAA,QAAQ,CAAC,IAAI,CAAC,+BAA+B,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAC3E,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;AAC5B,YAAA,OAAO,KAAK;QACd;IACF;AAAO,SAAA,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE;;AAExC,QAAA,OAAO,IAAI;IACb;SAAO;QACL,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC,CAAC;AACtC,QAAA,OAAO,KAAK;IACd;AACF;;MClBa,cAAc,CAAA;AACzB,IAAA,YAAY,GAAG,MAAM,CAAC,EAAE,mFAAC;IACzB,YAAY,GAAG,IAAI;AACnB,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC;AACzB,IAAA,SAAS;AACQ,IAAA,WAAW,GAAgB,MAAM,CAAC,sBAAsB,CAAC;AACzD,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AACxB,IAAA,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACjD,IAAA,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;;IAGxC,QAAQ,GAAA;AACN,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC;QACrD,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE;QACxC;IACF;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO;YAAE;AAC5B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AAExB,QAAA,IAAI;YACF,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK;YAChD,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC;YAC7F,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACnC;QAAE,OAAO,KAAc,EAAE;AACvB,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAE,KAA6C,CAAC,IAAI,IAAK,KAA6C,CAAC,OAAO,IAAI,EAAE,CAAC;AACzJ,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC;QAChC;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;AAEU,IAAA,MAAM,gBAAgB,GAAA;AAC9B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;;YAEF,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACnC;QAAE,OAAO,KAAc,EAAE;YACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAE,KAA6C,CAAC,IAAI,IAAK,KAA6C,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAClK;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;;;IAIQ,cAAc,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC;AACnB,YAAA,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;AACpD,YAAA,QAAQ,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;AACpC,SAAA,CAAC;IACJ;AAEQ,IAAA,eAAe,CAAC,SAAiB,EAAA;QACvC,QAAQ,SAAS;AACf,YAAA,KAAK,oBAAoB;AACvB,gBAAA,OAAO,uBAAuB;AAChC,YAAA,KAAK,oBAAoB;AACvB,gBAAA,OAAO,gCAAgC;AACzC,YAAA,KAAK,qBAAqB;AACxB,gBAAA,OAAO,kCAAkC;AAC3C,YAAA,KAAK,qBAAqB;AACxB,gBAAA,OAAO,kBAAkB;AAC3B,YAAA,KAAK,2BAA2B;AAC9B,gBAAA,OAAO,4CAA4C;AACrD,YAAA;AACE,gBAAA,OAAO,kCAAkC;;IAE/C;uGAzEW,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAd,cAAc,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAFd,EAAE,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECjBf,qjGAiDA,EAAA,MAAA,EAAA,CAAA,orBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDjCY,SAAS,EAAA,QAAA,EAAA,iOAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,WAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,IAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,YAAY,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,aAAa,EAAA,QAAA,EAAA,sFAAA,EAAA,QAAA,EAAA,CAAA,WAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,yHAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,IAAA,EAAA,aAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,mBAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,SAAS,EAAA,QAAA,EAAA,+CAAA,EAAA,MAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,UAAU,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,kBAAkB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGxJ,cAAc,EAAA,UAAA,EAAA,CAAA;kBAP1B,SAAS;+BACE,UAAU,EAAA,OAAA,EAGX,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,CAAC,EAAA,SAAA,EACzJ,EAAE,EAAA,QAAA,EAAA,qjGAAA,EAAA,MAAA,EAAA,CAAA,orBAAA,CAAA,EAAA;;;MEPF,kBAAkB,CAAA;uGAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAlB,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,SAAA,EAFlB,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,0BCR5C,uBACA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FDSa,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAP9B,SAAS;+BACE,eAAe,EAAA,OAAA,EAGhB,EAAE,EAAA,SAAA,EACA,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAA,QAAA,EAAA,uBAAA,EAAA;;;MEY/B,qBAAqB,CAAA;AACf,IAAA,WAAW,GAAgB,MAAM,CAAC,sBAAsB,CAAC;AACzD,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AACxB,IAAA,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAC1C,IAAA,QAAQ,GAAG,MAAM,CAAc,WAAW,CAAC;AACrD,IAAA,YAAY;AACZ,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,gFAAC;AAClC,IAAA,YAAY,GAAG,MAAM,CAAS,EAAE,mFAAC;IACjC,YAAY,GAAG,IAAI;IACnB,mBAAmB,GAAG,IAAI;AAEjC,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAC/B;AACE,YAAA,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;AACpD,YAAA,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,YAAA,eAAe,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;SAC3C,EACD;AACE,YAAA,UAAU,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC;AAC1C,SAAA,CACF;IACH;IAEQ,sBAAsB,GAAA;QAC5B,OAAO,CAAC,IAAqB,KAA6B;YACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK;YAC5C,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,KAAK;AAE1D,YAAA,IAAI,QAAQ,KAAK,eAAe,EAAE;AAChC,gBAAA,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE;YACnC;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC;IACH;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO;YAAE;AAE/B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AAExB,QAAA,IAAI;YACF,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK;AACnD,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC;QACnD;QAAE,OAAO,KAAc,EAAE;YACvB,MAAM,SAAS,GAAI,KAA6C,CAAC,IAAI,IAAK,KAA6C,CAAC,OAAO,IAAI,SAAS;AAC5I,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;AAC3D,gBAAA,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,CAAC,gBAAgB,CAAC;AAC/B,aAAA,CAAC;QACJ;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;AACzB,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;QAC5B;IACF;AAEQ,IAAA,eAAe,CAAC,SAAiB,EAAA;QACvC,QAAQ,SAAS;AACf,YAAA,KAAK,2BAA2B;AAC9B,gBAAA,OAAO,0CAA0C;AACnD,YAAA,KAAK,oBAAoB;AACvB,gBAAA,OAAO,oCAAoC;AAC7C,YAAA,KAAK,4BAA4B;AAC/B,gBAAA,OAAO,4CAA4C;AACrD,YAAA,KAAK,oBAAoB;AACvB,gBAAA,OAAO,mCAAmC;AAC5C,YAAA;AACE,gBAAA,OAAO,0DAA0D;;IAEvE;uGAtEW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,SAAA,EAFrB,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EClBvD,ghGAwDA,EAAA,MAAA,EAAA,CAAA,8RAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDvCY,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,cAAc,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,aAAA,EAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,QAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,YAAY,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,yHAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,IAAA,EAAA,aAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,mBAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,aAAa,uKAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,SAAS,EAAA,QAAA,EAAA,iOAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,WAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,UAAU,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,kFAAE,kBAAkB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGjJ,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAPjC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,EAAA,OAAA,EAGlB,CAAC,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EAAA,SAAA,EAClJ,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAA,QAAA,EAAA,ghGAAA,EAAA,MAAA,EAAA,CAAA,8RAAA,CAAA,EAAA;;;MEiB1C,eAAe,CAAA;AACT,IAAA,WAAW,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAC5C,IAAA,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACxD,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC;IAEnC,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE;IACnC;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YACxB,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE;AAC9C,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,CAAC;AAC7E,YAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE;QACnC;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;QAC9C;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;uGApBW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,wDAFf,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAxBhC;;;;;;;;;;;GAWT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,kEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAYS,cAAc,+HAAE,gBAAgB,EAAA,QAAA,EAAA,8DAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,gBAAgB,EAAA,QAAA,EAAA,8DAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,SAAS,yUAAE,kBAAkB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGhF,eAAe,EAAA,UAAA,EAAA,CAAA;kBA5B3B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,EAAA,QAAA,EACX;;;;;;;;;;;AAWT,EAAA,CAAA,EAAA,OAAA,EAYQ,CAAC,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,kBAAkB,CAAC,EAAA,SAAA,EACjF,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAA,MAAA,EAAA,CAAA,kEAAA,CAAA,EAAA;;;AC5BrC,MAAM,aAAa,GAAgC,YAAW;AACnE,IAAA,MAAM,UAAU,GAAgC,MAAM,CAAC,4BAA4B,CAAC;AACpF,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAClD,IAAA,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAEvD,IAAA,IAAI,UAAU,CAAC,uBAAuB,KAAK,eAAe;AAAE,QAAA,OAAO,SAAS;;AACvE,QAAA,OAAO,MAAM,WAAW,CAAC,KAAK,CAAC,mBAAmB,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,CAAC;AAChF,CAAC;;ACHM,MAAM,UAAU,GAAW;IAChC,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAE;AAChG,IAAA,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;AAC3K,IAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;IACtI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,qBAAqB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;IACzH,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;;;MCqB5G,mBAAmB,CAAA;AACb,IAAA,WAAW,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAC7D,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,sFAAC;IAC3D,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;uGAHnF,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,6DAFnB,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArBhC;;;;;;;;;;;;;;;;;;AAkBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACS,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,eAAe,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,sFAAA,EAAA,QAAA,EAAA,CAAA,WAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,eAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,WAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,OAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,QAAA,EAAA,OAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,WAAW,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,UAAU,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,cAAc,EAAA,QAAA,EAAA,6CAAA,EAAA,MAAA,EAAA,CAAA,sBAAA,EAAA,mBAAA,EAAA,oBAAA,EAAA,4BAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,aAAA,CAAA,EAAA,QAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAiB,kBAAkB,2LAAjC,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA;;2FAI9F,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAzB/B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,QAAA,EAChB;;;;;;;;;;;;;;;;;;GAkBT,EAAA,OAAA,EACQ,CAAC,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,CAAC,EAAA,SAAA,EAEnH,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,EAAA;;;ACjC5C;;AAEG;;;;"}