@vaultix.ai/react 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +62 -3
- package/dist/index.d.ts +62 -3
- package/dist/index.js +273 -97
- package/dist/index.mjs +334 -159
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -77,6 +77,7 @@ function VaultixProvider({
|
|
|
77
77
|
const [user, setUser] = useState(null);
|
|
78
78
|
const [session, setSession] = useState(null);
|
|
79
79
|
const [organization, setOrganization] = useState(null);
|
|
80
|
+
const [appConfig, setAppConfig] = useState(null);
|
|
80
81
|
const jwtRef = useRef(null);
|
|
81
82
|
const refreshTimerRef = useRef(null);
|
|
82
83
|
const clearAuth = useCallback(() => {
|
|
@@ -177,7 +178,21 @@ function VaultixProvider({
|
|
|
177
178
|
if (!cancelled) setIsLoaded(true);
|
|
178
179
|
}
|
|
179
180
|
}
|
|
181
|
+
async function fetchAppConfig() {
|
|
182
|
+
try {
|
|
183
|
+
const res = await fetch(
|
|
184
|
+
`${apiOrigin}/api/v1/app/config?pk=${encodeURIComponent(publishableKey)}`,
|
|
185
|
+
{ credentials: "omit" }
|
|
186
|
+
);
|
|
187
|
+
if (res.ok && !cancelled) {
|
|
188
|
+
const cfg = await res.json();
|
|
189
|
+
setAppConfig(cfg);
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
}
|
|
193
|
+
}
|
|
180
194
|
hydrate();
|
|
195
|
+
void fetchAppConfig();
|
|
181
196
|
return () => {
|
|
182
197
|
cancelled = true;
|
|
183
198
|
if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
|
|
@@ -236,6 +251,7 @@ function VaultixProvider({
|
|
|
236
251
|
isLoaded,
|
|
237
252
|
isSignedIn: !!session,
|
|
238
253
|
apiOrigin,
|
|
254
|
+
appConfig,
|
|
239
255
|
signOut,
|
|
240
256
|
updateUser,
|
|
241
257
|
connectPlatform
|
|
@@ -254,7 +270,7 @@ function VaultixProvider({
|
|
|
254
270
|
}
|
|
255
271
|
|
|
256
272
|
// src/hooks/index.ts
|
|
257
|
-
import { useCallback as useCallback2 } from "react";
|
|
273
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
258
274
|
function useVaultix() {
|
|
259
275
|
return useVaultixContext();
|
|
260
276
|
}
|
|
@@ -270,6 +286,44 @@ function useOrganization() {
|
|
|
270
286
|
const { organization, isLoaded } = useVaultixContext();
|
|
271
287
|
return { organization, isLoaded };
|
|
272
288
|
}
|
|
289
|
+
function usePlatformConnect(provider, defaultOptions) {
|
|
290
|
+
const { connectPlatform } = useVaultixContext();
|
|
291
|
+
const [connectedAccount, setConnectedAccount] = useState2(null);
|
|
292
|
+
const connect = useCallback2(
|
|
293
|
+
(overrides) => {
|
|
294
|
+
connectPlatform(provider, { ...defaultOptions, ...overrides });
|
|
295
|
+
},
|
|
296
|
+
[connectPlatform, provider, defaultOptions]
|
|
297
|
+
);
|
|
298
|
+
useEffect2(() => {
|
|
299
|
+
if (typeof window === "undefined") return;
|
|
300
|
+
const params = new URLSearchParams(window.location.search);
|
|
301
|
+
const connectToken = params.get("__vaultix_connect");
|
|
302
|
+
const returnedProvider = params.get("provider");
|
|
303
|
+
if (!connectToken || returnedProvider !== provider) return;
|
|
304
|
+
try {
|
|
305
|
+
const segment = connectToken.split(".")[1];
|
|
306
|
+
if (!segment) return;
|
|
307
|
+
const b64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
308
|
+
const payload = JSON.parse(atob(b64));
|
|
309
|
+
const result = {
|
|
310
|
+
provider: returnedProvider,
|
|
311
|
+
raw: payload,
|
|
312
|
+
...typeof payload["platform_user_id"] === "string" && { platformUserId: payload["platform_user_id"] },
|
|
313
|
+
...typeof payload["username"] === "string" && { username: payload["username"] },
|
|
314
|
+
...typeof payload["access_token"] === "string" && { accessToken: payload["access_token"] },
|
|
315
|
+
...typeof payload["scope"] === "string" && { scope: payload["scope"] }
|
|
316
|
+
};
|
|
317
|
+
setConnectedAccount(result);
|
|
318
|
+
const clean = new URL(window.location.href);
|
|
319
|
+
clean.searchParams.delete("__vaultix_connect");
|
|
320
|
+
clean.searchParams.delete("provider");
|
|
321
|
+
window.history.replaceState({}, "", clean.toString());
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
}, [provider]);
|
|
325
|
+
return { connect, connectedAccount };
|
|
326
|
+
}
|
|
273
327
|
function useAuth() {
|
|
274
328
|
const { user, session, isLoaded, isSignedIn, signOut } = useVaultixContext();
|
|
275
329
|
const getToken = useCallback2(async () => {
|
|
@@ -294,8 +348,8 @@ function useAuth() {
|
|
|
294
348
|
|
|
295
349
|
// src/components/SignIn.tsx
|
|
296
350
|
import { clsx } from "clsx";
|
|
297
|
-
import { useRef as useRef2, useState as
|
|
298
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
351
|
+
import { useRef as useRef2, useState as useState3 } from "react";
|
|
352
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
299
353
|
function toBase64url(buf) {
|
|
300
354
|
return btoa(String.fromCharCode(...new Uint8Array(buf))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
301
355
|
}
|
|
@@ -331,18 +385,34 @@ function SignIn({
|
|
|
331
385
|
onSuccess,
|
|
332
386
|
onError,
|
|
333
387
|
apiOrigin: apiOriginProp,
|
|
334
|
-
className
|
|
388
|
+
className,
|
|
389
|
+
appearance
|
|
335
390
|
}) {
|
|
336
391
|
const apiOrigin = resolveApiOrigin2(apiOriginProp);
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
392
|
+
const vars = appearance?.variables ?? {};
|
|
393
|
+
const primaryColor = vars.colorPrimary;
|
|
394
|
+
const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
|
|
395
|
+
const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
|
|
396
|
+
const mutedColor = vars.colorTextMuted ?? "#475569";
|
|
397
|
+
let appConfig = null;
|
|
398
|
+
try {
|
|
399
|
+
appConfig = useVaultixContext().appConfig;
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
|
|
403
|
+
const enabledMethods = appConfig?.methods ?? ["password", "magic_link", "passkey"];
|
|
404
|
+
const hasPassword = enabledMethods.includes("password");
|
|
405
|
+
const hasMagicLink = enabledMethods.includes("magic_link");
|
|
406
|
+
const hasPasskey = enabledMethods.includes("passkey");
|
|
407
|
+
const [step, setStep] = useState3("email");
|
|
408
|
+
const [email, setEmail] = useState3("");
|
|
409
|
+
const [password, setPassword] = useState3("");
|
|
410
|
+
const [totp, setTotp] = useState3("");
|
|
411
|
+
const [forgotCode, setForgotCode] = useState3("");
|
|
412
|
+
const [newPassword, setNewPassword] = useState3("");
|
|
413
|
+
const [error, setError] = useState3(null);
|
|
414
|
+
const [loading, setLoading] = useState3(false);
|
|
415
|
+
const [info, setInfo] = useState3(null);
|
|
346
416
|
const challengeIdRef = useRef2(null);
|
|
347
417
|
function setErr(msg) {
|
|
348
418
|
setError(msg);
|
|
@@ -383,7 +453,15 @@ function SignIn({
|
|
|
383
453
|
setErr(data.error ?? "Could not look up account.");
|
|
384
454
|
return;
|
|
385
455
|
}
|
|
386
|
-
|
|
456
|
+
if (data.preferred_challenge === "passkey" && hasPasskey) {
|
|
457
|
+
setStep("passkey");
|
|
458
|
+
} else if (hasPassword) {
|
|
459
|
+
setStep("password");
|
|
460
|
+
} else if (hasMagicLink) {
|
|
461
|
+
await handleMagicLinkRequest();
|
|
462
|
+
} else if (hasPasskey) {
|
|
463
|
+
setStep("passkey");
|
|
464
|
+
}
|
|
387
465
|
} catch {
|
|
388
466
|
setErr("Network error. Please try again.");
|
|
389
467
|
} finally {
|
|
@@ -598,24 +676,31 @@ function SignIn({
|
|
|
598
676
|
"backdrop-blur-[16px]",
|
|
599
677
|
className
|
|
600
678
|
),
|
|
601
|
-
style: { background:
|
|
679
|
+
style: { background: cardBg },
|
|
602
680
|
children: [
|
|
603
681
|
/* @__PURE__ */ jsxs("div", { className: "px-8 pt-8 pb-6 text-center", children: [
|
|
604
|
-
/* @__PURE__ */ jsx2(
|
|
605
|
-
|
|
606
|
-
|
|
682
|
+
/* @__PURE__ */ jsx2(
|
|
683
|
+
"div",
|
|
684
|
+
{
|
|
685
|
+
className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4",
|
|
686
|
+
style: primaryColor ? { background: primaryColor, boxShadow: `0 10px 15px -3px ${primaryColor}4d` } : { background: "linear-gradient(to bottom right, #7c3aed, #2563eb)", boxShadow: "0 10px 15px -3px rgba(124,58,237,0.3)" },
|
|
687
|
+
children: /* @__PURE__ */ jsx2(LockIcon, {})
|
|
688
|
+
}
|
|
689
|
+
),
|
|
690
|
+
/* @__PURE__ */ jsx2("h1", { className: "text-xl font-semibold", style: { color: textColor }, children: title[step] }),
|
|
691
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm mt-1", style: { color: mutedColor }, children: subtitle[step] })
|
|
607
692
|
] }),
|
|
608
693
|
/* @__PURE__ */ jsxs("div", { className: "px-8 pb-8 space-y-4", children: [
|
|
609
694
|
error && /* @__PURE__ */ jsx2("div", { className: "rounded-lg bg-red-500/10 border border-red-500/30 px-3 py-2", children: /* @__PURE__ */ jsx2("p", { className: "text-xs text-red-400", children: error }) }),
|
|
610
695
|
info && /* @__PURE__ */ jsx2("div", { className: "rounded-lg bg-blue-500/10 border border-blue-500/30 px-3 py-2", children: /* @__PURE__ */ jsx2("p", { className: "text-xs text-blue-400", children: info }) }),
|
|
611
696
|
step === "email" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
612
|
-
/* @__PURE__ */ jsx2(GoogleButton, { onClick: handleGoogleSignIn }),
|
|
613
|
-
/* @__PURE__ */ jsx2(GitHubButton, { onClick: handleGitHubSignIn }),
|
|
614
|
-
/* @__PURE__ */ jsx2(MetaButton, { onClick: handleMetaSignIn }),
|
|
615
|
-
/* @__PURE__ */ jsx2(LinkedInButton, { onClick: handleLinkedInSignIn }),
|
|
616
|
-
/* @__PURE__ */ jsx2(XButton, { onClick: handleXSignIn }),
|
|
617
|
-
/* @__PURE__ */ jsx2(Divider, {}),
|
|
618
|
-
/* @__PURE__ */ jsxs("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
|
|
697
|
+
enabledProviders.includes("google") && /* @__PURE__ */ jsx2(GoogleButton, { onClick: handleGoogleSignIn }),
|
|
698
|
+
enabledProviders.includes("github") && /* @__PURE__ */ jsx2(GitHubButton, { onClick: handleGitHubSignIn }),
|
|
699
|
+
enabledProviders.includes("meta") && /* @__PURE__ */ jsx2(MetaButton, { onClick: handleMetaSignIn }),
|
|
700
|
+
enabledProviders.includes("linkedin") && /* @__PURE__ */ jsx2(LinkedInButton, { onClick: handleLinkedInSignIn }),
|
|
701
|
+
enabledProviders.includes("x") && /* @__PURE__ */ jsx2(XButton, { onClick: handleXSignIn }),
|
|
702
|
+
(hasPassword || hasMagicLink || hasPasskey) && enabledProviders.length > 0 && /* @__PURE__ */ jsx2(Divider, { mutedColor }),
|
|
703
|
+
(hasPassword || hasMagicLink || hasPasskey) && /* @__PURE__ */ jsxs("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
|
|
619
704
|
/* @__PURE__ */ jsx2(
|
|
620
705
|
Input,
|
|
621
706
|
{
|
|
@@ -624,10 +709,11 @@ function SignIn({
|
|
|
624
709
|
value: email,
|
|
625
710
|
onChange: setEmail,
|
|
626
711
|
autoFocus: true,
|
|
627
|
-
required: true
|
|
712
|
+
required: true,
|
|
713
|
+
primaryColor
|
|
628
714
|
}
|
|
629
715
|
),
|
|
630
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Continue" })
|
|
716
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Continue" })
|
|
631
717
|
] })
|
|
632
718
|
] }),
|
|
633
719
|
step === "password" && /* @__PURE__ */ jsxs("form", { onSubmit: handlePasswordSubmit, className: "space-y-3", children: [
|
|
@@ -639,42 +725,52 @@ function SignIn({
|
|
|
639
725
|
value: password,
|
|
640
726
|
onChange: setPassword,
|
|
641
727
|
autoFocus: true,
|
|
642
|
-
required: true
|
|
728
|
+
required: true,
|
|
729
|
+
primaryColor
|
|
643
730
|
}
|
|
644
731
|
),
|
|
645
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Sign in" }),
|
|
646
|
-
/* @__PURE__ */ jsxs(
|
|
647
|
-
/* @__PURE__ */
|
|
648
|
-
|
|
649
|
-
|
|
732
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Sign in" }),
|
|
733
|
+
hasMagicLink && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
734
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
735
|
+
/* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" }),
|
|
736
|
+
/* @__PURE__ */ jsx2("span", { className: "text-[10px]", style: { color: mutedColor }, children: "or" }),
|
|
737
|
+
/* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" })
|
|
738
|
+
] }),
|
|
739
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: handleMagicLinkRequest, mutedColor, children: "\u2709 Email me a sign-in link" })
|
|
650
740
|
] }),
|
|
651
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: handleMagicLinkRequest, children: "\u2709 Email me a sign-in link" }),
|
|
652
741
|
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => {
|
|
653
742
|
setStep("forgot");
|
|
654
743
|
setError(null);
|
|
655
|
-
}, children: "Forgot password?" }),
|
|
656
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("email"), children: "\u2190 Back" })
|
|
744
|
+
}, mutedColor, children: "Forgot password?" }),
|
|
745
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("email"), mutedColor, children: "\u2190 Back" })
|
|
657
746
|
] }),
|
|
658
747
|
step === "magic-link-sent" && /* @__PURE__ */ jsxs("div", { className: "space-y-4 text-center", children: [
|
|
659
|
-
/* @__PURE__ */ jsx2(
|
|
660
|
-
|
|
748
|
+
/* @__PURE__ */ jsx2(
|
|
749
|
+
"div",
|
|
750
|
+
{
|
|
751
|
+
className: "w-14 h-14 rounded-2xl flex items-center justify-center mx-auto border",
|
|
752
|
+
style: primaryColor ? { background: `${primaryColor}26`, borderColor: `${primaryColor}4d` } : { background: "rgba(168,85,247,0.15)", borderColor: "rgba(168,85,247,0.3)" },
|
|
753
|
+
children: /* @__PURE__ */ jsx2(EnvelopeIcon, { color: primaryColor ?? "#a78bfa" })
|
|
754
|
+
}
|
|
755
|
+
),
|
|
756
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm leading-relaxed", style: { color: mutedColor }, children: [
|
|
661
757
|
"The link expires in ",
|
|
662
|
-
/* @__PURE__ */ jsx2("span", { className: "
|
|
758
|
+
/* @__PURE__ */ jsx2("span", { style: { color: textColor }, className: "font-medium", children: "15 minutes" }),
|
|
663
759
|
" and can only be used once."
|
|
664
760
|
] }),
|
|
665
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: handleMagicLinkRequest, children: "Resend link" }),
|
|
761
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: handleMagicLinkRequest, mutedColor, children: "Resend link" }),
|
|
666
762
|
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => {
|
|
667
763
|
setStep("password");
|
|
668
764
|
setError(null);
|
|
669
|
-
}, children: "Use password instead" })
|
|
765
|
+
}, mutedColor, children: "Use password instead" })
|
|
670
766
|
] }),
|
|
671
767
|
step === "passkey" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
672
|
-
/* @__PURE__ */ jsxs(PrimaryButton, { loading, onClick: handlePasskeySignIn, children: [
|
|
768
|
+
/* @__PURE__ */ jsxs(PrimaryButton, { loading, onClick: handlePasskeySignIn, primaryColor, children: [
|
|
673
769
|
/* @__PURE__ */ jsx2(FingerprintIcon, {}),
|
|
674
770
|
"Authenticate with passkey"
|
|
675
771
|
] }),
|
|
676
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("password"), children: "Use password instead" }),
|
|
677
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("email"), children: "\u2190 Back" })
|
|
772
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("password"), mutedColor, children: "Use password instead" }),
|
|
773
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("email"), mutedColor, children: "\u2190 Back" })
|
|
678
774
|
] }),
|
|
679
775
|
step === "totp" && /* @__PURE__ */ jsxs("form", { onSubmit: handleTotpSubmit, className: "space-y-3", children: [
|
|
680
776
|
/* @__PURE__ */ jsx2(
|
|
@@ -689,11 +785,12 @@ function SignIn({
|
|
|
689
785
|
onChange: setTotp,
|
|
690
786
|
autoFocus: true,
|
|
691
787
|
required: true,
|
|
692
|
-
className: "text-center tracking-[0.4em] text-lg"
|
|
788
|
+
className: "text-center tracking-[0.4em] text-lg",
|
|
789
|
+
primaryColor
|
|
693
790
|
}
|
|
694
791
|
),
|
|
695
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Verify" }),
|
|
696
|
-
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("password"), children: "\u2190 Back" })
|
|
792
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Verify" }),
|
|
793
|
+
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => setStep("password"), mutedColor, children: "\u2190 Back" })
|
|
697
794
|
] }),
|
|
698
795
|
step === "forgot" && /* @__PURE__ */ jsxs("form", { onSubmit: handleForgotSubmit, className: "space-y-3", children: [
|
|
699
796
|
/* @__PURE__ */ jsx2(
|
|
@@ -704,14 +801,15 @@ function SignIn({
|
|
|
704
801
|
value: email,
|
|
705
802
|
onChange: setEmail,
|
|
706
803
|
autoFocus: true,
|
|
707
|
-
required: true
|
|
804
|
+
required: true,
|
|
805
|
+
primaryColor
|
|
708
806
|
}
|
|
709
807
|
),
|
|
710
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Send reset code" }),
|
|
808
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Send reset code" }),
|
|
711
809
|
/* @__PURE__ */ jsx2(GhostButton, { onClick: () => {
|
|
712
810
|
setStep("password");
|
|
713
811
|
setError(null);
|
|
714
|
-
}, children: "\u2190 Back" })
|
|
812
|
+
}, mutedColor, children: "\u2190 Back" })
|
|
715
813
|
] }),
|
|
716
814
|
step === "forgot-verify" && /* @__PURE__ */ jsxs("form", { onSubmit: handleForgotVerifySubmit, className: "space-y-3", children: [
|
|
717
815
|
/* @__PURE__ */ jsx2(
|
|
@@ -726,10 +824,11 @@ function SignIn({
|
|
|
726
824
|
onChange: setForgotCode,
|
|
727
825
|
autoFocus: true,
|
|
728
826
|
required: true,
|
|
729
|
-
className: "text-center tracking-[0.4em] text-lg"
|
|
827
|
+
className: "text-center tracking-[0.4em] text-lg",
|
|
828
|
+
primaryColor
|
|
730
829
|
}
|
|
731
830
|
),
|
|
732
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Continue" })
|
|
831
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Continue" })
|
|
733
832
|
] }),
|
|
734
833
|
step === "forgot-reset" && /* @__PURE__ */ jsxs("form", { onSubmit: handleResetPasswordSubmit, className: "space-y-3", children: [
|
|
735
834
|
/* @__PURE__ */ jsx2(
|
|
@@ -741,18 +840,19 @@ function SignIn({
|
|
|
741
840
|
onChange: setNewPassword,
|
|
742
841
|
autoFocus: true,
|
|
743
842
|
required: true,
|
|
744
|
-
minLength: 8
|
|
843
|
+
minLength: 8,
|
|
844
|
+
primaryColor
|
|
745
845
|
}
|
|
746
846
|
),
|
|
747
847
|
/* @__PURE__ */ jsx2(PasswordStrength, { password: newPassword }),
|
|
748
|
-
/* @__PURE__ */ jsx2(PrimaryButton, { loading, children: "Reset password" })
|
|
848
|
+
/* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Reset password" })
|
|
749
849
|
] })
|
|
750
850
|
] })
|
|
751
851
|
]
|
|
752
852
|
}
|
|
753
853
|
);
|
|
754
854
|
}
|
|
755
|
-
function Input({ onChange, className, ...props }) {
|
|
855
|
+
function Input({ onChange, className, primaryColor, ...props }) {
|
|
756
856
|
return /* @__PURE__ */ jsx2(
|
|
757
857
|
"input",
|
|
758
858
|
{
|
|
@@ -761,39 +861,48 @@ function Input({ onChange, className, ...props }) {
|
|
|
761
861
|
className: clsx(
|
|
762
862
|
"w-full bg-white/5 border border-white/8 rounded-xl px-4 py-2.5",
|
|
763
863
|
"text-sm text-white/90 placeholder:text-[#475569]",
|
|
764
|
-
"focus:outline-none
|
|
864
|
+
"focus:outline-none transition-colors",
|
|
865
|
+
!primaryColor && "focus:border-purple-500/60",
|
|
765
866
|
className
|
|
766
|
-
)
|
|
867
|
+
),
|
|
868
|
+
style: primaryColor ? { "--vx-focus": primaryColor } : void 0,
|
|
869
|
+
onFocus: (e) => {
|
|
870
|
+
if (primaryColor) e.currentTarget.style.borderColor = `${primaryColor}99`;
|
|
871
|
+
props.onFocus?.(e);
|
|
872
|
+
},
|
|
873
|
+
onBlur: (e) => {
|
|
874
|
+
if (primaryColor) e.currentTarget.style.borderColor = "";
|
|
875
|
+
props.onBlur?.(e);
|
|
876
|
+
}
|
|
767
877
|
}
|
|
768
878
|
);
|
|
769
879
|
}
|
|
770
|
-
function PrimaryButton({ children, loading, onClick }) {
|
|
880
|
+
function PrimaryButton({ children, loading, onClick, primaryColor }) {
|
|
771
881
|
return /* @__PURE__ */ jsx2(
|
|
772
882
|
"button",
|
|
773
883
|
{
|
|
774
884
|
type: onClick ? "button" : "submit",
|
|
775
885
|
onClick,
|
|
776
886
|
disabled: loading,
|
|
887
|
+
style: primaryColor ? { background: primaryColor, boxShadow: `0 10px 15px -3px ${primaryColor}33` } : void 0,
|
|
777
888
|
className: clsx(
|
|
778
889
|
"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl",
|
|
779
|
-
"text-sm font-semibold text-white",
|
|
780
|
-
"
|
|
781
|
-
"hover:from-purple-500 hover:to-blue-500"
|
|
782
|
-
"shadow-lg shadow-purple-500/20",
|
|
783
|
-
"transition-all duration-150",
|
|
784
|
-
"disabled:opacity-60 disabled:cursor-not-allowed"
|
|
890
|
+
"text-sm font-semibold text-white transition-all duration-150",
|
|
891
|
+
"disabled:opacity-60 disabled:cursor-not-allowed",
|
|
892
|
+
!primaryColor && "bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-500 hover:to-blue-500 shadow-lg shadow-purple-500/20"
|
|
785
893
|
),
|
|
786
894
|
children: loading ? /* @__PURE__ */ jsx2(Spinner, {}) : children
|
|
787
895
|
}
|
|
788
896
|
);
|
|
789
897
|
}
|
|
790
|
-
function GhostButton({ children, onClick }) {
|
|
898
|
+
function GhostButton({ children, onClick, mutedColor }) {
|
|
791
899
|
return /* @__PURE__ */ jsx2(
|
|
792
900
|
"button",
|
|
793
901
|
{
|
|
794
902
|
type: "button",
|
|
795
903
|
onClick,
|
|
796
|
-
className: "w-full text-xs
|
|
904
|
+
className: "w-full text-xs transition-colors py-1 hover:opacity-80",
|
|
905
|
+
style: { color: mutedColor ?? "#475569" },
|
|
797
906
|
children
|
|
798
907
|
}
|
|
799
908
|
);
|
|
@@ -837,10 +946,10 @@ function GitHubButton({ onClick }) {
|
|
|
837
946
|
function XButton({ onClick }) {
|
|
838
947
|
return /* @__PURE__ */ jsx2(OAuthButton, { icon: /* @__PURE__ */ jsx2(XIcon, {}), label: "Continue with X", onClick });
|
|
839
948
|
}
|
|
840
|
-
function Divider() {
|
|
949
|
+
function Divider({ mutedColor }) {
|
|
841
950
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
842
951
|
/* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" }),
|
|
843
|
-
/* @__PURE__ */ jsx2("span", { className: "text-[10px]
|
|
952
|
+
/* @__PURE__ */ jsx2("span", { className: "text-[10px] uppercase tracking-wider", style: { color: mutedColor ?? "#475569" }, children: "or" }),
|
|
844
953
|
/* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" })
|
|
845
954
|
] });
|
|
846
955
|
}
|
|
@@ -910,8 +1019,8 @@ function GitHubIcon() {
|
|
|
910
1019
|
function XIcon() {
|
|
911
1020
|
return /* @__PURE__ */ jsx2("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "white", children: /* @__PURE__ */ jsx2("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.744l7.737-8.835L1.254 2.25H8.08l4.253 5.622 5.911-5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z" }) });
|
|
912
1021
|
}
|
|
913
|
-
function EnvelopeIcon() {
|
|
914
|
-
return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke:
|
|
1022
|
+
function EnvelopeIcon({ color = "#a78bfa" }) {
|
|
1023
|
+
return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
915
1024
|
/* @__PURE__ */ jsx2("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
|
|
916
1025
|
/* @__PURE__ */ jsx2("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })
|
|
917
1026
|
] });
|
|
@@ -919,7 +1028,7 @@ function EnvelopeIcon() {
|
|
|
919
1028
|
|
|
920
1029
|
// src/components/SignUp.tsx
|
|
921
1030
|
import { clsx as clsx2 } from "clsx";
|
|
922
|
-
import { useState as
|
|
1031
|
+
import { useState as useState4 } from "react";
|
|
923
1032
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
924
1033
|
function resolveApiOrigin3(prop) {
|
|
925
1034
|
if (prop) return prop;
|
|
@@ -929,6 +1038,13 @@ function resolveApiOrigin3(prop) {
|
|
|
929
1038
|
}
|
|
930
1039
|
return "";
|
|
931
1040
|
}
|
|
1041
|
+
function resolvePk2() {
|
|
1042
|
+
if (typeof document !== "undefined") {
|
|
1043
|
+
const el = document.querySelector("[data-vaultix-pk]");
|
|
1044
|
+
if (el) return el.getAttribute("data-vaultix-pk") ?? "";
|
|
1045
|
+
}
|
|
1046
|
+
return "";
|
|
1047
|
+
}
|
|
932
1048
|
function resolveAfterSignUpUrl(redirectUrlProp) {
|
|
933
1049
|
if (redirectUrlProp) return redirectUrlProp;
|
|
934
1050
|
if (typeof document !== "undefined") {
|
|
@@ -946,16 +1062,30 @@ function SignUp({
|
|
|
946
1062
|
onSuccess,
|
|
947
1063
|
onError,
|
|
948
1064
|
apiOrigin: apiOriginProp,
|
|
949
|
-
className
|
|
1065
|
+
className,
|
|
1066
|
+
appearance
|
|
950
1067
|
}) {
|
|
951
1068
|
const apiOrigin = resolveApiOrigin3(apiOriginProp);
|
|
952
|
-
const
|
|
953
|
-
const
|
|
954
|
-
const
|
|
955
|
-
const
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
|
|
1069
|
+
const vars = appearance?.variables ?? {};
|
|
1070
|
+
const primaryColor = vars.colorPrimary;
|
|
1071
|
+
const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
|
|
1072
|
+
const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
|
|
1073
|
+
const mutedColor = vars.colorTextMuted ?? "#475569";
|
|
1074
|
+
let appConfig = null;
|
|
1075
|
+
try {
|
|
1076
|
+
appConfig = useVaultixContext().appConfig;
|
|
1077
|
+
} catch {
|
|
1078
|
+
}
|
|
1079
|
+
const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
|
|
1080
|
+
const enabledMethods = appConfig?.methods ?? ["password", "magic_link", "passkey"];
|
|
1081
|
+
const hasPassword = enabledMethods.includes("password");
|
|
1082
|
+
const [step, setStep] = useState4("email");
|
|
1083
|
+
const [email, setEmail] = useState4("");
|
|
1084
|
+
const [password, setPassword] = useState4("");
|
|
1085
|
+
const [verificationCode, setVerificationCode] = useState4("");
|
|
1086
|
+
const [error, setError] = useState4(null);
|
|
1087
|
+
const [loading, setLoading] = useState4(false);
|
|
1088
|
+
const [registrationId, setRegistrationId] = useState4(null);
|
|
959
1089
|
function setErr(msg) {
|
|
960
1090
|
setError(msg);
|
|
961
1091
|
onError?.(msg);
|
|
@@ -967,10 +1097,12 @@ function SignUp({
|
|
|
967
1097
|
url.searchParams.set("__vaultix_handshake", handshakeToken);
|
|
968
1098
|
window.location.href = url.toString();
|
|
969
1099
|
}
|
|
970
|
-
function
|
|
1100
|
+
function oauthRedirect(provider) {
|
|
971
1101
|
const target = resolveAfterSignUpUrl(redirectUrl);
|
|
1102
|
+
const pk = resolvePk2();
|
|
972
1103
|
const params = new URLSearchParams({ redirect_url: target });
|
|
973
|
-
|
|
1104
|
+
if (pk) params.set("pk", pk);
|
|
1105
|
+
window.location.href = `${apiOrigin}/api/v1/auth/oauth/${provider}?${params}`;
|
|
974
1106
|
}
|
|
975
1107
|
async function handleEmailPassword(e) {
|
|
976
1108
|
e.preventDefault();
|
|
@@ -1041,48 +1173,61 @@ function SignUp({
|
|
|
1041
1173
|
"w-full max-w-sm mx-auto rounded-2xl border border-white/8 shadow-2xl backdrop-blur-[16px]",
|
|
1042
1174
|
className
|
|
1043
1175
|
),
|
|
1044
|
-
style: { background:
|
|
1176
|
+
style: { background: cardBg },
|
|
1045
1177
|
children: [
|
|
1046
1178
|
/* @__PURE__ */ jsxs2("div", { className: "px-8 pt-8 pb-6 text-center", children: [
|
|
1047
|
-
/* @__PURE__ */ jsx3(
|
|
1048
|
-
|
|
1049
|
-
|
|
1179
|
+
/* @__PURE__ */ jsx3(
|
|
1180
|
+
"div",
|
|
1181
|
+
{
|
|
1182
|
+
className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4",
|
|
1183
|
+
style: primaryColor ? { background: primaryColor, boxShadow: `0 10px 15px -3px ${primaryColor}4d` } : { background: "linear-gradient(to bottom right, #059669, #0d9488)", boxShadow: "0 10px 15px -3px rgba(5,150,105,0.3)" },
|
|
1184
|
+
children: /* @__PURE__ */ jsx3(SparkleIcon, {})
|
|
1185
|
+
}
|
|
1186
|
+
),
|
|
1187
|
+
/* @__PURE__ */ jsx3("h1", { className: "text-xl font-semibold", style: { color: textColor }, children: step === "verify" ? "Check your email" : "Create an account" }),
|
|
1188
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm mt-1", style: { color: mutedColor }, children: step === "verify" ? `We sent a code to ${email}` : "Start your free trial today" })
|
|
1050
1189
|
] }),
|
|
1051
1190
|
/* @__PURE__ */ jsxs2("div", { className: "px-8 pb-8 space-y-4", children: [
|
|
1052
1191
|
error && /* @__PURE__ */ jsx3("div", { className: "rounded-lg bg-red-500/10 border border-red-500/30 px-3 py-2", children: /* @__PURE__ */ jsx3("p", { className: "text-xs text-red-400", children: error }) }),
|
|
1053
1192
|
step === "email" && /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
|
|
1054
|
-
/* @__PURE__ */ jsx3(
|
|
1055
|
-
/* @__PURE__ */ jsx3(
|
|
1056
|
-
/* @__PURE__ */
|
|
1193
|
+
enabledProviders.includes("google") && /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(GoogleIcon2, {}), label: "Continue with Google", onClick: () => oauthRedirect("google") }),
|
|
1194
|
+
enabledProviders.includes("github") && /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(GitHubIcon2, {}), label: "Continue with GitHub", onClick: () => oauthRedirect("github") }),
|
|
1195
|
+
enabledProviders.includes("meta") && /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(MetaIcon2, {}), label: "Continue with Facebook", onClick: () => oauthRedirect("meta") }),
|
|
1196
|
+
enabledProviders.includes("linkedin") && /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(LinkedInIcon2, {}), label: "Continue with LinkedIn", onClick: () => oauthRedirect("linkedin") }),
|
|
1197
|
+
enabledProviders.includes("x") && /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(XIcon2, {}), label: "Continue with X", onClick: () => oauthRedirect("x") }),
|
|
1198
|
+
hasPassword && enabledProviders.length > 0 && /* @__PURE__ */ jsx3(Divider2, { mutedColor }),
|
|
1199
|
+
hasPassword && /* @__PURE__ */ jsxs2("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
|
|
1057
1200
|
/* @__PURE__ */ jsx3(
|
|
1058
|
-
|
|
1201
|
+
Input2,
|
|
1059
1202
|
{
|
|
1060
1203
|
type: "email",
|
|
1061
1204
|
placeholder: "you@company.com",
|
|
1062
1205
|
value: email,
|
|
1063
1206
|
onChange: setEmail,
|
|
1064
1207
|
autoFocus: true,
|
|
1065
|
-
required: true
|
|
1208
|
+
required: true,
|
|
1209
|
+
primaryColor
|
|
1066
1210
|
}
|
|
1067
1211
|
),
|
|
1068
1212
|
/* @__PURE__ */ jsx3(
|
|
1069
|
-
|
|
1213
|
+
Input2,
|
|
1070
1214
|
{
|
|
1071
1215
|
type: "password",
|
|
1072
1216
|
placeholder: "Create a password",
|
|
1073
1217
|
value: password,
|
|
1074
1218
|
onChange: setPassword,
|
|
1075
1219
|
required: true,
|
|
1076
|
-
minLength: 8
|
|
1220
|
+
minLength: 8,
|
|
1221
|
+
primaryColor
|
|
1077
1222
|
}
|
|
1078
1223
|
),
|
|
1079
|
-
/* @__PURE__ */ jsx3(PasswordStrength2, { password }),
|
|
1080
|
-
/* @__PURE__ */ jsx3(
|
|
1224
|
+
/* @__PURE__ */ jsx3(PasswordStrength2, { password, primaryColor }),
|
|
1225
|
+
/* @__PURE__ */ jsx3(PrimaryButton2, { loading, primaryColor, children: "Create account" })
|
|
1081
1226
|
] })
|
|
1082
1227
|
] }),
|
|
1083
1228
|
step === "verify" && /* @__PURE__ */ jsxs2("form", { onSubmit: handleVerification, className: "space-y-3", children: [
|
|
1084
1229
|
/* @__PURE__ */ jsx3(
|
|
1085
|
-
|
|
1230
|
+
Input2,
|
|
1086
1231
|
{
|
|
1087
1232
|
type: "text",
|
|
1088
1233
|
inputMode: "numeric",
|
|
@@ -1093,16 +1238,18 @@ function SignUp({
|
|
|
1093
1238
|
onChange: setVerificationCode,
|
|
1094
1239
|
autoFocus: true,
|
|
1095
1240
|
required: true,
|
|
1096
|
-
className: "text-center tracking-[0.4em] text-lg"
|
|
1241
|
+
className: "text-center tracking-[0.4em] text-lg",
|
|
1242
|
+
primaryColor
|
|
1097
1243
|
}
|
|
1098
1244
|
),
|
|
1099
|
-
/* @__PURE__ */ jsx3(
|
|
1245
|
+
/* @__PURE__ */ jsx3(PrimaryButton2, { loading, primaryColor, children: "Verify email" }),
|
|
1100
1246
|
/* @__PURE__ */ jsx3(
|
|
1101
1247
|
"button",
|
|
1102
1248
|
{
|
|
1103
1249
|
type: "button",
|
|
1104
1250
|
onClick: resendCode,
|
|
1105
|
-
className: "w-full text-xs
|
|
1251
|
+
className: "w-full text-xs transition-colors py-1 hover:opacity-80",
|
|
1252
|
+
style: { color: mutedColor },
|
|
1106
1253
|
children: "Resend code"
|
|
1107
1254
|
}
|
|
1108
1255
|
)
|
|
@@ -1112,7 +1259,7 @@ function SignUp({
|
|
|
1112
1259
|
}
|
|
1113
1260
|
);
|
|
1114
1261
|
}
|
|
1115
|
-
function
|
|
1262
|
+
function Input2({ onChange, className, primaryColor, ...props }) {
|
|
1116
1263
|
return /* @__PURE__ */ jsx3(
|
|
1117
1264
|
"input",
|
|
1118
1265
|
{
|
|
@@ -1121,34 +1268,47 @@ function SignUpInput({ onChange, className, ...props }) {
|
|
|
1121
1268
|
className: clsx2(
|
|
1122
1269
|
"w-full bg-white/5 border border-white/8 rounded-xl px-4 py-2.5",
|
|
1123
1270
|
"text-sm text-white/90 placeholder:text-[#475569]",
|
|
1124
|
-
"focus:outline-none
|
|
1271
|
+
"focus:outline-none transition-colors",
|
|
1272
|
+
!primaryColor && "focus:border-emerald-500/60",
|
|
1125
1273
|
className
|
|
1126
|
-
)
|
|
1274
|
+
),
|
|
1275
|
+
onFocus: (e) => {
|
|
1276
|
+
if (primaryColor) e.currentTarget.style.borderColor = `${primaryColor}99`;
|
|
1277
|
+
props.onFocus?.(e);
|
|
1278
|
+
},
|
|
1279
|
+
onBlur: (e) => {
|
|
1280
|
+
if (primaryColor) e.currentTarget.style.borderColor = "";
|
|
1281
|
+
props.onBlur?.(e);
|
|
1282
|
+
}
|
|
1127
1283
|
}
|
|
1128
1284
|
);
|
|
1129
1285
|
}
|
|
1130
|
-
function
|
|
1286
|
+
function PrimaryButton2({
|
|
1131
1287
|
children,
|
|
1132
|
-
loading
|
|
1288
|
+
loading,
|
|
1289
|
+
primaryColor
|
|
1133
1290
|
}) {
|
|
1134
1291
|
return /* @__PURE__ */ jsx3(
|
|
1135
1292
|
"button",
|
|
1136
1293
|
{
|
|
1137
1294
|
type: "submit",
|
|
1138
1295
|
disabled: loading,
|
|
1296
|
+
style: primaryColor ? { background: primaryColor, boxShadow: `0 10px 15px -3px ${primaryColor}33` } : void 0,
|
|
1139
1297
|
className: clsx2(
|
|
1140
1298
|
"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl",
|
|
1141
|
-
"text-sm font-semibold text-white",
|
|
1142
|
-
"
|
|
1143
|
-
"hover:from-emerald-500 hover:to-teal-500"
|
|
1144
|
-
"shadow-lg shadow-emerald-500/20 transition-all duration-150",
|
|
1145
|
-
"disabled:opacity-60 disabled:cursor-not-allowed"
|
|
1299
|
+
"text-sm font-semibold text-white transition-all duration-150",
|
|
1300
|
+
"disabled:opacity-60 disabled:cursor-not-allowed",
|
|
1301
|
+
!primaryColor && "bg-gradient-to-r from-emerald-600 to-teal-600 hover:from-emerald-500 hover:to-teal-500 shadow-lg shadow-emerald-500/20"
|
|
1146
1302
|
),
|
|
1147
1303
|
children: loading ? /* @__PURE__ */ jsx3(Spinner2, {}) : children
|
|
1148
1304
|
}
|
|
1149
1305
|
);
|
|
1150
1306
|
}
|
|
1151
|
-
function
|
|
1307
|
+
function OAuthButton2({
|
|
1308
|
+
icon,
|
|
1309
|
+
label,
|
|
1310
|
+
onClick
|
|
1311
|
+
}) {
|
|
1152
1312
|
return /* @__PURE__ */ jsxs2(
|
|
1153
1313
|
"button",
|
|
1154
1314
|
{
|
|
@@ -1162,20 +1322,20 @@ function GoogleButton2({ onClick }) {
|
|
|
1162
1322
|
"transition-all duration-150"
|
|
1163
1323
|
),
|
|
1164
1324
|
children: [
|
|
1165
|
-
|
|
1166
|
-
|
|
1325
|
+
icon,
|
|
1326
|
+
label
|
|
1167
1327
|
]
|
|
1168
1328
|
}
|
|
1169
1329
|
);
|
|
1170
1330
|
}
|
|
1171
|
-
function Divider2() {
|
|
1331
|
+
function Divider2({ mutedColor }) {
|
|
1172
1332
|
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
|
|
1173
1333
|
/* @__PURE__ */ jsx3("div", { className: "flex-1 h-px bg-white/8" }),
|
|
1174
|
-
/* @__PURE__ */ jsx3("span", { className: "text-[10px]
|
|
1334
|
+
/* @__PURE__ */ jsx3("span", { className: "text-[10px] uppercase tracking-wider", style: { color: mutedColor ?? "#475569" }, children: "or" }),
|
|
1175
1335
|
/* @__PURE__ */ jsx3("div", { className: "flex-1 h-px bg-white/8" })
|
|
1176
1336
|
] });
|
|
1177
1337
|
}
|
|
1178
|
-
function PasswordStrength2({ password }) {
|
|
1338
|
+
function PasswordStrength2({ password, primaryColor }) {
|
|
1179
1339
|
const score = (() => {
|
|
1180
1340
|
if (password.length === 0) return 0;
|
|
1181
1341
|
let s = 0;
|
|
@@ -1187,15 +1347,17 @@ function PasswordStrength2({ password }) {
|
|
|
1187
1347
|
})();
|
|
1188
1348
|
if (password.length === 0) return null;
|
|
1189
1349
|
const labels = ["", "Weak", "Fair", "Good", "Strong"];
|
|
1190
|
-
const
|
|
1350
|
+
const tailwindColors = ["", "bg-red-500", "bg-amber-400", "bg-blue-400", "bg-emerald-400"];
|
|
1191
1351
|
return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
|
|
1192
1352
|
/* @__PURE__ */ jsx3("div", { className: "flex gap-1", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx3(
|
|
1193
1353
|
"div",
|
|
1194
1354
|
{
|
|
1195
1355
|
className: clsx2(
|
|
1196
1356
|
"flex-1 h-0.5 rounded-full transition-all duration-300",
|
|
1197
|
-
i <= score ?
|
|
1198
|
-
|
|
1357
|
+
i <= score && !primaryColor ? tailwindColors[score] : void 0,
|
|
1358
|
+
i > score || !primaryColor && i <= score ? void 0 : void 0
|
|
1359
|
+
),
|
|
1360
|
+
style: i <= score && primaryColor ? { background: score >= 4 ? primaryColor : void 0 } : { background: i <= score ? void 0 : "rgba(255,255,255,0.1)" }
|
|
1199
1361
|
},
|
|
1200
1362
|
i
|
|
1201
1363
|
)) }),
|
|
@@ -1219,25 +1381,37 @@ function GoogleIcon2() {
|
|
|
1219
1381
|
/* @__PURE__ */ jsx3("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })
|
|
1220
1382
|
] });
|
|
1221
1383
|
}
|
|
1384
|
+
function MetaIcon2() {
|
|
1385
|
+
return /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "#1877F2", children: /* @__PURE__ */ jsx3("path", { d: "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" }) });
|
|
1386
|
+
}
|
|
1387
|
+
function LinkedInIcon2() {
|
|
1388
|
+
return /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "#0A66C2", children: /* @__PURE__ */ jsx3("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.063 2.063 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" }) });
|
|
1389
|
+
}
|
|
1390
|
+
function GitHubIcon2() {
|
|
1391
|
+
return /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "white", children: /* @__PURE__ */ jsx3("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2z" }) });
|
|
1392
|
+
}
|
|
1393
|
+
function XIcon2() {
|
|
1394
|
+
return /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "white", children: /* @__PURE__ */ jsx3("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.744l7.737-8.835L1.254 2.25H8.08l4.253 5.622 5.911-5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z" }) });
|
|
1395
|
+
}
|
|
1222
1396
|
|
|
1223
1397
|
// src/components/SignedIn.tsx
|
|
1224
|
-
import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
|
|
1398
|
+
import { Fragment as Fragment2, jsx as jsx4 } from "react/jsx-runtime";
|
|
1225
1399
|
function SignedIn({ children }) {
|
|
1226
1400
|
const { isLoaded, isSignedIn } = useVaultixContext();
|
|
1227
1401
|
if (!isLoaded || !isSignedIn) return null;
|
|
1228
|
-
return /* @__PURE__ */ jsx4(
|
|
1402
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children });
|
|
1229
1403
|
}
|
|
1230
1404
|
function SignedOut({ children }) {
|
|
1231
1405
|
const { isLoaded, isSignedIn } = useVaultixContext();
|
|
1232
1406
|
if (!isLoaded || isSignedIn) return null;
|
|
1233
|
-
return /* @__PURE__ */ jsx4(
|
|
1407
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children });
|
|
1234
1408
|
}
|
|
1235
1409
|
|
|
1236
1410
|
// src/components/RedirectComponents.tsx
|
|
1237
|
-
import { useEffect as
|
|
1411
|
+
import { useEffect as useEffect3 } from "react";
|
|
1238
1412
|
function RedirectToSignIn({ redirectUrl = "/sign-in" }) {
|
|
1239
1413
|
const { isLoaded, isSignedIn } = useVaultixContext();
|
|
1240
|
-
|
|
1414
|
+
useEffect3(() => {
|
|
1241
1415
|
if (isLoaded && !isSignedIn) {
|
|
1242
1416
|
window.location.href = redirectUrl;
|
|
1243
1417
|
}
|
|
@@ -1246,7 +1420,7 @@ function RedirectToSignIn({ redirectUrl = "/sign-in" }) {
|
|
|
1246
1420
|
}
|
|
1247
1421
|
function RedirectToSignUp({ redirectUrl = "/sign-up" }) {
|
|
1248
1422
|
const { isLoaded, isSignedIn } = useVaultixContext();
|
|
1249
|
-
|
|
1423
|
+
useEffect3(() => {
|
|
1250
1424
|
if (isLoaded && !isSignedIn) {
|
|
1251
1425
|
window.location.href = redirectUrl;
|
|
1252
1426
|
}
|
|
@@ -1256,15 +1430,15 @@ function RedirectToSignUp({ redirectUrl = "/sign-up" }) {
|
|
|
1256
1430
|
|
|
1257
1431
|
// src/components/UserButton.tsx
|
|
1258
1432
|
import { clsx as clsx3 } from "clsx";
|
|
1259
|
-
import { useCallback as useCallback3, useEffect as
|
|
1260
|
-
import { Fragment as
|
|
1433
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
|
|
1434
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1261
1435
|
function UserButton({ showName = false, afterSignOutUrl, className }) {
|
|
1262
1436
|
const { user, session, isLoaded, isSignedIn, signOut } = useVaultixContext();
|
|
1263
|
-
const [open, setOpen] =
|
|
1264
|
-
const [signingOut, setSigningOut] =
|
|
1265
|
-
const [showProfile, setShowProfile] =
|
|
1437
|
+
const [open, setOpen] = useState5(false);
|
|
1438
|
+
const [signingOut, setSigningOut] = useState5(false);
|
|
1439
|
+
const [showProfile, setShowProfile] = useState5(false);
|
|
1266
1440
|
const containerRef = useRef3(null);
|
|
1267
|
-
|
|
1441
|
+
useEffect4(() => {
|
|
1268
1442
|
function onPointerDown(e) {
|
|
1269
1443
|
if (containerRef.current && !containerRef.current.contains(e.target)) setOpen(false);
|
|
1270
1444
|
}
|
|
@@ -1279,7 +1453,7 @@ function UserButton({ showName = false, afterSignOutUrl, className }) {
|
|
|
1279
1453
|
await signOut();
|
|
1280
1454
|
if (afterSignOutUrl) window.location.href = afterSignOutUrl;
|
|
1281
1455
|
}
|
|
1282
|
-
return /* @__PURE__ */ jsxs3(
|
|
1456
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
1283
1457
|
/* @__PURE__ */ jsxs3("div", { ref: containerRef, className: clsx3("relative", className), children: [
|
|
1284
1458
|
/* @__PURE__ */ jsxs3(
|
|
1285
1459
|
"button",
|
|
@@ -1326,17 +1500,17 @@ function UserButton({ showName = false, afterSignOutUrl, className }) {
|
|
|
1326
1500
|
}
|
|
1327
1501
|
function ProfileModal({ onClose }) {
|
|
1328
1502
|
const { user, updateUser } = useVaultixContext();
|
|
1329
|
-
const [tab, setTab] =
|
|
1330
|
-
const [firstName, setFirstName] =
|
|
1331
|
-
const [lastName, setLastName] =
|
|
1332
|
-
const [imageUrl, setImageUrl] =
|
|
1333
|
-
const [currentPassword, setCurrentPassword] =
|
|
1334
|
-
const [newPassword, setNewPassword] =
|
|
1335
|
-
const [confirmPassword, setConfirmPassword] =
|
|
1336
|
-
const [saving, setSaving] =
|
|
1337
|
-
const [error, setError] =
|
|
1338
|
-
const [success, setSuccess] =
|
|
1339
|
-
|
|
1503
|
+
const [tab, setTab] = useState5("profile");
|
|
1504
|
+
const [firstName, setFirstName] = useState5(user?.firstName ?? "");
|
|
1505
|
+
const [lastName, setLastName] = useState5(user?.lastName ?? "");
|
|
1506
|
+
const [imageUrl, setImageUrl] = useState5(user?.imageUrl ?? "");
|
|
1507
|
+
const [currentPassword, setCurrentPassword] = useState5("");
|
|
1508
|
+
const [newPassword, setNewPassword] = useState5("");
|
|
1509
|
+
const [confirmPassword, setConfirmPassword] = useState5("");
|
|
1510
|
+
const [saving, setSaving] = useState5(false);
|
|
1511
|
+
const [error, setError] = useState5(null);
|
|
1512
|
+
const [success, setSuccess] = useState5(null);
|
|
1513
|
+
useEffect4(() => {
|
|
1340
1514
|
function onKey(e) {
|
|
1341
1515
|
if (e.key === "Escape") onClose();
|
|
1342
1516
|
}
|
|
@@ -1447,17 +1621,17 @@ function ProfileModal({ onClose }) {
|
|
|
1447
1621
|
}
|
|
1448
1622
|
function SecurityTab() {
|
|
1449
1623
|
const { apiOrigin } = useVaultixContext();
|
|
1450
|
-
const [totpEnabled, setTotpEnabled] =
|
|
1451
|
-
const [backupCodesLeft, setBackupCodesLeft] =
|
|
1452
|
-
const [enrollStep, setEnrollStep] =
|
|
1453
|
-
const [qrDataUrl, setQrDataUrl] =
|
|
1454
|
-
const [manualKey, setManualKey] =
|
|
1455
|
-
const [enrollCode, setEnrollCode] =
|
|
1456
|
-
const [disableCode, setDisableCode] =
|
|
1457
|
-
const [backupCodes, setBackupCodes] =
|
|
1458
|
-
const [loading, setLoading] =
|
|
1459
|
-
const [error, setError] =
|
|
1460
|
-
const [showDisable, setShowDisable] =
|
|
1624
|
+
const [totpEnabled, setTotpEnabled] = useState5(null);
|
|
1625
|
+
const [backupCodesLeft, setBackupCodesLeft] = useState5(null);
|
|
1626
|
+
const [enrollStep, setEnrollStep] = useState5("idle");
|
|
1627
|
+
const [qrDataUrl, setQrDataUrl] = useState5("");
|
|
1628
|
+
const [manualKey, setManualKey] = useState5("");
|
|
1629
|
+
const [enrollCode, setEnrollCode] = useState5("");
|
|
1630
|
+
const [disableCode, setDisableCode] = useState5("");
|
|
1631
|
+
const [backupCodes, setBackupCodes] = useState5([]);
|
|
1632
|
+
const [loading, setLoading] = useState5(false);
|
|
1633
|
+
const [error, setError] = useState5(null);
|
|
1634
|
+
const [showDisable, setShowDisable] = useState5(false);
|
|
1461
1635
|
const fetchStatus = useCallback3(async () => {
|
|
1462
1636
|
const res = await fetch(`${apiOrigin}/api/v1/auth/totp/status`, { credentials: "include" });
|
|
1463
1637
|
if (res.ok) {
|
|
@@ -1466,7 +1640,7 @@ function SecurityTab() {
|
|
|
1466
1640
|
setBackupCodesLeft(d.backup_codes_remaining);
|
|
1467
1641
|
}
|
|
1468
1642
|
}, [apiOrigin]);
|
|
1469
|
-
|
|
1643
|
+
useEffect4(() => {
|
|
1470
1644
|
void fetchStatus();
|
|
1471
1645
|
}, [fetchStatus]);
|
|
1472
1646
|
async function startEnroll() {
|
|
@@ -1782,7 +1956,7 @@ function CloseIcon() {
|
|
|
1782
1956
|
|
|
1783
1957
|
// src/components/OrganizationSwitcher.tsx
|
|
1784
1958
|
import { clsx as clsx4 } from "clsx";
|
|
1785
|
-
import { useEffect as
|
|
1959
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
1786
1960
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1787
1961
|
function resolveApiOrigin4() {
|
|
1788
1962
|
if (typeof document !== "undefined") {
|
|
@@ -1796,11 +1970,11 @@ function OrganizationSwitcher({
|
|
|
1796
1970
|
className
|
|
1797
1971
|
}) {
|
|
1798
1972
|
const { organization, isLoaded, isSignedIn } = useVaultixContext();
|
|
1799
|
-
const [open, setOpen] =
|
|
1800
|
-
const [orgs, setOrgs] =
|
|
1801
|
-
const [switching, setSwitching] =
|
|
1973
|
+
const [open, setOpen] = useState6(false);
|
|
1974
|
+
const [orgs, setOrgs] = useState6([]);
|
|
1975
|
+
const [switching, setSwitching] = useState6(null);
|
|
1802
1976
|
const containerRef = useRef4(null);
|
|
1803
|
-
|
|
1977
|
+
useEffect5(() => {
|
|
1804
1978
|
function onPointerDown(e) {
|
|
1805
1979
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
1806
1980
|
setOpen(false);
|
|
@@ -1809,7 +1983,7 @@ function OrganizationSwitcher({
|
|
|
1809
1983
|
document.addEventListener("pointerdown", onPointerDown);
|
|
1810
1984
|
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
1811
1985
|
}, []);
|
|
1812
|
-
|
|
1986
|
+
useEffect5(() => {
|
|
1813
1987
|
if (!open) return;
|
|
1814
1988
|
const api = resolveApiOrigin4();
|
|
1815
1989
|
fetch(`${api}/v1/me/organizations`, { credentials: "include" }).then((r) => r.json()).then(
|
|
@@ -2004,6 +2178,7 @@ export {
|
|
|
2004
2178
|
getStoredToken,
|
|
2005
2179
|
useAuth,
|
|
2006
2180
|
useOrganization,
|
|
2181
|
+
usePlatformConnect,
|
|
2007
2182
|
useSession,
|
|
2008
2183
|
useUser,
|
|
2009
2184
|
useVaultix
|