@authon/react 0.3.1 → 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/LICENSE +21 -0
- package/README.ko.md +1 -2
- package/README.md +4 -6
- package/dist/index.cjs +610 -325
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +569 -284
- package/dist/index.js.map +1 -1
- package/package.json +10 -8
package/dist/index.cjs
CHANGED
|
@@ -60,32 +60,35 @@ function AuthonProvider({ publishableKey, children, config }) {
|
|
|
60
60
|
const [activeOrganization, setActiveOrganization] = (0, import_react.useState)(null);
|
|
61
61
|
const clientRef = (0, import_react.useRef)(null);
|
|
62
62
|
(0, import_react.useEffect)(() => {
|
|
63
|
+
let active = true;
|
|
64
|
+
let receivedSessionChange = false;
|
|
63
65
|
const client = new import_js.Authon(publishableKey, config);
|
|
66
|
+
const sessionClient = client;
|
|
64
67
|
clientRef.current = client;
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const unsubscribeSession = sessionClient.onSessionChange((change) => {
|
|
69
|
+
if (!active) return;
|
|
70
|
+
receivedSessionChange = true;
|
|
71
|
+
setUser(change.user);
|
|
67
72
|
setIsLoading(false);
|
|
68
|
-
|
|
69
|
-
client.on("signedOut", () => {
|
|
70
|
-
setUser(null);
|
|
73
|
+
if (!change.user) setActiveOrganization(null);
|
|
71
74
|
});
|
|
72
75
|
client.on("error", () => {
|
|
73
76
|
setIsLoading(false);
|
|
74
77
|
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
setUser(
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
void sessionClient.waitUntilReady().then(() => {
|
|
79
|
+
if (!active) return;
|
|
80
|
+
if (!receivedSessionChange) setUser(client.getUser());
|
|
81
|
+
setIsLoading(false);
|
|
82
|
+
});
|
|
80
83
|
return () => {
|
|
84
|
+
active = false;
|
|
85
|
+
unsubscribeSession();
|
|
81
86
|
client.destroy();
|
|
82
87
|
clientRef.current = null;
|
|
83
88
|
};
|
|
84
89
|
}, [publishableKey]);
|
|
85
90
|
const signOut = (0, import_react.useCallback)(async () => {
|
|
86
91
|
await clientRef.current?.signOut();
|
|
87
|
-
setUser(null);
|
|
88
|
-
setActiveOrganization(null);
|
|
89
92
|
}, []);
|
|
90
93
|
const openSignIn = (0, import_react.useCallback)(async () => {
|
|
91
94
|
await clientRef.current?.openSignIn();
|
|
@@ -131,7 +134,7 @@ function useUser() {
|
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
// src/components/SignIn.tsx
|
|
134
|
-
var
|
|
137
|
+
var import_react8 = require("react");
|
|
135
138
|
var import_shared3 = require("@authon/shared");
|
|
136
139
|
var import_js2 = require("@authon/js");
|
|
137
140
|
|
|
@@ -249,8 +252,10 @@ function Input({
|
|
|
249
252
|
...rest
|
|
250
253
|
}) {
|
|
251
254
|
const theme = useTheme();
|
|
255
|
+
const generatedId = (0, import_react5.useId)();
|
|
252
256
|
const [focused, setFocused] = (0, import_react5.useState)(false);
|
|
253
257
|
const resolvedStyle = inputStyle ?? theme.inputStyle;
|
|
258
|
+
const inputId = rest.id ?? generatedId;
|
|
254
259
|
const wrapperStyle = {
|
|
255
260
|
display: "flex",
|
|
256
261
|
flexDirection: "column",
|
|
@@ -307,12 +312,13 @@ function Input({
|
|
|
307
312
|
color: error ? "#ef4444" : theme.textMuted
|
|
308
313
|
};
|
|
309
314
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: wrapperStyle, children: [
|
|
310
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: labelStyle, children: label }),
|
|
315
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { htmlFor: inputId, style: labelStyle, children: label }),
|
|
311
316
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: inputContainerStyle, children: [
|
|
312
317
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
313
318
|
"input",
|
|
314
319
|
{
|
|
315
320
|
...rest,
|
|
321
|
+
id: inputId,
|
|
316
322
|
style: { ...baseInputStyle, ...inputVariantStyle },
|
|
317
323
|
onFocus: (e) => {
|
|
318
324
|
setFocused(true);
|
|
@@ -460,19 +466,212 @@ function Divider({ label = "Or continue with" }) {
|
|
|
460
466
|
] });
|
|
461
467
|
}
|
|
462
468
|
|
|
463
|
-
// src/components/
|
|
469
|
+
// src/components/shared/AuthChallengeForms.tsx
|
|
470
|
+
var import_react7 = require("react");
|
|
464
471
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
465
|
-
function
|
|
472
|
+
function errorMessage(error, fallback) {
|
|
473
|
+
return error instanceof Error && error.message ? error.message : fallback;
|
|
474
|
+
}
|
|
475
|
+
function CodeForm({
|
|
476
|
+
title,
|
|
477
|
+
description,
|
|
478
|
+
label,
|
|
479
|
+
submitLabel,
|
|
480
|
+
backLabel,
|
|
481
|
+
onSubmit,
|
|
482
|
+
onBack,
|
|
483
|
+
onResend
|
|
484
|
+
}) {
|
|
485
|
+
const theme = useTheme();
|
|
486
|
+
const [code, setCode] = (0, import_react7.useState)("");
|
|
487
|
+
const [error, setError] = (0, import_react7.useState)("");
|
|
488
|
+
const [status, setStatus] = (0, import_react7.useState)("");
|
|
489
|
+
const [loading, setLoading] = (0, import_react7.useState)(false);
|
|
490
|
+
const [resending, setResending] = (0, import_react7.useState)(false);
|
|
491
|
+
const errorId = (0, import_react7.useId)();
|
|
492
|
+
const submitPending = (0, import_react7.useRef)(false);
|
|
493
|
+
const resendPending = (0, import_react7.useRef)(false);
|
|
494
|
+
const handleSubmit = async () => {
|
|
495
|
+
if (submitPending.current) return;
|
|
496
|
+
if (!code.trim()) {
|
|
497
|
+
setError(`${label} is required`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
submitPending.current = true;
|
|
501
|
+
setLoading(true);
|
|
502
|
+
setError("");
|
|
503
|
+
setStatus("");
|
|
504
|
+
try {
|
|
505
|
+
await onSubmit(code.trim());
|
|
506
|
+
} catch (submitError) {
|
|
507
|
+
setError(errorMessage(submitError, "Verification failed"));
|
|
508
|
+
} finally {
|
|
509
|
+
submitPending.current = false;
|
|
510
|
+
setLoading(false);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
const handleResend = async () => {
|
|
514
|
+
if (!onResend || resendPending.current) return;
|
|
515
|
+
resendPending.current = true;
|
|
516
|
+
setResending(true);
|
|
517
|
+
setError("");
|
|
518
|
+
setStatus("");
|
|
519
|
+
try {
|
|
520
|
+
await onResend();
|
|
521
|
+
setStatus("Verification code sent");
|
|
522
|
+
} catch (resendError) {
|
|
523
|
+
setError(errorMessage(resendError, "Could not resend verification code"));
|
|
524
|
+
} finally {
|
|
525
|
+
resendPending.current = false;
|
|
526
|
+
setResending(false);
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
const titleStyle = {
|
|
530
|
+
margin: 0,
|
|
531
|
+
fontSize: 24,
|
|
532
|
+
fontWeight: 700,
|
|
533
|
+
color: theme.text,
|
|
534
|
+
textAlign: "center",
|
|
535
|
+
letterSpacing: "-0.3px"
|
|
536
|
+
};
|
|
537
|
+
const descriptionStyle = {
|
|
538
|
+
margin: "-8px 0 0",
|
|
539
|
+
fontSize: 14,
|
|
540
|
+
lineHeight: 1.5,
|
|
541
|
+
color: theme.textMuted,
|
|
542
|
+
textAlign: "center"
|
|
543
|
+
};
|
|
544
|
+
const errorStyle = {
|
|
545
|
+
padding: "10px 14px",
|
|
546
|
+
borderRadius: theme.borderRadius,
|
|
547
|
+
background: "#fef2f2",
|
|
548
|
+
border: "1px solid #fecaca",
|
|
549
|
+
color: "#dc2626",
|
|
550
|
+
fontSize: 13
|
|
551
|
+
};
|
|
552
|
+
const statusStyle = {
|
|
553
|
+
padding: "10px 14px",
|
|
554
|
+
borderRadius: theme.borderRadius,
|
|
555
|
+
background: "#f0fdf4",
|
|
556
|
+
border: "1px solid #bbf7d0",
|
|
557
|
+
color: "#15803d",
|
|
558
|
+
fontSize: 13
|
|
559
|
+
};
|
|
560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
561
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { style: titleStyle, children: title }),
|
|
562
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: descriptionStyle, children: description }),
|
|
563
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { id: errorId, role: "alert", style: errorStyle, children: error }),
|
|
564
|
+
status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { role: "status", "aria-live": "polite", style: statusStyle, children: status }),
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
566
|
+
Input,
|
|
567
|
+
{
|
|
568
|
+
label,
|
|
569
|
+
value: code,
|
|
570
|
+
onChange: setCode,
|
|
571
|
+
inputMode: "numeric",
|
|
572
|
+
autoComplete: "one-time-code",
|
|
573
|
+
disabled: loading,
|
|
574
|
+
"aria-invalid": !!error,
|
|
575
|
+
"aria-describedby": error ? errorId : void 0
|
|
576
|
+
}
|
|
577
|
+
),
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
579
|
+
Button,
|
|
580
|
+
{
|
|
581
|
+
variant: "primary",
|
|
582
|
+
fullWidth: true,
|
|
583
|
+
loading,
|
|
584
|
+
disabled: resending,
|
|
585
|
+
onClick: handleSubmit,
|
|
586
|
+
children: submitLabel
|
|
587
|
+
}
|
|
588
|
+
),
|
|
589
|
+
onResend && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
590
|
+
Button,
|
|
591
|
+
{
|
|
592
|
+
variant: "outline",
|
|
593
|
+
fullWidth: true,
|
|
594
|
+
loading: resending,
|
|
595
|
+
disabled: loading,
|
|
596
|
+
onClick: handleResend,
|
|
597
|
+
children: "Resend code"
|
|
598
|
+
}
|
|
599
|
+
),
|
|
600
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
601
|
+
Button,
|
|
602
|
+
{
|
|
603
|
+
variant: "ghost",
|
|
604
|
+
fullWidth: true,
|
|
605
|
+
disabled: loading || resending,
|
|
606
|
+
onClick: onBack,
|
|
607
|
+
children: backLabel
|
|
608
|
+
}
|
|
609
|
+
)
|
|
610
|
+
] });
|
|
611
|
+
}
|
|
612
|
+
function VerificationForm({
|
|
613
|
+
email,
|
|
614
|
+
backLabel,
|
|
615
|
+
onVerify,
|
|
616
|
+
onResend,
|
|
617
|
+
onBack
|
|
618
|
+
}) {
|
|
619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
620
|
+
CodeForm,
|
|
621
|
+
{
|
|
622
|
+
title: "Verify your email",
|
|
623
|
+
description: `Enter the verification code sent to ${email}.`,
|
|
624
|
+
label: "Verification code",
|
|
625
|
+
submitLabel: "Verify email",
|
|
626
|
+
backLabel,
|
|
627
|
+
onSubmit: onVerify,
|
|
628
|
+
onResend,
|
|
629
|
+
onBack
|
|
630
|
+
}
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
function MfaForm({ onVerify, onBack }) {
|
|
634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
635
|
+
CodeForm,
|
|
636
|
+
{
|
|
637
|
+
title: "Two-factor authentication",
|
|
638
|
+
description: "Enter the code from your authenticator app.",
|
|
639
|
+
label: "Authenticator code",
|
|
640
|
+
submitLabel: "Verify code",
|
|
641
|
+
backLabel: "Back to sign in",
|
|
642
|
+
onSubmit: onVerify,
|
|
643
|
+
onBack
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// src/components/shared/navigation.ts
|
|
649
|
+
function navigateTo(url) {
|
|
650
|
+
window.location.assign(url);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/components/SignIn.tsx
|
|
654
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
655
|
+
function SignInCard({ afterSignInUrl, onSignIn, onForgotPassword, onNavigateSignUp }) {
|
|
466
656
|
const theme = useTheme();
|
|
467
657
|
const { client } = useAuthon();
|
|
468
658
|
const { branding, providers, isLoaded } = useBranding();
|
|
469
|
-
const [email, setEmail] = (0,
|
|
470
|
-
const [password, setPassword] = (0,
|
|
471
|
-
const [showPassword, setShowPassword] = (0,
|
|
472
|
-
const [loading, setLoading] = (0,
|
|
473
|
-
const [oauthLoading, setOauthLoading] = (0,
|
|
474
|
-
const [error, setError] = (0,
|
|
475
|
-
const [
|
|
659
|
+
const [email, setEmail] = (0, import_react8.useState)("");
|
|
660
|
+
const [password, setPassword] = (0, import_react8.useState)("");
|
|
661
|
+
const [showPassword, setShowPassword] = (0, import_react8.useState)(false);
|
|
662
|
+
const [loading, setLoading] = (0, import_react8.useState)(false);
|
|
663
|
+
const [oauthLoading, setOauthLoading] = (0, import_react8.useState)(null);
|
|
664
|
+
const [error, setError] = (0, import_react8.useState)("");
|
|
665
|
+
const [step, setStep] = (0, import_react8.useState)({ kind: "credentials" });
|
|
666
|
+
const [fieldErrors, setFieldErrors] = (0, import_react8.useState)({});
|
|
667
|
+
const authAttemptPending = (0, import_react8.useRef)(false);
|
|
668
|
+
const completed = (0, import_react8.useRef)(false);
|
|
669
|
+
const completeSignIn = () => {
|
|
670
|
+
if (completed.current) return;
|
|
671
|
+
completed.current = true;
|
|
672
|
+
if (afterSignInUrl) navigateTo(afterSignInUrl);
|
|
673
|
+
onSignIn?.();
|
|
674
|
+
};
|
|
476
675
|
const validate = () => {
|
|
477
676
|
const errs = {};
|
|
478
677
|
if (!email.trim()) errs.email = "Email is required";
|
|
@@ -482,21 +681,35 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
482
681
|
return Object.keys(errs).length === 0;
|
|
483
682
|
};
|
|
484
683
|
const handleSubmit = async () => {
|
|
485
|
-
if (!validate() || !client) return;
|
|
684
|
+
if (authAttemptPending.current || !validate() || !client) return;
|
|
685
|
+
authAttemptPending.current = true;
|
|
486
686
|
setLoading(true);
|
|
487
687
|
setError("");
|
|
488
688
|
try {
|
|
489
|
-
await client.signInWithEmail(email, password);
|
|
490
|
-
if (
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
689
|
+
const result = await client.signInWithEmail(email, password);
|
|
690
|
+
if ("needsVerification" in result && result.needsVerification) {
|
|
691
|
+
setStep({ kind: "verification", email: result.email });
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
completeSignIn();
|
|
695
|
+
} catch (submitError) {
|
|
696
|
+
if (submitError instanceof import_js2.AuthonMfaRequiredError) {
|
|
697
|
+
setStep({ kind: "mfa", mfaToken: submitError.mfaToken });
|
|
698
|
+
} else {
|
|
699
|
+
setError(submitError instanceof Error && submitError.message ? submitError.message : "Sign in failed");
|
|
700
|
+
}
|
|
494
701
|
} finally {
|
|
702
|
+
authAttemptPending.current = false;
|
|
495
703
|
setLoading(false);
|
|
496
704
|
}
|
|
497
705
|
};
|
|
706
|
+
const backToCredentials = () => {
|
|
707
|
+
setError("");
|
|
708
|
+
setStep({ kind: "credentials" });
|
|
709
|
+
};
|
|
498
710
|
const handleOAuth = async (provider) => {
|
|
499
|
-
if (!client) return;
|
|
711
|
+
if (!client || authAttemptPending.current) return;
|
|
712
|
+
authAttemptPending.current = true;
|
|
500
713
|
setOauthLoading(provider);
|
|
501
714
|
setError("");
|
|
502
715
|
try {
|
|
@@ -504,6 +717,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
504
717
|
} catch (e) {
|
|
505
718
|
setError(e?.message ?? "OAuth sign in failed");
|
|
506
719
|
} finally {
|
|
720
|
+
authAttemptPending.current = false;
|
|
507
721
|
setOauthLoading(null);
|
|
508
722
|
}
|
|
509
723
|
};
|
|
@@ -574,7 +788,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
574
788
|
(p) => !(branding.hiddenProviders ?? []).includes(p)
|
|
575
789
|
);
|
|
576
790
|
if (!isLoaded) {
|
|
577
|
-
return /* @__PURE__ */ (0,
|
|
791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
578
792
|
"span",
|
|
579
793
|
{
|
|
580
794
|
style: {
|
|
@@ -589,17 +803,49 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
589
803
|
}
|
|
590
804
|
) });
|
|
591
805
|
}
|
|
592
|
-
|
|
593
|
-
/* @__PURE__ */ (0,
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
806
|
+
if (step.kind === "verification") {
|
|
807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: cardStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
808
|
+
VerificationForm,
|
|
809
|
+
{
|
|
810
|
+
email: step.email,
|
|
811
|
+
backLabel: "Back to sign in",
|
|
812
|
+
onVerify: async (code) => {
|
|
813
|
+
if (!client) throw new Error("Sign in is unavailable");
|
|
814
|
+
await client.verifyEmail(step.email, code);
|
|
815
|
+
completeSignIn();
|
|
816
|
+
},
|
|
817
|
+
onResend: async () => {
|
|
818
|
+
if (!client) throw new Error("Sign in is unavailable");
|
|
819
|
+
await client.resendVerificationCode(step.email);
|
|
820
|
+
},
|
|
821
|
+
onBack: backToCredentials
|
|
822
|
+
}
|
|
823
|
+
) });
|
|
824
|
+
}
|
|
825
|
+
if (step.kind === "mfa") {
|
|
826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: cardStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
827
|
+
MfaForm,
|
|
828
|
+
{
|
|
829
|
+
onVerify: async (code) => {
|
|
830
|
+
if (!client) throw new Error("Sign in is unavailable");
|
|
831
|
+
await client.verifyMfa(step.mfaToken, code);
|
|
832
|
+
completeSignIn();
|
|
833
|
+
},
|
|
834
|
+
onBack: backToCredentials
|
|
835
|
+
}
|
|
836
|
+
) });
|
|
837
|
+
}
|
|
838
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: cardStyle, children: [
|
|
839
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: logoStyle, children: [
|
|
840
|
+
branding.logoDataUrl && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: titleStyle, children: "Sign in" }),
|
|
842
|
+
branding.brandName && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { style: subtitleStyle, children: [
|
|
597
843
|
"to ",
|
|
598
844
|
branding.brandName
|
|
599
845
|
] })
|
|
600
846
|
] }),
|
|
601
|
-
error && /* @__PURE__ */ (0,
|
|
602
|
-
providersToShow.length > 0 && /* @__PURE__ */ (0,
|
|
847
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "alert", style: errorBoxStyle, children: error }),
|
|
848
|
+
providersToShow.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
603
849
|
OAuthButton,
|
|
604
850
|
{
|
|
605
851
|
provider,
|
|
@@ -609,7 +855,7 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
609
855
|
borderRadius: theme.borderRadius
|
|
610
856
|
},
|
|
611
857
|
provider
|
|
612
|
-
)) : /* @__PURE__ */ (0,
|
|
858
|
+
)) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
613
859
|
CompactOAuthButton,
|
|
614
860
|
{
|
|
615
861
|
provider,
|
|
@@ -620,9 +866,9 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
620
866
|
},
|
|
621
867
|
provider
|
|
622
868
|
)) }) }),
|
|
623
|
-
showDivider && /* @__PURE__ */ (0,
|
|
624
|
-
showEmailPw && /* @__PURE__ */ (0,
|
|
625
|
-
/* @__PURE__ */ (0,
|
|
869
|
+
showDivider && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Divider, {}),
|
|
870
|
+
showEmailPw && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
626
872
|
Input,
|
|
627
873
|
{
|
|
628
874
|
label: "Email",
|
|
@@ -634,8 +880,8 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
634
880
|
autoComplete: "email"
|
|
635
881
|
}
|
|
636
882
|
),
|
|
637
|
-
/* @__PURE__ */ (0,
|
|
638
|
-
/* @__PURE__ */ (0,
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
639
885
|
Input,
|
|
640
886
|
{
|
|
641
887
|
label: "Password",
|
|
@@ -645,21 +891,21 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
645
891
|
onChange: setPassword,
|
|
646
892
|
error: fieldErrors.password,
|
|
647
893
|
autoComplete: "current-password",
|
|
648
|
-
rightElement: /* @__PURE__ */ (0,
|
|
894
|
+
rightElement: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
649
895
|
"button",
|
|
650
896
|
{
|
|
651
897
|
type: "button",
|
|
652
898
|
onClick: () => setShowPassword((v) => !v),
|
|
653
899
|
style: { background: "none", border: "none", cursor: "pointer", padding: 0, display: "flex", color: theme.textMuted },
|
|
654
900
|
"aria-label": showPassword ? "Hide password" : "Show password",
|
|
655
|
-
children: /* @__PURE__ */ (0,
|
|
901
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: eyeIconPath }) })
|
|
656
902
|
}
|
|
657
903
|
)
|
|
658
904
|
}
|
|
659
905
|
),
|
|
660
|
-
/* @__PURE__ */ (0,
|
|
906
|
+
onForgotPassword && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: forgotStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", style: linkStyle, onClick: onForgotPassword, children: "Forgot password?" }) })
|
|
661
907
|
] }),
|
|
662
|
-
/* @__PURE__ */ (0,
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
663
909
|
Button,
|
|
664
910
|
{
|
|
665
911
|
variant: "primary",
|
|
@@ -671,10 +917,10 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
671
917
|
}
|
|
672
918
|
)
|
|
673
919
|
] }),
|
|
674
|
-
/* @__PURE__ */ (0,
|
|
920
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: footerStyle, children: [
|
|
675
921
|
"Don't have an account?",
|
|
676
922
|
" ",
|
|
677
|
-
/* @__PURE__ */ (0,
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
678
924
|
"button",
|
|
679
925
|
{
|
|
680
926
|
type: "button",
|
|
@@ -684,16 +930,16 @@ function SignInCard({ afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
684
930
|
}
|
|
685
931
|
)
|
|
686
932
|
] }),
|
|
687
|
-
branding.showSecuredBy !== false && /* @__PURE__ */ (0,
|
|
688
|
-
branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ (0,
|
|
689
|
-
branding.termsUrl && /* @__PURE__ */ (0,
|
|
933
|
+
branding.showSecuredBy !== false && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SecuredByAuthon, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
|
|
934
|
+
branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
|
|
935
|
+
branding.termsUrl && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Terms" }),
|
|
690
936
|
branding.termsUrl && branding.privacyUrl && " \xB7 ",
|
|
691
|
-
branding.privacyUrl && /* @__PURE__ */ (0,
|
|
937
|
+
branding.privacyUrl && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.textMuted }, children: "Privacy" })
|
|
692
938
|
] }) : null
|
|
693
939
|
] });
|
|
694
940
|
}
|
|
695
941
|
function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
|
|
696
|
-
const [hovered, setHovered] = (0,
|
|
942
|
+
const [hovered, setHovered] = (0, import_react8.useState)(false);
|
|
697
943
|
const colors = import_shared3.PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
|
|
698
944
|
const name = import_shared3.PROVIDER_DISPLAY_NAMES[provider] ?? provider;
|
|
699
945
|
const config = (0, import_js2.getProviderButtonConfig)(provider);
|
|
@@ -719,7 +965,7 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
|
|
|
719
965
|
transition: "opacity 0.15s",
|
|
720
966
|
boxSizing: "border-box"
|
|
721
967
|
};
|
|
722
|
-
return /* @__PURE__ */ (0,
|
|
968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
723
969
|
"button",
|
|
724
970
|
{
|
|
725
971
|
type: "button",
|
|
@@ -729,9 +975,9 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
|
|
|
729
975
|
onMouseEnter: () => setHovered(true),
|
|
730
976
|
onMouseLeave: () => setHovered(false),
|
|
731
977
|
"aria-label": `Continue with ${name}`,
|
|
732
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
734
|
-
/* @__PURE__ */ (0,
|
|
978
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
|
|
980
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
735
981
|
"Continue with ",
|
|
736
982
|
name
|
|
737
983
|
] })
|
|
@@ -740,7 +986,7 @@ function OAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
|
|
|
740
986
|
);
|
|
741
987
|
}
|
|
742
988
|
function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius }) {
|
|
743
|
-
const [hovered, setHovered] = (0,
|
|
989
|
+
const [hovered, setHovered] = (0, import_react8.useState)(false);
|
|
744
990
|
const colors = import_shared3.PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
|
|
745
991
|
const name = import_shared3.PROVIDER_DISPLAY_NAMES[provider] ?? provider;
|
|
746
992
|
const config = (0, import_js2.getProviderButtonConfig)(provider);
|
|
@@ -759,7 +1005,7 @@ function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius
|
|
|
759
1005
|
transition: "opacity 0.15s",
|
|
760
1006
|
padding: 0
|
|
761
1007
|
};
|
|
762
|
-
return /* @__PURE__ */ (0,
|
|
1008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
763
1009
|
"button",
|
|
764
1010
|
{
|
|
765
1011
|
type: "button",
|
|
@@ -769,33 +1015,34 @@ function CompactOAuthButton({ provider, loading, disabled, onClick, borderRadius
|
|
|
769
1015
|
onMouseEnter: () => setHovered(true),
|
|
770
1016
|
onMouseLeave: () => setHovered(false),
|
|
771
1017
|
"aria-label": `Continue with ${name}`,
|
|
772
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
1018
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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__ */ (0, import_jsx_runtime7.jsx)("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
|
|
773
1019
|
}
|
|
774
1020
|
);
|
|
775
1021
|
}
|
|
776
1022
|
function SecuredByAuthon({ primaryStart, textMuted }) {
|
|
777
|
-
return /* @__PURE__ */ (0,
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
1023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
|
|
1024
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1025
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }),
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
781
1027
|
] }),
|
|
782
|
-
/* @__PURE__ */ (0,
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: 11, color: textMuted }, children: [
|
|
783
1029
|
"Secured by",
|
|
784
1030
|
" ",
|
|
785
|
-
/* @__PURE__ */ (0,
|
|
1031
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
|
|
786
1032
|
] })
|
|
787
1033
|
] });
|
|
788
1034
|
}
|
|
789
|
-
function SignIn({ appearance, afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
1035
|
+
function SignIn({ appearance, afterSignInUrl, onSignIn, onForgotPassword, onNavigateSignUp }) {
|
|
790
1036
|
const { branding, isLoaded } = useBranding();
|
|
791
1037
|
const effectiveBranding = isLoaded ? { ...branding, ...appearance?.variables ?? {} } : branding;
|
|
792
|
-
return /* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
1038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
795
1041
|
SignInCard,
|
|
796
1042
|
{
|
|
797
1043
|
afterSignInUrl,
|
|
798
1044
|
onSignIn,
|
|
1045
|
+
onForgotPassword,
|
|
799
1046
|
onNavigateSignUp
|
|
800
1047
|
}
|
|
801
1048
|
)
|
|
@@ -803,23 +1050,32 @@ function SignIn({ appearance, afterSignInUrl, onSignIn, onNavigateSignUp }) {
|
|
|
803
1050
|
}
|
|
804
1051
|
|
|
805
1052
|
// src/components/SignUp.tsx
|
|
806
|
-
var
|
|
1053
|
+
var import_react9 = require("react");
|
|
807
1054
|
var import_shared4 = require("@authon/shared");
|
|
808
1055
|
var import_js3 = require("@authon/js");
|
|
809
|
-
var
|
|
1056
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
810
1057
|
function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
811
1058
|
const theme = useTheme();
|
|
812
1059
|
const { client } = useAuthon();
|
|
813
1060
|
const { branding, providers, isLoaded } = useBranding();
|
|
814
|
-
const [displayName, setDisplayName] = (0,
|
|
815
|
-
const [email, setEmail] = (0,
|
|
816
|
-
const [password, setPassword] = (0,
|
|
817
|
-
const [confirmPassword, setConfirmPassword] = (0,
|
|
818
|
-
const [showPassword, setShowPassword] = (0,
|
|
819
|
-
const [loading, setLoading] = (0,
|
|
820
|
-
const [oauthLoading, setOauthLoading] = (0,
|
|
821
|
-
const [error, setError] = (0,
|
|
822
|
-
const [
|
|
1061
|
+
const [displayName, setDisplayName] = (0, import_react9.useState)("");
|
|
1062
|
+
const [email, setEmail] = (0, import_react9.useState)("");
|
|
1063
|
+
const [password, setPassword] = (0, import_react9.useState)("");
|
|
1064
|
+
const [confirmPassword, setConfirmPassword] = (0, import_react9.useState)("");
|
|
1065
|
+
const [showPassword, setShowPassword] = (0, import_react9.useState)(false);
|
|
1066
|
+
const [loading, setLoading] = (0, import_react9.useState)(false);
|
|
1067
|
+
const [oauthLoading, setOauthLoading] = (0, import_react9.useState)(null);
|
|
1068
|
+
const [error, setError] = (0, import_react9.useState)("");
|
|
1069
|
+
const [verificationEmail, setVerificationEmail] = (0, import_react9.useState)(null);
|
|
1070
|
+
const [fieldErrors, setFieldErrors] = (0, import_react9.useState)({});
|
|
1071
|
+
const authAttemptPending = (0, import_react9.useRef)(false);
|
|
1072
|
+
const completed = (0, import_react9.useRef)(false);
|
|
1073
|
+
const completeSignUp = () => {
|
|
1074
|
+
if (completed.current) return;
|
|
1075
|
+
completed.current = true;
|
|
1076
|
+
if (afterSignUpUrl) navigateTo(afterSignUpUrl);
|
|
1077
|
+
onSignUp?.();
|
|
1078
|
+
};
|
|
823
1079
|
const validate = () => {
|
|
824
1080
|
const errs = {};
|
|
825
1081
|
if (!email.trim()) errs.email = "Email is required";
|
|
@@ -831,21 +1087,27 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
831
1087
|
return Object.keys(errs).length === 0;
|
|
832
1088
|
};
|
|
833
1089
|
const handleSubmit = async () => {
|
|
834
|
-
if (!validate() || !client) return;
|
|
1090
|
+
if (authAttemptPending.current || !validate() || !client) return;
|
|
1091
|
+
authAttemptPending.current = true;
|
|
835
1092
|
setLoading(true);
|
|
836
1093
|
setError("");
|
|
837
1094
|
try {
|
|
838
|
-
await client.signUpWithEmail(email, password, displayName ? { displayName } : void 0);
|
|
839
|
-
if (
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1095
|
+
const result = await client.signUpWithEmail(email, password, displayName ? { displayName } : void 0);
|
|
1096
|
+
if ("needsVerification" in result && result.needsVerification) {
|
|
1097
|
+
setVerificationEmail(result.email);
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
completeSignUp();
|
|
1101
|
+
} catch (submitError) {
|
|
1102
|
+
setError(submitError instanceof Error && submitError.message ? submitError.message : "Sign up failed");
|
|
843
1103
|
} finally {
|
|
1104
|
+
authAttemptPending.current = false;
|
|
844
1105
|
setLoading(false);
|
|
845
1106
|
}
|
|
846
1107
|
};
|
|
847
1108
|
const handleOAuth = async (provider) => {
|
|
848
|
-
if (!client) return;
|
|
1109
|
+
if (!client || authAttemptPending.current) return;
|
|
1110
|
+
authAttemptPending.current = true;
|
|
849
1111
|
setOauthLoading(provider);
|
|
850
1112
|
setError("");
|
|
851
1113
|
try {
|
|
@@ -853,6 +1115,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
853
1115
|
} catch (e) {
|
|
854
1116
|
setError(e?.message ?? "OAuth sign in failed");
|
|
855
1117
|
} finally {
|
|
1118
|
+
authAttemptPending.current = false;
|
|
856
1119
|
setOauthLoading(null);
|
|
857
1120
|
}
|
|
858
1121
|
};
|
|
@@ -918,7 +1181,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
918
1181
|
(p) => !(branding.hiddenProviders ?? []).includes(p)
|
|
919
1182
|
);
|
|
920
1183
|
if (!isLoaded) {
|
|
921
|
-
return /* @__PURE__ */ (0,
|
|
1184
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { ...cardStyle, alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
922
1185
|
"span",
|
|
923
1186
|
{
|
|
924
1187
|
style: {
|
|
@@ -933,18 +1196,40 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
933
1196
|
}
|
|
934
1197
|
) });
|
|
935
1198
|
}
|
|
1199
|
+
if (verificationEmail) {
|
|
1200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: cardStyle, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1201
|
+
VerificationForm,
|
|
1202
|
+
{
|
|
1203
|
+
email: verificationEmail,
|
|
1204
|
+
backLabel: "Back to sign up",
|
|
1205
|
+
onVerify: async (code) => {
|
|
1206
|
+
if (!client) throw new Error("Sign up is unavailable");
|
|
1207
|
+
await client.verifyEmail(verificationEmail, code);
|
|
1208
|
+
completeSignUp();
|
|
1209
|
+
},
|
|
1210
|
+
onResend: async () => {
|
|
1211
|
+
if (!client) throw new Error("Sign up is unavailable");
|
|
1212
|
+
await client.resendVerificationCode(verificationEmail);
|
|
1213
|
+
},
|
|
1214
|
+
onBack: () => {
|
|
1215
|
+
setError("");
|
|
1216
|
+
setVerificationEmail(null);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
) });
|
|
1220
|
+
}
|
|
936
1221
|
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";
|
|
937
|
-
return /* @__PURE__ */ (0,
|
|
938
|
-
/* @__PURE__ */ (0,
|
|
939
|
-
branding.logoDataUrl && /* @__PURE__ */ (0,
|
|
940
|
-
/* @__PURE__ */ (0,
|
|
941
|
-
branding.brandName && /* @__PURE__ */ (0,
|
|
1222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: cardStyle, children: [
|
|
1223
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: logoStyle, children: [
|
|
1224
|
+
branding.logoDataUrl && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: branding.logoDataUrl, alt: branding.brandName ?? "Logo", style: { height: 40, objectFit: "contain" } }),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: titleStyle, children: "Create account" }),
|
|
1226
|
+
branding.brandName && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { style: subtitleStyle, children: [
|
|
942
1227
|
"Join ",
|
|
943
1228
|
branding.brandName
|
|
944
1229
|
] })
|
|
945
1230
|
] }),
|
|
946
|
-
error && /* @__PURE__ */ (0,
|
|
947
|
-
providersToShow.length > 0 && /* @__PURE__ */ (0,
|
|
1231
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", style: errorBoxStyle, children: error }),
|
|
1232
|
+
providersToShow.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: providersToShow.length <= 3 ? providersToShow.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
948
1233
|
OAuthButtonFull,
|
|
949
1234
|
{
|
|
950
1235
|
provider,
|
|
@@ -954,7 +1239,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
954
1239
|
borderRadius: theme.borderRadius
|
|
955
1240
|
},
|
|
956
1241
|
provider
|
|
957
|
-
)) : /* @__PURE__ */ (0,
|
|
1242
|
+
)) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, justifyContent: "center" }, children: providersToShow.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
958
1243
|
CompactOAuthBtn,
|
|
959
1244
|
{
|
|
960
1245
|
provider,
|
|
@@ -965,9 +1250,9 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
965
1250
|
},
|
|
966
1251
|
provider
|
|
967
1252
|
)) }) }),
|
|
968
|
-
showDivider && /* @__PURE__ */ (0,
|
|
969
|
-
showEmailPw && /* @__PURE__ */ (0,
|
|
970
|
-
/* @__PURE__ */ (0,
|
|
1253
|
+
showDivider && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Divider, {}),
|
|
1254
|
+
showEmailPw && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
971
1256
|
Input,
|
|
972
1257
|
{
|
|
973
1258
|
label: "Display name",
|
|
@@ -979,7 +1264,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
979
1264
|
autoComplete: "name"
|
|
980
1265
|
}
|
|
981
1266
|
),
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
983
1268
|
Input,
|
|
984
1269
|
{
|
|
985
1270
|
label: "Email",
|
|
@@ -991,7 +1276,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
991
1276
|
autoComplete: "email"
|
|
992
1277
|
}
|
|
993
1278
|
),
|
|
994
|
-
/* @__PURE__ */ (0,
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
995
1280
|
Input,
|
|
996
1281
|
{
|
|
997
1282
|
label: "Password",
|
|
@@ -1001,19 +1286,19 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
1001
1286
|
onChange: setPassword,
|
|
1002
1287
|
error: fieldErrors.password,
|
|
1003
1288
|
autoComplete: "new-password",
|
|
1004
|
-
rightElement: /* @__PURE__ */ (0,
|
|
1289
|
+
rightElement: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1005
1290
|
"button",
|
|
1006
1291
|
{
|
|
1007
1292
|
type: "button",
|
|
1008
1293
|
onClick: () => setShowPassword((v) => !v),
|
|
1009
1294
|
style: { background: "none", border: "none", cursor: "pointer", padding: 0, display: "flex", color: theme.textMuted },
|
|
1010
1295
|
"aria-label": showPassword ? "Hide password" : "Show password",
|
|
1011
|
-
children: /* @__PURE__ */ (0,
|
|
1296
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: eyeIconPath }) })
|
|
1012
1297
|
}
|
|
1013
1298
|
)
|
|
1014
1299
|
}
|
|
1015
1300
|
),
|
|
1016
|
-
/* @__PURE__ */ (0,
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1017
1302
|
Input,
|
|
1018
1303
|
{
|
|
1019
1304
|
label: "Confirm password",
|
|
@@ -1025,7 +1310,7 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
1025
1310
|
autoComplete: "new-password"
|
|
1026
1311
|
}
|
|
1027
1312
|
),
|
|
1028
|
-
/* @__PURE__ */ (0,
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1029
1314
|
Button,
|
|
1030
1315
|
{
|
|
1031
1316
|
variant: "primary",
|
|
@@ -1037,23 +1322,23 @@ function SignUpCard({ afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
1037
1322
|
}
|
|
1038
1323
|
)
|
|
1039
1324
|
] }),
|
|
1040
|
-
/* @__PURE__ */ (0,
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: footerStyle, children: [
|
|
1041
1326
|
"Already have an account?",
|
|
1042
1327
|
" ",
|
|
1043
|
-
/* @__PURE__ */ (0,
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", style: linkStyle, onClick: onNavigateSignIn, children: "Sign in" })
|
|
1044
1329
|
] }),
|
|
1045
|
-
branding.showSecuredBy !== false && /* @__PURE__ */ (0,
|
|
1046
|
-
branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ (0,
|
|
1330
|
+
branding.showSecuredBy !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SecuredByAuthon2, { primaryStart: theme.primaryStart, textMuted: theme.textMuted }),
|
|
1331
|
+
branding.termsUrl || branding.privacyUrl ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { textAlign: "center", fontSize: 11, color: theme.textMuted, marginTop: -8 }, children: [
|
|
1047
1332
|
"By creating an account you agree to our",
|
|
1048
1333
|
" ",
|
|
1049
|
-
branding.termsUrl && /* @__PURE__ */ (0,
|
|
1334
|
+
branding.termsUrl && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: branding.termsUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Terms" }),
|
|
1050
1335
|
branding.termsUrl && branding.privacyUrl && " and ",
|
|
1051
|
-
branding.privacyUrl && /* @__PURE__ */ (0,
|
|
1336
|
+
branding.privacyUrl && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: branding.privacyUrl, target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryStart }, children: "Privacy Policy" })
|
|
1052
1337
|
] }) : null
|
|
1053
1338
|
] });
|
|
1054
1339
|
}
|
|
1055
1340
|
function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius }) {
|
|
1056
|
-
const [hovered, setHovered] = (0,
|
|
1341
|
+
const [hovered, setHovered] = (0, import_react9.useState)(false);
|
|
1057
1342
|
const colors = import_shared4.PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
|
|
1058
1343
|
const name = import_shared4.PROVIDER_DISPLAY_NAMES[provider] ?? provider;
|
|
1059
1344
|
const config = (0, import_js3.getProviderButtonConfig)(provider);
|
|
@@ -1079,7 +1364,7 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
|
|
|
1079
1364
|
transition: "opacity 0.15s",
|
|
1080
1365
|
boxSizing: "border-box"
|
|
1081
1366
|
};
|
|
1082
|
-
return /* @__PURE__ */ (0,
|
|
1367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1083
1368
|
"button",
|
|
1084
1369
|
{
|
|
1085
1370
|
type: "button",
|
|
@@ -1089,9 +1374,9 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
|
|
|
1089
1374
|
onMouseEnter: () => setHovered(true),
|
|
1090
1375
|
onMouseLeave: () => setHovered(false),
|
|
1091
1376
|
"aria-label": `Continue with ${name}`,
|
|
1092
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
1093
|
-
/* @__PURE__ */ (0,
|
|
1094
|
-
/* @__PURE__ */ (0,
|
|
1377
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("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__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { display: "flex", alignItems: "center" }, dangerouslySetInnerHTML: { __html: config.iconSvg } }),
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
|
|
1095
1380
|
"Continue with ",
|
|
1096
1381
|
name
|
|
1097
1382
|
] })
|
|
@@ -1100,7 +1385,7 @@ function OAuthButtonFull({ provider, loading, disabled, onClick, borderRadius })
|
|
|
1100
1385
|
);
|
|
1101
1386
|
}
|
|
1102
1387
|
function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius }) {
|
|
1103
|
-
const [hovered, setHovered] = (0,
|
|
1388
|
+
const [hovered, setHovered] = (0, import_react9.useState)(false);
|
|
1104
1389
|
const colors = import_shared4.PROVIDER_COLORS[provider] ?? { bg: "#333", text: "#fff" };
|
|
1105
1390
|
const name = import_shared4.PROVIDER_DISPLAY_NAMES[provider] ?? provider;
|
|
1106
1391
|
const config = (0, import_js3.getProviderButtonConfig)(provider);
|
|
@@ -1119,7 +1404,7 @@ function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius })
|
|
|
1119
1404
|
transition: "opacity 0.15s",
|
|
1120
1405
|
padding: 0
|
|
1121
1406
|
};
|
|
1122
|
-
return /* @__PURE__ */ (0,
|
|
1407
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1123
1408
|
"button",
|
|
1124
1409
|
{
|
|
1125
1410
|
type: "button",
|
|
@@ -1129,29 +1414,29 @@ function CompactOAuthBtn({ provider, loading, disabled, onClick, borderRadius })
|
|
|
1129
1414
|
onMouseEnter: () => setHovered(true),
|
|
1130
1415
|
onMouseLeave: () => setHovered(false),
|
|
1131
1416
|
"aria-label": `Continue with ${name}`,
|
|
1132
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
1417
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("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__ */ (0, import_jsx_runtime8.jsx)("span", { style: { display: "flex" }, dangerouslySetInnerHTML: { __html: config.iconSvg } })
|
|
1133
1418
|
}
|
|
1134
1419
|
);
|
|
1135
1420
|
}
|
|
1136
1421
|
function SecuredByAuthon2({ primaryStart, textMuted }) {
|
|
1137
|
-
return /* @__PURE__ */ (0,
|
|
1138
|
-
/* @__PURE__ */ (0,
|
|
1139
|
-
/* @__PURE__ */ (0,
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 5, marginTop: -8 }, children: [
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "12", height: "14", viewBox: "0 0 12 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("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" }),
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 7L5.5 8.5L8.5 5.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1141
1426
|
] }),
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { style: { fontSize: 11, color: textMuted }, children: [
|
|
1143
1428
|
"Secured by",
|
|
1144
1429
|
" ",
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: "https://authon.dev", target: "_blank", rel: "noopener noreferrer", style: { color: primaryStart, textDecoration: "none", fontWeight: 600 }, children: "Authon" })
|
|
1146
1431
|
] })
|
|
1147
1432
|
] });
|
|
1148
1433
|
}
|
|
1149
1434
|
function SignUp({ appearance, afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
1150
1435
|
const { branding, isLoaded } = useBranding();
|
|
1151
1436
|
const effectiveBranding = isLoaded ? { ...branding, ...appearance?.variables ?? {} } : branding;
|
|
1152
|
-
return /* @__PURE__ */ (0,
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1154
|
-
/* @__PURE__ */ (0,
|
|
1437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ThemeProvider, { branding: effectiveBranding, overrides: appearance?.variables, style: { display: "flex", justifyContent: "center" }, children: [
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1155
1440
|
SignUpCard,
|
|
1156
1441
|
{
|
|
1157
1442
|
afterSignUpUrl,
|
|
@@ -1163,8 +1448,8 @@ function SignUp({ appearance, afterSignUpUrl, onSignUp, onNavigateSignIn }) {
|
|
|
1163
1448
|
}
|
|
1164
1449
|
|
|
1165
1450
|
// src/components/UserButton.tsx
|
|
1166
|
-
var
|
|
1167
|
-
var
|
|
1451
|
+
var import_react10 = require("react");
|
|
1452
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1168
1453
|
function UserAvatar({
|
|
1169
1454
|
avatarUrl,
|
|
1170
1455
|
displayName,
|
|
@@ -1188,24 +1473,24 @@ function UserAvatar({
|
|
|
1188
1473
|
fontWeight: 700,
|
|
1189
1474
|
userSelect: "none"
|
|
1190
1475
|
};
|
|
1191
|
-
return /* @__PURE__ */ (0,
|
|
1476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: avatarStyle, children: avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: avatarUrl, alt: displayName ?? "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials });
|
|
1192
1477
|
}
|
|
1193
1478
|
function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
1194
1479
|
const theme = useTheme();
|
|
1195
1480
|
const { user, signOut, openSignIn, isSignedIn, activeOrganization, client } = useAuthon();
|
|
1196
|
-
const [open, setOpen] = (0,
|
|
1197
|
-
const dropdownRef = (0,
|
|
1198
|
-
const handleClickOutside = (0,
|
|
1481
|
+
const [open, setOpen] = (0, import_react10.useState)(false);
|
|
1482
|
+
const dropdownRef = (0, import_react10.useRef)(null);
|
|
1483
|
+
const handleClickOutside = (0, import_react10.useCallback)((e) => {
|
|
1199
1484
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1200
1485
|
setOpen(false);
|
|
1201
1486
|
}
|
|
1202
1487
|
}, []);
|
|
1203
|
-
(0,
|
|
1488
|
+
(0, import_react10.useEffect)(() => {
|
|
1204
1489
|
if (open) document.addEventListener("mousedown", handleClickOutside);
|
|
1205
1490
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1206
1491
|
}, [open, handleClickOutside]);
|
|
1207
1492
|
if (!isSignedIn) {
|
|
1208
|
-
return /* @__PURE__ */ (0,
|
|
1493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1209
1494
|
"button",
|
|
1210
1495
|
{
|
|
1211
1496
|
type: "button",
|
|
@@ -1274,8 +1559,8 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1274
1559
|
fontFamily: theme.fontFamily,
|
|
1275
1560
|
boxSizing: "border-box"
|
|
1276
1561
|
});
|
|
1277
|
-
return /* @__PURE__ */ (0,
|
|
1278
|
-
/* @__PURE__ */ (0,
|
|
1562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref: dropdownRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", style: triggerStyle, onClick: () => setOpen((v) => !v), "aria-label": "User menu", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1279
1564
|
UserAvatar,
|
|
1280
1565
|
{
|
|
1281
1566
|
avatarUrl: user?.avatarUrl,
|
|
@@ -1286,9 +1571,9 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1286
1571
|
primaryEnd: theme.primaryEnd
|
|
1287
1572
|
}
|
|
1288
1573
|
) }),
|
|
1289
|
-
open && /* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1574
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: dropdownStyle, children: [
|
|
1575
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: headerStyle, children: [
|
|
1576
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1292
1577
|
UserAvatar,
|
|
1293
1578
|
{
|
|
1294
1579
|
avatarUrl: user?.avatarUrl,
|
|
@@ -1299,12 +1584,12 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1299
1584
|
primaryEnd: theme.primaryEnd
|
|
1300
1585
|
}
|
|
1301
1586
|
),
|
|
1302
|
-
/* @__PURE__ */ (0,
|
|
1303
|
-
user?.displayName && /* @__PURE__ */ (0,
|
|
1304
|
-
user?.email && /* @__PURE__ */ (0,
|
|
1587
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1588
|
+
user?.displayName && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: 14, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: user.displayName }),
|
|
1589
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: 12, color: theme.textMuted, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 1 }, children: user.email })
|
|
1305
1590
|
] })
|
|
1306
1591
|
] }),
|
|
1307
|
-
activeOrganization && /* @__PURE__ */ (0,
|
|
1592
|
+
activeOrganization && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1308
1593
|
OrgSwitcherRow,
|
|
1309
1594
|
{
|
|
1310
1595
|
org: activeOrganization,
|
|
@@ -1313,7 +1598,7 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1313
1598
|
client
|
|
1314
1599
|
}
|
|
1315
1600
|
),
|
|
1316
|
-
userProfileUrl && /* @__PURE__ */ (0,
|
|
1601
|
+
userProfileUrl && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1317
1602
|
MenuButton,
|
|
1318
1603
|
{
|
|
1319
1604
|
style: menuItemStyle(),
|
|
@@ -1321,14 +1606,14 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1321
1606
|
setOpen(false);
|
|
1322
1607
|
window.location.assign(userProfileUrl);
|
|
1323
1608
|
},
|
|
1324
|
-
icon: /* @__PURE__ */ (0,
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1326
|
-
/* @__PURE__ */ (0,
|
|
1609
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" }),
|
|
1611
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { cx: "12", cy: "7", r: "4" })
|
|
1327
1612
|
] }),
|
|
1328
1613
|
children: "Manage account"
|
|
1329
1614
|
}
|
|
1330
1615
|
),
|
|
1331
|
-
/* @__PURE__ */ (0,
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1332
1617
|
MenuButton,
|
|
1333
1618
|
{
|
|
1334
1619
|
style: menuItemStyle(true),
|
|
@@ -1337,10 +1622,10 @@ function UserButtonInner({ afterSignOutUrl, userProfileUrl }) {
|
|
|
1337
1622
|
await signOut();
|
|
1338
1623
|
if (afterSignOutUrl) window.location.assign(afterSignOutUrl);
|
|
1339
1624
|
},
|
|
1340
|
-
icon: /* @__PURE__ */ (0,
|
|
1341
|
-
/* @__PURE__ */ (0,
|
|
1342
|
-
/* @__PURE__ */ (0,
|
|
1343
|
-
/* @__PURE__ */ (0,
|
|
1625
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1626
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4" }),
|
|
1627
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "16 17 21 12 16 7" }),
|
|
1628
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
|
|
1344
1629
|
] }),
|
|
1345
1630
|
children: "Sign out"
|
|
1346
1631
|
}
|
|
@@ -1354,8 +1639,8 @@ function MenuButton({
|
|
|
1354
1639
|
icon,
|
|
1355
1640
|
children
|
|
1356
1641
|
}) {
|
|
1357
|
-
const [hovered, setHovered] = (0,
|
|
1358
|
-
return /* @__PURE__ */ (0,
|
|
1642
|
+
const [hovered, setHovered] = (0, import_react10.useState)(false);
|
|
1643
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1359
1644
|
"button",
|
|
1360
1645
|
{
|
|
1361
1646
|
type: "button",
|
|
@@ -1379,7 +1664,7 @@ function OrgSwitcherRow({
|
|
|
1379
1664
|
theme,
|
|
1380
1665
|
client
|
|
1381
1666
|
}) {
|
|
1382
|
-
return /* @__PURE__ */ (0,
|
|
1667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1383
1668
|
"div",
|
|
1384
1669
|
{
|
|
1385
1670
|
style: {
|
|
@@ -1390,7 +1675,7 @@ function OrgSwitcherRow({
|
|
|
1390
1675
|
gap: 10
|
|
1391
1676
|
},
|
|
1392
1677
|
children: [
|
|
1393
|
-
org.logoUrl ? /* @__PURE__ */ (0,
|
|
1678
|
+
org.logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: org.logoUrl, alt: org.name, style: { width: 24, height: 24, borderRadius: 6, objectFit: "cover" } }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1394
1679
|
"div",
|
|
1395
1680
|
{
|
|
1396
1681
|
style: {
|
|
@@ -1408,9 +1693,9 @@ function OrgSwitcherRow({
|
|
|
1408
1693
|
children: org.name[0]?.toUpperCase()
|
|
1409
1694
|
}
|
|
1410
1695
|
),
|
|
1411
|
-
/* @__PURE__ */ (0,
|
|
1412
|
-
/* @__PURE__ */ (0,
|
|
1413
|
-
/* @__PURE__ */ (0,
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1697
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: 12, color: theme.textMuted }, children: "Organization" }),
|
|
1698
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: 13, fontWeight: 600, color: theme.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: org.name })
|
|
1414
1699
|
] })
|
|
1415
1700
|
]
|
|
1416
1701
|
}
|
|
@@ -1419,39 +1704,39 @@ function OrgSwitcherRow({
|
|
|
1419
1704
|
function UserButton({ appearance, afterSignOutUrl, userProfileUrl }) {
|
|
1420
1705
|
const { branding } = useBranding();
|
|
1421
1706
|
const effectiveBranding = { ...branding, ...appearance?.variables ?? {} };
|
|
1422
|
-
return /* @__PURE__ */ (0,
|
|
1707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ThemeProvider, { branding: effectiveBranding, style: { display: "inline-block" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UserButtonInner, { afterSignOutUrl, userProfileUrl }) });
|
|
1423
1708
|
}
|
|
1424
1709
|
|
|
1425
1710
|
// src/SignedIn.tsx
|
|
1426
|
-
var
|
|
1711
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1427
1712
|
function SignedIn({ children }) {
|
|
1428
1713
|
const { isSignedIn, isLoading } = useAuthon();
|
|
1429
1714
|
if (isLoading || !isSignedIn) return null;
|
|
1430
|
-
return /* @__PURE__ */ (0,
|
|
1715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children });
|
|
1431
1716
|
}
|
|
1432
1717
|
|
|
1433
1718
|
// src/SignedOut.tsx
|
|
1434
|
-
var
|
|
1719
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1435
1720
|
function SignedOut({ children }) {
|
|
1436
1721
|
const { isSignedIn, isLoading } = useAuthon();
|
|
1437
1722
|
if (isLoading || isSignedIn) return null;
|
|
1438
|
-
return /* @__PURE__ */ (0,
|
|
1723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children });
|
|
1439
1724
|
}
|
|
1440
1725
|
|
|
1441
1726
|
// src/Protect.tsx
|
|
1442
|
-
var
|
|
1727
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1443
1728
|
function Protect({ children, fallback = null, condition }) {
|
|
1444
1729
|
const { isSignedIn, isLoading, user } = useAuthon();
|
|
1445
1730
|
if (isLoading) return null;
|
|
1446
|
-
if (!isSignedIn || !user) return /* @__PURE__ */ (0,
|
|
1447
|
-
if (condition && !condition(user)) return /* @__PURE__ */ (0,
|
|
1448
|
-
return /* @__PURE__ */ (0,
|
|
1731
|
+
if (!isSignedIn || !user) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: fallback });
|
|
1732
|
+
if (condition && !condition(user)) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: fallback });
|
|
1733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children });
|
|
1449
1734
|
}
|
|
1450
1735
|
|
|
1451
1736
|
// src/SocialButton.tsx
|
|
1452
1737
|
var import_shared5 = require("@authon/shared");
|
|
1453
1738
|
var import_js4 = require("@authon/js");
|
|
1454
|
-
var
|
|
1739
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1455
1740
|
var baseStyle = {
|
|
1456
1741
|
display: "flex",
|
|
1457
1742
|
alignItems: "center",
|
|
@@ -1497,7 +1782,7 @@ function SocialButton({
|
|
|
1497
1782
|
const iconSvg = config.iconSvg.replace(/width="\d+"/, `width="${resolvedIconSize}"`).replace(/height="\d+"/, `height="${resolvedIconSize}"`);
|
|
1498
1783
|
const borderProps = needsBorder ? { border: "1px solid #dadce0" } : {};
|
|
1499
1784
|
if (compact) {
|
|
1500
|
-
return /* @__PURE__ */ (0,
|
|
1785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1501
1786
|
"button",
|
|
1502
1787
|
{
|
|
1503
1788
|
className,
|
|
@@ -1513,7 +1798,7 @@ function SocialButton({
|
|
|
1513
1798
|
onClick: () => onClick(provider),
|
|
1514
1799
|
disabled: disabled || loading,
|
|
1515
1800
|
"aria-label": `Sign in with ${displayName}`,
|
|
1516
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
1801
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1517
1802
|
"span",
|
|
1518
1803
|
{
|
|
1519
1804
|
style: {
|
|
@@ -1526,7 +1811,7 @@ function SocialButton({
|
|
|
1526
1811
|
animation: "authon-spin 0.6s linear infinite"
|
|
1527
1812
|
}
|
|
1528
1813
|
}
|
|
1529
|
-
) : /* @__PURE__ */ (0,
|
|
1814
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1530
1815
|
"span",
|
|
1531
1816
|
{
|
|
1532
1817
|
style: { display: "flex", alignItems: "center", flexShrink: 0 },
|
|
@@ -1536,7 +1821,7 @@ function SocialButton({
|
|
|
1536
1821
|
}
|
|
1537
1822
|
);
|
|
1538
1823
|
}
|
|
1539
|
-
return /* @__PURE__ */ (0,
|
|
1824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1540
1825
|
"button",
|
|
1541
1826
|
{
|
|
1542
1827
|
className,
|
|
@@ -1552,7 +1837,7 @@ function SocialButton({
|
|
|
1552
1837
|
onClick: () => onClick(provider),
|
|
1553
1838
|
disabled: disabled || loading,
|
|
1554
1839
|
"aria-label": `Sign in with ${displayName}`,
|
|
1555
|
-
children: loading ? /* @__PURE__ */ (0,
|
|
1840
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1556
1841
|
"span",
|
|
1557
1842
|
{
|
|
1558
1843
|
style: {
|
|
@@ -1565,23 +1850,23 @@ function SocialButton({
|
|
|
1565
1850
|
animation: "authon-spin 0.6s linear infinite"
|
|
1566
1851
|
}
|
|
1567
1852
|
}
|
|
1568
|
-
) : /* @__PURE__ */ (0,
|
|
1569
|
-
/* @__PURE__ */ (0,
|
|
1853
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
1854
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1570
1855
|
"span",
|
|
1571
1856
|
{
|
|
1572
1857
|
style: { display: "flex", alignItems: "center", flexShrink: 0 },
|
|
1573
1858
|
dangerouslySetInnerHTML: { __html: iconSvg }
|
|
1574
1859
|
}
|
|
1575
1860
|
),
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1861
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 15, fontWeight: 600, whiteSpace: "nowrap" }, children: buttonLabel })
|
|
1577
1862
|
] })
|
|
1578
1863
|
}
|
|
1579
1864
|
);
|
|
1580
1865
|
}
|
|
1581
1866
|
|
|
1582
1867
|
// src/SocialButtons.tsx
|
|
1583
|
-
var
|
|
1584
|
-
var
|
|
1868
|
+
var import_react11 = require("react");
|
|
1869
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1585
1870
|
function SocialButtons({
|
|
1586
1871
|
onSuccess,
|
|
1587
1872
|
onError,
|
|
@@ -1593,9 +1878,9 @@ function SocialButtons({
|
|
|
1593
1878
|
buttonProps
|
|
1594
1879
|
}) {
|
|
1595
1880
|
const { client } = useAuthon();
|
|
1596
|
-
const [providers, setProviders] = (0,
|
|
1597
|
-
const [loadingProvider, setLoadingProvider] = (0,
|
|
1598
|
-
(0,
|
|
1881
|
+
const [providers, setProviders] = (0, import_react11.useState)([]);
|
|
1882
|
+
const [loadingProvider, setLoadingProvider] = (0, import_react11.useState)(null);
|
|
1883
|
+
(0, import_react11.useEffect)(() => {
|
|
1599
1884
|
if (!client) return;
|
|
1600
1885
|
client.getProviders().then((p) => setProviders(p));
|
|
1601
1886
|
}, [client]);
|
|
@@ -1615,7 +1900,7 @@ function SocialButtons({
|
|
|
1615
1900
|
}
|
|
1616
1901
|
};
|
|
1617
1902
|
const containerStyle = compact ? { display: "flex", flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: resolvedGap, ...userStyle } : { display: "flex", flexDirection: "column", gap: resolvedGap, ...userStyle };
|
|
1618
|
-
return /* @__PURE__ */ (0,
|
|
1903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1619
1904
|
SocialButton,
|
|
1620
1905
|
{
|
|
1621
1906
|
provider,
|
|
@@ -1631,13 +1916,13 @@ function SocialButtons({
|
|
|
1631
1916
|
}
|
|
1632
1917
|
|
|
1633
1918
|
// src/useAuthonMfa.ts
|
|
1634
|
-
var
|
|
1919
|
+
var import_react12 = require("react");
|
|
1635
1920
|
function useAuthonMfa() {
|
|
1636
|
-
const ctx = (0,
|
|
1921
|
+
const ctx = (0, import_react12.useContext)(AuthonContext);
|
|
1637
1922
|
if (!ctx) throw new Error("useAuthonMfa must be used within <AuthonProvider>");
|
|
1638
|
-
const [isLoading, setIsLoading] = (0,
|
|
1639
|
-
const [error, setError] = (0,
|
|
1640
|
-
const wrap = (0,
|
|
1923
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
|
|
1924
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
1925
|
+
const wrap = (0, import_react12.useCallback)(
|
|
1641
1926
|
async (fn) => {
|
|
1642
1927
|
setIsLoading(true);
|
|
1643
1928
|
setError(null);
|
|
@@ -1653,34 +1938,34 @@ function useAuthonMfa() {
|
|
|
1653
1938
|
},
|
|
1654
1939
|
[]
|
|
1655
1940
|
);
|
|
1656
|
-
const setupMfa = (0,
|
|
1941
|
+
const setupMfa = (0, import_react12.useCallback)(async () => {
|
|
1657
1942
|
return wrap(() => ctx.client.setupMfa());
|
|
1658
1943
|
}, [ctx.client, wrap]);
|
|
1659
|
-
const verifyMfaSetup = (0,
|
|
1944
|
+
const verifyMfaSetup = (0, import_react12.useCallback)(
|
|
1660
1945
|
async (code) => {
|
|
1661
1946
|
const result = await wrap(() => ctx.client.verifyMfaSetup(code));
|
|
1662
1947
|
return result !== null;
|
|
1663
1948
|
},
|
|
1664
1949
|
[ctx.client, wrap]
|
|
1665
1950
|
);
|
|
1666
|
-
const verifyMfa = (0,
|
|
1951
|
+
const verifyMfa = (0, import_react12.useCallback)(
|
|
1667
1952
|
async (mfaToken, code) => {
|
|
1668
1953
|
const result = await wrap(() => ctx.client.verifyMfa(mfaToken, code));
|
|
1669
1954
|
return result !== null;
|
|
1670
1955
|
},
|
|
1671
1956
|
[ctx.client, wrap]
|
|
1672
1957
|
);
|
|
1673
|
-
const disableMfa = (0,
|
|
1958
|
+
const disableMfa = (0, import_react12.useCallback)(
|
|
1674
1959
|
async (code) => {
|
|
1675
1960
|
const result = await wrap(() => ctx.client.disableMfa(code));
|
|
1676
1961
|
return result !== null;
|
|
1677
1962
|
},
|
|
1678
1963
|
[ctx.client, wrap]
|
|
1679
1964
|
);
|
|
1680
|
-
const getMfaStatus = (0,
|
|
1965
|
+
const getMfaStatus = (0, import_react12.useCallback)(async () => {
|
|
1681
1966
|
return wrap(() => ctx.client.getMfaStatus());
|
|
1682
1967
|
}, [ctx.client, wrap]);
|
|
1683
|
-
const regenerateBackupCodes = (0,
|
|
1968
|
+
const regenerateBackupCodes = (0, import_react12.useCallback)(
|
|
1684
1969
|
async (code) => {
|
|
1685
1970
|
return wrap(() => ctx.client.regenerateBackupCodes(code));
|
|
1686
1971
|
},
|
|
@@ -1699,13 +1984,13 @@ function useAuthonMfa() {
|
|
|
1699
1984
|
}
|
|
1700
1985
|
|
|
1701
1986
|
// src/useAuthonPasskeys.ts
|
|
1702
|
-
var
|
|
1987
|
+
var import_react13 = require("react");
|
|
1703
1988
|
function useAuthonPasskeys() {
|
|
1704
|
-
const ctx = (0,
|
|
1989
|
+
const ctx = (0, import_react13.useContext)(AuthonContext);
|
|
1705
1990
|
if (!ctx) throw new Error("useAuthonPasskeys must be used within <AuthonProvider>");
|
|
1706
|
-
const [isLoading, setIsLoading] = (0,
|
|
1707
|
-
const [error, setError] = (0,
|
|
1708
|
-
const wrap = (0,
|
|
1991
|
+
const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
|
|
1992
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
1993
|
+
const wrap = (0, import_react13.useCallback)(
|
|
1709
1994
|
async (fn) => {
|
|
1710
1995
|
setIsLoading(true);
|
|
1711
1996
|
setError(null);
|
|
@@ -1720,26 +2005,26 @@ function useAuthonPasskeys() {
|
|
|
1720
2005
|
},
|
|
1721
2006
|
[]
|
|
1722
2007
|
);
|
|
1723
|
-
const registerPasskey = (0,
|
|
2008
|
+
const registerPasskey = (0, import_react13.useCallback)(
|
|
1724
2009
|
(name) => wrap(() => ctx.client.registerPasskey(name)),
|
|
1725
2010
|
[ctx.client, wrap]
|
|
1726
2011
|
);
|
|
1727
|
-
const authenticateWithPasskey = (0,
|
|
2012
|
+
const authenticateWithPasskey = (0, import_react13.useCallback)(
|
|
1728
2013
|
async (email) => {
|
|
1729
2014
|
const result = await wrap(() => ctx.client.authenticateWithPasskey(email));
|
|
1730
2015
|
return result !== null;
|
|
1731
2016
|
},
|
|
1732
2017
|
[ctx.client, wrap]
|
|
1733
2018
|
);
|
|
1734
|
-
const listPasskeys = (0,
|
|
2019
|
+
const listPasskeys = (0, import_react13.useCallback)(
|
|
1735
2020
|
() => wrap(() => ctx.client.listPasskeys()),
|
|
1736
2021
|
[ctx.client, wrap]
|
|
1737
2022
|
);
|
|
1738
|
-
const renamePasskey = (0,
|
|
2023
|
+
const renamePasskey = (0, import_react13.useCallback)(
|
|
1739
2024
|
(id, name) => wrap(() => ctx.client.renamePasskey(id, name)),
|
|
1740
2025
|
[ctx.client, wrap]
|
|
1741
2026
|
);
|
|
1742
|
-
const revokePasskey = (0,
|
|
2027
|
+
const revokePasskey = (0, import_react13.useCallback)(
|
|
1743
2028
|
async (id) => {
|
|
1744
2029
|
const result = await wrap(() => ctx.client.revokePasskey(id));
|
|
1745
2030
|
return result !== null;
|
|
@@ -1758,13 +2043,13 @@ function useAuthonPasskeys() {
|
|
|
1758
2043
|
}
|
|
1759
2044
|
|
|
1760
2045
|
// src/useAuthonPasswordless.ts
|
|
1761
|
-
var
|
|
2046
|
+
var import_react14 = require("react");
|
|
1762
2047
|
function useAuthonPasswordless() {
|
|
1763
|
-
const ctx = (0,
|
|
2048
|
+
const ctx = (0, import_react14.useContext)(AuthonContext);
|
|
1764
2049
|
if (!ctx) throw new Error("useAuthonPasswordless must be used within <AuthonProvider>");
|
|
1765
|
-
const [isLoading, setIsLoading] = (0,
|
|
1766
|
-
const [error, setError] = (0,
|
|
1767
|
-
const wrap = (0,
|
|
2050
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
|
|
2051
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2052
|
+
const wrap = (0, import_react14.useCallback)(
|
|
1768
2053
|
async (fn) => {
|
|
1769
2054
|
setIsLoading(true);
|
|
1770
2055
|
setError(null);
|
|
@@ -1779,21 +2064,21 @@ function useAuthonPasswordless() {
|
|
|
1779
2064
|
},
|
|
1780
2065
|
[]
|
|
1781
2066
|
);
|
|
1782
|
-
const sendMagicLink = (0,
|
|
2067
|
+
const sendMagicLink = (0, import_react14.useCallback)(
|
|
1783
2068
|
async (email) => {
|
|
1784
2069
|
const result = await wrap(() => ctx.client.sendMagicLink(email));
|
|
1785
2070
|
return result !== null;
|
|
1786
2071
|
},
|
|
1787
2072
|
[ctx.client, wrap]
|
|
1788
2073
|
);
|
|
1789
|
-
const sendEmailOtp = (0,
|
|
2074
|
+
const sendEmailOtp = (0, import_react14.useCallback)(
|
|
1790
2075
|
async (email) => {
|
|
1791
2076
|
const result = await wrap(() => ctx.client.sendEmailOtp(email));
|
|
1792
2077
|
return result !== null;
|
|
1793
2078
|
},
|
|
1794
2079
|
[ctx.client, wrap]
|
|
1795
2080
|
);
|
|
1796
|
-
const verifyPasswordless = (0,
|
|
2081
|
+
const verifyPasswordless = (0, import_react14.useCallback)(
|
|
1797
2082
|
async (opts) => {
|
|
1798
2083
|
const result = await wrap(() => ctx.client.verifyPasswordless(opts));
|
|
1799
2084
|
return result !== null;
|
|
@@ -1810,13 +2095,13 @@ function useAuthonPasswordless() {
|
|
|
1810
2095
|
}
|
|
1811
2096
|
|
|
1812
2097
|
// src/useAuthonWeb3.ts
|
|
1813
|
-
var
|
|
2098
|
+
var import_react15 = require("react");
|
|
1814
2099
|
function useAuthonWeb3() {
|
|
1815
|
-
const ctx = (0,
|
|
2100
|
+
const ctx = (0, import_react15.useContext)(AuthonContext);
|
|
1816
2101
|
if (!ctx) throw new Error("useAuthonWeb3 must be used within <AuthonProvider>");
|
|
1817
|
-
const [isLoading, setIsLoading] = (0,
|
|
1818
|
-
const [error, setError] = (0,
|
|
1819
|
-
const wrap = (0,
|
|
2102
|
+
const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
|
|
2103
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
2104
|
+
const wrap = (0, import_react15.useCallback)(
|
|
1820
2105
|
async (fn) => {
|
|
1821
2106
|
setIsLoading(true);
|
|
1822
2107
|
setError(null);
|
|
@@ -1831,11 +2116,11 @@ function useAuthonWeb3() {
|
|
|
1831
2116
|
},
|
|
1832
2117
|
[]
|
|
1833
2118
|
);
|
|
1834
|
-
const getNonce = (0,
|
|
2119
|
+
const getNonce = (0, import_react15.useCallback)(
|
|
1835
2120
|
(address, chain, walletType, chainId) => wrap(() => ctx.client.web3GetNonce(address, chain, walletType, chainId)),
|
|
1836
2121
|
[ctx.client, wrap]
|
|
1837
2122
|
);
|
|
1838
|
-
const verify = (0,
|
|
2123
|
+
const verify = (0, import_react15.useCallback)(
|
|
1839
2124
|
async (message, signature, address, chain, walletType) => {
|
|
1840
2125
|
const result = await wrap(
|
|
1841
2126
|
() => ctx.client.web3Verify(message, signature, address, chain, walletType)
|
|
@@ -1844,15 +2129,15 @@ function useAuthonWeb3() {
|
|
|
1844
2129
|
},
|
|
1845
2130
|
[ctx.client, wrap]
|
|
1846
2131
|
);
|
|
1847
|
-
const listWallets = (0,
|
|
2132
|
+
const listWallets = (0, import_react15.useCallback)(
|
|
1848
2133
|
() => wrap(() => ctx.client.listWallets()),
|
|
1849
2134
|
[ctx.client, wrap]
|
|
1850
2135
|
);
|
|
1851
|
-
const linkWallet = (0,
|
|
2136
|
+
const linkWallet = (0, import_react15.useCallback)(
|
|
1852
2137
|
(params) => wrap(() => ctx.client.linkWallet(params)),
|
|
1853
2138
|
[ctx.client, wrap]
|
|
1854
2139
|
);
|
|
1855
|
-
const unlinkWallet = (0,
|
|
2140
|
+
const unlinkWallet = (0, import_react15.useCallback)(
|
|
1856
2141
|
async (walletId) => {
|
|
1857
2142
|
const result = await wrap(() => ctx.client.unlinkWallet(walletId));
|
|
1858
2143
|
return result !== null;
|
|
@@ -1871,13 +2156,13 @@ function useAuthonWeb3() {
|
|
|
1871
2156
|
}
|
|
1872
2157
|
|
|
1873
2158
|
// src/useAuthonSessions.ts
|
|
1874
|
-
var
|
|
2159
|
+
var import_react16 = require("react");
|
|
1875
2160
|
function useAuthonSessions() {
|
|
1876
|
-
const ctx = (0,
|
|
2161
|
+
const ctx = (0, import_react16.useContext)(AuthonContext);
|
|
1877
2162
|
if (!ctx) throw new Error("useAuthonSessions must be used within <AuthonProvider>");
|
|
1878
|
-
const [isLoading, setIsLoading] = (0,
|
|
1879
|
-
const [error, setError] = (0,
|
|
1880
|
-
const wrap = (0,
|
|
2163
|
+
const [isLoading, setIsLoading] = (0, import_react16.useState)(false);
|
|
2164
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
2165
|
+
const wrap = (0, import_react16.useCallback)(
|
|
1881
2166
|
async (fn) => {
|
|
1882
2167
|
setIsLoading(true);
|
|
1883
2168
|
setError(null);
|
|
@@ -1892,11 +2177,11 @@ function useAuthonSessions() {
|
|
|
1892
2177
|
},
|
|
1893
2178
|
[]
|
|
1894
2179
|
);
|
|
1895
|
-
const listSessions = (0,
|
|
2180
|
+
const listSessions = (0, import_react16.useCallback)(
|
|
1896
2181
|
() => wrap(() => ctx.client.listSessions()),
|
|
1897
2182
|
[ctx.client, wrap]
|
|
1898
2183
|
);
|
|
1899
|
-
const revokeSession = (0,
|
|
2184
|
+
const revokeSession = (0, import_react16.useCallback)(
|
|
1900
2185
|
async (sessionId) => {
|
|
1901
2186
|
const result = await wrap(() => ctx.client.revokeSession(sessionId));
|
|
1902
2187
|
return result !== null;
|
|
@@ -1912,14 +2197,14 @@ function useAuthonSessions() {
|
|
|
1912
2197
|
}
|
|
1913
2198
|
|
|
1914
2199
|
// src/useOrganization.ts
|
|
1915
|
-
var
|
|
2200
|
+
var import_react17 = require("react");
|
|
1916
2201
|
function useOrganization() {
|
|
1917
|
-
const ctx = (0,
|
|
2202
|
+
const ctx = (0, import_react17.useContext)(AuthonContext);
|
|
1918
2203
|
if (!ctx) throw new Error("useOrganization must be used within <AuthonProvider>");
|
|
1919
|
-
const [members, setMembers] = (0,
|
|
1920
|
-
const [isLoaded, setIsLoaded] = (0,
|
|
2204
|
+
const [members, setMembers] = (0, import_react17.useState)([]);
|
|
2205
|
+
const [isLoaded, setIsLoaded] = (0, import_react17.useState)(false);
|
|
1921
2206
|
const organization = ctx.activeOrganization;
|
|
1922
|
-
(0,
|
|
2207
|
+
(0, import_react17.useEffect)(() => {
|
|
1923
2208
|
if (!organization || !ctx.client) {
|
|
1924
2209
|
setMembers([]);
|
|
1925
2210
|
setIsLoaded(!organization);
|
|
@@ -1942,13 +2227,13 @@ function useOrganization() {
|
|
|
1942
2227
|
}
|
|
1943
2228
|
|
|
1944
2229
|
// src/useOrganizationList.ts
|
|
1945
|
-
var
|
|
2230
|
+
var import_react18 = require("react");
|
|
1946
2231
|
function useOrganizationList() {
|
|
1947
|
-
const ctx = (0,
|
|
2232
|
+
const ctx = (0, import_react18.useContext)(AuthonContext);
|
|
1948
2233
|
if (!ctx) throw new Error("useOrganizationList must be used within <AuthonProvider>");
|
|
1949
|
-
const [organizations, setOrganizations] = (0,
|
|
1950
|
-
const [isLoaded, setIsLoaded] = (0,
|
|
1951
|
-
(0,
|
|
2234
|
+
const [organizations, setOrganizations] = (0, import_react18.useState)([]);
|
|
2235
|
+
const [isLoaded, setIsLoaded] = (0, import_react18.useState)(false);
|
|
2236
|
+
(0, import_react18.useEffect)(() => {
|
|
1952
2237
|
if (!ctx.client || !ctx.isSignedIn) {
|
|
1953
2238
|
setOrganizations([]);
|
|
1954
2239
|
setIsLoaded(!ctx.isSignedIn);
|
|
@@ -1963,7 +2248,7 @@ function useOrganizationList() {
|
|
|
1963
2248
|
setIsLoaded(true);
|
|
1964
2249
|
});
|
|
1965
2250
|
}, [ctx.client, ctx.isSignedIn]);
|
|
1966
|
-
const createOrganization = (0,
|
|
2251
|
+
const createOrganization = (0, import_react18.useCallback)(
|
|
1967
2252
|
async (params) => {
|
|
1968
2253
|
if (!ctx.client) return null;
|
|
1969
2254
|
try {
|
|
@@ -1976,7 +2261,7 @@ function useOrganizationList() {
|
|
|
1976
2261
|
},
|
|
1977
2262
|
[ctx.client]
|
|
1978
2263
|
);
|
|
1979
|
-
const setActive = (0,
|
|
2264
|
+
const setActive = (0, import_react18.useCallback)(
|
|
1980
2265
|
(org) => {
|
|
1981
2266
|
ctx.setActiveOrganization(org);
|
|
1982
2267
|
},
|
|
@@ -1991,16 +2276,16 @@ function useOrganizationList() {
|
|
|
1991
2276
|
}
|
|
1992
2277
|
|
|
1993
2278
|
// src/components/UserProfile.tsx
|
|
1994
|
-
var
|
|
1995
|
-
var
|
|
2279
|
+
var import_react19 = require("react");
|
|
2280
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1996
2281
|
function ProfileTab() {
|
|
1997
2282
|
const theme = useTheme();
|
|
1998
2283
|
const { user, client } = useAuthon();
|
|
1999
|
-
const [displayName, setDisplayName] = (0,
|
|
2000
|
-
const [phone, setPhone] = (0,
|
|
2001
|
-
const [loading, setLoading] = (0,
|
|
2002
|
-
const [success, setSuccess] = (0,
|
|
2003
|
-
const [error, setError] = (0,
|
|
2284
|
+
const [displayName, setDisplayName] = (0, import_react19.useState)(user?.displayName ?? "");
|
|
2285
|
+
const [phone, setPhone] = (0, import_react19.useState)(user?.phone ?? "");
|
|
2286
|
+
const [loading, setLoading] = (0, import_react19.useState)(false);
|
|
2287
|
+
const [success, setSuccess] = (0, import_react19.useState)("");
|
|
2288
|
+
const [error, setError] = (0, import_react19.useState)("");
|
|
2004
2289
|
const handleSave = async () => {
|
|
2005
2290
|
if (!client) return;
|
|
2006
2291
|
setLoading(true);
|
|
@@ -2016,9 +2301,9 @@ function ProfileTab() {
|
|
|
2016
2301
|
}
|
|
2017
2302
|
};
|
|
2018
2303
|
const initials = user?.displayName ? user.displayName.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : (user?.email?.[0] ?? "?").toUpperCase();
|
|
2019
|
-
return /* @__PURE__ */ (0,
|
|
2020
|
-
/* @__PURE__ */ (0,
|
|
2021
|
-
/* @__PURE__ */ (0,
|
|
2304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 16 }, children: [
|
|
2306
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2022
2307
|
"div",
|
|
2023
2308
|
{
|
|
2024
2309
|
style: {
|
|
@@ -2035,37 +2320,37 @@ function ProfileTab() {
|
|
|
2035
2320
|
overflow: "hidden",
|
|
2036
2321
|
flexShrink: 0
|
|
2037
2322
|
},
|
|
2038
|
-
children: user?.avatarUrl ? /* @__PURE__ */ (0,
|
|
2323
|
+
children: user?.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src: user.avatarUrl, alt: "avatar", style: { width: "100%", height: "100%", objectFit: "cover" } }) : initials
|
|
2039
2324
|
}
|
|
2040
2325
|
),
|
|
2041
|
-
/* @__PURE__ */ (0,
|
|
2042
|
-
/* @__PURE__ */ (0,
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
2044
|
-
!user?.emailVerified && /* @__PURE__ */ (0,
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 16, fontWeight: 600, color: theme.text }, children: user?.displayName ?? "User" }),
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 13, color: theme.textMuted }, children: user?.email }),
|
|
2329
|
+
!user?.emailVerified && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontSize: 11, color: "#d97706", background: "#fef3c7", padding: "2px 8px", borderRadius: 99, fontWeight: 500, marginTop: 4, display: "inline-block" }, children: "Email not verified" })
|
|
2045
2330
|
] })
|
|
2046
2331
|
] }),
|
|
2047
|
-
success && /* @__PURE__ */ (0,
|
|
2048
|
-
error && /* @__PURE__ */ (0,
|
|
2049
|
-
/* @__PURE__ */ (0,
|
|
2050
|
-
/* @__PURE__ */ (0,
|
|
2051
|
-
/* @__PURE__ */ (0,
|
|
2052
|
-
/* @__PURE__ */ (0,
|
|
2332
|
+
success && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#f0fdf4", border: "1px solid #bbf7d0", color: "#166534", fontSize: 13 }, children: success }),
|
|
2333
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { padding: "10px 14px", borderRadius: theme.borderRadius, background: "#fef2f2", border: "1px solid #fecaca", color: "#dc2626", fontSize: 13 }, children: error }),
|
|
2334
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "Display name", value: displayName, onChange: setDisplayName, placeholder: "Your name" }),
|
|
2336
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "Email", type: "email", value: user?.email ?? "", disabled: true, placeholder: "Email" }),
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "Phone", type: "tel", value: phone, onChange: setPhone, placeholder: "+1 (555) 000-0000" })
|
|
2053
2338
|
] }),
|
|
2054
|
-
/* @__PURE__ */ (0,
|
|
2339
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "primary", onClick: handleSave, loading, style: { alignSelf: "flex-start", minWidth: 120 }, children: "Save changes" })
|
|
2055
2340
|
] });
|
|
2056
2341
|
}
|
|
2057
2342
|
function SecurityTab() {
|
|
2058
2343
|
const theme = useTheme();
|
|
2059
2344
|
const { client } = useAuthon();
|
|
2060
|
-
const [currentPw, setCurrentPw] = (0,
|
|
2061
|
-
const [newPw, setNewPw] = (0,
|
|
2062
|
-
const [confirmPw, setConfirmPw] = (0,
|
|
2063
|
-
const [pwLoading, setPwLoading] = (0,
|
|
2064
|
-
const [pwError, setPwError] = (0,
|
|
2065
|
-
const [pwSuccess, setPwSuccess] = (0,
|
|
2066
|
-
const [mfaStatus, setMfaStatus] = (0,
|
|
2067
|
-
const [mfaLoading, setMfaLoading] = (0,
|
|
2068
|
-
(0,
|
|
2345
|
+
const [currentPw, setCurrentPw] = (0, import_react19.useState)("");
|
|
2346
|
+
const [newPw, setNewPw] = (0, import_react19.useState)("");
|
|
2347
|
+
const [confirmPw, setConfirmPw] = (0, import_react19.useState)("");
|
|
2348
|
+
const [pwLoading, setPwLoading] = (0, import_react19.useState)(false);
|
|
2349
|
+
const [pwError, setPwError] = (0, import_react19.useState)("");
|
|
2350
|
+
const [pwSuccess, setPwSuccess] = (0, import_react19.useState)("");
|
|
2351
|
+
const [mfaStatus, setMfaStatus] = (0, import_react19.useState)(null);
|
|
2352
|
+
const [mfaLoading, setMfaLoading] = (0, import_react19.useState)(false);
|
|
2353
|
+
(0, import_react19.useEffect)(() => {
|
|
2069
2354
|
if (!client) return;
|
|
2070
2355
|
client.getMfaStatus().then(setMfaStatus).catch(() => null);
|
|
2071
2356
|
}, [client]);
|
|
@@ -2102,26 +2387,26 @@ function SecurityTab() {
|
|
|
2102
2387
|
paddingBottom: 10,
|
|
2103
2388
|
borderBottom: `1px solid ${theme.border}`
|
|
2104
2389
|
};
|
|
2105
|
-
return /* @__PURE__ */ (0,
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2108
|
-
/* @__PURE__ */ (0,
|
|
2109
|
-
/* @__PURE__ */ (0,
|
|
2110
|
-
/* @__PURE__ */ (0,
|
|
2111
|
-
/* @__PURE__ */ (0,
|
|
2112
|
-
pwError && /* @__PURE__ */ (0,
|
|
2113
|
-
pwSuccess && /* @__PURE__ */ (0,
|
|
2114
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
2392
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: sectionTitle, children: "Change password" }),
|
|
2393
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
2394
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "Current password", type: "password", value: currentPw, onChange: setCurrentPw, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", autoComplete: "current-password" }),
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "New password", type: "password", value: newPw, onChange: setNewPw, placeholder: "Minimum 8 characters", autoComplete: "new-password" }),
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Input, { label: "Confirm new password", type: "password", value: confirmPw, onChange: setConfirmPw, placeholder: "Repeat new password", autoComplete: "new-password" }),
|
|
2397
|
+
pwError && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { color: "#dc2626", fontSize: 13 }, children: pwError }),
|
|
2398
|
+
pwSuccess && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { color: "#166534", fontSize: 13 }, children: pwSuccess }),
|
|
2399
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "primary", onClick: handlePasswordChange, loading: pwLoading, style: { alignSelf: "flex-start", minWidth: 160 }, children: "Update password" })
|
|
2115
2400
|
] })
|
|
2116
2401
|
] }),
|
|
2117
|
-
/* @__PURE__ */ (0,
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2119
|
-
/* @__PURE__ */ (0,
|
|
2120
|
-
/* @__PURE__ */ (0,
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2122
|
-
/* @__PURE__ */ (0,
|
|
2402
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
2403
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: sectionTitle, children: "Two-factor authentication" }),
|
|
2404
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 0" }, children: [
|
|
2405
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
2406
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 14, fontWeight: 500, color: theme.text }, children: "Authenticator app" }),
|
|
2407
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("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" })
|
|
2123
2408
|
] }),
|
|
2124
|
-
/* @__PURE__ */ (0,
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2125
2410
|
"span",
|
|
2126
2411
|
{
|
|
2127
2412
|
style: {
|
|
@@ -2136,7 +2421,7 @@ function SecurityTab() {
|
|
|
2136
2421
|
color: mfaStatus?.enabled ? "#166534" : theme.textMuted
|
|
2137
2422
|
},
|
|
2138
2423
|
children: [
|
|
2139
|
-
/* @__PURE__ */ (0,
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { width: 6, height: 6, borderRadius: "50%", background: mfaStatus?.enabled ? "#22c55e" : "#9ca3af", display: "inline-block" } }),
|
|
2140
2425
|
mfaStatus?.enabled ? "Enabled" : "Disabled"
|
|
2141
2426
|
]
|
|
2142
2427
|
}
|
|
@@ -2148,10 +2433,10 @@ function SecurityTab() {
|
|
|
2148
2433
|
function SessionsTab() {
|
|
2149
2434
|
const theme = useTheme();
|
|
2150
2435
|
const { client } = useAuthon();
|
|
2151
|
-
const [sessions, setSessions] = (0,
|
|
2152
|
-
const [loading, setLoading] = (0,
|
|
2153
|
-
const [revoking, setRevoking] = (0,
|
|
2154
|
-
const loadSessions = (0,
|
|
2436
|
+
const [sessions, setSessions] = (0, import_react19.useState)([]);
|
|
2437
|
+
const [loading, setLoading] = (0, import_react19.useState)(true);
|
|
2438
|
+
const [revoking, setRevoking] = (0, import_react19.useState)(null);
|
|
2439
|
+
const loadSessions = (0, import_react19.useCallback)(async () => {
|
|
2155
2440
|
if (!client) return;
|
|
2156
2441
|
setLoading(true);
|
|
2157
2442
|
try {
|
|
@@ -2162,7 +2447,7 @@ function SessionsTab() {
|
|
|
2162
2447
|
setLoading(false);
|
|
2163
2448
|
}
|
|
2164
2449
|
}, [client]);
|
|
2165
|
-
(0,
|
|
2450
|
+
(0, import_react19.useEffect)(() => {
|
|
2166
2451
|
loadSessions();
|
|
2167
2452
|
}, [loadSessions]);
|
|
2168
2453
|
const handleRevoke = async (sessionId) => {
|
|
@@ -2185,11 +2470,11 @@ function SessionsTab() {
|
|
|
2185
2470
|
borderBottom: `1px solid ${theme.border}`
|
|
2186
2471
|
};
|
|
2187
2472
|
if (loading) {
|
|
2188
|
-
return /* @__PURE__ */ (0,
|
|
2473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", justifyContent: "center", padding: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("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" } }) });
|
|
2189
2474
|
}
|
|
2190
|
-
return /* @__PURE__ */ (0,
|
|
2191
|
-
/* @__PURE__ */ (0,
|
|
2192
|
-
/* @__PURE__ */ (0,
|
|
2475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
2476
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: sectionTitle, children: "Active sessions" }),
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { color: theme.textMuted, fontSize: 14, textAlign: "center", padding: "24px 0" }, children: "No active sessions" }) : sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2193
2478
|
"div",
|
|
2194
2479
|
{
|
|
2195
2480
|
style: {
|
|
@@ -2202,24 +2487,24 @@ function SessionsTab() {
|
|
|
2202
2487
|
gap: 12
|
|
2203
2488
|
},
|
|
2204
2489
|
children: [
|
|
2205
|
-
/* @__PURE__ */ (0,
|
|
2206
|
-
/* @__PURE__ */ (0,
|
|
2207
|
-
/* @__PURE__ */ (0,
|
|
2208
|
-
/* @__PURE__ */ (0,
|
|
2209
|
-
/* @__PURE__ */ (0,
|
|
2490
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12, flex: 1, minWidth: 0 }, children: [
|
|
2491
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("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__ */ (0, import_jsx_runtime15.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2492
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", ry: "2" }),
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("line", { x1: "8", y1: "21", x2: "16", y2: "21" }),
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("line", { x1: "12", y1: "17", x2: "12", y2: "21" })
|
|
2210
2495
|
] }) }),
|
|
2211
|
-
/* @__PURE__ */ (0,
|
|
2212
|
-
/* @__PURE__ */ (0,
|
|
2213
|
-
/* @__PURE__ */ (0,
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { minWidth: 0 }, children: [
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("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" }),
|
|
2498
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { fontSize: 12, color: theme.textMuted, marginTop: 2 }, children: [
|
|
2214
2499
|
session.ipAddress ?? "Unknown IP",
|
|
2215
|
-
session.lastActiveAt && /* @__PURE__ */ (0,
|
|
2500
|
+
session.lastActiveAt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2216
2501
|
" \xB7 ",
|
|
2217
2502
|
formatRelative(session.lastActiveAt)
|
|
2218
2503
|
] })
|
|
2219
2504
|
] })
|
|
2220
2505
|
] })
|
|
2221
2506
|
] }),
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2223
2508
|
Button,
|
|
2224
2509
|
{
|
|
2225
2510
|
variant: "outline",
|
|
@@ -2247,7 +2532,7 @@ function formatRelative(dateStr) {
|
|
|
2247
2532
|
}
|
|
2248
2533
|
function UserProfilePanel() {
|
|
2249
2534
|
const theme = useTheme();
|
|
2250
|
-
const [tab, setTab] = (0,
|
|
2535
|
+
const [tab, setTab] = (0, import_react19.useState)("profile");
|
|
2251
2536
|
const panelStyle = {
|
|
2252
2537
|
width: "100%",
|
|
2253
2538
|
maxWidth: 640,
|
|
@@ -2282,9 +2567,9 @@ function UserProfilePanel() {
|
|
|
2282
2567
|
{ key: "security", label: "Security" },
|
|
2283
2568
|
{ key: "sessions", label: "Sessions" }
|
|
2284
2569
|
];
|
|
2285
|
-
return /* @__PURE__ */ (0,
|
|
2286
|
-
/* @__PURE__ */ (0,
|
|
2287
|
-
/* @__PURE__ */ (0,
|
|
2570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: panelStyle, children: [
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("style", { children: `@keyframes authon-spin { to { transform: rotate(360deg); } }` }),
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: tabBarStyle, children: tabs.map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2288
2573
|
"button",
|
|
2289
2574
|
{
|
|
2290
2575
|
type: "button",
|
|
@@ -2294,26 +2579,26 @@ function UserProfilePanel() {
|
|
|
2294
2579
|
},
|
|
2295
2580
|
key
|
|
2296
2581
|
)) }),
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
2298
|
-
tab === "profile" && /* @__PURE__ */ (0,
|
|
2299
|
-
tab === "security" && /* @__PURE__ */ (0,
|
|
2300
|
-
tab === "sessions" && /* @__PURE__ */ (0,
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: contentStyle, children: [
|
|
2583
|
+
tab === "profile" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ProfileTab, {}),
|
|
2584
|
+
tab === "security" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SecurityTab, {}),
|
|
2585
|
+
tab === "sessions" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SessionsTab, {})
|
|
2301
2586
|
] })
|
|
2302
2587
|
] });
|
|
2303
2588
|
}
|
|
2304
2589
|
function UserProfile({ appearance }) {
|
|
2305
2590
|
const { branding } = useBranding();
|
|
2306
2591
|
const effectiveBranding = { ...branding, ...appearance?.variables ?? {} };
|
|
2307
|
-
return /* @__PURE__ */ (0,
|
|
2592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ThemeProvider, { branding: effectiveBranding, style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UserProfilePanel, {}) });
|
|
2308
2593
|
}
|
|
2309
2594
|
|
|
2310
2595
|
// src/components/shared/ProviderIcon.tsx
|
|
2311
2596
|
var import_js5 = require("@authon/js");
|
|
2312
|
-
var
|
|
2597
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2313
2598
|
function ProviderIcon({ provider, size = 20 }) {
|
|
2314
2599
|
const config = (0, import_js5.getProviderButtonConfig)(provider);
|
|
2315
2600
|
const svg = config.iconSvg.replace(/width="\d+"/, `width="${size}"`).replace(/height="\d+"/, `height="${size}"`);
|
|
2316
|
-
return /* @__PURE__ */ (0,
|
|
2601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2317
2602
|
"span",
|
|
2318
2603
|
{
|
|
2319
2604
|
style: { display: "flex", alignItems: "center", flexShrink: 0 },
|