@vaultix.ai/react 0.3.4 → 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 CHANGED
@@ -1,6 +1,12 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
+ type AuthMethod = "password" | "magic_link" | "passkey";
5
+ type OAuthProvider = "google" | "github" | "meta" | "linkedin" | "x" | "threads";
6
+ interface AppConfig {
7
+ methods: AuthMethod[];
8
+ providers: OAuthProvider[];
9
+ }
4
10
  type RiskLevel = "low" | "medium" | "high" | "critical";
5
11
  type ChallengeType = "passkey" | "magic_link" | "password" | "totp" | "sms_otp" | "email_otp";
6
12
  interface SessionClaims {
@@ -76,6 +82,11 @@ interface VaultixContextValue {
76
82
  isSignedIn: boolean;
77
83
  /** Resolved API origin derived from the publishable key. */
78
84
  apiOrigin: string;
85
+ /**
86
+ * Per-app auth configuration. Null while loading, then set from /api/v1/app/config.
87
+ * Controls which login methods and OAuth providers are rendered by <SignIn /> and <SignUp />.
88
+ */
89
+ appConfig: AppConfig | null;
79
90
  signOut: (redirectUrl?: string) => Promise<void>;
80
91
  /** Update the current user's profile. Resolves with the updated user. */
81
92
  updateUser: (params: UpdateUserParams) => Promise<VaultixUser>;
@@ -240,4 +251,4 @@ declare function getStoredToken(): string | null;
240
251
  /** Clears the stored session JWT. Call on 401 so the user is prompted to sign in again. */
241
252
  declare function clearStoredToken(): void;
242
253
 
243
- export { type ChallengeType, type ConnectPlatformOptions, OrganizationSwitcher, type PlatformConnectResult, RedirectToSignIn, RedirectToSignUp, type RiskLevel, type SessionClaims, SignIn, SignUp, SignedIn, SignedOut, type UpdateUserParams, UserButton, type VaultixAppearance, type VaultixAppearanceVariables, type VaultixContextValue, type VaultixOrganization, VaultixProvider, type VaultixProviderProps, type VaultixSession, type VaultixUser, clearStoredToken, getStoredToken, useAuth, useOrganization, usePlatformConnect, useSession, useUser, useVaultix };
254
+ export { type AppConfig, type AuthMethod, type ChallengeType, type ConnectPlatformOptions, type OAuthProvider, OrganizationSwitcher, type PlatformConnectResult, RedirectToSignIn, RedirectToSignUp, type RiskLevel, type SessionClaims, SignIn, SignUp, SignedIn, SignedOut, type UpdateUserParams, UserButton, type VaultixAppearance, type VaultixAppearanceVariables, type VaultixContextValue, type VaultixOrganization, VaultixProvider, type VaultixProviderProps, type VaultixSession, type VaultixUser, clearStoredToken, getStoredToken, useAuth, useOrganization, usePlatformConnect, useSession, useUser, useVaultix };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
+ type AuthMethod = "password" | "magic_link" | "passkey";
5
+ type OAuthProvider = "google" | "github" | "meta" | "linkedin" | "x" | "threads";
6
+ interface AppConfig {
7
+ methods: AuthMethod[];
8
+ providers: OAuthProvider[];
9
+ }
4
10
  type RiskLevel = "low" | "medium" | "high" | "critical";
5
11
  type ChallengeType = "passkey" | "magic_link" | "password" | "totp" | "sms_otp" | "email_otp";
6
12
  interface SessionClaims {
@@ -76,6 +82,11 @@ interface VaultixContextValue {
76
82
  isSignedIn: boolean;
77
83
  /** Resolved API origin derived from the publishable key. */
78
84
  apiOrigin: string;
85
+ /**
86
+ * Per-app auth configuration. Null while loading, then set from /api/v1/app/config.
87
+ * Controls which login methods and OAuth providers are rendered by <SignIn /> and <SignUp />.
88
+ */
89
+ appConfig: AppConfig | null;
79
90
  signOut: (redirectUrl?: string) => Promise<void>;
80
91
  /** Update the current user's profile. Resolves with the updated user. */
81
92
  updateUser: (params: UpdateUserParams) => Promise<VaultixUser>;
@@ -240,4 +251,4 @@ declare function getStoredToken(): string | null;
240
251
  /** Clears the stored session JWT. Call on 401 so the user is prompted to sign in again. */
241
252
  declare function clearStoredToken(): void;
242
253
 
243
- export { type ChallengeType, type ConnectPlatformOptions, OrganizationSwitcher, type PlatformConnectResult, RedirectToSignIn, RedirectToSignUp, type RiskLevel, type SessionClaims, SignIn, SignUp, SignedIn, SignedOut, type UpdateUserParams, UserButton, type VaultixAppearance, type VaultixAppearanceVariables, type VaultixContextValue, type VaultixOrganization, VaultixProvider, type VaultixProviderProps, type VaultixSession, type VaultixUser, clearStoredToken, getStoredToken, useAuth, useOrganization, usePlatformConnect, useSession, useUser, useVaultix };
254
+ export { type AppConfig, type AuthMethod, type ChallengeType, type ConnectPlatformOptions, type OAuthProvider, OrganizationSwitcher, type PlatformConnectResult, RedirectToSignIn, RedirectToSignUp, type RiskLevel, type SessionClaims, SignIn, SignUp, SignedIn, SignedOut, type UpdateUserParams, UserButton, type VaultixAppearance, type VaultixAppearanceVariables, type VaultixContextValue, type VaultixOrganization, VaultixProvider, type VaultixProviderProps, type VaultixSession, type VaultixUser, clearStoredToken, getStoredToken, useAuth, useOrganization, usePlatformConnect, useSession, useUser, useVaultix };
package/dist/index.js CHANGED
@@ -112,6 +112,7 @@ function VaultixProvider({
112
112
  const [user, setUser] = (0, import_react.useState)(null);
113
113
  const [session, setSession] = (0, import_react.useState)(null);
114
114
  const [organization, setOrganization] = (0, import_react.useState)(null);
115
+ const [appConfig, setAppConfig] = (0, import_react.useState)(null);
115
116
  const jwtRef = (0, import_react.useRef)(null);
116
117
  const refreshTimerRef = (0, import_react.useRef)(null);
117
118
  const clearAuth = (0, import_react.useCallback)(() => {
@@ -212,7 +213,21 @@ function VaultixProvider({
212
213
  if (!cancelled) setIsLoaded(true);
213
214
  }
214
215
  }
216
+ async function fetchAppConfig() {
217
+ try {
218
+ const res = await fetch(
219
+ `${apiOrigin}/api/v1/app/config?pk=${encodeURIComponent(publishableKey)}`,
220
+ { credentials: "omit" }
221
+ );
222
+ if (res.ok && !cancelled) {
223
+ const cfg = await res.json();
224
+ setAppConfig(cfg);
225
+ }
226
+ } catch {
227
+ }
228
+ }
215
229
  hydrate();
230
+ void fetchAppConfig();
216
231
  return () => {
217
232
  cancelled = true;
218
233
  if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
@@ -271,6 +286,7 @@ function VaultixProvider({
271
286
  isLoaded,
272
287
  isSignedIn: !!session,
273
288
  apiOrigin,
289
+ appConfig,
274
290
  signOut,
275
291
  updateUser,
276
292
  connectPlatform
@@ -413,6 +429,16 @@ function SignIn({
413
429
  const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
414
430
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
415
431
  const mutedColor = vars.colorTextMuted ?? "#475569";
432
+ let appConfig = null;
433
+ try {
434
+ appConfig = useVaultixContext().appConfig;
435
+ } catch {
436
+ }
437
+ const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
438
+ const enabledMethods = appConfig?.methods ?? ["password", "magic_link", "passkey"];
439
+ const hasPassword = enabledMethods.includes("password");
440
+ const hasMagicLink = enabledMethods.includes("magic_link");
441
+ const hasPasskey = enabledMethods.includes("passkey");
416
442
  const [step, setStep] = (0, import_react3.useState)("email");
417
443
  const [email, setEmail] = (0, import_react3.useState)("");
418
444
  const [password, setPassword] = (0, import_react3.useState)("");
@@ -462,7 +488,15 @@ function SignIn({
462
488
  setErr(data.error ?? "Could not look up account.");
463
489
  return;
464
490
  }
465
- setStep(data.preferred_challenge === "passkey" ? "passkey" : "password");
491
+ if (data.preferred_challenge === "passkey" && hasPasskey) {
492
+ setStep("passkey");
493
+ } else if (hasPassword) {
494
+ setStep("password");
495
+ } else if (hasMagicLink) {
496
+ await handleMagicLinkRequest();
497
+ } else if (hasPasskey) {
498
+ setStep("passkey");
499
+ }
466
500
  } catch {
467
501
  setErr("Network error. Please try again.");
468
502
  } finally {
@@ -695,13 +729,13 @@ function SignIn({
695
729
  error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "rounded-lg bg-red-500/10 border border-red-500/30 px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-red-400", children: error }) }),
696
730
  info && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "rounded-lg bg-blue-500/10 border border-blue-500/30 px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-blue-400", children: info }) }),
697
731
  step === "email" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GoogleButton, { onClick: handleGoogleSignIn }),
699
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GitHubButton, { onClick: handleGitHubSignIn }),
700
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MetaButton, { onClick: handleMetaSignIn }),
701
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LinkedInButton, { onClick: handleLinkedInSignIn }),
702
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(XButton, { onClick: handleXSignIn }),
703
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Divider, { mutedColor }),
704
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
732
+ enabledProviders.includes("google") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GoogleButton, { onClick: handleGoogleSignIn }),
733
+ enabledProviders.includes("github") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GitHubButton, { onClick: handleGitHubSignIn }),
734
+ enabledProviders.includes("meta") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MetaButton, { onClick: handleMetaSignIn }),
735
+ enabledProviders.includes("linkedin") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LinkedInButton, { onClick: handleLinkedInSignIn }),
736
+ enabledProviders.includes("x") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(XButton, { onClick: handleXSignIn }),
737
+ (hasPassword || hasMagicLink || hasPasskey) && enabledProviders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Divider, { mutedColor }),
738
+ (hasPassword || hasMagicLink || hasPasskey) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
705
739
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
706
740
  Input,
707
741
  {
@@ -731,12 +765,14 @@ function SignIn({
731
765
  }
732
766
  ),
733
767
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, primaryColor, children: "Sign in" }),
734
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
735
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" }),
736
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", style: { color: mutedColor }, children: "or" }),
737
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" })
768
+ hasMagicLink && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
769
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
770
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" }),
771
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", style: { color: mutedColor }, children: "or" }),
772
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" })
773
+ ] }),
774
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: handleMagicLinkRequest, mutedColor, children: "\u2709 Email me a sign-in link" })
738
775
  ] }),
739
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: handleMagicLinkRequest, mutedColor, children: "\u2709 Email me a sign-in link" }),
740
776
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: () => {
741
777
  setStep("forgot");
742
778
  setError(null);
@@ -1070,6 +1106,14 @@ function SignUp({
1070
1106
  const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
1071
1107
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
1072
1108
  const mutedColor = vars.colorTextMuted ?? "#475569";
1109
+ let appConfig = null;
1110
+ try {
1111
+ appConfig = useVaultixContext().appConfig;
1112
+ } catch {
1113
+ }
1114
+ const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
1115
+ const enabledMethods = appConfig?.methods ?? ["password", "magic_link", "passkey"];
1116
+ const hasPassword = enabledMethods.includes("password");
1073
1117
  const [step, setStep] = (0, import_react4.useState)("email");
1074
1118
  const [email, setEmail] = (0, import_react4.useState)("");
1075
1119
  const [password, setPassword] = (0, import_react4.useState)("");
@@ -1181,13 +1225,13 @@ function SignUp({
1181
1225
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-8 pb-8 space-y-4", children: [
1182
1226
  error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rounded-lg bg-red-500/10 border border-red-500/30 px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-red-400", children: error }) }),
1183
1227
  step === "email" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-3", children: [
1184
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GoogleIcon2, {}), label: "Continue with Google", onClick: () => oauthRedirect("google") }),
1185
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GitHubIcon2, {}), label: "Continue with GitHub", onClick: () => oauthRedirect("github") }),
1186
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MetaIcon2, {}), label: "Continue with Facebook", onClick: () => oauthRedirect("meta") }),
1187
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LinkedInIcon2, {}), label: "Continue with LinkedIn", onClick: () => oauthRedirect("linkedin") }),
1188
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(XIcon2, {}), label: "Continue with X", onClick: () => oauthRedirect("x") }),
1189
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Divider2, { mutedColor }),
1190
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
1228
+ enabledProviders.includes("google") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GoogleIcon2, {}), label: "Continue with Google", onClick: () => oauthRedirect("google") }),
1229
+ enabledProviders.includes("github") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GitHubIcon2, {}), label: "Continue with GitHub", onClick: () => oauthRedirect("github") }),
1230
+ enabledProviders.includes("meta") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MetaIcon2, {}), label: "Continue with Facebook", onClick: () => oauthRedirect("meta") }),
1231
+ enabledProviders.includes("linkedin") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LinkedInIcon2, {}), label: "Continue with LinkedIn", onClick: () => oauthRedirect("linkedin") }),
1232
+ enabledProviders.includes("x") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OAuthButton2, { icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(XIcon2, {}), label: "Continue with X", onClick: () => oauthRedirect("x") }),
1233
+ hasPassword && enabledProviders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Divider2, { mutedColor }),
1234
+ hasPassword && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
1191
1235
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1192
1236
  Input2,
1193
1237
  {
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
@@ -333,7 +349,7 @@ function useAuth() {
333
349
  // src/components/SignIn.tsx
334
350
  import { clsx } from "clsx";
335
351
  import { useRef as useRef2, useState as useState3 } from "react";
336
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
352
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
337
353
  function toBase64url(buf) {
338
354
  return btoa(String.fromCharCode(...new Uint8Array(buf))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
339
355
  }
@@ -378,6 +394,16 @@ function SignIn({
378
394
  const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
379
395
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
380
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");
381
407
  const [step, setStep] = useState3("email");
382
408
  const [email, setEmail] = useState3("");
383
409
  const [password, setPassword] = useState3("");
@@ -427,7 +453,15 @@ function SignIn({
427
453
  setErr(data.error ?? "Could not look up account.");
428
454
  return;
429
455
  }
430
- 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
+ }
431
465
  } catch {
432
466
  setErr("Network error. Please try again.");
433
467
  } finally {
@@ -660,13 +694,13 @@ function SignIn({
660
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 }) }),
661
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 }) }),
662
696
  step === "email" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
663
- /* @__PURE__ */ jsx2(GoogleButton, { onClick: handleGoogleSignIn }),
664
- /* @__PURE__ */ jsx2(GitHubButton, { onClick: handleGitHubSignIn }),
665
- /* @__PURE__ */ jsx2(MetaButton, { onClick: handleMetaSignIn }),
666
- /* @__PURE__ */ jsx2(LinkedInButton, { onClick: handleLinkedInSignIn }),
667
- /* @__PURE__ */ jsx2(XButton, { onClick: handleXSignIn }),
668
- /* @__PURE__ */ jsx2(Divider, { mutedColor }),
669
- /* @__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: [
670
704
  /* @__PURE__ */ jsx2(
671
705
  Input,
672
706
  {
@@ -696,12 +730,14 @@ function SignIn({
696
730
  }
697
731
  ),
698
732
  /* @__PURE__ */ jsx2(PrimaryButton, { loading, primaryColor, children: "Sign in" }),
699
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
700
- /* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" }),
701
- /* @__PURE__ */ jsx2("span", { className: "text-[10px]", style: { color: mutedColor }, children: "or" }),
702
- /* @__PURE__ */ jsx2("div", { className: "flex-1 h-px bg-white/8" })
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" })
703
740
  ] }),
704
- /* @__PURE__ */ jsx2(GhostButton, { onClick: handleMagicLinkRequest, mutedColor, children: "\u2709 Email me a sign-in link" }),
705
741
  /* @__PURE__ */ jsx2(GhostButton, { onClick: () => {
706
742
  setStep("forgot");
707
743
  setError(null);
@@ -1035,6 +1071,14 @@ function SignUp({
1035
1071
  const cardBg = vars.colorBackground ?? "rgba(22,27,45,0.92)";
1036
1072
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
1037
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");
1038
1082
  const [step, setStep] = useState4("email");
1039
1083
  const [email, setEmail] = useState4("");
1040
1084
  const [password, setPassword] = useState4("");
@@ -1146,13 +1190,13 @@ function SignUp({
1146
1190
  /* @__PURE__ */ jsxs2("div", { className: "px-8 pb-8 space-y-4", children: [
1147
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 }) }),
1148
1192
  step === "email" && /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
1149
- /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(GoogleIcon2, {}), label: "Continue with Google", onClick: () => oauthRedirect("google") }),
1150
- /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(GitHubIcon2, {}), label: "Continue with GitHub", onClick: () => oauthRedirect("github") }),
1151
- /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(MetaIcon2, {}), label: "Continue with Facebook", onClick: () => oauthRedirect("meta") }),
1152
- /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(LinkedInIcon2, {}), label: "Continue with LinkedIn", onClick: () => oauthRedirect("linkedin") }),
1153
- /* @__PURE__ */ jsx3(OAuthButton2, { icon: /* @__PURE__ */ jsx3(XIcon2, {}), label: "Continue with X", onClick: () => oauthRedirect("x") }),
1154
- /* @__PURE__ */ jsx3(Divider2, { mutedColor }),
1155
- /* @__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: [
1156
1200
  /* @__PURE__ */ jsx3(
1157
1201
  Input2,
1158
1202
  {
@@ -1351,16 +1395,16 @@ function XIcon2() {
1351
1395
  }
1352
1396
 
1353
1397
  // src/components/SignedIn.tsx
1354
- import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
1398
+ import { Fragment as Fragment2, jsx as jsx4 } from "react/jsx-runtime";
1355
1399
  function SignedIn({ children }) {
1356
1400
  const { isLoaded, isSignedIn } = useVaultixContext();
1357
1401
  if (!isLoaded || !isSignedIn) return null;
1358
- return /* @__PURE__ */ jsx4(Fragment, { children });
1402
+ return /* @__PURE__ */ jsx4(Fragment2, { children });
1359
1403
  }
1360
1404
  function SignedOut({ children }) {
1361
1405
  const { isLoaded, isSignedIn } = useVaultixContext();
1362
1406
  if (!isLoaded || isSignedIn) return null;
1363
- return /* @__PURE__ */ jsx4(Fragment, { children });
1407
+ return /* @__PURE__ */ jsx4(Fragment2, { children });
1364
1408
  }
1365
1409
 
1366
1410
  // src/components/RedirectComponents.tsx
@@ -1387,7 +1431,7 @@ function RedirectToSignUp({ redirectUrl = "/sign-up" }) {
1387
1431
  // src/components/UserButton.tsx
1388
1432
  import { clsx as clsx3 } from "clsx";
1389
1433
  import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
1390
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1434
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1391
1435
  function UserButton({ showName = false, afterSignOutUrl, className }) {
1392
1436
  const { user, session, isLoaded, isSignedIn, signOut } = useVaultixContext();
1393
1437
  const [open, setOpen] = useState5(false);
@@ -1409,7 +1453,7 @@ function UserButton({ showName = false, afterSignOutUrl, className }) {
1409
1453
  await signOut();
1410
1454
  if (afterSignOutUrl) window.location.href = afterSignOutUrl;
1411
1455
  }
1412
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
1456
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1413
1457
  /* @__PURE__ */ jsxs3("div", { ref: containerRef, className: clsx3("relative", className), children: [
1414
1458
  /* @__PURE__ */ jsxs3(
1415
1459
  "button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultix.ai/react",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Vaultix-ID React SDK — drop-in auth components for any React app",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",