@proveanything/smartlinks-auth-ui 0.1.5 → 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
@@ -11434,10 +11434,52 @@ const useAuth = () => {
11434
11434
 
11435
11435
  // Default Smartlinks Google OAuth Client ID (public - safe to expose)
11436
11436
  const DEFAULT_GOOGLE_CLIENT_ID = '696509063554-jdlbjl8vsjt7cr0vgkjkjf3ffnvi3a70.apps.googleusercontent.com';
11437
- const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'light', className, customization, skipConfigFetch = false, minimal = false, }) => {
11437
+ // Default auth UI configuration when no clientId is provided
11438
+ const DEFAULT_AUTH_CONFIG = {
11439
+ branding: {
11440
+ title: '', // No title by default (minimal)
11441
+ subtitle: 'Sign in to your account',
11442
+ logoUrl: 'https://smartlinks.app/smartlinks/landscape-medium.png',
11443
+ primaryColor: '#3B82F6',
11444
+ secondaryColor: '#1D4ED8',
11445
+ backgroundColor: '#e0f2fe',
11446
+ buttonStyle: 'rounded',
11447
+ fontFamily: 'Inter, sans-serif'
11448
+ },
11449
+ emailDisplayMode: 'button',
11450
+ googleOAuthFlow: 'oneTap'
11451
+ };
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, }) => {
11438
11479
  const [mode, setMode] = React.useState(initialMode);
11439
11480
  const [loading, setLoading] = React.useState(false);
11440
11481
  const [error, setError] = React.useState();
11482
+ const [resolvedTheme, setResolvedTheme] = React.useState('light');
11441
11483
  const [resetSuccess, setResetSuccess] = React.useState(false);
11442
11484
  const [authSuccess, setAuthSuccess] = React.useState(false);
11443
11485
  const [successMessage, setSuccessMessage] = React.useState();
@@ -11451,6 +11493,19 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11451
11493
  const [showEmailForm, setShowEmailForm] = React.useState(false); // Track if email form should be shown when emailDisplayMode is 'button'
11452
11494
  const api = new AuthAPI(apiEndpoint, clientId, clientName);
11453
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]);
11454
11509
  // Reinitialize Smartlinks SDK when apiEndpoint changes (for test/dev scenarios)
11455
11510
  // IMPORTANT: Preserve bearer token during reinitialization
11456
11511
  React.useEffect(() => {
@@ -11489,9 +11544,19 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11489
11544
  return;
11490
11545
  }
11491
11546
  const fetchConfig = async () => {
11547
+ // If no clientId provided, use default config immediately without API call
11548
+ if (!clientId) {
11549
+ const defaultConfig = {
11550
+ ...DEFAULT_AUTH_CONFIG,
11551
+ enabledProviders: enabledProviders || ['email', 'google', 'phone']
11552
+ };
11553
+ setConfig({ ...defaultConfig, ...customization });
11554
+ setConfigLoading(false);
11555
+ return;
11556
+ }
11492
11557
  try {
11493
11558
  // Check localStorage cache first
11494
- const cacheKey = `auth_ui_config_${clientId || 'default'}`;
11559
+ const cacheKey = `auth_ui_config_${clientId}`;
11495
11560
  const cached = localStorage.getItem(cacheKey);
11496
11561
  if (cached) {
11497
11562
  const { config: cachedConfig, timestamp } = JSON.parse(cached);
@@ -11809,9 +11874,11 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11809
11874
  setLoading(true);
11810
11875
  setError(undefined);
11811
11876
  try {
11877
+ // Dynamically load Google Identity Services if not already loaded
11878
+ await loadGoogleIdentityServices();
11812
11879
  const google = window.google;
11813
- if (!google) {
11814
- 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');
11815
11882
  }
11816
11883
  if (oauthFlow === 'popup') {
11817
11884
  // Use OAuth2 popup flow (works in iframes but requires popup permission)
@@ -11981,9 +12048,9 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
11981
12048
  }
11982
12049
  };
11983
12050
  if (configLoading) {
11984
- 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" }) }) }));
11985
12052
  }
11986
- 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: {
11987
12054
  color: 'var(--auth-primary-color, #4F46E5)',
11988
12055
  fontSize: '3rem',
11989
12056
  marginBottom: '1rem'