@insforge/react 0.4.0 → 0.4.6
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 +6 -12
- 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 +600 -795
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -17
- package/dist/index.d.ts +40 -17
- package/dist/index.js +600 -795
- package/dist/index.js.map +1 -1
- package/dist/router.cjs +2 -2
- 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 +2 -2
- 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';
|
|
@@ -22,13 +23,15 @@ var InsforgeContext = createContext(void 0);
|
|
|
22
23
|
function InsforgeProvider({
|
|
23
24
|
children,
|
|
24
25
|
baseUrl,
|
|
26
|
+
afterSignInUrl = "/",
|
|
25
27
|
onAuthChange,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
onSignIn,
|
|
29
|
+
onSignOut
|
|
28
30
|
}) {
|
|
29
31
|
const [user, setUser] = useState(null);
|
|
30
32
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
31
33
|
const refreshIntervalRef = useRef(null);
|
|
34
|
+
const hasProcessedCallbackRef = useRef(false);
|
|
32
35
|
const [insforge] = useState(() => createClient({ baseUrl }));
|
|
33
36
|
const loadAuthState = useCallback(async () => {
|
|
34
37
|
try {
|
|
@@ -60,9 +63,9 @@ function InsforgeProvider({
|
|
|
60
63
|
return { success: true };
|
|
61
64
|
} else {
|
|
62
65
|
await insforge.auth.signOut();
|
|
63
|
-
if (
|
|
66
|
+
if (onSignOut) {
|
|
64
67
|
try {
|
|
65
|
-
await
|
|
68
|
+
await onSignOut();
|
|
66
69
|
} catch (error) {
|
|
67
70
|
if (error instanceof Error) {
|
|
68
71
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -79,9 +82,9 @@ function InsforgeProvider({
|
|
|
79
82
|
} catch (error) {
|
|
80
83
|
console.error("[InsforgeProvider] Token validation failed:", error);
|
|
81
84
|
await insforge.auth.signOut();
|
|
82
|
-
if (
|
|
85
|
+
if (onSignOut) {
|
|
83
86
|
try {
|
|
84
|
-
await
|
|
87
|
+
await onSignOut();
|
|
85
88
|
} catch (error2) {
|
|
86
89
|
if (error2 instanceof Error) {
|
|
87
90
|
console.error("[InsforgeProvider] Error clearing cookie:", error2.message);
|
|
@@ -98,7 +101,7 @@ function InsforgeProvider({
|
|
|
98
101
|
error: error instanceof Error ? error.message : "Authentication failed"
|
|
99
102
|
};
|
|
100
103
|
}
|
|
101
|
-
}, [insforge, onAuthChange,
|
|
104
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
102
105
|
useEffect(() => {
|
|
103
106
|
loadAuthState();
|
|
104
107
|
const intervalId = refreshIntervalRef.current;
|
|
@@ -108,6 +111,22 @@ function InsforgeProvider({
|
|
|
108
111
|
}
|
|
109
112
|
};
|
|
110
113
|
}, [loadAuthState]);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (!isLoaded || hasProcessedCallbackRef.current) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
119
|
+
const accessToken = searchParams.get("access_token");
|
|
120
|
+
if (accessToken && !!user) {
|
|
121
|
+
hasProcessedCallbackRef.current = true;
|
|
122
|
+
const url = new URL(window.location.href);
|
|
123
|
+
url.search = "";
|
|
124
|
+
window.history.replaceState({}, "", url.toString());
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
window.location.href = afterSignInUrl;
|
|
127
|
+
}, 100);
|
|
128
|
+
}
|
|
129
|
+
}, [isLoaded, user, afterSignInUrl]);
|
|
111
130
|
const getPublicAuthConfig = useCallback(async () => {
|
|
112
131
|
try {
|
|
113
132
|
const result = await insforge.auth.getPublicAuthConfig();
|
|
@@ -137,9 +156,9 @@ function InsforgeProvider({
|
|
|
137
156
|
if (onAuthChange) {
|
|
138
157
|
onAuthChange(userData);
|
|
139
158
|
}
|
|
140
|
-
if (
|
|
159
|
+
if (onSignIn) {
|
|
141
160
|
try {
|
|
142
|
-
await
|
|
161
|
+
await onSignIn(authToken);
|
|
143
162
|
} catch (error) {
|
|
144
163
|
if (error instanceof Error) {
|
|
145
164
|
console.error("[InsforgeProvider] Error syncing token to cookie:", error.message);
|
|
@@ -159,7 +178,7 @@ function InsforgeProvider({
|
|
|
159
178
|
}
|
|
160
179
|
}
|
|
161
180
|
},
|
|
162
|
-
[insforge, onAuthChange,
|
|
181
|
+
[insforge, onAuthChange, onSignIn]
|
|
163
182
|
);
|
|
164
183
|
const signIn = useCallback(
|
|
165
184
|
async (email, password) => {
|
|
@@ -214,9 +233,9 @@ function InsforgeProvider({
|
|
|
214
233
|
);
|
|
215
234
|
const signOut = useCallback(async () => {
|
|
216
235
|
await insforge.auth.signOut();
|
|
217
|
-
if (
|
|
236
|
+
if (onSignOut) {
|
|
218
237
|
try {
|
|
219
|
-
await
|
|
238
|
+
await onSignOut();
|
|
220
239
|
} catch (error) {
|
|
221
240
|
if (error instanceof Error) {
|
|
222
241
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -230,7 +249,7 @@ function InsforgeProvider({
|
|
|
230
249
|
if (onAuthChange) {
|
|
231
250
|
onAuthChange(null);
|
|
232
251
|
}
|
|
233
|
-
}, [insforge, onAuthChange,
|
|
252
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
234
253
|
const updateUser = useCallback(
|
|
235
254
|
async (data) => {
|
|
236
255
|
if (!user) {
|
|
@@ -260,6 +279,13 @@ function InsforgeProvider({
|
|
|
260
279
|
},
|
|
261
280
|
[user, onAuthChange, insforge]
|
|
262
281
|
);
|
|
282
|
+
const sendVerificationEmail = useCallback(
|
|
283
|
+
async (email) => {
|
|
284
|
+
const sdkResult = await insforge.auth.sendVerificationEmail({ email });
|
|
285
|
+
return sdkResult.data;
|
|
286
|
+
},
|
|
287
|
+
[insforge]
|
|
288
|
+
);
|
|
263
289
|
const sendResetPasswordEmail = useCallback(
|
|
264
290
|
async (email) => {
|
|
265
291
|
const sdkResult = await insforge.auth.sendResetPasswordEmail({ email });
|
|
@@ -278,8 +304,39 @@ function InsforgeProvider({
|
|
|
278
304
|
[insforge]
|
|
279
305
|
);
|
|
280
306
|
const verifyEmail = useCallback(
|
|
281
|
-
async (
|
|
282
|
-
const sdkResult = await insforge.auth.verifyEmail({ otp:
|
|
307
|
+
async (otp, email) => {
|
|
308
|
+
const sdkResult = await insforge.auth.verifyEmail({ otp, email: email || void 0 });
|
|
309
|
+
if (sdkResult.data) {
|
|
310
|
+
return sdkResult.data;
|
|
311
|
+
} else {
|
|
312
|
+
return {
|
|
313
|
+
accessToken: "",
|
|
314
|
+
error: {
|
|
315
|
+
message: sdkResult.error?.message || "Email verification failed"
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
[insforge]
|
|
321
|
+
);
|
|
322
|
+
const exchangeResetPasswordToken = useCallback(
|
|
323
|
+
async (email, code) => {
|
|
324
|
+
const sdkResult = await insforge.auth.exchangeResetPasswordToken({ email, code });
|
|
325
|
+
if (sdkResult.data) {
|
|
326
|
+
return sdkResult.data;
|
|
327
|
+
} else {
|
|
328
|
+
return {
|
|
329
|
+
error: {
|
|
330
|
+
message: sdkResult.error?.message || "Failed to exchange reset password token"
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
[insforge]
|
|
336
|
+
);
|
|
337
|
+
const loginWithOAuth = useCallback(
|
|
338
|
+
async (provider, redirectTo) => {
|
|
339
|
+
const sdkResult = await insforge.auth.signInWithOAuth({ provider, redirectTo });
|
|
283
340
|
return sdkResult.data;
|
|
284
341
|
},
|
|
285
342
|
[insforge]
|
|
@@ -298,10 +355,13 @@ function InsforgeProvider({
|
|
|
298
355
|
updateUser,
|
|
299
356
|
reloadAuth: loadAuthState,
|
|
300
357
|
baseUrl,
|
|
358
|
+
sendVerificationEmail,
|
|
301
359
|
sendResetPasswordEmail,
|
|
302
360
|
resetPassword,
|
|
303
361
|
verifyEmail,
|
|
304
|
-
|
|
362
|
+
exchangeResetPasswordToken,
|
|
363
|
+
getPublicAuthConfig,
|
|
364
|
+
loginWithOAuth
|
|
305
365
|
},
|
|
306
366
|
children
|
|
307
367
|
}
|
|
@@ -419,21 +479,12 @@ function AuthErrorBanner({ error }) {
|
|
|
419
479
|
if (!error) {
|
|
420
480
|
return null;
|
|
421
481
|
}
|
|
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
|
-
),
|
|
482
|
+
return /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", { className: "if-errorBanner-content", children: [
|
|
483
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "if-errorBanner-icon" }),
|
|
429
484
|
/* @__PURE__ */ jsx("span", { className: "if-errorBanner-text", children: error })
|
|
430
485
|
] }) });
|
|
431
486
|
}
|
|
432
|
-
function AuthFormField({
|
|
433
|
-
label,
|
|
434
|
-
id,
|
|
435
|
-
...props
|
|
436
|
-
}) {
|
|
487
|
+
function AuthFormField({ label, id, ...props }) {
|
|
437
488
|
return /* @__PURE__ */ jsxs("div", { className: "if-formField if-internal-f9n6p2", children: [
|
|
438
489
|
/* @__PURE__ */ jsx("label", { htmlFor: id, className: "if-formField-label if-internal-l3k8m1", children: label }),
|
|
439
490
|
/* @__PURE__ */ jsx("input", { id, className: "if-formField-input if-internal-i2v8k4", ...props })
|
|
@@ -560,14 +611,17 @@ function AuthSubmitButton({
|
|
|
560
611
|
children,
|
|
561
612
|
isLoading = false,
|
|
562
613
|
confirmed = false,
|
|
563
|
-
disabled = false
|
|
614
|
+
disabled = false,
|
|
615
|
+
type = "submit",
|
|
616
|
+
onClick
|
|
564
617
|
}) {
|
|
565
618
|
return /* @__PURE__ */ jsxs(
|
|
566
619
|
"button",
|
|
567
620
|
{
|
|
568
|
-
type
|
|
621
|
+
type,
|
|
569
622
|
className: "if-submitButton if-internal-b8p3m4",
|
|
570
623
|
disabled: disabled || isLoading || confirmed,
|
|
624
|
+
onClick,
|
|
571
625
|
children: [
|
|
572
626
|
isLoading && /* @__PURE__ */ jsx(Loader2, { className: "if-submitButton-icon if-submitButton-spinner", size: 20 }),
|
|
573
627
|
confirmed && /* @__PURE__ */ jsx(CircleCheck, { className: "if-submitButton-icon", size: 20 }),
|
|
@@ -576,24 +630,16 @@ function AuthSubmitButton({
|
|
|
576
630
|
}
|
|
577
631
|
);
|
|
578
632
|
}
|
|
579
|
-
function AuthLink({
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
href
|
|
583
|
-
}) {
|
|
584
|
-
const currentSearch = typeof window !== "undefined" ? window.location.search : "";
|
|
633
|
+
function AuthLink({ text, linkText, href }) {
|
|
634
|
+
const [searchParams] = useSearchParams();
|
|
635
|
+
const currentSearch = searchParams.toString();
|
|
585
636
|
const finalHref = (() => {
|
|
586
637
|
if (!currentSearch) {
|
|
587
638
|
return href;
|
|
588
639
|
}
|
|
589
640
|
try {
|
|
590
641
|
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
|
-
});
|
|
642
|
+
url.search = currentSearch;
|
|
597
643
|
return url.pathname + url.search;
|
|
598
644
|
} catch {
|
|
599
645
|
return href;
|
|
@@ -953,28 +999,26 @@ function AuthVerificationCodeInput({
|
|
|
953
999
|
}
|
|
954
1000
|
function AuthEmailVerificationStep({
|
|
955
1001
|
email,
|
|
956
|
-
description,
|
|
957
1002
|
method = "code",
|
|
958
1003
|
onVerifyCode
|
|
959
1004
|
}) {
|
|
960
|
-
const {
|
|
961
|
-
const [insforge] = useState(() => createClient({ baseUrl }));
|
|
1005
|
+
const { sendVerificationEmail } = useInsforge();
|
|
962
1006
|
const [resendDisabled, setResendDisabled] = useState(true);
|
|
963
1007
|
const [resendCountdown, setResendCountdown] = useState(60);
|
|
964
1008
|
const [isSending, setIsSending] = useState(false);
|
|
965
1009
|
const [verificationCode, setVerificationCode] = useState("");
|
|
966
1010
|
const [isVerifying, setIsVerifying] = useState(false);
|
|
967
|
-
const [verificationError, setVerificationError] = useState("");
|
|
968
1011
|
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
1012
|
useEffect(() => {
|
|
970
1013
|
const sendInitialEmail = async () => {
|
|
971
1014
|
try {
|
|
972
|
-
await
|
|
973
|
-
} catch {
|
|
1015
|
+
await sendVerificationEmail(email);
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
console.error("Failed to send verification email:", error);
|
|
974
1018
|
}
|
|
975
1019
|
};
|
|
976
1020
|
void sendInitialEmail();
|
|
977
|
-
}, [email,
|
|
1021
|
+
}, [email, sendVerificationEmail]);
|
|
978
1022
|
useEffect(() => {
|
|
979
1023
|
if (resendCountdown > 0) {
|
|
980
1024
|
const timer = setInterval(() => {
|
|
@@ -993,9 +1037,8 @@ function AuthEmailVerificationStep({
|
|
|
993
1037
|
setResendDisabled(true);
|
|
994
1038
|
setResendCountdown(60);
|
|
995
1039
|
setIsSending(true);
|
|
996
|
-
setVerificationError("");
|
|
997
1040
|
try {
|
|
998
|
-
await
|
|
1041
|
+
await sendVerificationEmail(email);
|
|
999
1042
|
} catch {
|
|
1000
1043
|
setResendDisabled(false);
|
|
1001
1044
|
setResendCountdown(0);
|
|
@@ -1003,123 +1046,157 @@ function AuthEmailVerificationStep({
|
|
|
1003
1046
|
setIsSending(false);
|
|
1004
1047
|
}
|
|
1005
1048
|
};
|
|
1006
|
-
const
|
|
1007
|
-
if (!onVerifyCode) {
|
|
1049
|
+
const handleSubmit = async () => {
|
|
1050
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1008
1051
|
return;
|
|
1009
1052
|
}
|
|
1010
1053
|
setIsVerifying(true);
|
|
1011
|
-
setVerificationError("");
|
|
1012
1054
|
try {
|
|
1013
|
-
await onVerifyCode(
|
|
1014
|
-
} catch (error) {
|
|
1015
|
-
setVerificationError(
|
|
1016
|
-
error instanceof Error ? error.message : "Invalid verification code. Please try again."
|
|
1017
|
-
);
|
|
1018
|
-
setVerificationCode("");
|
|
1055
|
+
await onVerifyCode(verificationCode);
|
|
1019
1056
|
} finally {
|
|
1020
1057
|
setIsVerifying(false);
|
|
1058
|
+
setVerificationCode("");
|
|
1021
1059
|
}
|
|
1022
1060
|
};
|
|
1023
|
-
const displayDescription =
|
|
1024
|
-
|
|
1025
|
-
|
|
1061
|
+
const displayDescription = defaultDescription;
|
|
1062
|
+
const isLinkMethod = method === "link";
|
|
1063
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
|
|
1064
|
+
/* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
|
|
1026
1065
|
part,
|
|
1027
1066
|
index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email })
|
|
1028
1067
|
] }, index)) }),
|
|
1029
|
-
|
|
1068
|
+
!isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1069
|
+
/* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
|
|
1070
|
+
AuthVerificationCodeInput,
|
|
1071
|
+
{
|
|
1072
|
+
value: verificationCode,
|
|
1073
|
+
onChange: setVerificationCode,
|
|
1074
|
+
email,
|
|
1075
|
+
disabled: isVerifying
|
|
1076
|
+
}
|
|
1077
|
+
) }),
|
|
1030
1078
|
/* @__PURE__ */ jsx(
|
|
1031
|
-
|
|
1079
|
+
AuthSubmitButton,
|
|
1032
1080
|
{
|
|
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" })
|
|
1081
|
+
type: "button",
|
|
1082
|
+
isLoading: isVerifying,
|
|
1083
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1084
|
+
onClick: () => {
|
|
1085
|
+
void handleSubmit();
|
|
1086
|
+
},
|
|
1087
|
+
children: isVerifying ? "Verifying..." : "Verify Code"
|
|
1041
1088
|
}
|
|
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
|
-
|
|
1089
|
+
)
|
|
1090
|
+
] }),
|
|
1091
|
+
/* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1092
|
+
"Didn't receive the email?",
|
|
1093
|
+
" ",
|
|
1094
|
+
/* @__PURE__ */ jsx(
|
|
1095
|
+
"button",
|
|
1096
|
+
{
|
|
1097
|
+
onClick: () => {
|
|
1098
|
+
void handleResend();
|
|
1099
|
+
},
|
|
1100
|
+
disabled: resendDisabled || isSending,
|
|
1101
|
+
className: "if-verificationStep-resendButton",
|
|
1102
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1103
|
+
}
|
|
1104
|
+
)
|
|
1105
|
+
] })
|
|
1106
|
+
] });
|
|
1107
|
+
}
|
|
1108
|
+
function AuthResetPasswordVerificationStep({
|
|
1109
|
+
email,
|
|
1110
|
+
method,
|
|
1111
|
+
onVerifyCode,
|
|
1112
|
+
onResendEmail
|
|
1113
|
+
}) {
|
|
1114
|
+
const [resendDisabled, setResendDisabled] = useState(true);
|
|
1115
|
+
const [resendCountdown, setResendCountdown] = useState(60);
|
|
1116
|
+
const [isSending, setIsSending] = useState(false);
|
|
1117
|
+
const [verificationCode, setVerificationCode] = useState("");
|
|
1118
|
+
const [isVerifying, setIsVerifying] = useState(false);
|
|
1119
|
+
useEffect(() => {
|
|
1120
|
+
if (resendCountdown > 0) {
|
|
1121
|
+
const timer = setInterval(() => {
|
|
1122
|
+
setResendCountdown((prev) => {
|
|
1123
|
+
if (prev <= 1) {
|
|
1124
|
+
setResendDisabled(false);
|
|
1125
|
+
return 0;
|
|
1126
|
+
}
|
|
1127
|
+
return prev - 1;
|
|
1128
|
+
});
|
|
1129
|
+
}, 1e3);
|
|
1130
|
+
return () => clearInterval(timer);
|
|
1131
|
+
}
|
|
1132
|
+
}, [resendCountdown]);
|
|
1133
|
+
const handleResend = useCallback(async () => {
|
|
1134
|
+
setResendDisabled(true);
|
|
1135
|
+
setResendCountdown(60);
|
|
1136
|
+
setIsSending(true);
|
|
1137
|
+
try {
|
|
1138
|
+
await onResendEmail();
|
|
1139
|
+
} catch {
|
|
1140
|
+
setResendDisabled(false);
|
|
1141
|
+
setResendCountdown(0);
|
|
1142
|
+
} finally {
|
|
1143
|
+
setIsSending(false);
|
|
1144
|
+
}
|
|
1145
|
+
}, [onResendEmail]);
|
|
1146
|
+
const handleSubmit = async () => {
|
|
1147
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
setIsVerifying(true);
|
|
1151
|
+
try {
|
|
1152
|
+
await onVerifyCode(verificationCode);
|
|
1153
|
+
} finally {
|
|
1154
|
+
setIsVerifying(false);
|
|
1155
|
+
setVerificationCode("");
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
const isLinkMethod = method === "link";
|
|
1159
|
+
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.`;
|
|
1160
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
|
|
1161
|
+
/* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: description }),
|
|
1162
|
+
!isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1163
|
+
/* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
|
|
1164
|
+
AuthVerificationCodeInput,
|
|
1165
|
+
{
|
|
1166
|
+
value: verificationCode,
|
|
1167
|
+
onChange: setVerificationCode,
|
|
1168
|
+
email,
|
|
1169
|
+
disabled: isVerifying
|
|
1170
|
+
}
|
|
1171
|
+
) }),
|
|
1172
|
+
/* @__PURE__ */ jsx(
|
|
1173
|
+
AuthSubmitButton,
|
|
1174
|
+
{
|
|
1175
|
+
type: "button",
|
|
1176
|
+
isLoading: isVerifying,
|
|
1177
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1178
|
+
onClick: () => {
|
|
1179
|
+
void handleSubmit();
|
|
1180
|
+
},
|
|
1181
|
+
children: isVerifying ? "Verifying..." : "Continue"
|
|
1182
|
+
}
|
|
1183
|
+
)
|
|
1184
|
+
] }),
|
|
1185
|
+
/* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1186
|
+
"Didn't receive the email?",
|
|
1187
|
+
" ",
|
|
1188
|
+
/* @__PURE__ */ jsx(
|
|
1189
|
+
"button",
|
|
1190
|
+
{
|
|
1191
|
+
onClick: () => {
|
|
1192
|
+
void handleResend();
|
|
1193
|
+
},
|
|
1194
|
+
disabled: resendDisabled || isSending,
|
|
1195
|
+
className: "if-verificationStep-resendButton",
|
|
1196
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1197
|
+
}
|
|
1198
|
+
)
|
|
1199
|
+
] })
|
|
1123
1200
|
] });
|
|
1124
1201
|
}
|
|
1125
1202
|
function SignInForm({
|
|
@@ -1149,8 +1226,7 @@ function SignInForm({
|
|
|
1149
1226
|
signUpUrl = "/sign-up",
|
|
1150
1227
|
dividerText = "or",
|
|
1151
1228
|
showVerificationStep = false,
|
|
1152
|
-
onVerifyCode
|
|
1153
|
-
verificationDescription
|
|
1229
|
+
onVerifyCode
|
|
1154
1230
|
}) {
|
|
1155
1231
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1156
1232
|
/* @__PURE__ */ jsx(
|
|
@@ -1161,14 +1237,7 @@ function SignInForm({
|
|
|
1161
1237
|
}
|
|
1162
1238
|
),
|
|
1163
1239
|
/* @__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: [
|
|
1240
|
+
showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1172
1241
|
/* @__PURE__ */ jsx(
|
|
1173
1242
|
AuthFormField,
|
|
1174
1243
|
{
|
|
@@ -1218,16 +1287,17 @@ function SignInForm({
|
|
|
1218
1287
|
] })
|
|
1219
1288
|
] });
|
|
1220
1289
|
}
|
|
1221
|
-
function SignIn({
|
|
1222
|
-
const { signIn,
|
|
1290
|
+
function SignIn({ onError, ...uiProps }) {
|
|
1291
|
+
const { signIn, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1223
1292
|
const { authConfig } = usePublicAuthConfig();
|
|
1224
1293
|
const [email, setEmail] = useState("");
|
|
1225
1294
|
const [password, setPassword] = useState("");
|
|
1226
1295
|
const [error, setError] = useState("");
|
|
1227
1296
|
const [loading, setLoading] = useState(false);
|
|
1228
1297
|
const [step, setStep] = useState("form");
|
|
1229
|
-
const [oauthLoading
|
|
1230
|
-
const [
|
|
1298
|
+
const [oauthLoading] = useState(null);
|
|
1299
|
+
const [searchParams] = useSearchParams();
|
|
1300
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1231
1301
|
async function handleSubmit(e) {
|
|
1232
1302
|
e.preventDefault();
|
|
1233
1303
|
setLoading(true);
|
|
@@ -1243,10 +1313,13 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1243
1313
|
throw new Error(result.error);
|
|
1244
1314
|
}
|
|
1245
1315
|
const { user, accessToken, redirectTo } = result;
|
|
1246
|
-
if (
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1316
|
+
if (user) {
|
|
1317
|
+
const finalUrl = new URL(redirectTo || redirectUrl || "", window.location.origin);
|
|
1318
|
+
finalUrl.searchParams.set("access_token", accessToken);
|
|
1319
|
+
finalUrl.searchParams.set("user_id", user.id);
|
|
1320
|
+
finalUrl.searchParams.set("email", user.email);
|
|
1321
|
+
finalUrl.searchParams.set("name", user.name);
|
|
1322
|
+
window.location.href = finalUrl.toString();
|
|
1250
1323
|
}
|
|
1251
1324
|
} catch (err) {
|
|
1252
1325
|
const errorMessage = err instanceof Error ? err.message : "Sign in failed";
|
|
@@ -1259,38 +1332,28 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1259
1332
|
}
|
|
1260
1333
|
}
|
|
1261
1334
|
async function handleVerifyCode(code) {
|
|
1335
|
+
setError("");
|
|
1262
1336
|
try {
|
|
1263
|
-
const result = await
|
|
1264
|
-
if (result
|
|
1337
|
+
const result = await verifyEmail(email, code);
|
|
1338
|
+
if (result?.error) {
|
|
1265
1339
|
throw new Error(result.error.message || "Verification failed");
|
|
1266
1340
|
}
|
|
1267
|
-
if (result
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1341
|
+
if (result?.user) {
|
|
1342
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1343
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1344
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1345
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1346
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1347
|
+
window.location.href = finalUrl.toString();
|
|
1271
1348
|
}
|
|
1272
1349
|
} catch (err) {
|
|
1273
1350
|
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
1351
|
setError(errorMessage);
|
|
1288
|
-
if (onError) {
|
|
1289
|
-
onError(new Error(errorMessage));
|
|
1290
|
-
}
|
|
1291
|
-
setOauthLoading(null);
|
|
1292
1352
|
}
|
|
1293
1353
|
}
|
|
1354
|
+
function handleOAuth(provider) {
|
|
1355
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1356
|
+
}
|
|
1294
1357
|
if (!authConfig) {
|
|
1295
1358
|
return null;
|
|
1296
1359
|
}
|
|
@@ -1339,8 +1402,7 @@ function SignUpForm({
|
|
|
1339
1402
|
signInUrl = "/sign-in",
|
|
1340
1403
|
dividerText = "or",
|
|
1341
1404
|
showVerificationStep = false,
|
|
1342
|
-
onVerifyCode
|
|
1343
|
-
verificationDescription
|
|
1405
|
+
onVerifyCode
|
|
1344
1406
|
}) {
|
|
1345
1407
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1346
1408
|
/* @__PURE__ */ jsx(
|
|
@@ -1351,14 +1413,7 @@ function SignUpForm({
|
|
|
1351
1413
|
}
|
|
1352
1414
|
),
|
|
1353
1415
|
/* @__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: [
|
|
1416
|
+
showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1362
1417
|
/* @__PURE__ */ jsx(
|
|
1363
1418
|
AuthFormField,
|
|
1364
1419
|
{
|
|
@@ -1477,16 +1532,17 @@ function checkPasswordStrength(password) {
|
|
|
1477
1532
|
}
|
|
1478
1533
|
return { score, feedback };
|
|
1479
1534
|
}
|
|
1480
|
-
function SignUp({
|
|
1481
|
-
const { signUp,
|
|
1535
|
+
function SignUp({ onError, ...uiProps }) {
|
|
1536
|
+
const { signUp, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1482
1537
|
const { authConfig } = usePublicAuthConfig();
|
|
1483
1538
|
const [email, setEmail] = useState("");
|
|
1484
1539
|
const [password, setPassword] = useState("");
|
|
1485
1540
|
const [error, setError] = useState("");
|
|
1486
1541
|
const [loading, setLoading] = useState(false);
|
|
1487
1542
|
const [step, setStep] = useState("form");
|
|
1488
|
-
const [oauthLoading
|
|
1489
|
-
const [
|
|
1543
|
+
const [oauthLoading] = useState(null);
|
|
1544
|
+
const [searchParams] = useSearchParams();
|
|
1545
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1490
1546
|
async function handleSubmit(e) {
|
|
1491
1547
|
e.preventDefault();
|
|
1492
1548
|
setLoading(true);
|
|
@@ -1528,9 +1584,12 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1528
1584
|
return;
|
|
1529
1585
|
}
|
|
1530
1586
|
if (result.accessToken && result.user) {
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1587
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1588
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1589
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1590
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1591
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1592
|
+
window.location.href = finalUrl.toString();
|
|
1534
1593
|
}
|
|
1535
1594
|
} catch (err) {
|
|
1536
1595
|
const errorMessage = err instanceof Error ? err.message : "Sign up failed";
|
|
@@ -1543,38 +1602,28 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1543
1602
|
}
|
|
1544
1603
|
}
|
|
1545
1604
|
async function handleVerifyCode(code) {
|
|
1605
|
+
setError("");
|
|
1546
1606
|
try {
|
|
1547
|
-
const result = await
|
|
1548
|
-
if (result
|
|
1607
|
+
const result = await verifyEmail(email, code);
|
|
1608
|
+
if (result?.error) {
|
|
1549
1609
|
throw new Error(result.error.message || "Verification failed");
|
|
1550
1610
|
}
|
|
1551
|
-
if (result
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1611
|
+
if (result?.user) {
|
|
1612
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1613
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1614
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1615
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1616
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1617
|
+
window.location.href = finalUrl.toString();
|
|
1555
1618
|
}
|
|
1556
1619
|
} catch (err) {
|
|
1557
1620
|
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
1621
|
setError(errorMessage);
|
|
1572
|
-
if (onError) {
|
|
1573
|
-
onError(new Error(errorMessage));
|
|
1574
|
-
}
|
|
1575
|
-
setOauthLoading(null);
|
|
1576
1622
|
}
|
|
1577
1623
|
}
|
|
1624
|
+
function handleOAuth(provider) {
|
|
1625
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1626
|
+
}
|
|
1578
1627
|
if (!authConfig) {
|
|
1579
1628
|
return null;
|
|
1580
1629
|
}
|
|
@@ -1604,7 +1653,6 @@ function ForgotPasswordForm({
|
|
|
1604
1653
|
onSubmit,
|
|
1605
1654
|
error,
|
|
1606
1655
|
loading = false,
|
|
1607
|
-
success = false,
|
|
1608
1656
|
title = "Forgot Password?",
|
|
1609
1657
|
subtitle = "Enter your email address and we'll send you a code to reset your password.",
|
|
1610
1658
|
emailLabel = "Email",
|
|
@@ -1613,53 +1661,30 @@ function ForgotPasswordForm({
|
|
|
1613
1661
|
loadingButtonText = "Sending...",
|
|
1614
1662
|
backToSignInText = "Remember your password?",
|
|
1615
1663
|
backToSignInUrl = "/sign-in",
|
|
1616
|
-
|
|
1617
|
-
|
|
1664
|
+
showVerificationStep = false,
|
|
1665
|
+
resetPasswordMethod = "code",
|
|
1666
|
+
onVerifyCode,
|
|
1667
|
+
onResendEmail
|
|
1618
1668
|
}) {
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1669
|
+
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1670
|
+
/* @__PURE__ */ jsx(
|
|
1671
|
+
AuthHeader,
|
|
1622
1672
|
{
|
|
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
|
-
]
|
|
1673
|
+
title: showVerificationStep ? resetPasswordMethod === "link" ? "Check Your Email" : "Enter Reset Code" : title,
|
|
1674
|
+
subtitle: showVerificationStep ? "" : subtitle
|
|
1656
1675
|
}
|
|
1657
|
-
)
|
|
1658
|
-
}
|
|
1659
|
-
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
1660
|
-
/* @__PURE__ */ jsx(AuthHeader, { title, subtitle }),
|
|
1676
|
+
),
|
|
1661
1677
|
/* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
|
|
1662
|
-
/* @__PURE__ */
|
|
1678
|
+
showVerificationStep ? /* @__PURE__ */ jsx(
|
|
1679
|
+
AuthResetPasswordVerificationStep,
|
|
1680
|
+
{
|
|
1681
|
+
email,
|
|
1682
|
+
method: resetPasswordMethod,
|
|
1683
|
+
onVerifyCode,
|
|
1684
|
+
onResendEmail: onResendEmail || (async () => {
|
|
1685
|
+
})
|
|
1686
|
+
}
|
|
1687
|
+
) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1663
1688
|
/* @__PURE__ */ jsx(
|
|
1664
1689
|
AuthFormField,
|
|
1665
1690
|
{
|
|
@@ -1675,7 +1700,7 @@ function ForgotPasswordForm({
|
|
|
1675
1700
|
),
|
|
1676
1701
|
/* @__PURE__ */ jsx(AuthSubmitButton, { isLoading: loading, disabled: loading, children: loading ? loadingButtonText : submitButtonText })
|
|
1677
1702
|
] }),
|
|
1678
|
-
/* @__PURE__ */ jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1703
|
+
!showVerificationStep && /* @__PURE__ */ jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1679
1704
|
] });
|
|
1680
1705
|
}
|
|
1681
1706
|
function ResetPasswordForm({
|
|
@@ -1696,11 +1721,12 @@ function ResetPasswordForm({
|
|
|
1696
1721
|
confirmPasswordPlaceholder = "\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
1697
1722
|
submitButtonText = "Reset Password",
|
|
1698
1723
|
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."
|
|
1724
|
+
successTitle = "Password Reset Successful!"
|
|
1703
1725
|
}) {
|
|
1726
|
+
let successMessage = "Your password has been successfully reset. You can close this page and sign in with your new password.";
|
|
1727
|
+
if (authConfig && authConfig.verifyEmailMethod === "code") {
|
|
1728
|
+
successMessage = "Your password has been successfully reset. You can wait for redirect to sign in with your new password.";
|
|
1729
|
+
}
|
|
1704
1730
|
if (success) {
|
|
1705
1731
|
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs(
|
|
1706
1732
|
"div",
|
|
@@ -1735,8 +1761,7 @@ function ResetPasswordForm({
|
|
|
1735
1761
|
}
|
|
1736
1762
|
),
|
|
1737
1763
|
/* @__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" })
|
|
1764
|
+
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
1740
1765
|
]
|
|
1741
1766
|
}
|
|
1742
1767
|
) });
|
|
@@ -1773,40 +1798,87 @@ function ResetPasswordForm({
|
|
|
1773
1798
|
}
|
|
1774
1799
|
),
|
|
1775
1800
|
/* @__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 })
|
|
1801
|
+
] })
|
|
1778
1802
|
] });
|
|
1779
1803
|
}
|
|
1780
|
-
function
|
|
1781
|
-
|
|
1782
|
-
backToSignInUrl = "/sign-in",
|
|
1783
|
-
onSuccess,
|
|
1784
|
-
onError,
|
|
1785
|
-
...uiProps
|
|
1786
|
-
}) {
|
|
1787
|
-
const { resetPassword } = useInsforge();
|
|
1804
|
+
function ForgotPassword({ onError, ...uiProps }) {
|
|
1805
|
+
const { sendResetPasswordEmail, exchangeResetPasswordToken, resetPassword } = useInsforge();
|
|
1788
1806
|
const { authConfig } = usePublicAuthConfig();
|
|
1807
|
+
const [searchParams] = useSearchParams();
|
|
1808
|
+
const [step, setStep] = useState("email");
|
|
1809
|
+
const [email, setEmail] = useState("");
|
|
1810
|
+
const [resetToken, setResetToken] = useState("");
|
|
1789
1811
|
const [newPassword, setNewPassword] = useState("");
|
|
1790
1812
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
1791
1813
|
const [error, setError] = useState("");
|
|
1792
1814
|
const [loading, setLoading] = useState(false);
|
|
1793
1815
|
const [success, setSuccess] = useState(false);
|
|
1794
|
-
|
|
1816
|
+
const [showVerificationStep, setShowVerificationStep] = useState(false);
|
|
1817
|
+
async function handleEmailSubmit(e) {
|
|
1795
1818
|
e.preventDefault();
|
|
1796
1819
|
setLoading(true);
|
|
1797
1820
|
setError("");
|
|
1798
|
-
|
|
1799
|
-
|
|
1821
|
+
const emailValidation = emailSchema.safeParse(email);
|
|
1822
|
+
if (!emailValidation.success) {
|
|
1823
|
+
const firstError = emailValidation.error.issues[0];
|
|
1824
|
+
setError(firstError.message);
|
|
1800
1825
|
setLoading(false);
|
|
1801
1826
|
return;
|
|
1802
1827
|
}
|
|
1828
|
+
try {
|
|
1829
|
+
const result = await sendResetPasswordEmail(emailValidation.data);
|
|
1830
|
+
if (result?.success) {
|
|
1831
|
+
setShowVerificationStep(true);
|
|
1832
|
+
} else {
|
|
1833
|
+
const errorMessage = result?.message || "Failed to send reset email";
|
|
1834
|
+
setError(errorMessage);
|
|
1835
|
+
if (onError) {
|
|
1836
|
+
onError(new Error(errorMessage));
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
} catch (err) {
|
|
1840
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to send reset email";
|
|
1841
|
+
setError(errorMessage);
|
|
1842
|
+
if (onError) {
|
|
1843
|
+
onError(new Error(errorMessage));
|
|
1844
|
+
}
|
|
1845
|
+
} finally {
|
|
1846
|
+
setLoading(false);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
async function handleVerifyCode(code) {
|
|
1850
|
+
setError("");
|
|
1851
|
+
try {
|
|
1852
|
+
const result = await exchangeResetPasswordToken(email, code);
|
|
1853
|
+
if ("error" in result) {
|
|
1854
|
+
throw new Error(result.error.message || "Failed to verify code");
|
|
1855
|
+
}
|
|
1856
|
+
if (result.token) {
|
|
1857
|
+
setResetToken(result.token);
|
|
1858
|
+
setStep("password");
|
|
1859
|
+
}
|
|
1860
|
+
} catch (err) {
|
|
1861
|
+
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1862
|
+
setError(errorMessage);
|
|
1863
|
+
if (onError) {
|
|
1864
|
+
onError(new Error(errorMessage));
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
async function handleResendEmail() {
|
|
1869
|
+
await sendResetPasswordEmail(email);
|
|
1870
|
+
}
|
|
1871
|
+
async function handleResetPasswordSubmit(e) {
|
|
1872
|
+
e.preventDefault();
|
|
1873
|
+
setLoading(true);
|
|
1874
|
+
setError("");
|
|
1803
1875
|
if (newPassword !== confirmPassword) {
|
|
1804
1876
|
setError("Passwords do not match");
|
|
1805
1877
|
setLoading(false);
|
|
1806
1878
|
return;
|
|
1807
1879
|
}
|
|
1808
|
-
if (!
|
|
1809
|
-
setError("
|
|
1880
|
+
if (!authConfig) {
|
|
1881
|
+
setError("Configuration not loaded");
|
|
1810
1882
|
setLoading(false);
|
|
1811
1883
|
return;
|
|
1812
1884
|
}
|
|
@@ -1825,12 +1897,16 @@ function ResetPassword({
|
|
|
1825
1897
|
return;
|
|
1826
1898
|
}
|
|
1827
1899
|
try {
|
|
1828
|
-
const result = await resetPassword(
|
|
1900
|
+
const result = await resetPassword(resetToken, newPassword);
|
|
1829
1901
|
if (result?.message) {
|
|
1830
1902
|
setSuccess(true);
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1903
|
+
const signInUrl = new URL("/sign-in", window.location.origin);
|
|
1904
|
+
searchParams.forEach((value, key) => {
|
|
1905
|
+
signInUrl.searchParams.set(key, value);
|
|
1906
|
+
});
|
|
1907
|
+
setTimeout(() => {
|
|
1908
|
+
window.location.href = signInUrl.toString();
|
|
1909
|
+
}, 2e3);
|
|
1834
1910
|
} else {
|
|
1835
1911
|
const errorMessage = "Failed to reset password";
|
|
1836
1912
|
setError(errorMessage);
|
|
@@ -1851,6 +1927,25 @@ function ResetPassword({
|
|
|
1851
1927
|
if (!authConfig) {
|
|
1852
1928
|
return null;
|
|
1853
1929
|
}
|
|
1930
|
+
if (step === "email") {
|
|
1931
|
+
return /* @__PURE__ */ jsx(
|
|
1932
|
+
ForgotPasswordForm,
|
|
1933
|
+
{
|
|
1934
|
+
email,
|
|
1935
|
+
onEmailChange: setEmail,
|
|
1936
|
+
onSubmit: (e) => {
|
|
1937
|
+
void handleEmailSubmit(e);
|
|
1938
|
+
},
|
|
1939
|
+
error,
|
|
1940
|
+
loading,
|
|
1941
|
+
showVerificationStep,
|
|
1942
|
+
resetPasswordMethod: authConfig.resetPasswordMethod,
|
|
1943
|
+
onVerifyCode: handleVerifyCode,
|
|
1944
|
+
onResendEmail: handleResendEmail,
|
|
1945
|
+
...uiProps
|
|
1946
|
+
}
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1854
1949
|
return /* @__PURE__ */ jsx(
|
|
1855
1950
|
ResetPasswordForm,
|
|
1856
1951
|
{
|
|
@@ -1858,83 +1953,71 @@ function ResetPassword({
|
|
|
1858
1953
|
confirmPassword,
|
|
1859
1954
|
onNewPasswordChange: setNewPassword,
|
|
1860
1955
|
onConfirmPasswordChange: setConfirmPassword,
|
|
1861
|
-
onSubmit:
|
|
1956
|
+
onSubmit: handleResetPasswordSubmit,
|
|
1862
1957
|
error,
|
|
1863
1958
|
loading,
|
|
1864
1959
|
success,
|
|
1865
1960
|
authConfig,
|
|
1866
|
-
backToSignInUrl,
|
|
1867
1961
|
...uiProps
|
|
1868
1962
|
}
|
|
1869
1963
|
);
|
|
1870
1964
|
}
|
|
1871
|
-
function
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
...uiProps
|
|
1876
|
-
}) {
|
|
1877
|
-
const { sendResetPasswordEmail, baseUrl } = useInsforge();
|
|
1965
|
+
function ResetPassword({ onError, ...uiProps }) {
|
|
1966
|
+
const [searchParams] = useSearchParams();
|
|
1967
|
+
const token = searchParams.get("token");
|
|
1968
|
+
const { resetPassword } = useInsforge();
|
|
1878
1969
|
const { authConfig } = usePublicAuthConfig();
|
|
1879
|
-
const [
|
|
1880
|
-
const [
|
|
1881
|
-
const [email, setEmail] = useState("");
|
|
1882
|
-
const [verificationCode, setVerificationCode] = useState("");
|
|
1883
|
-
const [resetToken, setResetToken] = useState("");
|
|
1970
|
+
const [newPassword, setNewPassword] = useState("");
|
|
1971
|
+
const [confirmPassword, setConfirmPassword] = useState("");
|
|
1884
1972
|
const [error, setError] = useState("");
|
|
1885
1973
|
const [loading, setLoading] = useState(false);
|
|
1886
1974
|
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) {
|
|
1975
|
+
async function handleSubmit(e) {
|
|
1906
1976
|
e.preventDefault();
|
|
1907
1977
|
setLoading(true);
|
|
1908
1978
|
setError("");
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1979
|
+
if (!authConfig) {
|
|
1980
|
+
setError("Configuration not loaded. Please refresh the page.");
|
|
1981
|
+
setLoading(false);
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
if (newPassword !== confirmPassword) {
|
|
1985
|
+
setError("Passwords do not match");
|
|
1986
|
+
setLoading(false);
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
if (!token) {
|
|
1990
|
+
setError("Reset token is missing");
|
|
1991
|
+
setLoading(false);
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
const passwordZodSchema = createPasswordSchema({
|
|
1995
|
+
minLength: authConfig.passwordMinLength,
|
|
1996
|
+
requireUppercase: authConfig.requireUppercase,
|
|
1997
|
+
requireLowercase: authConfig.requireLowercase,
|
|
1998
|
+
requireNumber: authConfig.requireNumber,
|
|
1999
|
+
requireSpecialChar: authConfig.requireSpecialChar
|
|
2000
|
+
});
|
|
2001
|
+
const passwordValidation = passwordZodSchema.safeParse(newPassword);
|
|
2002
|
+
if (!passwordValidation.success) {
|
|
2003
|
+
const firstError = passwordValidation.error.issues[0];
|
|
1912
2004
|
setError(firstError.message);
|
|
1913
2005
|
setLoading(false);
|
|
1914
2006
|
return;
|
|
1915
2007
|
}
|
|
1916
2008
|
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
|
-
}
|
|
2009
|
+
const result = await resetPassword(token, newPassword);
|
|
2010
|
+
if (result?.message) {
|
|
2011
|
+
setSuccess(true);
|
|
1929
2012
|
} else {
|
|
1930
|
-
const errorMessage =
|
|
2013
|
+
const errorMessage = "Failed to reset password";
|
|
1931
2014
|
setError(errorMessage);
|
|
1932
2015
|
if (onError) {
|
|
1933
2016
|
onError(new Error(errorMessage));
|
|
1934
2017
|
}
|
|
1935
2018
|
}
|
|
1936
2019
|
} catch (err) {
|
|
1937
|
-
const errorMessage = err instanceof Error ? err.message : "Failed to
|
|
2020
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to reset password";
|
|
1938
2021
|
setError(errorMessage);
|
|
1939
2022
|
if (onError) {
|
|
1940
2023
|
onError(new Error(errorMessage));
|
|
@@ -1943,297 +2026,157 @@ function ForgotPassword({
|
|
|
1943
2026
|
setLoading(false);
|
|
1944
2027
|
}
|
|
1945
2028
|
}
|
|
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
2029
|
if (!authConfig) {
|
|
1993
2030
|
return null;
|
|
1994
2031
|
}
|
|
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") {
|
|
2032
|
+
if (!token) {
|
|
2013
2033
|
return /* @__PURE__ */ jsxs(AuthContainer, { children: [
|
|
2034
|
+
/* @__PURE__ */ jsx(AuthHeader, { title: "Invalid Reset Link", subtitle: "" }),
|
|
2014
2035
|
/* @__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
2036
|
"div",
|
|
2024
2037
|
{
|
|
2025
2038
|
style: {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
alignItems: "center"
|
|
2039
|
+
padding: "1.5rem",
|
|
2040
|
+
backgroundColor: "#FEE2E2",
|
|
2041
|
+
borderRadius: "0.5rem",
|
|
2042
|
+
border: "1px solid #DC2626"
|
|
2031
2043
|
},
|
|
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
|
-
]
|
|
2044
|
+
children: /* @__PURE__ */ jsx(
|
|
2045
|
+
"p",
|
|
2046
|
+
{
|
|
2047
|
+
style: {
|
|
2048
|
+
fontSize: "0.875rem",
|
|
2049
|
+
color: "#DC2626",
|
|
2050
|
+
margin: 0,
|
|
2051
|
+
fontFamily: "var(--if-font-family)"
|
|
2052
|
+
},
|
|
2053
|
+
children: "The password reset link is missing or invalid. Please request a new password reset link."
|
|
2054
|
+
}
|
|
2055
|
+
)
|
|
2112
2056
|
}
|
|
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" }) })
|
|
2057
|
+
)
|
|
2115
2058
|
] });
|
|
2116
2059
|
}
|
|
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") {
|
|
2060
|
+
if (success) {
|
|
2136
2061
|
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs(
|
|
2137
2062
|
"div",
|
|
2138
2063
|
{
|
|
2139
|
-
style: {
|
|
2140
|
-
width: "100%",
|
|
2141
|
-
display: "flex",
|
|
2142
|
-
flexDirection: "column",
|
|
2143
|
-
alignItems: "center",
|
|
2144
|
-
justifyContent: "center",
|
|
2145
|
-
gap: "1.5rem"
|
|
2146
|
-
},
|
|
2064
|
+
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "1rem" },
|
|
2147
2065
|
children: [
|
|
2148
|
-
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2149
2066
|
/* @__PURE__ */ jsx(
|
|
2150
2067
|
"div",
|
|
2151
2068
|
{
|
|
2152
|
-
className: "if-submitButton-spinner",
|
|
2153
2069
|
style: {
|
|
2070
|
+
width: "4rem",
|
|
2071
|
+
height: "4rem",
|
|
2154
2072
|
borderRadius: "50%",
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2073
|
+
backgroundColor: "#D1FAE5",
|
|
2074
|
+
display: "flex",
|
|
2075
|
+
alignItems: "center",
|
|
2076
|
+
justifyContent: "center"
|
|
2077
|
+
},
|
|
2078
|
+
children: /* @__PURE__ */ jsx(
|
|
2079
|
+
"svg",
|
|
2080
|
+
{
|
|
2081
|
+
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
2082
|
+
fill: "none",
|
|
2083
|
+
strokeLinecap: "round",
|
|
2084
|
+
strokeLinejoin: "round",
|
|
2085
|
+
strokeWidth: "2",
|
|
2086
|
+
viewBox: "0 0 24 24",
|
|
2087
|
+
stroke: "currentColor",
|
|
2088
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2089
|
+
}
|
|
2090
|
+
)
|
|
2091
|
+
}
|
|
2092
|
+
),
|
|
2093
|
+
/* @__PURE__ */ jsx(
|
|
2094
|
+
"h2",
|
|
2095
|
+
{
|
|
2096
|
+
style: {
|
|
2097
|
+
fontSize: "1.5rem",
|
|
2098
|
+
fontWeight: 600,
|
|
2099
|
+
color: "#000",
|
|
2100
|
+
margin: 0,
|
|
2101
|
+
textAlign: "center",
|
|
2102
|
+
fontFamily: "var(--if-font-family)"
|
|
2103
|
+
},
|
|
2104
|
+
children: "Password Reset Successfully"
|
|
2105
|
+
}
|
|
2106
|
+
),
|
|
2107
|
+
/* @__PURE__ */ jsx(
|
|
2108
|
+
"p",
|
|
2109
|
+
{
|
|
2110
|
+
style: {
|
|
2111
|
+
fontSize: "0.875rem",
|
|
2112
|
+
color: "#828282",
|
|
2113
|
+
textAlign: "center",
|
|
2114
|
+
margin: 0,
|
|
2115
|
+
fontFamily: "var(--if-font-family)"
|
|
2116
|
+
},
|
|
2117
|
+
children: "Your password has been reset successfully. You can now close this page and return to the login page in your original tab."
|
|
2159
2118
|
}
|
|
2160
2119
|
)
|
|
2161
2120
|
]
|
|
2162
2121
|
}
|
|
2163
2122
|
) });
|
|
2164
2123
|
}
|
|
2124
|
+
return /* @__PURE__ */ jsx(
|
|
2125
|
+
ResetPasswordForm,
|
|
2126
|
+
{
|
|
2127
|
+
newPassword,
|
|
2128
|
+
confirmPassword,
|
|
2129
|
+
onNewPasswordChange: setNewPassword,
|
|
2130
|
+
onConfirmPasswordChange: setConfirmPassword,
|
|
2131
|
+
onSubmit: handleSubmit,
|
|
2132
|
+
error,
|
|
2133
|
+
loading,
|
|
2134
|
+
success: false,
|
|
2135
|
+
authConfig,
|
|
2136
|
+
...uiProps
|
|
2137
|
+
}
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
function VerifyEmailStatus({
|
|
2141
|
+
status,
|
|
2142
|
+
error,
|
|
2143
|
+
verifyingTitle = "Verifying your email...",
|
|
2144
|
+
successTitle = "Email Verified!",
|
|
2145
|
+
successMessage = "Your email has been verified successfully. You can close this page and sign in to your app.",
|
|
2146
|
+
errorTitle = "Verification Failed"
|
|
2147
|
+
}) {
|
|
2148
|
+
if (status === "verifying") {
|
|
2149
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsxs("div", { className: "if-verifyStatus-container", children: [
|
|
2150
|
+
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2151
|
+
/* @__PURE__ */ jsx("div", { className: "if-submitButton-spinner if-verifyStatus-spinner" })
|
|
2152
|
+
] }) });
|
|
2153
|
+
}
|
|
2165
2154
|
if (status === "error") {
|
|
2166
|
-
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx(
|
|
2167
|
-
"
|
|
2155
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxs("div", { className: "if-authHeader if-internal-h3m7w5", children: [
|
|
2156
|
+
/* @__PURE__ */ jsx("h1", { className: "if-authHeader-title if-internal-t4p1k9", children: errorTitle }),
|
|
2157
|
+
/* @__PURE__ */ jsxs("p", { className: "if-authHeader-subtitle if-internal-s7q2m3", children: [
|
|
2158
|
+
error || "The verification link is invalid or has expired.",
|
|
2159
|
+
" Please try again or contact support if the problem persists. You can close this page and return to your app."
|
|
2160
|
+
] })
|
|
2161
|
+
] }) }) });
|
|
2162
|
+
}
|
|
2163
|
+
return /* @__PURE__ */ jsx(AuthContainer, { children: /* @__PURE__ */ jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxs("div", { className: "if-verifyStatus-successContent", children: [
|
|
2164
|
+
/* @__PURE__ */ jsx("div", { className: "if-verifyStatus-successIcon", children: /* @__PURE__ */ jsx(
|
|
2165
|
+
"svg",
|
|
2168
2166
|
{
|
|
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
|
-
] })
|
|
2167
|
+
className: "if-verifyStatus-successIconSvg",
|
|
2168
|
+
fill: "none",
|
|
2169
|
+
strokeLinecap: "round",
|
|
2170
|
+
strokeLinejoin: "round",
|
|
2171
|
+
strokeWidth: "2",
|
|
2172
|
+
viewBox: "0 0 24 24",
|
|
2173
|
+
stroke: "currentColor",
|
|
2174
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2184
2175
|
}
|
|
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
|
-
) });
|
|
2176
|
+
) }),
|
|
2177
|
+
/* @__PURE__ */ jsx("h2", { className: "if-authHeader-title if-verifyStatus-textCenter", children: successTitle }),
|
|
2178
|
+
/* @__PURE__ */ jsx("p", { className: "if-authHeader-subtitle if-verifyStatus-textCenter", children: successMessage })
|
|
2179
|
+
] }) }) });
|
|
2237
2180
|
}
|
|
2238
2181
|
function VerifyEmail({ token, onSuccess, onError, ...uiProps }) {
|
|
2239
2182
|
const { verifyEmail } = useInsforge();
|
|
@@ -2334,93 +2277,43 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
|
|
|
2334
2277
|
}
|
|
2335
2278
|
const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
|
|
2336
2279
|
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
|
-
);
|
|
2280
|
+
return /* @__PURE__ */ jsxs("div", { className: "if-userButton-container if-internal-ub3k8p", ref: dropdownRef, children: [
|
|
2281
|
+
/* @__PURE__ */ jsxs(
|
|
2282
|
+
"button",
|
|
2283
|
+
{
|
|
2284
|
+
className: buttonClassName,
|
|
2285
|
+
onClick: () => setIsOpen(!isOpen),
|
|
2286
|
+
"aria-expanded": isOpen,
|
|
2287
|
+
"aria-haspopup": "true",
|
|
2288
|
+
children: [
|
|
2289
|
+
/* @__PURE__ */ jsx("div", { className: "if-userButton-avatar", children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
|
|
2290
|
+
"img",
|
|
2291
|
+
{
|
|
2292
|
+
src: user.avatarUrl,
|
|
2293
|
+
alt: user.email,
|
|
2294
|
+
onError: () => setImageError(true),
|
|
2295
|
+
className: "if-userButton-avatarImage"
|
|
2296
|
+
}
|
|
2297
|
+
) : /* @__PURE__ */ jsx("span", { className: "if-userButton-avatarInitials", children: initials }) }),
|
|
2298
|
+
mode === "detailed" && /* @__PURE__ */ jsxs("div", { className: "if-userButton-info", children: [
|
|
2299
|
+
user.name && /* @__PURE__ */ jsx("div", { className: "if-userButton-name", children: user.name }),
|
|
2300
|
+
/* @__PURE__ */ jsx("div", { className: "if-userButton-email", children: user.email })
|
|
2301
|
+
] })
|
|
2302
|
+
]
|
|
2303
|
+
}
|
|
2304
|
+
),
|
|
2305
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxs(
|
|
2306
|
+
"button",
|
|
2307
|
+
{
|
|
2308
|
+
onClick: handleSignOut,
|
|
2309
|
+
className: "if-userButton-menuItem if-userButton-menuItem-signout",
|
|
2310
|
+
children: [
|
|
2311
|
+
/* @__PURE__ */ jsx(LogOut, { className: "if-userButton-menuItem-icon" }),
|
|
2312
|
+
"Sign out"
|
|
2313
|
+
]
|
|
2314
|
+
}
|
|
2315
|
+
) })
|
|
2316
|
+
] });
|
|
2424
2317
|
}
|
|
2425
2318
|
function Protect({
|
|
2426
2319
|
children,
|
|
@@ -2478,94 +2371,6 @@ function SignedOut({ children }) {
|
|
|
2478
2371
|
}
|
|
2479
2372
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
2480
2373
|
}
|
|
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
2374
|
|
|
2570
2375
|
// src/hooks/useAuth.ts
|
|
2571
2376
|
function useAuth() {
|
|
@@ -2580,9 +2385,9 @@ function useUser() {
|
|
|
2580
2385
|
}
|
|
2581
2386
|
function RedirectToAuth({ baseUrl, path }) {
|
|
2582
2387
|
useEffect(() => {
|
|
2583
|
-
const
|
|
2388
|
+
const currentUrl = window.location.href;
|
|
2584
2389
|
const authUrl = new URL(path, baseUrl);
|
|
2585
|
-
authUrl.searchParams.set("redirect",
|
|
2390
|
+
authUrl.searchParams.set("redirect", currentUrl);
|
|
2586
2391
|
window.location.replace(authUrl.toString());
|
|
2587
2392
|
}, [baseUrl, path]);
|
|
2588
2393
|
return null;
|
|
@@ -2624,6 +2429,6 @@ function getInsforgeRoutes(config) {
|
|
|
2624
2429
|
return routes;
|
|
2625
2430
|
}
|
|
2626
2431
|
|
|
2627
|
-
export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm,
|
|
2432
|
+
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
2433
|
//# sourceMappingURL=index.js.map
|
|
2629
2434
|
//# sourceMappingURL=index.js.map
|