valtech-components 2.0.730 → 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/bottom-nav/bottom-nav.component.mjs +4 -4
- package/esm2022/lib/components/organisms/bottom-nav/types.mjs +2 -2
- package/esm2022/lib/components/organisms/login/login.component.mjs +3 -3
- package/esm2022/lib/config/company-footer.config.mjs +34 -20
- 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/services/legal-link/legal-link.service.mjs +68 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +10 -1
- package/fesm2022/valtech-components.mjs +458 -28
- 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/bottom-nav/types.d.ts +1 -1
- package/lib/components/organisms/toolbar/toolbar.component.d.ts +1 -1
- package/lib/config/company-footer.config.d.ts +24 -4
- 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/services/legal-link/legal-link.service.d.ts +59 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +4 -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: [{
|
|
@@ -32472,7 +32565,7 @@ const BOTTOM_NAV_DEFAULTS = {
|
|
|
32472
32565
|
hideLabels: false,
|
|
32473
32566
|
safeArea: true,
|
|
32474
32567
|
animation: 'scale',
|
|
32475
|
-
maxWidth: '
|
|
32568
|
+
maxWidth: 'md',
|
|
32476
32569
|
theme: {
|
|
32477
32570
|
background: 'var(--ion-background-color)',
|
|
32478
32571
|
activeColor: 'primary',
|
|
@@ -32647,7 +32740,7 @@ class BottomNavComponent {
|
|
|
32647
32740
|
return 'none';
|
|
32648
32741
|
case undefined:
|
|
32649
32742
|
case '':
|
|
32650
|
-
return 'var(--val-container-
|
|
32743
|
+
return 'var(--val-container-md, 720px)';
|
|
32651
32744
|
default:
|
|
32652
32745
|
return v;
|
|
32653
32746
|
}
|
|
@@ -32773,7 +32866,7 @@ class BottomNavComponent {
|
|
|
32773
32866
|
}
|
|
32774
32867
|
</div>
|
|
32775
32868
|
</nav>
|
|
32776
|
-
`, isInline: true, styles: [":host{display:block;position:fixed;bottom:0;left:0;right:0;z-index:100;pointer-events:none}.bottom-nav{--bottom-nav-bg: var(--ion-background-color);--bottom-nav-active: var(--ion-color-primary);--bottom-nav-inactive: var(--ion-color-medium);--bottom-nav-radius: 16px 16px 0 0;--bottom-nav-height: 64px;--bottom-nav-fab-size: 56px;--bottom-nav-max-width: var(--val-container-
|
|
32869
|
+
`, isInline: true, styles: [":host{display:block;position:fixed;bottom:0;left:0;right:0;z-index:100;pointer-events:none}.bottom-nav{--bottom-nav-bg: var(--ion-background-color);--bottom-nav-active: var(--ion-color-primary);--bottom-nav-inactive: var(--ion-color-medium);--bottom-nav-radius: 16px 16px 0 0;--bottom-nav-height: 64px;--bottom-nav-fab-size: 56px;--bottom-nav-max-width: var(--val-container-md, 720px);--fab-color: var(--ion-color-primary);pointer-events:auto;background:var(--bottom-nav-bg);border-radius:var(--bottom-nav-radius);height:var(--bottom-nav-height);padding:0 8px;max-width:var(--bottom-nav-max-width);margin:0 auto}.bottom-nav--elevated{box-shadow:0 -4px 20px #00000014}.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.75);backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border-top:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.06)}.bottom-nav--floating{margin:0 auto 8px;width:calc(100% - 32px);border-radius:32px;border:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.08);box-shadow:0 4px 24px #00000014,0 8px 32px #0000000a;--bottom-nav-radius: 32px}.bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.82);backdrop-filter:blur(28px) saturate(200%);-webkit-backdrop-filter:blur(28px) saturate(200%);border:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.08)}.bottom-nav--floating.bottom-nav--elevated{box-shadow:0 4px 24px #0000001a,0 12px 48px #00000014}.bottom-nav--floating.bottom-nav--safe-area{margin-bottom:calc(8px + env(safe-area-inset-bottom,0))}.bottom-nav--safe-area{padding-bottom:env(safe-area-inset-bottom,0);height:calc(var(--bottom-nav-height) + env(safe-area-inset-bottom,0))}.bottom-nav__container{display:flex;align-items:center;justify-content:space-around;height:var(--bottom-nav-height);max-width:500px;margin:0 auto}.bottom-nav__tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;height:100%;padding:8px 4px;background:transparent;border:none;cursor:pointer;position:relative;overflow:hidden;color:var(--bottom-nav-inactive);transition:color .2s ease;max-width:80px;--ripple-color: var(--bottom-nav-active)}.bottom-nav__tab:focus-visible{outline:2px solid var(--bottom-nav-active);outline-offset:-2px;border-radius:8px}.bottom-nav__tab--active{color:var(--bottom-nav-active)}.bottom-nav__tab--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bottom-nav__tab[data-animation=scale] .bottom-nav__tab-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}.bottom-nav__tab[data-animation=scale].bottom-nav__tab--active .bottom-nav__tab-icon{transform:scale(1.15)}.bottom-nav__tab[data-animation=fade]{transition:opacity .2s ease,color .2s ease}.bottom-nav__tab[data-animation=fade]:not(.bottom-nav__tab--active){opacity:.6}.bottom-nav__tab[data-animation=slide] .bottom-nav__tab-label{transition:transform .2s ease,opacity .2s ease;transform:translateY(6px);opacity:0}.bottom-nav__tab[data-animation=slide].bottom-nav__tab--active .bottom-nav__tab-label{transform:translateY(0);opacity:1}.bottom-nav__tab-icon{position:relative;font-size:24px;line-height:1}.bottom-nav__tab-icon ion-icon{display:block}.bottom-nav__tab-label{font-size:11px;font-weight:500;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;letter-spacing:.01em}.bottom-nav__badge{position:absolute;top:-4px;right:-10px;min-width:18px;height:18px;padding:0 5px;font-size:10px;font-weight:600;line-height:18px;text-align:center;color:#fff;background-color:var(--ion-color-danger);border-radius:9px;box-shadow:0 1px 3px #0003}.bottom-nav__badge--dot{min-width:10px;width:10px;height:10px;padding:0;top:-2px;right:-4px;border-radius:50%}.bottom-nav__fab{position:relative;flex-shrink:0;width:var(--bottom-nav-fab-size);height:var(--bottom-nav-fab-size);margin:0 12px;margin-top:calc(var(--bottom-nav-fab-size) * -.35);background:var(--fab-color);border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#fff;font-size:28px;box-shadow:0 4px 14px rgba(var(--ion-color-primary-rgb, 56, 128, 255),.4);transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s ease;overflow:hidden;--ripple-color: rgba(255, 255, 255, .3)}.bottom-nav__fab:hover{transform:scale(1.08);box-shadow:0 6px 20px rgba(var(--ion-color-primary-rgb, 56, 128, 255),.5)}.bottom-nav__fab:active{transform:scale(.95)}.bottom-nav__fab:focus-visible{outline:3px solid white;outline-offset:2px}.bottom-nav__fab--small{--bottom-nav-fab-size: 48px;font-size:24px;margin-top:-14.4px}.bottom-nav__fab ion-icon{display:block}.bottom-nav--hide-labels{--bottom-nav-height: 56px}.bottom-nav--hide-labels .bottom-nav__tab-label{display:none}.bottom-nav--hide-labels .bottom-nav__tab-icon{font-size:26px}@media (prefers-color-scheme: dark){.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 0, 0, 0),.8);border-top-color:#ffffff14}.bottom-nav--elevated{box-shadow:0 -4px 20px #00000040}.bottom-nav--floating{border-color:#ffffff1a;box-shadow:0 4px 24px #0003,0 8px 32px #00000026}.bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.88);border-color:#ffffff1a}.bottom-nav__fab{box-shadow:0 4px 14px #0006}.bottom-nav__fab:hover{box-shadow:0 6px 20px #00000080}}:host-context(.dark) .bottom-nav--translucent,:host-context(body.dark) .bottom-nav--translucent,:host-context([data-theme=dark]) .bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.85);border-top-color:#ffffff14}:host-context(.dark) .bottom-nav--elevated,:host-context(body.dark) .bottom-nav--elevated,:host-context([data-theme=dark]) .bottom-nav--elevated{box-shadow:0 -4px 20px #0000004d}:host-context(.dark) .bottom-nav--floating,:host-context(body.dark) .bottom-nav--floating,:host-context([data-theme=dark]) .bottom-nav--floating{border-color:#ffffff1a;box-shadow:0 4px 24px #0003,0 8px 32px #00000026}:host-context(.dark) .bottom-nav--floating.bottom-nav--translucent,:host-context(body.dark) .bottom-nav--floating.bottom-nav--translucent,:host-context([data-theme=dark]) .bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.88);border-color:#ffffff1a}:host-context(.dark) .bottom-nav__fab,:host-context(body.dark) .bottom-nav__fab,:host-context([data-theme=dark]) .bottom-nav__fab{box-shadow:0 4px 14px #00000080}:host-context(.dark) .bottom-nav__fab:hover,:host-context(body.dark) .bottom-nav__fab:hover,:host-context([data-theme=dark]) .bottom-nav__fab:hover{box-shadow:0 6px 20px #0009}@supports (padding-bottom: env(safe-area-inset-bottom)){.bottom-nav--safe-area .bottom-nav__container{height:var(--bottom-nav-height)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonRippleEffect, selector: "ion-ripple-effect", inputs: ["type"] }] }); }
|
|
32777
32870
|
}
|
|
32778
32871
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BottomNavComponent, decorators: [{
|
|
32779
32872
|
type: Component,
|
|
@@ -32847,7 +32940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
32847
32940
|
}
|
|
32848
32941
|
</div>
|
|
32849
32942
|
</nav>
|
|
32850
|
-
`, styles: [":host{display:block;position:fixed;bottom:0;left:0;right:0;z-index:100;pointer-events:none}.bottom-nav{--bottom-nav-bg: var(--ion-background-color);--bottom-nav-active: var(--ion-color-primary);--bottom-nav-inactive: var(--ion-color-medium);--bottom-nav-radius: 16px 16px 0 0;--bottom-nav-height: 64px;--bottom-nav-fab-size: 56px;--bottom-nav-max-width: var(--val-container-
|
|
32943
|
+
`, styles: [":host{display:block;position:fixed;bottom:0;left:0;right:0;z-index:100;pointer-events:none}.bottom-nav{--bottom-nav-bg: var(--ion-background-color);--bottom-nav-active: var(--ion-color-primary);--bottom-nav-inactive: var(--ion-color-medium);--bottom-nav-radius: 16px 16px 0 0;--bottom-nav-height: 64px;--bottom-nav-fab-size: 56px;--bottom-nav-max-width: var(--val-container-md, 720px);--fab-color: var(--ion-color-primary);pointer-events:auto;background:var(--bottom-nav-bg);border-radius:var(--bottom-nav-radius);height:var(--bottom-nav-height);padding:0 8px;max-width:var(--bottom-nav-max-width);margin:0 auto}.bottom-nav--elevated{box-shadow:0 -4px 20px #00000014}.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.75);backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border-top:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.06)}.bottom-nav--floating{margin:0 auto 8px;width:calc(100% - 32px);border-radius:32px;border:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.08);box-shadow:0 4px 24px #00000014,0 8px 32px #0000000a;--bottom-nav-radius: 32px}.bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.82);backdrop-filter:blur(28px) saturate(200%);-webkit-backdrop-filter:blur(28px) saturate(200%);border:1px solid rgba(var(--ion-text-color-rgb, 0, 0, 0),.08)}.bottom-nav--floating.bottom-nav--elevated{box-shadow:0 4px 24px #0000001a,0 12px 48px #00000014}.bottom-nav--floating.bottom-nav--safe-area{margin-bottom:calc(8px + env(safe-area-inset-bottom,0))}.bottom-nav--safe-area{padding-bottom:env(safe-area-inset-bottom,0);height:calc(var(--bottom-nav-height) + env(safe-area-inset-bottom,0))}.bottom-nav__container{display:flex;align-items:center;justify-content:space-around;height:var(--bottom-nav-height);max-width:500px;margin:0 auto}.bottom-nav__tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;height:100%;padding:8px 4px;background:transparent;border:none;cursor:pointer;position:relative;overflow:hidden;color:var(--bottom-nav-inactive);transition:color .2s ease;max-width:80px;--ripple-color: var(--bottom-nav-active)}.bottom-nav__tab:focus-visible{outline:2px solid var(--bottom-nav-active);outline-offset:-2px;border-radius:8px}.bottom-nav__tab--active{color:var(--bottom-nav-active)}.bottom-nav__tab--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bottom-nav__tab[data-animation=scale] .bottom-nav__tab-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}.bottom-nav__tab[data-animation=scale].bottom-nav__tab--active .bottom-nav__tab-icon{transform:scale(1.15)}.bottom-nav__tab[data-animation=fade]{transition:opacity .2s ease,color .2s ease}.bottom-nav__tab[data-animation=fade]:not(.bottom-nav__tab--active){opacity:.6}.bottom-nav__tab[data-animation=slide] .bottom-nav__tab-label{transition:transform .2s ease,opacity .2s ease;transform:translateY(6px);opacity:0}.bottom-nav__tab[data-animation=slide].bottom-nav__tab--active .bottom-nav__tab-label{transform:translateY(0);opacity:1}.bottom-nav__tab-icon{position:relative;font-size:24px;line-height:1}.bottom-nav__tab-icon ion-icon{display:block}.bottom-nav__tab-label{font-size:11px;font-weight:500;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;letter-spacing:.01em}.bottom-nav__badge{position:absolute;top:-4px;right:-10px;min-width:18px;height:18px;padding:0 5px;font-size:10px;font-weight:600;line-height:18px;text-align:center;color:#fff;background-color:var(--ion-color-danger);border-radius:9px;box-shadow:0 1px 3px #0003}.bottom-nav__badge--dot{min-width:10px;width:10px;height:10px;padding:0;top:-2px;right:-4px;border-radius:50%}.bottom-nav__fab{position:relative;flex-shrink:0;width:var(--bottom-nav-fab-size);height:var(--bottom-nav-fab-size);margin:0 12px;margin-top:calc(var(--bottom-nav-fab-size) * -.35);background:var(--fab-color);border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#fff;font-size:28px;box-shadow:0 4px 14px rgba(var(--ion-color-primary-rgb, 56, 128, 255),.4);transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s ease;overflow:hidden;--ripple-color: rgba(255, 255, 255, .3)}.bottom-nav__fab:hover{transform:scale(1.08);box-shadow:0 6px 20px rgba(var(--ion-color-primary-rgb, 56, 128, 255),.5)}.bottom-nav__fab:active{transform:scale(.95)}.bottom-nav__fab:focus-visible{outline:3px solid white;outline-offset:2px}.bottom-nav__fab--small{--bottom-nav-fab-size: 48px;font-size:24px;margin-top:-14.4px}.bottom-nav__fab ion-icon{display:block}.bottom-nav--hide-labels{--bottom-nav-height: 56px}.bottom-nav--hide-labels .bottom-nav__tab-label{display:none}.bottom-nav--hide-labels .bottom-nav__tab-icon{font-size:26px}@media (prefers-color-scheme: dark){.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 0, 0, 0),.8);border-top-color:#ffffff14}.bottom-nav--elevated{box-shadow:0 -4px 20px #00000040}.bottom-nav--floating{border-color:#ffffff1a;box-shadow:0 4px 24px #0003,0 8px 32px #00000026}.bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.88);border-color:#ffffff1a}.bottom-nav__fab{box-shadow:0 4px 14px #0006}.bottom-nav__fab:hover{box-shadow:0 6px 20px #00000080}}:host-context(.dark) .bottom-nav--translucent,:host-context(body.dark) .bottom-nav--translucent,:host-context([data-theme=dark]) .bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.85);border-top-color:#ffffff14}:host-context(.dark) .bottom-nav--elevated,:host-context(body.dark) .bottom-nav--elevated,:host-context([data-theme=dark]) .bottom-nav--elevated{box-shadow:0 -4px 20px #0000004d}:host-context(.dark) .bottom-nav--floating,:host-context(body.dark) .bottom-nav--floating,:host-context([data-theme=dark]) .bottom-nav--floating{border-color:#ffffff1a;box-shadow:0 4px 24px #0003,0 8px 32px #00000026}:host-context(.dark) .bottom-nav--floating.bottom-nav--translucent,:host-context(body.dark) .bottom-nav--floating.bottom-nav--translucent,:host-context([data-theme=dark]) .bottom-nav--floating.bottom-nav--translucent{background:rgba(var(--ion-background-color-rgb, 18, 18, 18),.88);border-color:#ffffff1a}:host-context(.dark) .bottom-nav__fab,:host-context(body.dark) .bottom-nav__fab,:host-context([data-theme=dark]) .bottom-nav__fab{box-shadow:0 4px 14px #00000080}:host-context(.dark) .bottom-nav__fab:hover,:host-context(body.dark) .bottom-nav__fab:hover,:host-context([data-theme=dark]) .bottom-nav__fab:hover{box-shadow:0 6px 20px #0009}@supports (padding-bottom: env(safe-area-inset-bottom)){.bottom-nav--safe-area .bottom-nav__container{height:var(--bottom-nav-height)}}\n"] }]
|
|
32851
32944
|
}], propDecorators: { tabClick: [{
|
|
32852
32945
|
type: Output
|
|
32853
32946
|
}], fabClick: [{
|
|
@@ -35327,6 +35420,72 @@ function provideLegalContent(config) {
|
|
|
35327
35420
|
return { provide: LEGAL_CONTENT_CONFIG, useValue: config };
|
|
35328
35421
|
}
|
|
35329
35422
|
|
|
35423
|
+
const VALTECH_LEGAL_CONFIG = new InjectionToken('VALTECH_LEGAL_CONFIG');
|
|
35424
|
+
/**
|
|
35425
|
+
* Resolves legal/site paths against a configurable main-site base URL.
|
|
35426
|
+
*
|
|
35427
|
+
* - **Main site mode**: no `provideValtechLegal` called → `resolve('/legal/terms')` returns `/legal/terms` (relative).
|
|
35428
|
+
* - **Satellite mode**: `provideValtechLegal({ baseUrl: 'https://myvaltech.com' })` → `resolve('/legal/terms')` returns `'https://myvaltech.com/legal/terms'` and `isExternal('/legal/terms')` returns `true`.
|
|
35429
|
+
*
|
|
35430
|
+
* Absolute URLs passed in are returned unchanged (no double-prefix).
|
|
35431
|
+
*/
|
|
35432
|
+
class LegalLinkService {
|
|
35433
|
+
constructor() {
|
|
35434
|
+
this.config = inject(VALTECH_LEGAL_CONFIG, { optional: true }) ?? {};
|
|
35435
|
+
}
|
|
35436
|
+
/** Effective base URL (null if running as main site). */
|
|
35437
|
+
get baseUrl() {
|
|
35438
|
+
return this.config.baseUrl?.replace(/\/$/, '') ?? null;
|
|
35439
|
+
}
|
|
35440
|
+
/** Whether resolved external links should open in a new tab. */
|
|
35441
|
+
get openInNewTab() {
|
|
35442
|
+
return this.config.openInNewTab ?? Boolean(this.config.baseUrl);
|
|
35443
|
+
}
|
|
35444
|
+
/**
|
|
35445
|
+
* Returns the URL to use for a given internal path. Absolute URLs pass through.
|
|
35446
|
+
* @example
|
|
35447
|
+
* resolve('/legal/terms') // main site: '/legal/terms'
|
|
35448
|
+
* // satellite: 'https://myvaltech.com/legal/terms'
|
|
35449
|
+
* resolve('https://x.com/y') // unchanged
|
|
35450
|
+
*/
|
|
35451
|
+
resolve(path) {
|
|
35452
|
+
if (!path)
|
|
35453
|
+
return path;
|
|
35454
|
+
if (/^https?:\/\//i.test(path))
|
|
35455
|
+
return path;
|
|
35456
|
+
const base = this.baseUrl;
|
|
35457
|
+
if (!base)
|
|
35458
|
+
return path;
|
|
35459
|
+
return `${base}${path.startsWith('/') ? '' : '/'}${path}`;
|
|
35460
|
+
}
|
|
35461
|
+
/** `true` if the path would be resolved to a cross-origin URL. */
|
|
35462
|
+
isExternal(path) {
|
|
35463
|
+
if (/^https?:\/\//i.test(path))
|
|
35464
|
+
return true;
|
|
35465
|
+
return this.baseUrl !== null;
|
|
35466
|
+
}
|
|
35467
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LegalLinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
35468
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LegalLinkService, providedIn: 'root' }); }
|
|
35469
|
+
}
|
|
35470
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LegalLinkService, decorators: [{
|
|
35471
|
+
type: Injectable,
|
|
35472
|
+
args: [{ providedIn: 'root' }]
|
|
35473
|
+
}] });
|
|
35474
|
+
/**
|
|
35475
|
+
* Wires `LegalLinkService` for satellite apps. Omit in the main site (the one
|
|
35476
|
+
* that hosts the canonical /legal/* routes) so links stay relative.
|
|
35477
|
+
*
|
|
35478
|
+
* @example
|
|
35479
|
+
* // main.ts of showcase / sigify / etc.
|
|
35480
|
+
* provideValtechLegal({
|
|
35481
|
+
* baseUrl: 'https://myvaltech.com',
|
|
35482
|
+
* openInNewTab: true,
|
|
35483
|
+
* }),
|
|
35484
|
+
*/
|
|
35485
|
+
function provideValtechLegal(config) {
|
|
35486
|
+
return { provide: VALTECH_LEGAL_CONFIG, useValue: config };
|
|
35487
|
+
}
|
|
35488
|
+
|
|
35330
35489
|
/**
|
|
35331
35490
|
* PreferencesService — preferencias del user en el doc canónico Firestore
|
|
35332
35491
|
* `/apps/{appId}/users/{uid}/preferences/main`.
|
|
@@ -35488,6 +35647,263 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35488
35647
|
* Cliente NUNCA escribe directo — todas las mutaciones via PUT /v2/auth/preferences.
|
|
35489
35648
|
*/
|
|
35490
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
|
+
|
|
35491
35907
|
/**
|
|
35492
35908
|
* Cross-Platform Version Helpers
|
|
35493
35909
|
*
|
|
@@ -42527,11 +42943,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
42527
42943
|
* Social media links for Valtech
|
|
42528
42944
|
*/
|
|
42529
42945
|
const VALTECH_SOCIAL_LINKS = [
|
|
42530
|
-
{
|
|
42946
|
+
{
|
|
42947
|
+
icon: 'logo-facebook',
|
|
42948
|
+
url: 'https://m.facebook.com/profile.php?id=61557610734470',
|
|
42949
|
+
name: 'Facebook',
|
|
42950
|
+
},
|
|
42531
42951
|
{ icon: 'logo-instagram', url: 'https://www.instagram.com/valtechltda/', name: 'Instagram' },
|
|
42532
42952
|
{ icon: 'logo-linkedin', url: 'https://www.linkedin.com/company/valtechltda/', name: 'LinkedIn' },
|
|
42533
42953
|
{ icon: 'logo-twitter', url: 'https://twitter.com/valtechltda', name: 'Twitter' },
|
|
42534
|
-
{
|
|
42954
|
+
{
|
|
42955
|
+
icon: 'logo-youtube',
|
|
42956
|
+
url: 'https://www.youtube.com/channel/UCuF4FGdTiUXxANx1HS4Wi5Q',
|
|
42957
|
+
name: 'YouTube',
|
|
42958
|
+
},
|
|
42535
42959
|
{ icon: 'logo-tiktok', url: 'https://www.tiktok.com/@valtechltda', name: 'TikTok' },
|
|
42536
42960
|
];
|
|
42537
42961
|
/**
|
|
@@ -42548,14 +42972,14 @@ const VALTECH_FOOTER_LOGO = {
|
|
|
42548
42972
|
*/
|
|
42549
42973
|
const VALTECH_COMPANY_LINKS = {
|
|
42550
42974
|
legal: [
|
|
42551
|
-
{ key: 'aboutUs', url: '/about', external: false },
|
|
42552
|
-
{ key: 'privacyPolicy', url: '/legal/privacy', external: false },
|
|
42553
|
-
{ key: 'termsConditions', url: '/legal/terms', external: false },
|
|
42975
|
+
{ key: 'aboutUs', url: '/about', kind: 'site', external: false },
|
|
42976
|
+
{ key: 'privacyPolicy', url: '/legal/privacy', kind: 'legal', external: false },
|
|
42977
|
+
{ key: 'termsConditions', url: '/legal/terms', kind: 'legal', external: false },
|
|
42554
42978
|
],
|
|
42555
42979
|
support: [
|
|
42556
|
-
{ key: 'contactSupport', url: '/contact', external: false },
|
|
42557
|
-
{ key: 'faq', url: '/help/faq', external: false },
|
|
42558
|
-
{ key: 'feedback', url: '/feedback', external: false },
|
|
42980
|
+
{ key: 'contactSupport', url: '/contact', kind: 'support', external: false },
|
|
42981
|
+
{ key: 'faq', url: '/help/faq', kind: 'support', external: false },
|
|
42982
|
+
{ key: 'feedback', url: '/feedback', kind: 'support', external: false },
|
|
42559
42983
|
],
|
|
42560
42984
|
};
|
|
42561
42985
|
/**
|
|
@@ -42605,21 +43029,27 @@ const VALTECH_LANGUAGE_SELECTOR = {
|
|
|
42605
43029
|
size: 'default',
|
|
42606
43030
|
};
|
|
42607
43031
|
/**
|
|
42608
|
-
* Helper to build footer links from company links config
|
|
43032
|
+
* Helper to build footer links from company links config.
|
|
43033
|
+
*
|
|
42609
43034
|
* @param links - Array of company links
|
|
42610
43035
|
* @param t - Translation function (key: string) => string
|
|
43036
|
+
* @param resolver - Optional resolver — typically `(link) => ({ url: legalLink.resolve(link.url), external: legalLink.isExternal(link.url) && (link.kind === 'legal' || link.kind === 'site') })` to point cross-app legal/site links to the main site.
|
|
42611
43037
|
* @returns Array of link objects ready for FooterLinksMetadata
|
|
42612
43038
|
*/
|
|
42613
|
-
function buildFooterLinks(links, t) {
|
|
42614
|
-
return links.map(link =>
|
|
42615
|
-
url: link.url,
|
|
42616
|
-
|
|
42617
|
-
|
|
42618
|
-
|
|
42619
|
-
|
|
42620
|
-
|
|
42621
|
-
|
|
42622
|
-
|
|
43039
|
+
function buildFooterLinks(links, t, resolver) {
|
|
43040
|
+
return links.map(link => {
|
|
43041
|
+
const resolved = resolver ? resolver(link) : { url: link.url, external: link.external };
|
|
43042
|
+
const external = resolved.external ?? link.external;
|
|
43043
|
+
return {
|
|
43044
|
+
url: resolved.url,
|
|
43045
|
+
text: t(link.key),
|
|
43046
|
+
color: 'dark',
|
|
43047
|
+
token: '',
|
|
43048
|
+
download: false,
|
|
43049
|
+
hoverable: true,
|
|
43050
|
+
...(external ? { target: '_blank' } : {}),
|
|
43051
|
+
};
|
|
43052
|
+
});
|
|
42623
43053
|
}
|
|
42624
43054
|
|
|
42625
43055
|
/**
|
|
@@ -42635,5 +43065,5 @@ function buildFooterLinks(links, t) {
|
|
|
42635
43065
|
* Generated bundle index. Do not edit.
|
|
42636
43066
|
*/
|
|
42637
43067
|
|
|
42638
|
-
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, 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_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, 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 };
|
|
42639
43069
|
//# sourceMappingURL=valtech-components.mjs.map
|