@dloizides/auth-web 1.21.0 → 1.22.1

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
@@ -354,6 +354,31 @@ var DEFAULT_REGISTER_LABELS = {
354
354
  }
355
355
  };
356
356
 
357
+ // src/components/labels/verifyEmailLabels.ts
358
+ var DEFAULT_VERIFY_EMAIL_LABELS = {
359
+ loadingTitle: "Verifying your email...",
360
+ loadingHint: "Please wait while we verify your address.",
361
+ successTitle: "Your email is verified",
362
+ successBody: "Thanks for confirming your email address.",
363
+ successContinue: "Continue",
364
+ successContinueHint: "Go to the app",
365
+ errorTitle: "We couldn't verify your email",
366
+ errorInvalid: "This verification link is invalid. Request a new one.",
367
+ errorExpired: "This verification link has expired. Request a new one.",
368
+ errorUsed: "This link has already been used.",
369
+ errorGeneric: "Verification failed. Please try again later.",
370
+ missingToken: "This verification link is missing a token.",
371
+ resendCta: "Send a new verification email",
372
+ resendCtaHint: "Show the resend verification email form",
373
+ resendEmailLabel: "Email",
374
+ resendEmailHint: "The address to send a new verification link to",
375
+ resendEmailPlaceholder: "you@example.com",
376
+ resendMissingEmail: "Enter your email address.",
377
+ resendSubmit: "Send link",
378
+ resendSubmitHint: "Sends a new verification email",
379
+ resendConfirmation: "If that address has an account, a new verification link is on its way."
380
+ };
381
+
357
382
  // src/components/testIds.ts
358
383
  var AuthTestIds = {
359
384
  loginForm: "auth-login-form",
@@ -444,7 +469,17 @@ var AuthTestIds = {
444
469
  demoCredentialsPassword: "auth-demo-credentials-password",
445
470
  demoCredentialsUseButton: "auth-demo-credentials-use",
446
471
  // The collapsed disclosure trigger (`disclosure` variant only).
447
- demoCredentialsToggle: "auth-demo-credentials-toggle"
472
+ demoCredentialsToggle: "auth-demo-credentials-toggle",
473
+ verifyEmailScreen: "auth-verify-email",
474
+ verifyEmailLoading: "auth-verify-email-loading",
475
+ verifyEmailSuccess: "auth-verify-email-success",
476
+ verifyEmailContinue: "auth-verify-email-continue",
477
+ verifyEmailError: "auth-verify-email-error",
478
+ verifyEmailResendCta: "auth-verify-email-resend-cta",
479
+ verifyEmailResendForm: "auth-verify-email-resend-form",
480
+ verifyEmailResendEmail: "auth-verify-email-resend-email",
481
+ verifyEmailResendSubmit: "auth-verify-email-resend-submit",
482
+ verifyEmailResendConfirmation: "auth-verify-email-resend-confirmation"
448
483
  };
449
484
  function withTestIdPrefix(baseId, prefix) {
450
485
  return prefix === void 0 || prefix === "" ? baseId : `${prefix}-${baseId}`;
@@ -541,6 +576,12 @@ function useAuthStyles(theme) {
541
576
  marginTop: spacing.xs,
542
577
  color: colors.danger
543
578
  },
579
+ errorBody: {
580
+ fontSize: typography.body,
581
+ marginTop: spacing.xs,
582
+ marginBottom: spacing.md,
583
+ color: colors.danger
584
+ },
544
585
  successText: {
545
586
  fontSize: typography.body,
546
587
  lineHeight: typography.body * 1.4,
@@ -1316,19 +1357,19 @@ function useResetMutation(client, callbacks) {
1316
1357
  }
1317
1358
  function runSubmit(args) {
1318
1359
  args.setErrorKey(null);
1319
- const failure = preflight({
1360
+ const failure2 = preflight({
1320
1361
  newPassword: args.newPassword,
1321
1362
  confirm: args.confirmPassword,
1322
1363
  token: args.token
1323
1364
  });
1324
- if (failure === null) {
1365
+ if (failure2 === null) {
1325
1366
  args.mutate({ token: args.token, newPassword: args.newPassword });
1326
1367
  return;
1327
1368
  }
1328
- if (failure === "tokenInvalid" /* TokenInvalid */) {
1369
+ if (failure2 === "tokenInvalid" /* TokenInvalid */) {
1329
1370
  args.setHasInvalidToken(true);
1330
1371
  }
1331
- args.setErrorKey(failure);
1372
+ args.setErrorKey(failure2);
1332
1373
  }
1333
1374
  function useFormState() {
1334
1375
  const [newPassword, setNewPassword] = react.useState("");
@@ -4325,15 +4366,15 @@ function typedFailureOf(error) {
4325
4366
  }
4326
4367
  return { status: hasStatus ? status : null, errorCode: hasCode ? errorCode : null };
4327
4368
  }
4328
- function mapTypedFailure(failure) {
4329
- const byCode = failure.errorCode === null ? void 0 : BODY_ERROR_CODES[failure.errorCode];
4369
+ function mapTypedFailure(failure2) {
4370
+ const byCode = failure2.errorCode === null ? void 0 : BODY_ERROR_CODES[failure2.errorCode];
4330
4371
  if (byCode !== void 0) {
4331
4372
  return byCode;
4332
4373
  }
4333
- if (failure.status === HTTP_TOO_MANY_REQUESTS) {
4374
+ if (failure2.status === HTTP_TOO_MANY_REQUESTS) {
4334
4375
  return "rateLimited" /* RateLimited */;
4335
4376
  }
4336
- const isServerError = failure.status !== null && failure.status >= HTTP_SERVER_ERROR_MIN;
4377
+ const isServerError = failure2.status !== null && failure2.status >= HTTP_SERVER_ERROR_MIN;
4337
4378
  return isServerError ? "failed" /* Failed */ : null;
4338
4379
  }
4339
4380
  function messageOf(error) {
@@ -4343,8 +4384,8 @@ function messageOf(error) {
4343
4384
  return typeof error === "string" ? error : "";
4344
4385
  }
4345
4386
  function mapRegisterErrorCode(error) {
4346
- const failure = typedFailureOf(error);
4347
- const typed = failure === null ? null : mapTypedFailure(failure);
4387
+ const failure2 = typedFailureOf(error);
4388
+ const typed = failure2 === null ? null : mapTypedFailure(failure2);
4348
4389
  if (typed !== null) {
4349
4390
  return typed;
4350
4391
  }
@@ -4638,6 +4679,360 @@ function createBffChangePasswordClient(options = {}) {
4638
4679
  }
4639
4680
  };
4640
4681
  }
4682
+ function useFocusOnMount(ref) {
4683
+ react.useEffect(() => {
4684
+ ref.current?.focus();
4685
+ }, [ref]);
4686
+ }
4687
+ function useResendVerification({ client, verifyUrlTemplate }) {
4688
+ const [email, setEmail] = react.useState("");
4689
+ const [missingEmail, setMissingEmail] = react.useState(false);
4690
+ const [submitting, setSubmitting] = react.useState(false);
4691
+ const [confirmed, setConfirmed] = react.useState(false);
4692
+ const submit = react.useCallback(async () => {
4693
+ const trimmed = email.trim();
4694
+ if (trimmed === "") {
4695
+ setMissingEmail(true);
4696
+ return;
4697
+ }
4698
+ setMissingEmail(false);
4699
+ setSubmitting(true);
4700
+ await client.resendVerification(trimmed, verifyUrlTemplate);
4701
+ setSubmitting(false);
4702
+ setConfirmed(true);
4703
+ }, [client, email, verifyUrlTemplate]);
4704
+ return { email, setEmail, missingEmail, submitting, confirmed, submit };
4705
+ }
4706
+ function ResendConfirmation({ style, testID, text }) {
4707
+ const ref = react.useRef(null);
4708
+ useFocusOnMount(ref);
4709
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ref, accessible: true, accessibilityLiveRegion: "polite", focusable: true, testID, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style, children: text }) });
4710
+ }
4711
+ function VerifyEmailResendForm({
4712
+ client,
4713
+ labels,
4714
+ styles: styles3,
4715
+ theme,
4716
+ verifyUrlTemplate,
4717
+ testIdPrefix
4718
+ }) {
4719
+ const resend = useResendVerification({ client, verifyUrlTemplate });
4720
+ const id = (base) => withTestIdPrefix(base, testIdPrefix);
4721
+ if (resend.confirmed) {
4722
+ return /* @__PURE__ */ jsxRuntime.jsx(ResendConfirmation, { style: styles3.successText, testID: id(AuthTestIds.verifyEmailResendConfirmation), text: labels.resendConfirmation });
4723
+ }
4724
+ const submit = () => {
4725
+ void resend.submit();
4726
+ };
4727
+ const buttonStyle = resend.submitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
4728
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailResendForm), children: [
4729
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
4730
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.resendEmailLabel }),
4731
+ /* @__PURE__ */ jsxRuntime.jsx(
4732
+ reactNative.TextInput,
4733
+ {
4734
+ accessibilityHint: labels.resendEmailHint,
4735
+ accessibilityLabel: labels.resendEmailLabel,
4736
+ autoCapitalize: "none",
4737
+ autoComplete: "email",
4738
+ autoCorrect: false,
4739
+ autoFocus: true,
4740
+ editable: !resend.submitting,
4741
+ keyboardType: "email-address",
4742
+ placeholder: labels.resendEmailPlaceholder,
4743
+ placeholderTextColor: theme.colors.textSecondary,
4744
+ style: styles3.input,
4745
+ testID: id(AuthTestIds.verifyEmailResendEmail),
4746
+ value: resend.email,
4747
+ onChangeText: resend.setEmail
4748
+ }
4749
+ )
4750
+ ] }),
4751
+ resend.missingEmail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: labels.resendMissingEmail }) : null,
4752
+ /* @__PURE__ */ jsxRuntime.jsx(
4753
+ reactNative.TouchableOpacity,
4754
+ {
4755
+ accessibilityHint: labels.resendSubmitHint,
4756
+ accessibilityLabel: labels.resendSubmit,
4757
+ accessibilityRole: "button",
4758
+ disabled: resend.submitting,
4759
+ style: buttonStyle,
4760
+ testID: id(AuthTestIds.verifyEmailResendSubmit),
4761
+ onPress: submit,
4762
+ children: resend.submitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.resendSubmit })
4763
+ }
4764
+ )
4765
+ ] });
4766
+ }
4767
+
4768
+ // src/verify/VerifyEmailErrorCode.ts
4769
+ var VerifyEmailErrorCode = /* @__PURE__ */ ((VerifyEmailErrorCode2) => {
4770
+ VerifyEmailErrorCode2["TokenInvalid"] = "TOKEN_INVALID";
4771
+ VerifyEmailErrorCode2["TokenExpired"] = "TOKEN_EXPIRED";
4772
+ VerifyEmailErrorCode2["TokenUsed"] = "TOKEN_USED";
4773
+ VerifyEmailErrorCode2["KeycloakUpdateFailed"] = "KEYCLOAK_UPDATE_FAILED";
4774
+ VerifyEmailErrorCode2["MissingToken"] = "MISSING_TOKEN";
4775
+ VerifyEmailErrorCode2["Generic"] = "GENERIC";
4776
+ return VerifyEmailErrorCode2;
4777
+ })(VerifyEmailErrorCode || {});
4778
+
4779
+ // src/verify/VerifyEmailPhase.ts
4780
+ var VerifyEmailPhase = /* @__PURE__ */ ((VerifyEmailPhase2) => {
4781
+ VerifyEmailPhase2["Loading"] = "loading";
4782
+ VerifyEmailPhase2["Success"] = "success";
4783
+ VerifyEmailPhase2["Failure"] = "failure";
4784
+ return VerifyEmailPhase2;
4785
+ })(VerifyEmailPhase || {});
4786
+
4787
+ // src/verify/useVerifyEmail.ts
4788
+ var LOADING = {
4789
+ phase: "loading" /* Loading */,
4790
+ errorCode: "GENERIC" /* Generic */
4791
+ };
4792
+ var SUCCESS = {
4793
+ phase: "success" /* Success */,
4794
+ errorCode: "GENERIC" /* Generic */
4795
+ };
4796
+ var REJECTED = { success: false, errorCode: "GENERIC" /* Generic */ };
4797
+ function failure(errorCode) {
4798
+ return { phase: "failure" /* Failure */, errorCode };
4799
+ }
4800
+ function useVerifyEmail({ client, token, onVerified, onFailed }) {
4801
+ const [state, setState] = react.useState(LOADING);
4802
+ const latest = react.useRef({ client, onVerified, onFailed });
4803
+ latest.current = { client, onVerified, onFailed };
4804
+ react.useEffect(() => {
4805
+ if (token === "") {
4806
+ setState(failure("MISSING_TOKEN" /* MissingToken */));
4807
+ latest.current.onFailed?.("MISSING_TOKEN" /* MissingToken */);
4808
+ return void 0;
4809
+ }
4810
+ let active = true;
4811
+ setState(LOADING);
4812
+ const settle = (result) => {
4813
+ if (!active) {
4814
+ return;
4815
+ }
4816
+ if (result.success) {
4817
+ setState(SUCCESS);
4818
+ latest.current.onVerified?.();
4819
+ return;
4820
+ }
4821
+ setState(failure(result.errorCode));
4822
+ latest.current.onFailed?.(result.errorCode);
4823
+ };
4824
+ void latest.current.client.verifyEmail(token).catch(() => REJECTED).then(settle);
4825
+ return () => {
4826
+ active = false;
4827
+ };
4828
+ }, [token]);
4829
+ return state;
4830
+ }
4831
+
4832
+ // src/verify/verifyEmailErrorText.ts
4833
+ function verifyEmailErrorText(code, labels) {
4834
+ if (code === "TOKEN_INVALID" /* TokenInvalid */) {
4835
+ return labels.errorInvalid;
4836
+ }
4837
+ if (code === "TOKEN_EXPIRED" /* TokenExpired */) {
4838
+ return labels.errorExpired;
4839
+ }
4840
+ if (code === "TOKEN_USED" /* TokenUsed */) {
4841
+ return labels.errorUsed;
4842
+ }
4843
+ if (code === "MISSING_TOKEN" /* MissingToken */) {
4844
+ return labels.missingToken;
4845
+ }
4846
+ return labels.errorGeneric;
4847
+ }
4848
+ function ResendCta({ label, hint, style, textStyle, testID, onPress }) {
4849
+ const ref = react.useRef(null);
4850
+ useFocusOnMount(ref);
4851
+ return /* @__PURE__ */ jsxRuntime.jsx(
4852
+ reactNative.TouchableOpacity,
4853
+ {
4854
+ ref,
4855
+ accessibilityHint: hint,
4856
+ accessibilityLabel: label,
4857
+ accessibilityRole: "button",
4858
+ style,
4859
+ testID,
4860
+ onPress,
4861
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: textStyle, children: label })
4862
+ }
4863
+ );
4864
+ }
4865
+ function VerifyEmailScreen({
4866
+ client,
4867
+ token,
4868
+ onContinue,
4869
+ theme: themeProp,
4870
+ labels: labelsProp,
4871
+ verifyUrlTemplate,
4872
+ onVerified,
4873
+ onFailed,
4874
+ testIdPrefix
4875
+ }) {
4876
+ const theme = useAuthTheme(themeProp);
4877
+ const styles3 = useAuthStyles(theme);
4878
+ const labels = react.useMemo(
4879
+ () => ({ ...DEFAULT_VERIFY_EMAIL_LABELS, ...labelsProp }),
4880
+ [labelsProp]
4881
+ );
4882
+ const { phase, errorCode } = useVerifyEmail({ client, token, onVerified, onFailed });
4883
+ const [resendOpen, setResendOpen] = react.useState(false);
4884
+ const openResend = react.useCallback(() => setResendOpen(true), []);
4885
+ const id = (base) => withTestIdPrefix(base, testIdPrefix);
4886
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, testID: id(AuthTestIds.verifyEmailScreen), children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, children: [
4887
+ phase === "loading" /* Loading */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailLoading), children: [
4888
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.primary, size: "large" }),
4889
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.loadingTitle }),
4890
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.loadingHint })
4891
+ ] }) : null,
4892
+ phase === "success" /* Success */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailSuccess), children: [
4893
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.successTitle }),
4894
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.successBody }),
4895
+ /* @__PURE__ */ jsxRuntime.jsx(
4896
+ reactNative.TouchableOpacity,
4897
+ {
4898
+ accessibilityHint: labels.successContinueHint,
4899
+ accessibilityLabel: labels.successContinue,
4900
+ accessibilityRole: "button",
4901
+ style: styles3.primaryButton,
4902
+ testID: id(AuthTestIds.verifyEmailContinue),
4903
+ onPress: onContinue,
4904
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.successContinue })
4905
+ }
4906
+ )
4907
+ ] }) : null,
4908
+ phase === "failure" /* Failure */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailError), children: [
4909
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.errorTitle }),
4910
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: verifyEmailErrorText(errorCode, labels) }),
4911
+ resendOpen ? /* @__PURE__ */ jsxRuntime.jsx(
4912
+ VerifyEmailResendForm,
4913
+ {
4914
+ client,
4915
+ labels,
4916
+ styles: styles3,
4917
+ testIdPrefix,
4918
+ theme,
4919
+ verifyUrlTemplate
4920
+ }
4921
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
4922
+ ResendCta,
4923
+ {
4924
+ hint: labels.resendCtaHint,
4925
+ label: labels.resendCta,
4926
+ style: styles3.primaryButton,
4927
+ testID: id(AuthTestIds.verifyEmailResendCta),
4928
+ textStyle: styles3.primaryButtonText,
4929
+ onPress: openResend
4930
+ }
4931
+ )
4932
+ ] }) : null
4933
+ ] }) });
4934
+ }
4935
+ var VERIFY_EMAIL_ENDPOINT = "/bff/verify-email";
4936
+ var RESEND_VERIFICATION_ENDPOINT = "/bff/resend-verification";
4937
+ var CSRF_HEADER3 = "X-BFF-Csrf";
4938
+ var CSRF_HEADER_VALUE3 = "1";
4939
+ var JSON_CONTENT_TYPE3 = "application/json";
4940
+ var SERVER_ERROR_CODES2 = [
4941
+ "TOKEN_INVALID" /* TokenInvalid */,
4942
+ "TOKEN_EXPIRED" /* TokenExpired */,
4943
+ "TOKEN_USED" /* TokenUsed */,
4944
+ "KEYCLOAK_UPDATE_FAILED" /* KeycloakUpdateFailed */
4945
+ ];
4946
+ var GENERIC_FAILURE = { success: false, errorCode: "GENERIC" /* Generic */ };
4947
+ var INVALID_TOKEN = { success: false, errorCode: "TOKEN_INVALID" /* TokenInvalid */ };
4948
+ var HTTP_BAD_REQUEST3 = 400;
4949
+ var TOKEN_FIELD = "token";
4950
+ async function lazyFetchHttpClient3(request) {
4951
+ const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
4952
+ if (fetchImpl === void 0) {
4953
+ throw new Error("createBffVerifyEmailClient: fetch is not available in this environment");
4954
+ }
4955
+ return authClient.createFetchHttpClient(fetchImpl)(request);
4956
+ }
4957
+ function isServerErrorCode(value) {
4958
+ return typeof value === "string" && SERVER_ERROR_CODES2.includes(value);
4959
+ }
4960
+ function isRecord3(value) {
4961
+ return typeof value === "object" && value !== null;
4962
+ }
4963
+ function isTokenValidationRejection(status, body) {
4964
+ if (status !== HTTP_BAD_REQUEST3 || !isRecord3(body.errors)) {
4965
+ return false;
4966
+ }
4967
+ return Object.keys(body.errors).some((field2) => field2.toLowerCase() === TOKEN_FIELD);
4968
+ }
4969
+ function decodeVerifyResponse(status, body) {
4970
+ if (!isRecord3(body)) {
4971
+ return GENERIC_FAILURE;
4972
+ }
4973
+ if (body.success === true) {
4974
+ return { success: true };
4975
+ }
4976
+ if (isServerErrorCode(body.errorCode)) {
4977
+ return { success: false, errorCode: body.errorCode };
4978
+ }
4979
+ return isTokenValidationRejection(status, body) ? INVALID_TOKEN : GENERIC_FAILURE;
4980
+ }
4981
+ function createBffVerifyEmailClient(options = {}) {
4982
+ const http = options.http ?? lazyFetchHttpClient3;
4983
+ const baseUrl = options.baseUrl ?? "";
4984
+ const post = (path, body) => http({
4985
+ url: `${baseUrl}${path}`,
4986
+ method: "POST",
4987
+ headers: { "Content-Type": JSON_CONTENT_TYPE3, [CSRF_HEADER3]: CSRF_HEADER_VALUE3 },
4988
+ body: JSON.stringify(body),
4989
+ credentials: "include"
4990
+ });
4991
+ return {
4992
+ verifyEmail: async (token) => {
4993
+ try {
4994
+ const response = await post(VERIFY_EMAIL_ENDPOINT, { token });
4995
+ return decodeVerifyResponse(response.status, response.data);
4996
+ } catch {
4997
+ return GENERIC_FAILURE;
4998
+ }
4999
+ },
5000
+ resendVerification: async (email, verifyUrlTemplate) => {
5001
+ const body = verifyUrlTemplate === void 0 ? { email } : { email, verifyUrlTemplate };
5002
+ try {
5003
+ const response = await post(RESEND_VERIFICATION_ENDPOINT, body);
5004
+ return response.ok;
5005
+ } catch {
5006
+ return false;
5007
+ }
5008
+ }
5009
+ };
5010
+ }
5011
+
5012
+ // src/verify/verifyEmailUrl.ts
5013
+ var VERIFY_TOKEN_PLACEHOLDER = "{token}";
5014
+ var DEFAULT_VERIFY_PATH = "/verify-email";
5015
+ function readWindowOrigin() {
5016
+ if (typeof window === "undefined" || typeof window.location !== "object") {
5017
+ return null;
5018
+ }
5019
+ return typeof window.location.origin === "string" ? window.location.origin : null;
5020
+ }
5021
+ function nonEmpty(value) {
5022
+ return value !== void 0 && value !== "" ? value : null;
5023
+ }
5024
+ function buildVerifyUrlTemplate(options = {}) {
5025
+ const origin = nonEmpty(options.origin) ?? readWindowOrigin() ?? options.fallbackOrigin ?? "";
5026
+ const path = options.path ?? DEFAULT_VERIFY_PATH;
5027
+ return `${origin}${path}?token=${VERIFY_TOKEN_PLACEHOLDER}`;
5028
+ }
5029
+ function readVerifyToken(raw) {
5030
+ if (typeof raw === "string") {
5031
+ return raw;
5032
+ }
5033
+ const first = raw?.[0];
5034
+ return typeof first === "string" ? first : "";
5035
+ }
4641
5036
 
4642
5037
  Object.defineProperty(exports, "BffAuthClient", {
4643
5038
  enumerable: true,
@@ -4672,6 +5067,7 @@ exports.DEFAULT_PREFERRED_METHOD_HINT_LABELS = DEFAULT_PREFERRED_METHOD_HINT_LAB
4672
5067
  exports.DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS = DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS;
4673
5068
  exports.DEFAULT_REGISTER_LABELS = DEFAULT_REGISTER_LABELS;
4674
5069
  exports.DEFAULT_RESET_PASSWORD_LABELS = DEFAULT_RESET_PASSWORD_LABELS;
5070
+ exports.DEFAULT_VERIFY_EMAIL_LABELS = DEFAULT_VERIFY_EMAIL_LABELS;
4675
5071
  exports.DEVICE_PIN_ALLOWED_DIGITS = DEVICE_PIN_ALLOWED_DIGITS;
4676
5072
  exports.DEVICE_PIN_DEFAULT_DIGITS = DEVICE_PIN_DEFAULT_DIGITS;
4677
5073
  exports.DemoCredentialsHint = DemoCredentialsHint;
@@ -4700,16 +5096,24 @@ exports.PinForm = PinForm;
4700
5096
  exports.PreferredMethodHint = PreferredMethodHint;
4701
5097
  exports.PreferredMethodSettingsCard = PreferredMethodSettingsCard;
4702
5098
  exports.PrefillIntent = PrefillIntent;
5099
+ exports.RESEND_VERIFICATION_ENDPOINT = RESEND_VERIFICATION_ENDPOINT;
4703
5100
  exports.RegisterErrorCode = RegisterErrorCode;
4704
5101
  exports.RegisterForm = RegisterForm;
4705
5102
  exports.RegisterTestIds = RegisterTestIds;
4706
5103
  exports.ResetPasswordError = ResetPasswordError;
4707
5104
  exports.ResetPasswordForm = ResetPasswordForm;
5105
+ exports.VERIFY_EMAIL_ENDPOINT = VERIFY_EMAIL_ENDPOINT;
5106
+ exports.VERIFY_TOKEN_PLACEHOLDER = VERIFY_TOKEN_PLACEHOLDER;
5107
+ exports.VerifyEmailErrorCode = VerifyEmailErrorCode;
5108
+ exports.VerifyEmailPhase = VerifyEmailPhase;
5109
+ exports.VerifyEmailScreen = VerifyEmailScreen;
5110
+ exports.buildVerifyUrlTemplate = buildVerifyUrlTemplate;
4708
5111
  exports.cachePreferredMethod = cachePreferredMethod;
4709
5112
  exports.clearCachedPreferredMethod = clearCachedPreferredMethod;
4710
5113
  exports.collectUserRoles = collectUserRoles;
4711
5114
  exports.createBffAuthClient = createBffAuthClient;
4712
5115
  exports.createBffChangePasswordClient = createBffChangePasswordClient;
5116
+ exports.createBffVerifyEmailClient = createBffVerifyEmailClient;
4713
5117
  exports.createPreferencesClient = createPreferencesClient;
4714
5118
  exports.defaultAuthTheme = defaultAuthTheme;
4715
5119
  exports.deriveUsernameFromEmail = deriveUsernameFromEmail;
@@ -4721,6 +5125,7 @@ exports.performBffLogout = performBffLogout;
4721
5125
  exports.readCachedPreferredMethod = readCachedPreferredMethod;
4722
5126
  exports.readPasskeyError = readPasskeyError;
4723
5127
  exports.readPasskeyRegistered = readPasskeyRegistered;
5128
+ exports.readVerifyToken = readVerifyToken;
4724
5129
  exports.resolveAccessibleRoutes = resolveAccessibleRoutes;
4725
5130
  exports.resolveAccountList = resolveAccountList;
4726
5131
  exports.resolveDemoAccounts = resolveDemoAccounts;
@@ -4746,8 +5151,11 @@ exports.usePasskeyCeremony = usePasskeyCeremony;
4746
5151
  exports.usePinLogin = usePinLogin;
4747
5152
  exports.usePreferredMethodSetting = usePreferredMethodSetting;
4748
5153
  exports.useRegisterForm = useRegisterForm;
5154
+ exports.useResendVerification = useResendVerification;
4749
5155
  exports.useResetPasswordForm = useResetPasswordForm;
5156
+ exports.useVerifyEmail = useVerifyEmail;
4750
5157
  exports.validatePasswordPolicy = validatePasswordPolicy;
5158
+ exports.verifyEmailErrorText = verifyEmailErrorText;
4751
5159
  exports.withTestIdPrefix = withTestIdPrefix;
4752
5160
  //# sourceMappingURL=index.js.map
4753
5161
  //# sourceMappingURL=index.js.map