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