@dloizides/auth-web 1.2.2 → 1.4.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/CHANGELOG.md +32 -0
- package/dist/index.d.mts +802 -1
- package/dist/index.d.ts +802 -1
- package/dist/index.js +1330 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1302 -83
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,6 +34,11 @@ var DEFAULT_FORGOT_PASSWORD_LABELS = {
|
|
|
34
34
|
networkError: "Something went wrong. Please try again.",
|
|
35
35
|
invalidEmail: "Enter a valid email address."
|
|
36
36
|
};
|
|
37
|
+
var DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS = {
|
|
38
|
+
...DEFAULT_FORGOT_PASSWORD_LABELS,
|
|
39
|
+
cancel: "Cancel",
|
|
40
|
+
close: "Close"
|
|
41
|
+
};
|
|
37
42
|
var DEFAULT_OTP_LABELS = {
|
|
38
43
|
requestTitle: "Sign in with a code",
|
|
39
44
|
requestDescription: "Enter your email and we will send you a one-time code.",
|
|
@@ -64,6 +69,77 @@ var DEFAULT_PIN_LABELS = {
|
|
|
64
69
|
missingPin: "Enter your event PIN.",
|
|
65
70
|
invalidPin: "That PIN is incorrect, has expired, or is locked out."
|
|
66
71
|
};
|
|
72
|
+
var DEFAULT_DEVICE_PIN_UNLOCK_LABELS = {
|
|
73
|
+
title: "Welcome back, {name}",
|
|
74
|
+
titleNoName: "Welcome back",
|
|
75
|
+
description: "Enter your {count}-digit PIN to sign in on this device.",
|
|
76
|
+
pinLabel: "PIN",
|
|
77
|
+
pinPlaceholder: "Enter your PIN",
|
|
78
|
+
submit: "Unlock",
|
|
79
|
+
submitting: "Signing in...",
|
|
80
|
+
usePasswordInstead: "Sign in with password instead",
|
|
81
|
+
usePasswordHint: "Switch to signing in with your username and password",
|
|
82
|
+
errorIncomplete: "Enter all {count} digits of your PIN.",
|
|
83
|
+
errorInvalid: "That PIN is incorrect. Try again.",
|
|
84
|
+
errorLockedOut: "Too many attempts. Try again later.",
|
|
85
|
+
errorLockedOutRetry: "Too many attempts. Try again in {count} seconds.",
|
|
86
|
+
errorRateLimited: "Too many requests. Try again later.",
|
|
87
|
+
errorRateLimitedRetry: "Too many requests. Try again in {count} seconds.",
|
|
88
|
+
errorGeneric: "Something went wrong. Try again, or sign in with your password.",
|
|
89
|
+
digitFilledHint: "PIN digit entered",
|
|
90
|
+
digitEmptyHint: "PIN digit not yet entered"
|
|
91
|
+
};
|
|
92
|
+
var DEFAULT_DEVICE_PIN_ENROLL_LABELS = {
|
|
93
|
+
offerTitle: "Set a PIN for faster sign-in?",
|
|
94
|
+
offerDescription: "Next time, sign in on this device with a short PIN instead of your full password.",
|
|
95
|
+
offerAccept: "Set up a PIN",
|
|
96
|
+
offerAcceptHint: "Open the form to choose a quick sign-in PIN",
|
|
97
|
+
offerSkip: "Not now",
|
|
98
|
+
offerSkipHint: "Dismiss the PIN setup offer",
|
|
99
|
+
formTitle: "Choose your PIN",
|
|
100
|
+
formDescription: "Pick a {count}-digit PIN you will remember. You will use it to sign in on this device.",
|
|
101
|
+
lengthLabel: "PIN length",
|
|
102
|
+
lengthOptionHint: "Use a {count}-digit PIN",
|
|
103
|
+
pinLabel: "New PIN",
|
|
104
|
+
pinPlaceholder: "Enter a new PIN",
|
|
105
|
+
confirmLabel: "Confirm PIN",
|
|
106
|
+
confirmPlaceholder: "Re-enter your PIN",
|
|
107
|
+
submit: "Save PIN",
|
|
108
|
+
submitting: "Saving...",
|
|
109
|
+
cancel: "Cancel",
|
|
110
|
+
cancelHint: "Close the PIN setup form without saving",
|
|
111
|
+
errorMismatch: "The PINs must match and be exactly {count} digits.",
|
|
112
|
+
errorUnauthorized: "Your session has expired. Sign in again to set a PIN.",
|
|
113
|
+
errorForbidden: "A PIN is already set for this session.",
|
|
114
|
+
errorInvalidPin: "That PIN is not allowed. Choose a different one.",
|
|
115
|
+
errorFailed: "Could not set your PIN. Try again later."
|
|
116
|
+
};
|
|
117
|
+
var DEFAULT_DEVICE_PIN_SETTINGS_LABELS = {
|
|
118
|
+
title: "Quick PIN sign-in",
|
|
119
|
+
description: "Sign in on this device with a short PIN instead of your full password.",
|
|
120
|
+
statusEnabled: "Quick PIN sign-in is enabled on this device.",
|
|
121
|
+
statusDisabled: "Quick PIN sign-in is off.",
|
|
122
|
+
enable: "Enable quick PIN sign-in",
|
|
123
|
+
enableHint: "Set a PIN so you can sign in faster on this device",
|
|
124
|
+
disable: "Disable",
|
|
125
|
+
disableHint: "Remove the PIN sign-in from this device",
|
|
126
|
+
disabling: "Disabling...",
|
|
127
|
+
disableFailed: "Could not disable PIN sign-in. Try again later."
|
|
128
|
+
};
|
|
129
|
+
var DEFAULT_PASSKEY_LOGIN_LABELS = {
|
|
130
|
+
signInButton: "Sign in with a passkey",
|
|
131
|
+
signInHint: "Use your fingerprint, face, or security key to sign in",
|
|
132
|
+
errorCancelled: "Passkey sign-in was cancelled. You can try again or sign in another way.",
|
|
133
|
+
errorFailed: "Passkey sign-in didn't work. Try again, or sign in another way."
|
|
134
|
+
};
|
|
135
|
+
var DEFAULT_PASSKEY_SETTINGS_LABELS = {
|
|
136
|
+
title: "Passkeys",
|
|
137
|
+
description: "Add a passkey to sign in with your fingerprint, face, or a security key instead of a password.",
|
|
138
|
+
reauthHint: "You'll be asked to confirm your password before adding a passkey.",
|
|
139
|
+
addButton: "Add a passkey",
|
|
140
|
+
addHint: "Start setting up a passkey for this account",
|
|
141
|
+
registeredSuccess: "Your passkey was added. You can now use it to sign in."
|
|
142
|
+
};
|
|
67
143
|
var DEFAULT_RESET_PASSWORD_LABELS = {
|
|
68
144
|
title: "Reset password",
|
|
69
145
|
description: "Choose a new password for your account.",
|
|
@@ -92,6 +168,8 @@ var AuthTestIds = {
|
|
|
92
168
|
forgotPasswordForm: "auth-forgot-form",
|
|
93
169
|
forgotPasswordEmailInput: "auth-forgot-email",
|
|
94
170
|
forgotPasswordSubmitButton: "auth-forgot-submit",
|
|
171
|
+
forgotPasswordCancelButton: "auth-forgot-cancel",
|
|
172
|
+
forgotPasswordCloseButton: "auth-forgot-close",
|
|
95
173
|
forgotPasswordError: "auth-forgot-error",
|
|
96
174
|
forgotPasswordSuccess: "auth-forgot-success",
|
|
97
175
|
resetPasswordForm: "auth-reset-form",
|
|
@@ -110,7 +188,39 @@ var AuthTestIds = {
|
|
|
110
188
|
pinForm: "auth-pin-form",
|
|
111
189
|
pinInput: "auth-pin-input",
|
|
112
190
|
pinSubmitButton: "auth-pin-submit",
|
|
113
|
-
pinError: "auth-pin-error"
|
|
191
|
+
pinError: "auth-pin-error",
|
|
192
|
+
// Device-PIN unlock gate
|
|
193
|
+
devicePinUnlock: "auth-device-pin-unlock",
|
|
194
|
+
devicePinUnlockInput: "auth-device-pin-unlock-input",
|
|
195
|
+
devicePinUnlockSubmit: "auth-device-pin-unlock-submit",
|
|
196
|
+
devicePinUnlockUsePassword: "auth-device-pin-unlock-use-password",
|
|
197
|
+
devicePinUnlockError: "auth-device-pin-unlock-error",
|
|
198
|
+
// Device-PIN enrol form + length picker
|
|
199
|
+
devicePinEnrollForm: "auth-device-pin-enroll-form",
|
|
200
|
+
devicePinEnrollLength: "auth-device-pin-enroll-length",
|
|
201
|
+
devicePinEnrollPin: "auth-device-pin-enroll-pin",
|
|
202
|
+
devicePinEnrollConfirm: "auth-device-pin-enroll-confirm",
|
|
203
|
+
devicePinEnrollSubmit: "auth-device-pin-enroll-submit",
|
|
204
|
+
devicePinEnrollCancel: "auth-device-pin-enroll-cancel",
|
|
205
|
+
devicePinEnrollError: "auth-device-pin-enroll-error",
|
|
206
|
+
// Device-PIN offer (post-login)
|
|
207
|
+
devicePinOffer: "auth-device-pin-offer",
|
|
208
|
+
devicePinOfferAccept: "auth-device-pin-offer-accept",
|
|
209
|
+
devicePinOfferSkip: "auth-device-pin-offer-skip",
|
|
210
|
+
// Device-PIN settings card
|
|
211
|
+
devicePinSettings: "auth-device-pin-settings",
|
|
212
|
+
devicePinSettingsStatus: "auth-device-pin-settings-status",
|
|
213
|
+
devicePinSettingsEnable: "auth-device-pin-settings-enable",
|
|
214
|
+
devicePinSettingsDisable: "auth-device-pin-settings-disable",
|
|
215
|
+
devicePinSettingsError: "auth-device-pin-settings-error",
|
|
216
|
+
// Passkey login button
|
|
217
|
+
passkeyLogin: "auth-passkey-login",
|
|
218
|
+
passkeyLoginButton: "auth-passkey-login-button",
|
|
219
|
+
passkeyLoginError: "auth-passkey-login-error",
|
|
220
|
+
// Passkey settings card
|
|
221
|
+
passkeySettings: "auth-passkey-settings",
|
|
222
|
+
passkeySettingsAdd: "auth-passkey-settings-add",
|
|
223
|
+
passkeySettingsSuccess: "auth-passkey-settings-success"
|
|
114
224
|
};
|
|
115
225
|
function withTestIdPrefix(baseId, prefix) {
|
|
116
226
|
return prefix === void 0 || prefix === "" ? baseId : `${prefix}-${baseId}`;
|
|
@@ -204,6 +314,32 @@ function useAuthStyles(theme) {
|
|
|
204
314
|
helperText: {
|
|
205
315
|
fontSize: typography.caption,
|
|
206
316
|
color: colors.textSecondary
|
|
317
|
+
},
|
|
318
|
+
escapeLink: {
|
|
319
|
+
alignSelf: "center",
|
|
320
|
+
marginTop: spacing.md,
|
|
321
|
+
paddingVertical: spacing.xs / 2
|
|
322
|
+
},
|
|
323
|
+
secondaryButton: {
|
|
324
|
+
borderRadius: radii.input,
|
|
325
|
+
borderWidth: 1,
|
|
326
|
+
borderColor: colors.primary,
|
|
327
|
+
paddingVertical: BUTTON_VERTICAL_PADDING,
|
|
328
|
+
alignItems: "center",
|
|
329
|
+
justifyContent: "center",
|
|
330
|
+
marginTop: spacing.sm,
|
|
331
|
+
backgroundColor: colors.surface
|
|
332
|
+
},
|
|
333
|
+
secondaryButtonText: {
|
|
334
|
+
fontSize: typography.body,
|
|
335
|
+
fontWeight: "600",
|
|
336
|
+
color: colors.primary
|
|
337
|
+
},
|
|
338
|
+
statusText: {
|
|
339
|
+
fontSize: typography.label,
|
|
340
|
+
fontWeight: "600",
|
|
341
|
+
marginTop: spacing.sm,
|
|
342
|
+
color: colors.text
|
|
207
343
|
}
|
|
208
344
|
});
|
|
209
345
|
}, [theme]);
|
|
@@ -365,7 +501,7 @@ function LoginForm({
|
|
|
365
501
|
testIdPrefix
|
|
366
502
|
}) {
|
|
367
503
|
const theme = useAuthTheme(themeProp);
|
|
368
|
-
const
|
|
504
|
+
const styles3 = useAuthStyles(theme);
|
|
369
505
|
const labels = react.useMemo(
|
|
370
506
|
() => ({ ...DEFAULT_LOGIN_LABELS, ...labelsProp }),
|
|
371
507
|
[labelsProp]
|
|
@@ -392,12 +528,12 @@ function LoginForm({
|
|
|
392
528
|
const handleSubmit = react.useCallback(() => {
|
|
393
529
|
void runLogin();
|
|
394
530
|
}, [runLogin]);
|
|
395
|
-
const submitButtonStyle = isSubmitting ? [
|
|
396
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
397
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
398
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
399
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
400
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
531
|
+
const submitButtonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
532
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix), children: [
|
|
533
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
534
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.subtitle }),
|
|
535
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
536
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.usernameLabel }),
|
|
401
537
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
402
538
|
reactNative.TextInput,
|
|
403
539
|
{
|
|
@@ -408,15 +544,15 @@ function LoginForm({
|
|
|
408
544
|
editable: !isSubmitting,
|
|
409
545
|
placeholder: labels.usernamePlaceholder,
|
|
410
546
|
placeholderTextColor: theme.colors.textSecondary,
|
|
411
|
-
style:
|
|
547
|
+
style: styles3.input,
|
|
412
548
|
testID: withTestIdPrefix(AuthTestIds.loginUsernameInput, testIdPrefix),
|
|
413
549
|
value: username,
|
|
414
550
|
onChangeText: setUsername
|
|
415
551
|
}
|
|
416
552
|
)
|
|
417
553
|
] }),
|
|
418
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
419
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
554
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
555
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.passwordLabel }),
|
|
420
556
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
421
557
|
reactNative.TextInput,
|
|
422
558
|
{
|
|
@@ -428,7 +564,7 @@ function LoginForm({
|
|
|
428
564
|
editable: !isSubmitting,
|
|
429
565
|
placeholder: labels.passwordPlaceholder,
|
|
430
566
|
placeholderTextColor: theme.colors.textSecondary,
|
|
431
|
-
style:
|
|
567
|
+
style: styles3.input,
|
|
432
568
|
testID: withTestIdPrefix(AuthTestIds.loginPasswordInput, testIdPrefix),
|
|
433
569
|
value: password,
|
|
434
570
|
onChangeText: setPassword
|
|
@@ -438,7 +574,7 @@ function LoginForm({
|
|
|
438
574
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
439
575
|
reactNative.Text,
|
|
440
576
|
{
|
|
441
|
-
style:
|
|
577
|
+
style: styles3.errorText,
|
|
442
578
|
testID: withTestIdPrefix(AuthTestIds.loginError, testIdPrefix),
|
|
443
579
|
children: errorText
|
|
444
580
|
}
|
|
@@ -450,10 +586,10 @@ function LoginForm({
|
|
|
450
586
|
accessibilityLabel: labels.forgotPassword,
|
|
451
587
|
accessibilityRole: "link",
|
|
452
588
|
disabled: isSubmitting,
|
|
453
|
-
style:
|
|
589
|
+
style: styles3.fieldGroup,
|
|
454
590
|
testID: withTestIdPrefix(AuthTestIds.loginForgotLink, testIdPrefix),
|
|
455
591
|
onPress: onForgotPassword,
|
|
456
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
592
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.forgotPassword })
|
|
457
593
|
}
|
|
458
594
|
) : null,
|
|
459
595
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -466,7 +602,7 @@ function LoginForm({
|
|
|
466
602
|
style: submitButtonStyle,
|
|
467
603
|
testID: withTestIdPrefix(AuthTestIds.loginSubmitButton, testIdPrefix),
|
|
468
604
|
onPress: handleSubmit,
|
|
469
|
-
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
605
|
+
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
470
606
|
}
|
|
471
607
|
),
|
|
472
608
|
onSignUp !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -476,10 +612,10 @@ function LoginForm({
|
|
|
476
612
|
accessibilityLabel: labels.signUp,
|
|
477
613
|
accessibilityRole: "link",
|
|
478
614
|
disabled: isSubmitting,
|
|
479
|
-
style:
|
|
615
|
+
style: styles3.fieldGroup,
|
|
480
616
|
testID: withTestIdPrefix(AuthTestIds.loginSignUpLink, testIdPrefix),
|
|
481
617
|
onPress: onSignUp,
|
|
482
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
618
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.signUp })
|
|
483
619
|
}
|
|
484
620
|
) : null
|
|
485
621
|
] }) });
|
|
@@ -517,7 +653,7 @@ function ForgotPasswordForm({
|
|
|
517
653
|
testIdPrefix
|
|
518
654
|
}) {
|
|
519
655
|
const theme = useAuthTheme(themeProp);
|
|
520
|
-
const
|
|
656
|
+
const styles3 = useAuthStyles(theme);
|
|
521
657
|
const labels = react.useMemo(
|
|
522
658
|
() => ({ ...DEFAULT_FORGOT_PASSWORD_LABELS, ...labelsProp }),
|
|
523
659
|
[labelsProp]
|
|
@@ -549,25 +685,25 @@ function ForgotPasswordForm({
|
|
|
549
685
|
}
|
|
550
686
|
mutation.mutate({ email: trimmedEmail, resetUrlTemplate });
|
|
551
687
|
}, [email, mutation, resetUrlTemplate, labels.invalidEmail]);
|
|
552
|
-
const submitButtonStyle = isPending ? [
|
|
553
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
688
|
+
const submitButtonStyle = isPending ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
689
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
554
690
|
reactNative.View,
|
|
555
691
|
{
|
|
556
|
-
style:
|
|
692
|
+
style: styles3.card,
|
|
557
693
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix),
|
|
558
694
|
children: [
|
|
559
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
560
696
|
submitted ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
561
697
|
reactNative.Text,
|
|
562
698
|
{
|
|
563
|
-
style:
|
|
699
|
+
style: styles3.successText,
|
|
564
700
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix),
|
|
565
701
|
children: labels.successMessage
|
|
566
702
|
}
|
|
567
703
|
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
568
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
569
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
570
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
704
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
705
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
706
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.emailLabel }),
|
|
571
707
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
572
708
|
reactNative.TextInput,
|
|
573
709
|
{
|
|
@@ -579,7 +715,7 @@ function ForgotPasswordForm({
|
|
|
579
715
|
keyboardType: "email-address",
|
|
580
716
|
placeholder: labels.emailPlaceholder,
|
|
581
717
|
placeholderTextColor: theme.colors.textSecondary,
|
|
582
|
-
style:
|
|
718
|
+
style: styles3.input,
|
|
583
719
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix),
|
|
584
720
|
value: email,
|
|
585
721
|
onChangeText: setEmail
|
|
@@ -589,7 +725,7 @@ function ForgotPasswordForm({
|
|
|
589
725
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
590
726
|
reactNative.Text,
|
|
591
727
|
{
|
|
592
|
-
style:
|
|
728
|
+
style: styles3.errorText,
|
|
593
729
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix),
|
|
594
730
|
children: errorText
|
|
595
731
|
}
|
|
@@ -604,7 +740,7 @@ function ForgotPasswordForm({
|
|
|
604
740
|
style: submitButtonStyle,
|
|
605
741
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix),
|
|
606
742
|
onPress: handleSubmit,
|
|
607
|
-
children: isPending ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
743
|
+
children: isPending ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
608
744
|
}
|
|
609
745
|
)
|
|
610
746
|
] })
|
|
@@ -612,6 +748,182 @@ function ForgotPasswordForm({
|
|
|
612
748
|
}
|
|
613
749
|
) });
|
|
614
750
|
}
|
|
751
|
+
var EMAIL_REGEX2 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
|
|
752
|
+
function isValidForgotPasswordEmail(value) {
|
|
753
|
+
return EMAIL_REGEX2.test(value.trim());
|
|
754
|
+
}
|
|
755
|
+
function useForgotPasswordSubmit({
|
|
756
|
+
client,
|
|
757
|
+
resetUrlTemplate,
|
|
758
|
+
onSuccess
|
|
759
|
+
}) {
|
|
760
|
+
const [email, setEmail] = react.useState("");
|
|
761
|
+
const [submitted, setSubmitted] = react.useState(false);
|
|
762
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
763
|
+
const [hasNetworkError, setHasNetworkError] = react.useState(false);
|
|
764
|
+
const canSubmit = isValidForgotPasswordEmail(email) && !isSubmitting;
|
|
765
|
+
const submit = react.useCallback(() => {
|
|
766
|
+
const target = email.trim();
|
|
767
|
+
if (!isValidForgotPasswordEmail(target) || isSubmitting) {
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
setHasNetworkError(false);
|
|
771
|
+
setIsSubmitting(true);
|
|
772
|
+
const request = { email: target, resetUrlTemplate };
|
|
773
|
+
client.forgotPassword(request).then(() => {
|
|
774
|
+
setSubmitted(true);
|
|
775
|
+
onSuccess?.();
|
|
776
|
+
}).catch(() => setHasNetworkError(true)).finally(() => setIsSubmitting(false));
|
|
777
|
+
}, [client, email, isSubmitting, resetUrlTemplate, onSuccess]);
|
|
778
|
+
const reset = react.useCallback(() => {
|
|
779
|
+
setEmail("");
|
|
780
|
+
setSubmitted(false);
|
|
781
|
+
setIsSubmitting(false);
|
|
782
|
+
setHasNetworkError(false);
|
|
783
|
+
}, []);
|
|
784
|
+
return {
|
|
785
|
+
email,
|
|
786
|
+
setEmail,
|
|
787
|
+
submitted,
|
|
788
|
+
isSubmitting,
|
|
789
|
+
hasNetworkError,
|
|
790
|
+
canSubmit,
|
|
791
|
+
submit,
|
|
792
|
+
reset
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
var SECONDARY_BORDER_WIDTH = 1;
|
|
796
|
+
function useModalStyles(theme) {
|
|
797
|
+
return react.useMemo(
|
|
798
|
+
() => reactNative.StyleSheet.create({
|
|
799
|
+
body: { padding: theme.spacing.md },
|
|
800
|
+
actions: {
|
|
801
|
+
flexDirection: "row",
|
|
802
|
+
justifyContent: "flex-end",
|
|
803
|
+
alignItems: "center",
|
|
804
|
+
marginTop: theme.spacing.md,
|
|
805
|
+
gap: theme.spacing.sm
|
|
806
|
+
},
|
|
807
|
+
secondaryButton: {
|
|
808
|
+
borderRadius: theme.radii.input,
|
|
809
|
+
paddingVertical: theme.spacing.sm,
|
|
810
|
+
paddingHorizontal: theme.spacing.md,
|
|
811
|
+
borderWidth: SECONDARY_BORDER_WIDTH,
|
|
812
|
+
borderColor: theme.colors.border
|
|
813
|
+
},
|
|
814
|
+
secondaryButtonText: {
|
|
815
|
+
fontSize: theme.typography.body,
|
|
816
|
+
fontWeight: "600",
|
|
817
|
+
color: theme.colors.text
|
|
818
|
+
}
|
|
819
|
+
}),
|
|
820
|
+
[theme]
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
function ForgotPasswordFields({
|
|
824
|
+
client,
|
|
825
|
+
theme: themeProp,
|
|
826
|
+
labels: labelsProp,
|
|
827
|
+
resetUrlTemplate,
|
|
828
|
+
visible = true,
|
|
829
|
+
onSuccess,
|
|
830
|
+
onCancel,
|
|
831
|
+
onClose,
|
|
832
|
+
testIdPrefix
|
|
833
|
+
}) {
|
|
834
|
+
const theme = useAuthTheme(themeProp);
|
|
835
|
+
const styles3 = useAuthStyles(theme);
|
|
836
|
+
const modalStyles = useModalStyles(theme);
|
|
837
|
+
const labels = react.useMemo(
|
|
838
|
+
() => ({ ...DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, ...labelsProp }),
|
|
839
|
+
[labelsProp]
|
|
840
|
+
);
|
|
841
|
+
const form = useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess });
|
|
842
|
+
const { reset } = form;
|
|
843
|
+
react.useEffect(() => {
|
|
844
|
+
if (!visible) {
|
|
845
|
+
reset();
|
|
846
|
+
}
|
|
847
|
+
}, [visible, reset]);
|
|
848
|
+
const submitButtonStyle = form.canSubmit ? styles3.primaryButton : [styles3.primaryButton, styles3.primaryButtonDisabled];
|
|
849
|
+
const handleCancel = () => {
|
|
850
|
+
form.reset();
|
|
851
|
+
onCancel?.();
|
|
852
|
+
};
|
|
853
|
+
const handleClose = () => {
|
|
854
|
+
form.reset();
|
|
855
|
+
onClose?.();
|
|
856
|
+
};
|
|
857
|
+
if (form.submitted) {
|
|
858
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
859
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.successText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix), children: labels.successMessage }),
|
|
860
|
+
onClose !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: modalStyles.actions, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
861
|
+
reactNative.TouchableOpacity,
|
|
862
|
+
{
|
|
863
|
+
accessibilityHint: labels.close,
|
|
864
|
+
accessibilityLabel: labels.close,
|
|
865
|
+
accessibilityRole: "button",
|
|
866
|
+
style: styles3.primaryButton,
|
|
867
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordCloseButton, testIdPrefix),
|
|
868
|
+
onPress: handleClose,
|
|
869
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.close })
|
|
870
|
+
}
|
|
871
|
+
) }) : null
|
|
872
|
+
] });
|
|
873
|
+
}
|
|
874
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
875
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
876
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
877
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.emailLabel }),
|
|
878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
879
|
+
reactNative.TextInput,
|
|
880
|
+
{
|
|
881
|
+
accessibilityHint: labels.emailPlaceholder,
|
|
882
|
+
accessibilityLabel: labels.emailLabel,
|
|
883
|
+
autoCapitalize: "none",
|
|
884
|
+
autoCorrect: false,
|
|
885
|
+
editable: !form.isSubmitting,
|
|
886
|
+
keyboardType: "email-address",
|
|
887
|
+
placeholder: labels.emailPlaceholder,
|
|
888
|
+
placeholderTextColor: theme.colors.textSecondary,
|
|
889
|
+
style: styles3.input,
|
|
890
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix),
|
|
891
|
+
value: form.email,
|
|
892
|
+
onChangeText: form.setEmail
|
|
893
|
+
}
|
|
894
|
+
)
|
|
895
|
+
] }),
|
|
896
|
+
form.hasNetworkError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix), children: labels.networkError }) : null,
|
|
897
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.actions, children: [
|
|
898
|
+
onCancel !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
899
|
+
reactNative.TouchableOpacity,
|
|
900
|
+
{
|
|
901
|
+
accessibilityHint: labels.cancel,
|
|
902
|
+
accessibilityLabel: labels.cancel,
|
|
903
|
+
accessibilityRole: "button",
|
|
904
|
+
disabled: form.isSubmitting,
|
|
905
|
+
style: modalStyles.secondaryButton,
|
|
906
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordCancelButton, testIdPrefix),
|
|
907
|
+
onPress: handleCancel,
|
|
908
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: modalStyles.secondaryButtonText, children: labels.cancel })
|
|
909
|
+
}
|
|
910
|
+
) : null,
|
|
911
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
912
|
+
reactNative.TouchableOpacity,
|
|
913
|
+
{
|
|
914
|
+
accessibilityHint: labels.submit,
|
|
915
|
+
accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
|
|
916
|
+
accessibilityRole: "button",
|
|
917
|
+
disabled: !form.canSubmit,
|
|
918
|
+
style: submitButtonStyle,
|
|
919
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix),
|
|
920
|
+
onPress: form.submit,
|
|
921
|
+
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
] })
|
|
925
|
+
] });
|
|
926
|
+
}
|
|
615
927
|
|
|
616
928
|
// src/hooks/ResetPasswordError.ts
|
|
617
929
|
var ResetPasswordError = /* @__PURE__ */ ((ResetPasswordError2) => {
|
|
@@ -785,24 +1097,24 @@ function ResetPasswordForm({
|
|
|
785
1097
|
testIdPrefix
|
|
786
1098
|
}) {
|
|
787
1099
|
const theme = useAuthTheme(themeProp);
|
|
788
|
-
const
|
|
1100
|
+
const styles3 = useAuthStyles(theme);
|
|
789
1101
|
const labels = react.useMemo(
|
|
790
1102
|
() => ({ ...DEFAULT_RESET_PASSWORD_LABELS, ...labelsProp }),
|
|
791
1103
|
[labelsProp]
|
|
792
1104
|
);
|
|
793
1105
|
const form = useResetPasswordForm({ client, token, onSuccess });
|
|
794
1106
|
const message = errorMessage(form.errorKey, labels);
|
|
795
|
-
const submitButtonStyle = form.isSubmitting ? [
|
|
796
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
1107
|
+
const submitButtonStyle = form.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1108
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
797
1109
|
reactNative.View,
|
|
798
1110
|
{
|
|
799
|
-
style:
|
|
1111
|
+
style: styles3.card,
|
|
800
1112
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix),
|
|
801
1113
|
children: [
|
|
802
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
803
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
804
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
805
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
1115
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
1116
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1117
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.newPasswordLabel }),
|
|
806
1118
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
807
1119
|
reactNative.TextInput,
|
|
808
1120
|
{
|
|
@@ -814,15 +1126,15 @@ function ResetPasswordForm({
|
|
|
814
1126
|
editable: !form.isSubmitting,
|
|
815
1127
|
placeholder: labels.newPasswordPlaceholder,
|
|
816
1128
|
placeholderTextColor: theme.colors.textSecondary,
|
|
817
|
-
style:
|
|
1129
|
+
style: styles3.input,
|
|
818
1130
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
|
|
819
1131
|
value: form.newPassword,
|
|
820
1132
|
onChangeText: form.setNewPassword
|
|
821
1133
|
}
|
|
822
1134
|
)
|
|
823
1135
|
] }),
|
|
824
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
825
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1136
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1137
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
|
|
826
1138
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
827
1139
|
reactNative.TextInput,
|
|
828
1140
|
{
|
|
@@ -834,7 +1146,7 @@ function ResetPasswordForm({
|
|
|
834
1146
|
editable: !form.isSubmitting,
|
|
835
1147
|
placeholder: labels.confirmPasswordPlaceholder,
|
|
836
1148
|
placeholderTextColor: theme.colors.textSecondary,
|
|
837
|
-
style:
|
|
1149
|
+
style: styles3.input,
|
|
838
1150
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
|
|
839
1151
|
value: form.confirmPassword,
|
|
840
1152
|
onChangeText: form.setConfirmPassword
|
|
@@ -844,7 +1156,7 @@ function ResetPasswordForm({
|
|
|
844
1156
|
message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
845
1157
|
reactNative.Text,
|
|
846
1158
|
{
|
|
847
|
-
style:
|
|
1159
|
+
style: styles3.errorText,
|
|
848
1160
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
|
|
849
1161
|
children: message
|
|
850
1162
|
}
|
|
@@ -859,7 +1171,7 @@ function ResetPasswordForm({
|
|
|
859
1171
|
style: submitButtonStyle,
|
|
860
1172
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
|
|
861
1173
|
onPress: form.submit,
|
|
862
|
-
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1174
|
+
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
863
1175
|
}
|
|
864
1176
|
)
|
|
865
1177
|
]
|
|
@@ -867,7 +1179,7 @@ function ResetPasswordForm({
|
|
|
867
1179
|
) });
|
|
868
1180
|
}
|
|
869
1181
|
function OtpRequestStep({
|
|
870
|
-
styles,
|
|
1182
|
+
styles: styles3,
|
|
871
1183
|
theme,
|
|
872
1184
|
labels,
|
|
873
1185
|
testIdPrefix,
|
|
@@ -876,12 +1188,12 @@ function OtpRequestStep({
|
|
|
876
1188
|
onSubmit
|
|
877
1189
|
}) {
|
|
878
1190
|
const [email, setEmail] = react.useState("");
|
|
879
|
-
const buttonStyle = isSubmitting ? [
|
|
1191
|
+
const buttonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
880
1192
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
881
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
882
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
883
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
884
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1193
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.requestTitle }),
|
|
1194
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.requestDescription }),
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1196
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.emailLabel }),
|
|
885
1197
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
886
1198
|
reactNative.TextInput,
|
|
887
1199
|
{
|
|
@@ -893,14 +1205,14 @@ function OtpRequestStep({
|
|
|
893
1205
|
keyboardType: "email-address",
|
|
894
1206
|
placeholder: labels.emailPlaceholder,
|
|
895
1207
|
placeholderTextColor: theme.colors.textSecondary,
|
|
896
|
-
style:
|
|
1208
|
+
style: styles3.input,
|
|
897
1209
|
testID: withTestIdPrefix(AuthTestIds.otpEmailInput, testIdPrefix),
|
|
898
1210
|
value: email,
|
|
899
1211
|
onChangeText: setEmail
|
|
900
1212
|
}
|
|
901
1213
|
)
|
|
902
1214
|
] }),
|
|
903
|
-
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1215
|
+
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, testID: withTestIdPrefix(AuthTestIds.otpError, testIdPrefix), children: errorText }) : null,
|
|
904
1216
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
905
1217
|
reactNative.TouchableOpacity,
|
|
906
1218
|
{
|
|
@@ -911,13 +1223,13 @@ function OtpRequestStep({
|
|
|
911
1223
|
style: buttonStyle,
|
|
912
1224
|
testID: withTestIdPrefix(AuthTestIds.otpRequestButton, testIdPrefix),
|
|
913
1225
|
onPress: () => onSubmit(email.trim()),
|
|
914
|
-
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1226
|
+
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.requestSubmit })
|
|
915
1227
|
}
|
|
916
1228
|
)
|
|
917
1229
|
] });
|
|
918
1230
|
}
|
|
919
1231
|
function OtpVerifyStep({
|
|
920
|
-
styles,
|
|
1232
|
+
styles: styles3,
|
|
921
1233
|
theme,
|
|
922
1234
|
labels,
|
|
923
1235
|
testIdPrefix,
|
|
@@ -929,13 +1241,13 @@ function OtpVerifyStep({
|
|
|
929
1241
|
onChangeEmail
|
|
930
1242
|
}) {
|
|
931
1243
|
const [code, setCode] = react.useState("");
|
|
932
|
-
const buttonStyle = isSubmitting ? [
|
|
1244
|
+
const buttonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
933
1245
|
const description = labels.verifyDescription.replace("{identifier}", identifier);
|
|
934
1246
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
935
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
936
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
937
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
938
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1247
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.verifyTitle }),
|
|
1248
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: description }),
|
|
1249
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1250
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.codeLabel }),
|
|
939
1251
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
940
1252
|
reactNative.TextInput,
|
|
941
1253
|
{
|
|
@@ -947,14 +1259,14 @@ function OtpVerifyStep({
|
|
|
947
1259
|
keyboardType: "number-pad",
|
|
948
1260
|
placeholder: labels.codePlaceholder,
|
|
949
1261
|
placeholderTextColor: theme.colors.textSecondary,
|
|
950
|
-
style:
|
|
1262
|
+
style: styles3.input,
|
|
951
1263
|
testID: withTestIdPrefix(AuthTestIds.otpCodeInput, testIdPrefix),
|
|
952
1264
|
value: code,
|
|
953
1265
|
onChangeText: setCode
|
|
954
1266
|
}
|
|
955
1267
|
)
|
|
956
1268
|
] }),
|
|
957
|
-
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1269
|
+
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, testID: withTestIdPrefix(AuthTestIds.otpError, testIdPrefix), children: errorText }) : null,
|
|
958
1270
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
959
1271
|
reactNative.TouchableOpacity,
|
|
960
1272
|
{
|
|
@@ -965,7 +1277,7 @@ function OtpVerifyStep({
|
|
|
965
1277
|
style: buttonStyle,
|
|
966
1278
|
testID: withTestIdPrefix(AuthTestIds.otpVerifyButton, testIdPrefix),
|
|
967
1279
|
onPress: () => onSubmit(code.trim()),
|
|
968
|
-
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1280
|
+
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.verifySubmit })
|
|
969
1281
|
}
|
|
970
1282
|
),
|
|
971
1283
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -975,10 +1287,10 @@ function OtpVerifyStep({
|
|
|
975
1287
|
accessibilityLabel: isSubmitting ? labels.resending : labels.resend,
|
|
976
1288
|
accessibilityRole: "link",
|
|
977
1289
|
disabled: isSubmitting,
|
|
978
|
-
style:
|
|
1290
|
+
style: styles3.fieldGroup,
|
|
979
1291
|
testID: withTestIdPrefix(AuthTestIds.otpResendButton, testIdPrefix),
|
|
980
1292
|
onPress: onResend,
|
|
981
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: isSubmitting ? labels.resending : labels.resend })
|
|
982
1294
|
}
|
|
983
1295
|
),
|
|
984
1296
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -990,7 +1302,7 @@ function OtpVerifyStep({
|
|
|
990
1302
|
disabled: isSubmitting,
|
|
991
1303
|
testID: withTestIdPrefix(AuthTestIds.otpChangeEmailButton, testIdPrefix),
|
|
992
1304
|
onPress: onChangeEmail,
|
|
993
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1305
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.changeEmail })
|
|
994
1306
|
}
|
|
995
1307
|
)
|
|
996
1308
|
] });
|
|
@@ -1113,9 +1425,9 @@ function useOtpLogin(options) {
|
|
|
1113
1425
|
]
|
|
1114
1426
|
);
|
|
1115
1427
|
}
|
|
1116
|
-
var
|
|
1428
|
+
var EMAIL_REGEX3 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
|
|
1117
1429
|
function isValidEmail2(value) {
|
|
1118
|
-
return
|
|
1430
|
+
return EMAIL_REGEX3.test(value);
|
|
1119
1431
|
}
|
|
1120
1432
|
function transportErrorFor(step, error, labels) {
|
|
1121
1433
|
if (error === null) {
|
|
@@ -1159,7 +1471,7 @@ function OtpForm({
|
|
|
1159
1471
|
testIdPrefix
|
|
1160
1472
|
}) {
|
|
1161
1473
|
const theme = useAuthTheme(themeProp);
|
|
1162
|
-
const
|
|
1474
|
+
const styles3 = useAuthStyles(theme);
|
|
1163
1475
|
const labels = react.useMemo(
|
|
1164
1476
|
() => ({ ...DEFAULT_OTP_LABELS, ...labelsProp }),
|
|
1165
1477
|
[labelsProp]
|
|
@@ -1177,13 +1489,13 @@ function OtpForm({
|
|
|
1177
1489
|
otp.reset();
|
|
1178
1490
|
}, [otp]);
|
|
1179
1491
|
const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);
|
|
1180
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
1492
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix), children: otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1181
1493
|
OtpRequestStep,
|
|
1182
1494
|
{
|
|
1183
1495
|
errorText,
|
|
1184
1496
|
isSubmitting: otp.isSubmitting,
|
|
1185
1497
|
labels,
|
|
1186
|
-
styles,
|
|
1498
|
+
styles: styles3,
|
|
1187
1499
|
testIdPrefix,
|
|
1188
1500
|
theme,
|
|
1189
1501
|
onSubmit: handleRequest
|
|
@@ -1195,7 +1507,7 @@ function OtpForm({
|
|
|
1195
1507
|
identifier: otp.identifier,
|
|
1196
1508
|
isSubmitting: otp.isSubmitting,
|
|
1197
1509
|
labels,
|
|
1198
|
-
styles,
|
|
1510
|
+
styles: styles3,
|
|
1199
1511
|
testIdPrefix,
|
|
1200
1512
|
theme,
|
|
1201
1513
|
onChangeEmail: handleChangeEmail,
|
|
@@ -1284,7 +1596,7 @@ function PinForm({
|
|
|
1284
1596
|
testIdPrefix
|
|
1285
1597
|
}) {
|
|
1286
1598
|
const theme = useAuthTheme(themeProp);
|
|
1287
|
-
const
|
|
1599
|
+
const styles3 = useAuthStyles(theme);
|
|
1288
1600
|
const labels = react.useMemo(
|
|
1289
1601
|
() => ({ ...DEFAULT_PIN_LABELS, ...labelsProp }),
|
|
1290
1602
|
[labelsProp]
|
|
@@ -1294,12 +1606,12 @@ function PinForm({
|
|
|
1294
1606
|
const [pinValue, setPinValue] = react.useState("");
|
|
1295
1607
|
const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);
|
|
1296
1608
|
const errorText = localError ?? transportErrorFor2(pin.error, labels);
|
|
1297
|
-
const buttonStyle = pin.isSubmitting ? [
|
|
1298
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
1299
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1300
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1301
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1302
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1609
|
+
const buttonStyle = pin.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1610
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix), children: [
|
|
1611
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
1612
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
1613
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1614
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.pinLabel }),
|
|
1303
1615
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1304
1616
|
reactNative.TextInput,
|
|
1305
1617
|
{
|
|
@@ -1312,7 +1624,7 @@ function PinForm({
|
|
|
1312
1624
|
placeholder: labels.pinPlaceholder,
|
|
1313
1625
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1314
1626
|
secureTextEntry: true,
|
|
1315
|
-
style:
|
|
1627
|
+
style: styles3.input,
|
|
1316
1628
|
testID: withTestIdPrefix(AuthTestIds.pinInput, testIdPrefix),
|
|
1317
1629
|
value: pinValue,
|
|
1318
1630
|
onChangeText: setPinValue
|
|
@@ -1322,7 +1634,7 @@ function PinForm({
|
|
|
1322
1634
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1323
1635
|
reactNative.Text,
|
|
1324
1636
|
{
|
|
1325
|
-
style:
|
|
1637
|
+
style: styles3.errorText,
|
|
1326
1638
|
testID: withTestIdPrefix(AuthTestIds.pinError, testIdPrefix),
|
|
1327
1639
|
children: errorText
|
|
1328
1640
|
}
|
|
@@ -1337,11 +1649,918 @@ function PinForm({
|
|
|
1337
1649
|
style: buttonStyle,
|
|
1338
1650
|
testID: withTestIdPrefix(AuthTestIds.pinSubmitButton, testIdPrefix),
|
|
1339
1651
|
onPress: () => handleSubmit(pinValue.trim()),
|
|
1340
|
-
children: pin.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1652
|
+
children: pin.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
1341
1653
|
}
|
|
1342
1654
|
)
|
|
1343
1655
|
] }) });
|
|
1344
1656
|
}
|
|
1657
|
+
var DOT_SIZE = 18;
|
|
1658
|
+
var DOT_BORDER_WIDTH = 2;
|
|
1659
|
+
var DOT_RADIUS = 9;
|
|
1660
|
+
var ROW_GAP = 12;
|
|
1661
|
+
var ROW_MIN_HEIGHT = 44;
|
|
1662
|
+
var ROW_VERTICAL_MARGIN = 16;
|
|
1663
|
+
var HIDDEN_SIZE = 1;
|
|
1664
|
+
function sanitise(raw, length) {
|
|
1665
|
+
return raw.replace(/\D/g, "").slice(0, length);
|
|
1666
|
+
}
|
|
1667
|
+
function useDotStyles(theme) {
|
|
1668
|
+
return react.useMemo(
|
|
1669
|
+
() => ({
|
|
1670
|
+
filled: { backgroundColor: theme.colors.primary, borderColor: theme.colors.primary },
|
|
1671
|
+
empty: { backgroundColor: theme.colors.background, borderColor: theme.colors.border }
|
|
1672
|
+
}),
|
|
1673
|
+
[theme]
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
function DevicePinInput({
|
|
1677
|
+
value,
|
|
1678
|
+
length,
|
|
1679
|
+
disabled,
|
|
1680
|
+
testID,
|
|
1681
|
+
testIdPrefix,
|
|
1682
|
+
accessibilityLabel,
|
|
1683
|
+
accessibilityHint,
|
|
1684
|
+
filledHint,
|
|
1685
|
+
emptyHint,
|
|
1686
|
+
theme: themeProp,
|
|
1687
|
+
onChange
|
|
1688
|
+
}) {
|
|
1689
|
+
const theme = useAuthTheme(themeProp);
|
|
1690
|
+
const inputRef = react.useRef(null);
|
|
1691
|
+
const dotStyles = useDotStyles(theme);
|
|
1692
|
+
const cells = Array.from({ length }, (_unused, index) => index);
|
|
1693
|
+
const baseId = withTestIdPrefix(testID, testIdPrefix);
|
|
1694
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1695
|
+
reactNative.Pressable,
|
|
1696
|
+
{
|
|
1697
|
+
accessibilityHint,
|
|
1698
|
+
accessibilityLabel,
|
|
1699
|
+
accessibilityRole: "button",
|
|
1700
|
+
disabled,
|
|
1701
|
+
style: styles.row,
|
|
1702
|
+
testID: `${baseId}-row`,
|
|
1703
|
+
onPress: () => inputRef.current?.focus(),
|
|
1704
|
+
children: [
|
|
1705
|
+
cells.map((index) => {
|
|
1706
|
+
const filled = index < value.length;
|
|
1707
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1708
|
+
reactNative.View,
|
|
1709
|
+
{
|
|
1710
|
+
accessibilityLabel: filled ? filledHint : emptyHint,
|
|
1711
|
+
style: [styles.dot, filled ? dotStyles.filled : dotStyles.empty],
|
|
1712
|
+
testID: `${baseId}-dot-${String(index)}`
|
|
1713
|
+
},
|
|
1714
|
+
index
|
|
1715
|
+
);
|
|
1716
|
+
}),
|
|
1717
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1718
|
+
reactNative.TextInput,
|
|
1719
|
+
{
|
|
1720
|
+
ref: inputRef,
|
|
1721
|
+
accessibilityHint,
|
|
1722
|
+
accessibilityLabel,
|
|
1723
|
+
autoFocus: true,
|
|
1724
|
+
caretHidden: true,
|
|
1725
|
+
editable: !disabled,
|
|
1726
|
+
keyboardType: "number-pad",
|
|
1727
|
+
maxLength: length,
|
|
1728
|
+
secureTextEntry: true,
|
|
1729
|
+
style: styles.hiddenInput,
|
|
1730
|
+
testID: baseId,
|
|
1731
|
+
value,
|
|
1732
|
+
onChangeText: (raw) => onChange(sanitise(raw, length))
|
|
1733
|
+
}
|
|
1734
|
+
)
|
|
1735
|
+
]
|
|
1736
|
+
}
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
var styles = reactNative.StyleSheet.create({
|
|
1740
|
+
dot: {
|
|
1741
|
+
borderRadius: DOT_RADIUS,
|
|
1742
|
+
borderWidth: DOT_BORDER_WIDTH,
|
|
1743
|
+
height: DOT_SIZE,
|
|
1744
|
+
width: DOT_SIZE
|
|
1745
|
+
},
|
|
1746
|
+
hiddenInput: {
|
|
1747
|
+
height: HIDDEN_SIZE,
|
|
1748
|
+
opacity: 0,
|
|
1749
|
+
position: "absolute",
|
|
1750
|
+
width: HIDDEN_SIZE
|
|
1751
|
+
},
|
|
1752
|
+
row: {
|
|
1753
|
+
alignItems: "center",
|
|
1754
|
+
flexDirection: "row",
|
|
1755
|
+
gap: ROW_GAP,
|
|
1756
|
+
justifyContent: "center",
|
|
1757
|
+
marginVertical: ROW_VERTICAL_MARGIN,
|
|
1758
|
+
minHeight: ROW_MIN_HEIGHT
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
|
|
1762
|
+
// src/components/interpolate.ts
|
|
1763
|
+
function interpolate(template, values) {
|
|
1764
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
1765
|
+
const value = values[key];
|
|
1766
|
+
return value === void 0 ? match : String(value);
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// src/devicePin/devicePinConstants.ts
|
|
1771
|
+
var DEVICE_PIN_ALLOWED_DIGITS = [4, 6, 8];
|
|
1772
|
+
var DEVICE_PIN_DEFAULT_DIGITS = 4;
|
|
1773
|
+
function isAllowedPinDigits(value) {
|
|
1774
|
+
return DEVICE_PIN_ALLOWED_DIGITS.includes(value);
|
|
1775
|
+
}
|
|
1776
|
+
var PILL_VERTICAL_PADDING = 10;
|
|
1777
|
+
var PILL_FONT_SIZE = 15;
|
|
1778
|
+
function usePickerStyles(theme) {
|
|
1779
|
+
return react.useMemo(
|
|
1780
|
+
() => ({
|
|
1781
|
+
pill: { borderColor: theme.colors.border },
|
|
1782
|
+
active: { backgroundColor: theme.colors.primary, borderColor: theme.colors.primary },
|
|
1783
|
+
text: { color: theme.colors.text },
|
|
1784
|
+
textActive: { color: theme.colors.onPrimary }
|
|
1785
|
+
}),
|
|
1786
|
+
[theme]
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
function DevicePinLengthPicker({
|
|
1790
|
+
selected,
|
|
1791
|
+
disabled,
|
|
1792
|
+
optionHint,
|
|
1793
|
+
testIdPrefix,
|
|
1794
|
+
theme: themeProp,
|
|
1795
|
+
onSelect
|
|
1796
|
+
}) {
|
|
1797
|
+
const theme = useAuthTheme(themeProp);
|
|
1798
|
+
const dynamic = usePickerStyles(theme);
|
|
1799
|
+
const baseId = withTestIdPrefix(AuthTestIds.devicePinEnrollLength, testIdPrefix);
|
|
1800
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.row, children: DEVICE_PIN_ALLOWED_DIGITS.map((option) => {
|
|
1801
|
+
const active = option === selected;
|
|
1802
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1803
|
+
reactNative.Pressable,
|
|
1804
|
+
{
|
|
1805
|
+
accessibilityHint: interpolate(optionHint, { count: option }),
|
|
1806
|
+
accessibilityLabel: String(option),
|
|
1807
|
+
accessibilityRole: "button",
|
|
1808
|
+
accessibilityState: { selected: active },
|
|
1809
|
+
disabled,
|
|
1810
|
+
style: [styles2.pill, dynamic.pill, active ? dynamic.active : null],
|
|
1811
|
+
testID: `${baseId}-${String(option)}`,
|
|
1812
|
+
onPress: () => onSelect(option),
|
|
1813
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.text, dynamic.text, active ? dynamic.textActive : null], children: String(option) })
|
|
1814
|
+
},
|
|
1815
|
+
option
|
|
1816
|
+
);
|
|
1817
|
+
}) });
|
|
1818
|
+
}
|
|
1819
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
1820
|
+
pill: {
|
|
1821
|
+
alignItems: "center",
|
|
1822
|
+
borderRadius: 8,
|
|
1823
|
+
borderWidth: 1,
|
|
1824
|
+
flex: 1,
|
|
1825
|
+
paddingVertical: PILL_VERTICAL_PADDING
|
|
1826
|
+
},
|
|
1827
|
+
row: {
|
|
1828
|
+
flexDirection: "row",
|
|
1829
|
+
gap: 8,
|
|
1830
|
+
marginBottom: 8
|
|
1831
|
+
},
|
|
1832
|
+
text: {
|
|
1833
|
+
fontSize: PILL_FONT_SIZE,
|
|
1834
|
+
fontWeight: "700"
|
|
1835
|
+
}
|
|
1836
|
+
});
|
|
1837
|
+
|
|
1838
|
+
// src/devicePin/DevicePinErrorKey.ts
|
|
1839
|
+
var DevicePinErrorKey = /* @__PURE__ */ ((DevicePinErrorKey2) => {
|
|
1840
|
+
DevicePinErrorKey2["Incomplete"] = "incomplete";
|
|
1841
|
+
DevicePinErrorKey2["Invalid"] = "invalid";
|
|
1842
|
+
DevicePinErrorKey2["LockedOut"] = "locked_out";
|
|
1843
|
+
DevicePinErrorKey2["RateLimited"] = "rate_limited";
|
|
1844
|
+
DevicePinErrorKey2["Generic"] = "generic";
|
|
1845
|
+
return DevicePinErrorKey2;
|
|
1846
|
+
})(DevicePinErrorKey || {});
|
|
1847
|
+
function useDevicePinUnlock({
|
|
1848
|
+
client,
|
|
1849
|
+
digits,
|
|
1850
|
+
onSignedIn
|
|
1851
|
+
}) {
|
|
1852
|
+
const [pin, setPinState] = react.useState("");
|
|
1853
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
1854
|
+
const [errorKey, setErrorKey] = react.useState(null);
|
|
1855
|
+
const [retryAfterSeconds, setRetryAfterSeconds] = react.useState(null);
|
|
1856
|
+
const setPin = react.useCallback((next) => {
|
|
1857
|
+
setPinState(next);
|
|
1858
|
+
setErrorKey(null);
|
|
1859
|
+
setRetryAfterSeconds(null);
|
|
1860
|
+
}, []);
|
|
1861
|
+
const submit = react.useCallback(() => {
|
|
1862
|
+
setErrorKey(null);
|
|
1863
|
+
setRetryAfterSeconds(null);
|
|
1864
|
+
if (pin.length < digits) {
|
|
1865
|
+
setErrorKey("incomplete" /* Incomplete */);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
setSubmitting(true);
|
|
1869
|
+
client.unlockWithDevicePin({ pin }).then((result) => {
|
|
1870
|
+
if (result.status === "success") {
|
|
1871
|
+
onSignedIn(result.user);
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
if (result.status === "invalid") {
|
|
1875
|
+
setErrorKey("invalid" /* Invalid */);
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
if (result.status === "locked") {
|
|
1879
|
+
setRetryAfterSeconds(result.retryAfterSeconds);
|
|
1880
|
+
setErrorKey("locked_out" /* LockedOut */);
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
if (result.status === "rateLimited") {
|
|
1884
|
+
setRetryAfterSeconds(result.retryAfterSeconds);
|
|
1885
|
+
setErrorKey("rate_limited" /* RateLimited */);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
setErrorKey("generic" /* Generic */);
|
|
1889
|
+
}).catch(() => {
|
|
1890
|
+
setErrorKey("generic" /* Generic */);
|
|
1891
|
+
}).finally(() => {
|
|
1892
|
+
setSubmitting(false);
|
|
1893
|
+
});
|
|
1894
|
+
}, [client, pin, digits, onSignedIn]);
|
|
1895
|
+
return { pin, submitting, errorKey, retryAfterSeconds, setPin, submit };
|
|
1896
|
+
}
|
|
1897
|
+
function resolveErrorText(errorKey, digits, retryAfter, labels) {
|
|
1898
|
+
if (errorKey === null) {
|
|
1899
|
+
return null;
|
|
1900
|
+
}
|
|
1901
|
+
if (errorKey === "incomplete" /* Incomplete */) {
|
|
1902
|
+
return interpolate(labels.errorIncomplete, { count: digits });
|
|
1903
|
+
}
|
|
1904
|
+
if (errorKey === "invalid" /* Invalid */) {
|
|
1905
|
+
return labels.errorInvalid;
|
|
1906
|
+
}
|
|
1907
|
+
if (errorKey === "locked_out" /* LockedOut */) {
|
|
1908
|
+
return retryAfter !== null ? interpolate(labels.errorLockedOutRetry, { count: retryAfter }) : labels.errorLockedOut;
|
|
1909
|
+
}
|
|
1910
|
+
if (errorKey === "rate_limited" /* RateLimited */) {
|
|
1911
|
+
return retryAfter !== null ? interpolate(labels.errorRateLimitedRetry, { count: retryAfter }) : labels.errorRateLimited;
|
|
1912
|
+
}
|
|
1913
|
+
return labels.errorGeneric;
|
|
1914
|
+
}
|
|
1915
|
+
function DevicePinUnlockScreen({
|
|
1916
|
+
client,
|
|
1917
|
+
digits,
|
|
1918
|
+
rememberedUsername,
|
|
1919
|
+
theme: themeProp,
|
|
1920
|
+
labels: labelsProp,
|
|
1921
|
+
testIdPrefix,
|
|
1922
|
+
onSignedIn,
|
|
1923
|
+
onUsePassword
|
|
1924
|
+
}) {
|
|
1925
|
+
const theme = useAuthTheme(themeProp);
|
|
1926
|
+
const styles3 = useAuthStyles(theme);
|
|
1927
|
+
const labels = react.useMemo(
|
|
1928
|
+
() => ({ ...DEFAULT_DEVICE_PIN_UNLOCK_LABELS, ...labelsProp }),
|
|
1929
|
+
[labelsProp]
|
|
1930
|
+
);
|
|
1931
|
+
const { pin, submitting, errorKey, retryAfterSeconds, setPin, submit } = useDevicePinUnlock({
|
|
1932
|
+
client,
|
|
1933
|
+
digits,
|
|
1934
|
+
onSignedIn
|
|
1935
|
+
});
|
|
1936
|
+
const hasName = rememberedUsername !== "";
|
|
1937
|
+
const title = hasName ? interpolate(labels.title, { name: rememberedUsername }) : labels.titleNoName;
|
|
1938
|
+
const error = resolveErrorText(errorKey, digits, retryAfterSeconds, labels);
|
|
1939
|
+
const buttonStyle = submitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1940
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1941
|
+
reactNative.View,
|
|
1942
|
+
{
|
|
1943
|
+
style: styles3.card,
|
|
1944
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinUnlock, testIdPrefix),
|
|
1945
|
+
children: [
|
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: title }),
|
|
1947
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: interpolate(labels.description, { count: digits }) }),
|
|
1948
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1949
|
+
DevicePinInput,
|
|
1950
|
+
{
|
|
1951
|
+
accessibilityHint: labels.pinPlaceholder,
|
|
1952
|
+
accessibilityLabel: labels.pinLabel,
|
|
1953
|
+
disabled: submitting,
|
|
1954
|
+
emptyHint: labels.digitEmptyHint,
|
|
1955
|
+
filledHint: labels.digitFilledHint,
|
|
1956
|
+
length: digits,
|
|
1957
|
+
testID: AuthTestIds.devicePinUnlockInput,
|
|
1958
|
+
testIdPrefix,
|
|
1959
|
+
theme,
|
|
1960
|
+
value: pin,
|
|
1961
|
+
onChange: setPin
|
|
1962
|
+
}
|
|
1963
|
+
),
|
|
1964
|
+
error !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1965
|
+
reactNative.Text,
|
|
1966
|
+
{
|
|
1967
|
+
style: styles3.errorText,
|
|
1968
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinUnlockError, testIdPrefix),
|
|
1969
|
+
children: error
|
|
1970
|
+
}
|
|
1971
|
+
) : null,
|
|
1972
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1973
|
+
reactNative.TouchableOpacity,
|
|
1974
|
+
{
|
|
1975
|
+
accessibilityHint: labels.submit,
|
|
1976
|
+
accessibilityLabel: submitting ? labels.submitting : labels.submit,
|
|
1977
|
+
accessibilityRole: "button",
|
|
1978
|
+
disabled: submitting,
|
|
1979
|
+
style: buttonStyle,
|
|
1980
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinUnlockSubmit, testIdPrefix),
|
|
1981
|
+
onPress: submit,
|
|
1982
|
+
children: submitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
1983
|
+
}
|
|
1984
|
+
),
|
|
1985
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1986
|
+
reactNative.TouchableOpacity,
|
|
1987
|
+
{
|
|
1988
|
+
accessibilityHint: labels.usePasswordHint,
|
|
1989
|
+
accessibilityLabel: labels.usePasswordInstead,
|
|
1990
|
+
accessibilityRole: "button",
|
|
1991
|
+
disabled: submitting,
|
|
1992
|
+
style: styles3.escapeLink,
|
|
1993
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinUnlockUsePassword, testIdPrefix),
|
|
1994
|
+
onPress: onUsePassword,
|
|
1995
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.usePasswordInstead })
|
|
1996
|
+
}
|
|
1997
|
+
)
|
|
1998
|
+
]
|
|
1999
|
+
}
|
|
2000
|
+
) });
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
// src/devicePin/DevicePinEnrollErrorKey.ts
|
|
2004
|
+
var DevicePinEnrollErrorKey = /* @__PURE__ */ ((DevicePinEnrollErrorKey2) => {
|
|
2005
|
+
DevicePinEnrollErrorKey2["Mismatch"] = "mismatch";
|
|
2006
|
+
DevicePinEnrollErrorKey2["Unauthorized"] = "unauthorized";
|
|
2007
|
+
DevicePinEnrollErrorKey2["Forbidden"] = "forbidden";
|
|
2008
|
+
DevicePinEnrollErrorKey2["InvalidPin"] = "invalid_pin";
|
|
2009
|
+
DevicePinEnrollErrorKey2["Failed"] = "failed";
|
|
2010
|
+
return DevicePinEnrollErrorKey2;
|
|
2011
|
+
})(DevicePinEnrollErrorKey || {});
|
|
2012
|
+
function errorKeyFor(result) {
|
|
2013
|
+
if (result.status === "unauthorized") {
|
|
2014
|
+
return "unauthorized" /* Unauthorized */;
|
|
2015
|
+
}
|
|
2016
|
+
if (result.status === "forbidden") {
|
|
2017
|
+
return "forbidden" /* Forbidden */;
|
|
2018
|
+
}
|
|
2019
|
+
if (result.status === "invalidPin") {
|
|
2020
|
+
return "invalid_pin" /* InvalidPin */;
|
|
2021
|
+
}
|
|
2022
|
+
return "failed" /* Failed */;
|
|
2023
|
+
}
|
|
2024
|
+
function useDevicePinEnroll({
|
|
2025
|
+
client,
|
|
2026
|
+
digits,
|
|
2027
|
+
onEnrolled
|
|
2028
|
+
}) {
|
|
2029
|
+
const [pin, setPinState] = react.useState("");
|
|
2030
|
+
const [confirmPin, setConfirmState] = react.useState("");
|
|
2031
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
2032
|
+
const [errorKey, setErrorKey] = react.useState(null);
|
|
2033
|
+
const setPin = react.useCallback((next) => {
|
|
2034
|
+
setPinState(next);
|
|
2035
|
+
setErrorKey(null);
|
|
2036
|
+
}, []);
|
|
2037
|
+
const setConfirmPin = react.useCallback((next) => {
|
|
2038
|
+
setConfirmState(next);
|
|
2039
|
+
setErrorKey(null);
|
|
2040
|
+
}, []);
|
|
2041
|
+
const submit = react.useCallback(() => {
|
|
2042
|
+
setErrorKey(null);
|
|
2043
|
+
const wrongLength = pin.length !== digits;
|
|
2044
|
+
const mismatched = pin !== confirmPin;
|
|
2045
|
+
if (wrongLength || mismatched) {
|
|
2046
|
+
setErrorKey("mismatch" /* Mismatch */);
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
setSubmitting(true);
|
|
2050
|
+
client.enrollDevicePin({ pin, digits }).then((result) => {
|
|
2051
|
+
if (result.status === "success") {
|
|
2052
|
+
onEnrolled();
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
setErrorKey(errorKeyFor(result));
|
|
2056
|
+
}).catch(() => {
|
|
2057
|
+
setErrorKey("failed" /* Failed */);
|
|
2058
|
+
}).finally(() => {
|
|
2059
|
+
setSubmitting(false);
|
|
2060
|
+
});
|
|
2061
|
+
}, [client, pin, confirmPin, digits, onEnrolled]);
|
|
2062
|
+
return { pin, confirmPin, submitting, errorKey, setPin, setConfirmPin, submit };
|
|
2063
|
+
}
|
|
2064
|
+
function resolveErrorText2(errorKey, digits, labels) {
|
|
2065
|
+
if (errorKey === null) {
|
|
2066
|
+
return null;
|
|
2067
|
+
}
|
|
2068
|
+
if (errorKey === "mismatch" /* Mismatch */) {
|
|
2069
|
+
return interpolate(labels.errorMismatch, { count: digits });
|
|
2070
|
+
}
|
|
2071
|
+
if (errorKey === "unauthorized" /* Unauthorized */) {
|
|
2072
|
+
return labels.errorUnauthorized;
|
|
2073
|
+
}
|
|
2074
|
+
if (errorKey === "forbidden" /* Forbidden */) {
|
|
2075
|
+
return labels.errorForbidden;
|
|
2076
|
+
}
|
|
2077
|
+
if (errorKey === "invalid_pin" /* InvalidPin */) {
|
|
2078
|
+
return labels.errorInvalidPin;
|
|
2079
|
+
}
|
|
2080
|
+
return labels.errorFailed;
|
|
2081
|
+
}
|
|
2082
|
+
function DevicePinEnrollForm({
|
|
2083
|
+
client,
|
|
2084
|
+
initialDigits = DEVICE_PIN_DEFAULT_DIGITS,
|
|
2085
|
+
theme: themeProp,
|
|
2086
|
+
labels: labelsProp,
|
|
2087
|
+
testIdPrefix,
|
|
2088
|
+
onEnrolled,
|
|
2089
|
+
onCancel
|
|
2090
|
+
}) {
|
|
2091
|
+
const theme = useAuthTheme(themeProp);
|
|
2092
|
+
const styles3 = useAuthStyles(theme);
|
|
2093
|
+
const labels = react.useMemo(
|
|
2094
|
+
() => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...labelsProp }),
|
|
2095
|
+
[labelsProp]
|
|
2096
|
+
);
|
|
2097
|
+
const [digits, setDigits] = react.useState(initialDigits);
|
|
2098
|
+
const { pin, confirmPin, submitting, errorKey, setPin, setConfirmPin, submit } = useDevicePinEnroll({ client, digits, onEnrolled });
|
|
2099
|
+
const error = resolveErrorText2(errorKey, digits, labels);
|
|
2100
|
+
const buttonStyle = submitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
2101
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2102
|
+
reactNative.View,
|
|
2103
|
+
{
|
|
2104
|
+
style: styles3.card,
|
|
2105
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinEnrollForm, testIdPrefix),
|
|
2106
|
+
children: [
|
|
2107
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.formTitle }),
|
|
2108
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: interpolate(labels.formDescription, { count: digits }) }),
|
|
2109
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.lengthLabel }),
|
|
2110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2111
|
+
DevicePinLengthPicker,
|
|
2112
|
+
{
|
|
2113
|
+
disabled: submitting,
|
|
2114
|
+
optionHint: labels.lengthOptionHint,
|
|
2115
|
+
selected: digits,
|
|
2116
|
+
testIdPrefix,
|
|
2117
|
+
theme,
|
|
2118
|
+
onSelect: (option) => {
|
|
2119
|
+
setDigits(option);
|
|
2120
|
+
setPin("");
|
|
2121
|
+
setConfirmPin("");
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
),
|
|
2125
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.pinLabel }),
|
|
2126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2127
|
+
DevicePinInput,
|
|
2128
|
+
{
|
|
2129
|
+
accessibilityHint: labels.pinPlaceholder,
|
|
2130
|
+
accessibilityLabel: labels.pinLabel,
|
|
2131
|
+
disabled: submitting,
|
|
2132
|
+
emptyHint: labels.pinPlaceholder,
|
|
2133
|
+
filledHint: labels.pinLabel,
|
|
2134
|
+
length: digits,
|
|
2135
|
+
testID: AuthTestIds.devicePinEnrollPin,
|
|
2136
|
+
testIdPrefix,
|
|
2137
|
+
theme,
|
|
2138
|
+
value: pin,
|
|
2139
|
+
onChange: setPin
|
|
2140
|
+
}
|
|
2141
|
+
),
|
|
2142
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmLabel }),
|
|
2143
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2144
|
+
DevicePinInput,
|
|
2145
|
+
{
|
|
2146
|
+
accessibilityHint: labels.confirmPlaceholder,
|
|
2147
|
+
accessibilityLabel: labels.confirmLabel,
|
|
2148
|
+
disabled: submitting,
|
|
2149
|
+
emptyHint: labels.confirmPlaceholder,
|
|
2150
|
+
filledHint: labels.confirmLabel,
|
|
2151
|
+
length: digits,
|
|
2152
|
+
testID: AuthTestIds.devicePinEnrollConfirm,
|
|
2153
|
+
testIdPrefix,
|
|
2154
|
+
theme,
|
|
2155
|
+
value: confirmPin,
|
|
2156
|
+
onChange: setConfirmPin
|
|
2157
|
+
}
|
|
2158
|
+
),
|
|
2159
|
+
error !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2160
|
+
reactNative.Text,
|
|
2161
|
+
{
|
|
2162
|
+
style: styles3.errorText,
|
|
2163
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinEnrollError, testIdPrefix),
|
|
2164
|
+
children: error
|
|
2165
|
+
}
|
|
2166
|
+
) : null,
|
|
2167
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2168
|
+
reactNative.TouchableOpacity,
|
|
2169
|
+
{
|
|
2170
|
+
accessibilityHint: labels.submit,
|
|
2171
|
+
accessibilityLabel: submitting ? labels.submitting : labels.submit,
|
|
2172
|
+
accessibilityRole: "button",
|
|
2173
|
+
disabled: submitting,
|
|
2174
|
+
style: buttonStyle,
|
|
2175
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinEnrollSubmit, testIdPrefix),
|
|
2176
|
+
onPress: submit,
|
|
2177
|
+
children: submitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
2178
|
+
}
|
|
2179
|
+
),
|
|
2180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2181
|
+
reactNative.TouchableOpacity,
|
|
2182
|
+
{
|
|
2183
|
+
accessibilityHint: labels.cancelHint,
|
|
2184
|
+
accessibilityLabel: labels.cancel,
|
|
2185
|
+
accessibilityRole: "button",
|
|
2186
|
+
disabled: submitting,
|
|
2187
|
+
style: styles3.escapeLink,
|
|
2188
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinEnrollCancel, testIdPrefix),
|
|
2189
|
+
onPress: onCancel,
|
|
2190
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.cancel })
|
|
2191
|
+
}
|
|
2192
|
+
)
|
|
2193
|
+
]
|
|
2194
|
+
}
|
|
2195
|
+
);
|
|
2196
|
+
}
|
|
2197
|
+
function DevicePinOffer({
|
|
2198
|
+
client,
|
|
2199
|
+
initialDigits,
|
|
2200
|
+
theme: themeProp,
|
|
2201
|
+
labels: labelsProp,
|
|
2202
|
+
testIdPrefix,
|
|
2203
|
+
onDismiss
|
|
2204
|
+
}) {
|
|
2205
|
+
const theme = useAuthTheme(themeProp);
|
|
2206
|
+
const styles3 = useAuthStyles(theme);
|
|
2207
|
+
const labels = react.useMemo(
|
|
2208
|
+
() => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...labelsProp }),
|
|
2209
|
+
[labelsProp]
|
|
2210
|
+
);
|
|
2211
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
2212
|
+
const cardTestId = withTestIdPrefix(AuthTestIds.devicePinOffer, testIdPrefix);
|
|
2213
|
+
if (expanded) {
|
|
2214
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.card, testID: cardTestId, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2215
|
+
DevicePinEnrollForm,
|
|
2216
|
+
{
|
|
2217
|
+
client,
|
|
2218
|
+
initialDigits,
|
|
2219
|
+
labels: labelsProp,
|
|
2220
|
+
testIdPrefix,
|
|
2221
|
+
theme,
|
|
2222
|
+
onCancel: onDismiss,
|
|
2223
|
+
onEnrolled: onDismiss
|
|
2224
|
+
}
|
|
2225
|
+
) });
|
|
2226
|
+
}
|
|
2227
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, testID: cardTestId, children: [
|
|
2228
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.offerTitle }),
|
|
2229
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.offerDescription }),
|
|
2230
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2231
|
+
reactNative.TouchableOpacity,
|
|
2232
|
+
{
|
|
2233
|
+
accessibilityHint: labels.offerAcceptHint,
|
|
2234
|
+
accessibilityLabel: labels.offerAccept,
|
|
2235
|
+
accessibilityRole: "button",
|
|
2236
|
+
style: styles3.primaryButton,
|
|
2237
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinOfferAccept, testIdPrefix),
|
|
2238
|
+
onPress: () => setExpanded(true),
|
|
2239
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.offerAccept })
|
|
2240
|
+
}
|
|
2241
|
+
),
|
|
2242
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2243
|
+
reactNative.TouchableOpacity,
|
|
2244
|
+
{
|
|
2245
|
+
accessibilityHint: labels.offerSkipHint,
|
|
2246
|
+
accessibilityLabel: labels.offerSkip,
|
|
2247
|
+
accessibilityRole: "button",
|
|
2248
|
+
style: styles3.secondaryButton,
|
|
2249
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinOfferSkip, testIdPrefix),
|
|
2250
|
+
onPress: onDismiss,
|
|
2251
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.secondaryButtonText, children: labels.offerSkip })
|
|
2252
|
+
}
|
|
2253
|
+
)
|
|
2254
|
+
] });
|
|
2255
|
+
}
|
|
2256
|
+
function useDevicePinDisable({
|
|
2257
|
+
client,
|
|
2258
|
+
initialHasPin,
|
|
2259
|
+
onChanged
|
|
2260
|
+
}) {
|
|
2261
|
+
const [hasPin, setHasPin] = react.useState(initialHasPin);
|
|
2262
|
+
const [disabling, setDisabling] = react.useState(false);
|
|
2263
|
+
const [failed, setFailed] = react.useState(false);
|
|
2264
|
+
const disable = react.useCallback(() => {
|
|
2265
|
+
setFailed(false);
|
|
2266
|
+
setDisabling(true);
|
|
2267
|
+
client.disableDevicePin().then((ok) => {
|
|
2268
|
+
if (ok) {
|
|
2269
|
+
setHasPin(false);
|
|
2270
|
+
onChanged?.(false);
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
setFailed(true);
|
|
2274
|
+
}).catch(() => {
|
|
2275
|
+
setFailed(true);
|
|
2276
|
+
}).finally(() => {
|
|
2277
|
+
setDisabling(false);
|
|
2278
|
+
});
|
|
2279
|
+
}, [client, onChanged]);
|
|
2280
|
+
const markEnabled = react.useCallback(() => {
|
|
2281
|
+
setHasPin(true);
|
|
2282
|
+
onChanged?.(true);
|
|
2283
|
+
}, [onChanged]);
|
|
2284
|
+
return { hasPin, disabling, failed, disable, markEnabled };
|
|
2285
|
+
}
|
|
2286
|
+
function DevicePinSettingsCard({
|
|
2287
|
+
client,
|
|
2288
|
+
initialHasPin,
|
|
2289
|
+
theme: themeProp,
|
|
2290
|
+
labels: labelsProp,
|
|
2291
|
+
enrollLabels,
|
|
2292
|
+
testIdPrefix,
|
|
2293
|
+
onChanged
|
|
2294
|
+
}) {
|
|
2295
|
+
const theme = useAuthTheme(themeProp);
|
|
2296
|
+
const styles3 = useAuthStyles(theme);
|
|
2297
|
+
const labels = react.useMemo(
|
|
2298
|
+
() => ({ ...DEFAULT_DEVICE_PIN_SETTINGS_LABELS, ...labelsProp }),
|
|
2299
|
+
[labelsProp]
|
|
2300
|
+
);
|
|
2301
|
+
const resolvedEnrollLabels = react.useMemo(
|
|
2302
|
+
() => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...enrollLabels }),
|
|
2303
|
+
[enrollLabels]
|
|
2304
|
+
);
|
|
2305
|
+
const [enrolling, setEnrolling] = react.useState(false);
|
|
2306
|
+
const { hasPin, disabling, failed, disable, markEnabled } = useDevicePinDisable({
|
|
2307
|
+
client,
|
|
2308
|
+
initialHasPin,
|
|
2309
|
+
onChanged
|
|
2310
|
+
});
|
|
2311
|
+
const handleEnrolled = () => {
|
|
2312
|
+
setEnrolling(false);
|
|
2313
|
+
markEnabled();
|
|
2314
|
+
};
|
|
2315
|
+
const disableButtonStyle = disabling ? [styles3.secondaryButton, styles3.primaryButtonDisabled] : styles3.secondaryButton;
|
|
2316
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2317
|
+
reactNative.View,
|
|
2318
|
+
{
|
|
2319
|
+
style: styles3.card,
|
|
2320
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinSettings, testIdPrefix),
|
|
2321
|
+
children: [
|
|
2322
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
2323
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
2324
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2325
|
+
reactNative.Text,
|
|
2326
|
+
{
|
|
2327
|
+
style: styles3.statusText,
|
|
2328
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinSettingsStatus, testIdPrefix),
|
|
2329
|
+
children: hasPin ? labels.statusEnabled : labels.statusDisabled
|
|
2330
|
+
}
|
|
2331
|
+
),
|
|
2332
|
+
failed ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2333
|
+
reactNative.Text,
|
|
2334
|
+
{
|
|
2335
|
+
style: styles3.errorText,
|
|
2336
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinSettingsError, testIdPrefix),
|
|
2337
|
+
children: labels.disableFailed
|
|
2338
|
+
}
|
|
2339
|
+
) : null,
|
|
2340
|
+
renderAction()
|
|
2341
|
+
]
|
|
2342
|
+
}
|
|
2343
|
+
);
|
|
2344
|
+
function renderAction() {
|
|
2345
|
+
if (enrolling) {
|
|
2346
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2347
|
+
DevicePinEnrollForm,
|
|
2348
|
+
{
|
|
2349
|
+
client,
|
|
2350
|
+
labels: resolvedEnrollLabels,
|
|
2351
|
+
testIdPrefix,
|
|
2352
|
+
theme,
|
|
2353
|
+
onCancel: () => setEnrolling(false),
|
|
2354
|
+
onEnrolled: handleEnrolled
|
|
2355
|
+
}
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2358
|
+
if (hasPin) {
|
|
2359
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2360
|
+
reactNative.TouchableOpacity,
|
|
2361
|
+
{
|
|
2362
|
+
accessibilityHint: labels.disableHint,
|
|
2363
|
+
accessibilityLabel: disabling ? labels.disabling : labels.disable,
|
|
2364
|
+
accessibilityRole: "button",
|
|
2365
|
+
disabled: disabling,
|
|
2366
|
+
style: disableButtonStyle,
|
|
2367
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinSettingsDisable, testIdPrefix),
|
|
2368
|
+
onPress: disable,
|
|
2369
|
+
children: disabling ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.primary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.secondaryButtonText, children: labels.disable })
|
|
2370
|
+
}
|
|
2371
|
+
);
|
|
2372
|
+
}
|
|
2373
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2374
|
+
reactNative.TouchableOpacity,
|
|
2375
|
+
{
|
|
2376
|
+
accessibilityHint: labels.enableHint,
|
|
2377
|
+
accessibilityLabel: labels.enable,
|
|
2378
|
+
accessibilityRole: "button",
|
|
2379
|
+
style: styles3.primaryButton,
|
|
2380
|
+
testID: withTestIdPrefix(AuthTestIds.devicePinSettingsEnable, testIdPrefix),
|
|
2381
|
+
onPress: () => setEnrolling(true),
|
|
2382
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.enable })
|
|
2383
|
+
}
|
|
2384
|
+
);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
// src/passkey/passkeyNavigation.ts
|
|
2389
|
+
var PASSKEY_LOGIN_ENDPOINT = "/bff/passkey/login";
|
|
2390
|
+
var PASSKEY_REGISTER_ENDPOINT = "/bff/passkey/register";
|
|
2391
|
+
var RETURN_URL_PARAM = "returnUrl";
|
|
2392
|
+
var PASSKEY_ERROR_PARAM = "passkeyError";
|
|
2393
|
+
var PASSKEY_PARAM = "passkey";
|
|
2394
|
+
var PASSKEY_REGISTERED_VALUE = "registered";
|
|
2395
|
+
var PASSKEY_ERROR_CANCELLED = "cancelled";
|
|
2396
|
+
var PASSKEY_ERROR_FAILED = "failed";
|
|
2397
|
+
function buildNavigationUrl(endpoint, returnUrl) {
|
|
2398
|
+
return `${endpoint}?${RETURN_URL_PARAM}=${encodeURIComponent(returnUrl)}`;
|
|
2399
|
+
}
|
|
2400
|
+
function readSearchParams() {
|
|
2401
|
+
if (typeof window === "undefined") {
|
|
2402
|
+
return null;
|
|
2403
|
+
}
|
|
2404
|
+
return new URLSearchParams(window.location.search);
|
|
2405
|
+
}
|
|
2406
|
+
function startPasskeyLogin(returnUrl) {
|
|
2407
|
+
if (typeof window === "undefined") {
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
window.location.assign(buildNavigationUrl(PASSKEY_LOGIN_ENDPOINT, returnUrl));
|
|
2411
|
+
}
|
|
2412
|
+
function startPasskeyRegistration(returnUrl) {
|
|
2413
|
+
if (typeof window === "undefined") {
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
window.location.assign(buildNavigationUrl(PASSKEY_REGISTER_ENDPOINT, returnUrl));
|
|
2417
|
+
}
|
|
2418
|
+
function readPasskeyError() {
|
|
2419
|
+
const params = readSearchParams();
|
|
2420
|
+
if (params === null) {
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
const value = params.get(PASSKEY_ERROR_PARAM);
|
|
2424
|
+
if (value === PASSKEY_ERROR_CANCELLED) {
|
|
2425
|
+
return PASSKEY_ERROR_CANCELLED;
|
|
2426
|
+
}
|
|
2427
|
+
if (value === PASSKEY_ERROR_FAILED) {
|
|
2428
|
+
return PASSKEY_ERROR_FAILED;
|
|
2429
|
+
}
|
|
2430
|
+
return null;
|
|
2431
|
+
}
|
|
2432
|
+
function readPasskeyRegistered() {
|
|
2433
|
+
const params = readSearchParams();
|
|
2434
|
+
if (params === null) {
|
|
2435
|
+
return false;
|
|
2436
|
+
}
|
|
2437
|
+
return params.get(PASSKEY_PARAM) === PASSKEY_REGISTERED_VALUE;
|
|
2438
|
+
}
|
|
2439
|
+
var DEFAULT_RETURN_URL = "/";
|
|
2440
|
+
function PasskeyLoginButton({
|
|
2441
|
+
returnUrl = DEFAULT_RETURN_URL,
|
|
2442
|
+
theme: themeProp,
|
|
2443
|
+
labels: labelsProp,
|
|
2444
|
+
testIdPrefix
|
|
2445
|
+
}) {
|
|
2446
|
+
const theme = useAuthTheme(themeProp);
|
|
2447
|
+
const styles3 = useAuthStyles(theme);
|
|
2448
|
+
const labels = react.useMemo(
|
|
2449
|
+
() => ({ ...DEFAULT_PASSKEY_LOGIN_LABELS, ...labelsProp }),
|
|
2450
|
+
[labelsProp]
|
|
2451
|
+
);
|
|
2452
|
+
const error = readPasskeyError();
|
|
2453
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: withTestIdPrefix(AuthTestIds.passkeyLogin, testIdPrefix), children: [
|
|
2454
|
+
error !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2455
|
+
reactNative.Text,
|
|
2456
|
+
{
|
|
2457
|
+
style: styles3.errorText,
|
|
2458
|
+
testID: withTestIdPrefix(AuthTestIds.passkeyLoginError, testIdPrefix),
|
|
2459
|
+
children: error === "cancelled" ? labels.errorCancelled : labels.errorFailed
|
|
2460
|
+
}
|
|
2461
|
+
) : null,
|
|
2462
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2463
|
+
reactNative.TouchableOpacity,
|
|
2464
|
+
{
|
|
2465
|
+
accessibilityHint: labels.signInHint,
|
|
2466
|
+
accessibilityLabel: labels.signInButton,
|
|
2467
|
+
accessibilityRole: "button",
|
|
2468
|
+
style: styles3.secondaryButton,
|
|
2469
|
+
testID: withTestIdPrefix(AuthTestIds.passkeyLoginButton, testIdPrefix),
|
|
2470
|
+
onPress: () => startPasskeyLogin(returnUrl),
|
|
2471
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.secondaryButtonText, children: labels.signInButton })
|
|
2472
|
+
}
|
|
2473
|
+
)
|
|
2474
|
+
] });
|
|
2475
|
+
}
|
|
2476
|
+
var DEFAULT_RETURN_PATH = "/";
|
|
2477
|
+
function readCurrentPath() {
|
|
2478
|
+
if (typeof window === "undefined") {
|
|
2479
|
+
return DEFAULT_RETURN_PATH;
|
|
2480
|
+
}
|
|
2481
|
+
return window.location.pathname;
|
|
2482
|
+
}
|
|
2483
|
+
function PasskeySettingsCard({
|
|
2484
|
+
returnUrl,
|
|
2485
|
+
theme: themeProp,
|
|
2486
|
+
labels: labelsProp,
|
|
2487
|
+
testIdPrefix
|
|
2488
|
+
}) {
|
|
2489
|
+
const theme = useAuthTheme(themeProp);
|
|
2490
|
+
const styles3 = useAuthStyles(theme);
|
|
2491
|
+
const labels = react.useMemo(
|
|
2492
|
+
() => ({ ...DEFAULT_PASSKEY_SETTINGS_LABELS, ...labelsProp }),
|
|
2493
|
+
[labelsProp]
|
|
2494
|
+
);
|
|
2495
|
+
const justRegistered = readPasskeyRegistered();
|
|
2496
|
+
const target = returnUrl ?? readCurrentPath();
|
|
2497
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2498
|
+
reactNative.View,
|
|
2499
|
+
{
|
|
2500
|
+
style: styles3.card,
|
|
2501
|
+
testID: withTestIdPrefix(AuthTestIds.passkeySettings, testIdPrefix),
|
|
2502
|
+
children: [
|
|
2503
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
2504
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
2505
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.helperText, children: labels.reauthHint }),
|
|
2506
|
+
justRegistered ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2507
|
+
reactNative.Text,
|
|
2508
|
+
{
|
|
2509
|
+
style: styles3.successText,
|
|
2510
|
+
testID: withTestIdPrefix(AuthTestIds.passkeySettingsSuccess, testIdPrefix),
|
|
2511
|
+
children: labels.registeredSuccess
|
|
2512
|
+
}
|
|
2513
|
+
) : null,
|
|
2514
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2515
|
+
reactNative.TouchableOpacity,
|
|
2516
|
+
{
|
|
2517
|
+
accessibilityHint: labels.addHint,
|
|
2518
|
+
accessibilityLabel: labels.addButton,
|
|
2519
|
+
accessibilityRole: "button",
|
|
2520
|
+
style: styles3.primaryButton,
|
|
2521
|
+
testID: withTestIdPrefix(AuthTestIds.passkeySettingsAdd, testIdPrefix),
|
|
2522
|
+
onPress: () => startPasskeyRegistration(target),
|
|
2523
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.addButton })
|
|
2524
|
+
}
|
|
2525
|
+
)
|
|
2526
|
+
]
|
|
2527
|
+
}
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
var EMPTY_CONFIG = {
|
|
2531
|
+
methods: [],
|
|
2532
|
+
registrationEnabled: false,
|
|
2533
|
+
deviceState: {
|
|
2534
|
+
rememberedUsername: null,
|
|
2535
|
+
hasPin: false,
|
|
2536
|
+
pinDigits: null,
|
|
2537
|
+
preferredMethod: null
|
|
2538
|
+
}
|
|
2539
|
+
};
|
|
2540
|
+
function useBffLoginConfig(client) {
|
|
2541
|
+
const [config, setConfig] = react.useState(EMPTY_CONFIG);
|
|
2542
|
+
const [loading, setLoading] = react.useState(true);
|
|
2543
|
+
react.useEffect(() => {
|
|
2544
|
+
let active = true;
|
|
2545
|
+
client.getLoginConfig().then((next) => {
|
|
2546
|
+
if (active) {
|
|
2547
|
+
setConfig(next);
|
|
2548
|
+
}
|
|
2549
|
+
}).catch(() => {
|
|
2550
|
+
if (active) {
|
|
2551
|
+
setConfig(EMPTY_CONFIG);
|
|
2552
|
+
}
|
|
2553
|
+
}).finally(() => {
|
|
2554
|
+
if (active) {
|
|
2555
|
+
setLoading(false);
|
|
2556
|
+
}
|
|
2557
|
+
});
|
|
2558
|
+
return () => {
|
|
2559
|
+
active = false;
|
|
2560
|
+
};
|
|
2561
|
+
}, [client]);
|
|
2562
|
+
return { config, loading };
|
|
2563
|
+
}
|
|
1345
2564
|
async function lazyFetchHttpClient(request) {
|
|
1346
2565
|
const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
|
|
1347
2566
|
if (fetchImpl === void 0) {
|
|
@@ -1396,17 +2615,36 @@ Object.defineProperty(exports, "createFetchHttpClient", {
|
|
|
1396
2615
|
exports.AuthTestIds = AuthTestIds;
|
|
1397
2616
|
exports.AuthThemeProvider = AuthThemeProvider;
|
|
1398
2617
|
exports.BffAuthStatus = BffAuthStatus;
|
|
2618
|
+
exports.DEFAULT_DEVICE_PIN_ENROLL_LABELS = DEFAULT_DEVICE_PIN_ENROLL_LABELS;
|
|
2619
|
+
exports.DEFAULT_DEVICE_PIN_SETTINGS_LABELS = DEFAULT_DEVICE_PIN_SETTINGS_LABELS;
|
|
2620
|
+
exports.DEFAULT_DEVICE_PIN_UNLOCK_LABELS = DEFAULT_DEVICE_PIN_UNLOCK_LABELS;
|
|
2621
|
+
exports.DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS = DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS;
|
|
1399
2622
|
exports.DEFAULT_FORGOT_PASSWORD_LABELS = DEFAULT_FORGOT_PASSWORD_LABELS;
|
|
1400
2623
|
exports.DEFAULT_LOGIN_LABELS = DEFAULT_LOGIN_LABELS;
|
|
1401
2624
|
exports.DEFAULT_OTP_LABELS = DEFAULT_OTP_LABELS;
|
|
2625
|
+
exports.DEFAULT_PASSKEY_LOGIN_LABELS = DEFAULT_PASSKEY_LOGIN_LABELS;
|
|
2626
|
+
exports.DEFAULT_PASSKEY_SETTINGS_LABELS = DEFAULT_PASSKEY_SETTINGS_LABELS;
|
|
1402
2627
|
exports.DEFAULT_PIN_LABELS = DEFAULT_PIN_LABELS;
|
|
1403
2628
|
exports.DEFAULT_RESET_PASSWORD_LABELS = DEFAULT_RESET_PASSWORD_LABELS;
|
|
2629
|
+
exports.DEVICE_PIN_ALLOWED_DIGITS = DEVICE_PIN_ALLOWED_DIGITS;
|
|
2630
|
+
exports.DEVICE_PIN_DEFAULT_DIGITS = DEVICE_PIN_DEFAULT_DIGITS;
|
|
2631
|
+
exports.DevicePinEnrollErrorKey = DevicePinEnrollErrorKey;
|
|
2632
|
+
exports.DevicePinEnrollForm = DevicePinEnrollForm;
|
|
2633
|
+
exports.DevicePinErrorKey = DevicePinErrorKey;
|
|
2634
|
+
exports.DevicePinInput = DevicePinInput;
|
|
2635
|
+
exports.DevicePinLengthPicker = DevicePinLengthPicker;
|
|
2636
|
+
exports.DevicePinOffer = DevicePinOffer;
|
|
2637
|
+
exports.DevicePinSettingsCard = DevicePinSettingsCard;
|
|
2638
|
+
exports.DevicePinUnlockScreen = DevicePinUnlockScreen;
|
|
2639
|
+
exports.ForgotPasswordFields = ForgotPasswordFields;
|
|
1404
2640
|
exports.ForgotPasswordForm = ForgotPasswordForm;
|
|
1405
2641
|
exports.LoginForm = LoginForm;
|
|
1406
2642
|
exports.OtpForm = OtpForm;
|
|
1407
2643
|
exports.OtpLoginStep = OtpLoginStep;
|
|
1408
2644
|
exports.PASSWORD_MAX_LENGTH = PASSWORD_MAX_LENGTH;
|
|
1409
2645
|
exports.PASSWORD_MIN_LENGTH = PASSWORD_MIN_LENGTH;
|
|
2646
|
+
exports.PasskeyLoginButton = PasskeyLoginButton;
|
|
2647
|
+
exports.PasskeySettingsCard = PasskeySettingsCard;
|
|
1410
2648
|
exports.PasswordPolicyError = PasswordPolicyError;
|
|
1411
2649
|
exports.PinForm = PinForm;
|
|
1412
2650
|
exports.ResetPasswordError = ResetPasswordError;
|
|
@@ -1414,12 +2652,23 @@ exports.ResetPasswordForm = ResetPasswordForm;
|
|
|
1414
2652
|
exports.collectUserRoles = collectUserRoles;
|
|
1415
2653
|
exports.createBffAuthClient = createBffAuthClient;
|
|
1416
2654
|
exports.defaultAuthTheme = defaultAuthTheme;
|
|
2655
|
+
exports.isAllowedPinDigits = isAllowedPinDigits;
|
|
1417
2656
|
exports.isPasswordValid = isPasswordValid;
|
|
2657
|
+
exports.isValidForgotPasswordEmail = isValidForgotPasswordEmail;
|
|
2658
|
+
exports.readPasskeyError = readPasskeyError;
|
|
2659
|
+
exports.readPasskeyRegistered = readPasskeyRegistered;
|
|
1418
2660
|
exports.resolvePostLoginRoute = resolvePostLoginRoute;
|
|
2661
|
+
exports.startPasskeyLogin = startPasskeyLogin;
|
|
2662
|
+
exports.startPasskeyRegistration = startPasskeyRegistration;
|
|
1419
2663
|
exports.useAuthTheme = useAuthTheme;
|
|
1420
2664
|
exports.useBffAuth = useBffAuth;
|
|
1421
2665
|
exports.useBffForgotPassword = useBffForgotPassword;
|
|
2666
|
+
exports.useBffLoginConfig = useBffLoginConfig;
|
|
1422
2667
|
exports.useBffResetPassword = useBffResetPassword;
|
|
2668
|
+
exports.useDevicePinDisable = useDevicePinDisable;
|
|
2669
|
+
exports.useDevicePinEnroll = useDevicePinEnroll;
|
|
2670
|
+
exports.useDevicePinUnlock = useDevicePinUnlock;
|
|
2671
|
+
exports.useForgotPasswordSubmit = useForgotPasswordSubmit;
|
|
1423
2672
|
exports.useOtpLogin = useOtpLogin;
|
|
1424
2673
|
exports.usePinLogin = usePinLogin;
|
|
1425
2674
|
exports.useResetPasswordForm = useResetPasswordForm;
|