@cyberia-auth/auth 0.1.0 → 0.1.2
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/README.md +2 -0
- package/dist/index.cjs +153 -76
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +153 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,6 +69,7 @@ Props:
|
|
|
69
69
|
- `apiToken: string` - app API token
|
|
70
70
|
- `oauthRedirectUri?: string` - redirect URL for Google/Microsoft OAuth
|
|
71
71
|
- `initialMode?: 'login' | 'register'` - default mode
|
|
72
|
+
- `theme?: 'system' | 'light' | 'dark'` - color mode (`system` by default)
|
|
72
73
|
- `hideModeSwitch?: boolean` - hide sign-in/sign-up toggle footer
|
|
73
74
|
- `onAuthSuccess?: (result) => void` - callback with `{ token, user }`
|
|
74
75
|
|
|
@@ -81,6 +82,7 @@ Props:
|
|
|
81
82
|
- `backendUrl: string`
|
|
82
83
|
- `apiToken: string`
|
|
83
84
|
- `oauthRedirectUri?: string`
|
|
85
|
+
- `theme?: 'system' | 'light' | 'dark'` - applies to modal + `UserButton` UI
|
|
84
86
|
- `children: ReactNode`
|
|
85
87
|
- `storageKey?: string` - localStorage key override (default `cyberia_auth_session`)
|
|
86
88
|
|
package/dist/index.cjs
CHANGED
|
@@ -60,19 +60,29 @@ function CyberiaAuth({
|
|
|
60
60
|
apiToken,
|
|
61
61
|
oauthRedirectUri,
|
|
62
62
|
initialMode = "register",
|
|
63
|
+
theme = "system",
|
|
63
64
|
hideModeSwitch = false,
|
|
64
65
|
onAuthSuccess
|
|
65
66
|
}) {
|
|
66
67
|
const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
|
|
68
|
+
const resolvedApiToken = normalizeApiToken(apiToken);
|
|
69
|
+
const resolvedTheme = useResolvedTheme(theme);
|
|
70
|
+
const palette = getThemePalette(resolvedTheme);
|
|
67
71
|
const [mode, setMode] = (0, import_react.useState)(initialMode);
|
|
68
|
-
const [config, setConfig] = (0, import_react.useState)(() => getCachedAppConfig(
|
|
72
|
+
const [config, setConfig] = (0, import_react.useState)(() => getCachedAppConfig(resolvedApiToken));
|
|
69
73
|
const [isBrandingResolved, setIsBrandingResolved] = (0, import_react.useState)(
|
|
70
|
-
() => Boolean(getCachedAppConfig(
|
|
74
|
+
() => Boolean(getCachedAppConfig(resolvedApiToken))
|
|
71
75
|
);
|
|
72
76
|
const [message, setMessage] = (0, import_react.useState)("");
|
|
73
77
|
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
74
78
|
(0, import_react.useEffect)(() => {
|
|
75
|
-
|
|
79
|
+
if (!resolvedApiToken) {
|
|
80
|
+
setConfig(defaultAppConfig);
|
|
81
|
+
setIsBrandingResolved(true);
|
|
82
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const cached = getCachedAppConfig(resolvedApiToken);
|
|
76
86
|
if (cached) {
|
|
77
87
|
setConfig(cached);
|
|
78
88
|
setIsBrandingResolved(true);
|
|
@@ -80,10 +90,10 @@ function CyberiaAuth({
|
|
|
80
90
|
setIsBrandingResolved(false);
|
|
81
91
|
}
|
|
82
92
|
void import_axios.default.get(`${backendBaseUrl}/api/public/app/config`, {
|
|
83
|
-
params: { apiToken }
|
|
93
|
+
params: { apiToken: resolvedApiToken }
|
|
84
94
|
}).then((res) => {
|
|
85
95
|
setConfig(res.data);
|
|
86
|
-
cacheAppConfig(
|
|
96
|
+
cacheAppConfig(resolvedApiToken, res.data);
|
|
87
97
|
}).catch((error) => {
|
|
88
98
|
const errorMessage = error instanceof Error ? error.message : "Unable to load app config";
|
|
89
99
|
setMessage(errorMessage);
|
|
@@ -93,16 +103,20 @@ function CyberiaAuth({
|
|
|
93
103
|
}).finally(() => {
|
|
94
104
|
setIsBrandingResolved(true);
|
|
95
105
|
});
|
|
96
|
-
}, [
|
|
106
|
+
}, [resolvedApiToken, backendBaseUrl]);
|
|
97
107
|
const handleSubmit = async (event) => {
|
|
98
108
|
event.preventDefault();
|
|
109
|
+
if (!resolvedApiToken) {
|
|
110
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
99
113
|
setIsLoading(true);
|
|
100
114
|
setMessage("");
|
|
101
115
|
const form = new FormData(event.currentTarget);
|
|
102
116
|
try {
|
|
103
117
|
const endpoint = mode === "register" ? "/api/public/auth/register" : "/api/public/auth/login";
|
|
104
118
|
const payload = {
|
|
105
|
-
apiToken,
|
|
119
|
+
apiToken: resolvedApiToken,
|
|
106
120
|
email: String(form.get("email")),
|
|
107
121
|
password: String(form.get("password")),
|
|
108
122
|
displayName: String(form.get("displayName") ?? "")
|
|
@@ -122,12 +136,16 @@ function CyberiaAuth({
|
|
|
122
136
|
}
|
|
123
137
|
};
|
|
124
138
|
const startOAuth = (provider) => {
|
|
139
|
+
if (!resolvedApiToken) {
|
|
140
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
125
143
|
if (!oauthRedirectUri) {
|
|
126
144
|
setMessage("oauthRedirectUri is required for social login");
|
|
127
145
|
return;
|
|
128
146
|
}
|
|
129
147
|
const url = new URL(`${backendBaseUrl}/api/public/oauth/${provider}/start`);
|
|
130
|
-
url.searchParams.set("apiToken",
|
|
148
|
+
url.searchParams.set("apiToken", resolvedApiToken);
|
|
131
149
|
url.searchParams.set("redirectUri", oauthRedirectUri);
|
|
132
150
|
window.location.href = url.toString();
|
|
133
151
|
};
|
|
@@ -140,15 +158,15 @@ function CyberiaAuth({
|
|
|
140
158
|
"div",
|
|
141
159
|
{
|
|
142
160
|
style: {
|
|
143
|
-
border:
|
|
161
|
+
border: `1px solid ${palette.border}`,
|
|
144
162
|
borderRadius: 14,
|
|
145
163
|
padding: 20,
|
|
146
|
-
background:
|
|
164
|
+
background: palette.surface,
|
|
147
165
|
fontFamily: "Inter, Arial, sans-serif",
|
|
148
166
|
minHeight: 320,
|
|
149
167
|
display: "grid",
|
|
150
168
|
placeItems: "center",
|
|
151
|
-
color:
|
|
169
|
+
color: palette.textMuted
|
|
152
170
|
},
|
|
153
171
|
children: "Loading sign-in..."
|
|
154
172
|
}
|
|
@@ -158,15 +176,16 @@ function CyberiaAuth({
|
|
|
158
176
|
"div",
|
|
159
177
|
{
|
|
160
178
|
style: {
|
|
161
|
-
border:
|
|
179
|
+
border: `1px solid ${palette.border}`,
|
|
162
180
|
borderRadius: 14,
|
|
163
181
|
padding: 0,
|
|
164
|
-
background:
|
|
182
|
+
background: palette.surface,
|
|
165
183
|
overflow: "hidden",
|
|
166
184
|
fontFamily: "Inter, Arial, sans-serif",
|
|
167
185
|
width: "100%",
|
|
168
186
|
maxWidth: 500,
|
|
169
|
-
margin: "0 auto"
|
|
187
|
+
margin: "0 auto",
|
|
188
|
+
color: palette.text
|
|
170
189
|
},
|
|
171
190
|
children: [
|
|
172
191
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 20, display: "grid", gap: 14 }, children: [
|
|
@@ -190,15 +209,15 @@ function CyberiaAuth({
|
|
|
190
209
|
),
|
|
191
210
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center" }, children: [
|
|
192
211
|
/* @__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:
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: 0, color: palette.textMuted, fontSize: 13 }, children: subtitle })
|
|
194
213
|
] })
|
|
195
214
|
] }),
|
|
196
215
|
/* @__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: [
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", style: socialButtonStyle(palette), onClick: () => startOAuth("google"), children: [
|
|
198
217
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GoogleIcon, {}),
|
|
199
218
|
"Google"
|
|
200
219
|
] }),
|
|
201
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", style: socialButtonStyle, onClick: () => startOAuth("microsoft"), children: [
|
|
220
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", style: socialButtonStyle(palette), onClick: () => startOAuth("microsoft"), children: [
|
|
202
221
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MicrosoftIcon, {}),
|
|
203
222
|
"Microsoft"
|
|
204
223
|
] })
|
|
@@ -213,14 +232,14 @@ function CyberiaAuth({
|
|
|
213
232
|
gap: 12
|
|
214
233
|
},
|
|
215
234
|
children: [
|
|
216
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: 1, background:
|
|
217
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color:
|
|
218
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: 1, background:
|
|
235
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: 1, background: palette.border } }),
|
|
236
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: palette.textMuted, fontSize: 14 }, children: "or" }),
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: 1, background: palette.border } })
|
|
219
238
|
]
|
|
220
239
|
}
|
|
221
240
|
),
|
|
222
241
|
/* @__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: [
|
|
242
|
+
mode === "register" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: fieldLabelStyle(palette), children: [
|
|
224
243
|
"Full name",
|
|
225
244
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
226
245
|
"input",
|
|
@@ -228,15 +247,15 @@ function CyberiaAuth({
|
|
|
228
247
|
name: "displayName",
|
|
229
248
|
placeholder: "Enter your full name",
|
|
230
249
|
required: true,
|
|
231
|
-
style: inputStyle
|
|
250
|
+
style: inputStyle(palette)
|
|
232
251
|
}
|
|
233
252
|
)
|
|
234
253
|
] }),
|
|
235
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: fieldLabelStyle, children: [
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: fieldLabelStyle(palette), children: [
|
|
236
255
|
"Email address",
|
|
237
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "email", placeholder: "Enter your email address", required: true, style: inputStyle })
|
|
256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "email", placeholder: "Enter your email address", required: true, style: inputStyle(palette) })
|
|
238
257
|
] }),
|
|
239
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: fieldLabelStyle, children: [
|
|
258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: fieldLabelStyle(palette), children: [
|
|
240
259
|
"Password",
|
|
241
260
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
242
261
|
"input",
|
|
@@ -246,7 +265,7 @@ function CyberiaAuth({
|
|
|
246
265
|
placeholder: "Enter your password",
|
|
247
266
|
minLength: 8,
|
|
248
267
|
required: true,
|
|
249
|
-
style: inputStyle
|
|
268
|
+
style: inputStyle(palette)
|
|
250
269
|
}
|
|
251
270
|
)
|
|
252
271
|
] }),
|
|
@@ -274,10 +293,11 @@ function CyberiaAuth({
|
|
|
274
293
|
"div",
|
|
275
294
|
{
|
|
276
295
|
style: {
|
|
277
|
-
borderTop:
|
|
296
|
+
borderTop: `1px solid ${palette.border}`,
|
|
278
297
|
padding: 14,
|
|
279
298
|
textAlign: "center",
|
|
280
|
-
|
|
299
|
+
fontSize: 13,
|
|
300
|
+
background: palette.surfaceAlt
|
|
281
301
|
},
|
|
282
302
|
children: [
|
|
283
303
|
mode === "login" ? "Don't have an account? " : "Already have an account? ",
|
|
@@ -289,7 +309,7 @@ function CyberiaAuth({
|
|
|
289
309
|
style: {
|
|
290
310
|
border: "none",
|
|
291
311
|
background: "transparent",
|
|
292
|
-
color:
|
|
312
|
+
color: palette.text,
|
|
293
313
|
textDecoration: "underline",
|
|
294
314
|
fontWeight: 600,
|
|
295
315
|
cursor: "pointer",
|
|
@@ -310,10 +330,13 @@ function CyberiaAuthProvider({
|
|
|
310
330
|
backendUrl,
|
|
311
331
|
apiToken,
|
|
312
332
|
oauthRedirectUri,
|
|
333
|
+
theme = "system",
|
|
313
334
|
children,
|
|
314
335
|
storageKey = "cyberia_auth_session"
|
|
315
336
|
}) {
|
|
316
337
|
const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
|
|
338
|
+
const resolvedApiToken = normalizeApiToken(apiToken);
|
|
339
|
+
const resolvedTheme = useResolvedTheme(theme);
|
|
317
340
|
const [isLoaded, setIsLoaded] = (0, import_react.useState)(false);
|
|
318
341
|
const [session, setSession] = (0, import_react.useState)(null);
|
|
319
342
|
const [modalOpen, setModalOpen] = (0, import_react.useState)(false);
|
|
@@ -386,9 +409,10 @@ function CyberiaAuthProvider({
|
|
|
386
409
|
setModalOpen(true);
|
|
387
410
|
},
|
|
388
411
|
signOut,
|
|
389
|
-
setSessionFromAuth
|
|
412
|
+
setSessionFromAuth,
|
|
413
|
+
theme: resolvedTheme
|
|
390
414
|
}),
|
|
391
|
-
[isLoaded, session, setSessionFromAuth]
|
|
415
|
+
[isLoaded, resolvedTheme, session, setSessionFromAuth]
|
|
392
416
|
);
|
|
393
417
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CyberiaAuthContext.Provider, { value, children: [
|
|
394
418
|
children,
|
|
@@ -414,8 +438,9 @@ function CyberiaAuthProvider({
|
|
|
414
438
|
CyberiaAuth,
|
|
415
439
|
{
|
|
416
440
|
backendUrl: backendBaseUrl,
|
|
417
|
-
apiToken,
|
|
441
|
+
apiToken: resolvedApiToken,
|
|
418
442
|
oauthRedirectUri,
|
|
443
|
+
theme,
|
|
419
444
|
initialMode: modalMode,
|
|
420
445
|
hideModeSwitch: false,
|
|
421
446
|
onAuthSuccess: (result) => {
|
|
@@ -474,7 +499,8 @@ function SignOutButton({ children }) {
|
|
|
474
499
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: signOut, children: children ?? "Sign out" });
|
|
475
500
|
}
|
|
476
501
|
function UserButton() {
|
|
477
|
-
const { user, signOut, openSignIn, openSignUp } = useCyberiaAuth();
|
|
502
|
+
const { user, signOut, openSignIn, openSignUp, theme } = useCyberiaAuth();
|
|
503
|
+
const palette = getThemePalette(theme);
|
|
478
504
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
479
505
|
const [manageOpen, setManageOpen] = (0, import_react.useState)(false);
|
|
480
506
|
const [tab, setTab] = (0, import_react.useState)("profile");
|
|
@@ -505,8 +531,9 @@ function UserButton() {
|
|
|
505
531
|
width: 36,
|
|
506
532
|
height: 36,
|
|
507
533
|
borderRadius: 999,
|
|
508
|
-
border:
|
|
509
|
-
background:
|
|
534
|
+
border: `1px solid ${palette.border}`,
|
|
535
|
+
background: palette.surface,
|
|
536
|
+
color: palette.text,
|
|
510
537
|
fontWeight: 700,
|
|
511
538
|
cursor: "pointer"
|
|
512
539
|
},
|
|
@@ -522,8 +549,8 @@ function UserButton() {
|
|
|
522
549
|
right: 0,
|
|
523
550
|
top: 42,
|
|
524
551
|
minWidth: 320,
|
|
525
|
-
background:
|
|
526
|
-
border:
|
|
552
|
+
background: palette.surface,
|
|
553
|
+
border: `1px solid ${palette.border}`,
|
|
527
554
|
borderRadius: 12,
|
|
528
555
|
boxShadow: "0 12px 24px rgba(0,0,0,0.08)",
|
|
529
556
|
padding: 0,
|
|
@@ -538,22 +565,22 @@ function UserButton() {
|
|
|
538
565
|
width: 44,
|
|
539
566
|
height: 44,
|
|
540
567
|
borderRadius: 999,
|
|
541
|
-
border:
|
|
568
|
+
border: `1px solid ${palette.border}`,
|
|
542
569
|
display: "grid",
|
|
543
570
|
placeItems: "center",
|
|
544
571
|
fontWeight: 700,
|
|
545
|
-
color:
|
|
546
|
-
background:
|
|
572
|
+
color: palette.text,
|
|
573
|
+
background: palette.surfaceAlt
|
|
547
574
|
},
|
|
548
575
|
children: initials
|
|
549
576
|
}
|
|
550
577
|
),
|
|
551
578
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "grid" }, children: [
|
|
552
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { fontSize: 16, color:
|
|
553
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color:
|
|
579
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { fontSize: 16, color: palette.text, lineHeight: 1.2 }, children: profileName }),
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: palette.text, fontSize: 14 }, children: profileEmail })
|
|
554
581
|
] })
|
|
555
582
|
] }),
|
|
556
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { style: { border: 0, borderTop:
|
|
583
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { style: { border: 0, borderTop: `1px solid ${palette.border}`, margin: 0 } }),
|
|
557
584
|
!user && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
558
585
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
559
586
|
"button",
|
|
@@ -607,9 +634,9 @@ function UserButton() {
|
|
|
607
634
|
}
|
|
608
635
|
)
|
|
609
636
|
] }),
|
|
610
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop:
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: `1px solid ${palette.border}`, textAlign: "center", padding: "12px 10px", color: palette.textMuted, fontSize: 13 }, children: [
|
|
611
638
|
"Secured by ",
|
|
612
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Cyberia Auth" })
|
|
613
640
|
] })
|
|
614
641
|
]
|
|
615
642
|
}
|
|
@@ -634,9 +661,9 @@ function UserButton() {
|
|
|
634
661
|
width: "100%",
|
|
635
662
|
maxWidth: 940,
|
|
636
663
|
minHeight: 540,
|
|
637
|
-
background:
|
|
664
|
+
background: palette.surface,
|
|
638
665
|
borderRadius: 10,
|
|
639
|
-
border:
|
|
666
|
+
border: `1px solid ${palette.border}`,
|
|
640
667
|
display: "grid",
|
|
641
668
|
gridTemplateColumns: "220px 1fr",
|
|
642
669
|
overflow: "hidden"
|
|
@@ -647,15 +674,15 @@ function UserButton() {
|
|
|
647
674
|
"aside",
|
|
648
675
|
{
|
|
649
676
|
style: {
|
|
650
|
-
borderRight:
|
|
677
|
+
borderRight: `1px solid ${palette.border}`,
|
|
651
678
|
padding: 22,
|
|
652
|
-
background:
|
|
679
|
+
background: palette.surfaceAlt,
|
|
653
680
|
display: "flex",
|
|
654
681
|
flexDirection: "column"
|
|
655
682
|
},
|
|
656
683
|
children: [
|
|
657
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0, fontSize: 30, color:
|
|
658
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { marginTop: 6, color:
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0, fontSize: 30, color: palette.text }, children: "Account" }),
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { marginTop: 6, color: palette.textMuted, fontSize: 12 }, children: "Manage your account info." }),
|
|
659
686
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 20, display: "grid", gap: 8 }, children: [
|
|
660
687
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
661
688
|
"button",
|
|
@@ -664,8 +691,8 @@ function UserButton() {
|
|
|
664
691
|
onClick: () => setTab("profile"),
|
|
665
692
|
style: {
|
|
666
693
|
...tabButtonStyle,
|
|
667
|
-
background: tab === "profile" ? "#
|
|
668
|
-
color: tab === "profile" ? "#
|
|
694
|
+
background: tab === "profile" ? "#ffe8e8" : "transparent",
|
|
695
|
+
color: tab === "profile" ? "#d92828" : palette.textMuted
|
|
669
696
|
},
|
|
670
697
|
children: "Profile"
|
|
671
698
|
}
|
|
@@ -677,14 +704,14 @@ function UserButton() {
|
|
|
677
704
|
onClick: () => setTab("security"),
|
|
678
705
|
style: {
|
|
679
706
|
...tabButtonStyle,
|
|
680
|
-
background: tab === "security" ? "#
|
|
681
|
-
color: tab === "security" ? "#
|
|
707
|
+
background: tab === "security" ? "#ffe8e8" : "transparent",
|
|
708
|
+
color: tab === "security" ? "#d92828" : palette.textMuted
|
|
682
709
|
},
|
|
683
710
|
children: "Security"
|
|
684
711
|
}
|
|
685
712
|
)
|
|
686
713
|
] }),
|
|
687
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "auto", paddingTop: 24, color:
|
|
714
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "auto", paddingTop: 24, color: palette.textMuted, fontSize: 15 }, children: [
|
|
688
715
|
"Secure by ",
|
|
689
716
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Cyberia Auth" })
|
|
690
717
|
] })
|
|
@@ -693,7 +720,7 @@ function UserButton() {
|
|
|
693
720
|
),
|
|
694
721
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", { style: { padding: 26 }, children: [
|
|
695
722
|
/* @__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:
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { margin: 0, fontSize: 22, color: palette.text }, children: tab === "profile" ? "Profile details" : "Security" }),
|
|
697
724
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
698
725
|
"button",
|
|
699
726
|
{
|
|
@@ -704,10 +731,10 @@ function UserButton() {
|
|
|
704
731
|
}
|
|
705
732
|
)
|
|
706
733
|
] }),
|
|
707
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { style: { border: 0, borderTop:
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", { style: { border: 0, borderTop: `1px solid ${palette.border}`, margin: "16px 0 20px" } }),
|
|
708
735
|
tab === "profile" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "grid", gap: 20 }, children: [
|
|
709
736
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: profileRowStyle, children: [
|
|
710
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Profile" }),
|
|
711
738
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
712
739
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: avatarLargeStyle, children: initials }),
|
|
713
740
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 16 }, children: profileName })
|
|
@@ -715,25 +742,25 @@ function UserButton() {
|
|
|
715
742
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: linkButtonStyle, children: "Update profile" })
|
|
716
743
|
] }),
|
|
717
744
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: profileRowStyle, children: [
|
|
718
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Email addresses" }),
|
|
719
746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 16 }, children: profileEmail }),
|
|
720
747
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#6b7280", fontSize: 14 }, children: "Primary" })
|
|
721
748
|
] }),
|
|
722
749
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: profileRowStyle, children: [
|
|
723
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#
|
|
750
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Connected accounts" }),
|
|
724
751
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 16 }, children: "Google / Microsoft" }),
|
|
725
752
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: linkButtonStyle, children: "Connect account" })
|
|
726
753
|
] })
|
|
727
754
|
] }),
|
|
728
755
|
tab === "security" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "grid", gap: 20 }, children: [
|
|
729
756
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: profileRowStyle, children: [
|
|
730
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#
|
|
757
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Password" }),
|
|
731
758
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {}),
|
|
732
759
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: linkButtonStyle, children: "Set password" })
|
|
733
760
|
] }),
|
|
734
761
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...profileRowStyle, alignItems: "start" }, children: [
|
|
735
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#
|
|
736
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 14, color: "#
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Active devices" }),
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 14, color: "#c5c7ca", maxWidth: 430 }, children: userAgent }),
|
|
737
764
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#6b7280", fontSize: 14 }, children: "This device" })
|
|
738
765
|
] }),
|
|
739
766
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: profileRowStyle, children: [
|
|
@@ -787,25 +814,28 @@ var menuItemButtonStyle = {
|
|
|
787
814
|
background: "transparent",
|
|
788
815
|
cursor: "pointer"
|
|
789
816
|
};
|
|
790
|
-
var inputStyle = {
|
|
817
|
+
var inputStyle = (palette) => ({
|
|
791
818
|
width: "100%",
|
|
792
819
|
padding: 11,
|
|
793
820
|
borderRadius: 9,
|
|
794
|
-
border:
|
|
821
|
+
border: `1px solid ${palette.border}`,
|
|
822
|
+
background: palette.surface,
|
|
823
|
+
color: palette.text,
|
|
795
824
|
fontSize: 13
|
|
796
|
-
};
|
|
797
|
-
var fieldLabelStyle = {
|
|
825
|
+
});
|
|
826
|
+
var fieldLabelStyle = (palette) => ({
|
|
798
827
|
display: "grid",
|
|
799
828
|
gap: 6,
|
|
800
829
|
fontSize: 14,
|
|
801
|
-
color:
|
|
830
|
+
color: palette.text,
|
|
802
831
|
fontWeight: 600
|
|
803
|
-
};
|
|
804
|
-
var socialButtonStyle = {
|
|
805
|
-
border:
|
|
832
|
+
});
|
|
833
|
+
var socialButtonStyle = (palette) => ({
|
|
834
|
+
border: `1px solid ${palette.border}`,
|
|
806
835
|
borderRadius: 9,
|
|
807
836
|
padding: "10px 12px",
|
|
808
|
-
background:
|
|
837
|
+
background: palette.surface,
|
|
838
|
+
color: palette.text,
|
|
809
839
|
cursor: "pointer",
|
|
810
840
|
fontSize: 16,
|
|
811
841
|
fontWeight: 300,
|
|
@@ -813,7 +843,7 @@ var socialButtonStyle = {
|
|
|
813
843
|
alignItems: "center",
|
|
814
844
|
justifyContent: "center",
|
|
815
845
|
gap: 8
|
|
816
|
-
};
|
|
846
|
+
});
|
|
817
847
|
function GoogleIcon() {
|
|
818
848
|
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
849
|
/* @__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" }),
|
|
@@ -841,6 +871,53 @@ function resolveBackendBaseUrl(backendUrl) {
|
|
|
841
871
|
const candidate = backendUrl?.trim() || DEFAULT_BACKEND_URL;
|
|
842
872
|
return candidate.replace(/\/+$/, "");
|
|
843
873
|
}
|
|
874
|
+
function normalizeApiToken(apiToken) {
|
|
875
|
+
return apiToken.trim();
|
|
876
|
+
}
|
|
877
|
+
function getThemePalette(theme) {
|
|
878
|
+
if (theme === "dark") {
|
|
879
|
+
return {
|
|
880
|
+
surface: "#445364",
|
|
881
|
+
surfaceAlt: "#1f2937",
|
|
882
|
+
border: "#374151",
|
|
883
|
+
text: "#f9fafb",
|
|
884
|
+
textMuted: "#9ca3af"
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
return {
|
|
888
|
+
surface: "#ffffff",
|
|
889
|
+
surfaceAlt: "#fafafa",
|
|
890
|
+
border: "#e5e7eb",
|
|
891
|
+
text: "#111827",
|
|
892
|
+
textMuted: "#6b7280"
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function useResolvedTheme(theme) {
|
|
896
|
+
const [resolvedTheme, setResolvedTheme] = (0, import_react.useState)(() => {
|
|
897
|
+
if (theme === "light" || theme === "dark") {
|
|
898
|
+
return theme;
|
|
899
|
+
}
|
|
900
|
+
if (typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
901
|
+
return "dark";
|
|
902
|
+
}
|
|
903
|
+
return "light";
|
|
904
|
+
});
|
|
905
|
+
(0, import_react.useEffect)(() => {
|
|
906
|
+
if (theme === "light" || theme === "dark") {
|
|
907
|
+
setResolvedTheme(theme);
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
if (typeof window === "undefined") {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
914
|
+
const updateTheme = () => setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
915
|
+
updateTheme();
|
|
916
|
+
mediaQuery.addEventListener("change", updateTheme);
|
|
917
|
+
return () => mediaQuery.removeEventListener("change", updateTheme);
|
|
918
|
+
}, [theme]);
|
|
919
|
+
return resolvedTheme;
|
|
920
|
+
}
|
|
844
921
|
function getBrandingCacheKey(apiToken) {
|
|
845
922
|
return `cyberia_auth_branding:${apiToken}`;
|
|
846
923
|
}
|
|
@@ -887,7 +964,7 @@ var tabButtonStyle = {
|
|
|
887
964
|
};
|
|
888
965
|
var profileRowStyle = {
|
|
889
966
|
display: "grid",
|
|
890
|
-
gridTemplateColumns: "
|
|
967
|
+
gridTemplateColumns: "150px 1fr auto",
|
|
891
968
|
alignItems: "center",
|
|
892
969
|
gap: 12,
|
|
893
970
|
paddingBottom: 12,
|
|
@@ -907,7 +984,7 @@ var avatarLargeStyle = {
|
|
|
907
984
|
var linkButtonStyle = {
|
|
908
985
|
border: "none",
|
|
909
986
|
background: "transparent",
|
|
910
|
-
color: "#
|
|
987
|
+
color: "#d92828",
|
|
911
988
|
cursor: "pointer",
|
|
912
989
|
fontSize: 14
|
|
913
990
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
type AuthMode = 'register' | 'login';
|
|
5
|
+
type ThemeMode = 'system' | 'light' | 'dark';
|
|
6
|
+
type ResolvedTheme = 'light' | 'dark';
|
|
5
7
|
type AuthUser = {
|
|
6
8
|
id: string;
|
|
7
9
|
email: string;
|
|
@@ -16,10 +18,11 @@ type CyberiaAuthProps = {
|
|
|
16
18
|
apiToken: string;
|
|
17
19
|
oauthRedirectUri?: string;
|
|
18
20
|
initialMode?: AuthMode;
|
|
21
|
+
theme?: ThemeMode;
|
|
19
22
|
hideModeSwitch?: boolean;
|
|
20
23
|
onAuthSuccess?: (data: AuthResult) => void;
|
|
21
24
|
};
|
|
22
|
-
declare function CyberiaAuth({ backendUrl, apiToken, oauthRedirectUri, initialMode, hideModeSwitch, onAuthSuccess, }: CyberiaAuthProps): react_jsx_runtime.JSX.Element;
|
|
25
|
+
declare function CyberiaAuth({ backendUrl, apiToken, oauthRedirectUri, initialMode, theme, hideModeSwitch, onAuthSuccess, }: CyberiaAuthProps): react_jsx_runtime.JSX.Element;
|
|
23
26
|
type CyberiaAuthContextValue = {
|
|
24
27
|
isLoaded: boolean;
|
|
25
28
|
isSignedIn: boolean;
|
|
@@ -29,15 +32,17 @@ type CyberiaAuthContextValue = {
|
|
|
29
32
|
openSignUp: () => void;
|
|
30
33
|
signOut: () => void;
|
|
31
34
|
setSessionFromAuth: (result: AuthResult) => void;
|
|
35
|
+
theme: ResolvedTheme;
|
|
32
36
|
};
|
|
33
37
|
type CyberiaAuthProviderProps = {
|
|
34
38
|
backendUrl?: string;
|
|
35
39
|
apiToken: string;
|
|
36
40
|
oauthRedirectUri?: string;
|
|
41
|
+
theme?: ThemeMode;
|
|
37
42
|
children: ReactNode;
|
|
38
43
|
storageKey?: string;
|
|
39
44
|
};
|
|
40
|
-
declare function CyberiaAuthProvider({ backendUrl, apiToken, oauthRedirectUri, children, storageKey, }: CyberiaAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
45
|
+
declare function CyberiaAuthProvider({ backendUrl, apiToken, oauthRedirectUri, theme, children, storageKey, }: CyberiaAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
41
46
|
declare function useCyberiaAuth(): CyberiaAuthContextValue;
|
|
42
47
|
declare function Show({ when, children }: {
|
|
43
48
|
when: 'signed-in' | 'signed-out';
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
type AuthMode = 'register' | 'login';
|
|
5
|
+
type ThemeMode = 'system' | 'light' | 'dark';
|
|
6
|
+
type ResolvedTheme = 'light' | 'dark';
|
|
5
7
|
type AuthUser = {
|
|
6
8
|
id: string;
|
|
7
9
|
email: string;
|
|
@@ -16,10 +18,11 @@ type CyberiaAuthProps = {
|
|
|
16
18
|
apiToken: string;
|
|
17
19
|
oauthRedirectUri?: string;
|
|
18
20
|
initialMode?: AuthMode;
|
|
21
|
+
theme?: ThemeMode;
|
|
19
22
|
hideModeSwitch?: boolean;
|
|
20
23
|
onAuthSuccess?: (data: AuthResult) => void;
|
|
21
24
|
};
|
|
22
|
-
declare function CyberiaAuth({ backendUrl, apiToken, oauthRedirectUri, initialMode, hideModeSwitch, onAuthSuccess, }: CyberiaAuthProps): react_jsx_runtime.JSX.Element;
|
|
25
|
+
declare function CyberiaAuth({ backendUrl, apiToken, oauthRedirectUri, initialMode, theme, hideModeSwitch, onAuthSuccess, }: CyberiaAuthProps): react_jsx_runtime.JSX.Element;
|
|
23
26
|
type CyberiaAuthContextValue = {
|
|
24
27
|
isLoaded: boolean;
|
|
25
28
|
isSignedIn: boolean;
|
|
@@ -29,15 +32,17 @@ type CyberiaAuthContextValue = {
|
|
|
29
32
|
openSignUp: () => void;
|
|
30
33
|
signOut: () => void;
|
|
31
34
|
setSessionFromAuth: (result: AuthResult) => void;
|
|
35
|
+
theme: ResolvedTheme;
|
|
32
36
|
};
|
|
33
37
|
type CyberiaAuthProviderProps = {
|
|
34
38
|
backendUrl?: string;
|
|
35
39
|
apiToken: string;
|
|
36
40
|
oauthRedirectUri?: string;
|
|
41
|
+
theme?: ThemeMode;
|
|
37
42
|
children: ReactNode;
|
|
38
43
|
storageKey?: string;
|
|
39
44
|
};
|
|
40
|
-
declare function CyberiaAuthProvider({ backendUrl, apiToken, oauthRedirectUri, children, storageKey, }: CyberiaAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
45
|
+
declare function CyberiaAuthProvider({ backendUrl, apiToken, oauthRedirectUri, theme, children, storageKey, }: CyberiaAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
41
46
|
declare function useCyberiaAuth(): CyberiaAuthContextValue;
|
|
42
47
|
declare function Show({ when, children }: {
|
|
43
48
|
when: 'signed-in' | 'signed-out';
|
package/dist/index.js
CHANGED
|
@@ -21,19 +21,29 @@ function CyberiaAuth({
|
|
|
21
21
|
apiToken,
|
|
22
22
|
oauthRedirectUri,
|
|
23
23
|
initialMode = "register",
|
|
24
|
+
theme = "system",
|
|
24
25
|
hideModeSwitch = false,
|
|
25
26
|
onAuthSuccess
|
|
26
27
|
}) {
|
|
27
28
|
const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
|
|
29
|
+
const resolvedApiToken = normalizeApiToken(apiToken);
|
|
30
|
+
const resolvedTheme = useResolvedTheme(theme);
|
|
31
|
+
const palette = getThemePalette(resolvedTheme);
|
|
28
32
|
const [mode, setMode] = useState(initialMode);
|
|
29
|
-
const [config, setConfig] = useState(() => getCachedAppConfig(
|
|
33
|
+
const [config, setConfig] = useState(() => getCachedAppConfig(resolvedApiToken));
|
|
30
34
|
const [isBrandingResolved, setIsBrandingResolved] = useState(
|
|
31
|
-
() => Boolean(getCachedAppConfig(
|
|
35
|
+
() => Boolean(getCachedAppConfig(resolvedApiToken))
|
|
32
36
|
);
|
|
33
37
|
const [message, setMessage] = useState("");
|
|
34
38
|
const [isLoading, setIsLoading] = useState(false);
|
|
35
39
|
useEffect(() => {
|
|
36
|
-
|
|
40
|
+
if (!resolvedApiToken) {
|
|
41
|
+
setConfig(defaultAppConfig);
|
|
42
|
+
setIsBrandingResolved(true);
|
|
43
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const cached = getCachedAppConfig(resolvedApiToken);
|
|
37
47
|
if (cached) {
|
|
38
48
|
setConfig(cached);
|
|
39
49
|
setIsBrandingResolved(true);
|
|
@@ -41,10 +51,10 @@ function CyberiaAuth({
|
|
|
41
51
|
setIsBrandingResolved(false);
|
|
42
52
|
}
|
|
43
53
|
void axios.get(`${backendBaseUrl}/api/public/app/config`, {
|
|
44
|
-
params: { apiToken }
|
|
54
|
+
params: { apiToken: resolvedApiToken }
|
|
45
55
|
}).then((res) => {
|
|
46
56
|
setConfig(res.data);
|
|
47
|
-
cacheAppConfig(
|
|
57
|
+
cacheAppConfig(resolvedApiToken, res.data);
|
|
48
58
|
}).catch((error) => {
|
|
49
59
|
const errorMessage = error instanceof Error ? error.message : "Unable to load app config";
|
|
50
60
|
setMessage(errorMessage);
|
|
@@ -54,16 +64,20 @@ function CyberiaAuth({
|
|
|
54
64
|
}).finally(() => {
|
|
55
65
|
setIsBrandingResolved(true);
|
|
56
66
|
});
|
|
57
|
-
}, [
|
|
67
|
+
}, [resolvedApiToken, backendBaseUrl]);
|
|
58
68
|
const handleSubmit = async (event) => {
|
|
59
69
|
event.preventDefault();
|
|
70
|
+
if (!resolvedApiToken) {
|
|
71
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
60
74
|
setIsLoading(true);
|
|
61
75
|
setMessage("");
|
|
62
76
|
const form = new FormData(event.currentTarget);
|
|
63
77
|
try {
|
|
64
78
|
const endpoint = mode === "register" ? "/api/public/auth/register" : "/api/public/auth/login";
|
|
65
79
|
const payload = {
|
|
66
|
-
apiToken,
|
|
80
|
+
apiToken: resolvedApiToken,
|
|
67
81
|
email: String(form.get("email")),
|
|
68
82
|
password: String(form.get("password")),
|
|
69
83
|
displayName: String(form.get("displayName") ?? "")
|
|
@@ -83,12 +97,16 @@ function CyberiaAuth({
|
|
|
83
97
|
}
|
|
84
98
|
};
|
|
85
99
|
const startOAuth = (provider) => {
|
|
100
|
+
if (!resolvedApiToken) {
|
|
101
|
+
setMessage('Missing apiToken. Pass a valid app token to <CyberiaAuth apiToken="...">.');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
86
104
|
if (!oauthRedirectUri) {
|
|
87
105
|
setMessage("oauthRedirectUri is required for social login");
|
|
88
106
|
return;
|
|
89
107
|
}
|
|
90
108
|
const url = new URL(`${backendBaseUrl}/api/public/oauth/${provider}/start`);
|
|
91
|
-
url.searchParams.set("apiToken",
|
|
109
|
+
url.searchParams.set("apiToken", resolvedApiToken);
|
|
92
110
|
url.searchParams.set("redirectUri", oauthRedirectUri);
|
|
93
111
|
window.location.href = url.toString();
|
|
94
112
|
};
|
|
@@ -101,15 +119,15 @@ function CyberiaAuth({
|
|
|
101
119
|
"div",
|
|
102
120
|
{
|
|
103
121
|
style: {
|
|
104
|
-
border:
|
|
122
|
+
border: `1px solid ${palette.border}`,
|
|
105
123
|
borderRadius: 14,
|
|
106
124
|
padding: 20,
|
|
107
|
-
background:
|
|
125
|
+
background: palette.surface,
|
|
108
126
|
fontFamily: "Inter, Arial, sans-serif",
|
|
109
127
|
minHeight: 320,
|
|
110
128
|
display: "grid",
|
|
111
129
|
placeItems: "center",
|
|
112
|
-
color:
|
|
130
|
+
color: palette.textMuted
|
|
113
131
|
},
|
|
114
132
|
children: "Loading sign-in..."
|
|
115
133
|
}
|
|
@@ -119,15 +137,16 @@ function CyberiaAuth({
|
|
|
119
137
|
"div",
|
|
120
138
|
{
|
|
121
139
|
style: {
|
|
122
|
-
border:
|
|
140
|
+
border: `1px solid ${palette.border}`,
|
|
123
141
|
borderRadius: 14,
|
|
124
142
|
padding: 0,
|
|
125
|
-
background:
|
|
143
|
+
background: palette.surface,
|
|
126
144
|
overflow: "hidden",
|
|
127
145
|
fontFamily: "Inter, Arial, sans-serif",
|
|
128
146
|
width: "100%",
|
|
129
147
|
maxWidth: 500,
|
|
130
|
-
margin: "0 auto"
|
|
148
|
+
margin: "0 auto",
|
|
149
|
+
color: palette.text
|
|
131
150
|
},
|
|
132
151
|
children: [
|
|
133
152
|
/* @__PURE__ */ jsxs("div", { style: { padding: 20, display: "grid", gap: 14 }, children: [
|
|
@@ -151,15 +170,15 @@ function CyberiaAuth({
|
|
|
151
170
|
),
|
|
152
171
|
/* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
|
|
153
172
|
/* @__PURE__ */ jsx("h3", { style: { margin: "0 0 6px 0", fontSize: 16 }, children: title }),
|
|
154
|
-
/* @__PURE__ */ jsx("p", { style: { margin: 0, color:
|
|
173
|
+
/* @__PURE__ */ jsx("p", { style: { margin: 0, color: palette.textMuted, fontSize: 13 }, children: subtitle })
|
|
155
174
|
] })
|
|
156
175
|
] }),
|
|
157
176
|
/* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }, children: [
|
|
158
|
-
/* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle, onClick: () => startOAuth("google"), children: [
|
|
177
|
+
/* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle(palette), onClick: () => startOAuth("google"), children: [
|
|
159
178
|
/* @__PURE__ */ jsx(GoogleIcon, {}),
|
|
160
179
|
"Google"
|
|
161
180
|
] }),
|
|
162
|
-
/* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle, onClick: () => startOAuth("microsoft"), children: [
|
|
181
|
+
/* @__PURE__ */ jsxs("button", { type: "button", style: socialButtonStyle(palette), onClick: () => startOAuth("microsoft"), children: [
|
|
163
182
|
/* @__PURE__ */ jsx(MicrosoftIcon, {}),
|
|
164
183
|
"Microsoft"
|
|
165
184
|
] })
|
|
@@ -174,14 +193,14 @@ function CyberiaAuth({
|
|
|
174
193
|
gap: 12
|
|
175
194
|
},
|
|
176
195
|
children: [
|
|
177
|
-
/* @__PURE__ */ jsx("div", { style: { height: 1, background:
|
|
178
|
-
/* @__PURE__ */ jsx("span", { style: { color:
|
|
179
|
-
/* @__PURE__ */ jsx("div", { style: { height: 1, background:
|
|
196
|
+
/* @__PURE__ */ jsx("div", { style: { height: 1, background: palette.border } }),
|
|
197
|
+
/* @__PURE__ */ jsx("span", { style: { color: palette.textMuted, fontSize: 14 }, children: "or" }),
|
|
198
|
+
/* @__PURE__ */ jsx("div", { style: { height: 1, background: palette.border } })
|
|
180
199
|
]
|
|
181
200
|
}
|
|
182
201
|
),
|
|
183
202
|
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "grid", gap: 10 }, children: [
|
|
184
|
-
mode === "register" && /* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
|
|
203
|
+
mode === "register" && /* @__PURE__ */ jsxs("label", { style: fieldLabelStyle(palette), children: [
|
|
185
204
|
"Full name",
|
|
186
205
|
/* @__PURE__ */ jsx(
|
|
187
206
|
"input",
|
|
@@ -189,15 +208,15 @@ function CyberiaAuth({
|
|
|
189
208
|
name: "displayName",
|
|
190
209
|
placeholder: "Enter your full name",
|
|
191
210
|
required: true,
|
|
192
|
-
style: inputStyle
|
|
211
|
+
style: inputStyle(palette)
|
|
193
212
|
}
|
|
194
213
|
)
|
|
195
214
|
] }),
|
|
196
|
-
/* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
|
|
215
|
+
/* @__PURE__ */ jsxs("label", { style: fieldLabelStyle(palette), children: [
|
|
197
216
|
"Email address",
|
|
198
|
-
/* @__PURE__ */ jsx("input", { type: "email", name: "email", placeholder: "Enter your email address", required: true, style: inputStyle })
|
|
217
|
+
/* @__PURE__ */ jsx("input", { type: "email", name: "email", placeholder: "Enter your email address", required: true, style: inputStyle(palette) })
|
|
199
218
|
] }),
|
|
200
|
-
/* @__PURE__ */ jsxs("label", { style: fieldLabelStyle, children: [
|
|
219
|
+
/* @__PURE__ */ jsxs("label", { style: fieldLabelStyle(palette), children: [
|
|
201
220
|
"Password",
|
|
202
221
|
/* @__PURE__ */ jsx(
|
|
203
222
|
"input",
|
|
@@ -207,7 +226,7 @@ function CyberiaAuth({
|
|
|
207
226
|
placeholder: "Enter your password",
|
|
208
227
|
minLength: 8,
|
|
209
228
|
required: true,
|
|
210
|
-
style: inputStyle
|
|
229
|
+
style: inputStyle(palette)
|
|
211
230
|
}
|
|
212
231
|
)
|
|
213
232
|
] }),
|
|
@@ -235,10 +254,11 @@ function CyberiaAuth({
|
|
|
235
254
|
"div",
|
|
236
255
|
{
|
|
237
256
|
style: {
|
|
238
|
-
borderTop:
|
|
257
|
+
borderTop: `1px solid ${palette.border}`,
|
|
239
258
|
padding: 14,
|
|
240
259
|
textAlign: "center",
|
|
241
|
-
|
|
260
|
+
fontSize: 13,
|
|
261
|
+
background: palette.surfaceAlt
|
|
242
262
|
},
|
|
243
263
|
children: [
|
|
244
264
|
mode === "login" ? "Don't have an account? " : "Already have an account? ",
|
|
@@ -250,7 +270,7 @@ function CyberiaAuth({
|
|
|
250
270
|
style: {
|
|
251
271
|
border: "none",
|
|
252
272
|
background: "transparent",
|
|
253
|
-
color:
|
|
273
|
+
color: palette.text,
|
|
254
274
|
textDecoration: "underline",
|
|
255
275
|
fontWeight: 600,
|
|
256
276
|
cursor: "pointer",
|
|
@@ -271,10 +291,13 @@ function CyberiaAuthProvider({
|
|
|
271
291
|
backendUrl,
|
|
272
292
|
apiToken,
|
|
273
293
|
oauthRedirectUri,
|
|
294
|
+
theme = "system",
|
|
274
295
|
children,
|
|
275
296
|
storageKey = "cyberia_auth_session"
|
|
276
297
|
}) {
|
|
277
298
|
const backendBaseUrl = resolveBackendBaseUrl(backendUrl);
|
|
299
|
+
const resolvedApiToken = normalizeApiToken(apiToken);
|
|
300
|
+
const resolvedTheme = useResolvedTheme(theme);
|
|
278
301
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
279
302
|
const [session, setSession] = useState(null);
|
|
280
303
|
const [modalOpen, setModalOpen] = useState(false);
|
|
@@ -347,9 +370,10 @@ function CyberiaAuthProvider({
|
|
|
347
370
|
setModalOpen(true);
|
|
348
371
|
},
|
|
349
372
|
signOut,
|
|
350
|
-
setSessionFromAuth
|
|
373
|
+
setSessionFromAuth,
|
|
374
|
+
theme: resolvedTheme
|
|
351
375
|
}),
|
|
352
|
-
[isLoaded, session, setSessionFromAuth]
|
|
376
|
+
[isLoaded, resolvedTheme, session, setSessionFromAuth]
|
|
353
377
|
);
|
|
354
378
|
return /* @__PURE__ */ jsxs(CyberiaAuthContext.Provider, { value, children: [
|
|
355
379
|
children,
|
|
@@ -375,8 +399,9 @@ function CyberiaAuthProvider({
|
|
|
375
399
|
CyberiaAuth,
|
|
376
400
|
{
|
|
377
401
|
backendUrl: backendBaseUrl,
|
|
378
|
-
apiToken,
|
|
402
|
+
apiToken: resolvedApiToken,
|
|
379
403
|
oauthRedirectUri,
|
|
404
|
+
theme,
|
|
380
405
|
initialMode: modalMode,
|
|
381
406
|
hideModeSwitch: false,
|
|
382
407
|
onAuthSuccess: (result) => {
|
|
@@ -435,7 +460,8 @@ function SignOutButton({ children }) {
|
|
|
435
460
|
return /* @__PURE__ */ jsx("button", { type: "button", onClick: signOut, children: children ?? "Sign out" });
|
|
436
461
|
}
|
|
437
462
|
function UserButton() {
|
|
438
|
-
const { user, signOut, openSignIn, openSignUp } = useCyberiaAuth();
|
|
463
|
+
const { user, signOut, openSignIn, openSignUp, theme } = useCyberiaAuth();
|
|
464
|
+
const palette = getThemePalette(theme);
|
|
439
465
|
const [open, setOpen] = useState(false);
|
|
440
466
|
const [manageOpen, setManageOpen] = useState(false);
|
|
441
467
|
const [tab, setTab] = useState("profile");
|
|
@@ -466,8 +492,9 @@ function UserButton() {
|
|
|
466
492
|
width: 36,
|
|
467
493
|
height: 36,
|
|
468
494
|
borderRadius: 999,
|
|
469
|
-
border:
|
|
470
|
-
background:
|
|
495
|
+
border: `1px solid ${palette.border}`,
|
|
496
|
+
background: palette.surface,
|
|
497
|
+
color: palette.text,
|
|
471
498
|
fontWeight: 700,
|
|
472
499
|
cursor: "pointer"
|
|
473
500
|
},
|
|
@@ -483,8 +510,8 @@ function UserButton() {
|
|
|
483
510
|
right: 0,
|
|
484
511
|
top: 42,
|
|
485
512
|
minWidth: 320,
|
|
486
|
-
background:
|
|
487
|
-
border:
|
|
513
|
+
background: palette.surface,
|
|
514
|
+
border: `1px solid ${palette.border}`,
|
|
488
515
|
borderRadius: 12,
|
|
489
516
|
boxShadow: "0 12px 24px rgba(0,0,0,0.08)",
|
|
490
517
|
padding: 0,
|
|
@@ -499,22 +526,22 @@ function UserButton() {
|
|
|
499
526
|
width: 44,
|
|
500
527
|
height: 44,
|
|
501
528
|
borderRadius: 999,
|
|
502
|
-
border:
|
|
529
|
+
border: `1px solid ${palette.border}`,
|
|
503
530
|
display: "grid",
|
|
504
531
|
placeItems: "center",
|
|
505
532
|
fontWeight: 700,
|
|
506
|
-
color:
|
|
507
|
-
background:
|
|
533
|
+
color: palette.text,
|
|
534
|
+
background: palette.surfaceAlt
|
|
508
535
|
},
|
|
509
536
|
children: initials
|
|
510
537
|
}
|
|
511
538
|
),
|
|
512
539
|
/* @__PURE__ */ jsxs("div", { style: { display: "grid" }, children: [
|
|
513
|
-
/* @__PURE__ */ jsx("strong", { style: { fontSize: 16, color:
|
|
514
|
-
/* @__PURE__ */ jsx("span", { style: { color:
|
|
540
|
+
/* @__PURE__ */ jsx("strong", { style: { fontSize: 16, color: palette.text, lineHeight: 1.2 }, children: profileName }),
|
|
541
|
+
/* @__PURE__ */ jsx("span", { style: { color: palette.text, fontSize: 14 }, children: profileEmail })
|
|
515
542
|
] })
|
|
516
543
|
] }),
|
|
517
|
-
/* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop:
|
|
544
|
+
/* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop: `1px solid ${palette.border}`, margin: 0 } }),
|
|
518
545
|
!user && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
519
546
|
/* @__PURE__ */ jsx(
|
|
520
547
|
"button",
|
|
@@ -568,9 +595,9 @@ function UserButton() {
|
|
|
568
595
|
}
|
|
569
596
|
)
|
|
570
597
|
] }),
|
|
571
|
-
/* @__PURE__ */ jsxs("div", { style: { borderTop:
|
|
598
|
+
/* @__PURE__ */ jsxs("div", { style: { borderTop: `1px solid ${palette.border}`, textAlign: "center", padding: "12px 10px", color: palette.textMuted, fontSize: 13 }, children: [
|
|
572
599
|
"Secured by ",
|
|
573
|
-
/* @__PURE__ */ jsx("strong", { children: "
|
|
600
|
+
/* @__PURE__ */ jsx("strong", { children: "Cyberia Auth" })
|
|
574
601
|
] })
|
|
575
602
|
]
|
|
576
603
|
}
|
|
@@ -595,9 +622,9 @@ function UserButton() {
|
|
|
595
622
|
width: "100%",
|
|
596
623
|
maxWidth: 940,
|
|
597
624
|
minHeight: 540,
|
|
598
|
-
background:
|
|
625
|
+
background: palette.surface,
|
|
599
626
|
borderRadius: 10,
|
|
600
|
-
border:
|
|
627
|
+
border: `1px solid ${palette.border}`,
|
|
601
628
|
display: "grid",
|
|
602
629
|
gridTemplateColumns: "220px 1fr",
|
|
603
630
|
overflow: "hidden"
|
|
@@ -608,15 +635,15 @@ function UserButton() {
|
|
|
608
635
|
"aside",
|
|
609
636
|
{
|
|
610
637
|
style: {
|
|
611
|
-
borderRight:
|
|
638
|
+
borderRight: `1px solid ${palette.border}`,
|
|
612
639
|
padding: 22,
|
|
613
|
-
background:
|
|
640
|
+
background: palette.surfaceAlt,
|
|
614
641
|
display: "flex",
|
|
615
642
|
flexDirection: "column"
|
|
616
643
|
},
|
|
617
644
|
children: [
|
|
618
|
-
/* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 30, color:
|
|
619
|
-
/* @__PURE__ */ jsx("p", { style: { marginTop: 6, color:
|
|
645
|
+
/* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 30, color: palette.text }, children: "Account" }),
|
|
646
|
+
/* @__PURE__ */ jsx("p", { style: { marginTop: 6, color: palette.textMuted, fontSize: 12 }, children: "Manage your account info." }),
|
|
620
647
|
/* @__PURE__ */ jsxs("div", { style: { marginTop: 20, display: "grid", gap: 8 }, children: [
|
|
621
648
|
/* @__PURE__ */ jsx(
|
|
622
649
|
"button",
|
|
@@ -625,8 +652,8 @@ function UserButton() {
|
|
|
625
652
|
onClick: () => setTab("profile"),
|
|
626
653
|
style: {
|
|
627
654
|
...tabButtonStyle,
|
|
628
|
-
background: tab === "profile" ? "#
|
|
629
|
-
color: tab === "profile" ? "#
|
|
655
|
+
background: tab === "profile" ? "#ffe8e8" : "transparent",
|
|
656
|
+
color: tab === "profile" ? "#d92828" : palette.textMuted
|
|
630
657
|
},
|
|
631
658
|
children: "Profile"
|
|
632
659
|
}
|
|
@@ -638,14 +665,14 @@ function UserButton() {
|
|
|
638
665
|
onClick: () => setTab("security"),
|
|
639
666
|
style: {
|
|
640
667
|
...tabButtonStyle,
|
|
641
|
-
background: tab === "security" ? "#
|
|
642
|
-
color: tab === "security" ? "#
|
|
668
|
+
background: tab === "security" ? "#ffe8e8" : "transparent",
|
|
669
|
+
color: tab === "security" ? "#d92828" : palette.textMuted
|
|
643
670
|
},
|
|
644
671
|
children: "Security"
|
|
645
672
|
}
|
|
646
673
|
)
|
|
647
674
|
] }),
|
|
648
|
-
/* @__PURE__ */ jsxs("div", { style: { marginTop: "auto", paddingTop: 24, color:
|
|
675
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "auto", paddingTop: 24, color: palette.textMuted, fontSize: 15 }, children: [
|
|
649
676
|
"Secure by ",
|
|
650
677
|
/* @__PURE__ */ jsx("strong", { children: "Cyberia Auth" })
|
|
651
678
|
] })
|
|
@@ -654,7 +681,7 @@ function UserButton() {
|
|
|
654
681
|
),
|
|
655
682
|
/* @__PURE__ */ jsxs("main", { style: { padding: 26 }, children: [
|
|
656
683
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
657
|
-
/* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: 22, color:
|
|
684
|
+
/* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: 22, color: palette.text }, children: tab === "profile" ? "Profile details" : "Security" }),
|
|
658
685
|
/* @__PURE__ */ jsx(
|
|
659
686
|
"button",
|
|
660
687
|
{
|
|
@@ -665,10 +692,10 @@ function UserButton() {
|
|
|
665
692
|
}
|
|
666
693
|
)
|
|
667
694
|
] }),
|
|
668
|
-
/* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop:
|
|
695
|
+
/* @__PURE__ */ jsx("hr", { style: { border: 0, borderTop: `1px solid ${palette.border}`, margin: "16px 0 20px" } }),
|
|
669
696
|
tab === "profile" && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 20 }, children: [
|
|
670
697
|
/* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
|
|
671
|
-
/* @__PURE__ */ jsx("div", { style: { color: "#
|
|
698
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Profile" }),
|
|
672
699
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
673
700
|
/* @__PURE__ */ jsx("div", { style: avatarLargeStyle, children: initials }),
|
|
674
701
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: profileName })
|
|
@@ -676,25 +703,25 @@ function UserButton() {
|
|
|
676
703
|
/* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Update profile" })
|
|
677
704
|
] }),
|
|
678
705
|
/* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
|
|
679
|
-
/* @__PURE__ */ jsx("div", { style: { color: "#
|
|
706
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Email addresses" }),
|
|
680
707
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: profileEmail }),
|
|
681
708
|
/* @__PURE__ */ jsx("span", { style: { color: "#6b7280", fontSize: 14 }, children: "Primary" })
|
|
682
709
|
] }),
|
|
683
710
|
/* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
|
|
684
|
-
/* @__PURE__ */ jsx("div", { style: { color: "#
|
|
711
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Connected accounts" }),
|
|
685
712
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 16 }, children: "Google / Microsoft" }),
|
|
686
713
|
/* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Connect account" })
|
|
687
714
|
] })
|
|
688
715
|
] }),
|
|
689
716
|
tab === "security" && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 20 }, children: [
|
|
690
717
|
/* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
|
|
691
|
-
/* @__PURE__ */ jsx("div", { style: { color: "#
|
|
718
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Password" }),
|
|
692
719
|
/* @__PURE__ */ jsx("div", {}),
|
|
693
720
|
/* @__PURE__ */ jsx("button", { type: "button", style: linkButtonStyle, children: "Set password" })
|
|
694
721
|
] }),
|
|
695
722
|
/* @__PURE__ */ jsxs("div", { style: { ...profileRowStyle, alignItems: "start" }, children: [
|
|
696
|
-
/* @__PURE__ */ jsx("div", { style: { color: "#
|
|
697
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: "#
|
|
723
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#c5c7ca", fontSize: 14 }, children: "Active devices" }),
|
|
724
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 14, color: "#c5c7ca", maxWidth: 430 }, children: userAgent }),
|
|
698
725
|
/* @__PURE__ */ jsx("span", { style: { color: "#6b7280", fontSize: 14 }, children: "This device" })
|
|
699
726
|
] }),
|
|
700
727
|
/* @__PURE__ */ jsxs("div", { style: profileRowStyle, children: [
|
|
@@ -748,25 +775,28 @@ var menuItemButtonStyle = {
|
|
|
748
775
|
background: "transparent",
|
|
749
776
|
cursor: "pointer"
|
|
750
777
|
};
|
|
751
|
-
var inputStyle = {
|
|
778
|
+
var inputStyle = (palette) => ({
|
|
752
779
|
width: "100%",
|
|
753
780
|
padding: 11,
|
|
754
781
|
borderRadius: 9,
|
|
755
|
-
border:
|
|
782
|
+
border: `1px solid ${palette.border}`,
|
|
783
|
+
background: palette.surface,
|
|
784
|
+
color: palette.text,
|
|
756
785
|
fontSize: 13
|
|
757
|
-
};
|
|
758
|
-
var fieldLabelStyle = {
|
|
786
|
+
});
|
|
787
|
+
var fieldLabelStyle = (palette) => ({
|
|
759
788
|
display: "grid",
|
|
760
789
|
gap: 6,
|
|
761
790
|
fontSize: 14,
|
|
762
|
-
color:
|
|
791
|
+
color: palette.text,
|
|
763
792
|
fontWeight: 600
|
|
764
|
-
};
|
|
765
|
-
var socialButtonStyle = {
|
|
766
|
-
border:
|
|
793
|
+
});
|
|
794
|
+
var socialButtonStyle = (palette) => ({
|
|
795
|
+
border: `1px solid ${palette.border}`,
|
|
767
796
|
borderRadius: 9,
|
|
768
797
|
padding: "10px 12px",
|
|
769
|
-
background:
|
|
798
|
+
background: palette.surface,
|
|
799
|
+
color: palette.text,
|
|
770
800
|
cursor: "pointer",
|
|
771
801
|
fontSize: 16,
|
|
772
802
|
fontWeight: 300,
|
|
@@ -774,7 +804,7 @@ var socialButtonStyle = {
|
|
|
774
804
|
alignItems: "center",
|
|
775
805
|
justifyContent: "center",
|
|
776
806
|
gap: 8
|
|
777
|
-
};
|
|
807
|
+
});
|
|
778
808
|
function GoogleIcon() {
|
|
779
809
|
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
810
|
/* @__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" }),
|
|
@@ -802,6 +832,53 @@ function resolveBackendBaseUrl(backendUrl) {
|
|
|
802
832
|
const candidate = backendUrl?.trim() || DEFAULT_BACKEND_URL;
|
|
803
833
|
return candidate.replace(/\/+$/, "");
|
|
804
834
|
}
|
|
835
|
+
function normalizeApiToken(apiToken) {
|
|
836
|
+
return apiToken.trim();
|
|
837
|
+
}
|
|
838
|
+
function getThemePalette(theme) {
|
|
839
|
+
if (theme === "dark") {
|
|
840
|
+
return {
|
|
841
|
+
surface: "#445364",
|
|
842
|
+
surfaceAlt: "#1f2937",
|
|
843
|
+
border: "#374151",
|
|
844
|
+
text: "#f9fafb",
|
|
845
|
+
textMuted: "#9ca3af"
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
return {
|
|
849
|
+
surface: "#ffffff",
|
|
850
|
+
surfaceAlt: "#fafafa",
|
|
851
|
+
border: "#e5e7eb",
|
|
852
|
+
text: "#111827",
|
|
853
|
+
textMuted: "#6b7280"
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
function useResolvedTheme(theme) {
|
|
857
|
+
const [resolvedTheme, setResolvedTheme] = useState(() => {
|
|
858
|
+
if (theme === "light" || theme === "dark") {
|
|
859
|
+
return theme;
|
|
860
|
+
}
|
|
861
|
+
if (typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
862
|
+
return "dark";
|
|
863
|
+
}
|
|
864
|
+
return "light";
|
|
865
|
+
});
|
|
866
|
+
useEffect(() => {
|
|
867
|
+
if (theme === "light" || theme === "dark") {
|
|
868
|
+
setResolvedTheme(theme);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
if (typeof window === "undefined") {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
875
|
+
const updateTheme = () => setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
876
|
+
updateTheme();
|
|
877
|
+
mediaQuery.addEventListener("change", updateTheme);
|
|
878
|
+
return () => mediaQuery.removeEventListener("change", updateTheme);
|
|
879
|
+
}, [theme]);
|
|
880
|
+
return resolvedTheme;
|
|
881
|
+
}
|
|
805
882
|
function getBrandingCacheKey(apiToken) {
|
|
806
883
|
return `cyberia_auth_branding:${apiToken}`;
|
|
807
884
|
}
|
|
@@ -848,7 +925,7 @@ var tabButtonStyle = {
|
|
|
848
925
|
};
|
|
849
926
|
var profileRowStyle = {
|
|
850
927
|
display: "grid",
|
|
851
|
-
gridTemplateColumns: "
|
|
928
|
+
gridTemplateColumns: "150px 1fr auto",
|
|
852
929
|
alignItems: "center",
|
|
853
930
|
gap: 12,
|
|
854
931
|
paddingBottom: 12,
|
|
@@ -868,7 +945,7 @@ var avatarLargeStyle = {
|
|
|
868
945
|
var linkButtonStyle = {
|
|
869
946
|
border: "none",
|
|
870
947
|
background: "transparent",
|
|
871
|
-
color: "#
|
|
948
|
+
color: "#d92828",
|
|
872
949
|
cursor: "pointer",
|
|
873
950
|
fontSize: 14
|
|
874
951
|
};
|