@dloizides/auth-web 1.3.0 → 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/dist/index.d.mts +706 -1
- package/dist/index.d.ts +706 -1
- package/dist/index.js +1152 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1128 -92
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,6 +69,77 @@ var DEFAULT_PIN_LABELS = {
|
|
|
69
69
|
missingPin: "Enter your event PIN.",
|
|
70
70
|
invalidPin: "That PIN is incorrect, has expired, or is locked out."
|
|
71
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
|
+
};
|
|
72
143
|
var DEFAULT_RESET_PASSWORD_LABELS = {
|
|
73
144
|
title: "Reset password",
|
|
74
145
|
description: "Choose a new password for your account.",
|
|
@@ -117,7 +188,39 @@ var AuthTestIds = {
|
|
|
117
188
|
pinForm: "auth-pin-form",
|
|
118
189
|
pinInput: "auth-pin-input",
|
|
119
190
|
pinSubmitButton: "auth-pin-submit",
|
|
120
|
-
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"
|
|
121
224
|
};
|
|
122
225
|
function withTestIdPrefix(baseId, prefix) {
|
|
123
226
|
return prefix === void 0 || prefix === "" ? baseId : `${prefix}-${baseId}`;
|
|
@@ -211,6 +314,32 @@ function useAuthStyles(theme) {
|
|
|
211
314
|
helperText: {
|
|
212
315
|
fontSize: typography.caption,
|
|
213
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
|
|
214
343
|
}
|
|
215
344
|
});
|
|
216
345
|
}, [theme]);
|
|
@@ -372,7 +501,7 @@ function LoginForm({
|
|
|
372
501
|
testIdPrefix
|
|
373
502
|
}) {
|
|
374
503
|
const theme = useAuthTheme(themeProp);
|
|
375
|
-
const
|
|
504
|
+
const styles3 = useAuthStyles(theme);
|
|
376
505
|
const labels = react.useMemo(
|
|
377
506
|
() => ({ ...DEFAULT_LOGIN_LABELS, ...labelsProp }),
|
|
378
507
|
[labelsProp]
|
|
@@ -399,12 +528,12 @@ function LoginForm({
|
|
|
399
528
|
const handleSubmit = react.useCallback(() => {
|
|
400
529
|
void runLogin();
|
|
401
530
|
}, [runLogin]);
|
|
402
|
-
const submitButtonStyle = isSubmitting ? [
|
|
403
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
404
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
405
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
406
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
407
|
-
/* @__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 }),
|
|
408
537
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
409
538
|
reactNative.TextInput,
|
|
410
539
|
{
|
|
@@ -415,15 +544,15 @@ function LoginForm({
|
|
|
415
544
|
editable: !isSubmitting,
|
|
416
545
|
placeholder: labels.usernamePlaceholder,
|
|
417
546
|
placeholderTextColor: theme.colors.textSecondary,
|
|
418
|
-
style:
|
|
547
|
+
style: styles3.input,
|
|
419
548
|
testID: withTestIdPrefix(AuthTestIds.loginUsernameInput, testIdPrefix),
|
|
420
549
|
value: username,
|
|
421
550
|
onChangeText: setUsername
|
|
422
551
|
}
|
|
423
552
|
)
|
|
424
553
|
] }),
|
|
425
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
426
|
-
/* @__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 }),
|
|
427
556
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
428
557
|
reactNative.TextInput,
|
|
429
558
|
{
|
|
@@ -435,7 +564,7 @@ function LoginForm({
|
|
|
435
564
|
editable: !isSubmitting,
|
|
436
565
|
placeholder: labels.passwordPlaceholder,
|
|
437
566
|
placeholderTextColor: theme.colors.textSecondary,
|
|
438
|
-
style:
|
|
567
|
+
style: styles3.input,
|
|
439
568
|
testID: withTestIdPrefix(AuthTestIds.loginPasswordInput, testIdPrefix),
|
|
440
569
|
value: password,
|
|
441
570
|
onChangeText: setPassword
|
|
@@ -445,7 +574,7 @@ function LoginForm({
|
|
|
445
574
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
446
575
|
reactNative.Text,
|
|
447
576
|
{
|
|
448
|
-
style:
|
|
577
|
+
style: styles3.errorText,
|
|
449
578
|
testID: withTestIdPrefix(AuthTestIds.loginError, testIdPrefix),
|
|
450
579
|
children: errorText
|
|
451
580
|
}
|
|
@@ -457,10 +586,10 @@ function LoginForm({
|
|
|
457
586
|
accessibilityLabel: labels.forgotPassword,
|
|
458
587
|
accessibilityRole: "link",
|
|
459
588
|
disabled: isSubmitting,
|
|
460
|
-
style:
|
|
589
|
+
style: styles3.fieldGroup,
|
|
461
590
|
testID: withTestIdPrefix(AuthTestIds.loginForgotLink, testIdPrefix),
|
|
462
591
|
onPress: onForgotPassword,
|
|
463
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
592
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.forgotPassword })
|
|
464
593
|
}
|
|
465
594
|
) : null,
|
|
466
595
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -473,7 +602,7 @@ function LoginForm({
|
|
|
473
602
|
style: submitButtonStyle,
|
|
474
603
|
testID: withTestIdPrefix(AuthTestIds.loginSubmitButton, testIdPrefix),
|
|
475
604
|
onPress: handleSubmit,
|
|
476
|
-
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 })
|
|
477
606
|
}
|
|
478
607
|
),
|
|
479
608
|
onSignUp !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -483,10 +612,10 @@ function LoginForm({
|
|
|
483
612
|
accessibilityLabel: labels.signUp,
|
|
484
613
|
accessibilityRole: "link",
|
|
485
614
|
disabled: isSubmitting,
|
|
486
|
-
style:
|
|
615
|
+
style: styles3.fieldGroup,
|
|
487
616
|
testID: withTestIdPrefix(AuthTestIds.loginSignUpLink, testIdPrefix),
|
|
488
617
|
onPress: onSignUp,
|
|
489
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
618
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.signUp })
|
|
490
619
|
}
|
|
491
620
|
) : null
|
|
492
621
|
] }) });
|
|
@@ -524,7 +653,7 @@ function ForgotPasswordForm({
|
|
|
524
653
|
testIdPrefix
|
|
525
654
|
}) {
|
|
526
655
|
const theme = useAuthTheme(themeProp);
|
|
527
|
-
const
|
|
656
|
+
const styles3 = useAuthStyles(theme);
|
|
528
657
|
const labels = react.useMemo(
|
|
529
658
|
() => ({ ...DEFAULT_FORGOT_PASSWORD_LABELS, ...labelsProp }),
|
|
530
659
|
[labelsProp]
|
|
@@ -556,25 +685,25 @@ function ForgotPasswordForm({
|
|
|
556
685
|
}
|
|
557
686
|
mutation.mutate({ email: trimmedEmail, resetUrlTemplate });
|
|
558
687
|
}, [email, mutation, resetUrlTemplate, labels.invalidEmail]);
|
|
559
|
-
const submitButtonStyle = isPending ? [
|
|
560
|
-
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(
|
|
561
690
|
reactNative.View,
|
|
562
691
|
{
|
|
563
|
-
style:
|
|
692
|
+
style: styles3.card,
|
|
564
693
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix),
|
|
565
694
|
children: [
|
|
566
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
567
696
|
submitted ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
568
697
|
reactNative.Text,
|
|
569
698
|
{
|
|
570
|
-
style:
|
|
699
|
+
style: styles3.successText,
|
|
571
700
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix),
|
|
572
701
|
children: labels.successMessage
|
|
573
702
|
}
|
|
574
703
|
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
575
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
576
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
577
|
-
/* @__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 }),
|
|
578
707
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
579
708
|
reactNative.TextInput,
|
|
580
709
|
{
|
|
@@ -586,7 +715,7 @@ function ForgotPasswordForm({
|
|
|
586
715
|
keyboardType: "email-address",
|
|
587
716
|
placeholder: labels.emailPlaceholder,
|
|
588
717
|
placeholderTextColor: theme.colors.textSecondary,
|
|
589
|
-
style:
|
|
718
|
+
style: styles3.input,
|
|
590
719
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix),
|
|
591
720
|
value: email,
|
|
592
721
|
onChangeText: setEmail
|
|
@@ -596,7 +725,7 @@ function ForgotPasswordForm({
|
|
|
596
725
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
597
726
|
reactNative.Text,
|
|
598
727
|
{
|
|
599
|
-
style:
|
|
728
|
+
style: styles3.errorText,
|
|
600
729
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix),
|
|
601
730
|
children: errorText
|
|
602
731
|
}
|
|
@@ -611,7 +740,7 @@ function ForgotPasswordForm({
|
|
|
611
740
|
style: submitButtonStyle,
|
|
612
741
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix),
|
|
613
742
|
onPress: handleSubmit,
|
|
614
|
-
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 })
|
|
615
744
|
}
|
|
616
745
|
)
|
|
617
746
|
] })
|
|
@@ -703,7 +832,7 @@ function ForgotPasswordFields({
|
|
|
703
832
|
testIdPrefix
|
|
704
833
|
}) {
|
|
705
834
|
const theme = useAuthTheme(themeProp);
|
|
706
|
-
const
|
|
835
|
+
const styles3 = useAuthStyles(theme);
|
|
707
836
|
const modalStyles = useModalStyles(theme);
|
|
708
837
|
const labels = react.useMemo(
|
|
709
838
|
() => ({ ...DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, ...labelsProp }),
|
|
@@ -716,7 +845,7 @@ function ForgotPasswordFields({
|
|
|
716
845
|
reset();
|
|
717
846
|
}
|
|
718
847
|
}, [visible, reset]);
|
|
719
|
-
const submitButtonStyle = form.canSubmit ?
|
|
848
|
+
const submitButtonStyle = form.canSubmit ? styles3.primaryButton : [styles3.primaryButton, styles3.primaryButtonDisabled];
|
|
720
849
|
const handleCancel = () => {
|
|
721
850
|
form.reset();
|
|
722
851
|
onCancel?.();
|
|
@@ -727,25 +856,25 @@ function ForgotPasswordFields({
|
|
|
727
856
|
};
|
|
728
857
|
if (form.submitted) {
|
|
729
858
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
730
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
859
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.successText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix), children: labels.successMessage }),
|
|
731
860
|
onClose !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: modalStyles.actions, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
732
861
|
reactNative.TouchableOpacity,
|
|
733
862
|
{
|
|
734
863
|
accessibilityHint: labels.close,
|
|
735
864
|
accessibilityLabel: labels.close,
|
|
736
865
|
accessibilityRole: "button",
|
|
737
|
-
style:
|
|
866
|
+
style: styles3.primaryButton,
|
|
738
867
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordCloseButton, testIdPrefix),
|
|
739
868
|
onPress: handleClose,
|
|
740
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
869
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.close })
|
|
741
870
|
}
|
|
742
871
|
) }) : null
|
|
743
872
|
] });
|
|
744
873
|
}
|
|
745
874
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
746
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
747
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
748
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
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 }),
|
|
749
878
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
750
879
|
reactNative.TextInput,
|
|
751
880
|
{
|
|
@@ -757,14 +886,14 @@ function ForgotPasswordFields({
|
|
|
757
886
|
keyboardType: "email-address",
|
|
758
887
|
placeholder: labels.emailPlaceholder,
|
|
759
888
|
placeholderTextColor: theme.colors.textSecondary,
|
|
760
|
-
style:
|
|
889
|
+
style: styles3.input,
|
|
761
890
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix),
|
|
762
891
|
value: form.email,
|
|
763
892
|
onChangeText: form.setEmail
|
|
764
893
|
}
|
|
765
894
|
)
|
|
766
895
|
] }),
|
|
767
|
-
form.hasNetworkError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
896
|
+
form.hasNetworkError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix), children: labels.networkError }) : null,
|
|
768
897
|
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.actions, children: [
|
|
769
898
|
onCancel !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
770
899
|
reactNative.TouchableOpacity,
|
|
@@ -789,7 +918,7 @@ function ForgotPasswordFields({
|
|
|
789
918
|
style: submitButtonStyle,
|
|
790
919
|
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix),
|
|
791
920
|
onPress: form.submit,
|
|
792
|
-
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
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 })
|
|
793
922
|
}
|
|
794
923
|
)
|
|
795
924
|
] })
|
|
@@ -968,24 +1097,24 @@ function ResetPasswordForm({
|
|
|
968
1097
|
testIdPrefix
|
|
969
1098
|
}) {
|
|
970
1099
|
const theme = useAuthTheme(themeProp);
|
|
971
|
-
const
|
|
1100
|
+
const styles3 = useAuthStyles(theme);
|
|
972
1101
|
const labels = react.useMemo(
|
|
973
1102
|
() => ({ ...DEFAULT_RESET_PASSWORD_LABELS, ...labelsProp }),
|
|
974
1103
|
[labelsProp]
|
|
975
1104
|
);
|
|
976
1105
|
const form = useResetPasswordForm({ client, token, onSuccess });
|
|
977
1106
|
const message = errorMessage(form.errorKey, labels);
|
|
978
|
-
const submitButtonStyle = form.isSubmitting ? [
|
|
979
|
-
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(
|
|
980
1109
|
reactNative.View,
|
|
981
1110
|
{
|
|
982
|
-
style:
|
|
1111
|
+
style: styles3.card,
|
|
983
1112
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix),
|
|
984
1113
|
children: [
|
|
985
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
986
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
987
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
988
|
-
/* @__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 }),
|
|
989
1118
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
990
1119
|
reactNative.TextInput,
|
|
991
1120
|
{
|
|
@@ -997,15 +1126,15 @@ function ResetPasswordForm({
|
|
|
997
1126
|
editable: !form.isSubmitting,
|
|
998
1127
|
placeholder: labels.newPasswordPlaceholder,
|
|
999
1128
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1000
|
-
style:
|
|
1129
|
+
style: styles3.input,
|
|
1001
1130
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
|
|
1002
1131
|
value: form.newPassword,
|
|
1003
1132
|
onChangeText: form.setNewPassword
|
|
1004
1133
|
}
|
|
1005
1134
|
)
|
|
1006
1135
|
] }),
|
|
1007
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1008
|
-
/* @__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 }),
|
|
1009
1138
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1010
1139
|
reactNative.TextInput,
|
|
1011
1140
|
{
|
|
@@ -1017,7 +1146,7 @@ function ResetPasswordForm({
|
|
|
1017
1146
|
editable: !form.isSubmitting,
|
|
1018
1147
|
placeholder: labels.confirmPasswordPlaceholder,
|
|
1019
1148
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1020
|
-
style:
|
|
1149
|
+
style: styles3.input,
|
|
1021
1150
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
|
|
1022
1151
|
value: form.confirmPassword,
|
|
1023
1152
|
onChangeText: form.setConfirmPassword
|
|
@@ -1027,7 +1156,7 @@ function ResetPasswordForm({
|
|
|
1027
1156
|
message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1028
1157
|
reactNative.Text,
|
|
1029
1158
|
{
|
|
1030
|
-
style:
|
|
1159
|
+
style: styles3.errorText,
|
|
1031
1160
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
|
|
1032
1161
|
children: message
|
|
1033
1162
|
}
|
|
@@ -1042,7 +1171,7 @@ function ResetPasswordForm({
|
|
|
1042
1171
|
style: submitButtonStyle,
|
|
1043
1172
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
|
|
1044
1173
|
onPress: form.submit,
|
|
1045
|
-
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 })
|
|
1046
1175
|
}
|
|
1047
1176
|
)
|
|
1048
1177
|
]
|
|
@@ -1050,7 +1179,7 @@ function ResetPasswordForm({
|
|
|
1050
1179
|
) });
|
|
1051
1180
|
}
|
|
1052
1181
|
function OtpRequestStep({
|
|
1053
|
-
styles,
|
|
1182
|
+
styles: styles3,
|
|
1054
1183
|
theme,
|
|
1055
1184
|
labels,
|
|
1056
1185
|
testIdPrefix,
|
|
@@ -1059,12 +1188,12 @@ function OtpRequestStep({
|
|
|
1059
1188
|
onSubmit
|
|
1060
1189
|
}) {
|
|
1061
1190
|
const [email, setEmail] = react.useState("");
|
|
1062
|
-
const buttonStyle = isSubmitting ? [
|
|
1191
|
+
const buttonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1063
1192
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1064
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1065
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1066
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1067
|
-
/* @__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 }),
|
|
1068
1197
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1069
1198
|
reactNative.TextInput,
|
|
1070
1199
|
{
|
|
@@ -1076,14 +1205,14 @@ function OtpRequestStep({
|
|
|
1076
1205
|
keyboardType: "email-address",
|
|
1077
1206
|
placeholder: labels.emailPlaceholder,
|
|
1078
1207
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1079
|
-
style:
|
|
1208
|
+
style: styles3.input,
|
|
1080
1209
|
testID: withTestIdPrefix(AuthTestIds.otpEmailInput, testIdPrefix),
|
|
1081
1210
|
value: email,
|
|
1082
1211
|
onChangeText: setEmail
|
|
1083
1212
|
}
|
|
1084
1213
|
)
|
|
1085
1214
|
] }),
|
|
1086
|
-
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,
|
|
1087
1216
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1088
1217
|
reactNative.TouchableOpacity,
|
|
1089
1218
|
{
|
|
@@ -1094,13 +1223,13 @@ function OtpRequestStep({
|
|
|
1094
1223
|
style: buttonStyle,
|
|
1095
1224
|
testID: withTestIdPrefix(AuthTestIds.otpRequestButton, testIdPrefix),
|
|
1096
1225
|
onPress: () => onSubmit(email.trim()),
|
|
1097
|
-
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 })
|
|
1098
1227
|
}
|
|
1099
1228
|
)
|
|
1100
1229
|
] });
|
|
1101
1230
|
}
|
|
1102
1231
|
function OtpVerifyStep({
|
|
1103
|
-
styles,
|
|
1232
|
+
styles: styles3,
|
|
1104
1233
|
theme,
|
|
1105
1234
|
labels,
|
|
1106
1235
|
testIdPrefix,
|
|
@@ -1112,13 +1241,13 @@ function OtpVerifyStep({
|
|
|
1112
1241
|
onChangeEmail
|
|
1113
1242
|
}) {
|
|
1114
1243
|
const [code, setCode] = react.useState("");
|
|
1115
|
-
const buttonStyle = isSubmitting ? [
|
|
1244
|
+
const buttonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1116
1245
|
const description = labels.verifyDescription.replace("{identifier}", identifier);
|
|
1117
1246
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1118
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1119
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1120
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1121
|
-
/* @__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 }),
|
|
1122
1251
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1123
1252
|
reactNative.TextInput,
|
|
1124
1253
|
{
|
|
@@ -1130,14 +1259,14 @@ function OtpVerifyStep({
|
|
|
1130
1259
|
keyboardType: "number-pad",
|
|
1131
1260
|
placeholder: labels.codePlaceholder,
|
|
1132
1261
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1133
|
-
style:
|
|
1262
|
+
style: styles3.input,
|
|
1134
1263
|
testID: withTestIdPrefix(AuthTestIds.otpCodeInput, testIdPrefix),
|
|
1135
1264
|
value: code,
|
|
1136
1265
|
onChangeText: setCode
|
|
1137
1266
|
}
|
|
1138
1267
|
)
|
|
1139
1268
|
] }),
|
|
1140
|
-
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,
|
|
1141
1270
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1142
1271
|
reactNative.TouchableOpacity,
|
|
1143
1272
|
{
|
|
@@ -1148,7 +1277,7 @@ function OtpVerifyStep({
|
|
|
1148
1277
|
style: buttonStyle,
|
|
1149
1278
|
testID: withTestIdPrefix(AuthTestIds.otpVerifyButton, testIdPrefix),
|
|
1150
1279
|
onPress: () => onSubmit(code.trim()),
|
|
1151
|
-
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 })
|
|
1152
1281
|
}
|
|
1153
1282
|
),
|
|
1154
1283
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1158,10 +1287,10 @@ function OtpVerifyStep({
|
|
|
1158
1287
|
accessibilityLabel: isSubmitting ? labels.resending : labels.resend,
|
|
1159
1288
|
accessibilityRole: "link",
|
|
1160
1289
|
disabled: isSubmitting,
|
|
1161
|
-
style:
|
|
1290
|
+
style: styles3.fieldGroup,
|
|
1162
1291
|
testID: withTestIdPrefix(AuthTestIds.otpResendButton, testIdPrefix),
|
|
1163
1292
|
onPress: onResend,
|
|
1164
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: isSubmitting ? labels.resending : labels.resend })
|
|
1165
1294
|
}
|
|
1166
1295
|
),
|
|
1167
1296
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1173,7 +1302,7 @@ function OtpVerifyStep({
|
|
|
1173
1302
|
disabled: isSubmitting,
|
|
1174
1303
|
testID: withTestIdPrefix(AuthTestIds.otpChangeEmailButton, testIdPrefix),
|
|
1175
1304
|
onPress: onChangeEmail,
|
|
1176
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1305
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.changeEmail })
|
|
1177
1306
|
}
|
|
1178
1307
|
)
|
|
1179
1308
|
] });
|
|
@@ -1342,7 +1471,7 @@ function OtpForm({
|
|
|
1342
1471
|
testIdPrefix
|
|
1343
1472
|
}) {
|
|
1344
1473
|
const theme = useAuthTheme(themeProp);
|
|
1345
|
-
const
|
|
1474
|
+
const styles3 = useAuthStyles(theme);
|
|
1346
1475
|
const labels = react.useMemo(
|
|
1347
1476
|
() => ({ ...DEFAULT_OTP_LABELS, ...labelsProp }),
|
|
1348
1477
|
[labelsProp]
|
|
@@ -1360,13 +1489,13 @@ function OtpForm({
|
|
|
1360
1489
|
otp.reset();
|
|
1361
1490
|
}, [otp]);
|
|
1362
1491
|
const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);
|
|
1363
|
-
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(
|
|
1364
1493
|
OtpRequestStep,
|
|
1365
1494
|
{
|
|
1366
1495
|
errorText,
|
|
1367
1496
|
isSubmitting: otp.isSubmitting,
|
|
1368
1497
|
labels,
|
|
1369
|
-
styles,
|
|
1498
|
+
styles: styles3,
|
|
1370
1499
|
testIdPrefix,
|
|
1371
1500
|
theme,
|
|
1372
1501
|
onSubmit: handleRequest
|
|
@@ -1378,7 +1507,7 @@ function OtpForm({
|
|
|
1378
1507
|
identifier: otp.identifier,
|
|
1379
1508
|
isSubmitting: otp.isSubmitting,
|
|
1380
1509
|
labels,
|
|
1381
|
-
styles,
|
|
1510
|
+
styles: styles3,
|
|
1382
1511
|
testIdPrefix,
|
|
1383
1512
|
theme,
|
|
1384
1513
|
onChangeEmail: handleChangeEmail,
|
|
@@ -1467,7 +1596,7 @@ function PinForm({
|
|
|
1467
1596
|
testIdPrefix
|
|
1468
1597
|
}) {
|
|
1469
1598
|
const theme = useAuthTheme(themeProp);
|
|
1470
|
-
const
|
|
1599
|
+
const styles3 = useAuthStyles(theme);
|
|
1471
1600
|
const labels = react.useMemo(
|
|
1472
1601
|
() => ({ ...DEFAULT_PIN_LABELS, ...labelsProp }),
|
|
1473
1602
|
[labelsProp]
|
|
@@ -1477,12 +1606,12 @@ function PinForm({
|
|
|
1477
1606
|
const [pinValue, setPinValue] = react.useState("");
|
|
1478
1607
|
const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);
|
|
1479
1608
|
const errorText = localError ?? transportErrorFor2(pin.error, labels);
|
|
1480
|
-
const buttonStyle = pin.isSubmitting ? [
|
|
1481
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
1482
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1483
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
1484
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1485
|
-
/* @__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 }),
|
|
1486
1615
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1487
1616
|
reactNative.TextInput,
|
|
1488
1617
|
{
|
|
@@ -1495,7 +1624,7 @@ function PinForm({
|
|
|
1495
1624
|
placeholder: labels.pinPlaceholder,
|
|
1496
1625
|
placeholderTextColor: theme.colors.textSecondary,
|
|
1497
1626
|
secureTextEntry: true,
|
|
1498
|
-
style:
|
|
1627
|
+
style: styles3.input,
|
|
1499
1628
|
testID: withTestIdPrefix(AuthTestIds.pinInput, testIdPrefix),
|
|
1500
1629
|
value: pinValue,
|
|
1501
1630
|
onChangeText: setPinValue
|
|
@@ -1505,7 +1634,7 @@ function PinForm({
|
|
|
1505
1634
|
errorText !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1506
1635
|
reactNative.Text,
|
|
1507
1636
|
{
|
|
1508
|
-
style:
|
|
1637
|
+
style: styles3.errorText,
|
|
1509
1638
|
testID: withTestIdPrefix(AuthTestIds.pinError, testIdPrefix),
|
|
1510
1639
|
children: errorText
|
|
1511
1640
|
}
|
|
@@ -1520,11 +1649,918 @@ function PinForm({
|
|
|
1520
1649
|
style: buttonStyle,
|
|
1521
1650
|
testID: withTestIdPrefix(AuthTestIds.pinSubmitButton, testIdPrefix),
|
|
1522
1651
|
onPress: () => handleSubmit(pinValue.trim()),
|
|
1523
|
-
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 })
|
|
1524
1653
|
}
|
|
1525
1654
|
)
|
|
1526
1655
|
] }) });
|
|
1527
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
|
+
}
|
|
1528
2564
|
async function lazyFetchHttpClient(request) {
|
|
1529
2565
|
const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
|
|
1530
2566
|
if (fetchImpl === void 0) {
|
|
@@ -1579,12 +2615,27 @@ Object.defineProperty(exports, "createFetchHttpClient", {
|
|
|
1579
2615
|
exports.AuthTestIds = AuthTestIds;
|
|
1580
2616
|
exports.AuthThemeProvider = AuthThemeProvider;
|
|
1581
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;
|
|
1582
2621
|
exports.DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS = DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS;
|
|
1583
2622
|
exports.DEFAULT_FORGOT_PASSWORD_LABELS = DEFAULT_FORGOT_PASSWORD_LABELS;
|
|
1584
2623
|
exports.DEFAULT_LOGIN_LABELS = DEFAULT_LOGIN_LABELS;
|
|
1585
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;
|
|
1586
2627
|
exports.DEFAULT_PIN_LABELS = DEFAULT_PIN_LABELS;
|
|
1587
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;
|
|
1588
2639
|
exports.ForgotPasswordFields = ForgotPasswordFields;
|
|
1589
2640
|
exports.ForgotPasswordForm = ForgotPasswordForm;
|
|
1590
2641
|
exports.LoginForm = LoginForm;
|
|
@@ -1592,6 +2643,8 @@ exports.OtpForm = OtpForm;
|
|
|
1592
2643
|
exports.OtpLoginStep = OtpLoginStep;
|
|
1593
2644
|
exports.PASSWORD_MAX_LENGTH = PASSWORD_MAX_LENGTH;
|
|
1594
2645
|
exports.PASSWORD_MIN_LENGTH = PASSWORD_MIN_LENGTH;
|
|
2646
|
+
exports.PasskeyLoginButton = PasskeyLoginButton;
|
|
2647
|
+
exports.PasskeySettingsCard = PasskeySettingsCard;
|
|
1595
2648
|
exports.PasswordPolicyError = PasswordPolicyError;
|
|
1596
2649
|
exports.PinForm = PinForm;
|
|
1597
2650
|
exports.ResetPasswordError = ResetPasswordError;
|
|
@@ -1599,13 +2652,22 @@ exports.ResetPasswordForm = ResetPasswordForm;
|
|
|
1599
2652
|
exports.collectUserRoles = collectUserRoles;
|
|
1600
2653
|
exports.createBffAuthClient = createBffAuthClient;
|
|
1601
2654
|
exports.defaultAuthTheme = defaultAuthTheme;
|
|
2655
|
+
exports.isAllowedPinDigits = isAllowedPinDigits;
|
|
1602
2656
|
exports.isPasswordValid = isPasswordValid;
|
|
1603
2657
|
exports.isValidForgotPasswordEmail = isValidForgotPasswordEmail;
|
|
2658
|
+
exports.readPasskeyError = readPasskeyError;
|
|
2659
|
+
exports.readPasskeyRegistered = readPasskeyRegistered;
|
|
1604
2660
|
exports.resolvePostLoginRoute = resolvePostLoginRoute;
|
|
2661
|
+
exports.startPasskeyLogin = startPasskeyLogin;
|
|
2662
|
+
exports.startPasskeyRegistration = startPasskeyRegistration;
|
|
1605
2663
|
exports.useAuthTheme = useAuthTheme;
|
|
1606
2664
|
exports.useBffAuth = useBffAuth;
|
|
1607
2665
|
exports.useBffForgotPassword = useBffForgotPassword;
|
|
2666
|
+
exports.useBffLoginConfig = useBffLoginConfig;
|
|
1608
2667
|
exports.useBffResetPassword = useBffResetPassword;
|
|
2668
|
+
exports.useDevicePinDisable = useDevicePinDisable;
|
|
2669
|
+
exports.useDevicePinEnroll = useDevicePinEnroll;
|
|
2670
|
+
exports.useDevicePinUnlock = useDevicePinUnlock;
|
|
1609
2671
|
exports.useForgotPasswordSubmit = useForgotPasswordSubmit;
|
|
1610
2672
|
exports.useOtpLogin = useOtpLogin;
|
|
1611
2673
|
exports.usePinLogin = usePinLogin;
|