@massimo.mazzoleni/cognito-max 1.0.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.
Files changed (64) hide show
  1. package/README.md +2410 -0
  2. package/dist/chunk-AD7T42HJ.js +3 -0
  3. package/dist/chunk-AD7T42HJ.js.map +1 -0
  4. package/dist/chunk-DKPFVGTY.js +683 -0
  5. package/dist/chunk-DKPFVGTY.js.map +1 -0
  6. package/dist/chunk-N4OQLBV6.js +135 -0
  7. package/dist/chunk-N4OQLBV6.js.map +1 -0
  8. package/dist/client-63FraVdm.d.ts +69 -0
  9. package/dist/client-BAoL8h4E.d.cts +69 -0
  10. package/dist/core/index.cjs +696 -0
  11. package/dist/core/index.cjs.map +1 -0
  12. package/dist/core/index.d.cts +3 -0
  13. package/dist/core/index.d.ts +3 -0
  14. package/dist/core/index.js +4 -0
  15. package/dist/core/index.js.map +1 -0
  16. package/dist/errors-BkUDHleb.d.cts +22 -0
  17. package/dist/errors-BkUDHleb.d.ts +22 -0
  18. package/dist/index.cjs +696 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.cts +3 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.js +4 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/react/index.cjs +844 -0
  25. package/dist/react/index.cjs.map +1 -0
  26. package/dist/react/index.d.cts +104 -0
  27. package/dist/react/index.d.ts +104 -0
  28. package/dist/react/index.js +64 -0
  29. package/dist/react/index.js.map +1 -0
  30. package/dist/types-bxA1vonL.d.cts +113 -0
  31. package/dist/types-bxA1vonL.d.ts +113 -0
  32. package/dist/ui/index.cjs +1183 -0
  33. package/dist/ui/index.cjs.map +1 -0
  34. package/dist/ui/index.d.cts +241 -0
  35. package/dist/ui/index.d.ts +241 -0
  36. package/dist/ui/index.js +1109 -0
  37. package/dist/ui/index.js.map +1 -0
  38. package/package.json +81 -0
  39. package/src/core/client.ts +604 -0
  40. package/src/core/errors.ts +91 -0
  41. package/src/core/event-bus.ts +41 -0
  42. package/src/core/index.ts +5 -0
  43. package/src/core/internal/converters.ts +32 -0
  44. package/src/core/storage.ts +79 -0
  45. package/src/core/types.ts +87 -0
  46. package/src/index.ts +1 -0
  47. package/src/react/components/ProtectedRoute.tsx +56 -0
  48. package/src/react/context.tsx +126 -0
  49. package/src/react/hooks/useAuth.ts +75 -0
  50. package/src/react/hooks/useMfa.ts +19 -0
  51. package/src/react/hooks/useSession.ts +16 -0
  52. package/src/react/hooks/useUser.ts +24 -0
  53. package/src/react/index.ts +10 -0
  54. package/src/ui/components/ChangePasswordForm.tsx +105 -0
  55. package/src/ui/components/ForgotPasswordForm.tsx +159 -0
  56. package/src/ui/components/MfaSetupWizard.tsx +136 -0
  57. package/src/ui/components/RegisterForm.tsx +159 -0
  58. package/src/ui/components/SignInForm.tsx +296 -0
  59. package/src/ui/hooks/useChangePasswordForm.ts +81 -0
  60. package/src/ui/hooks/useForgotPasswordForm.ts +109 -0
  61. package/src/ui/hooks/useMfaSetup.ts +93 -0
  62. package/src/ui/hooks/useRegisterForm.ts +120 -0
  63. package/src/ui/hooks/useSignInForm.ts +245 -0
  64. package/src/ui/index.ts +31 -0
@@ -0,0 +1,1109 @@
1
+ import { useAuth, useMfa } from '../chunk-N4OQLBV6.js';
2
+ import '../chunk-DKPFVGTY.js';
3
+ import { useState, useCallback, useId, useRef, useEffect } from 'react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function useSignInForm(options = {}) {
7
+ const {
8
+ signIn,
9
+ respondToMfaChallenge,
10
+ respondToNewPasswordChallenge,
11
+ setupTotpChallenge,
12
+ verifyTotpChallenge
13
+ } = useAuth();
14
+ const [step, setStep] = useState("credentials");
15
+ const [isLoading, setLoading] = useState(false);
16
+ const [error, setError] = useState(null);
17
+ const [email, setEmail] = useState("");
18
+ const [password, setPassword] = useState("");
19
+ const [mfaType, setMfaType] = useState(null);
20
+ const [challengeSession, setChallengeSession] = useState(null);
21
+ const [mfaCode, setMfaCode] = useState("");
22
+ const [newPwd, setNewPwd] = useState("");
23
+ const [confirmPwd, setConfirmPwd] = useState("");
24
+ const [requiredAttributes, setRequiredAttributes] = useState([]);
25
+ const [mfaSetupQrCodeUri, setMfaSetupQrCodeUri] = useState(null);
26
+ const [mfaSetupSecretCode, setMfaSetupSecretCode] = useState(null);
27
+ const [mfaSetupTotpCode, setMfaSetupTotpCode] = useState("");
28
+ const handleSignInResult = useCallback(
29
+ (result) => {
30
+ if (result.status === "SUCCESS") {
31
+ options.onSuccess?.(result);
32
+ } else if (result.status === "MFA_REQUIRED") {
33
+ setMfaType(result.mfaType);
34
+ setChallengeSession(result.challengeSession);
35
+ setStep("mfa");
36
+ } else if (result.status === "NEW_PASSWORD_REQUIRED") {
37
+ setChallengeSession(result.challengeSession);
38
+ setRequiredAttributes(result.requiredAttributes);
39
+ setStep("new_password");
40
+ } else if (result.status === "MFA_SETUP_REQUIRED") {
41
+ setChallengeSession(result.challengeSession);
42
+ setStep("mfa_setup");
43
+ }
44
+ },
45
+ [options]
46
+ );
47
+ const handleCredentialsSubmit = useCallback(
48
+ async (e) => {
49
+ e.preventDefault();
50
+ setError(null);
51
+ setLoading(true);
52
+ try {
53
+ const result = await signIn(email, password);
54
+ handleSignInResult(result);
55
+ } catch (err) {
56
+ const authErr = err;
57
+ setError(authErr);
58
+ options.onError?.(authErr);
59
+ } finally {
60
+ setLoading(false);
61
+ }
62
+ },
63
+ [email, password, signIn, handleSignInResult, options]
64
+ );
65
+ const handleMfaSubmit = useCallback(
66
+ async (e) => {
67
+ e.preventDefault();
68
+ if (!challengeSession || !mfaType) return;
69
+ setError(null);
70
+ setLoading(true);
71
+ try {
72
+ const result = await respondToMfaChallenge(challengeSession, mfaCode, mfaType);
73
+ handleSignInResult(result);
74
+ } catch (err) {
75
+ const authErr = err;
76
+ setError(authErr);
77
+ options.onError?.(authErr);
78
+ } finally {
79
+ setLoading(false);
80
+ }
81
+ },
82
+ [challengeSession, mfaType, mfaCode, respondToMfaChallenge, handleSignInResult, options]
83
+ );
84
+ const handleNewPasswordSubmit = useCallback(
85
+ async (e) => {
86
+ e.preventDefault();
87
+ if (!challengeSession) return;
88
+ if (newPwd !== confirmPwd) {
89
+ setError({ message: "Le password non coincidono", code: "INVALID_PASSWORD" });
90
+ return;
91
+ }
92
+ setError(null);
93
+ setLoading(true);
94
+ try {
95
+ const result = await respondToNewPasswordChallenge(challengeSession, newPwd);
96
+ handleSignInResult(result);
97
+ } catch (err) {
98
+ const authErr = err;
99
+ setError(authErr);
100
+ options.onError?.(authErr);
101
+ } finally {
102
+ setLoading(false);
103
+ }
104
+ },
105
+ [challengeSession, newPwd, confirmPwd, respondToNewPasswordChallenge, handleSignInResult, options]
106
+ );
107
+ const handleMfaSetupStart = useCallback(async () => {
108
+ if (!challengeSession) return;
109
+ setError(null);
110
+ setLoading(true);
111
+ try {
112
+ const result = await setupTotpChallenge(challengeSession);
113
+ setMfaSetupQrCodeUri(result.qrCodeUri);
114
+ setMfaSetupSecretCode(result.secretCode);
115
+ } catch (err) {
116
+ const authErr = err;
117
+ setError(authErr);
118
+ options.onError?.(authErr);
119
+ } finally {
120
+ setLoading(false);
121
+ }
122
+ }, [challengeSession, setupTotpChallenge, options]);
123
+ const handleMfaSetupVerify = useCallback(
124
+ async (e) => {
125
+ e.preventDefault();
126
+ if (!challengeSession) return;
127
+ setError(null);
128
+ setLoading(true);
129
+ try {
130
+ const result = await verifyTotpChallenge(challengeSession, mfaSetupTotpCode);
131
+ handleSignInResult(result);
132
+ } catch (err) {
133
+ const authErr = err;
134
+ setError(authErr);
135
+ options.onError?.(authErr);
136
+ } finally {
137
+ setLoading(false);
138
+ }
139
+ },
140
+ [challengeSession, mfaSetupTotpCode, verifyTotpChallenge, handleSignInResult, options]
141
+ );
142
+ const reset = useCallback(() => {
143
+ setStep("credentials");
144
+ setEmail("");
145
+ setPassword("");
146
+ setMfaCode("");
147
+ setNewPwd("");
148
+ setConfirmPwd("");
149
+ setError(null);
150
+ setMfaType(null);
151
+ setChallengeSession(null);
152
+ setMfaSetupQrCodeUri(null);
153
+ setMfaSetupSecretCode(null);
154
+ setMfaSetupTotpCode("");
155
+ }, []);
156
+ return {
157
+ step,
158
+ isLoading,
159
+ error,
160
+ mfaType,
161
+ credentials: { email, password, setEmail, setPassword, onSubmit: handleCredentialsSubmit },
162
+ mfa: { code: mfaCode, setCode: setMfaCode, onSubmit: handleMfaSubmit },
163
+ newPassword: {
164
+ password: newPwd,
165
+ confirmPassword: confirmPwd,
166
+ requiredAttributes,
167
+ setPassword: setNewPwd,
168
+ setConfirmPassword: setConfirmPwd,
169
+ onSubmit: handleNewPasswordSubmit
170
+ },
171
+ mfaSetup: {
172
+ qrCodeUri: mfaSetupQrCodeUri,
173
+ secretCode: mfaSetupSecretCode,
174
+ totpCode: mfaSetupTotpCode,
175
+ setTotpCode: setMfaSetupTotpCode,
176
+ start: handleMfaSetupStart,
177
+ onVerify: handleMfaSetupVerify
178
+ },
179
+ reset
180
+ };
181
+ }
182
+ function useRegisterForm(options = {}) {
183
+ const { signUp, confirmSignUp, resendConfirmationCode } = useAuth();
184
+ const [step, setStep] = useState("register");
185
+ const [isLoading, setLoading] = useState(false);
186
+ const [error, setError] = useState(null);
187
+ const [email, setEmail] = useState("");
188
+ const [password, setPassword] = useState("");
189
+ const [confirmPassword, setConfirmPassword] = useState("");
190
+ const [code, setCode] = useState("");
191
+ const handleRegisterSubmit = useCallback(
192
+ async (e) => {
193
+ e.preventDefault();
194
+ if (password !== confirmPassword) {
195
+ setError({ message: "Le password non coincidono", code: "INVALID_PASSWORD" });
196
+ return;
197
+ }
198
+ setError(null);
199
+ setLoading(true);
200
+ try {
201
+ await signUp(email, password, options.extraAttributes);
202
+ setStep("confirm");
203
+ } catch (err) {
204
+ const authErr = err;
205
+ setError(authErr);
206
+ options.onError?.(authErr);
207
+ } finally {
208
+ setLoading(false);
209
+ }
210
+ },
211
+ [email, password, confirmPassword, signUp, options]
212
+ );
213
+ const handleConfirmSubmit = useCallback(
214
+ async (e) => {
215
+ e.preventDefault();
216
+ setError(null);
217
+ setLoading(true);
218
+ try {
219
+ await confirmSignUp(email, code);
220
+ options.onSuccess?.();
221
+ } catch (err) {
222
+ const authErr = err;
223
+ setError(authErr);
224
+ options.onError?.(authErr);
225
+ } finally {
226
+ setLoading(false);
227
+ }
228
+ },
229
+ [email, code, confirmSignUp, options]
230
+ );
231
+ const resend = useCallback(async () => {
232
+ setError(null);
233
+ try {
234
+ await resendConfirmationCode(email);
235
+ } catch (err) {
236
+ setError(err);
237
+ }
238
+ }, [email, resendConfirmationCode]);
239
+ const reset = useCallback(() => {
240
+ setStep("register");
241
+ setEmail("");
242
+ setPassword("");
243
+ setConfirmPassword("");
244
+ setCode("");
245
+ setError(null);
246
+ }, []);
247
+ return {
248
+ step,
249
+ isLoading,
250
+ error,
251
+ register: { email, password, confirmPassword, setEmail, setPassword, setConfirmPassword, onSubmit: handleRegisterSubmit },
252
+ confirm: { email, code, setCode, onSubmit: handleConfirmSubmit, resend },
253
+ reset
254
+ };
255
+ }
256
+ function useForgotPasswordForm(options = {}) {
257
+ const { forgotPassword, confirmForgotPassword } = useAuth();
258
+ const [step, setStep] = useState("request");
259
+ const [isLoading, setLoading] = useState(false);
260
+ const [error, setError] = useState(null);
261
+ const [email, setEmail] = useState("");
262
+ const [code, setCode] = useState("");
263
+ const [newPassword, setNewPassword] = useState("");
264
+ const [confirmPassword, setConfirmPassword] = useState("");
265
+ const handleRequestSubmit = useCallback(
266
+ async (e) => {
267
+ e.preventDefault();
268
+ setError(null);
269
+ setLoading(true);
270
+ try {
271
+ await forgotPassword(email);
272
+ setStep("reset");
273
+ } catch (err) {
274
+ const authErr = err;
275
+ setError(authErr);
276
+ options.onError?.(authErr);
277
+ } finally {
278
+ setLoading(false);
279
+ }
280
+ },
281
+ [email, forgotPassword, options]
282
+ );
283
+ const handleResetSubmit = useCallback(
284
+ async (e) => {
285
+ e.preventDefault();
286
+ if (newPassword !== confirmPassword) {
287
+ setError({ message: "Le password non coincidono", code: "INVALID_PASSWORD" });
288
+ return;
289
+ }
290
+ setError(null);
291
+ setLoading(true);
292
+ try {
293
+ await confirmForgotPassword(email, code, newPassword);
294
+ options.onSuccess?.();
295
+ } catch (err) {
296
+ const authErr = err;
297
+ setError(authErr);
298
+ options.onError?.(authErr);
299
+ } finally {
300
+ setLoading(false);
301
+ }
302
+ },
303
+ [email, code, newPassword, confirmPassword, confirmForgotPassword, options]
304
+ );
305
+ const restart = useCallback(() => {
306
+ setStep("request");
307
+ setCode("");
308
+ setNewPassword("");
309
+ setConfirmPassword("");
310
+ setError(null);
311
+ }, []);
312
+ return {
313
+ step,
314
+ isLoading,
315
+ error,
316
+ request: { email, setEmail, onSubmit: handleRequestSubmit },
317
+ reset: { email, code, newPassword, confirmPassword, setCode, setNewPassword, setConfirmPassword, onSubmit: handleResetSubmit },
318
+ restart
319
+ };
320
+ }
321
+ function useChangePasswordForm(options = {}) {
322
+ const { changePassword } = useAuth();
323
+ const [isLoading, setLoading] = useState(false);
324
+ const [error, setError] = useState(null);
325
+ const [success, setSuccess] = useState(false);
326
+ const [currentPassword, setCurrentPassword] = useState("");
327
+ const [newPassword, setNewPassword] = useState("");
328
+ const [confirmPassword, setConfirmPassword] = useState("");
329
+ const handleSubmit = useCallback(
330
+ async (e) => {
331
+ e.preventDefault();
332
+ if (newPassword !== confirmPassword) {
333
+ setError({ message: "Le nuove password non coincidono", code: "INVALID_PASSWORD" });
334
+ return;
335
+ }
336
+ setError(null);
337
+ setLoading(true);
338
+ try {
339
+ await changePassword(currentPassword, newPassword);
340
+ setSuccess(true);
341
+ options.onSuccess?.();
342
+ } catch (err) {
343
+ const authErr = err;
344
+ setError(authErr);
345
+ options.onError?.(authErr);
346
+ } finally {
347
+ setLoading(false);
348
+ }
349
+ },
350
+ [currentPassword, newPassword, confirmPassword, changePassword, options]
351
+ );
352
+ const reset = useCallback(() => {
353
+ setCurrentPassword("");
354
+ setNewPassword("");
355
+ setConfirmPassword("");
356
+ setError(null);
357
+ setSuccess(false);
358
+ }, []);
359
+ return {
360
+ isLoading,
361
+ error,
362
+ success,
363
+ currentPassword,
364
+ newPassword,
365
+ confirmPassword,
366
+ setCurrentPassword,
367
+ setNewPassword,
368
+ setConfirmPassword,
369
+ onSubmit: handleSubmit,
370
+ reset
371
+ };
372
+ }
373
+ function useMfaSetup(options = {}) {
374
+ const { setup, verifySetup } = useMfa();
375
+ const [step, setStep] = useState("idle");
376
+ const [error, setError] = useState(null);
377
+ const [qrCodeUri, setQrCodeUri] = useState(null);
378
+ const [secretCode, setSecretCode] = useState(null);
379
+ const [totpCode, setTotpCode] = useState("");
380
+ const start = useCallback(async () => {
381
+ setError(null);
382
+ setStep("loading");
383
+ try {
384
+ const result = await setup();
385
+ setQrCodeUri(result.qrCodeUri);
386
+ setSecretCode(result.secretCode);
387
+ setStep("scan");
388
+ } catch (err) {
389
+ const authErr = err;
390
+ setError(authErr);
391
+ setStep("idle");
392
+ options.onError?.(authErr);
393
+ }
394
+ }, [setup, options]);
395
+ const handleVerify = useCallback(
396
+ async (e) => {
397
+ e.preventDefault();
398
+ setError(null);
399
+ setStep("loading");
400
+ try {
401
+ await verifySetup(totpCode);
402
+ setStep("done");
403
+ options.onSuccess?.();
404
+ } catch (err) {
405
+ const authErr = err;
406
+ setError(authErr);
407
+ setStep("verify");
408
+ options.onError?.(authErr);
409
+ }
410
+ },
411
+ [totpCode, verifySetup, options]
412
+ );
413
+ const reset = useCallback(() => {
414
+ setStep("idle");
415
+ setError(null);
416
+ setQrCodeUri(null);
417
+ setSecretCode(null);
418
+ setTotpCode("");
419
+ }, []);
420
+ return {
421
+ step,
422
+ isLoading: step === "loading",
423
+ error,
424
+ qrCodeUri,
425
+ secretCode,
426
+ totpCode,
427
+ setTotpCode,
428
+ start,
429
+ onVerify: handleVerify,
430
+ reset
431
+ };
432
+ }
433
+ function SignInForm({
434
+ className,
435
+ labels = {},
436
+ forgotPasswordLink,
437
+ registerLink,
438
+ renderQrCode,
439
+ onSuccess,
440
+ onError
441
+ }) {
442
+ const uid = useId();
443
+ const form = useSignInForm({ onSuccess, onError });
444
+ const firstInputRef = useRef(null);
445
+ useEffect(() => {
446
+ firstInputRef.current?.focus();
447
+ if (form.step === "mfa_setup") {
448
+ void form.mfaSetup.start();
449
+ }
450
+ }, [form.step]);
451
+ const l = {
452
+ email: labels.email ?? "Email",
453
+ password: labels.password ?? "Password",
454
+ submit: labels.submit ?? "Accedi",
455
+ mfaCode: labels.mfaCode ?? "Codice",
456
+ mfaSubmit: labels.mfaSubmit ?? "Verifica",
457
+ newPassword: labels.newPassword ?? "Nuova password",
458
+ confirmNewPassword: labels.confirmNewPassword ?? "Conferma password",
459
+ newPasswordSubmit: labels.newPasswordSubmit ?? "Imposta password",
460
+ mfaSetupScanInstruction: labels.mfaSetupScanInstruction ?? "Scansiona il QR code con la tua app authenticator (Google Authenticator, Authy, 1Password\u2026)",
461
+ mfaSetupSecretLabel: labels.mfaSetupSecretLabel ?? "Oppure inserisci il codice manualmente",
462
+ mfaSetupCode: labels.mfaSetupCode ?? "Codice a 6 cifre",
463
+ mfaSetupSubmit: labels.mfaSetupSubmit ?? "Verifica e attiva"
464
+ };
465
+ const errorId = `${uid}-error`;
466
+ if (form.step === "mfa") {
467
+ return /* @__PURE__ */ jsxs(
468
+ "form",
469
+ {
470
+ onSubmit: form.mfa.onSubmit,
471
+ className,
472
+ "aria-label": "Verifica codice MFA",
473
+ children: [
474
+ /* @__PURE__ */ jsxs("p", { children: [
475
+ "Inserisci il codice",
476
+ " ",
477
+ form.mfaType === "TOTP" ? "dall'app authenticator" : "ricevuto via SMS"
478
+ ] }),
479
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
480
+ /* @__PURE__ */ jsxs("div", { children: [
481
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-mfa-code`, children: l.mfaCode }),
482
+ /* @__PURE__ */ jsx(
483
+ "input",
484
+ {
485
+ id: `${uid}-mfa-code`,
486
+ ref: firstInputRef,
487
+ type: "text",
488
+ inputMode: "numeric",
489
+ maxLength: 6,
490
+ autoComplete: "one-time-code",
491
+ autoFocus: true,
492
+ required: true,
493
+ "aria-required": "true",
494
+ "aria-invalid": !!form.error,
495
+ "aria-describedby": form.error ? errorId : void 0,
496
+ value: form.mfa.code,
497
+ onChange: (e) => form.mfa.setCode(e.target.value)
498
+ }
499
+ )
500
+ ] }),
501
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
502
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
503
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
504
+ ] }) : l.mfaSubmit })
505
+ ]
506
+ }
507
+ );
508
+ }
509
+ if (form.step === "new_password") {
510
+ return /* @__PURE__ */ jsxs(
511
+ "form",
512
+ {
513
+ onSubmit: form.newPassword.onSubmit,
514
+ className,
515
+ "aria-label": "Imposta nuova password",
516
+ children: [
517
+ /* @__PURE__ */ jsx("p", { children: "Devi impostare una nuova password per continuare." }),
518
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
519
+ /* @__PURE__ */ jsxs("div", { children: [
520
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-new-password`, children: l.newPassword }),
521
+ /* @__PURE__ */ jsx(
522
+ "input",
523
+ {
524
+ id: `${uid}-new-password`,
525
+ ref: firstInputRef,
526
+ type: "password",
527
+ autoComplete: "new-password",
528
+ autoFocus: true,
529
+ required: true,
530
+ "aria-required": "true",
531
+ "aria-invalid": !!form.error,
532
+ "aria-describedby": form.error ? errorId : void 0,
533
+ value: form.newPassword.password,
534
+ onChange: (e) => form.newPassword.setPassword(e.target.value)
535
+ }
536
+ )
537
+ ] }),
538
+ /* @__PURE__ */ jsxs("div", { children: [
539
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-confirm-password`, children: l.confirmNewPassword }),
540
+ /* @__PURE__ */ jsx(
541
+ "input",
542
+ {
543
+ id: `${uid}-confirm-password`,
544
+ type: "password",
545
+ autoComplete: "new-password",
546
+ required: true,
547
+ "aria-required": "true",
548
+ "aria-invalid": !!form.error,
549
+ value: form.newPassword.confirmPassword,
550
+ onChange: (e) => form.newPassword.setConfirmPassword(e.target.value)
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
555
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
556
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
557
+ ] }) : l.newPasswordSubmit })
558
+ ]
559
+ }
560
+ );
561
+ }
562
+ if (form.step === "mfa_setup") {
563
+ return /* @__PURE__ */ jsxs("div", { className, children: [
564
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
565
+ form.isLoading && !form.mfaSetup.qrCodeUri && /* @__PURE__ */ jsx("p", { "aria-live": "polite", "aria-atomic": "true", children: "Inizializzazione in corso..." }),
566
+ form.mfaSetup.qrCodeUri && /* @__PURE__ */ jsxs("div", { children: [
567
+ /* @__PURE__ */ jsx("p", { children: l.mfaSetupScanInstruction }),
568
+ renderQrCode ? renderQrCode(form.mfaSetup.qrCodeUri) : /* @__PURE__ */ jsx("code", { style: { wordBreak: "break-all", fontSize: "0.75em" }, children: form.mfaSetup.qrCodeUri }),
569
+ form.mfaSetup.secretCode && /* @__PURE__ */ jsxs("p", { children: [
570
+ l.mfaSetupSecretLabel,
571
+ ": ",
572
+ /* @__PURE__ */ jsx("code", { children: form.mfaSetup.secretCode })
573
+ ] })
574
+ ] }),
575
+ /* @__PURE__ */ jsxs("form", { onSubmit: form.mfaSetup.onVerify, "aria-label": "Verifica configurazione MFA", children: [
576
+ /* @__PURE__ */ jsxs("div", { children: [
577
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-totp-code`, children: l.mfaSetupCode }),
578
+ /* @__PURE__ */ jsx(
579
+ "input",
580
+ {
581
+ id: `${uid}-totp-code`,
582
+ ref: firstInputRef,
583
+ type: "text",
584
+ inputMode: "numeric",
585
+ maxLength: 6,
586
+ autoComplete: "one-time-code",
587
+ autoFocus: true,
588
+ required: true,
589
+ "aria-required": "true",
590
+ "aria-invalid": !!form.error,
591
+ "aria-describedby": form.error ? errorId : void 0,
592
+ disabled: form.isLoading && !form.mfaSetup.qrCodeUri,
593
+ value: form.mfaSetup.totpCode,
594
+ onChange: (e) => form.mfaSetup.setTotpCode(e.target.value)
595
+ }
596
+ )
597
+ ] }),
598
+ /* @__PURE__ */ jsx(
599
+ "button",
600
+ {
601
+ type: "submit",
602
+ disabled: form.isLoading || form.mfaSetup.totpCode.length !== 6,
603
+ "aria-busy": form.isLoading,
604
+ children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
605
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
606
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
607
+ ] }) : l.mfaSetupSubmit
608
+ }
609
+ )
610
+ ] })
611
+ ] });
612
+ }
613
+ return /* @__PURE__ */ jsxs(
614
+ "form",
615
+ {
616
+ onSubmit: form.credentials.onSubmit,
617
+ className,
618
+ "aria-label": "Accedi al tuo account",
619
+ children: [
620
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
621
+ /* @__PURE__ */ jsxs("div", { children: [
622
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-email`, children: l.email }),
623
+ /* @__PURE__ */ jsx(
624
+ "input",
625
+ {
626
+ id: `${uid}-email`,
627
+ ref: firstInputRef,
628
+ type: "email",
629
+ autoComplete: "email",
630
+ autoFocus: true,
631
+ required: true,
632
+ "aria-required": "true",
633
+ "aria-invalid": !!form.error,
634
+ "aria-describedby": form.error ? errorId : void 0,
635
+ value: form.credentials.email,
636
+ onChange: (e) => form.credentials.setEmail(e.target.value)
637
+ }
638
+ )
639
+ ] }),
640
+ /* @__PURE__ */ jsxs("div", { children: [
641
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-password`, children: l.password }),
642
+ /* @__PURE__ */ jsx(
643
+ "input",
644
+ {
645
+ id: `${uid}-password`,
646
+ type: "password",
647
+ autoComplete: "current-password",
648
+ required: true,
649
+ "aria-required": "true",
650
+ "aria-invalid": !!form.error,
651
+ value: form.credentials.password,
652
+ onChange: (e) => form.credentials.setPassword(e.target.value)
653
+ }
654
+ )
655
+ ] }),
656
+ forgotPasswordLink,
657
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
658
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
659
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
660
+ ] }) : l.submit }),
661
+ registerLink
662
+ ]
663
+ }
664
+ );
665
+ }
666
+ function RegisterForm({
667
+ className,
668
+ labels = {},
669
+ signInLink,
670
+ onSuccess,
671
+ onError,
672
+ extraAttributes
673
+ }) {
674
+ const uid = useId();
675
+ const form = useRegisterForm({ onSuccess, onError, extraAttributes });
676
+ const firstInputRef = useRef(null);
677
+ useEffect(() => {
678
+ firstInputRef.current?.focus();
679
+ }, [form.step]);
680
+ const l = {
681
+ email: labels.email ?? "Email",
682
+ password: labels.password ?? "Password",
683
+ confirmPassword: labels.confirmPassword ?? "Conferma password",
684
+ submit: labels.submit ?? "Registrati",
685
+ code: labels.code ?? "Codice di verifica",
686
+ confirmSubmit: labels.confirmSubmit ?? "Conferma",
687
+ resend: labels.resend ?? "Invia di nuovo"
688
+ };
689
+ const errorId = `${uid}-error`;
690
+ if (form.step === "confirm") {
691
+ return /* @__PURE__ */ jsxs(
692
+ "form",
693
+ {
694
+ onSubmit: form.confirm.onSubmit,
695
+ className,
696
+ "aria-label": "Conferma registrazione",
697
+ children: [
698
+ /* @__PURE__ */ jsxs("p", { children: [
699
+ "Controlla la tua email ",
700
+ /* @__PURE__ */ jsx("strong", { children: form.confirm.email }),
701
+ " e inserisci il codice ricevuto."
702
+ ] }),
703
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
704
+ /* @__PURE__ */ jsxs("div", { children: [
705
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-code`, children: l.code }),
706
+ /* @__PURE__ */ jsx(
707
+ "input",
708
+ {
709
+ id: `${uid}-code`,
710
+ ref: firstInputRef,
711
+ type: "text",
712
+ inputMode: "numeric",
713
+ maxLength: 6,
714
+ autoComplete: "one-time-code",
715
+ autoFocus: true,
716
+ required: true,
717
+ "aria-required": "true",
718
+ "aria-invalid": !!form.error,
719
+ "aria-describedby": form.error ? errorId : void 0,
720
+ value: form.confirm.code,
721
+ onChange: (e) => form.confirm.setCode(e.target.value)
722
+ }
723
+ )
724
+ ] }),
725
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
726
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
727
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
728
+ ] }) : l.confirmSubmit }),
729
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: form.confirm.resend, children: l.resend })
730
+ ]
731
+ }
732
+ );
733
+ }
734
+ return /* @__PURE__ */ jsxs(
735
+ "form",
736
+ {
737
+ onSubmit: form.register.onSubmit,
738
+ className,
739
+ "aria-label": "Crea un nuovo account",
740
+ children: [
741
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
742
+ /* @__PURE__ */ jsxs("div", { children: [
743
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-email`, children: l.email }),
744
+ /* @__PURE__ */ jsx(
745
+ "input",
746
+ {
747
+ id: `${uid}-email`,
748
+ ref: firstInputRef,
749
+ type: "email",
750
+ autoComplete: "email",
751
+ autoFocus: true,
752
+ required: true,
753
+ "aria-required": "true",
754
+ "aria-invalid": !!form.error,
755
+ "aria-describedby": form.error ? errorId : void 0,
756
+ value: form.register.email,
757
+ onChange: (e) => form.register.setEmail(e.target.value)
758
+ }
759
+ )
760
+ ] }),
761
+ /* @__PURE__ */ jsxs("div", { children: [
762
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-password`, children: l.password }),
763
+ /* @__PURE__ */ jsx(
764
+ "input",
765
+ {
766
+ id: `${uid}-password`,
767
+ type: "password",
768
+ autoComplete: "new-password",
769
+ required: true,
770
+ "aria-required": "true",
771
+ "aria-invalid": !!form.error,
772
+ value: form.register.password,
773
+ onChange: (e) => form.register.setPassword(e.target.value)
774
+ }
775
+ )
776
+ ] }),
777
+ /* @__PURE__ */ jsxs("div", { children: [
778
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-confirm-password`, children: l.confirmPassword }),
779
+ /* @__PURE__ */ jsx(
780
+ "input",
781
+ {
782
+ id: `${uid}-confirm-password`,
783
+ type: "password",
784
+ autoComplete: "new-password",
785
+ required: true,
786
+ "aria-required": "true",
787
+ "aria-invalid": !!form.error,
788
+ value: form.register.confirmPassword,
789
+ onChange: (e) => form.register.setConfirmPassword(e.target.value)
790
+ }
791
+ )
792
+ ] }),
793
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
794
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
795
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
796
+ ] }) : l.submit }),
797
+ signInLink
798
+ ]
799
+ }
800
+ );
801
+ }
802
+ function ForgotPasswordForm({
803
+ className,
804
+ labels = {},
805
+ signInLink,
806
+ onSuccess,
807
+ onError
808
+ }) {
809
+ const uid = useId();
810
+ const form = useForgotPasswordForm({ onSuccess, onError });
811
+ const firstInputRef = useRef(null);
812
+ useEffect(() => {
813
+ firstInputRef.current?.focus();
814
+ }, [form.step]);
815
+ const l = {
816
+ email: labels.email ?? "Email",
817
+ requestSubmit: labels.requestSubmit ?? "Invia codice",
818
+ code: labels.code ?? "Codice di verifica",
819
+ newPassword: labels.newPassword ?? "Nuova password",
820
+ confirmPassword: labels.confirmPassword ?? "Conferma password",
821
+ resetSubmit: labels.resetSubmit ?? "Reimposta password"
822
+ };
823
+ const errorId = `${uid}-error`;
824
+ if (form.step === "reset") {
825
+ return /* @__PURE__ */ jsxs(
826
+ "form",
827
+ {
828
+ onSubmit: form.reset.onSubmit,
829
+ className,
830
+ "aria-label": "Reimposta password",
831
+ children: [
832
+ /* @__PURE__ */ jsxs("p", { children: [
833
+ "Abbiamo inviato un codice a ",
834
+ /* @__PURE__ */ jsx("strong", { children: form.reset.email }),
835
+ "."
836
+ ] }),
837
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
838
+ /* @__PURE__ */ jsxs("div", { children: [
839
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-code`, children: l.code }),
840
+ /* @__PURE__ */ jsx(
841
+ "input",
842
+ {
843
+ id: `${uid}-code`,
844
+ ref: firstInputRef,
845
+ type: "text",
846
+ inputMode: "numeric",
847
+ maxLength: 6,
848
+ autoComplete: "one-time-code",
849
+ autoFocus: true,
850
+ required: true,
851
+ "aria-required": "true",
852
+ "aria-invalid": !!form.error,
853
+ "aria-describedby": form.error ? errorId : void 0,
854
+ value: form.reset.code,
855
+ onChange: (e) => form.reset.setCode(e.target.value)
856
+ }
857
+ )
858
+ ] }),
859
+ /* @__PURE__ */ jsxs("div", { children: [
860
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-new-password`, children: l.newPassword }),
861
+ /* @__PURE__ */ jsx(
862
+ "input",
863
+ {
864
+ id: `${uid}-new-password`,
865
+ type: "password",
866
+ autoComplete: "new-password",
867
+ required: true,
868
+ "aria-required": "true",
869
+ "aria-invalid": !!form.error,
870
+ value: form.reset.newPassword,
871
+ onChange: (e) => form.reset.setNewPassword(e.target.value)
872
+ }
873
+ )
874
+ ] }),
875
+ /* @__PURE__ */ jsxs("div", { children: [
876
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-confirm-password`, children: l.confirmPassword }),
877
+ /* @__PURE__ */ jsx(
878
+ "input",
879
+ {
880
+ id: `${uid}-confirm-password`,
881
+ type: "password",
882
+ autoComplete: "new-password",
883
+ required: true,
884
+ "aria-required": "true",
885
+ "aria-invalid": !!form.error,
886
+ value: form.reset.confirmPassword,
887
+ onChange: (e) => form.reset.setConfirmPassword(e.target.value)
888
+ }
889
+ )
890
+ ] }),
891
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
892
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
893
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
894
+ ] }) : l.resetSubmit }),
895
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: form.restart, children: "Torna all'inizio" })
896
+ ]
897
+ }
898
+ );
899
+ }
900
+ return /* @__PURE__ */ jsxs(
901
+ "form",
902
+ {
903
+ onSubmit: form.request.onSubmit,
904
+ className,
905
+ "aria-label": "Richiedi codice di reimpostazione password",
906
+ children: [
907
+ /* @__PURE__ */ jsx("p", { children: "Inserisci la tua email per ricevere il codice di reimpostazione." }),
908
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
909
+ /* @__PURE__ */ jsxs("div", { children: [
910
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-email`, children: l.email }),
911
+ /* @__PURE__ */ jsx(
912
+ "input",
913
+ {
914
+ id: `${uid}-email`,
915
+ ref: firstInputRef,
916
+ type: "email",
917
+ autoComplete: "email",
918
+ autoFocus: true,
919
+ required: true,
920
+ "aria-required": "true",
921
+ "aria-invalid": !!form.error,
922
+ "aria-describedby": form.error ? errorId : void 0,
923
+ value: form.request.email,
924
+ onChange: (e) => form.request.setEmail(e.target.value)
925
+ }
926
+ )
927
+ ] }),
928
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
929
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
930
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
931
+ ] }) : l.requestSubmit }),
932
+ signInLink
933
+ ]
934
+ }
935
+ );
936
+ }
937
+ function ChangePasswordForm({
938
+ className,
939
+ labels = {},
940
+ onSuccess,
941
+ onError
942
+ }) {
943
+ const uid = useId();
944
+ const form = useChangePasswordForm({ onSuccess, onError });
945
+ const firstInputRef = useRef(null);
946
+ const l = {
947
+ currentPassword: labels.currentPassword ?? "Password attuale",
948
+ newPassword: labels.newPassword ?? "Nuova password",
949
+ confirmPassword: labels.confirmPassword ?? "Conferma nuova password",
950
+ submit: labels.submit ?? "Cambia password",
951
+ successMessage: labels.successMessage ?? "Password aggiornata con successo."
952
+ };
953
+ const errorId = `${uid}-error`;
954
+ if (form.success) {
955
+ return /* @__PURE__ */ jsx("p", { role: "status", children: l.successMessage });
956
+ }
957
+ return /* @__PURE__ */ jsxs(
958
+ "form",
959
+ {
960
+ onSubmit: form.onSubmit,
961
+ className,
962
+ "aria-label": "Cambia password",
963
+ children: [
964
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: form.error?.message }),
965
+ /* @__PURE__ */ jsxs("div", { children: [
966
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-current-password`, children: l.currentPassword }),
967
+ /* @__PURE__ */ jsx(
968
+ "input",
969
+ {
970
+ id: `${uid}-current-password`,
971
+ ref: firstInputRef,
972
+ type: "password",
973
+ autoComplete: "current-password",
974
+ autoFocus: true,
975
+ required: true,
976
+ "aria-required": "true",
977
+ "aria-invalid": !!form.error,
978
+ "aria-describedby": form.error ? errorId : void 0,
979
+ value: form.currentPassword,
980
+ onChange: (e) => form.setCurrentPassword(e.target.value)
981
+ }
982
+ )
983
+ ] }),
984
+ /* @__PURE__ */ jsxs("div", { children: [
985
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-new-password`, children: l.newPassword }),
986
+ /* @__PURE__ */ jsx(
987
+ "input",
988
+ {
989
+ id: `${uid}-new-password`,
990
+ type: "password",
991
+ autoComplete: "new-password",
992
+ required: true,
993
+ "aria-required": "true",
994
+ "aria-invalid": !!form.error,
995
+ value: form.newPassword,
996
+ onChange: (e) => form.setNewPassword(e.target.value)
997
+ }
998
+ )
999
+ ] }),
1000
+ /* @__PURE__ */ jsxs("div", { children: [
1001
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-confirm-password`, children: l.confirmPassword }),
1002
+ /* @__PURE__ */ jsx(
1003
+ "input",
1004
+ {
1005
+ id: `${uid}-confirm-password`,
1006
+ type: "password",
1007
+ autoComplete: "new-password",
1008
+ required: true,
1009
+ "aria-required": "true",
1010
+ "aria-invalid": !!form.error,
1011
+ value: form.confirmPassword,
1012
+ onChange: (e) => form.setConfirmPassword(e.target.value)
1013
+ }
1014
+ )
1015
+ ] }),
1016
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: form.isLoading, "aria-busy": form.isLoading, children: form.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
1017
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
1018
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
1019
+ ] }) : l.submit })
1020
+ ]
1021
+ }
1022
+ );
1023
+ }
1024
+ function MfaSetupWizard({
1025
+ className,
1026
+ labels = {},
1027
+ renderQrCode,
1028
+ onSuccess,
1029
+ onError
1030
+ }) {
1031
+ const uid = useId();
1032
+ const wizard = useMfaSetup({ onSuccess, onError });
1033
+ const firstInputRef = useRef(null);
1034
+ useEffect(() => {
1035
+ firstInputRef.current?.focus();
1036
+ }, [wizard.step]);
1037
+ const l = {
1038
+ start: labels.start ?? "Configura autenticazione a due fattori (TOTP)",
1039
+ scanInstruction: labels.scanInstruction ?? "Scansiona il QR code con la tua app authenticator (Google Authenticator, Authy, 1Password\u2026)",
1040
+ manualEntry: labels.manualEntry ?? "Oppure inserisci il codice manualmente:",
1041
+ codeLabel: labels.codeLabel ?? "Codice a 6 cifre",
1042
+ verifySubmit: labels.verifySubmit ?? "Verifica e attiva",
1043
+ successMessage: labels.successMessage ?? "Autenticazione a due fattori attivata con successo."
1044
+ };
1045
+ const errorId = `${uid}-error`;
1046
+ if (wizard.step === "done") {
1047
+ return /* @__PURE__ */ jsx("p", { role: "status", children: l.successMessage });
1048
+ }
1049
+ if (wizard.step === "idle") {
1050
+ return /* @__PURE__ */ jsxs("div", { className, children: [
1051
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: wizard.error?.message }),
1052
+ /* @__PURE__ */ jsx("button", { type: "button", autoFocus: true, onClick: wizard.start, children: l.start })
1053
+ ] });
1054
+ }
1055
+ if (wizard.step === "loading") {
1056
+ return /* @__PURE__ */ jsx("div", { className, "aria-live": "polite", "aria-atomic": "true", children: "..." });
1057
+ }
1058
+ return /* @__PURE__ */ jsxs("div", { className, children: [
1059
+ /* @__PURE__ */ jsx("div", { id: errorId, role: "alert", "aria-live": "assertive", "aria-atomic": "true", children: wizard.error?.message }),
1060
+ wizard.qrCodeUri && /* @__PURE__ */ jsxs("div", { children: [
1061
+ /* @__PURE__ */ jsx("p", { children: l.scanInstruction }),
1062
+ renderQrCode ? renderQrCode(wizard.qrCodeUri) : /* @__PURE__ */ jsx("code", { style: { wordBreak: "break-all", fontSize: "0.75em" }, children: wizard.qrCodeUri }),
1063
+ wizard.secretCode && /* @__PURE__ */ jsxs("p", { children: [
1064
+ l.manualEntry,
1065
+ " ",
1066
+ /* @__PURE__ */ jsx("code", { children: wizard.secretCode })
1067
+ ] })
1068
+ ] }),
1069
+ /* @__PURE__ */ jsxs("form", { onSubmit: wizard.onVerify, "aria-label": "Verifica dispositivo TOTP", children: [
1070
+ /* @__PURE__ */ jsxs("div", { children: [
1071
+ /* @__PURE__ */ jsx("label", { htmlFor: `${uid}-totp-code`, children: l.codeLabel }),
1072
+ /* @__PURE__ */ jsx(
1073
+ "input",
1074
+ {
1075
+ id: `${uid}-totp-code`,
1076
+ ref: firstInputRef,
1077
+ type: "text",
1078
+ inputMode: "numeric",
1079
+ maxLength: 6,
1080
+ autoComplete: "one-time-code",
1081
+ autoFocus: true,
1082
+ required: true,
1083
+ "aria-required": "true",
1084
+ "aria-invalid": !!wizard.error,
1085
+ "aria-describedby": wizard.error ? errorId : void 0,
1086
+ value: wizard.totpCode,
1087
+ onChange: (e) => wizard.setTotpCode(e.target.value)
1088
+ }
1089
+ )
1090
+ ] }),
1091
+ /* @__PURE__ */ jsx(
1092
+ "button",
1093
+ {
1094
+ type: "submit",
1095
+ disabled: wizard.isLoading || wizard.totpCode.length !== 6,
1096
+ "aria-busy": wizard.isLoading,
1097
+ children: wizard.isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
1098
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "..." }),
1099
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Caricamento..." })
1100
+ ] }) : l.verifySubmit
1101
+ }
1102
+ )
1103
+ ] })
1104
+ ] });
1105
+ }
1106
+
1107
+ export { ChangePasswordForm, ForgotPasswordForm, MfaSetupWizard, RegisterForm, SignInForm, useChangePasswordForm, useForgotPasswordForm, useMfaSetup, useRegisterForm, useSignInForm };
1108
+ //# sourceMappingURL=index.js.map
1109
+ //# sourceMappingURL=index.js.map