@insforge/react 0.4.0 → 0.4.5
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/README.md +2 -11
- package/dist/atoms.cjs +158 -139
- package/dist/atoms.cjs.map +1 -1
- package/dist/atoms.d.cts +72 -41
- package/dist/atoms.d.ts +72 -41
- package/dist/atoms.js +159 -141
- package/dist/atoms.js.map +1 -1
- package/dist/components.cjs +544 -798
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +64 -94
- package/dist/components.d.ts +64 -94
- package/dist/components.js +544 -798
- package/dist/components.js.map +1 -1
- package/dist/forms.cjs +217 -310
- package/dist/forms.cjs.map +1 -1
- package/dist/forms.d.cts +10 -13
- package/dist/forms.d.ts +10 -13
- package/dist/forms.js +218 -311
- package/dist/forms.js.map +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +581 -794
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -16
- package/dist/index.d.ts +31 -16
- package/dist/index.js +581 -794
- package/dist/index.js.map +1 -1
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +0 -11
- package/dist/router.d.ts +0 -11
- package/dist/router.js.map +1 -1
- package/dist/styles.css +212 -3
- package/dist/types.d.cts +11 -613
- package/dist/types.d.ts +11 -613
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
|
|
5
5
|
if (!document.getElementById(styleId)) {
|
|
6
6
|
const style = document.createElement('style');
|
|
7
7
|
style.id = styleId;
|
|
8
|
-
style.textContent = "/**\n * InsForge React Component Library Styles\n * Traditional CSS with scoped class names (no Tailwind)\n */\n\n/* ============================================\n FONTS\n ============================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');\n@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap');\n\n/* ============================================\n CSS VARIABLES\n ============================================ */\n:root {\n /* Colors */\n --if-color-primary: #000000;\n --if-color-primary-hover: #1f1f1f;\n --if-color-text: #000000;\n --if-color-text-secondary: #828282;\n --if-color-text-muted: #a3a3a3;\n --if-color-border: #d4d4d4;\n --if-color-border-focus: #000000;\n --if-color-bg-white: #ffffff;\n --if-color-bg-light: #fafafa;\n --if-color-bg-hover: #f9fafb;\n --if-color-error: #dc2626;\n --if-color-error-bg: #fee2e2;\n --if-color-success: #16a34a;\n\n /* Spacing */\n --if-space-1: 0.25rem; /* 4px */\n --if-space-2: 0.5rem; /* 8px */\n --if-space-3: 0.75rem; /* 12px */\n --if-space-4: 1rem; /* 16px */\n --if-space-6: 1.5rem; /* 24px */\n --if-space-8: 2rem; /* 32px */\n\n /* Border Radius */\n --if-radius-xs: 0.125rem; /* 2px */\n --if-radius-sm: 0.25rem; /* 4px */\n --if-radius-md: 0.375rem; /* 6px */\n --if-radius-lg: 0.5rem; /* 8px */\n --if-radius-xl: 0.75rem; /* 12px */\n\n /* Typography */\n --if-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n --if-font-family-manrope:\n 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n --if-font-size-xs: 0.75rem; /* 12px */\n --if-font-size-sm: 0.875rem; /* 14px */\n --if-font-size-base: 1rem; /* 16px */\n --if-font-size-lg: 1.125rem; /* 18px */\n --if-font-size-xl: 1.25rem; /* 20px */\n --if-font-size-2xl: 1.5rem; /* 24px */\n\n /* Shadows */\n --if-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --if-shadow-md: 0 1px 2px 0 rgba(0, 0, 0, 0.1);\n --if-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n\n /* Transitions */\n --if-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);\n --if-transition-base: 200ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ============================================\n AUTH CONTAINER\n ============================================ */\n.if-authContainer {\n width: 100%;\n max-width: 400px;\n border-radius: var(--if-radius-xl);\n overflow: hidden;\n box-shadow: var(--if-shadow-lg);\n}\n\n.if-authCard {\n background-color: var(--if-color-bg-white);\n padding: var(--if-space-6);\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-6);\n}\n\n/* ============================================\n AUTH HEADER\n ============================================ */\n.if-authHeader {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n gap: var(--if-space-2);\n}\n\n.if-authHeader-title {\n font-size: var(--if-font-size-2xl);\n font-weight: 600;\n color: var(--if-color-text);\n line-height: 2rem;\n margin: 0;\n font-family: var(--if-font-family);\n}\n\n.if-authHeader-subtitle {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text-secondary);\n line-height: 1.5rem;\n margin: 0;\n font-family: var(--if-font-family);\n}\n\n/* ============================================\n FORM FIELD\n ============================================ */\n.if-formField {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-1);\n}\n\n.if-formField-label {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text);\n line-height: 1.5rem;\n font-family: var(--if-font-family);\n}\n\n.if-formField-input {\n width: 100%;\n display: flex;\n align-items: center;\n gap: var(--if-space-2);\n align-self: stretch;\n padding: var(--if-space-2) var(--if-space-3);\n border-radius: var(--if-radius-sm);\n border: 1px solid var(--if-color-border);\n background-color: var(--if-color-bg-white);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n line-height: 1.25rem;\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n transition: border-color var(--if-transition-base);\n}\n\n.if-formField-input::placeholder {\n color: var(--if-color-text-muted);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n}\n\n.if-formField-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n/* ============================================\n PASSWORD FIELD\n ============================================ */\n.if-passwordField {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-1);\n}\n\n.if-passwordField-labelRow {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.if-passwordField-label {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text);\n line-height: 1.5rem;\n font-family: var(--if-font-family);\n}\n\n.if-passwordField-forgotLink {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text-secondary);\n text-decoration: none;\n transition: color var(--if-transition-fast);\n font-family: var(--if-font-family);\n}\n\n.if-passwordField-inputWrapper {\n position: relative;\n width: 100%;\n}\n\n.if-passwordField-input {\n width: 100%;\n display: flex;\n align-items: center;\n align-self: stretch;\n padding: var(--if-space-2) var(--if-space-3);\n padding-right: 2.5rem; /* Space for toggle button */\n border-radius: var(--if-radius-sm);\n border: 1px solid var(--if-color-border);\n background-color: var(--if-color-bg-white);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n line-height: 1.25rem;\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n transition: border-color var(--if-transition-base);\n}\n\n.if-passwordField-input::placeholder {\n color: var(--if-color-text-muted);\n}\n\n.if-passwordField-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n.if-passwordField-toggleButton {\n position: absolute;\n right: var(--if-space-1);\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n cursor: pointer;\n padding: var(--if-space-1);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--if-color-text-secondary);\n transition: color var(--if-transition-fast);\n}\n\n/* ============================================\n SUBMIT BUTTON\n ============================================ */\n.if-submitButton {\n border-radius: var(--if-radius-sm);\n background-color: var(--if-color-primary);\n height: 2.5rem;\n width: 100%;\n display: flex;\n margin-top: var(--if-space-4);\n padding: var(--if-space-2) var(--if-space-4);\n justify-content: center;\n align-items: center;\n gap: 0.625rem;\n align-self: stretch;\n color: var(--if-color-bg-white);\n font-weight: 600;\n font-family: var(--if-font-family-manrope);\n font-size: var(--if-font-size-base);\n line-height: normal;\n border: none;\n cursor: pointer;\n transition: background-color var(--if-transition-base);\n}\n\n.if-submitButton:hover:not(:disabled) {\n background-color: var(--if-color-primary-hover);\n}\n\n.if-submitButton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.if-submitButton-icon {\n width: 1.25rem;\n height: 1.25rem;\n}\n\n/* Spinner animation */\n@keyframes if-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n.if-submitButton-spinner {\n animation: if-spin 1s linear infinite;\n}\n\n/* ============================================\n OAUTH BUTTON\n ============================================ */\n.if-oauthButton {\n display: flex;\n width: 100%;\n height: 2.25rem;\n padding: var(--if-space-2) var(--if-space-3);\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-3);\n border-radius: var(--if-radius-md);\n border: 1px solid #e4e4e7;\n background-color: var(--if-color-bg-white);\n box-shadow: var(--if-shadow-md);\n color: #09090b;\n text-align: center;\n font-size: var(--if-font-size-sm);\n font-weight: 500;\n line-height: 1.25rem;\n cursor: pointer;\n transition: all var(--if-transition-base);\n font-family: var(--if-font-family);\n}\n\n.if-oauthButton:hover:not(:disabled) {\n background-color: var(--if-color-bg-hover);\n border-color: #9ca3af;\n}\n\n.if-oauthButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.if-oauthButton-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1.125rem;\n height: 1.125rem;\n}\n\n.if-oauthButton-full {\n justify-content: center;\n}\n\n.if-oauthButton-short {\n justify-content: center;\n padding: var(--if-space-2);\n gap: var(--if-space-2);\n}\n\n.if-oauthButton-icon-only {\n justify-content: center;\n gap: 0;\n}\n\n/* ============================================\n OAUTH PROVIDERS CONTAINER\n ============================================ */\n.if-oauthProviders {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-3);\n width: 100%;\n}\n\n/* ============================================\n AUTH LINK\n ============================================ */\n.if-authLink {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-1);\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-authLink-text {\n font-weight: 400;\n}\n\n.if-authLink-link {\n font-weight: 600;\n color: var(--if-color-text);\n text-decoration: none;\n transition: opacity var(--if-transition-fast);\n}\n\n/* ============================================\n AUTH DIVIDER\n ============================================ */\n.if-authDivider {\n display: flex;\n align-items: center;\n text-align: center;\n width: 100%;\n gap: var(--if-space-3);\n}\n\n.if-authDivider-line {\n flex: 1;\n border-top: 1px solid var(--if-color-border);\n}\n\n.if-authDivider-text {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n font-weight: 400;\n font-family: var(--if-font-family-manrope);\n}\n\n/* ============================================\n ERROR BANNER\n ============================================ */\n.if-errorBanner {\n padding: var(--if-space-3);\n background-color: var(--if-color-error-bg);\n border-radius: var(--if-radius-md);\n border: 1px solid var(--if-color-error);\n}\n\n.if-errorBanner-text {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-error);\n font-weight: 400;\n font-family: var(--if-font-family);\n margin: 0;\n}\n\n/* ============================================\n AUTH BRANDING\n ============================================ */\n.if-authBranding {\n background-color: var(--if-color-bg-light);\n padding: var(--if-space-4) var(--if-space-2);\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-1);\n}\n\n.if-authBranding-text {\n font-size: var(--if-font-size-xs);\n font-weight: 500;\n color: var(--if-color-text);\n font-family: var(--if-font-family-manrope);\n margin: 0;\n}\n\n/* ============================================\n VERIFICATION CODE INPUT\n ============================================ */\n.if-verificationCode {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-4);\n}\n\n.if-verificationCode-description {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n text-align: center;\n font-family: var(--if-font-family);\n}\n\n.if-verificationCode-email {\n font-weight: 600;\n color: var(--if-color-text);\n}\n\n.if-verificationCode-inputContainer {\n display: flex;\n gap: var(--if-space-2);\n justify-content: center;\n}\n\n.if-verificationCode-input {\n width: 3rem;\n height: 3rem;\n text-align: center;\n font-size: var(--if-font-size-xl);\n font-weight: 600;\n border: 2px solid var(--if-color-border);\n border-radius: var(--if-radius-md);\n transition: border-color var(--if-transition-base);\n font-family: var(--if-font-family);\n}\n\n.if-verificationCode-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n/* ============================================\n PASSWORD STRENGTH INDICATOR\n ============================================ */\n.if-passwordStrength {\n margin-top: var(--if-space-2);\n}\n\n.if-passwordStrength-bar {\n height: 4px;\n background-color: #e5e7eb;\n border-radius: 2px;\n overflow: hidden;\n margin-bottom: var(--if-space-2);\n}\n\n.if-passwordStrength-fill {\n height: 100%;\n transition:\n width var(--if-transition-base),\n background-color var(--if-transition-base);\n}\n\n.if-passwordStrength-fill.weak {\n background-color: #ef4444;\n width: 33%;\n}\n\n.if-passwordStrength-fill.medium {\n background-color: #f59e0b;\n width: 66%;\n}\n\n.if-passwordStrength-fill.strong {\n background-color: var(--if-color-success);\n width: 100%;\n}\n\n.if-passwordStrength-text {\n font-size: var(--if-font-size-xs);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-passwordStrength-requirements {\n margin-top: var(--if-space-2);\n font-size: var(--if-font-size-xs);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-passwordStrength-requirement {\n display: flex;\n align-items: center;\n gap: var(--if-space-1);\n margin-bottom: var(--if-space-1);\n}\n\n.if-passwordStrength-requirement.met {\n color: var(--if-color-success);\n}\n\n.if-passwordStrength-requirement.unmet {\n color: var(--if-color-text-muted);\n}\n\n/* ============================================\n FORM CONTAINER\n ============================================ */\n.if-form {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n gap: var(--if-space-6);\n}\n\n/* ============================================\n USER BUTTON\n ============================================ */\n.if-userButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--if-space-2);\n border-radius: 9999px;\n background-color: var(--if-color-bg-white);\n border: 1px solid var(--if-color-border);\n cursor: pointer;\n transition: all var(--if-transition-base);\n}\n\n.if-userButton:hover {\n background-color: var(--if-color-bg-light);\n}\n\n.if-userButton-avatar {\n width: 2rem;\n height: 2rem;\n border-radius: 9999px;\n background-color: var(--if-color-primary);\n color: var(--if-color-bg-white);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: var(--if-font-size-sm);\n font-family: var(--if-font-family);\n}\n\n.if-userButton-menu {\n position: absolute;\n margin-top: var(--if-space-2);\n background-color: var(--if-color-bg-white);\n border: 1px solid var(--if-color-border);\n border-radius: var(--if-radius-md);\n box-shadow: var(--if-shadow-lg);\n padding: var(--if-space-2);\n min-width: 200px;\n z-index: 50;\n}\n\n.if-userButton-menuItem {\n display: flex;\n align-items: center;\n gap: var(--if-space-2);\n padding: var(--if-space-2);\n border-radius: var(--if-radius-sm);\n cursor: pointer;\n transition: background-color var(--if-transition-fast);\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n}\n\n.if-userButton-menuItem:hover {\n background-color: var(--if-color-bg-light);\n}\n\n/* ============================================\n UTILITY CLASSES\n ============================================ */\n.if-hidden {\n display: none;\n}\n\n.if-visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n";
|
|
8
|
+
style.textContent = "/**\n * InsForge React Component Library Styles\n * Traditional CSS with scoped class names (no Tailwind)\n */\n\n/* ============================================\n FONTS\n ============================================ */\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');\n@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap');\n\n/* ============================================\n CSS VARIABLES\n ============================================ */\n:root {\n /* Colors */\n --if-color-primary: #000000;\n --if-color-primary-hover: #1f1f1f;\n --if-color-text: #000000;\n --if-color-text-secondary: #828282;\n --if-color-text-muted: #a3a3a3;\n --if-color-border: #d4d4d4;\n --if-color-border-focus: #000000;\n --if-color-bg-white: #ffffff;\n --if-color-bg-light: #fafafa;\n --if-color-bg-hover: #f9fafb;\n --if-color-error: #dc2626;\n --if-color-error-bg: #fee2e2;\n --if-color-success: #16a34a;\n\n /* Spacing */\n --if-space-1: 0.25rem; /* 4px */\n --if-space-2: 0.5rem; /* 8px */\n --if-space-3: 0.75rem; /* 12px */\n --if-space-4: 1rem; /* 16px */\n --if-space-6: 1.5rem; /* 24px */\n --if-space-8: 2rem; /* 32px */\n\n /* Border Radius */\n --if-radius-xs: 0.125rem; /* 2px */\n --if-radius-sm: 0.25rem; /* 4px */\n --if-radius-md: 0.375rem; /* 6px */\n --if-radius-lg: 0.5rem; /* 8px */\n --if-radius-xl: 0.75rem; /* 12px */\n\n /* Typography */\n --if-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n --if-font-family-manrope:\n 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n --if-font-size-xs: 0.75rem; /* 12px */\n --if-font-size-sm: 0.875rem; /* 14px */\n --if-font-size-base: 1rem; /* 16px */\n --if-font-size-lg: 1.125rem; /* 18px */\n --if-font-size-xl: 1.25rem; /* 20px */\n --if-font-size-2xl: 1.5rem; /* 24px */\n\n /* Shadows */\n --if-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --if-shadow-md: 0 1px 2px 0 rgba(0, 0, 0, 0.1);\n --if-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n\n /* Transitions */\n --if-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);\n --if-transition-base: 200ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ============================================\n AUTH CONTAINER\n ============================================ */\n.if-authContainer {\n width: 100%;\n max-width: 400px;\n border-radius: var(--if-radius-xl);\n overflow: hidden;\n box-shadow: var(--if-shadow-lg);\n}\n\n.if-authCard {\n background-color: var(--if-color-bg-white);\n padding: var(--if-space-6);\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-6);\n}\n\n/* ============================================\n AUTH HEADER\n ============================================ */\n.if-authHeader {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n gap: var(--if-space-2);\n}\n\n.if-authHeader-title {\n font-size: var(--if-font-size-2xl);\n font-weight: 600;\n color: var(--if-color-text);\n line-height: 2rem;\n margin: 0;\n font-family: var(--if-font-family);\n}\n\n.if-authHeader-subtitle {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text-secondary);\n line-height: 1.5rem;\n margin: 0;\n font-family: var(--if-font-family);\n}\n\n/* ============================================\n FORM FIELD\n ============================================ */\n.if-formField {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-1);\n}\n\n.if-formField-label {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text);\n line-height: 1.5rem;\n font-family: var(--if-font-family);\n}\n\n.if-formField-input {\n width: 100%;\n display: flex;\n align-items: center;\n gap: var(--if-space-2);\n align-self: stretch;\n padding: var(--if-space-2) var(--if-space-3);\n border-radius: var(--if-radius-sm);\n border: 1px solid var(--if-color-border);\n background-color: var(--if-color-bg-white);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n line-height: 1.25rem;\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n transition: border-color var(--if-transition-base);\n}\n\n.if-formField-input::placeholder {\n color: var(--if-color-text-muted);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n}\n\n.if-formField-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n/* ============================================\n PASSWORD FIELD\n ============================================ */\n.if-passwordField {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: var(--if-space-1);\n}\n\n.if-passwordField-labelRow {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.if-passwordField-label {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text);\n line-height: 1.5rem;\n font-family: var(--if-font-family);\n}\n\n.if-passwordField-forgotLink {\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n color: var(--if-color-text-secondary);\n text-decoration: none;\n transition: color var(--if-transition-fast);\n font-family: var(--if-font-family);\n}\n\n.if-passwordField-inputWrapper {\n position: relative;\n width: 100%;\n}\n\n.if-passwordField-input {\n width: 100%;\n display: flex;\n align-items: center;\n align-self: stretch;\n padding: var(--if-space-2) var(--if-space-3);\n padding-right: 2.5rem; /* Space for toggle button */\n border-radius: var(--if-radius-sm);\n border: 1px solid var(--if-color-border);\n background-color: var(--if-color-bg-white);\n font-size: var(--if-font-size-sm);\n font-weight: 400;\n line-height: 1.25rem;\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n transition: border-color var(--if-transition-base);\n}\n\n.if-passwordField-input::placeholder {\n color: var(--if-color-text-muted);\n}\n\n.if-passwordField-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n.if-passwordField-toggleButton {\n position: absolute;\n right: var(--if-space-1);\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n cursor: pointer;\n padding: var(--if-space-1);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--if-color-text-secondary);\n transition: color var(--if-transition-fast);\n}\n\n/* ============================================\n SUBMIT BUTTON\n ============================================ */\n.if-submitButton {\n border-radius: var(--if-radius-sm);\n background-color: var(--if-color-primary);\n height: 2.5rem;\n width: 100%;\n display: flex;\n margin-top: var(--if-space-4);\n padding: var(--if-space-2) var(--if-space-4);\n justify-content: center;\n align-items: center;\n gap: 0.625rem;\n align-self: stretch;\n color: var(--if-color-bg-white);\n font-weight: 600;\n font-family: var(--if-font-family-manrope);\n font-size: var(--if-font-size-base);\n line-height: normal;\n border: none;\n cursor: pointer;\n transition: background-color var(--if-transition-base);\n}\n\n.if-submitButton:hover:not(:disabled) {\n background-color: var(--if-color-primary-hover);\n}\n\n.if-submitButton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.if-submitButton-icon {\n width: 1.25rem;\n height: 1.25rem;\n}\n\n/* Spinner animation */\n@keyframes if-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n.if-submitButton-spinner {\n animation: if-spin 1s linear infinite;\n}\n\n/* ============================================\n OAUTH BUTTON\n ============================================ */\n.if-oauthButton {\n display: flex;\n width: 100%;\n height: 2.25rem;\n padding: var(--if-space-2) var(--if-space-3);\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-3);\n border-radius: var(--if-radius-md);\n border: 1px solid #e4e4e7;\n background-color: var(--if-color-bg-white);\n box-shadow: var(--if-shadow-md);\n color: #09090b;\n text-align: center;\n font-size: var(--if-font-size-sm);\n font-weight: 500;\n line-height: 1.25rem;\n cursor: pointer;\n transition: all var(--if-transition-base);\n font-family: var(--if-font-family);\n}\n\n.if-oauthButton:hover:not(:disabled) {\n background-color: var(--if-color-bg-hover);\n border-color: #9ca3af;\n}\n\n.if-oauthButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.if-oauthButton-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1.125rem;\n height: 1.125rem;\n}\n\n.if-oauthButton-full {\n justify-content: center;\n}\n\n.if-oauthButton-short {\n justify-content: center;\n padding: var(--if-space-2);\n gap: var(--if-space-2);\n}\n\n.if-oauthButton-icon-only {\n justify-content: center;\n gap: 0;\n}\n\n/* ============================================\n OAUTH PROVIDERS CONTAINER\n ============================================ */\n.if-oauthProviders {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-3);\n width: 100%;\n}\n\n/* ============================================\n AUTH LINK\n ============================================ */\n.if-authLink {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-1);\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-authLink-text {\n font-weight: 400;\n}\n\n.if-authLink-link {\n font-weight: 600;\n color: var(--if-color-text);\n text-decoration: none;\n transition: opacity var(--if-transition-fast);\n}\n\n/* ============================================\n AUTH DIVIDER\n ============================================ */\n.if-authDivider {\n display: flex;\n align-items: center;\n text-align: center;\n width: 100%;\n gap: var(--if-space-3);\n}\n\n.if-authDivider-line {\n flex: 1;\n border-top: 1px solid var(--if-color-border);\n}\n\n.if-authDivider-text {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n font-weight: 400;\n font-family: var(--if-font-family-manrope);\n}\n\n/* ============================================\n ERROR BANNER\n ============================================ */\n.if-errorBanner {\n padding: var(--if-space-3);\n background-color: var(--if-color-error-bg);\n border-radius: var(--if-radius-md);\n border: 1px solid var(--if-color-error);\n}\n\n.if-errorBanner-content {\n display: flex;\n align-items: center;\n gap: var(--if-space-2);\n}\n\n.if-errorBanner-icon {\n width: 1.5rem;\n height: 1.5rem;\n flex-shrink: 0;\n color: var(--if-color-error);\n}\n\n.if-errorBanner-text {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-error);\n font-weight: 400;\n font-family: var(--if-font-family);\n margin: 0;\n}\n\n/* ============================================\n AUTH BRANDING\n ============================================ */\n.if-authBranding {\n background-color: var(--if-color-bg-light);\n padding: var(--if-space-4) var(--if-space-2);\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: var(--if-space-1);\n}\n\n.if-authBranding-text {\n font-size: var(--if-font-size-xs);\n font-weight: 500;\n color: var(--if-color-text);\n font-family: var(--if-font-family-manrope);\n margin: 0;\n}\n\n/* ============================================\n VERIFICATION CODE INPUT\n ============================================ */\n.if-verificationCode {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-4);\n}\n\n.if-verificationCode-description {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n text-align: center;\n font-family: var(--if-font-family);\n}\n\n.if-verificationCode-email {\n font-weight: 600;\n color: var(--if-color-text);\n}\n\n.if-verificationCode-inputContainer {\n display: flex;\n gap: var(--if-space-2);\n justify-content: center;\n}\n\n.if-verificationCode-input {\n width: 3rem;\n height: 3rem;\n text-align: center;\n font-size: var(--if-font-size-xl);\n font-weight: 600;\n border: 2px solid var(--if-color-border);\n border-radius: var(--if-radius-md);\n transition: border-color var(--if-transition-base);\n font-family: var(--if-font-family);\n}\n\n.if-verificationCode-input:focus {\n outline: none;\n border-color: var(--if-color-border-focus);\n}\n\n/* ============================================\n VERIFICATION STEP\n ============================================ */\n.if-verificationStep {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-6);\n align-items: stretch;\n}\n\n.if-verificationStep-description {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n text-align: center;\n margin: 0;\n font-family: var(--if-font-family);\n}\n\n.if-verificationStep-codeContainer {\n width: 100%;\n background-color: #f5f5f5;\n border-radius: var(--if-radius-lg);\n padding: var(--if-space-4) var(--if-space-4) var(--if-space-6);\n display: flex;\n flex-direction: column;\n gap: var(--if-space-4);\n}\n\n.if-verificationStep-codeInputWrapper {\n display: flex;\n flex-direction: column;\n gap: var(--if-space-3);\n margin-top: var(--if-space-2);\n}\n\n.if-verificationStep-verifyingText {\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text-secondary);\n text-align: center;\n font-family: var(--if-font-family);\n}\n\n.if-verificationStep-resendContainer {\n width: 100%;\n font-size: var(--if-font-size-sm);\n text-align: center;\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-verificationStep-resendButton {\n color: var(--if-color-text);\n font-weight: 500;\n transition: all var(--if-transition-base);\n background: none;\n border: none;\n padding: 0;\n font-family: var(--if-font-family);\n font-size: var(--if-font-size-sm);\n}\n\n.if-verificationStep-resendButton:not(:disabled) {\n cursor: pointer;\n text-decoration: underline;\n}\n\n.if-verificationStep-resendButton:disabled {\n cursor: not-allowed;\n text-decoration: none;\n opacity: 0.5;\n}\n\n/* ============================================\n PASSWORD STRENGTH INDICATOR\n ============================================ */\n.if-passwordStrength {\n margin-top: var(--if-space-2);\n}\n\n.if-passwordStrength-bar {\n height: 4px;\n background-color: #e5e7eb;\n border-radius: 2px;\n overflow: hidden;\n margin-bottom: var(--if-space-2);\n}\n\n.if-passwordStrength-fill {\n height: 100%;\n transition:\n width var(--if-transition-base),\n background-color var(--if-transition-base);\n}\n\n.if-passwordStrength-fill.weak {\n background-color: #ef4444;\n width: 33%;\n}\n\n.if-passwordStrength-fill.medium {\n background-color: #f59e0b;\n width: 66%;\n}\n\n.if-passwordStrength-fill.strong {\n background-color: var(--if-color-success);\n width: 100%;\n}\n\n.if-passwordStrength-text {\n font-size: var(--if-font-size-xs);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-passwordStrength-requirements {\n margin-top: var(--if-space-2);\n font-size: var(--if-font-size-xs);\n color: var(--if-color-text-secondary);\n font-family: var(--if-font-family);\n}\n\n.if-passwordStrength-requirement {\n display: flex;\n align-items: center;\n gap: var(--if-space-1);\n margin-bottom: var(--if-space-1);\n}\n\n.if-passwordStrength-requirement.met {\n color: var(--if-color-success);\n}\n\n.if-passwordStrength-requirement.unmet {\n color: var(--if-color-text-muted);\n}\n\n/* ============================================\n FORM CONTAINER\n ============================================ */\n.if-form {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n gap: var(--if-space-6);\n}\n\n/* ============================================\n USER BUTTON\n ============================================ */\n.if-userButton-container {\n position: relative;\n display: inline-block;\n}\n\n.if-userButton {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--if-space-2);\n padding: var(--if-space-2);\n border-radius: 9999px;\n background-color: transparent;\n border: none;\n cursor: pointer;\n transition: all var(--if-transition-base);\n}\n\n.if-userButton:hover {\n opacity: 0.8;\n}\n\n.if-userButton-detailed {\n background-color: var(--if-color-bg-white);\n border: 1px solid var(--if-color-border);\n border-radius: var(--if-radius-sm);\n padding: var(--if-space-2);\n}\n\n.if-userButton-detailed:hover {\n background-color: var(--if-color-bg-light);\n opacity: 1;\n}\n\n.if-userButton-avatar {\n width: 2rem;\n height: 2rem;\n border-radius: 9999px;\n background-color: var(--if-color-primary);\n color: var(--if-color-bg-white);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: var(--if-font-size-sm);\n font-family: var(--if-font-family);\n overflow: hidden;\n}\n\n.if-userButton-avatarImage {\n border-radius: 9999px;\n object-fit: cover;\n width: 100%;\n height: 100%;\n}\n\n.if-userButton-avatarInitials {\n color: var(--if-color-bg-white);\n font-weight: 600;\n font-size: var(--if-font-size-sm);\n}\n\n.if-userButton-info {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.125rem;\n}\n\n.if-userButton-name {\n font-size: var(--if-font-size-sm);\n font-weight: 600;\n color: var(--if-color-text);\n line-height: 1.25rem;\n text-align: left;\n font-family: var(--if-font-family);\n}\n\n.if-userButton-email {\n font-size: var(--if-font-size-xs);\n color: var(--if-color-text-secondary);\n line-height: 1rem;\n text-align: left;\n font-family: var(--if-font-family);\n}\n\n.if-userButton-menu {\n position: absolute;\n margin-top: var(--if-space-2);\n background-color: var(--if-color-bg-white);\n border: 1px solid var(--if-color-border);\n border-radius: var(--if-radius-md);\n box-shadow: var(--if-shadow-lg);\n padding: var(--if-space-2);\n min-width: 200px;\n z-index: 50;\n}\n\n.if-userButton-menuItem {\n display: flex;\n align-items: center;\n gap: var(--if-space-2);\n padding: var(--if-space-2);\n border-radius: var(--if-radius-sm);\n cursor: pointer;\n transition: background-color var(--if-transition-fast);\n font-size: var(--if-font-size-sm);\n color: var(--if-color-text);\n font-family: var(--if-font-family);\n background: none;\n border: none;\n width: 100%;\n text-align: left;\n}\n\n.if-userButton-menuItem:hover {\n background-color: var(--if-color-bg-light);\n}\n\n.if-userButton-menuItem-signout {\n color: var(--if-color-error);\n}\n\n.if-userButton-menuItem-icon {\n width: 1.25rem;\n height: 1.25rem;\n}\n\n/* ============================================\n EMAIL VERIFICATION STATUS\n ============================================ */\n.if-verifyStatus-container {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--if-space-6);\n}\n\n.if-verifyStatus-container-stretch {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n gap: var(--if-space-6);\n}\n\n.if-verifyStatus-spinner {\n border-radius: 9999px;\n height: 3rem;\n width: 3rem;\n border-bottom: 2px solid var(--if-color-primary);\n}\n\n.if-verifyStatus-successContent {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--if-space-4);\n}\n\n.if-verifyStatus-successIcon {\n width: 4rem;\n height: 4rem;\n border-radius: 9999px;\n background-color: #d1fae5;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.if-verifyStatus-successIconSvg {\n width: 2rem;\n height: 2rem;\n color: #059669;\n}\n\n.if-verifyStatus-textCenter {\n text-align: center;\n}\n\n/* ============================================\n UTILITY CLASSES\n ============================================ */\n.if-hidden {\n display: none;\n}\n\n.if-visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n";
|
|
9
9
|
if (document.head) {
|
|
10
10
|
document.head.appendChild(style);
|
|
11
11
|
}
|
|
@@ -13,6 +13,7 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
import { createContext, useState, useRef, useCallback, useEffect, useContext } from 'react';
|
|
16
|
+
import { useSearchParams } from 'react-router-dom';
|
|
16
17
|
import { createClient } from '@insforge/sdk';
|
|
17
18
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
18
19
|
import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, LogOut } from 'lucide-react';
|
|
@@ -23,8 +24,8 @@ function InsforgeProvider({
|
|
|
23
24
|
children,
|
|
24
25
|
baseUrl,
|
|
25
26
|
onAuthChange,
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
onSignIn,
|
|
28
|
+
onSignOut
|
|
28
29
|
}) {
|
|
29
30
|
const [user, setUser] = useState(null);
|
|
30
31
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
@@ -60,9 +61,9 @@ function InsforgeProvider({
|
|
|
60
61
|
return { success: true };
|
|
61
62
|
} else {
|
|
62
63
|
await insforge.auth.signOut();
|
|
63
|
-
if (
|
|
64
|
+
if (onSignOut) {
|
|
64
65
|
try {
|
|
65
|
-
await
|
|
66
|
+
await onSignOut();
|
|
66
67
|
} catch (error) {
|
|
67
68
|
if (error instanceof Error) {
|
|
68
69
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -79,9 +80,9 @@ function InsforgeProvider({
|
|
|
79
80
|
} catch (error) {
|
|
80
81
|
console.error("[InsforgeProvider] Token validation failed:", error);
|
|
81
82
|
await insforge.auth.signOut();
|
|
82
|
-
if (
|
|
83
|
+
if (onSignOut) {
|
|
83
84
|
try {
|
|
84
|
-
await
|
|
85
|
+
await onSignOut();
|
|
85
86
|
} catch (error2) {
|
|
86
87
|
if (error2 instanceof Error) {
|
|
87
88
|
console.error("[InsforgeProvider] Error clearing cookie:", error2.message);
|
|
@@ -98,7 +99,7 @@ function InsforgeProvider({
|
|
|
98
99
|
error: error instanceof Error ? error.message : "Authentication failed"
|
|
99
100
|
};
|
|
100
101
|
}
|
|
101
|
-
}, [insforge, onAuthChange,
|
|
102
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
102
103
|
useEffect(() => {
|
|
103
104
|
loadAuthState();
|
|
104
105
|
const intervalId = refreshIntervalRef.current;
|
|
@@ -137,9 +138,9 @@ function InsforgeProvider({
|
|
|
137
138
|
if (onAuthChange) {
|
|
138
139
|
onAuthChange(userData);
|
|
139
140
|
}
|
|
140
|
-
if (
|
|
141
|
+
if (onSignIn) {
|
|
141
142
|
try {
|
|
142
|
-
await
|
|
143
|
+
await onSignIn(authToken);
|
|
143
144
|
} catch (error) {
|
|
144
145
|
if (error instanceof Error) {
|
|
145
146
|
console.error("[InsforgeProvider] Error syncing token to cookie:", error.message);
|
|
@@ -159,7 +160,7 @@ function InsforgeProvider({
|
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
},
|
|
162
|
-
[insforge, onAuthChange,
|
|
163
|
+
[insforge, onAuthChange, onSignIn]
|
|
163
164
|
);
|
|
164
165
|
const signIn = useCallback(
|
|
165
166
|
async (email, password) => {
|
|
@@ -214,9 +215,9 @@ function InsforgeProvider({
|
|
|
214
215
|
);
|
|
215
216
|
const signOut = useCallback(async () => {
|
|
216
217
|
await insforge.auth.signOut();
|
|
217
|
-
if (
|
|
218
|
+
if (onSignOut) {
|
|
218
219
|
try {
|
|
219
|
-
await
|
|
220
|
+
await onSignOut();
|
|
220
221
|
} catch (error) {
|
|
221
222
|
if (error instanceof Error) {
|
|
222
223
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -230,7 +231,7 @@ function InsforgeProvider({
|
|
|
230
231
|
if (onAuthChange) {
|
|
231
232
|
onAuthChange(null);
|
|
232
233
|
}
|
|
233
|
-
}, [insforge, onAuthChange,
|
|
234
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
234
235
|
const updateUser = useCallback(
|
|
235
236
|
async (data) => {
|
|
236
237
|
if (!user) {
|
|
@@ -260,6 +261,13 @@ function InsforgeProvider({
|
|
|
260
261
|
},
|
|
261
262
|
[user, onAuthChange, insforge]
|
|
262
263
|
);
|
|
264
|
+
const sendVerificationEmail = useCallback(
|
|
265
|
+
async (email) => {
|
|
266
|
+
const sdkResult = await insforge.auth.sendVerificationEmail({ email });
|
|
267
|
+
return sdkResult.data;
|
|
268
|
+
},
|
|
269
|
+
[insforge]
|
|
270
|
+
);
|
|
263
271
|
const sendResetPasswordEmail = useCallback(
|
|
264
272
|
async (email) => {
|
|
265
273
|
const sdkResult = await insforge.auth.sendResetPasswordEmail({ email });
|
|
@@ -278,8 +286,39 @@ function InsforgeProvider({
|
|
|
278
286
|
[insforge]
|
|
279
287
|
);
|
|
280
288
|
const verifyEmail = useCallback(
|
|
281
|
-
async (
|
|
282
|
-
const sdkResult = await insforge.auth.verifyEmail({ otp:
|
|
289
|
+
async (otp, email) => {
|
|
290
|
+
const sdkResult = await insforge.auth.verifyEmail({ otp, email: email || void 0 });
|
|
291
|
+
if (sdkResult.data) {
|
|
292
|
+
return sdkResult.data;
|
|
293
|
+
} else {
|
|
294
|
+
return {
|
|
295
|
+
accessToken: "",
|
|
296
|
+
error: {
|
|
297
|
+
message: sdkResult.error?.message || "Email verification failed"
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
[insforge]
|
|
303
|
+
);
|
|
304
|
+
const exchangeResetPasswordToken = useCallback(
|
|
305
|
+
async (email, code) => {
|
|
306
|
+
const sdkResult = await insforge.auth.exchangeResetPasswordToken({ email, code });
|
|
307
|
+
if (sdkResult.data) {
|
|
308
|
+
return sdkResult.data;
|
|
309
|
+
} else {
|
|
310
|
+
return {
|
|
311
|
+
error: {
|
|
312
|
+
message: sdkResult.error?.message || "Failed to exchange reset password token"
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
[insforge]
|
|
318
|
+
);
|
|
319
|
+
const loginWithOAuth = useCallback(
|
|
320
|
+
async (provider, redirectTo) => {
|
|
321
|
+
const sdkResult = await insforge.auth.signInWithOAuth({ provider, redirectTo });
|
|
283
322
|
return sdkResult.data;
|
|
284
323
|
},
|
|
285
324
|
[insforge]
|
|
@@ -298,10 +337,13 @@ function InsforgeProvider({
|
|
|
298
337
|
updateUser,
|
|
299
338
|
reloadAuth: loadAuthState,
|
|
300
339
|
baseUrl,
|
|
340
|
+
sendVerificationEmail,
|
|
301
341
|
sendResetPasswordEmail,
|
|
302
342
|
resetPassword,
|
|
303
343
|
verifyEmail,
|
|
304
|
-
|
|
344
|
+
exchangeResetPasswordToken,
|
|
345
|
+
getPublicAuthConfig,
|
|
346
|
+
loginWithOAuth
|
|
305
347
|
},
|
|
306
348
|
children
|
|
307
349
|
}
|
|
@@ -419,21 +461,12 @@ function AuthErrorBanner({ error }) {
|
|
|
419
461
|
if (!error) {
|
|
420
462
|
return null;
|
|
421
463
|
}
|
|
422
|
-
return /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", {
|
|
423
|
-
/* @__PURE__ */ jsx(
|
|
424
|
-
AlertTriangle,
|
|
425
|
-
{
|
|
426
|
-
style: { width: "1.5rem", height: "1.5rem", flexShrink: 0, color: "#dc2626" }
|
|
427
|
-
}
|
|
428
|
-
),
|
|
464
|
+
return /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", { className: "if-errorBanner-content", children: [
|
|
465
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "if-errorBanner-icon" }),
|
|
429
466
|
/* @__PURE__ */ jsx("span", { className: "if-errorBanner-text", children: error })
|
|
430
467
|
] }) });
|
|
431
468
|
}
|
|
432
|
-
function AuthFormField({
|
|
433
|
-
label,
|
|
434
|
-
id,
|
|
435
|
-
...props
|
|
436
|
-
}) {
|
|
469
|
+
function AuthFormField({ label, id, ...props }) {
|
|
437
470
|
return /* @__PURE__ */ jsxs("div", { className: "if-formField if-internal-f9n6p2", children: [
|
|
438
471
|
/* @__PURE__ */ jsx("label", { htmlFor: id, className: "if-formField-label if-internal-l3k8m1", children: label }),
|
|
439
472
|
/* @__PURE__ */ jsx("input", { id, className: "if-formField-input if-internal-i2v8k4", ...props })
|
|
@@ -560,14 +593,17 @@ function AuthSubmitButton({
|
|
|
560
593
|
children,
|
|
561
594
|
isLoading = false,
|
|
562
595
|
confirmed = false,
|
|
563
|
-
disabled = false
|
|
596
|
+
disabled = false,
|
|
597
|
+
type = "submit",
|
|
598
|
+
onClick
|
|
564
599
|
}) {
|
|
565
600
|
return /* @__PURE__ */ jsxs(
|
|
566
601
|
"button",
|
|
567
602
|
{
|
|
568
|
-
type
|
|
603
|
+
type,
|
|
569
604
|
className: "if-submitButton if-internal-b8p3m4",
|
|
570
605
|
disabled: disabled || isLoading || confirmed,
|
|
606
|
+
onClick,
|
|
571
607
|
children: [
|
|
572
608
|
isLoading && /* @__PURE__ */ jsx(Loader2, { className: "if-submitButton-icon if-submitButton-spinner", size: 20 }),
|
|
573
609
|
confirmed && /* @__PURE__ */ jsx(CircleCheck, { className: "if-submitButton-icon", size: 20 }),
|
|
@@ -576,24 +612,16 @@ function AuthSubmitButton({
|
|
|
576
612
|
}
|
|
577
613
|
);
|
|
578
614
|
}
|
|
579
|
-
function AuthLink({
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
href
|
|
583
|
-
}) {
|
|
584
|
-
const currentSearch = typeof window !== "undefined" ? window.location.search : "";
|
|
615
|
+
function AuthLink({ text, linkText, href }) {
|
|
616
|
+
const [searchParams] = useSearchParams();
|
|
617
|
+
const currentSearch = searchParams.toString();
|
|
585
618
|
const finalHref = (() => {
|
|
586
619
|
if (!currentSearch) {
|
|
587
620
|
return href;
|
|
588
621
|
}
|
|
589
622
|
try {
|
|
590
623
|
const url = new URL(href, window.location.origin);
|
|
591
|
-
|
|
592
|
-
currentParams.forEach((value, key) => {
|
|
593
|
-
if (!url.searchParams.has(key)) {
|
|
594
|
-
url.searchParams.set(key, value);
|
|
595
|
-
}
|
|
596
|
-
});
|
|
624
|
+
url.search = currentSearch;
|
|
597
625
|
return url.pathname + url.search;
|
|
598
626
|
} catch {
|
|
599
627
|
return href;
|
|
@@ -953,28 +981,26 @@ function AuthVerificationCodeInput({
|
|
|
953
981
|
}
|
|
954
982
|
function AuthEmailVerificationStep({
|
|
955
983
|
email,
|
|
956
|
-
description,
|
|
957
984
|
method = "code",
|
|
958
985
|
onVerifyCode
|
|
959
986
|
}) {
|
|
960
|
-
const {
|
|
961
|
-
const [insforge] = useState(() => createClient({ baseUrl }));
|
|
987
|
+
const { sendVerificationEmail } = useInsforge();
|
|
962
988
|
const [resendDisabled, setResendDisabled] = useState(true);
|
|
963
989
|
const [resendCountdown, setResendCountdown] = useState(60);
|
|
964
990
|
const [isSending, setIsSending] = useState(false);
|
|
965
991
|
const [verificationCode, setVerificationCode] = useState("");
|
|
966
992
|
const [isVerifying, setIsVerifying] = useState(false);
|
|
967
|
-
const [verificationError, setVerificationError] = useState("");
|
|
968
993
|
const defaultDescription = method === "code" ? "We've sent a 6-digit verification code to {email}. Please enter it below to verify your account. The code will expire in 10 minutes." : "We've sent a verification link to {email}. Please check your email and click the link to verify your account. The link will expire in 10 minutes.";
|
|
969
994
|
useEffect(() => {
|
|
970
995
|
const sendInitialEmail = async () => {
|
|
971
996
|
try {
|
|
972
|
-
await
|
|
973
|
-
} catch {
|
|
997
|
+
await sendVerificationEmail(email);
|
|
998
|
+
} catch (error) {
|
|
999
|
+
console.error("Failed to send verification email:", error);
|
|
974
1000
|
}
|
|
975
1001
|
};
|
|
976
1002
|
void sendInitialEmail();
|
|
977
|
-
}, [email,
|
|
1003
|
+
}, [email, sendVerificationEmail]);
|
|
978
1004
|
useEffect(() => {
|
|
979
1005
|
if (resendCountdown > 0) {
|
|
980
1006
|
const timer = setInterval(() => {
|
|
@@ -993,9 +1019,8 @@ function AuthEmailVerificationStep({
|
|
|
993
1019
|
setResendDisabled(true);
|
|
994
1020
|
setResendCountdown(60);
|
|
995
1021
|
setIsSending(true);
|
|
996
|
-
setVerificationError("");
|
|
997
1022
|
try {
|
|
998
|
-
await
|
|
1023
|
+
await sendVerificationEmail(email);
|
|
999
1024
|
} catch {
|
|
1000
1025
|
setResendDisabled(false);
|
|
1001
1026
|
setResendCountdown(0);
|
|
@@ -1003,123 +1028,157 @@ function AuthEmailVerificationStep({
|
|
|
1003
1028
|
setIsSending(false);
|
|
1004
1029
|
}
|
|
1005
1030
|
};
|
|
1006
|
-
const
|
|
1007
|
-
if (!onVerifyCode) {
|
|
1031
|
+
const handleSubmit = async () => {
|
|
1032
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1008
1033
|
return;
|
|
1009
1034
|
}
|
|
1010
1035
|
setIsVerifying(true);
|
|
1011
|
-
setVerificationError("");
|
|
1012
1036
|
try {
|
|
1013
|
-
await onVerifyCode(
|
|
1014
|
-
} catch (error) {
|
|
1015
|
-
setVerificationError(
|
|
1016
|
-
error instanceof Error ? error.message : "Invalid verification code. Please try again."
|
|
1017
|
-
);
|
|
1018
|
-
setVerificationCode("");
|
|
1037
|
+
await onVerifyCode(verificationCode);
|
|
1019
1038
|
} finally {
|
|
1020
1039
|
setIsVerifying(false);
|
|
1040
|
+
setVerificationCode("");
|
|
1021
1041
|
}
|
|
1022
1042
|
};
|
|
1023
|
-
const displayDescription =
|
|
1024
|
-
|
|
1025
|
-
|
|
1043
|
+
const displayDescription = defaultDescription;
|
|
1044
|
+
const isLinkMethod = method === "link";
|
|
1045
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
|
|
1046
|
+
/* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
|
|
1026
1047
|
part,
|
|
1027
1048
|
index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email })
|
|
1028
1049
|
] }, index)) }),
|
|
1029
|
-
|
|
1050
|
+
!isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1051
|
+
/* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
|
|
1052
|
+
AuthVerificationCodeInput,
|
|
1053
|
+
{
|
|
1054
|
+
value: verificationCode,
|
|
1055
|
+
onChange: setVerificationCode,
|
|
1056
|
+
email,
|
|
1057
|
+
disabled: isVerifying
|
|
1058
|
+
}
|
|
1059
|
+
) }),
|
|
1030
1060
|
/* @__PURE__ */ jsx(
|
|
1031
|
-
|
|
1061
|
+
AuthSubmitButton,
|
|
1032
1062
|
{
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
children: /* @__PURE__ */ jsx("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" })
|
|
1063
|
+
type: "button",
|
|
1064
|
+
isLoading: isVerifying,
|
|
1065
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1066
|
+
onClick: () => {
|
|
1067
|
+
void handleSubmit();
|
|
1068
|
+
},
|
|
1069
|
+
children: isVerifying ? "Verifying..." : "Verify Code"
|
|
1041
1070
|
}
|
|
1042
|
-
)
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
"
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1071
|
+
)
|
|
1072
|
+
] }),
|
|
1073
|
+
/* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1074
|
+
"Didn't receive the email?",
|
|
1075
|
+
" ",
|
|
1076
|
+
/* @__PURE__ */ jsx(
|
|
1077
|
+
"button",
|
|
1078
|
+
{
|
|
1079
|
+
onClick: () => {
|
|
1080
|
+
void handleResend();
|
|
1081
|
+
},
|
|
1082
|
+
disabled: resendDisabled || isSending,
|
|
1083
|
+
className: "if-verificationStep-resendButton",
|
|
1084
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1085
|
+
}
|
|
1086
|
+
)
|
|
1087
|
+
] })
|
|
1088
|
+
] });
|
|
1089
|
+
}
|
|
1090
|
+
function AuthResetPasswordVerificationStep({
|
|
1091
|
+
email,
|
|
1092
|
+
method,
|
|
1093
|
+
onVerifyCode,
|
|
1094
|
+
onResendEmail
|
|
1095
|
+
}) {
|
|
1096
|
+
const [resendDisabled, setResendDisabled] = useState(true);
|
|
1097
|
+
const [resendCountdown, setResendCountdown] = useState(60);
|
|
1098
|
+
const [isSending, setIsSending] = useState(false);
|
|
1099
|
+
const [verificationCode, setVerificationCode] = useState("");
|
|
1100
|
+
const [isVerifying, setIsVerifying] = useState(false);
|
|
1101
|
+
useEffect(() => {
|
|
1102
|
+
if (resendCountdown > 0) {
|
|
1103
|
+
const timer = setInterval(() => {
|
|
1104
|
+
setResendCountdown((prev) => {
|
|
1105
|
+
if (prev <= 1) {
|
|
1106
|
+
setResendDisabled(false);
|
|
1107
|
+
return 0;
|
|
1108
|
+
}
|
|
1109
|
+
return prev - 1;
|
|
1110
|
+
});
|
|
1111
|
+
}, 1e3);
|
|
1112
|
+
return () => clearInterval(timer);
|
|
1113
|
+
}
|
|
1114
|
+
}, [resendCountdown]);
|
|
1115
|
+
const handleResend = useCallback(async () => {
|
|
1116
|
+
setResendDisabled(true);
|
|
1117
|
+
setResendCountdown(60);
|
|
1118
|
+
setIsSending(true);
|
|
1119
|
+
try {
|
|
1120
|
+
await onResendEmail();
|
|
1121
|
+
} catch {
|
|
1122
|
+
setResendDisabled(false);
|
|
1123
|
+
setResendCountdown(0);
|
|
1124
|
+
} finally {
|
|
1125
|
+
setIsSending(false);
|
|
1126
|
+
}
|
|
1127
|
+
}, [onResendEmail]);
|
|
1128
|
+
const handleSubmit = async () => {
|
|
1129
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
setIsVerifying(true);
|
|
1133
|
+
try {
|
|
1134
|
+
await onVerifyCode(verificationCode);
|
|
1135
|
+
} finally {
|
|
1136
|
+
setIsVerifying(false);
|
|
1137
|
+
setVerificationCode("");
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
const isLinkMethod = method === "link";
|
|
1141
|
+
const description = isLinkMethod ? `We've sent a password reset link to ${email}. Please check your email and click the link to reset your password. The link will expire in 10 minutes.` : `We've sent a 6-digit verification code to ${email}. Please enter it below to reset your password. The code will expire in 10 minutes.`;
|
|
1142
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
|
|
1143
|
+
/* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: description }),
|
|
1144
|
+
!isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1145
|
+
/* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
|
|
1146
|
+
AuthVerificationCodeInput,
|
|
1147
|
+
{
|
|
1148
|
+
value: verificationCode,
|
|
1149
|
+
onChange: setVerificationCode,
|
|
1150
|
+
email,
|
|
1151
|
+
disabled: isVerifying
|
|
1152
|
+
}
|
|
1153
|
+
) }),
|
|
1154
|
+
/* @__PURE__ */ jsx(
|
|
1155
|
+
AuthSubmitButton,
|
|
1156
|
+
{
|
|
1157
|
+
type: "button",
|
|
1158
|
+
isLoading: isVerifying,
|
|
1159
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1160
|
+
onClick: () => {
|
|
1161
|
+
void handleSubmit();
|
|
1162
|
+
},
|
|
1163
|
+
children: isVerifying ? "Verifying..." : "Continue"
|
|
1164
|
+
}
|
|
1165
|
+
)
|
|
1166
|
+
] }),
|
|
1167
|
+
/* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1168
|
+
"Didn't receive the email?",
|
|
1169
|
+
" ",
|
|
1170
|
+
/* @__PURE__ */ jsx(
|
|
1171
|
+
"button",
|
|
1172
|
+
{
|
|
1173
|
+
onClick: () => {
|
|
1174
|
+
void handleResend();
|
|
1175
|
+
},
|
|
1176
|
+
disabled: resendDisabled || isSending,
|
|
1177
|
+
className: "if-verificationStep-resendButton",
|
|
1178
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1179
|
+
}
|
|
1180
|
+
)
|
|
1181
|
+
] })
|
|
1123
1182
|
] });
|
|
1124
1183
|
}
|
|
1125
1184
|
function SignInForm({
|
|
@@ -1149,8 +1208,7 @@ function SignInForm({
|
|
|
1149
1208
|
signUpUrl = "/sign-up",
|
|
1150
1209
|
dividerText = "or",
|
|
1151
1210
|
showVerificationStep = false,
|
|
1152
|
-
onVerifyCode
|
|
1153
|
-
verificationDescription
|
|
1211
|
+
onVerifyCode
|
|
1154
1212
|
}) {
|
|
1155
1213
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1156
1214
|
/* @__PURE__ */ jsx(
|
|
@@ -1161,14 +1219,7 @@ function SignInForm({
|
|
|
1161
1219
|
}
|
|
1162
1220
|
),
|
|
1163
1221
|
/* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
|
|
1164
|
-
showVerificationStep ? /* @__PURE__ */ jsx(
|
|
1165
|
-
AuthEmailVerificationStep,
|
|
1166
|
-
{
|
|
1167
|
-
email,
|
|
1168
|
-
description: verificationDescription,
|
|
1169
|
-
onVerifyCode
|
|
1170
|
-
}
|
|
1171
|
-
) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1222
|
+
showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1172
1223
|
/* @__PURE__ */ jsx(
|
|
1173
1224
|
AuthFormField,
|
|
1174
1225
|
{
|
|
@@ -1218,16 +1269,17 @@ function SignInForm({
|
|
|
1218
1269
|
] })
|
|
1219
1270
|
] });
|
|
1220
1271
|
}
|
|
1221
|
-
function SignIn({
|
|
1222
|
-
const { signIn,
|
|
1272
|
+
function SignIn({ onError, ...uiProps }) {
|
|
1273
|
+
const { signIn, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1223
1274
|
const { authConfig } = usePublicAuthConfig();
|
|
1224
1275
|
const [email, setEmail] = useState("");
|
|
1225
1276
|
const [password, setPassword] = useState("");
|
|
1226
1277
|
const [error, setError] = useState("");
|
|
1227
1278
|
const [loading, setLoading] = useState(false);
|
|
1228
1279
|
const [step, setStep] = useState("form");
|
|
1229
|
-
const [oauthLoading
|
|
1230
|
-
const [
|
|
1280
|
+
const [oauthLoading] = useState(null);
|
|
1281
|
+
const [searchParams] = useSearchParams();
|
|
1282
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1231
1283
|
async function handleSubmit(e) {
|
|
1232
1284
|
e.preventDefault();
|
|
1233
1285
|
setLoading(true);
|
|
@@ -1243,10 +1295,13 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1243
1295
|
throw new Error(result.error);
|
|
1244
1296
|
}
|
|
1245
1297
|
const { user, accessToken, redirectTo } = result;
|
|
1246
|
-
if (
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1298
|
+
if (user) {
|
|
1299
|
+
const finalUrl = new URL(redirectTo || redirectUrl || "", window.location.origin);
|
|
1300
|
+
finalUrl.searchParams.set("access_token", accessToken);
|
|
1301
|
+
finalUrl.searchParams.set("user_id", user.id);
|
|
1302
|
+
finalUrl.searchParams.set("email", user.email);
|
|
1303
|
+
finalUrl.searchParams.set("name", user.name);
|
|
1304
|
+
window.location.href = finalUrl.toString();
|
|
1250
1305
|
}
|
|
1251
1306
|
} catch (err) {
|
|
1252
1307
|
const errorMessage = err instanceof Error ? err.message : "Sign in failed";
|
|
@@ -1259,38 +1314,28 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1259
1314
|
}
|
|
1260
1315
|
}
|
|
1261
1316
|
async function handleVerifyCode(code) {
|
|
1317
|
+
setError("");
|
|
1262
1318
|
try {
|
|
1263
|
-
const result = await
|
|
1264
|
-
if (result
|
|
1319
|
+
const result = await verifyEmail(email, code);
|
|
1320
|
+
if (result?.error) {
|
|
1265
1321
|
throw new Error(result.error.message || "Verification failed");
|
|
1266
1322
|
}
|
|
1267
|
-
if (result
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1323
|
+
if (result?.user) {
|
|
1324
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1325
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1326
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1327
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1328
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1329
|
+
window.location.href = finalUrl.toString();
|
|
1271
1330
|
}
|
|
1272
1331
|
} catch (err) {
|
|
1273
1332
|
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1274
|
-
throw new Error(errorMessage);
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
async function handleOAuth(provider) {
|
|
1278
|
-
try {
|
|
1279
|
-
setOauthLoading(provider);
|
|
1280
|
-
setError("");
|
|
1281
|
-
await insforge.auth.signInWithOAuth({
|
|
1282
|
-
provider,
|
|
1283
|
-
redirectTo: afterSignInUrl
|
|
1284
|
-
});
|
|
1285
|
-
} catch (err) {
|
|
1286
|
-
const errorMessage = err instanceof Error ? err.message : `${provider} sign in failed`;
|
|
1287
1333
|
setError(errorMessage);
|
|
1288
|
-
if (onError) {
|
|
1289
|
-
onError(new Error(errorMessage));
|
|
1290
|
-
}
|
|
1291
|
-
setOauthLoading(null);
|
|
1292
1334
|
}
|
|
1293
1335
|
}
|
|
1336
|
+
function handleOAuth(provider) {
|
|
1337
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1338
|
+
}
|
|
1294
1339
|
if (!authConfig) {
|
|
1295
1340
|
return null;
|
|
1296
1341
|
}
|
|
@@ -1339,8 +1384,7 @@ function SignUpForm({
|
|
|
1339
1384
|
signInUrl = "/sign-in",
|
|
1340
1385
|
dividerText = "or",
|
|
1341
1386
|
showVerificationStep = false,
|
|
1342
|
-
onVerifyCode
|
|
1343
|
-
verificationDescription
|
|
1387
|
+
onVerifyCode
|
|
1344
1388
|
}) {
|
|
1345
1389
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1346
1390
|
/* @__PURE__ */ jsx(
|
|
@@ -1351,14 +1395,7 @@ function SignUpForm({
|
|
|
1351
1395
|
}
|
|
1352
1396
|
),
|
|
1353
1397
|
/* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
|
|
1354
|
-
showVerificationStep ? /* @__PURE__ */ jsx(
|
|
1355
|
-
AuthEmailVerificationStep,
|
|
1356
|
-
{
|
|
1357
|
-
email,
|
|
1358
|
-
description: verificationDescription,
|
|
1359
|
-
onVerifyCode
|
|
1360
|
-
}
|
|
1361
|
-
) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1398
|
+
showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1362
1399
|
/* @__PURE__ */ jsx(
|
|
1363
1400
|
AuthFormField,
|
|
1364
1401
|
{
|
|
@@ -1477,16 +1514,17 @@ function checkPasswordStrength(password) {
|
|
|
1477
1514
|
}
|
|
1478
1515
|
return { score, feedback };
|
|
1479
1516
|
}
|
|
1480
|
-
function SignUp({
|
|
1481
|
-
const { signUp,
|
|
1517
|
+
function SignUp({ onError, ...uiProps }) {
|
|
1518
|
+
const { signUp, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1482
1519
|
const { authConfig } = usePublicAuthConfig();
|
|
1483
1520
|
const [email, setEmail] = useState("");
|
|
1484
1521
|
const [password, setPassword] = useState("");
|
|
1485
1522
|
const [error, setError] = useState("");
|
|
1486
1523
|
const [loading, setLoading] = useState(false);
|
|
1487
1524
|
const [step, setStep] = useState("form");
|
|
1488
|
-
const [oauthLoading
|
|
1489
|
-
const [
|
|
1525
|
+
const [oauthLoading] = useState(null);
|
|
1526
|
+
const [searchParams] = useSearchParams();
|
|
1527
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1490
1528
|
async function handleSubmit(e) {
|
|
1491
1529
|
e.preventDefault();
|
|
1492
1530
|
setLoading(true);
|
|
@@ -1528,9 +1566,12 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1528
1566
|
return;
|
|
1529
1567
|
}
|
|
1530
1568
|
if (result.accessToken && result.user) {
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1569
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1570
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1571
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1572
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1573
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1574
|
+
window.location.href = finalUrl.toString();
|
|
1534
1575
|
}
|
|
1535
1576
|
} catch (err) {
|
|
1536
1577
|
const errorMessage = err instanceof Error ? err.message : "Sign up failed";
|
|
@@ -1543,38 +1584,28 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1543
1584
|
}
|
|
1544
1585
|
}
|
|
1545
1586
|
async function handleVerifyCode(code) {
|
|
1587
|
+
setError("");
|
|
1546
1588
|
try {
|
|
1547
|
-
const result = await
|
|
1548
|
-
if (result
|
|
1589
|
+
const result = await verifyEmail(email, code);
|
|
1590
|
+
if (result?.error) {
|
|
1549
1591
|
throw new Error(result.error.message || "Verification failed");
|
|
1550
1592
|
}
|
|
1551
|
-
if (result
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1593
|
+
if (result?.user) {
|
|
1594
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1595
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1596
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1597
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1598
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1599
|
+
window.location.href = finalUrl.toString();
|
|
1555
1600
|
}
|
|
1556
1601
|
} catch (err) {
|
|
1557
1602
|
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1558
|
-
throw new Error(errorMessage);
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
async function handleOAuth(provider) {
|
|
1562
|
-
try {
|
|
1563
|
-
setOauthLoading(provider);
|
|
1564
|
-
setError("");
|
|
1565
|
-
await insforge.auth.signInWithOAuth({
|
|
1566
|
-
provider,
|
|
1567
|
-
redirectTo: afterSignUpUrl
|
|
1568
|
-
});
|
|
1569
|
-
} catch (err) {
|
|
1570
|
-
const errorMessage = err instanceof Error ? err.message : `${provider} sign up failed`;
|
|
1571
1603
|
setError(errorMessage);
|
|
1572
|
-
if (onError) {
|
|
1573
|
-
onError(new Error(errorMessage));
|
|
1574
|
-
}
|
|
1575
|
-
setOauthLoading(null);
|
|
1576
1604
|
}
|
|
1577
1605
|
}
|
|
1606
|
+
function handleOAuth(provider) {
|
|
1607
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1608
|
+
}
|
|
1578
1609
|
if (!authConfig) {
|
|
1579
1610
|
return null;
|
|
1580
1611
|
}
|
|
@@ -1604,7 +1635,6 @@ function ForgotPasswordForm({
|
|
|
1604
1635
|
onSubmit,
|
|
1605
1636
|
error,
|
|
1606
1637
|
loading = false,
|
|
1607
|
-
success = false,
|
|
1608
1638
|
title = "Forgot Password?",
|
|
1609
1639
|
subtitle = "Enter your email address and we'll send you a code to reset your password.",
|
|
1610
1640
|
emailLabel = "Email",
|
|
@@ -1613,53 +1643,30 @@ function ForgotPasswordForm({
|
|
|
1613
1643
|
loadingButtonText = "Sending...",
|
|
1614
1644
|
backToSignInText = "Remember your password?",
|
|
1615
1645
|
backToSignInUrl = "/sign-in",
|
|
1616
|
-
|
|
1617
|
-
|
|
1646
|
+
showVerificationStep = false,
|
|
1647
|
+
resetPasswordMethod = "code",
|
|
1648
|
+
onVerifyCode,
|
|
1649
|
+
onResendEmail
|
|
1618
1650
|
}) {
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1651
|
+
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1652
|
+
/* @__PURE__ */ jsx(
|
|
1653
|
+
AuthHeader,
|
|
1622
1654
|
{
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
/* @__PURE__ */ jsx(
|
|
1626
|
-
"div",
|
|
1627
|
-
{
|
|
1628
|
-
style: {
|
|
1629
|
-
width: "4rem",
|
|
1630
|
-
height: "4rem",
|
|
1631
|
-
borderRadius: "50%",
|
|
1632
|
-
backgroundColor: "#D1FAE5",
|
|
1633
|
-
display: "flex",
|
|
1634
|
-
alignItems: "center",
|
|
1635
|
-
justifyContent: "center"
|
|
1636
|
-
},
|
|
1637
|
-
children: /* @__PURE__ */ jsx(
|
|
1638
|
-
"svg",
|
|
1639
|
-
{
|
|
1640
|
-
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
1641
|
-
fill: "none",
|
|
1642
|
-
strokeLinecap: "round",
|
|
1643
|
-
strokeLinejoin: "round",
|
|
1644
|
-
strokeWidth: "2",
|
|
1645
|
-
viewBox: "0 0 24 24",
|
|
1646
|
-
stroke: "currentColor",
|
|
1647
|
-
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
1648
|
-
}
|
|
1649
|
-
)
|
|
1650
|
-
}
|
|
1651
|
-
),
|
|
1652
|
-
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
1653
|
-
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage || `We've sent a password reset link to ${email}. Please check your email and follow the instructions.` }),
|
|
1654
|
-
/* @__PURE__ */ jsx("a", { href: backToSignInUrl, className: "if-authLink-link", style: { marginTop: "1rem" }, children: "Back to Sign In" })
|
|
1655
|
-
]
|
|
1655
|
+
title: showVerificationStep ? resetPasswordMethod === "link" ? "Check Your Email" : "Enter Reset Code" : title,
|
|
1656
|
+
subtitle: showVerificationStep ? "" : subtitle
|
|
1656
1657
|
}
|
|
1657
|
-
)
|
|
1658
|
-
}
|
|
1659
|
-
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1660
|
-
/* @__PURE__ */ jsx(AuthHeader, { title, subtitle }),
|
|
1658
|
+
),
|
|
1661
1659
|
/* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
|
|
1662
|
-
/* @__PURE__ */
|
|
1660
|
+
showVerificationStep ? /* @__PURE__ */ jsx(
|
|
1661
|
+
AuthResetPasswordVerificationStep,
|
|
1662
|
+
{
|
|
1663
|
+
email,
|
|
1664
|
+
method: resetPasswordMethod,
|
|
1665
|
+
onVerifyCode,
|
|
1666
|
+
onResendEmail: onResendEmail || (async () => {
|
|
1667
|
+
})
|
|
1668
|
+
}
|
|
1669
|
+
) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1663
1670
|
/* @__PURE__ */ jsx(
|
|
1664
1671
|
AuthFormField,
|
|
1665
1672
|
{
|
|
@@ -1675,7 +1682,7 @@ function ForgotPasswordForm({
|
|
|
1675
1682
|
),
|
|
1676
1683
|
/* @__PURE__ */ jsx(AuthSubmitButton, { isLoading: loading, disabled: loading, children: loading ? loadingButtonText : submitButtonText })
|
|
1677
1684
|
] }),
|
|
1678
|
-
/* @__PURE__ */ jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1685
|
+
!showVerificationStep && /* @__PURE__ */ jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1679
1686
|
] });
|
|
1680
1687
|
}
|
|
1681
1688
|
function ResetPasswordForm({
|
|
@@ -1696,11 +1703,12 @@ function ResetPasswordForm({
|
|
|
1696
1703
|
confirmPasswordPlaceholder = "\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
1697
1704
|
submitButtonText = "Reset Password",
|
|
1698
1705
|
loadingButtonText = "Resetting...",
|
|
1699
|
-
|
|
1700
|
-
backToSignInUrl = "/sign-in",
|
|
1701
|
-
successTitle = "Password Reset Successful!",
|
|
1702
|
-
successMessage = "Your password has been successfully reset. You can now sign in with your new password."
|
|
1706
|
+
successTitle = "Password Reset Successful!"
|
|
1703
1707
|
}) {
|
|
1708
|
+
let successMessage = "Your password has been successfully reset. You can close this page and sign in with your new password.";
|
|
1709
|
+
if (authConfig && authConfig.verifyEmailMethod === "code") {
|
|
1710
|
+
successMessage = "Your password has been successfully reset. You can wait for redirect to sign in with your new password.";
|
|
1711
|
+
}
|
|
1704
1712
|
if (success) {
|
|
1705
1713
|
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs(
|
|
1706
1714
|
"div",
|
|
@@ -1735,8 +1743,7 @@ function ResetPasswordForm({
|
|
|
1735
1743
|
}
|
|
1736
1744
|
),
|
|
1737
1745
|
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
1738
|
-
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
1739
|
-
/* @__PURE__ */ jsx("a", { href: backToSignInUrl, className: "if-authLink-link", style: { marginTop: "1rem" }, children: "Back to Sign In" })
|
|
1746
|
+
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
1740
1747
|
]
|
|
1741
1748
|
}
|
|
1742
1749
|
) });
|
|
@@ -1773,40 +1780,87 @@ function ResetPasswordForm({
|
|
|
1773
1780
|
}
|
|
1774
1781
|
),
|
|
1775
1782
|
/* @__PURE__ */ jsx(AuthSubmitButton, { isLoading: loading, disabled: loading, children: loading ? loadingButtonText : submitButtonText })
|
|
1776
|
-
] })
|
|
1777
|
-
/* @__PURE__ */ jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1783
|
+
] })
|
|
1778
1784
|
] });
|
|
1779
1785
|
}
|
|
1780
|
-
function
|
|
1781
|
-
|
|
1782
|
-
backToSignInUrl = "/sign-in",
|
|
1783
|
-
onSuccess,
|
|
1784
|
-
onError,
|
|
1785
|
-
...uiProps
|
|
1786
|
-
}) {
|
|
1787
|
-
const { resetPassword } = useInsforge();
|
|
1786
|
+
function ForgotPassword({ onError, ...uiProps }) {
|
|
1787
|
+
const { sendResetPasswordEmail, exchangeResetPasswordToken, resetPassword } = useInsforge();
|
|
1788
1788
|
const { authConfig } = usePublicAuthConfig();
|
|
1789
|
-
const [
|
|
1789
|
+
const [searchParams] = useSearchParams();
|
|
1790
|
+
const [step, setStep] = useState("email");
|
|
1791
|
+
const [email, setEmail] = useState("");
|
|
1792
|
+
const [resetToken, setResetToken] = useState("");
|
|
1793
|
+
const [newPassword, setNewPassword] = useState("");
|
|
1790
1794
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
1791
1795
|
const [error, setError] = useState("");
|
|
1792
1796
|
const [loading, setLoading] = useState(false);
|
|
1793
1797
|
const [success, setSuccess] = useState(false);
|
|
1794
|
-
|
|
1798
|
+
const [showVerificationStep, setShowVerificationStep] = useState(false);
|
|
1799
|
+
async function handleEmailSubmit(e) {
|
|
1795
1800
|
e.preventDefault();
|
|
1796
1801
|
setLoading(true);
|
|
1797
1802
|
setError("");
|
|
1798
|
-
|
|
1799
|
-
|
|
1803
|
+
const emailValidation = emailSchema.safeParse(email);
|
|
1804
|
+
if (!emailValidation.success) {
|
|
1805
|
+
const firstError = emailValidation.error.issues[0];
|
|
1806
|
+
setError(firstError.message);
|
|
1800
1807
|
setLoading(false);
|
|
1801
1808
|
return;
|
|
1802
1809
|
}
|
|
1810
|
+
try {
|
|
1811
|
+
const result = await sendResetPasswordEmail(emailValidation.data);
|
|
1812
|
+
if (result?.success) {
|
|
1813
|
+
setShowVerificationStep(true);
|
|
1814
|
+
} else {
|
|
1815
|
+
const errorMessage = result?.message || "Failed to send reset email";
|
|
1816
|
+
setError(errorMessage);
|
|
1817
|
+
if (onError) {
|
|
1818
|
+
onError(new Error(errorMessage));
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
} catch (err) {
|
|
1822
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to send reset email";
|
|
1823
|
+
setError(errorMessage);
|
|
1824
|
+
if (onError) {
|
|
1825
|
+
onError(new Error(errorMessage));
|
|
1826
|
+
}
|
|
1827
|
+
} finally {
|
|
1828
|
+
setLoading(false);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
async function handleVerifyCode(code) {
|
|
1832
|
+
setError("");
|
|
1833
|
+
try {
|
|
1834
|
+
const result = await exchangeResetPasswordToken(email, code);
|
|
1835
|
+
if ("error" in result) {
|
|
1836
|
+
throw new Error(result.error.message || "Failed to verify code");
|
|
1837
|
+
}
|
|
1838
|
+
if (result.token) {
|
|
1839
|
+
setResetToken(result.token);
|
|
1840
|
+
setStep("password");
|
|
1841
|
+
}
|
|
1842
|
+
} catch (err) {
|
|
1843
|
+
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1844
|
+
setError(errorMessage);
|
|
1845
|
+
if (onError) {
|
|
1846
|
+
onError(new Error(errorMessage));
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
async function handleResendEmail() {
|
|
1851
|
+
await sendResetPasswordEmail(email);
|
|
1852
|
+
}
|
|
1853
|
+
async function handleResetPasswordSubmit(e) {
|
|
1854
|
+
e.preventDefault();
|
|
1855
|
+
setLoading(true);
|
|
1856
|
+
setError("");
|
|
1803
1857
|
if (newPassword !== confirmPassword) {
|
|
1804
1858
|
setError("Passwords do not match");
|
|
1805
1859
|
setLoading(false);
|
|
1806
1860
|
return;
|
|
1807
1861
|
}
|
|
1808
|
-
if (!
|
|
1809
|
-
setError("
|
|
1862
|
+
if (!authConfig) {
|
|
1863
|
+
setError("Configuration not loaded");
|
|
1810
1864
|
setLoading(false);
|
|
1811
1865
|
return;
|
|
1812
1866
|
}
|
|
@@ -1825,12 +1879,16 @@ function ResetPassword({
|
|
|
1825
1879
|
return;
|
|
1826
1880
|
}
|
|
1827
1881
|
try {
|
|
1828
|
-
const result = await resetPassword(
|
|
1882
|
+
const result = await resetPassword(resetToken, newPassword);
|
|
1829
1883
|
if (result?.message) {
|
|
1830
1884
|
setSuccess(true);
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1885
|
+
const signInUrl = new URL("/sign-in", window.location.origin);
|
|
1886
|
+
searchParams.forEach((value, key) => {
|
|
1887
|
+
signInUrl.searchParams.set(key, value);
|
|
1888
|
+
});
|
|
1889
|
+
setTimeout(() => {
|
|
1890
|
+
window.location.href = signInUrl.toString();
|
|
1891
|
+
}, 2e3);
|
|
1834
1892
|
} else {
|
|
1835
1893
|
const errorMessage = "Failed to reset password";
|
|
1836
1894
|
setError(errorMessage);
|
|
@@ -1851,6 +1909,25 @@ function ResetPassword({
|
|
|
1851
1909
|
if (!authConfig) {
|
|
1852
1910
|
return null;
|
|
1853
1911
|
}
|
|
1912
|
+
if (step === "email") {
|
|
1913
|
+
return /* @__PURE__ */ jsx(
|
|
1914
|
+
ForgotPasswordForm,
|
|
1915
|
+
{
|
|
1916
|
+
email,
|
|
1917
|
+
onEmailChange: setEmail,
|
|
1918
|
+
onSubmit: (e) => {
|
|
1919
|
+
void handleEmailSubmit(e);
|
|
1920
|
+
},
|
|
1921
|
+
error,
|
|
1922
|
+
loading,
|
|
1923
|
+
showVerificationStep,
|
|
1924
|
+
resetPasswordMethod: authConfig.resetPasswordMethod,
|
|
1925
|
+
onVerifyCode: handleVerifyCode,
|
|
1926
|
+
onResendEmail: handleResendEmail,
|
|
1927
|
+
...uiProps
|
|
1928
|
+
}
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1854
1931
|
return /* @__PURE__ */ jsx(
|
|
1855
1932
|
ResetPasswordForm,
|
|
1856
1933
|
{
|
|
@@ -1858,83 +1935,71 @@ function ResetPassword({
|
|
|
1858
1935
|
confirmPassword,
|
|
1859
1936
|
onNewPasswordChange: setNewPassword,
|
|
1860
1937
|
onConfirmPasswordChange: setConfirmPassword,
|
|
1861
|
-
onSubmit:
|
|
1938
|
+
onSubmit: handleResetPasswordSubmit,
|
|
1862
1939
|
error,
|
|
1863
1940
|
loading,
|
|
1864
1941
|
success,
|
|
1865
1942
|
authConfig,
|
|
1866
|
-
backToSignInUrl,
|
|
1867
1943
|
...uiProps
|
|
1868
1944
|
}
|
|
1869
1945
|
);
|
|
1870
1946
|
}
|
|
1871
|
-
function
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
...uiProps
|
|
1876
|
-
}) {
|
|
1877
|
-
const { sendResetPasswordEmail, baseUrl } = useInsforge();
|
|
1947
|
+
function ResetPassword({ onError, ...uiProps }) {
|
|
1948
|
+
const [searchParams] = useSearchParams();
|
|
1949
|
+
const token = searchParams.get("token");
|
|
1950
|
+
const { resetPassword } = useInsforge();
|
|
1878
1951
|
const { authConfig } = usePublicAuthConfig();
|
|
1879
|
-
const [
|
|
1880
|
-
const [
|
|
1881
|
-
const [email, setEmail] = useState("");
|
|
1882
|
-
const [verificationCode, setVerificationCode] = useState("");
|
|
1883
|
-
const [resetToken, setResetToken] = useState("");
|
|
1952
|
+
const [newPassword, setNewPassword] = useState("");
|
|
1953
|
+
const [confirmPassword, setConfirmPassword] = useState("");
|
|
1884
1954
|
const [error, setError] = useState("");
|
|
1885
1955
|
const [loading, setLoading] = useState(false);
|
|
1886
1956
|
const [success, setSuccess] = useState(false);
|
|
1887
|
-
|
|
1888
|
-
const [resendCountdown, setResendCountdown] = useState(60);
|
|
1889
|
-
const [isSendingCode, setIsSendingCode] = useState(false);
|
|
1890
|
-
const [isVerifyingCode, setIsVerifyingCode] = useState(false);
|
|
1891
|
-
useEffect(() => {
|
|
1892
|
-
if (resendCountdown > 0 && step === "code") {
|
|
1893
|
-
const timer = setInterval(() => {
|
|
1894
|
-
setResendCountdown((prev) => {
|
|
1895
|
-
if (prev <= 1) {
|
|
1896
|
-
setResendDisabled(false);
|
|
1897
|
-
return 0;
|
|
1898
|
-
}
|
|
1899
|
-
return prev - 1;
|
|
1900
|
-
});
|
|
1901
|
-
}, 1e3);
|
|
1902
|
-
return () => clearInterval(timer);
|
|
1903
|
-
}
|
|
1904
|
-
}, [resendCountdown, step]);
|
|
1905
|
-
async function handleEmailSubmit(e) {
|
|
1957
|
+
async function handleSubmit(e) {
|
|
1906
1958
|
e.preventDefault();
|
|
1907
1959
|
setLoading(true);
|
|
1908
1960
|
setError("");
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1961
|
+
if (!authConfig) {
|
|
1962
|
+
setError("Configuration not loaded. Please refresh the page.");
|
|
1963
|
+
setLoading(false);
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
if (newPassword !== confirmPassword) {
|
|
1967
|
+
setError("Passwords do not match");
|
|
1968
|
+
setLoading(false);
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
if (!token) {
|
|
1972
|
+
setError("Reset token is missing");
|
|
1973
|
+
setLoading(false);
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
const passwordZodSchema = createPasswordSchema({
|
|
1977
|
+
minLength: authConfig.passwordMinLength,
|
|
1978
|
+
requireUppercase: authConfig.requireUppercase,
|
|
1979
|
+
requireLowercase: authConfig.requireLowercase,
|
|
1980
|
+
requireNumber: authConfig.requireNumber,
|
|
1981
|
+
requireSpecialChar: authConfig.requireSpecialChar
|
|
1982
|
+
});
|
|
1983
|
+
const passwordValidation = passwordZodSchema.safeParse(newPassword);
|
|
1984
|
+
if (!passwordValidation.success) {
|
|
1985
|
+
const firstError = passwordValidation.error.issues[0];
|
|
1912
1986
|
setError(firstError.message);
|
|
1913
1987
|
setLoading(false);
|
|
1914
1988
|
return;
|
|
1915
1989
|
}
|
|
1916
1990
|
try {
|
|
1917
|
-
const result = await
|
|
1918
|
-
if (result?.
|
|
1919
|
-
|
|
1920
|
-
setSuccess(true);
|
|
1921
|
-
if (onSuccess) {
|
|
1922
|
-
onSuccess();
|
|
1923
|
-
}
|
|
1924
|
-
} else {
|
|
1925
|
-
setStep("code");
|
|
1926
|
-
setResendDisabled(true);
|
|
1927
|
-
setResendCountdown(60);
|
|
1928
|
-
}
|
|
1991
|
+
const result = await resetPassword(token, newPassword);
|
|
1992
|
+
if (result?.message) {
|
|
1993
|
+
setSuccess(true);
|
|
1929
1994
|
} else {
|
|
1930
|
-
const errorMessage =
|
|
1995
|
+
const errorMessage = "Failed to reset password";
|
|
1931
1996
|
setError(errorMessage);
|
|
1932
1997
|
if (onError) {
|
|
1933
1998
|
onError(new Error(errorMessage));
|
|
1934
1999
|
}
|
|
1935
2000
|
}
|
|
1936
2001
|
} catch (err) {
|
|
1937
|
-
const errorMessage = err instanceof Error ? err.message : "Failed to
|
|
2002
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to reset password";
|
|
1938
2003
|
setError(errorMessage);
|
|
1939
2004
|
if (onError) {
|
|
1940
2005
|
onError(new Error(errorMessage));
|
|
@@ -1943,297 +2008,157 @@ function ForgotPassword({
|
|
|
1943
2008
|
setLoading(false);
|
|
1944
2009
|
}
|
|
1945
2010
|
}
|
|
1946
|
-
async function handleVerifyCode(code) {
|
|
1947
|
-
setIsVerifyingCode(true);
|
|
1948
|
-
setError("");
|
|
1949
|
-
setVerificationCode(code);
|
|
1950
|
-
try {
|
|
1951
|
-
const result = await insforge.auth.exchangeResetPasswordToken({ email, code });
|
|
1952
|
-
if (result.error) {
|
|
1953
|
-
throw new Error(result.error.message || "Failed to verify code");
|
|
1954
|
-
}
|
|
1955
|
-
if (result.data) {
|
|
1956
|
-
setResetToken(result.data.token);
|
|
1957
|
-
setStep("password");
|
|
1958
|
-
}
|
|
1959
|
-
} catch (err) {
|
|
1960
|
-
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1961
|
-
setError(errorMessage);
|
|
1962
|
-
setVerificationCode("");
|
|
1963
|
-
} finally {
|
|
1964
|
-
setIsVerifyingCode(false);
|
|
1965
|
-
}
|
|
1966
|
-
}
|
|
1967
|
-
const handleResendCode = useCallback(async () => {
|
|
1968
|
-
setResendDisabled(true);
|
|
1969
|
-
setResendCountdown(60);
|
|
1970
|
-
setIsSendingCode(true);
|
|
1971
|
-
setError("");
|
|
1972
|
-
try {
|
|
1973
|
-
await sendResetPasswordEmail(email);
|
|
1974
|
-
} catch (err) {
|
|
1975
|
-
const errorMessage = err instanceof Error ? err.message : "Failed to resend code";
|
|
1976
|
-
setError(errorMessage);
|
|
1977
|
-
setResendDisabled(false);
|
|
1978
|
-
setResendCountdown(0);
|
|
1979
|
-
} finally {
|
|
1980
|
-
setIsSendingCode(false);
|
|
1981
|
-
}
|
|
1982
|
-
}, [email, sendResetPasswordEmail]);
|
|
1983
|
-
function handlePasswordResetSuccess(redirectTo) {
|
|
1984
|
-
const targetUrl = redirectTo || backToSignInUrl;
|
|
1985
|
-
if (onSuccess) {
|
|
1986
|
-
onSuccess();
|
|
1987
|
-
}
|
|
1988
|
-
setTimeout(() => {
|
|
1989
|
-
window.location.href = targetUrl;
|
|
1990
|
-
}, 1500);
|
|
1991
|
-
}
|
|
1992
2011
|
if (!authConfig) {
|
|
1993
2012
|
return null;
|
|
1994
2013
|
}
|
|
1995
|
-
if (
|
|
1996
|
-
return /* @__PURE__ */ jsx(
|
|
1997
|
-
ForgotPasswordForm,
|
|
1998
|
-
{
|
|
1999
|
-
email,
|
|
2000
|
-
onEmailChange: setEmail,
|
|
2001
|
-
onSubmit: (e) => {
|
|
2002
|
-
void handleEmailSubmit(e);
|
|
2003
|
-
},
|
|
2004
|
-
error,
|
|
2005
|
-
loading,
|
|
2006
|
-
success,
|
|
2007
|
-
backToSignInUrl,
|
|
2008
|
-
...uiProps
|
|
2009
|
-
}
|
|
2010
|
-
);
|
|
2011
|
-
}
|
|
2012
|
-
if (step === "code") {
|
|
2014
|
+
if (!token) {
|
|
2013
2015
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
2016
|
+
/* @__PURE__ */ jsx(AuthHeader, { title: "Invalid Reset Link", subtitle: "" }),
|
|
2014
2017
|
/* @__PURE__ */ jsx(
|
|
2015
|
-
AuthHeader,
|
|
2016
|
-
{
|
|
2017
|
-
title: "Enter Reset Code",
|
|
2018
|
-
subtitle: `We've sent a 6-digit verification code to ${email}. Please enter it below to reset your password. The code will expire in 10 minutes.`
|
|
2019
|
-
}
|
|
2020
|
-
),
|
|
2021
|
-
/* @__PURE__ */ jsx(AuthErrorBanner, { error }),
|
|
2022
|
-
/* @__PURE__ */ jsxs(
|
|
2023
2018
|
"div",
|
|
2024
2019
|
{
|
|
2025
2020
|
style: {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
alignItems: "center"
|
|
2021
|
+
padding: "1.5rem",
|
|
2022
|
+
backgroundColor: "#FEE2E2",
|
|
2023
|
+
borderRadius: "0.5rem",
|
|
2024
|
+
border: "1px solid #DC2626"
|
|
2031
2025
|
},
|
|
2032
|
-
children:
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
{
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
},
|
|
2045
|
-
children: /* @__PURE__ */ jsxs(
|
|
2046
|
-
"div",
|
|
2047
|
-
{
|
|
2048
|
-
style: {
|
|
2049
|
-
display: "flex",
|
|
2050
|
-
flexDirection: "column",
|
|
2051
|
-
gap: "0.75rem",
|
|
2052
|
-
marginTop: "0.5rem"
|
|
2053
|
-
},
|
|
2054
|
-
children: [
|
|
2055
|
-
/* @__PURE__ */ jsx(
|
|
2056
|
-
AuthVerificationCodeInput,
|
|
2057
|
-
{
|
|
2058
|
-
value: verificationCode,
|
|
2059
|
-
onChange: setVerificationCode,
|
|
2060
|
-
email,
|
|
2061
|
-
disabled: isVerifyingCode,
|
|
2062
|
-
onComplete: (code) => {
|
|
2063
|
-
void handleVerifyCode(code);
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
),
|
|
2067
|
-
isVerifyingCode && /* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: "Verifying..." })
|
|
2068
|
-
]
|
|
2069
|
-
}
|
|
2070
|
-
)
|
|
2071
|
-
}
|
|
2072
|
-
),
|
|
2073
|
-
/* @__PURE__ */ jsxs(
|
|
2074
|
-
"div",
|
|
2075
|
-
{
|
|
2076
|
-
style: {
|
|
2077
|
-
width: "100%",
|
|
2078
|
-
fontSize: "0.875rem",
|
|
2079
|
-
textAlign: "center",
|
|
2080
|
-
color: "#828282",
|
|
2081
|
-
fontFamily: "var(--if-font-family)"
|
|
2082
|
-
},
|
|
2083
|
-
children: [
|
|
2084
|
-
"Didn't receive the email?",
|
|
2085
|
-
" ",
|
|
2086
|
-
/* @__PURE__ */ jsx(
|
|
2087
|
-
"button",
|
|
2088
|
-
{
|
|
2089
|
-
onClick: () => {
|
|
2090
|
-
void handleResendCode();
|
|
2091
|
-
},
|
|
2092
|
-
disabled: resendDisabled || isSendingCode,
|
|
2093
|
-
style: {
|
|
2094
|
-
color: "#000",
|
|
2095
|
-
fontWeight: 500,
|
|
2096
|
-
transition: "all 0.2s",
|
|
2097
|
-
cursor: resendDisabled || isSendingCode ? "not-allowed" : "pointer",
|
|
2098
|
-
background: "none",
|
|
2099
|
-
border: "none",
|
|
2100
|
-
padding: 0,
|
|
2101
|
-
textDecoration: resendDisabled || isSendingCode ? "none" : "underline",
|
|
2102
|
-
opacity: resendDisabled || isSendingCode ? 0.5 : 1,
|
|
2103
|
-
fontFamily: "var(--if-font-family)"
|
|
2104
|
-
},
|
|
2105
|
-
children: isSendingCode ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
2106
|
-
}
|
|
2107
|
-
)
|
|
2108
|
-
]
|
|
2109
|
-
}
|
|
2110
|
-
)
|
|
2111
|
-
]
|
|
2026
|
+
children: /* @__PURE__ */ jsx(
|
|
2027
|
+
"p",
|
|
2028
|
+
{
|
|
2029
|
+
style: {
|
|
2030
|
+
fontSize: "0.875rem",
|
|
2031
|
+
color: "#DC2626",
|
|
2032
|
+
margin: 0,
|
|
2033
|
+
fontFamily: "var(--if-font-family)"
|
|
2034
|
+
},
|
|
2035
|
+
children: "The password reset link is missing or invalid. Please request a new password reset link."
|
|
2036
|
+
}
|
|
2037
|
+
)
|
|
2112
2038
|
}
|
|
2113
|
-
)
|
|
2114
|
-
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: /* @__PURE__ */ jsx("a", { href: backToSignInUrl, className: "if-authLink-link", children: "Back to Sign In" }) })
|
|
2039
|
+
)
|
|
2115
2040
|
] });
|
|
2116
2041
|
}
|
|
2117
|
-
|
|
2118
|
-
ResetPassword,
|
|
2119
|
-
{
|
|
2120
|
-
token: resetToken,
|
|
2121
|
-
backToSignInUrl,
|
|
2122
|
-
onSuccess: handlePasswordResetSuccess,
|
|
2123
|
-
onError
|
|
2124
|
-
}
|
|
2125
|
-
);
|
|
2126
|
-
}
|
|
2127
|
-
function VerifyEmailStatus({
|
|
2128
|
-
status,
|
|
2129
|
-
error,
|
|
2130
|
-
verifyingTitle = "Verifying your email...",
|
|
2131
|
-
successTitle = "Email Verified!",
|
|
2132
|
-
successMessage = "Your email has been verified successfully. You can close this page and return to your app.",
|
|
2133
|
-
errorTitle = "Verification Failed"
|
|
2134
|
-
}) {
|
|
2135
|
-
if (status === "verifying") {
|
|
2042
|
+
if (success) {
|
|
2136
2043
|
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs(
|
|
2137
2044
|
"div",
|
|
2138
2045
|
{
|
|
2139
|
-
style: {
|
|
2140
|
-
width: "100%",
|
|
2141
|
-
display: "flex",
|
|
2142
|
-
flexDirection: "column",
|
|
2143
|
-
alignItems: "center",
|
|
2144
|
-
justifyContent: "center",
|
|
2145
|
-
gap: "1.5rem"
|
|
2146
|
-
},
|
|
2046
|
+
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "1rem" },
|
|
2147
2047
|
children: [
|
|
2148
|
-
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2149
2048
|
/* @__PURE__ */ jsx(
|
|
2150
2049
|
"div",
|
|
2151
2050
|
{
|
|
2152
|
-
className: "if-submitButton-spinner",
|
|
2153
2051
|
style: {
|
|
2052
|
+
width: "4rem",
|
|
2053
|
+
height: "4rem",
|
|
2154
2054
|
borderRadius: "50%",
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2055
|
+
backgroundColor: "#D1FAE5",
|
|
2056
|
+
display: "flex",
|
|
2057
|
+
alignItems: "center",
|
|
2058
|
+
justifyContent: "center"
|
|
2059
|
+
},
|
|
2060
|
+
children: /* @__PURE__ */ jsx(
|
|
2061
|
+
"svg",
|
|
2062
|
+
{
|
|
2063
|
+
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
2064
|
+
fill: "none",
|
|
2065
|
+
strokeLinecap: "round",
|
|
2066
|
+
strokeLinejoin: "round",
|
|
2067
|
+
strokeWidth: "2",
|
|
2068
|
+
viewBox: "0 0 24 24",
|
|
2069
|
+
stroke: "currentColor",
|
|
2070
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2071
|
+
}
|
|
2072
|
+
)
|
|
2073
|
+
}
|
|
2074
|
+
),
|
|
2075
|
+
/* @__PURE__ */ jsx(
|
|
2076
|
+
"h2",
|
|
2077
|
+
{
|
|
2078
|
+
style: {
|
|
2079
|
+
fontSize: "1.5rem",
|
|
2080
|
+
fontWeight: 600,
|
|
2081
|
+
color: "#000",
|
|
2082
|
+
margin: 0,
|
|
2083
|
+
textAlign: "center",
|
|
2084
|
+
fontFamily: "var(--if-font-family)"
|
|
2085
|
+
},
|
|
2086
|
+
children: "Password Reset Successfully"
|
|
2087
|
+
}
|
|
2088
|
+
),
|
|
2089
|
+
/* @__PURE__ */ jsx(
|
|
2090
|
+
"p",
|
|
2091
|
+
{
|
|
2092
|
+
style: {
|
|
2093
|
+
fontSize: "0.875rem",
|
|
2094
|
+
color: "#828282",
|
|
2095
|
+
textAlign: "center",
|
|
2096
|
+
margin: 0,
|
|
2097
|
+
fontFamily: "var(--if-font-family)"
|
|
2098
|
+
},
|
|
2099
|
+
children: "Your password has been reset successfully. You can now close this page and return to the login page in your original tab."
|
|
2159
2100
|
}
|
|
2160
2101
|
)
|
|
2161
2102
|
]
|
|
2162
2103
|
}
|
|
2163
2104
|
) });
|
|
2164
2105
|
}
|
|
2106
|
+
return /* @__PURE__ */ jsx(
|
|
2107
|
+
ResetPasswordForm,
|
|
2108
|
+
{
|
|
2109
|
+
newPassword,
|
|
2110
|
+
confirmPassword,
|
|
2111
|
+
onNewPasswordChange: setNewPassword,
|
|
2112
|
+
onConfirmPasswordChange: setConfirmPassword,
|
|
2113
|
+
onSubmit: handleSubmit,
|
|
2114
|
+
error,
|
|
2115
|
+
loading,
|
|
2116
|
+
success: false,
|
|
2117
|
+
authConfig,
|
|
2118
|
+
...uiProps
|
|
2119
|
+
}
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
function VerifyEmailStatus({
|
|
2123
|
+
status,
|
|
2124
|
+
error,
|
|
2125
|
+
verifyingTitle = "Verifying your email...",
|
|
2126
|
+
successTitle = "Email Verified!",
|
|
2127
|
+
successMessage = "Your email has been verified successfully. You can close this page and sign in to your app.",
|
|
2128
|
+
errorTitle = "Verification Failed"
|
|
2129
|
+
}) {
|
|
2130
|
+
if (status === "verifying") {
|
|
2131
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs("div", { className: "if-verifyStatus-container", children: [
|
|
2132
|
+
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2133
|
+
/* @__PURE__ */ jsx("div", { className: "if-submitButton-spinner if-verifyStatus-spinner" })
|
|
2134
|
+
] }) });
|
|
2135
|
+
}
|
|
2165
2136
|
if (status === "error") {
|
|
2166
|
-
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx(
|
|
2167
|
-
"
|
|
2137
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxs("div", { className: "if-authHeader if-internal-h3m7w5", children: [
|
|
2138
|
+
/* @__PURE__ */ jsx("h1", { className: "if-authHeader-title if-internal-t4p1k9", children: errorTitle }),
|
|
2139
|
+
/* @__PURE__ */ jsxs("p", { className: "if-authHeader-subtitle if-internal-s7q2m3", children: [
|
|
2140
|
+
error || "The verification link is invalid or has expired.",
|
|
2141
|
+
" Please try again or contact support if the problem persists. You can close this page and return to your app."
|
|
2142
|
+
] })
|
|
2143
|
+
] }) }) });
|
|
2144
|
+
}
|
|
2145
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxs("div", { className: "if-verifyStatus-successContent", children: [
|
|
2146
|
+
/* @__PURE__ */ jsx("div", { className: "if-verifyStatus-successIcon", children: /* @__PURE__ */ jsx(
|
|
2147
|
+
"svg",
|
|
2168
2148
|
{
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
}
|
|
2177
|
-
children: /* @__PURE__ */ jsxs("div", { className: "if-authHeader if-internal-h3m7w5", children: [
|
|
2178
|
-
/* @__PURE__ */ jsx("h1", { className: "if-authHeader-title if-internal-t4p1k9", children: errorTitle }),
|
|
2179
|
-
/* @__PURE__ */ jsxs("p", { className: "if-authHeader-subtitle if-internal-s7q2m3", style: { lineHeight: "1.5" }, children: [
|
|
2180
|
-
error || "The verification link is invalid or has expired.",
|
|
2181
|
-
" Please try again or contact support if the problem persists. You can close this page and return to your app."
|
|
2182
|
-
] })
|
|
2183
|
-
] })
|
|
2149
|
+
className: "if-verifyStatus-successIconSvg",
|
|
2150
|
+
fill: "none",
|
|
2151
|
+
strokeLinecap: "round",
|
|
2152
|
+
strokeLinejoin: "round",
|
|
2153
|
+
strokeWidth: "2",
|
|
2154
|
+
viewBox: "0 0 24 24",
|
|
2155
|
+
stroke: "currentColor",
|
|
2156
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2184
2157
|
}
|
|
2185
|
-
) })
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
{
|
|
2190
|
-
style: {
|
|
2191
|
-
width: "100%",
|
|
2192
|
-
display: "flex",
|
|
2193
|
-
flexDirection: "column",
|
|
2194
|
-
alignItems: "stretch",
|
|
2195
|
-
justifyContent: "center",
|
|
2196
|
-
gap: "1.5rem"
|
|
2197
|
-
},
|
|
2198
|
-
children: /* @__PURE__ */ jsxs(
|
|
2199
|
-
"div",
|
|
2200
|
-
{
|
|
2201
|
-
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "1rem" },
|
|
2202
|
-
children: [
|
|
2203
|
-
/* @__PURE__ */ jsx(
|
|
2204
|
-
"div",
|
|
2205
|
-
{
|
|
2206
|
-
style: {
|
|
2207
|
-
width: "4rem",
|
|
2208
|
-
height: "4rem",
|
|
2209
|
-
borderRadius: "50%",
|
|
2210
|
-
backgroundColor: "#D1FAE5",
|
|
2211
|
-
display: "flex",
|
|
2212
|
-
alignItems: "center",
|
|
2213
|
-
justifyContent: "center"
|
|
2214
|
-
},
|
|
2215
|
-
children: /* @__PURE__ */ jsx(
|
|
2216
|
-
"svg",
|
|
2217
|
-
{
|
|
2218
|
-
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
2219
|
-
fill: "none",
|
|
2220
|
-
strokeLinecap: "round",
|
|
2221
|
-
strokeLinejoin: "round",
|
|
2222
|
-
strokeWidth: "2",
|
|
2223
|
-
viewBox: "0 0 24 24",
|
|
2224
|
-
stroke: "currentColor",
|
|
2225
|
-
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2226
|
-
}
|
|
2227
|
-
)
|
|
2228
|
-
}
|
|
2229
|
-
),
|
|
2230
|
-
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
2231
|
-
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
2232
|
-
]
|
|
2233
|
-
}
|
|
2234
|
-
)
|
|
2235
|
-
}
|
|
2236
|
-
) });
|
|
2158
|
+
) }),
|
|
2159
|
+
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title if-verifyStatus-textCenter", children: successTitle }),
|
|
2160
|
+
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle if-verifyStatus-textCenter", children: successMessage })
|
|
2161
|
+
] }) }) });
|
|
2237
2162
|
}
|
|
2238
2163
|
function VerifyEmail({ token, onSuccess, onError, ...uiProps }) {
|
|
2239
2164
|
const { verifyEmail } = useInsforge();
|
|
@@ -2334,93 +2259,43 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
|
|
|
2334
2259
|
}
|
|
2335
2260
|
const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
|
|
2336
2261
|
const buttonClassName = mode === "detailed" ? "if-userButton if-userButton-detailed" : "if-userButton";
|
|
2337
|
-
return /* @__PURE__ */ jsxs(
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
{
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
"
|
|
2357
|
-
"
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
alignItems: "flex-start",
|
|
2375
|
-
gap: "0.125rem"
|
|
2376
|
-
},
|
|
2377
|
-
children: [
|
|
2378
|
-
user.name && /* @__PURE__ */ jsx(
|
|
2379
|
-
"div",
|
|
2380
|
-
{
|
|
2381
|
-
style: {
|
|
2382
|
-
fontSize: "0.875rem",
|
|
2383
|
-
fontWeight: 600,
|
|
2384
|
-
color: "#1f1f1f",
|
|
2385
|
-
lineHeight: "1.25rem",
|
|
2386
|
-
textAlign: "left"
|
|
2387
|
-
},
|
|
2388
|
-
children: user.name
|
|
2389
|
-
}
|
|
2390
|
-
),
|
|
2391
|
-
/* @__PURE__ */ jsx(
|
|
2392
|
-
"div",
|
|
2393
|
-
{
|
|
2394
|
-
style: {
|
|
2395
|
-
fontSize: "0.75rem",
|
|
2396
|
-
color: "#828282",
|
|
2397
|
-
lineHeight: "1rem",
|
|
2398
|
-
textAlign: "left"
|
|
2399
|
-
},
|
|
2400
|
-
children: user.email
|
|
2401
|
-
}
|
|
2402
|
-
)
|
|
2403
|
-
]
|
|
2404
|
-
}
|
|
2405
|
-
)
|
|
2406
|
-
]
|
|
2407
|
-
}
|
|
2408
|
-
),
|
|
2409
|
-
isOpen && /* @__PURE__ */ jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxs(
|
|
2410
|
-
"button",
|
|
2411
|
-
{
|
|
2412
|
-
onClick: handleSignOut,
|
|
2413
|
-
className: "if-userButton-menuItem",
|
|
2414
|
-
style: { color: "#DC2626" },
|
|
2415
|
-
children: [
|
|
2416
|
-
/* @__PURE__ */ jsx(LogOut, { style: { width: "1.25rem", height: "1.25rem" } }),
|
|
2417
|
-
"Sign out"
|
|
2418
|
-
]
|
|
2419
|
-
}
|
|
2420
|
-
) })
|
|
2421
|
-
]
|
|
2422
|
-
}
|
|
2423
|
-
);
|
|
2262
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-userButton-container if-internal-ub3k8p", ref: dropdownRef, children: [
|
|
2263
|
+
/* @__PURE__ */ jsxs(
|
|
2264
|
+
"button",
|
|
2265
|
+
{
|
|
2266
|
+
className: buttonClassName,
|
|
2267
|
+
onClick: () => setIsOpen(!isOpen),
|
|
2268
|
+
"aria-expanded": isOpen,
|
|
2269
|
+
"aria-haspopup": "true",
|
|
2270
|
+
children: [
|
|
2271
|
+
/* @__PURE__ */ jsx("div", { className: "if-userButton-avatar", children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
|
|
2272
|
+
"img",
|
|
2273
|
+
{
|
|
2274
|
+
src: user.avatarUrl,
|
|
2275
|
+
alt: user.email,
|
|
2276
|
+
onError: () => setImageError(true),
|
|
2277
|
+
className: "if-userButton-avatarImage"
|
|
2278
|
+
}
|
|
2279
|
+
) : /* @__PURE__ */ jsx("span", { className: "if-userButton-avatarInitials", children: initials }) }),
|
|
2280
|
+
mode === "detailed" && /* @__PURE__ */ jsxs("div", { className: "if-userButton-info", children: [
|
|
2281
|
+
user.name && /* @__PURE__ */ jsx("div", { className: "if-userButton-name", children: user.name }),
|
|
2282
|
+
/* @__PURE__ */ jsx("div", { className: "if-userButton-email", children: user.email })
|
|
2283
|
+
] })
|
|
2284
|
+
]
|
|
2285
|
+
}
|
|
2286
|
+
),
|
|
2287
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxs(
|
|
2288
|
+
"button",
|
|
2289
|
+
{
|
|
2290
|
+
onClick: handleSignOut,
|
|
2291
|
+
className: "if-userButton-menuItem if-userButton-menuItem-signout",
|
|
2292
|
+
children: [
|
|
2293
|
+
/* @__PURE__ */ jsx(LogOut, { className: "if-userButton-menuItem-icon" }),
|
|
2294
|
+
"Sign out"
|
|
2295
|
+
]
|
|
2296
|
+
}
|
|
2297
|
+
) })
|
|
2298
|
+
] });
|
|
2424
2299
|
}
|
|
2425
2300
|
function Protect({
|
|
2426
2301
|
children,
|
|
@@ -2478,94 +2353,6 @@ function SignedOut({ children }) {
|
|
|
2478
2353
|
}
|
|
2479
2354
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
2480
2355
|
}
|
|
2481
|
-
function InsforgeCallback({
|
|
2482
|
-
redirectTo = "/",
|
|
2483
|
-
onSuccess,
|
|
2484
|
-
onError,
|
|
2485
|
-
loadingComponent,
|
|
2486
|
-
onRedirect
|
|
2487
|
-
}) {
|
|
2488
|
-
const isProcessingRef = useRef(false);
|
|
2489
|
-
const { isLoaded, isSignedIn } = useInsforge();
|
|
2490
|
-
useEffect(() => {
|
|
2491
|
-
if (!isLoaded) {
|
|
2492
|
-
return;
|
|
2493
|
-
}
|
|
2494
|
-
if (isProcessingRef.current) {
|
|
2495
|
-
return;
|
|
2496
|
-
}
|
|
2497
|
-
isProcessingRef.current = true;
|
|
2498
|
-
const processCallback = () => {
|
|
2499
|
-
const searchParams = new URLSearchParams(window.location.search);
|
|
2500
|
-
const error = searchParams.get("error");
|
|
2501
|
-
if (error) {
|
|
2502
|
-
if (onError) {
|
|
2503
|
-
onError(error);
|
|
2504
|
-
} else {
|
|
2505
|
-
const errorUrl = "/?error=" + encodeURIComponent(error);
|
|
2506
|
-
if (onRedirect) {
|
|
2507
|
-
onRedirect(errorUrl);
|
|
2508
|
-
} else {
|
|
2509
|
-
window.location.href = errorUrl;
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2512
|
-
return;
|
|
2513
|
-
}
|
|
2514
|
-
if (!isSignedIn) {
|
|
2515
|
-
const errorMsg = "authentication_failed";
|
|
2516
|
-
if (onError) {
|
|
2517
|
-
onError(errorMsg);
|
|
2518
|
-
} else {
|
|
2519
|
-
const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
|
|
2520
|
-
if (onRedirect) {
|
|
2521
|
-
onRedirect(errorUrl);
|
|
2522
|
-
} else {
|
|
2523
|
-
window.location.href = errorUrl;
|
|
2524
|
-
}
|
|
2525
|
-
}
|
|
2526
|
-
return;
|
|
2527
|
-
}
|
|
2528
|
-
window.history.replaceState({}, "", window.location.pathname);
|
|
2529
|
-
if (onSuccess) {
|
|
2530
|
-
onSuccess();
|
|
2531
|
-
}
|
|
2532
|
-
if (onRedirect) {
|
|
2533
|
-
onRedirect(redirectTo);
|
|
2534
|
-
} else {
|
|
2535
|
-
window.location.href = redirectTo;
|
|
2536
|
-
}
|
|
2537
|
-
};
|
|
2538
|
-
processCallback();
|
|
2539
|
-
}, [isLoaded, isSignedIn, redirectTo, onSuccess, onError, onRedirect]);
|
|
2540
|
-
const defaultLoading = /* @__PURE__ */ jsx(
|
|
2541
|
-
"div",
|
|
2542
|
-
{
|
|
2543
|
-
style: {
|
|
2544
|
-
display: "flex",
|
|
2545
|
-
alignItems: "center",
|
|
2546
|
-
justifyContent: "center",
|
|
2547
|
-
minHeight: "100vh"
|
|
2548
|
-
},
|
|
2549
|
-
children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
|
|
2550
|
-
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", style: { marginBottom: "1rem" }, children: "Completing authentication..." }),
|
|
2551
|
-
/* @__PURE__ */ jsx(
|
|
2552
|
-
"div",
|
|
2553
|
-
{
|
|
2554
|
-
className: "if-submitButton-spinner",
|
|
2555
|
-
style: {
|
|
2556
|
-
borderRadius: "50%",
|
|
2557
|
-
height: "3rem",
|
|
2558
|
-
width: "3rem",
|
|
2559
|
-
borderBottom: "2px solid #2563EB",
|
|
2560
|
-
margin: "0 auto"
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
)
|
|
2564
|
-
] })
|
|
2565
|
-
}
|
|
2566
|
-
);
|
|
2567
|
-
return loadingComponent || defaultLoading;
|
|
2568
|
-
}
|
|
2569
2356
|
|
|
2570
2357
|
// src/hooks/useAuth.ts
|
|
2571
2358
|
function useAuth() {
|
|
@@ -2624,6 +2411,6 @@ function getInsforgeRoutes(config) {
|
|
|
2624
2411
|
return routes;
|
|
2625
2412
|
}
|
|
2626
2413
|
|
|
2627
|
-
export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm,
|
|
2414
|
+
export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm, InsforgeProvider, OAUTH_PROVIDER_CONFIG, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInForm, SignUp, SignUpForm, SignedIn, SignedOut, UserButton, VerifyEmail, VerifyEmailStatus, checkPasswordStrength, createPasswordSchema, emailSchema, getAllProviderConfigs, getInsforgeRoutes, getProviderConfig, passwordSchema, useAuth, useInsforge, usePublicAuthConfig, useUser, validateEmail, validatePassword };
|
|
2628
2415
|
//# sourceMappingURL=index.js.map
|
|
2629
2416
|
//# sourceMappingURL=index.js.map
|