@avora-labs/meta-forge 1.0.5 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/README.md +0 -0
  2. package/fesm2022/{avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs → avora-labs-meta-forge-amf-auth-shell.component-C89gSPc9.mjs} +59 -59
  3. package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-C89gSPc9.mjs.map +1 -0
  4. package/fesm2022/{avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs → avora-labs-meta-forge-contact-support.page-C_kdmzhL.mjs} +148 -148
  5. package/fesm2022/avora-labs-meta-forge-contact-support.page-C_kdmzhL.mjs.map +1 -0
  6. package/fesm2022/{avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs → avora-labs-meta-forge-forgot-password.page-PY9_K4M-.mjs} +240 -240
  7. package/fesm2022/avora-labs-meta-forge-forgot-password.page-PY9_K4M-.mjs.map +1 -0
  8. package/fesm2022/{avora-labs-meta-forge-login.page-etTr5NqJ.mjs → avora-labs-meta-forge-login.page-BW-RWCQM.mjs} +76 -76
  9. package/fesm2022/avora-labs-meta-forge-login.page-BW-RWCQM.mjs.map +1 -0
  10. package/fesm2022/avora-labs-meta-forge.mjs +2098 -2098
  11. package/fesm2022/avora-labs-meta-forge.mjs.map +1 -1
  12. package/package.json +13 -6
  13. package/styles/_palettes.scss +84 -84
  14. package/styles/_themes.scss +96 -96
  15. package/styles/_variables.scss +56 -56
  16. package/styles/styles.scss +295 -295
  17. package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs.map +0 -1
  18. package/fesm2022/avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs.map +0 -1
  19. package/fesm2022/avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs.map +0 -1
  20. package/fesm2022/avora-labs-meta-forge-login.page-etTr5NqJ.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs","sources":["../../../projects/avora-meta-forge/src/lib/avora-meta-forge/pages/auth/forgot-password.page.ts"],"sourcesContent":["/**\r\n * Forgot Password Component\r\n *\r\n * Powered by AvoraMetaForge actions:\r\n * - Step 1: User enters email → fires mock-send-otp API → opens AMF OTP modal\r\n * - Modal verified → set-state marks otpVerified → page shows Step 2\r\n * - Step 2: User sets new password → mock-reset-password → back to login\r\n *\r\n * This component uses AmfAuthShellComponent for the shared visual shell.\r\n * Framework users can replicate this pattern by using AmfAuthShellComponent\r\n * with any custom content, or by building their own shell entirely.\r\n */\r\nimport { Component, inject, signal, OnDestroy, ViewChild } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Router, RouterModule } from '@angular/router';\r\n\r\nimport { Subscription } from 'rxjs';\r\nimport { ActionDispatcherService } from '../../core/action-dispatcher.service';\r\nimport { MetaStateService } from '../../services/meta-state.service';\r\nimport { AmfAuthShellComponent } from '../../renderers/auth/amf-auth-shell.component';\r\nimport { FormRendererComponent } from '../../renderers/form/form-renderer.component';\r\nimport { FormMeta } from '../../models/meta.types';\r\nimport { APP_META_CONFIG_TOKEN } from '../../avora-meta-forge.provider';\r\ntype Step = 'email' | 'reset';\r\n\r\n@Component({\r\n selector: 'amf-forgot-password',\r\n standalone: true,\r\n imports: [FormsModule, RouterModule, AmfAuthShellComponent, FormRendererComponent],\r\n template: `\r\n <amf-auth-shell \r\n [brandName]=\"meta.auth?.builtInUI?.brandName || meta.app.name\"\r\n [brandTagline]=\"meta.auth?.builtInUI?.brandTagline || 'Recover your account'\"\r\n maxWidth=\"620px\">\r\n <!-- Step Indicator -->\r\n <div class=\"steps\">\r\n <div class=\"step\" [class.active]=\"currentStep() === 'email'\" [class.done]=\"currentStep() === 'reset'\">\r\n <div class=\"step-dot\">\r\n @if (currentStep() === 'reset') {\r\n <span class=\"ms step-icon\">check</span>\r\n } @else {\r\n <span>1</span>\r\n }\r\n </div>\r\n <span class=\"step-label\">Email</span>\r\n </div>\r\n <div class=\"step-line\" [class.done]=\"currentStep() === 'reset'\"></div>\r\n <div class=\"step\" [class.active]=\"currentStep() === 'reset'\">\r\n <div class=\"step-dot\"><span>2</span></div>\r\n <span class=\"step-label\">New Password</span>\r\n </div>\r\n </div>\r\n\r\n <!-- ── STEP 1: Email ── -->\r\n @if (currentStep() === 'email') {\r\n <div class=\"form-section\">\r\n <div class=\"screen-label\">\r\n <div class=\"icon-wrap\"><span class=\"ms icon-ms\">lock</span></div>\r\n <h2>Forgot your password?</h2>\r\n <p>Enter your email and we'll send a verification code.</p>\r\n </div>\r\n\r\n <div class=\"auth-form-container\">\r\n <amf-form-renderer \r\n [config]=\"emailForm\" \r\n (formSubmit)=\"onEmailSubmit($event)\"\r\n (formChange)=\"onEmailChange($event)\">\r\n </amf-form-renderer>\r\n\r\n @if (errorMsg()) {\r\n <div class=\"error-banner\">{{ errorMsg() }}</div>\r\n }\r\n\r\n <div class=\"action-row\">\r\n <button type=\"button\" class=\"auth-btn\" (click)=\"triggerEmailSubmit()\" [disabled]=\"loading() || !email\">\r\n @if (loading()) {\r\n <div class=\"loader\"></div>\r\n } @else {\r\n <span>Send Verification Code</span>\r\n }\r\n </button>\r\n <a routerLink=\"/login\" class=\"back-link-inline\">\r\n <svg viewBox=\"0 0 24 24\"><path d=\"M19 12H5M12 19l-7-7 7-7\"/></svg>\r\n Back to Sign In\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- ── STEP 2: New Password (after OTP verified) ── -->\r\n @if (currentStep() === 'reset') {\r\n <div class=\"form-section\">\r\n <!-- Compact inline header for step 2 -->\r\n <div class=\"screen-label screen-label-sm\">\r\n <span class=\"ms icon-ms icon-ms-inline\">key</span>\r\n <div>\r\n <h2>Set a new password</h2>\r\n <p>Identity verified — choose a strong password.</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"auth-form-container\">\r\n <amf-form-renderer \r\n [config]=\"resetForm\" \r\n (formSubmit)=\"onResetSubmit($event)\"\r\n (formChange)=\"onResetChange($event)\">\r\n </amf-form-renderer>\r\n\r\n @if (confirmError) {\r\n <span class=\"field-error\" style=\"margin-top: -10px; display: block;\">Passwords don't match</span>\r\n }\r\n\r\n <!-- Strength bar: only show once user starts typing -->\r\n @if (newPassword) {\r\n <div class=\"strength-bar\">\r\n <div class=\"strength-track\">\r\n <div class=\"strength-fill\" [style.width]=\"strengthPct + '%'\" [class]=\"'strength-' + strengthLevel\"></div>\r\n </div>\r\n <span class=\"strength-label\">{{ strengthLabel }}</span>\r\n </div>\r\n }\r\n\r\n @if (errorMsg()) {\r\n <div class=\"error-banner\">{{ errorMsg() }}</div>\r\n }\r\n\r\n <!-- Inline action row: equal-width Submit + Back -->\r\n <div class=\"action-row\">\r\n <button type=\"button\" class=\"auth-btn\" (click)=\"triggerResetSubmit()\" [disabled]=\"loading() || !newPassword || !confirmPassword || confirmError\">\r\n @if (loading()) {\r\n <div class=\"loader\"></div>\r\n } @else {\r\n <span>Update Password</span>\r\n }\r\n </button>\r\n <a routerLink=\"/login\" class=\"back-link-inline\">\r\n <svg viewBox=\"0 0 24 24\"><path d=\"M19 12H5M12 19l-7-7 7-7\"/></svg>\r\n Back to Sign In\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n\r\n </amf-auth-shell>\r\n `,\r\n styles: [`\r\n :host { display: block; height: 100%; }\r\n\r\n /* ── Step Indicator ── */\r\n .steps {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0;\r\n margin-bottom: clamp(12px, 2.5vw, 20px);\r\n }\r\n .step {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n .step-dot {\r\n width: 32px; height: 32px;\r\n border-radius: 50%;\r\n border: 2px solid rgba(255,255,255,0.15);\r\n background: rgba(255,255,255,0.04);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 0.75rem;\r\n font-weight: 700;\r\n color: #64748b;\r\n transition: all 0.3s;\r\n }\r\n .step.active .step-dot {\r\n border-color: var(--app-primary, #6366f1);\r\n background: rgba(99,102,241,0.15);\r\n color: var(--app-primary, #6366f1);\r\n box-shadow: 0 0 16px var(--app-glow, rgba(99,102,241,0.4));\r\n }\r\n .step.done .step-dot {\r\n border-color: #10b981;\r\n background: rgba(16,185,129,0.15);\r\n color: #10b981;\r\n }\r\n .step-icon { font-size: 1rem !important; }\r\n .step-label {\r\n font-size: 0.7rem;\r\n color: #64748b;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n white-space: nowrap;\r\n }\r\n .step.active .step-label { color: #94a3b8; }\r\n .step-line {\r\n flex: 1;\r\n height: 2px;\r\n background: rgba(255,255,255,0.08);\r\n margin: 0 8px;\r\n margin-bottom: 22px;\r\n min-width: 24px;\r\n transition: background 0.3s;\r\n }\r\n .step-line.done { background: rgba(16,185,129,0.4); }\r\n\r\n /* ── Screen Label ── */\r\n .screen-label {\r\n text-align: center;\r\n margin-bottom: clamp(10px, 2vw, 16px);\r\n }\r\n /* Step 2 compact inline variant */\r\n .screen-label-sm {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n text-align: left;\r\n padding: 10px 14px;\r\n background: rgba(255,255,255,0.03);\r\n border: 1px solid rgba(255,255,255,0.07);\r\n border-radius: 12px;\r\n margin-bottom: clamp(10px, 2vw, 14px);\r\n }\r\n .screen-label-sm h2 {\r\n font-size: clamp(1rem, 3vw, 1.15rem) !important;\r\n margin-bottom: 2px !important;\r\n }\r\n .screen-label-sm p {\r\n font-size: clamp(0.75rem, 1.8vw, 0.82rem) !important;\r\n margin: 0;\r\n }\r\n .icon-ms-inline {\r\n font-size: 1.75rem !important;\r\n flex-shrink: 0;\r\n animation: float 3s ease-in-out infinite;\r\n }\r\n .icon-wrap {\r\n margin-bottom: 6px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n animation: float 3s ease-in-out infinite;\r\n }\r\n .icon-ms {\r\n font-size: 2.1rem !important;\r\n font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 48;\r\n background: linear-gradient(135deg, var(--app-primary, #6366f1), var(--app-accent, #c084fc));\r\n -webkit-background-clip: text;\r\n -webkit-text-fill-color: transparent;\r\n background-clip: text;\r\n }\r\n .screen-label h2 {\r\n font-size: clamp(1.15rem, 4vw, 1.4rem);\r\n font-weight: 700;\r\n color: #f1f5f9;\r\n margin-bottom: 6px;\r\n }\r\n .screen-label p {\r\n font-size: clamp(0.8rem, 2vw, 0.875rem);\r\n color: #64748b;\r\n line-height: 1.5;\r\n }\r\n /* 2-col row for the two password fields */\r\n .pw-row {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 10px;\r\n }\r\n @media (max-width: 460px) {\r\n .pw-row { grid-template-columns: 1fr; }\r\n .screen-label-sm { flex-direction: column; text-align: center; }\r\n }\r\n\r\n /* ── Form ── */\r\n .auth-form-container { display: flex; flex-direction: column; gap: clamp(10px, 2vw, 14px); }\r\n \r\n /* ── Map AMF Form classes to exactly match input-glass style ── */\r\n ::ng-deep .auth-form-container .amf-form { gap: clamp(10px, 2vw, 14px); }\r\n ::ng-deep .auth-form-container .amf-form-fields { gap: clamp(10px, 2vw, 14px); }\r\n ::ng-deep .auth-form-container .amf-field { display: flex; flex-direction: column; gap: 8px; }\r\n ::ng-deep .auth-form-container .field-label {\r\n font-size: 0.875rem !important;\r\n font-weight: 600 !important;\r\n color: #cbd5e1 !important;\r\n margin-bottom: 0 !important;\r\n }\r\n ::ng-deep .auth-form-container .field-input-wrapper {\r\n border-radius: 12px !important;\r\n border: 1px solid rgba(255,255,255,0.08) !important;\r\n background: rgba(255,255,255,0.04) !important;\r\n transition: all 0.25s !important;\r\n overflow: hidden;\r\n box-shadow: none !important;\r\n display: flex;\r\n align-items: center;\r\n }\r\n ::ng-deep .auth-form-container .field-input-wrapper:focus-within {\r\n border-color: var(--app-primary, #6366f1) !important;\r\n background: rgba(255,255,255,0.06) !important;\r\n box-shadow: 0 0 20px var(--app-glow, rgba(99,102,241,0.3)) !important;\r\n }\r\n ::ng-deep .auth-form-container .field-input {\r\n flex: 1;\r\n min-width: 0;\r\n padding: 13px 16px !important;\r\n border: none !important;\r\n background: transparent !important;\r\n font-size: clamp(0.9rem, 2vw, 1rem) !important;\r\n color: #f1f5f9 !important;\r\n }\r\n ::ng-deep .auth-form-container .field-input::placeholder { color: #64748b !important; }\r\n /* Eye toggle from FieldRendererComponent */\r\n ::ng-deep .auth-form-container .pwd-toggle-btn { color: #64748b !important; }\r\n ::ng-deep .auth-form-container .pwd-toggle-btn:hover { color: var(--app-primary, #6366f1) !important; }\r\n\r\n .field-error { font-size: 0.78rem; color: #ef4444; }\r\n\r\n /* ── Password Strength ── */\r\n .strength-bar { display: flex; align-items: center; gap: 10px; }\r\n .strength-track {\r\n flex: 1; height: 4px;\r\n background: rgba(255,255,255,0.07);\r\n border-radius: 2px;\r\n overflow: hidden;\r\n }\r\n .strength-fill {\r\n height: 100%;\r\n border-radius: 2px;\r\n transition: width 0.4s, background 0.4s;\r\n }\r\n .strength-weak { background: #ef4444; }\r\n .strength-fair { background: #f59e0b; }\r\n .strength-good { background: #10b981; }\r\n .strength-strong { background: #6366f1; }\r\n .strength-label { font-size: 0.75rem; color: #64748b; white-space: nowrap; }\r\n\r\n /* ── Button ── */\r\n .auth-btn {\r\n background: linear-gradient(135deg, var(--app-primary, #6366f1), var(--app-accent, #c084fc));\r\n color: white;\r\n padding: clamp(11px, 2.5vw, 14px);\r\n border: none;\r\n border-radius: 12px;\r\n font-size: clamp(0.9rem, 2vw, 1rem);\r\n font-weight: 600;\r\n cursor: pointer;\r\n transition: all 0.3s cubic-bezier(0.4,0,0.2,1);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n flex: 1; /* grows in action-row, fills full width standalone */\r\n min-width: 0;\r\n position: relative;\r\n overflow: hidden;\r\n }\r\n .auth-btn:hover:not(:disabled) {\r\n transform: translateY(-2px);\r\n box-shadow: 0 10px 30px -5px var(--app-glow, rgba(99,102,241,0.5));\r\n }\r\n .auth-btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }\r\n .btn-icon {\r\n width: 16px; height: 16px;\r\n fill: none; stroke: currentColor; stroke-width: 2.5;\r\n stroke-linecap: round; stroke-linejoin: round;\r\n flex-shrink: 0;\r\n }\r\n\r\n /* ── Error Banner ── */\r\n .error-banner {\r\n background: rgba(239,68,68,0.1);\r\n border: 1px solid rgba(239,68,68,0.3);\r\n border-radius: 10px;\r\n padding: 12px 16px;\r\n font-size: 0.875rem;\r\n color: #fca5a5;\r\n }\r\n\r\n /* ── Footer ── */\r\n .footer-note { text-align: center; margin-top: clamp(10px, 2vw, 18px); }\r\n .back-link {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n font-weight: 500;\r\n transition: color 0.2s;\r\n text-decoration: none;\r\n }\r\n .back-link svg {\r\n width: 14px; height: 14px;\r\n fill: none; stroke: currentColor; stroke-width: 2.5;\r\n stroke-linecap: round; stroke-linejoin: round;\r\n }\r\n .back-link:hover { color: var(--app-primary, #6366f1); }\r\n\r\n /* ── Inline action row — both steps ── */\r\n .action-row {\r\n display: flex;\r\n align-items: stretch; /* same height naturally */\r\n gap: 10px;\r\n }\r\n /* Ghost back button — equal width to the primary btn via flex:1 */\r\n .back-link-inline {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n flex: 1; /* equal width with .auth-btn */\r\n min-width: 0;\r\n padding: clamp(11px, 2.5vw, 14px) 12px;\r\n border-radius: 12px;\r\n border: 1px solid rgba(255,255,255,0.1);\r\n background: rgba(255,255,255,0.04);\r\n color: #94a3b8;\r\n font-size: clamp(0.82rem, 2vw, 0.9rem);\r\n font-weight: 500;\r\n text-decoration: none;\r\n white-space: nowrap;\r\n transition: all 0.2s;\r\n }\r\n .back-link-inline svg {\r\n width: 13px; height: 13px;\r\n fill: none; stroke: currentColor; stroke-width: 2.5;\r\n stroke-linecap: round; stroke-linejoin: round;\r\n flex-shrink: 0;\r\n }\r\n .back-link-inline:hover {\r\n color: #f1f5f9;\r\n border-color: rgba(99,102,241,0.35);\r\n background: rgba(99,102,241,0.06);\r\n }\r\n\r\n /* ── Loader ── */\r\n .loader {\r\n width: 20px; height: 20px;\r\n border: 3px solid rgba(255,255,255,0.2);\r\n border-top-color: white;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n }\r\n @keyframes spin { to { transform: rotate(360deg); } }\r\n @keyframes float {\r\n 0%, 100% { transform: translateY(0); }\r\n 50% { transform: translateY(-6px); }\r\n }\r\n\r\n /* ── Responsive: very small screens ── */\r\n @media (max-width: 400px) {\r\n .steps { margin-bottom: 14px; }\r\n .step-line { margin: 0 4px; margin-bottom: 22px; min-width: 12px; }\r\n .step-label { font-size: 0.6rem; }\r\n .screen-label { margin-bottom: 12px; }\r\n .icon-ms { font-size: 2.25rem !important; }\r\n .auth-form { gap: 12px; }\r\n }\r\n @media (prefers-reduced-motion: reduce) {\r\n .icon-wrap, .loader { animation: none !important; }\r\n }\r\n `]\r\n})\r\nexport class ForgotPasswordComponent implements OnDestroy {\r\n private readonly dispatcher = inject(ActionDispatcherService);\r\n private readonly stateService = inject(MetaStateService);\r\n private readonly router = inject(Router);\r\n protected meta: any = inject(APP_META_CONFIG_TOKEN, { optional: true }) || { app: { name: 'AvoraMetaForge' } };\r\n private readonly sub: Subscription;\r\n\r\n currentStep = signal<Step>('email');\r\n loading = signal(false);\r\n errorMsg = signal('');\r\n\r\n email = '';\r\n newPassword = '';\r\n confirmPassword = '';\r\n confirmError = false;\r\n\r\n // AMF Form Definitions\r\n emailForm: FormMeta = {\r\n id: 'emailForm',\r\n hideSubmit: true,\r\n fields: [\r\n {\r\n key: 'email',\r\n type: 'email',\r\n label: 'Email Address',\r\n placeholder: 'name@company.com',\r\n validators: [{ type: 'required' }]\r\n }\r\n ]\r\n };\r\n\r\n resetForm: FormMeta = {\r\n id: 'resetForm',\r\n hideSubmit: true,\r\n fields: [\r\n {\r\n key: 'newPassword',\r\n type: 'password',\r\n label: 'New Password',\r\n placeholder: 'Minimum 8 characters',\r\n validators: [{ type: 'required' }, { type: 'minLength', value: 8 }]\r\n },\r\n {\r\n key: 'confirmPassword',\r\n type: 'password',\r\n label: 'Confirm Password',\r\n placeholder: 'Re-enter password',\r\n validators: [{ type: 'required' }]\r\n }\r\n ]\r\n };\r\n\r\n constructor() {\r\n // Listen for modal events — when OTP is verified, advance to step 2\r\n this.sub = this.stateService.changes$.subscribe(change => {\r\n if (change.key === 'forgotPw.otpVerified' && change.newValue === true) {\r\n this.currentStep.set('reset');\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.sub.unsubscribe();\r\n this.stateService.clearNamespace('forgotPw');\r\n }\r\n\r\n get strengthPct(): number {\r\n const pw = this.newPassword;\r\n if (!pw) return 0;\r\n let score = 0;\r\n if (pw.length >= 8) score += 25;\r\n if (pw.length >= 12) score += 15;\r\n if (/[A-Z]/.test(pw)) score += 20;\r\n if (/[0-9]/.test(pw)) score += 20;\r\n if (/[^A-Za-z0-9]/.test(pw)) score += 20;\r\n return Math.min(score, 100);\r\n }\r\n get strengthLevel(): string {\r\n const p = this.strengthPct;\r\n if (p < 35) return 'weak';\r\n if (p < 60) return 'fair';\r\n if (p < 80) return 'good';\r\n return 'strong';\r\n }\r\n get strengthLabel(): string {\r\n const map: Record<string, string> = { weak: 'Weak', fair: 'Fair', good: 'Good', strong: 'Strong' };\r\n return this.strengthPct ? map[this.strengthLevel] : '';\r\n }\r\n\r\n checkConfirm(): void {\r\n this.confirmError = !!(this.confirmPassword && this.newPassword !== this.confirmPassword);\r\n }\r\n\r\n onEmailChange(values: any): void {\r\n this.email = values.email || '';\r\n }\r\n\r\n onResetChange(values: any): void {\r\n this.newPassword = values.newPassword || '';\r\n this.confirmPassword = values.confirmPassword || '';\r\n this.checkConfirm();\r\n }\r\n\r\n triggerEmailSubmit(): void {\r\n this.dispatcher.dispatch({ type: 'submit-form', config: { formId: 'emailForm' } });\r\n }\r\n\r\n triggerResetSubmit(): void {\r\n this.dispatcher.dispatch({ type: 'submit-form', config: { formId: 'resetForm' } });\r\n }\r\n\r\n onEmailSubmit(values: any): void {\r\n if (!values.email) return;\r\n\r\n this.loading.set(true);\r\n this.errorMsg.set('');\r\n\r\n // DEMO: calls mock-send-otp endpoint, then opens the OTP modal.\r\n // REAL: remove mock:true from 'mock-send-otp' and point it to your real endpoint.\r\n this.dispatcher.dispatch({\r\n type: 'dispatch-multiple',\r\n config: {\r\n mode: 'sequential',\r\n actions: [\r\n { type: 'api', config: { endpointId: 'mock-send-otp', body: { email: this.email } } },\r\n {\r\n type: 'open-modal',\r\n config: {\r\n title: 'Enter Verification Code',\r\n size: 'sm',\r\n disableCloseOnBackdrop: true,\r\n content: {\r\n type: 'form',\r\n config: {\r\n fields: [\r\n {\r\n key: 'code',\r\n label: 'We sent a 6-digit code to ' + this.email,\r\n type: 'otp',\r\n otpLength: 6,\r\n validators: [{ type: 'required' }, { type: 'minLength', value: 6 }]\r\n }\r\n ],\r\n submitLabel: 'Verify Code',\r\n onSubmit: {\r\n type: 'api',\r\n config: {\r\n endpointId: 'mock-verify-otp',\r\n body: 'formValue',\r\n storeInState: 'forgotPw.verifyResult'\r\n },\r\n then: {\r\n type: 'dispatch-multiple',\r\n config: {\r\n mode: 'sequential',\r\n actions: [\r\n { type: 'set-state', config: { key: 'forgotPw.otpVerified', value: true } },\r\n { type: 'close-modal', config: {} },\r\n { type: 'notify', config: { type: 'success', message: 'Code verified! Set your new password.' } }\r\n ]\r\n }\r\n },\r\n onError: {\r\n type: 'notify',\r\n config: { type: 'error', message: 'Invalid or expired code. Please try again.' }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n }).finally(() => this.loading.set(false));\r\n }\r\n\r\n onResetSubmit(values: any): void {\r\n this.checkConfirm();\r\n if (!values.newPassword || this.confirmError) return;\r\n\r\n this.loading.set(true);\r\n this.errorMsg.set('');\r\n\r\n // DEMO: calls mock-reset-password endpoint.\r\n // REAL: remove mock:true from 'mock-reset-password' and point to your real endpoint.\r\n this.dispatcher.dispatch({\r\n type: 'api',\r\n config: {\r\n endpointId: 'mock-reset-password',\r\n body: { password: values.newPassword, resetToken: this.stateService.get('forgotPw.verifyResult.resetToken') }\r\n },\r\n then: {\r\n type: 'dispatch-multiple',\r\n config: {\r\n mode: 'sequential',\r\n actions: [\r\n { type: 'notify', config: { type: 'success', message: 'Password updated! Please log in with your new password.' } },\r\n { type: 'delay', config: { duration: 800 } },\r\n { type: 'navigate', config: { path: '/login' } }\r\n ]\r\n }\r\n },\r\n onError: {\r\n type: 'notify',\r\n config: { type: 'error', message: 'Password reset failed. Please try again.' }\r\n }\r\n }).finally(() => this.loading.set(false));\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"avora-labs-meta-forge-login.page-etTr5NqJ.mjs","sources":["../../../projects/avora-meta-forge/src/lib/avora-meta-forge/pages/auth/login.page.ts"],"sourcesContent":["import { Component, inject, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Router, RouterModule } from '@angular/router';\r\nimport { AuthService } from '../../../core/auth/auth.service';\r\nimport { ActionDispatcherService } from '../../core/action-dispatcher.service';\r\nimport { AmfAuthShellComponent } from '../../renderers/auth/amf-auth-shell.component';\r\nimport { FormRendererComponent } from '../../renderers/form/form-renderer.component';\r\nimport { FormMeta } from '../../models/meta.types';\r\nimport { APP_META_CONFIG_TOKEN } from '../../avora-meta-forge.provider';\r\n@Component({\r\n selector: 'amf-login',\r\n standalone: true,\r\n imports: [FormsModule, RouterModule, AmfAuthShellComponent, FormRendererComponent],\r\n template: `\r\n <amf-auth-shell \r\n [brandName]=\"meta.auth?.builtInUI?.brandName || meta.app.name\" \r\n [brandTagline]=\"meta.auth?.builtInUI?.brandTagline || 'Sign in to your account'\">\r\n \r\n <div class=\"login-form-container\">\r\n <!-- AMF Data-Driven Form Definition -->\r\n <amf-form-renderer \r\n #renderer\r\n [config]=\"loginForm\" \r\n (formSubmit)=\"onFormSubmit($event)\">\r\n </amf-form-renderer>\r\n\r\n <!-- Custom Inline Options Row -->\r\n <div class=\"form-options\">\r\n <label class=\"remember-me\">\r\n <input type=\"checkbox\" name=\"remember\" [(ngModel)]=\"rememberMe\">\r\n <span class=\"custom-check\"></span>\r\n <span>Remember me</span>\r\n </label>\r\n <a routerLink=\"/forgot-password\" class=\"forgot-link\">Forgot password?</a>\r\n </div>\r\n\r\n <button type=\"button\" class=\"login-btn\" (click)=\"triggerSubmit()\" [disabled]=\"loading()\">\r\n @if (!loading()) {\r\n <span>Sign In</span>\r\n } @else {\r\n <div class=\"loader\"></div>\r\n }\r\n </button>\r\n </div>\r\n\r\n <div class=\"auth-footer-note\">\r\n Don't have an account? <a routerLink=\"/contact-support\">Contact Support</a>\r\n </div>\r\n </amf-auth-shell>\r\n `,\r\n styles: [`\r\n :host { display: block; height: 100%; }\r\n\r\n .login-form-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 24px;\r\n }\r\n\r\n /* ── Map AMF Form classes to exactly match input-glass style ── */\r\n ::ng-deep .login-form-container .amf-form {\r\n gap: 24px;\r\n }\r\n ::ng-deep .login-form-container .amf-form-fields {\r\n gap: 24px;\r\n }\r\n ::ng-deep .login-form-container .amf-field {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n ::ng-deep .login-form-container .field-label {\r\n font-size: 0.875rem !important;\r\n font-weight: 600 !important;\r\n color: #cbd5e1 !important;\r\n margin-bottom: 0 !important;\r\n }\r\n ::ng-deep .login-form-container .field-input-wrapper {\r\n border-radius: 12px !important;\r\n border: 1px solid rgba(255, 255, 255, 0.08) !important;\r\n background: rgba(255, 255, 255, 0.04) !important;\r\n transition: all 0.3s !important;\r\n overflow: hidden;\r\n box-shadow: none !important;\r\n }\r\n ::ng-deep .login-form-container .field-input-wrapper:focus-within {\r\n border-color: var(--app-primary, #6366f1) !important;\r\n background: rgba(255, 255, 255, 0.06) !important;\r\n box-shadow: 0 0 20px var(--app-glow, rgba(99,102,241,0.3)) !important;\r\n }\r\n ::ng-deep .login-form-container .field-input {\r\n padding: 13px 16px !important;\r\n border: none !important;\r\n background: transparent !important;\r\n font-size: 1rem !important;\r\n color: #f1f5f9 !important;\r\n }\r\n ::ng-deep .login-form-container .field-input::placeholder {\r\n color: #64748b !important;\r\n }\r\n /* Adjust password eye toggle specifically for this glass look */\r\n ::ng-deep .login-form-container .pwd-toggle-btn {\r\n color: #64748b !important;\r\n }\r\n ::ng-deep .login-form-container .pwd-toggle-btn:hover {\r\n color: var(--app-primary, #6366f1) !important;\r\n }\r\n\r\n .form-options {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n font-size: 0.875rem;\r\n }\r\n\r\n .remember-me {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n cursor: pointer;\r\n color: #94a3b8;\r\n }\r\n\r\n .remember-me input { display: none; }\r\n\r\n .custom-check {\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 4px;\r\n border: 1px solid rgba(255,255,255,0.15);\r\n background: rgba(255,255,255,0.04);\r\n position: relative;\r\n transition: all 0.2s;\r\n }\r\n\r\n .remember-me input:checked + .custom-check {\r\n background: linear-gradient(135deg, var(--app-primary, #6366f1), var(--app-accent, #c084fc));\r\n border-color: transparent;\r\n }\r\n\r\n .remember-me input:checked + .custom-check::after {\r\n content: '';\r\n position: absolute;\r\n left: 5px; top: 2px;\r\n width: 4px; height: 7px;\r\n border: solid white;\r\n border-width: 0 2px 2px 0;\r\n transform: rotate(45deg);\r\n }\r\n\r\n .forgot-link {\r\n color: var(--app-primary, #6366f1);\r\n font-weight: 500;\r\n transition: all 0.2s;\r\n text-decoration: none;\r\n }\r\n\r\n .forgot-link:hover {\r\n text-shadow: 0 0 12px var(--app-glow, rgba(99,102,241,0.3));\r\n }\r\n\r\n .login-btn {\r\n background: linear-gradient(135deg, var(--app-primary, #6366f1), var(--app-accent, #c084fc));\r\n color: white;\r\n padding: 14px;\r\n border: none;\r\n border-radius: 12px;\r\n font-size: 1rem;\r\n font-weight: 600;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n position: relative;\r\n overflow: hidden;\r\n }\r\n\r\n .login-btn:hover {\r\n transform: translateY(-2px);\r\n box-shadow: 0 10px 30px -5px var(--app-glow, rgba(99,102,241,0.5));\r\n }\r\n\r\n .login-btn:disabled {\r\n opacity: 0.7;\r\n cursor: not-allowed;\r\n transform: none;\r\n }\r\n\r\n .auth-footer-note {\r\n text-align: center;\r\n margin-top: 32px;\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n }\r\n\r\n .auth-footer-note a {\r\n color: var(--app-primary, #6366f1);\r\n font-weight: 600;\r\n text-decoration: none;\r\n }\r\n\r\n .loader {\r\n width: 20px;\r\n height: 20px;\r\n border: 3px solid rgba(255,255,255,0.2);\r\n border-top: 3px solid white;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n `]\r\n})\r\nexport class LoginComponent {\r\n private auth = inject(AuthService);\r\n private dispatcher = inject(ActionDispatcherService);\r\n protected meta: any = inject(APP_META_CONFIG_TOKEN, { optional: true }) || { app: { name: 'AvoraMetaForge' } };\r\n\r\n loading = signal(false);\r\n rememberMe = false;\r\n\r\n // JSON Meta Definition replacing the hardcoded HTML fields\r\n loginForm: FormMeta = {\r\n id: 'loginForm',\r\n hideSubmit: true, // We provide our own exact-match custom button below\r\n fields: [\r\n {\r\n key: 'email',\r\n type: 'email',\r\n label: 'Email Address',\r\n placeholder: 'name@company.com',\r\n validators: [{ type: 'required' }]\r\n },\r\n {\r\n key: 'password',\r\n type: 'password',\r\n label: 'Password',\r\n placeholder: '••••••••',\r\n validators: [{ type: 'required' }]\r\n }\r\n ]\r\n };\r\n\r\n constructor(private router: Router) { }\r\n\r\n triggerSubmit(): void {\r\n // Dispatches standard AMF action to submit the specific form\r\n this.dispatcher.dispatch({\r\n type: 'submit-form',\r\n config: { formId: 'loginForm' }\r\n });\r\n }\r\n\r\n onFormSubmit(values: any): void {\r\n if (!values.email || !values.password) return;\r\n\r\n this.loading.set(true);\r\n\r\n setTimeout(() => {\r\n this.loading.set(false);\r\n \r\n this.dispatcher.dispatch({\r\n type: 'open-modal',\r\n config: {\r\n title: 'Two-Step Verification',\r\n size: 'sm',\r\n content: {\r\n type: 'form',\r\n config: {\r\n fields: [\r\n {\r\n name: 'otp',\r\n label: 'Enter 6-digit PIN',\r\n type: 'otp',\r\n required: true,\r\n otpLength: 6,\r\n validation: { minLength: 6, maxLength: 6 }\r\n }\r\n ],\r\n submitLabel: 'Verify & Login',\r\n loadingLabel: 'Verifying...',\r\n onSubmit: {\r\n type: 'api',\r\n config: { endpointId: 'mock-login-otp', body: 'formValue' },\r\n then: {\r\n type: 'dispatch-multiple',\r\n config: {\r\n mode: 'parallel',\r\n actions: [\r\n { type: 'notify', config: { type: 'success', message: 'OTP Verified! Redirecting...' } },\r\n { type: 'close-modal' },\r\n { \r\n type: 'delay', \r\n config: { duration: 600 }, \r\n then: { type: 'navigate', config: { path: '/dashboard' } } \r\n }\r\n ]\r\n }\r\n },\r\n onError: { type: 'notify', config: { type: 'error', message: 'Invalid Verification Code' } }\r\n }\r\n }\r\n }\r\n }\r\n });\r\n }, 1200);\r\n }\r\n}\r\n"],"names":["i2"],"mappings":"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"}