From c1d0fdf99bd62298b034886b3d22c9ebe7156903 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Yadav Date: Thu, 11 Jun 2026 18:57:01 +0530 Subject: [PATCH 1/4] fix: improve auth UI customization options in react sdk --- examples/react-sdk-demo/src/App.tsx | 24 +- package-lock.json | 26 - sdks/urbackend-react/dist/index.d.mts | 69 ++- sdks/urbackend-react/dist/index.d.ts | 69 ++- sdks/urbackend-react/dist/index.js | 301 +++++++--- sdks/urbackend-react/dist/index.js.map | 2 +- sdks/urbackend-react/dist/index.mjs | 303 +++++++--- sdks/urbackend-react/dist/index.mjs.map | 2 +- .../urbackend-react/src/components/UrAuth.tsx | 562 +++++++++++++----- sdks/urbackend-react/tests/UrAuth.test.tsx | 45 +- 10 files changed, 1049 insertions(+), 354 deletions(-) diff --git a/examples/react-sdk-demo/src/App.tsx b/examples/react-sdk-demo/src/App.tsx index a7e74f01..08fc8d4f 100644 --- a/examples/react-sdk-demo/src/App.tsx +++ b/examples/react-sdk-demo/src/App.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { UrAuth, ProtectedRoute, GuestRoute, useUser, UrUserButton } from '@urbackend/react'; +import { UrAuth, ProtectedRoute, GuestRoute, useUser, useAuth, UrUserButton } from '@urbackend/react'; import './App.css'; // Mini router component for the demo @@ -28,7 +28,22 @@ function App() { return ( navigate('/')}>
- +
); @@ -43,7 +58,8 @@ function App() { } function Dashboard() { - const { user, logout } = useUser(); + const { user } = useUser(); + const { logout } = useAuth(); return (
@@ -67,7 +83,7 @@ function Dashboard() {
{user?.avatarUrl ? ( - Avatar + Avatar ) : (
{user?.name?.[0]?.toUpperCase() || user?.email?.[0]?.toUpperCase()} diff --git a/package-lock.json b/package-lock.json index 76c104f7..8df804eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2909,7 +2909,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2943,7 +2942,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2977,7 +2975,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3043,7 +3040,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6876,7 +6872,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6893,7 +6888,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6910,7 +6904,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6927,7 +6920,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6944,7 +6936,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6961,7 +6952,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6978,7 +6968,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6995,7 +6984,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7012,7 +7000,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7029,7 +7016,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7046,7 +7032,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7063,7 +7048,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7080,7 +7064,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7097,7 +7080,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7114,7 +7096,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7131,7 +7112,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7148,7 +7128,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7165,7 +7144,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7182,7 +7160,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7199,7 +7176,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7216,7 +7192,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7233,7 +7208,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ diff --git a/sdks/urbackend-react/dist/index.d.mts b/sdks/urbackend-react/dist/index.d.mts index b13ac82b..0ef81d52 100644 --- a/sdks/urbackend-react/dist/index.d.mts +++ b/sdks/urbackend-react/dist/index.d.mts @@ -83,9 +83,74 @@ interface GuestRouteProps { */ declare const GuestRoute: React.FC; +type AuthProvider = 'google' | 'github'; +type ThemeMode = 'light' | 'dark'; +interface AuthColors { + background: string; + surface: string; + text: string; + textMuted: string; + border: string; + inputBackground: string; + primary: string; + primaryText: string; + footerBackground: string; + dividerText: string; + socialButtonBackground: string; +} +interface AuthBranding { + brandName?: string; + appName?: string; + title?: string; + subtitle?: string; + logo?: React.ReactNode | string; + primaryColor?: string; +} +interface AuthLabels { + loginTab: string; + signupTab: string; + loginTitle: string; + signupTitle: string; + forgotTitle: string; + resetTitle: string; + loginButton: string; + signupButton: string; + forgotButton: string; + resetButton: string; + emailLabel: string; + emailPlaceholder: string; + passwordLabel: string; + passwordPlaceholder: string; + nameLabel: string; + namePlaceholder: string; + otpLabel: string; + otpPlaceholder: string; + forgotPasswordLink: string; + socialDivider: string; + googleButton: string; + githubButton: string; + footerSigninPrompt: string; + footerSignupPrompt: string; + footerForgotPrompt: string; + noAuthMethods: string; + signInTitle?: string; + signUpTitle?: string; + signInTab?: string; + signUpTab?: string; + signInButton?: string; + signUpButton?: string; +} interface UrAuthProps { - providers?: ('google' | 'github')[]; - theme?: 'light' | 'dark'; + providers?: AuthProvider[] | { + google?: boolean; + github?: boolean; + emailPassword?: boolean; + }; + enableEmailPassword?: boolean; + theme?: ThemeMode; + colors?: Partial; + branding?: AuthBranding; + labels?: Partial; onSuccess?: () => void; } declare const UrAuth: React.FC; diff --git a/sdks/urbackend-react/dist/index.d.ts b/sdks/urbackend-react/dist/index.d.ts index b13ac82b..0ef81d52 100644 --- a/sdks/urbackend-react/dist/index.d.ts +++ b/sdks/urbackend-react/dist/index.d.ts @@ -83,9 +83,74 @@ interface GuestRouteProps { */ declare const GuestRoute: React.FC; +type AuthProvider = 'google' | 'github'; +type ThemeMode = 'light' | 'dark'; +interface AuthColors { + background: string; + surface: string; + text: string; + textMuted: string; + border: string; + inputBackground: string; + primary: string; + primaryText: string; + footerBackground: string; + dividerText: string; + socialButtonBackground: string; +} +interface AuthBranding { + brandName?: string; + appName?: string; + title?: string; + subtitle?: string; + logo?: React.ReactNode | string; + primaryColor?: string; +} +interface AuthLabels { + loginTab: string; + signupTab: string; + loginTitle: string; + signupTitle: string; + forgotTitle: string; + resetTitle: string; + loginButton: string; + signupButton: string; + forgotButton: string; + resetButton: string; + emailLabel: string; + emailPlaceholder: string; + passwordLabel: string; + passwordPlaceholder: string; + nameLabel: string; + namePlaceholder: string; + otpLabel: string; + otpPlaceholder: string; + forgotPasswordLink: string; + socialDivider: string; + googleButton: string; + githubButton: string; + footerSigninPrompt: string; + footerSignupPrompt: string; + footerForgotPrompt: string; + noAuthMethods: string; + signInTitle?: string; + signUpTitle?: string; + signInTab?: string; + signUpTab?: string; + signInButton?: string; + signUpButton?: string; +} interface UrAuthProps { - providers?: ('google' | 'github')[]; - theme?: 'light' | 'dark'; + providers?: AuthProvider[] | { + google?: boolean; + github?: boolean; + emailPassword?: boolean; + }; + enableEmailPassword?: boolean; + theme?: ThemeMode; + colors?: Partial; + branding?: AuthBranding; + labels?: Partial; onSuccess?: () => void; } declare const UrAuth: React.FC; diff --git a/sdks/urbackend-react/dist/index.js b/sdks/urbackend-react/dist/index.js index 9444079b..fc9479aa 100644 --- a/sdks/urbackend-react/dist/index.js +++ b/sdks/urbackend-react/dist/index.js @@ -410,9 +410,69 @@ var Toast = ({ message, type, onClose, isDark = false }) => { // src/components/UrAuth.tsx var import_jsx_runtime4 = require("react/jsx-runtime"); +var defaultLabels = { + loginTab: "Login", + signupTab: "Sign Up", + loginTitle: "Welcome back", + signupTitle: "Create your account", + forgotTitle: "Reset Password", + resetTitle: "Enter Reset Code", + loginButton: "Log In", + signupButton: "Create Account", + forgotButton: "Send Reset Code", + resetButton: "Reset Password", + emailLabel: "Email address", + emailPlaceholder: "Enter your email address", + passwordLabel: "Password", + passwordPlaceholder: "Enter your password", + nameLabel: "Full Name", + namePlaceholder: "Enter your name", + otpLabel: "6-digit OTP Code", + otpPlaceholder: "Enter reset code", + forgotPasswordLink: "Forgot password?", + socialDivider: "OR", + googleButton: "Continue with Google", + githubButton: "Continue with GitHub", + footerSigninPrompt: "Don't have an account yet?", + footerSignupPrompt: "Already have an account?", + footerForgotPrompt: "Remember your password?", + noAuthMethods: "No authentication methods are enabled for this screen." +}; +var defaultThemeColors = { + light: { + background: "#ffffff", + surface: "#ffffff", + text: "#0f172a", + textMuted: "#64748b", + border: "#e2e8f0", + inputBackground: "#ffffff", + primary: "#111111", + primaryText: "#ffffff", + footerBackground: "#f8fafc", + dividerText: "#94a3b8", + socialButtonBackground: "#ffffff" + }, + dark: { + background: "#1a1a1a", + surface: "#1a1a1a", + text: "#ffffff", + textMuted: "#a1a1aa", + border: "#333333", + inputBackground: "#2a2a2a", + primary: "#ffffff", + primaryText: "#111111", + footerBackground: "#222222", + dividerText: "#94a3b8", + socialButtonBackground: "#2a2a2a" + } +}; var UrAuth = ({ providers = ["google", "github"], + enableEmailPassword = true, theme = "light", + colors, + branding, + labels, onSuccess }) => { const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth(); @@ -422,11 +482,47 @@ var UrAuth = ({ const [otp, setOtp] = (0, import_react5.useState)(""); const [name, setName] = (0, import_react5.useState)(""); const [toast, setToast] = (0, import_react5.useState)(null); + const text = { + ...defaultLabels, + ...labels, + loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab, + loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle, + loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton, + signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab, + signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle, + signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton + }; + const themeColors = { ...defaultThemeColors[theme], ...colors }; + const primaryColor = branding?.primaryColor || themeColors.primary; + let isGoogleEnabled = true; + let isGithubEnabled = true; + let isEmailPasswordEnabled = enableEmailPassword; + if (providers) { + if (Array.isArray(providers)) { + isGoogleEnabled = providers.includes("google"); + isGithubEnabled = providers.includes("github"); + } else if (typeof providers === "object") { + isGoogleEnabled = !!providers.google; + isGithubEnabled = !!providers.github; + isEmailPasswordEnabled = providers.emailPassword !== void 0 ? providers.emailPassword : false; + } + } + const hasPasswordAuth = isEmailPasswordEnabled; + const hasSocialAuth = isGoogleEnabled || isGithubEnabled; + const brandName = branding?.brandName || branding?.appName || branding?.title || "urBackend"; + const headerTitle = branding?.title || brandName; + const headerSubtitle = branding?.subtitle || (mode === "signin" ? text.loginTitle : mode === "signup" ? text.signupTitle : mode === "forgot" ? text.forgotTitle : text.resetTitle); + const showSwitcher = hasPasswordAuth; (0, import_react5.useEffect)(() => { if (error) { setToast({ message: error, type: "error" }); } }, [error]); + (0, import_react5.useEffect)(() => { + if (!hasPasswordAuth && mode !== "signin") { + setMode("signin"); + } + }, [hasPasswordAuth, mode]); const handleSubmit = async (e) => { e.preventDefault(); try { @@ -453,28 +549,58 @@ var UrAuth = ({ } catch (err) { } }; - const isDark = theme === "dark"; - const bg = isDark ? "#1a1a1a" : "#ffffff"; - const text = isDark ? "#ffffff" : "#0f172a"; - const textMuted = isDark ? "#a1a1aa" : "#64748b"; - const border = isDark ? "#333" : "#e2e8f0"; - const inputBg = isDark ? "#2a2a2a" : "#ffffff"; const styles = { wrapper: { width: "100%", maxWidth: "420px", margin: "0 auto", borderRadius: "0", - background: bg, - boxShadow: isDark ? "0 20px 40px rgba(0,0,0,0.5)" : "0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)", - border: `1px solid ${border}`, + background: themeColors.background, + boxShadow: theme === "dark" ? "0 20px 40px rgba(0,0,0,0.5)" : "0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)", + border: `1px solid ${themeColors.border}`, overflow: "hidden", fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', - color: text + color: themeColors.text }, body: { padding: "32px 32px 24px 32px" }, + header: { + textAlign: "center", + marginBottom: "28px" + }, + brandRow: { + display: "flex", + justifyContent: "center", + alignItems: "center", + gap: "12px", + marginBottom: "10px" + }, + brandLogo: { + width: "44px", + height: "44px", + borderRadius: "12px", + display: "inline-flex", + alignItems: "center", + justifyContent: "center", + background: theme === "dark" ? "#2a2a2a" : "#f1f5f9", + color: themeColors.text, + overflow: "hidden" + }, + brandTitle: { + margin: 0, + fontSize: "26px", + lineHeight: 1.1, + fontWeight: 800, + color: themeColors.text + }, + brandSubtitle: { + margin: "0 auto", + maxWidth: "320px", + fontSize: "14px", + lineHeight: 1.5, + color: themeColors.textMuted + }, switcherContainer: { display: "flex", alignItems: "center", @@ -483,7 +609,7 @@ var UrAuth = ({ }, switcher: { display: "inline-flex", - background: isDark ? "#2a2a2a" : "#f1f5f9", + background: theme === "dark" ? "#2a2a2a" : "#f1f5f9", padding: "4px", borderRadius: "0" }, @@ -496,9 +622,9 @@ var UrAuth = ({ fontSize: "13px", fontWeight: 600, cursor: "pointer", - color: active ? text : textMuted, - background: active ? isDark ? "#444" : "#ffffff" : "transparent", - boxShadow: active ? isDark ? "0 2px 4px rgba(0,0,0,0.2)" : "0 2px 8px rgba(0,0,0,0.05)" : "none", + color: active ? themeColors.text : themeColors.textMuted, + background: active ? theme === "dark" ? "#444444" : "#ffffff" : "transparent", + boxShadow: active ? theme === "dark" ? "0 2px 4px rgba(0,0,0,0.2)" : "0 2px 8px rgba(0,0,0,0.05)" : "none", border: "none", transition: "all 0.2s ease" }), @@ -514,12 +640,12 @@ var UrAuth = ({ label: { fontSize: "13px", fontWeight: 600, - color: isDark ? "#ddd" : "#334155" + color: theme === "dark" ? "#dddddd" : "#334155" }, forgotLink: { fontSize: "12px", fontWeight: 600, - color: text, + color: themeColors.text, cursor: "pointer", textDecoration: "none", background: "none", @@ -530,9 +656,9 @@ var UrAuth = ({ width: "100%", padding: "12px 16px", borderRadius: "0", - border: `1px solid ${border}`, - background: inputBg, - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.inputBackground, + color: themeColors.text, fontSize: "14px", boxSizing: "border-box", outline: "none", @@ -542,8 +668,8 @@ var UrAuth = ({ width: "100%", padding: "14px", borderRadius: "0", - background: "linear-gradient(180deg, #2a2a2a 0%, #111111 100%)", - color: "#ffffff", + background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === "dark" ? "#111111" : "#111111"} 100%)`, + color: themeColors.primaryText, fontSize: "15px", fontWeight: 600, border: "none", @@ -556,7 +682,7 @@ var UrAuth = ({ display: "flex", alignItems: "center", margin: "24px 0", - color: "#94a3b8", + color: themeColors.dividerText, fontSize: "11px", fontWeight: 600, letterSpacing: "1px" @@ -564,7 +690,7 @@ var UrAuth = ({ dividerLine: { flex: 1, height: "1px", - background: border + background: themeColors.border }, dividerText: { padding: "0 12px" @@ -573,9 +699,9 @@ var UrAuth = ({ width: "100%", padding: "12px", borderRadius: "0", - border: `1px solid ${border}`, - background: isDark ? "#2a2a2a" : "#ffffff", - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.socialButtonBackground, + color: themeColors.text, fontSize: "14px", fontWeight: 600, display: "flex", @@ -584,19 +710,19 @@ var UrAuth = ({ gap: "10px", marginBottom: "12px", cursor: "pointer", - boxShadow: isDark ? "none" : "0 1px 2px rgba(0,0,0,0.02)", + boxShadow: theme === "dark" ? "none" : "0 1px 2px rgba(0,0,0,0.02)", transition: "background 0.2s ease" }, footer: { - background: isDark ? "#222" : "#f8fafc", + background: themeColors.footerBackground, padding: "24px", textAlign: "center", - borderTop: `1px solid ${border}`, + borderTop: `1px solid ${themeColors.border}`, fontSize: "13px", - color: textMuted + color: themeColors.textMuted }, footerLink: { - color: text, + color: themeColors.text, fontWeight: 600, textDecoration: "underline", cursor: "pointer", @@ -612,14 +738,37 @@ var UrAuth = ({ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" }) ] }); - const GithubIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: isDark ? "#fff" : "#000", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" }) }); + const GithubIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: theme === "dark" ? "#fff" : "#000", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" }) }); + const renderSocialButtons = () => { + if (!hasSocialAuth) { + return null; + } + return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [ + hasPasswordAuth && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.divider, children: [ + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.dividerLine }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles.dividerText, children: text.socialDivider }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.dividerLine }) + ] }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [ + isGoogleEnabled && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { style: styles.socialBtn, onClick: () => socialLogin("google"), type: "button", children: [ + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GoogleIcon, {}), + text.googleButton + ] }), + isGithubEnabled && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { style: styles.socialBtn, onClick: () => socialLogin("github"), type: "button", children: [ + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GithubIcon, {}), + text.githubButton + ] }) + ] }) + ] }); + }; + const footerPrompt = mode === "signin" ? text.footerSigninPrompt : mode === "signup" ? text.footerSignupPrompt : text.footerForgotPrompt; return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.wrapper, children: [ toast && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( Toast, { message: toast.message, type: toast.type, - isDark, + isDark: theme === "dark", onClose: () => { setToast(null); if (toast.type === "error") clearError(); @@ -627,7 +776,12 @@ var UrAuth = ({ } ), /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.body, children: [ - (mode === "signin" || mode === "signup") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.switcherContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.switcher, children: [ + (branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.header, children: [ + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.brandRow, children: branding?.logo ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.brandLogo, children: typeof branding.logo === "string" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: branding.logo, alt: brandName, style: { width: "100%", height: "100%", objectFit: "contain" } }) : branding.logo }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.brandLogo, "aria-hidden": "true", children: brandName.slice(0, 1).toUpperCase() }) }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { style: styles.brandTitle, children: headerTitle }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: styles.brandSubtitle, children: headerSubtitle }) + ] }), + showSwitcher && (mode === "signin" || mode === "signup") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.switcherContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.switcher, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( "button", { @@ -643,7 +797,7 @@ var UrAuth = ({ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "10 17 15 12 10 7" }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "15", y1: "12", x2: "3", y2: "12" }) ] }), - "Login" + text.loginTab ] } ), @@ -663,24 +817,25 @@ var UrAuth = ({ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "19", y1: "8", x2: "19", y2: "14" }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "22", y1: "11", x2: "16", y2: "11" }) ] }), - "Sign Up" + text.signupTab ] } ) ] }) }), (mode === "forgot" || mode === "reset") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { style: { margin: "0 0 8px", fontSize: "20px", fontWeight: 700, color: text }, children: mode === "forgot" ? "Reset Password" : "Enter Reset Code" }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { margin: 0, fontSize: "14px", color: textMuted }, children: mode === "forgot" ? "Enter your email and we'll send a code" : `Enter the code sent to ${email}` }) + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { style: { margin: "0 0 8px", fontSize: "20px", fontWeight: 700, color: themeColors.text }, children: mode === "forgot" ? text.forgotTitle : text.resetTitle }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { margin: 0, fontSize: "14px", color: themeColors.textMuted }, children: mode === "forgot" ? text.loginTitle : `Enter the code sent to ${email}` }) ] }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { onSubmit: handleSubmit, children: [ + !hasPasswordAuth && !hasSocialAuth && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { textAlign: "center", color: themeColors.textMuted, fontSize: "14px", lineHeight: 1.5 }, children: text.noAuthMethods }), + hasPasswordAuth && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { onSubmit: handleSubmit, children: [ mode === "signup" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.field, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: "Full Name" }) }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: text.nameLabel }) }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "input", { style: styles.input, type: "text", - placeholder: "Enter your name", + placeholder: text.namePlaceholder, value: name, onChange: (e) => setName(e.target.value), required: true @@ -688,13 +843,13 @@ var UrAuth = ({ ) ] }), /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.field, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: "Email address" }) }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: text.emailLabel }) }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "input", { style: styles.input, type: "email", - placeholder: "Enter your email address", + placeholder: text.emailPlaceholder, value: email, onChange: (e) => setEmail(e.target.value), required: true, @@ -702,40 +857,40 @@ var UrAuth = ({ } ) ] }), - mode === "reset" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.field, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: "6-digit OTP Code" }) }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( - "input", - { - style: styles.input, - type: "text", - placeholder: "Enter reset code", - value: otp, - onChange: (e) => setOtp(e.target.value), - required: true - } - ) - ] }), (mode === "signin" || mode === "signup" || mode === "reset") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.field, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.labelRow, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: mode === "reset" ? "New Password" : "Password" }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: mode === "reset" ? text.passwordLabel : text.passwordLabel }), mode === "signin" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", style: styles.forgotLink, onClick: () => { setMode("forgot"); clearError(); - }, children: "Forgot password?" }) + }, children: text.forgotPasswordLink }) ] }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "input", { style: styles.input, type: "password", - placeholder: mode === "reset" ? "Enter new password" : "Enter your password", + placeholder: text.passwordPlaceholder, value: password, onChange: (e) => setPassword(e.target.value), required: true } ) ] }), + mode === "reset" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.field, children: [ + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.labelRow, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: styles.label, children: text.otpLabel }) }), + /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( + "input", + { + style: styles.input, + type: "text", + placeholder: text.otpPlaceholder, + value: otp, + onChange: (e) => setOtp(e.target.value), + required: true + } + ) + ] }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "button", { @@ -745,30 +900,14 @@ var UrAuth = ({ onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.98)", onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)", onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)", - children: isLoading ? "Processing..." : mode === "signin" ? "Log In" : mode === "signup" ? "Create Account" : mode === "forgot" ? "Send Reset Code" : "Reset Password" + children: isLoading ? "Processing..." : mode === "signin" ? text.loginButton : mode === "signup" ? text.signupButton : mode === "forgot" ? text.forgotButton : text.resetButton } ) ] }), - (mode === "signin" || mode === "signup") && providers && providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.divider, children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.dividerLine }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles.dividerText, children: "OR" }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles.dividerLine }) - ] }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [ - providers.includes("google") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { style: styles.socialBtn, onClick: () => socialLogin("google"), type: "button", children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GoogleIcon, {}), - "Continue with Google" - ] }), - providers.includes("github") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { style: styles.socialBtn, onClick: () => socialLogin("github"), type: "button", children: [ - /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GithubIcon, {}), - "Continue with GitHub" - ] }) - ] }) - ] }) + (mode === "signin" || mode === "signup") && renderSocialButtons() ] }), - /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.footer, children: [ - mode === "signin" ? "Don't have an account yet?" : mode === "signup" ? "Already have an account?" : "Remember your password?", + hasPasswordAuth && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.footer, children: [ + footerPrompt, /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "button", { @@ -778,7 +917,7 @@ var UrAuth = ({ setMode(mode === "signin" ? "signup" : "signin"); clearError(); }, - children: mode === "signin" ? "Sign up" : "Log in" + children: mode === "signin" ? text.signupTab : text.loginTab } ) ] }) diff --git a/sdks/urbackend-react/dist/index.js.map b/sdks/urbackend-react/dist/index.js.map index 258422d7..0e3b78de 100644 --- a/sdks/urbackend-react/dist/index.js.map +++ b/sdks/urbackend-react/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.ts","../src/context.tsx","../src/hooks.ts","../src/components.tsx","../src/components/UrAuth.tsx","../src/components/Toast.tsx","../src/components/UrUserButton.tsx"],"sourcesContent":["export { UrProvider, useUrContext } from './context';\nexport type { UrProviderProps } from './context';\n\nexport { useAuth, useUser, useDb, useStorage } from './hooks';\nexport { ProtectedRoute, GuestRoute } from './components';\nexport type { ProtectedRouteProps, GuestRouteProps } from './components';\n\nexport { UrAuth } from './components/UrAuth';\nexport type { UrAuthProps } from './components/UrAuth';\n\nexport * from './components/UrUserButton';\n\nexport * from '@urbackend/sdk'; // re-export types so users don't need to import from sdk directly","import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\r\nimport { UrBackendClient, AuthModule, DatabaseModule, StorageModule } from '@urbackend/sdk';\r\nimport type { AuthUser } from '@urbackend/sdk';\r\n\r\ninterface UrContextValue {\r\n client: UrBackendClient | null;\r\n auth: AuthModule | null;\r\n db: DatabaseModule | null;\r\n storage: StorageModule | null;\r\n user: AuthUser | null;\r\n setUser: React.Dispatch>;\r\n isInitializing: boolean;\r\n isLoading: boolean;\r\n setIsLoading: React.Dispatch>;\r\n error: string | null;\r\n setError: React.Dispatch>;\r\n}\r\n\r\nconst UrContext = createContext(undefined);\r\n\r\nexport interface UrProviderProps {\r\n apiKey: string;\r\n baseUrl?: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const UrProvider: React.FC = ({ apiKey, baseUrl, children }) => {\r\n const [user, setUser] = useState(null);\r\n const [isInitializing, setIsInitializing] = useState(true);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState(null);\r\n\r\n const { client, auth, db, storage } = useMemo(() => {\r\n const _client = new UrBackendClient({ apiKey, baseUrl });\r\n return {\r\n client: _client,\r\n auth: new AuthModule(_client),\r\n db: new DatabaseModule(_client),\r\n storage: new StorageModule(_client),\r\n };\r\n }, [apiKey, baseUrl]);\r\n\r\n useEffect(() => {\r\n let mounted = true;\r\n\r\n const initAuth = async () => {\r\n try {\r\n // Hydrate from localStorage first as a fallback for environments without cookies\r\n if (typeof window !== 'undefined') {\r\n const savedToken = localStorage.getItem('ur_auth_token');\r\n if (savedToken) auth.setToken(savedToken);\r\n }\r\n\r\n // Check for social auth callback params\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n const token = hashParams.get('token');\r\n const rtCode = urlParams.get('rtCode');\r\n const error = urlParams.get('error');\r\n\r\n if (error) {\r\n console.error('Social Auth Error:', error);\r\n if (mounted) setError(error);\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else if (token) {\r\n // Social auth succeeded, establish session immediately\r\n auth.setToken(token);\r\n if (typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n \r\n if (rtCode) {\r\n // Exchange for long-lived refresh token\r\n try {\r\n const exRes = await auth.socialExchange({ token, rtCode });\r\n const exToken = (exRes as any).accessToken || (exRes as any).token;\r\n if (exToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', exToken);\r\n } catch (err: any) {\r\n console.error('Failed to exchange refresh token', err);\r\n if (mounted) setError(err.message || 'Failed to complete social login');\r\n throw err;\r\n }\r\n }\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else {\r\n // Attempt to silently refresh session using the HTTP-only cookie\r\n try {\r\n const res = await auth.refreshToken();\r\n const newToken = res.accessToken || (res as any).token;\r\n if (newToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', newToken);\r\n } catch (e) {\r\n // If refresh fails, me() will catch it\r\n }\r\n }\r\n \r\n const currentUser = await auth.me();\r\n if (mounted) {\r\n setUser(currentUser);\r\n }\r\n } catch (error: any) {\r\n if (mounted) {\r\n setUser(null);\r\n // Don't set global error for initial me() check failure (usually just means not logged in)\r\n }\r\n } finally {\r\n if (mounted) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n };\r\n\r\n initAuth();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [auth]);\r\n\r\n const value: UrContextValue = {\r\n client,\r\n auth,\r\n db,\r\n storage,\r\n user,\r\n setUser,\r\n isInitializing,\r\n isLoading,\r\n setIsLoading,\r\n error,\r\n setError,\r\n };\r\n\r\n return {children};\r\n};\r\n\r\nexport const useUrContext = () => {\r\n const context = useContext(UrContext);\r\n if (!context) {\r\n throw new Error('useUrContext must be used within an UrProvider');\r\n }\r\n return context;\r\n};\r\n","import { useCallback } from 'react';\r\nimport { useUrContext } from './context';\r\nimport type { \r\n LoginPayload, \r\n SignUpPayload, \r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload\r\n} from '@urbackend/sdk';\r\n\r\nexport const useAuth = () => {\r\n const { auth, user, setUser, isInitializing, isLoading, setIsLoading, error, setError } = useUrContext();\r\n\r\n if (!auth) {\r\n throw new Error('Auth module not initialized. Make sure you are inside UrProvider.');\r\n }\r\n\r\n const login = useCallback(async (payload: LoginPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const res = await auth.login(payload);\r\n const token = res.accessToken || (res as any).token;\r\n if (token && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n const currentUser = await auth.me();\r\n setUser(currentUser);\r\n } catch (err: any) {\r\n setError(err.message || 'Login failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const signUp = useCallback(async (payload: SignUpPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const newUser = await auth.signUp(payload);\r\n return newUser;\r\n } catch (err: any) {\r\n setError(err.message || 'Sign up failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setIsLoading, setError]);\r\n\r\n const logout = useCallback(async () => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n await auth.logout();\r\n if (typeof window !== 'undefined') localStorage.removeItem('ur_auth_token');\r\n setUser(null);\r\n } catch (err: any) {\r\n setError(err.message || 'Logout failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const socialLogin = useCallback((provider: 'google' | 'github') => {\r\n setError(null);\r\n const url = auth.socialStart(provider);\r\n window.location.href = url;\r\n }, [auth, setError]);\r\n \r\n const verifyEmail = useCallback(async (payload: VerifyEmailPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.verifyEmail(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Email verification failed');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const changePassword = useCallback(async (payload: ChangePasswordPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.changePassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to change password');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const requestPasswordReset = useCallback(async (payload: RequestPasswordResetPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.requestPasswordReset(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to request password reset');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const resetPassword = useCallback(async (payload: ResetPasswordPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.resetPassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to reset password');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const clearError = useCallback(() => setError(null), [setError]);\r\n\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n login,\r\n signUp,\r\n logout,\r\n socialLogin,\r\n verifyEmail,\r\n changePassword,\r\n requestPasswordReset,\r\n resetPassword,\r\n clearError,\r\n authApi: auth // Escape hatch to underlying SDK\r\n };\r\n};\r\n\r\nexport const useUser = () => {\r\n const { user, isInitializing, isLoading, error } = useUrContext();\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n };\r\n};\r\n\r\nexport const useDb = () => {\r\n const { db } = useUrContext();\r\n if (!db) {\r\n throw new Error('Database module not initialized.');\r\n }\r\n return db;\r\n};\r\n\r\nexport const useStorage = () => {\r\n const { storage } = useUrContext();\r\n if (!storage) {\r\n throw new Error('Storage module not initialized.');\r\n }\r\n return storage;\r\n};\r\n","import React, { useEffect } from 'react';\r\nimport { useUser } from './hooks';\r\n\r\nexport interface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to be authenticated.\r\n * If the user is not authenticated after initialization, they will be redirected,\r\n * or the fallback will be rendered (or nothing if fallback is not provided and no window redirect occurs).\r\n */\r\nexport const ProtectedRoute: React.FC = ({ \r\n children, \r\n redirectTo = '/login', \r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && !isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (!isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n\r\nexport interface GuestRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to NOT be authenticated (e.g. for Login pages).\r\n * If the user IS authenticated, they will be redirected to the specified route.\r\n */\r\nexport const GuestRoute: React.FC = ({\r\n children,\r\n redirectTo = '/dashboard',\r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n","import React, { useState, useEffect } from 'react';\r\nimport { useAuth } from '../hooks';\r\nimport { Toast } from './Toast';\r\n\r\nexport interface UrAuthProps {\r\n providers?: ('google' | 'github')[];\r\n theme?: 'light' | 'dark'; // Dark mode not perfectly matched to image, but kept for API compat\r\n onSuccess?: () => void;\r\n}\r\n\r\nexport const UrAuth: React.FC = ({ \r\n providers = ['google', 'github'], \r\n theme = 'light',\r\n onSuccess\r\n}) => {\r\n const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth();\r\n const [mode, setMode] = useState<'signin' | 'signup' | 'forgot' | 'reset'>('signin');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [otp, setOtp] = useState('');\r\n const [name, setName] = useState('');\r\n const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null);\r\n\r\n useEffect(() => {\r\n if (error) {\r\n setToast({ message: error, type: 'error' });\r\n }\r\n }, [error]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n if (mode === 'signin') {\r\n await login({ email, password });\r\n setToast({ message: 'Welcome back!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'signup') {\r\n await signUp({ email, password, name });\r\n // Auto-login after signup for convenience\r\n await login({ email, password });\r\n setToast({ message: 'Account created successfully!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'forgot') {\r\n await requestPasswordReset({ email });\r\n setToast({ message: 'Reset code sent to your email', type: 'success' });\r\n setMode('reset');\r\n } else if (mode === 'reset') {\r\n await resetPassword({ email, otp, newPassword: password });\r\n setToast({ message: 'Password reset successfully', type: 'success' });\r\n setMode('signin');\r\n setPassword('');\r\n setOtp('');\r\n }\r\n } catch (err: any) {\r\n // Error is now handled and stored globally by useAuth hook, which triggers the useEffect toast\r\n }\r\n };\r\n\r\n const isDark = theme === 'dark';\r\n const bg = isDark ? '#1a1a1a' : '#ffffff';\r\n const text = isDark ? '#ffffff' : '#0f172a';\r\n const textMuted = isDark ? '#a1a1aa' : '#64748b';\r\n const border = isDark ? '#333' : '#e2e8f0';\r\n const inputBg = isDark ? '#2a2a2a' : '#ffffff';\r\n \r\n const styles = {\r\n wrapper: {\r\n width: '100%',\r\n maxWidth: '420px',\r\n margin: '0 auto',\r\n borderRadius: '0',\r\n background: bg,\r\n boxShadow: isDark ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)',\r\n border: `1px solid ${border}`,\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n color: text,\r\n },\r\n body: {\r\n padding: '32px 32px 24px 32px',\r\n },\r\n switcherContainer: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n marginBottom: '32px'\r\n },\r\n switcher: {\r\n display: 'inline-flex',\r\n background: isDark ? '#2a2a2a' : '#f1f5f9',\r\n padding: '4px',\r\n borderRadius: '0',\r\n },\r\n switchBtn: (active: boolean) => ({\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '8px 20px',\r\n borderRadius: '0',\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n color: active ? text : textMuted,\r\n background: active ? (isDark ? '#444' : '#ffffff') : 'transparent',\r\n boxShadow: active ? (isDark ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none',\r\n border: 'none',\r\n transition: 'all 0.2s ease',\r\n }),\r\n field: {\r\n marginBottom: '20px',\r\n },\r\n labelRow: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '8px',\r\n },\r\n label: {\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n color: isDark ? '#ddd' : '#334155',\r\n },\r\n forgotLink: {\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n color: text,\r\n cursor: 'pointer',\r\n textDecoration: 'none',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n },\r\n input: {\r\n width: '100%',\r\n padding: '12px 16px',\r\n borderRadius: '0',\r\n border: `1px solid ${border}`,\r\n background: inputBg,\r\n color: text,\r\n fontSize: '14px',\r\n boxSizing: 'border-box' as const,\r\n outline: 'none',\r\n transition: 'border-color 0.2s ease',\r\n },\r\n primaryBtn: {\r\n width: '100%',\r\n padding: '14px',\r\n borderRadius: '0',\r\n background: 'linear-gradient(180deg, #2a2a2a 0%, #111111 100%)',\r\n color: '#ffffff',\r\n fontSize: '15px',\r\n fontWeight: 600,\r\n border: 'none',\r\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n transition: 'transform 0.1s ease',\r\n },\r\n divider: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n margin: '24px 0',\r\n color: '#94a3b8',\r\n fontSize: '11px',\r\n fontWeight: 600,\r\n letterSpacing: '1px',\r\n },\r\n dividerLine: {\r\n flex: 1,\r\n height: '1px',\r\n background: border,\r\n },\r\n dividerText: {\r\n padding: '0 12px',\r\n },\r\n socialBtn: {\r\n width: '100%',\r\n padding: '12px',\r\n borderRadius: '0',\r\n border: `1px solid ${border}`,\r\n background: isDark ? '#2a2a2a' : '#ffffff',\r\n color: text,\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n gap: '10px',\r\n marginBottom: '12px',\r\n cursor: 'pointer',\r\n boxShadow: isDark ? 'none' : '0 1px 2px rgba(0,0,0,0.02)',\r\n transition: 'background 0.2s ease',\r\n },\r\n footer: {\r\n background: isDark ? '#222' : '#f8fafc',\r\n padding: '24px',\r\n textAlign: 'center' as const,\r\n borderTop: `1px solid ${border}`,\r\n fontSize: '13px',\r\n color: textMuted,\r\n },\r\n footerLink: {\r\n color: text,\r\n fontWeight: 600,\r\n textDecoration: 'underline',\r\n cursor: 'pointer',\r\n marginLeft: '4px',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n }\r\n };\r\n\r\n const GoogleIcon = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n\r\n const GithubIcon = () => (\r\n \r\n \r\n \r\n );\r\n\r\n return (\r\n
\r\n {toast && (\r\n {\r\n setToast(null);\r\n if (toast.type === 'error') clearError();\r\n }} \r\n />\r\n )}\r\n \r\n
\r\n {(mode === 'signin' || mode === 'signup') && (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {(mode === 'forgot' || mode === 'reset') && (\r\n
\r\n

\r\n {mode === 'forgot' ? 'Reset Password' : 'Enter Reset Code'}\r\n

\r\n

\r\n {mode === 'forgot' ? \"Enter your email and we'll send a code\" : `Enter the code sent to ${email}`}\r\n

\r\n
\r\n )}\r\n\r\n
\r\n {mode === 'signup' && (\r\n
\r\n
\r\n \r\n
\r\n setName(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n \r\n
\r\n
\r\n \r\n
\r\n setEmail(e.target.value)}\r\n required\r\n readOnly={mode === 'reset'}\r\n />\r\n
\r\n\r\n {mode === 'reset' && (\r\n
\r\n
\r\n \r\n
\r\n setOtp(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n {(mode === 'signin' || mode === 'signup' || mode === 'reset') && (\r\n
\r\n
\r\n \r\n {mode === 'signin' && (\r\n \r\n )}\r\n
\r\n setPassword(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n \r\n
\r\n\r\n {(mode === 'signin' || mode === 'signup') && providers && providers.length > 0 && (\r\n <>\r\n
\r\n
\r\n OR\r\n
\r\n
\r\n\r\n
\r\n {providers.includes('google') && (\r\n \r\n )}\r\n {providers.includes('github') && (\r\n \r\n )}\r\n
\r\n \r\n )}\r\n
\r\n\r\n
\r\n {mode === 'signin' ? \"Don't have an account yet?\" \r\n : mode === 'signup' ? \"Already have an account?\"\r\n : \"Remember your password?\"}\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\n\r\ninterface ToastProps {\r\n message: string;\r\n type: 'success' | 'error';\r\n onClose: () => void;\r\n isDark?: boolean;\r\n}\r\n\r\nexport const Toast: React.FC = ({ message, type, onClose, isDark = false }) => {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isLeaving, setIsLeaving] = useState(false);\r\n\r\n useEffect(() => {\r\n // Trigger enter animation on mount\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n\r\n let innerTimer: ReturnType;\r\n const timer = setTimeout(() => {\r\n setIsLeaving(true);\r\n innerTimer = setTimeout(onClose, 300); // Wait for exit animation\r\n }, 4000);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n if (innerTimer) clearTimeout(innerTimer);\r\n };\r\n }, [onClose]);\r\n\r\n const bgColor = isDark ? 'rgba(30, 30, 30, 0.9)' : 'rgba(255, 255, 255, 0.9)';\r\n const borderColor = type === 'success' ? 'rgba(34, 197, 94, 0.5)' : 'rgba(239, 68, 68, 0.5)';\r\n const iconColor = type === 'success' ? '#22c55e' : '#ef4444';\r\n const textColor = isDark ? '#fff' : '#000';\r\n\r\n return (\r\n <>\r\n \r\n \r\n {type === 'success' ? (\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {message}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\nimport { useUser, useAuth } from '../hooks';\n\nexport interface UrUserButtonProps {\n /**\n * Shape of the profile avatar. Defaults to 'square' as requested.\n */\n shape?: 'square' | 'circle';\n /**\n * Position of the button on the screen. Defaults to 'top-right'.\n * Use 'inline' if you want to place it within a normal flex/grid layout instead of absolute positioning.\n */\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'inline';\n /**\n * Called when \"Profile\" is clicked.\n */\n onProfileClick?: () => void;\n /**\n * Called when \"Settings\" is clicked.\n */\n onSettingsClick?: () => void;\n /**\n * Z-index for the fixed container. Defaults to 999.\n */\n zIndex?: number;\n}\n\nexport const UrUserButton: React.FC = ({\n shape = 'square',\n position = 'top-right',\n onProfileClick,\n onSettingsClick,\n zIndex = 999,\n}) => {\n const { user } = useUser();\n const { logout } = useAuth();\n const [isOpen, setIsOpen] = useState(false);\n const containerRef = useRef(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n if (!user) return null; // Only render if logged in\n\n const borderRadius = shape === 'circle' ? '50%' : '0px';\n const isFixed = position !== 'inline';\n\n const positionStyles: React.CSSProperties = isFixed\n ? {\n position: 'fixed',\n zIndex,\n top: position.includes('top') ? '24px' : 'auto',\n bottom: position.includes('bottom') ? '24px' : 'auto',\n right: position.includes('right') ? '24px' : 'auto',\n left: position.includes('left') ? '24px' : 'auto',\n }\n : { position: 'relative' };\n\n const dropdownStyles: React.CSSProperties = {\n position: 'absolute',\n top: position.includes('top') || position === 'inline' ? 'calc(100% + 8px)' : 'auto',\n bottom: position.includes('bottom') ? 'calc(100% + 8px)' : 'auto',\n right: position.includes('right') || position === 'inline' ? '0' : 'auto',\n left: position.includes('left') ? '0' : 'auto',\n background: '#ffffff',\n border: '1px solid #e2e8f0',\n borderRadius: '0px',\n boxShadow: '0 10px 25px rgba(0,0,0,0.1)',\n width: '220px',\n display: isOpen ? 'block' : 'none',\n overflow: 'hidden',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n };\n\n const getInitials = () => {\n return user.name?.[0]?.toUpperCase() || user.email?.[0]?.toUpperCase() || 'U';\n };\n\n return (\n
\n setIsOpen(!isOpen)}\n style={{\n width: '40px',\n height: '40px',\n padding: 0,\n border: '1px solid #e2e8f0',\n background: '#f8fafc',\n borderRadius,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n boxShadow: '0 2px 5px rgba(0,0,0,0.05)',\n transition: 'transform 0.1s ease',\n }}\n >\n {user.avatarUrl ? (\n \"User\"\n ) : (\n \n {getInitials()}\n \n )}\n \n\n
\n {/* User Info Header */}\n
\n
\n {user.name || 'User'}\n
\n
\n {user.email}\n
\n
\n\n {/* Action List */}\n
\n {onProfileClick && (\n {\n setIsOpen(false);\n onProfileClick();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#334155',\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Profile\n \n )}\n\n {onSettingsClick && (\n {\n setIsOpen(false);\n onSettingsClick();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#334155',\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Settings\n \n )}\n\n
\n\n {\n setIsOpen(false);\n logout();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#ef4444',\n fontWeight: 500,\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#fef2f2')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Logout\n \n
\n
\n
\n );\n};\n"],"mappings":"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","names":["error","import_react","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime"]} \ No newline at end of file +{"version":3,"sources":["../src/index.ts","../src/context.tsx","../src/hooks.ts","../src/components.tsx","../src/components/UrAuth.tsx","../src/components/Toast.tsx","../src/components/UrUserButton.tsx"],"sourcesContent":["export { UrProvider, useUrContext } from './context';\r\nexport type { UrProviderProps } from './context';\r\n\r\nexport { useAuth, useUser, useDb, useStorage } from './hooks';\r\nexport { ProtectedRoute, GuestRoute } from './components';\r\nexport type { ProtectedRouteProps, GuestRouteProps } from './components';\r\n\r\nexport { UrAuth } from './components/UrAuth';\r\nexport type { UrAuthProps } from './components/UrAuth';\r\n\r\nexport * from './components/UrUserButton';\r\n\r\nexport * from '@urbackend/sdk'; // re-export types so users don't need to import from sdk directly","import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\r\nimport { UrBackendClient, AuthModule, DatabaseModule, StorageModule } from '@urbackend/sdk';\r\nimport type { AuthUser } from '@urbackend/sdk';\r\n\r\ninterface UrContextValue {\r\n client: UrBackendClient | null;\r\n auth: AuthModule | null;\r\n db: DatabaseModule | null;\r\n storage: StorageModule | null;\r\n user: AuthUser | null;\r\n setUser: React.Dispatch>;\r\n isInitializing: boolean;\r\n isLoading: boolean;\r\n setIsLoading: React.Dispatch>;\r\n error: string | null;\r\n setError: React.Dispatch>;\r\n}\r\n\r\nconst UrContext = createContext(undefined);\r\n\r\nexport interface UrProviderProps {\r\n apiKey: string;\r\n baseUrl?: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const UrProvider: React.FC = ({ apiKey, baseUrl, children }) => {\r\n const [user, setUser] = useState(null);\r\n const [isInitializing, setIsInitializing] = useState(true);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState(null);\r\n\r\n const { client, auth, db, storage } = useMemo(() => {\r\n const _client = new UrBackendClient({ apiKey, baseUrl });\r\n return {\r\n client: _client,\r\n auth: new AuthModule(_client),\r\n db: new DatabaseModule(_client),\r\n storage: new StorageModule(_client),\r\n };\r\n }, [apiKey, baseUrl]);\r\n\r\n useEffect(() => {\r\n let mounted = true;\r\n\r\n const initAuth = async () => {\r\n try {\r\n // Hydrate from localStorage first as a fallback for environments without cookies\r\n if (typeof window !== 'undefined') {\r\n const savedToken = localStorage.getItem('ur_auth_token');\r\n if (savedToken) auth.setToken(savedToken);\r\n }\r\n\r\n // Check for social auth callback params\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n const token = hashParams.get('token');\r\n const rtCode = urlParams.get('rtCode');\r\n const error = urlParams.get('error');\r\n\r\n if (error) {\r\n console.error('Social Auth Error:', error);\r\n if (mounted) setError(error);\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else if (token) {\r\n // Social auth succeeded, establish session immediately\r\n auth.setToken(token);\r\n if (typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n \r\n if (rtCode) {\r\n // Exchange for long-lived refresh token\r\n try {\r\n const exRes = await auth.socialExchange({ token, rtCode });\r\n const exToken = (exRes as any).accessToken || (exRes as any).token;\r\n if (exToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', exToken);\r\n } catch (err: any) {\r\n console.error('Failed to exchange refresh token', err);\r\n if (mounted) setError(err.message || 'Failed to complete social login');\r\n throw err;\r\n }\r\n }\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else {\r\n // Attempt to silently refresh session using the HTTP-only cookie\r\n try {\r\n const res = await auth.refreshToken();\r\n const newToken = res.accessToken || (res as any).token;\r\n if (newToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', newToken);\r\n } catch (e) {\r\n // If refresh fails, me() will catch it\r\n }\r\n }\r\n \r\n const currentUser = await auth.me();\r\n if (mounted) {\r\n setUser(currentUser);\r\n }\r\n } catch (error: any) {\r\n if (mounted) {\r\n setUser(null);\r\n // Don't set global error for initial me() check failure (usually just means not logged in)\r\n }\r\n } finally {\r\n if (mounted) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n };\r\n\r\n initAuth();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [auth]);\r\n\r\n const value: UrContextValue = {\r\n client,\r\n auth,\r\n db,\r\n storage,\r\n user,\r\n setUser,\r\n isInitializing,\r\n isLoading,\r\n setIsLoading,\r\n error,\r\n setError,\r\n };\r\n\r\n return {children};\r\n};\r\n\r\nexport const useUrContext = () => {\r\n const context = useContext(UrContext);\r\n if (!context) {\r\n throw new Error('useUrContext must be used within an UrProvider');\r\n }\r\n return context;\r\n};\r\n","import { useCallback } from 'react';\r\nimport { useUrContext } from './context';\r\nimport type { \r\n LoginPayload, \r\n SignUpPayload, \r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload\r\n} from '@urbackend/sdk';\r\n\r\nexport const useAuth = () => {\r\n const { auth, user, setUser, isInitializing, isLoading, setIsLoading, error, setError } = useUrContext();\r\n\r\n if (!auth) {\r\n throw new Error('Auth module not initialized. Make sure you are inside UrProvider.');\r\n }\r\n\r\n const login = useCallback(async (payload: LoginPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const res = await auth.login(payload);\r\n const token = res.accessToken || (res as any).token;\r\n if (token && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n const currentUser = await auth.me();\r\n setUser(currentUser);\r\n } catch (err: any) {\r\n setError(err.message || 'Login failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const signUp = useCallback(async (payload: SignUpPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const newUser = await auth.signUp(payload);\r\n return newUser;\r\n } catch (err: any) {\r\n setError(err.message || 'Sign up failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setIsLoading, setError]);\r\n\r\n const logout = useCallback(async () => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n await auth.logout();\r\n if (typeof window !== 'undefined') localStorage.removeItem('ur_auth_token');\r\n setUser(null);\r\n } catch (err: any) {\r\n setError(err.message || 'Logout failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const socialLogin = useCallback((provider: 'google' | 'github') => {\r\n setError(null);\r\n const url = auth.socialStart(provider);\r\n window.location.href = url;\r\n }, [auth, setError]);\r\n \r\n const verifyEmail = useCallback(async (payload: VerifyEmailPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.verifyEmail(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Email verification failed');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const changePassword = useCallback(async (payload: ChangePasswordPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.changePassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to change password');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const requestPasswordReset = useCallback(async (payload: RequestPasswordResetPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.requestPasswordReset(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to request password reset');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const resetPassword = useCallback(async (payload: ResetPasswordPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.resetPassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to reset password');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const clearError = useCallback(() => setError(null), [setError]);\r\n\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n login,\r\n signUp,\r\n logout,\r\n socialLogin,\r\n verifyEmail,\r\n changePassword,\r\n requestPasswordReset,\r\n resetPassword,\r\n clearError,\r\n authApi: auth // Escape hatch to underlying SDK\r\n };\r\n};\r\n\r\nexport const useUser = () => {\r\n const { user, isInitializing, isLoading, error } = useUrContext();\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n };\r\n};\r\n\r\nexport const useDb = () => {\r\n const { db } = useUrContext();\r\n if (!db) {\r\n throw new Error('Database module not initialized.');\r\n }\r\n return db;\r\n};\r\n\r\nexport const useStorage = () => {\r\n const { storage } = useUrContext();\r\n if (!storage) {\r\n throw new Error('Storage module not initialized.');\r\n }\r\n return storage;\r\n};\r\n","import React, { useEffect } from 'react';\r\nimport { useUser } from './hooks';\r\n\r\nexport interface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to be authenticated.\r\n * If the user is not authenticated after initialization, they will be redirected,\r\n * or the fallback will be rendered (or nothing if fallback is not provided and no window redirect occurs).\r\n */\r\nexport const ProtectedRoute: React.FC = ({ \r\n children, \r\n redirectTo = '/login', \r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && !isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (!isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n\r\nexport interface GuestRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to NOT be authenticated (e.g. for Login pages).\r\n * If the user IS authenticated, they will be redirected to the specified route.\r\n */\r\nexport const GuestRoute: React.FC = ({\r\n children,\r\n redirectTo = '/dashboard',\r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\nimport { useAuth } from '../hooks';\r\nimport { Toast } from './Toast';\r\n\r\ntype AuthProvider = 'google' | 'github';\r\ntype ThemeMode = 'light' | 'dark';\r\n\r\ninterface AuthColors {\r\n background: string;\r\n surface: string;\r\n text: string;\r\n textMuted: string;\r\n border: string;\r\n inputBackground: string;\r\n primary: string;\r\n primaryText: string;\r\n footerBackground: string;\r\n dividerText: string;\r\n socialButtonBackground: string;\r\n}\r\n\r\ninterface AuthBranding {\r\n brandName?: string;\r\n appName?: string;\r\n title?: string;\r\n subtitle?: string;\r\n logo?: React.ReactNode | string;\r\n primaryColor?: string;\r\n}\r\n\r\ninterface AuthLabels {\r\n loginTab: string;\r\n signupTab: string;\r\n loginTitle: string;\r\n signupTitle: string;\r\n forgotTitle: string;\r\n resetTitle: string;\r\n loginButton: string;\r\n signupButton: string;\r\n forgotButton: string;\r\n resetButton: string;\r\n emailLabel: string;\r\n emailPlaceholder: string;\r\n passwordLabel: string;\r\n passwordPlaceholder: string;\r\n nameLabel: string;\r\n namePlaceholder: string;\r\n otpLabel: string;\r\n otpPlaceholder: string;\r\n forgotPasswordLink: string;\r\n socialDivider: string;\r\n googleButton: string;\r\n githubButton: string;\r\n footerSigninPrompt: string;\r\n footerSignupPrompt: string;\r\n footerForgotPrompt: string;\r\n noAuthMethods: string;\r\n // Aliases support\r\n signInTitle?: string;\r\n signUpTitle?: string;\r\n signInTab?: string;\r\n signUpTab?: string;\r\n signInButton?: string;\r\n signUpButton?: string;\r\n}\r\n\r\nexport interface UrAuthProps {\r\n providers?: AuthProvider[] | {\r\n google?: boolean;\r\n github?: boolean;\r\n emailPassword?: boolean;\r\n };\r\n enableEmailPassword?: boolean;\r\n theme?: ThemeMode;\r\n colors?: Partial;\r\n branding?: AuthBranding;\r\n labels?: Partial;\r\n onSuccess?: () => void;\r\n}\r\n\r\nconst defaultLabels: AuthLabels = {\r\n loginTab: 'Login',\r\n signupTab: 'Sign Up',\r\n loginTitle: 'Welcome back',\r\n signupTitle: 'Create your account',\r\n forgotTitle: 'Reset Password',\r\n resetTitle: 'Enter Reset Code',\r\n loginButton: 'Log In',\r\n signupButton: 'Create Account',\r\n forgotButton: 'Send Reset Code',\r\n resetButton: 'Reset Password',\r\n emailLabel: 'Email address',\r\n emailPlaceholder: 'Enter your email address',\r\n passwordLabel: 'Password',\r\n passwordPlaceholder: 'Enter your password',\r\n nameLabel: 'Full Name',\r\n namePlaceholder: 'Enter your name',\r\n otpLabel: '6-digit OTP Code',\r\n otpPlaceholder: 'Enter reset code',\r\n forgotPasswordLink: 'Forgot password?',\r\n socialDivider: 'OR',\r\n googleButton: 'Continue with Google',\r\n githubButton: 'Continue with GitHub',\r\n footerSigninPrompt: \"Don't have an account yet?\",\r\n footerSignupPrompt: 'Already have an account?',\r\n footerForgotPrompt: 'Remember your password?',\r\n noAuthMethods: 'No authentication methods are enabled for this screen.',\r\n};\r\n\r\nconst defaultThemeColors: Record = {\r\n light: {\r\n background: '#ffffff',\r\n surface: '#ffffff',\r\n text: '#0f172a',\r\n textMuted: '#64748b',\r\n border: '#e2e8f0',\r\n inputBackground: '#ffffff',\r\n primary: '#111111',\r\n primaryText: '#ffffff',\r\n footerBackground: '#f8fafc',\r\n dividerText: '#94a3b8',\r\n socialButtonBackground: '#ffffff',\r\n },\r\n dark: {\r\n background: '#1a1a1a',\r\n surface: '#1a1a1a',\r\n text: '#ffffff',\r\n textMuted: '#a1a1aa',\r\n border: '#333333',\r\n inputBackground: '#2a2a2a',\r\n primary: '#ffffff',\r\n primaryText: '#111111',\r\n footerBackground: '#222222',\r\n dividerText: '#94a3b8',\r\n socialButtonBackground: '#2a2a2a',\r\n },\r\n};\r\n\r\nexport const UrAuth: React.FC = ({ \r\n providers = ['google', 'github'], \r\n enableEmailPassword = true,\r\n theme = 'light',\r\n colors,\r\n branding,\r\n labels,\r\n onSuccess\r\n}) => {\r\n const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth();\r\n const [mode, setMode] = useState<'signin' | 'signup' | 'forgot' | 'reset'>('signin');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [otp, setOtp] = useState('');\r\n const [name, setName] = useState('');\r\n const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null);\r\n\r\n const text = {\r\n ...defaultLabels,\r\n ...labels,\r\n loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab,\r\n loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle,\r\n loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton,\r\n signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab,\r\n signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle,\r\n signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton,\r\n };\r\n\r\n const themeColors = { ...defaultThemeColors[theme], ...colors };\r\n const primaryColor = branding?.primaryColor || themeColors.primary;\r\n\r\n let isGoogleEnabled = true;\r\n let isGithubEnabled = true;\r\n let isEmailPasswordEnabled = enableEmailPassword;\r\n\r\n if (providers) {\r\n if (Array.isArray(providers)) {\r\n isGoogleEnabled = providers.includes('google');\r\n isGithubEnabled = providers.includes('github');\r\n } else if (typeof providers === 'object') {\r\n isGoogleEnabled = !!providers.google;\r\n isGithubEnabled = !!providers.github;\r\n isEmailPasswordEnabled = providers.emailPassword !== undefined ? providers.emailPassword : false;\r\n }\r\n }\r\n\r\n const hasPasswordAuth = isEmailPasswordEnabled;\r\n const hasSocialAuth = isGoogleEnabled || isGithubEnabled;\r\n const brandName = branding?.brandName || branding?.appName || branding?.title || 'urBackend';\r\n const headerTitle = branding?.title || brandName;\r\n const headerSubtitle = branding?.subtitle || (mode === 'signin'\r\n ? text.loginTitle\r\n : mode === 'signup'\r\n ? text.signupTitle\r\n : mode === 'forgot'\r\n ? text.forgotTitle\r\n : text.resetTitle);\r\n const showSwitcher = hasPasswordAuth;\r\n\r\n useEffect(() => {\r\n if (error) {\r\n setToast({ message: error, type: 'error' });\r\n }\r\n }, [error]);\r\n\r\n useEffect(() => {\r\n if (!hasPasswordAuth && mode !== 'signin') {\r\n setMode('signin');\r\n }\r\n }, [hasPasswordAuth, mode]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n if (mode === 'signin') {\r\n await login({ email, password });\r\n setToast({ message: 'Welcome back!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'signup') {\r\n await signUp({ email, password, name });\r\n await login({ email, password });\r\n setToast({ message: 'Account created successfully!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'forgot') {\r\n await requestPasswordReset({ email });\r\n setToast({ message: 'Reset code sent to your email', type: 'success' });\r\n setMode('reset');\r\n } else if (mode === 'reset') {\r\n await resetPassword({ email, otp, newPassword: password });\r\n setToast({ message: 'Password reset successfully', type: 'success' });\r\n setMode('signin');\r\n setPassword('');\r\n setOtp('');\r\n }\r\n } catch (err: any) {\r\n // Errors are surfaced via the shared auth hook state.\r\n }\r\n };\r\n\r\n const styles = {\r\n wrapper: {\r\n width: '100%',\r\n maxWidth: '420px',\r\n margin: '0 auto',\r\n borderRadius: '0',\r\n background: themeColors.background,\r\n boxShadow: theme === 'dark' ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)',\r\n border: `1px solid ${themeColors.border}`,\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n color: themeColors.text,\r\n },\r\n body: {\r\n padding: '32px 32px 24px 32px',\r\n },\r\n header: {\r\n textAlign: 'center' as const,\r\n marginBottom: '28px',\r\n },\r\n brandRow: {\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n gap: '12px',\r\n marginBottom: '10px',\r\n },\r\n brandLogo: {\r\n width: '44px',\r\n height: '44px',\r\n borderRadius: '12px',\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9',\r\n color: themeColors.text,\r\n overflow: 'hidden' as const,\r\n },\r\n brandTitle: {\r\n margin: 0,\r\n fontSize: '26px',\r\n lineHeight: 1.1,\r\n fontWeight: 800,\r\n color: themeColors.text,\r\n },\r\n brandSubtitle: {\r\n margin: '0 auto',\r\n maxWidth: '320px',\r\n fontSize: '14px',\r\n lineHeight: 1.5,\r\n color: themeColors.textMuted,\r\n },\r\n switcherContainer: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n marginBottom: '32px'\r\n },\r\n switcher: {\r\n display: 'inline-flex',\r\n background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9',\r\n padding: '4px',\r\n borderRadius: '0',\r\n },\r\n switchBtn: (active: boolean) => ({\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '8px 20px',\r\n borderRadius: '0',\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n color: active ? themeColors.text : themeColors.textMuted,\r\n background: active ? (theme === 'dark' ? '#444444' : '#ffffff') : 'transparent',\r\n boxShadow: active ? (theme === 'dark' ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none',\r\n border: 'none',\r\n transition: 'all 0.2s ease',\r\n }),\r\n field: {\r\n marginBottom: '20px',\r\n },\r\n labelRow: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '8px',\r\n },\r\n label: {\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n color: theme === 'dark' ? '#dddddd' : '#334155',\r\n },\r\n forgotLink: {\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n color: themeColors.text,\r\n cursor: 'pointer',\r\n textDecoration: 'none',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n },\r\n input: {\r\n width: '100%',\r\n padding: '12px 16px',\r\n borderRadius: '0',\r\n border: `1px solid ${themeColors.border}`,\r\n background: themeColors.inputBackground,\r\n color: themeColors.text,\r\n fontSize: '14px',\r\n boxSizing: 'border-box' as const,\r\n outline: 'none',\r\n transition: 'border-color 0.2s ease',\r\n },\r\n primaryBtn: {\r\n width: '100%',\r\n padding: '14px',\r\n borderRadius: '0',\r\n background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === 'dark' ? '#111111' : '#111111'} 100%)`,\r\n color: themeColors.primaryText,\r\n fontSize: '15px',\r\n fontWeight: 600,\r\n border: 'none',\r\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n transition: 'transform 0.1s ease',\r\n },\r\n divider: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n margin: '24px 0',\r\n color: themeColors.dividerText,\r\n fontSize: '11px',\r\n fontWeight: 600,\r\n letterSpacing: '1px',\r\n },\r\n dividerLine: {\r\n flex: 1,\r\n height: '1px',\r\n background: themeColors.border,\r\n },\r\n dividerText: {\r\n padding: '0 12px',\r\n },\r\n socialBtn: {\r\n width: '100%',\r\n padding: '12px',\r\n borderRadius: '0',\r\n border: `1px solid ${themeColors.border}`,\r\n background: themeColors.socialButtonBackground,\r\n color: themeColors.text,\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n gap: '10px',\r\n marginBottom: '12px',\r\n cursor: 'pointer',\r\n boxShadow: theme === 'dark' ? 'none' : '0 1px 2px rgba(0,0,0,0.02)',\r\n transition: 'background 0.2s ease',\r\n },\r\n footer: {\r\n background: themeColors.footerBackground,\r\n padding: '24px',\r\n textAlign: 'center' as const,\r\n borderTop: `1px solid ${themeColors.border}`,\r\n fontSize: '13px',\r\n color: themeColors.textMuted,\r\n },\r\n footerLink: {\r\n color: themeColors.text,\r\n fontWeight: 600,\r\n textDecoration: 'underline',\r\n cursor: 'pointer',\r\n marginLeft: '4px',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n }\r\n };\r\n\r\n const GoogleIcon = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n\r\n const GithubIcon = () => (\r\n \r\n \r\n \r\n );\r\n\r\n const renderSocialButtons = () => {\r\n if (!hasSocialAuth) {\r\n return null;\r\n }\r\n\r\n return (\r\n <>\r\n {hasPasswordAuth && (\r\n
\r\n
\r\n {text.socialDivider}\r\n
\r\n
\r\n )}\r\n\r\n
\r\n {isGoogleEnabled && (\r\n \r\n )}\r\n {isGithubEnabled && (\r\n \r\n )}\r\n
\r\n \r\n );\r\n };\r\n\r\n const footerPrompt = mode === 'signin'\r\n ? text.footerSigninPrompt\r\n : mode === 'signup'\r\n ? text.footerSignupPrompt\r\n : text.footerForgotPrompt;\r\n\r\n return (\r\n
\r\n {toast && (\r\n {\r\n setToast(null);\r\n if (toast.type === 'error') clearError();\r\n }} \r\n />\r\n )}\r\n \r\n
\r\n {(branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && (\r\n
\r\n
\r\n {branding?.logo ? (\r\n
\r\n {typeof branding.logo === 'string' ? (\r\n {brandName}\r\n ) : (\r\n branding.logo\r\n )}\r\n
\r\n ) : (\r\n
\r\n {brandName.slice(0, 1).toUpperCase()}\r\n
\r\n )}\r\n
\r\n

{headerTitle}

\r\n

{headerSubtitle}

\r\n
\r\n )}\r\n\r\n {showSwitcher && (mode === 'signin' || mode === 'signup') && (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {(mode === 'forgot' || mode === 'reset') && (\r\n
\r\n

\r\n {mode === 'forgot' ? text.forgotTitle : text.resetTitle}\r\n

\r\n

\r\n {mode === 'forgot' ? text.loginTitle : `Enter the code sent to ${email}`}\r\n

\r\n
\r\n )}\r\n\r\n {!hasPasswordAuth && !hasSocialAuth && (\r\n
\r\n {text.noAuthMethods}\r\n
\r\n )}\r\n\r\n {hasPasswordAuth && (\r\n
\r\n {mode === 'signup' && (\r\n
\r\n
\r\n \r\n
\r\n setName(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n
\r\n
\r\n \r\n
\r\n setEmail(e.target.value)}\r\n required\r\n readOnly={mode === 'reset'}\r\n />\r\n
\r\n\r\n {(mode === 'signin' || mode === 'signup' || mode === 'reset') && (\r\n
\r\n
\r\n \r\n {mode === 'signin' && (\r\n \r\n )}\r\n
\r\n setPassword(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n {mode === 'reset' && (\r\n
\r\n
\r\n \r\n
\r\n setOtp(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n \r\n
\r\n )}\r\n\r\n {(mode === 'signin' || mode === 'signup') && renderSocialButtons()}\r\n
\r\n\r\n {hasPasswordAuth && (\r\n
\r\n {footerPrompt}\r\n \r\n
\r\n )}\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\n\r\ninterface ToastProps {\r\n message: string;\r\n type: 'success' | 'error';\r\n onClose: () => void;\r\n isDark?: boolean;\r\n}\r\n\r\nexport const Toast: React.FC = ({ message, type, onClose, isDark = false }) => {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isLeaving, setIsLeaving] = useState(false);\r\n\r\n useEffect(() => {\r\n // Trigger enter animation on mount\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n\r\n let innerTimer: ReturnType;\r\n const timer = setTimeout(() => {\r\n setIsLeaving(true);\r\n innerTimer = setTimeout(onClose, 300); // Wait for exit animation\r\n }, 4000);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n if (innerTimer) clearTimeout(innerTimer);\r\n };\r\n }, [onClose]);\r\n\r\n const bgColor = isDark ? 'rgba(30, 30, 30, 0.9)' : 'rgba(255, 255, 255, 0.9)';\r\n const borderColor = type === 'success' ? 'rgba(34, 197, 94, 0.5)' : 'rgba(239, 68, 68, 0.5)';\r\n const iconColor = type === 'success' ? '#22c55e' : '#ef4444';\r\n const textColor = isDark ? '#fff' : '#000';\r\n\r\n return (\r\n <>\r\n \r\n \r\n {type === 'success' ? (\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {message}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\r\nimport { useUser, useAuth } from '../hooks';\r\n\r\nexport interface UrUserButtonProps {\r\n /**\r\n * Shape of the profile avatar. Defaults to 'square' as requested.\r\n */\r\n shape?: 'square' | 'circle';\r\n /**\r\n * Position of the button on the screen. Defaults to 'top-right'.\r\n * Use 'inline' if you want to place it within a normal flex/grid layout instead of absolute positioning.\r\n */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'inline';\r\n /**\r\n * Called when \"Profile\" is clicked.\r\n */\r\n onProfileClick?: () => void;\r\n /**\r\n * Called when \"Settings\" is clicked.\r\n */\r\n onSettingsClick?: () => void;\r\n /**\r\n * Z-index for the fixed container. Defaults to 999.\r\n */\r\n zIndex?: number;\r\n}\r\n\r\nexport const UrUserButton: React.FC = ({\r\n shape = 'square',\r\n position = 'top-right',\r\n onProfileClick,\r\n onSettingsClick,\r\n zIndex = 999,\r\n}) => {\r\n const { user } = useUser();\r\n const { logout } = useAuth();\r\n const [isOpen, setIsOpen] = useState(false);\r\n const containerRef = useRef(null);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\r\n setIsOpen(false);\r\n }\r\n };\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, []);\r\n\r\n if (!user) return null; // Only render if logged in\r\n\r\n const borderRadius = shape === 'circle' ? '50%' : '0px';\r\n const isFixed = position !== 'inline';\r\n\r\n const positionStyles: React.CSSProperties = isFixed\r\n ? {\r\n position: 'fixed',\r\n zIndex,\r\n top: position.includes('top') ? '24px' : 'auto',\r\n bottom: position.includes('bottom') ? '24px' : 'auto',\r\n right: position.includes('right') ? '24px' : 'auto',\r\n left: position.includes('left') ? '24px' : 'auto',\r\n }\r\n : { position: 'relative' };\r\n\r\n const dropdownStyles: React.CSSProperties = {\r\n position: 'absolute',\r\n top: position.includes('top') || position === 'inline' ? 'calc(100% + 8px)' : 'auto',\r\n bottom: position.includes('bottom') ? 'calc(100% + 8px)' : 'auto',\r\n right: position.includes('right') || position === 'inline' ? '0' : 'auto',\r\n left: position.includes('left') ? '0' : 'auto',\r\n background: '#ffffff',\r\n border: '1px solid #e2e8f0',\r\n borderRadius: '0px',\r\n boxShadow: '0 10px 25px rgba(0,0,0,0.1)',\r\n width: '220px',\r\n display: isOpen ? 'block' : 'none',\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, sans-serif',\r\n };\r\n\r\n const getInitials = () => {\r\n return user.name?.[0]?.toUpperCase() || user.email?.[0]?.toUpperCase() || 'U';\r\n };\r\n\r\n return (\r\n
\r\n setIsOpen(!isOpen)}\r\n style={{\r\n width: '40px',\r\n height: '40px',\r\n padding: 0,\r\n border: '1px solid #e2e8f0',\r\n background: '#f8fafc',\r\n borderRadius,\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden',\r\n boxShadow: '0 2px 5px rgba(0,0,0,0.05)',\r\n transition: 'transform 0.1s ease',\r\n }}\r\n >\r\n {user.avatarUrl ? (\r\n \"User\"\r\n ) : (\r\n \r\n {getInitials()}\r\n \r\n )}\r\n \r\n\r\n
\r\n {/* User Info Header */}\r\n
\r\n
\r\n {user.name || 'User'}\r\n
\r\n
\r\n {user.email}\r\n
\r\n
\r\n\r\n {/* Action List */}\r\n
\r\n {onProfileClick && (\r\n {\r\n setIsOpen(false);\r\n onProfileClick();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#334155',\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Profile\r\n \r\n )}\r\n\r\n {onSettingsClick && (\r\n {\r\n setIsOpen(false);\r\n onSettingsClick();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#334155',\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Settings\r\n \r\n )}\r\n\r\n
\r\n\r\n {\r\n setIsOpen(false);\r\n logout();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#ef4444',\r\n fontWeight: 500,\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#fef2f2')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Logout\r\n \r\n
\r\n
\r\n
\r\n );\r\n};\r\n"],"mappings":"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","names":["error","import_react","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime"]} \ No newline at end of file diff --git a/sdks/urbackend-react/dist/index.mjs b/sdks/urbackend-react/dist/index.mjs index c890d9a7..b2358536 100644 --- a/sdks/urbackend-react/dist/index.mjs +++ b/sdks/urbackend-react/dist/index.mjs @@ -294,7 +294,7 @@ var GuestRoute = ({ }; // src/components/UrAuth.tsx -import { useState as useState3, useEffect as useEffect4 } from "react"; +import { useEffect as useEffect4, useState as useState3 } from "react"; // src/components/Toast.tsx import { useEffect as useEffect3, useState as useState2 } from "react"; @@ -374,9 +374,69 @@ var Toast = ({ message, type, onClose, isDark = false }) => { // src/components/UrAuth.tsx import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime"; +var defaultLabels = { + loginTab: "Login", + signupTab: "Sign Up", + loginTitle: "Welcome back", + signupTitle: "Create your account", + forgotTitle: "Reset Password", + resetTitle: "Enter Reset Code", + loginButton: "Log In", + signupButton: "Create Account", + forgotButton: "Send Reset Code", + resetButton: "Reset Password", + emailLabel: "Email address", + emailPlaceholder: "Enter your email address", + passwordLabel: "Password", + passwordPlaceholder: "Enter your password", + nameLabel: "Full Name", + namePlaceholder: "Enter your name", + otpLabel: "6-digit OTP Code", + otpPlaceholder: "Enter reset code", + forgotPasswordLink: "Forgot password?", + socialDivider: "OR", + googleButton: "Continue with Google", + githubButton: "Continue with GitHub", + footerSigninPrompt: "Don't have an account yet?", + footerSignupPrompt: "Already have an account?", + footerForgotPrompt: "Remember your password?", + noAuthMethods: "No authentication methods are enabled for this screen." +}; +var defaultThemeColors = { + light: { + background: "#ffffff", + surface: "#ffffff", + text: "#0f172a", + textMuted: "#64748b", + border: "#e2e8f0", + inputBackground: "#ffffff", + primary: "#111111", + primaryText: "#ffffff", + footerBackground: "#f8fafc", + dividerText: "#94a3b8", + socialButtonBackground: "#ffffff" + }, + dark: { + background: "#1a1a1a", + surface: "#1a1a1a", + text: "#ffffff", + textMuted: "#a1a1aa", + border: "#333333", + inputBackground: "#2a2a2a", + primary: "#ffffff", + primaryText: "#111111", + footerBackground: "#222222", + dividerText: "#94a3b8", + socialButtonBackground: "#2a2a2a" + } +}; var UrAuth = ({ providers = ["google", "github"], + enableEmailPassword = true, theme = "light", + colors, + branding, + labels, onSuccess }) => { const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth(); @@ -386,11 +446,47 @@ var UrAuth = ({ const [otp, setOtp] = useState3(""); const [name, setName] = useState3(""); const [toast, setToast] = useState3(null); + const text = { + ...defaultLabels, + ...labels, + loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab, + loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle, + loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton, + signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab, + signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle, + signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton + }; + const themeColors = { ...defaultThemeColors[theme], ...colors }; + const primaryColor = branding?.primaryColor || themeColors.primary; + let isGoogleEnabled = true; + let isGithubEnabled = true; + let isEmailPasswordEnabled = enableEmailPassword; + if (providers) { + if (Array.isArray(providers)) { + isGoogleEnabled = providers.includes("google"); + isGithubEnabled = providers.includes("github"); + } else if (typeof providers === "object") { + isGoogleEnabled = !!providers.google; + isGithubEnabled = !!providers.github; + isEmailPasswordEnabled = providers.emailPassword !== void 0 ? providers.emailPassword : false; + } + } + const hasPasswordAuth = isEmailPasswordEnabled; + const hasSocialAuth = isGoogleEnabled || isGithubEnabled; + const brandName = branding?.brandName || branding?.appName || branding?.title || "urBackend"; + const headerTitle = branding?.title || brandName; + const headerSubtitle = branding?.subtitle || (mode === "signin" ? text.loginTitle : mode === "signup" ? text.signupTitle : mode === "forgot" ? text.forgotTitle : text.resetTitle); + const showSwitcher = hasPasswordAuth; useEffect4(() => { if (error) { setToast({ message: error, type: "error" }); } }, [error]); + useEffect4(() => { + if (!hasPasswordAuth && mode !== "signin") { + setMode("signin"); + } + }, [hasPasswordAuth, mode]); const handleSubmit = async (e) => { e.preventDefault(); try { @@ -417,28 +513,58 @@ var UrAuth = ({ } catch (err) { } }; - const isDark = theme === "dark"; - const bg = isDark ? "#1a1a1a" : "#ffffff"; - const text = isDark ? "#ffffff" : "#0f172a"; - const textMuted = isDark ? "#a1a1aa" : "#64748b"; - const border = isDark ? "#333" : "#e2e8f0"; - const inputBg = isDark ? "#2a2a2a" : "#ffffff"; const styles = { wrapper: { width: "100%", maxWidth: "420px", margin: "0 auto", borderRadius: "0", - background: bg, - boxShadow: isDark ? "0 20px 40px rgba(0,0,0,0.5)" : "0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)", - border: `1px solid ${border}`, + background: themeColors.background, + boxShadow: theme === "dark" ? "0 20px 40px rgba(0,0,0,0.5)" : "0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)", + border: `1px solid ${themeColors.border}`, overflow: "hidden", fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', - color: text + color: themeColors.text }, body: { padding: "32px 32px 24px 32px" }, + header: { + textAlign: "center", + marginBottom: "28px" + }, + brandRow: { + display: "flex", + justifyContent: "center", + alignItems: "center", + gap: "12px", + marginBottom: "10px" + }, + brandLogo: { + width: "44px", + height: "44px", + borderRadius: "12px", + display: "inline-flex", + alignItems: "center", + justifyContent: "center", + background: theme === "dark" ? "#2a2a2a" : "#f1f5f9", + color: themeColors.text, + overflow: "hidden" + }, + brandTitle: { + margin: 0, + fontSize: "26px", + lineHeight: 1.1, + fontWeight: 800, + color: themeColors.text + }, + brandSubtitle: { + margin: "0 auto", + maxWidth: "320px", + fontSize: "14px", + lineHeight: 1.5, + color: themeColors.textMuted + }, switcherContainer: { display: "flex", alignItems: "center", @@ -447,7 +573,7 @@ var UrAuth = ({ }, switcher: { display: "inline-flex", - background: isDark ? "#2a2a2a" : "#f1f5f9", + background: theme === "dark" ? "#2a2a2a" : "#f1f5f9", padding: "4px", borderRadius: "0" }, @@ -460,9 +586,9 @@ var UrAuth = ({ fontSize: "13px", fontWeight: 600, cursor: "pointer", - color: active ? text : textMuted, - background: active ? isDark ? "#444" : "#ffffff" : "transparent", - boxShadow: active ? isDark ? "0 2px 4px rgba(0,0,0,0.2)" : "0 2px 8px rgba(0,0,0,0.05)" : "none", + color: active ? themeColors.text : themeColors.textMuted, + background: active ? theme === "dark" ? "#444444" : "#ffffff" : "transparent", + boxShadow: active ? theme === "dark" ? "0 2px 4px rgba(0,0,0,0.2)" : "0 2px 8px rgba(0,0,0,0.05)" : "none", border: "none", transition: "all 0.2s ease" }), @@ -478,12 +604,12 @@ var UrAuth = ({ label: { fontSize: "13px", fontWeight: 600, - color: isDark ? "#ddd" : "#334155" + color: theme === "dark" ? "#dddddd" : "#334155" }, forgotLink: { fontSize: "12px", fontWeight: 600, - color: text, + color: themeColors.text, cursor: "pointer", textDecoration: "none", background: "none", @@ -494,9 +620,9 @@ var UrAuth = ({ width: "100%", padding: "12px 16px", borderRadius: "0", - border: `1px solid ${border}`, - background: inputBg, - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.inputBackground, + color: themeColors.text, fontSize: "14px", boxSizing: "border-box", outline: "none", @@ -506,8 +632,8 @@ var UrAuth = ({ width: "100%", padding: "14px", borderRadius: "0", - background: "linear-gradient(180deg, #2a2a2a 0%, #111111 100%)", - color: "#ffffff", + background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === "dark" ? "#111111" : "#111111"} 100%)`, + color: themeColors.primaryText, fontSize: "15px", fontWeight: 600, border: "none", @@ -520,7 +646,7 @@ var UrAuth = ({ display: "flex", alignItems: "center", margin: "24px 0", - color: "#94a3b8", + color: themeColors.dividerText, fontSize: "11px", fontWeight: 600, letterSpacing: "1px" @@ -528,7 +654,7 @@ var UrAuth = ({ dividerLine: { flex: 1, height: "1px", - background: border + background: themeColors.border }, dividerText: { padding: "0 12px" @@ -537,9 +663,9 @@ var UrAuth = ({ width: "100%", padding: "12px", borderRadius: "0", - border: `1px solid ${border}`, - background: isDark ? "#2a2a2a" : "#ffffff", - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.socialButtonBackground, + color: themeColors.text, fontSize: "14px", fontWeight: 600, display: "flex", @@ -548,19 +674,19 @@ var UrAuth = ({ gap: "10px", marginBottom: "12px", cursor: "pointer", - boxShadow: isDark ? "none" : "0 1px 2px rgba(0,0,0,0.02)", + boxShadow: theme === "dark" ? "none" : "0 1px 2px rgba(0,0,0,0.02)", transition: "background 0.2s ease" }, footer: { - background: isDark ? "#222" : "#f8fafc", + background: themeColors.footerBackground, padding: "24px", textAlign: "center", - borderTop: `1px solid ${border}`, + borderTop: `1px solid ${themeColors.border}`, fontSize: "13px", - color: textMuted + color: themeColors.textMuted }, footerLink: { - color: text, + color: themeColors.text, fontWeight: 600, textDecoration: "underline", cursor: "pointer", @@ -576,14 +702,37 @@ var UrAuth = ({ /* @__PURE__ */ jsx4("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }), /* @__PURE__ */ jsx4("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" }) ] }); - const GithubIcon = () => /* @__PURE__ */ jsx4("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: isDark ? "#fff" : "#000", children: /* @__PURE__ */ jsx4("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" }) }); + const GithubIcon = () => /* @__PURE__ */ jsx4("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: theme === "dark" ? "#fff" : "#000", children: /* @__PURE__ */ jsx4("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" }) }); + const renderSocialButtons = () => { + if (!hasSocialAuth) { + return null; + } + return /* @__PURE__ */ jsxs2(Fragment3, { children: [ + hasPasswordAuth && /* @__PURE__ */ jsxs2("div", { style: styles.divider, children: [ + /* @__PURE__ */ jsx4("div", { style: styles.dividerLine }), + /* @__PURE__ */ jsx4("span", { style: styles.dividerText, children: text.socialDivider }), + /* @__PURE__ */ jsx4("div", { style: styles.dividerLine }) + ] }), + /* @__PURE__ */ jsxs2("div", { children: [ + isGoogleEnabled && /* @__PURE__ */ jsxs2("button", { style: styles.socialBtn, onClick: () => socialLogin("google"), type: "button", children: [ + /* @__PURE__ */ jsx4(GoogleIcon, {}), + text.googleButton + ] }), + isGithubEnabled && /* @__PURE__ */ jsxs2("button", { style: styles.socialBtn, onClick: () => socialLogin("github"), type: "button", children: [ + /* @__PURE__ */ jsx4(GithubIcon, {}), + text.githubButton + ] }) + ] }) + ] }); + }; + const footerPrompt = mode === "signin" ? text.footerSigninPrompt : mode === "signup" ? text.footerSignupPrompt : text.footerForgotPrompt; return /* @__PURE__ */ jsxs2("div", { style: styles.wrapper, children: [ toast && /* @__PURE__ */ jsx4( Toast, { message: toast.message, type: toast.type, - isDark, + isDark: theme === "dark", onClose: () => { setToast(null); if (toast.type === "error") clearError(); @@ -591,7 +740,12 @@ var UrAuth = ({ } ), /* @__PURE__ */ jsxs2("div", { style: styles.body, children: [ - (mode === "signin" || mode === "signup") && /* @__PURE__ */ jsx4("div", { style: styles.switcherContainer, children: /* @__PURE__ */ jsxs2("div", { style: styles.switcher, children: [ + (branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && /* @__PURE__ */ jsxs2("div", { style: styles.header, children: [ + /* @__PURE__ */ jsx4("div", { style: styles.brandRow, children: branding?.logo ? /* @__PURE__ */ jsx4("div", { style: styles.brandLogo, children: typeof branding.logo === "string" ? /* @__PURE__ */ jsx4("img", { src: branding.logo, alt: brandName, style: { width: "100%", height: "100%", objectFit: "contain" } }) : branding.logo }) : /* @__PURE__ */ jsx4("div", { style: styles.brandLogo, "aria-hidden": "true", children: brandName.slice(0, 1).toUpperCase() }) }), + /* @__PURE__ */ jsx4("h1", { style: styles.brandTitle, children: headerTitle }), + /* @__PURE__ */ jsx4("p", { style: styles.brandSubtitle, children: headerSubtitle }) + ] }), + showSwitcher && (mode === "signin" || mode === "signup") && /* @__PURE__ */ jsx4("div", { style: styles.switcherContainer, children: /* @__PURE__ */ jsxs2("div", { style: styles.switcher, children: [ /* @__PURE__ */ jsxs2( "button", { @@ -607,7 +761,7 @@ var UrAuth = ({ /* @__PURE__ */ jsx4("polyline", { points: "10 17 15 12 10 7" }), /* @__PURE__ */ jsx4("line", { x1: "15", y1: "12", x2: "3", y2: "12" }) ] }), - "Login" + text.loginTab ] } ), @@ -627,24 +781,25 @@ var UrAuth = ({ /* @__PURE__ */ jsx4("line", { x1: "19", y1: "8", x2: "19", y2: "14" }), /* @__PURE__ */ jsx4("line", { x1: "22", y1: "11", x2: "16", y2: "11" }) ] }), - "Sign Up" + text.signupTab ] } ) ] }) }), (mode === "forgot" || mode === "reset") && /* @__PURE__ */ jsxs2("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [ - /* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 8px", fontSize: "20px", fontWeight: 700, color: text }, children: mode === "forgot" ? "Reset Password" : "Enter Reset Code" }), - /* @__PURE__ */ jsx4("p", { style: { margin: 0, fontSize: "14px", color: textMuted }, children: mode === "forgot" ? "Enter your email and we'll send a code" : `Enter the code sent to ${email}` }) + /* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 8px", fontSize: "20px", fontWeight: 700, color: themeColors.text }, children: mode === "forgot" ? text.forgotTitle : text.resetTitle }), + /* @__PURE__ */ jsx4("p", { style: { margin: 0, fontSize: "14px", color: themeColors.textMuted }, children: mode === "forgot" ? text.loginTitle : `Enter the code sent to ${email}` }) ] }), - /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, children: [ + !hasPasswordAuth && !hasSocialAuth && /* @__PURE__ */ jsx4("div", { style: { textAlign: "center", color: themeColors.textMuted, fontSize: "14px", lineHeight: 1.5 }, children: text.noAuthMethods }), + hasPasswordAuth && /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, children: [ mode === "signup" && /* @__PURE__ */ jsxs2("div", { style: styles.field, children: [ - /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: "Full Name" }) }), + /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: text.nameLabel }) }), /* @__PURE__ */ jsx4( "input", { style: styles.input, type: "text", - placeholder: "Enter your name", + placeholder: text.namePlaceholder, value: name, onChange: (e) => setName(e.target.value), required: true @@ -652,13 +807,13 @@ var UrAuth = ({ ) ] }), /* @__PURE__ */ jsxs2("div", { style: styles.field, children: [ - /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: "Email address" }) }), + /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: text.emailLabel }) }), /* @__PURE__ */ jsx4( "input", { style: styles.input, type: "email", - placeholder: "Enter your email address", + placeholder: text.emailPlaceholder, value: email, onChange: (e) => setEmail(e.target.value), required: true, @@ -666,40 +821,40 @@ var UrAuth = ({ } ) ] }), - mode === "reset" && /* @__PURE__ */ jsxs2("div", { style: styles.field, children: [ - /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: "6-digit OTP Code" }) }), - /* @__PURE__ */ jsx4( - "input", - { - style: styles.input, - type: "text", - placeholder: "Enter reset code", - value: otp, - onChange: (e) => setOtp(e.target.value), - required: true - } - ) - ] }), (mode === "signin" || mode === "signup" || mode === "reset") && /* @__PURE__ */ jsxs2("div", { style: styles.field, children: [ /* @__PURE__ */ jsxs2("div", { style: styles.labelRow, children: [ - /* @__PURE__ */ jsx4("label", { style: styles.label, children: mode === "reset" ? "New Password" : "Password" }), + /* @__PURE__ */ jsx4("label", { style: styles.label, children: mode === "reset" ? text.passwordLabel : text.passwordLabel }), mode === "signin" && /* @__PURE__ */ jsx4("button", { type: "button", style: styles.forgotLink, onClick: () => { setMode("forgot"); clearError(); - }, children: "Forgot password?" }) + }, children: text.forgotPasswordLink }) ] }), /* @__PURE__ */ jsx4( "input", { style: styles.input, type: "password", - placeholder: mode === "reset" ? "Enter new password" : "Enter your password", + placeholder: text.passwordPlaceholder, value: password, onChange: (e) => setPassword(e.target.value), required: true } ) ] }), + mode === "reset" && /* @__PURE__ */ jsxs2("div", { style: styles.field, children: [ + /* @__PURE__ */ jsx4("div", { style: styles.labelRow, children: /* @__PURE__ */ jsx4("label", { style: styles.label, children: text.otpLabel }) }), + /* @__PURE__ */ jsx4( + "input", + { + style: styles.input, + type: "text", + placeholder: text.otpPlaceholder, + value: otp, + onChange: (e) => setOtp(e.target.value), + required: true + } + ) + ] }), /* @__PURE__ */ jsx4( "button", { @@ -709,30 +864,14 @@ var UrAuth = ({ onMouseDown: (e) => e.currentTarget.style.transform = "scale(0.98)", onMouseUp: (e) => e.currentTarget.style.transform = "scale(1)", onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)", - children: isLoading ? "Processing..." : mode === "signin" ? "Log In" : mode === "signup" ? "Create Account" : mode === "forgot" ? "Send Reset Code" : "Reset Password" + children: isLoading ? "Processing..." : mode === "signin" ? text.loginButton : mode === "signup" ? text.signupButton : mode === "forgot" ? text.forgotButton : text.resetButton } ) ] }), - (mode === "signin" || mode === "signup") && providers && providers.length > 0 && /* @__PURE__ */ jsxs2(Fragment3, { children: [ - /* @__PURE__ */ jsxs2("div", { style: styles.divider, children: [ - /* @__PURE__ */ jsx4("div", { style: styles.dividerLine }), - /* @__PURE__ */ jsx4("span", { style: styles.dividerText, children: "OR" }), - /* @__PURE__ */ jsx4("div", { style: styles.dividerLine }) - ] }), - /* @__PURE__ */ jsxs2("div", { children: [ - providers.includes("google") && /* @__PURE__ */ jsxs2("button", { style: styles.socialBtn, onClick: () => socialLogin("google"), type: "button", children: [ - /* @__PURE__ */ jsx4(GoogleIcon, {}), - "Continue with Google" - ] }), - providers.includes("github") && /* @__PURE__ */ jsxs2("button", { style: styles.socialBtn, onClick: () => socialLogin("github"), type: "button", children: [ - /* @__PURE__ */ jsx4(GithubIcon, {}), - "Continue with GitHub" - ] }) - ] }) - ] }) + (mode === "signin" || mode === "signup") && renderSocialButtons() ] }), - /* @__PURE__ */ jsxs2("div", { style: styles.footer, children: [ - mode === "signin" ? "Don't have an account yet?" : mode === "signup" ? "Already have an account?" : "Remember your password?", + hasPasswordAuth && /* @__PURE__ */ jsxs2("div", { style: styles.footer, children: [ + footerPrompt, /* @__PURE__ */ jsx4( "button", { @@ -742,7 +881,7 @@ var UrAuth = ({ setMode(mode === "signin" ? "signup" : "signin"); clearError(); }, - children: mode === "signin" ? "Sign up" : "Log in" + children: mode === "signin" ? text.signupTab : text.loginTab } ) ] }) diff --git a/sdks/urbackend-react/dist/index.mjs.map b/sdks/urbackend-react/dist/index.mjs.map index 0dec3712..021540d5 100644 --- a/sdks/urbackend-react/dist/index.mjs.map +++ b/sdks/urbackend-react/dist/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../src/context.tsx","../src/hooks.ts","../src/components.tsx","../src/components/UrAuth.tsx","../src/components/Toast.tsx","../src/components/UrUserButton.tsx","../src/index.ts"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\r\nimport { UrBackendClient, AuthModule, DatabaseModule, StorageModule } from '@urbackend/sdk';\r\nimport type { AuthUser } from '@urbackend/sdk';\r\n\r\ninterface UrContextValue {\r\n client: UrBackendClient | null;\r\n auth: AuthModule | null;\r\n db: DatabaseModule | null;\r\n storage: StorageModule | null;\r\n user: AuthUser | null;\r\n setUser: React.Dispatch>;\r\n isInitializing: boolean;\r\n isLoading: boolean;\r\n setIsLoading: React.Dispatch>;\r\n error: string | null;\r\n setError: React.Dispatch>;\r\n}\r\n\r\nconst UrContext = createContext(undefined);\r\n\r\nexport interface UrProviderProps {\r\n apiKey: string;\r\n baseUrl?: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const UrProvider: React.FC = ({ apiKey, baseUrl, children }) => {\r\n const [user, setUser] = useState(null);\r\n const [isInitializing, setIsInitializing] = useState(true);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState(null);\r\n\r\n const { client, auth, db, storage } = useMemo(() => {\r\n const _client = new UrBackendClient({ apiKey, baseUrl });\r\n return {\r\n client: _client,\r\n auth: new AuthModule(_client),\r\n db: new DatabaseModule(_client),\r\n storage: new StorageModule(_client),\r\n };\r\n }, [apiKey, baseUrl]);\r\n\r\n useEffect(() => {\r\n let mounted = true;\r\n\r\n const initAuth = async () => {\r\n try {\r\n // Hydrate from localStorage first as a fallback for environments without cookies\r\n if (typeof window !== 'undefined') {\r\n const savedToken = localStorage.getItem('ur_auth_token');\r\n if (savedToken) auth.setToken(savedToken);\r\n }\r\n\r\n // Check for social auth callback params\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n const token = hashParams.get('token');\r\n const rtCode = urlParams.get('rtCode');\r\n const error = urlParams.get('error');\r\n\r\n if (error) {\r\n console.error('Social Auth Error:', error);\r\n if (mounted) setError(error);\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else if (token) {\r\n // Social auth succeeded, establish session immediately\r\n auth.setToken(token);\r\n if (typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n \r\n if (rtCode) {\r\n // Exchange for long-lived refresh token\r\n try {\r\n const exRes = await auth.socialExchange({ token, rtCode });\r\n const exToken = (exRes as any).accessToken || (exRes as any).token;\r\n if (exToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', exToken);\r\n } catch (err: any) {\r\n console.error('Failed to exchange refresh token', err);\r\n if (mounted) setError(err.message || 'Failed to complete social login');\r\n throw err;\r\n }\r\n }\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else {\r\n // Attempt to silently refresh session using the HTTP-only cookie\r\n try {\r\n const res = await auth.refreshToken();\r\n const newToken = res.accessToken || (res as any).token;\r\n if (newToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', newToken);\r\n } catch (e) {\r\n // If refresh fails, me() will catch it\r\n }\r\n }\r\n \r\n const currentUser = await auth.me();\r\n if (mounted) {\r\n setUser(currentUser);\r\n }\r\n } catch (error: any) {\r\n if (mounted) {\r\n setUser(null);\r\n // Don't set global error for initial me() check failure (usually just means not logged in)\r\n }\r\n } finally {\r\n if (mounted) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n };\r\n\r\n initAuth();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [auth]);\r\n\r\n const value: UrContextValue = {\r\n client,\r\n auth,\r\n db,\r\n storage,\r\n user,\r\n setUser,\r\n isInitializing,\r\n isLoading,\r\n setIsLoading,\r\n error,\r\n setError,\r\n };\r\n\r\n return {children};\r\n};\r\n\r\nexport const useUrContext = () => {\r\n const context = useContext(UrContext);\r\n if (!context) {\r\n throw new Error('useUrContext must be used within an UrProvider');\r\n }\r\n return context;\r\n};\r\n","import { useCallback } from 'react';\r\nimport { useUrContext } from './context';\r\nimport type { \r\n LoginPayload, \r\n SignUpPayload, \r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload\r\n} from '@urbackend/sdk';\r\n\r\nexport const useAuth = () => {\r\n const { auth, user, setUser, isInitializing, isLoading, setIsLoading, error, setError } = useUrContext();\r\n\r\n if (!auth) {\r\n throw new Error('Auth module not initialized. Make sure you are inside UrProvider.');\r\n }\r\n\r\n const login = useCallback(async (payload: LoginPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const res = await auth.login(payload);\r\n const token = res.accessToken || (res as any).token;\r\n if (token && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n const currentUser = await auth.me();\r\n setUser(currentUser);\r\n } catch (err: any) {\r\n setError(err.message || 'Login failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const signUp = useCallback(async (payload: SignUpPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const newUser = await auth.signUp(payload);\r\n return newUser;\r\n } catch (err: any) {\r\n setError(err.message || 'Sign up failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setIsLoading, setError]);\r\n\r\n const logout = useCallback(async () => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n await auth.logout();\r\n if (typeof window !== 'undefined') localStorage.removeItem('ur_auth_token');\r\n setUser(null);\r\n } catch (err: any) {\r\n setError(err.message || 'Logout failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const socialLogin = useCallback((provider: 'google' | 'github') => {\r\n setError(null);\r\n const url = auth.socialStart(provider);\r\n window.location.href = url;\r\n }, [auth, setError]);\r\n \r\n const verifyEmail = useCallback(async (payload: VerifyEmailPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.verifyEmail(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Email verification failed');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const changePassword = useCallback(async (payload: ChangePasswordPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.changePassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to change password');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const requestPasswordReset = useCallback(async (payload: RequestPasswordResetPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.requestPasswordReset(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to request password reset');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const resetPassword = useCallback(async (payload: ResetPasswordPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.resetPassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to reset password');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const clearError = useCallback(() => setError(null), [setError]);\r\n\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n login,\r\n signUp,\r\n logout,\r\n socialLogin,\r\n verifyEmail,\r\n changePassword,\r\n requestPasswordReset,\r\n resetPassword,\r\n clearError,\r\n authApi: auth // Escape hatch to underlying SDK\r\n };\r\n};\r\n\r\nexport const useUser = () => {\r\n const { user, isInitializing, isLoading, error } = useUrContext();\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n };\r\n};\r\n\r\nexport const useDb = () => {\r\n const { db } = useUrContext();\r\n if (!db) {\r\n throw new Error('Database module not initialized.');\r\n }\r\n return db;\r\n};\r\n\r\nexport const useStorage = () => {\r\n const { storage } = useUrContext();\r\n if (!storage) {\r\n throw new Error('Storage module not initialized.');\r\n }\r\n return storage;\r\n};\r\n","import React, { useEffect } from 'react';\r\nimport { useUser } from './hooks';\r\n\r\nexport interface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to be authenticated.\r\n * If the user is not authenticated after initialization, they will be redirected,\r\n * or the fallback will be rendered (or nothing if fallback is not provided and no window redirect occurs).\r\n */\r\nexport const ProtectedRoute: React.FC = ({ \r\n children, \r\n redirectTo = '/login', \r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && !isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (!isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n\r\nexport interface GuestRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to NOT be authenticated (e.g. for Login pages).\r\n * If the user IS authenticated, they will be redirected to the specified route.\r\n */\r\nexport const GuestRoute: React.FC = ({\r\n children,\r\n redirectTo = '/dashboard',\r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n","import React, { useState, useEffect } from 'react';\r\nimport { useAuth } from '../hooks';\r\nimport { Toast } from './Toast';\r\n\r\nexport interface UrAuthProps {\r\n providers?: ('google' | 'github')[];\r\n theme?: 'light' | 'dark'; // Dark mode not perfectly matched to image, but kept for API compat\r\n onSuccess?: () => void;\r\n}\r\n\r\nexport const UrAuth: React.FC = ({ \r\n providers = ['google', 'github'], \r\n theme = 'light',\r\n onSuccess\r\n}) => {\r\n const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth();\r\n const [mode, setMode] = useState<'signin' | 'signup' | 'forgot' | 'reset'>('signin');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [otp, setOtp] = useState('');\r\n const [name, setName] = useState('');\r\n const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null);\r\n\r\n useEffect(() => {\r\n if (error) {\r\n setToast({ message: error, type: 'error' });\r\n }\r\n }, [error]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n if (mode === 'signin') {\r\n await login({ email, password });\r\n setToast({ message: 'Welcome back!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'signup') {\r\n await signUp({ email, password, name });\r\n // Auto-login after signup for convenience\r\n await login({ email, password });\r\n setToast({ message: 'Account created successfully!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'forgot') {\r\n await requestPasswordReset({ email });\r\n setToast({ message: 'Reset code sent to your email', type: 'success' });\r\n setMode('reset');\r\n } else if (mode === 'reset') {\r\n await resetPassword({ email, otp, newPassword: password });\r\n setToast({ message: 'Password reset successfully', type: 'success' });\r\n setMode('signin');\r\n setPassword('');\r\n setOtp('');\r\n }\r\n } catch (err: any) {\r\n // Error is now handled and stored globally by useAuth hook, which triggers the useEffect toast\r\n }\r\n };\r\n\r\n const isDark = theme === 'dark';\r\n const bg = isDark ? '#1a1a1a' : '#ffffff';\r\n const text = isDark ? '#ffffff' : '#0f172a';\r\n const textMuted = isDark ? '#a1a1aa' : '#64748b';\r\n const border = isDark ? '#333' : '#e2e8f0';\r\n const inputBg = isDark ? '#2a2a2a' : '#ffffff';\r\n \r\n const styles = {\r\n wrapper: {\r\n width: '100%',\r\n maxWidth: '420px',\r\n margin: '0 auto',\r\n borderRadius: '0',\r\n background: bg,\r\n boxShadow: isDark ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)',\r\n border: `1px solid ${border}`,\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n color: text,\r\n },\r\n body: {\r\n padding: '32px 32px 24px 32px',\r\n },\r\n switcherContainer: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n marginBottom: '32px'\r\n },\r\n switcher: {\r\n display: 'inline-flex',\r\n background: isDark ? '#2a2a2a' : '#f1f5f9',\r\n padding: '4px',\r\n borderRadius: '0',\r\n },\r\n switchBtn: (active: boolean) => ({\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '8px 20px',\r\n borderRadius: '0',\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n color: active ? text : textMuted,\r\n background: active ? (isDark ? '#444' : '#ffffff') : 'transparent',\r\n boxShadow: active ? (isDark ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none',\r\n border: 'none',\r\n transition: 'all 0.2s ease',\r\n }),\r\n field: {\r\n marginBottom: '20px',\r\n },\r\n labelRow: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '8px',\r\n },\r\n label: {\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n color: isDark ? '#ddd' : '#334155',\r\n },\r\n forgotLink: {\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n color: text,\r\n cursor: 'pointer',\r\n textDecoration: 'none',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n },\r\n input: {\r\n width: '100%',\r\n padding: '12px 16px',\r\n borderRadius: '0',\r\n border: `1px solid ${border}`,\r\n background: inputBg,\r\n color: text,\r\n fontSize: '14px',\r\n boxSizing: 'border-box' as const,\r\n outline: 'none',\r\n transition: 'border-color 0.2s ease',\r\n },\r\n primaryBtn: {\r\n width: '100%',\r\n padding: '14px',\r\n borderRadius: '0',\r\n background: 'linear-gradient(180deg, #2a2a2a 0%, #111111 100%)',\r\n color: '#ffffff',\r\n fontSize: '15px',\r\n fontWeight: 600,\r\n border: 'none',\r\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n transition: 'transform 0.1s ease',\r\n },\r\n divider: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n margin: '24px 0',\r\n color: '#94a3b8',\r\n fontSize: '11px',\r\n fontWeight: 600,\r\n letterSpacing: '1px',\r\n },\r\n dividerLine: {\r\n flex: 1,\r\n height: '1px',\r\n background: border,\r\n },\r\n dividerText: {\r\n padding: '0 12px',\r\n },\r\n socialBtn: {\r\n width: '100%',\r\n padding: '12px',\r\n borderRadius: '0',\r\n border: `1px solid ${border}`,\r\n background: isDark ? '#2a2a2a' : '#ffffff',\r\n color: text,\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n gap: '10px',\r\n marginBottom: '12px',\r\n cursor: 'pointer',\r\n boxShadow: isDark ? 'none' : '0 1px 2px rgba(0,0,0,0.02)',\r\n transition: 'background 0.2s ease',\r\n },\r\n footer: {\r\n background: isDark ? '#222' : '#f8fafc',\r\n padding: '24px',\r\n textAlign: 'center' as const,\r\n borderTop: `1px solid ${border}`,\r\n fontSize: '13px',\r\n color: textMuted,\r\n },\r\n footerLink: {\r\n color: text,\r\n fontWeight: 600,\r\n textDecoration: 'underline',\r\n cursor: 'pointer',\r\n marginLeft: '4px',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n }\r\n };\r\n\r\n const GoogleIcon = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n\r\n const GithubIcon = () => (\r\n \r\n \r\n \r\n );\r\n\r\n return (\r\n
\r\n {toast && (\r\n {\r\n setToast(null);\r\n if (toast.type === 'error') clearError();\r\n }} \r\n />\r\n )}\r\n \r\n
\r\n {(mode === 'signin' || mode === 'signup') && (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {(mode === 'forgot' || mode === 'reset') && (\r\n
\r\n

\r\n {mode === 'forgot' ? 'Reset Password' : 'Enter Reset Code'}\r\n

\r\n

\r\n {mode === 'forgot' ? \"Enter your email and we'll send a code\" : `Enter the code sent to ${email}`}\r\n

\r\n
\r\n )}\r\n\r\n
\r\n {mode === 'signup' && (\r\n
\r\n
\r\n \r\n
\r\n setName(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n \r\n
\r\n
\r\n \r\n
\r\n setEmail(e.target.value)}\r\n required\r\n readOnly={mode === 'reset'}\r\n />\r\n
\r\n\r\n {mode === 'reset' && (\r\n
\r\n
\r\n \r\n
\r\n setOtp(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n {(mode === 'signin' || mode === 'signup' || mode === 'reset') && (\r\n
\r\n
\r\n \r\n {mode === 'signin' && (\r\n \r\n )}\r\n
\r\n setPassword(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n \r\n
\r\n\r\n {(mode === 'signin' || mode === 'signup') && providers && providers.length > 0 && (\r\n <>\r\n
\r\n
\r\n OR\r\n
\r\n
\r\n\r\n
\r\n {providers.includes('google') && (\r\n \r\n )}\r\n {providers.includes('github') && (\r\n \r\n )}\r\n
\r\n \r\n )}\r\n
\r\n\r\n
\r\n {mode === 'signin' ? \"Don't have an account yet?\" \r\n : mode === 'signup' ? \"Already have an account?\"\r\n : \"Remember your password?\"}\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\n\r\ninterface ToastProps {\r\n message: string;\r\n type: 'success' | 'error';\r\n onClose: () => void;\r\n isDark?: boolean;\r\n}\r\n\r\nexport const Toast: React.FC = ({ message, type, onClose, isDark = false }) => {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isLeaving, setIsLeaving] = useState(false);\r\n\r\n useEffect(() => {\r\n // Trigger enter animation on mount\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n\r\n let innerTimer: ReturnType;\r\n const timer = setTimeout(() => {\r\n setIsLeaving(true);\r\n innerTimer = setTimeout(onClose, 300); // Wait for exit animation\r\n }, 4000);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n if (innerTimer) clearTimeout(innerTimer);\r\n };\r\n }, [onClose]);\r\n\r\n const bgColor = isDark ? 'rgba(30, 30, 30, 0.9)' : 'rgba(255, 255, 255, 0.9)';\r\n const borderColor = type === 'success' ? 'rgba(34, 197, 94, 0.5)' : 'rgba(239, 68, 68, 0.5)';\r\n const iconColor = type === 'success' ? '#22c55e' : '#ef4444';\r\n const textColor = isDark ? '#fff' : '#000';\r\n\r\n return (\r\n <>\r\n \r\n \r\n {type === 'success' ? (\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {message}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\nimport { useUser, useAuth } from '../hooks';\n\nexport interface UrUserButtonProps {\n /**\n * Shape of the profile avatar. Defaults to 'square' as requested.\n */\n shape?: 'square' | 'circle';\n /**\n * Position of the button on the screen. Defaults to 'top-right'.\n * Use 'inline' if you want to place it within a normal flex/grid layout instead of absolute positioning.\n */\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'inline';\n /**\n * Called when \"Profile\" is clicked.\n */\n onProfileClick?: () => void;\n /**\n * Called when \"Settings\" is clicked.\n */\n onSettingsClick?: () => void;\n /**\n * Z-index for the fixed container. Defaults to 999.\n */\n zIndex?: number;\n}\n\nexport const UrUserButton: React.FC = ({\n shape = 'square',\n position = 'top-right',\n onProfileClick,\n onSettingsClick,\n zIndex = 999,\n}) => {\n const { user } = useUser();\n const { logout } = useAuth();\n const [isOpen, setIsOpen] = useState(false);\n const containerRef = useRef(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n if (!user) return null; // Only render if logged in\n\n const borderRadius = shape === 'circle' ? '50%' : '0px';\n const isFixed = position !== 'inline';\n\n const positionStyles: React.CSSProperties = isFixed\n ? {\n position: 'fixed',\n zIndex,\n top: position.includes('top') ? '24px' : 'auto',\n bottom: position.includes('bottom') ? '24px' : 'auto',\n right: position.includes('right') ? '24px' : 'auto',\n left: position.includes('left') ? '24px' : 'auto',\n }\n : { position: 'relative' };\n\n const dropdownStyles: React.CSSProperties = {\n position: 'absolute',\n top: position.includes('top') || position === 'inline' ? 'calc(100% + 8px)' : 'auto',\n bottom: position.includes('bottom') ? 'calc(100% + 8px)' : 'auto',\n right: position.includes('right') || position === 'inline' ? '0' : 'auto',\n left: position.includes('left') ? '0' : 'auto',\n background: '#ffffff',\n border: '1px solid #e2e8f0',\n borderRadius: '0px',\n boxShadow: '0 10px 25px rgba(0,0,0,0.1)',\n width: '220px',\n display: isOpen ? 'block' : 'none',\n overflow: 'hidden',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n };\n\n const getInitials = () => {\n return user.name?.[0]?.toUpperCase() || user.email?.[0]?.toUpperCase() || 'U';\n };\n\n return (\n
\n setIsOpen(!isOpen)}\n style={{\n width: '40px',\n height: '40px',\n padding: 0,\n border: '1px solid #e2e8f0',\n background: '#f8fafc',\n borderRadius,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n boxShadow: '0 2px 5px rgba(0,0,0,0.05)',\n transition: 'transform 0.1s ease',\n }}\n >\n {user.avatarUrl ? (\n \"User\"\n ) : (\n \n {getInitials()}\n \n )}\n \n\n
\n {/* User Info Header */}\n
\n
\n {user.name || 'User'}\n
\n
\n {user.email}\n
\n
\n\n {/* Action List */}\n
\n {onProfileClick && (\n {\n setIsOpen(false);\n onProfileClick();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#334155',\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Profile\n \n )}\n\n {onSettingsClick && (\n {\n setIsOpen(false);\n onSettingsClick();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#334155',\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Settings\n \n )}\n\n
\n\n {\n setIsOpen(false);\n logout();\n }}\n style={{\n width: '100%',\n textAlign: 'left',\n padding: '10px 12px',\n background: 'transparent',\n border: 'none',\n fontSize: '14px',\n color: '#ef4444',\n fontWeight: 500,\n cursor: 'pointer',\n borderRadius: '0px',\n display: 'block',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = '#fef2f2')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\n >\n Logout\n \n
\n
\n
\n );\n};\n","export { UrProvider, useUrContext } from './context';\nexport type { UrProviderProps } from './context';\n\nexport { useAuth, useUser, useDb, useStorage } from './hooks';\nexport { ProtectedRoute, GuestRoute } from './components';\nexport type { ProtectedRouteProps, GuestRouteProps } from './components';\n\nexport { UrAuth } from './components/UrAuth';\nexport type { UrAuthProps } from './components/UrAuth';\n\nexport * from './components/UrUserButton';\n\nexport * from '@urbackend/sdk'; // re-export types so users don't need to import from sdk directly"],"mappings":"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","names":["error","useEffect","jsx","useEffect","useState","useEffect","useEffect","useState","Fragment","jsx","Fragment","jsx","jsxs","useState","useEffect","useState","useEffect","jsx","jsxs","useState","useEffect"]} \ No newline at end of file +{"version":3,"sources":["../src/context.tsx","../src/hooks.ts","../src/components.tsx","../src/components/UrAuth.tsx","../src/components/Toast.tsx","../src/components/UrUserButton.tsx","../src/index.ts"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\r\nimport { UrBackendClient, AuthModule, DatabaseModule, StorageModule } from '@urbackend/sdk';\r\nimport type { AuthUser } from '@urbackend/sdk';\r\n\r\ninterface UrContextValue {\r\n client: UrBackendClient | null;\r\n auth: AuthModule | null;\r\n db: DatabaseModule | null;\r\n storage: StorageModule | null;\r\n user: AuthUser | null;\r\n setUser: React.Dispatch>;\r\n isInitializing: boolean;\r\n isLoading: boolean;\r\n setIsLoading: React.Dispatch>;\r\n error: string | null;\r\n setError: React.Dispatch>;\r\n}\r\n\r\nconst UrContext = createContext(undefined);\r\n\r\nexport interface UrProviderProps {\r\n apiKey: string;\r\n baseUrl?: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const UrProvider: React.FC = ({ apiKey, baseUrl, children }) => {\r\n const [user, setUser] = useState(null);\r\n const [isInitializing, setIsInitializing] = useState(true);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState(null);\r\n\r\n const { client, auth, db, storage } = useMemo(() => {\r\n const _client = new UrBackendClient({ apiKey, baseUrl });\r\n return {\r\n client: _client,\r\n auth: new AuthModule(_client),\r\n db: new DatabaseModule(_client),\r\n storage: new StorageModule(_client),\r\n };\r\n }, [apiKey, baseUrl]);\r\n\r\n useEffect(() => {\r\n let mounted = true;\r\n\r\n const initAuth = async () => {\r\n try {\r\n // Hydrate from localStorage first as a fallback for environments without cookies\r\n if (typeof window !== 'undefined') {\r\n const savedToken = localStorage.getItem('ur_auth_token');\r\n if (savedToken) auth.setToken(savedToken);\r\n }\r\n\r\n // Check for social auth callback params\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n const token = hashParams.get('token');\r\n const rtCode = urlParams.get('rtCode');\r\n const error = urlParams.get('error');\r\n\r\n if (error) {\r\n console.error('Social Auth Error:', error);\r\n if (mounted) setError(error);\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else if (token) {\r\n // Social auth succeeded, establish session immediately\r\n auth.setToken(token);\r\n if (typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n \r\n if (rtCode) {\r\n // Exchange for long-lived refresh token\r\n try {\r\n const exRes = await auth.socialExchange({ token, rtCode });\r\n const exToken = (exRes as any).accessToken || (exRes as any).token;\r\n if (exToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', exToken);\r\n } catch (err: any) {\r\n console.error('Failed to exchange refresh token', err);\r\n if (mounted) setError(err.message || 'Failed to complete social login');\r\n throw err;\r\n }\r\n }\r\n window.history.replaceState({}, document.title, window.location.pathname);\r\n } else {\r\n // Attempt to silently refresh session using the HTTP-only cookie\r\n try {\r\n const res = await auth.refreshToken();\r\n const newToken = res.accessToken || (res as any).token;\r\n if (newToken && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', newToken);\r\n } catch (e) {\r\n // If refresh fails, me() will catch it\r\n }\r\n }\r\n \r\n const currentUser = await auth.me();\r\n if (mounted) {\r\n setUser(currentUser);\r\n }\r\n } catch (error: any) {\r\n if (mounted) {\r\n setUser(null);\r\n // Don't set global error for initial me() check failure (usually just means not logged in)\r\n }\r\n } finally {\r\n if (mounted) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n };\r\n\r\n initAuth();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [auth]);\r\n\r\n const value: UrContextValue = {\r\n client,\r\n auth,\r\n db,\r\n storage,\r\n user,\r\n setUser,\r\n isInitializing,\r\n isLoading,\r\n setIsLoading,\r\n error,\r\n setError,\r\n };\r\n\r\n return {children};\r\n};\r\n\r\nexport const useUrContext = () => {\r\n const context = useContext(UrContext);\r\n if (!context) {\r\n throw new Error('useUrContext must be used within an UrProvider');\r\n }\r\n return context;\r\n};\r\n","import { useCallback } from 'react';\r\nimport { useUrContext } from './context';\r\nimport type { \r\n LoginPayload, \r\n SignUpPayload, \r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload\r\n} from '@urbackend/sdk';\r\n\r\nexport const useAuth = () => {\r\n const { auth, user, setUser, isInitializing, isLoading, setIsLoading, error, setError } = useUrContext();\r\n\r\n if (!auth) {\r\n throw new Error('Auth module not initialized. Make sure you are inside UrProvider.');\r\n }\r\n\r\n const login = useCallback(async (payload: LoginPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const res = await auth.login(payload);\r\n const token = res.accessToken || (res as any).token;\r\n if (token && typeof window !== 'undefined') localStorage.setItem('ur_auth_token', token);\r\n const currentUser = await auth.me();\r\n setUser(currentUser);\r\n } catch (err: any) {\r\n setError(err.message || 'Login failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const signUp = useCallback(async (payload: SignUpPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n const newUser = await auth.signUp(payload);\r\n return newUser;\r\n } catch (err: any) {\r\n setError(err.message || 'Sign up failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setIsLoading, setError]);\r\n\r\n const logout = useCallback(async () => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n await auth.logout();\r\n if (typeof window !== 'undefined') localStorage.removeItem('ur_auth_token');\r\n setUser(null);\r\n } catch (err: any) {\r\n setError(err.message || 'Logout failed');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setUser, setIsLoading, setError]);\r\n\r\n const socialLogin = useCallback((provider: 'google' | 'github') => {\r\n setError(null);\r\n const url = auth.socialStart(provider);\r\n window.location.href = url;\r\n }, [auth, setError]);\r\n \r\n const verifyEmail = useCallback(async (payload: VerifyEmailPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.verifyEmail(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Email verification failed');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const changePassword = useCallback(async (payload: ChangePasswordPayload) => {\r\n try {\r\n setError(null);\r\n return await auth.changePassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to change password');\r\n throw err;\r\n }\r\n }, [auth, setError]);\r\n\r\n const requestPasswordReset = useCallback(async (payload: RequestPasswordResetPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.requestPasswordReset(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to request password reset');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const resetPassword = useCallback(async (payload: ResetPasswordPayload) => {\r\n try {\r\n setError(null);\r\n setIsLoading(true);\r\n return await auth.resetPassword(payload);\r\n } catch (err: any) {\r\n setError(err.message || 'Failed to reset password');\r\n throw err;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [auth, setError, setIsLoading]);\r\n\r\n const clearError = useCallback(() => setError(null), [setError]);\r\n\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n login,\r\n signUp,\r\n logout,\r\n socialLogin,\r\n verifyEmail,\r\n changePassword,\r\n requestPasswordReset,\r\n resetPassword,\r\n clearError,\r\n authApi: auth // Escape hatch to underlying SDK\r\n };\r\n};\r\n\r\nexport const useUser = () => {\r\n const { user, isInitializing, isLoading, error } = useUrContext();\r\n return {\r\n user,\r\n isInitializing,\r\n isLoading,\r\n error,\r\n isAuthenticated: !!user,\r\n };\r\n};\r\n\r\nexport const useDb = () => {\r\n const { db } = useUrContext();\r\n if (!db) {\r\n throw new Error('Database module not initialized.');\r\n }\r\n return db;\r\n};\r\n\r\nexport const useStorage = () => {\r\n const { storage } = useUrContext();\r\n if (!storage) {\r\n throw new Error('Storage module not initialized.');\r\n }\r\n return storage;\r\n};\r\n","import React, { useEffect } from 'react';\r\nimport { useUser } from './hooks';\r\n\r\nexport interface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to be authenticated.\r\n * If the user is not authenticated after initialization, they will be redirected,\r\n * or the fallback will be rendered (or nothing if fallback is not provided and no window redirect occurs).\r\n */\r\nexport const ProtectedRoute: React.FC = ({ \r\n children, \r\n redirectTo = '/login', \r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && !isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (!isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n\r\nexport interface GuestRouteProps {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n fallback?: React.ReactNode;\r\n onRedirect?: () => void;\r\n}\r\n\r\n/**\r\n * A wrapper component that requires the user to NOT be authenticated (e.g. for Login pages).\r\n * If the user IS authenticated, they will be redirected to the specified route.\r\n */\r\nexport const GuestRoute: React.FC = ({\r\n children,\r\n redirectTo = '/dashboard',\r\n fallback = null,\r\n onRedirect\r\n}) => {\r\n const { isAuthenticated, isInitializing } = useUser();\r\n\r\n useEffect(() => {\r\n if (!isInitializing && isAuthenticated) {\r\n if (onRedirect) {\r\n onRedirect();\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = redirectTo;\r\n }\r\n }\r\n }, [isAuthenticated, isInitializing, redirectTo, onRedirect]);\r\n\r\n if (isInitializing) {\r\n return fallback;\r\n }\r\n\r\n if (isAuthenticated) {\r\n return fallback;\r\n }\r\n\r\n return <>{children};\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\nimport { useAuth } from '../hooks';\r\nimport { Toast } from './Toast';\r\n\r\ntype AuthProvider = 'google' | 'github';\r\ntype ThemeMode = 'light' | 'dark';\r\n\r\ninterface AuthColors {\r\n background: string;\r\n surface: string;\r\n text: string;\r\n textMuted: string;\r\n border: string;\r\n inputBackground: string;\r\n primary: string;\r\n primaryText: string;\r\n footerBackground: string;\r\n dividerText: string;\r\n socialButtonBackground: string;\r\n}\r\n\r\ninterface AuthBranding {\r\n brandName?: string;\r\n appName?: string;\r\n title?: string;\r\n subtitle?: string;\r\n logo?: React.ReactNode | string;\r\n primaryColor?: string;\r\n}\r\n\r\ninterface AuthLabels {\r\n loginTab: string;\r\n signupTab: string;\r\n loginTitle: string;\r\n signupTitle: string;\r\n forgotTitle: string;\r\n resetTitle: string;\r\n loginButton: string;\r\n signupButton: string;\r\n forgotButton: string;\r\n resetButton: string;\r\n emailLabel: string;\r\n emailPlaceholder: string;\r\n passwordLabel: string;\r\n passwordPlaceholder: string;\r\n nameLabel: string;\r\n namePlaceholder: string;\r\n otpLabel: string;\r\n otpPlaceholder: string;\r\n forgotPasswordLink: string;\r\n socialDivider: string;\r\n googleButton: string;\r\n githubButton: string;\r\n footerSigninPrompt: string;\r\n footerSignupPrompt: string;\r\n footerForgotPrompt: string;\r\n noAuthMethods: string;\r\n // Aliases support\r\n signInTitle?: string;\r\n signUpTitle?: string;\r\n signInTab?: string;\r\n signUpTab?: string;\r\n signInButton?: string;\r\n signUpButton?: string;\r\n}\r\n\r\nexport interface UrAuthProps {\r\n providers?: AuthProvider[] | {\r\n google?: boolean;\r\n github?: boolean;\r\n emailPassword?: boolean;\r\n };\r\n enableEmailPassword?: boolean;\r\n theme?: ThemeMode;\r\n colors?: Partial;\r\n branding?: AuthBranding;\r\n labels?: Partial;\r\n onSuccess?: () => void;\r\n}\r\n\r\nconst defaultLabels: AuthLabels = {\r\n loginTab: 'Login',\r\n signupTab: 'Sign Up',\r\n loginTitle: 'Welcome back',\r\n signupTitle: 'Create your account',\r\n forgotTitle: 'Reset Password',\r\n resetTitle: 'Enter Reset Code',\r\n loginButton: 'Log In',\r\n signupButton: 'Create Account',\r\n forgotButton: 'Send Reset Code',\r\n resetButton: 'Reset Password',\r\n emailLabel: 'Email address',\r\n emailPlaceholder: 'Enter your email address',\r\n passwordLabel: 'Password',\r\n passwordPlaceholder: 'Enter your password',\r\n nameLabel: 'Full Name',\r\n namePlaceholder: 'Enter your name',\r\n otpLabel: '6-digit OTP Code',\r\n otpPlaceholder: 'Enter reset code',\r\n forgotPasswordLink: 'Forgot password?',\r\n socialDivider: 'OR',\r\n googleButton: 'Continue with Google',\r\n githubButton: 'Continue with GitHub',\r\n footerSigninPrompt: \"Don't have an account yet?\",\r\n footerSignupPrompt: 'Already have an account?',\r\n footerForgotPrompt: 'Remember your password?',\r\n noAuthMethods: 'No authentication methods are enabled for this screen.',\r\n};\r\n\r\nconst defaultThemeColors: Record = {\r\n light: {\r\n background: '#ffffff',\r\n surface: '#ffffff',\r\n text: '#0f172a',\r\n textMuted: '#64748b',\r\n border: '#e2e8f0',\r\n inputBackground: '#ffffff',\r\n primary: '#111111',\r\n primaryText: '#ffffff',\r\n footerBackground: '#f8fafc',\r\n dividerText: '#94a3b8',\r\n socialButtonBackground: '#ffffff',\r\n },\r\n dark: {\r\n background: '#1a1a1a',\r\n surface: '#1a1a1a',\r\n text: '#ffffff',\r\n textMuted: '#a1a1aa',\r\n border: '#333333',\r\n inputBackground: '#2a2a2a',\r\n primary: '#ffffff',\r\n primaryText: '#111111',\r\n footerBackground: '#222222',\r\n dividerText: '#94a3b8',\r\n socialButtonBackground: '#2a2a2a',\r\n },\r\n};\r\n\r\nexport const UrAuth: React.FC = ({ \r\n providers = ['google', 'github'], \r\n enableEmailPassword = true,\r\n theme = 'light',\r\n colors,\r\n branding,\r\n labels,\r\n onSuccess\r\n}) => {\r\n const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth();\r\n const [mode, setMode] = useState<'signin' | 'signup' | 'forgot' | 'reset'>('signin');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [otp, setOtp] = useState('');\r\n const [name, setName] = useState('');\r\n const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null);\r\n\r\n const text = {\r\n ...defaultLabels,\r\n ...labels,\r\n loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab,\r\n loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle,\r\n loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton,\r\n signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab,\r\n signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle,\r\n signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton,\r\n };\r\n\r\n const themeColors = { ...defaultThemeColors[theme], ...colors };\r\n const primaryColor = branding?.primaryColor || themeColors.primary;\r\n\r\n let isGoogleEnabled = true;\r\n let isGithubEnabled = true;\r\n let isEmailPasswordEnabled = enableEmailPassword;\r\n\r\n if (providers) {\r\n if (Array.isArray(providers)) {\r\n isGoogleEnabled = providers.includes('google');\r\n isGithubEnabled = providers.includes('github');\r\n } else if (typeof providers === 'object') {\r\n isGoogleEnabled = !!providers.google;\r\n isGithubEnabled = !!providers.github;\r\n isEmailPasswordEnabled = providers.emailPassword !== undefined ? providers.emailPassword : false;\r\n }\r\n }\r\n\r\n const hasPasswordAuth = isEmailPasswordEnabled;\r\n const hasSocialAuth = isGoogleEnabled || isGithubEnabled;\r\n const brandName = branding?.brandName || branding?.appName || branding?.title || 'urBackend';\r\n const headerTitle = branding?.title || brandName;\r\n const headerSubtitle = branding?.subtitle || (mode === 'signin'\r\n ? text.loginTitle\r\n : mode === 'signup'\r\n ? text.signupTitle\r\n : mode === 'forgot'\r\n ? text.forgotTitle\r\n : text.resetTitle);\r\n const showSwitcher = hasPasswordAuth;\r\n\r\n useEffect(() => {\r\n if (error) {\r\n setToast({ message: error, type: 'error' });\r\n }\r\n }, [error]);\r\n\r\n useEffect(() => {\r\n if (!hasPasswordAuth && mode !== 'signin') {\r\n setMode('signin');\r\n }\r\n }, [hasPasswordAuth, mode]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n if (mode === 'signin') {\r\n await login({ email, password });\r\n setToast({ message: 'Welcome back!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'signup') {\r\n await signUp({ email, password, name });\r\n await login({ email, password });\r\n setToast({ message: 'Account created successfully!', type: 'success' });\r\n if (onSuccess) onSuccess();\r\n } else if (mode === 'forgot') {\r\n await requestPasswordReset({ email });\r\n setToast({ message: 'Reset code sent to your email', type: 'success' });\r\n setMode('reset');\r\n } else if (mode === 'reset') {\r\n await resetPassword({ email, otp, newPassword: password });\r\n setToast({ message: 'Password reset successfully', type: 'success' });\r\n setMode('signin');\r\n setPassword('');\r\n setOtp('');\r\n }\r\n } catch (err: any) {\r\n // Errors are surfaced via the shared auth hook state.\r\n }\r\n };\r\n\r\n const styles = {\r\n wrapper: {\r\n width: '100%',\r\n maxWidth: '420px',\r\n margin: '0 auto',\r\n borderRadius: '0',\r\n background: themeColors.background,\r\n boxShadow: theme === 'dark' ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)',\r\n border: `1px solid ${themeColors.border}`,\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n color: themeColors.text,\r\n },\r\n body: {\r\n padding: '32px 32px 24px 32px',\r\n },\r\n header: {\r\n textAlign: 'center' as const,\r\n marginBottom: '28px',\r\n },\r\n brandRow: {\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n gap: '12px',\r\n marginBottom: '10px',\r\n },\r\n brandLogo: {\r\n width: '44px',\r\n height: '44px',\r\n borderRadius: '12px',\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9',\r\n color: themeColors.text,\r\n overflow: 'hidden' as const,\r\n },\r\n brandTitle: {\r\n margin: 0,\r\n fontSize: '26px',\r\n lineHeight: 1.1,\r\n fontWeight: 800,\r\n color: themeColors.text,\r\n },\r\n brandSubtitle: {\r\n margin: '0 auto',\r\n maxWidth: '320px',\r\n fontSize: '14px',\r\n lineHeight: 1.5,\r\n color: themeColors.textMuted,\r\n },\r\n switcherContainer: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n marginBottom: '32px'\r\n },\r\n switcher: {\r\n display: 'inline-flex',\r\n background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9',\r\n padding: '4px',\r\n borderRadius: '0',\r\n },\r\n switchBtn: (active: boolean) => ({\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '8px 20px',\r\n borderRadius: '0',\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n color: active ? themeColors.text : themeColors.textMuted,\r\n background: active ? (theme === 'dark' ? '#444444' : '#ffffff') : 'transparent',\r\n boxShadow: active ? (theme === 'dark' ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none',\r\n border: 'none',\r\n transition: 'all 0.2s ease',\r\n }),\r\n field: {\r\n marginBottom: '20px',\r\n },\r\n labelRow: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '8px',\r\n },\r\n label: {\r\n fontSize: '13px',\r\n fontWeight: 600,\r\n color: theme === 'dark' ? '#dddddd' : '#334155',\r\n },\r\n forgotLink: {\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n color: themeColors.text,\r\n cursor: 'pointer',\r\n textDecoration: 'none',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n },\r\n input: {\r\n width: '100%',\r\n padding: '12px 16px',\r\n borderRadius: '0',\r\n border: `1px solid ${themeColors.border}`,\r\n background: themeColors.inputBackground,\r\n color: themeColors.text,\r\n fontSize: '14px',\r\n boxSizing: 'border-box' as const,\r\n outline: 'none',\r\n transition: 'border-color 0.2s ease',\r\n },\r\n primaryBtn: {\r\n width: '100%',\r\n padding: '14px',\r\n borderRadius: '0',\r\n background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === 'dark' ? '#111111' : '#111111'} 100%)`,\r\n color: themeColors.primaryText,\r\n fontSize: '15px',\r\n fontWeight: 600,\r\n border: 'none',\r\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n transition: 'transform 0.1s ease',\r\n },\r\n divider: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n margin: '24px 0',\r\n color: themeColors.dividerText,\r\n fontSize: '11px',\r\n fontWeight: 600,\r\n letterSpacing: '1px',\r\n },\r\n dividerLine: {\r\n flex: 1,\r\n height: '1px',\r\n background: themeColors.border,\r\n },\r\n dividerText: {\r\n padding: '0 12px',\r\n },\r\n socialBtn: {\r\n width: '100%',\r\n padding: '12px',\r\n borderRadius: '0',\r\n border: `1px solid ${themeColors.border}`,\r\n background: themeColors.socialButtonBackground,\r\n color: themeColors.text,\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n gap: '10px',\r\n marginBottom: '12px',\r\n cursor: 'pointer',\r\n boxShadow: theme === 'dark' ? 'none' : '0 1px 2px rgba(0,0,0,0.02)',\r\n transition: 'background 0.2s ease',\r\n },\r\n footer: {\r\n background: themeColors.footerBackground,\r\n padding: '24px',\r\n textAlign: 'center' as const,\r\n borderTop: `1px solid ${themeColors.border}`,\r\n fontSize: '13px',\r\n color: themeColors.textMuted,\r\n },\r\n footerLink: {\r\n color: themeColors.text,\r\n fontWeight: 600,\r\n textDecoration: 'underline',\r\n cursor: 'pointer',\r\n marginLeft: '4px',\r\n background: 'none',\r\n border: 'none',\r\n padding: 0,\r\n }\r\n };\r\n\r\n const GoogleIcon = () => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n\r\n const GithubIcon = () => (\r\n \r\n \r\n \r\n );\r\n\r\n const renderSocialButtons = () => {\r\n if (!hasSocialAuth) {\r\n return null;\r\n }\r\n\r\n return (\r\n <>\r\n {hasPasswordAuth && (\r\n
\r\n
\r\n {text.socialDivider}\r\n
\r\n
\r\n )}\r\n\r\n
\r\n {isGoogleEnabled && (\r\n \r\n )}\r\n {isGithubEnabled && (\r\n \r\n )}\r\n
\r\n \r\n );\r\n };\r\n\r\n const footerPrompt = mode === 'signin'\r\n ? text.footerSigninPrompt\r\n : mode === 'signup'\r\n ? text.footerSignupPrompt\r\n : text.footerForgotPrompt;\r\n\r\n return (\r\n
\r\n {toast && (\r\n {\r\n setToast(null);\r\n if (toast.type === 'error') clearError();\r\n }} \r\n />\r\n )}\r\n \r\n
\r\n {(branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && (\r\n
\r\n
\r\n {branding?.logo ? (\r\n
\r\n {typeof branding.logo === 'string' ? (\r\n {brandName}\r\n ) : (\r\n branding.logo\r\n )}\r\n
\r\n ) : (\r\n
\r\n {brandName.slice(0, 1).toUpperCase()}\r\n
\r\n )}\r\n
\r\n

{headerTitle}

\r\n

{headerSubtitle}

\r\n
\r\n )}\r\n\r\n {showSwitcher && (mode === 'signin' || mode === 'signup') && (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {(mode === 'forgot' || mode === 'reset') && (\r\n
\r\n

\r\n {mode === 'forgot' ? text.forgotTitle : text.resetTitle}\r\n

\r\n

\r\n {mode === 'forgot' ? text.loginTitle : `Enter the code sent to ${email}`}\r\n

\r\n
\r\n )}\r\n\r\n {!hasPasswordAuth && !hasSocialAuth && (\r\n
\r\n {text.noAuthMethods}\r\n
\r\n )}\r\n\r\n {hasPasswordAuth && (\r\n
\r\n {mode === 'signup' && (\r\n
\r\n
\r\n \r\n
\r\n setName(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n
\r\n
\r\n \r\n
\r\n setEmail(e.target.value)}\r\n required\r\n readOnly={mode === 'reset'}\r\n />\r\n
\r\n\r\n {(mode === 'signin' || mode === 'signup' || mode === 'reset') && (\r\n
\r\n
\r\n \r\n {mode === 'signin' && (\r\n \r\n )}\r\n
\r\n setPassword(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n {mode === 'reset' && (\r\n
\r\n
\r\n \r\n
\r\n setOtp(e.target.value)}\r\n required\r\n />\r\n
\r\n )}\r\n\r\n \r\n
\r\n )}\r\n\r\n {(mode === 'signin' || mode === 'signup') && renderSocialButtons()}\r\n
\r\n\r\n {hasPasswordAuth && (\r\n
\r\n {footerPrompt}\r\n \r\n
\r\n )}\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState } from 'react';\r\n\r\ninterface ToastProps {\r\n message: string;\r\n type: 'success' | 'error';\r\n onClose: () => void;\r\n isDark?: boolean;\r\n}\r\n\r\nexport const Toast: React.FC = ({ message, type, onClose, isDark = false }) => {\r\n const [isVisible, setIsVisible] = useState(false);\r\n const [isLeaving, setIsLeaving] = useState(false);\r\n\r\n useEffect(() => {\r\n // Trigger enter animation on mount\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n\r\n let innerTimer: ReturnType;\r\n const timer = setTimeout(() => {\r\n setIsLeaving(true);\r\n innerTimer = setTimeout(onClose, 300); // Wait for exit animation\r\n }, 4000);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n if (innerTimer) clearTimeout(innerTimer);\r\n };\r\n }, [onClose]);\r\n\r\n const bgColor = isDark ? 'rgba(30, 30, 30, 0.9)' : 'rgba(255, 255, 255, 0.9)';\r\n const borderColor = type === 'success' ? 'rgba(34, 197, 94, 0.5)' : 'rgba(239, 68, 68, 0.5)';\r\n const iconColor = type === 'success' ? '#22c55e' : '#ef4444';\r\n const textColor = isDark ? '#fff' : '#000';\r\n\r\n return (\r\n <>\r\n \r\n \r\n {type === 'success' ? (\r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {message}\r\n
\r\n \r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\r\nimport { useUser, useAuth } from '../hooks';\r\n\r\nexport interface UrUserButtonProps {\r\n /**\r\n * Shape of the profile avatar. Defaults to 'square' as requested.\r\n */\r\n shape?: 'square' | 'circle';\r\n /**\r\n * Position of the button on the screen. Defaults to 'top-right'.\r\n * Use 'inline' if you want to place it within a normal flex/grid layout instead of absolute positioning.\r\n */\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'inline';\r\n /**\r\n * Called when \"Profile\" is clicked.\r\n */\r\n onProfileClick?: () => void;\r\n /**\r\n * Called when \"Settings\" is clicked.\r\n */\r\n onSettingsClick?: () => void;\r\n /**\r\n * Z-index for the fixed container. Defaults to 999.\r\n */\r\n zIndex?: number;\r\n}\r\n\r\nexport const UrUserButton: React.FC = ({\r\n shape = 'square',\r\n position = 'top-right',\r\n onProfileClick,\r\n onSettingsClick,\r\n zIndex = 999,\r\n}) => {\r\n const { user } = useUser();\r\n const { logout } = useAuth();\r\n const [isOpen, setIsOpen] = useState(false);\r\n const containerRef = useRef(null);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\r\n setIsOpen(false);\r\n }\r\n };\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, []);\r\n\r\n if (!user) return null; // Only render if logged in\r\n\r\n const borderRadius = shape === 'circle' ? '50%' : '0px';\r\n const isFixed = position !== 'inline';\r\n\r\n const positionStyles: React.CSSProperties = isFixed\r\n ? {\r\n position: 'fixed',\r\n zIndex,\r\n top: position.includes('top') ? '24px' : 'auto',\r\n bottom: position.includes('bottom') ? '24px' : 'auto',\r\n right: position.includes('right') ? '24px' : 'auto',\r\n left: position.includes('left') ? '24px' : 'auto',\r\n }\r\n : { position: 'relative' };\r\n\r\n const dropdownStyles: React.CSSProperties = {\r\n position: 'absolute',\r\n top: position.includes('top') || position === 'inline' ? 'calc(100% + 8px)' : 'auto',\r\n bottom: position.includes('bottom') ? 'calc(100% + 8px)' : 'auto',\r\n right: position.includes('right') || position === 'inline' ? '0' : 'auto',\r\n left: position.includes('left') ? '0' : 'auto',\r\n background: '#ffffff',\r\n border: '1px solid #e2e8f0',\r\n borderRadius: '0px',\r\n boxShadow: '0 10px 25px rgba(0,0,0,0.1)',\r\n width: '220px',\r\n display: isOpen ? 'block' : 'none',\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, -apple-system, sans-serif',\r\n };\r\n\r\n const getInitials = () => {\r\n return user.name?.[0]?.toUpperCase() || user.email?.[0]?.toUpperCase() || 'U';\r\n };\r\n\r\n return (\r\n
\r\n setIsOpen(!isOpen)}\r\n style={{\r\n width: '40px',\r\n height: '40px',\r\n padding: 0,\r\n border: '1px solid #e2e8f0',\r\n background: '#f8fafc',\r\n borderRadius,\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden',\r\n boxShadow: '0 2px 5px rgba(0,0,0,0.05)',\r\n transition: 'transform 0.1s ease',\r\n }}\r\n >\r\n {user.avatarUrl ? (\r\n \"User\"\r\n ) : (\r\n \r\n {getInitials()}\r\n \r\n )}\r\n \r\n\r\n
\r\n {/* User Info Header */}\r\n
\r\n
\r\n {user.name || 'User'}\r\n
\r\n
\r\n {user.email}\r\n
\r\n
\r\n\r\n {/* Action List */}\r\n
\r\n {onProfileClick && (\r\n {\r\n setIsOpen(false);\r\n onProfileClick();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#334155',\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Profile\r\n \r\n )}\r\n\r\n {onSettingsClick && (\r\n {\r\n setIsOpen(false);\r\n onSettingsClick();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#334155',\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#f1f5f9')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Settings\r\n \r\n )}\r\n\r\n
\r\n\r\n {\r\n setIsOpen(false);\r\n logout();\r\n }}\r\n style={{\r\n width: '100%',\r\n textAlign: 'left',\r\n padding: '10px 12px',\r\n background: 'transparent',\r\n border: 'none',\r\n fontSize: '14px',\r\n color: '#ef4444',\r\n fontWeight: 500,\r\n cursor: 'pointer',\r\n borderRadius: '0px',\r\n display: 'block',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = '#fef2f2')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}\r\n >\r\n Logout\r\n \r\n
\r\n
\r\n
\r\n );\r\n};\r\n","export { UrProvider, useUrContext } from './context';\r\nexport type { UrProviderProps } from './context';\r\n\r\nexport { useAuth, useUser, useDb, useStorage } from './hooks';\r\nexport { ProtectedRoute, GuestRoute } from './components';\r\nexport type { ProtectedRouteProps, GuestRouteProps } from './components';\r\n\r\nexport { UrAuth } from './components/UrAuth';\r\nexport type { UrAuthProps } from './components/UrAuth';\r\n\r\nexport * from './components/UrUserButton';\r\n\r\nexport * from '@urbackend/sdk'; // re-export types so users don't need to import from sdk directly"],"mappings":"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","names":["error","useEffect","jsx","useEffect","useEffect","useState","useEffect","useState","Fragment","jsx","Fragment","jsx","jsxs","useState","useEffect","useState","useEffect","jsx","jsxs","useState","useEffect"]} \ No newline at end of file diff --git a/sdks/urbackend-react/src/components/UrAuth.tsx b/sdks/urbackend-react/src/components/UrAuth.tsx index 0c7cf91f..28cc8569 100644 --- a/sdks/urbackend-react/src/components/UrAuth.tsx +++ b/sdks/urbackend-react/src/components/UrAuth.tsx @@ -1,16 +1,148 @@ -import React, { useState, useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useAuth } from '../hooks'; import { Toast } from './Toast'; +type AuthProvider = 'google' | 'github'; +type ThemeMode = 'light' | 'dark'; + +interface AuthColors { + background: string; + surface: string; + text: string; + textMuted: string; + border: string; + inputBackground: string; + primary: string; + primaryText: string; + footerBackground: string; + dividerText: string; + socialButtonBackground: string; +} + +interface AuthBranding { + brandName?: string; + appName?: string; + title?: string; + subtitle?: string; + logo?: React.ReactNode | string; + primaryColor?: string; +} + +interface AuthLabels { + loginTab: string; + signupTab: string; + loginTitle: string; + signupTitle: string; + forgotTitle: string; + resetTitle: string; + loginButton: string; + signupButton: string; + forgotButton: string; + resetButton: string; + emailLabel: string; + emailPlaceholder: string; + passwordLabel: string; + passwordPlaceholder: string; + nameLabel: string; + namePlaceholder: string; + otpLabel: string; + otpPlaceholder: string; + forgotPasswordLink: string; + socialDivider: string; + googleButton: string; + githubButton: string; + footerSigninPrompt: string; + footerSignupPrompt: string; + footerForgotPrompt: string; + noAuthMethods: string; + // Aliases support + signInTitle?: string; + signUpTitle?: string; + signInTab?: string; + signUpTab?: string; + signInButton?: string; + signUpButton?: string; +} + export interface UrAuthProps { - providers?: ('google' | 'github')[]; - theme?: 'light' | 'dark'; // Dark mode not perfectly matched to image, but kept for API compat + providers?: AuthProvider[] | { + google?: boolean; + github?: boolean; + emailPassword?: boolean; + }; + enableEmailPassword?: boolean; + theme?: ThemeMode; + colors?: Partial; + branding?: AuthBranding; + labels?: Partial; onSuccess?: () => void; } +const defaultLabels: AuthLabels = { + loginTab: 'Login', + signupTab: 'Sign Up', + loginTitle: 'Welcome back', + signupTitle: 'Create your account', + forgotTitle: 'Reset Password', + resetTitle: 'Enter Reset Code', + loginButton: 'Log In', + signupButton: 'Create Account', + forgotButton: 'Send Reset Code', + resetButton: 'Reset Password', + emailLabel: 'Email address', + emailPlaceholder: 'Enter your email address', + passwordLabel: 'Password', + passwordPlaceholder: 'Enter your password', + nameLabel: 'Full Name', + namePlaceholder: 'Enter your name', + otpLabel: '6-digit OTP Code', + otpPlaceholder: 'Enter reset code', + forgotPasswordLink: 'Forgot password?', + socialDivider: 'OR', + googleButton: 'Continue with Google', + githubButton: 'Continue with GitHub', + footerSigninPrompt: "Don't have an account yet?", + footerSignupPrompt: 'Already have an account?', + footerForgotPrompt: 'Remember your password?', + noAuthMethods: 'No authentication methods are enabled for this screen.', +}; + +const defaultThemeColors: Record = { + light: { + background: '#ffffff', + surface: '#ffffff', + text: '#0f172a', + textMuted: '#64748b', + border: '#e2e8f0', + inputBackground: '#ffffff', + primary: '#111111', + primaryText: '#ffffff', + footerBackground: '#f8fafc', + dividerText: '#94a3b8', + socialButtonBackground: '#ffffff', + }, + dark: { + background: '#1a1a1a', + surface: '#1a1a1a', + text: '#ffffff', + textMuted: '#a1a1aa', + border: '#333333', + inputBackground: '#2a2a2a', + primary: '#ffffff', + primaryText: '#111111', + footerBackground: '#222222', + dividerText: '#94a3b8', + socialButtonBackground: '#2a2a2a', + }, +}; + export const UrAuth: React.FC = ({ providers = ['google', 'github'], + enableEmailPassword = true, theme = 'light', + colors, + branding, + labels, onSuccess }) => { const { login, signUp, socialLogin, requestPasswordReset, resetPassword, isLoading, error, clearError } = useAuth(); @@ -21,12 +153,60 @@ export const UrAuth: React.FC = ({ const [name, setName] = useState(''); const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null); + const text = { + ...defaultLabels, + ...labels, + loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab, + loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle, + loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton, + signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab, + signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle, + signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton, + }; + + const themeColors = { ...defaultThemeColors[theme], ...colors }; + const primaryColor = branding?.primaryColor || themeColors.primary; + + let isGoogleEnabled = true; + let isGithubEnabled = true; + let isEmailPasswordEnabled = enableEmailPassword; + + if (providers) { + if (Array.isArray(providers)) { + isGoogleEnabled = providers.includes('google'); + isGithubEnabled = providers.includes('github'); + } else if (typeof providers === 'object') { + isGoogleEnabled = !!providers.google; + isGithubEnabled = !!providers.github; + isEmailPasswordEnabled = providers.emailPassword !== undefined ? providers.emailPassword : false; + } + } + + const hasPasswordAuth = isEmailPasswordEnabled; + const hasSocialAuth = isGoogleEnabled || isGithubEnabled; + const brandName = branding?.brandName || branding?.appName || branding?.title || 'urBackend'; + const headerTitle = branding?.title || brandName; + const headerSubtitle = branding?.subtitle || (mode === 'signin' + ? text.loginTitle + : mode === 'signup' + ? text.signupTitle + : mode === 'forgot' + ? text.forgotTitle + : text.resetTitle); + const showSwitcher = hasPasswordAuth; + useEffect(() => { if (error) { setToast({ message: error, type: 'error' }); } }, [error]); + useEffect(() => { + if (!hasPasswordAuth && mode !== 'signin') { + setMode('signin'); + } + }, [hasPasswordAuth, mode]); + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { @@ -36,7 +216,6 @@ export const UrAuth: React.FC = ({ if (onSuccess) onSuccess(); } else if (mode === 'signup') { await signUp({ email, password, name }); - // Auto-login after signup for convenience await login({ email, password }); setToast({ message: 'Account created successfully!', type: 'success' }); if (onSuccess) onSuccess(); @@ -52,33 +231,62 @@ export const UrAuth: React.FC = ({ setOtp(''); } } catch (err: any) { - // Error is now handled and stored globally by useAuth hook, which triggers the useEffect toast + // Errors are surfaced via the shared auth hook state. } }; - const isDark = theme === 'dark'; - const bg = isDark ? '#1a1a1a' : '#ffffff'; - const text = isDark ? '#ffffff' : '#0f172a'; - const textMuted = isDark ? '#a1a1aa' : '#64748b'; - const border = isDark ? '#333' : '#e2e8f0'; - const inputBg = isDark ? '#2a2a2a' : '#ffffff'; - const styles = { wrapper: { width: '100%', maxWidth: '420px', margin: '0 auto', borderRadius: '0', - background: bg, - boxShadow: isDark ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)', - border: `1px solid ${border}`, + background: themeColors.background, + boxShadow: theme === 'dark' ? '0 20px 40px rgba(0,0,0,0.5)' : '0 20px 40px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.05)', + border: `1px solid ${themeColors.border}`, overflow: 'hidden', fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', - color: text, + color: themeColors.text, }, body: { padding: '32px 32px 24px 32px', }, + header: { + textAlign: 'center' as const, + marginBottom: '28px', + }, + brandRow: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + gap: '12px', + marginBottom: '10px', + }, + brandLogo: { + width: '44px', + height: '44px', + borderRadius: '12px', + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9', + color: themeColors.text, + overflow: 'hidden' as const, + }, + brandTitle: { + margin: 0, + fontSize: '26px', + lineHeight: 1.1, + fontWeight: 800, + color: themeColors.text, + }, + brandSubtitle: { + margin: '0 auto', + maxWidth: '320px', + fontSize: '14px', + lineHeight: 1.5, + color: themeColors.textMuted, + }, switcherContainer: { display: 'flex', alignItems: 'center', @@ -87,7 +295,7 @@ export const UrAuth: React.FC = ({ }, switcher: { display: 'inline-flex', - background: isDark ? '#2a2a2a' : '#f1f5f9', + background: theme === 'dark' ? '#2a2a2a' : '#f1f5f9', padding: '4px', borderRadius: '0', }, @@ -100,9 +308,9 @@ export const UrAuth: React.FC = ({ fontSize: '13px', fontWeight: 600, cursor: 'pointer', - color: active ? text : textMuted, - background: active ? (isDark ? '#444' : '#ffffff') : 'transparent', - boxShadow: active ? (isDark ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none', + color: active ? themeColors.text : themeColors.textMuted, + background: active ? (theme === 'dark' ? '#444444' : '#ffffff') : 'transparent', + boxShadow: active ? (theme === 'dark' ? '0 2px 4px rgba(0,0,0,0.2)' : '0 2px 8px rgba(0,0,0,0.05)') : 'none', border: 'none', transition: 'all 0.2s ease', }), @@ -118,12 +326,12 @@ export const UrAuth: React.FC = ({ label: { fontSize: '13px', fontWeight: 600, - color: isDark ? '#ddd' : '#334155', + color: theme === 'dark' ? '#dddddd' : '#334155', }, forgotLink: { fontSize: '12px', fontWeight: 600, - color: text, + color: themeColors.text, cursor: 'pointer', textDecoration: 'none', background: 'none', @@ -134,9 +342,9 @@ export const UrAuth: React.FC = ({ width: '100%', padding: '12px 16px', borderRadius: '0', - border: `1px solid ${border}`, - background: inputBg, - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.inputBackground, + color: themeColors.text, fontSize: '14px', boxSizing: 'border-box' as const, outline: 'none', @@ -146,8 +354,8 @@ export const UrAuth: React.FC = ({ width: '100%', padding: '14px', borderRadius: '0', - background: 'linear-gradient(180deg, #2a2a2a 0%, #111111 100%)', - color: '#ffffff', + background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === 'dark' ? '#111111' : '#111111'} 100%)`, + color: themeColors.primaryText, fontSize: '15px', fontWeight: 600, border: 'none', @@ -160,7 +368,7 @@ export const UrAuth: React.FC = ({ display: 'flex', alignItems: 'center', margin: '24px 0', - color: '#94a3b8', + color: themeColors.dividerText, fontSize: '11px', fontWeight: 600, letterSpacing: '1px', @@ -168,7 +376,7 @@ export const UrAuth: React.FC = ({ dividerLine: { flex: 1, height: '1px', - background: border, + background: themeColors.border, }, dividerText: { padding: '0 12px', @@ -177,9 +385,9 @@ export const UrAuth: React.FC = ({ width: '100%', padding: '12px', borderRadius: '0', - border: `1px solid ${border}`, - background: isDark ? '#2a2a2a' : '#ffffff', - color: text, + border: `1px solid ${themeColors.border}`, + background: themeColors.socialButtonBackground, + color: themeColors.text, fontSize: '14px', fontWeight: 600, display: 'flex', @@ -188,19 +396,19 @@ export const UrAuth: React.FC = ({ gap: '10px', marginBottom: '12px', cursor: 'pointer', - boxShadow: isDark ? 'none' : '0 1px 2px rgba(0,0,0,0.02)', + boxShadow: theme === 'dark' ? 'none' : '0 1px 2px rgba(0,0,0,0.02)', transition: 'background 0.2s ease', }, footer: { - background: isDark ? '#222' : '#f8fafc', + background: themeColors.footerBackground, padding: '24px', textAlign: 'center' as const, - borderTop: `1px solid ${border}`, + borderTop: `1px solid ${themeColors.border}`, fontSize: '13px', - color: textMuted, + color: themeColors.textMuted, }, footerLink: { - color: text, + color: themeColors.text, fontWeight: 600, textDecoration: 'underline', cursor: 'pointer', @@ -221,18 +429,57 @@ export const UrAuth: React.FC = ({ ); const GithubIcon = () => ( - + ); + const renderSocialButtons = () => { + if (!hasSocialAuth) { + return null; + } + + return ( + <> + {hasPasswordAuth && ( +
+
+ {text.socialDivider} +
+
+ )} + +
+ {isGoogleEnabled && ( + + )} + {isGithubEnabled && ( + + )} +
+ + ); + }; + + const footerPrompt = mode === 'signin' + ? text.footerSigninPrompt + : mode === 'signup' + ? text.footerSignupPrompt + : text.footerForgotPrompt; + return (
{toast && ( { setToast(null); if (toast.type === 'error') clearError(); @@ -241,7 +488,29 @@ export const UrAuth: React.FC = ({ )}
- {(mode === 'signin' || mode === 'signup') && ( + {(branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && ( +
+
+ {branding?.logo ? ( +
+ {typeof branding.logo === 'string' ? ( + {brandName} + ) : ( + branding.logo + )} +
+ ) : ( + + )} +
+

{headerTitle}

+

{headerSubtitle}

+
+ )} + + {showSwitcher && (mode === 'signin' || mode === 'signup') && (
@@ -266,140 +535,125 @@ export const UrAuth: React.FC = ({ {(mode === 'forgot' || mode === 'reset') && (
-

- {mode === 'forgot' ? 'Reset Password' : 'Enter Reset Code'} +

+ {mode === 'forgot' ? text.forgotTitle : text.resetTitle}

-

- {mode === 'forgot' ? "Enter your email and we'll send a code" : `Enter the code sent to ${email}`} +

+ {mode === 'forgot' ? text.loginTitle : `Enter the code sent to ${email}`}

)} -
- {mode === 'signup' && ( -
-
- -
- setName(e.target.value)} - required - /> -
- )} - -
-
- -
- setEmail(e.target.value)} - required - readOnly={mode === 'reset'} - /> + {!hasPasswordAuth && !hasSocialAuth && ( +
+ {text.noAuthMethods}
+ )} - {mode === 'reset' && ( -
-
- + {hasPasswordAuth && ( + + {mode === 'signup' && ( +
+
+ +
+ setName(e.target.value)} + required + />
- setOtp(e.target.value)} - required - /> -
- )} + )} - {(mode === 'signin' || mode === 'signup' || mode === 'reset') && (
- - {mode === 'signin' && ( - - )} +
setPassword(e.target.value)} + type="email" + placeholder={text.emailPlaceholder} + value={email} + onChange={e => setEmail(e.target.value)} required + readOnly={mode === 'reset'} />
- )} - - - - {(mode === 'signin' || mode === 'signup') && providers && providers.length > 0 && ( - <> -
-
- OR -
-
+ {(mode === 'signin' || mode === 'signup' || mode === 'reset') && ( +
+
+ + {mode === 'signin' && ( + + )} +
+ setPassword(e.target.value)} + required + /> +
+ )} -
- {providers.includes('google') && ( - - )} - {providers.includes('github') && ( - - )} -
- + {mode === 'reset' && ( +
+
+ +
+ setOtp(e.target.value)} + required + /> +
+ )} + + + )} -
-
- {mode === 'signin' ? "Don't have an account yet?" - : mode === 'signup' ? "Already have an account?" - : "Remember your password?"} - + {(mode === 'signin' || mode === 'signup') && renderSocialButtons()}
+ + {hasPasswordAuth && ( +
+ {footerPrompt} + +
+ )}
); }; diff --git a/sdks/urbackend-react/tests/UrAuth.test.tsx b/sdks/urbackend-react/tests/UrAuth.test.tsx index a4a2116c..8613008f 100644 --- a/sdks/urbackend-react/tests/UrAuth.test.tsx +++ b/sdks/urbackend-react/tests/UrAuth.test.tsx @@ -76,7 +76,7 @@ describe('UrAuth Component', () => { fireEvent.click(screen.getByText('Forgot password?')); - expect(screen.getByText('Reset Password')).toBeInTheDocument(); + expect(screen.getAllByText('Reset Password')[0]).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Send Reset Code' })).toBeInTheDocument(); mockRequestPasswordReset.mockResolvedValueOnce(undefined); @@ -87,4 +87,47 @@ describe('UrAuth Component', () => { expect(mockRequestPasswordReset).toHaveBeenCalledWith({ email: 'test@example.com' }); }); }); + + it('applies custom primary color to primary button', () => { + render(); + const primaryButton = screen.getByRole('button', { name: 'Log In' }); + expect(primaryButton.style.background).toContain('#4F46E5'); + }); + + it('hides email/password form when disabled via providers object', () => { + render(); + expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Log In' })).not.toBeInTheDocument(); + expect(screen.getByText('Continue with Google')).toBeInTheDocument(); + expect(screen.queryByText('Continue with GitHub')).not.toBeInTheDocument(); + }); + + it('only shows GitHub login when configured via providers object', () => { + render(); + expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument(); + expect(screen.getByText('Continue with GitHub')).toBeInTheDocument(); + expect(screen.queryByText('Continue with Google')).not.toBeInTheDocument(); + }); + + it('displays message when all authentication methods are disabled', () => { + render(); + expect(screen.getByText('No authentication methods are enabled for this screen.')).toBeInTheDocument(); + }); + + it('supports custom labels and aliases', () => { + render(); + expect(screen.getByText('Hello User')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Enter App' })).toBeInTheDocument(); + }); + + it('supports branding configurations', () => { + const { container } = render( + + ); + expect(screen.getByText('My Custom App')).toBeInTheDocument(); + expect(screen.getByText('Authentication')).toBeInTheDocument(); + const logoImg = container.querySelector('img'); + expect(logoImg).toBeInTheDocument(); + expect(logoImg?.getAttribute('src')).toBe('/assets/logo.png'); + }); }); From 6d6ff1ea3b10edb6bbd73887f512827a8e607a0d Mon Sep 17 00:00:00 2001 From: Nitin Kumar Yadav Date: Thu, 11 Jun 2026 20:53:03 +0530 Subject: [PATCH 2/4] coderabbit fixes on ui configuration PR --- examples/react-sdk-demo/src/App.tsx | 2 +- sdks/urbackend-react/src/components/UrAuth.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/react-sdk-demo/src/App.tsx b/examples/react-sdk-demo/src/App.tsx index 08fc8d4f..1de17448 100644 --- a/examples/react-sdk-demo/src/App.tsx +++ b/examples/react-sdk-demo/src/App.tsx @@ -83,7 +83,7 @@ function Dashboard() {
{user?.avatarUrl ? ( - Avatar + Avatar ) : (
{user?.name?.[0]?.toUpperCase() || user?.email?.[0]?.toUpperCase()} diff --git a/sdks/urbackend-react/src/components/UrAuth.tsx b/sdks/urbackend-react/src/components/UrAuth.tsx index 28cc8569..fb521af4 100644 --- a/sdks/urbackend-react/src/components/UrAuth.tsx +++ b/sdks/urbackend-react/src/components/UrAuth.tsx @@ -178,7 +178,7 @@ export const UrAuth: React.FC = ({ } else if (typeof providers === 'object') { isGoogleEnabled = !!providers.google; isGithubEnabled = !!providers.github; - isEmailPasswordEnabled = providers.emailPassword !== undefined ? providers.emailPassword : false; + isEmailPasswordEnabled = providers.emailPassword !== undefined ? providers.emailPassword : enableEmailPassword; } } From 9e67758eaa6ae226f82581051af0edd54bacb2ea Mon Sep 17 00:00:00 2001 From: Nitin Kumar Yadav Date: Fri, 12 Jun 2026 15:47:04 +0530 Subject: [PATCH 3/4] fixed coderabbit caution warining --- .../urbackend-react/src/components/UrAuth.tsx | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/sdks/urbackend-react/src/components/UrAuth.tsx b/sdks/urbackend-react/src/components/UrAuth.tsx index fb521af4..6754675c 100644 --- a/sdks/urbackend-react/src/components/UrAuth.tsx +++ b/sdks/urbackend-react/src/components/UrAuth.tsx @@ -55,6 +55,8 @@ interface AuthLabels { footerSignupPrompt: string; footerForgotPrompt: string; noAuthMethods: string; + forgotSubtitle: string; + resetSubtitle: string; // Aliases support signInTitle?: string; signUpTitle?: string; @@ -105,6 +107,8 @@ const defaultLabels: AuthLabels = { footerSignupPrompt: 'Already have an account?', footerForgotPrompt: 'Remember your password?', noAuthMethods: 'No authentication methods are enabled for this screen.', + forgotSubtitle: 'Welcome back', + resetSubtitle: 'Enter the code sent to {email}', }; const defaultThemeColors: Record = { @@ -136,6 +140,37 @@ const defaultThemeColors: Record = { }, }; +// Helper to adjust brightness of hex colors for professional gradient stops +const adjustColor = (color: string, percent: number) => { + try { + if (color.startsWith('#')) { + let hex = color.replace('#', ''); + if (hex.length === 3) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + let r = parseInt(hex.substring(0, 2), 16); + let g = parseInt(hex.substring(2, 4), 16); + let b = parseInt(hex.substring(4, 6), 16); + + r = Math.min(255, Math.max(0, r + percent)); + g = Math.min(255, Math.max(0, g + percent)); + b = Math.min(255, Math.max(0, b + percent)); + + const rr = r.toString(16).padStart(2, '0'); + const gg = g.toString(16).padStart(2, '0'); + const bb = b.toString(16).padStart(2, '0'); + + return `#${rr}${gg}${bb}`; + } + } catch (e) { + // Safe fallback to original color + } + return color; +}; + + + + export const UrAuth: React.FC = ({ providers = ['google', 'github'], enableEmailPassword = true, @@ -153,19 +188,20 @@ export const UrAuth: React.FC = ({ const [name, setName] = useState(''); const [toast, setToast] = useState<{message: string, type: 'success' | 'error'} | null>(null); - const text = { - ...defaultLabels, - ...labels, - loginTab: labels?.signInTab || labels?.loginTab || defaultLabels.loginTab, - loginTitle: labels?.signInTitle || labels?.loginTitle || defaultLabels.loginTitle, - loginButton: labels?.signInButton || labels?.loginButton || defaultLabels.loginButton, - signupTab: labels?.signUpTab || labels?.signupTab || defaultLabels.signupTab, - signupTitle: labels?.signUpTitle || labels?.signupTitle || defaultLabels.signupTitle, - signupButton: labels?.signUpButton || labels?.signupButton || defaultLabels.signupButton, - }; + const text = { + ...defaultLabels, + ...labels, + loginTab: labels?.signInTab ?? labels?.loginTab ?? defaultLabels.loginTab, + loginTitle: labels?.signInTitle ?? labels?.loginTitle ?? defaultLabels.loginTitle, + loginButton: labels?.signInButton ?? labels?.loginButton ?? defaultLabels.loginButton, + signupTab: labels?.signUpTab ?? labels?.signupTab ?? defaultLabels.signupTab, + signupTitle: labels?.signUpTitle ?? labels?.signupTitle ?? defaultLabels.signupTitle, + signupButton: labels?.signUpButton ?? labels?.signupButton ?? defaultLabels.signupButton, +}; const themeColors = { ...defaultThemeColors[theme], ...colors }; const primaryColor = branding?.primaryColor || themeColors.primary; + const secondStopColor = adjustColor(primaryColor, -15); let isGoogleEnabled = true; let isGithubEnabled = true; @@ -354,7 +390,7 @@ export const UrAuth: React.FC = ({ width: '100%', padding: '14px', borderRadius: '0', - background: `linear-gradient(180deg, ${primaryColor} 0%, ${theme === 'dark' ? '#111111' : '#111111'} 100%)`, + background: `linear-gradient(180deg, ${primaryColor} 0%, ${secondStopColor} 100%)`, color: themeColors.primaryText, fontSize: '15px', fontWeight: 600, @@ -539,7 +575,8 @@ export const UrAuth: React.FC = ({ {mode === 'forgot' ? text.forgotTitle : text.resetTitle}

- {mode === 'forgot' ? text.loginTitle : `Enter the code sent to ${email}`} + {mode === 'forgot' ? text.forgotSubtitle : text.resetSubtitle.replace('{email}', email)} +

)} From e6dd9aacfb2c99add4c2e794ce03d5f38ccc50c3 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Yadav Date: Sat, 13 Jun 2026 13:12:43 +0530 Subject: [PATCH 4/4] last fix --- examples/react-sdk-demo/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/react-sdk-demo/src/App.tsx b/examples/react-sdk-demo/src/App.tsx index 1de17448..34abff8e 100644 --- a/examples/react-sdk-demo/src/App.tsx +++ b/examples/react-sdk-demo/src/App.tsx @@ -82,8 +82,8 @@ function Dashboard() { }}>
- {user?.avatarUrl ? ( - Avatar + {typeof user?.avatarUrl === 'string' && user?.avatarUrl ? ( + Avatar ) : (
{user?.name?.[0]?.toUpperCase() || user?.email?.[0]?.toUpperCase()}