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