dauth-context-react 6.0.0 → 6.2.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.d.mts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +1086 -158
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1086 -158
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/DauthProfileModal.tsx +1102 -238
- package/src/api/dauth.api.ts +73 -0
- package/src/api/interfaces/dauth.api.responses.ts +36 -0
- package/src/index.tsx +33 -1
- package/src/initialDauthState.ts +3 -0
- package/src/interfaces.ts +31 -0
- package/src/reducer/dauth.actions.ts +91 -0
- package/src/webauthn.ts +111 -0
package/dist/index.mjs
CHANGED
|
@@ -21,7 +21,10 @@ var initialDauthState = {
|
|
|
21
21
|
logout: () => {
|
|
22
22
|
},
|
|
23
23
|
updateUser: () => Promise.resolve(false),
|
|
24
|
-
deleteAccount: () => Promise.resolve(false)
|
|
24
|
+
deleteAccount: () => Promise.resolve(false),
|
|
25
|
+
getPasskeyCredentials: () => Promise.resolve([]),
|
|
26
|
+
registerPasskey: () => Promise.resolve(null),
|
|
27
|
+
deletePasskeyCredential: () => Promise.resolve(false)
|
|
25
28
|
};
|
|
26
29
|
var initialDauthState_default = initialDauthState;
|
|
27
30
|
|
|
@@ -128,6 +131,134 @@ async function deleteAccountAPI(basePath) {
|
|
|
128
131
|
const data = await response.json();
|
|
129
132
|
return { response, data };
|
|
130
133
|
}
|
|
134
|
+
async function getPasskeyCredentialsAPI(basePath) {
|
|
135
|
+
const response = await fetch(
|
|
136
|
+
`${basePath}/passkey/credentials`,
|
|
137
|
+
{
|
|
138
|
+
method: "GET",
|
|
139
|
+
headers: { "X-CSRF-Token": getCsrfToken() },
|
|
140
|
+
credentials: "include"
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
const data = await response.json();
|
|
144
|
+
return { response, data };
|
|
145
|
+
}
|
|
146
|
+
async function startPasskeyRegistrationAPI(basePath) {
|
|
147
|
+
const response = await fetch(
|
|
148
|
+
`${basePath}/passkey/register/start`,
|
|
149
|
+
{
|
|
150
|
+
method: "POST",
|
|
151
|
+
headers: {
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
"X-CSRF-Token": getCsrfToken()
|
|
154
|
+
},
|
|
155
|
+
credentials: "include"
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
const data = await response.json();
|
|
159
|
+
return { response, data };
|
|
160
|
+
}
|
|
161
|
+
async function finishPasskeyRegistrationAPI(basePath, body) {
|
|
162
|
+
const response = await fetch(
|
|
163
|
+
`${basePath}/passkey/register/finish`,
|
|
164
|
+
{
|
|
165
|
+
method: "POST",
|
|
166
|
+
headers: {
|
|
167
|
+
"Content-Type": "application/json",
|
|
168
|
+
"X-CSRF-Token": getCsrfToken()
|
|
169
|
+
},
|
|
170
|
+
credentials: "include",
|
|
171
|
+
body: JSON.stringify(body)
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
const data = await response.json();
|
|
175
|
+
return { response, data };
|
|
176
|
+
}
|
|
177
|
+
async function deletePasskeyCredentialAPI(basePath, credentialId) {
|
|
178
|
+
const response = await fetch(
|
|
179
|
+
`${basePath}/passkey/credentials/${credentialId}`,
|
|
180
|
+
{
|
|
181
|
+
method: "DELETE",
|
|
182
|
+
headers: { "X-CSRF-Token": getCsrfToken() },
|
|
183
|
+
credentials: "include"
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
const data = await response.json();
|
|
187
|
+
return { response, data };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/webauthn.ts
|
|
191
|
+
function base64urlToBuffer(base64url) {
|
|
192
|
+
const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
193
|
+
const pad = base64.length % 4;
|
|
194
|
+
const padded = pad ? base64 + "=".repeat(4 - pad) : base64;
|
|
195
|
+
const binary = atob(padded);
|
|
196
|
+
const bytes = new Uint8Array(binary.length);
|
|
197
|
+
for (let i = 0; i < binary.length; i++) {
|
|
198
|
+
bytes[i] = binary.charCodeAt(i);
|
|
199
|
+
}
|
|
200
|
+
return bytes.buffer;
|
|
201
|
+
}
|
|
202
|
+
function bufferToBase64url(buffer) {
|
|
203
|
+
const bytes = new Uint8Array(buffer);
|
|
204
|
+
let binary = "";
|
|
205
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
206
|
+
binary += String.fromCharCode(bytes[i]);
|
|
207
|
+
}
|
|
208
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
209
|
+
}
|
|
210
|
+
async function createPasskeyCredential(options) {
|
|
211
|
+
const publicKey = {
|
|
212
|
+
...options,
|
|
213
|
+
challenge: base64urlToBuffer(options.challenge),
|
|
214
|
+
user: {
|
|
215
|
+
...options.user,
|
|
216
|
+
id: base64urlToBuffer(options.user.id)
|
|
217
|
+
},
|
|
218
|
+
excludeCredentials: (options.excludeCredentials ?? []).map(
|
|
219
|
+
(c) => ({
|
|
220
|
+
...c,
|
|
221
|
+
id: base64urlToBuffer(c.id)
|
|
222
|
+
})
|
|
223
|
+
)
|
|
224
|
+
};
|
|
225
|
+
const credential = await navigator.credentials.create({
|
|
226
|
+
publicKey
|
|
227
|
+
});
|
|
228
|
+
if (!credential) {
|
|
229
|
+
throw new Error("Passkey registration was cancelled");
|
|
230
|
+
}
|
|
231
|
+
const attestation = credential.response;
|
|
232
|
+
return {
|
|
233
|
+
id: credential.id,
|
|
234
|
+
rawId: bufferToBase64url(credential.rawId),
|
|
235
|
+
type: credential.type,
|
|
236
|
+
response: {
|
|
237
|
+
clientDataJSON: bufferToBase64url(
|
|
238
|
+
attestation.clientDataJSON
|
|
239
|
+
),
|
|
240
|
+
attestationObject: bufferToBase64url(
|
|
241
|
+
attestation.attestationObject
|
|
242
|
+
),
|
|
243
|
+
...attestation.getTransports ? { transports: attestation.getTransports() } : {},
|
|
244
|
+
...attestation.getPublicKeyAlgorithm ? {
|
|
245
|
+
publicKeyAlgorithm: attestation.getPublicKeyAlgorithm()
|
|
246
|
+
} : {},
|
|
247
|
+
...attestation.getPublicKey ? {
|
|
248
|
+
publicKey: bufferToBase64url(
|
|
249
|
+
attestation.getPublicKey()
|
|
250
|
+
)
|
|
251
|
+
} : {},
|
|
252
|
+
...attestation.getAuthenticatorData ? {
|
|
253
|
+
authenticatorData: bufferToBase64url(
|
|
254
|
+
attestation.getAuthenticatorData()
|
|
255
|
+
)
|
|
256
|
+
} : {}
|
|
257
|
+
},
|
|
258
|
+
clientExtensionResults: credential.getClientExtensionResults(),
|
|
259
|
+
authenticatorAttachment: credential.authenticatorAttachment ?? void 0
|
|
260
|
+
};
|
|
261
|
+
}
|
|
131
262
|
|
|
132
263
|
// src/reducer/dauth.actions.ts
|
|
133
264
|
async function exchangeCodeAction(ctx, code) {
|
|
@@ -251,6 +382,65 @@ async function deleteAccountAction(ctx) {
|
|
|
251
382
|
return false;
|
|
252
383
|
}
|
|
253
384
|
}
|
|
385
|
+
async function getPasskeyCredentialsAction(ctx) {
|
|
386
|
+
const { authProxyPath, onError } = ctx;
|
|
387
|
+
try {
|
|
388
|
+
const result = await getPasskeyCredentialsAPI(authProxyPath);
|
|
389
|
+
if (result.response.status === 200) {
|
|
390
|
+
return result.data.credentials ?? [];
|
|
391
|
+
}
|
|
392
|
+
return [];
|
|
393
|
+
} catch (error) {
|
|
394
|
+
onError(
|
|
395
|
+
error instanceof Error ? error : new Error("Get passkey credentials error")
|
|
396
|
+
);
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
async function registerPasskeyAction(ctx, name) {
|
|
401
|
+
const { authProxyPath, onError } = ctx;
|
|
402
|
+
try {
|
|
403
|
+
const startResult = await startPasskeyRegistrationAPI(authProxyPath);
|
|
404
|
+
if (startResult.response.status !== 200) {
|
|
405
|
+
onError(new Error("Failed to start passkey registration"));
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
const credential = await createPasskeyCredential(
|
|
409
|
+
startResult.data
|
|
410
|
+
);
|
|
411
|
+
const finishResult = await finishPasskeyRegistrationAPI(
|
|
412
|
+
authProxyPath,
|
|
413
|
+
{ credential, name }
|
|
414
|
+
);
|
|
415
|
+
if (finishResult.response.status === 200 || finishResult.response.status === 201) {
|
|
416
|
+
return finishResult.data.credential;
|
|
417
|
+
}
|
|
418
|
+
onError(
|
|
419
|
+
new Error("Failed to finish passkey registration")
|
|
420
|
+
);
|
|
421
|
+
return null;
|
|
422
|
+
} catch (error) {
|
|
423
|
+
onError(
|
|
424
|
+
error instanceof Error ? error : new Error("Passkey registration error")
|
|
425
|
+
);
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async function deletePasskeyCredentialAction(ctx, credentialId) {
|
|
430
|
+
const { authProxyPath, onError } = ctx;
|
|
431
|
+
try {
|
|
432
|
+
const result = await deletePasskeyCredentialAPI(
|
|
433
|
+
authProxyPath,
|
|
434
|
+
credentialId
|
|
435
|
+
);
|
|
436
|
+
return result.response.status === 200;
|
|
437
|
+
} catch (error) {
|
|
438
|
+
onError(
|
|
439
|
+
error instanceof Error ? error : new Error("Delete passkey error")
|
|
440
|
+
);
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
254
444
|
var resetUser = (dispatch) => {
|
|
255
445
|
return dispatch({
|
|
256
446
|
type: LOGIN,
|
|
@@ -348,6 +538,107 @@ function IconBack() {
|
|
|
348
538
|
}
|
|
349
539
|
);
|
|
350
540
|
}
|
|
541
|
+
function IconFingerprint() {
|
|
542
|
+
return /* @__PURE__ */ jsxs(
|
|
543
|
+
"svg",
|
|
544
|
+
{
|
|
545
|
+
width: "16",
|
|
546
|
+
height: "16",
|
|
547
|
+
viewBox: "0 0 24 24",
|
|
548
|
+
fill: "none",
|
|
549
|
+
stroke: "currentColor",
|
|
550
|
+
strokeWidth: "2",
|
|
551
|
+
strokeLinecap: "round",
|
|
552
|
+
strokeLinejoin: "round",
|
|
553
|
+
children: [
|
|
554
|
+
/* @__PURE__ */ jsx("path", { d: "M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4" }),
|
|
555
|
+
/* @__PURE__ */ jsx("path", { d: "M14 13.12c0 2.38 0 6.38-1 8.88" }),
|
|
556
|
+
/* @__PURE__ */ jsx("path", { d: "M17.29 21.02c.12-.6.43-2.3.5-3.02" }),
|
|
557
|
+
/* @__PURE__ */ jsx("path", { d: "M2 12a10 10 0 0 1 18-6" }),
|
|
558
|
+
/* @__PURE__ */ jsx("path", { d: "M2 16h.01" }),
|
|
559
|
+
/* @__PURE__ */ jsx("path", { d: "M21.8 16c.2-2 .131-5.354 0-6" }),
|
|
560
|
+
/* @__PURE__ */ jsx("path", { d: "M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2" }),
|
|
561
|
+
/* @__PURE__ */ jsx("path", { d: "M8.65 22c.21-.66.45-1.32.57-2" }),
|
|
562
|
+
/* @__PURE__ */ jsx("path", { d: "M9 6.8a6 6 0 0 1 9 5.2v2" })
|
|
563
|
+
]
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
function IconShield() {
|
|
568
|
+
return /* @__PURE__ */ jsx(
|
|
569
|
+
"svg",
|
|
570
|
+
{
|
|
571
|
+
width: "20",
|
|
572
|
+
height: "20",
|
|
573
|
+
viewBox: "0 0 24 24",
|
|
574
|
+
fill: "none",
|
|
575
|
+
stroke: "currentColor",
|
|
576
|
+
strokeWidth: "2",
|
|
577
|
+
strokeLinecap: "round",
|
|
578
|
+
strokeLinejoin: "round",
|
|
579
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" })
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
function IconTrash() {
|
|
584
|
+
return /* @__PURE__ */ jsxs(
|
|
585
|
+
"svg",
|
|
586
|
+
{
|
|
587
|
+
width: "14",
|
|
588
|
+
height: "14",
|
|
589
|
+
viewBox: "0 0 24 24",
|
|
590
|
+
fill: "none",
|
|
591
|
+
stroke: "currentColor",
|
|
592
|
+
strokeWidth: "2",
|
|
593
|
+
strokeLinecap: "round",
|
|
594
|
+
strokeLinejoin: "round",
|
|
595
|
+
children: [
|
|
596
|
+
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
597
|
+
/* @__PURE__ */ jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
|
|
598
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
function IconLogOut() {
|
|
604
|
+
return /* @__PURE__ */ jsxs(
|
|
605
|
+
"svg",
|
|
606
|
+
{
|
|
607
|
+
width: "16",
|
|
608
|
+
height: "16",
|
|
609
|
+
viewBox: "0 0 24 24",
|
|
610
|
+
fill: "none",
|
|
611
|
+
stroke: "currentColor",
|
|
612
|
+
strokeWidth: "2",
|
|
613
|
+
strokeLinecap: "round",
|
|
614
|
+
strokeLinejoin: "round",
|
|
615
|
+
children: [
|
|
616
|
+
/* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
|
|
617
|
+
/* @__PURE__ */ jsx("polyline", { points: "16 17 21 12 16 7" }),
|
|
618
|
+
/* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
|
|
619
|
+
]
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
function IconCamera() {
|
|
624
|
+
return /* @__PURE__ */ jsxs(
|
|
625
|
+
"svg",
|
|
626
|
+
{
|
|
627
|
+
width: "14",
|
|
628
|
+
height: "14",
|
|
629
|
+
viewBox: "0 0 24 24",
|
|
630
|
+
fill: "none",
|
|
631
|
+
stroke: "currentColor",
|
|
632
|
+
strokeWidth: "2",
|
|
633
|
+
strokeLinecap: "round",
|
|
634
|
+
strokeLinejoin: "round",
|
|
635
|
+
children: [
|
|
636
|
+
/* @__PURE__ */ jsx("path", { d: "M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z" }),
|
|
637
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "13", r: "3" })
|
|
638
|
+
]
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
}
|
|
351
642
|
function Spinner() {
|
|
352
643
|
return /* @__PURE__ */ jsx("span", { style: spinnerStyle, "aria-hidden": "true" });
|
|
353
644
|
}
|
|
@@ -375,7 +666,10 @@ function useModalAnimation(open) {
|
|
|
375
666
|
}
|
|
376
667
|
if (phase === "entered" || phase === "entering") {
|
|
377
668
|
setPhase("exiting");
|
|
378
|
-
const timer = setTimeout(
|
|
669
|
+
const timer = setTimeout(
|
|
670
|
+
() => setPhase("exited"),
|
|
671
|
+
MOBILE_TRANSITION_MS
|
|
672
|
+
);
|
|
379
673
|
return () => clearTimeout(timer);
|
|
380
674
|
}
|
|
381
675
|
return void 0;
|
|
@@ -443,11 +737,27 @@ function useScrollLock(active) {
|
|
|
443
737
|
};
|
|
444
738
|
}, [active]);
|
|
445
739
|
}
|
|
446
|
-
function DauthProfileModal({
|
|
447
|
-
|
|
740
|
+
function DauthProfileModal({
|
|
741
|
+
open,
|
|
742
|
+
onClose,
|
|
743
|
+
onAvatarUpload
|
|
744
|
+
}) {
|
|
745
|
+
const {
|
|
746
|
+
user,
|
|
747
|
+
domain,
|
|
748
|
+
updateUser,
|
|
749
|
+
deleteAccount,
|
|
750
|
+
logout,
|
|
751
|
+
getPasskeyCredentials,
|
|
752
|
+
registerPasskey,
|
|
753
|
+
deletePasskeyCredential
|
|
754
|
+
} = useDauth();
|
|
448
755
|
const isDesktop = useMediaQuery("(min-width: 641px)");
|
|
449
756
|
const phase = useModalAnimation(open);
|
|
450
757
|
const modalRef = useRef(null);
|
|
758
|
+
const avatarInputRef = useRef(null);
|
|
759
|
+
const showSecurity = domain.authMethods?.passkey === true;
|
|
760
|
+
const [activeTab, setActiveTab] = useState("profile");
|
|
451
761
|
const [name, setName] = useState("");
|
|
452
762
|
const [lastname, setLastname] = useState("");
|
|
453
763
|
const [nickname, setNickname] = useState("");
|
|
@@ -458,6 +768,13 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
458
768
|
const [showDelete, setShowDelete] = useState(false);
|
|
459
769
|
const [deleteText, setDeleteText] = useState("");
|
|
460
770
|
const [deleting, setDeleting] = useState(false);
|
|
771
|
+
const [credentials, setCredentials] = useState([]);
|
|
772
|
+
const [loadingCreds, setLoadingCreds] = useState(false);
|
|
773
|
+
const [showRegister, setShowRegister] = useState(false);
|
|
774
|
+
const [passkeyName, setPasskeyName] = useState("");
|
|
775
|
+
const [registering, setRegistering] = useState(false);
|
|
776
|
+
const [passkeyStatus, setPasskeyStatus] = useState(null);
|
|
777
|
+
const [uploadingAvatar, setUploadingAvatar] = useState(false);
|
|
461
778
|
useEffect(() => {
|
|
462
779
|
if (open && user?._id && !populated) {
|
|
463
780
|
setName(user.name || "");
|
|
@@ -471,13 +788,36 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
471
788
|
setStatus(null);
|
|
472
789
|
setShowDelete(false);
|
|
473
790
|
setDeleteText("");
|
|
791
|
+
setActiveTab("profile");
|
|
792
|
+
setPasskeyStatus(null);
|
|
793
|
+
setShowRegister(false);
|
|
794
|
+
setPasskeyName("");
|
|
474
795
|
}
|
|
475
796
|
}, [open, user, populated]);
|
|
797
|
+
useEffect(() => {
|
|
798
|
+
if (activeTab !== "security" || !showSecurity) return;
|
|
799
|
+
setLoadingCreds(true);
|
|
800
|
+
getPasskeyCredentials().then((creds) => {
|
|
801
|
+
setCredentials(creds);
|
|
802
|
+
setLoadingCreds(false);
|
|
803
|
+
});
|
|
804
|
+
}, [activeTab, showSecurity, getPasskeyCredentials]);
|
|
476
805
|
useEffect(() => {
|
|
477
806
|
if (status?.type !== "success") return;
|
|
478
|
-
const timer = setTimeout(
|
|
807
|
+
const timer = setTimeout(
|
|
808
|
+
() => setStatus(null),
|
|
809
|
+
SUCCESS_TIMEOUT_MS
|
|
810
|
+
);
|
|
479
811
|
return () => clearTimeout(timer);
|
|
480
812
|
}, [status]);
|
|
813
|
+
useEffect(() => {
|
|
814
|
+
if (passkeyStatus?.type !== "success") return;
|
|
815
|
+
const timer = setTimeout(
|
|
816
|
+
() => setPasskeyStatus(null),
|
|
817
|
+
SUCCESS_TIMEOUT_MS
|
|
818
|
+
);
|
|
819
|
+
return () => clearTimeout(timer);
|
|
820
|
+
}, [passkeyStatus]);
|
|
481
821
|
useFocusTrap(modalRef, phase === "entered", onClose);
|
|
482
822
|
useScrollLock(phase !== "exited");
|
|
483
823
|
const hasField = useCallback(
|
|
@@ -529,6 +869,90 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
529
869
|
setDeleteText("");
|
|
530
870
|
}
|
|
531
871
|
}, [deleteAccount, onClose]);
|
|
872
|
+
const handleLanguage = useCallback(
|
|
873
|
+
async (lang) => {
|
|
874
|
+
await updateUser({ language: lang });
|
|
875
|
+
},
|
|
876
|
+
[updateUser]
|
|
877
|
+
);
|
|
878
|
+
const handleRegisterPasskey = useCallback(async () => {
|
|
879
|
+
setRegistering(true);
|
|
880
|
+
setPasskeyStatus(null);
|
|
881
|
+
const cred = await registerPasskey(
|
|
882
|
+
passkeyName || void 0
|
|
883
|
+
);
|
|
884
|
+
setRegistering(false);
|
|
885
|
+
if (cred) {
|
|
886
|
+
setCredentials((prev) => [...prev, cred]);
|
|
887
|
+
setPasskeyName("");
|
|
888
|
+
setShowRegister(false);
|
|
889
|
+
setPasskeyStatus({
|
|
890
|
+
type: "success",
|
|
891
|
+
message: "Passkey registered successfully"
|
|
892
|
+
});
|
|
893
|
+
} else {
|
|
894
|
+
setPasskeyStatus({
|
|
895
|
+
type: "error",
|
|
896
|
+
message: "Failed to register passkey"
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}, [passkeyName, registerPasskey]);
|
|
900
|
+
const handleDeletePasskey = useCallback(
|
|
901
|
+
async (credentialId) => {
|
|
902
|
+
const ok = await deletePasskeyCredential(credentialId);
|
|
903
|
+
if (ok) {
|
|
904
|
+
setCredentials(
|
|
905
|
+
(prev) => prev.filter((c) => c._id !== credentialId)
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
[deletePasskeyCredential]
|
|
910
|
+
);
|
|
911
|
+
const handleAvatarClick = useCallback(() => {
|
|
912
|
+
if (onAvatarUpload) {
|
|
913
|
+
avatarInputRef.current?.click();
|
|
914
|
+
}
|
|
915
|
+
}, [onAvatarUpload]);
|
|
916
|
+
const handleAvatarChange = useCallback(
|
|
917
|
+
async (e) => {
|
|
918
|
+
const file = e.target.files?.[0];
|
|
919
|
+
if (!file || !onAvatarUpload) return;
|
|
920
|
+
setUploadingAvatar(true);
|
|
921
|
+
try {
|
|
922
|
+
const url = await onAvatarUpload(file);
|
|
923
|
+
if (url) {
|
|
924
|
+
await updateUser({ avatar: url });
|
|
925
|
+
}
|
|
926
|
+
} catch {
|
|
927
|
+
}
|
|
928
|
+
setUploadingAvatar(false);
|
|
929
|
+
if (avatarInputRef.current) {
|
|
930
|
+
avatarInputRef.current.value = "";
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
[onAvatarUpload, updateUser]
|
|
934
|
+
);
|
|
935
|
+
const handleSignOut = useCallback(() => {
|
|
936
|
+
logout();
|
|
937
|
+
onClose();
|
|
938
|
+
}, [logout, onClose]);
|
|
939
|
+
const themeVars = useMemo(() => {
|
|
940
|
+
const t = domain.modalTheme;
|
|
941
|
+
if (!t) return {};
|
|
942
|
+
const vars = {};
|
|
943
|
+
if (t.accent) vars["--dauth-accent"] = t.accent;
|
|
944
|
+
if (t.accentHover)
|
|
945
|
+
vars["--dauth-accent-hover"] = t.accentHover;
|
|
946
|
+
if (t.surface) vars["--dauth-surface"] = t.surface;
|
|
947
|
+
if (t.surfaceHover)
|
|
948
|
+
vars["--dauth-surface-hover"] = t.surfaceHover;
|
|
949
|
+
if (t.textPrimary)
|
|
950
|
+
vars["--dauth-text-primary"] = t.textPrimary;
|
|
951
|
+
if (t.textSecondary)
|
|
952
|
+
vars["--dauth-text-secondary"] = t.textSecondary;
|
|
953
|
+
if (t.border) vars["--dauth-border"] = t.border;
|
|
954
|
+
return vars;
|
|
955
|
+
}, [domain.modalTheme]);
|
|
532
956
|
if (phase === "exited") return null;
|
|
533
957
|
const dur = isDesktop ? TRANSITION_MS : MOBILE_TRANSITION_MS;
|
|
534
958
|
const easing = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
@@ -576,6 +1000,11 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
576
1000
|
transition: `transform ${dur}ms ${easing}`
|
|
577
1001
|
};
|
|
578
1002
|
const avatarInitial = (user.name || user.email || "?").charAt(0).toUpperCase();
|
|
1003
|
+
const tabs = [
|
|
1004
|
+
{ key: "profile", label: "Profile" },
|
|
1005
|
+
...showSecurity ? [{ key: "security", label: "Security" }] : [],
|
|
1006
|
+
{ key: "account", label: "Account" }
|
|
1007
|
+
];
|
|
579
1008
|
return createPortal(
|
|
580
1009
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
581
1010
|
/* @__PURE__ */ jsx(
|
|
@@ -589,7 +1018,7 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
589
1018
|
/* @__PURE__ */ jsx(
|
|
590
1019
|
"div",
|
|
591
1020
|
{
|
|
592
|
-
style: backdrop,
|
|
1021
|
+
style: { ...backdrop, ...themeVars },
|
|
593
1022
|
onClick: isDesktop ? onClose : void 0,
|
|
594
1023
|
"data-testid": "dauth-profile-backdrop",
|
|
595
1024
|
children: /* @__PURE__ */ jsxs(
|
|
@@ -619,191 +1048,542 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
619
1048
|
/* @__PURE__ */ jsx("h2", { id: "dauth-profile-title", style: titleStyle, children: "Your Profile" }),
|
|
620
1049
|
/* @__PURE__ */ jsx("div", { style: { width: 36 } })
|
|
621
1050
|
] }),
|
|
1051
|
+
/* @__PURE__ */ jsx("div", { style: tabBar, role: "tablist", children: tabs.map((t) => /* @__PURE__ */ jsx(
|
|
1052
|
+
"button",
|
|
1053
|
+
{
|
|
1054
|
+
role: "tab",
|
|
1055
|
+
type: "button",
|
|
1056
|
+
"aria-selected": activeTab === t.key,
|
|
1057
|
+
style: {
|
|
1058
|
+
...tabBtn,
|
|
1059
|
+
color: activeTab === t.key ? "var(--dauth-accent, #6366f1)" : "var(--dauth-text-secondary, #a1a1aa)",
|
|
1060
|
+
borderBottomColor: activeTab === t.key ? "var(--dauth-accent, #6366f1)" : "transparent"
|
|
1061
|
+
},
|
|
1062
|
+
onClick: () => setActiveTab(t.key),
|
|
1063
|
+
children: t.label
|
|
1064
|
+
},
|
|
1065
|
+
t.key
|
|
1066
|
+
)) }),
|
|
622
1067
|
/* @__PURE__ */ jsxs("div", { style: bodyStyle, children: [
|
|
623
|
-
/* @__PURE__ */ jsxs(
|
|
624
|
-
/* @__PURE__ */
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
src: user.avatar.url,
|
|
628
|
-
alt: "",
|
|
629
|
-
style: {
|
|
630
|
-
width: "100%",
|
|
631
|
-
height: "100%",
|
|
632
|
-
objectFit: "cover"
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
) : avatarInitial }),
|
|
636
|
-
/* @__PURE__ */ jsx("div", { style: emailText, children: user.email })
|
|
637
|
-
] }),
|
|
638
|
-
status && /* @__PURE__ */ jsx(
|
|
639
|
-
"div",
|
|
640
|
-
{
|
|
641
|
-
role: "status",
|
|
642
|
-
"aria-live": "polite",
|
|
643
|
-
style: statusMsg(status.type),
|
|
644
|
-
children: status.message
|
|
645
|
-
}
|
|
646
|
-
),
|
|
647
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
648
|
-
/* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
649
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "dauth-name", style: label, children: "Name *" }),
|
|
650
|
-
/* @__PURE__ */ jsx(
|
|
651
|
-
"input",
|
|
1068
|
+
activeTab === "profile" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1069
|
+
/* @__PURE__ */ jsxs("div", { style: avatarSection, children: [
|
|
1070
|
+
/* @__PURE__ */ jsxs(
|
|
1071
|
+
"div",
|
|
652
1072
|
{
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
1073
|
+
style: {
|
|
1074
|
+
...avatarCircle,
|
|
1075
|
+
cursor: onAvatarUpload ? "pointer" : "default",
|
|
1076
|
+
position: "relative"
|
|
1077
|
+
},
|
|
1078
|
+
onClick: handleAvatarClick,
|
|
1079
|
+
children: [
|
|
1080
|
+
uploadingAvatar ? /* @__PURE__ */ jsx(Spinner, {}) : user.avatar?.url ? /* @__PURE__ */ jsx(
|
|
1081
|
+
"img",
|
|
1082
|
+
{
|
|
1083
|
+
src: user.avatar.url,
|
|
1084
|
+
alt: "",
|
|
1085
|
+
style: {
|
|
1086
|
+
width: "100%",
|
|
1087
|
+
height: "100%",
|
|
1088
|
+
objectFit: "cover"
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
) : avatarInitial,
|
|
1092
|
+
onAvatarUpload && !uploadingAvatar && /* @__PURE__ */ jsx("div", { style: avatarOverlay, children: /* @__PURE__ */ jsx(IconCamera, {}) })
|
|
1093
|
+
]
|
|
662
1094
|
}
|
|
663
|
-
)
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
/* @__PURE__ */ jsxs("label", { htmlFor: "dauth-lastname", style: label, children: [
|
|
667
|
-
"Last name",
|
|
668
|
-
isRequired("lastname") ? " *" : ""
|
|
669
|
-
] }),
|
|
670
|
-
/* @__PURE__ */ jsx(
|
|
1095
|
+
),
|
|
1096
|
+
/* @__PURE__ */ jsx("div", { style: emailText, children: user.email }),
|
|
1097
|
+
onAvatarUpload && /* @__PURE__ */ jsx(
|
|
671
1098
|
"input",
|
|
672
1099
|
{
|
|
673
|
-
|
|
674
|
-
type: "
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
disabled: saving,
|
|
679
|
-
style: input,
|
|
680
|
-
onFocus: inputFocusHandler,
|
|
681
|
-
onBlur: inputBlurHandler
|
|
1100
|
+
ref: avatarInputRef,
|
|
1101
|
+
type: "file",
|
|
1102
|
+
accept: "image/*",
|
|
1103
|
+
style: { display: "none" },
|
|
1104
|
+
onChange: handleAvatarChange
|
|
682
1105
|
}
|
|
683
1106
|
)
|
|
684
1107
|
] }),
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
1108
|
+
status && /* @__PURE__ */ jsx(
|
|
1109
|
+
"div",
|
|
1110
|
+
{
|
|
1111
|
+
role: "status",
|
|
1112
|
+
"aria-live": "polite",
|
|
1113
|
+
style: statusMsg(status.type),
|
|
1114
|
+
children: status.message
|
|
1115
|
+
}
|
|
1116
|
+
),
|
|
1117
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1118
|
+
/* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1119
|
+
/* @__PURE__ */ jsx(
|
|
1120
|
+
"label",
|
|
1121
|
+
{
|
|
1122
|
+
htmlFor: "dauth-name",
|
|
1123
|
+
style: label,
|
|
1124
|
+
children: "Name *"
|
|
1125
|
+
}
|
|
1126
|
+
),
|
|
1127
|
+
/* @__PURE__ */ jsx(
|
|
1128
|
+
"input",
|
|
1129
|
+
{
|
|
1130
|
+
id: "dauth-name",
|
|
1131
|
+
type: "text",
|
|
1132
|
+
value: name,
|
|
1133
|
+
onChange: (e) => setName(e.target.value),
|
|
1134
|
+
placeholder: "Your name",
|
|
1135
|
+
disabled: saving,
|
|
1136
|
+
style: input,
|
|
1137
|
+
onFocus: inputFocusHandler,
|
|
1138
|
+
onBlur: inputBlurHandler
|
|
1139
|
+
}
|
|
1140
|
+
)
|
|
689
1141
|
] }),
|
|
690
|
-
/* @__PURE__ */
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1142
|
+
hasField("lastname") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1143
|
+
/* @__PURE__ */ jsxs(
|
|
1144
|
+
"label",
|
|
1145
|
+
{
|
|
1146
|
+
htmlFor: "dauth-lastname",
|
|
1147
|
+
style: label,
|
|
1148
|
+
children: [
|
|
1149
|
+
"Last name",
|
|
1150
|
+
isRequired("lastname") ? " *" : ""
|
|
1151
|
+
]
|
|
1152
|
+
}
|
|
1153
|
+
),
|
|
1154
|
+
/* @__PURE__ */ jsx(
|
|
1155
|
+
"input",
|
|
1156
|
+
{
|
|
1157
|
+
id: "dauth-lastname",
|
|
1158
|
+
type: "text",
|
|
1159
|
+
value: lastname,
|
|
1160
|
+
onChange: (e) => setLastname(e.target.value),
|
|
1161
|
+
placeholder: "Your last name",
|
|
1162
|
+
disabled: saving,
|
|
1163
|
+
style: input,
|
|
1164
|
+
onFocus: inputFocusHandler,
|
|
1165
|
+
onBlur: inputBlurHandler
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
709
1168
|
] }),
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
|
|
1169
|
+
hasField("nickname") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1170
|
+
/* @__PURE__ */ jsxs(
|
|
1171
|
+
"label",
|
|
1172
|
+
{
|
|
1173
|
+
htmlFor: "dauth-nickname",
|
|
1174
|
+
style: label,
|
|
1175
|
+
children: [
|
|
1176
|
+
"Nickname",
|
|
1177
|
+
isRequired("nickname") ? " *" : ""
|
|
1178
|
+
]
|
|
1179
|
+
}
|
|
1180
|
+
),
|
|
1181
|
+
/* @__PURE__ */ jsx(
|
|
1182
|
+
"input",
|
|
1183
|
+
{
|
|
1184
|
+
id: "dauth-nickname",
|
|
1185
|
+
type: "text",
|
|
1186
|
+
value: nickname,
|
|
1187
|
+
onChange: (e) => setNickname(e.target.value),
|
|
1188
|
+
placeholder: "Choose a nickname",
|
|
1189
|
+
disabled: saving,
|
|
1190
|
+
style: input,
|
|
1191
|
+
onFocus: inputFocusHandler,
|
|
1192
|
+
onBlur: inputBlurHandler
|
|
1193
|
+
}
|
|
1194
|
+
)
|
|
1195
|
+
] }),
|
|
1196
|
+
hasField("country") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1197
|
+
/* @__PURE__ */ jsxs(
|
|
1198
|
+
"label",
|
|
1199
|
+
{
|
|
1200
|
+
htmlFor: "dauth-country",
|
|
1201
|
+
style: label,
|
|
1202
|
+
children: [
|
|
1203
|
+
"Country",
|
|
1204
|
+
isRequired("country") ? " *" : ""
|
|
1205
|
+
]
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
1208
|
+
/* @__PURE__ */ jsx(
|
|
1209
|
+
"input",
|
|
1210
|
+
{
|
|
1211
|
+
id: "dauth-country",
|
|
1212
|
+
type: "text",
|
|
1213
|
+
value: country,
|
|
1214
|
+
onChange: (e) => setCountry(e.target.value),
|
|
1215
|
+
placeholder: "Your country",
|
|
1216
|
+
disabled: saving,
|
|
1217
|
+
style: input,
|
|
1218
|
+
onFocus: inputFocusHandler,
|
|
1219
|
+
onBlur: inputBlurHandler
|
|
1220
|
+
}
|
|
1221
|
+
)
|
|
1222
|
+
] })
|
|
1223
|
+
] }),
|
|
1224
|
+
/* @__PURE__ */ jsx("hr", { style: separator }),
|
|
1225
|
+
/* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1226
|
+
/* @__PURE__ */ jsx("div", { style: label, children: "Language" }),
|
|
1227
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 8 }, children: ["es", "en"].map((lang) => /* @__PURE__ */ jsx(
|
|
1228
|
+
"button",
|
|
712
1229
|
{
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
)
|
|
1230
|
+
type: "button",
|
|
1231
|
+
style: {
|
|
1232
|
+
...langBtn,
|
|
1233
|
+
backgroundColor: user.language === lang ? "var(--dauth-accent, #6366f1)" : "var(--dauth-surface-secondary, rgba(255, 255, 255, 0.04))",
|
|
1234
|
+
color: user.language === lang ? "#ffffff" : "var(--dauth-text-secondary, #a1a1aa)"
|
|
1235
|
+
},
|
|
1236
|
+
onClick: () => handleLanguage(lang),
|
|
1237
|
+
children: lang === "es" ? "Espa\xF1ol" : "English"
|
|
1238
|
+
},
|
|
1239
|
+
lang
|
|
1240
|
+
)) })
|
|
724
1241
|
] })
|
|
725
1242
|
] }),
|
|
726
|
-
/* @__PURE__ */
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
/* @__PURE__ */ jsx("div", { style: dangerDesc, children: "Permanently delete your account and all associated data." }),
|
|
730
|
-
!showDelete ? /* @__PURE__ */ jsx(
|
|
731
|
-
"button",
|
|
1243
|
+
activeTab === "security" && showSecurity && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1244
|
+
/* @__PURE__ */ jsxs(
|
|
1245
|
+
"div",
|
|
732
1246
|
{
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
1247
|
+
style: {
|
|
1248
|
+
display: "flex",
|
|
1249
|
+
alignItems: "center",
|
|
1250
|
+
justifyContent: "space-between",
|
|
1251
|
+
marginBottom: 16
|
|
1252
|
+
},
|
|
1253
|
+
children: [
|
|
1254
|
+
/* @__PURE__ */ jsx(
|
|
1255
|
+
"div",
|
|
1256
|
+
{
|
|
1257
|
+
style: {
|
|
1258
|
+
...label,
|
|
1259
|
+
marginBottom: 0,
|
|
1260
|
+
fontWeight: 600
|
|
1261
|
+
},
|
|
1262
|
+
children: "Passkeys"
|
|
1263
|
+
}
|
|
1264
|
+
),
|
|
1265
|
+
/* @__PURE__ */ jsx(
|
|
1266
|
+
"button",
|
|
1267
|
+
{
|
|
1268
|
+
type: "button",
|
|
1269
|
+
style: outlineBtn,
|
|
1270
|
+
onClick: () => setShowRegister(!showRegister),
|
|
1271
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "var(--dauth-surface-hover, #232340)",
|
|
1272
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
|
|
1273
|
+
children: "+ Add passkey"
|
|
1274
|
+
}
|
|
1275
|
+
)
|
|
1276
|
+
]
|
|
739
1277
|
}
|
|
740
|
-
)
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1278
|
+
),
|
|
1279
|
+
showRegister && /* @__PURE__ */ jsxs("div", { style: registerPanel, children: [
|
|
1280
|
+
/* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
1281
|
+
/* @__PURE__ */ jsx(
|
|
1282
|
+
"label",
|
|
1283
|
+
{
|
|
1284
|
+
htmlFor: "dauth-passkey-name",
|
|
1285
|
+
style: label,
|
|
1286
|
+
children: "Passkey name (optional)"
|
|
1287
|
+
}
|
|
1288
|
+
),
|
|
1289
|
+
/* @__PURE__ */ jsx(
|
|
1290
|
+
"input",
|
|
1291
|
+
{
|
|
1292
|
+
id: "dauth-passkey-name",
|
|
1293
|
+
type: "text",
|
|
1294
|
+
value: passkeyName,
|
|
1295
|
+
onChange: (e) => setPasskeyName(e.target.value),
|
|
1296
|
+
placeholder: "e.g. MacBook Touch ID",
|
|
1297
|
+
disabled: registering,
|
|
1298
|
+
style: input,
|
|
1299
|
+
onFocus: inputFocusHandler,
|
|
1300
|
+
onBlur: inputBlurHandler
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
746
1303
|
] }),
|
|
747
|
-
/* @__PURE__ */ jsx(
|
|
748
|
-
"input",
|
|
749
|
-
{
|
|
750
|
-
type: "text",
|
|
751
|
-
value: deleteText,
|
|
752
|
-
onChange: (e) => setDeleteText(e.target.value),
|
|
753
|
-
placeholder: `Type ${CONFIRM_WORD}`,
|
|
754
|
-
style: input,
|
|
755
|
-
onFocus: inputFocusHandler,
|
|
756
|
-
onBlur: inputBlurHandler,
|
|
757
|
-
disabled: deleting
|
|
758
|
-
}
|
|
759
|
-
),
|
|
760
1304
|
/* @__PURE__ */ jsxs(
|
|
761
1305
|
"div",
|
|
762
1306
|
{
|
|
763
1307
|
style: {
|
|
764
1308
|
display: "flex",
|
|
765
|
-
gap: 8
|
|
766
|
-
marginTop: 12
|
|
1309
|
+
gap: 8
|
|
767
1310
|
},
|
|
768
1311
|
children: [
|
|
769
|
-
/* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ jsxs(
|
|
770
1313
|
"button",
|
|
771
1314
|
{
|
|
772
1315
|
type: "button",
|
|
773
|
-
style:
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
setDeleteText("");
|
|
1316
|
+
style: {
|
|
1317
|
+
...smallAccentBtn,
|
|
1318
|
+
opacity: registering ? 0.6 : 1
|
|
777
1319
|
},
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
children:
|
|
1320
|
+
disabled: registering,
|
|
1321
|
+
onClick: handleRegisterPasskey,
|
|
1322
|
+
children: [
|
|
1323
|
+
registering ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(IconFingerprint, {}),
|
|
1324
|
+
registering ? "Registering..." : "Register"
|
|
1325
|
+
]
|
|
781
1326
|
}
|
|
782
1327
|
),
|
|
783
|
-
/* @__PURE__ */
|
|
1328
|
+
/* @__PURE__ */ jsx(
|
|
784
1329
|
"button",
|
|
785
1330
|
{
|
|
786
1331
|
type: "button",
|
|
787
|
-
style:
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
disabled: deleteText !== CONFIRM_WORD || deleting,
|
|
793
|
-
onClick: handleDelete,
|
|
794
|
-
children: [
|
|
795
|
-
deleting && /* @__PURE__ */ jsx(Spinner, {}),
|
|
796
|
-
"Delete my account"
|
|
797
|
-
]
|
|
1332
|
+
style: cancelBtn,
|
|
1333
|
+
onClick: () => setShowRegister(false),
|
|
1334
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "var(--dauth-surface-hover, #232340)",
|
|
1335
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
|
|
1336
|
+
children: "Cancel"
|
|
798
1337
|
}
|
|
799
1338
|
)
|
|
800
1339
|
]
|
|
801
1340
|
}
|
|
802
1341
|
)
|
|
803
|
-
] })
|
|
1342
|
+
] }),
|
|
1343
|
+
passkeyStatus && /* @__PURE__ */ jsx(
|
|
1344
|
+
"div",
|
|
1345
|
+
{
|
|
1346
|
+
role: "status",
|
|
1347
|
+
"aria-live": "polite",
|
|
1348
|
+
style: {
|
|
1349
|
+
...statusMsg(passkeyStatus.type),
|
|
1350
|
+
marginTop: 12
|
|
1351
|
+
},
|
|
1352
|
+
children: passkeyStatus.message
|
|
1353
|
+
}
|
|
1354
|
+
),
|
|
1355
|
+
/* @__PURE__ */ jsx("div", { style: { marginTop: 12 }, children: loadingCreds ? /* @__PURE__ */ jsx(
|
|
1356
|
+
"div",
|
|
1357
|
+
{
|
|
1358
|
+
style: {
|
|
1359
|
+
textAlign: "center",
|
|
1360
|
+
padding: 24
|
|
1361
|
+
},
|
|
1362
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1363
|
+
}
|
|
1364
|
+
) : credentials.length > 0 ? credentials.map((cred) => /* @__PURE__ */ jsxs(
|
|
1365
|
+
"div",
|
|
1366
|
+
{
|
|
1367
|
+
style: credentialRow,
|
|
1368
|
+
children: [
|
|
1369
|
+
/* @__PURE__ */ jsxs(
|
|
1370
|
+
"div",
|
|
1371
|
+
{
|
|
1372
|
+
style: {
|
|
1373
|
+
display: "flex",
|
|
1374
|
+
alignItems: "center",
|
|
1375
|
+
gap: 12,
|
|
1376
|
+
flex: 1,
|
|
1377
|
+
minWidth: 0
|
|
1378
|
+
},
|
|
1379
|
+
children: [
|
|
1380
|
+
/* @__PURE__ */ jsx(
|
|
1381
|
+
"span",
|
|
1382
|
+
{
|
|
1383
|
+
style: {
|
|
1384
|
+
color: "var(--dauth-accent, #6366f1)",
|
|
1385
|
+
flexShrink: 0
|
|
1386
|
+
},
|
|
1387
|
+
children: /* @__PURE__ */ jsx(IconFingerprint, {})
|
|
1388
|
+
}
|
|
1389
|
+
),
|
|
1390
|
+
/* @__PURE__ */ jsxs(
|
|
1391
|
+
"div",
|
|
1392
|
+
{
|
|
1393
|
+
style: {
|
|
1394
|
+
minWidth: 0,
|
|
1395
|
+
flex: 1
|
|
1396
|
+
},
|
|
1397
|
+
children: [
|
|
1398
|
+
/* @__PURE__ */ jsx(
|
|
1399
|
+
"div",
|
|
1400
|
+
{
|
|
1401
|
+
style: {
|
|
1402
|
+
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1403
|
+
fontWeight: 500,
|
|
1404
|
+
color: "var(--dauth-text-primary, #e4e4e7)",
|
|
1405
|
+
overflow: "hidden",
|
|
1406
|
+
textOverflow: "ellipsis",
|
|
1407
|
+
whiteSpace: "nowrap"
|
|
1408
|
+
},
|
|
1409
|
+
children: cred.name || "Passkey"
|
|
1410
|
+
}
|
|
1411
|
+
),
|
|
1412
|
+
/* @__PURE__ */ jsxs(
|
|
1413
|
+
"div",
|
|
1414
|
+
{
|
|
1415
|
+
style: {
|
|
1416
|
+
fontSize: "var(--dauth-font-size-xs, 0.75rem)",
|
|
1417
|
+
color: "var(--dauth-text-muted, #71717a)"
|
|
1418
|
+
},
|
|
1419
|
+
children: [
|
|
1420
|
+
cred.deviceType === "multiDevice" ? "Synced" : "Device-bound",
|
|
1421
|
+
cred.createdAt && ` \xB7 Created ${new Date(cred.createdAt).toLocaleDateString()}`
|
|
1422
|
+
]
|
|
1423
|
+
}
|
|
1424
|
+
)
|
|
1425
|
+
]
|
|
1426
|
+
}
|
|
1427
|
+
)
|
|
1428
|
+
]
|
|
1429
|
+
}
|
|
1430
|
+
),
|
|
1431
|
+
/* @__PURE__ */ jsx(
|
|
1432
|
+
"button",
|
|
1433
|
+
{
|
|
1434
|
+
type: "button",
|
|
1435
|
+
onClick: () => handleDeletePasskey(cred._id),
|
|
1436
|
+
style: trashBtn,
|
|
1437
|
+
onMouseEnter: (e) => e.currentTarget.style.color = "var(--dauth-error, #ef4444)",
|
|
1438
|
+
onMouseLeave: (e) => e.currentTarget.style.color = "var(--dauth-text-muted, #71717a)",
|
|
1439
|
+
"aria-label": `Delete passkey ${cred.name || ""}`,
|
|
1440
|
+
children: /* @__PURE__ */ jsx(IconTrash, {})
|
|
1441
|
+
}
|
|
1442
|
+
)
|
|
1443
|
+
]
|
|
1444
|
+
},
|
|
1445
|
+
cred._id
|
|
1446
|
+
)) : /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
|
|
1447
|
+
/* @__PURE__ */ jsx(
|
|
1448
|
+
"span",
|
|
1449
|
+
{
|
|
1450
|
+
style: {
|
|
1451
|
+
color: "var(--dauth-accent, #6366f1)"
|
|
1452
|
+
},
|
|
1453
|
+
children: /* @__PURE__ */ jsx(IconShield, {})
|
|
1454
|
+
}
|
|
1455
|
+
),
|
|
1456
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1457
|
+
/* @__PURE__ */ jsx(
|
|
1458
|
+
"div",
|
|
1459
|
+
{
|
|
1460
|
+
style: {
|
|
1461
|
+
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1462
|
+
fontWeight: 500,
|
|
1463
|
+
color: "var(--dauth-text-primary, #e4e4e7)"
|
|
1464
|
+
},
|
|
1465
|
+
children: "No passkeys registered"
|
|
1466
|
+
}
|
|
1467
|
+
),
|
|
1468
|
+
/* @__PURE__ */ jsx(
|
|
1469
|
+
"div",
|
|
1470
|
+
{
|
|
1471
|
+
style: {
|
|
1472
|
+
fontSize: "var(--dauth-font-size-xs, 0.75rem)",
|
|
1473
|
+
color: "var(--dauth-text-secondary, #a1a1aa)"
|
|
1474
|
+
},
|
|
1475
|
+
children: "Add a passkey for faster, more secure sign-in."
|
|
1476
|
+
}
|
|
1477
|
+
)
|
|
1478
|
+
] })
|
|
1479
|
+
] }) })
|
|
1480
|
+
] }),
|
|
1481
|
+
activeTab === "account" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1482
|
+
status && /* @__PURE__ */ jsx(
|
|
1483
|
+
"div",
|
|
1484
|
+
{
|
|
1485
|
+
role: "status",
|
|
1486
|
+
"aria-live": "polite",
|
|
1487
|
+
style: statusMsg(status.type),
|
|
1488
|
+
children: status.message
|
|
1489
|
+
}
|
|
1490
|
+
),
|
|
1491
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1492
|
+
/* @__PURE__ */ jsx("div", { style: dangerTitle, children: "Delete account" }),
|
|
1493
|
+
/* @__PURE__ */ jsx("div", { style: dangerDesc, children: "Permanently delete your account and all associated data." }),
|
|
1494
|
+
!showDelete ? /* @__PURE__ */ jsx(
|
|
1495
|
+
"button",
|
|
1496
|
+
{
|
|
1497
|
+
type: "button",
|
|
1498
|
+
style: deleteBtn,
|
|
1499
|
+
onClick: () => setShowDelete(true),
|
|
1500
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "rgba(239, 68, 68, 0.2)",
|
|
1501
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "var(--dauth-error-bg, rgba(239, 68, 68, 0.1))",
|
|
1502
|
+
children: "Delete account"
|
|
1503
|
+
}
|
|
1504
|
+
) : /* @__PURE__ */ jsxs("div", { style: deletePanel, children: [
|
|
1505
|
+
/* @__PURE__ */ jsxs("div", { style: deletePanelText, children: [
|
|
1506
|
+
"This action is permanent and cannot be undone. Type",
|
|
1507
|
+
" ",
|
|
1508
|
+
/* @__PURE__ */ jsx("strong", { children: CONFIRM_WORD }),
|
|
1509
|
+
" to confirm."
|
|
1510
|
+
] }),
|
|
1511
|
+
/* @__PURE__ */ jsx(
|
|
1512
|
+
"input",
|
|
1513
|
+
{
|
|
1514
|
+
type: "text",
|
|
1515
|
+
value: deleteText,
|
|
1516
|
+
onChange: (e) => setDeleteText(e.target.value),
|
|
1517
|
+
placeholder: `Type ${CONFIRM_WORD}`,
|
|
1518
|
+
style: input,
|
|
1519
|
+
onFocus: inputFocusHandler,
|
|
1520
|
+
onBlur: inputBlurHandler,
|
|
1521
|
+
disabled: deleting
|
|
1522
|
+
}
|
|
1523
|
+
),
|
|
1524
|
+
/* @__PURE__ */ jsxs(
|
|
1525
|
+
"div",
|
|
1526
|
+
{
|
|
1527
|
+
style: {
|
|
1528
|
+
display: "flex",
|
|
1529
|
+
gap: 8,
|
|
1530
|
+
marginTop: 12
|
|
1531
|
+
},
|
|
1532
|
+
children: [
|
|
1533
|
+
/* @__PURE__ */ jsx(
|
|
1534
|
+
"button",
|
|
1535
|
+
{
|
|
1536
|
+
type: "button",
|
|
1537
|
+
style: cancelBtn,
|
|
1538
|
+
onClick: () => {
|
|
1539
|
+
setShowDelete(false);
|
|
1540
|
+
setDeleteText("");
|
|
1541
|
+
},
|
|
1542
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "var(--dauth-surface-hover, #232340)",
|
|
1543
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
|
|
1544
|
+
children: "Cancel"
|
|
1545
|
+
}
|
|
1546
|
+
),
|
|
1547
|
+
/* @__PURE__ */ jsxs(
|
|
1548
|
+
"button",
|
|
1549
|
+
{
|
|
1550
|
+
type: "button",
|
|
1551
|
+
style: {
|
|
1552
|
+
...deleteConfirmBtn,
|
|
1553
|
+
opacity: deleteText !== CONFIRM_WORD || deleting ? 0.5 : 1,
|
|
1554
|
+
cursor: deleteText !== CONFIRM_WORD || deleting ? "not-allowed" : "pointer"
|
|
1555
|
+
},
|
|
1556
|
+
disabled: deleteText !== CONFIRM_WORD || deleting,
|
|
1557
|
+
onClick: handleDelete,
|
|
1558
|
+
children: [
|
|
1559
|
+
deleting && /* @__PURE__ */ jsx(Spinner, {}),
|
|
1560
|
+
"Delete my account"
|
|
1561
|
+
]
|
|
1562
|
+
}
|
|
1563
|
+
)
|
|
1564
|
+
]
|
|
1565
|
+
}
|
|
1566
|
+
)
|
|
1567
|
+
] })
|
|
1568
|
+
] }),
|
|
1569
|
+
/* @__PURE__ */ jsx("hr", { style: separator }),
|
|
1570
|
+
/* @__PURE__ */ jsxs(
|
|
1571
|
+
"button",
|
|
1572
|
+
{
|
|
1573
|
+
type: "button",
|
|
1574
|
+
style: signOutBtn,
|
|
1575
|
+
onClick: handleSignOut,
|
|
1576
|
+
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "rgba(239, 68, 68, 0.2)",
|
|
1577
|
+
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "var(--dauth-error-bg, rgba(239, 68, 68, 0.1))",
|
|
1578
|
+
children: [
|
|
1579
|
+
/* @__PURE__ */ jsx(IconLogOut, {}),
|
|
1580
|
+
"Sign out"
|
|
1581
|
+
]
|
|
1582
|
+
}
|
|
1583
|
+
)
|
|
804
1584
|
] })
|
|
805
1585
|
] }),
|
|
806
|
-
/* @__PURE__ */ jsx("div", { style: footerStyle(isDesktop), children: /* @__PURE__ */ jsxs(
|
|
1586
|
+
activeTab === "profile" && /* @__PURE__ */ jsx("div", { style: footerStyle(isDesktop), children: /* @__PURE__ */ jsxs(
|
|
807
1587
|
"button",
|
|
808
1588
|
{
|
|
809
1589
|
type: "button",
|
|
@@ -841,8 +1621,7 @@ var headerStyle = (isDesktop) => ({
|
|
|
841
1621
|
display: "flex",
|
|
842
1622
|
alignItems: "center",
|
|
843
1623
|
justifyContent: "space-between",
|
|
844
|
-
padding: "16px 24px",
|
|
845
|
-
borderBottom: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
1624
|
+
padding: "16px 24px 0",
|
|
846
1625
|
flexShrink: 0,
|
|
847
1626
|
...!isDesktop ? {
|
|
848
1627
|
position: "sticky",
|
|
@@ -873,6 +1652,25 @@ var closeBtn = {
|
|
|
873
1652
|
transition: "background-color 150ms, color 150ms",
|
|
874
1653
|
padding: 0
|
|
875
1654
|
};
|
|
1655
|
+
var tabBar = {
|
|
1656
|
+
display: "flex",
|
|
1657
|
+
padding: "0 24px",
|
|
1658
|
+
borderBottom: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
1659
|
+
flexShrink: 0
|
|
1660
|
+
};
|
|
1661
|
+
var tabBtn = {
|
|
1662
|
+
flex: 1,
|
|
1663
|
+
padding: "12px 4px",
|
|
1664
|
+
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1665
|
+
fontWeight: 500,
|
|
1666
|
+
border: "none",
|
|
1667
|
+
borderBottom: "2px solid transparent",
|
|
1668
|
+
backgroundColor: "transparent",
|
|
1669
|
+
cursor: "pointer",
|
|
1670
|
+
transition: "color 150ms, border-color 150ms",
|
|
1671
|
+
fontFamily: "inherit",
|
|
1672
|
+
textAlign: "center"
|
|
1673
|
+
};
|
|
876
1674
|
var bodyStyle = {
|
|
877
1675
|
flex: 1,
|
|
878
1676
|
overflowY: "auto",
|
|
@@ -899,6 +1697,18 @@ var avatarCircle = {
|
|
|
899
1697
|
fontSize: "1.5rem",
|
|
900
1698
|
fontWeight: 600
|
|
901
1699
|
};
|
|
1700
|
+
var avatarOverlay = {
|
|
1701
|
+
position: "absolute",
|
|
1702
|
+
inset: 0,
|
|
1703
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
1704
|
+
display: "flex",
|
|
1705
|
+
alignItems: "center",
|
|
1706
|
+
justifyContent: "center",
|
|
1707
|
+
borderRadius: "50%",
|
|
1708
|
+
opacity: 0.7,
|
|
1709
|
+
transition: "opacity 150ms",
|
|
1710
|
+
color: "#ffffff"
|
|
1711
|
+
};
|
|
902
1712
|
var emailText = {
|
|
903
1713
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
904
1714
|
color: "var(--dauth-text-secondary, #a1a1aa)"
|
|
@@ -913,7 +1723,9 @@ var statusMsg = (type) => ({
|
|
|
913
1723
|
textAlign: "center",
|
|
914
1724
|
lineHeight: 1.5
|
|
915
1725
|
});
|
|
916
|
-
var fieldGroup = {
|
|
1726
|
+
var fieldGroup = {
|
|
1727
|
+
marginBottom: 16
|
|
1728
|
+
};
|
|
917
1729
|
var label = {
|
|
918
1730
|
display: "block",
|
|
919
1731
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
@@ -943,12 +1755,88 @@ var inputBlurHandler = (e) => {
|
|
|
943
1755
|
e.currentTarget.style.borderColor = "var(--dauth-border, rgba(255, 255, 255, 0.08))";
|
|
944
1756
|
e.currentTarget.style.boxShadow = "none";
|
|
945
1757
|
};
|
|
1758
|
+
var langBtn = {
|
|
1759
|
+
padding: "8px 16px",
|
|
1760
|
+
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1761
|
+
fontWeight: 500,
|
|
1762
|
+
border: "none",
|
|
1763
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1764
|
+
cursor: "pointer",
|
|
1765
|
+
transition: "background-color 150ms, color 150ms",
|
|
1766
|
+
fontFamily: "inherit"
|
|
1767
|
+
};
|
|
946
1768
|
var separator = {
|
|
947
1769
|
height: 1,
|
|
948
1770
|
backgroundColor: "var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
949
1771
|
margin: "24px 0",
|
|
950
1772
|
border: "none"
|
|
951
1773
|
};
|
|
1774
|
+
var outlineBtn = {
|
|
1775
|
+
padding: "6px 12px",
|
|
1776
|
+
fontSize: "var(--dauth-font-size-xs, 0.75rem)",
|
|
1777
|
+
fontWeight: 500,
|
|
1778
|
+
color: "var(--dauth-text-secondary, #a1a1aa)",
|
|
1779
|
+
backgroundColor: "transparent",
|
|
1780
|
+
border: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
1781
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1782
|
+
cursor: "pointer",
|
|
1783
|
+
transition: "background-color 150ms",
|
|
1784
|
+
fontFamily: "inherit"
|
|
1785
|
+
};
|
|
1786
|
+
var registerPanel = {
|
|
1787
|
+
padding: 16,
|
|
1788
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1789
|
+
border: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
1790
|
+
backgroundColor: "var(--dauth-surface-secondary, rgba(255, 255, 255, 0.04))",
|
|
1791
|
+
marginBottom: 12
|
|
1792
|
+
};
|
|
1793
|
+
var smallAccentBtn = {
|
|
1794
|
+
padding: "8px 16px",
|
|
1795
|
+
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1796
|
+
fontWeight: 500,
|
|
1797
|
+
color: "#ffffff",
|
|
1798
|
+
backgroundColor: "var(--dauth-accent, #6366f1)",
|
|
1799
|
+
border: "none",
|
|
1800
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1801
|
+
cursor: "pointer",
|
|
1802
|
+
transition: "opacity 150ms",
|
|
1803
|
+
fontFamily: "inherit",
|
|
1804
|
+
display: "flex",
|
|
1805
|
+
alignItems: "center",
|
|
1806
|
+
gap: 6
|
|
1807
|
+
};
|
|
1808
|
+
var credentialRow = {
|
|
1809
|
+
display: "flex",
|
|
1810
|
+
alignItems: "center",
|
|
1811
|
+
justifyContent: "space-between",
|
|
1812
|
+
padding: 12,
|
|
1813
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1814
|
+
backgroundColor: "var(--dauth-surface-secondary, rgba(255, 255, 255, 0.04))",
|
|
1815
|
+
marginBottom: 8
|
|
1816
|
+
};
|
|
1817
|
+
var trashBtn = {
|
|
1818
|
+
display: "flex",
|
|
1819
|
+
alignItems: "center",
|
|
1820
|
+
justifyContent: "center",
|
|
1821
|
+
width: 28,
|
|
1822
|
+
height: 28,
|
|
1823
|
+
border: "none",
|
|
1824
|
+
backgroundColor: "transparent",
|
|
1825
|
+
color: "var(--dauth-text-muted, #71717a)",
|
|
1826
|
+
cursor: "pointer",
|
|
1827
|
+
transition: "color 150ms",
|
|
1828
|
+
padding: 0,
|
|
1829
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1830
|
+
flexShrink: 0
|
|
1831
|
+
};
|
|
1832
|
+
var emptyState = {
|
|
1833
|
+
display: "flex",
|
|
1834
|
+
alignItems: "center",
|
|
1835
|
+
gap: 12,
|
|
1836
|
+
padding: 16,
|
|
1837
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1838
|
+
backgroundColor: "var(--dauth-surface-secondary, rgba(255, 255, 255, 0.04))"
|
|
1839
|
+
};
|
|
952
1840
|
var dangerTitle = {
|
|
953
1841
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
954
1842
|
fontWeight: 600,
|
|
@@ -987,7 +1875,6 @@ var deletePanelText = {
|
|
|
987
1875
|
lineHeight: 1.5
|
|
988
1876
|
};
|
|
989
1877
|
var cancelBtn = {
|
|
990
|
-
flex: 1,
|
|
991
1878
|
padding: "8px 16px",
|
|
992
1879
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
993
1880
|
fontWeight: 500,
|
|
@@ -1016,6 +1903,23 @@ var deleteConfirmBtn = {
|
|
|
1016
1903
|
justifyContent: "center",
|
|
1017
1904
|
gap: 8
|
|
1018
1905
|
};
|
|
1906
|
+
var signOutBtn = {
|
|
1907
|
+
width: "100%",
|
|
1908
|
+
padding: "12px 24px",
|
|
1909
|
+
fontSize: "var(--dauth-font-size-base, 1rem)",
|
|
1910
|
+
fontWeight: 500,
|
|
1911
|
+
color: "var(--dauth-error, #ef4444)",
|
|
1912
|
+
backgroundColor: "var(--dauth-error-bg, rgba(239, 68, 68, 0.1))",
|
|
1913
|
+
border: "1px solid rgba(239, 68, 68, 0.2)",
|
|
1914
|
+
borderRadius: "var(--dauth-radius-sm, 8px)",
|
|
1915
|
+
cursor: "pointer",
|
|
1916
|
+
transition: "background-color 150ms",
|
|
1917
|
+
fontFamily: "inherit",
|
|
1918
|
+
display: "flex",
|
|
1919
|
+
alignItems: "center",
|
|
1920
|
+
justifyContent: "center",
|
|
1921
|
+
gap: 8
|
|
1922
|
+
};
|
|
1019
1923
|
var footerStyle = (isDesktop) => ({
|
|
1020
1924
|
padding: "16px 24px",
|
|
1021
1925
|
borderTop: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
@@ -1127,15 +2031,39 @@ var DauthProvider = (props) => {
|
|
|
1127
2031
|
() => deleteAccountAction(ctx),
|
|
1128
2032
|
[ctx]
|
|
1129
2033
|
);
|
|
2034
|
+
const getPasskeyCredentials = useCallback2(
|
|
2035
|
+
() => getPasskeyCredentialsAction(ctx),
|
|
2036
|
+
[ctx]
|
|
2037
|
+
);
|
|
2038
|
+
const registerPasskey = useCallback2(
|
|
2039
|
+
(name) => registerPasskeyAction(ctx, name),
|
|
2040
|
+
[ctx]
|
|
2041
|
+
);
|
|
2042
|
+
const deletePasskeyCredential = useCallback2(
|
|
2043
|
+
(credentialId) => deletePasskeyCredentialAction(ctx, credentialId),
|
|
2044
|
+
[ctx]
|
|
2045
|
+
);
|
|
1130
2046
|
const memoProvider = useMemo2(
|
|
1131
2047
|
() => ({
|
|
1132
2048
|
...dauthState,
|
|
1133
2049
|
loginWithRedirect,
|
|
1134
2050
|
logout,
|
|
1135
2051
|
updateUser,
|
|
1136
|
-
deleteAccount
|
|
2052
|
+
deleteAccount,
|
|
2053
|
+
getPasskeyCredentials,
|
|
2054
|
+
registerPasskey,
|
|
2055
|
+
deletePasskeyCredential
|
|
1137
2056
|
}),
|
|
1138
|
-
[
|
|
2057
|
+
[
|
|
2058
|
+
dauthState,
|
|
2059
|
+
loginWithRedirect,
|
|
2060
|
+
logout,
|
|
2061
|
+
updateUser,
|
|
2062
|
+
deleteAccount,
|
|
2063
|
+
getPasskeyCredentials,
|
|
2064
|
+
registerPasskey,
|
|
2065
|
+
deletePasskeyCredential
|
|
2066
|
+
]
|
|
1139
2067
|
);
|
|
1140
2068
|
return /* @__PURE__ */ jsx2(DauthContext.Provider, { value: memoProvider, children });
|
|
1141
2069
|
};
|