@proveanything/smartlinks-auth-ui 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11449,10 +11449,37 @@ const DEFAULT_AUTH_CONFIG = {
11449
11449
  emailDisplayMode: 'button',
11450
11450
  googleOAuthFlow: 'oneTap'
11451
11451
  };
11452
- const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'light', className, customization, skipConfigFetch = false, minimal = false, }) => {
11452
+ // Helper to dynamically load Google Identity Services if not already loaded
11453
+ const loadGoogleIdentityServices = () => {
11454
+ return new Promise((resolve, reject) => {
11455
+ // Check if already loaded
11456
+ if (window.google?.accounts) {
11457
+ resolve();
11458
+ return;
11459
+ }
11460
+ // Check if script is already being loaded
11461
+ const existingScript = document.querySelector('script[src="https://accounts.google.com/gsi/client"]');
11462
+ if (existingScript) {
11463
+ // Wait for existing script to load
11464
+ existingScript.addEventListener('load', () => resolve());
11465
+ existingScript.addEventListener('error', () => reject(new Error('Failed to load Google Identity Services')));
11466
+ return;
11467
+ }
11468
+ // Dynamically inject the script
11469
+ const script = document.createElement('script');
11470
+ script.src = 'https://accounts.google.com/gsi/client';
11471
+ script.async = true;
11472
+ script.defer = true;
11473
+ script.onload = () => resolve();
11474
+ script.onerror = () => reject(new Error('Failed to load Google Identity Services'));
11475
+ document.head.appendChild(script);
11476
+ });
11477
+ };
11478
+ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'auto', className, customization, skipConfigFetch = false, minimal = false, }) => {
11453
11479
  const [mode, setMode] = React.useState(initialMode);
11454
11480
  const [loading, setLoading] = React.useState(false);
11455
11481
  const [error, setError] = React.useState();
11482
+ const [resolvedTheme, setResolvedTheme] = React.useState('light');
11456
11483
  const [resetSuccess, setResetSuccess] = React.useState(false);
11457
11484
  const [authSuccess, setAuthSuccess] = React.useState(false);
11458
11485
  const [successMessage, setSuccessMessage] = React.useState();
@@ -11466,6 +11493,19 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11466
11493
  const [showEmailForm, setShowEmailForm] = React.useState(false); // Track if email form should be shown when emailDisplayMode is 'button'
11467
11494
  const api = new AuthAPI(apiEndpoint, clientId, clientName);
11468
11495
  const auth = useAuth();
11496
+ // Dark mode detection and theme management
11497
+ React.useEffect(() => {
11498
+ if (theme !== 'auto') {
11499
+ setResolvedTheme(theme);
11500
+ return;
11501
+ }
11502
+ // Auto-detect system theme preference
11503
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
11504
+ const updateTheme = () => setResolvedTheme(mediaQuery.matches ? 'dark' : 'light');
11505
+ updateTheme();
11506
+ mediaQuery.addEventListener('change', updateTheme);
11507
+ return () => mediaQuery.removeEventListener('change', updateTheme);
11508
+ }, [theme]);
11469
11509
  // Reinitialize Smartlinks SDK when apiEndpoint changes (for test/dev scenarios)
11470
11510
  // IMPORTANT: Preserve bearer token during reinitialization
11471
11511
  React.useEffect(() => {
@@ -11834,9 +11874,11 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11834
11874
  setLoading(true);
11835
11875
  setError(undefined);
11836
11876
  try {
11877
+ // Dynamically load Google Identity Services if not already loaded
11878
+ await loadGoogleIdentityServices();
11837
11879
  const google = window.google;
11838
- if (!google) {
11839
- throw new Error('Google Identity Services not loaded. Please check your internet connection.');
11880
+ if (!google?.accounts) {
11881
+ throw new Error('Google Identity Services failed to initialize');
11840
11882
  }
11841
11883
  if (oauthFlow === 'popup') {
11842
11884
  // Use OAuth2 popup flow (works in iframes but requires popup permission)
@@ -12006,9 +12048,9 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12006
12048
  }
12007
12049
  };
12008
12050
  if (configLoading) {
12009
- return (jsxRuntime.jsx(AuthContainer, { theme: theme, className: className, minimal: minimal || config?.branding?.minimal || false, children: jsxRuntime.jsx("div", { style: { textAlign: 'center', padding: '2rem' }, children: jsxRuntime.jsx("div", { className: "auth-spinner" }) }) }));
12051
+ return (jsxRuntime.jsx(AuthContainer, { theme: resolvedTheme, className: className, minimal: minimal || config?.branding?.minimal || false, children: jsxRuntime.jsx("div", { style: { textAlign: 'center', padding: '2rem' }, children: jsxRuntime.jsx("div", { className: "auth-spinner" }) }) }));
12010
12052
  }
12011
- return (jsxRuntime.jsx(AuthContainer, { theme: theme, className: className, config: config, minimal: minimal || config?.branding?.minimal || false, children: authSuccess ? (jsxRuntime.jsxs("div", { style: { textAlign: 'center', padding: '2rem' }, children: [jsxRuntime.jsx("div", { style: {
12053
+ return (jsxRuntime.jsx(AuthContainer, { theme: resolvedTheme, className: className, config: config, minimal: minimal || config?.branding?.minimal || false, children: authSuccess ? (jsxRuntime.jsxs("div", { style: { textAlign: 'center', padding: '2rem' }, children: [jsxRuntime.jsx("div", { style: {
12012
12054
  color: 'var(--auth-primary-color, #4F46E5)',
12013
12055
  fontSize: '3rem',
12014
12056
  marginBottom: '1rem'