@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.cjs
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
|
}
|
|
@@ -15,6 +15,7 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
var react = require('react');
|
|
18
|
+
var reactRouterDom = require('react-router-dom');
|
|
18
19
|
var sdk = require('@insforge/sdk');
|
|
19
20
|
var jsxRuntime = require('react/jsx-runtime');
|
|
20
21
|
var lucideReact = require('lucide-react');
|
|
@@ -24,13 +25,15 @@ var InsforgeContext = react.createContext(void 0);
|
|
|
24
25
|
function InsforgeProvider({
|
|
25
26
|
children,
|
|
26
27
|
baseUrl,
|
|
28
|
+
afterSignInUrl = "/",
|
|
27
29
|
onAuthChange,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
onSignIn,
|
|
31
|
+
onSignOut
|
|
30
32
|
}) {
|
|
31
33
|
const [user, setUser] = react.useState(null);
|
|
32
34
|
const [isLoaded, setIsLoaded] = react.useState(false);
|
|
33
35
|
const refreshIntervalRef = react.useRef(null);
|
|
36
|
+
const hasProcessedCallbackRef = react.useRef(false);
|
|
34
37
|
const [insforge] = react.useState(() => sdk.createClient({ baseUrl }));
|
|
35
38
|
const loadAuthState = react.useCallback(async () => {
|
|
36
39
|
try {
|
|
@@ -62,9 +65,9 @@ function InsforgeProvider({
|
|
|
62
65
|
return { success: true };
|
|
63
66
|
} else {
|
|
64
67
|
await insforge.auth.signOut();
|
|
65
|
-
if (
|
|
68
|
+
if (onSignOut) {
|
|
66
69
|
try {
|
|
67
|
-
await
|
|
70
|
+
await onSignOut();
|
|
68
71
|
} catch (error) {
|
|
69
72
|
if (error instanceof Error) {
|
|
70
73
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -81,9 +84,9 @@ function InsforgeProvider({
|
|
|
81
84
|
} catch (error) {
|
|
82
85
|
console.error("[InsforgeProvider] Token validation failed:", error);
|
|
83
86
|
await insforge.auth.signOut();
|
|
84
|
-
if (
|
|
87
|
+
if (onSignOut) {
|
|
85
88
|
try {
|
|
86
|
-
await
|
|
89
|
+
await onSignOut();
|
|
87
90
|
} catch (error2) {
|
|
88
91
|
if (error2 instanceof Error) {
|
|
89
92
|
console.error("[InsforgeProvider] Error clearing cookie:", error2.message);
|
|
@@ -100,7 +103,7 @@ function InsforgeProvider({
|
|
|
100
103
|
error: error instanceof Error ? error.message : "Authentication failed"
|
|
101
104
|
};
|
|
102
105
|
}
|
|
103
|
-
}, [insforge, onAuthChange,
|
|
106
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
104
107
|
react.useEffect(() => {
|
|
105
108
|
loadAuthState();
|
|
106
109
|
const intervalId = refreshIntervalRef.current;
|
|
@@ -110,6 +113,22 @@ function InsforgeProvider({
|
|
|
110
113
|
}
|
|
111
114
|
};
|
|
112
115
|
}, [loadAuthState]);
|
|
116
|
+
react.useEffect(() => {
|
|
117
|
+
if (!isLoaded || hasProcessedCallbackRef.current) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
121
|
+
const accessToken = searchParams.get("access_token");
|
|
122
|
+
if (accessToken && !!user) {
|
|
123
|
+
hasProcessedCallbackRef.current = true;
|
|
124
|
+
const url = new URL(window.location.href);
|
|
125
|
+
url.search = "";
|
|
126
|
+
window.history.replaceState({}, "", url.toString());
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
window.location.href = afterSignInUrl;
|
|
129
|
+
}, 100);
|
|
130
|
+
}
|
|
131
|
+
}, [isLoaded, user, afterSignInUrl]);
|
|
113
132
|
const getPublicAuthConfig = react.useCallback(async () => {
|
|
114
133
|
try {
|
|
115
134
|
const result = await insforge.auth.getPublicAuthConfig();
|
|
@@ -139,9 +158,9 @@ function InsforgeProvider({
|
|
|
139
158
|
if (onAuthChange) {
|
|
140
159
|
onAuthChange(userData);
|
|
141
160
|
}
|
|
142
|
-
if (
|
|
161
|
+
if (onSignIn) {
|
|
143
162
|
try {
|
|
144
|
-
await
|
|
163
|
+
await onSignIn(authToken);
|
|
145
164
|
} catch (error) {
|
|
146
165
|
if (error instanceof Error) {
|
|
147
166
|
console.error("[InsforgeProvider] Error syncing token to cookie:", error.message);
|
|
@@ -161,7 +180,7 @@ function InsforgeProvider({
|
|
|
161
180
|
}
|
|
162
181
|
}
|
|
163
182
|
},
|
|
164
|
-
[insforge, onAuthChange,
|
|
183
|
+
[insforge, onAuthChange, onSignIn]
|
|
165
184
|
);
|
|
166
185
|
const signIn = react.useCallback(
|
|
167
186
|
async (email, password) => {
|
|
@@ -216,9 +235,9 @@ function InsforgeProvider({
|
|
|
216
235
|
);
|
|
217
236
|
const signOut = react.useCallback(async () => {
|
|
218
237
|
await insforge.auth.signOut();
|
|
219
|
-
if (
|
|
238
|
+
if (onSignOut) {
|
|
220
239
|
try {
|
|
221
|
-
await
|
|
240
|
+
await onSignOut();
|
|
222
241
|
} catch (error) {
|
|
223
242
|
if (error instanceof Error) {
|
|
224
243
|
console.error("[InsforgeProvider] Error clearing cookie:", error.message);
|
|
@@ -232,7 +251,7 @@ function InsforgeProvider({
|
|
|
232
251
|
if (onAuthChange) {
|
|
233
252
|
onAuthChange(null);
|
|
234
253
|
}
|
|
235
|
-
}, [insforge, onAuthChange,
|
|
254
|
+
}, [insforge, onAuthChange, onSignOut]);
|
|
236
255
|
const updateUser = react.useCallback(
|
|
237
256
|
async (data) => {
|
|
238
257
|
if (!user) {
|
|
@@ -262,6 +281,13 @@ function InsforgeProvider({
|
|
|
262
281
|
},
|
|
263
282
|
[user, onAuthChange, insforge]
|
|
264
283
|
);
|
|
284
|
+
const sendVerificationEmail = react.useCallback(
|
|
285
|
+
async (email) => {
|
|
286
|
+
const sdkResult = await insforge.auth.sendVerificationEmail({ email });
|
|
287
|
+
return sdkResult.data;
|
|
288
|
+
},
|
|
289
|
+
[insforge]
|
|
290
|
+
);
|
|
265
291
|
const sendResetPasswordEmail = react.useCallback(
|
|
266
292
|
async (email) => {
|
|
267
293
|
const sdkResult = await insforge.auth.sendResetPasswordEmail({ email });
|
|
@@ -280,8 +306,39 @@ function InsforgeProvider({
|
|
|
280
306
|
[insforge]
|
|
281
307
|
);
|
|
282
308
|
const verifyEmail = react.useCallback(
|
|
283
|
-
async (
|
|
284
|
-
const sdkResult = await insforge.auth.verifyEmail({ otp:
|
|
309
|
+
async (otp, email) => {
|
|
310
|
+
const sdkResult = await insforge.auth.verifyEmail({ otp, email: email || void 0 });
|
|
311
|
+
if (sdkResult.data) {
|
|
312
|
+
return sdkResult.data;
|
|
313
|
+
} else {
|
|
314
|
+
return {
|
|
315
|
+
accessToken: "",
|
|
316
|
+
error: {
|
|
317
|
+
message: sdkResult.error?.message || "Email verification failed"
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
[insforge]
|
|
323
|
+
);
|
|
324
|
+
const exchangeResetPasswordToken = react.useCallback(
|
|
325
|
+
async (email, code) => {
|
|
326
|
+
const sdkResult = await insforge.auth.exchangeResetPasswordToken({ email, code });
|
|
327
|
+
if (sdkResult.data) {
|
|
328
|
+
return sdkResult.data;
|
|
329
|
+
} else {
|
|
330
|
+
return {
|
|
331
|
+
error: {
|
|
332
|
+
message: sdkResult.error?.message || "Failed to exchange reset password token"
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
[insforge]
|
|
338
|
+
);
|
|
339
|
+
const loginWithOAuth = react.useCallback(
|
|
340
|
+
async (provider, redirectTo) => {
|
|
341
|
+
const sdkResult = await insforge.auth.signInWithOAuth({ provider, redirectTo });
|
|
285
342
|
return sdkResult.data;
|
|
286
343
|
},
|
|
287
344
|
[insforge]
|
|
@@ -300,10 +357,13 @@ function InsforgeProvider({
|
|
|
300
357
|
updateUser,
|
|
301
358
|
reloadAuth: loadAuthState,
|
|
302
359
|
baseUrl,
|
|
360
|
+
sendVerificationEmail,
|
|
303
361
|
sendResetPasswordEmail,
|
|
304
362
|
resetPassword,
|
|
305
363
|
verifyEmail,
|
|
306
|
-
|
|
364
|
+
exchangeResetPasswordToken,
|
|
365
|
+
getPublicAuthConfig,
|
|
366
|
+
loginWithOAuth
|
|
307
367
|
},
|
|
308
368
|
children
|
|
309
369
|
}
|
|
@@ -421,21 +481,12 @@ function AuthErrorBanner({ error }) {
|
|
|
421
481
|
if (!error) {
|
|
422
482
|
return null;
|
|
423
483
|
}
|
|
424
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
425
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
426
|
-
lucideReact.AlertTriangle,
|
|
427
|
-
{
|
|
428
|
-
style: { width: "1.5rem", height: "1.5rem", flexShrink: 0, color: "#dc2626" }
|
|
429
|
-
}
|
|
430
|
-
),
|
|
484
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-errorBanner-content", children: [
|
|
485
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "if-errorBanner-icon" }),
|
|
431
486
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "if-errorBanner-text", children: error })
|
|
432
487
|
] }) });
|
|
433
488
|
}
|
|
434
|
-
function AuthFormField({
|
|
435
|
-
label,
|
|
436
|
-
id,
|
|
437
|
-
...props
|
|
438
|
-
}) {
|
|
489
|
+
function AuthFormField({ label, id, ...props }) {
|
|
439
490
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-formField if-internal-f9n6p2", children: [
|
|
440
491
|
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "if-formField-label if-internal-l3k8m1", children: label }),
|
|
441
492
|
/* @__PURE__ */ jsxRuntime.jsx("input", { id, className: "if-formField-input if-internal-i2v8k4", ...props })
|
|
@@ -562,14 +613,17 @@ function AuthSubmitButton({
|
|
|
562
613
|
children,
|
|
563
614
|
isLoading = false,
|
|
564
615
|
confirmed = false,
|
|
565
|
-
disabled = false
|
|
616
|
+
disabled = false,
|
|
617
|
+
type = "submit",
|
|
618
|
+
onClick
|
|
566
619
|
}) {
|
|
567
620
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
568
621
|
"button",
|
|
569
622
|
{
|
|
570
|
-
type
|
|
623
|
+
type,
|
|
571
624
|
className: "if-submitButton if-internal-b8p3m4",
|
|
572
625
|
disabled: disabled || isLoading || confirmed,
|
|
626
|
+
onClick,
|
|
573
627
|
children: [
|
|
574
628
|
isLoading && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "if-submitButton-icon if-submitButton-spinner", size: 20 }),
|
|
575
629
|
confirmed && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, { className: "if-submitButton-icon", size: 20 }),
|
|
@@ -578,24 +632,16 @@ function AuthSubmitButton({
|
|
|
578
632
|
}
|
|
579
633
|
);
|
|
580
634
|
}
|
|
581
|
-
function AuthLink({
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
href
|
|
585
|
-
}) {
|
|
586
|
-
const currentSearch = typeof window !== "undefined" ? window.location.search : "";
|
|
635
|
+
function AuthLink({ text, linkText, href }) {
|
|
636
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
637
|
+
const currentSearch = searchParams.toString();
|
|
587
638
|
const finalHref = (() => {
|
|
588
639
|
if (!currentSearch) {
|
|
589
640
|
return href;
|
|
590
641
|
}
|
|
591
642
|
try {
|
|
592
643
|
const url = new URL(href, window.location.origin);
|
|
593
|
-
|
|
594
|
-
currentParams.forEach((value, key) => {
|
|
595
|
-
if (!url.searchParams.has(key)) {
|
|
596
|
-
url.searchParams.set(key, value);
|
|
597
|
-
}
|
|
598
|
-
});
|
|
644
|
+
url.search = currentSearch;
|
|
599
645
|
return url.pathname + url.search;
|
|
600
646
|
} catch {
|
|
601
647
|
return href;
|
|
@@ -955,28 +1001,26 @@ function AuthVerificationCodeInput({
|
|
|
955
1001
|
}
|
|
956
1002
|
function AuthEmailVerificationStep({
|
|
957
1003
|
email,
|
|
958
|
-
description,
|
|
959
1004
|
method = "code",
|
|
960
1005
|
onVerifyCode
|
|
961
1006
|
}) {
|
|
962
|
-
const {
|
|
963
|
-
const [insforge] = react.useState(() => sdk.createClient({ baseUrl }));
|
|
1007
|
+
const { sendVerificationEmail } = useInsforge();
|
|
964
1008
|
const [resendDisabled, setResendDisabled] = react.useState(true);
|
|
965
1009
|
const [resendCountdown, setResendCountdown] = react.useState(60);
|
|
966
1010
|
const [isSending, setIsSending] = react.useState(false);
|
|
967
1011
|
const [verificationCode, setVerificationCode] = react.useState("");
|
|
968
1012
|
const [isVerifying, setIsVerifying] = react.useState(false);
|
|
969
|
-
const [verificationError, setVerificationError] = react.useState("");
|
|
970
1013
|
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.";
|
|
971
1014
|
react.useEffect(() => {
|
|
972
1015
|
const sendInitialEmail = async () => {
|
|
973
1016
|
try {
|
|
974
|
-
await
|
|
975
|
-
} catch {
|
|
1017
|
+
await sendVerificationEmail(email);
|
|
1018
|
+
} catch (error) {
|
|
1019
|
+
console.error("Failed to send verification email:", error);
|
|
976
1020
|
}
|
|
977
1021
|
};
|
|
978
1022
|
void sendInitialEmail();
|
|
979
|
-
}, [email,
|
|
1023
|
+
}, [email, sendVerificationEmail]);
|
|
980
1024
|
react.useEffect(() => {
|
|
981
1025
|
if (resendCountdown > 0) {
|
|
982
1026
|
const timer = setInterval(() => {
|
|
@@ -995,9 +1039,8 @@ function AuthEmailVerificationStep({
|
|
|
995
1039
|
setResendDisabled(true);
|
|
996
1040
|
setResendCountdown(60);
|
|
997
1041
|
setIsSending(true);
|
|
998
|
-
setVerificationError("");
|
|
999
1042
|
try {
|
|
1000
|
-
await
|
|
1043
|
+
await sendVerificationEmail(email);
|
|
1001
1044
|
} catch {
|
|
1002
1045
|
setResendDisabled(false);
|
|
1003
1046
|
setResendCountdown(0);
|
|
@@ -1005,123 +1048,157 @@ function AuthEmailVerificationStep({
|
|
|
1005
1048
|
setIsSending(false);
|
|
1006
1049
|
}
|
|
1007
1050
|
};
|
|
1008
|
-
const
|
|
1009
|
-
if (!onVerifyCode) {
|
|
1051
|
+
const handleSubmit = async () => {
|
|
1052
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1010
1053
|
return;
|
|
1011
1054
|
}
|
|
1012
1055
|
setIsVerifying(true);
|
|
1013
|
-
setVerificationError("");
|
|
1014
1056
|
try {
|
|
1015
|
-
await onVerifyCode(
|
|
1016
|
-
} catch (error) {
|
|
1017
|
-
setVerificationError(
|
|
1018
|
-
error instanceof Error ? error.message : "Invalid verification code. Please try again."
|
|
1019
|
-
);
|
|
1020
|
-
setVerificationCode("");
|
|
1057
|
+
await onVerifyCode(verificationCode);
|
|
1021
1058
|
} finally {
|
|
1022
1059
|
setIsVerifying(false);
|
|
1060
|
+
setVerificationCode("");
|
|
1023
1061
|
}
|
|
1024
1062
|
};
|
|
1025
|
-
const displayDescription =
|
|
1026
|
-
|
|
1027
|
-
|
|
1063
|
+
const displayDescription = defaultDescription;
|
|
1064
|
+
const isLinkMethod = method === "link";
|
|
1065
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep", children: [
|
|
1066
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1028
1067
|
part,
|
|
1029
1068
|
index < array.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "if-verificationCode-email", children: email })
|
|
1030
1069
|
] }, index)) }),
|
|
1031
|
-
|
|
1070
|
+
!isLinkMethod && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1071
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1072
|
+
AuthVerificationCodeInput,
|
|
1073
|
+
{
|
|
1074
|
+
value: verificationCode,
|
|
1075
|
+
onChange: setVerificationCode,
|
|
1076
|
+
email,
|
|
1077
|
+
disabled: isVerifying
|
|
1078
|
+
}
|
|
1079
|
+
) }),
|
|
1032
1080
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1033
|
-
|
|
1081
|
+
AuthSubmitButton,
|
|
1034
1082
|
{
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
children: /* @__PURE__ */ jsxRuntime.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" })
|
|
1083
|
+
type: "button",
|
|
1084
|
+
isLoading: isVerifying,
|
|
1085
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1086
|
+
onClick: () => {
|
|
1087
|
+
void handleSubmit();
|
|
1088
|
+
},
|
|
1089
|
+
children: isVerifying ? "Verifying..." : "Verify Code"
|
|
1043
1090
|
}
|
|
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
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1091
|
+
)
|
|
1092
|
+
] }),
|
|
1093
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1094
|
+
"Didn't receive the email?",
|
|
1095
|
+
" ",
|
|
1096
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1097
|
+
"button",
|
|
1098
|
+
{
|
|
1099
|
+
onClick: () => {
|
|
1100
|
+
void handleResend();
|
|
1101
|
+
},
|
|
1102
|
+
disabled: resendDisabled || isSending,
|
|
1103
|
+
className: "if-verificationStep-resendButton",
|
|
1104
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1105
|
+
}
|
|
1106
|
+
)
|
|
1107
|
+
] })
|
|
1108
|
+
] });
|
|
1109
|
+
}
|
|
1110
|
+
function AuthResetPasswordVerificationStep({
|
|
1111
|
+
email,
|
|
1112
|
+
method,
|
|
1113
|
+
onVerifyCode,
|
|
1114
|
+
onResendEmail
|
|
1115
|
+
}) {
|
|
1116
|
+
const [resendDisabled, setResendDisabled] = react.useState(true);
|
|
1117
|
+
const [resendCountdown, setResendCountdown] = react.useState(60);
|
|
1118
|
+
const [isSending, setIsSending] = react.useState(false);
|
|
1119
|
+
const [verificationCode, setVerificationCode] = react.useState("");
|
|
1120
|
+
const [isVerifying, setIsVerifying] = react.useState(false);
|
|
1121
|
+
react.useEffect(() => {
|
|
1122
|
+
if (resendCountdown > 0) {
|
|
1123
|
+
const timer = setInterval(() => {
|
|
1124
|
+
setResendCountdown((prev) => {
|
|
1125
|
+
if (prev <= 1) {
|
|
1126
|
+
setResendDisabled(false);
|
|
1127
|
+
return 0;
|
|
1128
|
+
}
|
|
1129
|
+
return prev - 1;
|
|
1130
|
+
});
|
|
1131
|
+
}, 1e3);
|
|
1132
|
+
return () => clearInterval(timer);
|
|
1133
|
+
}
|
|
1134
|
+
}, [resendCountdown]);
|
|
1135
|
+
const handleResend = react.useCallback(async () => {
|
|
1136
|
+
setResendDisabled(true);
|
|
1137
|
+
setResendCountdown(60);
|
|
1138
|
+
setIsSending(true);
|
|
1139
|
+
try {
|
|
1140
|
+
await onResendEmail();
|
|
1141
|
+
} catch {
|
|
1142
|
+
setResendDisabled(false);
|
|
1143
|
+
setResendCountdown(0);
|
|
1144
|
+
} finally {
|
|
1145
|
+
setIsSending(false);
|
|
1146
|
+
}
|
|
1147
|
+
}, [onResendEmail]);
|
|
1148
|
+
const handleSubmit = async () => {
|
|
1149
|
+
if (!onVerifyCode || verificationCode.length !== 6) {
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
setIsVerifying(true);
|
|
1153
|
+
try {
|
|
1154
|
+
await onVerifyCode(verificationCode);
|
|
1155
|
+
} finally {
|
|
1156
|
+
setIsVerifying(false);
|
|
1157
|
+
setVerificationCode("");
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
const isLinkMethod = method === "link";
|
|
1161
|
+
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.`;
|
|
1162
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep", children: [
|
|
1163
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-verificationStep-description", children: description }),
|
|
1164
|
+
!isLinkMethod && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep-codeContainer", children: [
|
|
1165
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1166
|
+
AuthVerificationCodeInput,
|
|
1167
|
+
{
|
|
1168
|
+
value: verificationCode,
|
|
1169
|
+
onChange: setVerificationCode,
|
|
1170
|
+
email,
|
|
1171
|
+
disabled: isVerifying
|
|
1172
|
+
}
|
|
1173
|
+
) }),
|
|
1174
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1175
|
+
AuthSubmitButton,
|
|
1176
|
+
{
|
|
1177
|
+
type: "button",
|
|
1178
|
+
isLoading: isVerifying,
|
|
1179
|
+
disabled: isVerifying || verificationCode.length !== 6,
|
|
1180
|
+
onClick: () => {
|
|
1181
|
+
void handleSubmit();
|
|
1182
|
+
},
|
|
1183
|
+
children: isVerifying ? "Verifying..." : "Continue"
|
|
1184
|
+
}
|
|
1185
|
+
)
|
|
1186
|
+
] }),
|
|
1187
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verificationStep-resendContainer", children: [
|
|
1188
|
+
"Didn't receive the email?",
|
|
1189
|
+
" ",
|
|
1190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1191
|
+
"button",
|
|
1192
|
+
{
|
|
1193
|
+
onClick: () => {
|
|
1194
|
+
void handleResend();
|
|
1195
|
+
},
|
|
1196
|
+
disabled: resendDisabled || isSending,
|
|
1197
|
+
className: "if-verificationStep-resendButton",
|
|
1198
|
+
children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
1199
|
+
}
|
|
1200
|
+
)
|
|
1201
|
+
] })
|
|
1125
1202
|
] });
|
|
1126
1203
|
}
|
|
1127
1204
|
function SignInForm({
|
|
@@ -1151,8 +1228,7 @@ function SignInForm({
|
|
|
1151
1228
|
signUpUrl = "/sign-up",
|
|
1152
1229
|
dividerText = "or",
|
|
1153
1230
|
showVerificationStep = false,
|
|
1154
|
-
onVerifyCode
|
|
1155
|
-
verificationDescription
|
|
1231
|
+
onVerifyCode
|
|
1156
1232
|
}) {
|
|
1157
1233
|
return /* @__PURE__ */ jsxRuntime.jsxs(AuthContainer, { children: [
|
|
1158
1234
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1163,14 +1239,7 @@ function SignInForm({
|
|
|
1163
1239
|
}
|
|
1164
1240
|
),
|
|
1165
1241
|
/* @__PURE__ */ jsxRuntime.jsx(AuthErrorBanner, { error: error || "" }),
|
|
1166
|
-
showVerificationStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1167
|
-
AuthEmailVerificationStep,
|
|
1168
|
-
{
|
|
1169
|
-
email,
|
|
1170
|
-
description: verificationDescription,
|
|
1171
|
-
onVerifyCode
|
|
1172
|
-
}
|
|
1173
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1242
|
+
showVerificationStep ? /* @__PURE__ */ jsxRuntime.jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1174
1243
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1175
1244
|
AuthFormField,
|
|
1176
1245
|
{
|
|
@@ -1220,16 +1289,17 @@ function SignInForm({
|
|
|
1220
1289
|
] })
|
|
1221
1290
|
] });
|
|
1222
1291
|
}
|
|
1223
|
-
function SignIn({
|
|
1224
|
-
const { signIn,
|
|
1292
|
+
function SignIn({ onError, ...uiProps }) {
|
|
1293
|
+
const { signIn, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1225
1294
|
const { authConfig } = usePublicAuthConfig();
|
|
1226
1295
|
const [email, setEmail] = react.useState("");
|
|
1227
1296
|
const [password, setPassword] = react.useState("");
|
|
1228
1297
|
const [error, setError] = react.useState("");
|
|
1229
1298
|
const [loading, setLoading] = react.useState(false);
|
|
1230
1299
|
const [step, setStep] = react.useState("form");
|
|
1231
|
-
const [oauthLoading
|
|
1232
|
-
const [
|
|
1300
|
+
const [oauthLoading] = react.useState(null);
|
|
1301
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
1302
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1233
1303
|
async function handleSubmit(e) {
|
|
1234
1304
|
e.preventDefault();
|
|
1235
1305
|
setLoading(true);
|
|
@@ -1245,10 +1315,13 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1245
1315
|
throw new Error(result.error);
|
|
1246
1316
|
}
|
|
1247
1317
|
const { user, accessToken, redirectTo } = result;
|
|
1248
|
-
if (
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1318
|
+
if (user) {
|
|
1319
|
+
const finalUrl = new URL(redirectTo || redirectUrl || "", window.location.origin);
|
|
1320
|
+
finalUrl.searchParams.set("access_token", accessToken);
|
|
1321
|
+
finalUrl.searchParams.set("user_id", user.id);
|
|
1322
|
+
finalUrl.searchParams.set("email", user.email);
|
|
1323
|
+
finalUrl.searchParams.set("name", user.name);
|
|
1324
|
+
window.location.href = finalUrl.toString();
|
|
1252
1325
|
}
|
|
1253
1326
|
} catch (err) {
|
|
1254
1327
|
const errorMessage = err instanceof Error ? err.message : "Sign in failed";
|
|
@@ -1261,38 +1334,28 @@ function SignIn({ afterSignInUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1261
1334
|
}
|
|
1262
1335
|
}
|
|
1263
1336
|
async function handleVerifyCode(code) {
|
|
1337
|
+
setError("");
|
|
1264
1338
|
try {
|
|
1265
|
-
const result = await
|
|
1266
|
-
if (result
|
|
1339
|
+
const result = await verifyEmail(email, code);
|
|
1340
|
+
if (result?.error) {
|
|
1267
1341
|
throw new Error(result.error.message || "Verification failed");
|
|
1268
1342
|
}
|
|
1269
|
-
if (result
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1343
|
+
if (result?.user) {
|
|
1344
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1345
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1346
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1347
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1348
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1349
|
+
window.location.href = finalUrl.toString();
|
|
1273
1350
|
}
|
|
1274
1351
|
} catch (err) {
|
|
1275
1352
|
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1276
|
-
throw new Error(errorMessage);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
async function handleOAuth(provider) {
|
|
1280
|
-
try {
|
|
1281
|
-
setOauthLoading(provider);
|
|
1282
|
-
setError("");
|
|
1283
|
-
await insforge.auth.signInWithOAuth({
|
|
1284
|
-
provider,
|
|
1285
|
-
redirectTo: afterSignInUrl
|
|
1286
|
-
});
|
|
1287
|
-
} catch (err) {
|
|
1288
|
-
const errorMessage = err instanceof Error ? err.message : `${provider} sign in failed`;
|
|
1289
1353
|
setError(errorMessage);
|
|
1290
|
-
if (onError) {
|
|
1291
|
-
onError(new Error(errorMessage));
|
|
1292
|
-
}
|
|
1293
|
-
setOauthLoading(null);
|
|
1294
1354
|
}
|
|
1295
1355
|
}
|
|
1356
|
+
function handleOAuth(provider) {
|
|
1357
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1358
|
+
}
|
|
1296
1359
|
if (!authConfig) {
|
|
1297
1360
|
return null;
|
|
1298
1361
|
}
|
|
@@ -1341,8 +1404,7 @@ function SignUpForm({
|
|
|
1341
1404
|
signInUrl = "/sign-in",
|
|
1342
1405
|
dividerText = "or",
|
|
1343
1406
|
showVerificationStep = false,
|
|
1344
|
-
onVerifyCode
|
|
1345
|
-
verificationDescription
|
|
1407
|
+
onVerifyCode
|
|
1346
1408
|
}) {
|
|
1347
1409
|
return /* @__PURE__ */ jsxRuntime.jsxs(AuthContainer, { children: [
|
|
1348
1410
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1353,14 +1415,7 @@ function SignUpForm({
|
|
|
1353
1415
|
}
|
|
1354
1416
|
),
|
|
1355
1417
|
/* @__PURE__ */ jsxRuntime.jsx(AuthErrorBanner, { error: error || "" }),
|
|
1356
|
-
showVerificationStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1357
|
-
AuthEmailVerificationStep,
|
|
1358
|
-
{
|
|
1359
|
-
email,
|
|
1360
|
-
description: verificationDescription,
|
|
1361
|
-
onVerifyCode
|
|
1362
|
-
}
|
|
1363
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1418
|
+
showVerificationStep ? /* @__PURE__ */ jsxRuntime.jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1364
1419
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1365
1420
|
AuthFormField,
|
|
1366
1421
|
{
|
|
@@ -1479,16 +1534,17 @@ function checkPasswordStrength(password) {
|
|
|
1479
1534
|
}
|
|
1480
1535
|
return { score, feedback };
|
|
1481
1536
|
}
|
|
1482
|
-
function SignUp({
|
|
1483
|
-
const { signUp,
|
|
1537
|
+
function SignUp({ onError, ...uiProps }) {
|
|
1538
|
+
const { signUp, verifyEmail, loginWithOAuth } = useInsforge();
|
|
1484
1539
|
const { authConfig } = usePublicAuthConfig();
|
|
1485
1540
|
const [email, setEmail] = react.useState("");
|
|
1486
1541
|
const [password, setPassword] = react.useState("");
|
|
1487
1542
|
const [error, setError] = react.useState("");
|
|
1488
1543
|
const [loading, setLoading] = react.useState(false);
|
|
1489
1544
|
const [step, setStep] = react.useState("form");
|
|
1490
|
-
const [oauthLoading
|
|
1491
|
-
const [
|
|
1545
|
+
const [oauthLoading] = react.useState(null);
|
|
1546
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
1547
|
+
const redirectUrl = searchParams.get("redirect");
|
|
1492
1548
|
async function handleSubmit(e) {
|
|
1493
1549
|
e.preventDefault();
|
|
1494
1550
|
setLoading(true);
|
|
@@ -1530,9 +1586,12 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1530
1586
|
return;
|
|
1531
1587
|
}
|
|
1532
1588
|
if (result.accessToken && result.user) {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1589
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1590
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1591
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1592
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1593
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1594
|
+
window.location.href = finalUrl.toString();
|
|
1536
1595
|
}
|
|
1537
1596
|
} catch (err) {
|
|
1538
1597
|
const errorMessage = err instanceof Error ? err.message : "Sign up failed";
|
|
@@ -1545,38 +1604,28 @@ function SignUp({ afterSignUpUrl, onSuccess, onError, ...uiProps }) {
|
|
|
1545
1604
|
}
|
|
1546
1605
|
}
|
|
1547
1606
|
async function handleVerifyCode(code) {
|
|
1607
|
+
setError("");
|
|
1548
1608
|
try {
|
|
1549
|
-
const result = await
|
|
1550
|
-
if (result
|
|
1609
|
+
const result = await verifyEmail(email, code);
|
|
1610
|
+
if (result?.error) {
|
|
1551
1611
|
throw new Error(result.error.message || "Verification failed");
|
|
1552
1612
|
}
|
|
1553
|
-
if (result
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1613
|
+
if (result?.user) {
|
|
1614
|
+
const finalUrl = new URL(result.redirectTo || redirectUrl || "", window.location.origin);
|
|
1615
|
+
finalUrl.searchParams.set("access_token", result.accessToken);
|
|
1616
|
+
finalUrl.searchParams.set("user_id", result.user.id);
|
|
1617
|
+
finalUrl.searchParams.set("email", result.user.email);
|
|
1618
|
+
finalUrl.searchParams.set("name", result.user.name);
|
|
1619
|
+
window.location.href = finalUrl.toString();
|
|
1557
1620
|
}
|
|
1558
1621
|
} catch (err) {
|
|
1559
1622
|
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1560
|
-
throw new Error(errorMessage);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
async function handleOAuth(provider) {
|
|
1564
|
-
try {
|
|
1565
|
-
setOauthLoading(provider);
|
|
1566
|
-
setError("");
|
|
1567
|
-
await insforge.auth.signInWithOAuth({
|
|
1568
|
-
provider,
|
|
1569
|
-
redirectTo: afterSignUpUrl
|
|
1570
|
-
});
|
|
1571
|
-
} catch (err) {
|
|
1572
|
-
const errorMessage = err instanceof Error ? err.message : `${provider} sign up failed`;
|
|
1573
1623
|
setError(errorMessage);
|
|
1574
|
-
if (onError) {
|
|
1575
|
-
onError(new Error(errorMessage));
|
|
1576
|
-
}
|
|
1577
|
-
setOauthLoading(null);
|
|
1578
1624
|
}
|
|
1579
1625
|
}
|
|
1626
|
+
function handleOAuth(provider) {
|
|
1627
|
+
loginWithOAuth(provider, redirectUrl || "");
|
|
1628
|
+
}
|
|
1580
1629
|
if (!authConfig) {
|
|
1581
1630
|
return null;
|
|
1582
1631
|
}
|
|
@@ -1606,7 +1655,6 @@ function ForgotPasswordForm({
|
|
|
1606
1655
|
onSubmit,
|
|
1607
1656
|
error,
|
|
1608
1657
|
loading = false,
|
|
1609
|
-
success = false,
|
|
1610
1658
|
title = "Forgot Password?",
|
|
1611
1659
|
subtitle = "Enter your email address and we'll send you a code to reset your password.",
|
|
1612
1660
|
emailLabel = "Email",
|
|
@@ -1615,53 +1663,30 @@ function ForgotPasswordForm({
|
|
|
1615
1663
|
loadingButtonText = "Sending...",
|
|
1616
1664
|
backToSignInText = "Remember your password?",
|
|
1617
1665
|
backToSignInUrl = "/sign-in",
|
|
1618
|
-
|
|
1619
|
-
|
|
1666
|
+
showVerificationStep = false,
|
|
1667
|
+
resetPasswordMethod = "code",
|
|
1668
|
+
onVerifyCode,
|
|
1669
|
+
onResendEmail
|
|
1620
1670
|
}) {
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1671
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(AuthContainer, { children: [
|
|
1672
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1673
|
+
AuthHeader,
|
|
1624
1674
|
{
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1628
|
-
"div",
|
|
1629
|
-
{
|
|
1630
|
-
style: {
|
|
1631
|
-
width: "4rem",
|
|
1632
|
-
height: "4rem",
|
|
1633
|
-
borderRadius: "50%",
|
|
1634
|
-
backgroundColor: "#D1FAE5",
|
|
1635
|
-
display: "flex",
|
|
1636
|
-
alignItems: "center",
|
|
1637
|
-
justifyContent: "center"
|
|
1638
|
-
},
|
|
1639
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1640
|
-
"svg",
|
|
1641
|
-
{
|
|
1642
|
-
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
1643
|
-
fill: "none",
|
|
1644
|
-
strokeLinecap: "round",
|
|
1645
|
-
strokeLinejoin: "round",
|
|
1646
|
-
strokeWidth: "2",
|
|
1647
|
-
viewBox: "0 0 24 24",
|
|
1648
|
-
stroke: "currentColor",
|
|
1649
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7" })
|
|
1650
|
-
}
|
|
1651
|
-
)
|
|
1652
|
-
}
|
|
1653
|
-
),
|
|
1654
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
1655
|
-
/* @__PURE__ */ jsxRuntime.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.` }),
|
|
1656
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { href: backToSignInUrl, className: "if-authLink-link", style: { marginTop: "1rem" }, children: "Back to Sign In" })
|
|
1657
|
-
]
|
|
1675
|
+
title: showVerificationStep ? resetPasswordMethod === "link" ? "Check Your Email" : "Enter Reset Code" : title,
|
|
1676
|
+
subtitle: showVerificationStep ? "" : subtitle
|
|
1658
1677
|
}
|
|
1659
|
-
)
|
|
1660
|
-
}
|
|
1661
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(AuthContainer, { children: [
|
|
1662
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuthHeader, { title, subtitle }),
|
|
1678
|
+
),
|
|
1663
1679
|
/* @__PURE__ */ jsxRuntime.jsx(AuthErrorBanner, { error: error || "" }),
|
|
1664
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1680
|
+
showVerificationStep ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1681
|
+
AuthResetPasswordVerificationStep,
|
|
1682
|
+
{
|
|
1683
|
+
email,
|
|
1684
|
+
method: resetPasswordMethod,
|
|
1685
|
+
onVerifyCode,
|
|
1686
|
+
onResendEmail: onResendEmail || (async () => {
|
|
1687
|
+
})
|
|
1688
|
+
}
|
|
1689
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
|
|
1665
1690
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1666
1691
|
AuthFormField,
|
|
1667
1692
|
{
|
|
@@ -1677,7 +1702,7 @@ function ForgotPasswordForm({
|
|
|
1677
1702
|
),
|
|
1678
1703
|
/* @__PURE__ */ jsxRuntime.jsx(AuthSubmitButton, { isLoading: loading, disabled: loading, children: loading ? loadingButtonText : submitButtonText })
|
|
1679
1704
|
] }),
|
|
1680
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1705
|
+
!showVerificationStep && /* @__PURE__ */ jsxRuntime.jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1681
1706
|
] });
|
|
1682
1707
|
}
|
|
1683
1708
|
function ResetPasswordForm({
|
|
@@ -1698,11 +1723,12 @@ function ResetPasswordForm({
|
|
|
1698
1723
|
confirmPasswordPlaceholder = "\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
1699
1724
|
submitButtonText = "Reset Password",
|
|
1700
1725
|
loadingButtonText = "Resetting...",
|
|
1701
|
-
|
|
1702
|
-
backToSignInUrl = "/sign-in",
|
|
1703
|
-
successTitle = "Password Reset Successful!",
|
|
1704
|
-
successMessage = "Your password has been successfully reset. You can now sign in with your new password."
|
|
1726
|
+
successTitle = "Password Reset Successful!"
|
|
1705
1727
|
}) {
|
|
1728
|
+
let successMessage = "Your password has been successfully reset. You can close this page and sign in with your new password.";
|
|
1729
|
+
if (authConfig && authConfig.verifyEmailMethod === "code") {
|
|
1730
|
+
successMessage = "Your password has been successfully reset. You can wait for redirect to sign in with your new password.";
|
|
1731
|
+
}
|
|
1706
1732
|
if (success) {
|
|
1707
1733
|
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1708
1734
|
"div",
|
|
@@ -1737,8 +1763,7 @@ function ResetPasswordForm({
|
|
|
1737
1763
|
}
|
|
1738
1764
|
),
|
|
1739
1765
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
1740
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
1741
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { href: backToSignInUrl, className: "if-authLink-link", style: { marginTop: "1rem" }, children: "Back to Sign In" })
|
|
1766
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
1742
1767
|
]
|
|
1743
1768
|
}
|
|
1744
1769
|
) });
|
|
@@ -1775,40 +1800,87 @@ function ResetPasswordForm({
|
|
|
1775
1800
|
}
|
|
1776
1801
|
),
|
|
1777
1802
|
/* @__PURE__ */ jsxRuntime.jsx(AuthSubmitButton, { isLoading: loading, disabled: loading, children: loading ? loadingButtonText : submitButtonText })
|
|
1778
|
-
] })
|
|
1779
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuthLink, { text: backToSignInText, linkText: "Back to Sign In", href: backToSignInUrl })
|
|
1803
|
+
] })
|
|
1780
1804
|
] });
|
|
1781
1805
|
}
|
|
1782
|
-
function
|
|
1783
|
-
|
|
1784
|
-
backToSignInUrl = "/sign-in",
|
|
1785
|
-
onSuccess,
|
|
1786
|
-
onError,
|
|
1787
|
-
...uiProps
|
|
1788
|
-
}) {
|
|
1789
|
-
const { resetPassword } = useInsforge();
|
|
1806
|
+
function ForgotPassword({ onError, ...uiProps }) {
|
|
1807
|
+
const { sendResetPasswordEmail, exchangeResetPasswordToken, resetPassword } = useInsforge();
|
|
1790
1808
|
const { authConfig } = usePublicAuthConfig();
|
|
1809
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
1810
|
+
const [step, setStep] = react.useState("email");
|
|
1811
|
+
const [email, setEmail] = react.useState("");
|
|
1812
|
+
const [resetToken, setResetToken] = react.useState("");
|
|
1791
1813
|
const [newPassword, setNewPassword] = react.useState("");
|
|
1792
1814
|
const [confirmPassword, setConfirmPassword] = react.useState("");
|
|
1793
1815
|
const [error, setError] = react.useState("");
|
|
1794
1816
|
const [loading, setLoading] = react.useState(false);
|
|
1795
1817
|
const [success, setSuccess] = react.useState(false);
|
|
1796
|
-
|
|
1818
|
+
const [showVerificationStep, setShowVerificationStep] = react.useState(false);
|
|
1819
|
+
async function handleEmailSubmit(e) {
|
|
1797
1820
|
e.preventDefault();
|
|
1798
1821
|
setLoading(true);
|
|
1799
1822
|
setError("");
|
|
1800
|
-
|
|
1801
|
-
|
|
1823
|
+
const emailValidation = emailSchema.safeParse(email);
|
|
1824
|
+
if (!emailValidation.success) {
|
|
1825
|
+
const firstError = emailValidation.error.issues[0];
|
|
1826
|
+
setError(firstError.message);
|
|
1802
1827
|
setLoading(false);
|
|
1803
1828
|
return;
|
|
1804
1829
|
}
|
|
1830
|
+
try {
|
|
1831
|
+
const result = await sendResetPasswordEmail(emailValidation.data);
|
|
1832
|
+
if (result?.success) {
|
|
1833
|
+
setShowVerificationStep(true);
|
|
1834
|
+
} else {
|
|
1835
|
+
const errorMessage = result?.message || "Failed to send reset email";
|
|
1836
|
+
setError(errorMessage);
|
|
1837
|
+
if (onError) {
|
|
1838
|
+
onError(new Error(errorMessage));
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
} catch (err) {
|
|
1842
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to send reset email";
|
|
1843
|
+
setError(errorMessage);
|
|
1844
|
+
if (onError) {
|
|
1845
|
+
onError(new Error(errorMessage));
|
|
1846
|
+
}
|
|
1847
|
+
} finally {
|
|
1848
|
+
setLoading(false);
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
async function handleVerifyCode(code) {
|
|
1852
|
+
setError("");
|
|
1853
|
+
try {
|
|
1854
|
+
const result = await exchangeResetPasswordToken(email, code);
|
|
1855
|
+
if ("error" in result) {
|
|
1856
|
+
throw new Error(result.error.message || "Failed to verify code");
|
|
1857
|
+
}
|
|
1858
|
+
if (result.token) {
|
|
1859
|
+
setResetToken(result.token);
|
|
1860
|
+
setStep("password");
|
|
1861
|
+
}
|
|
1862
|
+
} catch (err) {
|
|
1863
|
+
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1864
|
+
setError(errorMessage);
|
|
1865
|
+
if (onError) {
|
|
1866
|
+
onError(new Error(errorMessage));
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
async function handleResendEmail() {
|
|
1871
|
+
await sendResetPasswordEmail(email);
|
|
1872
|
+
}
|
|
1873
|
+
async function handleResetPasswordSubmit(e) {
|
|
1874
|
+
e.preventDefault();
|
|
1875
|
+
setLoading(true);
|
|
1876
|
+
setError("");
|
|
1805
1877
|
if (newPassword !== confirmPassword) {
|
|
1806
1878
|
setError("Passwords do not match");
|
|
1807
1879
|
setLoading(false);
|
|
1808
1880
|
return;
|
|
1809
1881
|
}
|
|
1810
|
-
if (!
|
|
1811
|
-
setError("
|
|
1882
|
+
if (!authConfig) {
|
|
1883
|
+
setError("Configuration not loaded");
|
|
1812
1884
|
setLoading(false);
|
|
1813
1885
|
return;
|
|
1814
1886
|
}
|
|
@@ -1827,12 +1899,16 @@ function ResetPassword({
|
|
|
1827
1899
|
return;
|
|
1828
1900
|
}
|
|
1829
1901
|
try {
|
|
1830
|
-
const result = await resetPassword(
|
|
1902
|
+
const result = await resetPassword(resetToken, newPassword);
|
|
1831
1903
|
if (result?.message) {
|
|
1832
1904
|
setSuccess(true);
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1905
|
+
const signInUrl = new URL("/sign-in", window.location.origin);
|
|
1906
|
+
searchParams.forEach((value, key) => {
|
|
1907
|
+
signInUrl.searchParams.set(key, value);
|
|
1908
|
+
});
|
|
1909
|
+
setTimeout(() => {
|
|
1910
|
+
window.location.href = signInUrl.toString();
|
|
1911
|
+
}, 2e3);
|
|
1836
1912
|
} else {
|
|
1837
1913
|
const errorMessage = "Failed to reset password";
|
|
1838
1914
|
setError(errorMessage);
|
|
@@ -1853,6 +1929,25 @@ function ResetPassword({
|
|
|
1853
1929
|
if (!authConfig) {
|
|
1854
1930
|
return null;
|
|
1855
1931
|
}
|
|
1932
|
+
if (step === "email") {
|
|
1933
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1934
|
+
ForgotPasswordForm,
|
|
1935
|
+
{
|
|
1936
|
+
email,
|
|
1937
|
+
onEmailChange: setEmail,
|
|
1938
|
+
onSubmit: (e) => {
|
|
1939
|
+
void handleEmailSubmit(e);
|
|
1940
|
+
},
|
|
1941
|
+
error,
|
|
1942
|
+
loading,
|
|
1943
|
+
showVerificationStep,
|
|
1944
|
+
resetPasswordMethod: authConfig.resetPasswordMethod,
|
|
1945
|
+
onVerifyCode: handleVerifyCode,
|
|
1946
|
+
onResendEmail: handleResendEmail,
|
|
1947
|
+
...uiProps
|
|
1948
|
+
}
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1856
1951
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1857
1952
|
ResetPasswordForm,
|
|
1858
1953
|
{
|
|
@@ -1860,83 +1955,71 @@ function ResetPassword({
|
|
|
1860
1955
|
confirmPassword,
|
|
1861
1956
|
onNewPasswordChange: setNewPassword,
|
|
1862
1957
|
onConfirmPasswordChange: setConfirmPassword,
|
|
1863
|
-
onSubmit:
|
|
1958
|
+
onSubmit: handleResetPasswordSubmit,
|
|
1864
1959
|
error,
|
|
1865
1960
|
loading,
|
|
1866
1961
|
success,
|
|
1867
1962
|
authConfig,
|
|
1868
|
-
backToSignInUrl,
|
|
1869
1963
|
...uiProps
|
|
1870
1964
|
}
|
|
1871
1965
|
);
|
|
1872
1966
|
}
|
|
1873
|
-
function
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
...uiProps
|
|
1878
|
-
}) {
|
|
1879
|
-
const { sendResetPasswordEmail, baseUrl } = useInsforge();
|
|
1967
|
+
function ResetPassword({ onError, ...uiProps }) {
|
|
1968
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
1969
|
+
const token = searchParams.get("token");
|
|
1970
|
+
const { resetPassword } = useInsforge();
|
|
1880
1971
|
const { authConfig } = usePublicAuthConfig();
|
|
1881
|
-
const [
|
|
1882
|
-
const [
|
|
1883
|
-
const [email, setEmail] = react.useState("");
|
|
1884
|
-
const [verificationCode, setVerificationCode] = react.useState("");
|
|
1885
|
-
const [resetToken, setResetToken] = react.useState("");
|
|
1972
|
+
const [newPassword, setNewPassword] = react.useState("");
|
|
1973
|
+
const [confirmPassword, setConfirmPassword] = react.useState("");
|
|
1886
1974
|
const [error, setError] = react.useState("");
|
|
1887
1975
|
const [loading, setLoading] = react.useState(false);
|
|
1888
1976
|
const [success, setSuccess] = react.useState(false);
|
|
1889
|
-
|
|
1890
|
-
const [resendCountdown, setResendCountdown] = react.useState(60);
|
|
1891
|
-
const [isSendingCode, setIsSendingCode] = react.useState(false);
|
|
1892
|
-
const [isVerifyingCode, setIsVerifyingCode] = react.useState(false);
|
|
1893
|
-
react.useEffect(() => {
|
|
1894
|
-
if (resendCountdown > 0 && step === "code") {
|
|
1895
|
-
const timer = setInterval(() => {
|
|
1896
|
-
setResendCountdown((prev) => {
|
|
1897
|
-
if (prev <= 1) {
|
|
1898
|
-
setResendDisabled(false);
|
|
1899
|
-
return 0;
|
|
1900
|
-
}
|
|
1901
|
-
return prev - 1;
|
|
1902
|
-
});
|
|
1903
|
-
}, 1e3);
|
|
1904
|
-
return () => clearInterval(timer);
|
|
1905
|
-
}
|
|
1906
|
-
}, [resendCountdown, step]);
|
|
1907
|
-
async function handleEmailSubmit(e) {
|
|
1977
|
+
async function handleSubmit(e) {
|
|
1908
1978
|
e.preventDefault();
|
|
1909
1979
|
setLoading(true);
|
|
1910
1980
|
setError("");
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1981
|
+
if (!authConfig) {
|
|
1982
|
+
setError("Configuration not loaded. Please refresh the page.");
|
|
1983
|
+
setLoading(false);
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1986
|
+
if (newPassword !== confirmPassword) {
|
|
1987
|
+
setError("Passwords do not match");
|
|
1988
|
+
setLoading(false);
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (!token) {
|
|
1992
|
+
setError("Reset token is missing");
|
|
1993
|
+
setLoading(false);
|
|
1994
|
+
return;
|
|
1995
|
+
}
|
|
1996
|
+
const passwordZodSchema = createPasswordSchema({
|
|
1997
|
+
minLength: authConfig.passwordMinLength,
|
|
1998
|
+
requireUppercase: authConfig.requireUppercase,
|
|
1999
|
+
requireLowercase: authConfig.requireLowercase,
|
|
2000
|
+
requireNumber: authConfig.requireNumber,
|
|
2001
|
+
requireSpecialChar: authConfig.requireSpecialChar
|
|
2002
|
+
});
|
|
2003
|
+
const passwordValidation = passwordZodSchema.safeParse(newPassword);
|
|
2004
|
+
if (!passwordValidation.success) {
|
|
2005
|
+
const firstError = passwordValidation.error.issues[0];
|
|
1914
2006
|
setError(firstError.message);
|
|
1915
2007
|
setLoading(false);
|
|
1916
2008
|
return;
|
|
1917
2009
|
}
|
|
1918
2010
|
try {
|
|
1919
|
-
const result = await
|
|
1920
|
-
if (result?.
|
|
1921
|
-
|
|
1922
|
-
setSuccess(true);
|
|
1923
|
-
if (onSuccess) {
|
|
1924
|
-
onSuccess();
|
|
1925
|
-
}
|
|
1926
|
-
} else {
|
|
1927
|
-
setStep("code");
|
|
1928
|
-
setResendDisabled(true);
|
|
1929
|
-
setResendCountdown(60);
|
|
1930
|
-
}
|
|
2011
|
+
const result = await resetPassword(token, newPassword);
|
|
2012
|
+
if (result?.message) {
|
|
2013
|
+
setSuccess(true);
|
|
1931
2014
|
} else {
|
|
1932
|
-
const errorMessage =
|
|
2015
|
+
const errorMessage = "Failed to reset password";
|
|
1933
2016
|
setError(errorMessage);
|
|
1934
2017
|
if (onError) {
|
|
1935
2018
|
onError(new Error(errorMessage));
|
|
1936
2019
|
}
|
|
1937
2020
|
}
|
|
1938
2021
|
} catch (err) {
|
|
1939
|
-
const errorMessage = err instanceof Error ? err.message : "Failed to
|
|
2022
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to reset password";
|
|
1940
2023
|
setError(errorMessage);
|
|
1941
2024
|
if (onError) {
|
|
1942
2025
|
onError(new Error(errorMessage));
|
|
@@ -1945,297 +2028,157 @@ function ForgotPassword({
|
|
|
1945
2028
|
setLoading(false);
|
|
1946
2029
|
}
|
|
1947
2030
|
}
|
|
1948
|
-
async function handleVerifyCode(code) {
|
|
1949
|
-
setIsVerifyingCode(true);
|
|
1950
|
-
setError("");
|
|
1951
|
-
setVerificationCode(code);
|
|
1952
|
-
try {
|
|
1953
|
-
const result = await insforge.auth.exchangeResetPasswordToken({ email, code });
|
|
1954
|
-
if (result.error) {
|
|
1955
|
-
throw new Error(result.error.message || "Failed to verify code");
|
|
1956
|
-
}
|
|
1957
|
-
if (result.data) {
|
|
1958
|
-
setResetToken(result.data.token);
|
|
1959
|
-
setStep("password");
|
|
1960
|
-
}
|
|
1961
|
-
} catch (err) {
|
|
1962
|
-
const errorMessage = err instanceof Error ? err.message : "Invalid verification code";
|
|
1963
|
-
setError(errorMessage);
|
|
1964
|
-
setVerificationCode("");
|
|
1965
|
-
} finally {
|
|
1966
|
-
setIsVerifyingCode(false);
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
const handleResendCode = react.useCallback(async () => {
|
|
1970
|
-
setResendDisabled(true);
|
|
1971
|
-
setResendCountdown(60);
|
|
1972
|
-
setIsSendingCode(true);
|
|
1973
|
-
setError("");
|
|
1974
|
-
try {
|
|
1975
|
-
await sendResetPasswordEmail(email);
|
|
1976
|
-
} catch (err) {
|
|
1977
|
-
const errorMessage = err instanceof Error ? err.message : "Failed to resend code";
|
|
1978
|
-
setError(errorMessage);
|
|
1979
|
-
setResendDisabled(false);
|
|
1980
|
-
setResendCountdown(0);
|
|
1981
|
-
} finally {
|
|
1982
|
-
setIsSendingCode(false);
|
|
1983
|
-
}
|
|
1984
|
-
}, [email, sendResetPasswordEmail]);
|
|
1985
|
-
function handlePasswordResetSuccess(redirectTo) {
|
|
1986
|
-
const targetUrl = redirectTo || backToSignInUrl;
|
|
1987
|
-
if (onSuccess) {
|
|
1988
|
-
onSuccess();
|
|
1989
|
-
}
|
|
1990
|
-
setTimeout(() => {
|
|
1991
|
-
window.location.href = targetUrl;
|
|
1992
|
-
}, 1500);
|
|
1993
|
-
}
|
|
1994
2031
|
if (!authConfig) {
|
|
1995
2032
|
return null;
|
|
1996
2033
|
}
|
|
1997
|
-
if (
|
|
1998
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1999
|
-
ForgotPasswordForm,
|
|
2000
|
-
{
|
|
2001
|
-
email,
|
|
2002
|
-
onEmailChange: setEmail,
|
|
2003
|
-
onSubmit: (e) => {
|
|
2004
|
-
void handleEmailSubmit(e);
|
|
2005
|
-
},
|
|
2006
|
-
error,
|
|
2007
|
-
loading,
|
|
2008
|
-
success,
|
|
2009
|
-
backToSignInUrl,
|
|
2010
|
-
...uiProps
|
|
2011
|
-
}
|
|
2012
|
-
);
|
|
2013
|
-
}
|
|
2014
|
-
if (step === "code") {
|
|
2034
|
+
if (!token) {
|
|
2015
2035
|
return /* @__PURE__ */ jsxRuntime.jsxs(AuthContainer, { children: [
|
|
2036
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuthHeader, { title: "Invalid Reset Link", subtitle: "" }),
|
|
2016
2037
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2017
|
-
AuthHeader,
|
|
2018
|
-
{
|
|
2019
|
-
title: "Enter Reset Code",
|
|
2020
|
-
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.`
|
|
2021
|
-
}
|
|
2022
|
-
),
|
|
2023
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuthErrorBanner, { error }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2025
2038
|
"div",
|
|
2026
2039
|
{
|
|
2027
2040
|
style: {
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
alignItems: "center"
|
|
2041
|
+
padding: "1.5rem",
|
|
2042
|
+
backgroundColor: "#FEE2E2",
|
|
2043
|
+
borderRadius: "0.5rem",
|
|
2044
|
+
border: "1px solid #DC2626"
|
|
2033
2045
|
},
|
|
2034
|
-
children:
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
{
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
},
|
|
2047
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2048
|
-
"div",
|
|
2049
|
-
{
|
|
2050
|
-
style: {
|
|
2051
|
-
display: "flex",
|
|
2052
|
-
flexDirection: "column",
|
|
2053
|
-
gap: "0.75rem",
|
|
2054
|
-
marginTop: "0.5rem"
|
|
2055
|
-
},
|
|
2056
|
-
children: [
|
|
2057
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2058
|
-
AuthVerificationCodeInput,
|
|
2059
|
-
{
|
|
2060
|
-
value: verificationCode,
|
|
2061
|
-
onChange: setVerificationCode,
|
|
2062
|
-
email,
|
|
2063
|
-
disabled: isVerifyingCode,
|
|
2064
|
-
onComplete: (code) => {
|
|
2065
|
-
void handleVerifyCode(code);
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
),
|
|
2069
|
-
isVerifyingCode && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: "Verifying..." })
|
|
2070
|
-
]
|
|
2071
|
-
}
|
|
2072
|
-
)
|
|
2073
|
-
}
|
|
2074
|
-
),
|
|
2075
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2076
|
-
"div",
|
|
2077
|
-
{
|
|
2078
|
-
style: {
|
|
2079
|
-
width: "100%",
|
|
2080
|
-
fontSize: "0.875rem",
|
|
2081
|
-
textAlign: "center",
|
|
2082
|
-
color: "#828282",
|
|
2083
|
-
fontFamily: "var(--if-font-family)"
|
|
2084
|
-
},
|
|
2085
|
-
children: [
|
|
2086
|
-
"Didn't receive the email?",
|
|
2087
|
-
" ",
|
|
2088
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2089
|
-
"button",
|
|
2090
|
-
{
|
|
2091
|
-
onClick: () => {
|
|
2092
|
-
void handleResendCode();
|
|
2093
|
-
},
|
|
2094
|
-
disabled: resendDisabled || isSendingCode,
|
|
2095
|
-
style: {
|
|
2096
|
-
color: "#000",
|
|
2097
|
-
fontWeight: 500,
|
|
2098
|
-
transition: "all 0.2s",
|
|
2099
|
-
cursor: resendDisabled || isSendingCode ? "not-allowed" : "pointer",
|
|
2100
|
-
background: "none",
|
|
2101
|
-
border: "none",
|
|
2102
|
-
padding: 0,
|
|
2103
|
-
textDecoration: resendDisabled || isSendingCode ? "none" : "underline",
|
|
2104
|
-
opacity: resendDisabled || isSendingCode ? 0.5 : 1,
|
|
2105
|
-
fontFamily: "var(--if-font-family)"
|
|
2106
|
-
},
|
|
2107
|
-
children: isSendingCode ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
|
|
2108
|
-
}
|
|
2109
|
-
)
|
|
2110
|
-
]
|
|
2111
|
-
}
|
|
2112
|
-
)
|
|
2113
|
-
]
|
|
2046
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2047
|
+
"p",
|
|
2048
|
+
{
|
|
2049
|
+
style: {
|
|
2050
|
+
fontSize: "0.875rem",
|
|
2051
|
+
color: "#DC2626",
|
|
2052
|
+
margin: 0,
|
|
2053
|
+
fontFamily: "var(--if-font-family)"
|
|
2054
|
+
},
|
|
2055
|
+
children: "The password reset link is missing or invalid. Please request a new password reset link."
|
|
2056
|
+
}
|
|
2057
|
+
)
|
|
2114
2058
|
}
|
|
2115
|
-
)
|
|
2116
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: backToSignInUrl, className: "if-authLink-link", children: "Back to Sign In" }) })
|
|
2059
|
+
)
|
|
2117
2060
|
] });
|
|
2118
2061
|
}
|
|
2119
|
-
|
|
2120
|
-
ResetPassword,
|
|
2121
|
-
{
|
|
2122
|
-
token: resetToken,
|
|
2123
|
-
backToSignInUrl,
|
|
2124
|
-
onSuccess: handlePasswordResetSuccess,
|
|
2125
|
-
onError
|
|
2126
|
-
}
|
|
2127
|
-
);
|
|
2128
|
-
}
|
|
2129
|
-
function VerifyEmailStatus({
|
|
2130
|
-
status,
|
|
2131
|
-
error,
|
|
2132
|
-
verifyingTitle = "Verifying your email...",
|
|
2133
|
-
successTitle = "Email Verified!",
|
|
2134
|
-
successMessage = "Your email has been verified successfully. You can close this page and return to your app.",
|
|
2135
|
-
errorTitle = "Verification Failed"
|
|
2136
|
-
}) {
|
|
2137
|
-
if (status === "verifying") {
|
|
2062
|
+
if (success) {
|
|
2138
2063
|
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2139
2064
|
"div",
|
|
2140
2065
|
{
|
|
2141
|
-
style: {
|
|
2142
|
-
width: "100%",
|
|
2143
|
-
display: "flex",
|
|
2144
|
-
flexDirection: "column",
|
|
2145
|
-
alignItems: "center",
|
|
2146
|
-
justifyContent: "center",
|
|
2147
|
-
gap: "1.5rem"
|
|
2148
|
-
},
|
|
2066
|
+
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "1rem" },
|
|
2149
2067
|
children: [
|
|
2150
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2151
2068
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2152
2069
|
"div",
|
|
2153
2070
|
{
|
|
2154
|
-
className: "if-submitButton-spinner",
|
|
2155
2071
|
style: {
|
|
2072
|
+
width: "4rem",
|
|
2073
|
+
height: "4rem",
|
|
2156
2074
|
borderRadius: "50%",
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2075
|
+
backgroundColor: "#D1FAE5",
|
|
2076
|
+
display: "flex",
|
|
2077
|
+
alignItems: "center",
|
|
2078
|
+
justifyContent: "center"
|
|
2079
|
+
},
|
|
2080
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2081
|
+
"svg",
|
|
2082
|
+
{
|
|
2083
|
+
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
2084
|
+
fill: "none",
|
|
2085
|
+
strokeLinecap: "round",
|
|
2086
|
+
strokeLinejoin: "round",
|
|
2087
|
+
strokeWidth: "2",
|
|
2088
|
+
viewBox: "0 0 24 24",
|
|
2089
|
+
stroke: "currentColor",
|
|
2090
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2091
|
+
}
|
|
2092
|
+
)
|
|
2093
|
+
}
|
|
2094
|
+
),
|
|
2095
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2096
|
+
"h2",
|
|
2097
|
+
{
|
|
2098
|
+
style: {
|
|
2099
|
+
fontSize: "1.5rem",
|
|
2100
|
+
fontWeight: 600,
|
|
2101
|
+
color: "#000",
|
|
2102
|
+
margin: 0,
|
|
2103
|
+
textAlign: "center",
|
|
2104
|
+
fontFamily: "var(--if-font-family)"
|
|
2105
|
+
},
|
|
2106
|
+
children: "Password Reset Successfully"
|
|
2107
|
+
}
|
|
2108
|
+
),
|
|
2109
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2110
|
+
"p",
|
|
2111
|
+
{
|
|
2112
|
+
style: {
|
|
2113
|
+
fontSize: "0.875rem",
|
|
2114
|
+
color: "#828282",
|
|
2115
|
+
textAlign: "center",
|
|
2116
|
+
margin: 0,
|
|
2117
|
+
fontFamily: "var(--if-font-family)"
|
|
2118
|
+
},
|
|
2119
|
+
children: "Your password has been reset successfully. You can now close this page and return to the login page in your original tab."
|
|
2161
2120
|
}
|
|
2162
2121
|
)
|
|
2163
2122
|
]
|
|
2164
2123
|
}
|
|
2165
2124
|
) });
|
|
2166
2125
|
}
|
|
2126
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2127
|
+
ResetPasswordForm,
|
|
2128
|
+
{
|
|
2129
|
+
newPassword,
|
|
2130
|
+
confirmPassword,
|
|
2131
|
+
onNewPasswordChange: setNewPassword,
|
|
2132
|
+
onConfirmPasswordChange: setConfirmPassword,
|
|
2133
|
+
onSubmit: handleSubmit,
|
|
2134
|
+
error,
|
|
2135
|
+
loading,
|
|
2136
|
+
success: false,
|
|
2137
|
+
authConfig,
|
|
2138
|
+
...uiProps
|
|
2139
|
+
}
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
function VerifyEmailStatus({
|
|
2143
|
+
status,
|
|
2144
|
+
error,
|
|
2145
|
+
verifyingTitle = "Verifying your email...",
|
|
2146
|
+
successTitle = "Email Verified!",
|
|
2147
|
+
successMessage = "Your email has been verified successfully. You can close this page and sign in to your app.",
|
|
2148
|
+
errorTitle = "Verification Failed"
|
|
2149
|
+
}) {
|
|
2150
|
+
if (status === "verifying") {
|
|
2151
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verifyStatus-container", children: [
|
|
2152
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", children: verifyingTitle }),
|
|
2153
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-submitButton-spinner if-verifyStatus-spinner" })
|
|
2154
|
+
] }) });
|
|
2155
|
+
}
|
|
2167
2156
|
if (status === "error") {
|
|
2168
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2169
|
-
"
|
|
2157
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-authHeader if-internal-h3m7w5", children: [
|
|
2158
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "if-authHeader-title if-internal-t4p1k9", children: errorTitle }),
|
|
2159
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "if-authHeader-subtitle if-internal-s7q2m3", children: [
|
|
2160
|
+
error || "The verification link is invalid or has expired.",
|
|
2161
|
+
" Please try again or contact support if the problem persists. You can close this page and return to your app."
|
|
2162
|
+
] })
|
|
2163
|
+
] }) }) });
|
|
2164
|
+
}
|
|
2165
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AuthContainer, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-verifyStatus-container-stretch", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-verifyStatus-successContent", children: [
|
|
2166
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-verifyStatus-successIcon", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2167
|
+
"svg",
|
|
2170
2168
|
{
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
}
|
|
2179
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-authHeader if-internal-h3m7w5", children: [
|
|
2180
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "if-authHeader-title if-internal-t4p1k9", children: errorTitle }),
|
|
2181
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "if-authHeader-subtitle if-internal-s7q2m3", style: { lineHeight: "1.5" }, children: [
|
|
2182
|
-
error || "The verification link is invalid or has expired.",
|
|
2183
|
-
" Please try again or contact support if the problem persists. You can close this page and return to your app."
|
|
2184
|
-
] })
|
|
2185
|
-
] })
|
|
2169
|
+
className: "if-verifyStatus-successIconSvg",
|
|
2170
|
+
fill: "none",
|
|
2171
|
+
strokeLinecap: "round",
|
|
2172
|
+
strokeLinejoin: "round",
|
|
2173
|
+
strokeWidth: "2",
|
|
2174
|
+
viewBox: "0 0 24 24",
|
|
2175
|
+
stroke: "currentColor",
|
|
2176
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2186
2177
|
}
|
|
2187
|
-
) })
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
{
|
|
2192
|
-
style: {
|
|
2193
|
-
width: "100%",
|
|
2194
|
-
display: "flex",
|
|
2195
|
-
flexDirection: "column",
|
|
2196
|
-
alignItems: "stretch",
|
|
2197
|
-
justifyContent: "center",
|
|
2198
|
-
gap: "1.5rem"
|
|
2199
|
-
},
|
|
2200
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2201
|
-
"div",
|
|
2202
|
-
{
|
|
2203
|
-
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "1rem" },
|
|
2204
|
-
children: [
|
|
2205
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2206
|
-
"div",
|
|
2207
|
-
{
|
|
2208
|
-
style: {
|
|
2209
|
-
width: "4rem",
|
|
2210
|
-
height: "4rem",
|
|
2211
|
-
borderRadius: "50%",
|
|
2212
|
-
backgroundColor: "#D1FAE5",
|
|
2213
|
-
display: "flex",
|
|
2214
|
-
alignItems: "center",
|
|
2215
|
-
justifyContent: "center"
|
|
2216
|
-
},
|
|
2217
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2218
|
-
"svg",
|
|
2219
|
-
{
|
|
2220
|
-
style: { width: "2rem", height: "2rem", color: "#059669" },
|
|
2221
|
-
fill: "none",
|
|
2222
|
-
strokeLinecap: "round",
|
|
2223
|
-
strokeLinejoin: "round",
|
|
2224
|
-
strokeWidth: "2",
|
|
2225
|
-
viewBox: "0 0 24 24",
|
|
2226
|
-
stroke: "currentColor",
|
|
2227
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7" })
|
|
2228
|
-
}
|
|
2229
|
-
)
|
|
2230
|
-
}
|
|
2231
|
-
),
|
|
2232
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", style: { textAlign: "center" }, children: successTitle }),
|
|
2233
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle", style: { textAlign: "center" }, children: successMessage })
|
|
2234
|
-
]
|
|
2235
|
-
}
|
|
2236
|
-
)
|
|
2237
|
-
}
|
|
2238
|
-
) });
|
|
2178
|
+
) }),
|
|
2179
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title if-verifyStatus-textCenter", children: successTitle }),
|
|
2180
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "if-authHeader-subtitle if-verifyStatus-textCenter", children: successMessage })
|
|
2181
|
+
] }) }) });
|
|
2239
2182
|
}
|
|
2240
2183
|
function VerifyEmail({ token, onSuccess, onError, ...uiProps }) {
|
|
2241
2184
|
const { verifyEmail } = useInsforge();
|
|
@@ -2336,93 +2279,43 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
|
|
|
2336
2279
|
}
|
|
2337
2280
|
const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
|
|
2338
2281
|
const buttonClassName = mode === "detailed" ? "if-userButton if-userButton-detailed" : "if-userButton";
|
|
2339
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
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
|
-
|
|
2375
|
-
|
|
2376
|
-
alignItems: "flex-start",
|
|
2377
|
-
gap: "0.125rem"
|
|
2378
|
-
},
|
|
2379
|
-
children: [
|
|
2380
|
-
user.name && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2381
|
-
"div",
|
|
2382
|
-
{
|
|
2383
|
-
style: {
|
|
2384
|
-
fontSize: "0.875rem",
|
|
2385
|
-
fontWeight: 600,
|
|
2386
|
-
color: "#1f1f1f",
|
|
2387
|
-
lineHeight: "1.25rem",
|
|
2388
|
-
textAlign: "left"
|
|
2389
|
-
},
|
|
2390
|
-
children: user.name
|
|
2391
|
-
}
|
|
2392
|
-
),
|
|
2393
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2394
|
-
"div",
|
|
2395
|
-
{
|
|
2396
|
-
style: {
|
|
2397
|
-
fontSize: "0.75rem",
|
|
2398
|
-
color: "#828282",
|
|
2399
|
-
lineHeight: "1rem",
|
|
2400
|
-
textAlign: "left"
|
|
2401
|
-
},
|
|
2402
|
-
children: user.email
|
|
2403
|
-
}
|
|
2404
|
-
)
|
|
2405
|
-
]
|
|
2406
|
-
}
|
|
2407
|
-
)
|
|
2408
|
-
]
|
|
2409
|
-
}
|
|
2410
|
-
),
|
|
2411
|
-
isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2412
|
-
"button",
|
|
2413
|
-
{
|
|
2414
|
-
onClick: handleSignOut,
|
|
2415
|
-
className: "if-userButton-menuItem",
|
|
2416
|
-
style: { color: "#DC2626" },
|
|
2417
|
-
children: [
|
|
2418
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { style: { width: "1.25rem", height: "1.25rem" } }),
|
|
2419
|
-
"Sign out"
|
|
2420
|
-
]
|
|
2421
|
-
}
|
|
2422
|
-
) })
|
|
2423
|
-
]
|
|
2424
|
-
}
|
|
2425
|
-
);
|
|
2282
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-userButton-container if-internal-ub3k8p", ref: dropdownRef, children: [
|
|
2283
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2284
|
+
"button",
|
|
2285
|
+
{
|
|
2286
|
+
className: buttonClassName,
|
|
2287
|
+
onClick: () => setIsOpen(!isOpen),
|
|
2288
|
+
"aria-expanded": isOpen,
|
|
2289
|
+
"aria-haspopup": "true",
|
|
2290
|
+
children: [
|
|
2291
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-avatar", children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2292
|
+
"img",
|
|
2293
|
+
{
|
|
2294
|
+
src: user.avatarUrl,
|
|
2295
|
+
alt: user.email,
|
|
2296
|
+
onError: () => setImageError(true),
|
|
2297
|
+
className: "if-userButton-avatarImage"
|
|
2298
|
+
}
|
|
2299
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "if-userButton-avatarInitials", children: initials }) }),
|
|
2300
|
+
mode === "detailed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "if-userButton-info", children: [
|
|
2301
|
+
user.name && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-name", children: user.name }),
|
|
2302
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-email", children: user.email })
|
|
2303
|
+
] })
|
|
2304
|
+
]
|
|
2305
|
+
}
|
|
2306
|
+
),
|
|
2307
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2308
|
+
"button",
|
|
2309
|
+
{
|
|
2310
|
+
onClick: handleSignOut,
|
|
2311
|
+
className: "if-userButton-menuItem if-userButton-menuItem-signout",
|
|
2312
|
+
children: [
|
|
2313
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "if-userButton-menuItem-icon" }),
|
|
2314
|
+
"Sign out"
|
|
2315
|
+
]
|
|
2316
|
+
}
|
|
2317
|
+
) })
|
|
2318
|
+
] });
|
|
2426
2319
|
}
|
|
2427
2320
|
function Protect({
|
|
2428
2321
|
children,
|
|
@@ -2480,94 +2373,6 @@ function SignedOut({ children }) {
|
|
|
2480
2373
|
}
|
|
2481
2374
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
2482
2375
|
}
|
|
2483
|
-
function InsforgeCallback({
|
|
2484
|
-
redirectTo = "/",
|
|
2485
|
-
onSuccess,
|
|
2486
|
-
onError,
|
|
2487
|
-
loadingComponent,
|
|
2488
|
-
onRedirect
|
|
2489
|
-
}) {
|
|
2490
|
-
const isProcessingRef = react.useRef(false);
|
|
2491
|
-
const { isLoaded, isSignedIn } = useInsforge();
|
|
2492
|
-
react.useEffect(() => {
|
|
2493
|
-
if (!isLoaded) {
|
|
2494
|
-
return;
|
|
2495
|
-
}
|
|
2496
|
-
if (isProcessingRef.current) {
|
|
2497
|
-
return;
|
|
2498
|
-
}
|
|
2499
|
-
isProcessingRef.current = true;
|
|
2500
|
-
const processCallback = () => {
|
|
2501
|
-
const searchParams = new URLSearchParams(window.location.search);
|
|
2502
|
-
const error = searchParams.get("error");
|
|
2503
|
-
if (error) {
|
|
2504
|
-
if (onError) {
|
|
2505
|
-
onError(error);
|
|
2506
|
-
} else {
|
|
2507
|
-
const errorUrl = "/?error=" + encodeURIComponent(error);
|
|
2508
|
-
if (onRedirect) {
|
|
2509
|
-
onRedirect(errorUrl);
|
|
2510
|
-
} else {
|
|
2511
|
-
window.location.href = errorUrl;
|
|
2512
|
-
}
|
|
2513
|
-
}
|
|
2514
|
-
return;
|
|
2515
|
-
}
|
|
2516
|
-
if (!isSignedIn) {
|
|
2517
|
-
const errorMsg = "authentication_failed";
|
|
2518
|
-
if (onError) {
|
|
2519
|
-
onError(errorMsg);
|
|
2520
|
-
} else {
|
|
2521
|
-
const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
|
|
2522
|
-
if (onRedirect) {
|
|
2523
|
-
onRedirect(errorUrl);
|
|
2524
|
-
} else {
|
|
2525
|
-
window.location.href = errorUrl;
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
return;
|
|
2529
|
-
}
|
|
2530
|
-
window.history.replaceState({}, "", window.location.pathname);
|
|
2531
|
-
if (onSuccess) {
|
|
2532
|
-
onSuccess();
|
|
2533
|
-
}
|
|
2534
|
-
if (onRedirect) {
|
|
2535
|
-
onRedirect(redirectTo);
|
|
2536
|
-
} else {
|
|
2537
|
-
window.location.href = redirectTo;
|
|
2538
|
-
}
|
|
2539
|
-
};
|
|
2540
|
-
processCallback();
|
|
2541
|
-
}, [isLoaded, isSignedIn, redirectTo, onSuccess, onError, onRedirect]);
|
|
2542
|
-
const defaultLoading = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2543
|
-
"div",
|
|
2544
|
-
{
|
|
2545
|
-
style: {
|
|
2546
|
-
display: "flex",
|
|
2547
|
-
alignItems: "center",
|
|
2548
|
-
justifyContent: "center",
|
|
2549
|
-
minHeight: "100vh"
|
|
2550
|
-
},
|
|
2551
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
|
|
2552
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "if-authHeader-title", style: { marginBottom: "1rem" }, children: "Completing authentication..." }),
|
|
2553
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2554
|
-
"div",
|
|
2555
|
-
{
|
|
2556
|
-
className: "if-submitButton-spinner",
|
|
2557
|
-
style: {
|
|
2558
|
-
borderRadius: "50%",
|
|
2559
|
-
height: "3rem",
|
|
2560
|
-
width: "3rem",
|
|
2561
|
-
borderBottom: "2px solid #2563EB",
|
|
2562
|
-
margin: "0 auto"
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
)
|
|
2566
|
-
] })
|
|
2567
|
-
}
|
|
2568
|
-
);
|
|
2569
|
-
return loadingComponent || defaultLoading;
|
|
2570
|
-
}
|
|
2571
2376
|
|
|
2572
2377
|
// src/hooks/useAuth.ts
|
|
2573
2378
|
function useAuth() {
|
|
@@ -2582,9 +2387,9 @@ function useUser() {
|
|
|
2582
2387
|
}
|
|
2583
2388
|
function RedirectToAuth({ baseUrl, path }) {
|
|
2584
2389
|
react.useEffect(() => {
|
|
2585
|
-
const
|
|
2390
|
+
const currentUrl = window.location.href;
|
|
2586
2391
|
const authUrl = new URL(path, baseUrl);
|
|
2587
|
-
authUrl.searchParams.set("redirect",
|
|
2392
|
+
authUrl.searchParams.set("redirect", currentUrl);
|
|
2588
2393
|
window.location.replace(authUrl.toString());
|
|
2589
2394
|
}, [baseUrl, path]);
|
|
2590
2395
|
return null;
|
|
@@ -2638,11 +2443,11 @@ exports.AuthOAuthButton = AuthOAuthButton;
|
|
|
2638
2443
|
exports.AuthOAuthProviders = AuthOAuthProviders;
|
|
2639
2444
|
exports.AuthPasswordField = AuthPasswordField;
|
|
2640
2445
|
exports.AuthPasswordStrengthIndicator = AuthPasswordStrengthIndicator;
|
|
2446
|
+
exports.AuthResetPasswordVerificationStep = AuthResetPasswordVerificationStep;
|
|
2641
2447
|
exports.AuthSubmitButton = AuthSubmitButton;
|
|
2642
2448
|
exports.AuthVerificationCodeInput = AuthVerificationCodeInput;
|
|
2643
2449
|
exports.ForgotPassword = ForgotPassword;
|
|
2644
2450
|
exports.ForgotPasswordForm = ForgotPasswordForm;
|
|
2645
|
-
exports.InsforgeCallback = InsforgeCallback;
|
|
2646
2451
|
exports.InsforgeProvider = InsforgeProvider;
|
|
2647
2452
|
exports.OAUTH_PROVIDER_CONFIG = OAUTH_PROVIDER_CONFIG;
|
|
2648
2453
|
exports.Protect = Protect;
|