@proveanything/smartlinks-auth-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +323 -0
  2. package/dist/api.d.ts +44 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +105 -0
  5. package/dist/components/AuthContainer.d.ts +12 -0
  6. package/dist/components/AuthContainer.d.ts.map +1 -0
  7. package/dist/components/AuthContainer.js +46 -0
  8. package/dist/components/AuthUIPreview.d.ts +11 -0
  9. package/dist/components/AuthUIPreview.d.ts.map +1 -0
  10. package/dist/components/AuthUIPreview.js +10 -0
  11. package/dist/components/EmailAuthForm.d.ts +14 -0
  12. package/dist/components/EmailAuthForm.d.ts.map +1 -0
  13. package/dist/components/EmailAuthForm.js +20 -0
  14. package/dist/components/PasswordResetForm.d.ts +13 -0
  15. package/dist/components/PasswordResetForm.d.ts.map +1 -0
  16. package/dist/components/PasswordResetForm.js +37 -0
  17. package/dist/components/PhoneAuthForm.d.ts +11 -0
  18. package/dist/components/PhoneAuthForm.d.ts.map +1 -0
  19. package/dist/components/PhoneAuthForm.js +20 -0
  20. package/dist/components/ProtectedRoute.d.ts +9 -0
  21. package/dist/components/ProtectedRoute.d.ts.map +1 -0
  22. package/dist/components/ProtectedRoute.js +20 -0
  23. package/dist/components/ProviderButtons.d.ts +12 -0
  24. package/dist/components/ProviderButtons.d.ts.map +1 -0
  25. package/dist/components/ProviderButtons.js +8 -0
  26. package/dist/context/AuthContext.d.ts +20 -0
  27. package/dist/context/AuthContext.d.ts.map +1 -0
  28. package/dist/context/AuthContext.js +113 -0
  29. package/dist/index.css +2 -0
  30. package/dist/index.css.map +1 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.esm.css +2 -0
  34. package/dist/index.esm.css.map +1 -0
  35. package/dist/index.esm.js +840 -0
  36. package/dist/index.esm.js.map +1 -0
  37. package/dist/index.js +867 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/smartlinks.d.ts +65 -0
  40. package/dist/smartlinks.d.ts.map +1 -0
  41. package/dist/smartlinks.js +141 -0
  42. package/dist/types.d.ts +101 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +1 -0
  45. package/dist/utils/tokenStorage.d.ts +14 -0
  46. package/dist/utils/tokenStorage.d.ts.map +1 -0
  47. package/dist/utils/tokenStorage.js +71 -0
  48. package/package.json +57 -0
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useState } from 'react';
3
+ import './AuthForm.css';
4
+ export const PasswordResetForm = ({ onSubmit, onBack, loading, error, success, token, }) => {
5
+ const [email, setEmail] = useState('');
6
+ const [password, setPassword] = useState('');
7
+ const [confirmPassword, setConfirmPassword] = useState('');
8
+ const [passwordError, setPasswordError] = useState('');
9
+ const handleSubmit = async (e) => {
10
+ e.preventDefault();
11
+ if (token) {
12
+ // Reset password with token
13
+ if (password !== confirmPassword) {
14
+ setPasswordError('Passwords do not match');
15
+ return;
16
+ }
17
+ if (password.length < 6) {
18
+ setPasswordError('Password must be at least 6 characters');
19
+ return;
20
+ }
21
+ setPasswordError('');
22
+ await onSubmit(password, confirmPassword);
23
+ }
24
+ else {
25
+ // Request password reset
26
+ await onSubmit(email);
27
+ }
28
+ };
29
+ if (success) {
30
+ return (_jsxs("div", { className: "auth-form", children: [_jsxs("div", { className: "auth-form-header", children: [_jsx("div", { style: { textAlign: 'center', marginBottom: '1rem' }, children: _jsxs("svg", { width: "64", height: "64", viewBox: "0 0 64 64", fill: "none", style: { margin: '0 auto' }, children: [_jsx("circle", { cx: "32", cy: "32", r: "32", fill: "#10b981", fillOpacity: "0.1" }), _jsx("path", { d: "M20 32l8 8 16-16", stroke: "#10b981", strokeWidth: "4", strokeLinecap: "round", strokeLinejoin: "round" })] }) }), _jsx("h2", { className: "auth-form-title", children: token ? 'Password reset!' : 'Check your email' }), _jsx("p", { className: "auth-form-subtitle", children: token
31
+ ? 'Your password has been successfully reset. You can now sign in with your new password.'
32
+ : `We've sent password reset instructions to ${email}` })] }), _jsx("button", { type: "button", className: "auth-button auth-button-primary", onClick: onBack, children: "Back to Sign in" })] }));
33
+ }
34
+ return (_jsxs("form", { className: "auth-form", onSubmit: handleSubmit, children: [_jsxs("div", { className: "auth-form-header", children: [_jsx("h2", { className: "auth-form-title", children: token ? 'Set new password' : 'Reset your password' }), _jsx("p", { className: "auth-form-subtitle", children: token
35
+ ? 'Enter your new password below.'
36
+ : "Enter your email address and we'll send you instructions to reset your password." })] }), (error || passwordError) && (_jsxs("div", { className: "auth-error", role: "alert", children: [_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm1 13H7v-2h2v2zm0-3H7V4h2v6z" }) }), error || passwordError] })), token ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "auth-form-group", children: [_jsx("label", { htmlFor: "password", className: "auth-label", children: "New Password" }), _jsx("input", { type: "password", id: "password", className: "auth-input", value: password, onChange: (e) => setPassword(e.target.value), required: true, disabled: loading, placeholder: "Enter new password", autoComplete: "new-password", minLength: 6 })] }), _jsxs("div", { className: "auth-form-group", children: [_jsx("label", { htmlFor: "confirmPassword", className: "auth-label", children: "Confirm Password" }), _jsx("input", { type: "password", id: "confirmPassword", className: "auth-input", value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), required: true, disabled: loading, placeholder: "Confirm new password", autoComplete: "new-password", minLength: 6 })] })] })) : (_jsxs("div", { className: "auth-form-group", children: [_jsx("label", { htmlFor: "email", className: "auth-label", children: "Email address" }), _jsx("input", { type: "email", id: "email", className: "auth-input", value: email, onChange: (e) => setEmail(e.target.value), required: true, disabled: loading, placeholder: "you@example.com", autoComplete: "email" })] })), _jsx("button", { type: "submit", className: "auth-button auth-button-primary", disabled: loading, children: loading ? (_jsx("span", { className: "auth-spinner" })) : token ? ('Reset password') : ('Send reset instructions') }), _jsx("div", { className: "auth-divider", children: _jsx("button", { type: "button", className: "auth-link auth-link-bold", onClick: onBack, disabled: loading, children: "\u2190 Back to Sign in" }) })] }));
37
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import './AuthForm.css';
3
+ interface PhoneAuthFormProps {
4
+ onSubmit: (phoneNumber: string, verificationCode?: string) => Promise<void>;
5
+ onBack: () => void;
6
+ loading: boolean;
7
+ error?: string;
8
+ }
9
+ export declare const PhoneAuthForm: React.FC<PhoneAuthFormProps>;
10
+ export {};
11
+ //# sourceMappingURL=PhoneAuthForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhoneAuthForm.d.ts","sourceRoot":"","sources":["../../src/components/PhoneAuthForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,gBAAgB,CAAC;AAExB,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAuGtD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState } from 'react';
3
+ import './AuthForm.css';
4
+ export const PhoneAuthForm = ({ onSubmit, onBack, loading, error, }) => {
5
+ const [phoneNumber, setPhoneNumber] = useState('');
6
+ const [verificationCode, setVerificationCode] = useState('');
7
+ const [codeSent, setCodeSent] = useState(false);
8
+ const handleSendCode = async (e) => {
9
+ e.preventDefault();
10
+ await onSubmit(phoneNumber);
11
+ setCodeSent(true);
12
+ };
13
+ const handleVerifyCode = async (e) => {
14
+ e.preventDefault();
15
+ await onSubmit(phoneNumber, verificationCode);
16
+ };
17
+ return (_jsxs("form", { className: "auth-form", onSubmit: codeSent ? handleVerifyCode : handleSendCode, children: [_jsxs("div", { className: "auth-form-header", children: [_jsx("h2", { className: "auth-form-title", children: "Phone Authentication" }), _jsx("p", { className: "auth-form-subtitle", children: codeSent
18
+ ? 'Enter the verification code sent to your phone.'
19
+ : 'Enter your phone number to receive a verification code.' })] }), error && (_jsxs("div", { className: "auth-error", role: "alert", children: [_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm1 13H7v-2h2v2zm0-3H7V4h2v6z" }) }), error] })), !codeSent ? (_jsxs("div", { className: "auth-form-group", children: [_jsx("label", { htmlFor: "phoneNumber", className: "auth-label", children: "Phone Number" }), _jsx("input", { type: "tel", id: "phoneNumber", className: "auth-input", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), required: true, disabled: loading, placeholder: "+1 (555) 123-4567" })] })) : (_jsxs("div", { className: "auth-form-group", children: [_jsx("label", { htmlFor: "verificationCode", className: "auth-label", children: "Verification Code" }), _jsx("input", { type: "text", id: "verificationCode", className: "auth-input", value: verificationCode, onChange: (e) => setVerificationCode(e.target.value), required: true, disabled: loading, placeholder: "123456", maxLength: 6, pattern: "[0-9]{6}" })] })), _jsx("button", { type: "submit", className: "auth-button auth-button-primary", disabled: loading, children: loading ? (_jsx("span", { className: "auth-spinner" })) : codeSent ? ('Verify Code') : ('Send Code') }), _jsx("div", { className: "auth-divider", children: _jsx("button", { type: "button", className: "auth-link auth-link-bold", onClick: onBack, disabled: loading, children: "\u2190 Back to login" }) })] }));
20
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ProtectedRouteProps {
3
+ children: React.ReactNode;
4
+ fallback?: React.ReactNode;
5
+ redirectTo?: string;
6
+ }
7
+ export declare const ProtectedRoute: React.FC<ProtectedRouteProps>;
8
+ export {};
9
+ //# sourceMappingURL=ProtectedRoute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.d.ts","sourceRoot":"","sources":["../../src/components/ProtectedRoute.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAwBxD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { useAuth } from '../context/AuthContext';
4
+ export const ProtectedRoute = ({ children, fallback, redirectTo, }) => {
5
+ const { isAuthenticated, isLoading } = useAuth();
6
+ // Show loading state
7
+ if (isLoading) {
8
+ return _jsx("div", { children: "Loading..." });
9
+ }
10
+ // If not authenticated, redirect or show fallback
11
+ if (!isAuthenticated) {
12
+ if (redirectTo) {
13
+ window.location.href = redirectTo;
14
+ return null;
15
+ }
16
+ return fallback ? _jsx(_Fragment, { children: fallback }) : _jsx("div", { children: "Access denied. Please log in." });
17
+ }
18
+ // Render protected content
19
+ return _jsx(_Fragment, { children: children });
20
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { AuthProvider } from '../types';
3
+ import './AuthForm.css';
4
+ interface ProviderButtonsProps {
5
+ enabledProviders: AuthProvider[];
6
+ onGoogleLogin: () => Promise<void>;
7
+ onPhoneLogin: () => void;
8
+ loading: boolean;
9
+ }
10
+ export declare const ProviderButtons: React.FC<ProviderButtonsProps>;
11
+ export {};
12
+ //# sourceMappingURL=ProviderButtons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderButtons.d.ts","sourceRoot":"","sources":["../../src/components/ProviderButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,gBAAgB,CAAC;AAExB,UAAU,oBAAoB;IAC5B,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuE1D,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import './AuthForm.css';
4
+ export const ProviderButtons = ({ enabledProviders, onGoogleLogin, onPhoneLogin, loading, }) => {
5
+ if (enabledProviders.length === 0)
6
+ return null;
7
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "auth-or-divider", children: _jsx("span", { children: "or continue with" }) }), _jsxs("div", { className: "auth-provider-buttons", children: [enabledProviders.includes('google') && (_jsxs("button", { type: "button", className: "auth-provider-button", onClick: onGoogleLogin, disabled: loading, children: [_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [_jsx("path", { d: "M19.6 10.227c0-.709-.064-1.39-.182-2.045H10v3.868h5.382a4.6 4.6 0 01-1.996 3.018v2.51h3.232c1.891-1.742 2.982-4.305 2.982-7.35z", fill: "#4285F4" }), _jsx("path", { d: "M10 20c2.7 0 4.964-.895 6.618-2.423l-3.232-2.509c-.895.6-2.04.955-3.386.955-2.605 0-4.81-1.76-5.595-4.123H1.064v2.59A9.996 9.996 0 0010 20z", fill: "#34A853" }), _jsx("path", { d: "M4.405 11.9c-.2-.6-.314-1.24-.314-1.9 0-.66.114-1.3.314-1.9V5.51H1.064A9.996 9.996 0 000 10c0 1.614.386 3.14 1.064 4.49l3.34-2.59z", fill: "#FBBC05" }), _jsx("path", { d: "M10 3.977c1.468 0 2.786.505 3.823 1.496l2.868-2.868C14.959.99 12.695 0 10 0 6.09 0 2.71 2.24 1.064 5.51l3.34 2.59C5.19 5.736 7.395 3.977 10 3.977z", fill: "#EA4335" })] }), "Continue with Google"] })), enabledProviders.includes('phone') && (_jsxs("button", { type: "button", className: "auth-provider-button", onClick: onPhoneLogin, disabled: loading, children: [_jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V15a2 2 0 01-2 2h-1C7.82 17 2 11.18 2 5V4z" }) }), "Continue with Phone"] }))] })] }));
8
+ };
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { AuthUser } from '../types';
3
+ interface AuthContextValue {
4
+ user: AuthUser | null;
5
+ token: string | null;
6
+ accountData: Record<string, any> | null;
7
+ isAuthenticated: boolean;
8
+ isLoading: boolean;
9
+ login: (token: string, user: AuthUser, accountData?: Record<string, any>) => void;
10
+ logout: () => Promise<void>;
11
+ getToken: () => string | null;
12
+ refreshToken: () => Promise<string>;
13
+ }
14
+ interface AuthProviderProps {
15
+ children: React.ReactNode;
16
+ }
17
+ export declare const AuthProvider: React.FC<AuthProviderProps>;
18
+ export declare const useAuth: () => AuthContextValue;
19
+ export {};
20
+ //# sourceMappingURL=AuthContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAClF,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACrC;AAID,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA4EpD,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
3
+ import { tokenStorage } from '../utils/tokenStorage';
4
+ import { createSmartlinksClient } from '../smartlinks';
5
+ const AuthContext = createContext(undefined);
6
+ export const AuthProvider = ({ children, apiEndpoint, clientId }) => {
7
+ const [user, setUser] = useState(null);
8
+ const [token, setToken] = useState(null);
9
+ const [accountData, setAccountData] = useState(null);
10
+ const [isLoading, setIsLoading] = useState(true);
11
+ const [smartlinks, setSmartlinks] = useState(null);
12
+ // Initialize Smartlinks SDK
13
+ useEffect(() => {
14
+ const client = createSmartlinksClient({
15
+ apiEndpoint,
16
+ clientId,
17
+ });
18
+ setSmartlinks(client);
19
+ }, [apiEndpoint, clientId]);
20
+ // Initialize auth state from localStorage
21
+ useEffect(() => {
22
+ const storedToken = tokenStorage.getToken();
23
+ const storedUser = tokenStorage.getUser();
24
+ const storedAccountData = tokenStorage.getAccountData();
25
+ if (storedToken && storedUser) {
26
+ setToken(storedToken.token);
27
+ setUser(storedUser);
28
+ setAccountData(storedAccountData);
29
+ // Set token in Smartlinks SDK
30
+ if (smartlinks) {
31
+ smartlinks.setToken(storedToken.token);
32
+ }
33
+ }
34
+ setIsLoading(false);
35
+ }, [smartlinks]);
36
+ const login = useCallback((authToken, authUser, authAccountData) => {
37
+ // Store token, user, and account data
38
+ tokenStorage.saveToken(authToken);
39
+ tokenStorage.saveUser(authUser);
40
+ if (authAccountData) {
41
+ tokenStorage.saveAccountData(authAccountData);
42
+ }
43
+ setToken(authToken);
44
+ setUser(authUser);
45
+ setAccountData(authAccountData || null);
46
+ // Set token in Smartlinks SDK
47
+ if (smartlinks) {
48
+ smartlinks.setToken(authToken);
49
+ }
50
+ }, [smartlinks]);
51
+ const logout = useCallback(async () => {
52
+ // Logout via Smartlinks SDK if available
53
+ if (smartlinks) {
54
+ try {
55
+ await smartlinks.logout();
56
+ }
57
+ catch (error) {
58
+ console.error('Smartlinks logout error:', error);
59
+ }
60
+ }
61
+ // Clear local storage
62
+ tokenStorage.clearAll();
63
+ setToken(null);
64
+ setUser(null);
65
+ setAccountData(null);
66
+ // Clear token from Smartlinks SDK
67
+ if (smartlinks) {
68
+ smartlinks.clearToken();
69
+ }
70
+ }, [smartlinks]);
71
+ const getToken = useCallback(() => {
72
+ const storedToken = tokenStorage.getToken();
73
+ return storedToken ? storedToken.token : null;
74
+ }, []);
75
+ const refreshToken = useCallback(async () => {
76
+ if (!smartlinks) {
77
+ throw new Error('Smartlinks SDK not initialized');
78
+ }
79
+ try {
80
+ const newToken = await smartlinks.refreshToken();
81
+ // Update stored token
82
+ tokenStorage.saveToken(newToken);
83
+ setToken(newToken);
84
+ return newToken;
85
+ }
86
+ catch (error) {
87
+ console.error('Token refresh failed:', error);
88
+ // If refresh fails, logout user
89
+ await logout();
90
+ throw error;
91
+ }
92
+ }, [smartlinks, logout]);
93
+ const value = {
94
+ user,
95
+ token,
96
+ accountData,
97
+ isAuthenticated: !!token && !!user,
98
+ isLoading,
99
+ smartlinks,
100
+ login,
101
+ logout,
102
+ getToken,
103
+ refreshToken,
104
+ };
105
+ return _jsx(AuthContext.Provider, { value: value, children: children });
106
+ };
107
+ export const useAuth = () => {
108
+ const context = useContext(AuthContext);
109
+ if (context === undefined) {
110
+ throw new Error('useAuth must be used within an AuthProvider');
111
+ }
112
+ return context;
113
+ };
package/dist/index.css ADDED
@@ -0,0 +1,2 @@
1
+ .auth-container{align-items:center;background:linear-gradient(135deg,var(--auth-bg-color,#e0f2fe) 0,#f0f9ff 100%);display:flex;font-family:var(--auth-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif);justify-content:center;min-height:100vh;padding:1rem}.auth-theme-dark.auth-container{background:linear-gradient(135deg,#0f172a,#1e293b)}.auth-card{animation:slideUp .4s cubic-bezier(.16,1,.3,1);background:#fff;border-radius:16px;box-shadow:0 10px 40px rgba(59,130,246,.1);max-width:440px;padding:2.5rem;width:100%}.auth-theme-dark .auth-card{background:#1e293b;box-shadow:0 10px 40px rgba(0,0,0,.3)}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.auth-header{margin-bottom:2rem;text-align:center}.auth-logo{animation:float 3s ease-in-out infinite;display:inline-flex;margin-bottom:1rem}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}.auth-title{color:#1e293b;font-size:1.75rem;font-weight:700;margin:0}.auth-subtitle{color:#64748b;font-size:.875rem;margin:.25rem 0 0}.auth-theme-dark .auth-title{color:#f1f5f9}.auth-theme-dark .auth-subtitle{color:#94a3b8}.auth-footer{align-items:center;border-top:1px solid #e2e8f0;display:flex;font-size:.875rem;gap:.75rem;justify-content:center;margin-top:1rem;padding-top:1rem}.auth-theme-dark .auth-footer{border-top-color:#334155}.auth-footer a{color:var(--auth-primary-color,#3b82f6);text-decoration:none}.auth-footer a:hover{text-decoration:underline}.auth-footer span{color:#cbd5e1}.auth-theme-dark .auth-footer span{color:#475569}.auth-spinner{border:3px solid #e2e8f0;border-top:3px solid var(--auth-primary-color,#3b82f6);height:40px;margin:0 auto;width:40px}@media (max-width:640px){.auth-card{padding:2rem 1.5rem}.auth-title{font-size:1.5rem}}.auth-form{width:100%}.auth-form-header{margin-bottom:1.5rem}.auth-form-title{color:#1e293b;font-size:1.5rem;font-weight:700;margin:0 0 .5rem}.auth-theme-dark .auth-form-title{color:#f1f5f9}.auth-form-subtitle{color:#64748b;font-size:.875rem;margin:0}.auth-theme-dark .auth-form-subtitle{color:#94a3b8}.auth-error{align-items:center;animation:shake .4s ease;background:#fef2f2;border:1px solid #fecaca;border-radius:.5rem;color:#dc2626;display:flex;font-size:.875rem;gap:.5rem;margin-bottom:1rem;padding:.75rem 1rem}.auth-theme-dark .auth-error{background:#7f1d1d;border-color:#991b1b;color:#fca5a5}@keyframes shake{0%,to{transform:translateX(0)}25%{transform:translateX(-8px)}75%{transform:translateX(8px)}}.auth-form-group{margin-bottom:1rem}.auth-label{color:#334155;display:block;font-size:.875rem;font-weight:500;margin-bottom:.5rem}.auth-theme-dark .auth-label{color:#cbd5e1}.auth-input{background:#f8fafc;border:1px solid #e2e8f0;border-radius:.5rem;box-sizing:border-box;color:#1e293b;font-size:1rem;padding:.75rem 1rem;transition:all .2s ease;width:100%}.auth-input:focus{background:#fff;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1);outline:none}.auth-input:disabled{cursor:not-allowed;opacity:.6}.auth-theme-dark .auth-input{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-input:focus{background:#1e293b;border-color:#3b82f6}.auth-form-footer{display:flex;justify-content:flex-end;margin-bottom:1.5rem}.auth-link{background:none;border:none;color:#3b82f6;cursor:pointer;font-size:.875rem;padding:0;transition:color .2s ease}.auth-link:hover:not(:disabled){color:#1d4ed8;text-decoration:underline}.auth-link:disabled{cursor:not-allowed;opacity:.6}.auth-button,.auth-link-bold{font-weight:600}.auth-button{align-items:center;border:none;border-radius:.5rem;cursor:pointer;display:flex;font-size:1rem;gap:.5rem;justify-content:center;padding:.875rem 1.5rem;transition:all .2s ease;width:100%}.auth-button:disabled{cursor:not-allowed;opacity:.6}.auth-button-primary{background:linear-gradient(135deg,#3b82f6,#1d4ed8);box-shadow:0 4px 12px rgba(59,130,246,.25);color:#fff}.auth-button-primary:hover:not(:disabled){box-shadow:0 6px 20px rgba(59,130,246,.35);transform:translateY(-2px)}.auth-button-primary:active:not(:disabled){transform:translateY(0)}.auth-button-secondary{background:#fff;border:1px solid #e2e8f0;box-shadow:0 1px 3px rgba(0,0,0,.05);color:#334155}.auth-button-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.auth-theme-dark .auth-button-secondary{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-button-secondary:hover:not(:disabled){background:#1e293b;border-color:#475569}.auth-spinner{animation:spin .8s linear infinite;border:2px solid hsla(0,0%,100%,.3);border-radius:50%;border-top-color:#fff;display:inline-block;height:18px;width:18px}@keyframes spin{to{transform:rotate(1turn)}}.auth-divider{align-items:center;color:#64748b;display:flex;font-size:.875rem;gap:.5rem;justify-content:center;margin-top:1.5rem}.auth-theme-dark .auth-divider{color:#94a3b8}.auth-provider-buttons{display:flex;flex-direction:column;gap:.75rem;margin-top:1.5rem}.auth-provider-button{align-items:center;background:#fff;border:1px solid #e2e8f0;border-radius:.5rem;color:#334155;cursor:pointer;display:flex;font-size:.9375rem;font-weight:500;gap:.75rem;justify-content:center;padding:.875rem 1.5rem;transition:all .2s ease;width:100%}.auth-provider-button:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1;box-shadow:0 4px 12px rgba(0,0,0,.08);transform:translateY(-1px)}.auth-provider-button:disabled{cursor:not-allowed;opacity:.6}.auth-theme-dark .auth-provider-button{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-provider-button:hover:not(:disabled){background:#1e293b;border-color:#475569}.auth-or-divider{align-items:center;color:#94a3b8;display:flex;font-size:.875rem;margin:1.5rem 0;text-align:center}.auth-or-divider:after,.auth-or-divider:before{border-bottom:1px solid #e2e8f0;content:"";flex:1}.auth-or-divider span{padding:0 1rem}.auth-theme-dark .auth-or-divider:after,.auth-theme-dark .auth-or-divider:before{border-color:#334155}@media (max-width:640px){.auth-form-title{font-size:1.25rem}.auth-button,.auth-provider-button{font-size:.9375rem;padding:.75rem 1rem}}
2
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["AuthContainer.css","AuthForm.css"],"names":[],"mappings":"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","file":"index.css","sourcesContent":[".auth-container {\r\n min-height: 100vh;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 1rem;\r\n background: linear-gradient(135deg, var(--auth-bg-color, #e0f2fe) 0%, #f0f9ff 100%);\r\n font-family: var(--auth-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif);\r\n}\r\n\r\n.auth-theme-dark.auth-container {\r\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\r\n}\r\n\r\n.auth-card {\r\n width: 100%;\r\n max-width: 440px;\r\n background: white;\r\n border-radius: 16px;\r\n box-shadow: 0 10px 40px rgba(59, 130, 246, 0.1);\r\n padding: 2.5rem;\r\n animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);\r\n}\r\n\r\n.auth-theme-dark .auth-card {\r\n background: #1e293b;\r\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n@keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n.auth-header {\r\n text-align: center;\r\n margin-bottom: 2rem;\r\n}\r\n\r\n.auth-logo {\r\n display: inline-flex;\r\n margin-bottom: 1rem;\r\n animation: float 3s ease-in-out infinite;\r\n}\r\n\r\n@keyframes float {\r\n 0%, 100% {\r\n transform: translateY(0);\r\n }\r\n 50% {\r\n transform: translateY(-8px);\r\n }\r\n}\r\n\r\n.auth-title {\r\n font-size: 1.75rem;\r\n font-weight: 700;\r\n color: #1e293b;\r\n margin: 0;\r\n}\r\n\r\n.auth-subtitle {\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n margin: 0.25rem 0 0 0;\r\n}\r\n\r\n.auth-theme-dark .auth-title {\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-theme-dark .auth-subtitle {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-content {\r\n /* Content styles handled by child components */\r\n}\r\n\r\n.auth-footer {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.75rem;\r\n padding-top: 1rem;\r\n margin-top: 1rem;\r\n border-top: 1px solid #e2e8f0;\r\n font-size: 0.875rem;\r\n}\r\n\r\n.auth-theme-dark .auth-footer {\r\n border-top-color: #334155;\r\n}\r\n\r\n.auth-footer a {\r\n color: var(--auth-primary-color, #3B82F6);\r\n text-decoration: none;\r\n}\r\n\r\n.auth-footer a:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.auth-footer span {\r\n color: #cbd5e1;\r\n}\r\n\r\n.auth-theme-dark .auth-footer span {\r\n color: #475569;\r\n}\r\n\r\n.auth-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 3px solid #e2e8f0;\r\n border-top-color: var(--auth-primary-color, #3B82F6);\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n margin: 0 auto;\r\n}\r\n\r\n@keyframes spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .auth-card {\r\n padding: 2rem 1.5rem;\r\n }\r\n \r\n .auth-title {\r\n font-size: 1.5rem;\r\n }\r\n}\r\n",".auth-form {\r\n width: 100%;\r\n}\r\n\r\n.auth-form-header {\r\n margin-bottom: 1.5rem;\r\n}\r\n\r\n.auth-form-title {\r\n font-size: 1.5rem;\r\n font-weight: 700;\r\n color: #1e293b;\r\n margin: 0 0 0.5rem 0;\r\n}\r\n\r\n.auth-theme-dark .auth-form-title {\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-form-subtitle {\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n margin: 0;\r\n}\r\n\r\n.auth-theme-dark .auth-form-subtitle {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-error {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.5rem;\r\n padding: 0.75rem 1rem;\r\n background: #fef2f2;\r\n border: 1px solid #fecaca;\r\n border-radius: 0.5rem;\r\n color: #dc2626;\r\n font-size: 0.875rem;\r\n margin-bottom: 1rem;\r\n animation: shake 0.4s ease;\r\n}\r\n\r\n.auth-theme-dark .auth-error {\r\n background: #7f1d1d;\r\n border-color: #991b1b;\r\n color: #fca5a5;\r\n}\r\n\r\n@keyframes shake {\r\n 0%, 100% { transform: translateX(0); }\r\n 25% { transform: translateX(-8px); }\r\n 75% { transform: translateX(8px); }\r\n}\r\n\r\n.auth-form-group {\r\n margin-bottom: 1rem;\r\n}\r\n\r\n.auth-label {\r\n display: block;\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: #334155;\r\n margin-bottom: 0.5rem;\r\n}\r\n\r\n.auth-theme-dark .auth-label {\r\n color: #cbd5e1;\r\n}\r\n\r\n.auth-input {\r\n width: 100%;\r\n padding: 0.75rem 1rem;\r\n font-size: 1rem;\r\n color: #1e293b;\r\n background: #f8fafc;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 0.5rem;\r\n transition: all 0.2s ease;\r\n box-sizing: border-box;\r\n}\r\n\r\n.auth-input:focus {\r\n outline: none;\r\n border-color: #3b82f6;\r\n background: white;\r\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\r\n}\r\n\r\n.auth-input:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-theme-dark .auth-input {\r\n background: #0f172a;\r\n border-color: #334155;\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-theme-dark .auth-input:focus {\r\n background: #1e293b;\r\n border-color: #3b82f6;\r\n}\r\n\r\n.auth-form-footer {\r\n display: flex;\r\n justify-content: flex-end;\r\n margin-bottom: 1.5rem;\r\n}\r\n\r\n.auth-link {\r\n background: none;\r\n border: none;\r\n padding: 0;\r\n font-size: 0.875rem;\r\n color: #3b82f6;\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.auth-link:hover:not(:disabled) {\r\n color: #1d4ed8;\r\n text-decoration: underline;\r\n}\r\n\r\n.auth-link:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-link-bold {\r\n font-weight: 600;\r\n}\r\n\r\n.auth-button {\r\n width: 100%;\r\n padding: 0.875rem 1.5rem;\r\n font-size: 1rem;\r\n font-weight: 600;\r\n border: none;\r\n border-radius: 0.5rem;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.5rem;\r\n}\r\n\r\n.auth-button:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-button-primary {\r\n background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);\r\n color: white;\r\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.25);\r\n}\r\n\r\n.auth-button-primary:hover:not(:disabled) {\r\n transform: translateY(-2px);\r\n box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);\r\n}\r\n\r\n.auth-button-primary:active:not(:disabled) {\r\n transform: translateY(0);\r\n}\r\n\r\n.auth-button-secondary {\r\n background: white;\r\n color: #334155;\r\n border: 1px solid #e2e8f0;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.auth-button-secondary:hover:not(:disabled) {\r\n background: #f8fafc;\r\n border-color: #cbd5e1;\r\n}\r\n\r\n.auth-theme-dark .auth-button-secondary {\r\n background: #0f172a;\r\n color: #f1f5f9;\r\n border-color: #334155;\r\n}\r\n\r\n.auth-theme-dark .auth-button-secondary:hover:not(:disabled) {\r\n background: #1e293b;\r\n border-color: #475569;\r\n}\r\n\r\n.auth-spinner {\r\n display: inline-block;\r\n width: 18px;\r\n height: 18px;\r\n border: 2px solid rgba(255, 255, 255, 0.3);\r\n border-top-color: white;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n\r\n.auth-divider {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.5rem;\r\n margin-top: 1.5rem;\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n}\r\n\r\n.auth-theme-dark .auth-divider {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-provider-buttons {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.75rem;\r\n margin-top: 1.5rem;\r\n}\r\n\r\n.auth-provider-button {\r\n width: 100%;\r\n padding: 0.875rem 1.5rem;\r\n font-size: 0.9375rem;\r\n font-weight: 500;\r\n background: white;\r\n color: #334155;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 0.5rem;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.75rem;\r\n}\r\n\r\n.auth-provider-button:hover:not(:disabled) {\r\n background: #f8fafc;\r\n border-color: #cbd5e1;\r\n transform: translateY(-1px);\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.auth-provider-button:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-theme-dark .auth-provider-button {\r\n background: #0f172a;\r\n color: #f1f5f9;\r\n border-color: #334155;\r\n}\r\n\r\n.auth-theme-dark .auth-provider-button:hover:not(:disabled) {\r\n background: #1e293b;\r\n border-color: #475569;\r\n}\r\n\r\n.auth-or-divider {\r\n display: flex;\r\n align-items: center;\r\n text-align: center;\r\n margin: 1.5rem 0;\r\n color: #94a3b8;\r\n font-size: 0.875rem;\r\n}\r\n\r\n.auth-or-divider::before,\r\n.auth-or-divider::after {\r\n content: '';\r\n flex: 1;\r\n border-bottom: 1px solid #e2e8f0;\r\n}\r\n\r\n.auth-or-divider span {\r\n padding: 0 1rem;\r\n}\r\n\r\n.auth-theme-dark .auth-or-divider::before,\r\n.auth-theme-dark .auth-or-divider::after {\r\n border-color: #334155;\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .auth-form-title {\r\n font-size: 1.25rem;\r\n }\r\n \r\n .auth-button,\r\n .auth-provider-button {\r\n padding: 0.75rem 1rem;\r\n font-size: 0.9375rem;\r\n }\r\n}\r\n"]}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import type { SmartlinksAuthUIProps } from './types';
3
+ export declare const SmartlinksAuthUI: React.FC<SmartlinksAuthUIProps>;
4
+ export { AuthProvider, useAuth } from './context/AuthContext';
5
+ export { ProtectedRoute } from './components/ProtectedRoute';
6
+ export { tokenStorage } from './utils/tokenStorage';
7
+ export { AuthUIPreview } from './components/AuthUIPreview';
8
+ export type * from './types';
9
+ export { SmartlinksAuthUI as FirebaseAuthUI };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAQnD,OAAO,KAAK,EAAE,qBAAqB,EAAyC,MAAM,SAAS,CAAC;AAE5F,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwnB5D,CAAC;AAGF,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAG3D,mBAAmB,SAAS,CAAC;AAG7B,OAAO,EAAE,gBAAgB,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ .auth-container{align-items:center;background:linear-gradient(135deg,var(--auth-bg-color,#e0f2fe) 0,#f0f9ff 100%);display:flex;font-family:var(--auth-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif);justify-content:center;min-height:100vh;padding:1rem}.auth-theme-dark.auth-container{background:linear-gradient(135deg,#0f172a,#1e293b)}.auth-card{animation:slideUp .4s cubic-bezier(.16,1,.3,1);background:#fff;border-radius:16px;box-shadow:0 10px 40px rgba(59,130,246,.1);max-width:440px;padding:2.5rem;width:100%}.auth-theme-dark .auth-card{background:#1e293b;box-shadow:0 10px 40px rgba(0,0,0,.3)}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.auth-header{margin-bottom:2rem;text-align:center}.auth-logo{animation:float 3s ease-in-out infinite;display:inline-flex;margin-bottom:1rem}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}.auth-title{color:#1e293b;font-size:1.75rem;font-weight:700;margin:0}.auth-subtitle{color:#64748b;font-size:.875rem;margin:.25rem 0 0}.auth-theme-dark .auth-title{color:#f1f5f9}.auth-theme-dark .auth-subtitle{color:#94a3b8}.auth-footer{align-items:center;border-top:1px solid #e2e8f0;display:flex;font-size:.875rem;gap:.75rem;justify-content:center;margin-top:1rem;padding-top:1rem}.auth-theme-dark .auth-footer{border-top-color:#334155}.auth-footer a{color:var(--auth-primary-color,#3b82f6);text-decoration:none}.auth-footer a:hover{text-decoration:underline}.auth-footer span{color:#cbd5e1}.auth-theme-dark .auth-footer span{color:#475569}.auth-spinner{border:3px solid #e2e8f0;border-top:3px solid var(--auth-primary-color,#3b82f6);height:40px;margin:0 auto;width:40px}@media (max-width:640px){.auth-card{padding:2rem 1.5rem}.auth-title{font-size:1.5rem}}.auth-form{width:100%}.auth-form-header{margin-bottom:1.5rem}.auth-form-title{color:#1e293b;font-size:1.5rem;font-weight:700;margin:0 0 .5rem}.auth-theme-dark .auth-form-title{color:#f1f5f9}.auth-form-subtitle{color:#64748b;font-size:.875rem;margin:0}.auth-theme-dark .auth-form-subtitle{color:#94a3b8}.auth-error{align-items:center;animation:shake .4s ease;background:#fef2f2;border:1px solid #fecaca;border-radius:.5rem;color:#dc2626;display:flex;font-size:.875rem;gap:.5rem;margin-bottom:1rem;padding:.75rem 1rem}.auth-theme-dark .auth-error{background:#7f1d1d;border-color:#991b1b;color:#fca5a5}@keyframes shake{0%,to{transform:translateX(0)}25%{transform:translateX(-8px)}75%{transform:translateX(8px)}}.auth-form-group{margin-bottom:1rem}.auth-label{color:#334155;display:block;font-size:.875rem;font-weight:500;margin-bottom:.5rem}.auth-theme-dark .auth-label{color:#cbd5e1}.auth-input{background:#f8fafc;border:1px solid #e2e8f0;border-radius:.5rem;box-sizing:border-box;color:#1e293b;font-size:1rem;padding:.75rem 1rem;transition:all .2s ease;width:100%}.auth-input:focus{background:#fff;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1);outline:none}.auth-input:disabled{cursor:not-allowed;opacity:.6}.auth-theme-dark .auth-input{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-input:focus{background:#1e293b;border-color:#3b82f6}.auth-form-footer{display:flex;justify-content:flex-end;margin-bottom:1.5rem}.auth-link{background:none;border:none;color:#3b82f6;cursor:pointer;font-size:.875rem;padding:0;transition:color .2s ease}.auth-link:hover:not(:disabled){color:#1d4ed8;text-decoration:underline}.auth-link:disabled{cursor:not-allowed;opacity:.6}.auth-button,.auth-link-bold{font-weight:600}.auth-button{align-items:center;border:none;border-radius:.5rem;cursor:pointer;display:flex;font-size:1rem;gap:.5rem;justify-content:center;padding:.875rem 1.5rem;transition:all .2s ease;width:100%}.auth-button:disabled{cursor:not-allowed;opacity:.6}.auth-button-primary{background:linear-gradient(135deg,#3b82f6,#1d4ed8);box-shadow:0 4px 12px rgba(59,130,246,.25);color:#fff}.auth-button-primary:hover:not(:disabled){box-shadow:0 6px 20px rgba(59,130,246,.35);transform:translateY(-2px)}.auth-button-primary:active:not(:disabled){transform:translateY(0)}.auth-button-secondary{background:#fff;border:1px solid #e2e8f0;box-shadow:0 1px 3px rgba(0,0,0,.05);color:#334155}.auth-button-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.auth-theme-dark .auth-button-secondary{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-button-secondary:hover:not(:disabled){background:#1e293b;border-color:#475569}.auth-spinner{animation:spin .8s linear infinite;border:2px solid hsla(0,0%,100%,.3);border-radius:50%;border-top-color:#fff;display:inline-block;height:18px;width:18px}@keyframes spin{to{transform:rotate(1turn)}}.auth-divider{align-items:center;color:#64748b;display:flex;font-size:.875rem;gap:.5rem;justify-content:center;margin-top:1.5rem}.auth-theme-dark .auth-divider{color:#94a3b8}.auth-provider-buttons{display:flex;flex-direction:column;gap:.75rem;margin-top:1.5rem}.auth-provider-button{align-items:center;background:#fff;border:1px solid #e2e8f0;border-radius:.5rem;color:#334155;cursor:pointer;display:flex;font-size:.9375rem;font-weight:500;gap:.75rem;justify-content:center;padding:.875rem 1.5rem;transition:all .2s ease;width:100%}.auth-provider-button:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1;box-shadow:0 4px 12px rgba(0,0,0,.08);transform:translateY(-1px)}.auth-provider-button:disabled{cursor:not-allowed;opacity:.6}.auth-theme-dark .auth-provider-button{background:#0f172a;border-color:#334155;color:#f1f5f9}.auth-theme-dark .auth-provider-button:hover:not(:disabled){background:#1e293b;border-color:#475569}.auth-or-divider{align-items:center;color:#94a3b8;display:flex;font-size:.875rem;margin:1.5rem 0;text-align:center}.auth-or-divider:after,.auth-or-divider:before{border-bottom:1px solid #e2e8f0;content:"";flex:1}.auth-or-divider span{padding:0 1rem}.auth-theme-dark .auth-or-divider:after,.auth-theme-dark .auth-or-divider:before{border-color:#334155}@media (max-width:640px){.auth-form-title{font-size:1.25rem}.auth-button,.auth-provider-button{font-size:.9375rem;padding:.75rem 1rem}}
2
+ /*# sourceMappingURL=index.esm.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["AuthContainer.css","AuthForm.css"],"names":[],"mappings":"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","file":"index.esm.css","sourcesContent":[".auth-container {\r\n min-height: 100vh;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 1rem;\r\n background: linear-gradient(135deg, var(--auth-bg-color, #e0f2fe) 0%, #f0f9ff 100%);\r\n font-family: var(--auth-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif);\r\n}\r\n\r\n.auth-theme-dark.auth-container {\r\n background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\r\n}\r\n\r\n.auth-card {\r\n width: 100%;\r\n max-width: 440px;\r\n background: white;\r\n border-radius: 16px;\r\n box-shadow: 0 10px 40px rgba(59, 130, 246, 0.1);\r\n padding: 2.5rem;\r\n animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);\r\n}\r\n\r\n.auth-theme-dark .auth-card {\r\n background: #1e293b;\r\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n@keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n.auth-header {\r\n text-align: center;\r\n margin-bottom: 2rem;\r\n}\r\n\r\n.auth-logo {\r\n display: inline-flex;\r\n margin-bottom: 1rem;\r\n animation: float 3s ease-in-out infinite;\r\n}\r\n\r\n@keyframes float {\r\n 0%, 100% {\r\n transform: translateY(0);\r\n }\r\n 50% {\r\n transform: translateY(-8px);\r\n }\r\n}\r\n\r\n.auth-title {\r\n font-size: 1.75rem;\r\n font-weight: 700;\r\n color: #1e293b;\r\n margin: 0;\r\n}\r\n\r\n.auth-subtitle {\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n margin: 0.25rem 0 0 0;\r\n}\r\n\r\n.auth-theme-dark .auth-title {\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-theme-dark .auth-subtitle {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-content {\r\n /* Content styles handled by child components */\r\n}\r\n\r\n.auth-footer {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.75rem;\r\n padding-top: 1rem;\r\n margin-top: 1rem;\r\n border-top: 1px solid #e2e8f0;\r\n font-size: 0.875rem;\r\n}\r\n\r\n.auth-theme-dark .auth-footer {\r\n border-top-color: #334155;\r\n}\r\n\r\n.auth-footer a {\r\n color: var(--auth-primary-color, #3B82F6);\r\n text-decoration: none;\r\n}\r\n\r\n.auth-footer a:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.auth-footer span {\r\n color: #cbd5e1;\r\n}\r\n\r\n.auth-theme-dark .auth-footer span {\r\n color: #475569;\r\n}\r\n\r\n.auth-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 3px solid #e2e8f0;\r\n border-top-color: var(--auth-primary-color, #3B82F6);\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n margin: 0 auto;\r\n}\r\n\r\n@keyframes spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .auth-card {\r\n padding: 2rem 1.5rem;\r\n }\r\n \r\n .auth-title {\r\n font-size: 1.5rem;\r\n }\r\n}\r\n",".auth-form {\r\n width: 100%;\r\n}\r\n\r\n.auth-form-header {\r\n margin-bottom: 1.5rem;\r\n}\r\n\r\n.auth-form-title {\r\n font-size: 1.5rem;\r\n font-weight: 700;\r\n color: #1e293b;\r\n margin: 0 0 0.5rem 0;\r\n}\r\n\r\n.auth-theme-dark .auth-form-title {\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-form-subtitle {\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n margin: 0;\r\n}\r\n\r\n.auth-theme-dark .auth-form-subtitle {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-error {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.5rem;\r\n padding: 0.75rem 1rem;\r\n background: #fef2f2;\r\n border: 1px solid #fecaca;\r\n border-radius: 0.5rem;\r\n color: #dc2626;\r\n font-size: 0.875rem;\r\n margin-bottom: 1rem;\r\n animation: shake 0.4s ease;\r\n}\r\n\r\n.auth-theme-dark .auth-error {\r\n background: #7f1d1d;\r\n border-color: #991b1b;\r\n color: #fca5a5;\r\n}\r\n\r\n@keyframes shake {\r\n 0%, 100% { transform: translateX(0); }\r\n 25% { transform: translateX(-8px); }\r\n 75% { transform: translateX(8px); }\r\n}\r\n\r\n.auth-form-group {\r\n margin-bottom: 1rem;\r\n}\r\n\r\n.auth-label {\r\n display: block;\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: #334155;\r\n margin-bottom: 0.5rem;\r\n}\r\n\r\n.auth-theme-dark .auth-label {\r\n color: #cbd5e1;\r\n}\r\n\r\n.auth-input {\r\n width: 100%;\r\n padding: 0.75rem 1rem;\r\n font-size: 1rem;\r\n color: #1e293b;\r\n background: #f8fafc;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 0.5rem;\r\n transition: all 0.2s ease;\r\n box-sizing: border-box;\r\n}\r\n\r\n.auth-input:focus {\r\n outline: none;\r\n border-color: #3b82f6;\r\n background: white;\r\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\r\n}\r\n\r\n.auth-input:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-theme-dark .auth-input {\r\n background: #0f172a;\r\n border-color: #334155;\r\n color: #f1f5f9;\r\n}\r\n\r\n.auth-theme-dark .auth-input:focus {\r\n background: #1e293b;\r\n border-color: #3b82f6;\r\n}\r\n\r\n.auth-form-footer {\r\n display: flex;\r\n justify-content: flex-end;\r\n margin-bottom: 1.5rem;\r\n}\r\n\r\n.auth-link {\r\n background: none;\r\n border: none;\r\n padding: 0;\r\n font-size: 0.875rem;\r\n color: #3b82f6;\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.auth-link:hover:not(:disabled) {\r\n color: #1d4ed8;\r\n text-decoration: underline;\r\n}\r\n\r\n.auth-link:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-link-bold {\r\n font-weight: 600;\r\n}\r\n\r\n.auth-button {\r\n width: 100%;\r\n padding: 0.875rem 1.5rem;\r\n font-size: 1rem;\r\n font-weight: 600;\r\n border: none;\r\n border-radius: 0.5rem;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.5rem;\r\n}\r\n\r\n.auth-button:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-button-primary {\r\n background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);\r\n color: white;\r\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.25);\r\n}\r\n\r\n.auth-button-primary:hover:not(:disabled) {\r\n transform: translateY(-2px);\r\n box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);\r\n}\r\n\r\n.auth-button-primary:active:not(:disabled) {\r\n transform: translateY(0);\r\n}\r\n\r\n.auth-button-secondary {\r\n background: white;\r\n color: #334155;\r\n border: 1px solid #e2e8f0;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.auth-button-secondary:hover:not(:disabled) {\r\n background: #f8fafc;\r\n border-color: #cbd5e1;\r\n}\r\n\r\n.auth-theme-dark .auth-button-secondary {\r\n background: #0f172a;\r\n color: #f1f5f9;\r\n border-color: #334155;\r\n}\r\n\r\n.auth-theme-dark .auth-button-secondary:hover:not(:disabled) {\r\n background: #1e293b;\r\n border-color: #475569;\r\n}\r\n\r\n.auth-spinner {\r\n display: inline-block;\r\n width: 18px;\r\n height: 18px;\r\n border: 2px solid rgba(255, 255, 255, 0.3);\r\n border-top-color: white;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n\r\n.auth-divider {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.5rem;\r\n margin-top: 1.5rem;\r\n font-size: 0.875rem;\r\n color: #64748b;\r\n}\r\n\r\n.auth-theme-dark .auth-divider {\r\n color: #94a3b8;\r\n}\r\n\r\n.auth-provider-buttons {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.75rem;\r\n margin-top: 1.5rem;\r\n}\r\n\r\n.auth-provider-button {\r\n width: 100%;\r\n padding: 0.875rem 1.5rem;\r\n font-size: 0.9375rem;\r\n font-weight: 500;\r\n background: white;\r\n color: #334155;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 0.5rem;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.75rem;\r\n}\r\n\r\n.auth-provider-button:hover:not(:disabled) {\r\n background: #f8fafc;\r\n border-color: #cbd5e1;\r\n transform: translateY(-1px);\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.auth-provider-button:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.auth-theme-dark .auth-provider-button {\r\n background: #0f172a;\r\n color: #f1f5f9;\r\n border-color: #334155;\r\n}\r\n\r\n.auth-theme-dark .auth-provider-button:hover:not(:disabled) {\r\n background: #1e293b;\r\n border-color: #475569;\r\n}\r\n\r\n.auth-or-divider {\r\n display: flex;\r\n align-items: center;\r\n text-align: center;\r\n margin: 1.5rem 0;\r\n color: #94a3b8;\r\n font-size: 0.875rem;\r\n}\r\n\r\n.auth-or-divider::before,\r\n.auth-or-divider::after {\r\n content: '';\r\n flex: 1;\r\n border-bottom: 1px solid #e2e8f0;\r\n}\r\n\r\n.auth-or-divider span {\r\n padding: 0 1rem;\r\n}\r\n\r\n.auth-theme-dark .auth-or-divider::before,\r\n.auth-theme-dark .auth-or-divider::after {\r\n border-color: #334155;\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .auth-form-title {\r\n font-size: 1.25rem;\r\n }\r\n \r\n .auth-button,\r\n .auth-provider-button {\r\n padding: 0.75rem 1rem;\r\n font-size: 0.9375rem;\r\n }\r\n}\r\n"]}