@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/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 styles = useAuthStyles(theme);
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
396
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.card, testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix), children: [
397
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: labels.title }),
398
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: labels.subtitle }),
399
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
400
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.usernameLabel }),
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: styles.input,
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: styles.fieldGroup, children: [
419
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.passwordLabel }),
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: styles.input,
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: styles.errorText,
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: styles.fieldGroup,
589
+ style: styles3.fieldGroup,
454
590
  testID: withTestIdPrefix(AuthTestIds.loginForgotLink, testIdPrefix),
455
591
  onPress: onForgotPassword,
456
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: labels.forgotPassword })
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: styles.primaryButtonText, children: labels.submit })
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: styles.fieldGroup,
615
+ style: styles3.fieldGroup,
480
616
  testID: withTestIdPrefix(AuthTestIds.loginSignUpLink, testIdPrefix),
481
617
  onPress: onSignUp,
482
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: labels.signUp })
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 styles = useAuthStyles(theme);
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
553
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
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: styles.card,
692
+ style: styles3.card,
557
693
  testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix),
558
694
  children: [
559
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: labels.title }),
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: styles.successText,
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: styles.subtitle, children: labels.description }),
569
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
570
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.emailLabel }),
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: styles.input,
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: styles.errorText,
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: styles.primaryButtonText, children: labels.submit })
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 styles = useAuthStyles(theme);
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
796
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
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: styles.card,
1111
+ style: styles3.card,
800
1112
  testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix),
801
1113
  children: [
802
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: labels.title }),
803
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: labels.description }),
804
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
805
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.newPasswordLabel }),
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: styles.input,
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: styles.fieldGroup, children: [
825
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.confirmPasswordLabel }),
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: styles.input,
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: styles.errorText,
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: styles.primaryButtonText, children: labels.submit })
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
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: styles.title, children: labels.requestTitle }),
882
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: labels.requestDescription }),
883
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
884
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.emailLabel }),
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: styles.input,
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: styles.errorText, testID: withTestIdPrefix(AuthTestIds.otpError, testIdPrefix), children: errorText }) : null,
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: styles.primaryButtonText, children: labels.requestSubmit })
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
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: styles.title, children: labels.verifyTitle }),
936
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: description }),
937
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
938
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.codeLabel }),
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: styles.input,
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: styles.errorText, testID: withTestIdPrefix(AuthTestIds.otpError, testIdPrefix), children: errorText }) : null,
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: styles.primaryButtonText, children: labels.verifySubmit })
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: styles.fieldGroup,
1290
+ style: styles3.fieldGroup,
979
1291
  testID: withTestIdPrefix(AuthTestIds.otpResendButton, testIdPrefix),
980
1292
  onPress: onResend,
981
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: isSubmitting ? labels.resending : labels.resend })
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: styles.linkText, children: labels.changeEmail })
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 EMAIL_REGEX2 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
1428
+ var EMAIL_REGEX3 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
1117
1429
  function isValidEmail2(value) {
1118
- return EMAIL_REGEX2.test(value);
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 styles = useAuthStyles(theme);
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: styles.screen, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.card, testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix), children: otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsxRuntime.jsx(
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 styles = useAuthStyles(theme);
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 ? [styles.primaryButton, styles.primaryButtonDisabled] : styles.primaryButton;
1298
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.card, testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix), children: [
1299
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: labels.title }),
1300
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: labels.description }),
1301
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
1302
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.pinLabel }),
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: styles.input,
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: styles.errorText,
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: styles.primaryButtonText, children: labels.submit })
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;