@insforge/react 0.4.0 → 0.4.5

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