@delmaredigital/payload-better-auth 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useEffect } from 'react';
4
+ import { Button, Banner } from '@payloadcms/ui';
5
+ import { CopyIcon } from '@payloadcms/ui/icons/Copy';
4
6
  import { createPayloadAuthClient } from '../../exports/client.js';
5
7
  /**
6
8
  * Client component for two-factor authentication management.
7
9
  * Shows 2FA status and allows enabling/disabling.
8
- */ export function TwoFactorManagementClient({ authClient: providedClient, title = 'Two-Factor Authentication' } = {}) {
10
+ */ export function TwoFactorManagementClient({ authClient: providedClient, title = 'Two-Factor Authentication', onComplete } = {}) {
9
11
  const [isEnabled, setIsEnabled] = useState(false);
10
12
  const [loading, setLoading] = useState(true);
11
13
  const [error, setError] = useState(null);
@@ -43,8 +45,7 @@ import { createPayloadAuthClient } from '../../exports/client.js';
43
45
  setPassword('');
44
46
  setError(null);
45
47
  }
46
- async function handleEnableWithPassword(e) {
47
- e.preventDefault();
48
+ async function handleEnableWithPassword() {
48
49
  setActionLoading(true);
49
50
  setError(null);
50
51
  try {
@@ -69,8 +70,7 @@ import { createPayloadAuthClient } from '../../exports/client.js';
69
70
  setActionLoading(false);
70
71
  }
71
72
  }
72
- async function handleVerify(e) {
73
- e.preventDefault();
73
+ async function handleVerify() {
74
74
  setActionLoading(true);
75
75
  setError(null);
76
76
  try {
@@ -86,6 +86,7 @@ import { createPayloadAuthClient } from '../../exports/client.js';
86
86
  } else {
87
87
  setIsEnabled(true);
88
88
  setStep('status');
89
+ onComplete?.();
89
90
  }
90
91
  }
91
92
  } catch {
@@ -109,6 +110,7 @@ import { createPayloadAuthClient } from '../../exports/client.js';
109
110
  setError(result.error.message ?? 'Failed to disable 2FA');
110
111
  } else {
111
112
  setIsEnabled(false);
113
+ onComplete?.();
112
114
  }
113
115
  } catch {
114
116
  setError('Failed to disable 2FA');
@@ -119,186 +121,92 @@ import { createPayloadAuthClient } from '../../exports/client.js';
119
121
  function handleBackupContinue() {
120
122
  setIsEnabled(true);
121
123
  setStep('status');
124
+ onComplete?.();
122
125
  }
123
126
  if (loading) {
124
- return /*#__PURE__*/ _jsx("div", {
125
- style: {
126
- display: 'flex',
127
- alignItems: 'center',
128
- justifyContent: 'center',
129
- padding: 'calc(var(--base) * 3)'
130
- },
131
- children: /*#__PURE__*/ _jsx("div", {
132
- style: {
133
- color: 'var(--theme-text)',
134
- opacity: 0.7
135
- },
136
- children: "Loading..."
137
- })
127
+ return /*#__PURE__*/ _jsx("p", {
128
+ className: "field-description",
129
+ children: "Loading..."
138
130
  });
139
131
  }
140
132
  return /*#__PURE__*/ _jsxs("div", {
141
- style: {
142
- maxWidth: '600px',
143
- margin: '0 auto',
144
- padding: 'calc(var(--base) * 2)'
145
- },
133
+ className: "field-type two-factor-management",
146
134
  children: [
147
- /*#__PURE__*/ _jsx("h1", {
148
- style: {
149
- color: 'var(--theme-text)',
150
- fontSize: 'var(--font-size-h2)',
151
- fontWeight: 600,
152
- margin: '0 0 calc(var(--base) * 2) 0'
153
- },
154
- children: title
155
- }),
156
- error && /*#__PURE__*/ _jsx("div", {
157
- style: {
158
- color: 'var(--theme-error-500)',
159
- marginBottom: 'var(--base)',
160
- fontSize: 'var(--font-size-small)',
161
- padding: 'calc(var(--base) * 0.75)',
162
- background: 'var(--theme-error-50)',
163
- borderRadius: 'var(--style-radius-s)',
164
- border: '1px solid var(--theme-error-200)'
165
- },
135
+ error && /*#__PURE__*/ _jsx(Banner, {
136
+ type: "error",
166
137
  children: error
167
138
  }),
168
- step === 'status' && /*#__PURE__*/ _jsx("div", {
139
+ step === 'status' && /*#__PURE__*/ _jsxs("div", {
169
140
  style: {
170
- background: 'var(--theme-elevation-50)',
171
- padding: 'calc(var(--base) * 1.5)',
172
- borderRadius: 'var(--style-radius-m)',
173
- border: '1px solid var(--theme-elevation-100)'
174
- },
175
- children: /*#__PURE__*/ _jsxs("div", {
176
- style: {
177
- display: 'flex',
178
- justifyContent: 'space-between',
179
- alignItems: 'center'
180
- },
181
- children: [
182
- /*#__PURE__*/ _jsxs("div", {
183
- children: [
184
- /*#__PURE__*/ _jsx("div", {
185
- style: {
186
- color: 'var(--theme-text)',
187
- fontWeight: 500,
188
- marginBottom: 'calc(var(--base) * 0.25)'
189
- },
190
- children: "Status"
191
- }),
192
- /*#__PURE__*/ _jsx("div", {
193
- style: {
194
- color: isEnabled ? 'var(--theme-success-500)' : 'var(--theme-elevation-600)',
195
- fontSize: 'var(--font-size-small)'
196
- },
197
- children: isEnabled ? '✓ Enabled' : 'Not enabled'
198
- })
199
- ]
200
- }),
201
- /*#__PURE__*/ _jsx("button", {
202
- onClick: isEnabled ? handleDisable : handleEnableClick,
203
- disabled: actionLoading,
204
- style: {
205
- padding: 'calc(var(--base) * 0.5) calc(var(--base) * 1)',
206
- background: isEnabled ? 'var(--theme-error-500)' : 'var(--theme-elevation-800)',
207
- border: 'none',
208
- borderRadius: 'var(--style-radius-s)',
209
- color: 'var(--theme-elevation-50)',
210
- fontSize: 'var(--font-size-small)',
211
- cursor: actionLoading ? 'not-allowed' : 'pointer',
212
- opacity: actionLoading ? 0.7 : 1
213
- },
214
- children: actionLoading ? 'Loading...' : isEnabled ? 'Disable' : 'Enable'
215
- })
216
- ]
217
- })
218
- }),
219
- step === 'password' && /*#__PURE__*/ _jsxs("div", {
220
- style: {
221
- background: 'var(--theme-elevation-50)',
222
- padding: 'calc(var(--base) * 2)',
223
- borderRadius: 'var(--style-radius-m)',
224
- border: '1px solid var(--theme-elevation-100)'
141
+ display: 'flex',
142
+ justifyContent: 'space-between',
143
+ alignItems: 'center'
225
144
  },
226
145
  children: [
227
- /*#__PURE__*/ _jsx("h2", {
146
+ /*#__PURE__*/ _jsx("p", {
147
+ className: "field-description",
228
148
  style: {
229
- color: 'var(--theme-text)',
230
- fontSize: 'var(--font-size-h4)',
231
- fontWeight: 500,
232
- margin: '0 0 var(--base) 0'
149
+ margin: 0
233
150
  },
234
- children: "Confirm Your Password"
151
+ children: isEnabled ? 'Two-factor authentication is enabled.' : 'Two-factor authentication is not enabled.'
235
152
  }),
153
+ /*#__PURE__*/ _jsx(Button, {
154
+ buttonStyle: isEnabled ? 'error' : 'secondary',
155
+ size: "small",
156
+ onClick: isEnabled ? handleDisable : handleEnableClick,
157
+ disabled: actionLoading,
158
+ children: actionLoading ? 'Loading...' : isEnabled ? 'Disable' : 'Enable'
159
+ })
160
+ ]
161
+ }),
162
+ step === 'password' && /*#__PURE__*/ _jsxs("div", {
163
+ children: [
236
164
  /*#__PURE__*/ _jsx("p", {
165
+ className: "field-description",
166
+ children: "Enter your password to enable two-factor authentication."
167
+ }),
168
+ /*#__PURE__*/ _jsx("input", {
169
+ type: "password",
170
+ value: password,
171
+ onChange: (e)=>setPassword(e.target.value),
172
+ onKeyDown: (e)=>{
173
+ if (e.key === 'Enter' && password) {
174
+ e.preventDefault();
175
+ handleEnableWithPassword();
176
+ }
177
+ },
178
+ placeholder: "Enter your password",
179
+ className: "field-type__wrap",
237
180
  style: {
181
+ width: '100%',
182
+ padding: 'var(--base)',
183
+ background: 'var(--theme-input-bg)',
184
+ border: '1px solid var(--theme-border-color)',
185
+ borderRadius: 'var(--style-radius-s)',
238
186
  color: 'var(--theme-text)',
239
- opacity: 0.7,
240
- fontSize: 'var(--font-size-small)',
241
- marginBottom: 'calc(var(--base) * 1.5)'
242
- },
243
- children: "Enter your password to enable two-factor authentication."
187
+ fontSize: 'var(--base-body-size)',
188
+ marginBottom: 'var(--base)',
189
+ boxSizing: 'border-box'
190
+ }
244
191
  }),
245
- /*#__PURE__*/ _jsxs("form", {
246
- onSubmit: handleEnableWithPassword,
192
+ /*#__PURE__*/ _jsxs("div", {
193
+ style: {
194
+ display: 'flex',
195
+ gap: 'calc(var(--base) * 0.5)'
196
+ },
247
197
  children: [
248
- /*#__PURE__*/ _jsx("input", {
249
- type: "password",
250
- value: password,
251
- onChange: (e)=>setPassword(e.target.value),
252
- placeholder: "Enter your password",
253
- required: true,
254
- style: {
255
- width: '100%',
256
- padding: 'calc(var(--base) * 0.75)',
257
- background: 'var(--theme-input-bg)',
258
- border: '1px solid var(--theme-elevation-150)',
259
- borderRadius: 'var(--style-radius-s)',
260
- color: 'var(--theme-text)',
261
- fontSize: 'var(--font-size-base)',
262
- marginBottom: 'var(--base)',
263
- boxSizing: 'border-box'
264
- }
198
+ /*#__PURE__*/ _jsx(Button, {
199
+ buttonStyle: "primary",
200
+ size: "small",
201
+ onClick: handleEnableWithPassword,
202
+ disabled: actionLoading || !password,
203
+ children: actionLoading ? 'Enabling...' : 'Continue'
265
204
  }),
266
- /*#__PURE__*/ _jsxs("div", {
267
- style: {
268
- display: 'flex',
269
- gap: 'calc(var(--base) * 0.5)'
270
- },
271
- children: [
272
- /*#__PURE__*/ _jsx("button", {
273
- type: "submit",
274
- disabled: actionLoading || !password,
275
- style: {
276
- padding: 'calc(var(--base) * 0.75) calc(var(--base) * 1.5)',
277
- background: 'var(--theme-elevation-800)',
278
- border: 'none',
279
- borderRadius: 'var(--style-radius-s)',
280
- color: 'var(--theme-elevation-50)',
281
- fontSize: 'var(--font-size-base)',
282
- cursor: actionLoading || !password ? 'not-allowed' : 'pointer',
283
- opacity: actionLoading || !password ? 0.7 : 1
284
- },
285
- children: actionLoading ? 'Enabling...' : 'Continue'
286
- }),
287
- /*#__PURE__*/ _jsx("button", {
288
- type: "button",
289
- onClick: ()=>setStep('status'),
290
- style: {
291
- padding: 'calc(var(--base) * 0.75) calc(var(--base) * 1.5)',
292
- background: 'transparent',
293
- border: '1px solid var(--theme-elevation-200)',
294
- borderRadius: 'var(--style-radius-s)',
295
- color: 'var(--theme-text)',
296
- fontSize: 'var(--font-size-base)',
297
- cursor: 'pointer'
298
- },
299
- children: "Cancel"
300
- })
301
- ]
205
+ /*#__PURE__*/ _jsx(Button, {
206
+ buttonStyle: "secondary",
207
+ size: "small",
208
+ onClick: ()=>setStep('status'),
209
+ children: "Cancel"
302
210
  })
303
211
  ]
304
212
  })
@@ -306,18 +214,11 @@ import { createPayloadAuthClient } from '../../exports/client.js';
306
214
  }),
307
215
  step === 'setup' && totpUri && /*#__PURE__*/ _jsxs("div", {
308
216
  style: {
309
- background: 'var(--theme-elevation-50)',
310
- padding: 'calc(var(--base) * 2)',
311
- borderRadius: 'var(--style-radius-m)',
312
217
  textAlign: 'center'
313
218
  },
314
219
  children: [
315
220
  /*#__PURE__*/ _jsx("p", {
316
- style: {
317
- color: 'var(--theme-text)',
318
- opacity: 0.7,
319
- marginBottom: 'calc(var(--base) * 1.5)'
320
- },
221
+ className: "field-description",
321
222
  children: "Scan this QR code with your authenticator app:"
322
223
  }),
323
224
  /*#__PURE__*/ _jsx("img", {
@@ -326,7 +227,7 @@ import { createPayloadAuthClient } from '../../exports/client.js';
326
227
  style: {
327
228
  width: '200px',
328
229
  height: '200px',
329
- border: '1px solid var(--theme-elevation-150)',
230
+ border: '1px solid var(--theme-border-color)',
330
231
  borderRadius: 'var(--style-radius-s)',
331
232
  marginBottom: 'var(--base)'
332
233
  }
@@ -337,10 +238,8 @@ import { createPayloadAuthClient } from '../../exports/client.js';
337
238
  },
338
239
  children: [
339
240
  /*#__PURE__*/ _jsx("p", {
241
+ className: "field-description",
340
242
  style: {
341
- color: 'var(--theme-text)',
342
- opacity: 0.7,
343
- fontSize: 'var(--font-size-small)',
344
243
  marginBottom: 'calc(var(--base) * 0.5)'
345
244
  },
346
245
  children: "Or enter manually:"
@@ -352,15 +251,14 @@ import { createPayloadAuthClient } from '../../exports/client.js';
352
251
  background: 'var(--theme-elevation-100)',
353
252
  borderRadius: 'var(--style-radius-s)',
354
253
  fontFamily: 'monospace',
355
- fontSize: 'var(--font-size-small)',
254
+ fontSize: 'var(--base-body-size)',
356
255
  color: 'var(--theme-text)'
357
256
  },
358
257
  children: secret
359
258
  })
360
259
  ]
361
260
  }),
362
- /*#__PURE__*/ _jsxs("form", {
363
- onSubmit: handleVerify,
261
+ /*#__PURE__*/ _jsxs("div", {
364
262
  children: [
365
263
  /*#__PURE__*/ _jsx("input", {
366
264
  type: "text",
@@ -368,16 +266,21 @@ import { createPayloadAuthClient } from '../../exports/client.js';
368
266
  pattern: "[0-9]*",
369
267
  value: verificationCode,
370
268
  onChange: (e)=>setVerificationCode(e.target.value.replace(/\D/g, '').slice(0, 6)),
371
- placeholder: "Enter 6-digit code",
269
+ onKeyDown: (e)=>{
270
+ if (e.key === 'Enter' && verificationCode.length === 6) {
271
+ e.preventDefault();
272
+ handleVerify();
273
+ }
274
+ },
275
+ placeholder: "000000",
372
276
  style: {
373
- width: '100%',
374
- maxWidth: '200px',
375
- padding: 'calc(var(--base) * 0.75)',
277
+ width: '200px',
278
+ padding: 'var(--base)',
376
279
  background: 'var(--theme-input-bg)',
377
- border: '1px solid var(--theme-elevation-150)',
280
+ border: '1px solid var(--theme-border-color)',
378
281
  borderRadius: 'var(--style-radius-s)',
379
282
  color: 'var(--theme-text)',
380
- fontSize: 'var(--font-size-h4)',
283
+ fontSize: '1.5rem',
381
284
  fontFamily: 'monospace',
382
285
  textAlign: 'center',
383
286
  letterSpacing: '0.5em',
@@ -386,19 +289,11 @@ import { createPayloadAuthClient } from '../../exports/client.js';
386
289
  }
387
290
  }),
388
291
  /*#__PURE__*/ _jsx("br", {}),
389
- /*#__PURE__*/ _jsx("button", {
390
- type: "submit",
292
+ /*#__PURE__*/ _jsx(Button, {
293
+ buttonStyle: "primary",
294
+ size: "small",
295
+ onClick: handleVerify,
391
296
  disabled: actionLoading || verificationCode.length !== 6,
392
- style: {
393
- padding: 'calc(var(--base) * 0.75) calc(var(--base) * 2)',
394
- background: 'var(--theme-elevation-800)',
395
- border: 'none',
396
- borderRadius: 'var(--style-radius-s)',
397
- color: 'var(--theme-elevation-50)',
398
- fontSize: 'var(--font-size-base)',
399
- cursor: actionLoading || verificationCode.length !== 6 ? 'not-allowed' : 'pointer',
400
- opacity: actionLoading || verificationCode.length !== 6 ? 0.7 : 1
401
- },
402
297
  children: actionLoading ? 'Verifying...' : 'Verify'
403
298
  })
404
299
  ]
@@ -406,37 +301,17 @@ import { createPayloadAuthClient } from '../../exports/client.js';
406
301
  ]
407
302
  }),
408
303
  step === 'backup' && /*#__PURE__*/ _jsxs("div", {
409
- style: {
410
- background: 'var(--theme-elevation-50)',
411
- padding: 'calc(var(--base) * 2)',
412
- borderRadius: 'var(--style-radius-m)'
413
- },
414
304
  children: [
415
- /*#__PURE__*/ _jsx("h2", {
416
- style: {
417
- color: 'var(--theme-text)',
418
- fontSize: 'var(--font-size-h3)',
419
- fontWeight: 600,
420
- margin: '0 0 var(--base) 0',
421
- textAlign: 'center'
422
- },
423
- children: "Save Your Backup Codes"
424
- }),
425
- /*#__PURE__*/ _jsx("p", {
426
- style: {
427
- color: 'var(--theme-text)',
428
- opacity: 0.7,
429
- fontSize: 'var(--font-size-small)',
430
- textAlign: 'center',
431
- marginBottom: 'calc(var(--base) * 1.5)'
432
- },
433
- children: "Store these codes safely. Use them if you lose your authenticator."
305
+ /*#__PURE__*/ _jsx(Banner, {
306
+ type: "info",
307
+ children: "Save these backup codes in a safe place. You can use them to sign in if you lose access to your authenticator app."
434
308
  }),
435
309
  /*#__PURE__*/ _jsx("div", {
436
310
  style: {
437
311
  background: 'var(--theme-elevation-100)',
438
312
  padding: 'var(--base)',
439
313
  borderRadius: 'var(--style-radius-s)',
314
+ marginTop: 'var(--base)',
440
315
  marginBottom: 'var(--base)',
441
316
  fontFamily: 'monospace'
442
317
  },
@@ -455,34 +330,26 @@ import { createPayloadAuthClient } from '../../exports/client.js';
455
330
  }, index))
456
331
  })
457
332
  }),
458
- /*#__PURE__*/ _jsx("button", {
459
- onClick: ()=>navigator.clipboard.writeText(backupCodes.join('\n')),
460
- style: {
461
- width: '100%',
462
- padding: 'calc(var(--base) * 0.5)',
463
- background: 'var(--theme-elevation-150)',
464
- border: 'none',
465
- borderRadius: 'var(--style-radius-s)',
466
- color: 'var(--theme-text)',
467
- fontSize: 'var(--font-size-small)',
468
- cursor: 'pointer',
469
- marginBottom: 'var(--base)'
470
- },
471
- children: "Copy to Clipboard"
472
- }),
473
- /*#__PURE__*/ _jsx("button", {
474
- onClick: handleBackupContinue,
333
+ /*#__PURE__*/ _jsxs("div", {
475
334
  style: {
476
- width: '100%',
477
- padding: 'calc(var(--base) * 0.75)',
478
- background: 'var(--theme-elevation-800)',
479
- border: 'none',
480
- borderRadius: 'var(--style-radius-s)',
481
- color: 'var(--theme-elevation-50)',
482
- fontSize: 'var(--font-size-base)',
483
- cursor: 'pointer'
335
+ display: 'flex',
336
+ gap: 'calc(var(--base) * 0.5)'
484
337
  },
485
- children: "I've Saved My Codes"
338
+ children: [
339
+ /*#__PURE__*/ _jsx(Button, {
340
+ buttonStyle: "secondary",
341
+ size: "small",
342
+ icon: /*#__PURE__*/ _jsx(CopyIcon, {}),
343
+ onClick: ()=>navigator.clipboard.writeText(backupCodes.join('\n')),
344
+ children: "Copy to Clipboard"
345
+ }),
346
+ /*#__PURE__*/ _jsx(Button, {
347
+ buttonStyle: "primary",
348
+ size: "small",
349
+ onClick: handleBackupContinue,
350
+ children: "I've Saved My Codes"
351
+ })
352
+ ]
486
353
  })
487
354
  ]
488
355
  })
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Thin wrapper around PasskeysManagementClient for use as a Payload `ui` field.
3
+ */
4
+ export declare function PasskeysField(): import("react").JSX.Element;
5
+ export default PasskeysField;
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { PasskeysManagementClient } from '../PasskeysManagementClient.js';
4
+ /**
5
+ * Thin wrapper around PasskeysManagementClient for use as a Payload `ui` field.
6
+ */ export function PasskeysField() {
7
+ return /*#__PURE__*/ _jsx(PasskeysManagementClient, {});
8
+ }
9
+ export default PasskeysField;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Wrapper around TwoFactorManagementClient for use as a Payload `ui` field.
3
+ *
4
+ * After 2FA is enabled or disabled, triggers a Next.js router refresh so that
5
+ * the document form re-fetches from the DB and picks up the `twoFactorEnabled`
6
+ * value that Better Auth wrote. Without this, navigating away without clicking
7
+ * Save would overwrite the change.
8
+ */
9
+ export declare function TwoFactorField(): import("react").JSX.Element;
10
+ export default TwoFactorField;
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useRouter } from 'next/navigation.js';
4
+ import { useCallback } from 'react';
5
+ import { TwoFactorManagementClient } from '../TwoFactorManagementClient.js';
6
+ /**
7
+ * Wrapper around TwoFactorManagementClient for use as a Payload `ui` field.
8
+ *
9
+ * After 2FA is enabled or disabled, triggers a Next.js router refresh so that
10
+ * the document form re-fetches from the DB and picks up the `twoFactorEnabled`
11
+ * value that Better Auth wrote. Without this, navigating away without clicking
12
+ * Save would overwrite the change.
13
+ */ export function TwoFactorField() {
14
+ const router = useRouter();
15
+ const handleComplete = useCallback(()=>{
16
+ router.refresh();
17
+ }, [
18
+ router
19
+ ]);
20
+ return /*#__PURE__*/ _jsx(TwoFactorManagementClient, {
21
+ onComplete: handleComplete
22
+ });
23
+ }
24
+ export default TwoFactorField;
@@ -21,3 +21,5 @@ export type { PasskeySignInButtonProps } from '../components/PasskeySignInButton
21
21
  export { PasskeySignInButton } from '../components/PasskeySignInButton.js';
22
22
  export type { PasskeyRegisterButtonProps } from '../components/PasskeyRegisterButton.js';
23
23
  export { PasskeyRegisterButton } from '../components/PasskeyRegisterButton.js';
24
+ export { TwoFactorField } from '../components/management/fields/TwoFactorField.js';
25
+ export { PasskeysField } from '../components/management/fields/PasskeysField.js';
@@ -12,3 +12,6 @@ export { TwoFactorSetupView } from '../components/twoFactor/TwoFactorSetupView.j
12
12
  export { TwoFactorVerifyView } from '../components/twoFactor/TwoFactorVerifyView.js';
13
13
  export { PasskeySignInButton } from '../components/PasskeySignInButton.js';
14
14
  export { PasskeyRegisterButton } from '../components/PasskeyRegisterButton.js';
15
+ // Management UI field wrappers (for Payload ui fields)
16
+ export { TwoFactorField } from '../components/management/fields/TwoFactorField.js';
17
+ export { PasskeysField } from '../components/management/fields/PasskeysField.js';