@reachfive/identity-ui 1.26.0 → 1.26.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reachfive/identity-ui",
3
- "version": "1.26.0",
3
+ "version": "1.26.1",
4
4
  "description": "ReachFive Identity Web UI SDK",
5
5
  "author": "ReachFive",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @reachfive/identity-ui - v1.26.0
3
- * Compiled Tue, 09 Apr 2024 15:08:41 UTC
2
+ * @reachfive/identity-ui - v1.26.1
3
+ * Compiled Fri, 19 Apr 2024 13:15:48 UTC
4
4
  *
5
5
  * Copyright (c) ReachFive.
6
6
  *
@@ -367,6 +367,44 @@ type LoginViewProps = {
367
367
  socialProviders?: string[];
368
368
  };
369
369
 
370
+ interface LoginWithWebAuthnViewProps {
371
+ /**
372
+ * @deprecated
373
+ */
374
+ acceptTos?: boolean;
375
+ /**
376
+ * Boolean that specifies whether signup is enabled.
377
+ *
378
+ * @default true
379
+ */
380
+ allowSignup?: boolean;
381
+ /**
382
+ * List of authentication options
383
+ */
384
+ auth?: AuthOptions;
385
+ /**
386
+ * Whether the signup form fields' labels are displayed on the login view.
387
+ *
388
+ * @default false
389
+ */
390
+ showLabels?: boolean;
391
+ /**
392
+ * Lists the available social providers. This is an array of strings.
393
+ * Tip: If you pass an empty array, social providers will not be displayed.
394
+ */
395
+ socialProviders?: string[];
396
+ }
397
+
398
+ interface LoginWithPasswordViewProps {
399
+ allowForgotPassword?: boolean;
400
+ auth?: AuthOptions;
401
+ canShowPassword?: boolean;
402
+ recaptcha_enabled?: boolean;
403
+ recaptcha_site_key?: string;
404
+ showLabels?: boolean;
405
+ showRememberMe?: boolean;
406
+ }
407
+
370
408
  interface PasswordSignupFormProps {
371
409
  auth?: AuthOptions;
372
410
  beforeSignup?: <T>(param: T) => T;
@@ -423,6 +461,12 @@ interface SignupWithWebAuthnViewProps {
423
461
  userAgreement?: string;
424
462
  }
425
463
 
464
+ /**
465
+ * The widget’s initial screen.
466
+ * @enum {('login' | 'login-with-web-authn' | 'signup' | 'forgot-password')}
467
+ */
468
+ type InitialScreen = 'login' | 'login-with-web-authn' | 'signup' | 'forgot-password';
469
+
426
470
  interface SignupViewProps extends SignupWithPasswordViewProps, SignupWithWebAuthnViewProps {
427
471
  /**
428
472
  * Boolean that specifies whether login is enabled.
@@ -430,6 +474,13 @@ interface SignupViewProps extends SignupWithPasswordViewProps, SignupWithWebAuth
430
474
  * @default true
431
475
  */
432
476
  allowLogin?: boolean;
477
+ initialScreen?: InitialScreen;
478
+ /**
479
+ * Boolean that specifies whether biometric login is enabled.
480
+ *
481
+ * @default false
482
+ */
483
+ allowWebAuthnLogin?: boolean;
433
484
  /**
434
485
  * Boolean that specifies whether biometric signup is enabled.
435
486
  *
@@ -463,6 +514,13 @@ interface ForgotPasswordViewProps {
463
514
  * @default false
464
515
  */
465
516
  showLabels?: boolean;
517
+ initialScreen?: InitialScreen;
518
+ /**
519
+ * Boolean that specifies whether biometric login is enabled.
520
+ *
521
+ * @default false
522
+ */
523
+ allowWebAuthnLogin?: boolean;
466
524
  /**
467
525
  * Boolean that specifies whether reCAPTCHA is enabled or not.
468
526
  */
@@ -485,9 +543,18 @@ interface ForgotPasswordViewProps {
485
543
  }
486
544
  interface ForgotPasswordSuccessViewProps {
487
545
  allowLogin?: boolean;
546
+ initialScreen?: InitialScreen;
547
+ allowWebAuthnLogin?: boolean;
488
548
  }
489
549
 
490
550
  interface QuickLoginViewProps {
551
+ initialScreen?: InitialScreen;
552
+ /**
553
+ * Boolean that specifies whether biometric login is enabled.
554
+ *
555
+ * @default false
556
+ */
557
+ allowWebAuthnLogin?: boolean;
491
558
  /**
492
559
  * List of authentication options
493
560
  */
@@ -566,7 +633,7 @@ type VerificationCodeViewProps$3 = Prettify<Partial<StepUpHandlerResponse> & {
566
633
  type MfaStepUpProps = MainViewProps$5 & FaSelectionViewProps & VerificationCodeViewProps$3;
567
634
  type MfaStepUpWidgetProps = MfaStepUpProps;
568
635
 
569
- interface AuthWidgetProps extends LoginViewProps, SignupViewProps, SignupWithPasswordViewProps, SignupWithWebAuthnViewProps, ForgotPasswordViewProps, ForgotPasswordSuccessViewProps, QuickLoginViewProps, ReauthViewProps, Omit<FaSelectionViewProps, keyof FaSelectionViewState>, Omit<VerificationCodeViewProps$3, keyof VerificationCodeViewState> {
636
+ interface AuthWidgetProps extends LoginViewProps, LoginWithWebAuthnViewProps, LoginWithPasswordViewProps, SignupViewProps, SignupWithPasswordViewProps, SignupWithWebAuthnViewProps, ForgotPasswordViewProps, ForgotPasswordSuccessViewProps, QuickLoginViewProps, ReauthViewProps, Omit<FaSelectionViewProps, keyof FaSelectionViewState>, Omit<VerificationCodeViewProps$3, keyof VerificationCodeViewState> {
570
637
  /**
571
638
  * Boolean that specifies whether quick login is enabled.
572
639
  *
@@ -574,13 +641,15 @@ interface AuthWidgetProps extends LoginViewProps, SignupViewProps, SignupWithPas
574
641
  */
575
642
  allowQuickLogin?: boolean;
576
643
  /**
577
- * The widget’s initial screen.
578
- *
579
- * - if `allowLogin` is set to `true`, it defaults to `login`.
580
- * - if `allowLogin` is set to `false` and `allowSignup` is set to `true`, it defaults to `signup`.
644
+ * The widget’s initial screen if a value is provided, otherwise:
645
+ * - if `quickLogin` is set to `true`, it defaults to `quick-login`.
646
+ * - otherwise if the user is authenticated, it defaults to `reauth`.
647
+ * - otherwise if `allowLogin` is set to `true` and `allowWebAuthnLogin` is not set to `true`, it defaults to `login`.
648
+ * - otherwise if `allowLogin` is set to `true`, it defaults to `login-with-web-authn`.
649
+ * - otherwise if `allowSignup` is set to `true`, it defaults to `signup`.
581
650
  * - otherwise, defaults to `forgot-password`.
582
651
  */
583
- initialScreen?: 'login' | 'signup' | 'forgot-password';
652
+ initialScreen?: InitialScreen;
584
653
  }
585
654
 
586
655
  interface MainViewProps$4 {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @reachfive/identity-ui - v1.26.0
3
- * Compiled Tue, 09 Apr 2024 15:08:41 UTC
2
+ * @reachfive/identity-ui - v1.26.1
3
+ * Compiled Fri, 19 Apr 2024 13:15:48 UTC
4
4
  *
5
5
  * Copyright (c) ReachFive.
6
6
  *
@@ -46782,6 +46782,7 @@
46782
46782
  const unwrap = v !== null && typeof v === "object" ? v[rawProperty] : v;
46783
46783
  return unwrap !== null && unwrap !== void 0 && unwrap !== "" && !Number.isNaN(unwrap) && (Array.isArray(unwrap) ? unwrap.length > 0 : true);
46784
46784
  }
46785
+ const isCustomIdentifier = (identifier) => "customIdentifier" in identifier;
46785
46786
  const specializeIdentifier = (identifier) => isValidEmail(identifier) ? { email: identifier } : isValidNumber(identifier) ? { phoneNumber: identifier.replace(/\s+/g, "") } : { customIdentifier: identifier };
46786
46787
  function specializeIdentifierData(data) {
46787
46788
  if ("identifier" in data && typeof data.identifier === "string") {
@@ -47474,7 +47475,7 @@
47474
47475
  }, () => callback && callback(!this.state.hasErrors));
47475
47476
  }
47476
47477
  render() {
47477
- const { submitLabel, i18n, fieldValidationDebounce } = this.props;
47478
+ const { submitLabel, allowWebAuthnLogin, i18n, fieldValidationDebounce } = this.props;
47478
47479
  const { errorMessage, isLoading, fields } = this.state;
47479
47480
  return /* @__PURE__ */ React.createElement(Form, { noValidate: true, onSubmit: this.handleSubmit }, errorMessage && /* @__PURE__ */ React.createElement(Error$1, null, errorMessage), this.allFields.map((field) => !field.staticContent ? field.render({
47480
47481
  state: fields[field.key],
@@ -47485,7 +47486,7 @@
47485
47486
  }, fieldValidationDebounce)(this);
47486
47487
  },
47487
47488
  ...this.props.sharedProps
47488
- }) : field.staticContent), /* @__PURE__ */ React.createElement(PrimaryButton, { disabled: isLoading }, i18n(submitLabel)));
47489
+ }) : field.staticContent), !allowWebAuthnLogin && /* @__PURE__ */ React.createElement(PrimaryButton, { disabled: isLoading }, i18n(submitLabel)), allowWebAuthnLogin && this.props.webAuthnButtons(isLoading, this.handleClick));
47489
47490
  }
47490
47491
  }
47491
47492
  __publicField$8(FormComponent, "defaultProps", {
@@ -56195,7 +56196,7 @@
56195
56196
  }
56196
56197
  });
56197
56198
 
56198
- const ForgotPasswordWrapper = styled.div`
56199
+ const ForgotPasswordWrapper$1 = styled.div`
56199
56200
  margin-bottom: ${(props) => props.theme.spacing}px;
56200
56201
  text-align: right;
56201
56202
  ${(props) => props.floating && `
@@ -56236,7 +56237,7 @@
56236
56237
  canShowPassword
56237
56238
  }),
56238
56239
  showForgotPassword && {
56239
- staticContent: /* @__PURE__ */ React.createElement(ForgotPasswordWrapper, { key: "forgot-password", floating: showRememberMe }, /* @__PURE__ */ React.createElement(Link, { target: "forgot-password" }, i18n("login.forgotPasswordLink")))
56240
+ staticContent: /* @__PURE__ */ React.createElement(ForgotPasswordWrapper$1, { key: "forgot-password", floating: showRememberMe }, /* @__PURE__ */ React.createElement(Link, { target: "forgot-password" }, i18n("login.forgotPasswordLink")))
56240
56241
  },
56241
56242
  showRememberMe && checkboxField({
56242
56243
  key: "auth.persistent",
@@ -56306,6 +56307,290 @@
56306
56307
  ), allowSignup && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement("span", null, i18n("login.signupLinkPrefix")), "\xA0", /* @__PURE__ */ React.createElement(Link, { target: "signup", controller }, i18n("login.signupLink"))));
56307
56308
  };
56308
56309
 
56310
+ var _path$3, _path2$1;
56311
+ function _extends$3() { _extends$3 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); }
56312
+ var SvgFingerprint = function SvgFingerprint(props) {
56313
+ return /*#__PURE__*/reactExports.createElement("svg", _extends$3({
56314
+ xmlns: "http://www.w3.org/2000/svg",
56315
+ fill: "currentColor",
56316
+ viewBox: "0 0 24 24"
56317
+ }, props), _path$3 || (_path$3 = /*#__PURE__*/reactExports.createElement("path", {
56318
+ fill: "none",
56319
+ d: "M0 0h24v24H0z"
56320
+ })), _path2$1 || (_path2$1 = /*#__PURE__*/reactExports.createElement("path", {
56321
+ d: "M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2a.506.506 0 0 1 .2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67a.49.49 0 0 1-.44.28M3.5 9.72a.499.499 0 0 1-.41-.79c.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25a.5.5 0 0 1-.12.7c-.23.16-.54.11-.7-.12a9.4 9.4 0 0 0-3.39-2.94c-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21m6.25 12.07a.47.47 0 0 1-.35-.15c-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39s-4.66 1.97-4.66 4.39c0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15m7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12M14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1a7.3 7.3 0 0 1-2.17-5.22c0-1.62 1.38-2.94 3.08-2.94s3.08 1.32 3.08 2.94c0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29a11.1 11.1 0 0 1-.73-3.96c0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38"
56322
+ })));
56323
+ };
56324
+
56325
+ var _path$2, _path2;
56326
+ function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
56327
+ var SvgKeyboard = function SvgKeyboard(props) {
56328
+ return /*#__PURE__*/reactExports.createElement("svg", _extends$2({
56329
+ xmlns: "http://www.w3.org/2000/svg",
56330
+ fill: "currentColor",
56331
+ viewBox: "0 0 24 24"
56332
+ }, props), _path$2 || (_path$2 = /*#__PURE__*/reactExports.createElement("path", {
56333
+ d: "M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m-9 3h2v2h-2zm0 3h2v2h-2zM8 8h2v2H8zm0 3h2v2H8zm-1 2H5v-2h2zm0-3H5V8h2zm9 7H8v-2h8zm0-4h-2v-2h2zm0-3h-2V8h2zm3 3h-2v-2h2zm0-3h-2V8h2z"
56334
+ })), _path2 || (_path2 = /*#__PURE__*/reactExports.createElement("path", {
56335
+ fill: "none",
56336
+ d: "M0 0h24v24H0zm0 0h24v24H0z"
56337
+ })));
56338
+ };
56339
+
56340
+ const iconStyle$1 = `
56341
+ width: 40px;
56342
+ height: 40px;
56343
+ `;
56344
+ const FingerPrintIcon = styled(SvgFingerprint)`${iconStyle$1}`;
56345
+ const KeyboardIcon = styled(SvgKeyboard)`${iconStyle$1}`;
56346
+ const PrimaryButtonWithIcon = styled(({
56347
+ type = "submit",
56348
+ disabled = false,
56349
+ text,
56350
+ children,
56351
+ className,
56352
+ ...props
56353
+ }) => {
56354
+ const theme = useTheme();
56355
+ return /* @__PURE__ */ React.createElement(
56356
+ Button,
56357
+ {
56358
+ type,
56359
+ disabled,
56360
+ ...props,
56361
+ className: classes(["r5-button-with-icon"], className),
56362
+ background: theme.backgroundColor,
56363
+ border: theme.backgroundColor,
56364
+ color: theme.primaryColor
56365
+ },
56366
+ children,
56367
+ text && /* @__PURE__ */ React.createElement("span", { className: "r5-button-text" }, text)
56368
+ );
56369
+ })`
56370
+ display: flex;
56371
+ align-items: center;
56372
+ justify-content: center;
56373
+
56374
+ .r5-button-text {
56375
+ margin-left: 10px;
56376
+ text-transform: uppercase;
56377
+ }
56378
+ `;
56379
+ const ButtonsSeparator = styled.div`
56380
+ text-align: center;
56381
+ color: ${(props) => props.theme.mutedTextColor}
56382
+ `;
56383
+ const WebAuthnLoginViewButtons = styled(({ disabled, onPasswordClick, className, ...props }) => {
56384
+ const i18n = useI18n();
56385
+ return /* @__PURE__ */ React.createElement("div", { className: classes(["r5-webauthn-login-buttons"], className) }, /* @__PURE__ */ React.createElement(
56386
+ PrimaryButtonWithIcon,
56387
+ {
56388
+ type: "submit",
56389
+ dataTestId: "webauthn-button",
56390
+ title: i18n("login.withBiometrics"),
56391
+ disabled,
56392
+ ...props
56393
+ },
56394
+ /* @__PURE__ */ React.createElement(FingerPrintIcon, null)
56395
+ ), /* @__PURE__ */ React.createElement(ButtonsSeparator, null, i18n("or")), /* @__PURE__ */ React.createElement(
56396
+ PrimaryButtonWithIcon,
56397
+ {
56398
+ dataTestId: "password-button",
56399
+ title: i18n("login.withPassword"),
56400
+ disabled,
56401
+ onClick: onPasswordClick
56402
+ },
56403
+ /* @__PURE__ */ React.createElement(KeyboardIcon, null)
56404
+ ));
56405
+ })`
56406
+ display: flex;
56407
+ align-items: center;
56408
+
56409
+ & > :not(:last-child) {
56410
+ margin-right: 20px;
56411
+ }
56412
+ `;
56413
+ const WebAuthnSignupViewButtons = styled(({ onBiometricClick, onPasswordClick, className }) => {
56414
+ const i18n = useI18n();
56415
+ return /* @__PURE__ */ React.createElement("div", { className: classes(["r5-webauthn-signup-buttons"], className) }, /* @__PURE__ */ React.createElement(
56416
+ PrimaryButtonWithIcon,
56417
+ {
56418
+ dataTestId: "webauthn-button",
56419
+ onClick: onBiometricClick,
56420
+ title: i18n("signup.withBiometrics"),
56421
+ text: i18n("biometrics")
56422
+ },
56423
+ /* @__PURE__ */ React.createElement(FingerPrintIcon, null)
56424
+ ), /* @__PURE__ */ React.createElement(Separator, { text: i18n("or") }), /* @__PURE__ */ React.createElement(
56425
+ PrimaryButtonWithIcon,
56426
+ {
56427
+ dataTestId: "password-button",
56428
+ onClick: onPasswordClick,
56429
+ title: i18n("signup.withPassword"),
56430
+ text: i18n("password")
56431
+ },
56432
+ /* @__PURE__ */ React.createElement(KeyboardIcon, null)
56433
+ ));
56434
+ })``;
56435
+
56436
+ const LoginWithWebAuthnForm = createForm({
56437
+ prefix: "r5-login-",
56438
+ fields({ showIdentifier = true, defaultIdentifier, config }) {
56439
+ return [
56440
+ identifierField(
56441
+ {
56442
+ defaultValue: defaultIdentifier,
56443
+ withPhoneNumber: showIdentifier && config.sms,
56444
+ required: true,
56445
+ autoComplete: "username webauthn"
56446
+ },
56447
+ config
56448
+ )
56449
+ ];
56450
+ },
56451
+ allowWebAuthnLogin: true
56452
+ });
56453
+ const LoginWithWebAuthnView = ({ acceptTos, allowSignup = true, auth, showLabels = false, socialProviders }) => {
56454
+ const coreClient = useReachfive();
56455
+ const { goTo } = useRouting();
56456
+ const i18n = useI18n();
56457
+ const session = useSession();
56458
+ const controller = new AbortController();
56459
+ const signal = controller.signal;
56460
+ React.useEffect(() => {
56461
+ coreClient.loginWithWebAuthn({
56462
+ conditionalMediation: "preferred",
56463
+ auth: {
56464
+ ...auth
56465
+ },
56466
+ signal
56467
+ }).catch(() => void 0);
56468
+ }, [coreClient, auth, signal]);
56469
+ const handleWebAuthnLogin = React.useCallback(
56470
+ (data) => {
56471
+ const { auth: dataAuth, ...identifier } = specializeIdentifierData(data);
56472
+ if (isCustomIdentifier(identifier)) {
56473
+ console.error("Custom identifier is not a valid WebAuthn identifier.");
56474
+ return Promise.reject(new Error("Custom identifier is not a valid WebAuthn identifier."));
56475
+ }
56476
+ return coreClient.loginWithWebAuthn({
56477
+ ...identifier,
56478
+ auth: {
56479
+ ...dataAuth,
56480
+ ...auth
56481
+ }
56482
+ });
56483
+ },
56484
+ [coreClient, auth]
56485
+ );
56486
+ const redirectToPasswordLoginView = reactExports.useCallback(
56487
+ (data) => {
56488
+ const username = "identifier" in data ? data.identifier : "email" in data ? data.email : "";
56489
+ goTo("login-with-password", { username });
56490
+ },
56491
+ [goTo]
56492
+ );
56493
+ const defaultIdentifier = session?.lastLoginType === "password" ? session.email : void 0;
56494
+ const webAuthnButtons = (disabled, handleClick) => /* @__PURE__ */ React.createElement(
56495
+ WebAuthnLoginViewButtons,
56496
+ {
56497
+ disabled,
56498
+ onPasswordClick: handleClick
56499
+ }
56500
+ );
56501
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, i18n("login.title")), socialProviders && socialProviders.length > 0 && /* @__PURE__ */ React.createElement(SocialButtons, { providers: socialProviders, auth, acceptTos }), socialProviders && socialProviders.length > 0 && /* @__PURE__ */ React.createElement(Separator, { text: i18n("or") }), /* @__PURE__ */ React.createElement(
56502
+ LoginWithWebAuthnForm,
56503
+ {
56504
+ showLabels,
56505
+ defaultIdentifier,
56506
+ handler: handleWebAuthnLogin,
56507
+ redirect: redirectToPasswordLoginView,
56508
+ webAuthnButtons
56509
+ }
56510
+ ), allowSignup && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement("span", null, i18n("login.signupLinkPrefix")), "\xA0", /* @__PURE__ */ React.createElement(Link, { controller, target: "signup" }, i18n("login.signupLink"))));
56511
+ };
56512
+
56513
+ const ForgotPasswordWrapper = styled.div`
56514
+ margin-bottom: ${(props) => props.theme.spacing}px;
56515
+ text-align: right;
56516
+ ${(props) => props.floating && `
56517
+ position: absolute;
56518
+ right: 0;
56519
+ `};
56520
+ `;
56521
+ const LoginWithPasswordForm = createForm({
56522
+ prefix: "r5-login-",
56523
+ fields({ username, showRememberMe, canShowPassword, showForgotPassword, i18n, config }) {
56524
+ return [
56525
+ config.sms ? identifierField({
56526
+ key: "identifier",
56527
+ defaultValue: username,
56528
+ withPhoneNumber: true,
56529
+ readOnly: true
56530
+ }, config) : identifierField({
56531
+ key: "identifier",
56532
+ defaultValue: username,
56533
+ withPhoneNumber: false,
56534
+ readOnly: true
56535
+ }, config),
56536
+ simplePasswordField({
56537
+ key: "password",
56538
+ label: "password",
56539
+ autoComplete: "current-password",
56540
+ canShowPassword
56541
+ }),
56542
+ showForgotPassword && {
56543
+ staticContent: /* @__PURE__ */ React.createElement(ForgotPasswordWrapper, { key: "forgot-password", floating: showRememberMe }, /* @__PURE__ */ React.createElement(Link, { target: "forgot-password" }, i18n("login.forgotPasswordLink")))
56544
+ },
56545
+ showRememberMe && checkboxField({
56546
+ key: "auth.persistent",
56547
+ label: "rememberMe",
56548
+ defaultValue: false
56549
+ })
56550
+ ];
56551
+ },
56552
+ submitLabel: "login.submitLabel"
56553
+ });
56554
+ const LoginWithPasswordView = ({
56555
+ allowForgotPassword = true,
56556
+ auth,
56557
+ canShowPassword,
56558
+ recaptcha_enabled = false,
56559
+ recaptcha_site_key,
56560
+ showLabels,
56561
+ showRememberMe
56562
+ }) => {
56563
+ const i18n = useI18n();
56564
+ const coreClient = useReachfive();
56565
+ const { goTo, params } = useRouting();
56566
+ const { username } = params;
56567
+ reactExports.useLayoutEffect(() => {
56568
+ importGoogleRecaptchaScript(recaptcha_site_key);
56569
+ }, [recaptcha_site_key]);
56570
+ const callback = (data) => {
56571
+ const { auth: dataAuth, ...specializedData } = specializeIdentifierData(data);
56572
+ return coreClient.loginWithPassword({
56573
+ ...specializedData,
56574
+ captchaToken: data.captchaToken,
56575
+ auth: {
56576
+ ...dataAuth,
56577
+ ...auth
56578
+ }
56579
+ }).then((res) => res?.stepUpToken ? goTo("fa-selection", { token: res.stepUpToken, amr: res.amr ?? [] }) : res);
56580
+ };
56581
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, i18n("login.title")), /* @__PURE__ */ React.createElement(
56582
+ LoginWithPasswordForm,
56583
+ {
56584
+ username,
56585
+ showLabels,
56586
+ showRememberMe,
56587
+ showForgotPassword: allowForgotPassword,
56588
+ canShowPassword,
56589
+ handler: (data) => ReCaptcha.handle(data, { recaptcha_enabled, recaptcha_site_key }, callback, "login")
56590
+ }
56591
+ ), /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: "login-with-web-authn" }, i18n("login.password.userAnotherIdentifier"))));
56592
+ };
56593
+
56309
56594
  const SelectField = (props) => {
56310
56595
  const {
56311
56596
  value = "",
@@ -66610,100 +66895,10 @@
66610
66895
  );
66611
66896
  };
66612
66897
 
66613
- var _path$3, _path2$1;
66614
- function _extends$3() { _extends$3 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); }
66615
- var SvgFingerprint = function SvgFingerprint(props) {
66616
- return /*#__PURE__*/reactExports.createElement("svg", _extends$3({
66617
- xmlns: "http://www.w3.org/2000/svg",
66618
- fill: "currentColor",
66619
- viewBox: "0 0 24 24"
66620
- }, props), _path$3 || (_path$3 = /*#__PURE__*/reactExports.createElement("path", {
66621
- fill: "none",
66622
- d: "M0 0h24v24H0z"
66623
- })), _path2$1 || (_path2$1 = /*#__PURE__*/reactExports.createElement("path", {
66624
- d: "M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2a.506.506 0 0 1 .2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67a.49.49 0 0 1-.44.28M3.5 9.72a.499.499 0 0 1-.41-.79c.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25a.5.5 0 0 1-.12.7c-.23.16-.54.11-.7-.12a9.4 9.4 0 0 0-3.39-2.94c-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21m6.25 12.07a.47.47 0 0 1-.35-.15c-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39s-4.66 1.97-4.66 4.39c0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15m7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12M14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1a7.3 7.3 0 0 1-2.17-5.22c0-1.62 1.38-2.94 3.08-2.94s3.08 1.32 3.08 2.94c0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29a11.1 11.1 0 0 1-.73-3.96c0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38"
66625
- })));
66626
- };
66627
-
66628
- var _path$2, _path2;
66629
- function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
66630
- var SvgKeyboard = function SvgKeyboard(props) {
66631
- return /*#__PURE__*/reactExports.createElement("svg", _extends$2({
66632
- xmlns: "http://www.w3.org/2000/svg",
66633
- fill: "currentColor",
66634
- viewBox: "0 0 24 24"
66635
- }, props), _path$2 || (_path$2 = /*#__PURE__*/reactExports.createElement("path", {
66636
- d: "M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m-9 3h2v2h-2zm0 3h2v2h-2zM8 8h2v2H8zm0 3h2v2H8zm-1 2H5v-2h2zm0-3H5V8h2zm9 7H8v-2h8zm0-4h-2v-2h2zm0-3h-2V8h2zm3 3h-2v-2h2zm0-3h-2V8h2z"
66637
- })), _path2 || (_path2 = /*#__PURE__*/reactExports.createElement("path", {
66638
- fill: "none",
66639
- d: "M0 0h24v24H0zm0 0h24v24H0z"
66640
- })));
66641
- };
66642
-
66643
- const iconStyle$1 = `
66644
- width: 40px;
66645
- height: 40px;
66646
- `;
66647
- const FingerPrintIcon = styled(SvgFingerprint)`${iconStyle$1}`;
66648
- const KeyboardIcon = styled(SvgKeyboard)`${iconStyle$1}`;
66649
- const PrimaryButtonWithIcon = styled(({
66650
- type = "submit",
66651
- disabled = false,
66652
- text,
66653
- children,
66654
- className,
66655
- ...props
66656
- }) => {
66657
- const theme = useTheme();
66658
- return /* @__PURE__ */ React.createElement(
66659
- Button,
66660
- {
66661
- type,
66662
- disabled,
66663
- ...props,
66664
- className: classes(["r5-button-with-icon"], className),
66665
- background: theme.backgroundColor,
66666
- border: theme.backgroundColor,
66667
- color: theme.primaryColor
66668
- },
66669
- children,
66670
- text && /* @__PURE__ */ React.createElement("span", { className: "r5-button-text" }, text)
66671
- );
66672
- })`
66673
- display: flex;
66674
- align-items: center;
66675
- justify-content: center;
66676
-
66677
- .r5-button-text {
66678
- margin-left: 10px;
66679
- text-transform: uppercase;
66680
- }
66681
- `;
66682
- const WebAuthnSignupViewButtons = styled(({ onBiometricClick, onPasswordClick, className }) => {
66683
- const i18n = useI18n();
66684
- return /* @__PURE__ */ React.createElement("div", { className: classes(["r5-webauthn-signup-buttons"], className) }, /* @__PURE__ */ React.createElement(
66685
- PrimaryButtonWithIcon,
66686
- {
66687
- dataTestId: "webauthn-button",
66688
- onClick: onBiometricClick,
66689
- title: i18n("signup.withBiometrics"),
66690
- text: i18n("biometrics")
66691
- },
66692
- /* @__PURE__ */ React.createElement(FingerPrintIcon, null)
66693
- ), /* @__PURE__ */ React.createElement(Separator, { text: i18n("or") }), /* @__PURE__ */ React.createElement(
66694
- PrimaryButtonWithIcon,
66695
- {
66696
- dataTestId: "password-button",
66697
- onClick: onPasswordClick,
66698
- title: i18n("signup.withPassword"),
66699
- text: i18n("password")
66700
- },
66701
- /* @__PURE__ */ React.createElement(KeyboardIcon, null)
66702
- ));
66703
- })``;
66704
-
66705
66898
  const SignupView = ({
66706
66899
  allowLogin = true,
66900
+ initialScreen,
66901
+ allowWebAuthnLogin = false,
66707
66902
  allowWebAuthnSignup = false,
66708
66903
  socialProviders,
66709
66904
  ...props
@@ -66716,7 +66911,7 @@
66716
66911
  onPasswordClick: () => goTo("signup-with-password"),
66717
66912
  onBiometricClick: () => goTo("signup-with-web-authn")
66718
66913
  }
66719
- ) : /* @__PURE__ */ React.createElement(PasswordSignupForm, { ...props }), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement("span", null, i18n("signup.loginLinkPrefix")), "\xA0", /* @__PURE__ */ React.createElement(Link, { target: "login" }, i18n("signup.loginLink"))));
66914
+ ) : /* @__PURE__ */ React.createElement(PasswordSignupForm, { ...props }), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement("span", null, i18n("signup.loginLinkPrefix")), "\xA0", /* @__PURE__ */ React.createElement(Link, { target: selectLogin(initialScreen, allowWebAuthnLogin) }, i18n("signup.loginLink"))));
66720
66915
  };
66721
66916
 
66722
66917
  const SignupWithPasswordView = (props) => {
@@ -66789,7 +66984,9 @@
66789
66984
  allowLogin = true,
66790
66985
  displaySafeErrorMessage = false,
66791
66986
  showLabels = false,
66987
+ allowWebAuthnLogin = false,
66792
66988
  recaptcha_enabled = false,
66989
+ initialScreen,
66793
66990
  recaptcha_site_key,
66794
66991
  redirectUrl,
66795
66992
  returnToAfterPasswordReset
@@ -66817,18 +67014,18 @@
66817
67014
  onSuccess: () => goTo("forgot-password-success"),
66818
67015
  skipError: displaySafeErrorMessage && skipError
66819
67016
  }
66820
- ), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: "login" }, i18n("forgotPassword.backToLoginLink"))));
67017
+ ), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: selectLogin(initialScreen, allowWebAuthnLogin) }, i18n("forgotPassword.backToLoginLink"))));
66821
67018
  };
66822
- const ForgotPasswordSuccessView = ({ allowLogin }) => {
67019
+ const ForgotPasswordSuccessView = ({ allowLogin, initialScreen, allowWebAuthnLogin }) => {
66823
67020
  const i18n = useI18n();
66824
- return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, i18n("forgotPassword.title")), /* @__PURE__ */ React.createElement(Info$1, null, i18n("forgotPassword.successMessage")), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: "login" }, i18n("back"))));
67021
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, i18n("forgotPassword.title")), /* @__PURE__ */ React.createElement(Info$1, null, i18n("forgotPassword.successMessage")), allowLogin && /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: selectLogin(initialScreen, allowWebAuthnLogin) }, i18n("back"))));
66825
67022
  };
66826
67023
 
66827
- const QuickLoginView = ({ auth, session }) => {
67024
+ const QuickLoginView = ({ initialScreen, allowWebAuthnLogin = false, auth, session }) => {
66828
67025
  const i18n = useI18n();
66829
67026
  if (!session)
66830
67027
  return null;
66831
- return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, session.name || session.email), /* @__PURE__ */ React.createElement(Intro, null, i18n("lastTimeYouLoggedInWith")), /* @__PURE__ */ React.createElement(SocialButtons, { providers: session.lastLoginType ? [session.lastLoginType] : [], auth }), /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: "login" }, i18n("notYourAccount"))));
67028
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Heading, null, session.name || session.email), /* @__PURE__ */ React.createElement(Intro, null, i18n("lastTimeYouLoggedInWith")), /* @__PURE__ */ React.createElement(SocialButtons, { providers: session.lastLoginType ? [session.lastLoginType] : [], auth }), /* @__PURE__ */ React.createElement(Alternative, null, /* @__PURE__ */ React.createElement(Link, { target: selectLogin(initialScreen, allowWebAuthnLogin) }, i18n("notYourAccount"))));
66832
67029
  };
66833
67030
 
66834
67031
  const ReauthView = ({ allowForgotPassword = true, auth, session, showLabels = false, socialProviders }) => {
@@ -66979,20 +67176,28 @@
66979
67176
  }
66980
67177
  });
66981
67178
 
67179
+ function selectLogin(initialScreen, allowWebAuthnLogin) {
67180
+ if (initialScreen === "login" || initialScreen === "login-with-web-authn")
67181
+ return initialScreen;
67182
+ return !allowWebAuthnLogin ? "login" : "login-with-web-authn";
67183
+ }
66982
67184
  var authWidget = createMultiViewWidget({
66983
67185
  initialView({
66984
67186
  initialScreen,
66985
67187
  allowLogin = true,
66986
67188
  allowQuickLogin = true,
66987
67189
  allowSignup = true,
67190
+ allowWebAuthnLogin,
66988
67191
  socialProviders,
66989
67192
  session = {}
66990
67193
  }) {
66991
67194
  const quickLogin = allowQuickLogin && !session.isAuthenticated && session.lastLoginType && socialProviders ? socialProviders.indexOf(session.lastLoginType) >= 0 : false;
66992
- return initialScreen || quickLogin && "quick-login" || session.isAuthenticated && "reauth" || allowLogin && "login" || allowSignup && "signup" || "forgot-password";
67195
+ return initialScreen || quickLogin && "quick-login" || session.isAuthenticated && "reauth" || allowLogin && !allowWebAuthnLogin && "login" || allowLogin && "login-with-web-authn" || allowSignup && "signup" || "forgot-password";
66993
67196
  },
66994
67197
  views: {
66995
67198
  "login": LoginView,
67199
+ "login-with-web-authn": LoginWithWebAuthnView,
67200
+ "login-with-password": LoginWithPasswordView,
66996
67201
  "signup": SignupView,
66997
67202
  "signup-with-password": SignupWithPasswordView,
66998
67203
  "signup-with-web-authn": SignupWithWebAuthnView,