dauth-context-react 6.1.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 +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +1076 -161
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1076 -161
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/DauthProfileModal.tsx +1090 -241
- package/src/api/dauth.api.ts +73 -0
- package/src/api/interfaces/dauth.api.responses.ts +36 -0
- package/src/index.tsx +31 -1
- package/src/initialDauthState.ts +3 -0
- package/src/interfaces.ts +20 -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,16 +869,87 @@ 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]);
|
|
532
939
|
const themeVars = useMemo(() => {
|
|
533
940
|
const t = domain.modalTheme;
|
|
534
941
|
if (!t) return {};
|
|
535
942
|
const vars = {};
|
|
536
943
|
if (t.accent) vars["--dauth-accent"] = t.accent;
|
|
537
|
-
if (t.accentHover)
|
|
944
|
+
if (t.accentHover)
|
|
945
|
+
vars["--dauth-accent-hover"] = t.accentHover;
|
|
538
946
|
if (t.surface) vars["--dauth-surface"] = t.surface;
|
|
539
|
-
if (t.surfaceHover)
|
|
540
|
-
|
|
541
|
-
if (t.
|
|
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;
|
|
542
953
|
if (t.border) vars["--dauth-border"] = t.border;
|
|
543
954
|
return vars;
|
|
544
955
|
}, [domain.modalTheme]);
|
|
@@ -589,6 +1000,11 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
589
1000
|
transition: `transform ${dur}ms ${easing}`
|
|
590
1001
|
};
|
|
591
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
|
+
];
|
|
592
1008
|
return createPortal(
|
|
593
1009
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
594
1010
|
/* @__PURE__ */ jsx(
|
|
@@ -632,191 +1048,542 @@ function DauthProfileModal({ open, onClose }) {
|
|
|
632
1048
|
/* @__PURE__ */ jsx("h2", { id: "dauth-profile-title", style: titleStyle, children: "Your Profile" }),
|
|
633
1049
|
/* @__PURE__ */ jsx("div", { style: { width: 36 } })
|
|
634
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
|
+
)) }),
|
|
635
1067
|
/* @__PURE__ */ jsxs("div", { style: bodyStyle, children: [
|
|
636
|
-
/* @__PURE__ */ jsxs(
|
|
637
|
-
/* @__PURE__ */
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
src: user.avatar.url,
|
|
641
|
-
alt: "",
|
|
642
|
-
style: {
|
|
643
|
-
width: "100%",
|
|
644
|
-
height: "100%",
|
|
645
|
-
objectFit: "cover"
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
) : avatarInitial }),
|
|
649
|
-
/* @__PURE__ */ jsx("div", { style: emailText, children: user.email })
|
|
650
|
-
] }),
|
|
651
|
-
status && /* @__PURE__ */ jsx(
|
|
652
|
-
"div",
|
|
653
|
-
{
|
|
654
|
-
role: "status",
|
|
655
|
-
"aria-live": "polite",
|
|
656
|
-
style: statusMsg(status.type),
|
|
657
|
-
children: status.message
|
|
658
|
-
}
|
|
659
|
-
),
|
|
660
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
661
|
-
/* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
|
|
662
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "dauth-name", style: label, children: "Name *" }),
|
|
663
|
-
/* @__PURE__ */ jsx(
|
|
664
|
-
"input",
|
|
1068
|
+
activeTab === "profile" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1069
|
+
/* @__PURE__ */ jsxs("div", { style: avatarSection, children: [
|
|
1070
|
+
/* @__PURE__ */ jsxs(
|
|
1071
|
+
"div",
|
|
665
1072
|
{
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
+
]
|
|
675
1094
|
}
|
|
676
|
-
)
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
/* @__PURE__ */ jsxs("label", { htmlFor: "dauth-lastname", style: label, children: [
|
|
680
|
-
"Last name",
|
|
681
|
-
isRequired("lastname") ? " *" : ""
|
|
682
|
-
] }),
|
|
683
|
-
/* @__PURE__ */ jsx(
|
|
1095
|
+
),
|
|
1096
|
+
/* @__PURE__ */ jsx("div", { style: emailText, children: user.email }),
|
|
1097
|
+
onAvatarUpload && /* @__PURE__ */ jsx(
|
|
684
1098
|
"input",
|
|
685
1099
|
{
|
|
686
|
-
|
|
687
|
-
type: "
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
disabled: saving,
|
|
692
|
-
style: input,
|
|
693
|
-
onFocus: inputFocusHandler,
|
|
694
|
-
onBlur: inputBlurHandler
|
|
1100
|
+
ref: avatarInputRef,
|
|
1101
|
+
type: "file",
|
|
1102
|
+
accept: "image/*",
|
|
1103
|
+
style: { display: "none" },
|
|
1104
|
+
onChange: handleAvatarChange
|
|
695
1105
|
}
|
|
696
1106
|
)
|
|
697
1107
|
] }),
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
+
)
|
|
702
1141
|
] }),
|
|
703
|
-
/* @__PURE__ */
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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
|
+
)
|
|
722
1168
|
] }),
|
|
723
|
-
/* @__PURE__ */
|
|
724
|
-
|
|
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",
|
|
725
1229
|
{
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
)
|
|
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
|
+
)) })
|
|
737
1241
|
] })
|
|
738
1242
|
] }),
|
|
739
|
-
/* @__PURE__ */
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
/* @__PURE__ */ jsx("div", { style: dangerDesc, children: "Permanently delete your account and all associated data." }),
|
|
743
|
-
!showDelete ? /* @__PURE__ */ jsx(
|
|
744
|
-
"button",
|
|
1243
|
+
activeTab === "security" && showSecurity && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1244
|
+
/* @__PURE__ */ jsxs(
|
|
1245
|
+
"div",
|
|
745
1246
|
{
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
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
|
+
]
|
|
752
1277
|
}
|
|
753
|
-
)
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
+
)
|
|
759
1303
|
] }),
|
|
760
|
-
/* @__PURE__ */ jsx(
|
|
761
|
-
"input",
|
|
762
|
-
{
|
|
763
|
-
type: "text",
|
|
764
|
-
value: deleteText,
|
|
765
|
-
onChange: (e) => setDeleteText(e.target.value),
|
|
766
|
-
placeholder: `Type ${CONFIRM_WORD}`,
|
|
767
|
-
style: input,
|
|
768
|
-
onFocus: inputFocusHandler,
|
|
769
|
-
onBlur: inputBlurHandler,
|
|
770
|
-
disabled: deleting
|
|
771
|
-
}
|
|
772
|
-
),
|
|
773
1304
|
/* @__PURE__ */ jsxs(
|
|
774
1305
|
"div",
|
|
775
1306
|
{
|
|
776
1307
|
style: {
|
|
777
1308
|
display: "flex",
|
|
778
|
-
gap: 8
|
|
779
|
-
marginTop: 12
|
|
1309
|
+
gap: 8
|
|
780
1310
|
},
|
|
781
1311
|
children: [
|
|
782
|
-
/* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ jsxs(
|
|
783
1313
|
"button",
|
|
784
1314
|
{
|
|
785
1315
|
type: "button",
|
|
786
|
-
style:
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
setDeleteText("");
|
|
1316
|
+
style: {
|
|
1317
|
+
...smallAccentBtn,
|
|
1318
|
+
opacity: registering ? 0.6 : 1
|
|
790
1319
|
},
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
children:
|
|
1320
|
+
disabled: registering,
|
|
1321
|
+
onClick: handleRegisterPasskey,
|
|
1322
|
+
children: [
|
|
1323
|
+
registering ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(IconFingerprint, {}),
|
|
1324
|
+
registering ? "Registering..." : "Register"
|
|
1325
|
+
]
|
|
794
1326
|
}
|
|
795
1327
|
),
|
|
796
|
-
/* @__PURE__ */
|
|
1328
|
+
/* @__PURE__ */ jsx(
|
|
797
1329
|
"button",
|
|
798
1330
|
{
|
|
799
1331
|
type: "button",
|
|
800
|
-
style:
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
disabled: deleteText !== CONFIRM_WORD || deleting,
|
|
806
|
-
onClick: handleDelete,
|
|
807
|
-
children: [
|
|
808
|
-
deleting && /* @__PURE__ */ jsx(Spinner, {}),
|
|
809
|
-
"Delete my account"
|
|
810
|
-
]
|
|
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"
|
|
811
1337
|
}
|
|
812
1338
|
)
|
|
813
1339
|
]
|
|
814
1340
|
}
|
|
815
1341
|
)
|
|
816
|
-
] })
|
|
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
|
+
)
|
|
817
1584
|
] })
|
|
818
1585
|
] }),
|
|
819
|
-
/* @__PURE__ */ jsx("div", { style: footerStyle(isDesktop), children: /* @__PURE__ */ jsxs(
|
|
1586
|
+
activeTab === "profile" && /* @__PURE__ */ jsx("div", { style: footerStyle(isDesktop), children: /* @__PURE__ */ jsxs(
|
|
820
1587
|
"button",
|
|
821
1588
|
{
|
|
822
1589
|
type: "button",
|
|
@@ -854,8 +1621,7 @@ var headerStyle = (isDesktop) => ({
|
|
|
854
1621
|
display: "flex",
|
|
855
1622
|
alignItems: "center",
|
|
856
1623
|
justifyContent: "space-between",
|
|
857
|
-
padding: "16px 24px",
|
|
858
|
-
borderBottom: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
1624
|
+
padding: "16px 24px 0",
|
|
859
1625
|
flexShrink: 0,
|
|
860
1626
|
...!isDesktop ? {
|
|
861
1627
|
position: "sticky",
|
|
@@ -886,6 +1652,25 @@ var closeBtn = {
|
|
|
886
1652
|
transition: "background-color 150ms, color 150ms",
|
|
887
1653
|
padding: 0
|
|
888
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
|
+
};
|
|
889
1674
|
var bodyStyle = {
|
|
890
1675
|
flex: 1,
|
|
891
1676
|
overflowY: "auto",
|
|
@@ -912,6 +1697,18 @@ var avatarCircle = {
|
|
|
912
1697
|
fontSize: "1.5rem",
|
|
913
1698
|
fontWeight: 600
|
|
914
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
|
+
};
|
|
915
1712
|
var emailText = {
|
|
916
1713
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
917
1714
|
color: "var(--dauth-text-secondary, #a1a1aa)"
|
|
@@ -926,7 +1723,9 @@ var statusMsg = (type) => ({
|
|
|
926
1723
|
textAlign: "center",
|
|
927
1724
|
lineHeight: 1.5
|
|
928
1725
|
});
|
|
929
|
-
var fieldGroup = {
|
|
1726
|
+
var fieldGroup = {
|
|
1727
|
+
marginBottom: 16
|
|
1728
|
+
};
|
|
930
1729
|
var label = {
|
|
931
1730
|
display: "block",
|
|
932
1731
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
@@ -956,12 +1755,88 @@ var inputBlurHandler = (e) => {
|
|
|
956
1755
|
e.currentTarget.style.borderColor = "var(--dauth-border, rgba(255, 255, 255, 0.08))";
|
|
957
1756
|
e.currentTarget.style.boxShadow = "none";
|
|
958
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
|
+
};
|
|
959
1768
|
var separator = {
|
|
960
1769
|
height: 1,
|
|
961
1770
|
backgroundColor: "var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
962
1771
|
margin: "24px 0",
|
|
963
1772
|
border: "none"
|
|
964
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
|
+
};
|
|
965
1840
|
var dangerTitle = {
|
|
966
1841
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
967
1842
|
fontWeight: 600,
|
|
@@ -1000,7 +1875,6 @@ var deletePanelText = {
|
|
|
1000
1875
|
lineHeight: 1.5
|
|
1001
1876
|
};
|
|
1002
1877
|
var cancelBtn = {
|
|
1003
|
-
flex: 1,
|
|
1004
1878
|
padding: "8px 16px",
|
|
1005
1879
|
fontSize: "var(--dauth-font-size-sm, 0.875rem)",
|
|
1006
1880
|
fontWeight: 500,
|
|
@@ -1029,6 +1903,23 @@ var deleteConfirmBtn = {
|
|
|
1029
1903
|
justifyContent: "center",
|
|
1030
1904
|
gap: 8
|
|
1031
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
|
+
};
|
|
1032
1923
|
var footerStyle = (isDesktop) => ({
|
|
1033
1924
|
padding: "16px 24px",
|
|
1034
1925
|
borderTop: "1px solid var(--dauth-border, rgba(255, 255, 255, 0.08))",
|
|
@@ -1140,15 +2031,39 @@ var DauthProvider = (props) => {
|
|
|
1140
2031
|
() => deleteAccountAction(ctx),
|
|
1141
2032
|
[ctx]
|
|
1142
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
|
+
);
|
|
1143
2046
|
const memoProvider = useMemo2(
|
|
1144
2047
|
() => ({
|
|
1145
2048
|
...dauthState,
|
|
1146
2049
|
loginWithRedirect,
|
|
1147
2050
|
logout,
|
|
1148
2051
|
updateUser,
|
|
1149
|
-
deleteAccount
|
|
2052
|
+
deleteAccount,
|
|
2053
|
+
getPasskeyCredentials,
|
|
2054
|
+
registerPasskey,
|
|
2055
|
+
deletePasskeyCredential
|
|
1150
2056
|
}),
|
|
1151
|
-
[
|
|
2057
|
+
[
|
|
2058
|
+
dauthState,
|
|
2059
|
+
loginWithRedirect,
|
|
2060
|
+
logout,
|
|
2061
|
+
updateUser,
|
|
2062
|
+
deleteAccount,
|
|
2063
|
+
getPasskeyCredentials,
|
|
2064
|
+
registerPasskey,
|
|
2065
|
+
deletePasskeyCredential
|
|
2066
|
+
]
|
|
1152
2067
|
);
|
|
1153
2068
|
return /* @__PURE__ */ jsx2(DauthContext.Provider, { value: memoProvider, children });
|
|
1154
2069
|
};
|