@cyberia-auth/auth 0.1.0

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 ADDED
@@ -0,0 +1,900 @@
1
+ // src/index.tsx
2
+ import axios from "axios";
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ var defaultAppConfig = {
13
+ appName: "App Auth",
14
+ organizationName: "Cyberia",
15
+ primaryColor: "#4f46e5",
16
+ secondaryColor: "#1f2937"
17
+ };
18
+ var DEFAULT_BACKEND_URL = "https://auth.cyberia.host";
19
+ function CyberiaAuth({
20
+ backendUrl,
21
+ apiToken,
22
+ oauthRedirectUri,
23
+ initialMode = "register",
24
+ hideModeSwitch = false,
25
+ onAuthSuccess
26
+ }) {
27
+ const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
28
+ const [mode, setMode] = useState(initialMode);
29
+ const [config, setConfig] = useState(() => getCachedAppConfig(apiToken));
30
+ const [isBrandingResolved, setIsBrandingResolved] = useState(
31
+ () => Boolean(getCachedAppConfig(apiToken))
32
+ );
33
+ const [message, setMessage] = useState("");
34
+ const [isLoading, setIsLoading] = useState(false);
35
+ useEffect(() => {
36
+ const cached = getCachedAppConfig(apiToken);
37
+ if (cached) {
38
+ setConfig(cached);
39
+ setIsBrandingResolved(true);
40
+ } else {
41
+ setIsBrandingResolved(false);
42
+ }
43
+ void axios.get(`${backendBaseUrl}/api/public/app/config`, {
44
+ params: { apiToken }
45
+ }).then((res) => {
46
+ setConfig(res.data);
47
+ cacheAppConfig(apiToken, res.data);
48
+ }).catch((error) => {
49
+ const errorMessage = error instanceof Error ? error.message : "Unable to load app config";
50
+ setMessage(errorMessage);
51
+ if (!cached) {
52
+ setConfig(defaultAppConfig);
53
+ }
54
+ }).finally(() => {
55
+ setIsBrandingResolved(true);
56
+ });
57
+ }, [apiToken, backendBaseUrl]);
58
+ const handleSubmit = async (event) => {
59
+ event.preventDefault();
60
+ setIsLoading(true);
61
+ setMessage("");
62
+ const form = new FormData(event.currentTarget);
63
+ try {
64
+ const endpoint = mode === "register" ? "/api/public/auth/register" : "/api/public/auth/login";
65
+ const payload = {
66
+ apiToken,
67
+ email: String(form.get("email")),
68
+ password: String(form.get("password")),
69
+ displayName: String(form.get("displayName") ?? "")
70
+ };
71
+ const response = await axios.post(`${backendBaseUrl}${endpoint}`, payload);
72
+ setMessage("");
73
+ onAuthSuccess?.(response.data);
74
+ } catch (error) {
75
+ if (axios.isAxiosError(error)) {
76
+ const apiError = error.response?.data;
77
+ setMessage(apiError?.error ?? error.message);
78
+ } else {
79
+ setMessage("Request failed");
80
+ }
81
+ } finally {
82
+ setIsLoading(false);
83
+ }
84
+ };
85
+ const startOAuth = (provider) => {
86
+ if (!oauthRedirectUri) {
87
+ setMessage("oauthRedirectUri is required for social login");
88
+ return;
89
+ }
90
+ const url = new URL(`${backendBaseUrl}/api/public/oauth/${provider}/start`);
91
+ url.searchParams.set("apiToken", apiToken);
92
+ url.searchParams.set("redirectUri", oauthRedirectUri);
93
+ window.location.href = url.toString();
94
+ };
95
+ const accent = resolveColor(config?.primaryColor, defaultAppConfig.primaryColor);
96
+ const brandName = config?.organizationName ?? defaultAppConfig.organizationName;
97
+ const title = mode === "login" ? `Sign in to ${brandName}` : `Create your ${brandName} account`;
98
+ const subtitle = mode === "login" ? "Welcome back! Please sign in to continue" : "Create your account to continue";
99
+ if (!isBrandingResolved) {
100
+ return /* @__PURE__ */ jsx(
101
+ "div",
102
+ {
103
+ style: {
104
+ border: "1px solid #e5e7eb",
105
+ borderRadius: 14,
106
+ padding: 20,
107
+ background: "#ffffff",
108
+ fontFamily: "Inter, Arial, sans-serif",
109
+ minHeight: 320,
110
+ display: "grid",
111
+ placeItems: "center",
112
+ color: "#6b7280"
113
+ },
114
+ children: "Loading sign-in..."
115
+ }
116
+ );
117
+ }
118
+ return /* @__PURE__ */ jsxs(
119
+ "div",
120
+ {
121
+ style: {
122
+ border: "1px solid #e5e7eb",
123
+ borderRadius: 14,
124
+ padding: 0,
125
+ background: "#ffffff",
126
+ overflow: "hidden",
127
+ fontFamily: "Inter, Arial, sans-serif",
128
+ width: "100%",
129
+ maxWidth: 500,
130
+ margin: "0 auto"
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ jsxs("div", { style: { padding: 20, display: "grid", gap: 14 }, children: [
134
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", justifyItems: "center", gap: 10 }, children: [
135
+ config?.logoUrl ? /* @__PURE__ */ jsx("img", { src: config.logoUrl, alt: "logo", style: { width: 56, height: 56, objectFit: "contain" } }) : /* @__PURE__ */ jsx(
136
+ "div",
137
+ {
138
+ style: {
139
+ width: 56,
140
+ height: 56,
141
+ borderRadius: 10,
142
+ background: accent,
143
+ color: "#fff",
144
+ display: "grid",
145
+ placeItems: "center",
146
+ fontSize: 24,
147
+ fontWeight: 700
148
+ },
149
+ children: (brandName[0] ?? "C").toUpperCase()
150
+ }
151
+ ),
152
+ /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
153
+ /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 6px 0", fontSize: 16 }, children: title }),
154
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "#6b7280", fontSize: 13 }, children: subtitle })
155
+ ] })
156
+ ] }),
157
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }, children: [
158
+ /* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle, onClick: () => startOAuth("google"), children: [
159
+ /* @__PURE__ */ jsx(GoogleIcon, {}),
160
+ "Google"
161
+ ] }),
162
+ /* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle, onClick: () => startOAuth("microsoft"), children: [
163
+ /* @__PURE__ */ jsx(MicrosoftIcon, {}),
164
+ "Microsoft"
165
+ ] })
166
+ ] }),
167
+ /* @__PURE__ */ jsxs(
168
+ "div",
169
+ {
170
+ style: {
171
+ display: "grid",
172
+ gridTemplateColumns: "1fr auto 1fr",
173
+ alignItems: "center",
174
+ gap: 12
175
+ },
176
+ children: [
177
+ /* @__PURE__ */ jsx("div", { style: { height: 1, background: "#e5e7eb" } }),
178
+ /* @__PURE__ */ jsx("span", { style: { color: "#9ca3af", fontSize: 14 }, children: "or" }),
179
+ /* @__PURE__ */ jsx("div", { style: { height: 1, background: "#e5e7eb" } })
180
+ ]
181
+ }
182
+ ),
183
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "grid", gap: 10 }, children: [
184
+ mode === "register" && /* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
185
+ "Full name",
186
+ /* @__PURE__ */ jsx(
187
+ "input",
188
+ {
189
+ name: "displayName",
190
+ placeholder: "Enter your full name",
191
+ required: true,
192
+ style: inputStyle
193
+ }
194
+ )
195
+ ] }),
196
+ /* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
197
+ "Email address",
198
+ /* @__PURE__ */ jsx("input", { type: "email", name: "email", placeholder: "Enter your email address", required: true, style: inputStyle })
199
+ ] }),
200
+ /* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
201
+ "Password",
202
+ /* @__PURE__ */ jsx(
203
+ "input",
204
+ {
205
+ type: "password",
206
+ name: "password",
207
+ placeholder: "Enter your password",
208
+ minLength: 8,
209
+ required: true,
210
+ style: inputStyle
211
+ }
212
+ )
213
+ ] }),
214
+ /* @__PURE__ */ jsx(
215
+ "button",
216
+ {
217
+ type: "submit",
218
+ disabled: isLoading,
219
+ style: {
220
+ background: accent,
221
+ color: "white",
222
+ border: 0,
223
+ borderRadius: 9,
224
+ padding: "11px 12px",
225
+ fontSize: 14,
226
+ fontWeight: 400
227
+ },
228
+ children: isLoading ? "Please wait..." : mode === "register" ? "Create account" : "Continue"
229
+ }
230
+ )
231
+ ] }),
232
+ message && /* @__PURE__ */ jsx("p", { style: { fontSize: 13, margin: 0 }, children: message })
233
+ ] }),
234
+ !hideModeSwitch && /* @__PURE__ */ jsxs(
235
+ "div",
236
+ {
237
+ style: {
238
+ borderTop: "1px solid #e5e7eb",
239
+ padding: 14,
240
+ textAlign: "center",
241
+ background: "#fafafa"
242
+ },
243
+ children: [
244
+ mode === "login" ? "Don't have an account? " : "Already have an account? ",
245
+ /* @__PURE__ */ jsx(
246
+ "button",
247
+ {
248
+ type: "button",
249
+ onClick: () => setMode(mode === "login" ? "register" : "login"),
250
+ style: {
251
+ border: "none",
252
+ background: "transparent",
253
+ color: "#111827",
254
+ textDecoration: "underline",
255
+ fontWeight: 600,
256
+ cursor: "pointer",
257
+ padding: 0
258
+ },
259
+ children: mode === "login" ? "Sign up" : "Sign in"
260
+ }
261
+ )
262
+ ]
263
+ }
264
+ )
265
+ ]
266
+ }
267
+ );
268
+ }
269
+ var CyberiaAuthContext = createContext(null);
270
+ function CyberiaAuthProvider({
271
+ backendUrl,
272
+ apiToken,
273
+ oauthRedirectUri,
274
+ children,
275
+ storageKey = "cyberia_auth_session"
276
+ }) {
277
+ const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
278
+ const [isLoaded, setIsLoaded] = useState(false);
279
+ const [session, setSession] = useState(null);
280
+ const [modalOpen, setModalOpen] = useState(false);
281
+ const [modalMode, setModalMode] = useState("login");
282
+ useEffect(() => {
283
+ if (typeof window === "undefined") {
284
+ return;
285
+ }
286
+ const stored = window.localStorage.getItem(storageKey);
287
+ if (stored) {
288
+ try {
289
+ setSession(JSON.parse(stored));
290
+ } catch {
291
+ window.localStorage.removeItem(storageKey);
292
+ }
293
+ }
294
+ const params = new URLSearchParams(window.location.search);
295
+ const token = params.get("token");
296
+ const email = params.get("email");
297
+ const displayName = params.get("displayName");
298
+ const provider = params.get("provider");
299
+ if (token && email && provider) {
300
+ const oauthUser = {
301
+ id: email,
302
+ email,
303
+ displayName: displayName ?? email
304
+ };
305
+ const nextSession = { token, user: oauthUser };
306
+ window.localStorage.setItem(storageKey, JSON.stringify(nextSession));
307
+ setSession(nextSession);
308
+ const cleanUrl = new URL(window.location.href);
309
+ cleanUrl.searchParams.delete("token");
310
+ cleanUrl.searchParams.delete("email");
311
+ cleanUrl.searchParams.delete("displayName");
312
+ cleanUrl.searchParams.delete("provider");
313
+ window.history.replaceState({}, "", cleanUrl.toString());
314
+ }
315
+ setIsLoaded(true);
316
+ }, [storageKey]);
317
+ const setSessionAndPersist = (nextSession) => {
318
+ if (typeof window !== "undefined") {
319
+ window.localStorage.setItem(storageKey, JSON.stringify(nextSession));
320
+ }
321
+ setSession(nextSession);
322
+ };
323
+ const setSessionFromAuth = (result) => {
324
+ setSessionAndPersist({
325
+ token: result.token,
326
+ user: result.user
327
+ });
328
+ };
329
+ const signOut = () => {
330
+ if (typeof window !== "undefined") {
331
+ window.localStorage.removeItem(storageKey);
332
+ }
333
+ setSession(null);
334
+ };
335
+ const value = useMemo(
336
+ () => ({
337
+ isLoaded,
338
+ isSignedIn: Boolean(session?.token),
339
+ user: session?.user ?? null,
340
+ token: session?.token ?? null,
341
+ openSignIn: () => {
342
+ setModalMode("login");
343
+ setModalOpen(true);
344
+ },
345
+ openSignUp: () => {
346
+ setModalMode("register");
347
+ setModalOpen(true);
348
+ },
349
+ signOut,
350
+ setSessionFromAuth
351
+ }),
352
+ [isLoaded, session, setSessionFromAuth]
353
+ );
354
+ return /* @__PURE__ */ jsxs(CyberiaAuthContext.Provider, { value, children: [
355
+ children,
356
+ modalOpen && /* @__PURE__ */ jsx(
357
+ "div",
358
+ {
359
+ style: {
360
+ position: "fixed",
361
+ inset: 0,
362
+ background: "rgba(0,0,0,0.55)",
363
+ display: "grid",
364
+ placeItems: "center",
365
+ zIndex: 9999,
366
+ padding: 16
367
+ },
368
+ onClick: () => setModalOpen(false),
369
+ children: /* @__PURE__ */ jsx(
370
+ "div",
371
+ {
372
+ style: { width: "100%", maxWidth: 440, background: "#fff", borderRadius: 12 },
373
+ onClick: (event) => event.stopPropagation(),
374
+ children: /* @__PURE__ */ jsx(
375
+ CyberiaAuth,
376
+ {
377
+ backendUrl: backendBaseUrl,
378
+ apiToken,
379
+ oauthRedirectUri,
380
+ initialMode: modalMode,
381
+ hideModeSwitch: false,
382
+ onAuthSuccess: (result) => {
383
+ setSessionFromAuth(result);
384
+ setModalOpen(false);
385
+ }
386
+ }
387
+ )
388
+ }
389
+ )
390
+ }
391
+ )
392
+ ] });
393
+ }
394
+ function useCyberiaAuth() {
395
+ const context = useContext(CyberiaAuthContext);
396
+ if (!context) {
397
+ throw new Error("useCyberiaAuth must be used inside <CyberiaAuthProvider>");
398
+ }
399
+ return context;
400
+ }
401
+ function Show({ when, children }) {
402
+ const { isSignedIn } = useCyberiaAuth();
403
+ if (when === "signed-in" && !isSignedIn) {
404
+ return null;
405
+ }
406
+ if (when === "signed-out" && isSignedIn) {
407
+ return null;
408
+ }
409
+ return /* @__PURE__ */ jsx(Fragment, { children });
410
+ }
411
+ function SignedIn({ children }) {
412
+ const { isLoaded, isSignedIn } = useCyberiaAuth();
413
+ if (!isLoaded || !isSignedIn) {
414
+ return null;
415
+ }
416
+ return /* @__PURE__ */ jsx(Fragment, { children });
417
+ }
418
+ function SignedOut({ children }) {
419
+ const { isLoaded, isSignedIn } = useCyberiaAuth();
420
+ if (!isLoaded || isSignedIn) {
421
+ return null;
422
+ }
423
+ return /* @__PURE__ */ jsx(Fragment, { children });
424
+ }
425
+ function SignInButton({ children }) {
426
+ const { openSignIn } = useCyberiaAuth();
427
+ return /* @__PURE__ */ jsx("button", { type: "button", onClick: openSignIn, children: children ?? "Sign in" });
428
+ }
429
+ function SignUpButton({ children }) {
430
+ const { openSignUp } = useCyberiaAuth();
431
+ return /* @__PURE__ */ jsx("button", { type: "button", onClick: openSignUp, children: children ?? "Sign up" });
432
+ }
433
+ function SignOutButton({ children }) {
434
+ const { signOut } = useCyberiaAuth();
435
+ return /* @__PURE__ */ jsx("button", { type: "button", onClick: signOut, children: children ?? "Sign out" });
436
+ }
437
+ function UserButton() {
438
+ const { user, signOut, openSignIn, openSignUp } = useCyberiaAuth();
439
+ const [open, setOpen] = useState(false);
440
+ const [manageOpen, setManageOpen] = useState(false);
441
+ const [tab, setTab] = useState("profile");
442
+ const menuRef = useRef(null);
443
+ useEffect(() => {
444
+ const onOutsideClick = (event) => {
445
+ if (!menuRef.current) {
446
+ return;
447
+ }
448
+ if (!menuRef.current.contains(event.target)) {
449
+ setOpen(false);
450
+ }
451
+ };
452
+ window.addEventListener("click", onOutsideClick);
453
+ return () => window.removeEventListener("click", onOutsideClick);
454
+ }, []);
455
+ const initials = (user?.displayName ?? user?.email ?? "U").slice(0, 1).toUpperCase();
456
+ const profileName = user?.displayName ?? "Guest";
457
+ const profileEmail = user?.email ?? "No email";
458
+ const userAgent = typeof navigator === "undefined" ? "Unknown device" : navigator.userAgent;
459
+ return /* @__PURE__ */ jsxs("div", { ref: menuRef, style: { position: "relative", display: "inline-flex" }, children: [
460
+ /* @__PURE__ */ jsx(
461
+ "button",
462
+ {
463
+ type: "button",
464
+ onClick: () => setOpen((value) => !value),
465
+ style: {
466
+ width: 36,
467
+ height: 36,
468
+ borderRadius: 999,
469
+ border: "1px solid #d1d5db",
470
+ background: "#fff",
471
+ fontWeight: 700,
472
+ cursor: "pointer"
473
+ },
474
+ "aria-label": "Open user menu",
475
+ children: initials
476
+ }
477
+ ),
478
+ open && /* @__PURE__ */ jsxs(
479
+ "div",
480
+ {
481
+ style: {
482
+ position: "absolute",
483
+ right: 0,
484
+ top: 42,
485
+ minWidth: 320,
486
+ background: "#fff",
487
+ border: "1px solid #e5e7eb",
488
+ borderRadius: 12,
489
+ boxShadow: "0 12px 24px rgba(0,0,0,0.08)",
490
+ padding: 0,
491
+ zIndex: 50
492
+ },
493
+ children: [
494
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 10, padding: 14, alignItems: "center" }, children: [
495
+ /* @__PURE__ */ jsx(
496
+ "div",
497
+ {
498
+ style: {
499
+ width: 44,
500
+ height: 44,
501
+ borderRadius: 999,
502
+ border: "1px solid #d1d5db",
503
+ display: "grid",
504
+ placeItems: "center",
505
+ fontWeight: 700,
506
+ color: "#111827",
507
+ background: "#f8fafc"
508
+ },
509
+ children: initials
510
+ }
511
+ ),
512
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid" }, children: [
513
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: 16, color: "#111827", lineHeight: 1.2 }, children: profileName }),
514
+ /* @__PURE__ */ jsx("span", { style: { color: "#111827", fontSize: 14 }, children: profileEmail })
515
+ ] })
516
+ ] }),
517
+ /* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop: "1px solid #e5e7eb", margin: 0 } }),
518
+ !user && /* @__PURE__ */ jsxs(Fragment, { children: [
519
+ /* @__PURE__ */ jsx(
520
+ "button",
521
+ {
522
+ type: "button",
523
+ style: menuItemButtonStyleLarge,
524
+ onClick: () => {
525
+ openSignIn();
526
+ setOpen(false);
527
+ },
528
+ children: "Sign in"
529
+ }
530
+ ),
531
+ /* @__PURE__ */ jsx(
532
+ "button",
533
+ {
534
+ type: "button",
535
+ style: menuItemButtonStyleLarge,
536
+ onClick: () => {
537
+ openSignUp();
538
+ setOpen(false);
539
+ },
540
+ children: "Sign up"
541
+ }
542
+ )
543
+ ] }),
544
+ user && /* @__PURE__ */ jsxs(Fragment, { children: [
545
+ /* @__PURE__ */ jsx(
546
+ "button",
547
+ {
548
+ type: "button",
549
+ style: menuItemButtonStyleLarge,
550
+ onClick: () => {
551
+ setManageOpen(true);
552
+ setTab("profile");
553
+ setOpen(false);
554
+ },
555
+ children: "Manage account"
556
+ }
557
+ ),
558
+ /* @__PURE__ */ jsx(
559
+ "button",
560
+ {
561
+ type: "button",
562
+ style: menuItemButtonStyleLarge,
563
+ onClick: () => {
564
+ signOut();
565
+ setOpen(false);
566
+ },
567
+ children: "Sign out"
568
+ }
569
+ )
570
+ ] }),
571
+ /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid #e5e7eb", textAlign: "center", padding: "12px 10px", color: "#6b7280" }, children: [
572
+ "Secured by ",
573
+ /* @__PURE__ */ jsx("strong", { children: "cyberia auth" })
574
+ ] })
575
+ ]
576
+ }
577
+ ),
578
+ manageOpen && user && /* @__PURE__ */ jsx(
579
+ "div",
580
+ {
581
+ style: {
582
+ position: "fixed",
583
+ inset: 0,
584
+ zIndex: 1e4,
585
+ background: "rgba(17,24,39,0.55)",
586
+ display: "grid",
587
+ placeItems: "center",
588
+ padding: 20
589
+ },
590
+ onClick: () => setManageOpen(false),
591
+ children: /* @__PURE__ */ jsxs(
592
+ "div",
593
+ {
594
+ style: {
595
+ width: "100%",
596
+ maxWidth: 940,
597
+ minHeight: 540,
598
+ background: "#fff",
599
+ borderRadius: 10,
600
+ border: "1px solid #e5e7eb",
601
+ display: "grid",
602
+ gridTemplateColumns: "220px 1fr",
603
+ overflow: "hidden"
604
+ },
605
+ onClick: (event) => event.stopPropagation(),
606
+ children: [
607
+ /* @__PURE__ */ jsxs(
608
+ "aside",
609
+ {
610
+ style: {
611
+ borderRight: "1px solid #e5e7eb",
612
+ padding: 22,
613
+ background: "#fafafa",
614
+ display: "flex",
615
+ flexDirection: "column"
616
+ },
617
+ children: [
618
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 30, color: "#111827" }, children: "Account" }),
619
+ /* @__PURE__ */ jsx("p", { style: { marginTop: 6, color: "#6b7280", fontSize: 12 }, children: "Manage your account info." }),
620
+ /* @__PURE__ */ jsxs("div", { style: { marginTop: 20, display: "grid", gap: 8 }, children: [
621
+ /* @__PURE__ */ jsx(
622
+ "button",
623
+ {
624
+ type: "button",
625
+ onClick: () => setTab("profile"),
626
+ style: {
627
+ ...tabButtonStyle,
628
+ background: tab === "profile" ? "#ece8ff" : "transparent",
629
+ color: tab === "profile" ? "#6d28d9" : "#4b5563"
630
+ },
631
+ children: "Profile"
632
+ }
633
+ ),
634
+ /* @__PURE__ */ jsx(
635
+ "button",
636
+ {
637
+ type: "button",
638
+ onClick: () => setTab("security"),
639
+ style: {
640
+ ...tabButtonStyle,
641
+ background: tab === "security" ? "#ece8ff" : "transparent",
642
+ color: tab === "security" ? "#6d28d9" : "#4b5563"
643
+ },
644
+ children: "Security"
645
+ }
646
+ )
647
+ ] }),
648
+ /* @__PURE__ */ jsxs("div", { style: { marginTop: "auto", paddingTop: 24, color: "#6b7280", fontSize: 15 }, children: [
649
+ "Secure by ",
650
+ /* @__PURE__ */ jsx("strong", { children: "Cyberia Auth" })
651
+ ] })
652
+ ]
653
+ }
654
+ ),
655
+ /* @__PURE__ */ jsxs("main", { style: { padding: 26 }, children: [
656
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
657
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: 22, color: "#111827" }, children: tab === "profile" ? "Profile details" : "Security" }),
658
+ /* @__PURE__ */ jsx(
659
+ "button",
660
+ {
661
+ type: "button",
662
+ onClick: () => setManageOpen(false),
663
+ style: { ...menuItemButtonStyle, width: "auto", fontSize: 24 },
664
+ children: "\xD7"
665
+ }
666
+ )
667
+ ] }),
668
+ /* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop: "1px solid #e5e7eb", margin: "16px 0 20px" } }),
669
+ tab === "profile" && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 20 }, children: [
670
+ /* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
671
+ /* @__PURE__ */ jsx("div", { style: { color: "#374151", fontSize: 14 }, children: "Profile" }),
672
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
673
+ /* @__PURE__ */ jsx("div", { style: avatarLargeStyle, children: initials }),
674
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: profileName })
675
+ ] }),
676
+ /* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Update profile" })
677
+ ] }),
678
+ /* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
679
+ /* @__PURE__ */ jsx("div", { style: { color: "#374151", fontSize: 14 }, children: "Email addresses" }),
680
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: profileEmail }),
681
+ /* @__PURE__ */ jsx("span", { style: { color: "#6b7280", fontSize: 14 }, children: "Primary" })
682
+ ] }),
683
+ /* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
684
+ /* @__PURE__ */ jsx("div", { style: { color: "#374151", fontSize: 14 }, children: "Connected accounts" }),
685
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "Google / Microsoft" }),
686
+ /* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Connect account" })
687
+ ] })
688
+ ] }),
689
+ tab === "security" && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 20 }, children: [
690
+ /* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
691
+ /* @__PURE__ */ jsx("div", { style: { color: "#374151", fontSize: 14 }, children: "Password" }),
692
+ /* @__PURE__ */ jsx("div", {}),
693
+ /* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Set password" })
694
+ ] }),
695
+ /* @__PURE__ */ jsxs("div", { style: { ...profileRowStyle, alignItems: "start" }, children: [
696
+ /* @__PURE__ */ jsx("div", { style: { color: "#374151", fontSize: 14 }, children: "Active devices" }),
697
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: "#374151", maxWidth: 430 }, children: userAgent }),
698
+ /* @__PURE__ */ jsx("span", { style: { color: "#6b7280", fontSize: 14 }, children: "This device" })
699
+ ] }),
700
+ /* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
701
+ /* @__PURE__ */ jsx("div", { style: { color: "#b91c1c", fontSize: 14 }, children: "Delete account" }),
702
+ /* @__PURE__ */ jsx("div", {}),
703
+ /* @__PURE__ */ jsx(
704
+ "button",
705
+ {
706
+ type: "button",
707
+ style: {
708
+ border: "none",
709
+ borderRadius: 8,
710
+ background: "#ef4444",
711
+ color: "#fff",
712
+ padding: "8px 12px",
713
+ cursor: "pointer",
714
+ fontSize: 14
715
+ },
716
+ children: "Delete account"
717
+ }
718
+ )
719
+ ] })
720
+ ] })
721
+ ] })
722
+ ]
723
+ }
724
+ )
725
+ }
726
+ )
727
+ ] });
728
+ }
729
+ function Protect({
730
+ children,
731
+ fallback = null
732
+ }) {
733
+ const { isLoaded, isSignedIn } = useCyberiaAuth();
734
+ if (!isLoaded) {
735
+ return null;
736
+ }
737
+ return isSignedIn ? /* @__PURE__ */ jsx(Fragment, { children }) : /* @__PURE__ */ jsx(Fragment, { children: fallback });
738
+ }
739
+ var cyberiaAuth = CyberiaAuth;
740
+ var index_default = CyberiaAuth;
741
+ var menuItemButtonStyle = {
742
+ width: "100%",
743
+ display: "block",
744
+ textAlign: "left",
745
+ padding: "8px 10px",
746
+ border: "none",
747
+ borderRadius: 8,
748
+ background: "transparent",
749
+ cursor: "pointer"
750
+ };
751
+ var inputStyle = {
752
+ width: "100%",
753
+ padding: 11,
754
+ borderRadius: 9,
755
+ border: "1px solid #d1d5db",
756
+ fontSize: 13
757
+ };
758
+ var fieldLabelStyle = {
759
+ display: "grid",
760
+ gap: 6,
761
+ fontSize: 14,
762
+ color: "#111827",
763
+ fontWeight: 600
764
+ };
765
+ var socialButtonStyle = {
766
+ border: "1px solid #d1d5db",
767
+ borderRadius: 9,
768
+ padding: "10px 12px",
769
+ background: "#ffffff",
770
+ cursor: "pointer",
771
+ fontSize: 16,
772
+ fontWeight: 300,
773
+ display: "inline-flex",
774
+ alignItems: "center",
775
+ justifyContent: "center",
776
+ gap: 8
777
+ };
778
+ function GoogleIcon() {
779
+ return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", height: "20", viewBox: "0 0 20 20", width: "20", "aria-hidden": "true", children: [
780
+ /* @__PURE__ */ jsx("path", { d: "M19.9905 10.1871C19.9905 9.36773 19.9224 8.7698 19.7752 8.14972H10.1992V11.848H15.8201C15.7068 12.7671 15.0948 14.1512 13.7349 15.0813L13.7159 15.2051L16.7436 17.497L16.9534 17.5174C18.8798 15.779 19.9905 13.2211 19.9905 10.1871Z", fill: "#4285F4" }),
781
+ /* @__PURE__ */ jsx("path", { d: "M10.1992 19.9313C12.953 19.9313 15.2648 19.0454 16.9534 17.5174L13.7349 15.0813C12.8737 15.6682 11.7177 16.0779 10.1992 16.0779C7.50211 16.0779 5.21297 14.3395 4.39695 11.9366L4.27734 11.9466L1.12906 14.3273L1.08789 14.4391C2.76508 17.6945 6.21016 19.9313 10.1992 19.9313Z", fill: "#34A853" }),
782
+ /* @__PURE__ */ jsx("path", { d: "M4.39695 11.9366C4.18164 11.3166 4.05703 10.6521 4.05703 9.96565C4.05703 9.27908 4.18164 8.61473 4.38562 7.99466L4.37992 7.8626L1.19219 5.44366L1.08789 5.49214C0.396641 6.84305 0 8.36008 0 9.96565C0 11.5712 0.396641 13.0882 1.08789 14.4391L4.39695 11.9366Z", fill: "#FBBC05" }),
783
+ /* @__PURE__ */ jsx("path", { d: "M10.1992 3.85336C12.1144 3.85336 13.4062 4.66168 14.1429 5.33718L17.0213 2.59107C15.2535 0.985496 12.953 0 10.1992 0C6.21016 0 2.76508 2.23672 1.08789 5.49214L4.38563 7.99466C5.21297 5.59183 7.50211 3.85336 10.1992 3.85336Z", fill: "#EB4335" })
784
+ ] });
785
+ }
786
+ function MicrosoftIcon() {
787
+ return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", height: "20", viewBox: "0 0 20 20", width: "20", "aria-hidden": "true", children: [
788
+ /* @__PURE__ */ jsx("path", { d: "M0 0H20V20H0V0Z", fill: "#F3F3F3" }),
789
+ /* @__PURE__ */ jsx("path", { d: "M0.870117 0.869141H9.56577V9.56479H0.870117V0.869141Z", fill: "#F35325" }),
790
+ /* @__PURE__ */ jsx("path", { d: "M10.4346 0.869141H19.1303V9.56479H10.4346V0.869141Z", fill: "#81BC06" }),
791
+ /* @__PURE__ */ jsx("path", { d: "M0.870117 10.4346H9.56577V19.1302H0.870117V10.4346Z", fill: "#05A6F0" }),
792
+ /* @__PURE__ */ jsx("path", { d: "M10.4346 10.4346H19.1303V19.1302H10.4346V10.4346Z", fill: "#FFBA08" })
793
+ ] });
794
+ }
795
+ function resolveColor(value, fallback) {
796
+ if (!value || value.trim().length === 0) {
797
+ return fallback;
798
+ }
799
+ return value;
800
+ }
801
+ function resolveBackendBaseUrl(backendUrl) {
802
+ const candidate = backendUrl?.trim() || DEFAULT_BACKEND_URL;
803
+ return candidate.replace(/\/+$/, "");
804
+ }
805
+ function getBrandingCacheKey(apiToken) {
806
+ return `cyberia_auth_branding:${apiToken}`;
807
+ }
808
+ function getCachedAppConfig(apiToken) {
809
+ if (typeof window === "undefined") {
810
+ return null;
811
+ }
812
+ try {
813
+ const raw = window.localStorage.getItem(getBrandingCacheKey(apiToken));
814
+ if (!raw) {
815
+ return null;
816
+ }
817
+ const parsed = JSON.parse(raw);
818
+ if (!parsed.organizationName || !parsed.appName) {
819
+ return null;
820
+ }
821
+ return {
822
+ appName: parsed.appName,
823
+ organizationName: parsed.organizationName,
824
+ primaryColor: resolveColor(parsed.primaryColor, defaultAppConfig.primaryColor),
825
+ secondaryColor: resolveColor(parsed.secondaryColor, defaultAppConfig.secondaryColor),
826
+ logoUrl: parsed.logoUrl
827
+ };
828
+ } catch {
829
+ return null;
830
+ }
831
+ }
832
+ function cacheAppConfig(apiToken, config) {
833
+ if (typeof window === "undefined") {
834
+ return;
835
+ }
836
+ try {
837
+ window.localStorage.setItem(getBrandingCacheKey(apiToken), JSON.stringify(config));
838
+ } catch {
839
+ }
840
+ }
841
+ var tabButtonStyle = {
842
+ border: "none",
843
+ borderRadius: 8,
844
+ padding: "8px 10px",
845
+ textAlign: "left",
846
+ cursor: "pointer",
847
+ fontSize: 14
848
+ };
849
+ var profileRowStyle = {
850
+ display: "grid",
851
+ gridTemplateColumns: "220px 1fr auto",
852
+ alignItems: "center",
853
+ gap: 12,
854
+ paddingBottom: 12,
855
+ borderBottom: "1px solid #f1f5f9"
856
+ };
857
+ var avatarLargeStyle = {
858
+ width: 48,
859
+ height: 48,
860
+ borderRadius: 999,
861
+ border: "1px solid #d1d5db",
862
+ display: "grid",
863
+ placeItems: "center",
864
+ fontWeight: 700,
865
+ color: "#111827",
866
+ background: "#f8fafc"
867
+ };
868
+ var linkButtonStyle = {
869
+ border: "none",
870
+ background: "transparent",
871
+ color: "#6d28d9",
872
+ cursor: "pointer",
873
+ fontSize: 14
874
+ };
875
+ var menuItemButtonStyleLarge = {
876
+ width: "100%",
877
+ display: "block",
878
+ textAlign: "left",
879
+ padding: "14px 14px",
880
+ border: "none",
881
+ background: "transparent",
882
+ cursor: "pointer",
883
+ fontSize: 15,
884
+ borderTop: "1px solid #f1f5f9"
885
+ };
886
+ export {
887
+ CyberiaAuth,
888
+ CyberiaAuthProvider,
889
+ Protect,
890
+ Show,
891
+ SignInButton,
892
+ SignOutButton,
893
+ SignUpButton,
894
+ SignedIn,
895
+ SignedOut,
896
+ UserButton,
897
+ cyberiaAuth,
898
+ index_default as default,
899
+ useCyberiaAuth
900
+ };