@proveanything/smartlinks-auth-ui 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +82 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +82 -5
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -399,6 +399,8 @@ const AuthUIPreview = ({ customization, enabledProviders = ['email', 'google', '
|
|
|
399
399
|
return (jsxRuntime.jsxs(AuthContainer, { theme: theme, className: className, config: customization, children: [showEmail && (jsxRuntime.jsxs("div", { className: "auth-form", children: [jsxRuntime.jsxs("div", { className: "auth-form-group", children: [jsxRuntime.jsx("label", { className: "auth-label", children: "Email" }), jsxRuntime.jsx("input", { type: "email", className: "auth-input", placeholder: "Enter your email", disabled: true })] }), jsxRuntime.jsxs("div", { className: "auth-form-group", children: [jsxRuntime.jsx("label", { className: "auth-label", children: "Password" }), jsxRuntime.jsx("input", { type: "password", className: "auth-input", placeholder: "Enter your password", disabled: true })] }), jsxRuntime.jsx("button", { className: "auth-button auth-button-primary", disabled: true, children: "Sign In" }), jsxRuntime.jsx("div", { style: { textAlign: 'center', marginTop: '1rem' }, children: jsxRuntime.jsx("button", { className: "auth-link", disabled: true, children: "Forgot password?" }) }), jsxRuntime.jsxs("div", { style: { textAlign: 'center', marginTop: '0.5rem', fontSize: '0.875rem', color: 'var(--auth-text-muted, #6B7280)' }, children: ["Don't have an account?", ' ', jsxRuntime.jsx("button", { className: "auth-link", disabled: true, children: "Sign up" })] })] })), hasProviders && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [showEmail && (jsxRuntime.jsx("div", { className: "auth-or-divider", children: jsxRuntime.jsx("span", { children: "or continue with" }) })), jsxRuntime.jsxs("div", { className: "auth-provider-buttons", children: [showGoogle && (jsxRuntime.jsxs("button", { className: "auth-provider-button", disabled: true, children: [jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [jsxRuntime.jsx("path", { d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z", fill: "#4285F4" }), jsxRuntime.jsx("path", { d: "M9 18c2.43 0 4.467-.806 5.956-2.183l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332C2.438 15.983 5.482 18 9 18z", fill: "#34A853" }), jsxRuntime.jsx("path", { d: "M3.964 10.707c-.18-.54-.282-1.117-.282-1.707 0-.593.102-1.167.282-1.707V4.961H.957C.347 6.175 0 7.548 0 9s.348 2.825.957 4.039l3.007-2.332z", fill: "#FBBC05" }), jsxRuntime.jsx("path", { d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0 5.482 0 2.438 2.017.957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z", fill: "#EA4335" })] }), jsxRuntime.jsx("span", { children: "Google" })] })), showPhone && (jsxRuntime.jsxs("button", { className: "auth-provider-button", disabled: true, children: [jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }), jsxRuntime.jsx("span", { children: "Phone" })] }))] })] }))] }));
|
|
400
400
|
};
|
|
401
401
|
|
|
402
|
+
// Default Smartlinks Google OAuth Client ID (public - safe to expose)
|
|
403
|
+
const DEFAULT_GOOGLE_CLIENT_ID = '696509063554-jdlbjl8vsjt7cr0vgkjkjf3ffnvi3a70.apps.googleusercontent.com';
|
|
402
404
|
const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], redirectUrl, theme = 'light', className, customization, skipConfigFetch = false, }) => {
|
|
403
405
|
const [mode, setMode] = react.useState('login');
|
|
404
406
|
const [loading, setLoading] = react.useState(false);
|
|
@@ -691,19 +693,94 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
691
693
|
}
|
|
692
694
|
};
|
|
693
695
|
const handleGoogleLogin = async () => {
|
|
696
|
+
// Use custom client ID from config, or fall back to default Smartlinks client ID
|
|
697
|
+
const googleClientId = config?.googleClientId || DEFAULT_GOOGLE_CLIENT_ID;
|
|
698
|
+
// Determine OAuth flow: default to 'oneTap' for better UX, but allow 'popup' for iframe compatibility
|
|
699
|
+
const oauthFlow = config?.googleOAuthFlow || 'oneTap';
|
|
694
700
|
setLoading(true);
|
|
695
701
|
setError(undefined);
|
|
696
702
|
try {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
703
|
+
const google = window.google;
|
|
704
|
+
if (!google) {
|
|
705
|
+
throw new Error('Google Identity Services not loaded. Please check your internet connection.');
|
|
706
|
+
}
|
|
707
|
+
if (oauthFlow === 'popup') {
|
|
708
|
+
// Use OAuth2 popup flow (works in iframes but requires popup permission)
|
|
709
|
+
if (!google.accounts.oauth2) {
|
|
710
|
+
throw new Error('Google OAuth2 not available');
|
|
711
|
+
}
|
|
712
|
+
const client = google.accounts.oauth2.initTokenClient({
|
|
713
|
+
client_id: googleClientId,
|
|
714
|
+
scope: 'openid email profile',
|
|
715
|
+
callback: async (response) => {
|
|
716
|
+
try {
|
|
717
|
+
if (response.error) {
|
|
718
|
+
throw new Error(response.error_description || response.error);
|
|
719
|
+
}
|
|
720
|
+
const accessToken = response.access_token;
|
|
721
|
+
// Send access token to backend
|
|
722
|
+
const authResponse = await api.loginWithGoogle(accessToken);
|
|
723
|
+
auth.login(authResponse.token, authResponse.user, authResponse.accountData);
|
|
724
|
+
setAuthSuccess(true);
|
|
725
|
+
setSuccessMessage('Google login successful!');
|
|
726
|
+
onAuthSuccess(authResponse.token, authResponse.user, authResponse.accountData);
|
|
727
|
+
if (redirectUrl) {
|
|
728
|
+
setTimeout(() => {
|
|
729
|
+
window.location.href = redirectUrl;
|
|
730
|
+
}, 2000);
|
|
731
|
+
}
|
|
732
|
+
setLoading(false);
|
|
733
|
+
}
|
|
734
|
+
catch (err) {
|
|
735
|
+
const errorMessage = err instanceof Error ? err.message : 'Google login failed';
|
|
736
|
+
setError(errorMessage);
|
|
737
|
+
onAuthError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
738
|
+
setLoading(false);
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
});
|
|
742
|
+
client.requestAccessToken();
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
// Use One Tap / Sign-In button flow (smoother UX but doesn't work in iframes)
|
|
746
|
+
google.accounts.id.initialize({
|
|
747
|
+
client_id: googleClientId,
|
|
748
|
+
callback: async (response) => {
|
|
749
|
+
try {
|
|
750
|
+
const idToken = response.credential;
|
|
751
|
+
const authResponse = await api.loginWithGoogle(idToken);
|
|
752
|
+
auth.login(authResponse.token, authResponse.user, authResponse.accountData);
|
|
753
|
+
setAuthSuccess(true);
|
|
754
|
+
setSuccessMessage('Google login successful!');
|
|
755
|
+
onAuthSuccess(authResponse.token, authResponse.user, authResponse.accountData);
|
|
756
|
+
if (redirectUrl) {
|
|
757
|
+
setTimeout(() => {
|
|
758
|
+
window.location.href = redirectUrl;
|
|
759
|
+
}, 2000);
|
|
760
|
+
}
|
|
761
|
+
setLoading(false);
|
|
762
|
+
}
|
|
763
|
+
catch (err) {
|
|
764
|
+
const errorMessage = err instanceof Error ? err.message : 'Google login failed';
|
|
765
|
+
setError(errorMessage);
|
|
766
|
+
onAuthError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
767
|
+
setLoading(false);
|
|
768
|
+
}
|
|
769
|
+
},
|
|
770
|
+
auto_select: false,
|
|
771
|
+
cancel_on_tap_outside: true,
|
|
772
|
+
});
|
|
773
|
+
google.accounts.id.prompt((notification) => {
|
|
774
|
+
if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
|
|
775
|
+
setLoading(false);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
700
779
|
}
|
|
701
780
|
catch (err) {
|
|
702
781
|
const errorMessage = err instanceof Error ? err.message : 'Google login failed';
|
|
703
782
|
setError(errorMessage);
|
|
704
783
|
onAuthError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
705
|
-
}
|
|
706
|
-
finally {
|
|
707
784
|
setLoading(false);
|
|
708
785
|
}
|
|
709
786
|
};
|