@passkeyme/react-auth 2.2.10 → 2.3.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/dist/index.js CHANGED
@@ -2249,7 +2249,7 @@ const PasskeymeAuthPanel = ({
2249
2249
  providers = ["google", "github", "apple", "microsoft"], enablePasskeys = true, enableUsernamePassword: _enableUsernamePassword = false, // Reserved for future implementation
2250
2250
  redirectUri, state: _state, // Reserved for future implementation
2251
2251
  // Layout & behavior
2252
- layout = "vertical", spacing = "normal", passkeyFirst = true, hideProvidersInitially = false, autoTriggerPasskey = true,
2252
+ layout = "vertical", spacing = "normal", passkeyFirst = true, hideProvidersInitially = false, autoTriggerPasskey = true, detectDeviceCredentials = true, detectUsingLocalStorage = true, localStorageKey = "passkeyme_initialized",
2253
2253
  // Content customization
2254
2254
  title = "Sign In", subtitle = "Choose your preferred authentication method", passkeyButtonText = "🔐 Sign in with Passkey", passkeyLoadingText = "⏳ Authenticating...", dividerText = "or continue with", successTitle = "✅ Welcome back!", successSubtitle, logoutButtonText = "Sign Out",
2255
2255
  // Visibility controls
@@ -2266,6 +2266,7 @@ debugMode = false, passkeyOptions = {}, }) => {
2266
2266
  const [availableProviders, setAvailableProviders] = React.useState(providers);
2267
2267
  const [passkeyAttempted, setPasskeyAttempted] = React.useState(false);
2268
2268
  const [internalError, setInternalError] = React.useState(null);
2269
+ const [hasDeviceCredentials, setHasDeviceCredentials] = React.useState(false);
2269
2270
  // Merge theme with defaults
2270
2271
  const mergedTheme = {
2271
2272
  container: { ...defaultTheme.container, ...theme.container },
@@ -2277,14 +2278,62 @@ debugMode = false, passkeyOptions = {}, }) => {
2277
2278
  successState: { ...defaultTheme.successState, ...theme.successState },
2278
2279
  debugInfo: { ...defaultTheme.debugInfo, ...theme.debugInfo },
2279
2280
  };
2280
- // Auto-trigger passkey on mount if enabled
2281
+ // Detect device credentials silently on mount
2282
+ React.useEffect(() => {
2283
+ if (!isPasskeySupported())
2284
+ return;
2285
+ const detectCredentials = async () => {
2286
+ var _a;
2287
+ let hasCredentials = false;
2288
+ // Check localStorage if enabled
2289
+ if (detectUsingLocalStorage) {
2290
+ const localStorageValue = localStorage.getItem(localStorageKey);
2291
+ if (localStorageValue === "true" || localStorageValue === "1") {
2292
+ hasCredentials = true;
2293
+ if (debugMode) {
2294
+ console.log("🔐 PasskeymeAuthPanel: Passkey setup detected in localStorage");
2295
+ }
2296
+ }
2297
+ }
2298
+ // Also check device credentials silently if enabled
2299
+ if (detectDeviceCredentials && !hasCredentials) {
2300
+ try {
2301
+ if (typeof ((_a = navigator.credentials) === null || _a === void 0 ? void 0 : _a.get) === "function") {
2302
+ const credentials = await navigator.credentials.get({
2303
+ mediation: "silent",
2304
+ publicKey: {},
2305
+ });
2306
+ hasCredentials = !!credentials;
2307
+ if (debugMode) {
2308
+ console.log("🔐 PasskeymeAuthPanel: Device credentials detected:", !!credentials);
2309
+ }
2310
+ }
2311
+ }
2312
+ catch (error) {
2313
+ if (debugMode) {
2314
+ console.log("🔐 PasskeymeAuthPanel: Silent credential detection skipped (expected in some contexts)");
2315
+ }
2316
+ }
2317
+ }
2318
+ setHasDeviceCredentials(hasCredentials);
2319
+ };
2320
+ detectCredentials();
2321
+ }, [
2322
+ detectDeviceCredentials,
2323
+ detectUsingLocalStorage,
2324
+ localStorageKey,
2325
+ isPasskeySupported,
2326
+ debugMode,
2327
+ ]);
2328
+ // Auto-trigger passkey on mount if enabled and device has credentials
2281
2329
  React.useEffect(() => {
2282
2330
  if (autoTriggerPasskey &&
2283
2331
  passkeyFirst &&
2284
2332
  enablePasskeys &&
2285
2333
  isPasskeySupported() &&
2286
2334
  !passkeyAttempted &&
2287
- !isAuthenticated) {
2335
+ !isAuthenticated &&
2336
+ hasDeviceCredentials) {
2288
2337
  handlePasskeyAuth();
2289
2338
  }
2290
2339
  }, [
@@ -2294,6 +2343,7 @@ debugMode = false, passkeyOptions = {}, }) => {
2294
2343
  isPasskeySupported,
2295
2344
  passkeyAttempted,
2296
2345
  isAuthenticated,
2346
+ hasDeviceCredentials,
2297
2347
  ]);
2298
2348
  const handlePasskeyAuth = () => {
2299
2349
  if (debugMode)
@@ -2403,7 +2453,7 @@ debugMode = false, passkeyOptions = {}, }) => {
2403
2453
  fontSize: "14px",
2404
2454
  width: "100%",
2405
2455
  textAlign: "center",
2406
- }, children: internalError })), enablePasskeys && showOAuthOptions && (jsxRuntime.jsx("button", { onClick: handlePasskeyAuth, disabled: authLoading, style: passkeyButtonStyles, onMouseEnter: e => {
2456
+ }, children: internalError })), enablePasskeys && showOAuthOptions && hasDeviceCredentials && (jsxRuntime.jsx("button", { onClick: handlePasskeyAuth, disabled: authLoading, style: passkeyButtonStyles, onMouseEnter: e => {
2407
2457
  var _a;
2408
2458
  if (!authLoading) {
2409
2459
  e.currentTarget.style.backgroundColor =
@@ -2418,13 +2468,39 @@ debugMode = false, passkeyOptions = {}, }) => {
2418
2468
  }, children: authLoading ? passkeyLoadingText : passkeyButtonText })), showDividerText &&
2419
2469
  showOAuthOptions &&
2420
2470
  enablePasskeys &&
2471
+ hasDeviceCredentials &&
2421
2472
  availableProviders.length > 0 && (jsxRuntime.jsx("p", { style: { margin: 0, ...mergedTheme.dividerText }, children: dividerText })), showOAuthOptions && availableProviders.length > 0 && (jsxRuntime.jsx("div", { style: oauthContainerStyles, children: availableProviders.map(provider => (jsxRuntime.jsx("div", { style: {
2422
2473
  flex: layout === "horizontal" ? 1 : undefined,
2423
2474
  minWidth: layout === "grid" ? "140px" : undefined,
2424
2475
  width: layout === "vertical" ? "100%" : undefined,
2425
2476
  }, children: jsxRuntime.jsxs(PasskeymeOAuthButton, { provider: provider, redirectUri: redirectUri, onClick: () => handleOAuthClick(provider), style: {
2426
2477
  width: layout === "vertical" ? "100%" : undefined,
2427
- }, children: ["Continue with", " ", provider.charAt(0).toUpperCase() + provider.slice(1)] }) }, provider))) })), (showDebugInfo || debugMode) && (jsxRuntime.jsxs("div", { style: mergedTheme.debugInfo, children: [jsxRuntime.jsx("strong", { children: "\uD83D\uDC1B Debug Info:" }), jsxRuntime.jsx("br", {}), "Passkey Support: ", isPasskeySupported() ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Authenticated: ", isAuthenticated ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Auth Loading: ", authLoading ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Passkey Attempted: ", passkeyAttempted ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Show OAuth: ", showOAuthOptions ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Available Providers: ", availableProviders.join(", ") || "None"] }))] }));
2478
+ }, children: ["Continue with", " ", provider.charAt(0).toUpperCase() + provider.slice(1)] }) }, provider))) })), enablePasskeys && showOAuthOptions && !hasDeviceCredentials && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("p", { style: {
2479
+ margin: 0,
2480
+ ...mergedTheme.dividerText,
2481
+ fontSize: "12px",
2482
+ opacity: "0.7",
2483
+ }, children: dividerText }), jsxRuntime.jsx("button", { onClick: handlePasskeyAuth, disabled: authLoading, style: {
2484
+ backgroundColor: "#e5e7eb",
2485
+ color: "#374151",
2486
+ border: "none",
2487
+ borderRadius: "8px",
2488
+ padding: "10px 20px",
2489
+ fontSize: "14px",
2490
+ fontWeight: "500",
2491
+ cursor: authLoading ? "not-allowed" : "pointer",
2492
+ transition: "all 0.2s ease",
2493
+ width: "100%",
2494
+ minHeight: "40px",
2495
+ }, onMouseEnter: e => {
2496
+ if (!authLoading) {
2497
+ e.currentTarget.style.backgroundColor = "#d1d5db";
2498
+ }
2499
+ }, onMouseLeave: e => {
2500
+ if (!authLoading) {
2501
+ e.currentTarget.style.backgroundColor = "#e5e7eb";
2502
+ }
2503
+ }, children: authLoading ? passkeyLoadingText : "🔑 Already have a passkey?" })] })), (showDebugInfo || debugMode) && (jsxRuntime.jsxs("div", { style: mergedTheme.debugInfo, children: [jsxRuntime.jsx("strong", { children: "\uD83D\uDC1B Debug Info:" }), jsxRuntime.jsx("br", {}), "Passkey Support: ", isPasskeySupported() ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Authenticated: ", isAuthenticated ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Auth Loading: ", authLoading ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Passkey Attempted: ", passkeyAttempted ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Device Credentials: ", hasDeviceCredentials ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Show OAuth: ", showOAuthOptions ? "Yes" : "No", jsxRuntime.jsx("br", {}), "Available Providers: ", availableProviders.join(", ") || "None"] }))] }));
2428
2504
  };
2429
2505
 
2430
2506
  /**