@authon/react 0.3.2 → 0.7.15

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
@@ -11,32 +11,35 @@ function AuthonProvider({ publishableKey, children, config }) {
11
11
  const [activeOrganization, setActiveOrganization] = useState(null);
12
12
  const clientRef = useRef(null);
13
13
  useEffect(() => {
14
+ let active = true;
15
+ let receivedSessionChange = false;
14
16
  const client = new Authon(publishableKey, config);
17
+ const sessionClient = client;
15
18
  clientRef.current = client;
16
- client.on("signedIn", (u) => {
17
- setUser(u);
19
+ const unsubscribeSession = sessionClient.onSessionChange((change) => {
20
+ if (!active) return;
21
+ receivedSessionChange = true;
22
+ setUser(change.user);
18
23
  setIsLoading(false);
19
- });
20
- client.on("signedOut", () => {
21
- setUser(null);
24
+ if (!change.user) setActiveOrganization(null);
22
25
  });
23
26
  client.on("error", () => {
24
27
  setIsLoading(false);
25
28
  });
26
- const existingUser = client.getUser();
27
- if (existingUser) {
28
- setUser(existingUser);
29
- }
30
- setIsLoading(false);
29
+ void sessionClient.waitUntilReady().then(() => {
30
+ if (!active) return;
31
+ if (!receivedSessionChange) setUser(client.getUser());
32
+ setIsLoading(false);
33
+ });
31
34
  return () => {
35
+ active = false;
36
+ unsubscribeSession();
32
37
  client.destroy();
33
38
  clientRef.current = null;
34
39
  };
35
40
  }, [publishableKey]);
36
41
  const signOut = useCallback(async () => {
37
42
  await clientRef.current?.signOut();
38
- setUser(null);
39
- setActiveOrganization(null);
40
43
  }, []);
41
44
  const openSignIn = useCallback(async () => {
42
45
  await clientRef.current?.openSignIn();
@@ -82,9 +85,9 @@ function useUser() {
82
85
  }
83
86
 
84
87
  // src/components/SignIn.tsx
85
- import { useState as useState5 } from "react";
88
+ import { useRef as useRef4, useState as useState6 } from "react";
86
89
  import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES } from "@authon/shared";
87
- import { getProviderButtonConfig } from "@authon/js";
90
+ import { AuthonMfaRequiredError, getProviderButtonConfig } from "@authon/js";
88
91
 
89
92
  // src/hooks/useBranding.ts
90
93
  import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
@@ -187,7 +190,7 @@ function ThemeProvider({ branding, children, overrides, style, className }) {
187
190
  }
188
191
 
189
192
  // src/components/shared/Input.tsx
190
- import { useState as useState3 } from "react";
193
+ import { useId, useState as useState3 } from "react";
191
194
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
192
195
  function Input({
193
196
  label,
@@ -200,8 +203,10 @@ function Input({
200
203
  ...rest
201
204
  }) {
202
205
  const theme = useTheme();
206
+ const generatedId = useId();
203
207
  const [focused, setFocused] = useState3(false);
204
208
  const resolvedStyle = inputStyle ?? theme.inputStyle;
209
+ const inputId = rest.id ?? generatedId;
205
210
  const wrapperStyle = {
206
211
  display: "flex",
207
212
  flexDirection: "column",
@@ -258,12 +263,13 @@ function Input({
258
263
  color: error ? "#ef4444" : theme.textMuted
259
264
  };
260
265
  return /* @__PURE__ */ jsxs("div", { style: wrapperStyle, children: [
261
- label && /* @__PURE__ */ jsx3("label", { style: labelStyle, children: label }),
266
+ label && /* @__PURE__ */ jsx3("label", { htmlFor: inputId, style: labelStyle, children: label }),
262
267
  /* @__PURE__ */ jsxs("div", { style: inputContainerStyle, children: [
263
268
  /* @__PURE__ */ jsx3(
264
269
  "input",
265
270
  {
266
271
  ...rest,
272
+ id: inputId,
267
273
  style: { ...baseInputStyle, ...inputVariantStyle },
268
274
  onFocus: (e) => {
269
275
  setFocused(true);
@@ -411,19 +417,212 @@ function Divider({ label = "Or continue with" }) {
411
417
  ] });
412
418
  }
413
419
 
414
- // src/components/SignIn.tsx
420
+ // src/components/shared/AuthChallengeForms.tsx
421
+ import { useId as useId2, useRef as useRef3, useState as useState5 } from "react";
415
422
  import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
416
- function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
423
+ function errorMessage(error, fallback) {
424
+ return error instanceof Error && error.message ? error.message : fallback;
425
+ }
426
+ function CodeForm({
427
+ title,
428
+ description,
429
+ label,
430
+ submitLabel,
431
+ backLabel,
432
+ onSubmit,
433
+ onBack,
434
+ onResend
435
+ }) {
436
+ const theme = useTheme();
437
+ const [code, setCode] = useState5("");
438
+ const [error, setError] = useState5("");
439
+ const [status, setStatus] = useState5("");
440
+ const [loading, setLoading] = useState5(false);
441
+ const [resending, setResending] = useState5(false);
442
+ const errorId = useId2();
443
+ const submitPending = useRef3(false);
444
+ const resendPending = useRef3(false);
445
+ const handleSubmit = async () => {
446
+ if (submitPending.current) return;
447
+ if (!code.trim()) {
448
+ setError(`${label} is required`);
449
+ return;
450
+ }
451
+ submitPending.current = true;
452
+ setLoading(true);
453
+ setError("");
454
+ setStatus("");
455
+ try {
456
+ await onSubmit(code.trim());
457
+ } catch (submitError) {
458
+ setError(errorMessage(submitError, "Verification failed"));
459
+ } finally {
460
+ submitPending.current = false;
461
+ setLoading(false);
462
+ }
463
+ };
464
+ const handleResend = async () => {
465
+ if (!onResend || resendPending.current) return;
466
+ resendPending.current = true;
467
+ setResending(true);
468
+ setError("");
469
+ setStatus("");
470
+ try {
471
+ await onResend();
472
+ setStatus("Verification code sent");
473
+ } catch (resendError) {
474
+ setError(errorMessage(resendError, "Could not resend verification code"));
475
+ } finally {
476
+ resendPending.current = false;
477
+ setResending(false);
478
+ }
479
+ };
480
+ const titleStyle = {
481
+ margin: 0,
482
+ fontSize: 24,
483
+ fontWeight: 700,
484
+ color: theme.text,
485
+ textAlign: "center",
486
+ letterSpacing: "-0.3px"
487
+ };
488
+ const descriptionStyle = {
489
+ margin: "-8px 0 0",
490
+ fontSize: 14,
491
+ lineHeight: 1.5,
492
+ color: theme.textMuted,
493
+ textAlign: "center"
494
+ };
495
+ const errorStyle = {
496
+ padding: "10px 14px",
497
+ borderRadius: theme.borderRadius,
498
+ background: "#fef2f2",
499
+ border: "1px solid #fecaca",
500
+ color: "#dc2626",
501
+ fontSize: 13
502
+ };
503
+ const statusStyle = {
504
+ padding: "10px 14px",
505
+ borderRadius: theme.borderRadius,
506
+ background: "#f0fdf4",
507
+ border: "1px solid #bbf7d0",
508
+ color: "#15803d",
509
+ fontSize: 13
510
+ };
511
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
512
+ /* @__PURE__ */ jsx6("h1", { style: titleStyle, children: title }),
513
+ /* @__PURE__ */ jsx6("p", { style: descriptionStyle, children: description }),
514
+ error && /* @__PURE__ */ jsx6("div", { id: errorId, role: "alert", style: errorStyle, children: error }),
515
+ status && /* @__PURE__ */ jsx6("div", { role: "status", "aria-live": "polite", style: statusStyle, children: status }),
516
+ /* @__PURE__ */ jsx6(
517
+ Input,
518
+ {
519
+ label,
520
+ value: code,
521
+ onChange: setCode,
522
+ inputMode: "numeric",
523
+ autoComplete: "one-time-code",
524
+ disabled: loading,
525
+ "aria-invalid": !!error,
526
+ "aria-describedby": error ? errorId : void 0
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsx6(
530
+ Button,
531
+ {
532
+ variant: "primary",
533
+ fullWidth: true,
534
+ loading,
535
+ disabled: resending,
536
+ onClick: handleSubmit,
537
+ children: submitLabel
538
+ }
539
+ ),
540
+ onResend && /* @__PURE__ */ jsx6(
541
+ Button,
542
+ {
543
+ variant: "outline",
544
+ fullWidth: true,
545
+ loading: resending,
546
+ disabled: loading,
547
+ onClick: handleResend,
548
+ children: "Resend code"
549
+ }
550
+ ),
551
+ /* @__PURE__ */ jsx6(
552
+ Button,
553
+ {
554
+ variant: "ghost",
555
+ fullWidth: true,
556
+ disabled: loading || resending,
557
+ onClick: onBack,
558
+ children: backLabel
559
+ }
560
+ )
561
+ ] });
562
+ }
563
+ function VerificationForm({
564
+ email,
565
+ backLabel,
566
+ onVerify,
567
+ onResend,
568
+ onBack
569
+ }) {
570
+ return /* @__PURE__ */ jsx6(
571
+ CodeForm,
572
+ {
573
+ title: "Verify your email",
574
+ description: `Enter the verification code sent to ${email}.`,
575
+ label: "Verification code",
576
+ submitLabel: "Verify email",
577
+ backLabel,
578
+ onSubmit: onVerify,
579
+ onResend,
580
+ onBack
581
+ }
582
+ );
583
+ }
584
+ function MfaForm({ onVerify, onBack }) {
585
+ return /* @__PURE__ */ jsx6(
586
+ CodeForm,
587
+ {
588
+ title: "Two-factor authentication",
589
+ description: "Enter the code from your authenticator app.",
590
+ label: "Authenticator code",
591
+ submitLabel: "Verify code",
592
+ backLabel: "Back to sign in",
593
+ onSubmit: onVerify,
594
+ onBack
595
+ }
596
+ );
597
+ }
598
+
599
+ // src/components/shared/navigation.ts
600
+ function navigateTo(url) {
601
+ window.location.assign(url);
602
+ }
603
+
604
+ // src/components/SignIn.tsx
605
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
606
+ function SignInCard({ afterSignInUrl, onSignIn, onForgotPassword, onNavigateSignUp }) {
417
607
  const theme = useTheme();
418
608
  const { client } = useAuthon();
419
609
  const { branding, providers, isLoaded } = useBranding();
420
- const [email, setEmail] = useState5("");
421
- const [password, setPassword] = useState5("");
422
- const [showPassword, setShowPassword] = useState5(false);
423
- const [loading, setLoading] = useState5(false);
424
- const [oauthLoading, setOauthLoading] = useState5(null);
425
- const [error, setError] = useState5("");
426
- const [fieldErrors, setFieldErrors] = useState5({});
610
+ const [email, setEmail] = useState6("");
611
+ const [password, setPassword] = useState6("");
612
+ const [showPassword, setShowPassword] = useState6(false);
613
+ const [loading, setLoading] = useState6(false);
614
+ const [oauthLoading, setOauthLoading] = useState6(null);
615
+ const [error, setError] = useState6("");
616
+ const [step, setStep] = useState6({ kind: "credentials" });
617
+ const [fieldErrors, setFieldErrors] = useState6({});
618
+ const authAttemptPending = useRef4(false);
619
+ const completed = useRef4(false);
620
+ const completeSignIn = () => {
621
+ if (completed.current) return;
622
+ completed.current = true;
623
+ if (afterSignInUrl) navigateTo(afterSignInUrl);
624
+ onSignIn?.();
625
+ };
427
626
  const validate = () => {
428
627
  const errs = {};
429
628
  if (!email.trim()) errs.email = "Email is required";
@@ -433,21 +632,35 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
433
632
  return Object.keys(errs).length === 0;
434
633
  };
435
634
  const handleSubmit = async () => {
436
- if (!validate() || !client) return;
635
+ if (authAttemptPending.current || !validate() || !client) return;
636
+ authAttemptPending.current = true;
437
637
  setLoading(true);
438
638
  setError("");
439
639
  try {
440
- await client.signInWithEmail(email, password);
441
- if (afterSignInUrl) window.location.assign(afterSignInUrl);
442
- onSignIn?.();
443
- } catch (e) {
444
- setError(e?.message ?? "Sign in failed");
640
+ const result = await client.signInWithEmail(email, password);
641
+ if ("needsVerification" in result && result.needsVerification) {
642
+ setStep({ kind: "verification", email: result.email });
643
+ return;
644
+ }
645
+ completeSignIn();
646
+ } catch (submitError) {
647
+ if (submitError instanceof AuthonMfaRequiredError) {
648
+ setStep({ kind: "mfa", mfaToken: submitError.mfaToken });
649
+ } else {
650
+ setError(submitError instanceof Error && submitError.message ? submitError.message : "Sign in failed");
651
+ }
445
652
  } finally {
653
+ authAttemptPending.current = false;
446
654
  setLoading(false);
447
655
  }
448
656
  };
657
+ const backToCredentials = () => {
658
+ setError("");
659
+ setStep({ kind: "credentials" });
660
+ };
449
661
  const handleOAuth = async (provider) => {
450
- if (!client) return;
662
+ if (!client || authAttemptPending.current) return;
663
+ authAttemptPending.current = true;
451
664
  setOauthLoading(provider);
452
665
  setError("");
453
666
  try {
@@ -455,6 +668,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
455
668
  } catch (e) {
456
669
  setError(e?.message ?? "OAuth sign in failed");
457
670
  } finally {
671
+ authAttemptPending.current = false;
458
672
  setOauthLoading(null);
459
673
  }
460
674
  };
@@ -525,7 +739,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
525
739
  (p) => !(branding.hiddenProviders ?? []).includes(p)
526
740
  );
527
741
  if (!isLoaded) {
528
- return /* @__PURE__ */ jsx6("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx6(
742
+ return /* @__PURE__ */ jsx7("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx7(
529
743
  "span",
530
744
  {
531
745
  style: {
@@ -540,17 +754,49 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
540
754
  }
541
755
  ) });
542
756
  }
543
- return /* @__PURE__ */ jsxs4("div", { style: cardStyle, children: [
544
- /* @__PURE__ */ jsxs4("div", { style: logoStyle, children: [
545
- branding.logoDataUrl && /* @__PURE__ */ jsx6("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
546
- /* @__PURE__ */ jsx6("h1", { style: titleStyle, children: "Sign in" }),
547
- branding.brandName && /* @__PURE__ */ jsxs4("p", { style: subtitleStyle, children: [
757
+ if (step.kind === "verification") {
758
+ return /* @__PURE__ */ jsx7("div", { style: cardStyle, children: /* @__PURE__ */ jsx7(
759
+ VerificationForm,
760
+ {
761
+ email: step.email,
762
+ backLabel: "Back to sign in",
763
+ onVerify: async (code) => {
764
+ if (!client) throw new Error("Sign in is unavailable");
765
+ await client.verifyEmail(step.email, code);
766
+ completeSignIn();
767
+ },
768
+ onResend: async () => {
769
+ if (!client) throw new Error("Sign in is unavailable");
770
+ await client.resendVerificationCode(step.email);
771
+ },
772
+ onBack: backToCredentials
773
+ }
774
+ ) });
775
+ }
776
+ if (step.kind === "mfa") {
777
+ return /* @__PURE__ */ jsx7("div", { style: cardStyle, children: /* @__PURE__ */ jsx7(
778
+ MfaForm,
779
+ {
780
+ onVerify: async (code) => {
781
+ if (!client) throw new Error("Sign in is unavailable");
782
+ await client.verifyMfa(step.mfaToken, code);
783
+ completeSignIn();
784
+ },
785
+ onBack: backToCredentials
786
+ }
787
+ ) });
788
+ }
789
+ return /* @__PURE__ */ jsxs5("div", { style: cardStyle, children: [
790
+ /* @__PURE__ */ jsxs5("div", { style: logoStyle, children: [
791
+ branding.logoDataUrl && /* @__PURE__ */ jsx7("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
792
+ /* @__PURE__ */ jsx7("h1", { style: titleStyle, children: "Sign in" }),
793
+ branding.brandName && /* @__PURE__ */ jsxs5("p", { style: subtitleStyle, children: [
548
794
  "to ",
549
795
  branding.brandName
550
796
  ] })
551
797
  ] }),
552
- error && /* @__PURE__ */ jsx6("div", { style: errorBoxStyle, children: error }),
553
- providersToShow.length > 0 && /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ jsx6(
798
+ error && /* @__PURE__ */ jsx7("div", { role: "alert", style: errorBoxStyle, children: error }),
799
+ providersToShow.length > 0 && /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ jsx7(
554
800
  OAuthButton,
555
801
  {
556
802
  provider,
@@ -560,7 +806,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
560
806
  borderRadius: theme.borderRadius
561
807
  },
562
808
  provider
563
- )) : /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ jsx6(
809
+ )) : /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ jsx7(
564
810
  CompactOAuthButton,
565
811
  {
566
812
  provider,
@@ -571,9 +817,9 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
571
817
  },
572
818
  provider
573
819
  )) }) }),
574
- showDivider && /* @__PURE__ */ jsx6(Divider, {}),
575
- showEmailPw && /* @__PURE__ */ jsxs4(Fragment2, { children: [
576
- /* @__PURE__ */ jsx6(
820
+ showDivider && /* @__PURE__ */ jsx7(Divider, {}),
821
+ showEmailPw && /* @__PURE__ */ jsxs5(Fragment3, { children: [
822
+ /* @__PURE__ */ jsx7(
577
823
  Input,
578
824
  {
579
825
  label: "Email",
@@ -585,8 +831,8 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
585
831
  autoComplete: "email"
586
832
  }
587
833
  ),
588
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
589
- /* @__PURE__ */ jsx6(
834
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
835
+ /* @__PURE__ */ jsx7(
590
836
  Input,
591
837
  {
592
838
  label: "Password",
@@ -596,21 +842,21 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
596
842
  onChange: setPassword,
597
843
  error: fieldErrors.password,
598
844
  autoComplete: "current-password",
599
- rightElement: /* @__PURE__ */ jsx6(
845
+ rightElement: /* @__PURE__ */ jsx7(
600
846
  "button",
601
847
  {
602
848
  type: "button",
603
849
  onClick: () => setShowPassword((v) => !v),
604
850
  style: { background: "none", border: "none", cursor: "pointer", padding: 0, display: "flex", color: theme.textMuted },
605
851
  "aria-label": showPassword ? "Hide password" : "Show password",
606
- children: /* @__PURE__ */ jsx6("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: eyeIconPath }) })
852
+ children: /* @__PURE__ */ jsx7("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: eyeIconPath }) })
607
853
  }
608
854
  )
609
855
  }
610
856
  ),
611
- /* @__PURE__ */ jsx6("div", { style: forgotStyle, children: /* @__PURE__ */ jsx6("button", { type: "button", style: linkStyle, children: "Forgot password?" }) })
857
+ onForgotPassword && /* @__PURE__ */ jsx7("div", { style: forgotStyle, children: /* @__PURE__ */ jsx7("button", { type: "button", style: linkStyle, onClick: onForgotPassword, children: "Forgot password?" }) })
612
858
  ] }),
613
- /* @__PURE__ */ jsx6(
859
+ /* @__PURE__ */ jsx7(
614
860
  Button,
615
861
  {
616
862
  variant: "primary",
@@ -622,10 +868,10 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
622
868
  }
623
869
  )
624
870
  ] }),
625
- /* @__PURE__ */ jsxs4("div", { style: footerStyle, children: [
871
+ /* @__PURE__ */ jsxs5("div", { style: footerStyle, children: [
626
872
  "Don't have an account?",
627
873
  " ",
628
- /* @__PURE__ */ jsx6(
874
+ /* @__PURE__ */ jsx7(
629
875
  "button",
630
876
  {
631
877
  type: "button",
@@ -635,16 +881,16 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
635
881
  }
636
882
  )
637
883
  ] }),
638
- branding.showSecuredBy !== false && /* @__PURE__ */ jsx6(SecuredByAuthon, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
639
- branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ jsxs4("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
640
- branding.termsUrl && /* @__PURE__ */ jsx6("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Terms" }),
884
+ branding.showSecuredBy !== false && /* @__PURE__ */ jsx7(SecuredByAuthon, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
885
+ branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ jsxs5("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
886
+ branding.termsUrl && /* @__PURE__ */ jsx7("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Terms" }),
641
887
  branding.termsUrl && branding.privacyUrl && " \xB7 ",
642
- branding.privacyUrl && /* @__PURE__ */ jsx6("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Privacy" })
888
+ branding.privacyUrl && /* @__PURE__ */ jsx7("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Privacy" })
643
889
  ] }) : null
644
890
  ] });
645
891
  }
646
892
  function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
647
- const [hovered, setHovered] = useState5(false);
893
+ const [hovered, setHovered] = useState6(false);
648
894
  const colors = PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
649
895
  const name = PROVIDER_DISPLAY_NAMES[provider] ?? provider;
650
896
  const config = getProviderButtonConfig(provider);
@@ -670,7 +916,7 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
670
916
  transition: "opacity 0.15s",
671
917
  boxSizing: "border-box"
672
918
  };
673
- return /* @__PURE__ */ jsx6(
919
+ return /* @__PURE__ */ jsx7(
674
920
  "button",
675
921
  {
676
922
  type: "button",
@@ -680,9 +926,9 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
680
926
  onMouseEnter: () => setHovered(true),
681
927
  onMouseLeave: () => setHovered(false),
682
928
  "aria-label": `Continue with ${name}`,
683
- children: loading ? /* @__PURE__ */ jsx6("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
684
- /* @__PURE__ */ jsx6("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
685
- /* @__PURE__ */ jsxs4("span", { children: [
929
+ children: loading ? /* @__PURE__ */ jsx7("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
930
+ /* @__PURE__ */ jsx7("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
931
+ /* @__PURE__ */ jsxs5("span", { children: [
686
932
  "Continue with ",
687
933
  name
688
934
  ] })
@@ -691,7 +937,7 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
691
937
  );
692
938
  }
693
939
  function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
694
- const [hovered, setHovered] = useState5(false);
940
+ const [hovered, setHovered] = useState6(false);
695
941
  const colors = PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
696
942
  const name = PROVIDER_DISPLAY_NAMES[provider] ?? provider;
697
943
  const config = getProviderButtonConfig(provider);
@@ -710,7 +956,7 @@ function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius
710
956
  transition: "opacity 0.15s",
711
957
  padding: 0
712
958
  };
713
- return /* @__PURE__ */ jsx6(
959
+ return /* @__PURE__ */ jsx7(
714
960
  "button",
715
961
  {
716
962
  type: "button",
@@ -720,33 +966,34 @@ function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius
720
966
  onMouseEnter: () => setHovered(true),
721
967
  onMouseLeave: () => setHovered(false),
722
968
  "aria-label": `Continue with ${name}`,
723
- children: loading ? /* @__PURE__ */ jsx6("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsx6("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
969
+ children: loading ? /* @__PURE__ */ jsx7("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsx7("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
724
970
  }
725
971
  );
726
972
  }
727
973
  function SecuredByAuthon({ primaryStart, textMuted }) {
728
- return /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
729
- /* @__PURE__ */ jsxs4("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
730
- /* @__PURE__ */ jsx6("path", { d: "M6 0L0.5 2.5V6.5C0.5 9.7 2.9 12.7 6 13.5C9.1 12.7 11.5 9.7 11.5 6.5V2.5L6 0Z", fill: primaryStart, opacity: "0.85" }),
731
- /* @__PURE__ */ jsx6("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
974
+ return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
975
+ /* @__PURE__ */ jsxs5("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
976
+ /* @__PURE__ */ jsx7("path", { d: "M6 0L0.5 2.5V6.5C0.5 9.7 2.9 12.7 6 13.5C9.1 12.7 11.5 9.7 11.5 6.5V2.5L6 0Z", fill: primaryStart, opacity: "0.85" }),
977
+ /* @__PURE__ */ jsx7("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
732
978
  ] }),
733
- /* @__PURE__ */ jsxs4("span", { style: { fontSize: 11, color: textMuted }, children: [
979
+ /* @__PURE__ */ jsxs5("span", { style: { fontSize: 11, color: textMuted }, children: [
734
980
  "Secured by",
735
981
  " ",
736
- /* @__PURE__ */ jsx6("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
982
+ /* @__PURE__ */ jsx7("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
737
983
  ] })
738
984
  ] });
739
985
  }
740
- function SignIn({ appearance, afterSignInUrl, onSignIn, onNavigateSignUp }) {
986
+ function SignIn({ appearance, afterSignInUrl, onSignIn, onForgotPassword, onNavigateSignUp }) {
741
987
  const { branding, isLoaded } = useBranding();
742
988
  const effectiveBranding = isLoaded ? { ...branding, ...appearance?.variables ?? {} } : branding;
743
- return /* @__PURE__ */ jsxs4(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
744
- /* @__PURE__ */ jsx6("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
745
- /* @__PURE__ */ jsx6(
989
+ return /* @__PURE__ */ jsxs5(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
990
+ /* @__PURE__ */ jsx7("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
991
+ /* @__PURE__ */ jsx7(
746
992
  SignInCard,
747
993
  {
748
994
  afterSignInUrl,
749
995
  onSignIn,
996
+ onForgotPassword,
750
997
  onNavigateSignUp
751
998
  }
752
999
  )
@@ -754,23 +1001,32 @@ function SignIn({ appearance, afterSignInUrl, onSignIn, onNavigateSignUp }) {
754
1001
  }
755
1002
 
756
1003
  // src/components/SignUp.tsx
757
- import { useState as useState6 } from "react";
1004
+ import { useRef as useRef5, useState as useState7 } from "react";
758
1005
  import { PROVIDER_COLORS as PROVIDER_COLORS2, PROVIDER_DISPLAY_NAMES as PROVIDER_DISPLAY_NAMES2 } from "@authon/shared";
759
1006
  import { getProviderButtonConfig as getProviderButtonConfig2 } from "@authon/js";
760
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1007
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
761
1008
  function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
762
1009
  const theme = useTheme();
763
1010
  const { client } = useAuthon();
764
1011
  const { branding, providers, isLoaded } = useBranding();
765
- const [displayName, setDisplayName] = useState6("");
766
- const [email, setEmail] = useState6("");
767
- const [password, setPassword] = useState6("");
768
- const [confirmPassword, setConfirmPassword] = useState6("");
769
- const [showPassword, setShowPassword] = useState6(false);
770
- const [loading, setLoading] = useState6(false);
771
- const [oauthLoading, setOauthLoading] = useState6(null);
772
- const [error, setError] = useState6("");
773
- const [fieldErrors, setFieldErrors] = useState6({});
1012
+ const [displayName, setDisplayName] = useState7("");
1013
+ const [email, setEmail] = useState7("");
1014
+ const [password, setPassword] = useState7("");
1015
+ const [confirmPassword, setConfirmPassword] = useState7("");
1016
+ const [showPassword, setShowPassword] = useState7(false);
1017
+ const [loading, setLoading] = useState7(false);
1018
+ const [oauthLoading, setOauthLoading] = useState7(null);
1019
+ const [error, setError] = useState7("");
1020
+ const [verificationEmail, setVerificationEmail] = useState7(null);
1021
+ const [fieldErrors, setFieldErrors] = useState7({});
1022
+ const authAttemptPending = useRef5(false);
1023
+ const completed = useRef5(false);
1024
+ const completeSignUp = () => {
1025
+ if (completed.current) return;
1026
+ completed.current = true;
1027
+ if (afterSignUpUrl) navigateTo(afterSignUpUrl);
1028
+ onSignUp?.();
1029
+ };
774
1030
  const validate = () => {
775
1031
  const errs = {};
776
1032
  if (!email.trim()) errs.email = "Email is required";
@@ -782,21 +1038,27 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
782
1038
  return Object.keys(errs).length === 0;
783
1039
  };
784
1040
  const handleSubmit = async () => {
785
- if (!validate() || !client) return;
1041
+ if (authAttemptPending.current || !validate() || !client) return;
1042
+ authAttemptPending.current = true;
786
1043
  setLoading(true);
787
1044
  setError("");
788
1045
  try {
789
- await client.signUpWithEmail(email, password, displayName ? { displayName } : void 0);
790
- if (afterSignUpUrl) window.location.assign(afterSignUpUrl);
791
- onSignUp?.();
792
- } catch (e) {
793
- setError(e?.message ?? "Sign up failed");
1046
+ const result = await client.signUpWithEmail(email, password, displayName ? { displayName } : void 0);
1047
+ if ("needsVerification" in result && result.needsVerification) {
1048
+ setVerificationEmail(result.email);
1049
+ return;
1050
+ }
1051
+ completeSignUp();
1052
+ } catch (submitError) {
1053
+ setError(submitError instanceof Error && submitError.message ? submitError.message : "Sign up failed");
794
1054
  } finally {
1055
+ authAttemptPending.current = false;
795
1056
  setLoading(false);
796
1057
  }
797
1058
  };
798
1059
  const handleOAuth = async (provider) => {
799
- if (!client) return;
1060
+ if (!client || authAttemptPending.current) return;
1061
+ authAttemptPending.current = true;
800
1062
  setOauthLoading(provider);
801
1063
  setError("");
802
1064
  try {
@@ -804,6 +1066,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
804
1066
  } catch (e) {
805
1067
  setError(e?.message ?? "OAuth sign in failed");
806
1068
  } finally {
1069
+ authAttemptPending.current = false;
807
1070
  setOauthLoading(null);
808
1071
  }
809
1072
  };
@@ -869,7 +1132,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
869
1132
  (p) => !(branding.hiddenProviders ?? []).includes(p)
870
1133
  );
871
1134
  if (!isLoaded) {
872
- return /* @__PURE__ */ jsx7("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx7(
1135
+ return /* @__PURE__ */ jsx8("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx8(
873
1136
  "span",
874
1137
  {
875
1138
  style: {
@@ -884,18 +1147,40 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
884
1147
  }
885
1148
  ) });
886
1149
  }
1150
+ if (verificationEmail) {
1151
+ return /* @__PURE__ */ jsx8("div", { style: cardStyle, children: /* @__PURE__ */ jsx8(
1152
+ VerificationForm,
1153
+ {
1154
+ email: verificationEmail,
1155
+ backLabel: "Back to sign up",
1156
+ onVerify: async (code) => {
1157
+ if (!client) throw new Error("Sign up is unavailable");
1158
+ await client.verifyEmail(verificationEmail, code);
1159
+ completeSignUp();
1160
+ },
1161
+ onResend: async () => {
1162
+ if (!client) throw new Error("Sign up is unavailable");
1163
+ await client.resendVerificationCode(verificationEmail);
1164
+ },
1165
+ onBack: () => {
1166
+ setError("");
1167
+ setVerificationEmail(null);
1168
+ }
1169
+ }
1170
+ ) });
1171
+ }
887
1172
  const eyeIconPath = showPassword ? "M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24 M1 1l22 22" : "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z M12 9a3 3 0 100 6 3 3 0 000-6z";
888
- return /* @__PURE__ */ jsxs5("div", { style: cardStyle, children: [
889
- /* @__PURE__ */ jsxs5("div", { style: logoStyle, children: [
890
- branding.logoDataUrl && /* @__PURE__ */ jsx7("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
891
- /* @__PURE__ */ jsx7("h1", { style: titleStyle, children: "Create account" }),
892
- branding.brandName && /* @__PURE__ */ jsxs5("p", { style: subtitleStyle, children: [
1173
+ return /* @__PURE__ */ jsxs6("div", { style: cardStyle, children: [
1174
+ /* @__PURE__ */ jsxs6("div", { style: logoStyle, children: [
1175
+ branding.logoDataUrl && /* @__PURE__ */ jsx8("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
1176
+ /* @__PURE__ */ jsx8("h1", { style: titleStyle, children: "Create account" }),
1177
+ branding.brandName && /* @__PURE__ */ jsxs6("p", { style: subtitleStyle, children: [
893
1178
  "Join ",
894
1179
  branding.brandName
895
1180
  ] })
896
1181
  ] }),
897
- error && /* @__PURE__ */ jsx7("div", { style: errorBoxStyle, children: error }),
898
- providersToShow.length > 0 && /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ jsx7(
1182
+ error && /* @__PURE__ */ jsx8("div", { role: "alert", style: errorBoxStyle, children: error }),
1183
+ providersToShow.length > 0 && /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ jsx8(
899
1184
  OAuthButtonFull,
900
1185
  {
901
1186
  provider,
@@ -905,7 +1190,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
905
1190
  borderRadius: theme.borderRadius
906
1191
  },
907
1192
  provider
908
- )) : /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ jsx7(
1193
+ )) : /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ jsx8(
909
1194
  CompactOAuthBtn,
910
1195
  {
911
1196
  provider,
@@ -916,9 +1201,9 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
916
1201
  },
917
1202
  provider
918
1203
  )) }) }),
919
- showDivider && /* @__PURE__ */ jsx7(Divider, {}),
920
- showEmailPw && /* @__PURE__ */ jsxs5(Fragment3, { children: [
921
- /* @__PURE__ */ jsx7(
1204
+ showDivider && /* @__PURE__ */ jsx8(Divider, {}),
1205
+ showEmailPw && /* @__PURE__ */ jsxs6(Fragment4, { children: [
1206
+ /* @__PURE__ */ jsx8(
922
1207
  Input,
923
1208
  {
924
1209
  label: "Display name",
@@ -930,7 +1215,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
930
1215
  autoComplete: "name"
931
1216
  }
932
1217
  ),
933
- /* @__PURE__ */ jsx7(
1218
+ /* @__PURE__ */ jsx8(
934
1219
  Input,
935
1220
  {
936
1221
  label: "Email",
@@ -942,7 +1227,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
942
1227
  autoComplete: "email"
943
1228
  }
944
1229
  ),
945
- /* @__PURE__ */ jsx7(
1230
+ /* @__PURE__ */ jsx8(
946
1231
  Input,
947
1232
  {
948
1233
  label: "Password",
@@ -952,19 +1237,19 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
952
1237
  onChange: setPassword,
953
1238
  error: fieldErrors.password,
954
1239
  autoComplete: "new-password",
955
- rightElement: /* @__PURE__ */ jsx7(
1240
+ rightElement: /* @__PURE__ */ jsx8(
956
1241
  "button",
957
1242
  {
958
1243
  type: "button",
959
1244
  onClick: () => setShowPassword((v) => !v),
960
1245
  style: { background: "none", border: "none", cursor: "pointer", padding: 0, display: "flex", color: theme.textMuted },
961
1246
  "aria-label": showPassword ? "Hide password" : "Show password",
962
- children: /* @__PURE__ */ jsx7("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: eyeIconPath }) })
1247
+ children: /* @__PURE__ */ jsx8("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: eyeIconPath }) })
963
1248
  }
964
1249
  )
965
1250
  }
966
1251
  ),
967
- /* @__PURE__ */ jsx7(
1252
+ /* @__PURE__ */ jsx8(
968
1253
  Input,
969
1254
  {
970
1255
  label: "Confirm password",
@@ -976,7 +1261,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
976
1261
  autoComplete: "new-password"
977
1262
  }
978
1263
  ),
979
- /* @__PURE__ */ jsx7(
1264
+ /* @__PURE__ */ jsx8(
980
1265
  Button,
981
1266
  {
982
1267
  variant: "primary",
@@ -988,23 +1273,23 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
988
1273
  }
989
1274
  )
990
1275
  ] }),
991
- /* @__PURE__ */ jsxs5("div", { style: footerStyle, children: [
1276
+ /* @__PURE__ */ jsxs6("div", { style: footerStyle, children: [
992
1277
  "Already have an account?",
993
1278
  " ",
994
- /* @__PURE__ */ jsx7("button", { type: "button", style: linkStyle, onClick: onNavigateSignIn, children: "Sign in" })
1279
+ /* @__PURE__ */ jsx8("button", { type: "button", style: linkStyle, onClick: onNavigateSignIn, children: "Sign in" })
995
1280
  ] }),
996
- branding.showSecuredBy !== false && /* @__PURE__ */ jsx7(SecuredByAuthon2, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
997
- branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ jsxs5("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
1281
+ branding.showSecuredBy !== false && /* @__PURE__ */ jsx8(SecuredByAuthon2, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
1282
+ branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ jsxs6("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
998
1283
  "By creating an account you agree to our",
999
1284
  " ",
1000
- branding.termsUrl && /* @__PURE__ */ jsx7("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Terms" }),
1285
+ branding.termsUrl && /* @__PURE__ */ jsx8("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Terms" }),
1001
1286
  branding.termsUrl && branding.privacyUrl && " and ",
1002
- branding.privacyUrl && /* @__PURE__ */ jsx7("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Privacy Policy" })
1287
+ branding.privacyUrl && /* @__PURE__ */ jsx8("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Privacy Policy" })
1003
1288
  ] }) : null
1004
1289
  ] });
1005
1290
  }
1006
1291
  function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius }) {
1007
- const [hovered, setHovered] = useState6(false);
1292
+ const [hovered, setHovered] = useState7(false);
1008
1293
  const colors = PROVIDER_COLORS2[provider] ?? { bg: "#333", text: "#fff" };
1009
1294
  const name = PROVIDER_DISPLAY_NAMES2[provider] ?? provider;
1010
1295
  const config = getProviderButtonConfig2(provider);
@@ -1030,7 +1315,7 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
1030
1315
  transition: "opacity 0.15s",
1031
1316
  boxSizing: "border-box"
1032
1317
  };
1033
- return /* @__PURE__ */ jsx7(
1318
+ return /* @__PURE__ */ jsx8(
1034
1319
  "button",
1035
1320
  {
1036
1321
  type: "button",
@@ -1040,9 +1325,9 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
1040
1325
  onMouseEnter: () => setHovered(true),
1041
1326
  onMouseLeave: () => setHovered(false),
1042
1327
  "aria-label": `Continue with ${name}`,
1043
- children: loading ? /* @__PURE__ */ jsx7("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
1044
- /* @__PURE__ */ jsx7("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
1045
- /* @__PURE__ */ jsxs5("span", { children: [
1328
+ children: loading ? /* @__PURE__ */ jsx8("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
1329
+ /* @__PURE__ */ jsx8("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
1330
+ /* @__PURE__ */ jsxs6("span", { children: [
1046
1331
  "Continue with ",
1047
1332
  name
1048
1333
  ] })
@@ -1051,7 +1336,7 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
1051
1336
  );
1052
1337
  }
1053
1338
  function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius }) {
1054
- const [hovered, setHovered] = useState6(false);
1339
+ const [hovered, setHovered] = useState7(false);
1055
1340
  const colors = PROVIDER_COLORS2[provider] ?? { bg: "#333", text: "#fff" };
1056
1341
  const name = PROVIDER_DISPLAY_NAMES2[provider] ?? provider;
1057
1342
  const config = getProviderButtonConfig2(provider);
@@ -1070,7 +1355,7 @@ function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius })
1070
1355
  transition: "opacity 0.15s",
1071
1356
  padding: 0
1072
1357
  };
1073
- return /* @__PURE__ */ jsx7(
1358
+ return /* @__PURE__ */ jsx8(
1074
1359
  "button",
1075
1360
  {
1076
1361
  type: "button",
@@ -1080,29 +1365,29 @@ function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius })
1080
1365
  onMouseEnter: () => setHovered(true),
1081
1366
  onMouseLeave: () => setHovered(false),
1082
1367
  "aria-label": `Continue with ${name}`,
1083
- children: loading ? /* @__PURE__ */ jsx7("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsx7("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
1368
+ children: loading ? /* @__PURE__ */ jsx8("span", { style: { width: 18, height: 18, border: `2px solid ${colors.text}`, borderTopColor: "transparent", borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.6s linear infinite" } }) : /* @__PURE__ */ jsx8("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
1084
1369
  }
1085
1370
  );
1086
1371
  }
1087
1372
  function SecuredByAuthon2({ primaryStart, textMuted }) {
1088
- return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
1089
- /* @__PURE__ */ jsxs5("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
1090
- /* @__PURE__ */ jsx7("path", { d: "M6 0L0.5 2.5V6.5C0.5 9.7 2.9 12.7 6 13.5C9.1 12.7 11.5 9.7 11.5 6.5V2.5L6 0Z", fill: primaryStart, opacity: "0.85" }),
1091
- /* @__PURE__ */ jsx7("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
1373
+ return /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
1374
+ /* @__PURE__ */ jsxs6("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
1375
+ /* @__PURE__ */ jsx8("path", { d: "M6 0L0.5 2.5V6.5C0.5 9.7 2.9 12.7 6 13.5C9.1 12.7 11.5 9.7 11.5 6.5V2.5L6 0Z", fill: primaryStart, opacity: "0.85" }),
1376
+ /* @__PURE__ */ jsx8("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
1092
1377
  ] }),
1093
- /* @__PURE__ */ jsxs5("span", { style: { fontSize: 11, color: textMuted }, children: [
1378
+ /* @__PURE__ */ jsxs6("span", { style: { fontSize: 11, color: textMuted }, children: [
1094
1379
  "Secured by",
1095
1380
  " ",
1096
- /* @__PURE__ */ jsx7("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
1381
+ /* @__PURE__ */ jsx8("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
1097
1382
  ] })
1098
1383
  ] });
1099
1384
  }
1100
1385
  function SignUp({ appearance, afterSignUpUrl, onSignUp, onNavigateSignIn }) {
1101
1386
  const { branding, isLoaded } = useBranding();
1102
1387
  const effectiveBranding = isLoaded ? { ...branding, ...appearance?.variables ?? {} } : branding;
1103
- return /* @__PURE__ */ jsxs5(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
1104
- /* @__PURE__ */ jsx7("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
1105
- /* @__PURE__ */ jsx7(
1388
+ return /* @__PURE__ */ jsxs6(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
1389
+ /* @__PURE__ */ jsx8("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
1390
+ /* @__PURE__ */ jsx8(
1106
1391
  SignUpCard,
1107
1392
  {
1108
1393
  afterSignUpUrl,
@@ -1114,8 +1399,8 @@ function SignUp({ appearance, afterSignUpUrl, onSignUp, onNavigateSignIn }) {
1114
1399
  }
1115
1400
 
1116
1401
  // src/components/UserButton.tsx
1117
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState7 } from "react";
1118
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1402
+ import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef6, useState as useState8 } from "react";
1403
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1119
1404
  function UserAvatar({
1120
1405
  avatarUrl,
1121
1406
  displayName,
@@ -1139,13 +1424,13 @@ function UserAvatar({
1139
1424
  fontWeight: 700,
1140
1425
  userSelect: "none"
1141
1426
  };
1142
- return /* @__PURE__ */ jsx8("div", { style: avatarStyle, children: avatarUrl ? /* @__PURE__ */ jsx8("img", { src: avatarUrl, alt: displayName ?? "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials });
1427
+ return /* @__PURE__ */ jsx9("div", { style: avatarStyle, children: avatarUrl ? /* @__PURE__ */ jsx9("img", { src: avatarUrl, alt: displayName ?? "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials });
1143
1428
  }
1144
1429
  function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1145
1430
  const theme = useTheme();
1146
1431
  const { user, signOut, openSignIn, isSignedIn, activeOrganization, client } = useAuthon();
1147
- const [open, setOpen] = useState7(false);
1148
- const dropdownRef = useRef3(null);
1432
+ const [open, setOpen] = useState8(false);
1433
+ const dropdownRef = useRef6(null);
1149
1434
  const handleClickOutside = useCallback3((e) => {
1150
1435
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
1151
1436
  setOpen(false);
@@ -1156,7 +1441,7 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1156
1441
  return () => document.removeEventListener("mousedown", handleClickOutside);
1157
1442
  }, [open, handleClickOutside]);
1158
1443
  if (!isSignedIn) {
1159
- return /* @__PURE__ */ jsx8(
1444
+ return /* @__PURE__ */ jsx9(
1160
1445
  "button",
1161
1446
  {
1162
1447
  type: "button",
@@ -1225,8 +1510,8 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1225
1510
  fontFamily: theme.fontFamily,
1226
1511
  boxSizing: "border-box"
1227
1512
  });
1228
- return /* @__PURE__ */ jsxs6("div", { ref: dropdownRef, style: { position: "relative", display: "inline-block" }, children: [
1229
- /* @__PURE__ */ jsx8("button", { type: "button", style: triggerStyle, onClick: () => setOpen((v) => !v), "aria-label": "User menu", children: /* @__PURE__ */ jsx8(
1513
+ return /* @__PURE__ */ jsxs7("div", { ref: dropdownRef, style: { position: "relative", display: "inline-block" }, children: [
1514
+ /* @__PURE__ */ jsx9("button", { type: "button", style: triggerStyle, onClick: () => setOpen((v) => !v), "aria-label": "User menu", children: /* @__PURE__ */ jsx9(
1230
1515
  UserAvatar,
1231
1516
  {
1232
1517
  avatarUrl: user?.avatarUrl,
@@ -1237,9 +1522,9 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1237
1522
  primaryEnd: theme.primaryEnd
1238
1523
  }
1239
1524
  ) }),
1240
- open && /* @__PURE__ */ jsxs6("div", { style: dropdownStyle, children: [
1241
- /* @__PURE__ */ jsxs6("div", { style: headerStyle, children: [
1242
- /* @__PURE__ */ jsx8(
1525
+ open && /* @__PURE__ */ jsxs7("div", { style: dropdownStyle, children: [
1526
+ /* @__PURE__ */ jsxs7("div", { style: headerStyle, children: [
1527
+ /* @__PURE__ */ jsx9(
1243
1528
  UserAvatar,
1244
1529
  {
1245
1530
  avatarUrl: user?.avatarUrl,
@@ -1250,12 +1535,12 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1250
1535
  primaryEnd: theme.primaryEnd
1251
1536
  }
1252
1537
  ),
1253
- /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0 }, children: [
1254
- user?.displayName && /* @__PURE__ */ jsx8("div", { style: { fontSize: 14, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: user.displayName }),
1255
- user?.email && /* @__PURE__ */ jsx8("div", { style: { fontSize: 12, color: theme.textMuted, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 1 }, children: user.email })
1538
+ /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
1539
+ user?.displayName && /* @__PURE__ */ jsx9("div", { style: { fontSize: 14, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: user.displayName }),
1540
+ user?.email && /* @__PURE__ */ jsx9("div", { style: { fontSize: 12, color: theme.textMuted, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 1 }, children: user.email })
1256
1541
  ] })
1257
1542
  ] }),
1258
- activeOrganization && /* @__PURE__ */ jsx8(
1543
+ activeOrganization && /* @__PURE__ */ jsx9(
1259
1544
  OrgSwitcherRow,
1260
1545
  {
1261
1546
  org: activeOrganization,
@@ -1264,7 +1549,7 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1264
1549
  client
1265
1550
  }
1266
1551
  ),
1267
- userProfileUrl && /* @__PURE__ */ jsx8(
1552
+ userProfileUrl && /* @__PURE__ */ jsx9(
1268
1553
  MenuButton,
1269
1554
  {
1270
1555
  style: menuItemStyle(),
@@ -1272,14 +1557,14 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1272
1557
  setOpen(false);
1273
1558
  window.location.assign(userProfileUrl);
1274
1559
  },
1275
- icon: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1276
- /* @__PURE__ */ jsx8("path", { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" }),
1277
- /* @__PURE__ */ jsx8("circle", { cx: "12", cy: "7", r: "4" })
1560
+ icon: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1561
+ /* @__PURE__ */ jsx9("path", { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" }),
1562
+ /* @__PURE__ */ jsx9("circle", { cx: "12", cy: "7", r: "4" })
1278
1563
  ] }),
1279
1564
  children: "Manage account"
1280
1565
  }
1281
1566
  ),
1282
- /* @__PURE__ */ jsx8("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ jsx8(
1567
+ /* @__PURE__ */ jsx9("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ jsx9(
1283
1568
  MenuButton,
1284
1569
  {
1285
1570
  style: menuItemStyle(true),
@@ -1288,10 +1573,10 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
1288
1573
  await signOut();
1289
1574
  if (afterSignOutUrl) window.location.assign(afterSignOutUrl);
1290
1575
  },
1291
- icon: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1292
- /* @__PURE__ */ jsx8("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4" }),
1293
- /* @__PURE__ */ jsx8("polyline", { points: "16 17 21 12 16 7" }),
1294
- /* @__PURE__ */ jsx8("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
1576
+ icon: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1577
+ /* @__PURE__ */ jsx9("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4" }),
1578
+ /* @__PURE__ */ jsx9("polyline", { points: "16 17 21 12 16 7" }),
1579
+ /* @__PURE__ */ jsx9("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
1295
1580
  ] }),
1296
1581
  children: "Sign out"
1297
1582
  }
@@ -1305,8 +1590,8 @@ function MenuButton({
1305
1590
  icon,
1306
1591
  children
1307
1592
  }) {
1308
- const [hovered, setHovered] = useState7(false);
1309
- return /* @__PURE__ */ jsxs6(
1593
+ const [hovered, setHovered] = useState8(false);
1594
+ return /* @__PURE__ */ jsxs7(
1310
1595
  "button",
1311
1596
  {
1312
1597
  type: "button",
@@ -1330,7 +1615,7 @@ function OrgSwitcherRow({
1330
1615
  theme,
1331
1616
  client
1332
1617
  }) {
1333
- return /* @__PURE__ */ jsxs6(
1618
+ return /* @__PURE__ */ jsxs7(
1334
1619
  "div",
1335
1620
  {
1336
1621
  style: {
@@ -1341,7 +1626,7 @@ function OrgSwitcherRow({
1341
1626
  gap: 10
1342
1627
  },
1343
1628
  children: [
1344
- org.logoUrl ? /* @__PURE__ */ jsx8("img", { src: org.logoUrl, alt: org.name, style: { width: 24, height: 24, borderRadius: 6, objectFit: "cover" } }) : /* @__PURE__ */ jsx8(
1629
+ org.logoUrl ? /* @__PURE__ */ jsx9("img", { src: org.logoUrl, alt: org.name, style: { width: 24, height: 24, borderRadius: 6, objectFit: "cover" } }) : /* @__PURE__ */ jsx9(
1345
1630
  "div",
1346
1631
  {
1347
1632
  style: {
@@ -1359,9 +1644,9 @@ function OrgSwitcherRow({
1359
1644
  children: org.name[0]?.toUpperCase()
1360
1645
  }
1361
1646
  ),
1362
- /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0 }, children: [
1363
- /* @__PURE__ */ jsx8("div", { style: { fontSize: 12, color: theme.textMuted }, children: "Organization" }),
1364
- /* @__PURE__ */ jsx8("div", { style: { fontSize: 13, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: org.name })
1647
+ /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
1648
+ /* @__PURE__ */ jsx9("div", { style: { fontSize: 12, color: theme.textMuted }, children: "Organization" }),
1649
+ /* @__PURE__ */ jsx9("div", { style: { fontSize: 13, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: org.name })
1365
1650
  ] })
1366
1651
  ]
1367
1652
  }
@@ -1370,39 +1655,39 @@ function OrgSwitcherRow({
1370
1655
  function UserButton({ appearance, afterSignOutUrl, userProfileUrl }) {
1371
1656
  const { branding } = useBranding();
1372
1657
  const effectiveBranding = { ...branding, ...appearance?.variables ?? {} };
1373
- return /* @__PURE__ */ jsx8(ThemeProvider, { branding: effectiveBranding, style: { display: "inline-block" }, children: /* @__PURE__ */ jsx8(UserButtonInner, { afterSignOutUrl, userProfileUrl }) });
1658
+ return /* @__PURE__ */ jsx9(ThemeProvider, { branding: effectiveBranding, style: { display: "inline-block" }, children: /* @__PURE__ */ jsx9(UserButtonInner, { afterSignOutUrl, userProfileUrl }) });
1374
1659
  }
1375
1660
 
1376
1661
  // src/SignedIn.tsx
1377
- import { Fragment as Fragment4, jsx as jsx9 } from "react/jsx-runtime";
1662
+ import { Fragment as Fragment5, jsx as jsx10 } from "react/jsx-runtime";
1378
1663
  function SignedIn({ children }) {
1379
1664
  const { isSignedIn, isLoading } = useAuthon();
1380
1665
  if (isLoading || !isSignedIn) return null;
1381
- return /* @__PURE__ */ jsx9(Fragment4, { children });
1666
+ return /* @__PURE__ */ jsx10(Fragment5, { children });
1382
1667
  }
1383
1668
 
1384
1669
  // src/SignedOut.tsx
1385
- import { Fragment as Fragment5, jsx as jsx10 } from "react/jsx-runtime";
1670
+ import { Fragment as Fragment6, jsx as jsx11 } from "react/jsx-runtime";
1386
1671
  function SignedOut({ children }) {
1387
1672
  const { isSignedIn, isLoading } = useAuthon();
1388
1673
  if (isLoading || isSignedIn) return null;
1389
- return /* @__PURE__ */ jsx10(Fragment5, { children });
1674
+ return /* @__PURE__ */ jsx11(Fragment6, { children });
1390
1675
  }
1391
1676
 
1392
1677
  // src/Protect.tsx
1393
- import { Fragment as Fragment6, jsx as jsx11 } from "react/jsx-runtime";
1678
+ import { Fragment as Fragment7, jsx as jsx12 } from "react/jsx-runtime";
1394
1679
  function Protect({ children, fallback = null, condition }) {
1395
1680
  const { isSignedIn, isLoading, user } = useAuthon();
1396
1681
  if (isLoading) return null;
1397
- if (!isSignedIn || !user) return /* @__PURE__ */ jsx11(Fragment6, { children: fallback });
1398
- if (condition && !condition(user)) return /* @__PURE__ */ jsx11(Fragment6, { children: fallback });
1399
- return /* @__PURE__ */ jsx11(Fragment6, { children });
1682
+ if (!isSignedIn || !user) return /* @__PURE__ */ jsx12(Fragment7, { children: fallback });
1683
+ if (condition && !condition(user)) return /* @__PURE__ */ jsx12(Fragment7, { children: fallback });
1684
+ return /* @__PURE__ */ jsx12(Fragment7, { children });
1400
1685
  }
1401
1686
 
1402
1687
  // src/SocialButton.tsx
1403
1688
  import { PROVIDER_COLORS as PROVIDER_COLORS3, PROVIDER_DISPLAY_NAMES as PROVIDER_DISPLAY_NAMES3 } from "@authon/shared";
1404
1689
  import { getProviderButtonConfig as getProviderButtonConfig3 } from "@authon/js";
1405
- import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1690
+ import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1406
1691
  var baseStyle = {
1407
1692
  display: "flex",
1408
1693
  alignItems: "center",
@@ -1448,7 +1733,7 @@ function SocialButton({
1448
1733
  const iconSvg = config.iconSvg.replace(/width="\d+"/, `width="${resolvedIconSize}"`).replace(/height="\d+"/, `height="${resolvedIconSize}"`);
1449
1734
  const borderProps = needsBorder ? { border: "1px solid #dadce0" } : {};
1450
1735
  if (compact) {
1451
- return /* @__PURE__ */ jsx12(
1736
+ return /* @__PURE__ */ jsx13(
1452
1737
  "button",
1453
1738
  {
1454
1739
  className,
@@ -1464,7 +1749,7 @@ function SocialButton({
1464
1749
  onClick: () => onClick(provider),
1465
1750
  disabled: disabled || loading,
1466
1751
  "aria-label": `Sign in with ${displayName}`,
1467
- children: loading ? /* @__PURE__ */ jsx12(
1752
+ children: loading ? /* @__PURE__ */ jsx13(
1468
1753
  "span",
1469
1754
  {
1470
1755
  style: {
@@ -1477,7 +1762,7 @@ function SocialButton({
1477
1762
  animation: "authon-spin 0.6s linear infinite"
1478
1763
  }
1479
1764
  }
1480
- ) : /* @__PURE__ */ jsx12(
1765
+ ) : /* @__PURE__ */ jsx13(
1481
1766
  "span",
1482
1767
  {
1483
1768
  style: { display: "flex", alignItems: "center", flexShrink: 0 },
@@ -1487,7 +1772,7 @@ function SocialButton({
1487
1772
  }
1488
1773
  );
1489
1774
  }
1490
- return /* @__PURE__ */ jsx12(
1775
+ return /* @__PURE__ */ jsx13(
1491
1776
  "button",
1492
1777
  {
1493
1778
  className,
@@ -1503,7 +1788,7 @@ function SocialButton({
1503
1788
  onClick: () => onClick(provider),
1504
1789
  disabled: disabled || loading,
1505
1790
  "aria-label": `Sign in with ${displayName}`,
1506
- children: loading ? /* @__PURE__ */ jsx12(
1791
+ children: loading ? /* @__PURE__ */ jsx13(
1507
1792
  "span",
1508
1793
  {
1509
1794
  style: {
@@ -1516,23 +1801,23 @@ function SocialButton({
1516
1801
  animation: "authon-spin 0.6s linear infinite"
1517
1802
  }
1518
1803
  }
1519
- ) : /* @__PURE__ */ jsxs7(Fragment7, { children: [
1520
- /* @__PURE__ */ jsx12(
1804
+ ) : /* @__PURE__ */ jsxs8(Fragment8, { children: [
1805
+ /* @__PURE__ */ jsx13(
1521
1806
  "span",
1522
1807
  {
1523
1808
  style: { display: "flex", alignItems: "center", flexShrink: 0 },
1524
1809
  dangerouslySetInnerHTML: { __html: iconSvg }
1525
1810
  }
1526
1811
  ),
1527
- /* @__PURE__ */ jsx12("span", { style: { fontSize: 15, fontWeight: 600, whiteSpace: "nowrap" }, children: buttonLabel })
1812
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 15, fontWeight: 600, whiteSpace: "nowrap" }, children: buttonLabel })
1528
1813
  ] })
1529
1814
  }
1530
1815
  );
1531
1816
  }
1532
1817
 
1533
1818
  // src/SocialButtons.tsx
1534
- import { useState as useState8, useEffect as useEffect4 } from "react";
1535
- import { jsx as jsx13 } from "react/jsx-runtime";
1819
+ import { useState as useState9, useEffect as useEffect4 } from "react";
1820
+ import { jsx as jsx14 } from "react/jsx-runtime";
1536
1821
  function SocialButtons({
1537
1822
  onSuccess,
1538
1823
  onError,
@@ -1544,8 +1829,8 @@ function SocialButtons({
1544
1829
  buttonProps
1545
1830
  }) {
1546
1831
  const { client } = useAuthon();
1547
- const [providers, setProviders] = useState8([]);
1548
- const [loadingProvider, setLoadingProvider] = useState8(null);
1832
+ const [providers, setProviders] = useState9([]);
1833
+ const [loadingProvider, setLoadingProvider] = useState9(null);
1549
1834
  useEffect4(() => {
1550
1835
  if (!client) return;
1551
1836
  client.getProviders().then((p) => setProviders(p));
@@ -1566,7 +1851,7 @@ function SocialButtons({
1566
1851
  }
1567
1852
  };
1568
1853
  const containerStyle = compact ? { display: "flex", flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: resolvedGap, ...userStyle } : { display: "flex", flexDirection: "column", gap: resolvedGap, ...userStyle };
1569
- return /* @__PURE__ */ jsx13("div", { className, style: containerStyle, children: providers.map((provider) => /* @__PURE__ */ jsx13(
1854
+ return /* @__PURE__ */ jsx14("div", { className, style: containerStyle, children: providers.map((provider) => /* @__PURE__ */ jsx14(
1570
1855
  SocialButton,
1571
1856
  {
1572
1857
  provider,
@@ -1582,12 +1867,12 @@ function SocialButtons({
1582
1867
  }
1583
1868
 
1584
1869
  // src/useAuthonMfa.ts
1585
- import { useCallback as useCallback4, useContext as useContext3, useState as useState9 } from "react";
1870
+ import { useCallback as useCallback4, useContext as useContext3, useState as useState10 } from "react";
1586
1871
  function useAuthonMfa() {
1587
1872
  const ctx = useContext3(AuthonContext);
1588
1873
  if (!ctx) throw new Error("useAuthonMfa must be used within <AuthonProvider>");
1589
- const [isLoading, setIsLoading] = useState9(false);
1590
- const [error, setError] = useState9(null);
1874
+ const [isLoading, setIsLoading] = useState10(false);
1875
+ const [error, setError] = useState10(null);
1591
1876
  const wrap = useCallback4(
1592
1877
  async (fn) => {
1593
1878
  setIsLoading(true);
@@ -1650,12 +1935,12 @@ function useAuthonMfa() {
1650
1935
  }
1651
1936
 
1652
1937
  // src/useAuthonPasskeys.ts
1653
- import { useCallback as useCallback5, useContext as useContext4, useState as useState10 } from "react";
1938
+ import { useCallback as useCallback5, useContext as useContext4, useState as useState11 } from "react";
1654
1939
  function useAuthonPasskeys() {
1655
1940
  const ctx = useContext4(AuthonContext);
1656
1941
  if (!ctx) throw new Error("useAuthonPasskeys must be used within <AuthonProvider>");
1657
- const [isLoading, setIsLoading] = useState10(false);
1658
- const [error, setError] = useState10(null);
1942
+ const [isLoading, setIsLoading] = useState11(false);
1943
+ const [error, setError] = useState11(null);
1659
1944
  const wrap = useCallback5(
1660
1945
  async (fn) => {
1661
1946
  setIsLoading(true);
@@ -1709,12 +1994,12 @@ function useAuthonPasskeys() {
1709
1994
  }
1710
1995
 
1711
1996
  // src/useAuthonPasswordless.ts
1712
- import { useCallback as useCallback6, useContext as useContext5, useState as useState11 } from "react";
1997
+ import { useCallback as useCallback6, useContext as useContext5, useState as useState12 } from "react";
1713
1998
  function useAuthonPasswordless() {
1714
1999
  const ctx = useContext5(AuthonContext);
1715
2000
  if (!ctx) throw new Error("useAuthonPasswordless must be used within <AuthonProvider>");
1716
- const [isLoading, setIsLoading] = useState11(false);
1717
- const [error, setError] = useState11(null);
2001
+ const [isLoading, setIsLoading] = useState12(false);
2002
+ const [error, setError] = useState12(null);
1718
2003
  const wrap = useCallback6(
1719
2004
  async (fn) => {
1720
2005
  setIsLoading(true);
@@ -1761,12 +2046,12 @@ function useAuthonPasswordless() {
1761
2046
  }
1762
2047
 
1763
2048
  // src/useAuthonWeb3.ts
1764
- import { useCallback as useCallback7, useContext as useContext6, useState as useState12 } from "react";
2049
+ import { useCallback as useCallback7, useContext as useContext6, useState as useState13 } from "react";
1765
2050
  function useAuthonWeb3() {
1766
2051
  const ctx = useContext6(AuthonContext);
1767
2052
  if (!ctx) throw new Error("useAuthonWeb3 must be used within <AuthonProvider>");
1768
- const [isLoading, setIsLoading] = useState12(false);
1769
- const [error, setError] = useState12(null);
2053
+ const [isLoading, setIsLoading] = useState13(false);
2054
+ const [error, setError] = useState13(null);
1770
2055
  const wrap = useCallback7(
1771
2056
  async (fn) => {
1772
2057
  setIsLoading(true);
@@ -1822,12 +2107,12 @@ function useAuthonWeb3() {
1822
2107
  }
1823
2108
 
1824
2109
  // src/useAuthonSessions.ts
1825
- import { useCallback as useCallback8, useContext as useContext7, useState as useState13 } from "react";
2110
+ import { useCallback as useCallback8, useContext as useContext7, useState as useState14 } from "react";
1826
2111
  function useAuthonSessions() {
1827
2112
  const ctx = useContext7(AuthonContext);
1828
2113
  if (!ctx) throw new Error("useAuthonSessions must be used within <AuthonProvider>");
1829
- const [isLoading, setIsLoading] = useState13(false);
1830
- const [error, setError] = useState13(null);
2114
+ const [isLoading, setIsLoading] = useState14(false);
2115
+ const [error, setError] = useState14(null);
1831
2116
  const wrap = useCallback8(
1832
2117
  async (fn) => {
1833
2118
  setIsLoading(true);
@@ -1863,12 +2148,12 @@ function useAuthonSessions() {
1863
2148
  }
1864
2149
 
1865
2150
  // src/useOrganization.ts
1866
- import { useContext as useContext8, useEffect as useEffect5, useState as useState14 } from "react";
2151
+ import { useContext as useContext8, useEffect as useEffect5, useState as useState15 } from "react";
1867
2152
  function useOrganization() {
1868
2153
  const ctx = useContext8(AuthonContext);
1869
2154
  if (!ctx) throw new Error("useOrganization must be used within <AuthonProvider>");
1870
- const [members, setMembers] = useState14([]);
1871
- const [isLoaded, setIsLoaded] = useState14(false);
2155
+ const [members, setMembers] = useState15([]);
2156
+ const [isLoaded, setIsLoaded] = useState15(false);
1872
2157
  const organization = ctx.activeOrganization;
1873
2158
  useEffect5(() => {
1874
2159
  if (!organization || !ctx.client) {
@@ -1893,12 +2178,12 @@ function useOrganization() {
1893
2178
  }
1894
2179
 
1895
2180
  // src/useOrganizationList.ts
1896
- import { useCallback as useCallback10, useContext as useContext9, useEffect as useEffect6, useState as useState15 } from "react";
2181
+ import { useCallback as useCallback10, useContext as useContext9, useEffect as useEffect6, useState as useState16 } from "react";
1897
2182
  function useOrganizationList() {
1898
2183
  const ctx = useContext9(AuthonContext);
1899
2184
  if (!ctx) throw new Error("useOrganizationList must be used within <AuthonProvider>");
1900
- const [organizations, setOrganizations] = useState15([]);
1901
- const [isLoaded, setIsLoaded] = useState15(false);
2185
+ const [organizations, setOrganizations] = useState16([]);
2186
+ const [isLoaded, setIsLoaded] = useState16(false);
1902
2187
  useEffect6(() => {
1903
2188
  if (!ctx.client || !ctx.isSignedIn) {
1904
2189
  setOrganizations([]);
@@ -1942,16 +2227,16 @@ function useOrganizationList() {
1942
2227
  }
1943
2228
 
1944
2229
  // src/components/UserProfile.tsx
1945
- import { useCallback as useCallback11, useEffect as useEffect7, useState as useState16 } from "react";
1946
- import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
2230
+ import { useCallback as useCallback11, useEffect as useEffect7, useState as useState17 } from "react";
2231
+ import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1947
2232
  function ProfileTab() {
1948
2233
  const theme = useTheme();
1949
2234
  const { user, client } = useAuthon();
1950
- const [displayName, setDisplayName] = useState16(user?.displayName ?? "");
1951
- const [phone, setPhone] = useState16(user?.phone ?? "");
1952
- const [loading, setLoading] = useState16(false);
1953
- const [success, setSuccess] = useState16("");
1954
- const [error, setError] = useState16("");
2235
+ const [displayName, setDisplayName] = useState17(user?.displayName ?? "");
2236
+ const [phone, setPhone] = useState17(user?.phone ?? "");
2237
+ const [loading, setLoading] = useState17(false);
2238
+ const [success, setSuccess] = useState17("");
2239
+ const [error, setError] = useState17("");
1955
2240
  const handleSave = async () => {
1956
2241
  if (!client) return;
1957
2242
  setLoading(true);
@@ -1967,9 +2252,9 @@ function ProfileTab() {
1967
2252
  }
1968
2253
  };
1969
2254
  const initials = user?.displayName ? user.displayName.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : (user?.email?.[0] ?? "?").toUpperCase();
1970
- return /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
1971
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 16 }, children: [
1972
- /* @__PURE__ */ jsx14(
2255
+ return /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
2256
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: 16 }, children: [
2257
+ /* @__PURE__ */ jsx15(
1973
2258
  "div",
1974
2259
  {
1975
2260
  style: {
@@ -1986,36 +2271,36 @@ function ProfileTab() {
1986
2271
  overflow: "hidden",
1987
2272
  flexShrink: 0
1988
2273
  },
1989
- children: user?.avatarUrl ? /* @__PURE__ */ jsx14("img", { src: user.avatarUrl, alt: "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials
2274
+ children: user?.avatarUrl ? /* @__PURE__ */ jsx15("img", { src: user.avatarUrl, alt: "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials
1990
2275
  }
1991
2276
  ),
1992
- /* @__PURE__ */ jsxs8("div", { children: [
1993
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 16, fontWeight: 600, color: theme.text }, children: user?.displayName ?? "User" }),
1994
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 13, color: theme.textMuted }, children: user?.email }),
1995
- !user?.emailVerified && /* @__PURE__ */ jsx14("span", { style: { fontSize: 11, color: "#d97706", background: "#fef3c7", padding: "2px 8px", borderRadius: 99, fontWeight: 500, marginTop: 4, display: "inline-block" }, children: "Email not verified" })
2277
+ /* @__PURE__ */ jsxs9("div", { children: [
2278
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 16, fontWeight: 600, color: theme.text }, children: user?.displayName ?? "User" }),
2279
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 13, color: theme.textMuted }, children: user?.email }),
2280
+ !user?.emailVerified && /* @__PURE__ */ jsx15("span", { style: { fontSize: 11, color: "#d97706", background: "#fef3c7", padding: "2px 8px", borderRadius: 99, fontWeight: 500, marginTop: 4, display: "inline-block" }, children: "Email not verified" })
1996
2281
  ] })
1997
2282
  ] }),
1998
- success && /* @__PURE__ */ jsx14("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#f0fdf4", border: "1px solid #bbf7d0", color: "#166534", fontSize: 13 }, children: success }),
1999
- error && /* @__PURE__ */ jsx14("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#fef2f2", border: "1px solid #fecaca", color: "#dc2626", fontSize: 13 }, children: error }),
2000
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
2001
- /* @__PURE__ */ jsx14(Input, { label: "Display name", value: displayName, onChange: setDisplayName, placeholder: "Your name" }),
2002
- /* @__PURE__ */ jsx14(Input, { label: "Email", type: "email", value: user?.email ?? "", disabled: true, placeholder: "Email" }),
2003
- /* @__PURE__ */ jsx14(Input, { label: "Phone", type: "tel", value: phone, onChange: setPhone, placeholder: "+1 (555) 000-0000" })
2283
+ success && /* @__PURE__ */ jsx15("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#f0fdf4", border: "1px solid #bbf7d0", color: "#166534", fontSize: 13 }, children: success }),
2284
+ error && /* @__PURE__ */ jsx15("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#fef2f2", border: "1px solid #fecaca", color: "#dc2626", fontSize: 13 }, children: error }),
2285
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
2286
+ /* @__PURE__ */ jsx15(Input, { label: "Display name", value: displayName, onChange: setDisplayName, placeholder: "Your name" }),
2287
+ /* @__PURE__ */ jsx15(Input, { label: "Email", type: "email", value: user?.email ?? "", disabled: true, placeholder: "Email" }),
2288
+ /* @__PURE__ */ jsx15(Input, { label: "Phone", type: "tel", value: phone, onChange: setPhone, placeholder: "+1 (555) 000-0000" })
2004
2289
  ] }),
2005
- /* @__PURE__ */ jsx14(Button, { variant: "primary", onClick: handleSave, loading, style: { alignSelf: "flex-start", minWidth: 120 }, children: "Save changes" })
2290
+ /* @__PURE__ */ jsx15(Button, { variant: "primary", onClick: handleSave, loading, style: { alignSelf: "flex-start", minWidth: 120 }, children: "Save changes" })
2006
2291
  ] });
2007
2292
  }
2008
2293
  function SecurityTab() {
2009
2294
  const theme = useTheme();
2010
2295
  const { client } = useAuthon();
2011
- const [currentPw, setCurrentPw] = useState16("");
2012
- const [newPw, setNewPw] = useState16("");
2013
- const [confirmPw, setConfirmPw] = useState16("");
2014
- const [pwLoading, setPwLoading] = useState16(false);
2015
- const [pwError, setPwError] = useState16("");
2016
- const [pwSuccess, setPwSuccess] = useState16("");
2017
- const [mfaStatus, setMfaStatus] = useState16(null);
2018
- const [mfaLoading, setMfaLoading] = useState16(false);
2296
+ const [currentPw, setCurrentPw] = useState17("");
2297
+ const [newPw, setNewPw] = useState17("");
2298
+ const [confirmPw, setConfirmPw] = useState17("");
2299
+ const [pwLoading, setPwLoading] = useState17(false);
2300
+ const [pwError, setPwError] = useState17("");
2301
+ const [pwSuccess, setPwSuccess] = useState17("");
2302
+ const [mfaStatus, setMfaStatus] = useState17(null);
2303
+ const [mfaLoading, setMfaLoading] = useState17(false);
2019
2304
  useEffect7(() => {
2020
2305
  if (!client) return;
2021
2306
  client.getMfaStatus().then(setMfaStatus).catch(() => null);
@@ -2053,26 +2338,26 @@ function SecurityTab() {
2053
2338
  paddingBottom: 10,
2054
2339
  borderBottom: `1px solid ${theme.border}`
2055
2340
  };
2056
- return /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
2057
- /* @__PURE__ */ jsxs8("div", { children: [
2058
- /* @__PURE__ */ jsx14("div", { style: sectionTitle, children: "Change password" }),
2059
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
2060
- /* @__PURE__ */ jsx14(Input, { label: "Current password", type: "password", value: currentPw, onChange: setCurrentPw, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", autoComplete: "current-password" }),
2061
- /* @__PURE__ */ jsx14(Input, { label: "New password", type: "password", value: newPw, onChange: setNewPw, placeholder: "Minimum 8 characters", autoComplete: "new-password" }),
2062
- /* @__PURE__ */ jsx14(Input, { label: "Confirm new password", type: "password", value: confirmPw, onChange: setConfirmPw, placeholder: "Repeat new password", autoComplete: "new-password" }),
2063
- pwError && /* @__PURE__ */ jsx14("div", { style: { color: "#dc2626", fontSize: 13 }, children: pwError }),
2064
- pwSuccess && /* @__PURE__ */ jsx14("div", { style: { color: "#166534", fontSize: 13 }, children: pwSuccess }),
2065
- /* @__PURE__ */ jsx14(Button, { variant: "primary", onClick: handlePasswordChange, loading: pwLoading, style: { alignSelf: "flex-start", minWidth: 160 }, children: "Update password" })
2341
+ return /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
2342
+ /* @__PURE__ */ jsxs9("div", { children: [
2343
+ /* @__PURE__ */ jsx15("div", { style: sectionTitle, children: "Change password" }),
2344
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
2345
+ /* @__PURE__ */ jsx15(Input, { label: "Current password", type: "password", value: currentPw, onChange: setCurrentPw, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", autoComplete: "current-password" }),
2346
+ /* @__PURE__ */ jsx15(Input, { label: "New password", type: "password", value: newPw, onChange: setNewPw, placeholder: "Minimum 8 characters", autoComplete: "new-password" }),
2347
+ /* @__PURE__ */ jsx15(Input, { label: "Confirm new password", type: "password", value: confirmPw, onChange: setConfirmPw, placeholder: "Repeat new password", autoComplete: "new-password" }),
2348
+ pwError && /* @__PURE__ */ jsx15("div", { style: { color: "#dc2626", fontSize: 13 }, children: pwError }),
2349
+ pwSuccess && /* @__PURE__ */ jsx15("div", { style: { color: "#166534", fontSize: 13 }, children: pwSuccess }),
2350
+ /* @__PURE__ */ jsx15(Button, { variant: "primary", onClick: handlePasswordChange, loading: pwLoading, style: { alignSelf: "flex-start", minWidth: 160 }, children: "Update password" })
2066
2351
  ] })
2067
2352
  ] }),
2068
- /* @__PURE__ */ jsxs8("div", { children: [
2069
- /* @__PURE__ */ jsx14("div", { style: sectionTitle, children: "Two-factor authentication" }),
2070
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 0" }, children: [
2071
- /* @__PURE__ */ jsxs8("div", { children: [
2072
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 14, fontWeight: 500, color: theme.text }, children: "Authenticator app" }),
2073
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 13, color: theme.textMuted, marginTop: 2 }, children: mfaStatus?.enabled ? `Enabled \xB7 ${mfaStatus.backupCodesRemaining} backup codes remaining` : "Add extra security to your account" })
2353
+ /* @__PURE__ */ jsxs9("div", { children: [
2354
+ /* @__PURE__ */ jsx15("div", { style: sectionTitle, children: "Two-factor authentication" }),
2355
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 0" }, children: [
2356
+ /* @__PURE__ */ jsxs9("div", { children: [
2357
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 14, fontWeight: 500, color: theme.text }, children: "Authenticator app" }),
2358
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 13, color: theme.textMuted, marginTop: 2 }, children: mfaStatus?.enabled ? `Enabled \xB7 ${mfaStatus.backupCodesRemaining} backup codes remaining` : "Add extra security to your account" })
2074
2359
  ] }),
2075
- /* @__PURE__ */ jsx14("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: /* @__PURE__ */ jsxs8(
2360
+ /* @__PURE__ */ jsx15("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: /* @__PURE__ */ jsxs9(
2076
2361
  "span",
2077
2362
  {
2078
2363
  style: {
@@ -2087,7 +2372,7 @@ function SecurityTab() {
2087
2372
  color: mfaStatus?.enabled ? "#166534" : theme.textMuted
2088
2373
  },
2089
2374
  children: [
2090
- /* @__PURE__ */ jsx14("span", { style: { width: 6, height: 6, borderRadius: "50%", background: mfaStatus?.enabled ? "#22c55e" : "#9ca3af", display: "inline-block" } }),
2375
+ /* @__PURE__ */ jsx15("span", { style: { width: 6, height: 6, borderRadius: "50%", background: mfaStatus?.enabled ? "#22c55e" : "#9ca3af", display: "inline-block" } }),
2091
2376
  mfaStatus?.enabled ? "Enabled" : "Disabled"
2092
2377
  ]
2093
2378
  }
@@ -2099,9 +2384,9 @@ function SecurityTab() {
2099
2384
  function SessionsTab() {
2100
2385
  const theme = useTheme();
2101
2386
  const { client } = useAuthon();
2102
- const [sessions, setSessions] = useState16([]);
2103
- const [loading, setLoading] = useState16(true);
2104
- const [revoking, setRevoking] = useState16(null);
2387
+ const [sessions, setSessions] = useState17([]);
2388
+ const [loading, setLoading] = useState17(true);
2389
+ const [revoking, setRevoking] = useState17(null);
2105
2390
  const loadSessions = useCallback11(async () => {
2106
2391
  if (!client) return;
2107
2392
  setLoading(true);
@@ -2136,11 +2421,11 @@ function SessionsTab() {
2136
2421
  borderBottom: `1px solid ${theme.border}`
2137
2422
  };
2138
2423
  if (loading) {
2139
- return /* @__PURE__ */ jsx14("div", { style: { display: "flex", justifyContent: "center", padding: 40 }, children: /* @__PURE__ */ jsx14("span", { style: { width: 24, height: 24, border: `3px solid ${theme.primaryStart}33`, borderTopColor: theme.primaryStart, borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.7s linear infinite" } }) });
2424
+ return /* @__PURE__ */ jsx15("div", { style: { display: "flex", justifyContent: "center", padding: 40 }, children: /* @__PURE__ */ jsx15("span", { style: { width: 24, height: 24, border: `3px solid ${theme.primaryStart}33`, borderTopColor: theme.primaryStart, borderRadius: "50%", display: "inline-block", animation: "authon-spin 0.7s linear infinite" } }) });
2140
2425
  }
2141
- return /* @__PURE__ */ jsxs8("div", { children: [
2142
- /* @__PURE__ */ jsx14("div", { style: sectionTitle, children: "Active sessions" }),
2143
- /* @__PURE__ */ jsx14("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx14("div", { style: { color: theme.textMuted, fontSize: 14, textAlign: "center", padding: "24px 0" }, children: "No active sessions" }) : sessions.map((session) => /* @__PURE__ */ jsxs8(
2426
+ return /* @__PURE__ */ jsxs9("div", { children: [
2427
+ /* @__PURE__ */ jsx15("div", { style: sectionTitle, children: "Active sessions" }),
2428
+ /* @__PURE__ */ jsx15("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx15("div", { style: { color: theme.textMuted, fontSize: 14, textAlign: "center", padding: "24px 0" }, children: "No active sessions" }) : sessions.map((session) => /* @__PURE__ */ jsxs9(
2144
2429
  "div",
2145
2430
  {
2146
2431
  style: {
@@ -2153,24 +2438,24 @@ function SessionsTab() {
2153
2438
  gap: 12
2154
2439
  },
2155
2440
  children: [
2156
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 12, flex: 1, minWidth: 0 }, children: [
2157
- /* @__PURE__ */ jsx14("div", { style: { width: 36, height: 36, borderRadius: "50%", background: `${theme.primaryStart}18`, color: theme.primaryStart, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxs8("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2158
- /* @__PURE__ */ jsx14("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", ry: "2" }),
2159
- /* @__PURE__ */ jsx14("line", { x1: "8", y1: "21", x2: "16", y2: "21" }),
2160
- /* @__PURE__ */ jsx14("line", { x1: "12", y1: "17", x2: "12", y2: "21" })
2441
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: 12, flex: 1, minWidth: 0 }, children: [
2442
+ /* @__PURE__ */ jsx15("div", { style: { width: 36, height: 36, borderRadius: "50%", background: `${theme.primaryStart}18`, color: theme.primaryStart, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: /* @__PURE__ */ jsxs9("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2443
+ /* @__PURE__ */ jsx15("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", ry: "2" }),
2444
+ /* @__PURE__ */ jsx15("line", { x1: "8", y1: "21", x2: "16", y2: "21" }),
2445
+ /* @__PURE__ */ jsx15("line", { x1: "12", y1: "17", x2: "12", y2: "21" })
2161
2446
  ] }) }),
2162
- /* @__PURE__ */ jsxs8("div", { style: { minWidth: 0 }, children: [
2163
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 13, fontWeight: 500, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: session.userAgent ? session.userAgent.length > 50 ? session.userAgent.slice(0, 50) + "\u2026" : session.userAgent : "Unknown device" }),
2164
- /* @__PURE__ */ jsxs8("div", { style: { fontSize: 12, color: theme.textMuted, marginTop: 2 }, children: [
2447
+ /* @__PURE__ */ jsxs9("div", { style: { minWidth: 0 }, children: [
2448
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 13, fontWeight: 500, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: session.userAgent ? session.userAgent.length > 50 ? session.userAgent.slice(0, 50) + "\u2026" : session.userAgent : "Unknown device" }),
2449
+ /* @__PURE__ */ jsxs9("div", { style: { fontSize: 12, color: theme.textMuted, marginTop: 2 }, children: [
2165
2450
  session.ipAddress ?? "Unknown IP",
2166
- session.lastActiveAt && /* @__PURE__ */ jsxs8(Fragment8, { children: [
2451
+ session.lastActiveAt && /* @__PURE__ */ jsxs9(Fragment9, { children: [
2167
2452
  " \xB7 ",
2168
2453
  formatRelative(session.lastActiveAt)
2169
2454
  ] })
2170
2455
  ] })
2171
2456
  ] })
2172
2457
  ] }),
2173
- /* @__PURE__ */ jsx14(
2458
+ /* @__PURE__ */ jsx15(
2174
2459
  Button,
2175
2460
  {
2176
2461
  variant: "outline",
@@ -2198,7 +2483,7 @@ function formatRelative(dateStr) {
2198
2483
  }
2199
2484
  function UserProfilePanel() {
2200
2485
  const theme = useTheme();
2201
- const [tab, setTab] = useState16("profile");
2486
+ const [tab, setTab] = useState17("profile");
2202
2487
  const panelStyle = {
2203
2488
  width: "100%",
2204
2489
  maxWidth: 640,
@@ -2233,9 +2518,9 @@ function UserProfilePanel() {
2233
2518
  { key: "security", label: "Security" },
2234
2519
  { key: "sessions", label: "Sessions" }
2235
2520
  ];
2236
- return /* @__PURE__ */ jsxs8("div", { style: panelStyle, children: [
2237
- /* @__PURE__ */ jsx14("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
2238
- /* @__PURE__ */ jsx14("div", { style: tabBarStyle, children: tabs.map(({ key, label }) => /* @__PURE__ */ jsx14(
2521
+ return /* @__PURE__ */ jsxs9("div", { style: panelStyle, children: [
2522
+ /* @__PURE__ */ jsx15("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
2523
+ /* @__PURE__ */ jsx15("div", { style: tabBarStyle, children: tabs.map(({ key, label }) => /* @__PURE__ */ jsx15(
2239
2524
  "button",
2240
2525
  {
2241
2526
  type: "button",
@@ -2245,26 +2530,26 @@ function UserProfilePanel() {
2245
2530
  },
2246
2531
  key
2247
2532
  )) }),
2248
- /* @__PURE__ */ jsxs8("div", { style: contentStyle, children: [
2249
- tab === "profile" && /* @__PURE__ */ jsx14(ProfileTab, {}),
2250
- tab === "security" && /* @__PURE__ */ jsx14(SecurityTab, {}),
2251
- tab === "sessions" && /* @__PURE__ */ jsx14(SessionsTab, {})
2533
+ /* @__PURE__ */ jsxs9("div", { style: contentStyle, children: [
2534
+ tab === "profile" && /* @__PURE__ */ jsx15(ProfileTab, {}),
2535
+ tab === "security" && /* @__PURE__ */ jsx15(SecurityTab, {}),
2536
+ tab === "sessions" && /* @__PURE__ */ jsx15(SessionsTab, {})
2252
2537
  ] })
2253
2538
  ] });
2254
2539
  }
2255
2540
  function UserProfile({ appearance }) {
2256
2541
  const { branding } = useBranding();
2257
2542
  const effectiveBranding = { ...branding, ...appearance?.variables ?? {} };
2258
- return /* @__PURE__ */ jsx14(ThemeProvider, { branding: effectiveBranding, style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx14(UserProfilePanel, {}) });
2543
+ return /* @__PURE__ */ jsx15(ThemeProvider, { branding: effectiveBranding, style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx15(UserProfilePanel, {}) });
2259
2544
  }
2260
2545
 
2261
2546
  // src/components/shared/ProviderIcon.tsx
2262
2547
  import { getProviderButtonConfig as getProviderButtonConfig4 } from "@authon/js";
2263
- import { jsx as jsx15 } from "react/jsx-runtime";
2548
+ import { jsx as jsx16 } from "react/jsx-runtime";
2264
2549
  function ProviderIcon({ provider, size = 20 }) {
2265
2550
  const config = getProviderButtonConfig4(provider);
2266
2551
  const svg = config.iconSvg.replace(/width="\d+"/, `width="${size}"`).replace(/height="\d+"/, `height="${size}"`);
2267
- return /* @__PURE__ */ jsx15(
2552
+ return /* @__PURE__ */ jsx16(
2268
2553
  "span",
2269
2554
  {
2270
2555
  style: { display: "flex", alignItems: "center", flexShrink: 0 },