@dloizides/auth-web 1.22.0 → 1.23.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
@@ -306,7 +306,8 @@ var DEFAULT_RESET_PASSWORD_LABELS = {
306
306
  errorWeakPassword: "Use at least 8 characters with an uppercase letter, a lowercase letter and a digit.",
307
307
  errorMismatch: "The passwords do not match.",
308
308
  errorTokenInvalid: "This reset link is invalid or has expired. Request a new one.",
309
- errorNetwork: "Something went wrong. Please try again."
309
+ errorNetwork: "Something went wrong. Please try again.",
310
+ errorRateLimited: "Too many attempts. Wait a minute and try again."
310
311
  };
311
312
 
312
313
  // src/components/labels/accountSettingsLabels.ts
@@ -343,6 +344,8 @@ var DEFAULT_REGISTER_LABELS = {
343
344
  submitHint: "Creates your account",
344
345
  submitting: "Creating account...",
345
346
  fullName: field("Your name", "Enter your full name"),
347
+ checkEmailTitle: "Check your email",
348
+ checkEmailBody: "If this address can be used, a link to finish signing up is on its way.",
346
349
  fields: {
347
350
  firstName: field("First name", "Enter your first name"),
348
351
  lastName: field("Last name", "Enter your last name"),
@@ -355,6 +358,19 @@ var DEFAULT_REGISTER_LABELS = {
355
358
  };
356
359
 
357
360
  // src/components/labels/verifyEmailLabels.ts
361
+ var DEFAULT_VERIFY_NEW_PASSWORD_LABELS = {
362
+ ...DEFAULT_RESET_PASSWORD_LABELS,
363
+ title: "Set a new password",
364
+ description: "To finish signing in, choose a new password for your account.",
365
+ submit: "Save and sign in",
366
+ submitting: "Saving..."
367
+ };
368
+ var DEFAULT_VERIFY_SIGN_IN_LABELS = {
369
+ title: "Your email is verified",
370
+ body: "We could not sign you in automatically. Please sign in with your password.",
371
+ action: "Sign in",
372
+ actionHint: "Go to the sign in page"
373
+ };
358
374
  var DEFAULT_VERIFY_EMAIL_LABELS = {
359
375
  loadingTitle: "Verifying your email...",
360
376
  loadingHint: "Please wait while we verify your address.",
@@ -376,7 +392,10 @@ var DEFAULT_VERIFY_EMAIL_LABELS = {
376
392
  resendMissingEmail: "Enter your email address.",
377
393
  resendSubmit: "Send link",
378
394
  resendSubmitHint: "Sends a new verification email",
379
- resendConfirmation: "If that address has an account, a new verification link is on its way."
395
+ resendConfirmation: "If that address has an account, a new verification link is on its way.",
396
+ errorRateLimited: "Too many attempts. Wait a minute and try again.",
397
+ newPassword: DEFAULT_VERIFY_NEW_PASSWORD_LABELS,
398
+ signIn: DEFAULT_VERIFY_SIGN_IN_LABELS
380
399
  };
381
400
 
382
401
  // src/components/testIds.ts
@@ -475,6 +494,8 @@ var AuthTestIds = {
475
494
  verifyEmailSuccess: "auth-verify-email-success",
476
495
  verifyEmailContinue: "auth-verify-email-continue",
477
496
  verifyEmailError: "auth-verify-email-error",
497
+ verifyEmailSignIn: "auth-verify-email-sign-in",
498
+ verifyEmailSignInContinue: "auth-verify-email-sign-in-continue",
478
499
  verifyEmailResendCta: "auth-verify-email-resend-cta",
479
500
  verifyEmailResendForm: "auth-verify-email-resend-form",
480
501
  verifyEmailResendEmail: "auth-verify-email-resend-email",
@@ -576,6 +597,12 @@ function useAuthStyles(theme) {
576
597
  marginTop: spacing.xs,
577
598
  color: colors.danger
578
599
  },
600
+ errorBody: {
601
+ fontSize: typography.body,
602
+ marginTop: spacing.xs,
603
+ marginBottom: spacing.md,
604
+ color: colors.danger
605
+ },
579
606
  successText: {
580
607
  fontSize: typography.body,
581
608
  lineHeight: typography.body * 1.4,
@@ -1269,8 +1296,107 @@ var ResetPasswordError = /* @__PURE__ */ ((ResetPasswordError2) => {
1269
1296
  ResetPasswordError2["Mismatch"] = "mismatch";
1270
1297
  ResetPasswordError2["TokenInvalid"] = "tokenInvalid";
1271
1298
  ResetPasswordError2["Network"] = "network";
1299
+ ResetPasswordError2["RateLimited"] = "rateLimited";
1272
1300
  return ResetPasswordError2;
1273
1301
  })(ResetPasswordError || {});
1302
+ function errorMessage(errorKey, labels) {
1303
+ switch (errorKey) {
1304
+ case "empty" /* Empty */:
1305
+ return labels.errorEmpty;
1306
+ case "weakPassword" /* WeakPassword */:
1307
+ return labels.errorWeakPassword;
1308
+ case "mismatch" /* Mismatch */:
1309
+ return labels.errorMismatch;
1310
+ case "tokenInvalid" /* TokenInvalid */:
1311
+ return labels.errorTokenInvalid;
1312
+ case "network" /* Network */:
1313
+ return labels.errorNetwork;
1314
+ case "rateLimited" /* RateLimited */:
1315
+ return labels.errorRateLimited ?? labels.errorNetwork;
1316
+ default:
1317
+ return null;
1318
+ }
1319
+ }
1320
+ function ResetPasswordFields({
1321
+ form,
1322
+ labels,
1323
+ styles: styles3,
1324
+ theme,
1325
+ testIdPrefix,
1326
+ newPasswordRef,
1327
+ onSubmitEditing
1328
+ }) {
1329
+ const message = errorMessage(form.errorKey, labels);
1330
+ const submitButtonStyle = form.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
1331
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1332
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
1333
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
1334
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
1335
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.newPasswordLabel }),
1336
+ /* @__PURE__ */ jsxRuntime.jsx(
1337
+ reactNative.TextInput,
1338
+ {
1339
+ ref: newPasswordRef,
1340
+ secureTextEntry: true,
1341
+ accessibilityHint: labels.newPasswordPlaceholder,
1342
+ accessibilityLabel: labels.newPasswordLabel,
1343
+ autoCapitalize: "none",
1344
+ autoCorrect: false,
1345
+ editable: !form.isSubmitting,
1346
+ placeholder: labels.newPasswordPlaceholder,
1347
+ placeholderTextColor: theme.colors.textSecondary,
1348
+ style: styles3.input,
1349
+ testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
1350
+ value: form.newPassword,
1351
+ onChangeText: form.setNewPassword,
1352
+ onSubmitEditing
1353
+ }
1354
+ )
1355
+ ] }),
1356
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
1357
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
1358
+ /* @__PURE__ */ jsxRuntime.jsx(
1359
+ reactNative.TextInput,
1360
+ {
1361
+ secureTextEntry: true,
1362
+ accessibilityHint: labels.confirmPasswordPlaceholder,
1363
+ accessibilityLabel: labels.confirmPasswordLabel,
1364
+ autoCapitalize: "none",
1365
+ autoCorrect: false,
1366
+ editable: !form.isSubmitting,
1367
+ placeholder: labels.confirmPasswordPlaceholder,
1368
+ placeholderTextColor: theme.colors.textSecondary,
1369
+ style: styles3.input,
1370
+ testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
1371
+ value: form.confirmPassword,
1372
+ onChangeText: form.setConfirmPassword,
1373
+ onSubmitEditing
1374
+ }
1375
+ )
1376
+ ] }),
1377
+ message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
1378
+ reactNative.Text,
1379
+ {
1380
+ style: styles3.errorText,
1381
+ testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
1382
+ children: message
1383
+ }
1384
+ ) : null,
1385
+ /* @__PURE__ */ jsxRuntime.jsx(
1386
+ reactNative.TouchableOpacity,
1387
+ {
1388
+ accessibilityHint: labels.submit,
1389
+ accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
1390
+ accessibilityRole: "button",
1391
+ disabled: form.isSubmitting,
1392
+ style: submitButtonStyle,
1393
+ testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
1394
+ onPress: form.submit,
1395
+ 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 })
1396
+ }
1397
+ )
1398
+ ] });
1399
+ }
1274
1400
 
1275
1401
  // src/password/PasswordPolicyError.ts
1276
1402
  var PasswordPolicyError = /* @__PURE__ */ ((PasswordPolicyError2) => {
@@ -1409,22 +1535,6 @@ function useResetPasswordForm({
1409
1535
  submit
1410
1536
  };
1411
1537
  }
1412
- function errorMessage(errorKey, labels) {
1413
- switch (errorKey) {
1414
- case "empty" /* Empty */:
1415
- return labels.errorEmpty;
1416
- case "weakPassword" /* WeakPassword */:
1417
- return labels.errorWeakPassword;
1418
- case "mismatch" /* Mismatch */:
1419
- return labels.errorMismatch;
1420
- case "tokenInvalid" /* TokenInvalid */:
1421
- return labels.errorTokenInvalid;
1422
- case "network" /* Network */:
1423
- return labels.errorNetwork;
1424
- default:
1425
- return null;
1426
- }
1427
- }
1428
1538
  function ResetPasswordForm({
1429
1539
  client,
1430
1540
  token,
@@ -1440,78 +1550,21 @@ function ResetPasswordForm({
1440
1550
  [labelsProp]
1441
1551
  );
1442
1552
  const form = useResetPasswordForm({ client, token, onSuccess });
1443
- const message = errorMessage(form.errorKey, labels);
1444
- const submitButtonStyle = form.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
1445
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
1553
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsx(
1446
1554
  reactNative.View,
1447
1555
  {
1448
1556
  style: styles3.card,
1449
1557
  testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix),
1450
- children: [
1451
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
1453
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
1454
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.newPasswordLabel }),
1455
- /* @__PURE__ */ jsxRuntime.jsx(
1456
- reactNative.TextInput,
1457
- {
1458
- secureTextEntry: true,
1459
- accessibilityHint: labels.newPasswordPlaceholder,
1460
- accessibilityLabel: labels.newPasswordLabel,
1461
- autoCapitalize: "none",
1462
- autoCorrect: false,
1463
- editable: !form.isSubmitting,
1464
- placeholder: labels.newPasswordPlaceholder,
1465
- placeholderTextColor: theme.colors.textSecondary,
1466
- style: styles3.input,
1467
- testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
1468
- value: form.newPassword,
1469
- onChangeText: form.setNewPassword
1470
- }
1471
- )
1472
- ] }),
1473
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
1474
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
1475
- /* @__PURE__ */ jsxRuntime.jsx(
1476
- reactNative.TextInput,
1477
- {
1478
- secureTextEntry: true,
1479
- accessibilityHint: labels.confirmPasswordPlaceholder,
1480
- accessibilityLabel: labels.confirmPasswordLabel,
1481
- autoCapitalize: "none",
1482
- autoCorrect: false,
1483
- editable: !form.isSubmitting,
1484
- placeholder: labels.confirmPasswordPlaceholder,
1485
- placeholderTextColor: theme.colors.textSecondary,
1486
- style: styles3.input,
1487
- testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
1488
- value: form.confirmPassword,
1489
- onChangeText: form.setConfirmPassword
1490
- }
1491
- )
1492
- ] }),
1493
- message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
1494
- reactNative.Text,
1495
- {
1496
- style: styles3.errorText,
1497
- testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
1498
- children: message
1499
- }
1500
- ) : null,
1501
- /* @__PURE__ */ jsxRuntime.jsx(
1502
- reactNative.TouchableOpacity,
1503
- {
1504
- accessibilityHint: labels.submit,
1505
- accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
1506
- accessibilityRole: "button",
1507
- disabled: form.isSubmitting,
1508
- style: submitButtonStyle,
1509
- testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
1510
- onPress: form.submit,
1511
- 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 })
1512
- }
1513
- )
1514
- ]
1558
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1559
+ ResetPasswordFields,
1560
+ {
1561
+ form,
1562
+ labels,
1563
+ styles: styles3,
1564
+ testIdPrefix,
1565
+ theme
1566
+ }
1567
+ )
1515
1568
  }
1516
1569
  ) });
1517
1570
  }
@@ -4140,7 +4193,8 @@ var RegisterTestIds = {
4140
4193
  confirmPasswordInput: "register-confirm-password-input",
4141
4194
  tenantNameInput: "register-tenant-name-input",
4142
4195
  submitButton: "register-submit-button",
4143
- websiteInput: "register-website"
4196
+ websiteInput: "register-website",
4197
+ checkEmail: "register-check-email"
4144
4198
  };
4145
4199
  var FIELDS = [
4146
4200
  { key: "firstName", testId: RegisterTestIds.firstNameInput, autoComplete: "name" },
@@ -4262,6 +4316,14 @@ function routeRegisterOutcome(outcome, handlers) {
4262
4316
  }
4263
4317
  }
4264
4318
 
4319
+ // src/hooks/registerAccepted.ts
4320
+ function isRegisterAccepted(result) {
4321
+ if (typeof result !== "object" || result === null) {
4322
+ return false;
4323
+ }
4324
+ return result.accepted === true;
4325
+ }
4326
+
4265
4327
  // src/hooks/registerErrors.ts
4266
4328
  var MIN_PASSWORD_LENGTH = 8;
4267
4329
  var WHITESPACE_REGEX = /\s/;
@@ -4414,6 +4476,42 @@ function expandCompactRegisterValues(values) {
4414
4476
  };
4415
4477
  }
4416
4478
 
4479
+ // src/hooks/newIdempotencyKey.ts
4480
+ var HEX_RADIX = 16;
4481
+ var HEX_BYTE_LENGTH = 2;
4482
+ var KEY_BYTES = 16;
4483
+ var fallbackSequence = 0;
4484
+ function newIdempotencyKey() {
4485
+ const cryptoApi = globalThis.crypto;
4486
+ if (typeof cryptoApi?.randomUUID === "function") {
4487
+ return cryptoApi.randomUUID();
4488
+ }
4489
+ if (typeof cryptoApi?.getRandomValues === "function") {
4490
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(KEY_BYTES));
4491
+ return Array.from(bytes, (byte) => byte.toString(HEX_RADIX).padStart(HEX_BYTE_LENGTH, "0")).join("");
4492
+ }
4493
+ fallbackSequence += 1;
4494
+ return `${Date.now().toString(HEX_RADIX)}-${String(fallbackSequence)}`;
4495
+ }
4496
+
4497
+ // src/hooks/useRegisterSubmitMeta.ts
4498
+ function useRegisterSubmitMeta() {
4499
+ const openedAt = react.useRef(Date.now());
4500
+ const key = react.useRef(null);
4501
+ return react.useMemo(
4502
+ () => ({
4503
+ next: () => {
4504
+ key.current ?? (key.current = newIdempotencyKey());
4505
+ return { idempotencyKey: key.current, formElapsedMs: Date.now() - openedAt.current };
4506
+ },
4507
+ resetKey: () => {
4508
+ key.current = null;
4509
+ }
4510
+ }),
4511
+ []
4512
+ );
4513
+ }
4514
+
4417
4515
  // src/hooks/useRegisterForm.ts
4418
4516
  var EMPTY_VALUES = {
4419
4517
  firstName: "",
@@ -4425,6 +4523,9 @@ var EMPTY_VALUES = {
4425
4523
  tenantName: "",
4426
4524
  website: ""
4427
4525
  };
4526
+ function withoutPasswords(values) {
4527
+ return { ...values, password: "", confirmPassword: "" };
4528
+ }
4428
4529
  function toSubmitValues(values) {
4429
4530
  return {
4430
4531
  firstName: values.firstName,
@@ -4440,15 +4541,18 @@ function useRegisterForm({
4440
4541
  onSubmit,
4441
4542
  passwordPolicy = isRegisterPasswordStrong,
4442
4543
  onSubmitAttempt,
4443
- compact = false
4544
+ compact = false,
4545
+ sharedRegistration = false
4444
4546
  }) {
4445
4547
  const [state, setState] = react.useState(EMPTY_VALUES);
4446
4548
  const [isSubmitting, setIsSubmitting] = react.useState(false);
4447
4549
  const [error, setError] = react.useState(null);
4448
4550
  const inFlight = react.useRef(false);
4551
+ const submitMeta = useRegisterSubmitMeta();
4449
4552
  const setField = react.useCallback((field2, value) => {
4553
+ submitMeta.resetKey();
4450
4554
  setState((prev) => ({ ...prev, [field2]: value }));
4451
- }, []);
4555
+ }, [submitMeta]);
4452
4556
  const submit = react.useCallback(async () => {
4453
4557
  if (inFlight.current) {
4454
4558
  return { ok: false, error: "inFlight" /* InFlight */ };
@@ -4465,7 +4569,11 @@ function useRegisterForm({
4465
4569
  setError(null);
4466
4570
  setIsSubmitting(true);
4467
4571
  try {
4468
- const result = await onSubmit(toSubmitValues(trimmed));
4572
+ const values = toSubmitValues(trimmed);
4573
+ const result = await (sharedRegistration ? onSubmit(values, submitMeta.next()) : onSubmit(values));
4574
+ if (sharedRegistration && isRegisterAccepted(result)) {
4575
+ setState(withoutPasswords);
4576
+ }
4469
4577
  return { ok: true, result };
4470
4578
  } catch (caught) {
4471
4579
  const code = mapRegisterErrorCode(caught);
@@ -4475,10 +4583,10 @@ function useRegisterForm({
4475
4583
  inFlight.current = false;
4476
4584
  setIsSubmitting(false);
4477
4585
  }
4478
- }, [compact, onSubmit, onSubmitAttempt, passwordPolicy, state]);
4586
+ }, [compact, onSubmit, onSubmitAttempt, passwordPolicy, sharedRegistration, state, submitMeta]);
4479
4587
  return { state, setField, submit, isSubmitting, error };
4480
4588
  }
4481
- function RegisterForm({
4589
+ function RegisterFormCore({
4482
4590
  onSubmit,
4483
4591
  onSuccess,
4484
4592
  onError,
@@ -4488,7 +4596,8 @@ function RegisterForm({
4488
4596
  theme: themeProp,
4489
4597
  footer,
4490
4598
  testIdPrefix,
4491
- compact = false
4599
+ compact = false,
4600
+ sharedRegistration
4492
4601
  }) {
4493
4602
  const theme = useAuthTheme(themeProp);
4494
4603
  const styles3 = useAuthStyles(theme);
@@ -4500,7 +4609,8 @@ function RegisterForm({
4500
4609
  onSubmit,
4501
4610
  onSubmitAttempt,
4502
4611
  passwordPolicy,
4503
- compact
4612
+ compact,
4613
+ sharedRegistration
4504
4614
  });
4505
4615
  const handlePress = react.useCallback(async () => {
4506
4616
  routeRegisterOutcome(await submit(), { onSuccess, onError });
@@ -4538,6 +4648,9 @@ function RegisterForm({
4538
4648
  footer
4539
4649
  ] }) });
4540
4650
  }
4651
+ function RegisterForm(props) {
4652
+ return /* @__PURE__ */ jsxRuntime.jsx(RegisterFormCore, { ...props, sharedRegistration: false });
4653
+ }
4541
4654
  async function lazyFetchHttpClient(request) {
4542
4655
  const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
4543
4656
  if (fetchImpl === void 0) {
@@ -4673,6 +4786,11 @@ function createBffChangePasswordClient(options = {}) {
4673
4786
  }
4674
4787
  };
4675
4788
  }
4789
+ function useFocusOnMount(ref) {
4790
+ react.useEffect(() => {
4791
+ ref.current?.focus();
4792
+ }, [ref]);
4793
+ }
4676
4794
  function useResendVerification({ client, verifyUrlTemplate }) {
4677
4795
  const [email, setEmail] = react.useState("");
4678
4796
  const [missingEmail, setMissingEmail] = react.useState(false);
@@ -4692,6 +4810,11 @@ function useResendVerification({ client, verifyUrlTemplate }) {
4692
4810
  }, [client, email, verifyUrlTemplate]);
4693
4811
  return { email, setEmail, missingEmail, submitting, confirmed, submit };
4694
4812
  }
4813
+ function ResendConfirmation({ style, testID, text }) {
4814
+ const ref = react.useRef(null);
4815
+ useFocusOnMount(ref);
4816
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ref, accessible: true, accessibilityLiveRegion: "polite", focusable: true, testID, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style, children: text }) });
4817
+ }
4695
4818
  function VerifyEmailResendForm({
4696
4819
  client,
4697
4820
  labels,
@@ -4703,7 +4826,7 @@ function VerifyEmailResendForm({
4703
4826
  const resend = useResendVerification({ client, verifyUrlTemplate });
4704
4827
  const id = (base) => withTestIdPrefix(base, testIdPrefix);
4705
4828
  if (resend.confirmed) {
4706
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.successText, testID: id(AuthTestIds.verifyEmailResendConfirmation), children: labels.resendConfirmation });
4829
+ return /* @__PURE__ */ jsxRuntime.jsx(ResendConfirmation, { style: styles3.successText, testID: id(AuthTestIds.verifyEmailResendConfirmation), text: labels.resendConfirmation });
4707
4830
  }
4708
4831
  const submit = () => {
4709
4832
  void resend.submit();
@@ -4732,7 +4855,7 @@ function VerifyEmailResendForm({
4732
4855
  }
4733
4856
  )
4734
4857
  ] }),
4735
- resend.missingEmail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, children: labels.resendMissingEmail }) : null,
4858
+ resend.missingEmail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: labels.resendMissingEmail }) : null,
4736
4859
  /* @__PURE__ */ jsxRuntime.jsx(
4737
4860
  reactNative.TouchableOpacity,
4738
4861
  {
@@ -4756,19 +4879,155 @@ var VerifyEmailErrorCode = /* @__PURE__ */ ((VerifyEmailErrorCode2) => {
4756
4879
  VerifyEmailErrorCode2["TokenUsed"] = "TOKEN_USED";
4757
4880
  VerifyEmailErrorCode2["KeycloakUpdateFailed"] = "KEYCLOAK_UPDATE_FAILED";
4758
4881
  VerifyEmailErrorCode2["MissingToken"] = "MISSING_TOKEN";
4882
+ VerifyEmailErrorCode2["NewPasswordRequired"] = "NEW_PASSWORD_REQUIRED";
4883
+ VerifyEmailErrorCode2["WeakPassword"] = "WEAK_PASSWORD";
4884
+ VerifyEmailErrorCode2["RateLimited"] = "RATE_LIMITED";
4885
+ VerifyEmailErrorCode2["SignInFailed"] = "SIGN_IN_FAILED";
4759
4886
  VerifyEmailErrorCode2["Generic"] = "GENERIC";
4760
4887
  return VerifyEmailErrorCode2;
4761
4888
  })(VerifyEmailErrorCode || {});
4762
4889
 
4890
+ // src/verify/useVerifyNewPasswordForm.ts
4891
+ var GENERIC_FAILURE = { success: false, errorCode: "GENERIC" /* Generic */ };
4892
+ var DEAD_LINK_CODES = [
4893
+ "TOKEN_INVALID" /* TokenInvalid */,
4894
+ "TOKEN_EXPIRED" /* TokenExpired */,
4895
+ "TOKEN_USED" /* TokenUsed */,
4896
+ "SIGN_IN_FAILED" /* SignInFailed */
4897
+ ];
4898
+ function retryableError(code) {
4899
+ if (DEAD_LINK_CODES.includes(code)) {
4900
+ return null;
4901
+ }
4902
+ if (code === "WEAK_PASSWORD" /* WeakPassword */) {
4903
+ return "weakPassword" /* WeakPassword */;
4904
+ }
4905
+ return code === "RATE_LIMITED" /* RateLimited */ ? "rateLimited" /* RateLimited */ : "network" /* Network */;
4906
+ }
4907
+ function useVerifyNewPasswordForm({
4908
+ client,
4909
+ token,
4910
+ onSettled
4911
+ }) {
4912
+ const { state, setters } = useFormState();
4913
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
4914
+ const inFlight = react.useRef(false);
4915
+ const send = react.useMemo(
4916
+ () => async (newPassword) => {
4917
+ if (inFlight.current) {
4918
+ return;
4919
+ }
4920
+ inFlight.current = true;
4921
+ setIsSubmitting(true);
4922
+ const result = await (client.setNewPassword?.(token, newPassword) ?? Promise.resolve(GENERIC_FAILURE)).catch(
4923
+ () => GENERIC_FAILURE
4924
+ );
4925
+ inFlight.current = false;
4926
+ setIsSubmitting(false);
4927
+ const formError = result.success ? null : retryableError(result.errorCode);
4928
+ if (formError === null) {
4929
+ onSettled(result);
4930
+ return;
4931
+ }
4932
+ setters.setErrorKey(formError);
4933
+ },
4934
+ [client, onSettled, setters, token]
4935
+ );
4936
+ return {
4937
+ ...state,
4938
+ setNewPassword: setters.setNewPassword,
4939
+ setConfirmPassword: setters.setConfirmPassword,
4940
+ isSubmitting,
4941
+ submit: () => runSubmit({
4942
+ newPassword: state.newPassword,
4943
+ confirmPassword: state.confirmPassword,
4944
+ token,
4945
+ setErrorKey: setters.setErrorKey,
4946
+ setHasInvalidToken: setters.setHasInvalidToken,
4947
+ mutate: (request) => {
4948
+ void send(request.newPassword);
4949
+ }
4950
+ })
4951
+ };
4952
+ }
4953
+ function VerifyNewPasswordStep({
4954
+ client,
4955
+ token,
4956
+ labels: labelsProp,
4957
+ styles: styles3,
4958
+ theme,
4959
+ testIdPrefix,
4960
+ onSettled
4961
+ }) {
4962
+ const labels = react.useMemo(
4963
+ () => ({ ...DEFAULT_VERIFY_NEW_PASSWORD_LABELS, ...labelsProp }),
4964
+ [labelsProp]
4965
+ );
4966
+ const form = useVerifyNewPasswordForm({ client, token, onSettled });
4967
+ const handleSubmitEditing = useSubmitOnEnter(form.submit);
4968
+ const newPasswordRef = react.useRef(null);
4969
+ useFocusOnMount(newPasswordRef);
4970
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix), children: /* @__PURE__ */ jsxRuntime.jsx(
4971
+ ResetPasswordFields,
4972
+ {
4973
+ form,
4974
+ labels,
4975
+ newPasswordRef,
4976
+ styles: styles3,
4977
+ testIdPrefix,
4978
+ theme,
4979
+ onSubmitEditing: handleSubmitEditing
4980
+ }
4981
+ ) });
4982
+ }
4983
+ function VerifySignInPrompt({
4984
+ labels: labelsProp,
4985
+ styles: styles3,
4986
+ testID,
4987
+ actionTestID,
4988
+ onContinue
4989
+ }) {
4990
+ const labels = react.useMemo(() => ({ ...DEFAULT_VERIFY_SIGN_IN_LABELS, ...labelsProp }), [labelsProp]);
4991
+ const actionRef = react.useRef(null);
4992
+ useFocusOnMount(actionRef);
4993
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID, children: [
4994
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.title }),
4995
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.body }),
4996
+ /* @__PURE__ */ jsxRuntime.jsx(
4997
+ reactNative.TouchableOpacity,
4998
+ {
4999
+ ref: actionRef,
5000
+ accessibilityHint: labels.actionHint,
5001
+ accessibilityLabel: labels.action,
5002
+ accessibilityRole: "button",
5003
+ style: styles3.primaryButton,
5004
+ testID: actionTestID,
5005
+ onPress: onContinue,
5006
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.action })
5007
+ }
5008
+ )
5009
+ ] });
5010
+ }
5011
+
4763
5012
  // src/verify/VerifyEmailPhase.ts
4764
5013
  var VerifyEmailPhase = /* @__PURE__ */ ((VerifyEmailPhase2) => {
4765
5014
  VerifyEmailPhase2["Loading"] = "loading";
4766
5015
  VerifyEmailPhase2["Success"] = "success";
4767
5016
  VerifyEmailPhase2["Failure"] = "failure";
5017
+ VerifyEmailPhase2["NewPasswordRequired"] = "newPasswordRequired";
4768
5018
  return VerifyEmailPhase2;
4769
5019
  })(VerifyEmailPhase || {});
4770
5020
 
4771
- // src/verify/useVerifyEmail.ts
5021
+ // src/verify/resolveVerifyView.ts
5022
+ function resolveVerifyView(verify, passwordOutcome) {
5023
+ if (passwordOutcome === null) {
5024
+ return verify;
5025
+ }
5026
+ if (passwordOutcome.success) {
5027
+ return { phase: "success" /* Success */, errorCode: "GENERIC" /* Generic */ };
5028
+ }
5029
+ return { phase: "failure" /* Failure */, errorCode: passwordOutcome.errorCode };
5030
+ }
4772
5031
  var LOADING = {
4773
5032
  phase: "loading" /* Loading */,
4774
5033
  errorCode: "GENERIC" /* Generic */
@@ -4777,6 +5036,10 @@ var SUCCESS = {
4777
5036
  phase: "success" /* Success */,
4778
5037
  errorCode: "GENERIC" /* Generic */
4779
5038
  };
5039
+ var NEW_PASSWORD_REQUIRED = {
5040
+ phase: "newPasswordRequired" /* NewPasswordRequired */,
5041
+ errorCode: "GENERIC" /* Generic */
5042
+ };
4780
5043
  var REJECTED = { success: false, errorCode: "GENERIC" /* Generic */ };
4781
5044
  function failure(errorCode) {
4782
5045
  return { phase: "failure" /* Failure */, errorCode };
@@ -4802,6 +5065,10 @@ function useVerifyEmail({ client, token, onVerified, onFailed }) {
4802
5065
  latest.current.onVerified?.();
4803
5066
  return;
4804
5067
  }
5068
+ if (result.errorCode === "NEW_PASSWORD_REQUIRED" /* NewPasswordRequired */) {
5069
+ setState(NEW_PASSWORD_REQUIRED);
5070
+ return;
5071
+ }
4805
5072
  setState(failure(result.errorCode));
4806
5073
  latest.current.onFailed?.(result.errorCode);
4807
5074
  };
@@ -4827,8 +5094,31 @@ function verifyEmailErrorText(code, labels) {
4827
5094
  if (code === "MISSING_TOKEN" /* MissingToken */) {
4828
5095
  return labels.missingToken;
4829
5096
  }
5097
+ if (code === "SIGN_IN_FAILED" /* SignInFailed */) {
5098
+ return labels.signIn?.body ?? DEFAULT_VERIFY_SIGN_IN_LABELS.body;
5099
+ }
5100
+ if (code === "RATE_LIMITED" /* RateLimited */) {
5101
+ return labels.errorRateLimited ?? labels.errorGeneric;
5102
+ }
4830
5103
  return labels.errorGeneric;
4831
5104
  }
5105
+ function ResendCta({ label, hint, style, textStyle, testID, onPress }) {
5106
+ const ref = react.useRef(null);
5107
+ useFocusOnMount(ref);
5108
+ return /* @__PURE__ */ jsxRuntime.jsx(
5109
+ reactNative.TouchableOpacity,
5110
+ {
5111
+ ref,
5112
+ accessibilityHint: hint,
5113
+ accessibilityLabel: label,
5114
+ accessibilityRole: "button",
5115
+ style,
5116
+ testID,
5117
+ onPress,
5118
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: textStyle, children: label })
5119
+ }
5120
+ );
5121
+ }
4832
5122
  function VerifyEmailScreen({
4833
5123
  client,
4834
5124
  token,
@@ -4846,7 +5136,20 @@ function VerifyEmailScreen({
4846
5136
  () => ({ ...DEFAULT_VERIFY_EMAIL_LABELS, ...labelsProp }),
4847
5137
  [labelsProp]
4848
5138
  );
4849
- const { phase, errorCode } = useVerifyEmail({ client, token, onVerified, onFailed });
5139
+ const verify = useVerifyEmail({ client, token, onVerified, onFailed });
5140
+ const [passwordOutcome, setPasswordOutcome] = react.useState(null);
5141
+ const { phase, errorCode } = resolveVerifyView(verify, passwordOutcome);
5142
+ const settlePassword = react.useCallback(
5143
+ (result) => {
5144
+ setPasswordOutcome(result);
5145
+ if (result.success) {
5146
+ onVerified?.();
5147
+ return;
5148
+ }
5149
+ onFailed?.(result.errorCode);
5150
+ },
5151
+ [onFailed, onVerified]
5152
+ );
4850
5153
  const [resendOpen, setResendOpen] = react.useState(false);
4851
5154
  const openResend = react.useCallback(() => setResendOpen(true), []);
4852
5155
  const id = (base) => withTestIdPrefix(base, testIdPrefix);
@@ -4856,6 +5159,18 @@ function VerifyEmailScreen({
4856
5159
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.loadingTitle }),
4857
5160
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.loadingHint })
4858
5161
  ] }) : null,
5162
+ phase === "newPasswordRequired" /* NewPasswordRequired */ ? /* @__PURE__ */ jsxRuntime.jsx(
5163
+ VerifyNewPasswordStep,
5164
+ {
5165
+ client,
5166
+ labels: labels.newPassword,
5167
+ styles: styles3,
5168
+ testIdPrefix,
5169
+ theme,
5170
+ token,
5171
+ onSettled: settlePassword
5172
+ }
5173
+ ) : null,
4859
5174
  phase === "success" /* Success */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailSuccess), children: [
4860
5175
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.successTitle }),
4861
5176
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.successBody }),
@@ -4872,9 +5187,19 @@ function VerifyEmailScreen({
4872
5187
  }
4873
5188
  )
4874
5189
  ] }) : null,
4875
- phase === "failure" /* Failure */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailError), children: [
5190
+ phase === "failure" /* Failure */ && errorCode === "SIGN_IN_FAILED" /* SignInFailed */ ? /* @__PURE__ */ jsxRuntime.jsx(
5191
+ VerifySignInPrompt,
5192
+ {
5193
+ actionTestID: id(AuthTestIds.verifyEmailSignInContinue),
5194
+ labels: labels.signIn,
5195
+ styles: styles3,
5196
+ testID: id(AuthTestIds.verifyEmailSignIn),
5197
+ onContinue
5198
+ }
5199
+ ) : null,
5200
+ phase === "failure" /* Failure */ && errorCode !== "SIGN_IN_FAILED" /* SignInFailed */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailError), children: [
4876
5201
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.errorTitle }),
4877
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorText, children: verifyEmailErrorText(errorCode, labels) }),
5202
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: verifyEmailErrorText(errorCode, labels) }),
4878
5203
  resendOpen ? /* @__PURE__ */ jsxRuntime.jsx(
4879
5204
  VerifyEmailResendForm,
4880
5205
  {
@@ -4886,15 +5211,14 @@ function VerifyEmailScreen({
4886
5211
  verifyUrlTemplate
4887
5212
  }
4888
5213
  ) : /* @__PURE__ */ jsxRuntime.jsx(
4889
- reactNative.TouchableOpacity,
5214
+ ResendCta,
4890
5215
  {
4891
- accessibilityHint: labels.resendCtaHint,
4892
- accessibilityLabel: labels.resendCta,
4893
- accessibilityRole: "button",
5216
+ hint: labels.resendCtaHint,
5217
+ label: labels.resendCta,
4894
5218
  style: styles3.primaryButton,
4895
5219
  testID: id(AuthTestIds.verifyEmailResendCta),
4896
- onPress: openResend,
4897
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.resendCta })
5220
+ textStyle: styles3.primaryButtonText,
5221
+ onPress: openResend
4898
5222
  }
4899
5223
  )
4900
5224
  ] }) : null
@@ -4911,7 +5235,10 @@ var SERVER_ERROR_CODES2 = [
4911
5235
  "TOKEN_USED" /* TokenUsed */,
4912
5236
  "KEYCLOAK_UPDATE_FAILED" /* KeycloakUpdateFailed */
4913
5237
  ];
4914
- var GENERIC_FAILURE = { success: false, errorCode: "GENERIC" /* Generic */ };
5238
+ var GENERIC_FAILURE2 = { success: false, errorCode: "GENERIC" /* Generic */ };
5239
+ var INVALID_TOKEN = { success: false, errorCode: "TOKEN_INVALID" /* TokenInvalid */ };
5240
+ var HTTP_BAD_REQUEST3 = 400;
5241
+ var TOKEN_FIELD = "token";
4915
5242
  async function lazyFetchHttpClient3(request) {
4916
5243
  const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
4917
5244
  if (fetchImpl === void 0) {
@@ -4925,14 +5252,23 @@ function isServerErrorCode(value) {
4925
5252
  function isRecord3(value) {
4926
5253
  return typeof value === "object" && value !== null;
4927
5254
  }
4928
- function decodeVerifyResponse(body) {
5255
+ function isTokenValidationRejection(status, body) {
5256
+ if (status !== HTTP_BAD_REQUEST3 || !isRecord3(body.errors)) {
5257
+ return false;
5258
+ }
5259
+ return Object.keys(body.errors).some((field2) => field2.toLowerCase() === TOKEN_FIELD);
5260
+ }
5261
+ function decodeVerifyResponse(status, body) {
4929
5262
  if (!isRecord3(body)) {
4930
- return GENERIC_FAILURE;
5263
+ return GENERIC_FAILURE2;
4931
5264
  }
4932
5265
  if (body.success === true) {
4933
5266
  return { success: true };
4934
5267
  }
4935
- return isServerErrorCode(body.errorCode) ? { success: false, errorCode: body.errorCode } : GENERIC_FAILURE;
5268
+ if (isServerErrorCode(body.errorCode)) {
5269
+ return { success: false, errorCode: body.errorCode };
5270
+ }
5271
+ return isTokenValidationRejection(status, body) ? INVALID_TOKEN : GENERIC_FAILURE2;
4936
5272
  }
4937
5273
  function createBffVerifyEmailClient(options = {}) {
4938
5274
  const http = options.http ?? lazyFetchHttpClient3;
@@ -4948,9 +5284,9 @@ function createBffVerifyEmailClient(options = {}) {
4948
5284
  verifyEmail: async (token) => {
4949
5285
  try {
4950
5286
  const response = await post(VERIFY_EMAIL_ENDPOINT, { token });
4951
- return decodeVerifyResponse(response.data);
5287
+ return decodeVerifyResponse(response.status, response.data);
4952
5288
  } catch {
4953
- return GENERIC_FAILURE;
5289
+ return GENERIC_FAILURE2;
4954
5290
  }
4955
5291
  },
4956
5292
  resendVerification: async (email, verifyUrlTemplate) => {
@@ -4990,6 +5326,122 @@ function readVerifyToken(raw) {
4990
5326
  return typeof first === "string" ? first : "";
4991
5327
  }
4992
5328
 
5329
+ // src/verify/sharedRegistrationClient.ts
5330
+ var REGISTER_ENDPOINT = "/bff/register";
5331
+ var VERIFY_AND_LOGIN_ENDPOINT = "/bff/verify-and-login";
5332
+ var HTTP_ACCEPTED = 202;
5333
+ var HTTP_UNAUTHORIZED2 = 401;
5334
+ var HTTP_TOO_MANY_REQUESTS2 = 429;
5335
+ var NO_MESSAGE = "";
5336
+ var GENERIC_FAILURE3 = { success: false, errorCode: "GENERIC" /* Generic */ };
5337
+ function decodeVerifyAndLogin(response) {
5338
+ if (response.ok) {
5339
+ return { success: true };
5340
+ }
5341
+ if (response.status === HTTP_TOO_MANY_REQUESTS2) {
5342
+ return { success: false, errorCode: "RATE_LIMITED" /* RateLimited */ };
5343
+ }
5344
+ if (response.status === HTTP_UNAUTHORIZED2) {
5345
+ return { success: false, errorCode: "SIGN_IN_FAILED" /* SignInFailed */ };
5346
+ }
5347
+ const body = isRecord3(response.data) ? response.data : {};
5348
+ if (body.errorCode === "NEW_PASSWORD_REQUIRED" /* NewPasswordRequired */ || body.errorCode === "WEAK_PASSWORD" /* WeakPassword */) {
5349
+ return { success: false, errorCode: body.errorCode };
5350
+ }
5351
+ return decodeVerifyResponse(response.status, response.data);
5352
+ }
5353
+ function registerFailure(response) {
5354
+ const body = isRecord3(response.data) ? response.data : {};
5355
+ const errorCode = body.errorCode ?? body.code;
5356
+ const message = `Registration failed with status ${String(response.status)}`;
5357
+ return Object.assign(new Error(message), { status: response.status, errorCode });
5358
+ }
5359
+ function createSharedRegistrationClient(options = {}) {
5360
+ const http = options.http ?? lazyFetchHttpClient3;
5361
+ const baseUrl = options.baseUrl ?? "";
5362
+ const post = (path, body, headers = {}) => http({
5363
+ url: `${baseUrl}${path}`,
5364
+ method: "POST",
5365
+ headers: { "Content-Type": "application/json", "X-BFF-Csrf": "1", ...headers },
5366
+ body: JSON.stringify(body),
5367
+ credentials: "include"
5368
+ });
5369
+ const verifyAndLogin = async (body) => {
5370
+ try {
5371
+ return decodeVerifyAndLogin(await post(VERIFY_AND_LOGIN_ENDPOINT, body));
5372
+ } catch {
5373
+ return GENERIC_FAILURE3;
5374
+ }
5375
+ };
5376
+ const verifyEmailClient = createBffVerifyEmailClient(options);
5377
+ return {
5378
+ register: async (request, meta) => {
5379
+ const body = meta === void 0 ? request : { ...request, formElapsedMs: meta.formElapsedMs };
5380
+ const headers = meta === void 0 ? {} : { "Idempotency-Key": meta.idempotencyKey };
5381
+ const response = await post(REGISTER_ENDPOINT, body, headers).catch(() => {
5382
+ throw new Error(NO_MESSAGE);
5383
+ });
5384
+ if (!response.ok) {
5385
+ throw registerFailure(response);
5386
+ }
5387
+ return { accepted: response.status === HTTP_ACCEPTED, body: response.data };
5388
+ },
5389
+ verifyEmail: (token) => verifyAndLogin({ token }),
5390
+ setNewPassword: (token, newPassword) => verifyAndLogin({ token, newPassword }),
5391
+ resendVerification: (email, verifyUrlTemplate) => verifyEmailClient.resendVerification(email, verifyUrlTemplate)
5392
+ };
5393
+ }
5394
+ function RegisterCheckEmail({
5395
+ labels,
5396
+ styles: styles3,
5397
+ footer,
5398
+ testIdPrefix
5399
+ }) {
5400
+ const headingRef = react.useRef(null);
5401
+ useFocusOnMount(headingRef);
5402
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
5403
+ reactNative.View,
5404
+ {
5405
+ accessibilityLiveRegion: "polite",
5406
+ style: styles3.card,
5407
+ testID: withTestIdPrefix(RegisterTestIds.checkEmail, testIdPrefix),
5408
+ children: [
5409
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ref: headingRef, accessible: true, focusable: true, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.checkEmailTitle }) }),
5410
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.checkEmailBody }),
5411
+ footer
5412
+ ]
5413
+ }
5414
+ ) });
5415
+ }
5416
+ function SharedRegisterForm({
5417
+ onSuccess,
5418
+ onAccepted,
5419
+ ...formProps
5420
+ }) {
5421
+ const { footer, labels: labelsProp, testIdPrefix, theme: themeProp } = formProps;
5422
+ const styles3 = useAuthStyles(useAuthTheme(themeProp));
5423
+ const labels = react.useMemo(
5424
+ () => ({ ...DEFAULT_REGISTER_LABELS, ...labelsProp }),
5425
+ [labelsProp]
5426
+ );
5427
+ const [accepted, setAccepted] = react.useState(false);
5428
+ const handleResult = react.useCallback(
5429
+ (result) => {
5430
+ if (!isRegisterAccepted(result)) {
5431
+ onSuccess(result);
5432
+ return;
5433
+ }
5434
+ setAccepted(true);
5435
+ onAccepted?.(result);
5436
+ },
5437
+ [onAccepted, onSuccess]
5438
+ );
5439
+ if (accepted) {
5440
+ return /* @__PURE__ */ jsxRuntime.jsx(RegisterCheckEmail, { footer, labels, styles: styles3, testIdPrefix });
5441
+ }
5442
+ return /* @__PURE__ */ jsxRuntime.jsx(RegisterFormCore, { ...formProps, sharedRegistration: true, onSuccess: handleResult });
5443
+ }
5444
+
4993
5445
  Object.defineProperty(exports, "BffAuthClient", {
4994
5446
  enumerable: true,
4995
5447
  get: function () { return authClient.BffAuthClient; }
@@ -5024,6 +5476,8 @@ exports.DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS = DEFAULT_PREFERRED_METHOD_SETT
5024
5476
  exports.DEFAULT_REGISTER_LABELS = DEFAULT_REGISTER_LABELS;
5025
5477
  exports.DEFAULT_RESET_PASSWORD_LABELS = DEFAULT_RESET_PASSWORD_LABELS;
5026
5478
  exports.DEFAULT_VERIFY_EMAIL_LABELS = DEFAULT_VERIFY_EMAIL_LABELS;
5479
+ exports.DEFAULT_VERIFY_NEW_PASSWORD_LABELS = DEFAULT_VERIFY_NEW_PASSWORD_LABELS;
5480
+ exports.DEFAULT_VERIFY_SIGN_IN_LABELS = DEFAULT_VERIFY_SIGN_IN_LABELS;
5027
5481
  exports.DEVICE_PIN_ALLOWED_DIGITS = DEVICE_PIN_ALLOWED_DIGITS;
5028
5482
  exports.DEVICE_PIN_DEFAULT_DIGITS = DEVICE_PIN_DEFAULT_DIGITS;
5029
5483
  exports.DemoCredentialsHint = DemoCredentialsHint;
@@ -5052,12 +5506,15 @@ exports.PinForm = PinForm;
5052
5506
  exports.PreferredMethodHint = PreferredMethodHint;
5053
5507
  exports.PreferredMethodSettingsCard = PreferredMethodSettingsCard;
5054
5508
  exports.PrefillIntent = PrefillIntent;
5509
+ exports.REGISTER_ENDPOINT = REGISTER_ENDPOINT;
5055
5510
  exports.RESEND_VERIFICATION_ENDPOINT = RESEND_VERIFICATION_ENDPOINT;
5056
5511
  exports.RegisterErrorCode = RegisterErrorCode;
5057
5512
  exports.RegisterForm = RegisterForm;
5058
5513
  exports.RegisterTestIds = RegisterTestIds;
5059
5514
  exports.ResetPasswordError = ResetPasswordError;
5060
5515
  exports.ResetPasswordForm = ResetPasswordForm;
5516
+ exports.SharedRegisterForm = SharedRegisterForm;
5517
+ exports.VERIFY_AND_LOGIN_ENDPOINT = VERIFY_AND_LOGIN_ENDPOINT;
5061
5518
  exports.VERIFY_EMAIL_ENDPOINT = VERIFY_EMAIL_ENDPOINT;
5062
5519
  exports.VERIFY_TOKEN_PLACEHOLDER = VERIFY_TOKEN_PLACEHOLDER;
5063
5520
  exports.VerifyEmailErrorCode = VerifyEmailErrorCode;
@@ -5071,10 +5528,12 @@ exports.createBffAuthClient = createBffAuthClient;
5071
5528
  exports.createBffChangePasswordClient = createBffChangePasswordClient;
5072
5529
  exports.createBffVerifyEmailClient = createBffVerifyEmailClient;
5073
5530
  exports.createPreferencesClient = createPreferencesClient;
5531
+ exports.createSharedRegistrationClient = createSharedRegistrationClient;
5074
5532
  exports.defaultAuthTheme = defaultAuthTheme;
5075
5533
  exports.deriveUsernameFromEmail = deriveUsernameFromEmail;
5076
5534
  exports.isAllowedPinDigits = isAllowedPinDigits;
5077
5535
  exports.isPasswordValid = isPasswordValid;
5536
+ exports.isRegisterAccepted = isRegisterAccepted;
5078
5537
  exports.isRegisterPasswordStrong = isRegisterPasswordStrong;
5079
5538
  exports.isValidForgotPasswordEmail = isValidForgotPasswordEmail;
5080
5539
  exports.performBffLogout = performBffLogout;