valtech-components 4.0.1026 → 4.0.1027
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/version.mjs
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Current version of valtech-components.
|
|
3
3
|
* This is automatically updated during the publish process.
|
|
4
4
|
*/
|
|
5
|
-
export const VERSION = '4.0.
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
export const VERSION = '4.0.1027';
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDdXJyZW50IHZlcnNpb24gb2YgdmFsdGVjaC1jb21wb25lbnRzLlxuICogVGhpcyBpcyBhdXRvbWF0aWNhbGx5IHVwZGF0ZWQgZHVyaW5nIHRoZSBwdWJsaXNoIHByb2Nlc3MuXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC4xMDI3JztcbiJdfQ==
|
|
@@ -70,7 +70,7 @@ import fixWebmDuration from 'fix-webm-duration';
|
|
|
70
70
|
* Current version of valtech-components.
|
|
71
71
|
* This is automatically updated during the publish process.
|
|
72
72
|
*/
|
|
73
|
-
const VERSION = '4.0.
|
|
73
|
+
const VERSION = '4.0.1027';
|
|
74
74
|
|
|
75
75
|
function evaluateValtechAccess(rule, context, features = {}, visitedFeatures = new Set()) {
|
|
76
76
|
if (rule == null)
|
|
@@ -57079,7 +57079,7 @@ class LoginComponent {
|
|
|
57079
57079
|
this.stopListeningForOAuthReturn();
|
|
57080
57080
|
}
|
|
57081
57081
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
57082
|
-
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" }, viewQueries: [{ propertyName: "forms", predicate: FormComponent, descendants: true }], ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo \u2014 default de marca (--main-logo) si el consumer no pasa logo -->\n <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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 <val-button\n [props]=\"oauthButtonProps(provider)\"\n (onClick)=\"loginWithOAuth(provider)\"\n />\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 (resolvedCompanyLink) {\n <a [href]=\"resolvedCompanyLink\" target=\"_blank\" rel=\"noopener noreferrer\"\n ><strong>{{ props.legal.companyName }}</strong></a\n >\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\" color=\"dark\" (click)=\"closeRegisterModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"onRegisterSwitchToLogin()\">{{ 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\" color=\"dark\" (click)=\"closeVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" color=\"dark\" (click)=\"closeForgotPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" color=\"dark\" (click)=\"closeResetPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" (didDismiss)=\"onMFAVerifyDismissed()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n @if (mfaMethod() === 'TOTP') {\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n @if (mfaUseBackupCode()) {\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseTotpAction') }}</a>\n } @else { {{ t('mfaUseBackupLink') }}\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseBackupAction') }}</a>\n }\n </ion-text>\n </div>\n }\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('mfaLostBackupLink') }}\n <a (click)=\"openMFAResetModal()\">{{ t('mfaResetAction') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Reset Modal (B) \u2014 recovery por email cuando no hay backup codes -->\n<ion-modal [isOpen]=\"isMFAResetModalOpen\" [backdropDismiss]=\"false\" (didDismiss)=\"closeMFAResetModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAResetModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n @if (mfaResetStep() === 'request') {\n <val-form [props]=\"mfaResetRequestFormProps()\" (onSubmit)=\"mfaResetRequestHandler($event)\" />\n } @else {\n <val-form [props]=\"mfaResetConfirmFormProps()\" (onSubmit)=\"mfaResetConfirmHandler($event)\" />\n }\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem .75rem;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;display:flex;flex-direction:column;gap:.5rem}.oauth-buttons val-button{--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-dark)}\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: 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", "onValueChange", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
57082
|
+
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" }, viewQueries: [{ propertyName: "forms", predicate: FormComponent, descendants: true }], ngImport: i0, template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo \u2014 default de marca (--main-logo) si el consumer no pasa logo -->\n <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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 <val-button\n [props]=\"oauthButtonProps(provider)\"\n (onClick)=\"loginWithOAuth(provider)\"\n />\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 (resolvedCompanyLink) {\n <a [href]=\"resolvedCompanyLink\" target=\"_blank\" rel=\"noopener noreferrer\"\n ><strong>{{ props.legal.companyName }}</strong></a\n >\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\" cssClass=\"val-modal-adaptive\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeRegisterModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"onRegisterSwitchToLogin()\">{{ 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\" cssClass=\"val-modal-adaptive\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" cssClass=\"val-modal-adaptive\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeForgotPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" cssClass=\"val-modal-adaptive\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeResetPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\n [isOpen]=\"isMFAVerifyModalOpen\"\n cssClass=\"val-modal-adaptive\"\n [backdropDismiss]=\"false\"\n (didDismiss)=\"onMFAVerifyDismissed()\"\n>\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n @if (mfaMethod() === 'TOTP') {\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n @if (mfaUseBackupCode()) {\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseTotpAction') }}</a>\n } @else { {{ t('mfaUseBackupLink') }}\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseBackupAction') }}</a>\n }\n </ion-text>\n </div>\n }\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('mfaLostBackupLink') }}\n <a (click)=\"openMFAResetModal()\">{{ t('mfaResetAction') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Reset Modal (B) \u2014 recovery por email cuando no hay backup codes -->\n<ion-modal\n [isOpen]=\"isMFAResetModalOpen\"\n cssClass=\"val-modal-adaptive\"\n [backdropDismiss]=\"false\"\n (didDismiss)=\"closeMFAResetModal()\"\n>\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAResetModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n @if (mfaResetStep() === 'request') {\n <val-form [props]=\"mfaResetRequestFormProps()\" (onSubmit)=\"mfaResetRequestHandler($event)\" />\n } @else {\n <val-form [props]=\"mfaResetConfirmFormProps()\" (onSubmit)=\"mfaResetConfirmHandler($event)\" />\n }\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem .75rem;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;display:flex;flex-direction:column;gap:.5rem}.oauth-buttons val-button{--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-dark)}\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: 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", "onValueChange", "onInvalid", "onSelectChange"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
57083
57083
|
}
|
|
57084
57084
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoginComponent, decorators: [{
|
|
57085
57085
|
type: Component,
|
|
@@ -57096,7 +57096,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
57096
57096
|
FormComponent,
|
|
57097
57097
|
ImageComponent,
|
|
57098
57098
|
ButtonComponent,
|
|
57099
|
-
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo \u2014 default de marca (--main-logo) si el consumer no pasa logo -->\n <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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 <val-button\n [props]=\"oauthButtonProps(provider)\"\n (onClick)=\"loginWithOAuth(provider)\"\n />\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 (resolvedCompanyLink) {\n <a [href]=\"resolvedCompanyLink\" target=\"_blank\" rel=\"noopener noreferrer\"\n ><strong>{{ props.legal.companyName }}</strong></a\n >\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\" color=\"dark\" (click)=\"closeRegisterModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"onRegisterSwitchToLogin()\">{{ 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\" color=\"dark\" (click)=\"closeVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" color=\"dark\" (click)=\"closeForgotPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" color=\"dark\" (click)=\"closeResetPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" (didDismiss)=\"onMFAVerifyDismissed()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n @if (mfaMethod() === 'TOTP') {\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n @if (mfaUseBackupCode()) {\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseTotpAction') }}</a>\n } @else { {{ t('mfaUseBackupLink') }}\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseBackupAction') }}</a>\n }\n </ion-text>\n </div>\n }\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('mfaLostBackupLink') }}\n <a (click)=\"openMFAResetModal()\">{{ t('mfaResetAction') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Reset Modal (B) \u2014 recovery por email cuando no hay backup codes -->\n<ion-modal [isOpen]=\"isMFAResetModalOpen\" [backdropDismiss]=\"false\" (didDismiss)=\"closeMFAResetModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAResetModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n @if (mfaResetStep() === 'request') {\n <val-form [props]=\"mfaResetRequestFormProps()\" (onSubmit)=\"mfaResetRequestHandler($event)\" />\n } @else {\n <val-form [props]=\"mfaResetConfirmFormProps()\" (onSubmit)=\"mfaResetConfirmHandler($event)\" />\n }\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem .75rem;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;display:flex;flex-direction:column;gap:.5rem}.oauth-buttons val-button{--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-dark)}\n"] }]
|
|
57099
|
+
], template: "<div class=\"val-login\" [class.val-login--card]=\"config.showCard\">\n <!-- Logo \u2014 default de marca (--main-logo) si el consumer no pasa logo -->\n <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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 <val-button\n [props]=\"oauthButtonProps(provider)\"\n (onClick)=\"loginWithOAuth(provider)\"\n />\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 (resolvedCompanyLink) {\n <a [href]=\"resolvedCompanyLink\" target=\"_blank\" rel=\"noopener noreferrer\"\n ><strong>{{ props.legal.companyName }}</strong></a\n >\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\" cssClass=\"val-modal-adaptive\" (didDismiss)=\"closeRegisterModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeRegisterModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"registerFormProps()\" (onSubmit)=\"registerHandler($event)\" />\n <div class=\"auth-link\">\n <ion-text color=\"dark\">\n {{ t('hasAccount') }}\n <a (click)=\"onRegisterSwitchToLogin()\">{{ 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\" cssClass=\"val-modal-adaptive\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" cssClass=\"val-modal-adaptive\" (didDismiss)=\"closeForgotPasswordModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeForgotPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\" cssClass=\"val-modal-adaptive\" [backdropDismiss]=\"false\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeResetPasswordModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\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\n [isOpen]=\"isMFAVerifyModalOpen\"\n cssClass=\"val-modal-adaptive\"\n [backdropDismiss]=\"false\"\n (didDismiss)=\"onMFAVerifyDismissed()\"\n>\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAVerifyModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n <val-form [props]=\"mfaVerifyFormProps()\" (onSubmit)=\"verifyMFAHandler($event)\" />\n @if (mfaMethod() === 'TOTP') {\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n @if (mfaUseBackupCode()) {\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseTotpAction') }}</a>\n } @else { {{ t('mfaUseBackupLink') }}\n <a (click)=\"toggleMFABackupCode()\">{{ t('mfaUseBackupAction') }}</a>\n }\n </ion-text>\n </div>\n }\n <div class=\"resend-link\">\n <ion-text color=\"dark\">\n {{ t('mfaLostBackupLink') }}\n <a (click)=\"openMFAResetModal()\">{{ t('mfaResetAction') }}</a>\n </ion-text>\n </div>\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n\n<!-- MFA Reset Modal (B) \u2014 recovery por email cuando no hay backup codes -->\n<ion-modal\n [isOpen]=\"isMFAResetModalOpen\"\n cssClass=\"val-modal-adaptive\"\n [backdropDismiss]=\"false\"\n (didDismiss)=\"closeMFAResetModal()\"\n>\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"end\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"closeMFAResetModal()\">\n <strong>{{ t('close') }}</strong>\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 <div class=\"logo-container\">\n <val-image [props]=\"resolvedLogo\" />\n </div>\n @if (mfaResetStep() === 'request') {\n <val-form [props]=\"mfaResetRequestFormProps()\" (onSubmit)=\"mfaResetRequestHandler($event)\" />\n } @else {\n <val-form [props]=\"mfaResetConfirmFormProps()\" (onSubmit)=\"mfaResetConfirmHandler($event)\" />\n }\n </section>\n </ion-content>\n </ng-template>\n</ion-modal>\n", styles: [".val-login{width:100%}.val-login--card{padding:1rem .75rem;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;display:flex;flex-direction:column;gap:.5rem}.oauth-buttons val-button{--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-dark)}\n"] }]
|
|
57100
57100
|
}], propDecorators: { forms: [{
|
|
57101
57101
|
type: ViewChildren,
|
|
57102
57102
|
args: [FormComponent]
|