@vaultix.ai/react 0.1.0 → 0.2.1

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.js CHANGED
@@ -21,10 +21,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  OrganizationSwitcher: () => OrganizationSwitcher,
24
+ RedirectToSignIn: () => RedirectToSignIn,
25
+ RedirectToSignUp: () => RedirectToSignUp,
24
26
  SignIn: () => SignIn,
25
27
  SignUp: () => SignUp,
28
+ SignedIn: () => SignedIn,
29
+ SignedOut: () => SignedOut,
26
30
  UserButton: () => UserButton,
27
31
  VaultixProvider: () => VaultixProvider,
32
+ useAuth: () => useAuth,
28
33
  useOrganization: () => useOrganization,
29
34
  useSession: () => useSession,
30
35
  useUser: () => useUser,
@@ -55,6 +60,26 @@ function resolveApiOrigin(key, apiUrlProp) {
55
60
  throw new Error("Publishable key has an unreadable API origin payload.");
56
61
  }
57
62
  }
63
+ var STORAGE_KEY = "vaultix_jwt";
64
+ function storeJwt(jwt) {
65
+ try {
66
+ sessionStorage.setItem(STORAGE_KEY, jwt);
67
+ } catch {
68
+ }
69
+ }
70
+ function loadJwt() {
71
+ try {
72
+ return sessionStorage.getItem(STORAGE_KEY);
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ function clearJwt() {
78
+ try {
79
+ sessionStorage.removeItem(STORAGE_KEY);
80
+ } catch {
81
+ }
82
+ }
58
83
  var VaultixContext = (0, import_react.createContext)(null);
59
84
  function useVaultixContext() {
60
85
  const ctx = (0, import_react.useContext)(VaultixContext);
@@ -77,42 +102,89 @@ function VaultixProvider({
77
102
  const [user, setUser] = (0, import_react.useState)(null);
78
103
  const [session, setSession] = (0, import_react.useState)(null);
79
104
  const [organization, setOrganization] = (0, import_react.useState)(null);
105
+ const jwtRef = (0, import_react.useRef)(null);
80
106
  const refreshTimerRef = (0, import_react.useRef)(null);
107
+ const clearAuth = (0, import_react.useCallback)(() => {
108
+ jwtRef.current = null;
109
+ clearJwt();
110
+ setUser(null);
111
+ setSession(null);
112
+ setOrganization(null);
113
+ }, []);
81
114
  const scheduleRefresh = (0, import_react.useCallback)(
82
115
  (expiresAt) => {
83
116
  if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
84
- const msUntilRefresh = expiresAt * 1e3 - Date.now() - 1e4;
117
+ const msUntilRefresh = expiresAt * 1e3 - Date.now() - 3e4;
85
118
  if (msUntilRefresh <= 0) return;
86
119
  refreshTimerRef.current = setTimeout(async () => {
87
120
  try {
88
- const res = await fetch(`${apiOrigin}/v1/session/refresh`, {
121
+ const headers = {};
122
+ if (jwtRef.current) headers["Authorization"] = `Bearer ${jwtRef.current}`;
123
+ const res = await fetch(`${apiOrigin}/api/v1/session/refresh`, {
89
124
  method: "POST",
90
- credentials: "include"
125
+ credentials: jwtRef.current ? "omit" : "include",
126
+ headers
91
127
  });
92
128
  if (!res.ok) {
93
- setUser(null);
94
- setSession(null);
95
- setOrganization(null);
129
+ clearAuth();
96
130
  return;
97
131
  }
98
132
  const data = await res.json();
133
+ if (data.session_jwt) {
134
+ jwtRef.current = data.session_jwt;
135
+ storeJwt(data.session_jwt);
136
+ }
99
137
  setSession(data.session);
100
138
  scheduleRefresh(data.session.expiresAt);
101
139
  } catch {
102
140
  }
103
141
  }, msUntilRefresh);
104
142
  },
105
- [apiOrigin]
143
+ [apiOrigin, clearAuth]
106
144
  );
107
145
  (0, import_react.useEffect)(() => {
108
146
  let cancelled = false;
109
147
  async function hydrate() {
148
+ let jwt = null;
149
+ if (typeof window !== "undefined") {
150
+ const url = new URL(window.location.href);
151
+ const handshakeToken = url.searchParams.get("__vaultix_handshake");
152
+ if (handshakeToken) {
153
+ url.searchParams.delete("__vaultix_handshake");
154
+ window.history.replaceState({}, "", url.toString());
155
+ try {
156
+ const res = await fetch(`${apiOrigin}/api/v1/tokens/exchange`, {
157
+ method: "POST",
158
+ headers: { "Content-Type": "application/json" },
159
+ body: JSON.stringify({ handshake_token: handshakeToken })
160
+ });
161
+ if (res.ok) {
162
+ const data = await res.json();
163
+ jwt = data.session_jwt;
164
+ storeJwt(jwt);
165
+ }
166
+ } catch {
167
+ }
168
+ } else {
169
+ jwt = loadJwt();
170
+ }
171
+ jwtRef.current = jwt;
172
+ }
110
173
  try {
111
- const res = await fetch(`${apiOrigin}/v1/me`, {
112
- credentials: "include",
113
- headers: { "X-Vaultix-Publishable-Key": publishableKey }
174
+ const headers = {
175
+ "X-Vaultix-Publishable-Key": publishableKey
176
+ };
177
+ if (jwt) headers["Authorization"] = `Bearer ${jwt}`;
178
+ const res = await fetch(`${apiOrigin}/api/v1/me`, {
179
+ // Use Bearer token for cross-domain; fall back to cookie for same-domain
180
+ credentials: jwt ? "omit" : "include",
181
+ headers
114
182
  });
115
183
  if (!res.ok) {
184
+ if (jwt) {
185
+ clearJwt();
186
+ jwtRef.current = null;
187
+ }
116
188
  if (!cancelled) setIsLoaded(true);
117
189
  return;
118
190
  }
@@ -135,19 +207,21 @@ function VaultixProvider({
135
207
  };
136
208
  }, [apiOrigin, publishableKey, scheduleRefresh]);
137
209
  const signOut = (0, import_react.useCallback)(async () => {
210
+ const jwt = jwtRef.current;
211
+ clearAuth();
212
+ if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
138
213
  try {
139
- await fetch(`${apiOrigin}/v1/session`, {
214
+ const headers = {};
215
+ if (jwt) headers["Authorization"] = `Bearer ${jwt}`;
216
+ await fetch(`${apiOrigin}/api/v1/session`, {
140
217
  method: "DELETE",
141
- credentials: "include"
218
+ credentials: jwt ? "omit" : "include",
219
+ headers
142
220
  });
143
221
  } catch {
144
- } finally {
145
- setUser(null);
146
- setSession(null);
147
- setOrganization(null);
148
- if (afterSignInUrl) window.location.href = afterSignInUrl;
149
222
  }
150
- }, [apiOrigin, afterSignInUrl]);
223
+ if (afterSignInUrl) window.location.href = afterSignInUrl;
224
+ }, [apiOrigin, afterSignInUrl, clearAuth]);
151
225
  const value = {
152
226
  user,
153
227
  session,
@@ -169,6 +243,7 @@ function VaultixProvider({
169
243
  }
170
244
 
171
245
  // src/hooks/index.ts
246
+ var import_react2 = require("react");
172
247
  function useVaultix() {
173
248
  return useVaultixContext();
174
249
  }
@@ -184,10 +259,26 @@ function useOrganization() {
184
259
  const { organization, isLoaded } = useVaultixContext();
185
260
  return { organization, isLoaded };
186
261
  }
262
+ function useAuth() {
263
+ const { user, session, isLoaded, isSignedIn, signOut } = useVaultixContext();
264
+ const getToken = (0, import_react2.useCallback)(async () => {
265
+ if (!isSignedIn) return null;
266
+ return null;
267
+ }, [isSignedIn]);
268
+ return {
269
+ isLoaded,
270
+ isSignedIn,
271
+ userId: user?.id ?? null,
272
+ sessionId: session?.id ?? null,
273
+ orgId: session?.orgId ?? null,
274
+ signOut,
275
+ getToken
276
+ };
277
+ }
187
278
 
188
279
  // src/components/SignIn.tsx
189
280
  var import_clsx = require("clsx");
190
- var import_react2 = require("react");
281
+ var import_react3 = require("react");
191
282
  var import_jsx_runtime2 = require("react/jsx-runtime");
192
283
  function toBase64url(buf) {
193
284
  return btoa(String.fromCharCode(...new Uint8Array(buf))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -200,6 +291,18 @@ function resolveApiOrigin2(prop) {
200
291
  }
201
292
  return "";
202
293
  }
294
+ function resolveAfterSignInUrl(redirectUrlProp) {
295
+ if (redirectUrlProp) return redirectUrlProp;
296
+ if (typeof document !== "undefined") {
297
+ const el = document.querySelector("[data-vaultix-after-sign-in]");
298
+ const attr = el?.getAttribute("data-vaultix-after-sign-in");
299
+ if (attr) return attr;
300
+ const params = new URLSearchParams(window.location.search);
301
+ const redirectUrl = params.get("redirect_url");
302
+ if (redirectUrl) return redirectUrl;
303
+ }
304
+ return "/";
305
+ }
203
306
  function SignIn({
204
307
  redirectUrl,
205
308
  onSuccess,
@@ -208,17 +311,32 @@ function SignIn({
208
311
  className
209
312
  }) {
210
313
  const apiOrigin = resolveApiOrigin2(apiOriginProp);
211
- const [step, setStep] = (0, import_react2.useState)("email");
212
- const [email, setEmail] = (0, import_react2.useState)("");
213
- const [password, setPassword] = (0, import_react2.useState)("");
214
- const [totp, setTotp] = (0, import_react2.useState)("");
215
- const [error, setError] = (0, import_react2.useState)(null);
216
- const [loading, setLoading] = (0, import_react2.useState)(false);
217
- const challengeIdRef = (0, import_react2.useRef)(null);
314
+ const [step, setStep] = (0, import_react3.useState)("email");
315
+ const [email, setEmail] = (0, import_react3.useState)("");
316
+ const [password, setPassword] = (0, import_react3.useState)("");
317
+ const [totp, setTotp] = (0, import_react3.useState)("");
318
+ const [forgotCode, setForgotCode] = (0, import_react3.useState)("");
319
+ const [newPassword, setNewPassword] = (0, import_react3.useState)("");
320
+ const [error, setError] = (0, import_react3.useState)(null);
321
+ const [loading, setLoading] = (0, import_react3.useState)(false);
322
+ const [info, setInfo] = (0, import_react3.useState)(null);
323
+ const challengeIdRef = (0, import_react3.useRef)(null);
218
324
  function setErr(msg) {
219
325
  setError(msg);
220
326
  onError?.(msg);
221
327
  }
328
+ function handleSuccess(handshakeToken) {
329
+ onSuccess?.(handshakeToken);
330
+ const target = resolveAfterSignInUrl(redirectUrl);
331
+ const url = new URL(target, window.location.origin);
332
+ url.searchParams.set("__vaultix_handshake", handshakeToken);
333
+ window.location.href = url.toString();
334
+ }
335
+ function handleGoogleSignIn() {
336
+ const target = resolveAfterSignInUrl(redirectUrl);
337
+ const params = new URLSearchParams({ redirect_url: target });
338
+ window.location.href = `${apiOrigin}/v1/auth/oauth/google?${params}`;
339
+ }
222
340
  async function handleEmailSubmit(e) {
223
341
  e.preventDefault();
224
342
  setError(null);
@@ -263,7 +381,7 @@ function SignIn({
263
381
  setStep("totp");
264
382
  return;
265
383
  }
266
- handleSuccess(data.session_id);
384
+ handleSuccess(data.handshake_token);
267
385
  } catch {
268
386
  setErr("Network error. Please try again.");
269
387
  } finally {
@@ -319,7 +437,7 @@ function SignIn({
319
437
  setErr(verifyData.error ?? "Passkey verification failed.");
320
438
  return;
321
439
  }
322
- handleSuccess(verifyData.session_id);
440
+ handleSuccess(verifyData.handshake_token);
323
441
  } catch (err) {
324
442
  if (err instanceof Error && err.name === "NotAllowedError") {
325
443
  setErr("Passkey was cancelled or timed out.");
@@ -339,28 +457,86 @@ function SignIn({
339
457
  method: "POST",
340
458
  credentials: "include",
341
459
  headers: { "Content-Type": "application/json" },
342
- body: JSON.stringify({
343
- challenge_id: challengeIdRef.current,
344
- code: totp
345
- })
460
+ body: JSON.stringify({ challenge_id: challengeIdRef.current, code: totp })
346
461
  });
347
462
  const data = await res.json();
348
463
  if (!res.ok) {
349
464
  setErr(data.error ?? "Invalid code.");
350
465
  return;
351
466
  }
352
- handleSuccess(data.session_id);
467
+ handleSuccess(data.handshake_token);
353
468
  } catch {
354
469
  setErr("Network error. Please try again.");
355
470
  } finally {
356
471
  setLoading(false);
357
472
  }
358
473
  }
359
- function handleSuccess(sessionId) {
360
- onSuccess?.(sessionId);
361
- const target = redirectUrl ?? document.querySelector("[data-vaultix-after-sign-in]")?.getAttribute("data-vaultix-after-sign-in") ?? "/";
362
- if (target) window.location.href = target;
474
+ async function handleForgotSubmit(e) {
475
+ e.preventDefault();
476
+ setError(null);
477
+ setLoading(true);
478
+ try {
479
+ await fetch(`${apiOrigin}/v1/auth/forgot-password`, {
480
+ method: "POST",
481
+ credentials: "include",
482
+ headers: { "Content-Type": "application/json" },
483
+ body: JSON.stringify({ email })
484
+ });
485
+ setInfo("Check your email for a reset code.");
486
+ setStep("forgot-verify");
487
+ } catch {
488
+ setErr("Network error. Please try again.");
489
+ } finally {
490
+ setLoading(false);
491
+ }
492
+ }
493
+ async function handleForgotVerifySubmit(e) {
494
+ e.preventDefault();
495
+ setError(null);
496
+ setInfo(null);
497
+ setStep("forgot-reset");
498
+ }
499
+ async function handleResetPasswordSubmit(e) {
500
+ e.preventDefault();
501
+ setError(null);
502
+ setLoading(true);
503
+ try {
504
+ const res = await fetch(`${apiOrigin}/v1/auth/reset-password`, {
505
+ method: "POST",
506
+ credentials: "include",
507
+ headers: { "Content-Type": "application/json" },
508
+ body: JSON.stringify({ email, code: forgotCode, new_password: newPassword })
509
+ });
510
+ const data = await res.json();
511
+ if (!res.ok) {
512
+ setErr(data.error ?? "Could not reset password.");
513
+ return;
514
+ }
515
+ handleSuccess(data.handshake_token);
516
+ } catch {
517
+ setErr("Network error. Please try again.");
518
+ } finally {
519
+ setLoading(false);
520
+ }
363
521
  }
522
+ const title = {
523
+ email: "Sign in",
524
+ password: "Enter password",
525
+ passkey: "Passkey sign-in",
526
+ totp: "Two-factor code",
527
+ forgot: "Forgot password",
528
+ "forgot-verify": "Enter reset code",
529
+ "forgot-reset": "New password"
530
+ };
531
+ const subtitle = {
532
+ email: "Welcome back",
533
+ password: email,
534
+ passkey: email,
535
+ totp: "Enter the 6-digit code from your authenticator app",
536
+ forgot: "We'll send a reset code to your email",
537
+ "forgot-verify": `Code sent to ${email}`,
538
+ "forgot-reset": "Choose a new password"
539
+ };
364
540
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
365
541
  "div",
366
542
  {
@@ -373,34 +549,29 @@ function SignIn({
373
549
  children: [
374
550
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-8 pt-8 pb-6 text-center", children: [
375
551
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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__ */ (0, import_jsx_runtime2.jsx)(LockIcon, {}) }),
376
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h1", { className: "text-xl font-semibold text-white/90", children: [
377
- step === "email" && "Sign in",
378
- step === "password" && "Enter password",
379
- step === "passkey" && "Passkey sign-in",
380
- step === "totp" && "Two-factor code"
381
- ] }),
382
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-sm text-[#475569] mt-1", children: [
383
- step === "email" && "Welcome back",
384
- step === "password" && email,
385
- step === "passkey" && email,
386
- step === "totp" && "Enter the 6-digit code from your authenticator app"
387
- ] })
552
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: "text-xl font-semibold text-white/90", children: title[step] }),
553
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-[#475569] mt-1", children: subtitle[step] })
388
554
  ] }),
389
555
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-8 pb-8 space-y-4", children: [
390
556
  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 }) }),
391
- step === "email" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
392
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
393
- Input,
394
- {
395
- type: "email",
396
- placeholder: "you@company.com",
397
- value: email,
398
- onChange: setEmail,
399
- autoFocus: true,
400
- required: true
401
- }
402
- ),
403
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Continue" })
557
+ 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 }) }),
558
+ step === "email" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
559
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GoogleButton, { onClick: handleGoogleSignIn }),
560
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Divider, {}),
561
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleEmailSubmit, className: "space-y-3", children: [
562
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
563
+ Input,
564
+ {
565
+ type: "email",
566
+ placeholder: "you@company.com",
567
+ value: email,
568
+ onChange: setEmail,
569
+ autoFocus: true,
570
+ required: true
571
+ }
572
+ ),
573
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Continue" })
574
+ ] })
404
575
  ] }),
405
576
  step === "password" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handlePasswordSubmit, className: "space-y-3", children: [
406
577
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -415,6 +586,10 @@ function SignIn({
415
586
  }
416
587
  ),
417
588
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Sign in" }),
589
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: () => {
590
+ setStep("forgot");
591
+ setError(null);
592
+ }, children: "Forgot password?" }),
418
593
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: () => setStep("email"), children: "\u2190 Back" })
419
594
  ] }),
420
595
  step === "passkey" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
@@ -443,6 +618,58 @@ function SignIn({
443
618
  ),
444
619
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Verify" }),
445
620
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: () => setStep("password"), children: "\u2190 Back" })
621
+ ] }),
622
+ step === "forgot" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleForgotSubmit, className: "space-y-3", children: [
623
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
624
+ Input,
625
+ {
626
+ type: "email",
627
+ placeholder: "you@company.com",
628
+ value: email,
629
+ onChange: setEmail,
630
+ autoFocus: true,
631
+ required: true
632
+ }
633
+ ),
634
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Send reset code" }),
635
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GhostButton, { onClick: () => {
636
+ setStep("password");
637
+ setError(null);
638
+ }, children: "\u2190 Back" })
639
+ ] }),
640
+ step === "forgot-verify" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleForgotVerifySubmit, className: "space-y-3", children: [
641
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
642
+ Input,
643
+ {
644
+ type: "text",
645
+ inputMode: "numeric",
646
+ pattern: "[0-9]{6}",
647
+ maxLength: 6,
648
+ placeholder: "000000",
649
+ value: forgotCode,
650
+ onChange: setForgotCode,
651
+ autoFocus: true,
652
+ required: true,
653
+ className: "text-center tracking-[0.4em] text-lg"
654
+ }
655
+ ),
656
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Continue" })
657
+ ] }),
658
+ step === "forgot-reset" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: handleResetPasswordSubmit, className: "space-y-3", children: [
659
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
660
+ Input,
661
+ {
662
+ type: "password",
663
+ placeholder: "New password",
664
+ value: newPassword,
665
+ onChange: setNewPassword,
666
+ autoFocus: true,
667
+ required: true,
668
+ minLength: 8
669
+ }
670
+ ),
671
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PasswordStrength, { password: newPassword }),
672
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { loading, children: "Reset password" })
446
673
  ] })
447
674
  ] })
448
675
  ]
@@ -495,28 +722,63 @@ function GhostButton({ children, onClick }) {
495
722
  }
496
723
  );
497
724
  }
498
- function Spinner() {
725
+ function GoogleButton({ onClick }) {
499
726
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
500
- "svg",
727
+ "button",
501
728
  {
502
- className: "animate-spin h-4 w-4 text-white/80",
503
- xmlns: "http://www.w3.org/2000/svg",
504
- fill: "none",
505
- viewBox: "0 0 24 24",
729
+ type: "button",
730
+ onClick,
731
+ className: (0, import_clsx.clsx)(
732
+ "w-full flex items-center justify-center gap-3 px-4 py-2.5 rounded-xl",
733
+ "text-sm font-medium text-white/80",
734
+ "bg-white/5 border border-white/10",
735
+ "hover:bg-white/10 hover:border-white/20",
736
+ "transition-all duration-150"
737
+ ),
506
738
  children: [
507
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
508
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
509
- "path",
510
- {
511
- className: "opacity-75",
512
- fill: "currentColor",
513
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
514
- }
515
- )
739
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GoogleIcon, {}),
740
+ "Continue with Google"
516
741
  ]
517
742
  }
518
743
  );
519
744
  }
745
+ function Divider() {
746
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-3", children: [
747
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" }),
748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] text-[#475569] uppercase tracking-wider", children: "or" }),
749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 h-px bg-white/8" })
750
+ ] });
751
+ }
752
+ function PasswordStrength({ password }) {
753
+ const score = (() => {
754
+ if (password.length === 0) return 0;
755
+ let s = 0;
756
+ if (password.length >= 8) s++;
757
+ if (/[A-Z]/.test(password)) s++;
758
+ if (/[0-9]/.test(password)) s++;
759
+ if (/[^A-Za-z0-9]/.test(password)) s++;
760
+ return s;
761
+ })();
762
+ if (password.length === 0) return null;
763
+ const labels = ["", "Weak", "Fair", "Good", "Strong"];
764
+ const colors = ["", "bg-red-500", "bg-amber-400", "bg-blue-400", "bg-emerald-400"];
765
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-1", children: [
766
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
767
+ "div",
768
+ {
769
+ className: (0, import_clsx.clsx)("flex-1 h-0.5 rounded-full transition-all duration-300", i <= score ? colors[score] : "bg-white/10")
770
+ },
771
+ i
772
+ )) }),
773
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[10px] text-[#475569]", children: labels[score] })
774
+ ] });
775
+ }
776
+ function Spinner() {
777
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "animate-spin h-4 w-4 text-white/80", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
778
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
779
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
780
+ ] });
781
+ }
520
782
  function LockIcon() {
521
783
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
522
784
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
@@ -533,10 +795,18 @@ function FingerprintIcon() {
533
795
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 12v.01" })
534
796
  ] });
535
797
  }
798
+ function GoogleIcon() {
799
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", children: [
800
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z", fill: "#4285F4" }),
801
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
802
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
803
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" })
804
+ ] });
805
+ }
536
806
 
537
807
  // src/components/SignUp.tsx
538
808
  var import_clsx2 = require("clsx");
539
- var import_react3 = require("react");
809
+ var import_react4 = require("react");
540
810
  var import_jsx_runtime3 = require("react/jsx-runtime");
541
811
  function resolveApiOrigin3(prop) {
542
812
  if (prop) return prop;
@@ -546,6 +816,18 @@ function resolveApiOrigin3(prop) {
546
816
  }
547
817
  return "";
548
818
  }
819
+ function resolveAfterSignUpUrl(redirectUrlProp) {
820
+ if (redirectUrlProp) return redirectUrlProp;
821
+ if (typeof document !== "undefined") {
822
+ const el = document.querySelector("[data-vaultix-after-sign-up]");
823
+ const attr = el?.getAttribute("data-vaultix-after-sign-up");
824
+ if (attr) return attr;
825
+ const params = new URLSearchParams(window.location.search);
826
+ const redirectUrl = params.get("redirect_url");
827
+ if (redirectUrl) return redirectUrl;
828
+ }
829
+ return "/";
830
+ }
549
831
  function SignUp({
550
832
  redirectUrl,
551
833
  onSuccess,
@@ -554,17 +836,29 @@ function SignUp({
554
836
  className
555
837
  }) {
556
838
  const apiOrigin = resolveApiOrigin3(apiOriginProp);
557
- const [step, setStep] = (0, import_react3.useState)("email");
558
- const [email, setEmail] = (0, import_react3.useState)("");
559
- const [password, setPassword] = (0, import_react3.useState)("");
560
- const [verificationCode, setVerificationCode] = (0, import_react3.useState)("");
561
- const [error, setError] = (0, import_react3.useState)(null);
562
- const [loading, setLoading] = (0, import_react3.useState)(false);
563
- const [registrationId, setRegistrationId] = (0, import_react3.useState)(null);
839
+ const [step, setStep] = (0, import_react4.useState)("email");
840
+ const [email, setEmail] = (0, import_react4.useState)("");
841
+ const [password, setPassword] = (0, import_react4.useState)("");
842
+ const [verificationCode, setVerificationCode] = (0, import_react4.useState)("");
843
+ const [error, setError] = (0, import_react4.useState)(null);
844
+ const [loading, setLoading] = (0, import_react4.useState)(false);
845
+ const [registrationId, setRegistrationId] = (0, import_react4.useState)(null);
564
846
  function setErr(msg) {
565
847
  setError(msg);
566
848
  onError?.(msg);
567
849
  }
850
+ function handleSuccess(handshakeToken) {
851
+ onSuccess?.(handshakeToken);
852
+ const target = resolveAfterSignUpUrl(redirectUrl);
853
+ const url = new URL(target, window.location.origin);
854
+ url.searchParams.set("__vaultix_handshake", handshakeToken);
855
+ window.location.href = url.toString();
856
+ }
857
+ function handleGoogleSignUp() {
858
+ const target = resolveAfterSignUpUrl(redirectUrl);
859
+ const params = new URLSearchParams({ redirect_url: target });
860
+ window.location.href = `${apiOrigin}/v1/auth/oauth/google?${params}`;
861
+ }
568
862
  async function handleEmailPassword(e) {
569
863
  e.preventDefault();
570
864
  setError(null);
@@ -608,9 +902,7 @@ function SignUp({
608
902
  setErr(data.error ?? "Invalid code.");
609
903
  return;
610
904
  }
611
- onSuccess?.(data.session_id);
612
- const target = redirectUrl ?? document.querySelector("[data-vaultix-after-sign-up]")?.getAttribute("data-vaultix-after-sign-up") ?? "/";
613
- if (target) window.location.href = target;
905
+ handleSuccess(data.handshake_token);
614
906
  } catch {
615
907
  setErr("Network error. Please try again.");
616
908
  } finally {
@@ -645,31 +937,35 @@ function SignUp({
645
937
  ] }),
646
938
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-8 pb-8 space-y-4", children: [
647
939
  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 }) }),
648
- (step === "email" || step === "password") && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
649
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
650
- SignUpInput,
651
- {
652
- type: "email",
653
- placeholder: "you@company.com",
654
- value: email,
655
- onChange: setEmail,
656
- autoFocus: true,
657
- required: true
658
- }
659
- ),
660
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
661
- SignUpInput,
662
- {
663
- type: "password",
664
- placeholder: "Create a password",
665
- value: password,
666
- onChange: setPassword,
667
- required: true,
668
- minLength: 8
669
- }
670
- ),
671
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PasswordStrength, { password }),
672
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SignUpPrimaryButton, { loading, children: "Create account" })
940
+ step === "email" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-3", children: [
941
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GoogleButton2, { onClick: handleGoogleSignUp }),
942
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Divider2, {}),
943
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit: handleEmailPassword, className: "space-y-3", children: [
944
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
945
+ SignUpInput,
946
+ {
947
+ type: "email",
948
+ placeholder: "you@company.com",
949
+ value: email,
950
+ onChange: setEmail,
951
+ autoFocus: true,
952
+ required: true
953
+ }
954
+ ),
955
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
956
+ SignUpInput,
957
+ {
958
+ type: "password",
959
+ placeholder: "Create a password",
960
+ value: password,
961
+ onChange: setPassword,
962
+ required: true,
963
+ minLength: 8
964
+ }
965
+ ),
966
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PasswordStrength2, { password }),
967
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SignUpPrimaryButton, { loading, children: "Create account" })
968
+ ] })
673
969
  ] }),
674
970
  step === "verify" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit: handleVerification, className: "space-y-3", children: [
675
971
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -739,7 +1035,34 @@ function SignUpPrimaryButton({
739
1035
  }
740
1036
  );
741
1037
  }
742
- function PasswordStrength({ password }) {
1038
+ function GoogleButton2({ onClick }) {
1039
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1040
+ "button",
1041
+ {
1042
+ type: "button",
1043
+ onClick,
1044
+ className: (0, import_clsx2.clsx)(
1045
+ "w-full flex items-center justify-center gap-3 px-4 py-2.5 rounded-xl",
1046
+ "text-sm font-medium text-white/80",
1047
+ "bg-white/5 border border-white/10",
1048
+ "hover:bg-white/10 hover:border-white/20",
1049
+ "transition-all duration-150"
1050
+ ),
1051
+ children: [
1052
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GoogleIcon2, {}),
1053
+ "Continue with Google"
1054
+ ]
1055
+ }
1056
+ );
1057
+ }
1058
+ function Divider2() {
1059
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-3", children: [
1060
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex-1 h-px bg-white/8" }),
1061
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[10px] text-[#475569] uppercase tracking-wider", children: "or" }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex-1 h-px bg-white/8" })
1063
+ ] });
1064
+ }
1065
+ function PasswordStrength2({ password }) {
743
1066
  const score = (() => {
744
1067
  if (password.length === 0) return 0;
745
1068
  let s = 0;
@@ -751,13 +1074,7 @@ function PasswordStrength({ password }) {
751
1074
  })();
752
1075
  if (password.length === 0) return null;
753
1076
  const labels = ["", "Weak", "Fair", "Good", "Strong"];
754
- const colors = [
755
- "",
756
- "bg-red-500",
757
- "bg-amber-400",
758
- "bg-blue-400",
759
- "bg-emerald-400"
760
- ];
1077
+ const colors = ["", "bg-red-500", "bg-amber-400", "bg-blue-400", "bg-emerald-400"];
761
1078
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-1", children: [
762
1079
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex gap-1", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
763
1080
  "div",
@@ -773,45 +1090,71 @@ function PasswordStrength({ password }) {
773
1090
  ] });
774
1091
  }
775
1092
  function Spinner2() {
776
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
777
- "svg",
778
- {
779
- className: "animate-spin h-4 w-4 text-white/80",
780
- xmlns: "http://www.w3.org/2000/svg",
781
- fill: "none",
782
- viewBox: "0 0 24 24",
783
- children: [
784
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
785
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
786
- "path",
787
- {
788
- className: "opacity-75",
789
- fill: "currentColor",
790
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
791
- }
792
- )
793
- ]
794
- }
795
- );
1093
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "animate-spin h-4 w-4 text-white/80", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
1094
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1095
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
1096
+ ] });
796
1097
  }
797
1098
  function SparkleIcon() {
798
1099
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) });
799
1100
  }
1101
+ function GoogleIcon2() {
1102
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", children: [
1103
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z", fill: "#4285F4" }),
1104
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
1105
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
1106
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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" })
1107
+ ] });
1108
+ }
1109
+
1110
+ // src/components/SignedIn.tsx
1111
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1112
+ function SignedIn({ children }) {
1113
+ const { isLoaded, isSignedIn } = useVaultixContext();
1114
+ if (!isLoaded || !isSignedIn) return null;
1115
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
1116
+ }
1117
+ function SignedOut({ children }) {
1118
+ const { isLoaded, isSignedIn } = useVaultixContext();
1119
+ if (!isLoaded || isSignedIn) return null;
1120
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
1121
+ }
1122
+
1123
+ // src/components/RedirectComponents.tsx
1124
+ var import_react5 = require("react");
1125
+ function RedirectToSignIn({ redirectUrl = "/sign-in" }) {
1126
+ const { isLoaded, isSignedIn } = useVaultixContext();
1127
+ (0, import_react5.useEffect)(() => {
1128
+ if (isLoaded && !isSignedIn) {
1129
+ window.location.href = redirectUrl;
1130
+ }
1131
+ }, [isLoaded, isSignedIn, redirectUrl]);
1132
+ return null;
1133
+ }
1134
+ function RedirectToSignUp({ redirectUrl = "/sign-up" }) {
1135
+ const { isLoaded, isSignedIn } = useVaultixContext();
1136
+ (0, import_react5.useEffect)(() => {
1137
+ if (isLoaded && !isSignedIn) {
1138
+ window.location.href = redirectUrl;
1139
+ }
1140
+ }, [isLoaded, isSignedIn, redirectUrl]);
1141
+ return null;
1142
+ }
800
1143
 
801
1144
  // src/components/UserButton.tsx
802
1145
  var import_clsx3 = require("clsx");
803
- var import_react4 = require("react");
804
- var import_jsx_runtime4 = require("react/jsx-runtime");
1146
+ var import_react6 = require("react");
1147
+ var import_jsx_runtime5 = require("react/jsx-runtime");
805
1148
  function UserButton({
806
1149
  showName = false,
807
1150
  afterSignOutUrl,
808
1151
  className
809
1152
  }) {
810
1153
  const { user, session, isLoaded, isSignedIn, signOut } = useVaultixContext();
811
- const [open, setOpen] = (0, import_react4.useState)(false);
812
- const [signingOut, setSigningOut] = (0, import_react4.useState)(false);
813
- const containerRef = (0, import_react4.useRef)(null);
814
- (0, import_react4.useEffect)(() => {
1154
+ const [open, setOpen] = (0, import_react6.useState)(false);
1155
+ const [signingOut, setSigningOut] = (0, import_react6.useState)(false);
1156
+ const containerRef = (0, import_react6.useRef)(null);
1157
+ (0, import_react6.useEffect)(() => {
815
1158
  function onPointerDown(e) {
816
1159
  if (containerRef.current && !containerRef.current.contains(e.target)) {
817
1160
  setOpen(false);
@@ -820,7 +1163,7 @@ function UserButton({
820
1163
  document.addEventListener("pointerdown", onPointerDown);
821
1164
  return () => document.removeEventListener("pointerdown", onPointerDown);
822
1165
  }, []);
823
- if (!isLoaded) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AvatarSkeleton, {});
1166
+ if (!isLoaded) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AvatarSkeleton, {});
824
1167
  if (!isSignedIn || !user) return null;
825
1168
  const initials = [user.firstName, user.lastName].filter(Boolean).map((s) => s.charAt(0)).join("").toUpperCase() || user.email.charAt(0).toUpperCase();
826
1169
  async function handleSignOut() {
@@ -828,19 +1171,19 @@ function UserButton({
828
1171
  await signOut();
829
1172
  if (afterSignOutUrl) window.location.href = afterSignOutUrl;
830
1173
  }
831
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: containerRef, className: (0, import_clsx3.clsx)("relative", className), children: [
832
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1174
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: containerRef, className: (0, import_clsx3.clsx)("relative", className), children: [
1175
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
833
1176
  "button",
834
1177
  {
835
1178
  onClick: () => setOpen((o) => !o),
836
1179
  className: "flex items-center gap-2 rounded-xl p-1 hover:bg-white/8 transition-colors",
837
1180
  children: [
838
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { initials, imageUrl: user.imageUrl }),
839
- showName && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-medium text-white/90 pr-1", children: user.firstName ?? user.email })
1181
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Avatar, { initials, imageUrl: user.imageUrl }),
1182
+ showName && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm font-medium text-white/90 pr-1", children: user.firstName ?? user.email })
840
1183
  ]
841
1184
  }
842
1185
  ),
843
- open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1186
+ open && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
844
1187
  "div",
845
1188
  {
846
1189
  className: (0, import_clsx3.clsx)(
@@ -849,40 +1192,40 @@ function UserButton({
849
1192
  ),
850
1193
  style: { background: "rgba(22,27,45,0.96)" },
851
1194
  children: [
852
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-white/8", children: [
853
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { initials, imageUrl: user.imageUrl, size: "lg" }),
854
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-1 min-w-0", children: [
855
- (user.firstName || user.lastName) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-sm font-semibold text-white/90 truncate", children: [user.firstName, user.lastName].filter(Boolean).join(" ") }),
856
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-xs text-[#475569] truncate", children: user.email })
1195
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-white/8", children: [
1196
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Avatar, { initials, imageUrl: user.imageUrl, size: "lg" }),
1197
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex-1 min-w-0", children: [
1198
+ (user.firstName || user.lastName) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-sm font-semibold text-white/90 truncate", children: [user.firstName, user.lastName].filter(Boolean).join(" ") }),
1199
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-[#475569] truncate", children: user.email })
857
1200
  ] })
858
1201
  ] }),
859
- session && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "px-4 py-2 border-b border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-between", children: [
860
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[10px] uppercase tracking-widest text-[#475569]", children: "Risk level" }),
861
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RiskBadge, { level: session.riskLevel })
1202
+ session && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-4 py-2 border-b border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
1203
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-[10px] uppercase tracking-widest text-[#475569]", children: "Risk level" }),
1204
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RiskBadge, { level: session.riskLevel })
862
1205
  ] }) }),
863
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "p-2", children: [
864
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1206
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-2", children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
865
1208
  DropdownItem,
866
1209
  {
867
1210
  label: "Manage account",
868
- icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UserIcon, {}),
1211
+ icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UserIcon, {}),
869
1212
  onClick: () => setOpen(false)
870
1213
  }
871
1214
  ),
872
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1215
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
873
1216
  DropdownItem,
874
1217
  {
875
1218
  label: "Security settings",
876
- icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ShieldIcon, {}),
1219
+ icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ShieldIcon, {}),
877
1220
  onClick: () => setOpen(false)
878
1221
  }
879
1222
  ),
880
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "h-px bg-white/8 my-1" }),
881
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1223
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-px bg-white/8 my-1" }),
1224
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
882
1225
  DropdownItem,
883
1226
  {
884
1227
  label: signingOut ? "Signing out\u2026" : "Sign out",
885
- icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SignOutIcon, {}),
1228
+ icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SignOutIcon, {}),
886
1229
  onClick: handleSignOut,
887
1230
  destructive: true
888
1231
  }
@@ -898,7 +1241,7 @@ function Avatar({ initials, imageUrl, size = "sm" }) {
898
1241
  if (imageUrl) {
899
1242
  return (
900
1243
  // eslint-disable-next-line @next/next/no-img-element
901
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1244
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
902
1245
  "img",
903
1246
  {
904
1247
  src: imageUrl,
@@ -908,7 +1251,7 @@ function Avatar({ initials, imageUrl, size = "sm" }) {
908
1251
  )
909
1252
  );
910
1253
  }
911
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1254
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
912
1255
  "div",
913
1256
  {
914
1257
  className: (0, import_clsx3.clsx)(
@@ -921,7 +1264,7 @@ function Avatar({ initials, imageUrl, size = "sm" }) {
921
1264
  );
922
1265
  }
923
1266
  function AvatarSkeleton() {
924
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "w-8 h-8 rounded-full bg-white/5 animate-pulse" });
1267
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-8 h-8 rounded-full bg-white/5 animate-pulse" });
925
1268
  }
926
1269
  function RiskBadge({ level }) {
927
1270
  const styles = {
@@ -930,7 +1273,7 @@ function RiskBadge({ level }) {
930
1273
  high: "bg-orange-500/15 text-orange-400 border-orange-500/30",
931
1274
  critical: "bg-red-500/15 text-red-400 border-red-500/30"
932
1275
  };
933
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1276
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
934
1277
  "span",
935
1278
  {
936
1279
  className: (0, import_clsx3.clsx)(
@@ -942,7 +1285,7 @@ function RiskBadge({ level }) {
942
1285
  );
943
1286
  }
944
1287
  function DropdownItem({ label, icon, onClick, destructive }) {
945
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1288
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
946
1289
  "button",
947
1290
  {
948
1291
  onClick,
@@ -951,33 +1294,33 @@ function DropdownItem({ label, icon, onClick, destructive }) {
951
1294
  destructive ? "text-red-400 hover:bg-red-500/10" : "text-white/70 hover:text-white hover:bg-white/8"
952
1295
  ),
953
1296
  children: [
954
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "opacity-70", children: icon }),
1297
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "opacity-70", children: icon }),
955
1298
  label
956
1299
  ]
957
1300
  }
958
1301
  );
959
1302
  }
960
1303
  function UserIcon() {
961
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
962
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
963
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "7", r: "4" })
1304
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1305
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1306
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "7", r: "4" })
964
1307
  ] });
965
1308
  }
966
1309
  function ShieldIcon() {
967
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) });
1310
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) });
968
1311
  }
969
1312
  function SignOutIcon() {
970
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
971
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
972
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "16 17 21 12 16 7" }),
973
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
1313
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1314
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
1315
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "16 17 21 12 16 7" }),
1316
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
974
1317
  ] });
975
1318
  }
976
1319
 
977
1320
  // src/components/OrganizationSwitcher.tsx
978
1321
  var import_clsx4 = require("clsx");
979
- var import_react5 = require("react");
980
- var import_jsx_runtime5 = require("react/jsx-runtime");
1322
+ var import_react7 = require("react");
1323
+ var import_jsx_runtime6 = require("react/jsx-runtime");
981
1324
  function resolveApiOrigin4() {
982
1325
  if (typeof document !== "undefined") {
983
1326
  const el = document.querySelector("[data-vaultix-api]");
@@ -990,11 +1333,11 @@ function OrganizationSwitcher({
990
1333
  className
991
1334
  }) {
992
1335
  const { organization, isLoaded, isSignedIn } = useVaultixContext();
993
- const [open, setOpen] = (0, import_react5.useState)(false);
994
- const [orgs, setOrgs] = (0, import_react5.useState)([]);
995
- const [switching, setSwitching] = (0, import_react5.useState)(null);
996
- const containerRef = (0, import_react5.useRef)(null);
997
- (0, import_react5.useEffect)(() => {
1336
+ const [open, setOpen] = (0, import_react7.useState)(false);
1337
+ const [orgs, setOrgs] = (0, import_react7.useState)([]);
1338
+ const [switching, setSwitching] = (0, import_react7.useState)(null);
1339
+ const containerRef = (0, import_react7.useRef)(null);
1340
+ (0, import_react7.useEffect)(() => {
998
1341
  function onPointerDown(e) {
999
1342
  if (containerRef.current && !containerRef.current.contains(e.target)) {
1000
1343
  setOpen(false);
@@ -1003,7 +1346,7 @@ function OrganizationSwitcher({
1003
1346
  document.addEventListener("pointerdown", onPointerDown);
1004
1347
  return () => document.removeEventListener("pointerdown", onPointerDown);
1005
1348
  }, []);
1006
- (0, import_react5.useEffect)(() => {
1349
+ (0, import_react7.useEffect)(() => {
1007
1350
  if (!open) return;
1008
1351
  const api = resolveApiOrigin4();
1009
1352
  fetch(`${api}/v1/me/organizations`, { credentials: "include" }).then((r) => r.json()).then(
@@ -1037,8 +1380,8 @@ function OrganizationSwitcher({
1037
1380
  }
1038
1381
  const displayName = organization?.name ?? "Personal";
1039
1382
  const initials = displayName.split(/\s+/).slice(0, 2).map((w) => w[0]).join("").toUpperCase();
1040
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: containerRef, className: (0, import_clsx4.clsx)("relative", className), children: [
1041
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1383
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: containerRef, className: (0, import_clsx4.clsx)("relative", className), children: [
1384
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1042
1385
  "button",
1043
1386
  {
1044
1387
  onClick: () => setOpen((o) => !o),
@@ -1048,16 +1391,16 @@ function OrganizationSwitcher({
1048
1391
  "transition-all duration-150"
1049
1392
  ),
1050
1393
  children: [
1051
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OrgAvatar, { initials }),
1052
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-left min-w-0", children: [
1053
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-sm font-semibold text-white/90 truncate max-w-[120px]", children: displayName }),
1054
- organization && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] text-[#475569] capitalize", children: organization.role })
1394
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(OrgAvatar, { initials }),
1395
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "text-left min-w-0", children: [
1396
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-sm font-semibold text-white/90 truncate max-w-[120px]", children: displayName }),
1397
+ organization && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[10px] text-[#475569] capitalize", children: organization.role })
1055
1398
  ] }),
1056
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronIcon, {})
1399
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChevronIcon, {})
1057
1400
  ]
1058
1401
  }
1059
1402
  ),
1060
- open && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1403
+ open && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1061
1404
  "div",
1062
1405
  {
1063
1406
  className: (0, import_clsx4.clsx)(
@@ -1066,13 +1409,13 @@ function OrganizationSwitcher({
1066
1409
  ),
1067
1410
  style: { background: "rgba(22,27,45,0.96)" },
1068
1411
  children: [
1069
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-4 py-3 border-b border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] uppercase tracking-widest text-[#475569]", children: "Switch organization" }) }),
1070
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-2 max-h-56 overflow-y-auto", children: [
1071
- orgs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-[#475569] text-center py-4", children: "Loading\u2026" }),
1412
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-4 py-3 border-b border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[10px] uppercase tracking-widest text-[#475569]", children: "Switch organization" }) }),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-2 max-h-56 overflow-y-auto", children: [
1414
+ orgs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-[#475569] text-center py-4", children: "Loading\u2026" }),
1072
1415
  orgs.map((org) => {
1073
1416
  const isActive = org.id === organization?.id;
1074
1417
  const orgInitials = org.name.split(/\s+/).slice(0, 2).map((w) => w[0]).join("").toUpperCase();
1075
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1418
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1076
1419
  "button",
1077
1420
  {
1078
1421
  onClick: () => !isActive && switchOrg(org.id),
@@ -1082,9 +1425,9 @@ function OrganizationSwitcher({
1082
1425
  isActive ? "bg-purple-500/10 cursor-default" : "hover:bg-white/8 cursor-pointer"
1083
1426
  ),
1084
1427
  children: [
1085
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OrgAvatar, { initials: orgInitials, active: isActive }),
1086
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex-1 min-w-0", children: [
1087
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1428
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(OrgAvatar, { initials: orgInitials, active: isActive }),
1429
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex-1 min-w-0", children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1088
1431
  "p",
1089
1432
  {
1090
1433
  className: (0, import_clsx4.clsx)(
@@ -1094,17 +1437,17 @@ function OrganizationSwitcher({
1094
1437
  children: org.name
1095
1438
  }
1096
1439
  ),
1097
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] text-[#475569] capitalize", children: org.role })
1440
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[10px] text-[#475569] capitalize", children: org.role })
1098
1441
  ] }),
1099
- isActive && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-purple-400 shrink-0" }),
1100
- switching === org.id && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MiniSpinner, {})
1442
+ isActive && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-purple-400 shrink-0" }),
1443
+ switching === org.id && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MiniSpinner, {})
1101
1444
  ]
1102
1445
  },
1103
1446
  org.id
1104
1447
  );
1105
1448
  })
1106
1449
  ] }),
1107
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-2 border-t border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1450
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-2 border-t border-white/8", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1108
1451
  "button",
1109
1452
  {
1110
1453
  onClick: () => {
@@ -1112,7 +1455,7 @@ function OrganizationSwitcher({
1112
1455
  },
1113
1456
  className: "w-full flex items-center gap-2 px-3 py-2 rounded-xl text-sm text-[#475569] hover:text-white hover:bg-white/8 transition-colors",
1114
1457
  children: [
1115
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PlusIcon, {}),
1458
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, {}),
1116
1459
  "Create organization"
1117
1460
  ]
1118
1461
  }
@@ -1126,7 +1469,7 @@ function OrgAvatar({
1126
1469
  initials,
1127
1470
  active = false
1128
1471
  }) {
1129
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1472
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1130
1473
  "div",
1131
1474
  {
1132
1475
  className: (0, import_clsx4.clsx)(
@@ -1138,7 +1481,7 @@ function OrgAvatar({
1138
1481
  );
1139
1482
  }
1140
1483
  function ChevronIcon() {
1141
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1484
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1142
1485
  "svg",
1143
1486
  {
1144
1487
  width: "12",
@@ -1150,29 +1493,34 @@ function ChevronIcon() {
1150
1493
  strokeLinecap: "round",
1151
1494
  strokeLinejoin: "round",
1152
1495
  className: "text-[#475569] shrink-0",
1153
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "6 9 12 15 18 9" })
1496
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "6 9 12 15 18 9" })
1154
1497
  }
1155
1498
  );
1156
1499
  }
1157
1500
  function PlusIcon() {
1158
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1159
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1160
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1501
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1502
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1503
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1161
1504
  ] });
1162
1505
  }
1163
1506
  function MiniSpinner() {
1164
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { className: "animate-spin h-3 w-3 text-[#475569]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
1165
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1166
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
1507
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "animate-spin h-3 w-3 text-[#475569]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
1508
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1509
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
1167
1510
  ] });
1168
1511
  }
1169
1512
  // Annotate the CommonJS export names for ESM import in node:
1170
1513
  0 && (module.exports = {
1171
1514
  OrganizationSwitcher,
1515
+ RedirectToSignIn,
1516
+ RedirectToSignUp,
1172
1517
  SignIn,
1173
1518
  SignUp,
1519
+ SignedIn,
1520
+ SignedOut,
1174
1521
  UserButton,
1175
1522
  VaultixProvider,
1523
+ useAuth,
1176
1524
  useOrganization,
1177
1525
  useSession,
1178
1526
  useUser,