dauth-context-react 6.5.0 → 6.6.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.mjs CHANGED
@@ -26,7 +26,8 @@ var initialDauthState = {
26
26
  getPasskeyCredentials: () => Promise.resolve([]),
27
27
  registerPasskey: () => Promise.resolve(null),
28
28
  deletePasskeyCredential: () => Promise.resolve(false),
29
- uploadAvatar: () => Promise.resolve(false)
29
+ uploadAvatar: () => Promise.resolve(false),
30
+ loginWithPasskey: () => Promise.resolve(false)
30
31
  };
31
32
  var initialDauthState_default = initialDauthState;
32
33
 
@@ -134,45 +135,59 @@ async function deleteAccountAPI(basePath) {
134
135
  return { response, data };
135
136
  }
136
137
  async function getPasskeyCredentialsAPI(basePath) {
137
- const response = await fetch(
138
- `${basePath}/passkey/credentials`,
139
- {
140
- method: "GET",
141
- headers: { "X-CSRF-Token": getCsrfToken() },
142
- credentials: "include"
143
- }
144
- );
138
+ const response = await fetch(`${basePath}/passkey/credentials`, {
139
+ method: "GET",
140
+ headers: { "X-CSRF-Token": getCsrfToken() },
141
+ credentials: "include"
142
+ });
145
143
  const data = await response.json();
146
144
  return { response, data };
147
145
  }
148
146
  async function startPasskeyRegistrationAPI(basePath) {
149
- const response = await fetch(
150
- `${basePath}/passkey/register/start`,
151
- {
152
- method: "POST",
153
- headers: {
154
- "Content-Type": "application/json",
155
- "X-CSRF-Token": getCsrfToken()
156
- },
157
- credentials: "include"
158
- }
159
- );
147
+ const response = await fetch(`${basePath}/passkey/register/start`, {
148
+ method: "POST",
149
+ headers: {
150
+ "Content-Type": "application/json",
151
+ "X-CSRF-Token": getCsrfToken()
152
+ },
153
+ credentials: "include"
154
+ });
160
155
  const data = await response.json();
161
156
  return { response, data };
162
157
  }
163
158
  async function finishPasskeyRegistrationAPI(basePath, body) {
164
- const response = await fetch(
165
- `${basePath}/passkey/register/finish`,
166
- {
167
- method: "POST",
168
- headers: {
169
- "Content-Type": "application/json",
170
- "X-CSRF-Token": getCsrfToken()
171
- },
172
- credentials: "include",
173
- body: JSON.stringify(body)
174
- }
175
- );
159
+ const response = await fetch(`${basePath}/passkey/register/finish`, {
160
+ method: "POST",
161
+ headers: {
162
+ "Content-Type": "application/json",
163
+ "X-CSRF-Token": getCsrfToken()
164
+ },
165
+ credentials: "include",
166
+ body: JSON.stringify(body)
167
+ });
168
+ const data = await response.json();
169
+ return { response, data };
170
+ }
171
+ async function startPasskeyAuthAPI(basePath) {
172
+ const response = await fetch(`${basePath}/passkey/auth-start`, {
173
+ method: "POST",
174
+ headers: {
175
+ "Content-Type": "application/json"
176
+ },
177
+ credentials: "include"
178
+ });
179
+ const data = await response.json();
180
+ return { response, data };
181
+ }
182
+ async function finishPasskeyAuthAPI(basePath, body) {
183
+ const response = await fetch(`${basePath}/passkey/auth-finish`, {
184
+ method: "POST",
185
+ headers: {
186
+ "Content-Type": "application/json"
187
+ },
188
+ credentials: "include",
189
+ body: JSON.stringify(body)
190
+ });
176
191
  const data = await response.json();
177
192
  return { response, data };
178
193
  }
@@ -224,17 +239,16 @@ function bufferToBase64url(buffer) {
224
239
  async function createPasskeyCredential(options) {
225
240
  const publicKey = {
226
241
  ...options,
242
+ rp: { ...options.rp, id: window.location.hostname },
227
243
  challenge: base64urlToBuffer(options.challenge),
228
244
  user: {
229
245
  ...options.user,
230
246
  id: base64urlToBuffer(options.user.id)
231
247
  },
232
- excludeCredentials: (options.excludeCredentials ?? []).map(
233
- (c) => ({
234
- ...c,
235
- id: base64urlToBuffer(c.id)
236
- })
237
- )
248
+ excludeCredentials: (options.excludeCredentials ?? []).map((c) => ({
249
+ ...c,
250
+ id: base64urlToBuffer(c.id)
251
+ }))
238
252
  };
239
253
  const credential = await navigator.credentials.create({
240
254
  publicKey
@@ -248,20 +262,14 @@ async function createPasskeyCredential(options) {
248
262
  rawId: bufferToBase64url(credential.rawId),
249
263
  type: credential.type,
250
264
  response: {
251
- clientDataJSON: bufferToBase64url(
252
- attestation.clientDataJSON
253
- ),
254
- attestationObject: bufferToBase64url(
255
- attestation.attestationObject
256
- ),
265
+ clientDataJSON: bufferToBase64url(attestation.clientDataJSON),
266
+ attestationObject: bufferToBase64url(attestation.attestationObject),
257
267
  ...attestation.getTransports ? { transports: attestation.getTransports() } : {},
258
268
  ...attestation.getPublicKeyAlgorithm ? {
259
269
  publicKeyAlgorithm: attestation.getPublicKeyAlgorithm()
260
270
  } : {},
261
271
  ...attestation.getPublicKey ? {
262
- publicKey: bufferToBase64url(
263
- attestation.getPublicKey()
264
- )
272
+ publicKey: bufferToBase64url(attestation.getPublicKey())
265
273
  } : {},
266
274
  ...attestation.getAuthenticatorData ? {
267
275
  authenticatorData: bufferToBase64url(
@@ -273,6 +281,38 @@ async function createPasskeyCredential(options) {
273
281
  authenticatorAttachment: credential.authenticatorAttachment ?? void 0
274
282
  };
275
283
  }
284
+ async function getPasskeyCredential(options) {
285
+ const publicKey = {
286
+ challenge: base64urlToBuffer(options.challenge),
287
+ timeout: options.timeout,
288
+ rpId: window.location.hostname,
289
+ userVerification: options.userVerification || "preferred",
290
+ allowCredentials: (options.allowCredentials || []).map(
291
+ (c) => ({
292
+ ...c,
293
+ id: base64urlToBuffer(c.id)
294
+ })
295
+ )
296
+ };
297
+ const credential = await navigator.credentials.get({
298
+ publicKey
299
+ });
300
+ if (!credential) throw new Error("No credential returned");
301
+ const assertion = credential.response;
302
+ return {
303
+ id: credential.id,
304
+ rawId: bufferToBase64url(credential.rawId),
305
+ type: credential.type,
306
+ response: {
307
+ clientDataJSON: bufferToBase64url(assertion.clientDataJSON),
308
+ authenticatorData: bufferToBase64url(assertion.authenticatorData),
309
+ signature: bufferToBase64url(assertion.signature),
310
+ userHandle: assertion.userHandle ? bufferToBase64url(assertion.userHandle) : null
311
+ },
312
+ clientExtensionResults: credential.getClientExtensionResults(),
313
+ authenticatorAttachment: credential.authenticatorAttachment
314
+ };
315
+ }
276
316
 
277
317
  // src/reducer/dauth.actions.ts
278
318
  async function exchangeCodeAction(ctx, code) {
@@ -419,19 +459,15 @@ async function registerPasskeyAction(ctx, name) {
419
459
  onError(new Error("Failed to start passkey registration"));
420
460
  return null;
421
461
  }
422
- const credential = await createPasskeyCredential(
423
- startResult.data
424
- );
425
- const finishResult = await finishPasskeyRegistrationAPI(
426
- authProxyPath,
427
- { credential, name }
428
- );
462
+ const credential = await createPasskeyCredential(startResult.data);
463
+ const finishResult = await finishPasskeyRegistrationAPI(authProxyPath, {
464
+ credential,
465
+ name
466
+ });
429
467
  if (finishResult.response.status === 200 || finishResult.response.status === 201) {
430
468
  return finishResult.data.credential;
431
469
  }
432
- onError(
433
- new Error("Failed to finish passkey registration")
434
- );
470
+ onError(new Error("Failed to finish passkey registration"));
435
471
  return null;
436
472
  } catch (error) {
437
473
  onError(
@@ -449,9 +485,7 @@ async function deletePasskeyCredentialAction(ctx, credentialId) {
449
485
  );
450
486
  return result.response.status === 200;
451
487
  } catch (error) {
452
- onError(
453
- error instanceof Error ? error : new Error("Delete passkey error")
454
- );
488
+ onError(error instanceof Error ? error : new Error("Delete passkey error"));
455
489
  return false;
456
490
  }
457
491
  }
@@ -466,16 +500,69 @@ async function uploadAvatarAction(ctx, file) {
466
500
  });
467
501
  return true;
468
502
  }
469
- onError(
470
- new Error(
471
- "Avatar upload error: " + result.data.message
472
- )
503
+ onError(new Error("Avatar upload error: " + result.data.message));
504
+ return false;
505
+ } catch (error) {
506
+ onError(error instanceof Error ? error : new Error("Avatar upload error"));
507
+ return false;
508
+ }
509
+ }
510
+ async function loginWithPasskeyAction(ctx) {
511
+ const { dispatch, authProxyPath, onError } = ctx;
512
+ dispatch({
513
+ type: SET_IS_LOADING,
514
+ payload: { isLoading: true }
515
+ });
516
+ try {
517
+ const startResult = await startPasskeyAuthAPI(authProxyPath);
518
+ if (startResult.data.status !== "success" || !startResult.data.options) {
519
+ dispatch({
520
+ type: SET_IS_LOADING,
521
+ payload: { isLoading: false }
522
+ });
523
+ return false;
524
+ }
525
+ const credential = await getPasskeyCredential(
526
+ startResult.data.options
473
527
  );
528
+ const finishResult = await finishPasskeyAuthAPI(authProxyPath, {
529
+ credential,
530
+ sessionId: startResult.data.sessionId
531
+ });
532
+ if (finishResult.data.status === "login-success" && finishResult.data.redirect) {
533
+ const code = new URL(finishResult.data.redirect).searchParams.get("code");
534
+ if (code) {
535
+ const exchangeResult = await exchangeCodeAPI(authProxyPath, code);
536
+ if (exchangeResult.response.status === 200) {
537
+ dispatch({
538
+ type: LOGIN,
539
+ payload: {
540
+ user: exchangeResult.data.user,
541
+ domain: exchangeResult.data.domain,
542
+ isAuthenticated: true
543
+ }
544
+ });
545
+ dispatch({
546
+ type: SET_IS_LOADING,
547
+ payload: { isLoading: false }
548
+ });
549
+ return true;
550
+ }
551
+ }
552
+ }
553
+ dispatch({
554
+ type: SET_IS_LOADING,
555
+ payload: { isLoading: false }
556
+ });
474
557
  return false;
475
558
  } catch (error) {
476
559
  onError(
477
- error instanceof Error ? error : new Error("Avatar upload error")
560
+ error instanceof Error ? error : new Error("Passkey authentication error")
478
561
  );
562
+ dispatch({
563
+ type: SET_IS_LOADING,
564
+ payload: { isLoading: false }
565
+ });
479
566
  return false;
480
567
  }
481
568
  }
@@ -499,13 +586,7 @@ function setDauthUrl(url) {
499
586
  function checkIsLocalhost() {
500
587
  if (typeof window === "undefined") return false;
501
588
  const hostname = window.location.hostname;
502
- return hostname === "localhost" || hostname === "[::1]" || /^127(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/.test(
503
- hostname
504
- ) || /^192\.168(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){2}$/.test(
505
- hostname
506
- ) || /^10(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/.test(
507
- hostname
508
- );
589
+ return hostname === "localhost" || hostname === "[::1]" || /^127(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/.test(hostname) || /^192\.168(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){2}$/.test(hostname) || /^10(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/.test(hostname);
509
590
  }
510
591
  function getClientBasePath() {
511
592
  if (_dauthUrl) return _dauthUrl;
@@ -704,10 +785,7 @@ function useModalAnimation(open) {
704
785
  }
705
786
  if (phase === "entered" || phase === "entering") {
706
787
  setPhase("exiting");
707
- const timer = setTimeout(
708
- () => setPhase("exited"),
709
- MOBILE_TRANSITION_MS
710
- );
788
+ const timer = setTimeout(() => setPhase("exited"), MOBILE_TRANSITION_MS);
711
789
  return () => clearTimeout(timer);
712
790
  }
713
791
  return void 0;
@@ -857,18 +935,12 @@ function DauthProfileModal({
857
935
  }, [activeTab, showSecurity, getPasskeyCredentials]);
858
936
  useEffect(() => {
859
937
  if (status?.type !== "success") return;
860
- const timer = setTimeout(
861
- () => setStatus(null),
862
- SUCCESS_TIMEOUT_MS
863
- );
938
+ const timer = setTimeout(() => setStatus(null), SUCCESS_TIMEOUT_MS);
864
939
  return () => clearTimeout(timer);
865
940
  }, [status]);
866
941
  useEffect(() => {
867
942
  if (passkeyStatus?.type !== "success") return;
868
- const timer = setTimeout(
869
- () => setPasskeyStatus(null),
870
- SUCCESS_TIMEOUT_MS
871
- );
943
+ const timer = setTimeout(() => setPasskeyStatus(null), SUCCESS_TIMEOUT_MS);
872
944
  return () => clearTimeout(timer);
873
945
  }, [passkeyStatus]);
874
946
  useFocusTrap(modalRef, phase === "entered", onClose);
@@ -908,12 +980,9 @@ function DauthProfileModal({
908
980
  if (hasField("lastname")) fields.lastname = lastname;
909
981
  if (hasField("nickname")) fields.nickname = nickname;
910
982
  if (hasField("country")) fields.country = country;
911
- if (hasField("tel_prefix"))
912
- fields.telPrefix = telPrefix;
913
- if (hasField("tel_suffix"))
914
- fields.telSuffix = telSuffix;
915
- if (hasField("birth_date") && birthDate)
916
- fields.birthDate = birthDate;
983
+ if (hasField("tel_prefix")) fields.telPrefix = telPrefix;
984
+ if (hasField("tel_suffix")) fields.telSuffix = telSuffix;
985
+ if (hasField("birth_date") && birthDate) fields.birthDate = birthDate;
917
986
  if ((domain.customFields ?? []).length > 0)
918
987
  fields.customFields = customFieldValues;
919
988
  const ok = await updateUser(fields);
@@ -966,9 +1035,7 @@ function DauthProfileModal({
966
1035
  const handleRegisterPasskey = useCallback(async () => {
967
1036
  setRegistering(true);
968
1037
  setPasskeyStatus(null);
969
- const cred = await registerPasskey(
970
- passkeyName || void 0
971
- );
1038
+ const cred = await registerPasskey(passkeyName || void 0);
972
1039
  setRegistering(false);
973
1040
  if (cred) {
974
1041
  setCredentials((prev) => [...prev, cred]);
@@ -989,9 +1056,7 @@ function DauthProfileModal({
989
1056
  async (credentialId) => {
990
1057
  const ok = await deletePasskeyCredential(credentialId);
991
1058
  if (ok) {
992
- setCredentials(
993
- (prev) => prev.filter((c) => c._id !== credentialId)
994
- );
1059
+ setCredentials((prev) => prev.filter((c) => c._id !== credentialId));
995
1060
  }
996
1061
  },
997
1062
  [deletePasskeyCredential]
@@ -1031,15 +1096,11 @@ function DauthProfileModal({
1031
1096
  if (!t) return {};
1032
1097
  const vars = {};
1033
1098
  if (t.accent) vars["--dauth-accent"] = t.accent;
1034
- if (t.accentHover)
1035
- vars["--dauth-accent-hover"] = t.accentHover;
1099
+ if (t.accentHover) vars["--dauth-accent-hover"] = t.accentHover;
1036
1100
  if (t.surface) vars["--dauth-surface"] = t.surface;
1037
- if (t.surfaceHover)
1038
- vars["--dauth-surface-hover"] = t.surfaceHover;
1039
- if (t.textPrimary)
1040
- vars["--dauth-text-primary"] = t.textPrimary;
1041
- if (t.textSecondary)
1042
- vars["--dauth-text-secondary"] = t.textSecondary;
1101
+ if (t.surfaceHover) vars["--dauth-surface-hover"] = t.surfaceHover;
1102
+ if (t.textPrimary) vars["--dauth-text-primary"] = t.textPrimary;
1103
+ if (t.textSecondary) vars["--dauth-text-secondary"] = t.textSecondary;
1043
1104
  if (t.border) vars["--dauth-border"] = t.border;
1044
1105
  return vars;
1045
1106
  }, [domain.modalTheme]);
@@ -1206,14 +1267,7 @@ function DauthProfileModal({
1206
1267
  ),
1207
1268
  /* @__PURE__ */ jsxs("div", { children: [
1208
1269
  /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1209
- /* @__PURE__ */ jsx(
1210
- "label",
1211
- {
1212
- htmlFor: "dauth-name",
1213
- style: label,
1214
- children: "Name *"
1215
- }
1216
- ),
1270
+ /* @__PURE__ */ jsx("label", { htmlFor: "dauth-name", style: label, children: "Name *" }),
1217
1271
  /* @__PURE__ */ jsx(
1218
1272
  "input",
1219
1273
  {
@@ -1230,17 +1284,10 @@ function DauthProfileModal({
1230
1284
  )
1231
1285
  ] }),
1232
1286
  hasField("lastname") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1233
- /* @__PURE__ */ jsxs(
1234
- "label",
1235
- {
1236
- htmlFor: "dauth-lastname",
1237
- style: label,
1238
- children: [
1239
- "Last name",
1240
- isRequired("lastname") ? " *" : ""
1241
- ]
1242
- }
1243
- ),
1287
+ /* @__PURE__ */ jsxs("label", { htmlFor: "dauth-lastname", style: label, children: [
1288
+ "Last name",
1289
+ isRequired("lastname") ? " *" : ""
1290
+ ] }),
1244
1291
  /* @__PURE__ */ jsx(
1245
1292
  "input",
1246
1293
  {
@@ -1257,17 +1304,10 @@ function DauthProfileModal({
1257
1304
  )
1258
1305
  ] }),
1259
1306
  hasField("nickname") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1260
- /* @__PURE__ */ jsxs(
1261
- "label",
1262
- {
1263
- htmlFor: "dauth-nickname",
1264
- style: label,
1265
- children: [
1266
- "Nickname",
1267
- isRequired("nickname") ? " *" : ""
1268
- ]
1269
- }
1270
- ),
1307
+ /* @__PURE__ */ jsxs("label", { htmlFor: "dauth-nickname", style: label, children: [
1308
+ "Nickname",
1309
+ isRequired("nickname") ? " *" : ""
1310
+ ] }),
1271
1311
  /* @__PURE__ */ jsx(
1272
1312
  "input",
1273
1313
  {
@@ -1284,17 +1324,10 @@ function DauthProfileModal({
1284
1324
  )
1285
1325
  ] }),
1286
1326
  hasField("country") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1287
- /* @__PURE__ */ jsxs(
1288
- "label",
1289
- {
1290
- htmlFor: "dauth-country",
1291
- style: label,
1292
- children: [
1293
- "Country",
1294
- isRequired("country") ? " *" : ""
1295
- ]
1296
- }
1297
- ),
1327
+ /* @__PURE__ */ jsxs("label", { htmlFor: "dauth-country", style: label, children: [
1328
+ "Country",
1329
+ isRequired("country") ? " *" : ""
1330
+ ] }),
1298
1331
  /* @__PURE__ */ jsx(
1299
1332
  "input",
1300
1333
  {
@@ -1365,17 +1398,10 @@ function DauthProfileModal({
1365
1398
  )
1366
1399
  ] }),
1367
1400
  hasField("birth_date") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1368
- /* @__PURE__ */ jsxs(
1369
- "label",
1370
- {
1371
- htmlFor: "dauth-birthdate",
1372
- style: label,
1373
- children: [
1374
- "Birth date",
1375
- isRequired("birth_date") ? " *" : ""
1376
- ]
1377
- }
1378
- ),
1401
+ /* @__PURE__ */ jsxs("label", { htmlFor: "dauth-birthdate", style: label, children: [
1402
+ "Birth date",
1403
+ isRequired("birth_date") ? " *" : ""
1404
+ ] }),
1379
1405
  /* @__PURE__ */ jsx(
1380
1406
  "input",
1381
1407
  {
@@ -1392,44 +1418,28 @@ function DauthProfileModal({
1392
1418
  ] }),
1393
1419
  (domain.customFields ?? []).length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1394
1420
  /* @__PURE__ */ jsx("hr", { style: separator }),
1395
- domain.customFields.map((cf) => /* @__PURE__ */ jsxs(
1396
- "div",
1397
- {
1398
- style: fieldGroup,
1399
- children: [
1400
- /* @__PURE__ */ jsxs(
1401
- "label",
1402
- {
1403
- htmlFor: `dauth-cf-${cf.key}`,
1404
- style: label,
1405
- children: [
1406
- cf.label,
1407
- cf.required ? " *" : ""
1408
- ]
1409
- }
1410
- ),
1411
- /* @__PURE__ */ jsx(
1412
- "input",
1413
- {
1414
- id: `dauth-cf-${cf.key}`,
1415
- type: "text",
1416
- value: customFieldValues[cf.key] ?? "",
1417
- onChange: (e) => setCustomFieldValues(
1418
- (prev) => ({
1419
- ...prev,
1420
- [cf.key]: e.target.value
1421
- })
1422
- ),
1423
- disabled: saving,
1424
- style: input,
1425
- onFocus: inputFocusHandler,
1426
- onBlur: inputBlurHandler
1427
- }
1428
- )
1429
- ]
1430
- },
1431
- cf.key
1432
- ))
1421
+ domain.customFields.map((cf) => /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1422
+ /* @__PURE__ */ jsxs("label", { htmlFor: `dauth-cf-${cf.key}`, style: label, children: [
1423
+ cf.label,
1424
+ cf.required ? " *" : ""
1425
+ ] }),
1426
+ /* @__PURE__ */ jsx(
1427
+ "input",
1428
+ {
1429
+ id: `dauth-cf-${cf.key}`,
1430
+ type: "text",
1431
+ value: customFieldValues[cf.key] ?? "",
1432
+ onChange: (e) => setCustomFieldValues((prev) => ({
1433
+ ...prev,
1434
+ [cf.key]: e.target.value
1435
+ })),
1436
+ disabled: saving,
1437
+ style: input,
1438
+ onFocus: inputFocusHandler,
1439
+ onBlur: inputBlurHandler
1440
+ }
1441
+ )
1442
+ ] }, cf.key))
1433
1443
  ] })
1434
1444
  ] }),
1435
1445
  /* @__PURE__ */ jsx("hr", { style: separator }),
@@ -1489,14 +1499,7 @@ function DauthProfileModal({
1489
1499
  ),
1490
1500
  showRegister && /* @__PURE__ */ jsxs("div", { style: registerPanel, children: [
1491
1501
  /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1492
- /* @__PURE__ */ jsx(
1493
- "label",
1494
- {
1495
- htmlFor: "dauth-passkey-name",
1496
- style: label,
1497
- children: "Passkey name (optional)"
1498
- }
1499
- ),
1502
+ /* @__PURE__ */ jsx("label", { htmlFor: "dauth-passkey-name", style: label, children: "Passkey name (optional)" }),
1500
1503
  /* @__PURE__ */ jsx(
1501
1504
  "input",
1502
1505
  {
@@ -1572,89 +1575,82 @@ function DauthProfileModal({
1572
1575
  },
1573
1576
  children: /* @__PURE__ */ jsx(Spinner, {})
1574
1577
  }
1575
- ) : credentials.length > 0 ? credentials.map((cred) => /* @__PURE__ */ jsxs(
1576
- "div",
1577
- {
1578
- style: credentialRow,
1579
- children: [
1580
- /* @__PURE__ */ jsxs(
1581
- "div",
1582
- {
1583
- style: {
1584
- display: "flex",
1585
- alignItems: "center",
1586
- gap: 12,
1587
- flex: 1,
1588
- minWidth: 0
1589
- },
1590
- children: [
1591
- /* @__PURE__ */ jsx(
1592
- "span",
1593
- {
1594
- style: {
1595
- color: "var(--dauth-accent, #6366f1)",
1596
- flexShrink: 0
1597
- },
1598
- children: /* @__PURE__ */ jsx(IconFingerprint, {})
1599
- }
1600
- ),
1601
- /* @__PURE__ */ jsxs(
1602
- "div",
1603
- {
1604
- style: {
1605
- minWidth: 0,
1606
- flex: 1
1607
- },
1608
- children: [
1609
- /* @__PURE__ */ jsx(
1610
- "div",
1611
- {
1612
- style: {
1613
- fontSize: "var(--dauth-font-size-sm, 0.875rem)",
1614
- fontWeight: 500,
1615
- color: "var(--dauth-text-primary, #e4e4e7)",
1616
- overflow: "hidden",
1617
- textOverflow: "ellipsis",
1618
- whiteSpace: "nowrap"
1619
- },
1620
- children: cred.name || "Passkey"
1621
- }
1622
- ),
1623
- /* @__PURE__ */ jsxs(
1624
- "div",
1625
- {
1626
- style: {
1627
- fontSize: "var(--dauth-font-size-xs, 0.75rem)",
1628
- color: "var(--dauth-text-muted, #71717a)"
1629
- },
1630
- children: [
1631
- cred.deviceType === "multiDevice" ? "Synced" : "Device-bound",
1632
- cred.createdAt && ` \xB7 Created ${new Date(cred.createdAt).toLocaleDateString()}`
1633
- ]
1634
- }
1635
- )
1636
- ]
1637
- }
1638
- )
1639
- ]
1640
- }
1641
- ),
1642
- /* @__PURE__ */ jsx(
1643
- "button",
1644
- {
1645
- type: "button",
1646
- onClick: () => handleDeletePasskey(cred._id),
1647
- style: trashBtn,
1648
- onMouseEnter: (e) => e.currentTarget.style.color = "var(--dauth-error, #ef4444)",
1649
- onMouseLeave: (e) => e.currentTarget.style.color = "var(--dauth-text-muted, #71717a)",
1650
- "aria-label": `Delete passkey ${cred.name || ""}`,
1651
- children: /* @__PURE__ */ jsx(IconTrash, {})
1652
- }
1653
- )
1654
- ]
1655
- },
1656
- cred._id
1657
- )) : /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
1578
+ ) : credentials.length > 0 ? credentials.map((cred) => /* @__PURE__ */ jsxs("div", { style: credentialRow, children: [
1579
+ /* @__PURE__ */ jsxs(
1580
+ "div",
1581
+ {
1582
+ style: {
1583
+ display: "flex",
1584
+ alignItems: "center",
1585
+ gap: 12,
1586
+ flex: 1,
1587
+ minWidth: 0
1588
+ },
1589
+ children: [
1590
+ /* @__PURE__ */ jsx(
1591
+ "span",
1592
+ {
1593
+ style: {
1594
+ color: "var(--dauth-accent, #6366f1)",
1595
+ flexShrink: 0
1596
+ },
1597
+ children: /* @__PURE__ */ jsx(IconFingerprint, {})
1598
+ }
1599
+ ),
1600
+ /* @__PURE__ */ jsxs(
1601
+ "div",
1602
+ {
1603
+ style: {
1604
+ minWidth: 0,
1605
+ flex: 1
1606
+ },
1607
+ children: [
1608
+ /* @__PURE__ */ jsx(
1609
+ "div",
1610
+ {
1611
+ style: {
1612
+ fontSize: "var(--dauth-font-size-sm, 0.875rem)",
1613
+ fontWeight: 500,
1614
+ color: "var(--dauth-text-primary, #e4e4e7)",
1615
+ overflow: "hidden",
1616
+ textOverflow: "ellipsis",
1617
+ whiteSpace: "nowrap"
1618
+ },
1619
+ children: cred.name || "Passkey"
1620
+ }
1621
+ ),
1622
+ /* @__PURE__ */ jsxs(
1623
+ "div",
1624
+ {
1625
+ style: {
1626
+ fontSize: "var(--dauth-font-size-xs, 0.75rem)",
1627
+ color: "var(--dauth-text-muted, #71717a)"
1628
+ },
1629
+ children: [
1630
+ cred.deviceType === "multiDevice" ? "Synced" : "Device-bound",
1631
+ cred.createdAt && ` \xB7 Created ${new Date(cred.createdAt).toLocaleDateString()}`
1632
+ ]
1633
+ }
1634
+ )
1635
+ ]
1636
+ }
1637
+ )
1638
+ ]
1639
+ }
1640
+ ),
1641
+ /* @__PURE__ */ jsx(
1642
+ "button",
1643
+ {
1644
+ type: "button",
1645
+ onClick: () => handleDeletePasskey(cred._id),
1646
+ style: trashBtn,
1647
+ onMouseEnter: (e) => e.currentTarget.style.color = "var(--dauth-error, #ef4444)",
1648
+ onMouseLeave: (e) => e.currentTarget.style.color = "var(--dauth-text-muted, #71717a)",
1649
+ "aria-label": `Delete passkey ${cred.name || ""}`,
1650
+ children: /* @__PURE__ */ jsx(IconTrash, {})
1651
+ }
1652
+ )
1653
+ ] }, cred._id)) : /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
1658
1654
  /* @__PURE__ */ jsx(
1659
1655
  "span",
1660
1656
  {
@@ -2262,6 +2258,10 @@ var DauthProvider = (props) => {
2262
2258
  (file) => uploadAvatarAction(ctx, file),
2263
2259
  [ctx]
2264
2260
  );
2261
+ const loginWithPasskey = useCallback2(
2262
+ () => loginWithPasskeyAction(ctx),
2263
+ [ctx]
2264
+ );
2265
2265
  const memoProvider = useMemo2(
2266
2266
  () => ({
2267
2267
  ...dauthState,
@@ -2272,7 +2272,8 @@ var DauthProvider = (props) => {
2272
2272
  getPasskeyCredentials,
2273
2273
  registerPasskey,
2274
2274
  deletePasskeyCredential,
2275
- uploadAvatar
2275
+ uploadAvatar,
2276
+ loginWithPasskey
2276
2277
  }),
2277
2278
  [
2278
2279
  dauthState,
@@ -2283,7 +2284,8 @@ var DauthProvider = (props) => {
2283
2284
  getPasskeyCredentials,
2284
2285
  registerPasskey,
2285
2286
  deletePasskeyCredential,
2286
- uploadAvatar
2287
+ uploadAvatar,
2288
+ loginWithPasskey
2287
2289
  ]
2288
2290
  );
2289
2291
  return /* @__PURE__ */ jsx2(DauthContext.Provider, { value: memoProvider, children });