@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.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 useState2 } from "react";
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 [step, setStep] = useState2("email");
338
- const [email, setEmail] = useState2("");
339
- const [password, setPassword] = useState2("");
340
- const [totp, setTotp] = useState2("");
341
- const [forgotCode, setForgotCode] = useState2("");
342
- const [newPassword, setNewPassword] = useState2("");
343
- const [error, setError] = useState2(null);
344
- const [loading, setLoading] = useState2(false);
345
- const [info, setInfo] = useState2(null);
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
- setStep(data.preferred_challenge === "passkey" ? "passkey" : "password");
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: "rgba(22,27,45,0.92)" },
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("div", { className: "inline-flex items-center justify-center w-10 h-10 rounded-xl bg-gradient-to-br from-purple-600 to-blue-600 shadow-lg shadow-purple-500/30 mb-4", children: /* @__PURE__ */ jsx2(LockIcon, {}) }),
605
- /* @__PURE__ */ jsx2("h1", { className: "text-xl font-semibold text-white/90", children: title[step] }),
606
- /* @__PURE__ */ jsx2("p", { className: "text-sm text-[#475569] mt-1", children: subtitle[step] })
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("div", { className: "flex items-center gap-2", children: [
647
- /* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" }),
648
- /* @__PURE__ */ jsx2("span", { className: "text-[10px] text-[#475569]", children: "or" }),
649
- /* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" })
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("div", { className: "w-14 h-14 rounded-2xl bg-purple-500/15 border border-purple-500/30 flex items-center justify-center mx-auto", children: /* @__PURE__ */ jsx2(EnvelopeIcon, {}) }),
660
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-[#94a3b8] leading-relaxed", children: [
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: "text-white/80 font-medium", children: "15 minutes" }),
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 focus:border-purple-500/60 transition-colors",
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
- "bg-gradient-to-r from-purple-600 to-blue-600",
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 text-[#475569] hover:text-white/70 transition-colors py-1",
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] text-[#475569] uppercase tracking-wider", children: "or" }),
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: "#a78bfa", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
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 useState3 } from "react";
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 [step, setStep] = useState3("email");
953
- const [email, setEmail] = useState3("");
954
- const [password, setPassword] = useState3("");
955
- const [verificationCode, setVerificationCode] = useState3("");
956
- const [error, setError] = useState3(null);
957
- const [loading, setLoading] = useState3(false);
958
- const [registrationId, setRegistrationId] = useState3(null);
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 handleGoogleSignUp() {
1100
+ function oauthRedirect(provider) {
971
1101
  const target = resolveAfterSignUpUrl(redirectUrl);
1102
+ const pk = resolvePk2();
972
1103
  const params = new URLSearchParams({ redirect_url: target });
973
- window.location.href = `${apiOrigin}/api/v1/auth/oauth/google?${params}`;
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: "rgba(22,27,45,0.92)" },
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("div", { className: "inline-flex items-center justify-center w-10 h-10 rounded-xl bg-gradient-to-br from-emerald-600 to-teal-600 shadow-lg shadow-emerald-500/30 mb-4", children: /* @__PURE__ */ jsx3(SparkleIcon, {}) }),
1048
- /* @__PURE__ */ jsx3("h1", { className: "text-xl font-semibold text-white/90", children: step === "verify" ? "Check your email" : "Create an account" }),
1049
- /* @__PURE__ */ jsx3("p", { className: "text-sm text-[#475569] mt-1", children: step === "verify" ? `We sent a code to ${email}` : "Start your free trial today" })
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(GoogleButton2, { onClick: handleGoogleSignUp }),
1055
- /* @__PURE__ */ jsx3(Divider2, {}),
1056
- /* @__PURE__ */ jsxs2("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
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
- SignUpInput,
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
- SignUpInput,
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(SignUpPrimaryButton, { loading, children: "Create account" })
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
- SignUpInput,
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(SignUpPrimaryButton, { loading, children: "Verify email" }),
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 text-[#475569] hover:text-white/70 transition-colors py-1",
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 SignUpInput({ onChange, className, ...props }) {
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 focus:border-emerald-500/60 transition-colors",
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 SignUpPrimaryButton({
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
- "bg-gradient-to-r from-emerald-600 to-teal-600",
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 GoogleButton2({ onClick }) {
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
- /* @__PURE__ */ jsx3(GoogleIcon2, {}),
1166
- "Continue with Google"
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] text-[#475569] uppercase tracking-wider", children: "or" }),
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 colors = ["", "bg-red-500", "bg-amber-400", "bg-blue-400", "bg-emerald-400"];
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 ? colors[score] : "bg-white/10"
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(Fragment, { children });
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(Fragment, { children });
1407
+ return /* @__PURE__ */ jsx4(Fragment2, { children });
1234
1408
  }
1235
1409
 
1236
1410
  // src/components/RedirectComponents.tsx
1237
- import { useEffect as useEffect2 } from "react";
1411
+ import { useEffect as useEffect3 } from "react";
1238
1412
  function RedirectToSignIn({ redirectUrl = "/sign-in" }) {
1239
1413
  const { isLoaded, isSignedIn } = useVaultixContext();
1240
- useEffect2(() => {
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
- useEffect2(() => {
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 useEffect3, useRef as useRef3, useState as useState4 } from "react";
1260
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
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] = useState4(false);
1264
- const [signingOut, setSigningOut] = useState4(false);
1265
- const [showProfile, setShowProfile] = useState4(false);
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
- useEffect3(() => {
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(Fragment2, { children: [
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] = useState4("profile");
1330
- const [firstName, setFirstName] = useState4(user?.firstName ?? "");
1331
- const [lastName, setLastName] = useState4(user?.lastName ?? "");
1332
- const [imageUrl, setImageUrl] = useState4(user?.imageUrl ?? "");
1333
- const [currentPassword, setCurrentPassword] = useState4("");
1334
- const [newPassword, setNewPassword] = useState4("");
1335
- const [confirmPassword, setConfirmPassword] = useState4("");
1336
- const [saving, setSaving] = useState4(false);
1337
- const [error, setError] = useState4(null);
1338
- const [success, setSuccess] = useState4(null);
1339
- useEffect3(() => {
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] = useState4(null);
1451
- const [backupCodesLeft, setBackupCodesLeft] = useState4(null);
1452
- const [enrollStep, setEnrollStep] = useState4("idle");
1453
- const [qrDataUrl, setQrDataUrl] = useState4("");
1454
- const [manualKey, setManualKey] = useState4("");
1455
- const [enrollCode, setEnrollCode] = useState4("");
1456
- const [disableCode, setDisableCode] = useState4("");
1457
- const [backupCodes, setBackupCodes] = useState4([]);
1458
- const [loading, setLoading] = useState4(false);
1459
- const [error, setError] = useState4(null);
1460
- const [showDisable, setShowDisable] = useState4(false);
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
- useEffect3(() => {
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 useEffect4, useRef as useRef4, useState as useState5 } from "react";
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] = useState5(false);
1800
- const [orgs, setOrgs] = useState5([]);
1801
- const [switching, setSwitching] = useState5(null);
1973
+ const [open, setOpen] = useState6(false);
1974
+ const [orgs, setOrgs] = useState6([]);
1975
+ const [switching, setSwitching] = useState6(null);
1802
1976
  const containerRef = useRef4(null);
1803
- useEffect4(() => {
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
- useEffect4(() => {
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