valtech-components 2.0.731 → 2.0.732
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/esm2022/lib/components/atoms/glow/glow.component.mjs +95 -0
- package/esm2022/lib/components/atoms/glow/types.mjs +2 -0
- package/esm2022/lib/components/organisms/login/login.component.mjs +3 -3
- package/esm2022/lib/services/devices/devices.service.mjs +259 -0
- package/esm2022/lib/services/devices/index.mjs +3 -0
- package/esm2022/lib/services/devices/types.mjs +8 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +7 -1
- package/fesm2022/valtech-components.mjs +355 -5
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/atoms/glow/glow.component.d.ts +42 -0
- package/lib/components/atoms/glow/types.d.ts +40 -0
- package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +1 -1
- package/lib/components/molecules/features-list/features-list.component.d.ts +1 -1
- package/lib/components/organisms/article/article.component.d.ts +3 -3
- package/lib/components/organisms/toolbar/toolbar.component.d.ts +1 -1
- package/lib/services/devices/devices.service.d.ts +73 -0
- package/lib/services/devices/index.d.ts +2 -0
- package/lib/services/devices/types.d.ts +11 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +3 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, Injectable, makeEnvironmentProviders, APP_INITIALIZER, inject, EventEmitter, Component, Input, Output, input, computed, HostBinding, HostListener, Pipe,
|
|
2
|
+
import { signal, Injectable, makeEnvironmentProviders, APP_INITIALIZER, inject, EventEmitter, Component, Input, Output, input, computed, ChangeDetectionStrategy, HostBinding, HostListener, Pipe, ViewChild, ChangeDetectorRef, ContentChild, PLATFORM_ID, Inject, ErrorHandler, DestroyRef, InjectionToken, runInInjectionContext, effect, Optional, TemplateRef, ViewContainerRef, isSignal, Directive, ElementRef, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import * as i2$1 from '@ionic/angular/standalone';
|
|
4
4
|
import { IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonDatetimeButton, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonRippleEffect, AlertController, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
@@ -50,7 +50,7 @@ import 'prismjs/components/prism-json';
|
|
|
50
50
|
* Current version of valtech-components.
|
|
51
51
|
* This is automatically updated during the publish process.
|
|
52
52
|
*/
|
|
53
|
-
const VERSION = '2.0.
|
|
53
|
+
const VERSION = '2.0.732';
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Servicio para gestionar presets de componentes.
|
|
@@ -445,6 +445,99 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
445
445
|
type: Output
|
|
446
446
|
}] } });
|
|
447
447
|
|
|
448
|
+
const POSITION_MAP = {
|
|
449
|
+
'top-left': '0% 0%',
|
|
450
|
+
top: '50% 0%',
|
|
451
|
+
'top-right': '100% 0%',
|
|
452
|
+
left: '0% 50%',
|
|
453
|
+
center: '50% 50%',
|
|
454
|
+
right: '100% 50%',
|
|
455
|
+
'bottom-left': '0% 100%',
|
|
456
|
+
bottom: '50% 100%',
|
|
457
|
+
'bottom-right': '100% 100%',
|
|
458
|
+
};
|
|
459
|
+
const SIZE_MAP = {
|
|
460
|
+
small: '300px',
|
|
461
|
+
medium: '500px',
|
|
462
|
+
large: '800px',
|
|
463
|
+
xlarge: '1200px',
|
|
464
|
+
};
|
|
465
|
+
const INTENSITY_MAP = {
|
|
466
|
+
subtle: 0.08,
|
|
467
|
+
medium: 0.18,
|
|
468
|
+
strong: 0.35,
|
|
469
|
+
};
|
|
470
|
+
const LINEAR_ANGLE_MAP = {
|
|
471
|
+
'top-left': '135deg',
|
|
472
|
+
top: '180deg',
|
|
473
|
+
'top-right': '225deg',
|
|
474
|
+
left: '90deg',
|
|
475
|
+
center: '180deg',
|
|
476
|
+
right: '270deg',
|
|
477
|
+
'bottom-left': '45deg',
|
|
478
|
+
bottom: '0deg',
|
|
479
|
+
'bottom-right': '315deg',
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* `val-glow` — wrapper that paints a colored radial or linear gradient behind its
|
|
483
|
+
* projected content. Uses Ionic color tokens, so it respects light/dark theme.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* <val-glow [props]="{ color: 'primary', position: 'top', size: 'large' }">
|
|
487
|
+
* <h1>Hero title</h1>
|
|
488
|
+
* <p>Body copy...</p>
|
|
489
|
+
* </val-glow>
|
|
490
|
+
*
|
|
491
|
+
* @example Two-tone radial
|
|
492
|
+
* <val-glow [props]="{ color: 'primary', secondaryColor: 'tertiary', position: 'center' }">
|
|
493
|
+
* ...
|
|
494
|
+
* </val-glow>
|
|
495
|
+
*
|
|
496
|
+
* @example Linear sweep from top
|
|
497
|
+
* <val-glow [props]="{ color: 'success', shape: 'linear', position: 'top', intensity: 'strong' }">
|
|
498
|
+
* ...
|
|
499
|
+
* </val-glow>
|
|
500
|
+
*/
|
|
501
|
+
class GlowComponent {
|
|
502
|
+
constructor() {
|
|
503
|
+
this.props = input.required();
|
|
504
|
+
this.color = computed(() => this.props().color ?? 'primary');
|
|
505
|
+
this.secondaryColor = computed(() => this.props().secondaryColor);
|
|
506
|
+
this.hasSecondary = computed(() => Boolean(this.secondaryColor()));
|
|
507
|
+
this.position = computed(() => this.props().position ?? 'center');
|
|
508
|
+
this.size = computed(() => this.props().size ?? 'large');
|
|
509
|
+
this.intensity = computed(() => this.props().intensity ?? 'medium');
|
|
510
|
+
this.shape = computed(() => this.props().shape ?? 'radial');
|
|
511
|
+
this.animated = computed(() => this.props().animated ?? false);
|
|
512
|
+
this.blendMode = computed(() => this.props().blendMode ?? 'normal');
|
|
513
|
+
this.colorRgbVar = computed(() => `var(--ion-color-${this.color()}-rgb)`);
|
|
514
|
+
this.secondaryColorRgbVar = computed(() => this.secondaryColor() ? `var(--ion-color-${this.secondaryColor()}-rgb)` : null);
|
|
515
|
+
this.positionCss = computed(() => POSITION_MAP[this.position()]);
|
|
516
|
+
this.sizeCss = computed(() => SIZE_MAP[this.size()]);
|
|
517
|
+
this.intensityValue = computed(() => INTENSITY_MAP[this.intensity()].toString());
|
|
518
|
+
this.angleCss = computed(() => LINEAR_ANGLE_MAP[this.position()]);
|
|
519
|
+
}
|
|
520
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
521
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: GlowComponent, isStandalone: true, selector: "val-glow", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.val-glow--radial": "shape() === 'radial'", "class.val-glow--linear": "shape() === 'linear'", "class.val-glow--animated": "animated()", "class.val-glow--dual": "hasSecondary()", "style.--val-glow-color-rgb": "colorRgbVar()", "style.--val-glow-color-secondary-rgb": "secondaryColorRgbVar()", "style.--val-glow-position": "positionCss()", "style.--val-glow-size": "sizeCss()", "style.--val-glow-intensity": "intensityValue()", "style.--val-glow-angle": "angleCss()", "style.--val-glow-blend-mode": "blendMode()" }, classAttribute: "val-glow" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{position:relative;display:block;isolation:isolate;overflow:hidden;--val-glow-color-rgb: var(--ion-color-primary-rgb);--val-glow-color-secondary-rgb: var(--val-glow-color-rgb);--val-glow-position: 50% 50%;--val-glow-size: 800px;--val-glow-intensity: .18;--val-glow-angle: 180deg;--val-glow-blend-mode: normal}:host:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background-blend-mode:var(--val-glow-blend-mode);background-repeat:no-repeat}:host(.val-glow--radial):before{background-image:radial-gradient(circle var(--val-glow-size) at var(--val-glow-position),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-rgb),0) 70%)}:host(.val-glow--radial.val-glow--dual):before{background-image:radial-gradient(circle var(--val-glow-size) at var(--val-glow-position),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-secondary-rgb),calc(var(--val-glow-intensity) * .7)) 35%,rgba(var(--val-glow-color-secondary-rgb),0) 70%)}:host(.val-glow--linear):before{background-image:linear-gradient(var(--val-glow-angle),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-rgb),0) 100%)}:host(.val-glow--linear.val-glow--dual):before{background-image:linear-gradient(var(--val-glow-angle),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-secondary-rgb),calc(var(--val-glow-intensity) * .8)) 50%,rgba(var(--val-glow-color-secondary-rgb),0) 100%)}:host(.val-glow--animated):before{animation:val-glow-drift 16s ease-in-out infinite alternate}@keyframes val-glow-drift{0%{transform:translateZ(0) scale(1);opacity:1}50%{transform:translate3d(-2%,1.5%,0) scale(1.05);opacity:.95}to{transform:translate3d(2%,-1.5%,0) scale(1.02);opacity:1}}@media (prefers-reduced-motion: reduce){:host(.val-glow--animated):before{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
522
|
+
}
|
|
523
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GlowComponent, decorators: [{
|
|
524
|
+
type: Component,
|
|
525
|
+
args: [{ selector: 'val-glow', standalone: true, template: `<ng-content />`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
526
|
+
class: 'val-glow',
|
|
527
|
+
'[class.val-glow--radial]': "shape() === 'radial'",
|
|
528
|
+
'[class.val-glow--linear]': "shape() === 'linear'",
|
|
529
|
+
'[class.val-glow--animated]': 'animated()',
|
|
530
|
+
'[class.val-glow--dual]': 'hasSecondary()',
|
|
531
|
+
'[style.--val-glow-color-rgb]': 'colorRgbVar()',
|
|
532
|
+
'[style.--val-glow-color-secondary-rgb]': 'secondaryColorRgbVar()',
|
|
533
|
+
'[style.--val-glow-position]': 'positionCss()',
|
|
534
|
+
'[style.--val-glow-size]': 'sizeCss()',
|
|
535
|
+
'[style.--val-glow-intensity]': 'intensityValue()',
|
|
536
|
+
'[style.--val-glow-angle]': 'angleCss()',
|
|
537
|
+
'[style.--val-glow-blend-mode]': 'blendMode()',
|
|
538
|
+
}, styles: [":host{position:relative;display:block;isolation:isolate;overflow:hidden;--val-glow-color-rgb: var(--ion-color-primary-rgb);--val-glow-color-secondary-rgb: var(--val-glow-color-rgb);--val-glow-position: 50% 50%;--val-glow-size: 800px;--val-glow-intensity: .18;--val-glow-angle: 180deg;--val-glow-blend-mode: normal}:host:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background-blend-mode:var(--val-glow-blend-mode);background-repeat:no-repeat}:host(.val-glow--radial):before{background-image:radial-gradient(circle var(--val-glow-size) at var(--val-glow-position),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-rgb),0) 70%)}:host(.val-glow--radial.val-glow--dual):before{background-image:radial-gradient(circle var(--val-glow-size) at var(--val-glow-position),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-secondary-rgb),calc(var(--val-glow-intensity) * .7)) 35%,rgba(var(--val-glow-color-secondary-rgb),0) 70%)}:host(.val-glow--linear):before{background-image:linear-gradient(var(--val-glow-angle),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-rgb),0) 100%)}:host(.val-glow--linear.val-glow--dual):before{background-image:linear-gradient(var(--val-glow-angle),rgba(var(--val-glow-color-rgb),var(--val-glow-intensity)) 0%,rgba(var(--val-glow-color-secondary-rgb),calc(var(--val-glow-intensity) * .8)) 50%,rgba(var(--val-glow-color-secondary-rgb),0) 100%)}:host(.val-glow--animated):before{animation:val-glow-drift 16s ease-in-out infinite alternate}@keyframes val-glow-drift{0%{transform:translateZ(0) scale(1);opacity:1}50%{transform:translate3d(-2%,1.5%,0) scale(1.05);opacity:.95}to{transform:translate3d(2%,-1.5%,0) scale(1.02);opacity:1}}@media (prefers-reduced-motion: reduce){:host(.val-glow--animated):before{animation:none}}\n"] }]
|
|
539
|
+
}] });
|
|
540
|
+
|
|
448
541
|
/**
|
|
449
542
|
* val-container
|
|
450
543
|
*
|
|
@@ -32055,7 +32148,7 @@ class LoginComponent {
|
|
|
32055
32148
|
this.stopResetResendCooldown();
|
|
32056
32149
|
}
|
|
32057
32150
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32058
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoginComponent, isStandalone: true, selector: "val-login", inputs: { props: "props" }, outputs: { onSuccess: "onSuccess", onError: "onError", onMFARequired: "onMFARequired" }, ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps()\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>{{ t('orContinueWith') }}</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) {\n @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithGoogle') }}\n }\n @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithApple') }}\n }\n @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithMicrosoft') }}\n }\n }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('noAccount') }}\n <a (click)=\"openRegisterModal()\">{{ t('register') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n {{ t('forgotLink') }}\n <a (click)=\"openForgotPasswordModal()\">{{ t('recoverPassword') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"medium\">\n <p>\n {{ t('legalPrefix') }}\n @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n }\n {{ t('legalSuffix') }}\n @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">{{ t('termsAndConditions') }}</a>\n } @else {\n <span>{{ t('termsAndConditions') }}</span>\n }\n {{ t('and') }}\n @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">{{ t('privacyPolicy') }}</a>\n } @else {\n <span>{{ t('privacyPolicy') }}</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"closeRegisterModal()\">{{ t('signIn') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps()\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps()\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps()\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }}\n @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resetResendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendResetCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }] }); }
|
|
32151
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoginComponent, isStandalone: true, selector: "val-login", inputs: { props: "props" }, outputs: { onSuccess: "onSuccess", onError: "onError", onMFARequired: "onMFARequired" }, ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps()\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>{{ t('orContinueWith') }}</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) { @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithGoogle') }} } @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithApple') }} } @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithMicrosoft') }} } }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('noAccount') }}\n <a (click)=\"openRegisterModal()\">{{ t('register') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n {{ t('forgotLink') }}\n <a (click)=\"openForgotPasswordModal()\">{{ t('recoverPassword') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"dark\">\n <p>\n {{ t('legalPrefix') }} @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n } {{ t('legalSuffix') }} @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">{{ t('termsAndConditions') }}</a>\n } @else {\n <span>{{ t('termsAndConditions') }}</span>\n } {{ t('and') }} @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">{{ t('privacyPolicy') }}</a>\n } @else {\n <span>{{ t('privacyPolicy') }}</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"closeRegisterModal()\">{{ t('signIn') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps()\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }} @if (resendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps()\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps()\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }} @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resetResendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendResetCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }] }); }
|
|
32059
32152
|
}
|
|
32060
32153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, decorators: [{
|
|
32061
32154
|
type: Component,
|
|
@@ -32071,7 +32164,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
32071
32164
|
IonToolbar,
|
|
32072
32165
|
FormComponent,
|
|
32073
32166
|
ImageComponent,
|
|
32074
|
-
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n
|
|
32167
|
+
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo -->\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n\n <!-- Login Form -->\n <val-form [props]=\"loginFormProps()\" (onSubmit)=\"loginHandler($event)\" />\n\n <!-- OAuth Section -->\n @if (config.showOAuth && config.oauthProviders.length > 0) {\n <div class=\"oauth-separator\">\n <span>{{ t('orContinueWith') }}</span>\n </div>\n\n <div class=\"oauth-buttons\">\n @for (provider of config.oauthProviders; track provider) {\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n color=\"dark\"\n (click)=\"loginWithOAuth(provider)\"\n [disabled]=\"isOAuthLoading\"\n >\n @switch (provider) { @case ('google') {\n <ion-icon slot=\"start\" name=\"logo-google\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithGoogle') }} } @case ('apple') {\n <ion-icon slot=\"start\" name=\"logo-apple\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithApple') }} } @case ('microsoft') {\n <ion-icon slot=\"start\" name=\"logo-microsoft\"></ion-icon>\n {{ isOAuthLoading ? t('connecting') : t('continueWithMicrosoft') }} } }\n </ion-button>\n }\n </div>\n }\n\n <!-- Register Link -->\n @if (config.showRegister) {\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('noAccount') }}\n <a (click)=\"openRegisterModal()\">{{ t('register') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Forgot Password Link -->\n @if (config.showForgotPassword) {\n <div class=\"auth-link forgot-password\">\n <ion-text color=\"dark\">\n {{ t('forgotLink') }}\n <a (click)=\"openForgotPasswordModal()\">{{ t('recoverPassword') }}</a>\n </ion-text>\n </div>\n }\n\n <!-- Legal Notice -->\n @if (props.legal) {\n <div class=\"legal-notice\">\n <ion-text color=\"dark\">\n <p>\n {{ t('legalPrefix') }} @if (props.legal.companyLink) {\n <a [href]=\"props.legal.companyLink\"><strong>{{ props.legal.companyName }}</strong></a>\n } @else {\n <strong>{{ props.legal.companyName }}</strong>\n } {{ t('legalSuffix') }} @if (props.legal.termsLink) {\n <a [href]=\"props.legal.termsLink\">{{ t('termsAndConditions') }}</a>\n } @else {\n <span>{{ t('termsAndConditions') }}</span>\n } {{ t('and') }} @if (props.legal.privacyLink) {\n <a [href]=\"props.legal.privacyLink\">{{ t('privacyPolicy') }}</a>\n } @else {\n <span>{{ t('privacyPolicy') }}</span>\n }.\n </p>\n </ion-text>\n </div>\n }\n</div>\n\n<!-- Register Modal -->\n<ion-modal [isOpen]=\"isRegisterModalOpen\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeRegisterModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"closeRegisterModal()\">{{ t('signIn') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Verify Email Modal -->\n<ion-modal [isOpen]=\"isVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"verifyFormProps()\" (onSubmit)=\"verifyHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }} @if (resendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Forgot Password Modal -->\n<ion-modal [isOpen]=\"isForgotPasswordModalOpen\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeForgotPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"forgotPasswordFormProps()\" (onSubmit)=\"forgotPasswordHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- Reset Password Modal -->\n<ion-modal [isOpen]=\"isResetPasswordModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeResetPasswordModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"resetPasswordFormProps()\" (onSubmit)=\"resetPasswordHandler($event)\" />\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('noCodeReceived') }} @if (resetResendCooldown > 0) {\n <span class=\"cooldown\">{{ t('resendIn', { seconds: resetResendCooldown.toString() }) }}</span>\n } @else {\n <a (click)=\"resendResetCode()\">{{ t('resend') }}</a>\n }\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Verify Modal -->\n<ion-modal [isOpen]=\"isMFAVerifyModalOpen\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" (click)=\"closeMFAVerifyModal()\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <section class=\"modal-form-section\">\n @if (props.logo) {\n <div class=\"logo-container\">\n <val-image [props]=\"props.logo\" />\n </div>\n }\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem;background:var(--ion-color-light);border-radius:16px;box-shadow:0 2px 8px #00000014}.logo-container{max-width:130px;margin-bottom:1.5rem}.auth-link{text-align:center;margin-top:1rem;font-size:.9rem}.auth-link a{color:var(--ion-color-primary);text-decoration:none;font-weight:500;cursor:pointer}.auth-link a:hover{text-decoration:underline}.oauth-separator{display:flex;align-items:center;margin:1.5rem 0}.oauth-separator:before,.oauth-separator:after{content:\"\";flex:1;height:1px;background:var(--ion-color-medium-tint)}.oauth-separator span{padding:0 1rem;color:var(--ion-color-dark);font-size:.85rem}.oauth-buttons{margin-bottom:1rem}.oauth-buttons ion-button{--border-radius: 8px;--border-width: 1px}.oauth-buttons ion-icon{font-size:1.2rem;margin-right:.5rem}.legal-notice{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--ion-color-medium-tint)}.legal-notice p{font-size:.75rem;line-height:1.5;text-align:center;margin:0}.legal-notice a{color:var(--ion-color-primary);text-decoration:none}.legal-notice a:hover{text-decoration:underline}.resend-link{text-align:center;margin-top:1rem;font-size:.9rem}.resend-link a{color:var(--ion-color-primary);cursor:pointer;font-weight:500}.resend-link a:hover{text-decoration:underline}.resend-link .cooldown{color:var(--ion-color-medium)}\n"] }]
|
|
32075
32168
|
}], propDecorators: { props: [{
|
|
32076
32169
|
type: Input
|
|
32077
32170
|
}], onSuccess: [{
|
|
@@ -35554,6 +35647,263 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35554
35647
|
* Cliente NUNCA escribe directo — todas las mutaciones via PUT /v2/auth/preferences.
|
|
35555
35648
|
*/
|
|
35556
35649
|
|
|
35650
|
+
/**
|
|
35651
|
+
* DeviceRegistrationService — orquesta el flow combinado de:
|
|
35652
|
+
* - `PreferencesService.notificationsMaster` (flag user)
|
|
35653
|
+
* - `Notification.permission` del browser
|
|
35654
|
+
* - `MessagingService` (FCM: requestPermission, getToken, deleteToken)
|
|
35655
|
+
* - Backend `/v2/users/me/devices` (POST/GET/DELETE)
|
|
35656
|
+
*
|
|
35657
|
+
* Auto-sync:
|
|
35658
|
+
* - master=true & permission=granted & sin token → auto-register (silent, sin prompt).
|
|
35659
|
+
* - master=false & device registrado → auto-unregister (FCM deleteToken + DELETE backend).
|
|
35660
|
+
* - permission=denied → status='error', requiere acción manual del user.
|
|
35661
|
+
*
|
|
35662
|
+
* Cliente:
|
|
35663
|
+
* - `requestAndRegister()` para CTA "permitir notificaciones" (dispara browser prompt).
|
|
35664
|
+
* - `unregister()` para "olvidar este dispositivo".
|
|
35665
|
+
* - `refreshPermission()` tras volver al tab (focus) — el browser puede haber cambiado el estado.
|
|
35666
|
+
*/
|
|
35667
|
+
class DeviceRegistrationService {
|
|
35668
|
+
constructor(config, platformId, http, messaging, prefs, auth) {
|
|
35669
|
+
this.config = config;
|
|
35670
|
+
this.platformId = platformId;
|
|
35671
|
+
this.http = http;
|
|
35672
|
+
this.messaging = messaging;
|
|
35673
|
+
this.prefs = prefs;
|
|
35674
|
+
this.auth = auth;
|
|
35675
|
+
this._permission = signal('default');
|
|
35676
|
+
this._status = signal('idle');
|
|
35677
|
+
this._currentToken = signal(null);
|
|
35678
|
+
this._currentDeviceId = signal(null);
|
|
35679
|
+
this._lastError = signal(null);
|
|
35680
|
+
this._isSupported = signal(false);
|
|
35681
|
+
this.permission = this._permission.asReadonly();
|
|
35682
|
+
this.status = this._status.asReadonly();
|
|
35683
|
+
this.currentToken = this._currentToken.asReadonly();
|
|
35684
|
+
this.currentDeviceId = this._currentDeviceId.asReadonly();
|
|
35685
|
+
this.lastError = this._lastError.asReadonly();
|
|
35686
|
+
this.isSupported = this._isSupported.asReadonly();
|
|
35687
|
+
/** true si el browser puede recibir push y el user ya autorizó */
|
|
35688
|
+
this.canReceive = computed(() => this._isSupported() && this._permission() === 'granted' && this._status() === 'registered');
|
|
35689
|
+
this.autoSyncInFlight = false;
|
|
35690
|
+
if (!isPlatformBrowser(this.platformId))
|
|
35691
|
+
return;
|
|
35692
|
+
this._isSupported.set(this.detectSupport());
|
|
35693
|
+
this.refreshPermission();
|
|
35694
|
+
// Refrescar permission al volver al tab — el user pudo cambiarla en browser settings.
|
|
35695
|
+
window.addEventListener('focus', () => this.refreshPermission());
|
|
35696
|
+
const destroyRef = inject(DestroyRef);
|
|
35697
|
+
destroyRef.onDestroy(() => {
|
|
35698
|
+
window.removeEventListener('focus', () => this.refreshPermission());
|
|
35699
|
+
});
|
|
35700
|
+
// Auto-sync: reaccionar a cambios de master / permission / user.
|
|
35701
|
+
effect(() => {
|
|
35702
|
+
const user = this.auth.user();
|
|
35703
|
+
const master = this.prefs.notificationsMaster();
|
|
35704
|
+
const perm = this._permission();
|
|
35705
|
+
const hasDevice = !!this._currentDeviceId();
|
|
35706
|
+
if (!user)
|
|
35707
|
+
return;
|
|
35708
|
+
if (!this.prefs.synced())
|
|
35709
|
+
return;
|
|
35710
|
+
if (this.autoSyncInFlight)
|
|
35711
|
+
return;
|
|
35712
|
+
// Master OFF + device registrado → unregister.
|
|
35713
|
+
if (!master && hasDevice) {
|
|
35714
|
+
void this.unregister();
|
|
35715
|
+
return;
|
|
35716
|
+
}
|
|
35717
|
+
// Master ON + granted + sin device → register silent (no prompt, ya granted).
|
|
35718
|
+
if (master && perm === 'granted' && !hasDevice && this._status() === 'idle') {
|
|
35719
|
+
void this.registerSilent();
|
|
35720
|
+
}
|
|
35721
|
+
});
|
|
35722
|
+
}
|
|
35723
|
+
/**
|
|
35724
|
+
* CTA explícito del user: dispara `Notification.requestPermission()` + registro.
|
|
35725
|
+
* Único método que puede generar el browser prompt.
|
|
35726
|
+
*/
|
|
35727
|
+
async requestAndRegister() {
|
|
35728
|
+
if (!this._isSupported()) {
|
|
35729
|
+
this._lastError.set('not-supported');
|
|
35730
|
+
this._status.set('error');
|
|
35731
|
+
return;
|
|
35732
|
+
}
|
|
35733
|
+
this.autoSyncInFlight = true;
|
|
35734
|
+
this._status.set('registering');
|
|
35735
|
+
this._lastError.set(null);
|
|
35736
|
+
try {
|
|
35737
|
+
const token = await this.messaging.requestPermission();
|
|
35738
|
+
this.refreshPermission();
|
|
35739
|
+
if (!token) {
|
|
35740
|
+
this._status.set('error');
|
|
35741
|
+
this._lastError.set(this._permission() === 'denied' ? 'permission-denied' : 'no-token');
|
|
35742
|
+
return;
|
|
35743
|
+
}
|
|
35744
|
+
await this.registerDeviceBackend(token);
|
|
35745
|
+
}
|
|
35746
|
+
catch (err) {
|
|
35747
|
+
this._status.set('error');
|
|
35748
|
+
this._lastError.set(this.errorMessage(err));
|
|
35749
|
+
}
|
|
35750
|
+
finally {
|
|
35751
|
+
this.autoSyncInFlight = false;
|
|
35752
|
+
}
|
|
35753
|
+
}
|
|
35754
|
+
/**
|
|
35755
|
+
* Unregister: borra token FCM + DELETE backend del device actual.
|
|
35756
|
+
* Idempotente: si no hay device, no hace nada.
|
|
35757
|
+
*/
|
|
35758
|
+
async unregister() {
|
|
35759
|
+
const deviceId = this._currentDeviceId();
|
|
35760
|
+
if (!deviceId && !this._currentToken()) {
|
|
35761
|
+
this._status.set('idle');
|
|
35762
|
+
return;
|
|
35763
|
+
}
|
|
35764
|
+
this.autoSyncInFlight = true;
|
|
35765
|
+
this._status.set('unregistering');
|
|
35766
|
+
this._lastError.set(null);
|
|
35767
|
+
try {
|
|
35768
|
+
if (deviceId) {
|
|
35769
|
+
await firstValueFrom(this.http.delete(`${this.config.apiUrl}/v2/users/me/devices/${deviceId}`));
|
|
35770
|
+
}
|
|
35771
|
+
try {
|
|
35772
|
+
await this.messaging.deleteToken();
|
|
35773
|
+
}
|
|
35774
|
+
catch {
|
|
35775
|
+
// deleteToken puede fallar si el token ya no existe; aceptable.
|
|
35776
|
+
}
|
|
35777
|
+
this._currentToken.set(null);
|
|
35778
|
+
this._currentDeviceId.set(null);
|
|
35779
|
+
this._status.set('idle');
|
|
35780
|
+
}
|
|
35781
|
+
catch (err) {
|
|
35782
|
+
this._status.set('error');
|
|
35783
|
+
this._lastError.set(this.errorMessage(err));
|
|
35784
|
+
}
|
|
35785
|
+
finally {
|
|
35786
|
+
this.autoSyncInFlight = false;
|
|
35787
|
+
}
|
|
35788
|
+
}
|
|
35789
|
+
/** Refresca `permission` desde `Notification.permission` del browser. */
|
|
35790
|
+
refreshPermission() {
|
|
35791
|
+
if (!isPlatformBrowser(this.platformId) || !('Notification' in window)) {
|
|
35792
|
+
this._permission.set('default');
|
|
35793
|
+
return;
|
|
35794
|
+
}
|
|
35795
|
+
this._permission.set(Notification.permission);
|
|
35796
|
+
}
|
|
35797
|
+
/** Lista devices del user actual desde backend. Útil para vista Seguridad. */
|
|
35798
|
+
async listDevices() {
|
|
35799
|
+
const res = await firstValueFrom(this.http.get(`${this.config.apiUrl}/v2/users/me/devices`));
|
|
35800
|
+
return res.devices;
|
|
35801
|
+
}
|
|
35802
|
+
/** Reintenta el último flow fallido. */
|
|
35803
|
+
async retry() {
|
|
35804
|
+
if (this._permission() === 'granted') {
|
|
35805
|
+
await this.registerSilent();
|
|
35806
|
+
}
|
|
35807
|
+
else {
|
|
35808
|
+
await this.requestAndRegister();
|
|
35809
|
+
}
|
|
35810
|
+
}
|
|
35811
|
+
// ---------------------------------------------------------------------------
|
|
35812
|
+
// Privados
|
|
35813
|
+
// ---------------------------------------------------------------------------
|
|
35814
|
+
/** Register sin prompt — asume permission ya granted. */
|
|
35815
|
+
async registerSilent() {
|
|
35816
|
+
this.autoSyncInFlight = true;
|
|
35817
|
+
this._status.set('registering');
|
|
35818
|
+
this._lastError.set(null);
|
|
35819
|
+
try {
|
|
35820
|
+
const token = await this.messaging.getToken();
|
|
35821
|
+
if (!token) {
|
|
35822
|
+
this._status.set('error');
|
|
35823
|
+
this._lastError.set('no-token');
|
|
35824
|
+
return;
|
|
35825
|
+
}
|
|
35826
|
+
await this.registerDeviceBackend(token);
|
|
35827
|
+
}
|
|
35828
|
+
catch (err) {
|
|
35829
|
+
this._status.set('error');
|
|
35830
|
+
this._lastError.set(this.errorMessage(err));
|
|
35831
|
+
}
|
|
35832
|
+
finally {
|
|
35833
|
+
this.autoSyncInFlight = false;
|
|
35834
|
+
}
|
|
35835
|
+
}
|
|
35836
|
+
async registerDeviceBackend(token) {
|
|
35837
|
+
const env = this.detectEnv();
|
|
35838
|
+
const body = {
|
|
35839
|
+
token,
|
|
35840
|
+
platform: 'web',
|
|
35841
|
+
browser: env.browser,
|
|
35842
|
+
os: env.os,
|
|
35843
|
+
appVersion: env.appVersion,
|
|
35844
|
+
};
|
|
35845
|
+
const res = await firstValueFrom(this.http.post(`${this.config.apiUrl}/v2/users/me/devices`, body));
|
|
35846
|
+
this._currentToken.set(token);
|
|
35847
|
+
this._currentDeviceId.set(res.device.deviceId);
|
|
35848
|
+
this._status.set('registered');
|
|
35849
|
+
}
|
|
35850
|
+
detectSupport() {
|
|
35851
|
+
if (!isPlatformBrowser(this.platformId))
|
|
35852
|
+
return false;
|
|
35853
|
+
return 'Notification' in window && 'serviceWorker' in navigator;
|
|
35854
|
+
}
|
|
35855
|
+
detectEnv() {
|
|
35856
|
+
const ua = navigator.userAgent;
|
|
35857
|
+
let browser = 'Unknown';
|
|
35858
|
+
if (/edg/i.test(ua))
|
|
35859
|
+
browser = 'Edge';
|
|
35860
|
+
else if (/chrome|chromium|crios/i.test(ua))
|
|
35861
|
+
browser = 'Chrome';
|
|
35862
|
+
else if (/firefox|fxios/i.test(ua))
|
|
35863
|
+
browser = 'Firefox';
|
|
35864
|
+
else if (/safari/i.test(ua))
|
|
35865
|
+
browser = 'Safari';
|
|
35866
|
+
let os = 'Unknown';
|
|
35867
|
+
if (/Windows/i.test(ua))
|
|
35868
|
+
os = 'Windows';
|
|
35869
|
+
else if (/Android/i.test(ua))
|
|
35870
|
+
os = 'Android';
|
|
35871
|
+
else if (/iPhone|iPad|iPod/i.test(ua))
|
|
35872
|
+
os = 'iOS';
|
|
35873
|
+
else if (/Mac OS X/i.test(ua))
|
|
35874
|
+
os = 'macOS';
|
|
35875
|
+
else if (/Linux/i.test(ua))
|
|
35876
|
+
os = 'Linux';
|
|
35877
|
+
return { browser, os, appVersion: 'web-1.0' };
|
|
35878
|
+
}
|
|
35879
|
+
errorMessage(err) {
|
|
35880
|
+
if (err instanceof Error)
|
|
35881
|
+
return err.message;
|
|
35882
|
+
if (typeof err === 'string')
|
|
35883
|
+
return err;
|
|
35884
|
+
return 'unknown-error';
|
|
35885
|
+
}
|
|
35886
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DeviceRegistrationService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: PLATFORM_ID }, { token: i1$8.HttpClient }, { token: MessagingService }, { token: PreferencesService }, { token: AuthService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
35887
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DeviceRegistrationService, providedIn: 'root' }); }
|
|
35888
|
+
}
|
|
35889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DeviceRegistrationService, decorators: [{
|
|
35890
|
+
type: Injectable,
|
|
35891
|
+
args: [{ providedIn: 'root' }]
|
|
35892
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
35893
|
+
type: Inject,
|
|
35894
|
+
args: [VALTECH_AUTH_CONFIG]
|
|
35895
|
+
}] }, { type: Object, decorators: [{
|
|
35896
|
+
type: Inject,
|
|
35897
|
+
args: [PLATFORM_ID]
|
|
35898
|
+
}] }, { type: i1$8.HttpClient }, { type: MessagingService }, { type: PreferencesService }, { type: AuthService }] });
|
|
35899
|
+
|
|
35900
|
+
/**
|
|
35901
|
+
* Devices types específicos del `DeviceRegistrationService`.
|
|
35902
|
+
* Los contratos base (`RegisterDeviceRequest`, `RegisterDeviceResponse`,
|
|
35903
|
+
* `ListDevicesResponse`, `DeviceInfo`, `DevicePlatform`) viven en `auth/types.ts`
|
|
35904
|
+
* — este archivo solo agrega lo que falta.
|
|
35905
|
+
*/
|
|
35906
|
+
|
|
35557
35907
|
/**
|
|
35558
35908
|
* Cross-Platform Version Helpers
|
|
35559
35909
|
*
|
|
@@ -42715,5 +43065,5 @@ function buildFooterLinks(links, t, resolver) {
|
|
|
42715
43065
|
* Generated bundle index. Do not edit.
|
|
42716
43066
|
*/
|
|
42717
43067
|
|
|
42718
|
-
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AppConfigService, ArticleBuilder, ArticleComponent, AuthBackgroundComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FabComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RightsFooterComponent, RotatingTextComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UpdateBannerComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_DEFAULT_CONTENT, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_SOCIAL_LINKS, VERSION, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
43068
|
+
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AppConfigService, ArticleBuilder, ArticleComponent, AuthBackgroundComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceRegistrationService, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FabComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RightsFooterComponent, RotatingTextComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UpdateBannerComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_DEFAULT_CONTENT, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_SOCIAL_LINKS, VERSION, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
42719
43069
|
//# sourceMappingURL=valtech-components.mjs.map
|