From 153da4054692706b0fc0e2d7924990c883523f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Lengyel?= Date: Sun, 10 Dec 2023 23:40:10 +0100 Subject: [PATCH 1/2] feat: update passwordless to support OTP based MFA (#759) * chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: update pwless to support otp based mfa * feat: add back button to factor chooser and filter the options * feat: update how back buttons are styled * test: update how back button is selected in tests * feat: self-review fixes & updates * feat: self-review fixes&cleanup * fix: firstFactors + test helpers * fix: small test based fixes * feat: clean up first factor handling * refactor: rename passwordlessFirstFactors since it's not only first factors * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * chore: increase size limits * test: add reset method to mfa recipe * feat: make sure firstFactor conflicts hit user error boundaries * feat: update design and fix font-weight issues * chore: update web-js dep * feat: update design * refactor: self-review fixes * refactor: self-review fixes * chore: update changelog * feat: use redirect info if available on mfa success * refactor: use redirectToFactor instead of re-implementing * fix: add missing param into redirectToFactorChooser call * fix: override and routing fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * fix: exposing mfa in tppwless + cleanup/refactor --- CHANGELOG.md | 19 + examples/for-tests-react-16/src/App.js | 8 + examples/for-tests/src/App.js | 8 + lib/build/components/assets/otpEmailIcon.d.ts | 2 + lib/build/components/assets/otpSMSIcon.d.ts | 2 + lib/build/components/errorBoundary.d.ts | 12 - lib/build/emailverification-shared2.js | 2 +- lib/build/index2.js | 91 +- lib/build/multifactorauthprebuiltui.js | 2 +- lib/build/passwordless-shared2.js | 146 + lib/build/passwordless-shared3.js | 2874 ++++++++++++----- lib/build/passwordless.js | 3 + lib/build/passwordlessprebuiltui.js | 9 +- .../resetPasswordEmail.d.ts | 2 +- .../submitNewPassword.d.ts | 2 +- .../components/themes/signInAndUp/signIn.d.ts | 2 +- .../themes/signInAndUp/signInForm.d.ts | 2 +- .../components/themes/signInAndUp/signUp.d.ts | 5 +- .../themes/signInAndUp/signUpForm.d.ts | 5 +- .../components/features/mfa/index.d.ts | 32 + .../components/themes/mfa/index.d.ts | 12 + .../components/themes/mfa/mfaFooter.d.ts | 3 + .../components/themes/mfa/mfaHeader.d.ts | 5 + .../components/themes/mfa/mfaOTPFooter.d.ts | 3 + .../components/themes/mfa/mfaOTPHeader.d.ts | 3 + .../components/themes/signInUp/emailForm.d.ts | 6 +- .../themes/signInUp/emailOrPhoneForm.d.ts | 6 +- .../components/themes/signInUp/index.d.ts | 6 +- .../components/themes/signInUp/phoneForm.d.ts | 6 +- .../themes/signInUp/userInputCodeForm.d.ts | 1 - .../components/themes/translations.d.ts | 6 + lib/build/recipe/passwordless/prebuiltui.d.ts | 10 +- lib/build/recipe/passwordless/recipe.d.ts | 15 + lib/build/recipe/passwordless/types.d.ts | 84 + lib/build/recipe/passwordless/utils.d.ts | 5 + .../components/themes/translations.d.ts | 6 + .../thirdpartypasswordless/prebuiltui.d.ts | 10 +- .../recipe/thirdpartypasswordless/types.d.ts | 1 + lib/build/sessionprebuiltui.js | 2 +- lib/build/thirdparty-shared2.js | 2 +- .../thirdpartyemailpasswordprebuiltui.js | 2 +- lib/build/thirdpartypasswordless-shared.js | 1 + lib/build/thirdpartypasswordless.js | 3 + lib/build/thirdpartypasswordlessprebuiltui.js | 35 +- lib/ts/components/assets/otpEmailIcon.tsx | 17 + lib/ts/components/assets/otpSMSIcon.tsx | 17 + lib/ts/components/errorBoundary.tsx | 49 - lib/ts/components/featureWrapper.tsx | 18 +- .../components/themes/styles.css | 16 - .../dynamicLoginMethodsSpinner/index.tsx | 9 +- .../components/features/mfa/index.tsx | 480 +++ .../components/themes/mfa/index.tsx | 182 ++ .../components/themes/mfa/mfaFooter.tsx | 44 + .../components/themes/mfa/mfaHeader.tsx | 53 + .../components/themes/mfa/mfaOTPFooter.tsx | 66 + .../components/themes/mfa/mfaOTPHeader.tsx | 61 + .../components/themes/signInUp/emailForm.tsx | 16 +- .../themes/signInUp/emailOrPhoneForm.tsx | 16 +- .../components/themes/signInUp/index.tsx | 22 +- .../components/themes/signInUp/phoneForm.tsx | 16 +- .../themes/signInUp/userInputCodeForm.tsx | 5 +- .../components/themes/translations.ts | 7 + lib/ts/recipe/passwordless/prebuiltui.tsx | 63 +- lib/ts/recipe/passwordless/recipe.tsx | 26 + lib/ts/recipe/passwordless/types.ts | 89 + lib/ts/recipe/passwordless/utils.ts | 44 + .../components/themes/signInUp/index.tsx | 12 +- .../thirdpartypasswordless/prebuiltui.tsx | 16 +- lib/ts/recipe/thirdpartypasswordless/types.ts | 1 + lib/ts/recipe/thirdpartypasswordless/utils.ts | 1 + lib/ts/styles/styles.css | 68 + test/with-typescript/src/App.tsx | 18 + 72 files changed, 3789 insertions(+), 1104 deletions(-) create mode 100644 lib/build/components/assets/otpEmailIcon.d.ts create mode 100644 lib/build/components/assets/otpSMSIcon.d.ts delete mode 100644 lib/build/components/errorBoundary.d.ts create mode 100644 lib/build/recipe/passwordless/components/features/mfa/index.d.ts create mode 100644 lib/build/recipe/passwordless/components/themes/mfa/index.d.ts create mode 100644 lib/build/recipe/passwordless/components/themes/mfa/mfaFooter.d.ts create mode 100644 lib/build/recipe/passwordless/components/themes/mfa/mfaHeader.d.ts create mode 100644 lib/build/recipe/passwordless/components/themes/mfa/mfaOTPFooter.d.ts create mode 100644 lib/build/recipe/passwordless/components/themes/mfa/mfaOTPHeader.d.ts create mode 100644 lib/ts/components/assets/otpEmailIcon.tsx create mode 100644 lib/ts/components/assets/otpSMSIcon.tsx delete mode 100644 lib/ts/components/errorBoundary.tsx create mode 100644 lib/ts/recipe/passwordless/components/features/mfa/index.tsx create mode 100644 lib/ts/recipe/passwordless/components/themes/mfa/index.tsx create mode 100644 lib/ts/recipe/passwordless/components/themes/mfa/mfaFooter.tsx create mode 100644 lib/ts/recipe/passwordless/components/themes/mfa/mfaHeader.tsx create mode 100644 lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPFooter.tsx create mode 100644 lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPHeader.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index c2e5dd2ee..3712dbb0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,25 @@ To use this you'll need compatible versions: - Refactored/renamed some styling options (`resetPasswordHeaderTitle` -> `headerTitle withBackButton`) - Added a `useShadowDom` prop to the `AccessDeniedScreen` - Added an `error` prop to the `AccessDeniedScreen` that can be used to describe the reason access is denied. +- Added new MFA related components to Passwordless + - Added new prop `mfaFeature` to recipe config + - `disableDefaultUI`: can be used to disable paths: `${websiteBasePath}/mfa/otp-phone`, `${websiteBasePath}/mfa/otp-email` + - `style`: is applied on top of normal sign in/up styles on the MFA paths + - New embeddable components: + - `MfaOtpPhone` (by default handling path `${websiteBasePath}/mfa/otp-phone`) + - `MfaOtpEmail` (by default handling path `${websiteBasePath}/mfa/otp-email`) + - New overrideable components: + - `PasswordlessMFAHeader_Override` + - `PasswordlessMFAFooter_Override` + - `PasswordlessMFAOTPHeader_Override` + - `PasswordlessMFAOTPFooter_Override` + - Please note, that during MFA we re-use the existing overrideable comps for the form section: + - `PasswordlessEmailForm_Override` + - `PasswordlessPhoneForm_Override` + - `PasswordlessEmailOrPhoneForm_Override` +- Removed an `ErrorBoundary` wrapping all our feature components to make sure all errors are properly catchable by the app +- Added a `footer` prop to `EmailOrPhoneForm`, `EmailForm` and `PhoneForm` which is used to override the default sign in/up footers in case the component is for MFA +- The passwordless and thirdpartypasswordless sign in/up screens now respect the first configuration (defined in the `MultiFactorAuth` recipe or in the tenant information) when selecting the available contact methods. - Fixed a font loading issue, that caused apps using the default (Rubik) font to appear with the incorrect font weights - Some default styling has changed related to how fonts/font-weights are applied diff --git a/examples/for-tests-react-16/src/App.js b/examples/for-tests-react-16/src/App.js index 63b2e0aad..ef83fa06d 100644 --- a/examples/for-tests-react-16/src/App.js +++ b/examples/for-tests-react-16/src/App.js @@ -767,6 +767,10 @@ function getThirdPartyPasswordlessConfigs({ staticProviderList, disableDefaultUI disableDefaultUI, style: theme.style, }, + mfaFeature: { + disableDefaultUI, + style: theme, + }, }); } @@ -845,6 +849,10 @@ function getPasswordlessConfigs({ disableDefaultUI }) { disableDefaultUI, style: theme.style, }, + mfaFeature: { + disableDefaultUI, + style: theme, + }, }); } diff --git a/examples/for-tests/src/App.js b/examples/for-tests/src/App.js index 838091694..29611c0c3 100644 --- a/examples/for-tests/src/App.js +++ b/examples/for-tests/src/App.js @@ -991,6 +991,10 @@ function getThirdPartyPasswordlessConfigs({ staticProviderList, disableDefaultUI disableDefaultUI, style: theme, }, + mfaFeature: { + disableDefaultUI, + style: theme, + }, }); } @@ -1078,6 +1082,10 @@ function getPasswordlessConfigs({ disableDefaultUI }) { disableDefaultUI, style: theme, }, + mfaFeature: { + disableDefaultUI, + style: theme, + }, }); } diff --git a/lib/build/components/assets/otpEmailIcon.d.ts b/lib/build/components/assets/otpEmailIcon.d.ts new file mode 100644 index 000000000..1de53f103 --- /dev/null +++ b/lib/build/components/assets/otpEmailIcon.d.ts @@ -0,0 +1,2 @@ +/// +export declare const OTPEmailIcon: () => JSX.Element; diff --git a/lib/build/components/assets/otpSMSIcon.d.ts b/lib/build/components/assets/otpSMSIcon.d.ts new file mode 100644 index 000000000..5e409d35a --- /dev/null +++ b/lib/build/components/assets/otpSMSIcon.d.ts @@ -0,0 +1,2 @@ +/// +export declare const OTPSMSIcon: () => JSX.Element; diff --git a/lib/build/components/errorBoundary.d.ts b/lib/build/components/errorBoundary.d.ts deleted file mode 100644 index 2b672d624..000000000 --- a/lib/build/components/errorBoundary.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import type { ErrorInfo, ReactNode } from "react"; -declare type ErrorBoundaryState = { - hasError: boolean; -}; -export default class ErrorBoundary extends React.Component { - constructor(props: { hasError: boolean }); - static getDerivedStateFromError(): ErrorBoundaryState; - componentDidCatch(error: Error, errorInfo: ErrorInfo): void; - render(): JSX.Element | ReactNode | undefined; -} -export {}; diff --git a/lib/build/emailverification-shared2.js b/lib/build/emailverification-shared2.js index 74b25374b..ec7512b09 100644 --- a/lib/build/emailverification-shared2.js +++ b/lib/build/emailverification-shared2.js @@ -6,7 +6,7 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext var translations = require("./translations.js"); var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n'; + '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/index2.js b/lib/build/index2.js index 31d5e4906..cfcf81a7d 100644 --- a/lib/build/index2.js +++ b/lib/build/index2.js @@ -19,31 +19,6 @@ var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath var ComponentOverrideContext = React__default.default.createContext("IS_DEFAULT"); -/* - * Component. - */ -var ErrorBoundary = /** @class */ (function (_super) { - genericComponentOverrideContext.__extends(ErrorBoundary, _super); - function ErrorBoundary(props) { - var _this = _super.call(this, props) || this; - _this.state = { hasError: false }; - return _this; - } - ErrorBoundary.getDerivedStateFromError = function () { - return { hasError: true }; - }; - ErrorBoundary.prototype.componentDidCatch = function (error, errorInfo) { - console.info(error, errorInfo); - }; - ErrorBoundary.prototype.render = function () { - if (this.state.hasError) { - return jsxRuntime.jsx(React.Fragment, {}); - } - return this.props.children; - }; - return ErrorBoundary; -})(React__default.default.Component); - var dynamicLoginMethodsContext = React__default.default.createContext(undefined); var useDynamicLoginMethods = function () { var value = React__default.default.useContext(dynamicLoginMethodsContext); @@ -117,31 +92,29 @@ function FeatureWrapper(_a) { genericComponentOverrideContext.__assign( { value: loadedDynamicLoginMethods }, { - children: jsxRuntime.jsx(ErrorBoundary, { - children: jsxRuntime.jsx( - translationContext.TranslationContextProvider, - genericComponentOverrideContext.__assign( - { - defaultLanguage: st.languageTranslations.defaultLanguage, - defaultStore: genericComponentOverrideContext.mergeObjects( - defaultStore, - st.languageTranslations.userTranslationStore - ), - translationControlEventSource: st.languageTranslations.translationEventSource, - userTranslationFunc: st.languageTranslations.userTranslationFunc, - }, - { - children: jsxRuntime.jsx( - WithOrWithoutShadowDom, - genericComponentOverrideContext.__assign( - { useShadowDom: useShadowDom }, - { children: children } - ) - ), - } - ) - ), - }), + children: jsxRuntime.jsx( + translationContext.TranslationContextProvider, + genericComponentOverrideContext.__assign( + { + defaultLanguage: st.languageTranslations.defaultLanguage, + defaultStore: genericComponentOverrideContext.mergeObjects( + defaultStore, + st.languageTranslations.userTranslationStore + ), + translationControlEventSource: st.languageTranslations.translationEventSource, + userTranslationFunc: st.languageTranslations.userTranslationFunc, + }, + { + children: jsxRuntime.jsx( + WithOrWithoutShadowDom, + genericComponentOverrideContext.__assign( + { useShadowDom: useShadowDom }, + { children: children } + ) + ), + } + ) + ), } ) ); @@ -303,7 +276,7 @@ var withOverride = function (overrideKey, DefaultComponent) { }; var styles = - '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n'; + '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n'; var ThemeBase = function (_a) { var children = _a.children, @@ -373,15 +346,13 @@ var DynamicLoginMethodsSpinner = function () { genericComponentOverrideContext.__assign( { value: recipeComponentOverrides }, { - children: jsxRuntime.jsx(ErrorBoundary, { - children: jsxRuntime.jsx( - WithOrWithoutShadowDom, - genericComponentOverrideContext.__assign( - { useShadowDom: recipe.config.useShadowDom }, - { children: jsxRuntime.jsx(DynamicLoginMethodsSpinnerTheme, { config: recipe.config }) } - ) - ), - }), + children: jsxRuntime.jsx( + WithOrWithoutShadowDom, + genericComponentOverrideContext.__assign( + { useShadowDom: recipe.config.useShadowDom }, + { children: jsxRuntime.jsx(DynamicLoginMethodsSpinnerTheme, { config: recipe.config }) } + ) + ), } ) ); diff --git a/lib/build/multifactorauthprebuiltui.js b/lib/build/multifactorauthprebuiltui.js index 176bf6f58..5df6c54ca 100644 --- a/lib/build/multifactorauthprebuiltui.js +++ b/lib/build/multifactorauthprebuiltui.js @@ -64,7 +64,7 @@ var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath var React__namespace = /*#__PURE__*/ _interopNamespace(React); var styles = - '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="mfa"][data-supertokens~="container"] {\n padding-top: 34px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="row"] {\n padding-top: 6px;\n padding-bottom: 6px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="headerTitle"] {\n font-size: var(--font-size-3);\n font-weight: 600;\n line-height: 30px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="factorChooserList"] {\n margin-bottom: 12px;\n}\n[data-supertokens~="factorChooserOption"] {\n display: flex;\n flex-direction: row;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n padding: 20px 16px;\n cursor: pointer;\n margin-top: 12px;\n}\n[data-supertokens~="factorChooserOption"]:hover {\n border: 1px solid rgb(var(--palette-textLink));\n}\n[data-supertokens~="factorOptionText"] {\n flex-grow: 1;\n display: flex;\n flex-direction: column;\n align-items: start;\n text-align: left;\n}\n[data-supertokens~="factorLogo"] {\n flex-grow: 0;\n min-width: 30px;\n text-align: left;\n margin-top: 6px;\n}\n[data-supertokens~="factorName"] {\n color: rgb(var(--palette-textPrimary));\n font-size: var(--font-size-1);\n font-weight: 500;\n margin: 4px;\n}\n[data-supertokens~="factorChooserOption"]:hover [data-supertokens~="factorName"] {\n color: rgb(var(--palette-textLink));\n}\n[data-supertokens~="factorDescription"] {\n color: rgb(var(--palette-textGray));\n font-size: var(--font-size-0);\n margin: 4px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n margin-bottom: 26px;\n text-align: right;\n}\n'; + '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n[data-supertokens~="mfa"][data-supertokens~="container"] {\n padding-top: 34px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="row"] {\n padding-top: 6px;\n padding-bottom: 6px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="headerTitle"] {\n font-size: var(--font-size-3);\n font-weight: 600;\n line-height: 30px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="factorChooserList"] {\n margin-bottom: 12px;\n}\n[data-supertokens~="factorChooserOption"] {\n display: flex;\n flex-direction: row;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n padding: 20px 16px;\n cursor: pointer;\n margin-top: 12px;\n}\n[data-supertokens~="factorChooserOption"]:hover {\n border: 1px solid rgb(var(--palette-textLink));\n}\n[data-supertokens~="factorOptionText"] {\n flex-grow: 1;\n display: flex;\n flex-direction: column;\n align-items: start;\n text-align: left;\n}\n[data-supertokens~="factorLogo"] {\n flex-grow: 0;\n min-width: 30px;\n text-align: left;\n margin-top: 6px;\n}\n[data-supertokens~="factorName"] {\n color: rgb(var(--palette-textPrimary));\n font-size: var(--font-size-1);\n font-weight: 500;\n margin: 4px;\n}\n[data-supertokens~="factorChooserOption"]:hover [data-supertokens~="factorName"] {\n color: rgb(var(--palette-textLink));\n}\n[data-supertokens~="factorDescription"] {\n color: rgb(var(--palette-textGray));\n font-size: var(--font-size-0);\n margin: 4px;\n}\n[data-supertokens~="mfa"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n margin-bottom: 26px;\n text-align: right;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/passwordless-shared2.js b/lib/build/passwordless-shared2.js index 90bcc72d8..94a68dd00 100644 --- a/lib/build/passwordless-shared2.js +++ b/lib/build/passwordless-shared2.js @@ -2,7 +2,10 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); var PasswordlessWebJS = require("supertokens-web-js/recipe/passwordless"); +var postSuperTokensInitCallbacks = require("supertokens-web-js/utils/postSuperTokensInitCallbacks"); +var jsxRuntime = require("react/jsx-runtime"); var utils = require("./authRecipe-shared.js"); +var recipe = require("./multifactorauth-shared.js"); var windowHandler = require("supertokens-web-js/utils/windowHandler"); function _interopDefault(e) { @@ -11,6 +14,88 @@ function _interopDefault(e) { var PasswordlessWebJS__default = /*#__PURE__*/ _interopDefault(PasswordlessWebJS); +var OTPEmailIcon = function () { + return jsxRuntime.jsxs( + "svg", + genericComponentOverrideContext.__assign( + { width: "17", height: "15", viewBox: "0 0 17 15", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, + { + children: [ + jsxRuntime.jsx("path", { + id: "image 414 (Traced)", + "fill-rule": "evenodd", + "clip-rule": "evenodd", + d: "M2.01513 0.0546421C1.19571 0.195435 0.393224 0.877322 0.143564 1.64496C0.0564841 1.9127 -0.00197242 1.84636 0.659082 2.22993C0.91105 2.37612 1.64082 2.80042 2.28084 3.17276C2.92086 3.54514 3.96809 4.1544 4.60811 4.52674C5.24813 4.89905 6.37321 5.55428 7.10833 5.98278C7.84346 6.41131 8.46401 6.7689 8.48736 6.77743C8.52111 6.78982 10.4367 5.69077 12.6253 4.40341C12.7865 4.30852 13.8173 3.70613 14.9159 3.06475L16.9133 1.89856L16.903 1.78079C16.8974 1.71603 16.8178 1.51568 16.7262 1.3356C16.3776 0.650318 15.6775 0.156143 14.8905 0.039982C14.4716 -0.0218423 2.38016 -0.00809191 2.01513 0.0546421ZM6.60933e-06 6.62054C0.000739608 10.251 -0.00834948 10.1158 0.27063 10.655C0.659815 11.4073 1.39721 11.8833 2.30408 11.9675C2.77169 12.0109 14.2345 12.0108 14.7024 11.9673C15.3604 11.9062 15.8152 11.7008 16.2911 11.2498C16.5236 11.0295 16.619 10.9066 16.7395 10.6725C17.0173 10.133 17.0065 10.3025 16.996 6.65494L16.9866 3.40211L15.8322 4.07294C15.1972 4.44186 13.9767 5.15156 13.1201 5.65004C11.2459 6.74049 10.2603 7.31342 9.46206 7.77628C8.76656 8.17962 8.59368 8.23389 8.2745 8.14908C8.14446 8.11454 7.64668 7.84559 6.81451 7.36034C4.15032 5.80665 0.097862 3.44588 0.0268711 3.40617C0.0117346 3.39774 -0.00032324 4.84419 6.60933e-06 6.62054Z", + fill: "url(#paint0_linear_4445_310)", + }), + jsxRuntime.jsx("defs", { + children: jsxRuntime.jsxs( + "linearGradient", + genericComponentOverrideContext.__assign( + { + id: "paint0_linear_4445_310", + x1: "8.5", + y1: "0", + x2: "8.5", + y2: "12", + gradientUnits: "userSpaceOnUse", + }, + { + children: [ + jsxRuntime.jsx("stop", { "stop-color": "#5FACFF" }), + jsxRuntime.jsx("stop", { offset: "1", "stop-color": "#1686FF" }), + ], + } + ) + ), + }), + ], + } + ) + ); +}; + +var OTPSMSIcon = function () { + return jsxRuntime.jsxs( + "svg", + genericComponentOverrideContext.__assign( + { width: "17", height: "15", viewBox: "0 0 17 15", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, + { + children: [ + jsxRuntime.jsx("path", { + id: "image 412 (Traced)", + "fill-rule": "evenodd", + "clip-rule": "evenodd", + d: "M2.23143 0.0484105C1.11677 0.26606 0.230705 1.14148 0.0548812 2.19882C0.0207171 2.40417 -0.000319148 3.89779 3.66265e-06 6.09367C0.000595481 10.0175 0.00446909 10.0713 0.330507 10.706C0.544477 11.1223 1.03692 11.597 1.49058 11.8243C1.9253 12.042 2.4213 12.1389 3.10571 12.14L3.65718 12.1409L3.65739 13.3581C3.65755 14.4585 3.66729 14.5903 3.75859 14.733C3.88347 14.9281 4.1338 15.0332 4.37209 14.9906C4.50192 14.9674 5.03536 14.5737 6.32332 13.5507L8.09582 12.1427L11.2701 12.1409C14.8062 12.1389 14.8922 12.1322 15.5441 11.8059C15.9514 11.602 16.4058 11.1868 16.6406 10.8041C16.7198 10.6748 16.8331 10.3886 16.8923 10.1681C16.9951 9.78536 17 9.6 17 6.0949C17 3.67866 16.98 2.31864 16.9417 2.11857C16.7993 1.37604 16.1965 0.620747 15.4792 0.286303C15.2652 0.186472 14.9464 0.0801328 14.7708 0.049999C14.3886 -0.0156495 2.5671 -0.0171356 2.23143 0.0484105ZM5.24433 4.97226C5.37743 5.00736 5.55471 5.1197 5.70901 5.26668C6.20818 5.74216 6.20834 6.40218 5.70933 6.86336C5.19445 7.3393 4.53167 7.33945 4.03228 6.86382C3.54451 6.3992 3.53069 5.75907 3.99822 5.28943C4.33561 4.95053 4.75602 4.84352 5.24433 4.97226ZM8.87594 4.96544C9.55686 5.14589 9.9071 5.95945 9.57246 6.58313C9.13161 7.40469 7.91806 7.41591 7.45342 6.60271C7.32215 6.37302 7.3066 6.29861 7.32494 5.98907C7.34211 5.69977 7.37455 5.59794 7.50653 5.41904C7.804 5.01592 8.36509 4.83005 8.87594 4.96544ZM12.7023 5.05815C13.4409 5.4257 13.5612 6.36097 12.94 6.90635C12.6706 7.14291 12.3468 7.24567 12.0095 7.20164C11.0115 7.07132 10.59 5.99614 11.2623 5.29563C11.6485 4.89313 12.1909 4.80365 12.7023 5.05815Z", + fill: "url(#paint0_linear_4445_316)", + }), + jsxRuntime.jsx("defs", { + children: jsxRuntime.jsxs( + "linearGradient", + genericComponentOverrideContext.__assign( + { + id: "paint0_linear_4445_316", + x1: "8.5", + y1: "0", + x2: "8.5", + y2: "15", + gradientUnits: "userSpaceOnUse", + }, + { + children: [ + jsxRuntime.jsx("stop", { "stop-color": "#5FACFF" }), + jsxRuntime.jsx("stop", { offset: "1", "stop-color": "#1585FF" }), + ], + } + ) + ), + }), + ], + } + ) + ); +}; + var getFunctionOverrides = function (onHandleEvent) { return function (originalImp) { return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, originalImp), { @@ -390,6 +475,7 @@ function normalisePasswordlessConfig(config) { validatePhoneNumber: validatePhoneNumber, signInUpFeature: signInUpFeature, linkClickedScreenFeature: normalisePasswordlessBaseConfig(config.linkClickedScreenFeature), + mfaFeature: normalisePasswordlessBaseConfig(config.mfaFeature), contactMethod: config.contactMethod, override: override, } @@ -455,6 +541,45 @@ function normalisePasswordlessBaseConfig(config) { style: style, }); } +function getEnabledContactMethods(contactMethod, currentDynamicLoginMethods) { + var _a; + var enabledContactMethods = contactMethod === "EMAIL_OR_PHONE" ? ["EMAIL", "PHONE"] : [contactMethod]; + var firstFactors; + if (currentDynamicLoginMethods.loaded && currentDynamicLoginMethods.loginMethods.firstFactors) { + firstFactors = currentDynamicLoginMethods.loginMethods.firstFactors; + } else { + firstFactors = + (_a = recipe.MultiFactorAuth.getInstance()) === null || _a === void 0 ? void 0 : _a.config.firstFactors; + } + if (firstFactors !== undefined) { + if (enabledContactMethods.includes("PHONE")) { + if (!firstFactors.includes("otp-phone") && !firstFactors.includes("link-phone")) { + enabledContactMethods = enabledContactMethods.filter(function (c) { + return c !== "PHONE"; + }); + } + } else { + if (firstFactors.includes("otp-phone") || firstFactors.includes("link-phone")) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + } + if (enabledContactMethods.includes("EMAIL")) { + if (!firstFactors.includes("otp-email") && !firstFactors.includes("link-email")) { + enabledContactMethods = enabledContactMethods.filter(function (c) { + return c !== "EMAIL"; + }); + } + } else { + if (firstFactors.includes("otp-email") || firstFactors.includes("link-email")) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + } + } + if (enabledContactMethods.length === 0) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + return enabledContactMethods; +} /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -470,6 +595,20 @@ function normalisePasswordlessBaseConfig(config) { * License for the specific language governing permissions and limitations * under the License. */ +var otpPhoneFactor = { + id: "otp-phone", + name: "SMS based OTP", + description: "Get an OTP code on your phone to complete the authentication request", + path: "/mfa/otp-phone", + logo: OTPSMSIcon, +}; +var otpEmailFactor = { + id: "otp-email", + name: "Email based OTP", + description: "Get an OTP code on your email address to complete the authentication request", + path: "/mfa/otp-email", + logo: OTPEmailIcon, +}; var passwordlessFirstFactors = ["otp-phone", "otp-email", "link-phone", "link-email"]; /* * Class. @@ -490,6 +629,12 @@ var Passwordless = /** @class */ (function (_super) { }); }); }; + postSuperTokensInitCallbacks.PostSuperTokensInitCallbacks.addPostInitCallback(function () { + var mfa = recipe.MultiFactorAuth.getInstance(); + if (mfa !== undefined) { + mfa.addMFAFactors([otpPhoneFactor, otpEmailFactor]); + } + }); return _this; } Passwordless.init = function (config) { @@ -552,6 +697,7 @@ var Passwordless = /** @class */ (function (_super) { exports.Passwordless = Passwordless; exports.defaultEmailValidator = defaultEmailValidator; exports.defaultValidate = defaultValidate; +exports.getEnabledContactMethods = getEnabledContactMethods; exports.getPhoneNumberUtils = getPhoneNumberUtils; exports.normalisePasswordlessConfig = normalisePasswordlessConfig; exports.passwordlessFirstFactors = passwordlessFirstFactors; diff --git a/lib/build/passwordless-shared3.js b/lib/build/passwordless-shared3.js index 43a217daf..62f455661 100644 --- a/lib/build/passwordless-shared3.js +++ b/lib/build/passwordless-shared3.js @@ -5,6 +5,7 @@ var jsxRuntime = require("react/jsx-runtime"); var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); var uiEntry = require("./index2.js"); var authWidgetWrapper = require("./authRecipe-shared2.js"); +var session = require("./session-shared.js"); var componentOverrideContext = require("./passwordless-shared.js"); var React = require("react"); var STGeneralError = require("supertokens-web-js/utils/error"); @@ -12,14 +13,18 @@ var recipe = require("./session-shared2.js"); var translations = require("./translations.js"); var translationContext = require("./translationContext.js"); var button = require("./emailpassword-shared2.js"); -var session = require("./session-shared.js"); +var windowHandler = require("supertokens-web-js/utils/windowHandler"); +var recipe$2 = require("./multifactorauth-shared.js"); var recipe$1 = require("./passwordless-shared2.js"); var SuperTokensBranding = require("./SuperTokensBranding.js"); var generalError = require("./emailpassword-shared.js"); +var sessionprebuiltui = require("./sessionprebuiltui.js"); var checkedRoundIcon = require("./checkedRoundIcon.js"); var formBase = require("./emailpassword-shared8.js"); var validators = require("./emailpassword-shared5.js"); var arrowLeftIcon = require("./arrowLeftIcon.js"); +var multifactorauth = require("./multifactorauth-shared2.js"); +var backButton = require("./emailpassword-shared7.js"); function _interopDefault(e) { return e && e.__esModule ? e : { default: e }; @@ -56,7 +61,7 @@ var React__namespace = /*#__PURE__*/ _interopNamespace(React); var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n\n[data-supertokens~="generalSuccess"] {\n margin-bottom: 20px;\n -webkit-animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n}\n\n[data-supertokens~="codeInputLabelWrapper"] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="headerSubtitle"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="sendCodeText"] {\n margin-top: 15px;\n margin-bottom: 20px;\n}\n\n[data-supertokens~="sendCodeText"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="resendCodeBtn"] {\n width: auto;\n margin-top: 0;\n line-height: 24px;\n}\n\n[data-supertokens~="resendCodeBtn"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="resendCodeBtn"]:disabled {\n color: rgb(var(--palette-textPrimary));\n cursor: default;\n text-decoration: none;\n}\n\n[data-supertokens~="phoneInputLibRoot"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti [data-supertokens~="input"] {\n padding-left: 15px;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti {\n flex: 1 1;\n min-width: 0;\n width: 100%;\n background: transparent;\n border: none;\n color: inherit;\n outline: none;\n}\n\n[data-supertokens~="continueButtonWrapper"] {\n margin-top: 10px;\n margin-bottom: 30px;\n}\n\n.iti__country-list {\n border: 0;\n top: 40px;\n width: min(72.2vw, 320px);\n border-radius: 6;\n box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);\n}\n\n.iti__country {\n display: flex;\n align-items: center;\n height: 34px;\n cursor: pointer;\n\n padding: 0 8px;\n}\n\n.iti__country-name {\n color: var(--palette-textLabel);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: "0 16px";\n}\n'; + '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n\n[data-supertokens~="generalSuccess"] {\n margin-bottom: 20px;\n -webkit-animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n}\n\n[data-supertokens~="codeInputLabelWrapper"] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="headerSubtitle"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="sendCodeText"] {\n margin-top: 15px;\n margin-bottom: 20px;\n}\n\n[data-supertokens~="sendCodeText"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="resendCodeBtn"] {\n width: auto;\n margin-top: 0;\n line-height: 24px;\n}\n\n[data-supertokens~="resendCodeBtn"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="resendCodeBtn"]:disabled {\n color: rgb(var(--palette-textPrimary));\n cursor: default;\n text-decoration: none;\n}\n\n[data-supertokens~="phoneInputLibRoot"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti [data-supertokens~="input"] {\n padding-left: 15px;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti {\n flex: 1 1;\n min-width: 0;\n width: 100%;\n background: transparent;\n border: none;\n color: inherit;\n outline: none;\n}\n\n[data-supertokens~="continueButtonWrapper"] {\n margin-top: 10px;\n margin-bottom: 30px;\n}\n\n.iti__country-list {\n border: 0;\n top: 40px;\n width: min(72.2vw, 320px);\n border-radius: 6;\n box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);\n}\n\n.iti__country {\n display: flex;\n align-items: center;\n height: 34px;\n cursor: pointer;\n\n padding: 0 8px;\n}\n\n.iti__country-name {\n color: var(--palette-textLabel);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: "0 16px";\n}\n'; var ThemeBase = function (_a) { var children = _a.children, @@ -222,6 +227,12 @@ var defaultTranslationsPasswordless = { PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE: "An OTP was sent to you at", PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK: "An OTP and a magic link was sent to you at", PWLESS_USER_INPUT_CODE_INPUT_LABEL: "OTP", + PWLESS_MFA_LOGOUT: "Logout", + PWLESS_MFA_HEADER_TITLE_PHONE: "SMS based OTP", + PWLESS_MFA_HEADER_TITLE_EMAIL: "Email based OTP", + PWLESS_MFA_FOOTER_CHOOSER_ANOTHER: "Choose another factor", + PWLESS_MFA_FOOTER_LOGOUT: "Logout", + PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP: "You are not allowed to set up OTP.", /* * The following are error messages from our backend SDK. * These are returned as full messages to preserver compatibilty, but they work just like the keys above. @@ -569,6 +580,7 @@ var SignInUpFooter = uiEntry.withOverride("PasswordlessSignInUpFooter", function var EmailForm = uiEntry.withOverride("PasswordlessEmailForm", function PasswordlessEmailForm(props) { var _this = this; + var _a; var userContext = uiEntry.useUserContext(); return jsxRuntime.jsx(formBase.FormBase, { clearError: props.clearError, @@ -628,10 +640,13 @@ var EmailForm = uiEntry.withOverride("PasswordlessEmailForm", function Passwordl }, validateOnBlur: false, showLabels: true, - footer: jsxRuntime.jsx(SignInUpFooter, { - privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, - termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, - }), + footer: + (_a = props.footer) !== null && _a !== void 0 + ? _a + : jsxRuntime.jsx(SignInUpFooter, { + privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, + termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, + }), }); }); @@ -2731,812 +2746,1797 @@ var phoneNumberInputWithInjectedProps = function (injectedProps) { }; }; -var EmailOrPhoneForm = uiEntry.withOverride( - "PasswordlessEmailOrPhoneForm", - function PasswordlessEmailOrPhoneForm(props) { +var PhoneForm = uiEntry.withOverride("PasswordlessPhoneForm", function PasswordlessPhoneForm(props) { + var _this = this; + var _a; + var userContext = uiEntry.useUserContext(); + React.useEffect(function () { + // We preload this here, since it will be used almost for sure, but loading it + void recipe$1.preloadPhoneNumberUtils(); + }, []); + var phoneInput = React.useMemo( + function () { + return phoneNumberInputWithInjectedProps({ + defaultCountry: props.config.signInUpFeature.defaultCountry, + }); + }, + [props.config.signInUpFeature.defaultCountry] + ); + return jsxRuntime.jsx(formBase.FormBase, { + clearError: props.clearError, + onError: props.onError, + formFields: [ + { + id: "phoneNumber", + label: "PWLESS_SIGN_IN_UP_PHONE_LABEL", + inputComponent: phoneInput, + optional: false, + autofocus: true, + placeholder: "", + autoComplete: "tel", + validate: validators.defaultValidate, + }, + ], + buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", + onSuccess: props.onSuccess, + callAPI: function (formFields) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var phoneNumber, validationRes, response; + var _a; + return genericComponentOverrideContext.__generator(this, function (_b) { + switch (_b.label) { + case 0: + phoneNumber = + (_a = formFields.find(function (field) { + return field.id === "phoneNumber"; + })) === null || _a === void 0 + ? void 0 + : _a.value; + if (phoneNumber === undefined) { + throw new STGeneralError__default.default("GENERAL_ERROR_PHONE_UNDEFINED"); + } + return [4 /*yield*/, props.config.validatePhoneNumber(phoneNumber)]; + case 1: + validationRes = _b.sent(); + if (validationRes !== undefined) { + throw new STGeneralError__default.default(validationRes); + } + return [ + 4 /*yield*/, + props.recipeImplementation.createCode({ + phoneNumber: phoneNumber, + userContext: userContext, + }), + ]; + case 2: + response = _b.sent(); + if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { + throw new STGeneralError__default.default(response.reason); + } + return [2 /*return*/, response]; + } + }); + }); + }, + validateOnBlur: false, + showLabels: true, + footer: + (_a = props.footer) !== null && _a !== void 0 + ? _a + : jsxRuntime.jsx(SignInUpFooter, { + privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, + termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, + }), + }); +}); + +var ResendButton = uiEntry.withOverride("PasswordlessResendButton", function PasswordlessResendButton(_a) { + var loginAttemptInfo = _a.loginAttemptInfo, + resendEmailOrSMSGapInSeconds = _a.resendEmailOrSMSGapInSeconds, + onClick = _a.onClick; + var t = translationContext.useTranslation(); + var getTimeLeft = React.useCallback( + function () { + var timeLeft = loginAttemptInfo.lastResend + resendEmailOrSMSGapInSeconds * 1000 - Date.now(); + return timeLeft < 0 ? undefined : Math.ceil(timeLeft / 1000); + }, + [loginAttemptInfo, resendEmailOrSMSGapInSeconds] + ); + var _b = React.useState(getTimeLeft()), + secsUntilResend = _b[0], + setSecsUntilResend = _b[1]; + React.useEffect( + function () { + // This runs every time the loginAttemptInfo updates, so after every resend + var interval = setInterval(function () { + var timeLeft = getTimeLeft(); + if (timeLeft === undefined) { + clearInterval(interval); + } + setSecsUntilResend(timeLeft); + }, 500); + return function () { + // This can safely run twice + clearInterval(interval); + }; + }, + [getTimeLeft, setSecsUntilResend] + ); + return jsxRuntime.jsx( + "button", + genericComponentOverrideContext.__assign( + { + type: "button", + disabled: secsUntilResend !== undefined, + onClick: onClick, + "data-supertokens": "link linkButton resendCodeBtn", + }, + { + children: + secsUntilResend !== undefined + ? jsxRuntime.jsxs(React__namespace.default.Fragment, { + children: [ + t("PWLESS_RESEND_BTN_DISABLED_START"), + jsxRuntime.jsxs("strong", { + children: [ + Math.floor(secsUntilResend / 60) + .toString() + .padStart(2, "0"), + ":", + (secsUntilResend % 60).toString().padStart(2, "0"), + ], + }), + t("PWLESS_RESEND_BTN_DISABLED_END"), + ], + }) + : loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_RESEND_BTN_EMAIL") + : t("PWLESS_RESEND_BTN_PHONE"), + } + ) + ); +}); + +var UserInputCodeFormFooter = uiEntry.withOverride( + "PasswordlessUserInputCodeFormFooter", + function PasswordlessUserInputCodeFormFooter(_a) { + var loginAttemptInfo = _a.loginAttemptInfo, + recipeImplementation = _a.recipeImplementation; + var t = translationContext.useTranslation(); + var userContext = uiEntry.useUserContext(); + return jsxRuntime.jsx(React.Fragment, { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", + onClick: function () { + return recipeImplementation.clearLoginAttemptInfo({ + userContext: userContext, + }); + }, + }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { color: "rgb(var(--palette-textPrimary))" }), + loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") + : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE"), + ], + } + ) + ), + }); + } +); + +var UserInputCodeForm = uiEntry.withOverride( + "PasswordlessUserInputCodeForm", + function PasswordlessUserInputCodeForm(props) { var _this = this; - var _a = React.useState(false), - isPhoneNumber = _a[0], - setIsPhoneNumber = _a[1]; + var _a; + var t = translationContext.useTranslation(); var userContext = uiEntry.useUserContext(); - React.useEffect(function () { - // We preload this here, since it will be used almost for sure, but loading it - void recipe$1.preloadPhoneNumberUtils(); - }, []); - var emailOrPhoneInput = React.useMemo( + // We need this any because the node types are also loaded + var _b = React.useState(), + clearResendNotifTimeout = _b[0], + setClearResendNotifTimeout = _b[1]; + React.useEffect( function () { - return isPhoneNumber - ? phoneNumberInputWithInjectedProps({ - defaultCountry: props.config.signInUpFeature.defaultCountry, - }) - : undefined; + // This is just to clean up on unmount and if the clear timeout changes + return function () { + clearTimeout(clearResendNotifTimeout); + }; }, - [props.config.signInUpFeature.defaultCountry, isPhoneNumber] + [clearResendNotifTimeout] ); - return jsxRuntime.jsx(formBase.FormBase, { - clearError: props.clearError, - onError: props.onError, - formFields: [ - { - id: "emailOrPhone", - label: "PWLESS_SIGN_IN_UP_EMAIL_OR_PHONE_LABEL", - inputComponent: emailOrPhoneInput, - optional: false, - autofocus: true, - placeholder: "", - // We do not add an autocomplete prop in this case, since we do not really have any sensible option to set - // Setting them to either "tel" or "email" would give people the wrong impression since this could have either - // AFAIK we can't set them both at the same time - validate: recipe$1.defaultValidate, - }, - ], - buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", - onSuccess: props.onSuccess, - callAPI: function (formFields, setValue) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var emailOrPhone, - emailValidationRes, - response, - phoneValidationRes, - response, - intPhoneNumber, - phoneValidationResAfterGuess, - response, - ex_1; - var _a; - return genericComponentOverrideContext.__generator(this, function (_b) { - switch (_b.label) { - case 0: - emailOrPhone = - (_a = formFields.find(function (field) { - return field.id === "emailOrPhone"; - })) === null || _a === void 0 - ? void 0 - : _a.value; - if (emailOrPhone === undefined) { - throw new STGeneralError__default.default("GENERAL_ERROR_EMAIL_OR_PHONE_UNDEFINED"); - } - return [4 /*yield*/, recipe$1.defaultEmailValidator(emailOrPhone)]; - case 1: - if (!(_b.sent() === undefined)) return [3 /*break*/, 6]; - return [4 /*yield*/, props.config.validateEmailAddress(emailOrPhone)]; - case 2: - emailValidationRes = _b.sent(); - if (!(emailValidationRes === undefined)) return [3 /*break*/, 4]; - return [ - 4 /*yield*/, - props.recipeImplementation.createCode({ - email: emailOrPhone, - userContext: userContext, - }), - ]; - case 3: - response = _b.sent(); - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); - } - return [2 /*return*/, response]; - case 4: - throw new STGeneralError__default.default(emailValidationRes); - case 5: - return [3 /*break*/, 19]; - case 6: - return [4 /*yield*/, props.config.validatePhoneNumber(emailOrPhone)]; - case 7: - phoneValidationRes = _b.sent(); - if (!(phoneValidationRes === undefined)) return [3 /*break*/, 9]; - return [ - 4 /*yield*/, - props.recipeImplementation.createCode({ - phoneNumber: emailOrPhone, - userContext: userContext, - }), - ]; - case 8: - response = _b.sent(); - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); + function resend() { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + var response, generalError, e_1; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 5, , 6]); + response = void 0; + generalError = void 0; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [ + 4 /*yield*/, + props.recipeImplementation.resendCode({ + userContext: userContext, + }), + ]; + case 2: + response = _a.sent(); + return [3 /*break*/, 4]; + case 3: + e_1 = _a.sent(); + if (STGeneralError__default.default.isThisError(e_1)) { + generalError = e_1; + } else { + throw e_1; + } + return [3 /*break*/, 4]; + case 4: + if (generalError !== undefined) { + props.onError(generalError.message); + } else { + if (response === undefined) { + throw new Error("Should not come here"); } - return [2 /*return*/, response]; - case 9: - return [ - 4 /*yield*/, - props.config.signInUpFeature.guessInternationPhoneNumberFromInputPhoneNumber( - emailOrPhone, - props.config.signInUpFeature.defaultCountry - ), - ]; - case 10: - intPhoneNumber = _b.sent(); - if (!(intPhoneNumber && isPhoneNumber !== true)) return [3 /*break*/, 18]; - return [4 /*yield*/, props.config.validatePhoneNumber(intPhoneNumber)]; - case 11: - phoneValidationResAfterGuess = _b.sent(); - if (!(phoneValidationResAfterGuess === undefined)) return [3 /*break*/, 16]; - _b.label = 12; - case 12: - _b.trys.push([12, 14, , 15]); - return [ - 4 /*yield*/, - props.recipeImplementation.createCode({ - phoneNumber: intPhoneNumber, - userContext: userContext, - }), - ]; - case 13: - response = _b.sent(); - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); + if (response.status === "OK") { + setClearResendNotifTimeout( + setTimeout(function () { + setClearResendNotifTimeout(undefined); + }, 2000) + ); } - return [2 /*return*/, response]; - case 14: - ex_1 = _b.sent(); - // General errors from the API can make createCode throw but we want to switch to the phone UI anyway - setValue("emailOrPhone", intPhoneNumber); - setIsPhoneNumber(true); - throw ex_1; - case 15: - return [3 /*break*/, 17]; - case 16: - // In this case we could get a phonenumber but not a completely valid one - // We want to switch to the phone UI and pre-fill the number - setValue("emailOrPhone", intPhoneNumber); - setIsPhoneNumber(true); - throw new STGeneralError__default.default( - "PWLESS_EMAIL_OR_PHONE_INVALID_INPUT_GUESS_PHONE_ERR" - ); - case 17: - return [3 /*break*/, 19]; - case 18: - throw new STGeneralError__default.default(phoneValidationRes); - case 19: - return [2 /*return*/]; - } - }); + } + return [3 /*break*/, 6]; + case 5: + _a.sent(); + props.onError("SOMETHING_WENT_WRONG_ERROR"); + return [3 /*break*/, 6]; + case 6: + return [2 /*return*/]; + } }); - }, - validateOnBlur: false, - showLabels: true, - footer: jsxRuntime.jsx(SignInUpFooter, { - privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, - termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, - }), - }); - } -); - -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http="//www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Imports. - */ -/* - * Component. - */ -function SMSLargeIcon() { - return jsxRuntime.jsx( - "svg", - genericComponentOverrideContext.__assign( - { xmlns: "http://www.w3.org/2000/svg", width: "52.013", height: "41.889", viewBox: "0 0 52.013 41.889" }, - { - children: jsxRuntime.jsx( - "g", - genericComponentOverrideContext.__assign( - { id: "Group_10400", "data-name": "Group 10400", transform: "translate(-724.625 -241.125)" }, + }); + } + return jsxRuntime.jsxs(React__namespace.default.Fragment, { + children: [ + clearResendNotifTimeout !== undefined && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "generalSuccess" }, + { + children: + props.loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_RESEND_SUCCESS_EMAIL") + : t("PWLESS_RESEND_SUCCESS_PHONE"), + } + ) + ), + jsxRuntime.jsx(formBase.FormBase, { + clearError: props.clearError, + onError: props.onError, + formFields: [ { - children: jsxRuntime.jsxs( - "g", + id: "userInputCode", + label: "", + labelComponent: jsxRuntime.jsxs( + "div", genericComponentOverrideContext.__assign( - { id: "Group_10399", "data-name": "Group 10399" }, + { "data-supertokens": "codeInputLabelWrapper" }, { children: [ - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { id: "Group_10398", "data-name": "Group 10398" }, - { - children: [ - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { - id: "_2639922_sms_icon", - "data-name": "2639922_sms_icon", - transform: "translate(732.916 242)", - }, - { - children: [ - jsxRuntime.jsx("path", { - id: "Union_52", - "data-name": "Union 52", - d: "M7.124 37.96a6.26 6.26 0 0 0 3.652-5H6.593A6.592 6.592 0 0 1 0 26.367V6.592A6.592 6.592 0 0 1 6.593 0h29.664a6.592 6.592 0 0 1 6.593 6.592v19.775a6.592 6.592 0 0 1-6.593 6.592h-17.68a13.355 13.355 0 0 1-11.159 6.576zm20.893-21.48a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.3 3.3zm-9.887 0a3.3 3.3 0 1 0 3.3-3.3 3.295 3.295 0 0 0-3.3 3.3zm-9.888 0a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.301 3.3z", - transform: "translate(-.001)", - strokeWidth: "1.75px", - stroke: "#000", - fill: "#c4f3ff", - }), - jsxRuntime.jsx("ellipse", { - id: "Ellipse_3013", - "data-name": "Ellipse 3013", - cy: ".917", - ry: ".917", - transform: "translate(7.335 38.506)", - stroke: "#000", - fill: "#c4f3ff", - }), - ], - } - ) - ), - jsxRuntime.jsx("path", { - id: "Intersection_2", - "data-name": "Intersection 2", - fill: "#8ae7ff", - d: "M177.409-21836.576v-.33l-.214-1.131a6.271 6.271 0 0 0 3.651-5h-4.184a6.59 6.59 0 0 1-6.512-5.588h42.495a7.846 7.846 0 0 1-1.607 3.605 6.576 6.576 0 0 1-4.712 1.982h-14.845c-1.545-.09-2.537-.164-2.537-.164l-.077.164h-.219a13.342 13.342 0 0 1-11.156 6.572l-.082-.439z", - transform: "translate(562.766 22118)", - }), - jsxRuntime.jsx("path", { - id: "Intersection_1", - "data-name": "Intersection 1", - fill: "#8ae7ff", - d: "M209.246-21846.41s.494-22.641 0-25.178a8.7 8.7 0 0 0-2.767-4.41 6.6 6.6 0 0 1 6.369 6.59v19.775a6.6 6.6 0 0 1-5.724 6.537 6.213 6.213 0 0 0 2.122-3.314z", - transform: "translate(561.882 22118.172)", - }), - ], - } - ) - ), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { - id: "_2639922_sms_icon-2", - "data-name": "2639922_sms_icon", - transform: "translate(732.916 242.174)", - }, - { - children: [ - jsxRuntime.jsx("path", { - id: "Union_52-2", - "data-name": "Union 52", - d: "M7.124 37.96a6.26 6.26 0 0 0 3.652-5H6.593A6.592 6.592 0 0 1 0 26.367V6.592A6.592 6.592 0 0 1 6.593 0h29.664a6.592 6.592 0 0 1 6.593 6.592v19.775a6.592 6.592 0 0 1-6.593 6.592h-17.68a13.355 13.355 0 0 1-11.159 6.576zm20.893-21.48a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.3 3.3zm-9.887 0a3.3 3.3 0 1 0 3.3-3.3 3.295 3.295 0 0 0-3.3 3.3zm-9.888 0a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.301 3.3z", - transform: "translate(-.001)", - fill: "none", - strokeWidth: "1.75px", - stroke: "#000", - }), - jsxRuntime.jsx("ellipse", { - id: "Ellipse_3013-2", - "data-name": "Ellipse 3013", - cy: ".917", - ry: ".917", - transform: "translate(7.335 38.506)", - fill: "none", - stroke: "#000", - }), - ], - } - ) - ), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { id: "Group_10397", "data-name": "Group 10397" }, - { - children: [ - jsxRuntime.jsx("path", { - id: "Line_104", - "data-name": "Line 104", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#000", - transform: "translate(725.5 266.84)", - d: "M0 0h9.872", - }), - jsxRuntime.jsx("path", { - id: "Line_105", - "data-name": "Line 105", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#fff", - transform: "translate(725.5 268.59)", - d: "M0 0h9.872", - }), - ], - } - ) - ), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { id: "Group_10396", "data-name": "Group 10396" }, - { - children: [ - jsxRuntime.jsx("path", { - id: "Line_103", - "data-name": "Line 103", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#000", - transform: "translate(725.5 260.17)", - d: "M0 0h12.461", - }), - jsxRuntime.jsx("path", { - id: "Line_102", - "data-name": "Line 102", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#fff", - transform: "translate(725.5 261.92)", - d: "M0 0h12.461", - }), - ], - } - ) - ), - jsxRuntime.jsx("path", { - id: "Path_91918", - "data-name": "Path 91918", - fill: "#8ae7ff", - d: "M599.827 22145.373a1.62 1.62 0 0 0 1.38-1.336c.247-1.234.267 1.752.267 1.752l-1.647-.178z", - transform: "translate(170 -21876)", + jsxRuntime.jsx(formBase.Label, { + value: "PWLESS_USER_INPUT_CODE_INPUT_LABEL", + "data-supertokens": "codeInputLabel", + }), + jsxRuntime.jsx(ResendButton, { + loginAttemptInfo: props.loginAttemptInfo, + resendEmailOrSMSGapInSeconds: + props.config.signInUpFeature.resendEmailOrSMSGapInSeconds, + onClick: resend, }), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { id: "Group_10395", "data-name": "Group 10395" }, - { - children: [ - jsxRuntime.jsx("path", { - id: "Line_100", - "data-name": "Line 100", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#000", - transform: "translate(725.5 253.5)", - d: "M0 0h9.872", - }), - jsxRuntime.jsx("path", { - id: "Line_101", - "data-name": "Line 101", - strokeWidth: "1.75px", - fill: "none", - strokeLinecap: "round", - stroke: "#fff", - transform: "translate(725.5 255.25)", - d: "M0 0h9.872", - }), - ], - } - ) - ), ], } ) ), - } - ) - ), + autofocus: true, + optional: false, + clearOnSubmit: true, + autoComplete: "one-time-code", + placeholder: "", + validate: recipe$1.userInputCodeValidate, + }, + ], + onSuccess: props.onSuccess, + buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", + callAPI: function (formFields) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var userInputCode, response; + var _a; + return genericComponentOverrideContext.__generator(this, function (_b) { + switch (_b.label) { + case 0: + userInputCode = + (_a = formFields.find(function (field) { + return field.id === "userInputCode"; + })) === null || _a === void 0 + ? void 0 + : _a.value; + if (userInputCode === undefined || userInputCode.length === 0) { + throw new STGeneralError__default.default("GENERAL_ERROR_OTP_UNDEFINED"); + } + return [ + 4 /*yield*/, + props.recipeImplementation.consumeCode({ + userInputCode: userInputCode, + userContext: userContext, + }), + ]; + case 1: + response = _b.sent(); + // We can redirect these statuses, since they all cause a redirection + // and we don't really want to show anything + if ( + response.status === "OK" || + response.status === "RESTART_FLOW_ERROR" || + response.status === "SIGN_IN_UP_NOT_ALLOWED" + ) { + return [2 /*return*/, response]; + } + if (response.status === "INCORRECT_USER_INPUT_CODE_ERROR") { + throw new STGeneralError__default.default("GENERAL_ERROR_OTP_INVALID"); + } + if (response.status === "EXPIRED_USER_INPUT_CODE_ERROR") { + throw new STGeneralError__default.default("GENERAL_ERROR_OTP_EXPIRED"); + } + throw new STGeneralError__default.default("SOMETHING_WENT_WRONG_ERROR"); + } + }); + }); + }, + validateOnBlur: false, + showLabels: true, + footer: + (_a = props.footer) !== null && _a !== void 0 + ? _a + : jsxRuntime.jsx( + UserInputCodeFormFooter, + genericComponentOverrideContext.__assign({}, props, { + loginAttemptInfo: props.loginAttemptInfo, + }) + ), + }), + ], + }); + } +); + +var MFAFooter = uiEntry.withOverride("PasswordlessMFAFooter", function PasswordlessMFAFooter(props) { + var _a, _b; + var t = translationContext.useTranslation(); + var claim = session.useClaimValue(multifactorauth.MultiFactorAuthClaim); + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "footerLinkGroupVert pwlessMFAFooter" }, + { + children: [ + claim.loading === false && + ((_b = (_a = claim.value) === null || _a === void 0 ? void 0 : _a.n.length) !== null && + _b !== void 0 + ? _b + : 0) > 1 && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText", onClick: props.onFactorChooserButtonClicked }, + { children: t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER") } + ) + ), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", + onClick: props.onSignOutClicked, + }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { + color: "rgb(var(--palette-textPrimary))", + }), + t("PWLESS_MFA_FOOTER_LOGOUT"), + ], + } + ) + ), + ], } ) ); -} +}); -var ResendButton = uiEntry.withOverride("PasswordlessResendButton", function PasswordlessResendButton(_a) { +var MFAHeader = uiEntry.withOverride("PasswordlessMFAHeader", function PasswordlessMFAHeader(props) { + var _a; + var t = translationContext.useTranslation(); + var claim = session.useClaimValue(multifactorauth.MultiFactorAuthClaim); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle withBackButton" }, + { + children: [ + claim.loading === false && + ((_a = claim.value) === null || _a === void 0 ? void 0 : _a.n.length) === 0 + ? jsxRuntime.jsx(backButton.BackButton, { onClick: props.onBackButtonClicked }) + : jsxRuntime.jsx("span", { + "data-supertokens": "backButtonPlaceholder backButtonCommon", + }), + props.contactMethod === "EMAIL" + ? t("PWLESS_MFA_HEADER_TITLE_EMAIL") + : t("PWLESS_MFA_HEADER_TITLE_PHONE"), + jsxRuntime.jsx("span", { "data-supertokens": "backButtonPlaceholder backButtonCommon" }), + ], + } + ) + ), + jsxRuntime.jsx("div", { "data-supertokens": "divider" }), + ], + }); +}); + +var MFAOTPFooter = uiEntry.withOverride("PasswordlessMFAOTPFooter", function PasswordlessMFAOTPFooter(_a) { + var _b, _c; var loginAttemptInfo = _a.loginAttemptInfo, - resendEmailOrSMSGapInSeconds = _a.resendEmailOrSMSGapInSeconds, - onClick = _a.onClick; + recipeImplementation = _a.recipeImplementation, + onSignOutClicked = _a.onSignOutClicked, + onFactorChooserButtonClicked = _a.onFactorChooserButtonClicked, + isSetupAllowed = _a.isSetupAllowed; var t = translationContext.useTranslation(); - var getTimeLeft = React.useCallback( - function () { - var timeLeft = loginAttemptInfo.lastResend + resendEmailOrSMSGapInSeconds * 1000 - Date.now(); - return timeLeft < 0 ? undefined : Math.ceil(timeLeft / 1000); - }, - [loginAttemptInfo, resendEmailOrSMSGapInSeconds] - ); - var _b = React.useState(getTimeLeft()), - secsUntilResend = _b[0], - setSecsUntilResend = _b[1]; - React.useEffect( - function () { - // This runs every time the loginAttemptInfo updates, so after every resend - var interval = setInterval(function () { - var timeLeft = getTimeLeft(); - if (timeLeft === undefined) { - clearInterval(interval); - } - setSecsUntilResend(timeLeft); - }, 500); - return function () { - // This can safely run twice - clearInterval(interval); - }; - }, - [getTimeLeft, setSecsUntilResend] - ); - return jsxRuntime.jsx( - "button", + var claim = session.useClaimValue(multifactorauth.MultiFactorAuthClaim); + var userContext = uiEntry.useUserContext(); + return jsxRuntime.jsxs( + "div", genericComponentOverrideContext.__assign( + { "data-supertokens": "footerLinkGroupVert pwlessMFAOTPFooter" }, { - type: "button", - disabled: secsUntilResend !== undefined, - onClick: onClick, - "data-supertokens": "link linkButton resendCodeBtn", - }, - { - children: - secsUntilResend !== undefined - ? jsxRuntime.jsxs(React__namespace.default.Fragment, { - children: [ - t("PWLESS_RESEND_BTN_DISABLED_START"), - jsxRuntime.jsxs("strong", { - children: [ - Math.floor(secsUntilResend / 60) - .toString() - .padStart(2, "0"), - ":", - (secsUntilResend % 60).toString().padStart(2, "0"), - ], - }), - t("PWLESS_RESEND_BTN_DISABLED_END"), - ], - }) - : loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_RESEND_BTN_EMAIL") - : t("PWLESS_RESEND_BTN_PHONE"), + children: [ + isSetupAllowed + ? jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText", + onClick: function () { + return recipeImplementation.clearLoginAttemptInfo({ + userContext: userContext, + }); + }, + }, + { + children: + loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") + : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE"), + } + ) + ) + : claim.loading === false && + ((_c = (_b = claim.value) === null || _b === void 0 ? void 0 : _b.n.length) !== null && + _c !== void 0 + ? _c + : 0) > 1 && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText", onClick: onFactorChooserButtonClicked }, + { children: t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER") } + ) + ), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", + onClick: onSignOutClicked, + }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { + color: "rgb(var(--palette-textPrimary))", + }), + t("PWLESS_MFA_LOGOUT"), + ], + } + ) + ), + ], } ) ); }); -var PasswordlessLinkSent = function (props) { +var MFAOTPHeader = uiEntry.withOverride("PasswordlessMFAOTPHeader", function PasswordlessMFAOTPHeader(_a) { + var _b; + var loginAttemptInfo = _a.loginAttemptInfo, + onBackButtonClicked = _a.onBackButtonClicked, + isSetupAllowed = _a.isSetupAllowed; var t = translationContext.useTranslation(); - var userContext = uiEntry.useUserContext(); - var _a = React.useState(props.error !== undefined ? "ERROR" : "READY"), - status = _a[0], - setStatus = _a[1]; - // Any because node types are included here, messing with return type of setTimeout - var resendNotifTimeout = React.useRef(); - React.useEffect(function () { - return function () { - // This can safely run even if it was cleared before - if (resendNotifTimeout.current) { - clearTimeout(resendNotifTimeout.current); - } - }; - }, []); - var resendEmail = React.useCallback( - function () { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var response, generalError, e_1; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 5, , 6]); - props.clearError(); - response = void 0; - generalError = void 0; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [ - 4 /*yield*/, - props.recipeImplementation.resendCode({ - userContext: userContext, - }), - ]; - case 2: - response = _a.sent(); - return [3 /*break*/, 4]; - case 3: - e_1 = _a.sent(); - if (STGeneralError__default.default.isThisError(e_1)) { - generalError = e_1; - } else { - throw e_1; - } - return [3 /*break*/, 4]; - case 4: - if (response !== undefined && response.status === "OK") { - setStatus("LINK_RESENT"); - resendNotifTimeout.current = setTimeout(function () { - setStatus(function (status) { - return status === "LINK_RESENT" ? "READY" : status; - }); - resendNotifTimeout.current = undefined; - }, 2000); - } else { - setStatus("ERROR"); - if (generalError !== undefined) { - props.onError(generalError.message); - } - } - return [3 /*break*/, 6]; - case 5: - _a.sent(); - setStatus("ERROR"); - return [3 /*break*/, 6]; - case 6: - return [2 /*return*/]; + var claim = session.useClaimValue(multifactorauth.MultiFactorAuthClaim); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle withBackButton" }, + { + children: [ + claim.loading === false && + ((_b = claim.value) === null || _b === void 0 ? void 0 : _b.n.length) === 0 && + isSetupAllowed === false + ? jsxRuntime.jsx(backButton.BackButton, { onClick: onBackButtonClicked }) + : jsxRuntime.jsx("span", { + "data-supertokens": "backButtonPlaceholder backButtonCommon", + }), + t("PWLESS_USER_INPUT_CODE_HEADER_TITLE"), + jsxRuntime.jsx("span", { "data-supertokens": "backButtonPlaceholder backButtonCommon" }), + ], } - }); - }); + ) + ), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerSubtitle secondaryText" }, + { + children: [ + loginAttemptInfo.flowType === "USER_INPUT_CODE" + ? t("PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE") + : t("PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK"), + jsxRuntime.jsx("br", {}), + jsxRuntime.jsx("strong", { children: loginAttemptInfo.contactInfo }), + ], + } + ) + ), + jsxRuntime.jsx("div", { "data-supertokens": "divider" }), + ], + }); +}); + +var MFAScreens; +(function (MFAScreens) { + MFAScreens[(MFAScreens["CloseTab"] = 0)] = "CloseTab"; + MFAScreens[(MFAScreens["EmailForm"] = 1)] = "EmailForm"; + MFAScreens[(MFAScreens["PhoneForm"] = 2)] = "PhoneForm"; + MFAScreens[(MFAScreens["UserInputCodeForm"] = 3)] = "UserInputCodeForm"; + MFAScreens[(MFAScreens["AccessDenied"] = 4)] = "AccessDenied"; +})(MFAScreens || (MFAScreens = {})); +var MFATheme = function (_a) { + var activeScreen = _a.activeScreen, + featureState = _a.featureState, + onBackButtonClicked = _a.onBackButtonClicked, + props = genericComponentOverrideContext.__rest(_a, ["activeScreen", "featureState", "onBackButtonClicked"]); + var t = translationContext.useTranslation(); + var commonProps = { + recipeImplementation: props.recipeImplementation, + config: props.config, + clearError: function () { + return props.dispatch({ type: "setError", error: undefined }); }, - [props.recipeImplementation, props.loginAttemptInfo, props.config, setStatus] - ); - var resendActive = status === "LINK_RESENT"; + onError: function (error) { + return props.dispatch({ type: "setError", error: error }); + }, + error: featureState.error, + }; + if (!featureState.loaded) { + return null; + } + return activeScreen === MFAScreens.CloseTab + ? jsxRuntime.jsx(CloseTabScreen, genericComponentOverrideContext.__assign({}, commonProps)) + : activeScreen === MFAScreens.AccessDenied + ? jsxRuntime.jsx(sessionprebuiltui.AccessDeniedScreen, { useShadowDom: false, error: t(featureState.error) }) + : jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container pwlessMFA" }, + { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: jsxRuntime.jsxs(React__namespace.default.Fragment, { + children: [ + activeScreen === MFAScreens.UserInputCodeForm + ? jsxRuntime.jsx( + MFAOTPHeader, + genericComponentOverrideContext.__assign({}, commonProps, { + loginAttemptInfo: featureState.loginAttemptInfo, + isSetupAllowed: featureState.isSetupAllowed, + onBackButtonClicked: onBackButtonClicked, + }) + ) + : jsxRuntime.jsx(MFAHeader, { + onBackButtonClicked: onBackButtonClicked, + contactMethod: + activeScreen === MFAScreens.EmailForm ? "EMAIL" : "PHONE", + }), + featureState.error !== undefined && + jsxRuntime.jsx(generalError.GeneralError, { + error: featureState.error, + }), + activeScreen === MFAScreens.EmailForm + ? jsxRuntime.jsx( + EmailForm, + genericComponentOverrideContext.__assign({}, commonProps, { + footer: jsxRuntime.jsx( + MFAFooter, + genericComponentOverrideContext.__assign( + {}, + commonProps, + { + onFactorChooserButtonClicked: + props.onFactorChooserButtonClicked, + onSignOutClicked: props.onSignOutClicked, + isSetupAllowed: featureState.isSetupAllowed, + } + ) + ), + }) + ) + : activeScreen === MFAScreens.PhoneForm + ? jsxRuntime.jsx( + PhoneForm, + genericComponentOverrideContext.__assign({}, commonProps, { + footer: jsxRuntime.jsx( + MFAFooter, + genericComponentOverrideContext.__assign( + {}, + commonProps, + { + onFactorChooserButtonClicked: + props.onFactorChooserButtonClicked, + onSignOutClicked: props.onSignOutClicked, + isSetupAllowed: featureState.isSetupAllowed, + } + ) + ), + }) + ) + : activeScreen === MFAScreens.UserInputCodeForm + ? jsxRuntime.jsx( + UserInputCodeForm, + genericComponentOverrideContext.__assign({}, commonProps, { + loginAttemptInfo: featureState.loginAttemptInfo, + onSuccess: props.onSuccess, + footer: jsxRuntime.jsx( + MFAOTPFooter, + genericComponentOverrideContext.__assign( + {}, + commonProps, + { + onFactorChooserButtonClicked: + props.onFactorChooserButtonClicked, + onSignOutClicked: props.onSignOutClicked, + isSetupAllowed: featureState.isSetupAllowed, + loginAttemptInfo: featureState.loginAttemptInfo, + } + ) + ), + }) + ) + : null, + ], + }), + } + ) + ), + jsxRuntime.jsx(SuperTokensBranding.SuperTokensBranding, {}), + ], + } + ) + ); +}; +function MFAThemeWrapper(props) { + var hasFont = translations.hasFontDefined(props.config.rootStyle); + var activeScreen = getActiveScreen$1(props); + var activeStyle; + if (activeScreen === MFAScreens.CloseTab) { + activeStyle = props.config.signInUpFeature.closeTabScreenStyle; + } else if (activeScreen === MFAScreens.UserInputCodeForm) { + activeStyle = props.config.signInUpFeature.userInputCodeFormStyle; + } else if (activeScreen === MFAScreens.EmailForm) { + activeStyle = props.config.signInUpFeature.emailOrPhoneFormStyle; + } else if (activeScreen === MFAScreens.PhoneForm) { + activeStyle = props.config.signInUpFeature.emailOrPhoneFormStyle; + } else { + activeStyle = ""; // styling the access denied screen is handled through the session recipe + } return jsxRuntime.jsx( - "div", + uiEntry.UserContextWrapper, genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, + { userContext: props.userContext }, { - children: jsxRuntime.jsxs( - "div", + children: jsxRuntime.jsx( + ThemeBase, genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, { - children: [ - status === "ERROR" && - jsxRuntime.jsx(generalError.GeneralError, { - error: props.error === undefined ? "SOMETHING_WENT_WRONG_ERROR" : props.error, - }), - resendActive && - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "generalSuccess" }, - { children: t("PWLESS_LINK_SENT_RESEND_SUCCESS") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "sendCodeIcon" }, - { - children: - props.loginAttemptInfo.contactMethod === "EMAIL" - ? jsxRuntime.jsx(checkedRoundIcon.EmailLargeIcon, {}) - : jsxRuntime.jsx(SMSLargeIcon, {}), - } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle headerTinyTitle" }, - { children: t("PWLESS_LINK_SENT_RESEND_TITLE") } - ) - ), - jsxRuntime.jsxs( - "div", + loadDefaultFont: !hasFont, + userStyles: [props.config.rootStyle, activeStyle, props.config.mfaFeature.style], + }, + { + children: jsxRuntime.jsx( + MFATheme, + genericComponentOverrideContext.__assign({}, props, { activeScreen: activeScreen }) + ), + } + ) + ), + } + ) + ); +} +function getActiveScreen$1(props) { + if (props.featureState.successInAnotherTab) { + return MFAScreens.CloseTab; + } else if ( + props.featureState.error === "PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP" || + (props.featureState.isSetupAllowed === false && props.featureState.loginAttemptInfo === undefined) + ) { + return MFAScreens.AccessDenied; + } else if (props.featureState.loginAttemptInfo) { + return MFAScreens.UserInputCodeForm; + } else if (props.contactMethod === "EMAIL") { + return MFAScreens.EmailForm; + } else if (props.contactMethod === "PHONE") { + return MFAScreens.PhoneForm; + } + throw new Error("Couldn't choose active screen; Should never happen"); +} + +var useSuccessInAnotherTabChecker$1 = function (callingConsumeCodeRef, recipeImpl, state, dispatch, userContext) { + React.useEffect( + function () { + // We only need to start checking this if we have an active login attempt + if (state.loginAttemptInfo && !state.successInAnotherTab) { + var checkSessionIntervalHandle_1 = setInterval(function () { + return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { + var currLoginAttempt; + var _a; + return genericComponentOverrideContext.__generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!(callingConsumeCodeRef.current === false)) return [3 /*break*/, 2]; + return [4 /*yield*/, recipeImpl.getLoginAttemptInfo({ userContext: userContext })]; + case 1: + currLoginAttempt = _b.sent(); + if ( + currLoginAttempt === undefined || + currLoginAttempt.deviceId !== + ((_a = state.loginAttemptInfo) === null || _a === void 0 + ? void 0 + : _a.deviceId) + ) { + dispatch({ type: "successInAnotherTab" }); + } + _b.label = 2; + case 2: + return [2 /*return*/]; + } + }); + }); + }, 2000); + return function () { + clearInterval(checkSessionIntervalHandle_1); + }; + } + // Nothing to clean up + return; + }, + [state.loginAttemptInfo, state.successInAnotherTab] + ); +}; +var useFeatureReducer$1 = function () { + return React__namespace.useReducer( + function (oldState, action) { + switch (action.type) { + case "load": + return { + loaded: true, + error: action.error, + loginAttemptInfo: action.loginAttemptInfo, + isSetupAllowed: action.isAllowedToSetup, + successInAnotherTab: false, + }; + case "resendCode": + if (!oldState.loginAttemptInfo) { + return oldState; + } + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { + error: undefined, + loginAttemptInfo: genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState.loginAttemptInfo), + { lastResend: action.timestamp } + ), + } + ); + case "restartFlow": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { error: action.error, loginAttemptInfo: undefined } + ); + case "setError": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { loaded: true, error: action.error } + ); + case "startVerify": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { + loaded: true, + loginAttemptInfo: action.loginAttemptInfo, + error: undefined, + successInAnotherTab: false, + } + ); + case "successInAnotherTab": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { successInAnotherTab: true } + ); + default: + return oldState; + } + }, + { + error: undefined, + loaded: false, + loginAttemptInfo: undefined, + isSetupAllowed: false, + successInAnotherTab: false, + }, + function (initArg) { + var error = undefined; + var errorQueryParam = genericComponentOverrideContext.getQueryParams("error"); + if (errorQueryParam !== null) { + error = "SOMETHING_WENT_WRONG_ERROR"; + } + return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, initArg), { + error: error, + }); + } + ); +}; +function useChildProps$1(recipe$1, recipeImplementation, state, contactMethod, userContext, history) { + var _this = this; + return React.useMemo( + function () { + return { + onSuccess: function () { + var redirectToPath = genericComponentOverrideContext.getRedirectToPathFromURL(); + var redirectInfo = + redirectToPath === undefined + ? undefined + : { + rid: "passwordless", + successRedirectContext: { + action: "SUCCESS", + isNewRecipeUser: false, + user: undefined, + redirectToPath: redirectToPath, + }, + }; + return recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( + redirectInfo, + userContext, + history + ); + }, + onSignOutClicked: function () { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + recipe.Session.getInstanceOrThrow().signOut({ userContext: userContext }), + ]; + case 1: + _a.sent(); + return [ + 4 /*yield*/, + recipeImplementation.clearLoginAttemptInfo({ userContext: userContext }), + ]; + case 2: + _a.sent(); + return [ + 4 /*yield*/, + uiEntry.redirectToAuth({ redirectBack: false, history: history }), + ]; + case 3: + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }, + onBackButtonClicked: function () { + // If we don't have history available this would mean we are not using react-router-dom, so we use window's history + if (history === undefined) { + return windowHandler.WindowHandlerReference.getReferenceOrThrow() + .windowHandler.getWindowUnsafe() + .history.back(); + } + // If we do have history and goBack function on it this means we are using react-router-dom v5 or lower + if (history.goBack !== undefined) { + return history.goBack(); + } + // If we reach this code this means we are using react-router-dom v6 + return history(-1); + }, + onFactorChooserButtonClicked: function () { + return recipe$2.MultiFactorAuth.getInstanceOrThrow().redirectToFactorChooser(false, history); + }, + recipeImplementation: recipeImplementation, + config: recipe$1.config, + contactMethod: contactMethod, + }; + }, + [contactMethod, state, recipeImplementation] + ); +} +var MFAFeature = function (props) { + var recipeComponentOverrides = props.useComponentOverrides(); + var userContext = uiEntry.useUserContext(); + var callingConsumeCodeRef = React.useRef(false); + var _a = useFeatureReducer$1(), + state = _a[0], + dispatch = _a[1]; + var recipeImplementation = React__namespace.useMemo( + function () { + return ( + props.recipe && + getModifiedRecipeImplementation$1( + props.recipe.webJSRecipe, + props.recipe.config, + dispatch, + callingConsumeCodeRef + ) + ); + }, + [props.recipe] + ); + useOnLoad(props, recipeImplementation, dispatch, userContext); + var childProps = useChildProps$1( + props.recipe, + recipeImplementation, + state, + props.contactMethod, + userContext, + props.history + ); + useSuccessInAnotherTabChecker$1(callingConsumeCodeRef, recipeImplementation, state, dispatch, userContext); + return jsxRuntime.jsx( + uiEntry.ComponentOverrideContext.Provider, + genericComponentOverrideContext.__assign( + { value: recipeComponentOverrides }, + { + children: jsxRuntime.jsx( + uiEntry.FeatureWrapper, + genericComponentOverrideContext.__assign( + { + useShadowDom: props.recipe.config.useShadowDom, + defaultStore: defaultTranslationsPasswordless, + }, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + props.children === undefined && + jsxRuntime.jsx( + MFAThemeWrapper, + genericComponentOverrideContext.__assign({}, childProps, { + featureState: state, + dispatch: dispatch, + }) + ), + props.children && + React__namespace.Children.map(props.children, function (child) { + if (React__namespace.isValidElement(child)) { + return React__namespace.cloneElement( + child, + genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, childProps), + { featureState: state, dispatch: dispatch } + ) + ); + } + return child; + }), + ], + }), + } + ) + ), + } + ) + ); +}; +function useOnLoad(props, recipeImplementation, dispatch, userContext) { + var _this = this; + var fetchMFAInfo = React__namespace.useCallback( + function () { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + return [ + 2 /*return*/, + recipe$2.MultiFactorAuth.getInstanceOrThrow().webJSRecipe.getMFAInfo({ + userContext: userContext, + }), + ]; + }); + }); + }, + [userContext] + ); + var handleLoadError = React__namespace.useCallback( + function () { + return dispatch({ type: "setError", error: "SOMETHING_WENT_WRONG_ERROR" }); + }, + [dispatch] + ); + var onLoad = React__namespace.useCallback( + function (mfaInfo) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var error, + errorQueryParam, + doSetup, + loginAttemptInfo, + isAlreadySetup, + isAllowedToSetup, + createCodeInfo, + factorId; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + error = undefined; + errorQueryParam = genericComponentOverrideContext.getQueryParams("error"); + doSetup = genericComponentOverrideContext.getQueryParams("setup"); + if (errorQueryParam !== null) { + error = "SOMETHING_WENT_WRONG_ERROR"; + } + return [ + 4 /*yield*/, + recipeImplementation.getLoginAttemptInfo({ + userContext: userContext, + }), + ]; + case 1: + loginAttemptInfo = _a.sent(); + isAlreadySetup = + props.contactMethod === "EMAIL" + ? mfaInfo.factors.isAlreadySetup.includes("otp-email") + : mfaInfo.factors.isAlreadySetup.includes("otp-phone"); + isAllowedToSetup = + props.contactMethod === "EMAIL" + ? mfaInfo.factors.isAllowedToSetup.includes("otp-email") + : mfaInfo.factors.isAllowedToSetup.includes("otp-phone"); + if (!!loginAttemptInfo) return [3 /*break*/, 8]; + createCodeInfo = + props.contactMethod === "EMAIL" + ? { email: mfaInfo.email } + : { phoneNumber: mfaInfo.phoneNumber }; + factorId = props.contactMethod === "EMAIL" ? "otp-email" : "otp-phone"; + if (!(isAlreadySetup && doSetup !== "true")) return [3 /*break*/, 6]; + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + // createCode also dispatches the necessary events + return [ + 4 /*yield*/, + recipeImplementation.createCode( genericComponentOverrideContext.__assign( - { "data-supertokens": "primaryText sendCodeText" }, - { - children: [ - props.loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_LINK_SENT_RESEND_DESC_START_EMAIL") - : t("PWLESS_LINK_SENT_RESEND_DESC_START_PHONE"), - jsxRuntime.jsx("strong", { - children: props.loginAttemptInfo.contactInfo, - }), - props.loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_LINK_SENT_RESEND_DESC_END_EMAIL") - : t("PWLESS_LINK_SENT_RESEND_DESC_END_PHONE"), - ], - } + genericComponentOverrideContext.__assign({}, createCodeInfo), + { userContext: userContext } ) ), - jsxRuntime.jsx(ResendButton, { - loginAttemptInfo: props.loginAttemptInfo, - resendEmailOrSMSGapInSeconds: - props.config.signInUpFeature.resendEmailOrSMSGapInSeconds, - onClick: resendEmail, - }), - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", - onClick: function () { - return props.recipeImplementation.clearLoginAttemptInfo({ - userContext: userContext, - }); - }, - }, - { - children: [ - jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { - color: "rgb(var(--palette-textPrimary))", - }), - props.loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") - : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE"), - ], + ]; + case 3: + // createCode also dispatches the necessary events + _a.sent(); + return [3 /*break*/, 5]; + case 4: + _a.sent(); + dispatch({ type: "setError", error: "SOMETHING_WENT_WRONG_ERROR" }); + return [3 /*break*/, 5]; + case 5: + return [3 /*break*/, 7]; + case 6: + if (!mfaInfo.factors.isAllowedToSetup.includes(factorId)) { + dispatch({ + type: "load", + loginAttemptInfo: undefined, + isAllowedToSetup: false, + error: "PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP", + }); + } else { + // since loginAttemptInfo is undefined, this will ask the user for the email/phone + dispatch({ + type: "load", + loginAttemptInfo: loginAttemptInfo, + error: error, + isAllowedToSetup: true, + }); + } + _a.label = 7; + case 7: + return [3 /*break*/, 9]; + case 8: + // No need to check if the component is unmounting, since this has no effect then. + dispatch({ + type: "load", + loginAttemptInfo: loginAttemptInfo, + error: error, + isAllowedToSetup: isAllowedToSetup, + }); + _a.label = 9; + case 9: + return [2 /*return*/]; + } + }); + }); + }, + [dispatch, recipeImplementation, props.contactMethod, userContext] + ); + genericComponentOverrideContext.useOnMountAPICall(fetchMFAInfo, onLoad, handleLoadError); +} +function getModifiedRecipeImplementation$1(originalImpl, config, dispatch, callingConsumeCodeRef) { + var _this = this; + return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, originalImpl), { + createCode: function (input) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var contactInfo, phoneNumberUtils, contactMethod, additionalAttemptInfo, res, loginAttemptInfo; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, recipe$1.getPhoneNumberUtils()]; + case 1: + phoneNumberUtils = _a.sent(); + if ("email" in input) { + contactInfo = input.email; + } else { + contactInfo = phoneNumberUtils.formatNumber( + input.phoneNumber, + config.signInUpFeature.defaultCountry || "", + phoneNumberUtils.numberFormat.E164 + ); + } + contactMethod = "email" in input ? "EMAIL" : "PHONE"; + additionalAttemptInfo = { + lastResend: Date.now(), + contactMethod: contactMethod, + contactInfo: contactInfo, + redirectToPath: genericComponentOverrideContext.getRedirectToPathFromURL(), + }; + return [ + 4 /*yield*/, + originalImpl.createCode( + genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, input), + { + userContext: genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, input.userContext), + { additionalAttemptInfo: additionalAttemptInfo } + ), } ) ), - ], + ]; + case 2: + res = _a.sent(); + if (!(res.status === "OK")) return [3 /*break*/, 4]; + return [ + 4 /*yield*/, + originalImpl.getLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 3: + loginAttemptInfo = _a.sent(); + dispatch({ type: "startVerify", loginAttemptInfo: loginAttemptInfo }); + _a.label = 4; + case 4: + return [2 /*return*/, res]; + } + }); + }); + }, + resendCode: function (input) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var res, loginAttemptInfo, timestamp; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, originalImpl.resendCode(input)]; + case 1: + res = _a.sent(); + if (!(res.status === "OK")) return [3 /*break*/, 5]; + return [ + 4 /*yield*/, + originalImpl.getLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 2: + loginAttemptInfo = _a.sent(); + if (!(loginAttemptInfo !== undefined)) return [3 /*break*/, 4]; + timestamp = Date.now(); + return [ + 4 /*yield*/, + originalImpl.setLoginAttemptInfo({ + userContext: input.userContext, + attemptInfo: genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, loginAttemptInfo), + { lastResend: timestamp } + ), + }), + ]; + case 3: + _a.sent(); + dispatch({ type: "resendCode", timestamp: timestamp }); + _a.label = 4; + case 4: + return [3 /*break*/, 7]; + case 5: + if (!(res.status === "RESTART_FLOW_ERROR")) return [3 /*break*/, 7]; + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 6: + _a.sent(); + dispatch({ type: "restartFlow", error: "ERROR_SIGN_IN_UP_RESEND_RESTART_FLOW" }); + _a.label = 7; + case 7: + return [2 /*return*/, res]; + } + }); + }); + }, + consumeCode: function (input) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var res; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + // We need to set call callingConsumeCodeRef to true while consumeCode is running, + // so we don't detect the login attempt disappearing too early and + // go to successInAnotherTab too early + callingConsumeCodeRef.current = true; + return [4 /*yield*/, originalImpl.consumeCode(input)]; + case 1: + res = _a.sent(); + if (!(res.status === "RESTART_FLOW_ERROR")) return [3 /*break*/, 3]; + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 2: + _a.sent(); + dispatch({ type: "restartFlow", error: "ERROR_SIGN_IN_UP_CODE_CONSUME_RESTART_FLOW" }); + return [3 /*break*/, 7]; + case 3: + if (!(res.status === "SIGN_IN_UP_NOT_ALLOWED")) return [3 /*break*/, 5]; + // This should never happen, but technically possible based on the API specs + // so we keep this here to cover all cases + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 4: + // This should never happen, but technically possible based on the API specs + // so we keep this here to cover all cases + _a.sent(); + dispatch({ type: "restartFlow", error: res.reason }); + return [3 /*break*/, 7]; + case 5: + if (!(res.status === "OK")) return [3 /*break*/, 7]; + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 6: + _a.sent(); + _a.label = 7; + case 7: + callingConsumeCodeRef.current = false; + return [2 /*return*/, res]; + } + }); + }); + }, + clearLoginAttemptInfo: function (input) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 1: + _a.sent(); + genericComponentOverrideContext.clearErrorQueryParam(); + dispatch({ type: "restartFlow", error: undefined }); + return [2 /*return*/]; + } + }); + }); + }, + }); +} + +var EmailOrPhoneForm = uiEntry.withOverride( + "PasswordlessEmailOrPhoneForm", + function PasswordlessEmailOrPhoneForm(props) { + var _this = this; + var _a; + var _b = React.useState(false), + isPhoneNumber = _b[0], + setIsPhoneNumber = _b[1]; + var userContext = uiEntry.useUserContext(); + React.useEffect(function () { + // We preload this here, since it will be used almost for sure, but loading it + void recipe$1.preloadPhoneNumberUtils(); + }, []); + var emailOrPhoneInput = React.useMemo( + function () { + return isPhoneNumber + ? phoneNumberInputWithInjectedProps({ + defaultCountry: props.config.signInUpFeature.defaultCountry, + }) + : undefined; + }, + [props.config.signInUpFeature.defaultCountry, isPhoneNumber] + ); + return jsxRuntime.jsx(formBase.FormBase, { + clearError: props.clearError, + onError: props.onError, + formFields: [ + { + id: "emailOrPhone", + label: "PWLESS_SIGN_IN_UP_EMAIL_OR_PHONE_LABEL", + inputComponent: emailOrPhoneInput, + optional: false, + autofocus: true, + placeholder: "", + // We do not add an autocomplete prop in this case, since we do not really have any sensible option to set + // Setting them to either "tel" or "email" would give people the wrong impression since this could have either + // AFAIK we can't set them both at the same time + validate: recipe$1.defaultValidate, + }, + ], + buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", + onSuccess: props.onSuccess, + callAPI: function (formFields, setValue) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var emailOrPhone, + emailValidationRes, + response, + phoneValidationRes, + response, + intPhoneNumber, + phoneValidationResAfterGuess, + response, + ex_1; + var _a; + return genericComponentOverrideContext.__generator(this, function (_b) { + switch (_b.label) { + case 0: + emailOrPhone = + (_a = formFields.find(function (field) { + return field.id === "emailOrPhone"; + })) === null || _a === void 0 + ? void 0 + : _a.value; + if (emailOrPhone === undefined) { + throw new STGeneralError__default.default("GENERAL_ERROR_EMAIL_OR_PHONE_UNDEFINED"); + } + return [4 /*yield*/, recipe$1.defaultEmailValidator(emailOrPhone)]; + case 1: + if (!(_b.sent() === undefined)) return [3 /*break*/, 6]; + return [4 /*yield*/, props.config.validateEmailAddress(emailOrPhone)]; + case 2: + emailValidationRes = _b.sent(); + if (!(emailValidationRes === undefined)) return [3 /*break*/, 4]; + return [ + 4 /*yield*/, + props.recipeImplementation.createCode({ + email: emailOrPhone, + userContext: userContext, + }), + ]; + case 3: + response = _b.sent(); + if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { + throw new STGeneralError__default.default(response.reason); + } + return [2 /*return*/, response]; + case 4: + throw new STGeneralError__default.default(emailValidationRes); + case 5: + return [3 /*break*/, 19]; + case 6: + return [4 /*yield*/, props.config.validatePhoneNumber(emailOrPhone)]; + case 7: + phoneValidationRes = _b.sent(); + if (!(phoneValidationRes === undefined)) return [3 /*break*/, 9]; + return [ + 4 /*yield*/, + props.recipeImplementation.createCode({ + phoneNumber: emailOrPhone, + userContext: userContext, + }), + ]; + case 8: + response = _b.sent(); + if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { + throw new STGeneralError__default.default(response.reason); + } + return [2 /*return*/, response]; + case 9: + return [ + 4 /*yield*/, + props.config.signInUpFeature.guessInternationPhoneNumberFromInputPhoneNumber( + emailOrPhone, + props.config.signInUpFeature.defaultCountry + ), + ]; + case 10: + intPhoneNumber = _b.sent(); + if (!(intPhoneNumber && isPhoneNumber !== true)) return [3 /*break*/, 18]; + return [4 /*yield*/, props.config.validatePhoneNumber(intPhoneNumber)]; + case 11: + phoneValidationResAfterGuess = _b.sent(); + if (!(phoneValidationResAfterGuess === undefined)) return [3 /*break*/, 16]; + _b.label = 12; + case 12: + _b.trys.push([12, 14, , 15]); + return [ + 4 /*yield*/, + props.recipeImplementation.createCode({ + phoneNumber: intPhoneNumber, + userContext: userContext, + }), + ]; + case 13: + response = _b.sent(); + if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { + throw new STGeneralError__default.default(response.reason); + } + return [2 /*return*/, response]; + case 14: + ex_1 = _b.sent(); + // General errors from the API can make createCode throw but we want to switch to the phone UI anyway + setValue("emailOrPhone", intPhoneNumber); + setIsPhoneNumber(true); + throw ex_1; + case 15: + return [3 /*break*/, 17]; + case 16: + // In this case we could get a phonenumber but not a completely valid one + // We want to switch to the phone UI and pre-fill the number + setValue("emailOrPhone", intPhoneNumber); + setIsPhoneNumber(true); + throw new STGeneralError__default.default( + "PWLESS_EMAIL_OR_PHONE_INVALID_INPUT_GUESS_PHONE_ERR" + ); + case 17: + return [3 /*break*/, 19]; + case 18: + throw new STGeneralError__default.default(phoneValidationRes); + case 19: + return [2 /*return*/]; + } + }); + }); + }, + validateOnBlur: false, + showLabels: true, + footer: + (_a = props.footer) !== null && _a !== void 0 + ? _a + : jsxRuntime.jsx(SignInUpFooter, { + privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, + termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, + }), + }); + } +); + +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http="//www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Imports. + */ +/* + * Component. + */ +function SMSLargeIcon() { + return jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { xmlns: "http://www.w3.org/2000/svg", width: "52.013", height: "41.889", viewBox: "0 0 52.013 41.889" }, + { + children: jsxRuntime.jsx( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10400", "data-name": "Group 10400", transform: "translate(-724.625 -241.125)" }, + { + children: jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10399", "data-name": "Group 10399" }, + { + children: [ + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10398", "data-name": "Group 10398" }, + { + children: [ + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { + id: "_2639922_sms_icon", + "data-name": "2639922_sms_icon", + transform: "translate(732.916 242)", + }, + { + children: [ + jsxRuntime.jsx("path", { + id: "Union_52", + "data-name": "Union 52", + d: "M7.124 37.96a6.26 6.26 0 0 0 3.652-5H6.593A6.592 6.592 0 0 1 0 26.367V6.592A6.592 6.592 0 0 1 6.593 0h29.664a6.592 6.592 0 0 1 6.593 6.592v19.775a6.592 6.592 0 0 1-6.593 6.592h-17.68a13.355 13.355 0 0 1-11.159 6.576zm20.893-21.48a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.3 3.3zm-9.887 0a3.3 3.3 0 1 0 3.3-3.3 3.295 3.295 0 0 0-3.3 3.3zm-9.888 0a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.301 3.3z", + transform: "translate(-.001)", + strokeWidth: "1.75px", + stroke: "#000", + fill: "#c4f3ff", + }), + jsxRuntime.jsx("ellipse", { + id: "Ellipse_3013", + "data-name": "Ellipse 3013", + cy: ".917", + ry: ".917", + transform: "translate(7.335 38.506)", + stroke: "#000", + fill: "#c4f3ff", + }), + ], + } + ) + ), + jsxRuntime.jsx("path", { + id: "Intersection_2", + "data-name": "Intersection 2", + fill: "#8ae7ff", + d: "M177.409-21836.576v-.33l-.214-1.131a6.271 6.271 0 0 0 3.651-5h-4.184a6.59 6.59 0 0 1-6.512-5.588h42.495a7.846 7.846 0 0 1-1.607 3.605 6.576 6.576 0 0 1-4.712 1.982h-14.845c-1.545-.09-2.537-.164-2.537-.164l-.077.164h-.219a13.342 13.342 0 0 1-11.156 6.572l-.082-.439z", + transform: "translate(562.766 22118)", + }), + jsxRuntime.jsx("path", { + id: "Intersection_1", + "data-name": "Intersection 1", + fill: "#8ae7ff", + d: "M209.246-21846.41s.494-22.641 0-25.178a8.7 8.7 0 0 0-2.767-4.41 6.6 6.6 0 0 1 6.369 6.59v19.775a6.6 6.6 0 0 1-5.724 6.537 6.213 6.213 0 0 0 2.122-3.314z", + transform: "translate(561.882 22118.172)", + }), + ], + } + ) + ), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { + id: "_2639922_sms_icon-2", + "data-name": "2639922_sms_icon", + transform: "translate(732.916 242.174)", + }, + { + children: [ + jsxRuntime.jsx("path", { + id: "Union_52-2", + "data-name": "Union 52", + d: "M7.124 37.96a6.26 6.26 0 0 0 3.652-5H6.593A6.592 6.592 0 0 1 0 26.367V6.592A6.592 6.592 0 0 1 6.593 0h29.664a6.592 6.592 0 0 1 6.593 6.592v19.775a6.592 6.592 0 0 1-6.593 6.592h-17.68a13.355 13.355 0 0 1-11.159 6.576zm20.893-21.48a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.3 3.3zm-9.887 0a3.3 3.3 0 1 0 3.3-3.3 3.295 3.295 0 0 0-3.3 3.3zm-9.888 0a3.3 3.3 0 1 0 3.3-3.3 3.3 3.3 0 0 0-3.301 3.3z", + transform: "translate(-.001)", + fill: "none", + strokeWidth: "1.75px", + stroke: "#000", + }), + jsxRuntime.jsx("ellipse", { + id: "Ellipse_3013-2", + "data-name": "Ellipse 3013", + cy: ".917", + ry: ".917", + transform: "translate(7.335 38.506)", + fill: "none", + stroke: "#000", + }), + ], + } + ) + ), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10397", "data-name": "Group 10397" }, + { + children: [ + jsxRuntime.jsx("path", { + id: "Line_104", + "data-name": "Line 104", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#000", + transform: "translate(725.5 266.84)", + d: "M0 0h9.872", + }), + jsxRuntime.jsx("path", { + id: "Line_105", + "data-name": "Line 105", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#fff", + transform: "translate(725.5 268.59)", + d: "M0 0h9.872", + }), + ], + } + ) + ), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10396", "data-name": "Group 10396" }, + { + children: [ + jsxRuntime.jsx("path", { + id: "Line_103", + "data-name": "Line 103", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#000", + transform: "translate(725.5 260.17)", + d: "M0 0h12.461", + }), + jsxRuntime.jsx("path", { + id: "Line_102", + "data-name": "Line 102", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#fff", + transform: "translate(725.5 261.92)", + d: "M0 0h12.461", + }), + ], + } + ) + ), + jsxRuntime.jsx("path", { + id: "Path_91918", + "data-name": "Path 91918", + fill: "#8ae7ff", + d: "M599.827 22145.373a1.62 1.62 0 0 0 1.38-1.336c.247-1.234.267 1.752.267 1.752l-1.647-.178z", + transform: "translate(170 -21876)", + }), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { id: "Group_10395", "data-name": "Group 10395" }, + { + children: [ + jsxRuntime.jsx("path", { + id: "Line_100", + "data-name": "Line 100", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#000", + transform: "translate(725.5 253.5)", + d: "M0 0h9.872", + }), + jsxRuntime.jsx("path", { + id: "Line_101", + "data-name": "Line 101", + strokeWidth: "1.75px", + fill: "none", + strokeLinecap: "round", + stroke: "#fff", + transform: "translate(725.5 255.25)", + d: "M0 0h9.872", + }), + ], + } + ) + ), + ], + } + ) + ), } ) ), } ) ); -}; -var LinkSent = uiEntry.withOverride("PasswordlessLinkSent", PasswordlessLinkSent); +} -var PhoneForm = uiEntry.withOverride("PasswordlessPhoneForm", function PasswordlessPhoneForm(props) { - var _this = this; +var PasswordlessLinkSent = function (props) { + var t = translationContext.useTranslation(); var userContext = uiEntry.useUserContext(); + var _a = React.useState(props.error !== undefined ? "ERROR" : "READY"), + status = _a[0], + setStatus = _a[1]; + // Any because node types are included here, messing with return type of setTimeout + var resendNotifTimeout = React.useRef(); React.useEffect(function () { - // We preload this here, since it will be used almost for sure, but loading it - void recipe$1.preloadPhoneNumberUtils(); + return function () { + // This can safely run even if it was cleared before + if (resendNotifTimeout.current) { + clearTimeout(resendNotifTimeout.current); + } + }; }, []); - var phoneInput = React.useMemo( + var resendEmail = React.useCallback( function () { - return phoneNumberInputWithInjectedProps({ - defaultCountry: props.config.signInUpFeature.defaultCountry, - }); - }, - [props.config.signInUpFeature.defaultCountry] - ); - return jsxRuntime.jsx(formBase.FormBase, { - clearError: props.clearError, - onError: props.onError, - formFields: [ - { - id: "phoneNumber", - label: "PWLESS_SIGN_IN_UP_PHONE_LABEL", - inputComponent: phoneInput, - optional: false, - autofocus: true, - placeholder: "", - autoComplete: "tel", - validate: validators.defaultValidate, - }, - ], - buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", - onSuccess: props.onSuccess, - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var phoneNumber, validationRes, response; - var _a; - return genericComponentOverrideContext.__generator(this, function (_b) { - switch (_b.label) { - case 0: - phoneNumber = - (_a = formFields.find(function (field) { - return field.id === "phoneNumber"; - })) === null || _a === void 0 - ? void 0 - : _a.value; - if (phoneNumber === undefined) { - throw new STGeneralError__default.default("GENERAL_ERROR_PHONE_UNDEFINED"); - } - return [4 /*yield*/, props.config.validatePhoneNumber(phoneNumber)]; - case 1: - validationRes = _b.sent(); - if (validationRes !== undefined) { - throw new STGeneralError__default.default(validationRes); - } - return [ - 4 /*yield*/, - props.recipeImplementation.createCode({ - phoneNumber: phoneNumber, - userContext: userContext, - }), - ]; - case 2: - response = _b.sent(); - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); - } - return [2 /*return*/, response]; - } - }); - }); - }, - validateOnBlur: false, - showLabels: true, - footer: jsxRuntime.jsx(SignInUpFooter, { - privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, - termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, - }), - }); -}); - -var SignInUpHeader = uiEntry.withOverride("PasswordlessSignInUpHeader", function PasswordlessSignInUpHeader() { - var t = translationContext.useTranslation(); - return jsxRuntime.jsxs(React.Fragment, { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("PWLESS_SIGN_IN_UP_HEADER_TITLE") } - ) - ), - jsxRuntime.jsx("div", { "data-supertokens": "divider" }), - ], - }); -}); - -var UserInputCodeFormFooter = uiEntry.withOverride( - "PasswordlessUserInputCodeFormFooter", - function PasswordlessUserInputCodeFormFooter(_a) { - var loginAttemptInfo = _a.loginAttemptInfo, - recipeImplementation = _a.recipeImplementation; - var t = translationContext.useTranslation(); - var userContext = uiEntry.useUserContext(); - return jsxRuntime.jsx(React.Fragment, { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", - onClick: function () { - return recipeImplementation.clearLoginAttemptInfo({ - userContext: userContext, - }); - }, - }, - { - children: [ - jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { color: "rgb(var(--palette-textPrimary))" }), - loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") - : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE"), - ], - } - ) - ), - }); - } -); - -var UserInputCodeForm = uiEntry.withOverride( - "PasswordlessUserInputCodeForm", - function PasswordlessUserInputCodeForm(props) { - var _this = this; - var t = translationContext.useTranslation(); - var userContext = uiEntry.useUserContext(); - // We need this any because the node types are also loaded - var _a = React.useState(), - clearResendNotifTimeout = _a[0], - setClearResendNotifTimeout = _a[1]; - React.useEffect( - function () { - // This is just to clean up on unmount and if the clear timeout changes - return function () { - clearTimeout(clearResendNotifTimeout); - }; - }, - [clearResendNotifTimeout] - ); - function resend() { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { var response, generalError, e_1; return genericComponentOverrideContext.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 5, , 6]); + props.clearError(); response = void 0; generalError = void 0; _a.label = 1; @@ -3560,141 +4560,149 @@ var UserInputCodeForm = uiEntry.withOverride( } return [3 /*break*/, 4]; case 4: - if (generalError !== undefined) { - props.onError(generalError.message); + if (response !== undefined && response.status === "OK") { + setStatus("LINK_RESENT"); + resendNotifTimeout.current = setTimeout(function () { + setStatus(function (status) { + return status === "LINK_RESENT" ? "READY" : status; + }); + resendNotifTimeout.current = undefined; + }, 2000); } else { - if (response === undefined) { - throw new Error("Should not come here"); - } - if (response.status === "OK") { - setClearResendNotifTimeout( - setTimeout(function () { - setClearResendNotifTimeout(undefined); - }, 2000) - ); + setStatus("ERROR"); + if (generalError !== undefined) { + props.onError(generalError.message); } } return [3 /*break*/, 6]; case 5: _a.sent(); - props.onError("SOMETHING_WENT_WRONG_ERROR"); + setStatus("ERROR"); return [3 /*break*/, 6]; case 6: return [2 /*return*/]; } }); }); - } - return jsxRuntime.jsxs(React__namespace.default.Fragment, { - children: [ - clearResendNotifTimeout !== undefined && - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "generalSuccess" }, - { - children: - props.loginAttemptInfo.contactMethod === "EMAIL" - ? t("PWLESS_RESEND_SUCCESS_EMAIL") - : t("PWLESS_RESEND_SUCCESS_PHONE"), - } - ) - ), - jsxRuntime.jsx(formBase.FormBase, { - clearError: props.clearError, - onError: props.onError, - formFields: [ + }, + [props.recipeImplementation, props.loginAttemptInfo, props.config, setStatus] + ); + var resendActive = status === "LINK_RESENT"; + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, { - id: "userInputCode", - label: "", - labelComponent: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "codeInputLabelWrapper" }, - { - children: [ - jsxRuntime.jsx(formBase.Label, { - value: "PWLESS_USER_INPUT_CODE_INPUT_LABEL", - "data-supertokens": "codeInputLabel", - }), - jsxRuntime.jsx(ResendButton, { - loginAttemptInfo: props.loginAttemptInfo, - resendEmailOrSMSGapInSeconds: - props.config.signInUpFeature.resendEmailOrSMSGapInSeconds, - onClick: resend, - }), - ], - } - ) - ), - autofocus: true, - optional: false, - clearOnSubmit: true, - autoComplete: "one-time-code", - placeholder: "", - validate: recipe$1.userInputCodeValidate, - }, - ], - onSuccess: props.onSuccess, - buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var userInputCode, response; - var _a; - return genericComponentOverrideContext.__generator(this, function (_b) { - switch (_b.label) { - case 0: - userInputCode = - (_a = formFields.find(function (field) { - return field.id === "userInputCode"; - })) === null || _a === void 0 - ? void 0 - : _a.value; - if (userInputCode === undefined || userInputCode.length === 0) { - throw new STGeneralError__default.default("GENERAL_ERROR_OTP_UNDEFINED"); - } - return [ - 4 /*yield*/, - props.recipeImplementation.consumeCode({ - userInputCode: userInputCode, - userContext: userContext, - }), - ]; - case 1: - response = _b.sent(); - // We can redirect these statuses, since they all cause a redirection - // and we don't really want to show anything - if ( - response.status === "OK" || - response.status === "RESTART_FLOW_ERROR" || - response.status === "SIGN_IN_UP_NOT_ALLOWED" - ) { - return [2 /*return*/, response]; + children: [ + status === "ERROR" && + jsxRuntime.jsx(generalError.GeneralError, { + error: props.error === undefined ? "SOMETHING_WENT_WRONG_ERROR" : props.error, + }), + resendActive && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "generalSuccess" }, + { children: t("PWLESS_LINK_SENT_RESEND_SUCCESS") } + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "sendCodeIcon" }, + { + children: + props.loginAttemptInfo.contactMethod === "EMAIL" + ? jsxRuntime.jsx(checkedRoundIcon.EmailLargeIcon, {}) + : jsxRuntime.jsx(SMSLargeIcon, {}), } - if (response.status === "INCORRECT_USER_INPUT_CODE_ERROR") { - throw new STGeneralError__default.default("GENERAL_ERROR_OTP_INVALID"); + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle headerTinyTitle" }, + { children: t("PWLESS_LINK_SENT_RESEND_TITLE") } + ) + ), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "primaryText sendCodeText" }, + { + children: [ + props.loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_LINK_SENT_RESEND_DESC_START_EMAIL") + : t("PWLESS_LINK_SENT_RESEND_DESC_START_PHONE"), + jsxRuntime.jsx("strong", { + children: props.loginAttemptInfo.contactInfo, + }), + props.loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_LINK_SENT_RESEND_DESC_END_EMAIL") + : t("PWLESS_LINK_SENT_RESEND_DESC_END_PHONE"), + ], } - if (response.status === "EXPIRED_USER_INPUT_CODE_ERROR") { - throw new STGeneralError__default.default("GENERAL_ERROR_OTP_EXPIRED"); + ) + ), + jsxRuntime.jsx(ResendButton, { + loginAttemptInfo: props.loginAttemptInfo, + resendEmailOrSMSGapInSeconds: + props.config.signInUpFeature.resendEmailOrSMSGapInSeconds, + onClick: resendEmail, + }), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", + onClick: function () { + return props.recipeImplementation.clearLoginAttemptInfo({ + userContext: userContext, + }); + }, + }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { + color: "rgb(var(--palette-textPrimary))", + }), + props.loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") + : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE"), + ], } - throw new STGeneralError__default.default("SOMETHING_WENT_WRONG_ERROR"); - } - }); - }); - }, - validateOnBlur: false, - showLabels: true, - footer: jsxRuntime.jsx( - UserInputCodeFormFooter, - genericComponentOverrideContext.__assign({}, props, { - loginAttemptInfo: props.loginAttemptInfo, - }) - ), - }), - ], - }); - } -); + ) + ), + ], + } + ) + ), + } + ) + ); +}; +var LinkSent = uiEntry.withOverride("PasswordlessLinkSent", PasswordlessLinkSent); + +var SignInUpHeader = uiEntry.withOverride("PasswordlessSignInUpHeader", function PasswordlessSignInUpHeader() { + var t = translationContext.useTranslation(); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle" }, + { children: t("PWLESS_SIGN_IN_UP_HEADER_TITLE") } + ) + ), + jsxRuntime.jsx("div", { "data-supertokens": "divider" }), + ], + }); +}); var UserInputCodeFormHeader = uiEntry.withOverride( "PasswordlessUserInputCodeFormHeader", @@ -3831,7 +4839,8 @@ var SignInUpTheme = function (_a) { }; function SignInUpThemeWrapper(props) { var hasFont = translations.hasFontDefined(props.config.rootStyle); - var activeScreen = getActiveScreen(props); + var currentDynamicLoginMethods = uiEntry.useDynamicLoginMethods(); + var activeScreen = getActiveScreen(props, currentDynamicLoginMethods); var activeStyle; if (activeScreen === exports.SignInUpScreens.CloseTab) { activeStyle = props.config.signInUpFeature.closeTabScreenStyle; @@ -3867,19 +4876,23 @@ function SignInUpThemeWrapper(props) { ) ); } -function getActiveScreen(props) { +function getActiveScreen(props, currentDynamicLoginMethods) { + var enabledContactMethods = recipe$1.getEnabledContactMethods( + props.config.contactMethod, + currentDynamicLoginMethods + ); if (props.featureState.successInAnotherTab) { return exports.SignInUpScreens.CloseTab; } else if (props.featureState.loginAttemptInfo && props.featureState.loginAttemptInfo.flowType === "MAGIC_LINK") { return exports.SignInUpScreens.LinkSent; } else if (props.featureState.loginAttemptInfo) { return exports.SignInUpScreens.UserInputCodeForm; - } else if (props.config.contactMethod === "EMAIL") { + } else if (enabledContactMethods.length > 1) { + return exports.SignInUpScreens.EmailOrPhoneForm; + } else if (enabledContactMethods[0] === "EMAIL") { return exports.SignInUpScreens.EmailForm; - } else if (props.config.contactMethod === "PHONE") { + } else if (enabledContactMethods[0] === "PHONE") { return exports.SignInUpScreens.PhoneForm; - } else if (props.config.contactMethod === "EMAIL_OR_PHONE") { - return exports.SignInUpScreens.EmailOrPhoneForm; } throw new Error("Couldn't choose active screen; Should never happen"); } @@ -4370,6 +5383,32 @@ var PasswordlessPreBuiltUI = /** @class */ (function (_super) { recipeID: recipe$1.Passwordless.RECIPE_ID, }; } + if (_this.recipeInstance.config.mfaFeature.disableDefaultUI !== true) { + var normalisedFullPathPhone = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath__default.default("/mfa/otp-phone") + ); + features[normalisedFullPathPhone.getAsStringDangerous()] = { + matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( + _this.recipeInstance.config.recipeId + ), + component: function (props) { + return _this.getFeatureComponent("otp-phone", props, useComponentOverrides); + }, + recipeID: recipe$1.Passwordless.RECIPE_ID, + }; + var normalisedFullPathEmail = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath__default.default("/mfa/otp-email") + ); + features[normalisedFullPathEmail.getAsStringDangerous()] = { + matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( + _this.recipeInstance.config.recipeId + ), + component: function (props) { + return _this.getFeatureComponent("otp-email", props, useComponentOverrides); + }, + recipeID: recipe$1.Passwordless.RECIPE_ID, + }; + } return features; }; _this.getFeatureComponent = function (componentName, props, useComponentOverrides) { @@ -4437,9 +5476,76 @@ var PasswordlessPreBuiltUI = /** @class */ (function (_super) { } ) ); - } else { - throw new Error("Should never come here."); } + if (componentName === "otp-email") { + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + session.SessionAuth, + genericComponentOverrideContext.__assign( + { + overrideGlobalClaimValidators: function () { + return []; + }, + }, + { + children: jsxRuntime.jsx( + MFAFeature, + genericComponentOverrideContext.__assign( + { + recipe: _this.recipeInstance, + useComponentOverrides: useComponentOverrides, + contactMethod: "EMAIL", + flowType: "USER_INPUT_CODE", + }, + props + ) + ), + } + ) + ), + } + ) + ); + } + if (componentName === "otp-phone") { + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + session.SessionAuth, + genericComponentOverrideContext.__assign( + { + overrideGlobalClaimValidators: function () { + return []; + }, + }, + { + children: jsxRuntime.jsx( + MFAFeature, + genericComponentOverrideContext.__assign( + { + recipe: _this.recipeInstance, + useComponentOverrides: useComponentOverrides, + contactMethod: "PHONE", + flowType: "USER_INPUT_CODE", + }, + props + ) + ), + } + ) + ), + } + ) + ); + } + throw new Error("Should never come here."); }; return _this; } @@ -4486,17 +5592,27 @@ var PasswordlessPreBuiltUI = /** @class */ (function (_super) { PasswordlessPreBuiltUI.LinkClicked = function (prop) { return _a.getFeatureComponent("linkClickedScreen", prop); }; + PasswordlessPreBuiltUI.MfaOtpPhone = function (prop) { + return _a.getFeatureComponent("otp-phone", prop); + }; + PasswordlessPreBuiltUI.MfaOtpEmail = function (prop) { + return _a.getFeatureComponent("otp-email", prop); + }; PasswordlessPreBuiltUI.SignInUpTheme = SignInUpThemeWrapper; return PasswordlessPreBuiltUI; })(uiEntry.RecipeRouter); var SignInUp = PasswordlessPreBuiltUI.SignInUp; var LinkClicked = PasswordlessPreBuiltUI.LinkClicked; +var MfaOtpPhone = PasswordlessPreBuiltUI.MfaOtpPhone; +var MfaOtpEmail = PasswordlessPreBuiltUI.MfaOtpEmail; exports.CloseTabScreen = CloseTabScreen; exports.EmailForm = EmailForm; exports.EmailOrPhoneForm = EmailOrPhoneForm; exports.LinkClicked = LinkClicked; exports.LinkSent = LinkSent; +exports.MfaOtpEmail = MfaOtpEmail; +exports.MfaOtpPhone = MfaOtpPhone; exports.PasswordlessPreBuiltUI = PasswordlessPreBuiltUI; exports.PhoneForm = PhoneForm; exports.SignInUp = SignInUp; diff --git a/lib/build/passwordless.js b/lib/build/passwordless.js index f8cba3862..ce950e342 100644 --- a/lib/build/passwordless.js +++ b/lib/build/passwordless.js @@ -20,6 +20,9 @@ require("./authRecipe-shared.js"); require("./recipeModule-shared.js"); require("./session-shared2.js"); require("supertokens-web-js/recipe/session"); +require("./multifactorauth-shared.js"); +require("supertokens-web-js/recipe/multifactorauth"); +require("supertokens-web-js/utils/sessionClaimValidatorStore"); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * diff --git a/lib/build/passwordlessprebuiltui.js b/lib/build/passwordlessprebuiltui.js index 68f6309d0..b360b58e7 100644 --- a/lib/build/passwordlessprebuiltui.js +++ b/lib/build/passwordlessprebuiltui.js @@ -5,6 +5,7 @@ require("react/jsx-runtime"); require("supertokens-web-js/utils/normalisedURLPath"); require("./index2.js"); require("./authRecipe-shared2.js"); +require("./session-shared.js"); require("./passwordless-shared.js"); var passwordlessprebuiltui = require("./passwordless-shared3.js"); require("./passwordless-shared2.js"); @@ -25,21 +26,25 @@ require("supertokens-web-js/utils/sessionClaimValidatorStore"); require("./recipeModule-shared.js"); require("./session-shared2.js"); require("supertokens-web-js/recipe/session"); -require("./session-shared.js"); require("./session-shared3.js"); require("supertokens-web-js/utils/error"); require("./translations.js"); require("./emailpassword-shared2.js"); require("./SuperTokensBranding.js"); require("./emailpassword-shared.js"); +require("./sessionprebuiltui.js"); +require("./arrowLeftIcon.js"); require("./checkedRoundIcon.js"); require("./emailpassword-shared8.js"); require("./emailpassword-shared5.js"); -require("./arrowLeftIcon.js"); +require("./multifactorauth-shared2.js"); +require("./emailpassword-shared7.js"); require("supertokens-web-js/recipe/passwordless"); require("./authRecipe-shared.js"); exports.LinkClicked = passwordlessprebuiltui.LinkClicked; +exports.MfaOtpEmail = passwordlessprebuiltui.MfaOtpEmail; +exports.MfaOtpPhone = passwordlessprebuiltui.MfaOtpPhone; exports.PasswordlessPreBuiltUI = passwordlessprebuiltui.PasswordlessPreBuiltUI; exports.SignInUp = passwordlessprebuiltui.SignInUp; exports.SignInUpTheme = passwordlessprebuiltui.SignInUpThemeWrapper; diff --git a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts index 8ff8a9b05..bcc6e2b05 100644 --- a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts @@ -1,7 +1,7 @@ /// export declare const ResetPasswordEmail: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; + formFields: Omit[]; error: string | undefined; } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; diff --git a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/submitNewPassword.d.ts b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/submitNewPassword.d.ts index b8ec36fd7..9c795dce2 100644 --- a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/submitNewPassword.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/submitNewPassword.d.ts @@ -1,7 +1,7 @@ /// export declare const SubmitNewPassword: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; + formFields: Omit[]; error: string | undefined; } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts index 2b40c960b..64639bb96 100644 --- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts @@ -1,7 +1,7 @@ /// export declare const SignIn: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; + formFields: Omit[]; error: string | undefined; } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts index 7dbc1321c..f57175ca5 100644 --- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts @@ -1,7 +1,7 @@ /// export declare const SignInForm: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; + formFields: Omit[]; error: string | undefined; } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts index 380a6e333..32bc386b1 100644 --- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts @@ -1,14 +1,13 @@ /// export declare const SignUp: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; - error: string | undefined; - } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; clearError: () => void; onError: (error: string) => void; config: import("../../../types").NormalisedConfig; signInClicked?: (() => void) | undefined; onSuccess: (result: { user: import("supertokens-web-js/types").User }) => void; + formFields: import("../../../types").FormFieldThemeProps[]; + error: string | undefined; } >; diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts index bbe4a2eb2..85b7e4c8d 100644 --- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts +++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts @@ -1,15 +1,14 @@ /// export declare const SignUpForm: import("react").ComponentType< import("../../../../../types").ThemeBaseProps & { - formFields: import("../../../types").FormFieldThemeProps[]; - error: string | undefined; - } & { recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface; clearError: () => void; onError: (error: string) => void; config: import("../../../types").NormalisedConfig; signInClicked?: (() => void) | undefined; onSuccess: (result: { user: import("supertokens-web-js/types").User }) => void; + formFields: import("../../../types").FormFieldThemeProps[]; + error: string | undefined; } & { header?: JSX.Element | undefined; footer?: JSX.Element | undefined; diff --git a/lib/build/recipe/passwordless/components/features/mfa/index.d.ts b/lib/build/recipe/passwordless/components/features/mfa/index.d.ts new file mode 100644 index 000000000..2b32343e7 --- /dev/null +++ b/lib/build/recipe/passwordless/components/features/mfa/index.d.ts @@ -0,0 +1,32 @@ +import * as React from "react"; +import type { FeatureBaseProps } from "../../../../../types"; +import type Recipe from "../../../recipe"; +import type { ComponentOverrideMap, MFAChildProps } from "../../../types"; +import type { MFAAction, MFAState } from "../../../types"; +import type { RecipeInterface } from "supertokens-web-js/recipe/passwordless"; +import type { PasswordlessFlowType } from "supertokens-web-js/recipe/thirdpartypasswordless"; +export declare const useSuccessInAnotherTabChecker: ( + callingConsumeCodeRef: React.MutableRefObject, + recipeImpl: RecipeInterface, + state: MFAState, + dispatch: React.Dispatch, + userContext: any +) => void; +export declare const useFeatureReducer: () => [MFAState, React.Dispatch]; +export declare function useChildProps( + recipe: Recipe, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", + userContext: any, + history: any +): MFAChildProps; +export declare const MFAFeature: React.FC< + FeatureBaseProps & { + contactMethod: "PHONE" | "EMAIL"; + flowType: PasswordlessFlowType; + recipe: Recipe; + useComponentOverrides: () => ComponentOverrideMap; + } +>; +export default MFAFeature; diff --git a/lib/build/recipe/passwordless/components/themes/mfa/index.d.ts b/lib/build/recipe/passwordless/components/themes/mfa/index.d.ts new file mode 100644 index 000000000..bdc60d2d1 --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/index.d.ts @@ -0,0 +1,12 @@ +/// +import type { MFAProps } from "../../../types"; +export declare enum MFAScreens { + CloseTab = 0, + EmailForm = 1, + PhoneForm = 2, + UserInputCodeForm = 3, + AccessDenied = 4, +} +declare function MFAThemeWrapper(props: MFAProps): JSX.Element; +export default MFAThemeWrapper; +export declare function getActiveScreen(props: Pick): MFAScreens; diff --git a/lib/build/recipe/passwordless/components/themes/mfa/mfaFooter.d.ts b/lib/build/recipe/passwordless/components/themes/mfa/mfaFooter.d.ts new file mode 100644 index 000000000..400242689 --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/mfaFooter.d.ts @@ -0,0 +1,3 @@ +/// +import type { MFAFooterProps } from "../../../types"; +export declare const MFAFooter: import("react").ComponentType; diff --git a/lib/build/recipe/passwordless/components/themes/mfa/mfaHeader.d.ts b/lib/build/recipe/passwordless/components/themes/mfa/mfaHeader.d.ts new file mode 100644 index 000000000..20436f4ba --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/mfaHeader.d.ts @@ -0,0 +1,5 @@ +/// +export declare const MFAHeader: import("react").ComponentType<{ + contactMethod: "EMAIL" | "PHONE"; + onBackButtonClicked: () => void; +}>; diff --git a/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPFooter.d.ts b/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPFooter.d.ts new file mode 100644 index 000000000..f71b639fc --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPFooter.d.ts @@ -0,0 +1,3 @@ +/// +import type { MFAOTPFooterProps } from "../../../types"; +export declare const MFAOTPFooter: import("react").ComponentType; diff --git a/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPHeader.d.ts b/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPHeader.d.ts new file mode 100644 index 000000000..f95966180 --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/mfaOTPHeader.d.ts @@ -0,0 +1,3 @@ +/// +import type { MFAOTPHeaderProps } from "../../../types"; +export declare const MFAOTPHeader: import("react").ComponentType; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/emailForm.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/emailForm.d.ts index ecf6f7a4d..41ef958b1 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/emailForm.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/emailForm.d.ts @@ -1,3 +1,7 @@ /// import type { SignInUpEmailFormProps } from "../../../types"; -export declare const EmailForm: import("react").ComponentType; +export declare const EmailForm: import("react").ComponentType< + SignInUpEmailFormProps & { + footer?: JSX.Element | undefined; + } +>; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.d.ts index 944b6e423..9db710975 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.d.ts @@ -1,3 +1,7 @@ /// import type { SignInUpEmailOrPhoneFormProps } from "../../../types"; -export declare const EmailOrPhoneForm: import("react").ComponentType; +export declare const EmailOrPhoneForm: import("react").ComponentType< + SignInUpEmailOrPhoneFormProps & { + footer?: JSX.Element | undefined; + } +>; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/index.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/index.d.ts index db29249a5..e7b8a7537 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/index.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/index.d.ts @@ -1,4 +1,5 @@ /// +import type { DynamicLoginMethodsContextValue } from "../../../../multitenancy/dynamicLoginMethodsContext"; import type { SignInUpProps } from "../../../types"; export declare enum SignInUpScreens { CloseTab = 0, @@ -10,4 +11,7 @@ export declare enum SignInUpScreens { } declare function SignInUpThemeWrapper(props: SignInUpProps): JSX.Element; export default SignInUpThemeWrapper; -export declare function getActiveScreen(props: Pick): SignInUpScreens; +export declare function getActiveScreen( + props: Pick, + currentDynamicLoginMethods: DynamicLoginMethodsContextValue +): SignInUpScreens; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/phoneForm.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/phoneForm.d.ts index d19b4dbe1..cced54acb 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/phoneForm.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/phoneForm.d.ts @@ -1,3 +1,7 @@ /// import type { SignInUpPhoneFormProps } from "../../../types"; -export declare const PhoneForm: import("react").ComponentType; +export declare const PhoneForm: import("react").ComponentType< + SignInUpPhoneFormProps & { + footer?: JSX.Element | undefined; + } +>; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/userInputCodeForm.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/userInputCodeForm.d.ts index 52d820aba..c2abc87e7 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/userInputCodeForm.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/userInputCodeForm.d.ts @@ -2,7 +2,6 @@ import React from "react"; import type { SignInUpUserInputCodeFormProps } from "../../../types"; export declare const UserInputCodeForm: React.ComponentType< SignInUpUserInputCodeFormProps & { - header?: JSX.Element | undefined; footer?: JSX.Element | undefined; } >; diff --git a/lib/build/recipe/passwordless/components/themes/translations.d.ts b/lib/build/recipe/passwordless/components/themes/translations.d.ts index 0fed6a0d3..78ccc297c 100644 --- a/lib/build/recipe/passwordless/components/themes/translations.d.ts +++ b/lib/build/recipe/passwordless/components/themes/translations.d.ts @@ -52,6 +52,12 @@ export declare const defaultTranslationsPasswordless: { PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE: string; PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK: string; PWLESS_USER_INPUT_CODE_INPUT_LABEL: string; + PWLESS_MFA_LOGOUT: string; + PWLESS_MFA_HEADER_TITLE_PHONE: string; + PWLESS_MFA_HEADER_TITLE_EMAIL: string; + PWLESS_MFA_FOOTER_CHOOSER_ANOTHER: string; + PWLESS_MFA_FOOTER_LOGOUT: string; + PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP: string; "Failed to generate a one time code. Please try again": undefined; "Phone number is invalid": undefined; "Email is invalid": undefined; diff --git a/lib/build/recipe/passwordless/prebuiltui.d.ts b/lib/build/recipe/passwordless/prebuiltui.d.ts index 68c945509..a68abcdc8 100644 --- a/lib/build/recipe/passwordless/prebuiltui.d.ts +++ b/lib/build/recipe/passwordless/prebuiltui.d.ts @@ -11,7 +11,7 @@ export declare class PasswordlessPreBuiltUI extends RecipeRouter { static getInstanceOrInitAndGetInstance(): PasswordlessPreBuiltUI; static getFeatures(useComponentOverrides?: () => GenericComponentOverrideMap): RecipeFeatureComponentMap; static getFeatureComponent( - componentName: "signInUp" | "linkClickedScreen", + componentName: "signInUp" | "linkClickedScreen" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any; @@ -20,7 +20,7 @@ export declare class PasswordlessPreBuiltUI extends RecipeRouter { ): JSX.Element; getFeatures: (useComponentOverrides?: () => GenericComponentOverrideMap) => RecipeFeatureComponentMap; getFeatureComponent: ( - componentName: "signInUp" | "linkClickedScreen", + componentName: "signInUp" | "linkClickedScreen" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any; @@ -35,6 +35,8 @@ export declare class PasswordlessPreBuiltUI extends RecipeRouter { }> ) => JSX.Element; static LinkClicked: (prop?: any) => JSX.Element; + static MfaOtpPhone: (prop?: any) => JSX.Element; + static MfaOtpEmail: (prop?: any) => JSX.Element; static SignInUpTheme: typeof SignInUpTheme; } declare const SignInUp: ( @@ -44,4 +46,6 @@ declare const SignInUp: ( }> ) => JSX.Element; declare const LinkClicked: (prop?: any) => JSX.Element; -export { SignInUp, LinkClicked, SignInUpTheme }; +declare const MfaOtpPhone: (prop?: any) => JSX.Element; +declare const MfaOtpEmail: (prop?: any) => JSX.Element; +export { SignInUp, LinkClicked, SignInUpTheme, MfaOtpPhone, MfaOtpEmail }; diff --git a/lib/build/recipe/passwordless/recipe.d.ts b/lib/build/recipe/passwordless/recipe.d.ts index b3532f13e..109883c51 100644 --- a/lib/build/recipe/passwordless/recipe.d.ts +++ b/lib/build/recipe/passwordless/recipe.d.ts @@ -1,3 +1,4 @@ +/// import PasswordlessWebJS from "supertokens-web-js/recipe/passwordless"; import AuthRecipe from "../authRecipe"; import type { @@ -8,6 +9,20 @@ import type { UserInput, } from "./types"; import type { RecipeInitResult, NormalisedConfigWithAppInfoAndRecipeID, WebJSRecipeInterface } from "../../types"; +export declare const otpPhoneFactor: { + id: string; + name: string; + description: string; + path: string; + logo: () => JSX.Element; +}; +export declare const otpEmailFactor: { + id: string; + name: string; + description: string; + path: string; + logo: () => JSX.Element; +}; export declare const passwordlessFirstFactors: readonly ["otp-phone", "otp-email", "link-phone", "link-email"]; export default class Passwordless extends AuthRecipe< GetRedirectionURLContext, diff --git a/lib/build/recipe/passwordless/types.d.ts b/lib/build/recipe/passwordless/types.d.ts index 617b38663..4859c2c99 100644 --- a/lib/build/recipe/passwordless/types.d.ts +++ b/lib/build/recipe/passwordless/types.d.ts @@ -1,4 +1,8 @@ import type { LinkClickedScreen } from "./components/themes/linkClickedScreen"; +import type { MFAFooter } from "./components/themes/mfa/mfaFooter"; +import type { MFAHeader } from "./components/themes/mfa/mfaHeader"; +import type { MFAOTPFooter } from "./components/themes/mfa/mfaOTPFooter"; +import type { MFAOTPHeader } from "./components/themes/mfa/mfaOTPHeader"; import type { CloseTabScreen } from "./components/themes/signInUp/closeTabScreen"; import type { EmailForm } from "./components/themes/signInUp/emailForm"; import type { EmailOrPhoneForm } from "./components/themes/signInUp/emailOrPhoneForm"; @@ -70,6 +74,7 @@ export declare type NormalisedConfig = { disableDefaultUI?: boolean; }; linkClickedScreenFeature: PasswordlessNormalisedBaseConfig; + mfaFeature: PasswordlessNormalisedBaseConfig; contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE"; override: { functions: (originalImplementation: RecipeInterface) => RecipeInterface; @@ -120,7 +125,26 @@ export declare type UserInput = ( functions?: (originalImplementation: RecipeInterface) => RecipeInterface; }; linkClickedScreenFeature?: PasswordlessFeatureBaseConfig; + mfaFeature?: PasswordlessFeatureBaseConfig; } & AuthRecipeModuleUserInput; +export declare type MFAProps = { + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; + contactMethod: "EMAIL" | "PHONE"; + onBackButtonClicked: () => void; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + onSuccess?: () => void; + dispatch: Dispatch; + featureState: { + isSetupAllowed: boolean; + loginAttemptInfo?: LoginAttemptInfo; + loaded: boolean; + successInAnotherTab: boolean; + error: string | undefined; + }; + userContext?: any; +}; export declare type SignInUpProps = { recipeImplementation: RecipeImplementation; config: NormalisedConfig; @@ -232,7 +256,41 @@ export declare type SignInUpState = { loginAttemptInfo: LoginAttemptInfo | undefined; successInAnotherTab: boolean; }; +export declare type MFAAction = + | { + type: "load"; + loginAttemptInfo: LoginAttemptInfo | undefined; + isAllowedToSetup: boolean; + error: string | undefined; + } + | { + type: "startVerify"; + loginAttemptInfo: LoginAttemptInfo; + } + | { + type: "resendCode"; + timestamp: number; + } + | { + type: "restartFlow"; + error: string | undefined; + } + | { + type: "setError"; + error: string | undefined; + } + | { + type: "successInAnotherTab"; + }; +export declare type MFAState = { + error: string | undefined; + loaded: boolean; + loginAttemptInfo: LoginAttemptInfo | undefined; + isSetupAllowed: boolean; + successInAnotherTab: boolean; +}; export declare type SignInUpChildProps = Omit; +export declare type MFAChildProps = Omit; export declare type LinkSentThemeProps = { clearError: () => void; onError: (error: string) => void; @@ -251,6 +309,28 @@ export declare type UserInputCodeFormHeaderProps = { recipeImplementation: RecipeImplementation; config: NormalisedConfig; }; +export declare type MFAFooterProps = { + isSetupAllowed: boolean; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; +export declare type MFAOTPFooterProps = { + isSetupAllowed: boolean; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + loginAttemptInfo: LoginAttemptInfo; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; +export declare type MFAOTPHeaderProps = { + isSetupAllowed: boolean; + onBackButtonClicked: () => void; + loginAttemptInfo: LoginAttemptInfo; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; export declare type ComponentOverrideMap = { PasswordlessSignInUpHeader_Override?: ComponentOverride; PasswordlessSignInUpFooter_Override?: ComponentOverride; @@ -263,4 +343,8 @@ export declare type ComponentOverrideMap = { PasswordlessLinkSent_Override?: ComponentOverride; PasswordlessLinkClickedScreen_Override?: ComponentOverride; PasswordlessCloseTabScreen_Override?: ComponentOverride; + PasswordlessMFAHeader_Override?: ComponentOverride; + PasswordlessMFAFooter_Override?: ComponentOverride; + PasswordlessMFAOTPHeader_Override?: ComponentOverride; + PasswordlessMFAOTPFooter_Override?: ComponentOverride; }; diff --git a/lib/build/recipe/passwordless/utils.d.ts b/lib/build/recipe/passwordless/utils.d.ts index a5b28e889..c6762d875 100644 --- a/lib/build/recipe/passwordless/utils.d.ts +++ b/lib/build/recipe/passwordless/utils.d.ts @@ -1,2 +1,7 @@ import type { Config, NormalisedConfig } from "./types"; +import type { DynamicLoginMethodsContextValue } from "../multitenancy/dynamicLoginMethodsContext"; export declare function normalisePasswordlessConfig(config: Config): NormalisedConfig; +export declare function getEnabledContactMethods( + contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE", + currentDynamicLoginMethods: DynamicLoginMethodsContextValue +): string[]; diff --git a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts index b24b59e60..14113e5ca 100644 --- a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts @@ -54,6 +54,12 @@ export declare const defaultTranslationsThirdPartyPasswordless: { PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE: string; PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK: string; PWLESS_USER_INPUT_CODE_INPUT_LABEL: string; + PWLESS_MFA_LOGOUT: string; + PWLESS_MFA_HEADER_TITLE_PHONE: string; + PWLESS_MFA_HEADER_TITLE_EMAIL: string; + PWLESS_MFA_FOOTER_CHOOSER_ANOTHER: string; + PWLESS_MFA_FOOTER_LOGOUT: string; + PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP: string; "Failed to generate a one time code. Please try again": undefined; "Phone number is invalid": undefined; "Email is invalid": undefined; diff --git a/lib/build/recipe/thirdpartypasswordless/prebuiltui.d.ts b/lib/build/recipe/thirdpartypasswordless/prebuiltui.d.ts index 773b9b4cd..cdf4b0d10 100644 --- a/lib/build/recipe/thirdpartypasswordless/prebuiltui.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/prebuiltui.d.ts @@ -13,7 +13,7 @@ export declare class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { static getInstanceOrInitAndGetInstance(): ThirdPartyPasswordlessPreBuiltUI; static getFeatures(useComponentOverrides?: () => GenericComponentOverrideMap): RecipeFeatureComponentMap; static getFeatureComponent( - componentName: "signInUp" | "linkClickedScreen" | "signinupcallback", + componentName: "signInUp" | "linkClickedScreen" | "signinupcallback" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any; @@ -21,7 +21,7 @@ export declare class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { useComponentOverrides?: () => GenericComponentOverrideMap ): JSX.Element; getFeatureComponent: ( - componentName: "signInUp" | "linkClickedScreen" | "signinupcallback", + componentName: "signInUp" | "linkClickedScreen" | "signinupcallback" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any; @@ -39,6 +39,8 @@ export declare class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { static ThirdPartySignInAndUpCallback: (prop?: any) => JSX.Element; static SignInUpTheme: typeof SignInUpTheme; static PasswordlessLinkClicked: (prop?: any) => JSX.Element; + static MfaOtpPhone: (prop?: any) => JSX.Element; + static MfaOtpEmail: (prop?: any) => JSX.Element; } declare const SignInAndUp: ( prop?: PropsWithChildren<{ @@ -48,4 +50,6 @@ declare const SignInAndUp: ( ) => JSX.Element; declare const ThirdPartySignInAndUpCallback: (prop?: any) => JSX.Element; declare const PasswordlessLinkClicked: (prop?: any) => JSX.Element; -export { SignInAndUp, ThirdPartySignInAndUpCallback, PasswordlessLinkClicked, SignInUpTheme }; +declare const MfaOtpPhone: (prop?: any) => JSX.Element; +declare const MfaOtpEmail: (prop?: any) => JSX.Element; +export { SignInAndUp, ThirdPartySignInAndUpCallback, PasswordlessLinkClicked, SignInUpTheme, MfaOtpPhone, MfaOtpEmail }; diff --git a/lib/build/recipe/thirdpartypasswordless/types.d.ts b/lib/build/recipe/thirdpartypasswordless/types.d.ts index b328d24f2..0fa2fc39b 100644 --- a/lib/build/recipe/thirdpartypasswordless/types.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/types.d.ts @@ -89,6 +89,7 @@ export declare type UserInput = ( ) => RecipeInterface; }; linkClickedScreenFeature?: PasswordlessFeatureBaseConfig; + mfaFeature?: PasswordlessFeatureBaseConfig; oAuthCallbackScreen?: FeatureBaseConfig; disablePasswordless?: boolean; } & AuthRecipeModuleUserInput; diff --git a/lib/build/sessionprebuiltui.js b/lib/build/sessionprebuiltui.js index e4cd239bf..60f00c8a6 100644 --- a/lib/build/sessionprebuiltui.js +++ b/lib/build/sessionprebuiltui.js @@ -82,7 +82,7 @@ function LogoutButton(_a) { } var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n/* Override */\n\n[data-supertokens~="accessDenied"] [data-supertokens~="row"] {\n padding-bottom: 24px;\n}\n\n[data-supertokens~="accessDenied"] [data-supertokens~="divider"] {\n padding: 0;\n margin: 34px 0 18px 0;\n}\n\n[data-supertokens~="accessDenied"] [data-supertokens~="headerTitle"] {\n margin: 10px 0 0 0;\n font-style: normal;\n font-weight: 700;\n font-size: 20px;\n line-height: 30px;\n}\n\n/* Override end */\n\n[data-supertokens~="center"] {\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n}\n\n[data-supertokens~="buttonsGroup"] {\n margin-top: 34px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n[data-supertokens~="buttonBase"] {\n font-family: "Rubik", sans-serif;\n font-size: var(--font-size-1);\n line-height: 21px;\n font-weight: 500;\n background: transparent;\n outline: none;\n border: none;\n cursor: pointer;\n}\n\n[data-supertokens~="backButton"] {\n color: rgb(var(--palette-textLink));\n}\n\n[data-supertokens~="logoutButton"] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: rgb(var(--palette-textGray));\n}\n\n[data-supertokens~="primaryText"][data-supertokens~="accessDeniedError"] {\n font-weight: 400;\n}\n'; + '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n\n/* Override */\n\n[data-supertokens~="accessDenied"] [data-supertokens~="row"] {\n padding-bottom: 24px;\n}\n\n[data-supertokens~="accessDenied"] [data-supertokens~="divider"] {\n padding: 0;\n margin: 34px 0 18px 0;\n}\n\n[data-supertokens~="accessDenied"] [data-supertokens~="headerTitle"] {\n margin: 10px 0 0 0;\n font-style: normal;\n font-weight: 700;\n font-size: 20px;\n line-height: 30px;\n}\n\n/* Override end */\n\n[data-supertokens~="center"] {\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n}\n\n[data-supertokens~="buttonsGroup"] {\n margin-top: 34px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n[data-supertokens~="buttonBase"] {\n font-family: "Rubik", sans-serif;\n font-size: var(--font-size-1);\n line-height: 21px;\n font-weight: 500;\n background: transparent;\n outline: none;\n border: none;\n cursor: pointer;\n}\n\n[data-supertokens~="backButton"] {\n color: rgb(var(--palette-textLink));\n}\n\n[data-supertokens~="logoutButton"] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: rgb(var(--palette-textGray));\n}\n\n[data-supertokens~="primaryText"][data-supertokens~="accessDeniedError"] {\n font-weight: 400;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/thirdparty-shared2.js b/lib/build/thirdparty-shared2.js index 0d25408c5..3efbc4971 100644 --- a/lib/build/thirdparty-shared2.js +++ b/lib/build/thirdparty-shared2.js @@ -49,7 +49,7 @@ var React__namespace = /*#__PURE__*/ _interopNamespace(React); var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); var styles = - '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n'; + '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/thirdpartyemailpasswordprebuiltui.js b/lib/build/thirdpartyemailpasswordprebuiltui.js index 803be9c24..afa1c8990 100644 --- a/lib/build/thirdpartyemailpasswordprebuiltui.js +++ b/lib/build/thirdpartyemailpasswordprebuiltui.js @@ -81,7 +81,7 @@ var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath var React__namespace = /*#__PURE__*/ _interopNamespace(React); var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n[data-supertokens~="thirdPartyEmailPasswordDivider"] {\n padding-top: 5px;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="thirdPartyEmailPasswordDividerOr"] {\n flex: 1 1;\n margin-top: 0.75em;\n}\n[data-supertokens~="divider"] {\n flex: 3 3;\n}\n[data-supertokens~="providerButton"] {\n margin: auto !important;\n max-width: 240px !important;\n}\n[data-supertokens~="providerButtonLeft"] {\n margin-left: 30px !important;\n}\n'; + '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n[data-supertokens~="thirdPartyEmailPasswordDivider"] {\n padding-top: 5px;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="thirdPartyEmailPasswordDividerOr"] {\n flex: 1 1;\n margin-top: 0.75em;\n}\n[data-supertokens~="divider"] {\n flex: 3 3;\n}\n[data-supertokens~="providerButton"] {\n margin: auto !important;\n max-width: 240px !important;\n}\n[data-supertokens~="providerButtonLeft"] {\n margin-left: 30px !important;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/thirdpartypasswordless-shared.js b/lib/build/thirdpartypasswordless-shared.js index ef7d96ef0..47576003b 100644 --- a/lib/build/thirdpartypasswordless-shared.js +++ b/lib/build/thirdpartypasswordless-shared.js @@ -236,6 +236,7 @@ function normaliseThirdPartyPasswordlessConfig(config) { { emailOrPhoneFormStyle: thirdPartyProviderAndEmailOrPhoneFormStyle } ), linkClickedScreenFeature: config.linkClickedScreenFeature, + mfaFeature: config.mfaFeature, override: {}, }), disablePasswordless: config.disablePasswordless === true, diff --git a/lib/build/thirdpartypasswordless.js b/lib/build/thirdpartypasswordless.js index 7de9631c9..796cbe40c 100644 --- a/lib/build/thirdpartypasswordless.js +++ b/lib/build/thirdpartypasswordless.js @@ -26,6 +26,9 @@ require("supertokens-web-js/lib/build/normalisedURLPath"); require("supertokens-web-js/recipe/thirdpartypasswordless"); require("./passwordless-shared2.js"); require("supertokens-web-js/recipe/passwordless"); +require("./multifactorauth-shared.js"); +require("supertokens-web-js/recipe/multifactorauth"); +require("supertokens-web-js/utils/sessionClaimValidatorStore"); var Wrapper = /** @class */ (function () { function Wrapper() {} diff --git a/lib/build/thirdpartypasswordlessprebuiltui.js b/lib/build/thirdpartypasswordlessprebuiltui.js index 4dfaa4fb7..fdef202cd 100644 --- a/lib/build/thirdpartypasswordlessprebuiltui.js +++ b/lib/build/thirdpartypasswordlessprebuiltui.js @@ -32,10 +32,13 @@ require("./session-shared3.js"); require("./passwordless-shared.js"); require("supertokens-web-js/utils/error"); require("./emailpassword-shared2.js"); +require("./sessionprebuiltui.js"); +require("./arrowLeftIcon.js"); require("./checkedRoundIcon.js"); require("./emailpassword-shared8.js"); require("./emailpassword-shared5.js"); -require("./arrowLeftIcon.js"); +require("./multifactorauth-shared2.js"); +require("./emailpassword-shared7.js"); require("./thirdparty-shared.js"); require("supertokens-web-js/recipe/thirdparty"); require("./authRecipe-shared.js"); @@ -79,7 +82,7 @@ var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath var React__namespace = /*#__PURE__*/ _interopNamespace(React); var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n[data-supertokens~="generalSuccess"] {\n margin-bottom: 20px;\n -webkit-animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n}\n[data-supertokens~="codeInputLabelWrapper"] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="headerSubtitle"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n[data-supertokens~="sendCodeText"] {\n margin-top: 15px;\n margin-bottom: 20px;\n}\n[data-supertokens~="sendCodeText"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n[data-supertokens~="resendCodeBtn"] {\n width: auto;\n margin-top: 0;\n line-height: 24px;\n}\n[data-supertokens~="resendCodeBtn"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="resendCodeBtn"]:disabled {\n color: rgb(var(--palette-textPrimary));\n cursor: default;\n text-decoration: none;\n}\n[data-supertokens~="phoneInputLibRoot"] {\n display: flex;\n align-items: center;\n}\n[data-supertokens~="phoneInputWrapper"] {\n display: flex;\n align-items: center;\n}\n[data-supertokens~="phoneInputWrapper"] .iti [data-supertokens~="input"] {\n padding-left: 15px;\n}\n[data-supertokens~="phoneInputWrapper"] .iti {\n flex: 1 1;\n min-width: 0;\n width: 100%;\n background: transparent;\n border: none;\n color: inherit;\n outline: none;\n}\n[data-supertokens~="continueButtonWrapper"] {\n margin-top: 10px;\n margin-bottom: 30px;\n}\n.iti__country-list {\n border: 0;\n top: 40px;\n width: min(72.2vw, 320px);\n border-radius: 6;\n box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);\n}\n.iti__country {\n display: flex;\n align-items: center;\n height: 34px;\n cursor: pointer;\n\n padding: 0 8px;\n}\n.iti__country-name {\n color: var(--palette-textLabel);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: "0 16px";\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n[data-supertokens~="thirdPartyPasswordlessDivider"] {\n padding-top: 5px;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="thirdPartyPasswordlessDividerText"] {\n flex: 1 1;\n margin-top: 0.75em;\n}\n[data-supertokens~="divider"] {\n flex: 3 3;\n}\n[data-supertokens~="providerButton"] {\n margin: auto !important;\n max-width: 240px !important;\n}\n[data-supertokens~="providerButtonLeft"] {\n margin-left: 30px !important;\n}\n'; + '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n[data-supertokens~="generalSuccess"] {\n margin-bottom: 20px;\n -webkit-animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n}\n[data-supertokens~="codeInputLabelWrapper"] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n[data-supertokens~="headerSubtitle"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n[data-supertokens~="sendCodeText"] {\n margin-top: 15px;\n margin-bottom: 20px;\n}\n[data-supertokens~="sendCodeText"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n[data-supertokens~="resendCodeBtn"] {\n width: auto;\n margin-top: 0;\n line-height: 24px;\n}\n[data-supertokens~="resendCodeBtn"]:hover {\n text-decoration: underline;\n}\n[data-supertokens~="resendCodeBtn"]:disabled {\n color: rgb(var(--palette-textPrimary));\n cursor: default;\n text-decoration: none;\n}\n[data-supertokens~="phoneInputLibRoot"] {\n display: flex;\n align-items: center;\n}\n[data-supertokens~="phoneInputWrapper"] {\n display: flex;\n align-items: center;\n}\n[data-supertokens~="phoneInputWrapper"] .iti [data-supertokens~="input"] {\n padding-left: 15px;\n}\n[data-supertokens~="phoneInputWrapper"] .iti {\n flex: 1 1;\n min-width: 0;\n width: 100%;\n background: transparent;\n border: none;\n color: inherit;\n outline: none;\n}\n[data-supertokens~="continueButtonWrapper"] {\n margin-top: 10px;\n margin-bottom: 30px;\n}\n.iti__country-list {\n border: 0;\n top: 40px;\n width: min(72.2vw, 320px);\n border-radius: 6;\n box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);\n}\n.iti__country {\n display: flex;\n align-items: center;\n height: 34px;\n cursor: pointer;\n\n padding: 0 8px;\n}\n.iti__country-name {\n color: var(--palette-textLabel);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: "0 16px";\n}\n[data-supertokens~="row"] {\n padding-bottom: 30px;\n}\n[data-supertokens~="providerContainer"] {\n padding-top: 9px;\n padding-bottom: 9px;\n}\n[data-supertokens~="providerButton"] {\n border-color: rgb(221, 221, 221) !important;\n}\n[data-supertokens~="providerButton"] {\n min-height: 32px;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 2px 8px;\n\n background-color: white;\n color: black;\n}\n[data-supertokens~="providerButton"]:hover {\n -webkit-filter: none !important;\n filter: none !important;\n}\n[data-supertokens~="providerButton"]:hover {\n background-color: #fafafa;\n}\n[data-supertokens~="providerButtonLeft"] {\n min-width: 34px;\n margin-left: 66px;\n}\n[data-supertokens~="providerButtonLogo"] {\n height: 30px;\n display: flex;\n}\n[data-supertokens~="providerButtonLogoCenter"] {\n display: flex;\n margin: auto;\n}\n[data-supertokens~="providerButtonText"] {\n font-weight: 400;\n text-align: center;\n justify-content: center;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n display: inline-block;\n}\n[data-supertokens~="providerButtonText"]:only-child {\n margin: 0 auto;\n}\n[data-supertokens~="thirdPartyPasswordlessDivider"] {\n padding-top: 5px;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="thirdPartyPasswordlessDividerText"] {\n flex: 1 1;\n margin-top: 0.75em;\n}\n[data-supertokens~="divider"] {\n flex: 3 3;\n}\n[data-supertokens~="providerButton"] {\n margin: auto !important;\n max-width: 240px !important;\n}\n[data-supertokens~="providerButtonLeft"] {\n margin-left: 30px !important;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, @@ -303,14 +306,18 @@ var SignInUpTheme = function (props) { }; function SignInUpThemeWrapper(props) { var hasFont = translations.hasFontDefined(props.config.rootStyle); + var currentDynamicLoginMethods = uiEntry.useDynamicLoginMethods(); // By defining it in a single object here TSC can deduce the connection between props var childProps = props.passwordlessRecipe !== undefined && props.pwlessChildProps !== undefined ? genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, props), { - activeScreen: passwordlessprebuiltui.getActiveScreen({ - config: props.pwlessChildProps.config, - featureState: props.pwlessState, - }), + activeScreen: passwordlessprebuiltui.getActiveScreen( + { + config: props.pwlessChildProps.config, + featureState: props.pwlessState, + }, + currentDynamicLoginMethods + ), pwlessChildProps: props.pwlessChildProps, passwordlessRecipe: props.passwordlessRecipe, }) @@ -559,7 +566,11 @@ var ThirdPartyPasswordlessPreBuiltUI = /** @class */ (function (_super) { ) ); } - } else if (componentName === "linkClickedScreen") { + } else if ( + "linkClickedScreen" === componentName || + "otp-phone" === componentName || + "otp-email" === componentName + ) { if (_this.passwordlessPreBuiltUI === undefined) { throw new Error( "Embedding this component requires the passwordless recipe to be enabled. Please check the value of disablePasswordless in the configuration." @@ -677,12 +688,22 @@ var ThirdPartyPasswordlessPreBuiltUI = /** @class */ (function (_super) { ThirdPartyPasswordlessPreBuiltUI.PasswordlessLinkClicked = function (prop) { return _a.getFeatureComponent("linkClickedScreen", prop); }; + ThirdPartyPasswordlessPreBuiltUI.MfaOtpPhone = function (prop) { + return _a.getFeatureComponent("otp-phone", prop); + }; + ThirdPartyPasswordlessPreBuiltUI.MfaOtpEmail = function (prop) { + return _a.getFeatureComponent("otp-email", prop); + }; return ThirdPartyPasswordlessPreBuiltUI; })(uiEntry.RecipeRouter); var SignInAndUp = ThirdPartyPasswordlessPreBuiltUI.SignInAndUp; var ThirdPartySignInAndUpCallback = ThirdPartyPasswordlessPreBuiltUI.ThirdPartySignInAndUpCallback; var PasswordlessLinkClicked = ThirdPartyPasswordlessPreBuiltUI.PasswordlessLinkClicked; +var MfaOtpPhone = passwordlessprebuiltui.PasswordlessPreBuiltUI.MfaOtpPhone; +var MfaOtpEmail = passwordlessprebuiltui.PasswordlessPreBuiltUI.MfaOtpEmail; +exports.MfaOtpEmail = MfaOtpEmail; +exports.MfaOtpPhone = MfaOtpPhone; exports.PasswordlessLinkClicked = PasswordlessLinkClicked; exports.SignInAndUp = SignInAndUp; exports.SignInUpTheme = SignInUpThemeWrapper; diff --git a/lib/ts/components/assets/otpEmailIcon.tsx b/lib/ts/components/assets/otpEmailIcon.tsx new file mode 100644 index 000000000..665747f81 --- /dev/null +++ b/lib/ts/components/assets/otpEmailIcon.tsx @@ -0,0 +1,17 @@ +export const OTPEmailIcon = () => ( + + + + + + + + + +); diff --git a/lib/ts/components/assets/otpSMSIcon.tsx b/lib/ts/components/assets/otpSMSIcon.tsx new file mode 100644 index 000000000..8e0864e81 --- /dev/null +++ b/lib/ts/components/assets/otpSMSIcon.tsx @@ -0,0 +1,17 @@ +export const OTPSMSIcon = () => ( + + + + + + + + + +); diff --git a/lib/ts/components/errorBoundary.tsx b/lib/ts/components/errorBoundary.tsx deleted file mode 100644 index 0cab7dbbf..000000000 --- a/lib/ts/components/errorBoundary.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* - * Imports. - */ -import React from "react"; -import { Fragment } from "react"; - -import type { ErrorInfo, ReactNode } from "react"; - -type ErrorBoundaryState = { hasError: boolean }; -/* - * Component. - */ -export default class ErrorBoundary extends React.Component { - constructor(props: { hasError: boolean }) { - super(props); - this.state = { hasError: false }; - } - - static getDerivedStateFromError(): ErrorBoundaryState { - return { hasError: true }; - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo): void { - console.info(error, errorInfo); - } - - render(): JSX.Element | ReactNode | undefined { - if (this.state.hasError) { - return ; - } - - return this.props.children; - } -} diff --git a/lib/ts/components/featureWrapper.tsx b/lib/ts/components/featureWrapper.tsx index 6a4366767..dea33ce57 100644 --- a/lib/ts/components/featureWrapper.tsx +++ b/lib/ts/components/featureWrapper.tsx @@ -29,8 +29,6 @@ import { TranslationContextProvider } from "../translation/translationContext"; import { useUserContext } from "../usercontext"; import { mergeObjects } from "../utils"; -import ErrorBoundary from "./errorBoundary"; - import type { GetLoginMethodsResponseNormalized } from "../recipe/multitenancy/types"; import type { TranslationStore } from "../translation/translationHelpers"; import type { PropsWithChildren } from "react"; @@ -74,15 +72,13 @@ export default function FeatureWrapper({ return ( - - - {children} - - + + {children} + ); } diff --git a/lib/ts/recipe/emailpassword/components/themes/styles.css b/lib/ts/recipe/emailpassword/components/themes/styles.css index bcaaa11be..a43cbf734 100644 --- a/lib/ts/recipe/emailpassword/components/themes/styles.css +++ b/lib/ts/recipe/emailpassword/components/themes/styles.css @@ -201,22 +201,6 @@ align-items: center; } -[data-supertokens~="backButtonCommon"] { - width: 16px; - height: 13px; -} - -[data-supertokens~="backButton"] { - cursor: pointer; - border: none; - background-color: transparent; - padding: 0px; -} - -[data-supertokens~="backButtonPlaceholder"] { - display: block; -} - [data-supertokens~="resendEmailLink"] { display: inline-block; } diff --git a/lib/ts/recipe/multitenancy/components/features/dynamicLoginMethodsSpinner/index.tsx b/lib/ts/recipe/multitenancy/components/features/dynamicLoginMethodsSpinner/index.tsx index 2680f8c70..b801a5328 100644 --- a/lib/ts/recipe/multitenancy/components/features/dynamicLoginMethodsSpinner/index.tsx +++ b/lib/ts/recipe/multitenancy/components/features/dynamicLoginMethodsSpinner/index.tsx @@ -13,7 +13,6 @@ * under the License. */ import { ComponentOverrideContext } from "../../../../../components/componentOverride/componentOverrideContext"; -import ErrorBoundary from "../../../../../components/errorBoundary"; import { WithOrWithoutShadowDom } from "../../../../../components/featureWrapper"; import { useRecipeComponentOverrideContext } from "../../../componentOverrideContext"; import Multitenancy from "../../../recipe"; @@ -28,11 +27,9 @@ const DynamicLoginMethodsSpinner: React.FC = () => { return ( - - - - - + + + ); }; diff --git a/lib/ts/recipe/passwordless/components/features/mfa/index.tsx b/lib/ts/recipe/passwordless/components/features/mfa/index.tsx new file mode 100644 index 000000000..2f533420f --- /dev/null +++ b/lib/ts/recipe/passwordless/components/features/mfa/index.tsx @@ -0,0 +1,480 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Imports. + */ +import * as React from "react"; +import { Fragment } from "react"; +import { useMemo } from "react"; +import { useRef } from "react"; +import { useEffect } from "react"; +import { WindowHandlerReference } from "supertokens-web-js/utils/windowHandler"; + +import { redirectToAuth } from "../../../../.."; +import { ComponentOverrideContext } from "../../../../../components/componentOverride/componentOverrideContext"; +import FeatureWrapper from "../../../../../components/featureWrapper"; +import { useUserContext } from "../../../../../usercontext"; +import { + clearErrorQueryParam, + getQueryParams, + getRedirectToPathFromURL, + useOnMountAPICall, +} from "../../../../../utils"; +import MultiFactorAuth from "../../../../multifactorauth/recipe"; +import SessionRecipe from "../../../../session/recipe"; +import { getPhoneNumberUtils } from "../../../phoneNumberUtils"; +import MFAThemeWrapper from "../../themes/mfa"; +import { defaultTranslationsPasswordless } from "../../themes/translations"; + +import type { FeatureBaseProps } from "../../../../../types"; +import type Recipe from "../../../recipe"; +import type { AdditionalLoginAttemptInfoProperties, ComponentOverrideMap, MFAChildProps } from "../../../types"; +import type { MFAAction, MFAState, NormalisedConfig } from "../../../types"; +import type { MFAFactorInfo } from "supertokens-web-js/recipe/multifactorauth/types"; +import type { RecipeInterface } from "supertokens-web-js/recipe/passwordless"; +import type { PasswordlessFlowType } from "supertokens-web-js/recipe/thirdpartypasswordless"; + +export const useSuccessInAnotherTabChecker = ( + callingConsumeCodeRef: React.MutableRefObject, + recipeImpl: RecipeInterface, + state: MFAState, + dispatch: React.Dispatch, + userContext: any +) => { + useEffect(() => { + // We only need to start checking this if we have an active login attempt + if (state.loginAttemptInfo && !state.successInAnotherTab) { + const checkSessionIntervalHandle = setInterval(async () => { + if (callingConsumeCodeRef.current === false) { + const currLoginAttempt = await recipeImpl.getLoginAttemptInfo({ userContext }); + if ( + currLoginAttempt === undefined || + currLoginAttempt.deviceId !== state.loginAttemptInfo?.deviceId + ) { + dispatch({ type: "successInAnotherTab" }); + } + } + }, 2000); + + return () => { + clearInterval(checkSessionIntervalHandle); + }; + } + // Nothing to clean up + return; + }, [state.loginAttemptInfo, state.successInAnotherTab]); +}; + +export const useFeatureReducer = (): [MFAState, React.Dispatch] => { + return React.useReducer( + (oldState: MFAState, action: MFAAction): MFAState => { + switch (action.type) { + case "load": + return { + loaded: true, + error: action.error, + loginAttemptInfo: action.loginAttemptInfo, + isSetupAllowed: action.isAllowedToSetup, + successInAnotherTab: false, + }; + case "resendCode": + if (!oldState.loginAttemptInfo) { + return oldState; + } + return { + ...oldState, + error: undefined, + loginAttemptInfo: { + ...oldState.loginAttemptInfo, + lastResend: action.timestamp, + }, + }; + case "restartFlow": + return { + ...oldState, + error: action.error, + loginAttemptInfo: undefined, + }; + case "setError": + return { + ...oldState, + loaded: true, + error: action.error, + }; + case "startVerify": + return { + ...oldState, + loaded: true, + loginAttemptInfo: action.loginAttemptInfo, + error: undefined, + successInAnotherTab: false, + }; + case "successInAnotherTab": + return { + ...oldState, + successInAnotherTab: true, + }; + default: + return oldState; + } + }, + { + error: undefined, + loaded: false, + loginAttemptInfo: undefined, + isSetupAllowed: false, + successInAnotherTab: false, + }, + (initArg) => { + let error: string | undefined = undefined; + const errorQueryParam = getQueryParams("error"); + if (errorQueryParam !== null) { + error = "SOMETHING_WENT_WRONG_ERROR"; + } + return { + ...initArg, + error, + }; + } + ); +}; + +export function useChildProps( + recipe: Recipe, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", + userContext: any, + history: any +): MFAChildProps { + return useMemo(() => { + return { + onSuccess: () => { + const redirectToPath = getRedirectToPathFromURL(); + const redirectInfo = + redirectToPath === undefined + ? undefined + : { + rid: "passwordless", + successRedirectContext: { + action: "SUCCESS", + isNewRecipeUser: false, + user: undefined, + redirectToPath, + }, + }; + + return SessionRecipe.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( + redirectInfo, + userContext, + history + ); + }, + onSignOutClicked: async () => { + await SessionRecipe.getInstanceOrThrow().signOut({ userContext }); + await recipeImplementation.clearLoginAttemptInfo({ userContext }); + await redirectToAuth({ redirectBack: false, history: history }); + }, + onBackButtonClicked: () => { + // If we don't have history available this would mean we are not using react-router-dom, so we use window's history + if (history === undefined) { + return WindowHandlerReference.getReferenceOrThrow().windowHandler.getWindowUnsafe().history.back(); + } + // If we do have history and goBack function on it this means we are using react-router-dom v5 or lower + if (history.goBack !== undefined) { + return history.goBack(); + } + // If we reach this code this means we are using react-router-dom v6 + return history(-1); + }, + onFactorChooserButtonClicked: () => { + return MultiFactorAuth.getInstanceOrThrow().redirectToFactorChooser(false, history); + }, + recipeImplementation: recipeImplementation, + config: recipe.config, + contactMethod, + }; + }, [contactMethod, state, recipeImplementation]); +} + +export const MFAFeature: React.FC< + FeatureBaseProps & { + contactMethod: "PHONE" | "EMAIL"; + flowType: PasswordlessFlowType; + recipe: Recipe; + useComponentOverrides: () => ComponentOverrideMap; + } +> = (props) => { + const recipeComponentOverrides = props.useComponentOverrides(); + const userContext = useUserContext(); + + const callingConsumeCodeRef = useRef(false); + const [state, dispatch] = useFeatureReducer(); + const recipeImplementation = React.useMemo( + () => + props.recipe && + getModifiedRecipeImplementation( + props.recipe.webJSRecipe, + props.recipe.config, + dispatch, + callingConsumeCodeRef + ), + [props.recipe] + ); + + useOnLoad(props, recipeImplementation, dispatch, userContext); + + const childProps = useChildProps( + props.recipe, + recipeImplementation, + state, + props.contactMethod, + userContext, + props.history + )!; + useSuccessInAnotherTabChecker(callingConsumeCodeRef, recipeImplementation, state, dispatch, userContext); + + return ( + + + + {/* No custom theme, use default. */} + {props.children === undefined && ( + + )} + + {/* Otherwise, custom theme is provided, propagate props. */} + {props.children && + React.Children.map(props.children, (child) => { + if (React.isValidElement(child)) { + return React.cloneElement(child, { + ...childProps, + featureState: state, + dispatch: dispatch, + }); + } + return child; + })} + + + + ); +}; + +export default MFAFeature; + +function useOnLoad( + props: React.PropsWithChildren< + { history?: any } & { children?: React.ReactNode } & { + contactMethod: "PHONE" | "EMAIL"; + flowType: PasswordlessFlowType; + recipe: Recipe; + useComponentOverrides: () => ComponentOverrideMap; + } + >, + recipeImplementation: RecipeInterface, + dispatch: React.Dispatch, + userContext: any +) { + const fetchMFAInfo = React.useCallback( + async () => MultiFactorAuth.getInstanceOrThrow().webJSRecipe.getMFAInfo({ userContext }), + [userContext] + ); + const handleLoadError = React.useCallback( + () => dispatch({ type: "setError", error: "SOMETHING_WENT_WRONG_ERROR" }), + [dispatch] + ); + const onLoad = React.useCallback( + async (mfaInfo: { factors: MFAFactorInfo; email?: string; phoneNumber?: string }) => { + let error: string | undefined = undefined; + const errorQueryParam = getQueryParams("error"); + const doSetup = getQueryParams("setup"); + if (errorQueryParam !== null) { + error = "SOMETHING_WENT_WRONG_ERROR"; + } + const loginAttemptInfo = + await recipeImplementation.getLoginAttemptInfo({ + userContext, + }); + + const isAlreadySetup = + props.contactMethod === "EMAIL" + ? mfaInfo.factors.isAlreadySetup.includes("otp-email") + : mfaInfo.factors.isAlreadySetup.includes("otp-phone"); + const isAllowedToSetup = + props.contactMethod === "EMAIL" + ? mfaInfo.factors.isAllowedToSetup.includes("otp-email") + : mfaInfo.factors.isAllowedToSetup.includes("otp-phone"); + + if (!loginAttemptInfo) { + // We can assume these are defined if we use these, we check that the mfaInfo states that the related factor has been set up + const createCodeInfo = + props.contactMethod === "EMAIL" ? { email: mfaInfo.email! } : { phoneNumber: mfaInfo.phoneNumber! }; + const factorId = props.contactMethod === "EMAIL" ? "otp-email" : "otp-phone"; + + if (isAlreadySetup && doSetup !== "true") { + try { + // createCode also dispatches the necessary events + await recipeImplementation!.createCode({ + ...createCodeInfo, + userContext, + }); + } catch (err) { + dispatch({ type: "setError", error: "SOMETHING_WENT_WRONG_ERROR" }); + } + } else if (!mfaInfo.factors.isAllowedToSetup.includes(factorId)) { + dispatch({ + type: "load", + loginAttemptInfo: undefined, + isAllowedToSetup: false, + error: "PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP", + }); + } else { + // since loginAttemptInfo is undefined, this will ask the user for the email/phone + dispatch({ type: "load", loginAttemptInfo, error, isAllowedToSetup: true }); + } + } else { + // No need to check if the component is unmounting, since this has no effect then. + dispatch({ type: "load", loginAttemptInfo, error, isAllowedToSetup }); + } + }, + [dispatch, recipeImplementation, props.contactMethod, userContext] + ); + + useOnMountAPICall(fetchMFAInfo, onLoad, handleLoadError); +} + +function getModifiedRecipeImplementation( + originalImpl: RecipeInterface, + config: NormalisedConfig, + dispatch: React.Dispatch, + callingConsumeCodeRef: React.MutableRefObject +): RecipeInterface { + return { + ...originalImpl, + createCode: async (input) => { + let contactInfo; + const phoneNumberUtils = await getPhoneNumberUtils(); + if ("email" in input) { + contactInfo = input.email; + } else { + contactInfo = phoneNumberUtils.formatNumber( + input.phoneNumber, + config.signInUpFeature.defaultCountry || "", + phoneNumberUtils.numberFormat.E164 + ); + } + + // This contactMethod refers to the one that was used to deliver the login info + const contactMethod: "EMAIL" | "PHONE" = "email" in input ? "EMAIL" : "PHONE"; + const additionalAttemptInfo = { + lastResend: Date.now(), + contactMethod, + contactInfo, + redirectToPath: getRedirectToPathFromURL(), + }; + + const res = await originalImpl.createCode({ + ...input, + userContext: { ...input.userContext, additionalAttemptInfo }, + }); + + if (res.status === "OK") { + const loginAttemptInfo = (await originalImpl.getLoginAttemptInfo({ + userContext: input.userContext, + }))!; + dispatch({ type: "startVerify", loginAttemptInfo }); + } + return res; + }, + resendCode: async (input) => { + /** + * In this case we want the code that is calling resendCode in the + * UI to handle STGeneralError so we let this throw + */ + const res = await originalImpl.resendCode(input); + + if (res.status === "OK") { + const loginAttemptInfo = await originalImpl.getLoginAttemptInfo({ + userContext: input.userContext, + }); + + if (loginAttemptInfo !== undefined) { + const timestamp = Date.now(); + + await originalImpl.setLoginAttemptInfo({ + userContext: input.userContext, + attemptInfo: { + ...loginAttemptInfo, + lastResend: timestamp, + }, + }); + dispatch({ type: "resendCode", timestamp }); + } + } else if (res.status === "RESTART_FLOW_ERROR") { + await originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }); + + dispatch({ type: "restartFlow", error: "ERROR_SIGN_IN_UP_RESEND_RESTART_FLOW" }); + } + return res; + }, + + consumeCode: async (input) => { + // We need to set call callingConsumeCodeRef to true while consumeCode is running, + // so we don't detect the login attempt disappearing too early and + // go to successInAnotherTab too early + callingConsumeCodeRef.current = true; + + const res = await originalImpl.consumeCode(input); + + if (res.status === "RESTART_FLOW_ERROR") { + await originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }); + + dispatch({ type: "restartFlow", error: "ERROR_SIGN_IN_UP_CODE_CONSUME_RESTART_FLOW" }); + } else if (res.status === "SIGN_IN_UP_NOT_ALLOWED") { + // This should never happen, but technically possible based on the API specs + // so we keep this here to cover all cases + await originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }); + + dispatch({ type: "restartFlow", error: res.reason }); + } else if (res.status === "OK") { + await originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }); + // we wait for the redirection to happen in this case. + } + + callingConsumeCodeRef.current = false; + + return res; + }, + + clearLoginAttemptInfo: async (input) => { + await originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }); + clearErrorQueryParam(); + dispatch({ type: "restartFlow", error: undefined }); + }, + }; +} diff --git a/lib/ts/recipe/passwordless/components/themes/mfa/index.tsx b/lib/ts/recipe/passwordless/components/themes/mfa/index.tsx new file mode 100644 index 000000000..75c608b97 --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/index.tsx @@ -0,0 +1,182 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import React from "react"; + +import { SuperTokensBranding } from "../../../../../components/SuperTokensBranding"; +import { hasFontDefined } from "../../../../../styles/styles"; +import { useTranslation } from "../../../../../translation/translationContext"; +import UserContextWrapper from "../../../../../usercontext/userContextWrapper"; +import GeneralError from "../../../../emailpassword/components/library/generalError"; +import { AccessDeniedScreen } from "../../../../session/prebuiltui"; +import { CloseTabScreen } from "../signInUp/closeTabScreen"; +import { EmailForm } from "../signInUp/emailForm"; +import { PhoneForm } from "../signInUp/phoneForm"; +import { UserInputCodeForm } from "../signInUp/userInputCodeForm"; +import { ThemeBase } from "../themeBase"; + +import { MFAFooter } from "./mfaFooter"; +import { MFAHeader } from "./mfaHeader"; +import { MFAOTPFooter } from "./mfaOTPFooter"; +import { MFAOTPHeader } from "./mfaOTPHeader"; + +import type { MFAProps } from "../../../types"; + +export enum MFAScreens { + CloseTab, + EmailForm, + PhoneForm, + UserInputCodeForm, + AccessDenied, +} + +const MFATheme: React.FC = ({ + activeScreen, + featureState, + onBackButtonClicked, + ...props +}) => { + const t = useTranslation(); + const commonProps = { + recipeImplementation: props.recipeImplementation, + config: props.config, + clearError: () => props.dispatch({ type: "setError", error: undefined }), + onError: (error: string) => props.dispatch({ type: "setError", error }), + error: featureState.error, + }; + + if (!featureState.loaded) { + return null; + } + + return activeScreen === MFAScreens.CloseTab ? ( + + ) : activeScreen === MFAScreens.AccessDenied ? ( + + ) : ( +
+
+ { + + {activeScreen === MFAScreens.UserInputCodeForm ? ( + + ) : ( + + )} + {featureState.error !== undefined && } + {activeScreen === MFAScreens.EmailForm ? ( + + } + /> + ) : activeScreen === MFAScreens.PhoneForm ? ( + + } + /> + ) : activeScreen === MFAScreens.UserInputCodeForm ? ( + + } + /> + ) : null} + + } +
+ +
+ ); +}; + +function MFAThemeWrapper(props: MFAProps): JSX.Element { + const hasFont = hasFontDefined(props.config.rootStyle); + + const activeScreen = getActiveScreen(props); + + let activeStyle; + if (activeScreen === MFAScreens.CloseTab) { + activeStyle = props.config.signInUpFeature.closeTabScreenStyle; + } else if (activeScreen === MFAScreens.UserInputCodeForm) { + activeStyle = props.config.signInUpFeature.userInputCodeFormStyle; + } else if (activeScreen === MFAScreens.EmailForm) { + activeStyle = props.config.signInUpFeature.emailOrPhoneFormStyle; + } else if (activeScreen === MFAScreens.PhoneForm) { + activeStyle = props.config.signInUpFeature.emailOrPhoneFormStyle; + } else { + activeStyle = ""; // styling the access denied screen is handled through the session recipe + } + + return ( + + + + + + ); +} + +export default MFAThemeWrapper; + +export function getActiveScreen(props: Pick) { + if (props.featureState.successInAnotherTab) { + return MFAScreens.CloseTab; + } else if ( + props.featureState.error === "PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP" || + (props.featureState.isSetupAllowed === false && props.featureState.loginAttemptInfo === undefined) + ) { + return MFAScreens.AccessDenied; + } else if (props.featureState.loginAttemptInfo) { + return MFAScreens.UserInputCodeForm; + } else if (props.contactMethod === "EMAIL") { + return MFAScreens.EmailForm; + } else if (props.contactMethod === "PHONE") { + return MFAScreens.PhoneForm; + } + + throw new Error("Couldn't choose active screen; Should never happen"); +} diff --git a/lib/ts/recipe/passwordless/components/themes/mfa/mfaFooter.tsx b/lib/ts/recipe/passwordless/components/themes/mfa/mfaFooter.tsx new file mode 100644 index 000000000..8d9f9636e --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaFooter.tsx @@ -0,0 +1,44 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +import ArrowLeftIcon from "../../../../../components/assets/arrowLeftIcon"; +import { withOverride } from "../../../../../components/componentOverride/withOverride"; +import { useTranslation } from "../../../../../translation/translationContext"; +import { MultiFactorAuthClaim } from "../../../../multifactorauth"; +import { useClaimValue } from "../../../../session"; + +import type { MFAFooterProps } from "../../../types"; + +export const MFAFooter = withOverride( + "PasswordlessMFAFooter", + function PasswordlessMFAFooter(props: MFAFooterProps): JSX.Element | null { + const t = useTranslation(); + const claim = useClaimValue(MultiFactorAuthClaim); + + return ( +
+ {claim.loading === false && (claim.value?.n.length ?? 0) > 1 && ( +
+ {t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER")} +
+ )} +
+ + {t("PWLESS_MFA_FOOTER_LOGOUT")} +
+
+ ); + } +); diff --git a/lib/ts/recipe/passwordless/components/themes/mfa/mfaHeader.tsx b/lib/ts/recipe/passwordless/components/themes/mfa/mfaHeader.tsx new file mode 100644 index 000000000..c2ac7399b --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaHeader.tsx @@ -0,0 +1,53 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import { Fragment } from "react"; + +import { withOverride } from "../../../../../components/componentOverride/withOverride"; +import { useTranslation } from "../../../../../translation/translationContext"; +import BackButton from "../../../../emailpassword/components/library/backButton"; +import { MultiFactorAuthClaim } from "../../../../multifactorauth"; +import { useClaimValue } from "../../../../session"; + +export const MFAHeader = withOverride( + "PasswordlessMFAHeader", + function PasswordlessMFAHeader(props: { + contactMethod: "EMAIL" | "PHONE"; + onBackButtonClicked: () => void; + }): JSX.Element { + const t = useTranslation(); + const claim = useClaimValue(MultiFactorAuthClaim); + + return ( + +
+ {claim.loading === false && claim.value?.n.length === 0 ? ( + + ) : ( + + {/* empty span for spacing the back button */} + + )} + {props.contactMethod === "EMAIL" + ? t("PWLESS_MFA_HEADER_TITLE_EMAIL") + : t("PWLESS_MFA_HEADER_TITLE_PHONE")} + + {/* empty span for spacing the back button */} + +
+
+
+ ); + } +); diff --git a/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPFooter.tsx b/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPFooter.tsx new file mode 100644 index 000000000..0a04ddc6e --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPFooter.tsx @@ -0,0 +1,66 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import ArrowLeftIcon from "../../../../../components/assets/arrowLeftIcon"; +import { withOverride } from "../../../../../components/componentOverride/withOverride"; +import { useTranslation } from "../../../../../translation/translationContext"; +import { useUserContext } from "../../../../../usercontext"; +import { MultiFactorAuthClaim } from "../../../../multifactorauth"; +import { useClaimValue } from "../../../../session"; + +import type { MFAOTPFooterProps } from "../../../types"; + +export const MFAOTPFooter = withOverride( + "PasswordlessMFAOTPFooter", + function PasswordlessMFAOTPFooter({ + loginAttemptInfo, + recipeImplementation, + onSignOutClicked, + onFactorChooserButtonClicked, + isSetupAllowed, + }: MFAOTPFooterProps): JSX.Element { + const t = useTranslation(); + const claim = useClaimValue(MultiFactorAuthClaim); + const userContext = useUserContext(); + + return ( +
+ {isSetupAllowed ? ( +
+ recipeImplementation.clearLoginAttemptInfo({ + userContext, + }) + }> + {loginAttemptInfo.contactMethod === "EMAIL" + ? t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL") + : t("PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE")} +
+ ) : ( + claim.loading === false && + (claim.value?.n.length ?? 0) > 1 && ( +
+ {t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER")} +
+ ) + )} +
+ + {t("PWLESS_MFA_LOGOUT")} +
+
+ ); + } +); diff --git a/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPHeader.tsx b/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPHeader.tsx new file mode 100644 index 000000000..60837edac --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPHeader.tsx @@ -0,0 +1,61 @@ +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import { Fragment } from "react"; + +import { withOverride } from "../../../../../components/componentOverride/withOverride"; +import { useTranslation } from "../../../../../translation/translationContext"; +import BackButton from "../../../../emailpassword/components/library/backButton"; +import { MultiFactorAuthClaim } from "../../../../multifactorauth"; +import { useClaimValue } from "../../../../session"; + +import type { MFAOTPHeaderProps } from "../../../types"; + +export const MFAOTPHeader = withOverride( + "PasswordlessMFAOTPHeader", + function PasswordlessMFAOTPHeader({ + loginAttemptInfo, + onBackButtonClicked, + isSetupAllowed, + }: MFAOTPHeaderProps): JSX.Element { + const t = useTranslation(); + const claim = useClaimValue(MultiFactorAuthClaim); + + return ( + +
+ {claim.loading === false && claim.value?.n.length === 0 && isSetupAllowed === false ? ( + + ) : ( + + {/* empty span for spacing the back button */} + + )} + {t("PWLESS_USER_INPUT_CODE_HEADER_TITLE")} + + {/* empty span for spacing the back button */} + +
+
+ {loginAttemptInfo.flowType === "USER_INPUT_CODE" + ? t("PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE") + : t("PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK")} +
+ {loginAttemptInfo.contactInfo} +
+
+
+ ); + } +); diff --git a/lib/ts/recipe/passwordless/components/themes/signInUp/emailForm.tsx b/lib/ts/recipe/passwordless/components/themes/signInUp/emailForm.tsx index 97159f306..3a582cdf3 100644 --- a/lib/ts/recipe/passwordless/components/themes/signInUp/emailForm.tsx +++ b/lib/ts/recipe/passwordless/components/themes/signInUp/emailForm.tsx @@ -26,7 +26,11 @@ import type { SignInUpEmailFormProps } from "../../../types"; export const EmailForm = withOverride( "PasswordlessEmailForm", - function PasswordlessEmailForm(props: SignInUpEmailFormProps): JSX.Element { + function PasswordlessEmailForm( + props: SignInUpEmailFormProps & { + footer?: JSX.Element; + } + ): JSX.Element { const userContext = useUserContext(); return ( @@ -71,10 +75,12 @@ export const EmailForm = withOverride( validateOnBlur={false} showLabels={true} footer={ - + props.footer ?? ( + + ) } /> ); diff --git a/lib/ts/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.tsx b/lib/ts/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.tsx index 54d2f0295..6cfaa4247 100644 --- a/lib/ts/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.tsx +++ b/lib/ts/recipe/passwordless/components/themes/signInUp/emailOrPhoneForm.tsx @@ -30,7 +30,11 @@ import type { SignInUpEmailOrPhoneFormProps } from "../../../types"; export const EmailOrPhoneForm = withOverride( "PasswordlessEmailOrPhoneForm", - function PasswordlessEmailOrPhoneForm(props: SignInUpEmailOrPhoneFormProps): JSX.Element { + function PasswordlessEmailOrPhoneForm( + props: SignInUpEmailOrPhoneFormProps & { + footer?: JSX.Element; + } + ): JSX.Element { const [isPhoneNumber, setIsPhoneNumber] = useState(false); const userContext = useUserContext(); @@ -149,10 +153,12 @@ export const EmailOrPhoneForm = withOverride( validateOnBlur={false} showLabels={true} footer={ - + props.footer ?? ( + + ) } /> ); diff --git a/lib/ts/recipe/passwordless/components/themes/signInUp/index.tsx b/lib/ts/recipe/passwordless/components/themes/signInUp/index.tsx index 289f2c251..b2ddd22c8 100644 --- a/lib/ts/recipe/passwordless/components/themes/signInUp/index.tsx +++ b/lib/ts/recipe/passwordless/components/themes/signInUp/index.tsx @@ -21,6 +21,8 @@ import { SuperTokensBranding } from "../../../../../components/SuperTokensBrandi import { hasFontDefined } from "../../../../../styles/styles"; import UserContextWrapper from "../../../../../usercontext/userContextWrapper"; import GeneralError from "../../../../emailpassword/components/library/generalError"; +import { useDynamicLoginMethods } from "../../../../multitenancy/dynamicLoginMethodsContext"; +import { getEnabledContactMethods } from "../../../utils"; import { ThemeBase } from "../themeBase"; import { CloseTabScreen } from "./closeTabScreen"; @@ -32,6 +34,7 @@ import { SignInUpHeader } from "./signInUpHeader"; import { UserInputCodeForm } from "./userInputCodeForm"; import { UserInputCodeFormHeader } from "./userInputCodeFormHeader"; +import type { DynamicLoginMethodsContextValue } from "../../../../multitenancy/dynamicLoginMethodsContext"; import type { SignInUpProps } from "../../../types"; export enum SignInUpScreens { @@ -101,7 +104,8 @@ const SignInUpTheme: React.FC function SignInUpThemeWrapper(props: SignInUpProps): JSX.Element { const hasFont = hasFontDefined(props.config.rootStyle); - const activeScreen = getActiveScreen(props); + const currentDynamicLoginMethods = useDynamicLoginMethods(); + const activeScreen = getActiveScreen(props, currentDynamicLoginMethods); let activeStyle; if (activeScreen === SignInUpScreens.CloseTab) { @@ -129,19 +133,25 @@ function SignInUpThemeWrapper(props: SignInUpProps): JSX.Element { export default SignInUpThemeWrapper; -export function getActiveScreen(props: Pick) { +export function getActiveScreen( + props: Pick, + currentDynamicLoginMethods: DynamicLoginMethodsContextValue +) { + const enabledContactMethods = getEnabledContactMethods(props.config.contactMethod, currentDynamicLoginMethods); + if (props.featureState.successInAnotherTab) { return SignInUpScreens.CloseTab; } else if (props.featureState.loginAttemptInfo && props.featureState.loginAttemptInfo.flowType === "MAGIC_LINK") { return SignInUpScreens.LinkSent; } else if (props.featureState.loginAttemptInfo) { return SignInUpScreens.UserInputCodeForm; - } else if (props.config.contactMethod === "EMAIL") { + } else if (enabledContactMethods.length > 1) { + return SignInUpScreens.EmailOrPhoneForm; + } else if (enabledContactMethods[0] === "EMAIL") { return SignInUpScreens.EmailForm; - } else if (props.config.contactMethod === "PHONE") { + } else if (enabledContactMethods[0] === "PHONE") { return SignInUpScreens.PhoneForm; - } else if (props.config.contactMethod === "EMAIL_OR_PHONE") { - return SignInUpScreens.EmailOrPhoneForm; } + throw new Error("Couldn't choose active screen; Should never happen"); } diff --git a/lib/ts/recipe/passwordless/components/themes/signInUp/phoneForm.tsx b/lib/ts/recipe/passwordless/components/themes/signInUp/phoneForm.tsx index fb2b8805f..a978bc138 100644 --- a/lib/ts/recipe/passwordless/components/themes/signInUp/phoneForm.tsx +++ b/lib/ts/recipe/passwordless/components/themes/signInUp/phoneForm.tsx @@ -29,7 +29,11 @@ import type { SignInUpPhoneFormProps } from "../../../types"; export const PhoneForm = withOverride( "PasswordlessPhoneForm", - function PasswordlessPhoneForm(props: SignInUpPhoneFormProps): JSX.Element { + function PasswordlessPhoneForm( + props: SignInUpPhoneFormProps & { + footer?: JSX.Element; + } + ): JSX.Element { const userContext = useUserContext(); useEffect(() => { @@ -87,10 +91,12 @@ export const PhoneForm = withOverride( validateOnBlur={false} showLabels={true} footer={ - + props.footer ?? ( + + ) } /> ); diff --git a/lib/ts/recipe/passwordless/components/themes/signInUp/userInputCodeForm.tsx b/lib/ts/recipe/passwordless/components/themes/signInUp/userInputCodeForm.tsx index d237ed0e6..fb8203bc5 100644 --- a/lib/ts/recipe/passwordless/components/themes/signInUp/userInputCodeForm.tsx +++ b/lib/ts/recipe/passwordless/components/themes/signInUp/userInputCodeForm.tsx @@ -32,7 +32,6 @@ export const UserInputCodeForm = withOverride( "PasswordlessUserInputCodeForm", function PasswordlessUserInputCodeForm( props: SignInUpUserInputCodeFormProps & { - header?: JSX.Element; footer?: JSX.Element; } ): JSX.Element { @@ -160,7 +159,9 @@ export const UserInputCodeForm = withOverride( }} validateOnBlur={false} showLabels={true} - footer={} + footer={ + props.footer ?? + } /> ); diff --git a/lib/ts/recipe/passwordless/components/themes/translations.ts b/lib/ts/recipe/passwordless/components/themes/translations.ts index 0fa66ae81..3885a07ba 100644 --- a/lib/ts/recipe/passwordless/components/themes/translations.ts +++ b/lib/ts/recipe/passwordless/components/themes/translations.ts @@ -71,6 +71,13 @@ export const defaultTranslationsPasswordless = { PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK: "An OTP and a magic link was sent to you at", PWLESS_USER_INPUT_CODE_INPUT_LABEL: "OTP", + PWLESS_MFA_LOGOUT: "Logout", + PWLESS_MFA_HEADER_TITLE_PHONE: "SMS based OTP", + PWLESS_MFA_HEADER_TITLE_EMAIL: "Email based OTP", + PWLESS_MFA_FOOTER_CHOOSER_ANOTHER: "Choose another factor", + PWLESS_MFA_FOOTER_LOGOUT: "Logout", + + PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP: "You are not allowed to set up OTP.", /* * The following are error messages from our backend SDK. * These are returned as full messages to preserver compatibilty, but they work just like the keys above. diff --git a/lib/ts/recipe/passwordless/prebuiltui.tsx b/lib/ts/recipe/passwordless/prebuiltui.tsx index 06e7315b9..9248b54e4 100644 --- a/lib/ts/recipe/passwordless/prebuiltui.tsx +++ b/lib/ts/recipe/passwordless/prebuiltui.tsx @@ -4,9 +4,11 @@ import UserContextWrapper from "../../usercontext/userContextWrapper"; import { isTest, matchRecipeIdUsingQueryParams } from "../../utils"; import AuthWidgetWrapper from "../authRecipe/authWidgetWrapper"; import { RecipeRouter } from "../recipeRouter"; +import { SessionAuth } from "../session"; import { useRecipeComponentOverrideContext } from "./componentOverrideContext"; import LinkClickedScreen from "./components/features/linkClickedScreen"; +import MFAFeature from "./components/features/mfa"; import SignInUpFeature from "./components/features/signInAndUp"; import SignInUpTheme from "./components/themes/signInUp"; import Passwordless from "./recipe"; @@ -42,7 +44,7 @@ export class PasswordlessPreBuiltUI extends RecipeRouter { return PasswordlessPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatures(useComponentOverrides); } static getFeatureComponent( - componentName: "signInUp" | "linkClickedScreen", + componentName: "signInUp" | "linkClickedScreen" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any }, useComponentOverrides: () => GenericComponentOverrideMap = useRecipeComponentOverrideContext ): JSX.Element { @@ -79,11 +81,29 @@ export class PasswordlessPreBuiltUI extends RecipeRouter { recipeID: Passwordless.RECIPE_ID, }; } + if (this.recipeInstance.config.mfaFeature.disableDefaultUI !== true) { + const normalisedFullPathPhone = this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath("/mfa/otp-phone") + ); + features[normalisedFullPathPhone.getAsStringDangerous()] = { + matches: matchRecipeIdUsingQueryParams(this.recipeInstance.config.recipeId), + component: (props) => this.getFeatureComponent("otp-phone", props as any, useComponentOverrides), + recipeID: Passwordless.RECIPE_ID, + }; + const normalisedFullPathEmail = this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath("/mfa/otp-email") + ); + features[normalisedFullPathEmail.getAsStringDangerous()] = { + matches: matchRecipeIdUsingQueryParams(this.recipeInstance.config.recipeId), + component: (props) => this.getFeatureComponent("otp-email", props as any, useComponentOverrides), + recipeID: Passwordless.RECIPE_ID, + }; + } return features; }; getFeatureComponent = ( - componentName: "signInUp" | "linkClickedScreen", + componentName: "signInUp" | "linkClickedScreen" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any }, useComponentOverrides: () => GenericComponentOverrideMap = useRecipeComponentOverrideContext ): JSX.Element => { @@ -129,9 +149,38 @@ export class PasswordlessPreBuiltUI extends RecipeRouter { /> ); - } else { - throw new Error("Should never come here."); } + if (componentName === "otp-email") { + return ( + + []}> + + + + ); + } + if (componentName === "otp-phone") { + return ( + + []}> + + + + ); + } + throw new Error("Should never come here."); }; // For tests @@ -148,11 +197,15 @@ export class PasswordlessPreBuiltUI extends RecipeRouter { this.getFeatureComponent("signInUp", prop); static LinkClicked = (prop?: any) => this.getFeatureComponent("linkClickedScreen", prop); + static MfaOtpPhone = (prop?: any) => this.getFeatureComponent("otp-phone", prop); + static MfaOtpEmail = (prop?: any) => this.getFeatureComponent("otp-email", prop); static SignInUpTheme = SignInUpTheme; } const SignInUp = PasswordlessPreBuiltUI.SignInUp; const LinkClicked = PasswordlessPreBuiltUI.LinkClicked; +const MfaOtpPhone = PasswordlessPreBuiltUI.MfaOtpPhone; +const MfaOtpEmail = PasswordlessPreBuiltUI.MfaOtpEmail; -export { SignInUp, LinkClicked, SignInUpTheme }; +export { SignInUp, LinkClicked, SignInUpTheme, MfaOtpPhone, MfaOtpEmail }; diff --git a/lib/ts/recipe/passwordless/recipe.tsx b/lib/ts/recipe/passwordless/recipe.tsx index 7974b587d..3c552b3b6 100644 --- a/lib/ts/recipe/passwordless/recipe.tsx +++ b/lib/ts/recipe/passwordless/recipe.tsx @@ -18,10 +18,14 @@ */ import PasswordlessWebJS from "supertokens-web-js/recipe/passwordless"; +import { PostSuperTokensInitCallbacks } from "supertokens-web-js/utils/postSuperTokensInitCallbacks"; +import { OTPEmailIcon } from "../../components/assets/otpEmailIcon"; +import { OTPSMSIcon } from "../../components/assets/otpSMSIcon"; import { SSR_ERROR } from "../../constants"; import { isTest } from "../../utils"; import AuthRecipe from "../authRecipe"; +import MultiFactorAuth from "../multifactorauth/recipe"; import { getFunctionOverrides } from "./functionOverrides"; import { normalisePasswordlessConfig } from "./utils"; @@ -37,6 +41,21 @@ import type { RecipeInitResult, NormalisedConfigWithAppInfoAndRecipeID, WebJSRec import type { NormalisedAppInfo } from "../../types"; import type RecipeModule from "../recipeModule"; +export const otpPhoneFactor = { + id: "otp-phone", + name: "SMS based OTP", + description: "Get an OTP code on your phone to complete the authentication request", + path: "/mfa/otp-phone", + logo: OTPSMSIcon, +}; +export const otpEmailFactor = { + id: "otp-email", + name: "Email based OTP", + description: "Get an OTP code on your email address to complete the authentication request", + path: "/mfa/otp-email", + logo: OTPEmailIcon, +}; + export const passwordlessFirstFactors = ["otp-phone", "otp-email", "link-phone", "link-email"] as const; /* @@ -58,6 +77,13 @@ export default class Passwordless extends AuthRecipe< public readonly webJSRecipe: WebJSRecipeInterface = PasswordlessWebJS ) { super(config); + + PostSuperTokensInitCallbacks.addPostInitCallback(() => { + const mfa = MultiFactorAuth.getInstance(); + if (mfa !== undefined) { + mfa.addMFAFactors([otpPhoneFactor, otpEmailFactor]); + } + }); } getDefaultRedirectionURL = async (context: GetRedirectionURLContext): Promise => { diff --git a/lib/ts/recipe/passwordless/types.ts b/lib/ts/recipe/passwordless/types.ts index bd78c63ce..3992c9111 100644 --- a/lib/ts/recipe/passwordless/types.ts +++ b/lib/ts/recipe/passwordless/types.ts @@ -14,6 +14,10 @@ */ import type { LinkClickedScreen } from "./components/themes/linkClickedScreen"; +import type { MFAFooter } from "./components/themes/mfa/mfaFooter"; +import type { MFAHeader } from "./components/themes/mfa/mfaHeader"; +import type { MFAOTPFooter } from "./components/themes/mfa/mfaOTPFooter"; +import type { MFAOTPHeader } from "./components/themes/mfa/mfaOTPHeader"; import type { CloseTabScreen } from "./components/themes/signInUp/closeTabScreen"; import type { EmailForm } from "./components/themes/signInUp/emailForm"; import type { EmailOrPhoneForm } from "./components/themes/signInUp/emailOrPhoneForm"; @@ -106,6 +110,7 @@ export type NormalisedConfig = { disableDefaultUI?: boolean; }; linkClickedScreenFeature: PasswordlessNormalisedBaseConfig; + mfaFeature: PasswordlessNormalisedBaseConfig; contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE"; @@ -183,8 +188,27 @@ export type UserInput = ( functions?: (originalImplementation: RecipeInterface) => RecipeInterface; }; linkClickedScreenFeature?: PasswordlessFeatureBaseConfig; + mfaFeature?: PasswordlessFeatureBaseConfig; } & AuthRecipeModuleUserInput; +export type MFAProps = { + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; + contactMethod: "EMAIL" | "PHONE"; + onBackButtonClicked: () => void; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + onSuccess?: () => void; + dispatch: Dispatch; + featureState: { + isSetupAllowed: boolean; + loginAttemptInfo?: LoginAttemptInfo; + loaded: boolean; + successInAnotherTab: boolean; + error: string | undefined; + }; + userContext?: any; +}; export type SignInUpProps = { recipeImplementation: RecipeImplementation; config: NormalisedConfig; @@ -307,7 +331,42 @@ export type SignInUpState = { successInAnotherTab: boolean; }; +export type MFAAction = + | { + type: "load"; + loginAttemptInfo: LoginAttemptInfo | undefined; + isAllowedToSetup: boolean; + error: string | undefined; + } + | { + type: "startVerify"; + loginAttemptInfo: LoginAttemptInfo; + } + | { + type: "resendCode"; + timestamp: number; + } + | { + type: "restartFlow"; + error: string | undefined; + } + | { + type: "setError"; + error: string | undefined; + } + | { + type: "successInAnotherTab"; + }; +export type MFAState = { + error: string | undefined; + loaded: boolean; + loginAttemptInfo: LoginAttemptInfo | undefined; + isSetupAllowed: boolean; + successInAnotherTab: boolean; +}; + export type SignInUpChildProps = Omit; +export type MFAChildProps = Omit; export type LinkSentThemeProps = { clearError: () => void; @@ -330,6 +389,31 @@ export type UserInputCodeFormHeaderProps = { config: NormalisedConfig; }; +export type MFAFooterProps = { + isSetupAllowed: boolean; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; + +export type MFAOTPFooterProps = { + isSetupAllowed: boolean; + onSignOutClicked: () => void; + onFactorChooserButtonClicked: () => void; + loginAttemptInfo: LoginAttemptInfo; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; + +export type MFAOTPHeaderProps = { + isSetupAllowed: boolean; + onBackButtonClicked: () => void; + loginAttemptInfo: LoginAttemptInfo; + recipeImplementation: RecipeImplementation; + config: NormalisedConfig; +}; + export type ComponentOverrideMap = { PasswordlessSignInUpHeader_Override?: ComponentOverride; PasswordlessSignInUpFooter_Override?: ComponentOverride; @@ -345,4 +429,9 @@ export type ComponentOverrideMap = { PasswordlessLinkClickedScreen_Override?: ComponentOverride; PasswordlessCloseTabScreen_Override?: ComponentOverride; + + PasswordlessMFAHeader_Override?: ComponentOverride; + PasswordlessMFAFooter_Override?: ComponentOverride; + PasswordlessMFAOTPHeader_Override?: ComponentOverride; + PasswordlessMFAOTPFooter_Override?: ComponentOverride; }; diff --git a/lib/ts/recipe/passwordless/utils.ts b/lib/ts/recipe/passwordless/utils.ts index d1bc38892..bd459381a 100644 --- a/lib/ts/recipe/passwordless/utils.ts +++ b/lib/ts/recipe/passwordless/utils.ts @@ -14,6 +14,7 @@ */ import { normaliseAuthRecipe } from "../authRecipe/utils"; +import MultiFactorAuth from "../multifactorauth/recipe"; import { defaultPhoneNumberValidator, @@ -25,6 +26,7 @@ import { import type { Config, NormalisedConfig, SignInUpFeatureConfigInput } from "./types"; import type { FeatureBaseConfig, NormalisedBaseConfig } from "../../types"; +import type { DynamicLoginMethodsContextValue } from "../multitenancy/dynamicLoginMethodsContext"; import type { RecipeInterface } from "supertokens-web-js/recipe/passwordless"; export function normalisePasswordlessConfig(config: Config): NormalisedConfig { @@ -71,6 +73,7 @@ export function normalisePasswordlessConfig(config: Config): NormalisedConfig { signInUpFeature, linkClickedScreenFeature: normalisePasswordlessBaseConfig(config.linkClickedScreenFeature), + mfaFeature: normalisePasswordlessBaseConfig(config.mfaFeature), contactMethod: config.contactMethod, @@ -136,3 +139,44 @@ function normalisePasswordlessBaseConfig(config?: T & FeatureBaseConfig): T & style, }; } + +export function getEnabledContactMethods( + contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE", + currentDynamicLoginMethods: DynamicLoginMethodsContextValue +) { + let enabledContactMethods = contactMethod === "EMAIL_OR_PHONE" ? ["EMAIL", "PHONE"] : [contactMethod]; + + let firstFactors; + if (currentDynamicLoginMethods.loaded && currentDynamicLoginMethods.loginMethods.firstFactors) { + firstFactors = currentDynamicLoginMethods.loginMethods.firstFactors; + } else { + firstFactors = MultiFactorAuth.getInstance()?.config.firstFactors; + } + + if (firstFactors !== undefined) { + if (enabledContactMethods.includes("PHONE")) { + if (!firstFactors.includes("otp-phone") && !firstFactors.includes("link-phone")) { + enabledContactMethods = enabledContactMethods.filter((c) => c !== "PHONE"); + } + } else { + if (firstFactors.includes("otp-phone") || firstFactors.includes("link-phone")) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + } + + if (enabledContactMethods.includes("EMAIL")) { + if (!firstFactors.includes("otp-email") && !firstFactors.includes("link-email")) { + enabledContactMethods = enabledContactMethods.filter((c) => c !== "EMAIL"); + } + } else { + if (firstFactors.includes("otp-email") || firstFactors.includes("link-email")) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + } + } + + if (enabledContactMethods.length === 0) { + throw new Error("The enabled contact method is not a superset of the requested first factors"); + } + return enabledContactMethods; +} diff --git a/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx b/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx index 8aefd9417..afb6b7ea8 100644 --- a/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx +++ b/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx @@ -152,15 +152,19 @@ const SignInUpTheme: React.FC GenericComponentOverrideMap = useRecipeComponentOverrideContext ): JSX.Element { @@ -67,7 +67,7 @@ export class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { // Instance methods getFeatureComponent = ( - componentName: "signInUp" | "linkClickedScreen" | "signinupcallback", + componentName: "signInUp" | "linkClickedScreen" | "signinupcallback" | "otp-phone" | "otp-email", props: FeatureBaseProps & { redirectOnSessionExists?: boolean; userContext?: any }, useComponentOverrides: () => GenericComponentOverrideMap = useRecipeComponentOverrideContext ): JSX.Element => { @@ -102,7 +102,11 @@ export class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { ); } - } else if (componentName === "linkClickedScreen") { + } else if ( + "linkClickedScreen" === componentName || + "otp-phone" === componentName || + "otp-email" === componentName + ) { if (this.passwordlessPreBuiltUI === undefined) { throw new Error( "Embedding this component requires the passwordless recipe to be enabled. Please check the value of disablePasswordless in the configuration." @@ -176,10 +180,14 @@ export class ThirdPartyPasswordlessPreBuiltUI extends RecipeRouter { static SignInUpTheme = SignInUpTheme; static PasswordlessLinkClicked = (prop?: any) => this.getFeatureComponent("linkClickedScreen", prop); + static MfaOtpPhone = (prop?: any) => this.getFeatureComponent("otp-phone", prop); + static MfaOtpEmail = (prop?: any) => this.getFeatureComponent("otp-email", prop); } const SignInAndUp = ThirdPartyPasswordlessPreBuiltUI.SignInAndUp; const ThirdPartySignInAndUpCallback = ThirdPartyPasswordlessPreBuiltUI.ThirdPartySignInAndUpCallback; const PasswordlessLinkClicked = ThirdPartyPasswordlessPreBuiltUI.PasswordlessLinkClicked; +const MfaOtpPhone = PasswordlessPreBuiltUI.MfaOtpPhone; +const MfaOtpEmail = PasswordlessPreBuiltUI.MfaOtpEmail; -export { SignInAndUp, ThirdPartySignInAndUpCallback, PasswordlessLinkClicked, SignInUpTheme }; +export { SignInAndUp, ThirdPartySignInAndUpCallback, PasswordlessLinkClicked, SignInUpTheme, MfaOtpPhone, MfaOtpEmail }; diff --git a/lib/ts/recipe/thirdpartypasswordless/types.ts b/lib/ts/recipe/thirdpartypasswordless/types.ts index 4c0bc8e98..0fa42cfec 100644 --- a/lib/ts/recipe/thirdpartypasswordless/types.ts +++ b/lib/ts/recipe/thirdpartypasswordless/types.ts @@ -123,6 +123,7 @@ export type UserInput = ( ) => RecipeInterface; }; linkClickedScreenFeature?: PasswordlessFeatureBaseConfig; + mfaFeature?: PasswordlessFeatureBaseConfig; oAuthCallbackScreen?: FeatureBaseConfig; disablePasswordless?: boolean; } & AuthRecipeModuleUserInput; diff --git a/lib/ts/recipe/thirdpartypasswordless/utils.ts b/lib/ts/recipe/thirdpartypasswordless/utils.ts index 9a0e74eeb..48ef02ba0 100644 --- a/lib/ts/recipe/thirdpartypasswordless/utils.ts +++ b/lib/ts/recipe/thirdpartypasswordless/utils.ts @@ -68,6 +68,7 @@ export function normaliseThirdPartyPasswordlessConfig(config?: Config): Normalis emailOrPhoneFormStyle: thirdPartyProviderAndEmailOrPhoneFormStyle, }, linkClickedScreenFeature: config.linkClickedScreenFeature, + mfaFeature: config.mfaFeature, override: {}, }), disablePasswordless: config.disablePasswordless === true, diff --git a/lib/ts/styles/styles.css b/lib/ts/styles/styles.css index ccb25636e..69ccc2bd0 100644 --- a/lib/ts/styles/styles.css +++ b/lib/ts/styles/styles.css @@ -260,3 +260,71 @@ [data-supertokens~="button"]:focus { outline: none; } + +[data-supertokens~="backButtonCommon"] { + width: 16px; + height: 13px; +} + +[data-supertokens~="backButton"] { + cursor: pointer; + border: none; + background-color: transparent; + padding: 0px; +} + +[data-supertokens~="backButtonPlaceholder"] { + display: block; +} + +[data-supertokens~="delayedRender"] { + animation-duration: 0.1s; + animation-name: animate-fade; + animation-delay: 0.2s; + animation-fill-mode: backwards; +} + +@keyframes animate-fade { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +[data-supertokens~="footerLinkGroupVert"] { + display: flex; + flex-direction: column; + margin-top: 10px; + gap: 24px; +} + +[data-supertokens~="footerLinkGroupVert"] > div { + margin: 0; +} + +[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] { + font-weight: 400; +} + +[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] { + font-weight: 500; + position: relative; + left: -6px; /* half the width of the left arrow */ +} + +@media (max-width: 360px) { + [data-supertokens~="footerLinkGroupVert"] { + flex-direction: column; + } + [data-supertokens~="footerLinkGroupVert"] > div { + margin: 0 auto; + } +} + +[data-supertokens~="footerLinkGroupVert"] div:only-child { + margin-left: auto; + margin-right: auto; + margin-top: 14px; +} diff --git a/test/with-typescript/src/App.tsx b/test/with-typescript/src/App.tsx index b47daecf6..ebcd3bd1b 100644 --- a/test/with-typescript/src/App.tsx +++ b/test/with-typescript/src/App.tsx @@ -1465,3 +1465,21 @@ MultiFactorAuth.init({ { id: "asfd", logo: () =>
A
, description: "test", name: "asdf", path: "/mfa/asdf" }, ], }); + +Passwordless.init({ + contactMethod: "EMAIL", + mfaFeature: { + style: "", + }, +}); + +ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", + mfaFeature: { + style: "", + }, +}); + +ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", +}); From 2e8132353589c247ae9a675f191c6a56983ec09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Lengyel?= Date: Mon, 11 Dec 2023 01:00:08 +0100 Subject: [PATCH 2/2] feat: totp recipe for MFA (#763) * chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: update pwless to support otp based mfa * feat: initial impl of totp mfa * feat: export totp bundle * feat: finish TOTP + test setup WIP * feat: finish TOTP + test setup WIP * feat: add back button to factor chooser and filter the options * feat: update how back buttons are styled * test: update how back button is selected in tests * feat: finishing totp initial impl * test: initial test for MFA * feat: self-review fixes & updates * feat: self-review fixes&cleanup * feat: self-review fixes&cleanup * test: add firstFactors tests * tests: complete initial test-set of MFA * fix: firstFactors + test helpers * fix: small test based fixes * feat: finishing touches * test: update first factor tests to match new behaviour w/ extra checks * feat: clean up first factor handling * feat: add retry info to verifyCode/Device * refactor: rename passwordlessFirstFactors since it's not only first factors * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * test: clean up * chore: increase size limits * test: add reset method to mfa recipe * feat: make sure firstFactor conflicts hit user error boundaries * feat: update design and fix font-weight issues * chore: update web-js dep * feat: update design * feat: update design * refactor: self-review fixes * refactor: self-review fixes * chore: update changelog * fix: revert unnecessary changes * feat: use redirect info if available on mfa success * refactor: use redirectToFactor instead of re-implementing * fix: add missing param into redirectToFactorChooser call * chore: update changelog * test: update tests for MFA * test: skip mock mfa tests until removal * fix: override and routing fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * fix: exposing mfa in tppwless + cleanup/refactor * refactor: cleanup&renames --- CHANGELOG.md | 1 + examples/for-tests/src/App.js | 102 +- .../for-tests/src/AppWithReactDomRouter.js | 3 +- examples/for-tests/src/testContext.js | 31 +- lib/build/components/assets/blockedIcon.d.ts | 2 + lib/build/components/assets/totpIcon.d.ts | 2 + lib/build/emailpassword-shared4.js | 9 +- lib/build/emailpassword-shared5.js | 100 - lib/build/emailpassword-shared6.js | 1572 +---- lib/build/emailpassword-shared7.js | 1521 ++++- lib/build/emailpassword-shared8.js | 814 +-- lib/build/emailpassword-shared9.js | 847 +++ lib/build/emailpassword.js | 1 + lib/build/emailpasswordprebuiltui.js | 7 +- lib/build/index2.js | 2 +- lib/build/multifactorauth-shared.js | 19 +- lib/build/multifactorauthprebuiltui.js | 2 +- lib/build/passwordless-shared2.js | 245 +- lib/build/passwordless-shared3.js | 5780 +---------------- lib/build/passwordless-shared4.js | 5627 ++++++++++++++++ lib/build/passwordless.js | 1 + lib/build/passwordlessprebuiltui.js | 8 +- .../recipe/totp/componentOverrideContext.d.ts | 9 + .../totp/components/features/mfa/index.d.ts | 21 + .../components/themes/mfa/blockedScreen.d.ts | 10 + .../totp/components/themes/mfa/index.d.ts | 12 + .../components/themes/mfa/loadingScreen.d.ts | 4 + .../components/themes/mfa/retryButton.d.ts | 5 + .../components/themes/mfa/totpCodeForm.d.ts | 10 + .../mfa/totpCodeVerificationFooter.d.ts | 8 + .../mfa/totpCodeVerificationHeader.d.ts | 8 + .../themes/mfa/totpDeviceInfoSection.d.ts | 10 + .../themes/mfa/totpDeviceSetupFooter.d.ts | 8 + .../themes/mfa/totpDeviceSetupHeader.d.ts | 8 + .../totp/components/themes/themeBase.d.ts | 8 + .../totp/components/themes/translations.d.ts | 29 + lib/build/recipe/totp/constants.d.ts | 1 + lib/build/recipe/totp/functionOverrides.d.ts | 6 + lib/build/recipe/totp/index.d.ts | 119 + lib/build/recipe/totp/prebuiltui.d.ts | 29 + lib/build/recipe/totp/recipe.d.ts | 39 + lib/build/recipe/totp/types.d.ts | 147 + lib/build/recipe/totp/utils.d.ts | 2 + lib/build/thirdpartyemailpassword.js | 1 + .../thirdpartyemailpasswordprebuiltui.js | 7 +- lib/build/thirdpartypasswordless.js | 1 + lib/build/thirdpartypasswordlessprebuiltui.js | 8 +- lib/build/totp-shared.js | 257 + lib/build/totp.js | 107 + lib/build/totpprebuiltui.js | 4271 ++++++++++++ lib/build/ui-entry.js | 2 +- lib/ts/components/assets/blockedIcon.tsx | 13 + lib/ts/components/assets/totpIcon.tsx | 32 + lib/ts/recipe/multifactorauth/recipe.tsx | 9 +- .../multitenancy/components/themes/styles.css | 16 - .../recipe/totp/componentOverrideContext.tsx | 7 + .../totp/components/features/mfa/index.tsx | 371 ++ .../components/themes/mfa/blockedScreen.tsx | 47 + .../totp/components/themes/mfa/index.tsx | 178 + .../components/themes/mfa/loadingScreen.tsx | 30 + .../components/themes/mfa/retryButton.tsx | 77 + .../components/themes/mfa/totpCodeForm.tsx | 98 + .../themes/mfa/totpCodeVerificationFooter.tsx | 46 + .../themes/mfa/totpCodeVerificationHeader.tsx | 50 + .../themes/mfa/totpDeviceInfoSection.tsx | 55 + .../themes/mfa/totpDeviceSetupFooter.tsx | 50 + .../themes/mfa/totpDeviceSetupHeader.tsx | 50 + .../recipe/totp/components/themes/styles.css | 55 + .../totp/components/themes/themeBase.tsx | 41 + .../totp/components/themes/translations.ts | 35 + lib/ts/recipe/totp/constants.ts | 15 + lib/ts/recipe/totp/functionOverrides.ts | 12 + lib/ts/recipe/totp/index.ts | 94 + lib/ts/recipe/totp/prebuiltui.tsx | 102 + lib/ts/recipe/totp/recipe.tsx | 144 + lib/ts/recipe/totp/types.ts | 178 + lib/ts/recipe/totp/utils.ts | 43 + package-lock.json | 60 +- package.json | 1 + recipe/totp/index.d.ts | 17 + recipe/totp/index.js | 20 + recipe/totp/prebuiltui.d.ts | 17 + recipe/totp/prebuiltui.js | 20 + rollup.config.mjs | 2 + test/constants.js | 3 + ...multitenancy.dynamic_login_methods.test.js | 25 +- test/helpers.js | 22 +- test/prepTestApp.sh | 1 + test/server/index.js | 321 +- test/server/package-lock.json | 13 +- test/server/package.json | 2 +- test/unit/componentOverrides.test.tsx | 38 +- test/unit/recipe/session/sessionAuth.test.tsx | 94 +- 93 files changed, 15868 insertions(+), 8479 deletions(-) create mode 100644 lib/build/components/assets/blockedIcon.d.ts create mode 100644 lib/build/components/assets/totpIcon.d.ts create mode 100644 lib/build/emailpassword-shared9.js create mode 100644 lib/build/passwordless-shared4.js create mode 100644 lib/build/recipe/totp/componentOverrideContext.d.ts create mode 100644 lib/build/recipe/totp/components/features/mfa/index.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/blockedScreen.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/index.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/loadingScreen.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/retryButton.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpCodeForm.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpCodeVerificationFooter.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpCodeVerificationHeader.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpDeviceInfoSection.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpDeviceSetupFooter.d.ts create mode 100644 lib/build/recipe/totp/components/themes/mfa/totpDeviceSetupHeader.d.ts create mode 100644 lib/build/recipe/totp/components/themes/themeBase.d.ts create mode 100644 lib/build/recipe/totp/components/themes/translations.d.ts create mode 100644 lib/build/recipe/totp/constants.d.ts create mode 100644 lib/build/recipe/totp/functionOverrides.d.ts create mode 100644 lib/build/recipe/totp/index.d.ts create mode 100644 lib/build/recipe/totp/prebuiltui.d.ts create mode 100644 lib/build/recipe/totp/recipe.d.ts create mode 100644 lib/build/recipe/totp/types.d.ts create mode 100644 lib/build/recipe/totp/utils.d.ts create mode 100644 lib/build/totp-shared.js create mode 100644 lib/build/totp.js create mode 100644 lib/build/totpprebuiltui.js create mode 100644 lib/ts/components/assets/blockedIcon.tsx create mode 100644 lib/ts/components/assets/totpIcon.tsx create mode 100644 lib/ts/recipe/totp/componentOverrideContext.tsx create mode 100644 lib/ts/recipe/totp/components/features/mfa/index.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/blockedScreen.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/index.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/loadingScreen.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/retryButton.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpCodeForm.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpCodeVerificationFooter.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpCodeVerificationHeader.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpDeviceInfoSection.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpDeviceSetupFooter.tsx create mode 100644 lib/ts/recipe/totp/components/themes/mfa/totpDeviceSetupHeader.tsx create mode 100644 lib/ts/recipe/totp/components/themes/styles.css create mode 100644 lib/ts/recipe/totp/components/themes/themeBase.tsx create mode 100644 lib/ts/recipe/totp/components/themes/translations.ts create mode 100644 lib/ts/recipe/totp/constants.ts create mode 100644 lib/ts/recipe/totp/functionOverrides.ts create mode 100644 lib/ts/recipe/totp/index.ts create mode 100644 lib/ts/recipe/totp/prebuiltui.tsx create mode 100644 lib/ts/recipe/totp/recipe.tsx create mode 100644 lib/ts/recipe/totp/types.ts create mode 100644 lib/ts/recipe/totp/utils.ts create mode 100644 recipe/totp/index.d.ts create mode 100644 recipe/totp/index.js create mode 100644 recipe/totp/prebuiltui.d.ts create mode 100644 recipe/totp/prebuiltui.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3712dbb0c..4f4fa2766 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ To use this you'll need compatible versions: - Removed an `ErrorBoundary` wrapping all our feature components to make sure all errors are properly catchable by the app - Added a `footer` prop to `EmailOrPhoneForm`, `EmailForm` and `PhoneForm` which is used to override the default sign in/up footers in case the component is for MFA - The passwordless and thirdpartypasswordless sign in/up screens now respect the first configuration (defined in the `MultiFactorAuth` recipe or in the tenant information) when selecting the available contact methods. +- Added TOTP recipe. For more details please check our guide [here](TODO) - Fixed a font loading issue, that caused apps using the default (Rubik) font to appear with the incorrect font weights - Some default styling has changed related to how fonts/font-weights are applied diff --git a/examples/for-tests/src/App.js b/examples/for-tests/src/App.js index 29611c0c3..d6e6e3206 100644 --- a/examples/for-tests/src/App.js +++ b/examples/for-tests/src/App.js @@ -15,6 +15,7 @@ import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyema import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; import UserRoles from "supertokens-auth-react/recipe/userroles"; import MultiFactorAuth from "supertokens-auth-react/recipe/multifactorauth"; +import TOTP from "supertokens-auth-react/recipe/totp"; import axios from "axios"; import { useSessionContext } from "supertokens-auth-react/recipe/session"; @@ -332,7 +333,100 @@ const customFields = [ const testContext = getTestContext(); +let storedTOTPDevices = window.localStorage.getItem("totpDevices"); +let totpDevices = storedTOTPDevices ? JSON.parse(storedTOTPDevices) : []; + +function removeTOTPDevice(deviceName) { + const origLength = totpDevices.length; + totpDevices = totpDevices.filter((d) => d.deviceName !== deviceName); + window.localStorage.setItem("totpDevices", JSON.stringify(totpDevices)); + return totpDevices.length !== origLength; +} + +function addTOTPDevice(deviceName) { + totpDevices.push({ + deviceName, + verified: false, + }); + window.localStorage.setItem("totpDevices", JSON.stringify(totpDevices)); +} + +function verifyTOTPDevice(deviceName) { + totpDevices = totpDevices.filter((d) => d.deviceName !== deviceName); + totpDevices.push({ + deviceName, + verified: true, + }); + window.localStorage.setItem("totpDevices", JSON.stringify(totpDevices)); +} +let tryCount = 0; + +setInterval(() => (tryCount = tryCount > 0 ? tryCount - 1 : 0), 30000); +window.resetTOTP = () => { + totpDevices = []; + window.localStorage.setItem("totpDevices", JSON.stringify(totpDevices)); + tryCount = 0; +}; let recipeList = [ + TOTP.init({ + override: { + functions: (oI) => ({ + ...oI, + listDevices: async () => ({ devices: totpDevices, status: "OK" }), + removeDevice: async ({ deviceName }) => { + return { status: "OK", didDeviceExist: removeTOTPDevice(deviceName) }; + }, + createDevice: async ({ deviceName }) => { + deviceName = deviceName ?? `totp-${Date.now()}`; + addTOTPDevice(deviceName); + return { + status: "OK", + deviceName: deviceName, + issuerName: "st", + qrCodeString: deviceName, + secret: `secret-${deviceName}`, + }; + }, + verifyCode: async ({ totp }) => { + const dev = totpDevices.find((d) => d.deviceName.endsWith(totp) && d.verified); + if (dev) { + await fetch("http://localhost:8082/completeFactor", { + method: "POST", + body: JSON.stringify({ id: "totp" }), + headers: new Headers([["Content-Type", "application/json"]]), + }); + return { status: "OK" }; + } + + if (++tryCount > 3) { + return { status: "LIMIT_REACHED_ERROR", retryAfterMs: 30000 }; + } + return { status: "INVALID_TOTP_ERROR" }; + }, + verifyDevice: async ({ deviceName, totp }) => { + const dev = totpDevices.find((d) => d.deviceName === deviceName); + if (!dev) { + return { status: "UNKNOWN_DEVICE_ERROR" }; + } + if (deviceName.endsWith(totp)) { + const wasAlreadyVerified = dev.verified; + verifyTOTPDevice(deviceName); + await fetch("http://localhost:8082/completeFactor", { + method: "POST", + body: JSON.stringify({ id: "totp" }), + headers: new Headers([["Content-Type", "application/json"]]), + }); + return { status: "OK", wasAlreadyVerified }; + } + + if (++tryCount > 3) { + return { status: "LIMIT_REACHED_ERROR", retryAfterMs: 30000 }; + } + return { status: "INVALID_TOTP_ERROR" }; + }, + }), + }, + }), MultiFactorAuth.init({ firstFactors: testContext.firstFactors, }), @@ -645,7 +739,13 @@ export function DashboardHelper({ redirectOnLogout, ...props } = {}) {
session context userID: {sessionContext.userId}
{JSON.stringify(sessionContext.invalidClaims, undefined, 2)}
- MultiFactorAuth.redirectToFactorChooser(true, props.history)}>MFA chooser + { + return MultiFactorAuth.redirectToFactorChooser(true, props.history); + }}> + MFA chooser + ); } diff --git a/examples/for-tests/src/AppWithReactDomRouter.js b/examples/for-tests/src/AppWithReactDomRouter.js index 7c007ceb8..76373238a 100644 --- a/examples/for-tests/src/AppWithReactDomRouter.js +++ b/examples/for-tests/src/AppWithReactDomRouter.js @@ -16,6 +16,7 @@ import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/email import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui"; import { AccessDeniedScreen } from "supertokens-auth-react/recipe/session/prebuiltui"; import { MultiFactorAuthPreBuiltUI } from "supertokens-auth-react/recipe/multifactorauth/prebuiltui"; +import { TOTPPreBuiltUI } from "supertokens-auth-react/recipe/totp/prebuiltui"; import { BaseComponent, Home, Contact, Dashboard, DashboardNoAuthRequired } from "./App"; import { getEnabledRecipes } from "./testContext"; @@ -35,7 +36,7 @@ function AppWithReactDomRouter(props) { const emailVerificationMode = window.localStorage.getItem("mode") || "OFF"; const websiteBasePath = window.localStorage.getItem("websiteBasePath") || undefined; - let recipePreBuiltUIList = [MultiFactorAuthPreBuiltUI]; + let recipePreBuiltUIList = [MultiFactorAuthPreBuiltUI, TOTPPreBuiltUI]; if (enabledRecipes.includes("emailpassword")) { recipePreBuiltUIList.push(EmailPasswordPreBuiltUI); } diff --git a/examples/for-tests/src/testContext.js b/examples/for-tests/src/testContext.js index 3851358dd..901c43978 100644 --- a/examples/for-tests/src/testContext.js +++ b/examples/for-tests/src/testContext.js @@ -9,6 +9,7 @@ export function getTestContext() { thirdPartyRedirectURL: localStorage.getItem("thirdPartyRedirectURL"), authRecipe: window.localStorage.getItem("authRecipe") || "emailpassword", usesDynamicLoginMethods: localStorage.getItem("usesDynamicLoginMethods") === "true", + enableAllRecipes: localStorage.getItem("enableAllRecipes") === "true", clientRecipeListForDynamicLogin: localStorage.getItem("clientRecipeListForDynamicLogin"), mockLoginMethodsForDynamicLogin: localStorage.getItem("mockLoginMethodsForDynamicLogin"), staticProviderList: localStorage.getItem("staticProviderList"), @@ -28,18 +29,24 @@ export function getEnabledRecipes() { let enabledRecipes = []; - if (testContext.usesDynamicLoginMethods) { - if (testContext.clientRecipeListForDynamicLogin) { - enabledRecipes = JSON.parse(testContext.clientRecipeListForDynamicLogin); - } else { - enabledRecipes = [ - "emailpassword", - "thirdparty", - "thirdpartyemailpassword", - "passwordless", - "thirdpartypasswordless", - ]; - } + if (testContext.enableAllRecipes) { + enabledRecipes = [ + "emailpassword", + "thirdparty", + "thirdpartyemailpassword", + "passwordless", + "thirdpartypasswordless", + ]; + } else if (testContext.clientRecipeListForDynamicLogin) { + enabledRecipes = JSON.parse(testContext.clientRecipeListForDynamicLogin); + } else if (testContext.usesDynamicLoginMethods) { + enabledRecipes = [ + "emailpassword", + "thirdparty", + "thirdpartyemailpassword", + "passwordless", + "thirdpartypasswordless", + ]; } else { if (testContext.authRecipe === "both") { enabledRecipes.push("emailpassword", "thirdparty"); diff --git a/lib/build/components/assets/blockedIcon.d.ts b/lib/build/components/assets/blockedIcon.d.ts new file mode 100644 index 000000000..1832c8417 --- /dev/null +++ b/lib/build/components/assets/blockedIcon.d.ts @@ -0,0 +1,2 @@ +/// +export declare const BlockedIcon: () => JSX.Element; diff --git a/lib/build/components/assets/totpIcon.d.ts b/lib/build/components/assets/totpIcon.d.ts new file mode 100644 index 000000000..8f2bba229 --- /dev/null +++ b/lib/build/components/assets/totpIcon.d.ts @@ -0,0 +1,2 @@ +/// +export declare const TOTPIcon: () => JSX.Element; diff --git a/lib/build/emailpassword-shared4.js b/lib/build/emailpassword-shared4.js index e2f54ebcc..937af37ee 100644 --- a/lib/build/emailpassword-shared4.js +++ b/lib/build/emailpassword-shared4.js @@ -4,7 +4,8 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext var EmailPasswordWebJS = require("supertokens-web-js/recipe/emailpassword"); var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); var utils = require("./authRecipe-shared.js"); -var validators = require("./emailpassword-shared5.js"); +var constants = require("./emailpassword-shared5.js"); +var validators = require("./emailpassword-shared6.js"); function _interopDefault(e) { return e && e.__esModule ? e : { default: e }; @@ -235,7 +236,7 @@ function normaliseSignInFormFeatureConfig(defaultFormFields, config) { userFormFields = config.formFields // Filter on email and password only. .filter(function (field) { - return validators.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(field.id); + return constants.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(field.id); }) // Sign In fields are never optional. .map(function (field) { @@ -345,7 +346,7 @@ function mergeFormFields(defaultFormFields, userFormFields) { optional = userField.optional; } // If "email" or "password", always mandatory. - if (validators.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(userField.id)) { + if (constants.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(userField.id)) { optional = false; } // Merge. @@ -435,7 +436,7 @@ var EmailPassword = /** @class */ (function (_super) { return genericComponentOverrideContext.__generator(this, function (_a) { if (context.action === "RESET_PASSWORD") { resetPasswordPath = new NormalisedURLPath__default.default( - validators.DEFAULT_RESET_PASSWORD_PATH + constants.DEFAULT_RESET_PASSWORD_PATH ); return [ 2 /*return*/, diff --git a/lib/build/emailpassword-shared5.js b/lib/build/emailpassword-shared5.js index 2f2d37441..8b145c4f7 100644 --- a/lib/build/emailpassword-shared5.js +++ b/lib/build/emailpassword-shared5.js @@ -1,7 +1,5 @@ "use strict"; -var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); - /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the @@ -19,103 +17,5 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext var MANDATORY_FORM_FIELDS_ID_ARRAY = ["email", "password"]; var DEFAULT_RESET_PASSWORD_PATH = "/reset-password"; -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * defaultEmailValidator. - */ -function defaultEmailValidator(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - var defaultEmailValidatorRegexp; - return genericComponentOverrideContext.__generator(this, function (_a) { - if (typeof value !== "string") { - return [2 /*return*/, "ERROR_EMAIL_NON_STRING"]; - } - value = value.trim(); - defaultEmailValidatorRegexp = - // eslint-disable-next-line no-useless-escape - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - // We check if the email syntax is correct - // As per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 - // Regex from https://stackoverflow.com/a/46181/3867175 - if (value.match(defaultEmailValidatorRegexp) === null) { - return [2 /*return*/, "ERROR_EMAIL_INVALID"]; - } - return [2 /*return*/, undefined]; - }); - }); -} -/* - * defaultPasswordValidator. - * min 8 characters. - * Contains lowercase, uppercase, and numbers. - */ -function defaultPasswordValidator(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - if (typeof value !== "string") { - return [2 /*return*/, "ERROR_PASSWORD_NON_STRING"]; - } - // length >= 8 && < 100 - // must have a number and a character - // as per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 - if (value.length < 8) { - return [2 /*return*/, "ERROR_PASSWORD_TOO_SHORT"]; - } - if (value.length >= 100) { - return [2 /*return*/, "ERROR_PASSWORD_TOO_LONG"]; - } - if (value.match(/^.*[A-Za-z]+.*$/) === null) { - return [2 /*return*/, "ERROR_PASSWORD_NO_ALPHA"]; - } - if (value.match(/^.*[0-9]+.*$/) === null) { - return [2 /*return*/, "ERROR_PASSWORD_NO_NUM"]; - } - return [2 /*return*/, undefined]; - }); - }); -} -/* - * defaultLoginPasswordValidator. - * type string - */ -function defaultLoginPasswordValidator(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - if (typeof value !== "string") { - return [2 /*return*/, "ERROR_PASSWORD_NON_STRING"]; - } - return [2 /*return*/, undefined]; - }); - }); -} -/* - * defaultValidate - */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function defaultValidate(_) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - return [2 /*return*/, undefined]; - }); - }); -} - exports.DEFAULT_RESET_PASSWORD_PATH = DEFAULT_RESET_PASSWORD_PATH; exports.MANDATORY_FORM_FIELDS_ID_ARRAY = MANDATORY_FORM_FIELDS_ID_ARRAY; -exports.defaultEmailValidator = defaultEmailValidator; -exports.defaultLoginPasswordValidator = defaultLoginPasswordValidator; -exports.defaultPasswordValidator = defaultPasswordValidator; -exports.defaultValidate = defaultValidate; diff --git a/lib/build/emailpassword-shared6.js b/lib/build/emailpassword-shared6.js index 2916a01a4..97e3b35d7 100644 --- a/lib/build/emailpassword-shared6.js +++ b/lib/build/emailpassword-shared6.js @@ -1,1514 +1,102 @@ "use strict"; var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); -var jsxRuntime = require("react/jsx-runtime"); -var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); -var uiEntry = require("./index2.js"); -var authWidgetWrapper = require("./authRecipe-shared2.js"); -var componentOverrideContext = require("./emailpassword-shared3.js"); -var React = require("react"); -var translations = require("./translations.js"); -var translations$1 = require("./emailverification-shared2.js"); -var translationContext = require("./translationContext.js"); -var backButton = require("./emailpassword-shared7.js"); -var arrowLeftIcon = require("./arrowLeftIcon.js"); -var formBase = require("./emailpassword-shared8.js"); -var generalError = require("./emailpassword-shared.js"); -var STGeneralError = require("supertokens-web-js/utils/error"); -var button = require("./emailpassword-shared2.js"); -var recipe = require("./session-shared2.js"); -var SuperTokensBranding = require("./SuperTokensBranding.js"); -var STGeneralError$1 = require("supertokens-web-js/lib/build/error"); -var validators = require("./emailpassword-shared5.js"); -var recipe$1 = require("./emailpassword-shared4.js"); -function _interopDefault(e) { - return e && e.__esModule ? e : { default: e }; -} - -function _interopNamespace(e) { - if (e && e.__esModule) return e; - var n = Object.create(null); - if (e) { - Object.keys(e).forEach(function (k) { - if (k !== "default") { - var d = Object.getOwnPropertyDescriptor(e, k); - Object.defineProperty( - n, - k, - d.get - ? d - : { - enumerable: true, - get: function () { - return e[k]; - }, - } - ); - } +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * defaultEmailValidator. + */ +function defaultEmailValidator(value) { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + var defaultEmailValidatorRegexp; + return genericComponentOverrideContext.__generator(this, function (_a) { + if (typeof value !== "string") { + return [2 /*return*/, "ERROR_EMAIL_NON_STRING"]; + } + value = value.trim(); + defaultEmailValidatorRegexp = + // eslint-disable-next-line no-useless-escape + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + // We check if the email syntax is correct + // As per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 + // Regex from https://stackoverflow.com/a/46181/3867175 + if (value.match(defaultEmailValidatorRegexp) === null) { + return [2 /*return*/, "ERROR_EMAIL_INVALID"]; + } + return [2 /*return*/, undefined]; }); - } - n.default = e; - return Object.freeze(n); + }); } - -var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath); -var React__namespace = /*#__PURE__*/ _interopNamespace(React); -var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); -var STGeneralError__default$1 = /*#__PURE__*/ _interopDefault(STGeneralError$1); - /* - * Component. + * defaultPasswordValidator. + * min 8 characters. + * Contains lowercase, uppercase, and numbers. */ -function BackToSignInButton(_a) { - var onClick = _a.onClick; - var t = translationContext.useTranslation(); - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", onClick: onClick }, - { - children: [ - jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { color: "rgb(var(--palette-secondaryText))" }), - t("EMAIL_PASSWORD_RESET_SIGN_IN_LINK"), - ], +function defaultPasswordValidator(value) { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + if (typeof value !== "string") { + return [2 /*return*/, "ERROR_PASSWORD_NON_STRING"]; } - ) - ); -} - -var EmailPasswordResetPasswordEmail = function (props) { - var t = translationContext.useTranslation(); - var userContext = uiEntry.useUserContext(); - var _a = React.useState("READY"), - status = _a[0], - setStatus = _a[1]; - var _b = React.useState(""), - emailFieldValue = _b[0], - setEmailFieldValue = _b[1]; - var onSuccess = function () { - setStatus("SENT"); - }; - var resend = function () { - setStatus("READY"); - }; - var formFields = props.formFields; - var emailSuccessText = - t("EMAIL_PASSWORD_RESET_SEND_BEFORE_EMAIL") + - (emailFieldValue !== undefined && emailFieldValue.length > 0 - ? emailFieldValue - : t("EMAIL_PASSWORD_RESET_SEND_FALLBACK_EMAIL")) + - t("EMAIL_PASSWORD_RESET_SEND_AFTER_EMAIL"); - if (status === "SENT") { - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "primaryText enterEmailSuccessMessage" }, - { - children: [ - emailSuccessText, - jsxRuntime.jsx( - "span", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "link resendEmailLink", - onClick: resend, - }, - { children: t("EMAIL_PASSWORD_RESET_RESEND_LINK") } - ) - ), - ], - } - ) - ), - jsxRuntime.jsx(BackToSignInButton, { onClick: props.onBackButtonClicked }), - ], - } - ) - ), - } - ) - ); - } - // Otherwise, return Form. - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle withBackButton" }, - { - children: [ - jsxRuntime.jsx(backButton.BackButton, { - onClick: props.onBackButtonClicked, - }), - t("EMAIL_PASSWORD_RESET_HEADER_TITLE"), - jsxRuntime.jsx("span", { - "data-supertokens": "backButtonPlaceholder backButtonCommon", - }), - ], - } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle" }, - { - children: jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText" }, - { children: t("EMAIL_PASSWORD_RESET_HEADER_SUBTITLE") } - ) - ), - } - ) - ), - props.error !== undefined && - jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), - jsxRuntime.jsx(formBase.FormBase, { - clearError: props.clearError, - onError: props.onError, - formFields: formFields, - buttonLabel: "EMAIL_PASSWORD_RESET_SEND_BTN", - onSuccess: onSuccess, - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter( - void 0, - void 0, - void 0, - function () { - var validationErrors, emailField, resp; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [ - 4 /*yield*/, - genericComponentOverrideContext.validateForm( - formFields, - props.config.resetPasswordUsingTokenFeature - .enterEmailForm.formFields - ), - ]; - case 1: - validationErrors = _a.sent(); - if (validationErrors.length > 0) { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: validationErrors, - }, - ]; - } - emailField = formFields.find(function (field) { - return field.id === "email"; - }); - if (emailField !== undefined) { - setEmailFieldValue(emailField.value); - } - return [ - 4 /*yield*/, - props.recipeImplementation.sendPasswordResetEmail({ - formFields: formFields, - userContext: userContext, - }), - ]; - case 2: - resp = _a.sent(); - if (resp.status === "PASSWORD_RESET_NOT_ALLOWED") { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: [ - { id: "email", error: resp.reason }, - ], - }, - ]; - } - return [2 /*return*/, resp]; - } - }); - } - ); - }, - showLabels: true, - validateOnBlur: true, - }), - ], - } - ) - ), + // length >= 8 && < 100 + // must have a number and a character + // as per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 + if (value.length < 8) { + return [2 /*return*/, "ERROR_PASSWORD_TOO_SHORT"]; } - ) - ); -}; -var ResetPasswordEmail = uiEntry.withOverride("EmailPasswordResetPasswordEmail", EmailPasswordResetPasswordEmail); - -var EmailPasswordSubmitNewPassword = function (props) { - var t = translationContext.useTranslation(); - var userContext = uiEntry.useUserContext(); - var _a = React.useState("READY"), - status = _a[0], - setStatus = _a[1]; - var onSuccess = function () { - setStatus("SUCCESS"); - }; - var formFields = props.formFields, - onSignInClicked = props.onSignInClicked; - if (status === "SUCCESS") { - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_HEADER_TITLE") } - ) - ), - jsxRuntime.jsx( - formBase.FormRow, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { - "data-supertokens": - "primaryText submitNewPasswordSuccessMessage", - }, - { - children: t( - "EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_DESC" - ), - } - ) - ), - jsxRuntime.jsx(button.Button, { - disabled: false, - isLoading: false, - type: "button", - onClick: onSignInClicked, - label: "EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_SIGN_IN_BTN", - }), - ], - }), - }, - "form-button" - ), - ], - } - ) - ), - } - ) - ); - } - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_TITLE") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle" }, - { - children: jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText" }, - { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_SUBTITLE") } - ) - ), - } - ) - ), - props.error !== undefined && - jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), - jsxRuntime.jsx(formBase.FormBase, { - formFields: formFields, - clearError: props.clearError, - onError: props.onError, - buttonLabel: "EMAIL_PASSWORD_RESET_SUBMIT_PW_CHANGE_PW_BTN", - onSuccess: onSuccess, - validateOnBlur: true, - callAPI: function (fields) { - return genericComponentOverrideContext.__awaiter( - void 0, - void 0, - void 0, - function () { - var validationErrors, response; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [ - 4 /*yield*/, - genericComponentOverrideContext.validateForm( - fields, - props.config.resetPasswordUsingTokenFeature - .submitNewPasswordForm.formFields - ), - ]; - case 1: - validationErrors = _a.sent(); - if (validationErrors.length > 0) { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: validationErrors, - }, - ]; - } - // Verify that both passwords match. - if (fields[0].value !== fields[1].value) { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: [ - { - id: fields[1].id, - error: "ERROR_CONFIRM_PASSWORD_NO_MATCH", - }, - ], - }, - ]; - } - return [ - 4 /*yield*/, - props.recipeImplementation.submitNewPassword({ - formFields: fields, - userContext: userContext, - }), - ]; - case 2: - response = _a.sent(); - if ( - response.status === "RESET_PASSWORD_INVALID_TOKEN_ERROR" - ) { - throw new STGeneralError__default.default( - "EMAIL_PASSWORD_RESET_PASSWORD_INVALID_TOKEN_ERROR" - ); - } - return [ - 2 /*return*/, - response.status === "FIELD_ERROR" - ? response - : { - status: "OK", - }, - ]; - } - }); - } - ); - }, - showLabels: true, - }), - ], - } - ) - ), + if (value.length >= 100) { + return [2 /*return*/, "ERROR_PASSWORD_TOO_LONG"]; } - ) - ); -}; -var SubmitNewPassword = uiEntry.withOverride("EmailPasswordSubmitNewPassword", EmailPasswordSubmitNewPassword); - -/* - * Component. - */ -function ResetPasswordUsingTokenTheme(props) { - /* - * Render. - */ - // If no token, return SubmitNewPassword. - if (props.submitNewPasswordForm !== undefined) { - return jsxRuntime.jsx( - SubmitNewPassword, - genericComponentOverrideContext.__assign({}, props.submitNewPasswordForm) - ); - } - // Otherwise, return EnterEmail. - return jsxRuntime.jsx(ResetPasswordEmail, genericComponentOverrideContext.__assign({}, props.enterEmailForm)); -} -function ResetPasswordUsingTokenThemeWrapper(props) { - var hasFont = translations.hasFontDefined(props.config.rootStyle); - var userStyles = props.submitNewPasswordForm - ? props.config.resetPasswordUsingTokenFeature.submitNewPasswordForm.style - : props.config.resetPasswordUsingTokenFeature.enterEmailForm.style; - return jsxRuntime.jsx( - uiEntry.UserContextWrapper, - genericComponentOverrideContext.__assign( - { userContext: props.userContext }, - { - children: jsxRuntime.jsx( - translations$1.ThemeBase, - genericComponentOverrideContext.__assign( - { loadDefaultFont: !hasFont, userStyles: [props.config.rootStyle, userStyles] }, - { - children: jsxRuntime.jsx( - ResetPasswordUsingTokenTheme, - genericComponentOverrideContext.__assign({}, props) - ), - } - ) - ), + if (value.match(/^.*[A-Za-z]+.*$/) === null) { + return [2 /*return*/, "ERROR_PASSWORD_NO_ALPHA"]; } - ) - ); -} - -var defaultTranslationsEmailPassword = { - en: genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, translations.defaultTranslationsCommon.en), - translations$1.defaultTranslationsEmailVerification.en - ), - { - EMAIL_PASSWORD_EMAIL_LABEL: "Email", - EMAIL_PASSWORD_EMAIL_PLACEHOLDER: "Email address", - EMAIL_PASSWORD_PASSWORD_LABEL: "Password", - EMAIL_PASSWORD_PASSWORD_PLACEHOLDER: "Password", - EMAIL_PASSWORD_SIGN_IN_HEADER_TITLE: "Sign In", - EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_START: "Not registered yet?", - EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_SIGN_UP_LINK: "Sign Up", - EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_END: "", - EMAIL_PASSWORD_SIGN_IN_FOOTER_FORGOT_PW_LINK: "Forgot password?", - EMAIL_PASSWORD_SIGN_IN_SUBMIT_BTN: "SIGN IN", - EMAIL_PASSWORD_SIGN_IN_WRONG_CREDENTIALS_ERROR: "Incorrect email and password combination", - EMAIL_PASSWORD_SIGN_UP_HEADER_TITLE: "Sign Up", - EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_START: "Already have an account?", - EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_SIGN_IN_LINK: "Sign In", - EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_END: "", - EMAIL_PASSWORD_SIGN_UP_FOOTER_START: "By continuing, you agree to our ", - EMAIL_PASSWORD_SIGN_UP_FOOTER_TOS: "Terms of Service", - EMAIL_PASSWORD_SIGN_UP_FOOTER_AND: " and ", - EMAIL_PASSWORD_SIGN_UP_FOOTER_PP: "Privacy Policy", - EMAIL_PASSWORD_SIGN_UP_FOOTER_END: "", - EMAIL_PASSWORD_SIGN_UP_SUBMIT_BTN: "SIGN UP", - EMAIL_PASSWORD_EMAIL_ALREADY_EXISTS: "This email already exists. Please sign in instead", - EMAIL_PASSWORD_RESET_HEADER_TITLE: "Reset your password", - EMAIL_PASSWORD_RESET_HEADER_SUBTITLE: "We will send you an email to reset your password", - EMAIL_PASSWORD_RESET_SEND_FALLBACK_EMAIL: "your account", - EMAIL_PASSWORD_RESET_SEND_BEFORE_EMAIL: "A password reset email has been sent to ", - EMAIL_PASSWORD_RESET_SEND_AFTER_EMAIL: ", if it exists in our system. ", - EMAIL_PASSWORD_RESET_RESEND_LINK: "Resend or change email", - EMAIL_PASSWORD_RESET_SEND_BTN: "Email me", - EMAIL_PASSWORD_RESET_SIGN_IN_LINK: "Sign In", - EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_HEADER_TITLE: "Success!", - EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_DESC: "Your password has been updated successfully", - EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_SIGN_IN_BTN: "SIGN IN", - EMAIL_PASSWORD_NEW_PASSWORD_LABEL: "New password", - EMAIL_PASSWORD_NEW_PASSWORD_PLACEHOLDER: "New password", - EMAIL_PASSWORD_CONFIRM_PASSWORD_LABEL: "Confirm password", - EMAIL_PASSWORD_CONFIRM_PASSWORD_PLACEHOLDER: "Confirm your password", - EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_TITLE: "Change your password", - EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_SUBTITLE: "Enter a new password below to change your password", - EMAIL_PASSWORD_RESET_SUBMIT_PW_CHANGE_PW_BTN: "CHANGE PASSWORD", - EMAIL_PASSWORD_RESET_PASSWORD_INVALID_TOKEN_ERROR: "Invalid password reset token", - ERROR_EMAIL_NON_STRING: "Email must be of type string", - ERROR_EMAIL_INVALID: "Email is invalid", - ERROR_PASSWORD_NON_STRING: "Password must be of type string", - ERROR_PASSWORD_TOO_SHORT: "Password must contain at least 8 characters, including a number", - ERROR_PASSWORD_TOO_LONG: "Password's length must be lesser than 100 characters", - ERROR_PASSWORD_NO_ALPHA: "Password must contain at least one alphabet", - ERROR_PASSWORD_NO_NUM: "Password must contain at least one number", - ERROR_CONFIRM_PASSWORD_NO_MATCH: "Confirmation password doesn't match", - ERROR_NON_OPTIONAL: "Field is not optional", - /* - * The following are error messages from our backend SDK. - * These are returned as full messages to preserver compatibilty, but they work just like the keys above. - * They are shown as is by default (setting the value to undefined will display the raw translation key) - */ - "This email already exists. Please sign in instead.": undefined, - "Field is not optional": undefined, - "Password must contain at least 8 characters, including a number": undefined, - "Password's length must be lesser than 100 characters": undefined, - "Password must contain at least one alphabet": undefined, - "Password must contain at least one number": undefined, - "Email is invalid": undefined, - "Reset password link was not created because of account take over risk. Please contact support. (ERR_CODE_001)": - undefined, - "Cannot sign up due to security reasons. Please try logging in, use a different login method or contact support. (ERR_CODE_007)": - undefined, - "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)": - undefined, - } - ), -}; - -var ResetPasswordUsingToken$1 = function (props) { - var token = genericComponentOverrideContext.getQueryParams("token"); - var _a = React__namespace.useState(), - error = _a[0], - setError = _a[1]; - var enterEmailFormFeature = props.recipe.config.resetPasswordUsingTokenFeature.enterEmailForm; - var submitNewPasswordFormFeature = props.recipe.config.resetPasswordUsingTokenFeature.submitNewPasswordForm; - var submitNewPasswordForm = - token === undefined || token === null - ? undefined - : { - error: error, - onError: function (error) { - return setError(error); - }, - clearError: function () { - return setError(undefined); - }, - styleFromInit: submitNewPasswordFormFeature.style, - formFields: submitNewPasswordFormFeature.formFields, - recipeImplementation: props.recipe.webJSRecipe, - config: props.recipe.config, - onSignInClicked: function () { - void genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - show: "signin", - history: props.history, - redirectBack: false, - }); - }, - token: token, - }; - var enterEmailForm = { - onBackButtonClicked: function () { - return genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - show: "signin", - history: props.history, - redirectBack: false, - }); - }, - error: error, - onError: function (error) { - return setError(error); - }, - clearError: function () { - return setError(undefined); - }, - styleFromInit: enterEmailFormFeature.style, - formFields: enterEmailFormFeature.formFields, - recipeImplementation: props.recipe.webJSRecipe, - config: props.recipe.config, - }; - var childProps = { - config: props.recipe.config, - submitNewPasswordForm: submitNewPasswordForm, - enterEmailForm: enterEmailForm, - }; - var recipeComponentOverrides = props.useComponentOverrides(); - return jsxRuntime.jsx( - uiEntry.ComponentOverrideContext.Provider, - genericComponentOverrideContext.__assign( - { value: recipeComponentOverrides }, - { - children: jsxRuntime.jsx( - uiEntry.FeatureWrapper, - genericComponentOverrideContext.__assign( - { - useShadowDom: props.recipe.config.useShadowDom, - defaultStore: defaultTranslationsEmailPassword, - }, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - props.children === undefined && - jsxRuntime.jsx( - ResetPasswordUsingTokenThemeWrapper, - genericComponentOverrideContext.__assign({}, childProps) - ), - props.children && - React__namespace.Children.map(props.children, function (child) { - if (React__namespace.isValidElement(child)) { - return React__namespace.cloneElement(child, childProps); - } - return child; - }), - ], - }), - } - ) - ), + if (value.match(/^.*[0-9]+.*$/) === null) { + return [2 /*return*/, "ERROR_PASSWORD_NO_NUM"]; } - ) - ); -}; - -var SignInFooter = uiEntry.withOverride("EmailPasswordSignInFooter", function EmailPasswordSignInFooter(_a) { - var onClick = _a.onClick; - var t = translationContext.useTranslation(); - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "link secondaryText forgotPasswordLink", onClick: onClick }, - { children: t("EMAIL_PASSWORD_SIGN_IN_FOOTER_FORGOT_PW_LINK") } - ) - ); -}); - -var SignInForm = uiEntry.withOverride("EmailPasswordSignInForm", function EmailPasswordSignInForm(props) { - var _this = this; - var userContext = uiEntry.useUserContext(); - return jsxRuntime.jsx(formBase.FormBase, { - formFields: props.formFields, - clearError: props.clearError, - onError: props.onError, - buttonLabel: "EMAIL_PASSWORD_SIGN_IN_SUBMIT_BTN", - onSuccess: props.onSuccess, - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var validationErrors, response; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [ - 4 /*yield*/, - genericComponentOverrideContext.validateForm( - formFields, - props.config.signInAndUpFeature.signInForm.formFields - ), - ]; - case 1: - validationErrors = _a.sent(); - if (validationErrors.length > 0) { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: validationErrors, - }, - ]; - } - return [ - 4 /*yield*/, - props.recipeImplementation.signIn({ - formFields: formFields, - userContext: userContext, - }), - ]; - case 2: - response = _a.sent(); - if (response.status === "WRONG_CREDENTIALS_ERROR") { - throw new STGeneralError__default.default( - "EMAIL_PASSWORD_SIGN_IN_WRONG_CREDENTIALS_ERROR" - ); - } else if (response.status === "SIGN_IN_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); - } else { - return [2 /*return*/, response]; - } - } - }); - }); - }, - validateOnBlur: false, - showLabels: true, - footer: props.footer, - }); -}); - -var SignInHeader = uiEntry.withOverride("EmailPasswordSignInHeader", function EmailPasswordSignInHeader(_a) { - var onClick = _a.onClick; - var t = translationContext.useTranslation(); - return jsxRuntime.jsxs(React.Fragment, { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("EMAIL_PASSWORD_SIGN_IN_HEADER_TITLE") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText" }, - { - children: [ - t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_START"), - jsxRuntime.jsx( - "span", - genericComponentOverrideContext.__assign( - { "data-supertokens": "link", onClick: onClick }, - { children: t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_SIGN_UP_LINK") } - ) - ), - t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_END"), - ], - } - ) - ), - } - ) - ), - jsxRuntime.jsx("div", { "data-supertokens": "divider" }), - ], + return [2 /*return*/, undefined]; + }); }); -}); - -var SignIn = uiEntry.withOverride("EmailPasswordSignIn", function EmailPasswordSignIn(props) { - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: [ - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsx(SignInHeader, { onClick: props.signUpClicked }), - props.error !== undefined && - jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), - jsxRuntime.jsx( - SignInForm, - genericComponentOverrideContext.__assign({}, props, { - footer: jsxRuntime.jsx(SignInFooter, { - onClick: props.forgotPasswordClick, - }), - }) - ), - ], - } - ) - ), - jsxRuntime.jsx(SuperTokensBranding.SuperTokensBranding, {}), - ], - } - ) - ); -}); - -var SignUpFooter = uiEntry.withOverride("EmailPasswordSignUpFooter", function EmailPasswordSignUpFooter(_a) { - var termsOfServiceLink = _a.termsOfServiceLink, - privacyPolicyLink = _a.privacyPolicyLink; - var t = translationContext.useTranslation(); - if (termsOfServiceLink === undefined && privacyPolicyLink === undefined) { - return null; - } - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText privacyPolicyAndTermsAndConditions" }, - { - children: [ - t("EMAIL_PASSWORD_SIGN_UP_FOOTER_START"), - termsOfServiceLink !== undefined && - jsxRuntime.jsx( - "a", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "link", - href: termsOfServiceLink, - target: "_blank", - rel: "noopener noreferer", - }, - { children: t("EMAIL_PASSWORD_SIGN_UP_FOOTER_TOS") } - ) - ), - termsOfServiceLink !== undefined && - privacyPolicyLink !== undefined && - t("EMAIL_PASSWORD_SIGN_UP_FOOTER_AND"), - privacyPolicyLink !== undefined && - jsxRuntime.jsx( - "a", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "link", - href: privacyPolicyLink, - target: "_blank", - rel: "noopener noreferer", - }, - { children: t("EMAIL_PASSWORD_SIGN_UP_FOOTER_PP") } - ) - ), - t("EMAIL_PASSWORD_SIGN_UP_FOOTER_END"), - ], - } - ) - ); -}); - +} /* - * Component. + * defaultLoginPasswordValidator. + * type string */ -var SignUpForm = uiEntry.withOverride("EmailPasswordSignUpForm", function EmailPasswordSignUpForm(props) { - var _this = this; - var userContext = uiEntry.useUserContext(); - return jsxRuntime.jsx(formBase.FormBase, { - formFields: props.formFields, - clearError: props.clearError, - onError: props.onError, - buttonLabel: "EMAIL_PASSWORD_SIGN_UP_SUBMIT_BTN", - onSuccess: props.onSuccess, - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var validationErrors, res; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [ - 4 /*yield*/, - genericComponentOverrideContext.validateForm( - formFields, - props.config.signInAndUpFeature.signUpForm.formFields - ), - ]; - case 1: - validationErrors = _a.sent(); - if (validationErrors.length > 0) { - return [ - 2 /*return*/, - { - status: "FIELD_ERROR", - formFields: validationErrors, - }, - ]; - } - return [ - 4 /*yield*/, - props.recipeImplementation.signUp({ - formFields: formFields, - userContext: userContext, - }), - ]; - case 2: - res = _a.sent(); - if (res.status === "SIGN_UP_NOT_ALLOWED") { - throw new STGeneralError__default$1.default(res.reason); - } - return [2 /*return*/, res]; - } - }); - }); - }, - validateOnBlur: true, - showLabels: true, - footer: props.footer, - }); -}); - -var SignUpHeader = uiEntry.withOverride("EmailPasswordSignUpHeader", function EmailPasswordSignUpHeader(_a) { - var onClick = _a.onClick; - var t = translationContext.useTranslation(); - return jsxRuntime.jsxs(React.Fragment, { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("EMAIL_PASSWORD_SIGN_UP_HEADER_TITLE") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText" }, - { - children: [ - t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_START"), - jsxRuntime.jsx( - "span", - genericComponentOverrideContext.__assign( - { "data-supertokens": "link", onClick: onClick }, - { children: t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_SIGN_IN_LINK") } - ) - ), - t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_END"), - ], - } - ) - ), - } - ) - ), - jsxRuntime.jsx("div", { "data-supertokens": "divider" }), - ], - }); -}); - -var SignUp = uiEntry.withOverride("EmailPasswordSignUp", function EmailPasswordSignUp(props) { - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: [ - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: [ - jsxRuntime.jsx(SignUpHeader, { onClick: props.signInClicked }), - props.error !== undefined && - jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), - jsxRuntime.jsx( - SignUpForm, - genericComponentOverrideContext.__assign({}, props, { - footer: jsxRuntime.jsx(SignUpFooter, { - privacyPolicyLink: - props.config.signInAndUpFeature.signUpForm.privacyPolicyLink, - termsOfServiceLink: - props.config.signInAndUpFeature.signUpForm.termsOfServiceLink, - }), - }) - ), - ], - } - ) - ), - jsxRuntime.jsx(SuperTokensBranding.SuperTokensBranding, {}), - ], - } - ) - ); -}); - -var SignInAndUpTheme = function (props) { - // If isSignUp, return signUp. - if (props.featureState.isSignUp) { - return jsxRuntime.jsx( - SignUp, - genericComponentOverrideContext.__assign({}, props.signUpForm, { - signInClicked: function () { - props.dispatch({ type: "setSignIn" }); - }, - }) - ); - } - // Otherwise, return SignIn. - return jsxRuntime.jsx( - SignIn, - genericComponentOverrideContext.__assign({}, props.signInForm, { - signUpClicked: function () { - props.dispatch({ type: "setSignUp" }); - }, - }) - ); -}; -function SignInAndUpThemeWrapper(props) { - var hasFont = translations.hasFontDefined(props.config.rootStyle); - var activeStyle = props.featureState.isSignUp - ? props.config.signInAndUpFeature.signUpForm.style - : props.config.signInAndUpFeature.signInForm.style; - return jsxRuntime.jsx( - uiEntry.UserContextWrapper, - genericComponentOverrideContext.__assign( - { userContext: props.userContext }, - { - children: jsxRuntime.jsx( - translations$1.ThemeBase, - genericComponentOverrideContext.__assign( - { loadDefaultFont: !hasFont, userStyles: [props.config.rootStyle, activeStyle] }, - { - children: jsxRuntime.jsx( - SignInAndUpTheme, - genericComponentOverrideContext.__assign({}, props) - ), - } - ) - ), - } - ) - ); -} - -var useFeatureReducer = function (recipe) { - return React__namespace.useReducer( - function (oldState, action) { - switch (action.type) { - case "setSignIn": - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, oldState), - { error: undefined, isSignUp: false } - ); - case "setSignUp": - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, oldState), - { error: undefined, isSignUp: true } - ); - case "setError": - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, oldState), - { error: action.error } - ); - default: - return oldState; +function defaultLoginPasswordValidator(value) { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + if (typeof value !== "string") { + return [2 /*return*/, "ERROR_PASSWORD_NON_STRING"]; } - }, - { - isSignUp: recipe === undefined ? false : recipe.config.signInAndUpFeature.defaultToSignUp, - user: undefined, - error: undefined, - }, - function (initArg) { - var show = genericComponentOverrideContext.getQueryParams("show"); - var isSignUp = initArg.isSignUp; - if (show !== null) { - isSignUp = show === "signup"; - } - return { - isSignUp: isSignUp, - user: undefined, - error: undefined, - }; - } - ); -}; -function useChildProps(recipe$1, state, dispatch, history) { - var _this = this; - var recipeImplementation = React.useMemo( - function () { - return recipe$1 && getModifiedRecipeImplementation(recipe$1.webJSRecipe); - }, - [recipe$1] - ); - var userContext = uiEntry.useUserContext(); - var onSignInSuccess = React.useCallback( - function (response) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - return [ - 2 /*return*/, - recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( - { - rid: recipe$1.config.recipeId, - successRedirectContext: { - action: "SUCCESS", - isNewRecipeUser: false, - user: response.user, - redirectToPath: genericComponentOverrideContext.getRedirectToPathFromURL(), - }, - }, - userContext, - history - ), - ]; - }); - }); - }, - [recipe$1, userContext, history] - ); - var onSignUpSuccess = React.useCallback( - function (response) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - return [ - 2 /*return*/, - recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( - { - rid: recipe$1.config.recipeId, - successRedirectContext: { - action: "SUCCESS", - isNewRecipeUser: true, - user: response.user, - redirectToPath: genericComponentOverrideContext.getRedirectToPathFromURL(), - }, - }, - userContext, - history - ), - ]; - }); - }); - }, - [recipe$1, userContext, history] - ); - return React.useMemo( - function () { - if (recipe$1 === undefined || recipeImplementation === undefined) { - return; - } - var signInAndUpFeature = recipe$1.config.signInAndUpFeature; - var signUpFeature = signInAndUpFeature.signUpForm; - var signInFeature = signInAndUpFeature.signInForm; - var signInForm = { - recipeImplementation: recipeImplementation, - config: recipe$1.config, - styleFromInit: signInFeature.style, - formFields: signInFeature.formFields, - error: state.error, - clearError: function () { - return dispatch({ type: "setError", error: undefined }); - }, - onError: function (error) { - return dispatch({ type: "setError", error: error }); - }, - onSuccess: onSignInSuccess, - forgotPasswordClick: function () { - return recipe$1.redirect({ action: "RESET_PASSWORD" }, history); - }, - }; - var signUpForm = { - recipeImplementation: recipeImplementation, - config: recipe$1.config, - styleFromInit: signUpFeature.style, - formFields: getThemeSignUpFeatureFormFields(signUpFeature.formFields, recipe$1, userContext), - error: state.error, - clearError: function () { - return dispatch({ type: "setError", error: undefined }); - }, - onError: function (error) { - return dispatch({ type: "setError", error: error }); - }, - onSuccess: onSignUpSuccess, - }; - return { - config: recipe$1.config, - signInForm: signInForm, - signUpForm: signUpForm, - }; - }, - [recipe$1, state, dispatch] - ); + return [2 /*return*/, undefined]; + }); + }); } -var SignInAndUpFeature = function (props) { - var _a = useFeatureReducer(props.recipe), - state = _a[0], - dispatch = _a[1]; - var childProps = useChildProps(props.recipe, state, dispatch, props.history); - var recipeComponentOverrides = props.useComponentOverrides(); - return jsxRuntime.jsx( - uiEntry.ComponentOverrideContext.Provider, - genericComponentOverrideContext.__assign( - { value: recipeComponentOverrides }, - { - children: jsxRuntime.jsx( - uiEntry.FeatureWrapper, - genericComponentOverrideContext.__assign( - { - useShadowDom: props.recipe.config.useShadowDom, - defaultStore: defaultTranslationsEmailPassword, - }, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - props.children === undefined && - jsxRuntime.jsx( - SignInAndUpThemeWrapper, - genericComponentOverrideContext.__assign({}, childProps, { - featureState: state, - dispatch: dispatch, - }) - ), - props.children && - React__namespace.Children.map(props.children, function (child) { - if (React__namespace.isValidElement(child)) { - return React__namespace.cloneElement( - child, - genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, childProps), - { featureState: state, dispatch: dispatch } - ) - ); - } - return child; - }), - ], - }), - } - ) - ), - } - ) - ); -}; -var getModifiedRecipeImplementation = function (origImpl) { - return genericComponentOverrideContext.__assign({}, origImpl); -}; -function getThemeSignUpFeatureFormFields(formFields, recipe, userContext) { - var _this = this; - var emailPasswordOnly = formFields.length === 2; - return formFields.map(function (field) { - return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, field), { - showIsRequired: (function () { - // If email and password only, do not show required indicator (*). - if (emailPasswordOnly) { - return false; - } - // Otherwise, show for all non optional fields (including email and password). - return field.optional === false; - })(), - validate: (function () { - // If field is not email, return field validate unchanged. - if (field.id !== "email") { - return field.validate; - } - // Otherwise, if email, use syntax validate method and check if email exists. - return function (value) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var error, emailExists, err_1; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [4 /*yield*/, field.validate(value)]; - case 1: - error = _a.sent(); - if (error !== undefined) { - return [2 /*return*/, error]; - } - if (typeof value !== "string") { - return [2 /*return*/, "GENERAL_ERROR_EMAIL_NON_STRING"]; - } - _a.label = 2; - case 2: - _a.trys.push([2, 4, , 5]); - return [ - 4 /*yield*/, - recipe.webJSRecipe.doesEmailExist({ - email: value, - userContext: userContext, - }), - ]; - case 3: - emailExists = _a.sent().doesExist; - if (emailExists) { - return [2 /*return*/, "EMAIL_PASSWORD_EMAIL_ALREADY_EXISTS"]; - } - return [3 /*break*/, 5]; - case 4: - err_1 = _a.sent(); - if (STGeneralError__default.default.isThisError(err_1)) { - return [2 /*return*/, err_1.message]; - } - return [3 /*break*/, 5]; - case 5: - return [2 /*return*/, undefined]; - } - }); - }); - }; - })(), +/* + * defaultValidate + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function defaultValidate(_) { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + return [2 /*return*/, undefined]; }); }); } -var EmailPasswordPreBuiltUI = /** @class */ (function (_super) { - genericComponentOverrideContext.__extends(EmailPasswordPreBuiltUI, _super); - function EmailPasswordPreBuiltUI(recipeInstance) { - var _this = _super.call(this) || this; - _this.recipeInstance = recipeInstance; - // Instance methods - _this.getFeatures = function (useComponentOverrides) { - if (useComponentOverrides === void 0) { - useComponentOverrides = componentOverrideContext.useContext; - } - var features = {}; - if (_this.recipeInstance.config.signInAndUpFeature.disableDefaultUI !== true) { - var normalisedFullPath = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( - new NormalisedURLPath__default.default("/") - ); - features[normalisedFullPath.getAsStringDangerous()] = { - matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( - _this.recipeInstance.config.recipeId - ), - component: function (props) { - return _this.getFeatureComponent("signinup", props, useComponentOverrides); - }, - recipeID: recipe$1.EmailPassword.RECIPE_ID, - }; - } - if (_this.recipeInstance.config.resetPasswordUsingTokenFeature.disableDefaultUI !== true) { - var normalisedFullPath = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( - new NormalisedURLPath__default.default(validators.DEFAULT_RESET_PASSWORD_PATH) - ); - features[normalisedFullPath.getAsStringDangerous()] = { - matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( - _this.recipeInstance.config.recipeId - ), - component: function (props) { - return _this.getFeatureComponent("resetpassword", props, useComponentOverrides); - }, - recipeID: recipe$1.EmailPassword.RECIPE_ID, - }; - } - return features; - }; - _this.getFeatureComponent = function (componentName, props, useComponentOverrides) { - if (useComponentOverrides === void 0) { - useComponentOverrides = componentOverrideContext.useContext; - } - if (componentName === "signinup") { - if (props.redirectOnSessionExists !== false) { - return jsxRuntime.jsx( - uiEntry.UserContextWrapper, - genericComponentOverrideContext.__assign( - { userContext: props.userContext }, - { - children: jsxRuntime.jsx( - authWidgetWrapper.AuthWidgetWrapper, - genericComponentOverrideContext.__assign( - { authRecipe: _this.recipeInstance, history: props.history }, - { - children: jsxRuntime.jsx( - SignInAndUpFeature, - genericComponentOverrideContext.__assign( - { recipe: _this.recipeInstance }, - props, - { useComponentOverrides: useComponentOverrides } - ) - ), - } - ) - ), - } - ) - ); - } else { - return jsxRuntime.jsx( - uiEntry.UserContextWrapper, - genericComponentOverrideContext.__assign( - { userContext: props.userContext }, - { - children: jsxRuntime.jsx( - SignInAndUpFeature, - genericComponentOverrideContext.__assign({ recipe: _this.recipeInstance }, props, { - useComponentOverrides: useComponentOverrides, - }) - ), - } - ) - ); - } - } else if (componentName === "resetpassword") { - return jsxRuntime.jsx( - uiEntry.UserContextWrapper, - genericComponentOverrideContext.__assign( - { userContext: props.userContext }, - { - children: jsxRuntime.jsx( - ResetPasswordUsingToken$1, - genericComponentOverrideContext.__assign({ recipe: _this.recipeInstance }, props, { - useComponentOverrides: useComponentOverrides, - }) - ), - } - ) - ); - } else { - throw new Error("Should never come here."); - } - }; - return _this; - } - // Static methods - EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance = function () { - if (EmailPasswordPreBuiltUI.instance === undefined) { - var recipeInstance = recipe$1.EmailPassword.getInstanceOrThrow(); - EmailPasswordPreBuiltUI.instance = new EmailPasswordPreBuiltUI(recipeInstance); - } - return EmailPasswordPreBuiltUI.instance; - }; - EmailPasswordPreBuiltUI.getFeatures = function (useComponentOverrides) { - if (useComponentOverrides === void 0) { - useComponentOverrides = componentOverrideContext.useContext; - } - return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatures(useComponentOverrides); - }; - EmailPasswordPreBuiltUI.getFeatureComponent = function (componentName, props, useComponentOverrides) { - if (useComponentOverrides === void 0) { - useComponentOverrides = componentOverrideContext.useContext; - } - return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent( - componentName, - props, - useComponentOverrides - ); - }; - // For tests - EmailPasswordPreBuiltUI.reset = function () { - if (!genericComponentOverrideContext.isTest()) { - return; - } - EmailPasswordPreBuiltUI.instance = undefined; - return; - }; - EmailPasswordPreBuiltUI.SignInAndUp = function (prop) { - if (prop === void 0) { - prop = {}; - } - return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent("signinup", prop); - }; - EmailPasswordPreBuiltUI.ResetPasswordUsingToken = function (prop) { - return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent("resetpassword", prop); - }; - EmailPasswordPreBuiltUI.ResetPasswordUsingTokenTheme = ResetPasswordUsingTokenThemeWrapper; - EmailPasswordPreBuiltUI.SignInAndUpTheme = SignInAndUpThemeWrapper; - return EmailPasswordPreBuiltUI; -})(uiEntry.RecipeRouter); -var SignInAndUp = EmailPasswordPreBuiltUI.SignInAndUp; -var ResetPasswordUsingToken = EmailPasswordPreBuiltUI.ResetPasswordUsingToken; - -exports.EmailPasswordPreBuiltUI = EmailPasswordPreBuiltUI; -exports.ResetPasswordUsingToken = ResetPasswordUsingToken; -exports.ResetPasswordUsingTokenThemeWrapper = ResetPasswordUsingTokenThemeWrapper; -exports.SignInAndUp = SignInAndUp; -exports.SignInAndUpThemeWrapper = SignInAndUpThemeWrapper; -exports.SignInFooter = SignInFooter; -exports.SignInForm = SignInForm; -exports.SignInHeader = SignInHeader; -exports.SignUpFooter = SignUpFooter; -exports.SignUpForm = SignUpForm; -exports.SignUpHeader = SignUpHeader; -exports.defaultTranslationsEmailPassword = defaultTranslationsEmailPassword; -exports.useChildProps = useChildProps; -exports.useFeatureReducer = useFeatureReducer; +exports.defaultEmailValidator = defaultEmailValidator; +exports.defaultLoginPasswordValidator = defaultLoginPasswordValidator; +exports.defaultPasswordValidator = defaultPasswordValidator; +exports.defaultValidate = defaultValidate; diff --git a/lib/build/emailpassword-shared7.js b/lib/build/emailpassword-shared7.js index d2336cadd..73b9b6e38 100644 --- a/lib/build/emailpassword-shared7.js +++ b/lib/build/emailpassword-shared7.js @@ -2,62 +2,1513 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); var jsxRuntime = require("react/jsx-runtime"); +var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); +var uiEntry = require("./index2.js"); +var authWidgetWrapper = require("./authRecipe-shared2.js"); +var componentOverrideContext = require("./emailpassword-shared3.js"); +var React = require("react"); +var translations = require("./translations.js"); +var translations$1 = require("./emailverification-shared2.js"); +var translationContext = require("./translationContext.js"); +var backButton = require("./emailpassword-shared8.js"); +var arrowLeftIcon = require("./arrowLeftIcon.js"); +var formBase = require("./emailpassword-shared9.js"); +var generalError = require("./emailpassword-shared.js"); +var STGeneralError = require("supertokens-web-js/utils/error"); +var button = require("./emailpassword-shared2.js"); +var recipe = require("./session-shared2.js"); +var SuperTokensBranding = require("./SuperTokensBranding.js"); +var STGeneralError$1 = require("supertokens-web-js/lib/build/error"); +var constants = require("./emailpassword-shared5.js"); +var recipe$1 = require("./emailpassword-shared4.js"); + +function _interopDefault(e) { + return e && e.__esModule ? e : { default: e }; +} + +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== "default") { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty( + n, + k, + d.get + ? d + : { + enumerable: true, + get: function () { + return e[k]; + }, + } + ); + } + }); + } + n.default = e; + return Object.freeze(n); +} + +var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath); +var React__namespace = /*#__PURE__*/ _interopNamespace(React); +var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); +var STGeneralError__default$1 = /*#__PURE__*/ _interopDefault(STGeneralError$1); -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ /* - * Imports. + * Component. */ +function BackToSignInButton(_a) { + var onClick = _a.onClick; + var t = translationContext.useTranslation(); + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", onClick: onClick }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { color: "rgb(var(--palette-secondaryText))" }), + t("EMAIL_PASSWORD_RESET_SIGN_IN_LINK"), + ], + } + ) + ); +} + +var EmailPasswordResetPasswordEmail = function (props) { + var t = translationContext.useTranslation(); + var userContext = uiEntry.useUserContext(); + var _a = React.useState("READY"), + status = _a[0], + setStatus = _a[1]; + var _b = React.useState(""), + emailFieldValue = _b[0], + setEmailFieldValue = _b[1]; + var onSuccess = function () { + setStatus("SENT"); + }; + var resend = function () { + setStatus("READY"); + }; + var formFields = props.formFields; + var emailSuccessText = + t("EMAIL_PASSWORD_RESET_SEND_BEFORE_EMAIL") + + (emailFieldValue !== undefined && emailFieldValue.length > 0 + ? emailFieldValue + : t("EMAIL_PASSWORD_RESET_SEND_FALLBACK_EMAIL")) + + t("EMAIL_PASSWORD_RESET_SEND_AFTER_EMAIL"); + if (status === "SENT") { + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "primaryText enterEmailSuccessMessage" }, + { + children: [ + emailSuccessText, + jsxRuntime.jsx( + "span", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "link resendEmailLink", + onClick: resend, + }, + { children: t("EMAIL_PASSWORD_RESET_RESEND_LINK") } + ) + ), + ], + } + ) + ), + jsxRuntime.jsx(BackToSignInButton, { onClick: props.onBackButtonClicked }), + ], + } + ) + ), + } + ) + ); + } + // Otherwise, return Form. + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle withBackButton" }, + { + children: [ + jsxRuntime.jsx(backButton.BackButton, { + onClick: props.onBackButtonClicked, + }), + t("EMAIL_PASSWORD_RESET_HEADER_TITLE"), + jsxRuntime.jsx("span", { + "data-supertokens": "backButtonPlaceholder backButtonCommon", + }), + ], + } + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerSubtitle" }, + { + children: jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText" }, + { children: t("EMAIL_PASSWORD_RESET_HEADER_SUBTITLE") } + ) + ), + } + ) + ), + props.error !== undefined && + jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), + jsxRuntime.jsx(formBase.FormBase, { + clearError: props.clearError, + onError: props.onError, + formFields: formFields, + buttonLabel: "EMAIL_PASSWORD_RESET_SEND_BTN", + onSuccess: onSuccess, + callAPI: function (formFields) { + return genericComponentOverrideContext.__awaiter( + void 0, + void 0, + void 0, + function () { + var validationErrors, emailField, resp; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + genericComponentOverrideContext.validateForm( + formFields, + props.config.resetPasswordUsingTokenFeature + .enterEmailForm.formFields + ), + ]; + case 1: + validationErrors = _a.sent(); + if (validationErrors.length > 0) { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: validationErrors, + }, + ]; + } + emailField = formFields.find(function (field) { + return field.id === "email"; + }); + if (emailField !== undefined) { + setEmailFieldValue(emailField.value); + } + return [ + 4 /*yield*/, + props.recipeImplementation.sendPasswordResetEmail({ + formFields: formFields, + userContext: userContext, + }), + ]; + case 2: + resp = _a.sent(); + if (resp.status === "PASSWORD_RESET_NOT_ALLOWED") { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: [ + { id: "email", error: resp.reason }, + ], + }, + ]; + } + return [2 /*return*/, resp]; + } + }); + } + ); + }, + showLabels: true, + validateOnBlur: true, + }), + ], + } + ) + ), + } + ) + ); +}; +var ResetPasswordEmail = uiEntry.withOverride("EmailPasswordResetPasswordEmail", EmailPasswordResetPasswordEmail); + +var EmailPasswordSubmitNewPassword = function (props) { + var t = translationContext.useTranslation(); + var userContext = uiEntry.useUserContext(); + var _a = React.useState("READY"), + status = _a[0], + setStatus = _a[1]; + var onSuccess = function () { + setStatus("SUCCESS"); + }; + var formFields = props.formFields, + onSignInClicked = props.onSignInClicked; + if (status === "SUCCESS") { + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle" }, + { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_HEADER_TITLE") } + ) + ), + jsxRuntime.jsx( + formBase.FormRow, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": + "primaryText submitNewPasswordSuccessMessage", + }, + { + children: t( + "EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_DESC" + ), + } + ) + ), + jsxRuntime.jsx(button.Button, { + disabled: false, + isLoading: false, + type: "button", + onClick: onSignInClicked, + label: "EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_SIGN_IN_BTN", + }), + ], + }), + }, + "form-button" + ), + ], + } + ) + ), + } + ) + ); + } + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle" }, + { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_TITLE") } + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerSubtitle" }, + { + children: jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText" }, + { children: t("EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_SUBTITLE") } + ) + ), + } + ) + ), + props.error !== undefined && + jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), + jsxRuntime.jsx(formBase.FormBase, { + formFields: formFields, + clearError: props.clearError, + onError: props.onError, + buttonLabel: "EMAIL_PASSWORD_RESET_SUBMIT_PW_CHANGE_PW_BTN", + onSuccess: onSuccess, + validateOnBlur: true, + callAPI: function (fields) { + return genericComponentOverrideContext.__awaiter( + void 0, + void 0, + void 0, + function () { + var validationErrors, response; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + genericComponentOverrideContext.validateForm( + fields, + props.config.resetPasswordUsingTokenFeature + .submitNewPasswordForm.formFields + ), + ]; + case 1: + validationErrors = _a.sent(); + if (validationErrors.length > 0) { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: validationErrors, + }, + ]; + } + // Verify that both passwords match. + if (fields[0].value !== fields[1].value) { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: [ + { + id: fields[1].id, + error: "ERROR_CONFIRM_PASSWORD_NO_MATCH", + }, + ], + }, + ]; + } + return [ + 4 /*yield*/, + props.recipeImplementation.submitNewPassword({ + formFields: fields, + userContext: userContext, + }), + ]; + case 2: + response = _a.sent(); + if ( + response.status === "RESET_PASSWORD_INVALID_TOKEN_ERROR" + ) { + throw new STGeneralError__default.default( + "EMAIL_PASSWORD_RESET_PASSWORD_INVALID_TOKEN_ERROR" + ); + } + return [ + 2 /*return*/, + response.status === "FIELD_ERROR" + ? response + : { + status: "OK", + }, + ]; + } + }); + } + ); + }, + showLabels: true, + }), + ], + } + ) + ), + } + ) + ); +}; +var SubmitNewPassword = uiEntry.withOverride("EmailPasswordSubmitNewPassword", EmailPasswordSubmitNewPassword); + /* * Component. */ -function HeavyArrowLeftIcon(_a) { - var color = _a.color; +function ResetPasswordUsingTokenTheme(props) { + /* + * Render. + */ + // If no token, return SubmitNewPassword. + if (props.submitNewPasswordForm !== undefined) { + return jsxRuntime.jsx( + SubmitNewPassword, + genericComponentOverrideContext.__assign({}, props.submitNewPasswordForm) + ); + } + // Otherwise, return EnterEmail. + return jsxRuntime.jsx(ResetPasswordEmail, genericComponentOverrideContext.__assign({}, props.enterEmailForm)); +} +function ResetPasswordUsingTokenThemeWrapper(props) { + var hasFont = translations.hasFontDefined(props.config.rootStyle); + var userStyles = props.submitNewPasswordForm + ? props.config.resetPasswordUsingTokenFeature.submitNewPasswordForm.style + : props.config.resetPasswordUsingTokenFeature.enterEmailForm.style; return jsxRuntime.jsx( - "svg", + uiEntry.UserContextWrapper, genericComponentOverrideContext.__assign( + { userContext: props.userContext }, { - xmlns: "http://www.w3.org/2000/svg", - width: "16", - height: "13", - viewBox: "0 0 16 13", - "data-supertokens": "heavyArrowLeftIcon", - }, - { - children: jsxRuntime.jsx("path", { - fill: color, - d: "M13 6.8h.022H3.8l2.9 2.9a.761.761 0 0 1 0 1.07l-.451.451a.754.754 0 0 1-1.064 0L.22 6.254a.759.759 0 0 1 0-1.068L5.186.22a.755.755 0 0 1 1.064 0l.45.451a.746.746 0 0 1 .22.532.724.724 0 0 1-.22.522l-2.93 2.92h9.24a.781.781 0 0 1 .764.773v.638A.766.766 0 0 1 13 6.8z", - transform: "translate(1.182 .708)", - }), + children: jsxRuntime.jsx( + translations$1.ThemeBase, + genericComponentOverrideContext.__assign( + { loadDefaultFont: !hasFont, userStyles: [props.config.rootStyle, userStyles] }, + { + children: jsxRuntime.jsx( + ResetPasswordUsingTokenTheme, + genericComponentOverrideContext.__assign({}, props) + ), + } + ) + ), } ) ); } +var defaultTranslationsEmailPassword = { + en: genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, translations.defaultTranslationsCommon.en), + translations$1.defaultTranslationsEmailVerification.en + ), + { + EMAIL_PASSWORD_EMAIL_LABEL: "Email", + EMAIL_PASSWORD_EMAIL_PLACEHOLDER: "Email address", + EMAIL_PASSWORD_PASSWORD_LABEL: "Password", + EMAIL_PASSWORD_PASSWORD_PLACEHOLDER: "Password", + EMAIL_PASSWORD_SIGN_IN_HEADER_TITLE: "Sign In", + EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_START: "Not registered yet?", + EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_SIGN_UP_LINK: "Sign Up", + EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_END: "", + EMAIL_PASSWORD_SIGN_IN_FOOTER_FORGOT_PW_LINK: "Forgot password?", + EMAIL_PASSWORD_SIGN_IN_SUBMIT_BTN: "SIGN IN", + EMAIL_PASSWORD_SIGN_IN_WRONG_CREDENTIALS_ERROR: "Incorrect email and password combination", + EMAIL_PASSWORD_SIGN_UP_HEADER_TITLE: "Sign Up", + EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_START: "Already have an account?", + EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_SIGN_IN_LINK: "Sign In", + EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_END: "", + EMAIL_PASSWORD_SIGN_UP_FOOTER_START: "By continuing, you agree to our ", + EMAIL_PASSWORD_SIGN_UP_FOOTER_TOS: "Terms of Service", + EMAIL_PASSWORD_SIGN_UP_FOOTER_AND: " and ", + EMAIL_PASSWORD_SIGN_UP_FOOTER_PP: "Privacy Policy", + EMAIL_PASSWORD_SIGN_UP_FOOTER_END: "", + EMAIL_PASSWORD_SIGN_UP_SUBMIT_BTN: "SIGN UP", + EMAIL_PASSWORD_EMAIL_ALREADY_EXISTS: "This email already exists. Please sign in instead", + EMAIL_PASSWORD_RESET_HEADER_TITLE: "Reset your password", + EMAIL_PASSWORD_RESET_HEADER_SUBTITLE: "We will send you an email to reset your password", + EMAIL_PASSWORD_RESET_SEND_FALLBACK_EMAIL: "your account", + EMAIL_PASSWORD_RESET_SEND_BEFORE_EMAIL: "A password reset email has been sent to ", + EMAIL_PASSWORD_RESET_SEND_AFTER_EMAIL: ", if it exists in our system. ", + EMAIL_PASSWORD_RESET_RESEND_LINK: "Resend or change email", + EMAIL_PASSWORD_RESET_SEND_BTN: "Email me", + EMAIL_PASSWORD_RESET_SIGN_IN_LINK: "Sign In", + EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_HEADER_TITLE: "Success!", + EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_DESC: "Your password has been updated successfully", + EMAIL_PASSWORD_RESET_SUBMIT_PW_SUCCESS_SIGN_IN_BTN: "SIGN IN", + EMAIL_PASSWORD_NEW_PASSWORD_LABEL: "New password", + EMAIL_PASSWORD_NEW_PASSWORD_PLACEHOLDER: "New password", + EMAIL_PASSWORD_CONFIRM_PASSWORD_LABEL: "Confirm password", + EMAIL_PASSWORD_CONFIRM_PASSWORD_PLACEHOLDER: "Confirm your password", + EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_TITLE: "Change your password", + EMAIL_PASSWORD_RESET_SUBMIT_PW_HEADER_SUBTITLE: "Enter a new password below to change your password", + EMAIL_PASSWORD_RESET_SUBMIT_PW_CHANGE_PW_BTN: "CHANGE PASSWORD", + EMAIL_PASSWORD_RESET_PASSWORD_INVALID_TOKEN_ERROR: "Invalid password reset token", + ERROR_EMAIL_NON_STRING: "Email must be of type string", + ERROR_EMAIL_INVALID: "Email is invalid", + ERROR_PASSWORD_NON_STRING: "Password must be of type string", + ERROR_PASSWORD_TOO_SHORT: "Password must contain at least 8 characters, including a number", + ERROR_PASSWORD_TOO_LONG: "Password's length must be lesser than 100 characters", + ERROR_PASSWORD_NO_ALPHA: "Password must contain at least one alphabet", + ERROR_PASSWORD_NO_NUM: "Password must contain at least one number", + ERROR_CONFIRM_PASSWORD_NO_MATCH: "Confirmation password doesn't match", + ERROR_NON_OPTIONAL: "Field is not optional", + /* + * The following are error messages from our backend SDK. + * These are returned as full messages to preserver compatibilty, but they work just like the keys above. + * They are shown as is by default (setting the value to undefined will display the raw translation key) + */ + "This email already exists. Please sign in instead.": undefined, + "Field is not optional": undefined, + "Password must contain at least 8 characters, including a number": undefined, + "Password's length must be lesser than 100 characters": undefined, + "Password must contain at least one alphabet": undefined, + "Password must contain at least one number": undefined, + "Email is invalid": undefined, + "Reset password link was not created because of account take over risk. Please contact support. (ERR_CODE_001)": + undefined, + "Cannot sign up due to security reasons. Please try logging in, use a different login method or contact support. (ERR_CODE_007)": + undefined, + "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)": + undefined, + } + ), +}; + +var ResetPasswordUsingToken$1 = function (props) { + var token = genericComponentOverrideContext.getQueryParams("token"); + var _a = React__namespace.useState(), + error = _a[0], + setError = _a[1]; + var enterEmailFormFeature = props.recipe.config.resetPasswordUsingTokenFeature.enterEmailForm; + var submitNewPasswordFormFeature = props.recipe.config.resetPasswordUsingTokenFeature.submitNewPasswordForm; + var submitNewPasswordForm = + token === undefined || token === null + ? undefined + : { + error: error, + onError: function (error) { + return setError(error); + }, + clearError: function () { + return setError(undefined); + }, + styleFromInit: submitNewPasswordFormFeature.style, + formFields: submitNewPasswordFormFeature.formFields, + recipeImplementation: props.recipe.webJSRecipe, + config: props.recipe.config, + onSignInClicked: function () { + void genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ + show: "signin", + history: props.history, + redirectBack: false, + }); + }, + token: token, + }; + var enterEmailForm = { + onBackButtonClicked: function () { + return genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ + show: "signin", + history: props.history, + redirectBack: false, + }); + }, + error: error, + onError: function (error) { + return setError(error); + }, + clearError: function () { + return setError(undefined); + }, + styleFromInit: enterEmailFormFeature.style, + formFields: enterEmailFormFeature.formFields, + recipeImplementation: props.recipe.webJSRecipe, + config: props.recipe.config, + }; + var childProps = { + config: props.recipe.config, + submitNewPasswordForm: submitNewPasswordForm, + enterEmailForm: enterEmailForm, + }; + var recipeComponentOverrides = props.useComponentOverrides(); + return jsxRuntime.jsx( + uiEntry.ComponentOverrideContext.Provider, + genericComponentOverrideContext.__assign( + { value: recipeComponentOverrides }, + { + children: jsxRuntime.jsx( + uiEntry.FeatureWrapper, + genericComponentOverrideContext.__assign( + { + useShadowDom: props.recipe.config.useShadowDom, + defaultStore: defaultTranslationsEmailPassword, + }, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + props.children === undefined && + jsxRuntime.jsx( + ResetPasswordUsingTokenThemeWrapper, + genericComponentOverrideContext.__assign({}, childProps) + ), + props.children && + React__namespace.Children.map(props.children, function (child) { + if (React__namespace.isValidElement(child)) { + return React__namespace.cloneElement(child, childProps); + } + return child; + }), + ], + }), + } + ) + ), + } + ) + ); +}; + +var SignInFooter = uiEntry.withOverride("EmailPasswordSignInFooter", function EmailPasswordSignInFooter(_a) { + var onClick = _a.onClick; + var t = translationContext.useTranslation(); + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "link secondaryText forgotPasswordLink", onClick: onClick }, + { children: t("EMAIL_PASSWORD_SIGN_IN_FOOTER_FORGOT_PW_LINK") } + ) + ); +}); + +var SignInForm = uiEntry.withOverride("EmailPasswordSignInForm", function EmailPasswordSignInForm(props) { + var _this = this; + var userContext = uiEntry.useUserContext(); + return jsxRuntime.jsx(formBase.FormBase, { + formFields: props.formFields, + clearError: props.clearError, + onError: props.onError, + buttonLabel: "EMAIL_PASSWORD_SIGN_IN_SUBMIT_BTN", + onSuccess: props.onSuccess, + callAPI: function (formFields) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var validationErrors, response; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + genericComponentOverrideContext.validateForm( + formFields, + props.config.signInAndUpFeature.signInForm.formFields + ), + ]; + case 1: + validationErrors = _a.sent(); + if (validationErrors.length > 0) { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: validationErrors, + }, + ]; + } + return [ + 4 /*yield*/, + props.recipeImplementation.signIn({ + formFields: formFields, + userContext: userContext, + }), + ]; + case 2: + response = _a.sent(); + if (response.status === "WRONG_CREDENTIALS_ERROR") { + throw new STGeneralError__default.default( + "EMAIL_PASSWORD_SIGN_IN_WRONG_CREDENTIALS_ERROR" + ); + } else if (response.status === "SIGN_IN_NOT_ALLOWED") { + throw new STGeneralError__default.default(response.reason); + } else { + return [2 /*return*/, response]; + } + } + }); + }); + }, + validateOnBlur: false, + showLabels: true, + footer: props.footer, + }); +}); + +var SignInHeader = uiEntry.withOverride("EmailPasswordSignInHeader", function EmailPasswordSignInHeader(_a) { + var onClick = _a.onClick; + var t = translationContext.useTranslation(); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle" }, + { children: t("EMAIL_PASSWORD_SIGN_IN_HEADER_TITLE") } + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerSubtitle" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText" }, + { + children: [ + t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_START"), + jsxRuntime.jsx( + "span", + genericComponentOverrideContext.__assign( + { "data-supertokens": "link", onClick: onClick }, + { children: t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_SIGN_UP_LINK") } + ) + ), + t("EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_END"), + ], + } + ) + ), + } + ) + ), + jsxRuntime.jsx("div", { "data-supertokens": "divider" }), + ], + }); +}); + +var SignIn = uiEntry.withOverride("EmailPasswordSignIn", function EmailPasswordSignIn(props) { + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsx(SignInHeader, { onClick: props.signUpClicked }), + props.error !== undefined && + jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), + jsxRuntime.jsx( + SignInForm, + genericComponentOverrideContext.__assign({}, props, { + footer: jsxRuntime.jsx(SignInFooter, { + onClick: props.forgotPasswordClick, + }), + }) + ), + ], + } + ) + ), + jsxRuntime.jsx(SuperTokensBranding.SuperTokensBranding, {}), + ], + } + ) + ); +}); + +var SignUpFooter = uiEntry.withOverride("EmailPasswordSignUpFooter", function EmailPasswordSignUpFooter(_a) { + var termsOfServiceLink = _a.termsOfServiceLink, + privacyPolicyLink = _a.privacyPolicyLink; + var t = translationContext.useTranslation(); + if (termsOfServiceLink === undefined && privacyPolicyLink === undefined) { + return null; + } + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText privacyPolicyAndTermsAndConditions" }, + { + children: [ + t("EMAIL_PASSWORD_SIGN_UP_FOOTER_START"), + termsOfServiceLink !== undefined && + jsxRuntime.jsx( + "a", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "link", + href: termsOfServiceLink, + target: "_blank", + rel: "noopener noreferer", + }, + { children: t("EMAIL_PASSWORD_SIGN_UP_FOOTER_TOS") } + ) + ), + termsOfServiceLink !== undefined && + privacyPolicyLink !== undefined && + t("EMAIL_PASSWORD_SIGN_UP_FOOTER_AND"), + privacyPolicyLink !== undefined && + jsxRuntime.jsx( + "a", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "link", + href: privacyPolicyLink, + target: "_blank", + rel: "noopener noreferer", + }, + { children: t("EMAIL_PASSWORD_SIGN_UP_FOOTER_PP") } + ) + ), + t("EMAIL_PASSWORD_SIGN_UP_FOOTER_END"), + ], + } + ) + ); +}); + /* * Component. */ -function BackButton(_a) { +var SignUpForm = uiEntry.withOverride("EmailPasswordSignUpForm", function EmailPasswordSignUpForm(props) { + var _this = this; + var userContext = uiEntry.useUserContext(); + return jsxRuntime.jsx(formBase.FormBase, { + formFields: props.formFields, + clearError: props.clearError, + onError: props.onError, + buttonLabel: "EMAIL_PASSWORD_SIGN_UP_SUBMIT_BTN", + onSuccess: props.onSuccess, + callAPI: function (formFields) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var validationErrors, res; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [ + 4 /*yield*/, + genericComponentOverrideContext.validateForm( + formFields, + props.config.signInAndUpFeature.signUpForm.formFields + ), + ]; + case 1: + validationErrors = _a.sent(); + if (validationErrors.length > 0) { + return [ + 2 /*return*/, + { + status: "FIELD_ERROR", + formFields: validationErrors, + }, + ]; + } + return [ + 4 /*yield*/, + props.recipeImplementation.signUp({ + formFields: formFields, + userContext: userContext, + }), + ]; + case 2: + res = _a.sent(); + if (res.status === "SIGN_UP_NOT_ALLOWED") { + throw new STGeneralError__default$1.default(res.reason); + } + return [2 /*return*/, res]; + } + }); + }); + }, + validateOnBlur: true, + showLabels: true, + footer: props.footer, + }); +}); + +var SignUpHeader = uiEntry.withOverride("EmailPasswordSignUpHeader", function EmailPasswordSignUpHeader(_a) { var onClick = _a.onClick; + var t = translationContext.useTranslation(); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle" }, + { children: t("EMAIL_PASSWORD_SIGN_UP_HEADER_TITLE") } + ) + ), + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerSubtitle" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "secondaryText" }, + { + children: [ + t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_START"), + jsxRuntime.jsx( + "span", + genericComponentOverrideContext.__assign( + { "data-supertokens": "link", onClick: onClick }, + { children: t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_SIGN_IN_LINK") } + ) + ), + t("EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_END"), + ], + } + ) + ), + } + ) + ), + jsxRuntime.jsx("div", { "data-supertokens": "divider" }), + ], + }); +}); + +var SignUp = uiEntry.withOverride("EmailPasswordSignUp", function EmailPasswordSignUp(props) { + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: [ + jsxRuntime.jsx(SignUpHeader, { onClick: props.signInClicked }), + props.error !== undefined && + jsxRuntime.jsx(generalError.GeneralError, { error: props.error }), + jsxRuntime.jsx( + SignUpForm, + genericComponentOverrideContext.__assign({}, props, { + footer: jsxRuntime.jsx(SignUpFooter, { + privacyPolicyLink: + props.config.signInAndUpFeature.signUpForm.privacyPolicyLink, + termsOfServiceLink: + props.config.signInAndUpFeature.signUpForm.termsOfServiceLink, + }), + }) + ), + ], + } + ) + ), + jsxRuntime.jsx(SuperTokensBranding.SuperTokensBranding, {}), + ], + } + ) + ); +}); + +var SignInAndUpTheme = function (props) { + // If isSignUp, return signUp. + if (props.featureState.isSignUp) { + return jsxRuntime.jsx( + SignUp, + genericComponentOverrideContext.__assign({}, props.signUpForm, { + signInClicked: function () { + props.dispatch({ type: "setSignIn" }); + }, + }) + ); + } + // Otherwise, return SignIn. + return jsxRuntime.jsx( + SignIn, + genericComponentOverrideContext.__assign({}, props.signInForm, { + signUpClicked: function () { + props.dispatch({ type: "setSignUp" }); + }, + }) + ); +}; +function SignInAndUpThemeWrapper(props) { + var hasFont = translations.hasFontDefined(props.config.rootStyle); + var activeStyle = props.featureState.isSignUp + ? props.config.signInAndUpFeature.signUpForm.style + : props.config.signInAndUpFeature.signInForm.style; return jsxRuntime.jsx( - "button", + uiEntry.UserContextWrapper, genericComponentOverrideContext.__assign( - { onClick: onClick, "data-supertokens": "backButton backButtonCommon" }, - { children: jsxRuntime.jsx(HeavyArrowLeftIcon, { color: "rgb(var(--palette-textTitle))" }) } + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + translations$1.ThemeBase, + genericComponentOverrideContext.__assign( + { loadDefaultFont: !hasFont, userStyles: [props.config.rootStyle, activeStyle] }, + { + children: jsxRuntime.jsx( + SignInAndUpTheme, + genericComponentOverrideContext.__assign({}, props) + ), + } + ) + ), + } + ) + ); +} + +var useFeatureReducer = function (recipe) { + return React__namespace.useReducer( + function (oldState, action) { + switch (action.type) { + case "setSignIn": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { error: undefined, isSignUp: false } + ); + case "setSignUp": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { error: undefined, isSignUp: true } + ); + case "setError": + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, oldState), + { error: action.error } + ); + default: + return oldState; + } + }, + { + isSignUp: recipe === undefined ? false : recipe.config.signInAndUpFeature.defaultToSignUp, + user: undefined, + error: undefined, + }, + function (initArg) { + var show = genericComponentOverrideContext.getQueryParams("show"); + var isSignUp = initArg.isSignUp; + if (show !== null) { + isSignUp = show === "signup"; + } + return { + isSignUp: isSignUp, + user: undefined, + error: undefined, + }; + } + ); +}; +function useChildProps(recipe$1, state, dispatch, history) { + var _this = this; + var recipeImplementation = React.useMemo( + function () { + return recipe$1 && getModifiedRecipeImplementation(recipe$1.webJSRecipe); + }, + [recipe$1] + ); + var userContext = uiEntry.useUserContext(); + var onSignInSuccess = React.useCallback( + function (response) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + return [ + 2 /*return*/, + recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( + { + rid: recipe$1.config.recipeId, + successRedirectContext: { + action: "SUCCESS", + isNewRecipeUser: false, + user: response.user, + redirectToPath: genericComponentOverrideContext.getRedirectToPathFromURL(), + }, + }, + userContext, + history + ), + ]; + }); + }); + }, + [recipe$1, userContext, history] + ); + var onSignUpSuccess = React.useCallback( + function (response) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + return genericComponentOverrideContext.__generator(this, function (_a) { + return [ + 2 /*return*/, + recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( + { + rid: recipe$1.config.recipeId, + successRedirectContext: { + action: "SUCCESS", + isNewRecipeUser: true, + user: response.user, + redirectToPath: genericComponentOverrideContext.getRedirectToPathFromURL(), + }, + }, + userContext, + history + ), + ]; + }); + }); + }, + [recipe$1, userContext, history] + ); + return React.useMemo( + function () { + if (recipe$1 === undefined || recipeImplementation === undefined) { + return; + } + var signInAndUpFeature = recipe$1.config.signInAndUpFeature; + var signUpFeature = signInAndUpFeature.signUpForm; + var signInFeature = signInAndUpFeature.signInForm; + var signInForm = { + recipeImplementation: recipeImplementation, + config: recipe$1.config, + styleFromInit: signInFeature.style, + formFields: signInFeature.formFields, + error: state.error, + clearError: function () { + return dispatch({ type: "setError", error: undefined }); + }, + onError: function (error) { + return dispatch({ type: "setError", error: error }); + }, + onSuccess: onSignInSuccess, + forgotPasswordClick: function () { + return recipe$1.redirect({ action: "RESET_PASSWORD" }, history); + }, + }; + var signUpForm = { + recipeImplementation: recipeImplementation, + config: recipe$1.config, + styleFromInit: signUpFeature.style, + formFields: getThemeSignUpFeatureFormFields(signUpFeature.formFields, recipe$1, userContext), + error: state.error, + clearError: function () { + return dispatch({ type: "setError", error: undefined }); + }, + onError: function (error) { + return dispatch({ type: "setError", error: error }); + }, + onSuccess: onSignUpSuccess, + }; + return { + config: recipe$1.config, + signInForm: signInForm, + signUpForm: signUpForm, + }; + }, + [recipe$1, state, dispatch] + ); +} +var SignInAndUpFeature = function (props) { + var _a = useFeatureReducer(props.recipe), + state = _a[0], + dispatch = _a[1]; + var childProps = useChildProps(props.recipe, state, dispatch, props.history); + var recipeComponentOverrides = props.useComponentOverrides(); + return jsxRuntime.jsx( + uiEntry.ComponentOverrideContext.Provider, + genericComponentOverrideContext.__assign( + { value: recipeComponentOverrides }, + { + children: jsxRuntime.jsx( + uiEntry.FeatureWrapper, + genericComponentOverrideContext.__assign( + { + useShadowDom: props.recipe.config.useShadowDom, + defaultStore: defaultTranslationsEmailPassword, + }, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + props.children === undefined && + jsxRuntime.jsx( + SignInAndUpThemeWrapper, + genericComponentOverrideContext.__assign({}, childProps, { + featureState: state, + dispatch: dispatch, + }) + ), + props.children && + React__namespace.Children.map(props.children, function (child) { + if (React__namespace.isValidElement(child)) { + return React__namespace.cloneElement( + child, + genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, childProps), + { featureState: state, dispatch: dispatch } + ) + ); + } + return child; + }), + ], + }), + } + ) + ), + } ) ); +}; +var getModifiedRecipeImplementation = function (origImpl) { + return genericComponentOverrideContext.__assign({}, origImpl); +}; +function getThemeSignUpFeatureFormFields(formFields, recipe, userContext) { + var _this = this; + var emailPasswordOnly = formFields.length === 2; + return formFields.map(function (field) { + return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, field), { + showIsRequired: (function () { + // If email and password only, do not show required indicator (*). + if (emailPasswordOnly) { + return false; + } + // Otherwise, show for all non optional fields (including email and password). + return field.optional === false; + })(), + validate: (function () { + // If field is not email, return field validate unchanged. + if (field.id !== "email") { + return field.validate; + } + // Otherwise, if email, use syntax validate method and check if email exists. + return function (value) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var error, emailExists, err_1; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, field.validate(value)]; + case 1: + error = _a.sent(); + if (error !== undefined) { + return [2 /*return*/, error]; + } + if (typeof value !== "string") { + return [2 /*return*/, "GENERAL_ERROR_EMAIL_NON_STRING"]; + } + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + return [ + 4 /*yield*/, + recipe.webJSRecipe.doesEmailExist({ + email: value, + userContext: userContext, + }), + ]; + case 3: + emailExists = _a.sent().doesExist; + if (emailExists) { + return [2 /*return*/, "EMAIL_PASSWORD_EMAIL_ALREADY_EXISTS"]; + } + return [3 /*break*/, 5]; + case 4: + err_1 = _a.sent(); + if (STGeneralError__default.default.isThisError(err_1)) { + return [2 /*return*/, err_1.message]; + } + return [3 /*break*/, 5]; + case 5: + return [2 /*return*/, undefined]; + } + }); + }); + }; + })(), + }); + }); } -exports.BackButton = BackButton; +var EmailPasswordPreBuiltUI = /** @class */ (function (_super) { + genericComponentOverrideContext.__extends(EmailPasswordPreBuiltUI, _super); + function EmailPasswordPreBuiltUI(recipeInstance) { + var _this = _super.call(this) || this; + _this.recipeInstance = recipeInstance; + // Instance methods + _this.getFeatures = function (useComponentOverrides) { + if (useComponentOverrides === void 0) { + useComponentOverrides = componentOverrideContext.useContext; + } + var features = {}; + if (_this.recipeInstance.config.signInAndUpFeature.disableDefaultUI !== true) { + var normalisedFullPath = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath__default.default("/") + ); + features[normalisedFullPath.getAsStringDangerous()] = { + matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( + _this.recipeInstance.config.recipeId + ), + component: function (props) { + return _this.getFeatureComponent("signinup", props, useComponentOverrides); + }, + recipeID: recipe$1.EmailPassword.RECIPE_ID, + }; + } + if (_this.recipeInstance.config.resetPasswordUsingTokenFeature.disableDefaultUI !== true) { + var normalisedFullPath = _this.recipeInstance.config.appInfo.websiteBasePath.appendPath( + new NormalisedURLPath__default.default(constants.DEFAULT_RESET_PASSWORD_PATH) + ); + features[normalisedFullPath.getAsStringDangerous()] = { + matches: genericComponentOverrideContext.matchRecipeIdUsingQueryParams( + _this.recipeInstance.config.recipeId + ), + component: function (props) { + return _this.getFeatureComponent("resetpassword", props, useComponentOverrides); + }, + recipeID: recipe$1.EmailPassword.RECIPE_ID, + }; + } + return features; + }; + _this.getFeatureComponent = function (componentName, props, useComponentOverrides) { + if (useComponentOverrides === void 0) { + useComponentOverrides = componentOverrideContext.useContext; + } + if (componentName === "signinup") { + if (props.redirectOnSessionExists !== false) { + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + authWidgetWrapper.AuthWidgetWrapper, + genericComponentOverrideContext.__assign( + { authRecipe: _this.recipeInstance, history: props.history }, + { + children: jsxRuntime.jsx( + SignInAndUpFeature, + genericComponentOverrideContext.__assign( + { recipe: _this.recipeInstance }, + props, + { useComponentOverrides: useComponentOverrides } + ) + ), + } + ) + ), + } + ) + ); + } else { + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + SignInAndUpFeature, + genericComponentOverrideContext.__assign({ recipe: _this.recipeInstance }, props, { + useComponentOverrides: useComponentOverrides, + }) + ), + } + ) + ); + } + } else if (componentName === "resetpassword") { + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + ResetPasswordUsingToken$1, + genericComponentOverrideContext.__assign({ recipe: _this.recipeInstance }, props, { + useComponentOverrides: useComponentOverrides, + }) + ), + } + ) + ); + } else { + throw new Error("Should never come here."); + } + }; + return _this; + } + // Static methods + EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance = function () { + if (EmailPasswordPreBuiltUI.instance === undefined) { + var recipeInstance = recipe$1.EmailPassword.getInstanceOrThrow(); + EmailPasswordPreBuiltUI.instance = new EmailPasswordPreBuiltUI(recipeInstance); + } + return EmailPasswordPreBuiltUI.instance; + }; + EmailPasswordPreBuiltUI.getFeatures = function (useComponentOverrides) { + if (useComponentOverrides === void 0) { + useComponentOverrides = componentOverrideContext.useContext; + } + return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatures(useComponentOverrides); + }; + EmailPasswordPreBuiltUI.getFeatureComponent = function (componentName, props, useComponentOverrides) { + if (useComponentOverrides === void 0) { + useComponentOverrides = componentOverrideContext.useContext; + } + return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent( + componentName, + props, + useComponentOverrides + ); + }; + // For tests + EmailPasswordPreBuiltUI.reset = function () { + if (!genericComponentOverrideContext.isTest()) { + return; + } + EmailPasswordPreBuiltUI.instance = undefined; + return; + }; + EmailPasswordPreBuiltUI.SignInAndUp = function (prop) { + if (prop === void 0) { + prop = {}; + } + return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent("signinup", prop); + }; + EmailPasswordPreBuiltUI.ResetPasswordUsingToken = function (prop) { + return EmailPasswordPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatureComponent("resetpassword", prop); + }; + EmailPasswordPreBuiltUI.ResetPasswordUsingTokenTheme = ResetPasswordUsingTokenThemeWrapper; + EmailPasswordPreBuiltUI.SignInAndUpTheme = SignInAndUpThemeWrapper; + return EmailPasswordPreBuiltUI; +})(uiEntry.RecipeRouter); +var SignInAndUp = EmailPasswordPreBuiltUI.SignInAndUp; +var ResetPasswordUsingToken = EmailPasswordPreBuiltUI.ResetPasswordUsingToken; + +exports.EmailPasswordPreBuiltUI = EmailPasswordPreBuiltUI; +exports.ResetPasswordUsingToken = ResetPasswordUsingToken; +exports.ResetPasswordUsingTokenThemeWrapper = ResetPasswordUsingTokenThemeWrapper; +exports.SignInAndUp = SignInAndUp; +exports.SignInAndUpThemeWrapper = SignInAndUpThemeWrapper; +exports.SignInFooter = SignInFooter; +exports.SignInForm = SignInForm; +exports.SignInHeader = SignInHeader; +exports.SignUpFooter = SignUpFooter; +exports.SignUpForm = SignUpForm; +exports.SignUpHeader = SignUpHeader; +exports.defaultTranslationsEmailPassword = defaultTranslationsEmailPassword; +exports.useChildProps = useChildProps; +exports.useFeatureReducer = useFeatureReducer; diff --git a/lib/build/emailpassword-shared8.js b/lib/build/emailpassword-shared8.js index e48dc5334..d2336cadd 100644 --- a/lib/build/emailpassword-shared8.js +++ b/lib/build/emailpassword-shared8.js @@ -2,33 +2,6 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); var jsxRuntime = require("react/jsx-runtime"); -var React = require("react"); -var STGeneralError = require("supertokens-web-js/utils/error"); -var validators = require("./emailpassword-shared5.js"); -var button = require("./emailpassword-shared2.js"); -require("./index2.js"); -var translationContext = require("./translationContext.js"); - -function _interopDefault(e) { - return e && e.__esModule ? e : { default: e }; -} - -var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); - -/* - * Component. - */ -function FormRow(_a) { - var children = _a.children, - hasError = _a.hasError; - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": ["formRow", hasError ? "hasError" : ""].join(" ") }, - { children: children } - ) - ); -} /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -50,798 +23,41 @@ function FormRow(_a) { /* * Component. */ -function CheckedIcon() { +function HeavyArrowLeftIcon(_a) { + var color = _a.color; return jsxRuntime.jsx( "svg", genericComponentOverrideContext.__assign( { xmlns: "http://www.w3.org/2000/svg", - width: "14.862", - height: "12.033", - viewBox: "0 0 14.862 12.033", - "data-supertokens": "checkedIcon", + width: "16", + height: "13", + viewBox: "0 0 16 13", + "data-supertokens": "heavyArrowLeftIcon", }, { children: jsxRuntime.jsx("path", { - fill: "rgb(var(--palette-primary))", - d: "M12.629 49L5.06 56.572l-2.829-2.829L0 55.977l5.057 5.057.654-.651 9.152-9.152z", - transform: "translate(0 -49)", + fill: color, + d: "M13 6.8h.022H3.8l2.9 2.9a.761.761 0 0 1 0 1.07l-.451.451a.754.754 0 0 1-1.064 0L.22 6.254a.759.759 0 0 1 0-1.068L5.186.22a.755.755 0 0 1 1.064 0l.45.451a.746.746 0 0 1 .22.532.724.724 0 0 1-.22.522l-2.93 2.92h9.24a.781.781 0 0 1 .764.773v.638A.766.766 0 0 1 13 6.8z", + transform: "translate(1.182 .708)", }), } ) ); } -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Imports. - */ /* * Component. */ -function ErrorIcon() { +function BackButton(_a) { + var onClick = _a.onClick; return jsxRuntime.jsx( - "svg", + "button", genericComponentOverrideContext.__assign( - { - xmlns: "http://www.w3.org/2000/svg", - width: "17", - height: "15", - viewBox: "0 0 17 15", - "data-supertokens": "errorIcon", - }, - { - children: jsxRuntime.jsxs("g", { - children: [ - jsxRuntime.jsx( - "g", - genericComponentOverrideContext.__assign( - { className: "Asdf", fill: "rgb(var(--palette-error))" }, - { - children: jsxRuntime.jsx("path", { - d: "M13.568 14.75H3.432c-.63 0-1.195-.325-1.512-.869-.317-.544-.32-1.196-.01-1.744l5.067-8.943c.315-.556.884-.887 1.523-.887.639 0 1.208.331 1.523.887l5.067 8.943c.31.548.307 1.2-.01 1.744s-.882.869-1.512.869z", - transform: "translate(-824.894 -352.829) translate(824.894 352.829)", - }), - } - ) - ), - jsxRuntime.jsx( - "text", - genericComponentOverrideContext.__assign( - { - fill: "#fff", - fontSize: "10px", - fontWeight: "700", - transform: "translate(-824.894 -352.829) translate(832.014 365.198)", - }, - { - children: jsxRuntime.jsx( - "tspan", - genericComponentOverrideContext.__assign({ x: "0", y: "0" }, { children: "!" }) - ), - } - ) - ), - ], - }), - } + { onClick: onClick, "data-supertokens": "backButton backButtonCommon" }, + { children: jsxRuntime.jsx(HeavyArrowLeftIcon, { color: "rgb(var(--palette-textTitle))" }) } ) ); } -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Imports. - */ -/* - * Component. - */ -function ShowPasswordIcon(_a) { - var showPassword = _a.showPassword; - if (showPassword === true) { - return jsxRuntime.jsx("div", { - children: jsxRuntime.jsx( - "svg", - genericComponentOverrideContext.__assign( - { - xmlns: "http://www.w3.org/2000/svg", - width: "18.391", - height: "16.276", - viewBox: "0 0 18.391 16.276", - "data-supertokens": "showPasswordIcon show", - }, - { - children: jsxRuntime.jsxs("g", { - children: [ - jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("path", { - fill: "rgb(var(--palette-textPrimary))", - d: "M29.289 100.33c-2.4-3.63-5.619-5.63-9.069-5.63s-6.67 2-9.069 5.63a.767.767 0 0 0 0 .845c2.4 3.63 5.619 5.63 9.069 5.63s6.67-2 9.069-5.63a.767.767 0 0 0 0-.845zm-9.069 4.944c-2.785 0-5.435-1.6-7.5-4.519 2.065-2.92 4.715-4.519 7.5-4.519s5.435 1.6 7.5 4.519c-2.064 2.92-4.711 4.519-7.5 4.519z", - transform: - "translate(-822 -420.048) translate(822 422.035) translate(-11.025 -94.7)", - }), - }), - }), - }), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { - fill: "rgb(var(--palette-textPrimary))", - stroke: "rgb(var(--palette-inputBackground))", - transform: "translate(-822 -420.048) translate(827.164 424.055)", - }, - { - children: [ - jsxRuntime.jsx("circle", { - cx: "4.036", - cy: "4.036", - r: "4.036", - stroke: "none", - }), - jsxRuntime.jsx("circle", { - cx: "4.036", - cy: "4.036", - r: "3.536", - fill: "none", - }), - ], - } - ) - ), - jsxRuntime.jsx("path", { - fill: "none", - stroke: "#707070", - strokeLinecap: "round", - strokeWidth: "2.25px", - d: "M11.981 0L0 11.981", - transform: "translate(-822 -420.048) translate(825.084 421.639)", - }), - jsxRuntime.jsx("path", { - fill: "none", - stroke: "rgb(var(--palette-inputBackground))", - strokeLinecap: "round", - d: "M13.978 0L0 13.978", - transform: "translate(-822 -420.048) translate(825.084 421.639)", - }), - ], - }), - } - ) - ), - }); - } - return jsxRuntime.jsx("div", { - children: jsxRuntime.jsx( - "svg", - genericComponentOverrideContext.__assign( - { - xmlns: "http://www.w3.org/2000/svg", - width: "18.281", - height: "12.033", - viewBox: "0 0 18.281 12.033", - "data-supertokens": "showPasswordIcon hide", - }, - { - children: jsxRuntime.jsxs("g", { - children: [ - jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("g", { - children: jsxRuntime.jsx("path", { - fill: "rgb(var(--palette-textPrimary))", - d: "M29.18 100.3c-2.384-3.608-5.586-5.6-9.015-5.6s-6.63 1.989-9.015 5.6a.763.763 0 0 0 0 .84c2.384 3.608 5.586 5.6 9.015 5.6s6.63-1.989 9.015-5.6a.763.763 0 0 0 0-.84zm-9.015 4.914c-2.769 0-5.4-1.589-7.459-4.492 2.052-2.9 4.686-4.492 7.459-4.492s5.4 1.589 7.459 4.492c-2.056 2.899-4.686 4.489-7.458 4.489z", - transform: - "translate(-822 -422.088) translate(822 422.088) translate(-11.025 -94.7)", - }), - }), - }), - }), - jsxRuntime.jsxs( - "g", - genericComponentOverrideContext.__assign( - { - fill: "rgb(var(--palette-textPrimary))", - stroke: "rgb(var(--palette-inputBackground))", - transform: "translate(-822 -422.088) translate(827.133 424.096)", - }, - { - children: [ - jsxRuntime.jsx("circle", { - cx: "4.012", - cy: "4.012", - r: "4.012", - stroke: "none", - }), - jsxRuntime.jsx("circle", { - cx: "4.012", - cy: "4.012", - r: "3.512", - fill: "none", - }), - ], - } - ) - ), - ], - }), - } - ) - ), - }); -} - -var Input = function (_a) { - var type = _a.type, - name = _a.name, - hasError = _a.hasError, - autoComplete = _a.autoComplete, - onInputFocus = _a.onInputFocus, - onInputBlur = _a.onInputBlur, - onChange = _a.onChange, - value = _a.value, - placeholder = _a.placeholder, - validated = _a.validated, - autofocus = _a.autofocus; - var t = translationContext.useTranslation(); - var _b = React.useState(false), - showPassword = _b[0], - setShowPassword = _b[1]; - /* - * Method. - */ - function handleFocus() { - if (onInputFocus !== undefined) { - onInputFocus(value); - } - } - function handleBlur() { - if (onInputBlur !== undefined) { - onInputBlur(value); - } - } - function handleChange(event) { - if (onChange) { - onChange(event.target.value); - } - } - if (autoComplete === undefined) { - autoComplete = "off"; - } - var inputType = type; - if (type === "password" && showPassword === true) { - inputType = "text"; - } - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "inputContainer" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": ["inputWrapper", hasError ? "inputError" : ""].join(" ") }, - { - children: [ - jsxRuntime.jsx("input", { - autoFocus: autofocus, - autoComplete: autoComplete, - "data-supertokens": "input", - className: "supertokens-input", - onFocus: handleFocus, - onBlur: handleBlur, - type: inputType, - name: name, - placeholder: t(placeholder), - onChange: handleChange, - value: value, - }), - hasError === true && - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "inputAdornment inputAdornmentError" }, - { children: jsxRuntime.jsx(ErrorIcon, {}) } - ) - ), - validated === true && - hasError === false && - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "inputAdornment inputAdornmentSuccess" }, - { children: jsxRuntime.jsx(CheckedIcon, {}) } - ) - ), - type === "password" && - value.length > 0 && - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { - onClick: function () { - return setShowPassword(showPassword === false); - }, - "data-supertokens": "inputAdornment showPassword", - }, - { - children: jsxRuntime.jsx(ShowPasswordIcon, { - showPassword: showPassword, - }), - } - ) - ), - ], - } - ) - ), - } - ) - ); -}; - -function InputError(_a) { - var error = _a.error; - var t = translationContext.useTranslation(); - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign({ "data-supertokens": "inputErrorMessage" }, { children: t(error) }) - ); -} - -function Label(_a) { - var value = _a.value, - showIsRequired = _a.showIsRequired; - var t = translationContext.useTranslation(); - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "label" }, - { children: [t(value), showIsRequired && value && value.trim() !== "" && " *"] } - ) - ); -} - -var fetchDefaultValue = function (field) { - if (field.getDefaultValue !== undefined) { - var defaultValue = field.getDefaultValue(); - if (typeof defaultValue !== "string") { - throw new Error("getDefaultValue for ".concat(field.id, " must return a string")); - } else { - return defaultValue; - } - } - return ""; -}; -function InputComponentWrapper(props) { - var field = props.field, - type = props.type, - fstate = props.fstate, - onInputFocus = props.onInputFocus, - onInputBlur = props.onInputBlur, - onInputChange = props.onInputChange; - var useCallbackOnInputFocus = React.useCallback( - function (value) { - onInputFocus({ - id: field.id, - value: value, - }); - }, - [onInputFocus, field] - ); - var useCallbackOnInputBlur = React.useCallback( - function (value) { - onInputBlur({ - id: field.id, - value: value, - }); - }, - [onInputBlur, field] - ); - var useCallbackOnInputChange = React.useCallback( - function (value) { - onInputChange({ - id: field.id, - value: value, - }); - }, - [onInputChange, field] - ); - return field.inputComponent !== undefined - ? jsxRuntime.jsx(field.inputComponent, { - type: type, - name: field.id, - validated: fstate.validated === true, - placeholder: field.placeholder, - value: fstate.value, - autoComplete: field.autoComplete, - autofocus: field.autofocus, - onInputFocus: useCallbackOnInputFocus, - onInputBlur: useCallbackOnInputBlur, - onChange: useCallbackOnInputChange, - hasError: fstate.error !== undefined, - }) - : jsxRuntime.jsx(Input, { - type: type, - name: field.id, - validated: fstate.validated === true, - placeholder: field.placeholder, - value: fstate.value, - autoComplete: field.autoComplete, - onInputFocus: useCallbackOnInputFocus, - onInputBlur: useCallbackOnInputBlur, - onChange: useCallbackOnInputChange, - autofocus: field.autofocus, - hasError: fstate.error !== undefined, - }); -} -var FormBase = function (props) { - var footer = props.footer, - buttonLabel = props.buttonLabel, - showLabels = props.showLabels, - validateOnBlur = props.validateOnBlur, - formFields = props.formFields; - var unmounting = React.useRef(new AbortController()); - React.useEffect( - function () { - // We need this because in some cases this gets called multiple times - unmounting.current = new AbortController(); - return function () { - unmounting.current.abort(); - }; - }, - [unmounting] - ); - var _a = React.useState( - props.formFields.map(function (f) { - return { id: f.id, value: fetchDefaultValue(f) }; - }) - ), - fieldStates = _a[0], - setFieldStates = _a[1]; - var _b = React.useState(false), - isLoading = _b[0], - setIsLoading = _b[1]; - var updateFieldState = React.useCallback( - function (id, update) { - setFieldStates(function (os) { - var field = os.find(function (f) { - return f.id === id; - }); - if (field === undefined) { - return genericComponentOverrideContext.__spreadArray( - genericComponentOverrideContext.__spreadArray([], os, true), - [update({ id: id, value: "" })], - false - ); - } - return os - .filter(function (f) { - return f !== field; - }) - .concat(update(field)); - }); - }, - [setFieldStates] - ); - var onInputFocus = React.useCallback( - function (field) { - updateFieldState(field.id, function (os) { - return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, os), { - validated: false, - }); - }); - }, - [updateFieldState] - ); - var onInputBlur = React.useCallback( - function (field) { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var fieldConfig, error, _a; - return genericComponentOverrideContext.__generator(this, function (_b) { - switch (_b.label) { - case 0: - if (!validateOnBlur) { - return [2 /*return*/]; - } - fieldConfig = props.formFields.find(function (f) { - return f.id === field.id; - }); - if (!(fieldConfig && field.value !== "")) return [3 /*break*/, 2]; - return [4 /*yield*/, fieldConfig.validate(field.value)]; - case 1: - _a = _b.sent(); - return [3 /*break*/, 3]; - case 2: - _a = undefined; - _b.label = 3; - case 3: - error = _a; - updateFieldState(field.id, function (os) { - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, os), - { error: error, validated: error === undefined && field.value.length !== 0 } - ); - }); - return [2 /*return*/]; - } - }); - }); - }, - [validateOnBlur, updateFieldState, props.formFields] - ); - var onInputChange = React.useCallback( - function (field) { - if (typeof field.value !== "string") { - throw new Error("".concat(field.id, " value must be a string")); - } - updateFieldState(field.id, function (os) { - return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, os), { - value: field.value, - error: undefined, - }); - }); - props.clearError(); - }, - [updateFieldState] - ); - var onFormSubmit = React.useCallback( - function (e) { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var apiFields, - fieldUpdates, - result, - generalError, - e_1, - _loop_1, - _i, - formFields_1, - field, - errorFields_1, - getErrorMessage_1; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - // Prevent default event propagation. - e.preventDefault(); - // Set loading state. - setIsLoading(true); - setFieldStates(function (os) { - return os.map(function (fs) { - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, fs), - { error: undefined } - ); - }); - }); - apiFields = formFields.map(function (field) { - var fieldState = fieldStates.find(function (fs) { - return fs.id === field.id; - }); - return { - id: field.id, - value: fieldState === undefined ? "" : fieldState.value, - }; - }); - fieldUpdates = []; - _a.label = 1; - case 1: - _a.trys.push([1, 6, 7, 8]); - result = void 0; - generalError = void 0; - _a.label = 2; - case 2: - _a.trys.push([2, 4, , 5]); - return [ - 4 /*yield*/, - props.callAPI(apiFields, function (id, value) { - return fieldUpdates.push({ id: id, value: value }); - }), - ]; - case 3: - result = _a.sent(); - return [3 /*break*/, 5]; - case 4: - e_1 = _a.sent(); - if (STGeneralError__default.default.isThisError(e_1)) { - generalError = e_1; - } else { - throw e_1; - } - return [3 /*break*/, 5]; - case 5: - if (unmounting.current.signal.aborted) { - return [2 /*return*/]; - } - _loop_1 = function (field) { - var update = fieldUpdates.find(function (f) { - return f.id === field.id; - }); - if (update || field.clearOnSubmit === true) { - // We can do these one by one, it's almost never more than one field - updateFieldState(field.id, function (os) { - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, os), - { value: update ? update.value : "" } - ); - }); - } - }; - for (_i = 0, formFields_1 = formFields; _i < formFields_1.length; _i++) { - field = formFields_1[_i]; - _loop_1(field); - } - if (generalError !== undefined) { - props.onError(generalError.message); - } else { - // If successful - if (result.status === "OK") { - setIsLoading(false); - props.clearError(); - if (props.onSuccess !== undefined) { - props.onSuccess(result); - } - } - if (unmounting.current.signal.aborted) { - return [2 /*return*/]; - } - // If field error. - if (result.status === "FIELD_ERROR") { - errorFields_1 = result.formFields; - getErrorMessage_1 = function (fs) { - var _a; - var errorMessage = - (_a = errorFields_1.find(function (ef) { - return ef.id === fs.id; - })) === null || _a === void 0 - ? void 0 - : _a.error; - if (errorMessage === "Field is not optional") { - var fieldConfigData = props.formFields.find(function (f) { - return f.id === fs.id; - }); - // replace non-optional server error message from nonOptionalErrorMsg - if ( - (fieldConfigData === null || fieldConfigData === void 0 - ? void 0 - : fieldConfigData.nonOptionalErrorMsg) !== undefined - ) { - return fieldConfigData === null || fieldConfigData === void 0 - ? void 0 - : fieldConfigData.nonOptionalErrorMsg; - } - } - return errorMessage; - }; - setFieldStates(function (os) { - return os.map(function (fs) { - return genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, fs), - { error: getErrorMessage_1(fs) } - ); - }); - }); - } - } - return [3 /*break*/, 8]; - case 6: - _a.sent(); - props.onError("SOMETHING_WENT_WRONG_ERROR"); - return [3 /*break*/, 8]; - case 7: - setIsLoading(false); - return [7 /*endfinally*/]; - case 8: - return [2 /*return*/]; - } - }); - }); - }, - [setIsLoading, setFieldStates, props, formFields, fieldStates] - ); - return jsxRuntime.jsxs( - "form", - genericComponentOverrideContext.__assign( - { autoComplete: "on", noValidate: true, onSubmit: onFormSubmit }, - { - children: [ - formFields.map(function (field) { - var type = "text"; - // If email or password, replace field type. - if (validators.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(field.id)) { - type = field.id; - } - if (field.id === "confirm-password") { - type = "password"; - } - var fstate = fieldStates.find(function (s) { - return s.id === field.id; - }); - if (fstate === undefined) { - throw new Error("Should never come here"); - } - return jsxRuntime.jsx( - FormRow, - genericComponentOverrideContext.__assign( - { hasError: fstate.error !== undefined }, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - showLabels && - (field.labelComponent !== undefined - ? field.labelComponent - : jsxRuntime.jsx(Label, { - value: field.label, - showIsRequired: field.showIsRequired, - })), - jsxRuntime.jsx(InputComponentWrapper, { - type: type, - field: field, - fstate: fstate, - onInputFocus: onInputFocus, - onInputBlur: onInputBlur, - onInputChange: onInputChange, - }), - fstate.error && jsxRuntime.jsx(InputError, { error: fstate.error }), - ], - }), - } - ), - field.id - ); - }), - jsxRuntime.jsx( - FormRow, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - jsxRuntime.jsx(button.Button, { - disabled: isLoading, - isLoading: isLoading, - type: "submit", - label: buttonLabel, - }), - footer, - ], - }), - }, - "form-button" - ), - ], - } - ) - ); -}; - -exports.ErrorIcon = ErrorIcon; -exports.FormBase = FormBase; -exports.FormRow = FormRow; -exports.Label = Label; +exports.BackButton = BackButton; diff --git a/lib/build/emailpassword-shared9.js b/lib/build/emailpassword-shared9.js new file mode 100644 index 000000000..51eb9af1f --- /dev/null +++ b/lib/build/emailpassword-shared9.js @@ -0,0 +1,847 @@ +"use strict"; + +var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); +var jsxRuntime = require("react/jsx-runtime"); +var React = require("react"); +var STGeneralError = require("supertokens-web-js/utils/error"); +var constants = require("./emailpassword-shared5.js"); +var button = require("./emailpassword-shared2.js"); +require("./index2.js"); +var translationContext = require("./translationContext.js"); + +function _interopDefault(e) { + return e && e.__esModule ? e : { default: e }; +} + +var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); + +/* + * Component. + */ +function FormRow(_a) { + var children = _a.children, + hasError = _a.hasError; + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": ["formRow", hasError ? "hasError" : ""].join(" ") }, + { children: children } + ) + ); +} + +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Imports. + */ +/* + * Component. + */ +function CheckedIcon() { + return jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { + xmlns: "http://www.w3.org/2000/svg", + width: "14.862", + height: "12.033", + viewBox: "0 0 14.862 12.033", + "data-supertokens": "checkedIcon", + }, + { + children: jsxRuntime.jsx("path", { + fill: "rgb(var(--palette-primary))", + d: "M12.629 49L5.06 56.572l-2.829-2.829L0 55.977l5.057 5.057.654-.651 9.152-9.152z", + transform: "translate(0 -49)", + }), + } + ) + ); +} + +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Imports. + */ +/* + * Component. + */ +function ErrorIcon() { + return jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { + xmlns: "http://www.w3.org/2000/svg", + width: "17", + height: "15", + viewBox: "0 0 17 15", + "data-supertokens": "errorIcon", + }, + { + children: jsxRuntime.jsxs("g", { + children: [ + jsxRuntime.jsx( + "g", + genericComponentOverrideContext.__assign( + { className: "Asdf", fill: "rgb(var(--palette-error))" }, + { + children: jsxRuntime.jsx("path", { + d: "M13.568 14.75H3.432c-.63 0-1.195-.325-1.512-.869-.317-.544-.32-1.196-.01-1.744l5.067-8.943c.315-.556.884-.887 1.523-.887.639 0 1.208.331 1.523.887l5.067 8.943c.31.548.307 1.2-.01 1.744s-.882.869-1.512.869z", + transform: "translate(-824.894 -352.829) translate(824.894 352.829)", + }), + } + ) + ), + jsxRuntime.jsx( + "text", + genericComponentOverrideContext.__assign( + { + fill: "#fff", + fontSize: "10px", + fontWeight: "700", + transform: "translate(-824.894 -352.829) translate(832.014 365.198)", + }, + { + children: jsxRuntime.jsx( + "tspan", + genericComponentOverrideContext.__assign({ x: "0", y: "0" }, { children: "!" }) + ), + } + ) + ), + ], + }), + } + ) + ); +} + +/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Imports. + */ +/* + * Component. + */ +function ShowPasswordIcon(_a) { + var showPassword = _a.showPassword; + if (showPassword === true) { + return jsxRuntime.jsx("div", { + children: jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { + xmlns: "http://www.w3.org/2000/svg", + width: "18.391", + height: "16.276", + viewBox: "0 0 18.391 16.276", + "data-supertokens": "showPasswordIcon show", + }, + { + children: jsxRuntime.jsxs("g", { + children: [ + jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("path", { + fill: "rgb(var(--palette-textPrimary))", + d: "M29.289 100.33c-2.4-3.63-5.619-5.63-9.069-5.63s-6.67 2-9.069 5.63a.767.767 0 0 0 0 .845c2.4 3.63 5.619 5.63 9.069 5.63s6.67-2 9.069-5.63a.767.767 0 0 0 0-.845zm-9.069 4.944c-2.785 0-5.435-1.6-7.5-4.519 2.065-2.92 4.715-4.519 7.5-4.519s5.435 1.6 7.5 4.519c-2.064 2.92-4.711 4.519-7.5 4.519z", + transform: + "translate(-822 -420.048) translate(822 422.035) translate(-11.025 -94.7)", + }), + }), + }), + }), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { + fill: "rgb(var(--palette-textPrimary))", + stroke: "rgb(var(--palette-inputBackground))", + transform: "translate(-822 -420.048) translate(827.164 424.055)", + }, + { + children: [ + jsxRuntime.jsx("circle", { + cx: "4.036", + cy: "4.036", + r: "4.036", + stroke: "none", + }), + jsxRuntime.jsx("circle", { + cx: "4.036", + cy: "4.036", + r: "3.536", + fill: "none", + }), + ], + } + ) + ), + jsxRuntime.jsx("path", { + fill: "none", + stroke: "#707070", + strokeLinecap: "round", + strokeWidth: "2.25px", + d: "M11.981 0L0 11.981", + transform: "translate(-822 -420.048) translate(825.084 421.639)", + }), + jsxRuntime.jsx("path", { + fill: "none", + stroke: "rgb(var(--palette-inputBackground))", + strokeLinecap: "round", + d: "M13.978 0L0 13.978", + transform: "translate(-822 -420.048) translate(825.084 421.639)", + }), + ], + }), + } + ) + ), + }); + } + return jsxRuntime.jsx("div", { + children: jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { + xmlns: "http://www.w3.org/2000/svg", + width: "18.281", + height: "12.033", + viewBox: "0 0 18.281 12.033", + "data-supertokens": "showPasswordIcon hide", + }, + { + children: jsxRuntime.jsxs("g", { + children: [ + jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("g", { + children: jsxRuntime.jsx("path", { + fill: "rgb(var(--palette-textPrimary))", + d: "M29.18 100.3c-2.384-3.608-5.586-5.6-9.015-5.6s-6.63 1.989-9.015 5.6a.763.763 0 0 0 0 .84c2.384 3.608 5.586 5.6 9.015 5.6s6.63-1.989 9.015-5.6a.763.763 0 0 0 0-.84zm-9.015 4.914c-2.769 0-5.4-1.589-7.459-4.492 2.052-2.9 4.686-4.492 7.459-4.492s5.4 1.589 7.459 4.492c-2.056 2.899-4.686 4.489-7.458 4.489z", + transform: + "translate(-822 -422.088) translate(822 422.088) translate(-11.025 -94.7)", + }), + }), + }), + }), + jsxRuntime.jsxs( + "g", + genericComponentOverrideContext.__assign( + { + fill: "rgb(var(--palette-textPrimary))", + stroke: "rgb(var(--palette-inputBackground))", + transform: "translate(-822 -422.088) translate(827.133 424.096)", + }, + { + children: [ + jsxRuntime.jsx("circle", { + cx: "4.012", + cy: "4.012", + r: "4.012", + stroke: "none", + }), + jsxRuntime.jsx("circle", { + cx: "4.012", + cy: "4.012", + r: "3.512", + fill: "none", + }), + ], + } + ) + ), + ], + }), + } + ) + ), + }); +} + +var Input = function (_a) { + var type = _a.type, + name = _a.name, + hasError = _a.hasError, + autoComplete = _a.autoComplete, + onInputFocus = _a.onInputFocus, + onInputBlur = _a.onInputBlur, + onChange = _a.onChange, + value = _a.value, + placeholder = _a.placeholder, + validated = _a.validated, + autofocus = _a.autofocus; + var t = translationContext.useTranslation(); + var _b = React.useState(false), + showPassword = _b[0], + setShowPassword = _b[1]; + /* + * Method. + */ + function handleFocus() { + if (onInputFocus !== undefined) { + onInputFocus(value); + } + } + function handleBlur() { + if (onInputBlur !== undefined) { + onInputBlur(value); + } + } + function handleChange(event) { + if (onChange) { + onChange(event.target.value); + } + } + if (autoComplete === undefined) { + autoComplete = "off"; + } + var inputType = type; + if (type === "password" && showPassword === true) { + inputType = "text"; + } + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "inputContainer" }, + { + children: jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": ["inputWrapper", hasError ? "inputError" : ""].join(" ") }, + { + children: [ + jsxRuntime.jsx("input", { + autoFocus: autofocus, + autoComplete: autoComplete, + "data-supertokens": "input", + className: "supertokens-input", + onFocus: handleFocus, + onBlur: handleBlur, + type: inputType, + name: name, + placeholder: t(placeholder), + onChange: handleChange, + value: value, + }), + hasError === true && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "inputAdornment inputAdornmentError" }, + { children: jsxRuntime.jsx(ErrorIcon, {}) } + ) + ), + validated === true && + hasError === false && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "inputAdornment inputAdornmentSuccess" }, + { children: jsxRuntime.jsx(CheckedIcon, {}) } + ) + ), + type === "password" && + value.length > 0 && + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { + onClick: function () { + return setShowPassword(showPassword === false); + }, + "data-supertokens": "inputAdornment showPassword", + }, + { + children: jsxRuntime.jsx(ShowPasswordIcon, { + showPassword: showPassword, + }), + } + ) + ), + ], + } + ) + ), + } + ) + ); +}; + +function InputError(_a) { + var error = _a.error; + var t = translationContext.useTranslation(); + return jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign({ "data-supertokens": "inputErrorMessage" }, { children: t(error) }) + ); +} + +function Label(_a) { + var value = _a.value, + showIsRequired = _a.showIsRequired; + var t = translationContext.useTranslation(); + return jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "label" }, + { children: [t(value), showIsRequired && value && value.trim() !== "" && " *"] } + ) + ); +} + +var fetchDefaultValue = function (field) { + if (field.getDefaultValue !== undefined) { + var defaultValue = field.getDefaultValue(); + if (typeof defaultValue !== "string") { + throw new Error("getDefaultValue for ".concat(field.id, " must return a string")); + } else { + return defaultValue; + } + } + return ""; +}; +function InputComponentWrapper(props) { + var field = props.field, + type = props.type, + fstate = props.fstate, + onInputFocus = props.onInputFocus, + onInputBlur = props.onInputBlur, + onInputChange = props.onInputChange; + var useCallbackOnInputFocus = React.useCallback( + function (value) { + onInputFocus({ + id: field.id, + value: value, + }); + }, + [onInputFocus, field] + ); + var useCallbackOnInputBlur = React.useCallback( + function (value) { + onInputBlur({ + id: field.id, + value: value, + }); + }, + [onInputBlur, field] + ); + var useCallbackOnInputChange = React.useCallback( + function (value) { + onInputChange({ + id: field.id, + value: value, + }); + }, + [onInputChange, field] + ); + return field.inputComponent !== undefined + ? jsxRuntime.jsx(field.inputComponent, { + type: type, + name: field.id, + validated: fstate.validated === true, + placeholder: field.placeholder, + value: fstate.value, + autoComplete: field.autoComplete, + autofocus: field.autofocus, + onInputFocus: useCallbackOnInputFocus, + onInputBlur: useCallbackOnInputBlur, + onChange: useCallbackOnInputChange, + hasError: fstate.error !== undefined, + }) + : jsxRuntime.jsx(Input, { + type: type, + name: field.id, + validated: fstate.validated === true, + placeholder: field.placeholder, + value: fstate.value, + autoComplete: field.autoComplete, + onInputFocus: useCallbackOnInputFocus, + onInputBlur: useCallbackOnInputBlur, + onChange: useCallbackOnInputChange, + autofocus: field.autofocus, + hasError: fstate.error !== undefined, + }); +} +var FormBase = function (props) { + var footer = props.footer, + buttonLabel = props.buttonLabel, + showLabels = props.showLabels, + validateOnBlur = props.validateOnBlur, + formFields = props.formFields; + var unmounting = React.useRef(new AbortController()); + React.useEffect( + function () { + // We need this because in some cases this gets called multiple times + unmounting.current = new AbortController(); + return function () { + unmounting.current.abort(); + }; + }, + [unmounting] + ); + var _a = React.useState( + props.formFields.map(function (f) { + return { id: f.id, value: fetchDefaultValue(f) }; + }) + ), + fieldStates = _a[0], + setFieldStates = _a[1]; + var _b = React.useState(false), + isLoading = _b[0], + setIsLoading = _b[1]; + var updateFieldState = React.useCallback( + function (id, update) { + setFieldStates(function (os) { + var field = os.find(function (f) { + return f.id === id; + }); + if (field === undefined) { + return genericComponentOverrideContext.__spreadArray( + genericComponentOverrideContext.__spreadArray([], os, true), + [update({ id: id, value: "" })], + false + ); + } + return os + .filter(function (f) { + return f !== field; + }) + .concat(update(field)); + }); + }, + [setFieldStates] + ); + var onInputFocus = React.useCallback( + function (field) { + updateFieldState(field.id, function (os) { + return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, os), { + validated: false, + }); + }); + }, + [updateFieldState] + ); + var onInputBlur = React.useCallback( + function (field) { + return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { + var fieldConfig, error, _a; + return genericComponentOverrideContext.__generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!validateOnBlur) { + return [2 /*return*/]; + } + fieldConfig = props.formFields.find(function (f) { + return f.id === field.id; + }); + if (!(fieldConfig && field.value !== "")) return [3 /*break*/, 2]; + return [4 /*yield*/, fieldConfig.validate(field.value)]; + case 1: + _a = _b.sent(); + return [3 /*break*/, 3]; + case 2: + _a = undefined; + _b.label = 3; + case 3: + error = _a; + updateFieldState(field.id, function (os) { + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, os), + { error: error, validated: error === undefined && field.value.length !== 0 } + ); + }); + return [2 /*return*/]; + } + }); + }); + }, + [validateOnBlur, updateFieldState, props.formFields] + ); + var onInputChange = React.useCallback( + function (field) { + if (typeof field.value !== "string") { + throw new Error("".concat(field.id, " value must be a string")); + } + updateFieldState(field.id, function (os) { + return genericComponentOverrideContext.__assign(genericComponentOverrideContext.__assign({}, os), { + value: field.value, + error: undefined, + }); + }); + props.clearError(); + }, + [updateFieldState] + ); + var onFormSubmit = React.useCallback( + function (e) { + return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { + var apiFields, + fieldUpdates, + result, + generalError, + e_1, + _loop_1, + _i, + formFields_1, + field, + errorFields_1, + getErrorMessage_1; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + // Prevent default event propagation. + e.preventDefault(); + // Set loading state. + setIsLoading(true); + setFieldStates(function (os) { + return os.map(function (fs) { + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, fs), + { error: undefined } + ); + }); + }); + apiFields = formFields.map(function (field) { + var fieldState = fieldStates.find(function (fs) { + return fs.id === field.id; + }); + return { + id: field.id, + value: fieldState === undefined ? "" : fieldState.value, + }; + }); + fieldUpdates = []; + _a.label = 1; + case 1: + _a.trys.push([1, 6, 7, 8]); + result = void 0; + generalError = void 0; + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + return [ + 4 /*yield*/, + props.callAPI(apiFields, function (id, value) { + return fieldUpdates.push({ id: id, value: value }); + }), + ]; + case 3: + result = _a.sent(); + return [3 /*break*/, 5]; + case 4: + e_1 = _a.sent(); + if (STGeneralError__default.default.isThisError(e_1)) { + generalError = e_1; + } else { + throw e_1; + } + return [3 /*break*/, 5]; + case 5: + if (unmounting.current.signal.aborted) { + return [2 /*return*/]; + } + _loop_1 = function (field) { + var update = fieldUpdates.find(function (f) { + return f.id === field.id; + }); + if (update || field.clearOnSubmit === true) { + // We can do these one by one, it's almost never more than one field + updateFieldState(field.id, function (os) { + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, os), + { value: update ? update.value : "" } + ); + }); + } + }; + for (_i = 0, formFields_1 = formFields; _i < formFields_1.length; _i++) { + field = formFields_1[_i]; + _loop_1(field); + } + if (generalError !== undefined) { + props.onError(generalError.message); + } else { + // If successful + if (result.status === "OK") { + setIsLoading(false); + props.clearError(); + if (props.onSuccess !== undefined) { + props.onSuccess(result); + } + } + if (unmounting.current.signal.aborted) { + return [2 /*return*/]; + } + // If field error. + if (result.status === "FIELD_ERROR") { + errorFields_1 = result.formFields; + getErrorMessage_1 = function (fs) { + var _a; + var errorMessage = + (_a = errorFields_1.find(function (ef) { + return ef.id === fs.id; + })) === null || _a === void 0 + ? void 0 + : _a.error; + if (errorMessage === "Field is not optional") { + var fieldConfigData = props.formFields.find(function (f) { + return f.id === fs.id; + }); + // replace non-optional server error message from nonOptionalErrorMsg + if ( + (fieldConfigData === null || fieldConfigData === void 0 + ? void 0 + : fieldConfigData.nonOptionalErrorMsg) !== undefined + ) { + return fieldConfigData === null || fieldConfigData === void 0 + ? void 0 + : fieldConfigData.nonOptionalErrorMsg; + } + } + return errorMessage; + }; + setFieldStates(function (os) { + return os.map(function (fs) { + return genericComponentOverrideContext.__assign( + genericComponentOverrideContext.__assign({}, fs), + { error: getErrorMessage_1(fs) } + ); + }); + }); + } + } + return [3 /*break*/, 8]; + case 6: + _a.sent(); + props.onError("SOMETHING_WENT_WRONG_ERROR"); + return [3 /*break*/, 8]; + case 7: + setIsLoading(false); + return [7 /*endfinally*/]; + case 8: + return [2 /*return*/]; + } + }); + }); + }, + [setIsLoading, setFieldStates, props, formFields, fieldStates] + ); + return jsxRuntime.jsxs( + "form", + genericComponentOverrideContext.__assign( + { autoComplete: "on", noValidate: true, onSubmit: onFormSubmit }, + { + children: [ + formFields.map(function (field) { + var type = "text"; + // If email or password, replace field type. + if (constants.MANDATORY_FORM_FIELDS_ID_ARRAY.includes(field.id)) { + type = field.id; + } + if (field.id === "confirm-password") { + type = "password"; + } + var fstate = fieldStates.find(function (s) { + return s.id === field.id; + }); + if (fstate === undefined) { + throw new Error("Should never come here"); + } + return jsxRuntime.jsx( + FormRow, + genericComponentOverrideContext.__assign( + { hasError: fstate.error !== undefined }, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + showLabels && + (field.labelComponent !== undefined + ? field.labelComponent + : jsxRuntime.jsx(Label, { + value: field.label, + showIsRequired: field.showIsRequired, + })), + jsxRuntime.jsx(InputComponentWrapper, { + type: type, + field: field, + fstate: fstate, + onInputFocus: onInputFocus, + onInputBlur: onInputBlur, + onInputChange: onInputChange, + }), + fstate.error && jsxRuntime.jsx(InputError, { error: fstate.error }), + ], + }), + } + ), + field.id + ); + }), + jsxRuntime.jsx( + FormRow, + { + children: jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsx(button.Button, { + disabled: isLoading, + isLoading: isLoading, + type: "submit", + label: buttonLabel, + }), + footer, + ], + }), + }, + "form-button" + ), + ], + } + ) + ); +}; + +exports.ErrorIcon = ErrorIcon; +exports.FormBase = FormBase; +exports.FormRow = FormRow; +exports.Label = Label; diff --git a/lib/build/emailpassword.js b/lib/build/emailpassword.js index 54ade2cbb..784e001ea 100644 --- a/lib/build/emailpassword.js +++ b/lib/build/emailpassword.js @@ -21,6 +21,7 @@ require("./recipeModule-shared.js"); require("./session-shared2.js"); require("supertokens-web-js/recipe/session"); require("./emailpassword-shared5.js"); +require("./emailpassword-shared6.js"); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * diff --git a/lib/build/emailpasswordprebuiltui.js b/lib/build/emailpasswordprebuiltui.js index 58e98cf2d..df890d7e1 100644 --- a/lib/build/emailpasswordprebuiltui.js +++ b/lib/build/emailpasswordprebuiltui.js @@ -6,7 +6,7 @@ require("supertokens-web-js/utils/normalisedURLPath"); require("./index2.js"); require("./authRecipe-shared2.js"); require("./emailpassword-shared3.js"); -var emailpasswordprebuiltui = require("./emailpassword-shared6.js"); +var emailpasswordprebuiltui = require("./emailpassword-shared7.js"); require("./emailpassword-shared5.js"); require("./emailpassword-shared4.js"); require("supertokens-web-js"); @@ -30,9 +30,9 @@ require("./session-shared.js"); require("./session-shared3.js"); require("./translations.js"); require("./emailverification-shared2.js"); -require("./emailpassword-shared7.js"); -require("./arrowLeftIcon.js"); require("./emailpassword-shared8.js"); +require("./arrowLeftIcon.js"); +require("./emailpassword-shared9.js"); require("supertokens-web-js/utils/error"); require("./emailpassword-shared2.js"); require("./emailpassword-shared.js"); @@ -40,6 +40,7 @@ require("./SuperTokensBranding.js"); require("supertokens-web-js/lib/build/error"); require("supertokens-web-js/recipe/emailpassword"); require("./authRecipe-shared.js"); +require("./emailpassword-shared6.js"); exports.EmailPasswordPreBuiltUI = emailpasswordprebuiltui.EmailPasswordPreBuiltUI; exports.ResetPasswordUsingToken = emailpasswordprebuiltui.ResetPasswordUsingToken; diff --git a/lib/build/index2.js b/lib/build/index2.js index cfcf81a7d..d7f1150c5 100644 --- a/lib/build/index2.js +++ b/lib/build/index2.js @@ -276,7 +276,7 @@ var withOverride = function (overrideKey, DefaultComponent) { }; var styles = - '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n'; + '[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n/*\n * Default styles.\n */\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n/* TODO: split the link style into separate things*/\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/multifactorauth-shared.js b/lib/build/multifactorauth-shared.js index 23669ebb0..23aeb7dee 100644 --- a/lib/build/multifactorauth-shared.js +++ b/lib/build/multifactorauth-shared.js @@ -2,7 +2,6 @@ var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); var MultiFactorAuthWebJS = require("supertokens-web-js/recipe/multifactorauth"); -var utils = require("supertokens-web-js/utils"); var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); var postSuperTokensInitCallbacks = require("supertokens-web-js/utils/postSuperTokensInitCallbacks"); var sessionClaimValidatorStore = require("supertokens-web-js/utils/sessionClaimValidatorStore"); @@ -273,7 +272,7 @@ var MultiFactorAuth = /** @class */ (function (_super) { }; MultiFactorAuth.getInstanceOrThrow = function () { if (MultiFactorAuth.instance === undefined) { - var error = "No instance of EmailVerification found. Make sure to call the EmailVerification.init method."; + var error = "No instance of MultiFactorAuth found. Make sure to call the MultiFactorAuth.init method."; // eslint-disable-next-line supertokens-auth-react/no-direct-window-object if (typeof window === "undefined") { error = error + genericComponentOverrideContext.SSR_ERROR; @@ -319,11 +318,15 @@ var MultiFactorAuth = /** @class */ (function (_super) { redirectUrl = genericComponentOverrideContext .getCurrentNormalisedUrlPath() .getAsStringDangerous(); - url = utils.appendQueryParamsToURL(url, { redirectToPath: redirectUrl }); + url = genericComponentOverrideContext.appendQueryParamsToURL(url, { + redirectToPath: redirectUrl, + }); } else { redirectUrl = genericComponentOverrideContext.getRedirectToPathFromURL(); if (redirectUrl) { - url = utils.appendQueryParamsToURL(url, { redirectToPath: redirectUrl }); + url = genericComponentOverrideContext.appendQueryParamsToURL(url, { + redirectToPath: redirectUrl, + }); } } return [ @@ -353,11 +356,15 @@ var MultiFactorAuth = /** @class */ (function (_super) { redirectUrl = genericComponentOverrideContext .getCurrentNormalisedUrlPath() .getAsStringDangerous(); - url = utils.appendQueryParamsToURL(url, { redirectToPath: redirectUrl }); + url = genericComponentOverrideContext.appendQueryParamsToURL(url, { + redirectToPath: redirectUrl, + }); } else { redirectUrl = genericComponentOverrideContext.getRedirectToPathFromURL(); if (redirectUrl) { - url = utils.appendQueryParamsToURL(url, { redirectToPath: redirectUrl }); + url = genericComponentOverrideContext.appendQueryParamsToURL(url, { + redirectToPath: redirectUrl, + }); } } return [ diff --git a/lib/build/multifactorauthprebuiltui.js b/lib/build/multifactorauthprebuiltui.js index 5df6c54ca..7c7dcfcdf 100644 --- a/lib/build/multifactorauthprebuiltui.js +++ b/lib/build/multifactorauthprebuiltui.js @@ -15,7 +15,7 @@ var translations = require("./translations.js"); var translationContext = require("./translationContext.js"); var sessionprebuiltui = require("./sessionprebuiltui.js"); var arrowLeftIcon = require("./arrowLeftIcon.js"); -var backButton = require("./emailpassword-shared7.js"); +var backButton = require("./emailpassword-shared8.js"); require("supertokens-web-js"); require("supertokens-web-js/utils/cookieHandler"); require("supertokens-web-js/utils/postSuperTokensInitCallbacks"); diff --git a/lib/build/passwordless-shared2.js b/lib/build/passwordless-shared2.js index 94a68dd00..b2723095d 100644 --- a/lib/build/passwordless-shared2.js +++ b/lib/build/passwordless-shared2.js @@ -6,7 +6,7 @@ var postSuperTokensInitCallbacks = require("supertokens-web-js/utils/postSuperTo var jsxRuntime = require("react/jsx-runtime"); var utils = require("./authRecipe-shared.js"); var recipe = require("./multifactorauth-shared.js"); -var windowHandler = require("supertokens-web-js/utils/windowHandler"); +var validators = require("./passwordless-shared3.js"); function _interopDefault(e) { return e && e.__esModule ? e : { default: e }; @@ -192,234 +192,6 @@ var getFunctionOverrides = function (onHandleEvent) { }; }; -var phoneNumberUtilsImport; -function getPhoneNumberUtils() { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - var global; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - return [4 /*yield*/, preloadPhoneNumberUtils()]; - case 1: - _a.sent(); - global = windowHandler.WindowHandlerReference.getReferenceOrThrow().windowHandler.getWindowUnsafe(); - return [2 /*return*/, global.intlTelInputUtils]; - } - }); - }); -} -function preloadPhoneNumberUtils() { - if (phoneNumberUtilsImport === undefined) { - /* eslint-disable @typescript-eslint/ban-ts-comment */ - // @ts-ignore: We need to disable no implicit any here, otherwise we'd need to add types for this module - phoneNumberUtilsImport = Promise.resolve().then(function () { - return require("./utils.js"); - }); - /* eslint-enable @typescript-eslint/ban-ts-comment */ - } - return phoneNumberUtilsImport; -} - -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -function defaultEmailValidator(value) { - if (typeof value !== "string") { - return "GENERAL_ERROR_EMAIL_NON_STRING"; - } - value = value.trim(); - var defaultEmailValidatorRegexp = - // eslint-disable-next-line no-useless-escape - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - // We check if the email syntax is correct - // As per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 - // Regex from https://stackoverflow.com/a/46181/3867175 - if (value.match(defaultEmailValidatorRegexp) === null) { - return "GENERAL_ERROR_EMAIL_INVALID"; - } - return undefined; -} -function defaultPhoneNumberValidator(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - var intlTelInputUtils; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (typeof value !== "string") { - return [2 /*return*/, "GENERAL_ERROR_PHONE_NON_STRING"]; - } - value = value.trim(); - return [4 /*yield*/, getPhoneNumberUtils()]; - case 1: - intlTelInputUtils = _a.sent(); - if (!intlTelInputUtils.isValidNumber(value, undefined)) { - return [2 /*return*/, "GENERAL_ERROR_PHONE_INVALID"]; - } - return [2 /*return*/, undefined]; - } - }); - }); -} -function defaultEmailValidatorForCombinedInput(value) { - if (typeof value !== "string") { - return "GENERAL_ERROR_EMAIL_OR_PHONE_NON_STRING"; - } - value = value.trim(); - var defaultEmailValidatorRegexp = - // eslint-disable-next-line no-useless-escape - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - // We check if the email syntax is correct - // As per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438 - // Regex from https://stackoverflow.com/a/46181/3867175 - if (value.match(defaultEmailValidatorRegexp) === null) { - return "GENERAL_ERROR_EMAIL_OR_PHONE_INVALID"; - } - return undefined; -} -function defaultPhoneNumberValidatorForCombinedInput(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - var intlTelInputUtils; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (typeof value !== "string") { - return [2 /*return*/, "GENERAL_ERROR_EMAIL_OR_PHONE_NON_STRING"]; - } - value = value.trim(); - return [4 /*yield*/, getPhoneNumberUtils()]; - case 1: - intlTelInputUtils = _a.sent(); - if (!intlTelInputUtils.isValidNumber(value, undefined)) { - return [2 /*return*/, "GENERAL_ERROR_EMAIL_OR_PHONE_INVALID"]; - } - return [2 /*return*/, undefined]; - } - }); - }); -} -function userInputCodeValidate(value) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - if (typeof value !== "string") { - return [2 /*return*/, "GENERAL_ERROR_OTP_NON_STRING"]; - } - if (value.length === 0) { - return [2 /*return*/, "GENERAL_ERROR_OTP_EMPTY"]; - } - return [2 /*return*/, undefined]; - }); - }); -} -/* - * defaultValidate - */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function defaultValidate(_) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - return genericComponentOverrideContext.__generator(this, function (_a) { - return [2 /*return*/, undefined]; - }); - }); -} -function defaultGuessInternationPhoneNumberFromInputPhoneNumber(value, defaultCountryFromConfig) { - return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { - var intlTelInputUtils, - libGuess, - phoneNumberCharCount, - filteredInput, - countryData, - matchingCountryCodes, - _i, - matchingCountryCodes_1, - code, - defaultCountry; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (value === undefined || value.length === 0) { - return [2 /*return*/, value]; - } - return [4 /*yield*/, getPhoneNumberUtils()]; - case 1: - intlTelInputUtils = _a.sent(); - libGuess = intlTelInputUtils.formatNumber( - value, - defaultCountryFromConfig, - intlTelInputUtils.numberFormat.E164 - ); - if (intlTelInputUtils.isValidNumber(libGuess, defaultCountryFromConfig)) { - return [2 /*return*/, libGuess]; - } - phoneNumberCharCount = (value.match(/(\d|[+\-().])/g) || []).length; - // If the number of valid characters for a phonenumber is less than half the input we assume it's not a phone number. - // I.e.: if less than half of the input is numbers or in: "+-()." - if (value.includes("@") || phoneNumberCharCount < value.length / 2) { - return [2 /*return*/, undefined]; - } - filteredInput = "+" + value.replace(/\D/g, "").replace(/^00/, ""); - if (intlTelInputUtils.isValidNumber(filteredInput, defaultCountryFromConfig)) { - return [ - 2 /*return*/, - intlTelInputUtils.formatNumber( - filteredInput, - defaultCountryFromConfig, - intlTelInputUtils.numberFormat.E164 - ), - ]; - } - countryData = windowHandler.WindowHandlerReference.getReferenceOrThrow() - .windowHandler.getWindowUnsafe() - .intlTelInputGlobals.getCountryData(); - matchingCountryCodes = countryData - .filter(function (c) { - return filteredInput.startsWith("+" + c.dialCode); - }) - .map(function (c) { - return c.iso2; - }); - for ( - _i = 0, matchingCountryCodes_1 = matchingCountryCodes; - _i < matchingCountryCodes_1.length; - _i++ - ) { - code = matchingCountryCodes_1[_i]; - if (intlTelInputUtils.isValidNumber(filteredInput, code)) { - return [ - 2 /*return*/, - intlTelInputUtils.formatNumber( - filteredInput, - code, - intlTelInputUtils.numberFormat.E164 - ), - ]; - } - } - if (defaultCountryFromConfig) { - defaultCountry = countryData.find(function (c) { - return c.iso2 === defaultCountryFromConfig.toLowerCase(); - }); - if (defaultCountry) { - return [2 /*return*/, "+" + defaultCountry.dialCode + filteredInput.substring(1)]; - } - } - // We want to return the value as an international number because the phone number input lib expects it this way - return [2 /*return*/, filteredInput]; - } - }); - }); -} - /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * * This software is licensed under the Apache License, Version 2.0 (the @@ -450,23 +222,23 @@ function normalisePasswordlessConfig(config) { }, config.override ); - var validateEmailAddress = defaultEmailValidator; + var validateEmailAddress = validators.defaultEmailValidator; if ( (config.contactMethod === "EMAIL" || config.contactMethod === "EMAIL_OR_PHONE") && config.validateEmailAddress !== undefined ) { validateEmailAddress = config.validateEmailAddress; } else if (config.contactMethod === "EMAIL_OR_PHONE") { - validateEmailAddress = defaultEmailValidatorForCombinedInput; + validateEmailAddress = validators.defaultEmailValidatorForCombinedInput; } - var validatePhoneNumber = defaultPhoneNumberValidator; + var validatePhoneNumber = validators.defaultPhoneNumberValidator; if ( (config.contactMethod === "PHONE" || config.contactMethod === "EMAIL_OR_PHONE") && config.validatePhoneNumber !== undefined ) { validatePhoneNumber = config.validatePhoneNumber; } else if (config.contactMethod === "EMAIL_OR_PHONE") { - validatePhoneNumber = defaultPhoneNumberValidatorForCombinedInput; + validatePhoneNumber = validators.defaultPhoneNumberValidatorForCombinedInput; } return genericComponentOverrideContext.__assign( genericComponentOverrideContext.__assign({}, utils.normaliseAuthRecipe(config)), @@ -530,7 +302,7 @@ function normalizeSignInUpFeatureConfig(signInUpInput, config) { "guessInternationPhoneNumberFromInputPhoneNumber" in signInUpInput && signInUpInput.guessInternationPhoneNumberFromInputPhoneNumber !== undefined ? signInUpInput.guessInternationPhoneNumberFromInputPhoneNumber - : defaultGuessInternationPhoneNumberFromInputPhoneNumber, + : validators.defaultGuessInternationPhoneNumberFromInputPhoneNumber, } ); return signInUpFeature; @@ -695,11 +467,6 @@ var Passwordless = /** @class */ (function (_super) { })(utils.AuthRecipe); exports.Passwordless = Passwordless; -exports.defaultEmailValidator = defaultEmailValidator; -exports.defaultValidate = defaultValidate; exports.getEnabledContactMethods = getEnabledContactMethods; -exports.getPhoneNumberUtils = getPhoneNumberUtils; exports.normalisePasswordlessConfig = normalisePasswordlessConfig; exports.passwordlessFirstFactors = passwordlessFirstFactors; -exports.preloadPhoneNumberUtils = preloadPhoneNumberUtils; -exports.userInputCodeValidate = userInputCodeValidate; diff --git a/lib/build/passwordless-shared3.js b/lib/build/passwordless-shared3.js index 62f455661..5decc31b4 100644 --- a/lib/build/passwordless-shared3.js +++ b/lib/build/passwordless-shared3.js @@ -1,4282 +1,35 @@ "use strict"; var genericComponentOverrideContext = require("./genericComponentOverrideContext.js"); -var jsxRuntime = require("react/jsx-runtime"); -var NormalisedURLPath = require("supertokens-web-js/utils/normalisedURLPath"); -var uiEntry = require("./index2.js"); -var authWidgetWrapper = require("./authRecipe-shared2.js"); -var session = require("./session-shared.js"); -var componentOverrideContext = require("./passwordless-shared.js"); -var React = require("react"); -var STGeneralError = require("supertokens-web-js/utils/error"); -var recipe = require("./session-shared2.js"); -var translations = require("./translations.js"); -var translationContext = require("./translationContext.js"); -var button = require("./emailpassword-shared2.js"); var windowHandler = require("supertokens-web-js/utils/windowHandler"); -var recipe$2 = require("./multifactorauth-shared.js"); -var recipe$1 = require("./passwordless-shared2.js"); -var SuperTokensBranding = require("./SuperTokensBranding.js"); -var generalError = require("./emailpassword-shared.js"); -var sessionprebuiltui = require("./sessionprebuiltui.js"); -var checkedRoundIcon = require("./checkedRoundIcon.js"); -var formBase = require("./emailpassword-shared8.js"); -var validators = require("./emailpassword-shared5.js"); -var arrowLeftIcon = require("./arrowLeftIcon.js"); -var multifactorauth = require("./multifactorauth-shared2.js"); -var backButton = require("./emailpassword-shared7.js"); -function _interopDefault(e) { - return e && e.__esModule ? e : { default: e }; -} - -function _interopNamespace(e) { - if (e && e.__esModule) return e; - var n = Object.create(null); - if (e) { - Object.keys(e).forEach(function (k) { - if (k !== "default") { - var d = Object.getOwnPropertyDescriptor(e, k); - Object.defineProperty( - n, - k, - d.get - ? d - : { - enumerable: true, - get: function () { - return e[k]; - }, - } - ); +var phoneNumberUtilsImport; +function getPhoneNumberUtils() { + return genericComponentOverrideContext.__awaiter(this, void 0, void 0, function () { + var global; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, preloadPhoneNumberUtils()]; + case 1: + _a.sent(); + global = windowHandler.WindowHandlerReference.getReferenceOrThrow().windowHandler.getWindowUnsafe(); + return [2 /*return*/, global.intlTelInputUtils]; } }); - } - n.default = e; - return Object.freeze(n); -} - -var NormalisedURLPath__default = /*#__PURE__*/ _interopDefault(NormalisedURLPath); -var React__namespace = /*#__PURE__*/ _interopNamespace(React); -var STGeneralError__default = /*#__PURE__*/ _interopDefault(STGeneralError); - -var styles = - '/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="container"] {\n --palette-background: 255, 255, 255;\n --palette-inputBackground: 250, 250, 250;\n --palette-inputBorder: 224, 224, 224;\n --palette-primary: 255, 155, 51;\n --palette-primaryBorder: 238, 141, 35;\n --palette-success: 65, 167, 0;\n --palette-successBackground: 217, 255, 191;\n --palette-error: 255, 23, 23;\n --palette-errorBackground: 255, 241, 235;\n --palette-textTitle: 34, 34, 34;\n --palette-textLabel: 34, 34, 34;\n --palette-textInput: 34, 34, 34;\n --palette-textPrimary: 101, 101, 101;\n --palette-textLink: 0, 118, 255;\n --palette-buttonText: 255, 255, 255;\n --palette-textGray: 128, 128, 128;\n --palette-superTokensBrandingBackground: 242, 245, 246;\n --palette-superTokensBrandingText: 173, 189, 196;\n\n --font-size-0: 12px;\n --font-size-1: 14px;\n --font-size-2: 16px;\n --font-size-3: 19px;\n --font-size-4: 24px;\n}\n\n/*\n * Default styles.\n */\n\n@-webkit-keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@keyframes slideTop {\n 0% {\n -webkit-transform: translateY(-5px);\n transform: translateY(-5px);\n }\n 100% {\n -webkit-transform: translateY(0px);\n transform: translateY(0px);\n }\n}\n\n@-webkit-keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n@keyframes swing-in-top-fwd {\n 0% {\n -webkit-transform: rotateX(-100deg);\n transform: rotateX(-100deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 0;\n }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n -webkit-transform-origin: top;\n transform-origin: top;\n opacity: 1;\n }\n}\n\n[data-supertokens~="container"] {\n font-family: "Rubik", sans-serif;\n margin: 12px auto;\n margin-top: 26px;\n margin-bottom: 26px;\n width: 420px;\n text-align: center;\n border-radius: 8px;\n box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.16);\n background-color: rgb(var(--palette-background));\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="container"] {\n width: 95vw;\n }\n}\n\n[data-supertokens~="row"] {\n margin: 0 auto;\n width: 76%;\n padding-top: 30px;\n padding-bottom: 10px;\n}\n\n[data-supertokens~="superTokensBranding"] {\n display: block;\n margin: 0 auto;\n background: rgb(var(--palette-superTokensBrandingBackground));\n color: rgb(var(--palette-superTokensBrandingText));\n text-decoration: none;\n width: -webkit-fit-content;\n width: -moz-fit-content;\n width: fit-content;\n border-radius: 6px 6px 0 0;\n padding: 4px 9px;\n font-weight: 400;\n font-size: var(--font-size-0);\n letter-spacing: 0.4px;\n}\n\n[data-supertokens~="generalError"] {\n background: rgb(var(--palette-errorBackground));\n padding-top: 10px;\n padding-bottom: 10px;\n margin-bottom: 15px;\n padding-left: 18px;\n padding-right: 18px;\n letter-spacing: 0.2px;\n font-size: var(--font-size-1);\n border-radius: 8px;\n color: rgb(var(--palette-error));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n word-wrap: break-word;\n}\n\n[data-supertokens~="headerTitle"] {\n font-size: var(--font-size-4);\n line-height: 40px;\n letter-spacing: 0.58px;\n font-weight: 600;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n font-weight: 400;\n margin-bottom: 21px;\n}\n\n[data-supertokens~="headerSubtitle"][data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] {\n max-width: 300px;\n margin-top: 10px;\n}\n\n[data-supertokens~="privacyPolicyAndTermsAndConditions"] a {\n line-height: 21px;\n}\n\n/* TODO: split the link style into separate things*/\n\n/* We add this before primary and secondary text, because if they are applied to the same element the other ones take priority */\n\n[data-supertokens~="link"] {\n padding-left: 3px;\n padding-right: 3px;\n color: rgb(var(--palette-textLink));\n font-size: var(--font-size-1);\n cursor: pointer;\n letter-spacing: 0.16px;\n line-height: 26px;\n}\n\n[data-supertokens~="primaryText"] {\n font-size: var(--font-size-1);\n font-weight: 500;\n letter-spacing: 0.4px;\n line-height: 21px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="secondaryText"] {\n font-size: var(--font-size-1);\n font-weight: 300;\n letter-spacing: 0.4px;\n color: rgb(var(--palette-textPrimary));\n}\n\n[data-supertokens~="divider"] {\n margin-top: 1em;\n margin-bottom: 1em;\n border-bottom: 0.3px solid #dddddd;\n align-items: center;\n padding-bottom: 5px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="generalSuccess"] {\n color: rgb(var(--palette-success));\n font-size: var(--font-size-1);\n background: rgb(var(--palette-successBackground));\n -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;\n padding: 9px 15px 9px 15px;\n border-radius: 6px;\n display: inline-block;\n}\n\n[data-supertokens~="spinner"] {\n width: 80px;\n height: auto;\n padding-top: 20px;\n padding-bottom: 40px;\n margin: 0 auto;\n}\n\n[data-supertokens~="error"] {\n color: rgb(var(--palette-error));\n}\n\n[data-supertokens~="linkButton"] {\n font-family: "Rubik", sans-serif;\n background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n margin-top: 10px;\n margin-bottom: 40px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] svg {\n margin-right: 0.3em;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"]:hover svg {\n position: relative;\n left: -4px;\n}\n\n[data-supertokens~="button"] {\n font-family: "Rubik", sans-serif;\n background-color: rgb(var(--palette-primary));\n color: rgb(var(--palette-buttonText));\n width: 100%;\n height: 34px;\n font-weight: 700;\n border-width: 1px;\n border-style: solid;\n border-radius: 6px;\n border-color: rgb(var(--palette-primaryBorder));\n background-position: center;\n transition: all 0.4s;\n background-size: 12000%;\n cursor: pointer;\n}\n\n[data-supertokens~="button"]:disabled {\n border: none;\n cursor: no-drop;\n}\n\n[data-supertokens~="button"]:active {\n outline: none;\n transition: all 0s;\n background-size: 100%;\n -webkit-filter: brightness(0.85);\n filter: brightness(0.85);\n}\n\n[data-supertokens~="button"]:focus {\n outline: none;\n}\n\n[data-supertokens~="backButtonCommon"] {\n width: 16px;\n height: 13px;\n}\n\n[data-supertokens~="backButton"] {\n cursor: pointer;\n border: none;\n background-color: transparent;\n padding: 0px;\n}\n\n[data-supertokens~="backButtonPlaceholder"] {\n display: block;\n}\n\n[data-supertokens~="delayedRender"] {\n -webkit-animation-duration: 0.1s;\n animation-duration: 0.1s;\n -webkit-animation-name: animate-fade;\n animation-name: animate-fade;\n -webkit-animation-delay: 0.2s;\n animation-delay: 0.2s;\n -webkit-animation-fill-mode: backwards;\n animation-fill-mode: backwards;\n}\n\n@-webkit-keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@keyframes animate-fade {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n gap: 24px;\n}\n\n[data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryText"] {\n font-weight: 400;\n}\n\n[data-supertokens~="footerLinkGroupVert"] [data-supertokens~="secondaryLinkWithLeftArrow"] {\n font-weight: 500;\n position: relative;\n left: -6px; /* half the width of the left arrow */\n}\n\n@media (max-width: 360px) {\n [data-supertokens~="footerLinkGroupVert"] {\n flex-direction: column;\n }\n [data-supertokens~="footerLinkGroupVert"] > div {\n margin: 0 auto;\n }\n}\n\n[data-supertokens~="footerLinkGroupVert"] div:only-child {\n margin-left: auto;\n margin-right: auto;\n margin-top: 14px;\n}\n\n/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.\n *\n * This software is licensed under the Apache License, Version 2.0 (the\n * "License") as published by the Apache Software Foundation.\n *\n * You may not use this file except in compliance with the License. You may\n * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the License.\n */\n\n[data-supertokens~="inputContainer"] {\n margin-top: 6px;\n}\n\n[data-supertokens~="inputWrapper"] {\n box-sizing: border-box;\n width: 100%;\n display: flex;\n align-items: center;\n background-color: rgb(var(--palette-inputBackground));\n height: 34px;\n border-radius: 6px;\n border: 1px solid rgb(var(--palette-inputBorder));\n}\n\n[data-supertokens~="inputWrapper"][focus-within] {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputWrapper"]:focus-within {\n background-color: rgba(var(--palette-inputBackground), 0.25);\n border: 1px solid rgb(var(--palette-primary));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-primary), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"][focus-within] {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="inputError"]:focus-within {\n border: 1px solid rgb(var(--palette-error));\n box-shadow: 0 0 0 0.2rem rgba(var(--palette-error), 0.25);\n outline: none;\n}\n\n[data-supertokens~="input"] {\n box-sizing: border-box;\n padding-left: 15px;\n -webkit-filter: none;\n filter: none;\n color: rgb(var(--palette-textInput));\n background-color: transparent;\n border-radius: 6px;\n font-size: var(--font-size-1);\n border: none;\n padding-right: 25px;\n letter-spacing: 1.2px;\n flex: 9 1 75%;\n width: 75%;\n height: 32px;\n}\n\n[data-supertokens~="input"]:focus {\n border: none;\n outline: none;\n}\n\n[data-supertokens~="input"]:-webkit-autofill,\n[data-supertokens~="input"]:-webkit-autofill:hover,\n[data-supertokens~="input"]:-webkit-autofill:focus,\n[data-supertokens~="input"]:-webkit-autofill:active {\n -webkit-text-fill-color: rgb(var(--palette-textInput));\n box-shadow: 0 0 0 30px rgb(var(--palette-inputBackground)) inset;\n}\n\n[data-supertokens~="inputAdornment"] {\n justify-content: center;\n margin-right: 5px;\n}\n\n[data-supertokens~="showPassword"] {\n cursor: pointer;\n}\n\n[data-supertokens~="forgotPasswordLink"] {\n margin-top: 10px;\n}\n\n[data-supertokens~="enterEmailSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n word-break: break-word;\n}\n\n[data-supertokens~="submitNewPasswordSuccessMessage"] {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n\n[data-supertokens~="inputErrorMessage"] {\n padding-top: 5px;\n padding-bottom: 5px;\n color: rgb(var(--palette-error));\n line-height: 24px;\n font-weight: 400;\n font-size: var(--font-size-1);\n text-align: left;\n -webkit-animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n animation: slideTop 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;\n max-width: 330px;\n}\n\n@media (max-width: 440px) {\n [data-supertokens~="inputErrorMessage"] {\n max-width: 250px;\n }\n}\n\n[data-supertokens~="inputErrorSymbol"] {\n margin-right: 5px;\n top: 1px;\n position: relative;\n left: 2px;\n}\n\n[data-supertokens~="label"] {\n text-align: left;\n font-weight: 600;\n font-size: var(--font-size-1);\n line-height: 24px;\n color: rgb(var(--palette-textLabel));\n}\n\n[data-supertokens~="formRow"] {\n display: flex;\n flex-direction: column;\n padding-top: 0px;\n padding-bottom: 34px;\n}\n\n[data-supertokens~="formRow"][data-supertokens~="hasError"] {\n padding-bottom: 0;\n}\n\n[data-supertokens~="sendVerifyEmailIcon"] {\n margin-top: 11px;\n}\n\n[data-supertokens~="headerTinyTitle"] {\n margin-top: 13px;\n font-size: var(--font-size-3);\n letter-spacing: 1.1px;\n font-weight: 500;\n line-height: 28px;\n}\n\n[data-supertokens~="sendVerifyEmailText"] {\n line-height: 21px;\n font-size: var(--font-size-1);\n text-align: center;\n font-weight: 300;\n letter-spacing: 0.8px;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"] {\n margin-top: 10px;\n margin-bottom: 30px;\n cursor: pointer;\n}\n\n[data-supertokens~="secondaryLinkWithArrow"]:hover {\n position: relative;\n left: 2px;\n word-spacing: 4px;\n}\n\n[data-supertokens~="sendVerifyEmailResend"] {\n margin-top: 13px;\n font-weight: 300;\n}\n\n[data-supertokens~="sendVerifyEmailResend"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="noFormRow"] {\n padding-bottom: 25px;\n}\n\n[data-supertokens~="emailVerificationButtonWrapper"] {\n padding-top: 25px;\n max-width: 96px;\n margin: 0 auto;\n}\n\n[data-supertokens~="withBackButton"] {\n position: relative;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="resendEmailLink"] {\n display: inline-block;\n}\n\n[data-supertokens~="generalSuccess"] {\n margin-bottom: 20px;\n -webkit-animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n animation: swingIn 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) alternate 2 both;\n}\n\n[data-supertokens~="codeInputLabelWrapper"] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n[data-supertokens~="headerSubtitle"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="sendCodeText"] {\n margin-top: 15px;\n margin-bottom: 20px;\n}\n\n[data-supertokens~="sendCodeText"] strong {\n max-width: 100%;\n display: inline-block;\n vertical-align: bottom;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n[data-supertokens~="resendCodeBtn"] {\n width: auto;\n margin-top: 0;\n line-height: 24px;\n}\n\n[data-supertokens~="resendCodeBtn"]:hover {\n text-decoration: underline;\n}\n\n[data-supertokens~="resendCodeBtn"]:disabled {\n color: rgb(var(--palette-textPrimary));\n cursor: default;\n text-decoration: none;\n}\n\n[data-supertokens~="phoneInputLibRoot"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] {\n display: flex;\n align-items: center;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti [data-supertokens~="input"] {\n padding-left: 15px;\n}\n\n[data-supertokens~="phoneInputWrapper"] .iti {\n flex: 1 1;\n min-width: 0;\n width: 100%;\n background: transparent;\n border: none;\n color: inherit;\n outline: none;\n}\n\n[data-supertokens~="continueButtonWrapper"] {\n margin-top: 10px;\n margin-bottom: 30px;\n}\n\n.iti__country-list {\n border: 0;\n top: 40px;\n width: min(72.2vw, 320px);\n border-radius: 6;\n box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);\n}\n\n.iti__country {\n display: flex;\n align-items: center;\n height: 34px;\n cursor: pointer;\n\n padding: 0 8px;\n}\n\n.iti__country-name {\n color: var(--palette-textLabel);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: "0 16px";\n}\n'; - -var ThemeBase = function (_a) { - var children = _a.children, - userStyles = _a.userStyles, - loadDefaultFont = _a.loadDefaultFont; - return jsxRuntime.jsxs(React.Fragment, { - children: [ - children, - loadDefaultFont && - jsxRuntime.jsx("link", { - href: "//fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700", - rel: "stylesheet", - type: "text/css", - }), - jsxRuntime.jsxs("style", { children: [styles, userStyles.join("\n")] }), - ], - }); -}; - -var PasswordlessLinkClickedScreen = function (props) { - var t = translationContext.useTranslation(); - var _a = React.useState(false), - loading = _a[0], - setLoading = _a[1]; - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row" }, - { - children: - props.requireUserInteraction === true - ? jsxRuntime.jsxs(React__namespace.default.Fragment, { - children: [ - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("PWLESS_LINK_CLICKED_CONTINUE_HEADER") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle secondaryText" }, - { children: t("PWLESS_LINK_CLICKED_CONTINUE_DESC") } - ) - ), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "continueButtonWrapper" }, - { - children: jsxRuntime.jsx(button.Button, { - isLoading: loading, - onClick: function () { - setLoading(true); - props.consumeCode(); - }, - type: "button", - label: "PWLESS_LINK_CLICKED_CONTINUE_BUTTON", - }), - } - ) - ), - ], - }) - : jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "spinner" }, - { children: jsxRuntime.jsx(uiEntry.SpinnerIcon, {}) } - ) - ), - } - ) - ), - } - ) - ); -}; -var LinkClickedScreenWithOverride = uiEntry.withOverride( - "PasswordlessLinkClickedScreen", - PasswordlessLinkClickedScreen -); -var LinkClickedScreen$1 = function (props) { - var hasFont = translations.hasFontDefined(props.config.rootStyle); - return jsxRuntime.jsx( - ThemeBase, - genericComponentOverrideContext.__assign( - { - loadDefaultFont: !hasFont, - userStyles: [props.config.rootStyle, props.config.linkClickedScreenFeature.style], - }, - { - children: jsxRuntime.jsx( - LinkClickedScreenWithOverride, - genericComponentOverrideContext.__assign({}, props) - ), - } - ) - ); -}; - -var defaultTranslationsPasswordless = { - en: genericComponentOverrideContext.__assign( - genericComponentOverrideContext.__assign({}, translations.defaultTranslationsCommon.en), - { - GENERAL_ERROR_EMAIL_UNDEFINED: "Please set your email", - GENERAL_ERROR_EMAIL_NON_STRING: "Email must be of type string", - GENERAL_ERROR_EMAIL_INVALID: "Email is invalid", - GENERAL_ERROR_PHONE_UNDEFINED: "Please set your phone number", - GENERAL_ERROR_PHONE_NON_STRING: "Phone number must be of type string", - GENERAL_ERROR_PHONE_INVALID: "Phone number is invalid", - GENERAL_ERROR_EMAIL_OR_PHONE_UNDEFINED: "Please set your email or phone number", - GENERAL_ERROR_EMAIL_OR_PHONE_NON_STRING: "Email or Phone number must be of type string", - GENERAL_ERROR_EMAIL_OR_PHONE_INVALID: "Email or Phone number is invalid", - GENERAL_ERROR_OTP_UNDEFINED: "Please fill your OTP", - GENERAL_ERROR_OTP_INVALID: "Invalid OTP", - GENERAL_ERROR_OTP_EXPIRED: "Expired OTP.", - GENERAL_ERROR_OTP_NON_STRING: "OTP must be of type string", - GENERAL_ERROR_OTP_EMPTY: "OTP cannot be empty", - ERROR_SIGN_IN_UP_LINK: "Invalid magic link. Please try again.", - ERROR_SIGN_IN_UP_RESEND_RESTART_FLOW: "Login timed out. Please try again.", - ERROR_SIGN_IN_UP_CODE_CONSUME_RESTART_FLOW: "Login unsuccessful. Please try again.", - PWLESS_CLOSE_TAB_TITLE: "Success!", - PWLESS_CLOSE_TAB_SUBTITLE_LINE1: "You have been successfully signed in.", - PWLESS_CLOSE_TAB_SUBTITLE_LINE2: "Please close this tab", - PWLESS_SIGN_IN_UP_HEADER_TITLE: "Sign Up or Log In", - PWLESS_SIGN_IN_UP_FOOTER_START: "By continuing, you agree to our ", - PWLESS_SIGN_IN_UP_FOOTER_TOS: "Terms of Service", - PWLESS_SIGN_IN_UP_FOOTER_AND: " and ", - PWLESS_SIGN_IN_UP_FOOTER_PP: "Privacy Policy", - PWLESS_SIGN_IN_UP_FOOTER_END: "", - PWLESS_SIGN_IN_UP_EMAIL_LABEL: "Email", - PWLESS_SIGN_IN_UP_PHONE_LABEL: "Phone Number", - PWLESS_SIGN_IN_UP_EMAIL_OR_PHONE_LABEL: "Email or Phone number", - PWLESS_SIGN_IN_UP_CONTINUE_BUTTON: "CONTINUE", - PWLESS_EMAIL_OR_PHONE_INVALID_INPUT_GUESS_PHONE_ERR: - "Please enter a valid phone number with its country code.", - PWLESS_LINK_SENT_RESEND_SUCCESS: "Link resent", - PWLESS_LINK_SENT_RESEND_TITLE: "Link sent!", - PWLESS_LINK_SENT_RESEND_DESC_START_EMAIL: "We sent a link to ", - PWLESS_LINK_SENT_RESEND_DESC_START_PHONE: "We sent a link to your phone number ", - PWLESS_LINK_SENT_RESEND_DESC_END_EMAIL: " Click the link to login or sign up", - PWLESS_LINK_SENT_RESEND_DESC_END_PHONE: "", - PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_EMAIL: "Change email", - PWLESS_SIGN_IN_UP_CHANGE_CONTACT_INFO_PHONE: "Change phone number", - PWLESS_LINK_CLICKED_CONTINUE_HEADER: "Sign Up or Log In", - PWLESS_LINK_CLICKED_CONTINUE_DESC: "Click the button below to log in on this device", - PWLESS_LINK_CLICKED_CONTINUE_BUTTON: "CONTINUE", - PWLESS_RESEND_SUCCESS_EMAIL: "Email resent", - PWLESS_RESEND_SUCCESS_PHONE: "SMS resent", - PWLESS_RESEND_BTN_DISABLED_START: "Resend in ", - PWLESS_RESEND_BTN_DISABLED_END: "", - PWLESS_RESEND_BTN_EMAIL: "Resend Email", - PWLESS_RESEND_BTN_PHONE: "Resend SMS", - PWLESS_USER_INPUT_CODE_HEADER_TITLE: "Enter OTP", - PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE: "An OTP was sent to you at", - PWLESS_USER_INPUT_CODE_HEADER_SUBTITLE_LINK: "An OTP and a magic link was sent to you at", - PWLESS_USER_INPUT_CODE_INPUT_LABEL: "OTP", - PWLESS_MFA_LOGOUT: "Logout", - PWLESS_MFA_HEADER_TITLE_PHONE: "SMS based OTP", - PWLESS_MFA_HEADER_TITLE_EMAIL: "Email based OTP", - PWLESS_MFA_FOOTER_CHOOSER_ANOTHER: "Choose another factor", - PWLESS_MFA_FOOTER_LOGOUT: "Logout", - PWLESS_MFA_OTP_NOT_ALLOWED_TO_SETUP: "You are not allowed to set up OTP.", - /* - * The following are error messages from our backend SDK. - * These are returned as full messages to preserver compatibilty, but they work just like the keys above. - * They are shown as is by default (setting the value to undefined will display the raw translation key) - */ - "Failed to generate a one time code. Please try again": undefined, - "Phone number is invalid": undefined, - "Email is invalid": undefined, - "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)": - undefined, - "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_003)": - undefined, - } - ), -}; - -var LinkClickedScreen = function (props) { - var userContext = uiEntry.useUserContext(); - var _a = React.useState(false), - requireUserInteraction = _a[0], - setRequireUserInteraction = _a[1]; - var consumeCodeAtMount = React.useCallback( - function () { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var preAuthSessionId, linkCode, loginAttemptInfo; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - preAuthSessionId = genericComponentOverrideContext.getQueryParams("preAuthSessionId"); - linkCode = genericComponentOverrideContext.getURLHash(); - if (!(preAuthSessionId === null || preAuthSessionId.length === 0 || linkCode.length === 0)) - return [3 /*break*/, 2]; - return [ - 4 /*yield*/, - genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - history: props.history, - queryParams: { - error: "signin", - }, - redirectBack: false, - }), - ]; - case 1: - _a.sent(); - return [2 /*return*/, "REDIRECTING"]; - case 2: - return [ - 4 /*yield*/, - props.recipe.webJSRecipe.getLoginAttemptInfo({ userContext: userContext }), - ]; - case 3: - loginAttemptInfo = _a.sent(); - if ( - (loginAttemptInfo === null || loginAttemptInfo === void 0 - ? void 0 - : loginAttemptInfo.preAuthSessionId) !== preAuthSessionId - ) { - return [2 /*return*/, "REQUIRES_INTERACTION"]; - } - return [ - 2 /*return*/, - props.recipe.webJSRecipe.consumeCode({ - userContext: userContext, - }), - ]; - } - }); - }); - }, - [props.recipe, props.history] - ); - var handleConsumeResp = React.useCallback( - function (response) { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var loginAttemptInfo; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - if (response === "REQUIRES_INTERACTION") { - // We set this here, to make sure it's set after a possible remount - setRequireUserInteraction(true); - } - if (typeof response === "string") { - // In this case we are already redirecting or showing the continue button - return [2 /*return*/]; - } - if (response.status === "RESTART_FLOW_ERROR") { - return [ - 2 /*return*/, - genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - history: props.history, - queryParams: { - error: "restart_link", - }, - redirectBack: false, - }), - ]; - } - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - return [ - 2 /*return*/, - genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - history: props.history, - queryParams: { - error: response.reason, - }, - redirectBack: false, - }), - ]; - } - if (!(response.status === "OK")) return [3 /*break*/, 3]; - return [ - 4 /*yield*/, - props.recipe.webJSRecipe.getLoginAttemptInfo({ - userContext: userContext, - }), - ]; - case 1: - loginAttemptInfo = _a.sent(); - return [ - 4 /*yield*/, - props.recipe.webJSRecipe.clearLoginAttemptInfo({ - userContext: userContext, - }), - ]; - case 2: - _a.sent(); - return [ - 2 /*return*/, - recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( - { - rid: props.recipe.config.recipeId, - successRedirectContext: { - action: "SUCCESS", - isNewRecipeUser: response.createdNewRecipeUser, - user: response.user, - redirectToPath: - loginAttemptInfo === null || loginAttemptInfo === void 0 - ? void 0 - : loginAttemptInfo.redirectToPath, - }, - }, - userContext, - props.history - ), - ]; - case 3: - return [2 /*return*/]; - } - }); - }); - }, - [props.history, props.recipe] - ); - var handleConsumeError = React.useCallback( - function (err) { - if (STGeneralError__default.default.isThisError(err)) { - return genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - history: props.history, - queryParams: { - error: "custom", - message: err.message, - }, - redirectBack: false, - }); - } else { - return genericComponentOverrideContext.SuperTokens.getInstanceOrThrow().redirectToAuth({ - history: props.history, - queryParams: { - error: "signin", - }, - redirectBack: false, - }); - } - }, - [props.recipe, props.history] - ); - genericComponentOverrideContext.useOnMountAPICall(consumeCodeAtMount, handleConsumeResp, handleConsumeError); - var recipeComponentOverrides = props.useComponentOverrides(); - var childProps = { - recipeImplementation: props.recipe.webJSRecipe, - config: props.recipe.config, - requireUserInteraction: requireUserInteraction, - consumeCode: function () { - return genericComponentOverrideContext.__awaiter(void 0, void 0, void 0, function () { - var consumeResp, err_1; - return genericComponentOverrideContext.__generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 3, , 4]); - return [ - 4 /*yield*/, - props.recipe.webJSRecipe.consumeCode({ - userContext: userContext, - }), - ]; - case 1: - consumeResp = _a.sent(); - return [4 /*yield*/, handleConsumeResp(consumeResp)]; - case 2: - _a.sent(); - return [3 /*break*/, 4]; - case 3: - err_1 = _a.sent(); - void handleConsumeError(err_1); - return [3 /*break*/, 4]; - case 4: - return [2 /*return*/]; - } - }); - }); - }, - }; - return jsxRuntime.jsx( - uiEntry.ComponentOverrideContext.Provider, - genericComponentOverrideContext.__assign( - { value: recipeComponentOverrides }, - { - children: jsxRuntime.jsx( - uiEntry.FeatureWrapper, - genericComponentOverrideContext.__assign( - { - useShadowDom: props.recipe.config.useShadowDom, - defaultStore: defaultTranslationsPasswordless, - }, - { - children: jsxRuntime.jsxs(React.Fragment, { - children: [ - props.children === undefined && - jsxRuntime.jsx( - LinkClickedScreen$1, - genericComponentOverrideContext.__assign({}, childProps) - ), - props.children && - React__namespace.default.Children.map(props.children, function (child) { - if (React__namespace.default.isValidElement(child)) { - return React__namespace.default.cloneElement(child, childProps); - } - return child; - }), - ], - }), - } - ) - ), - } - ) - ); -}; - -var PasswordlessCloseTabScreen = function () { - var t = translationContext.useTranslation(); - return jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "container" }, - { - children: jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "row noFormRow" }, - { - children: [ - jsxRuntime.jsx(checkedRoundIcon.CheckedRoundIcon, {}), - jsxRuntime.jsx( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerTitle" }, - { children: t("PWLESS_CLOSE_TAB_TITLE") } - ) - ), - jsxRuntime.jsx("div", { "data-supertokens": "divider" }), - jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "headerSubtitle secondaryText" }, - { - children: [ - t("PWLESS_CLOSE_TAB_SUBTITLE_LINE1"), - jsxRuntime.jsx("br", {}), - t("PWLESS_CLOSE_TAB_SUBTITLE_LINE2"), - ], - } - ) - ), - ], - } - ) - ), - } - ) - ); -}; -var CloseTabScreen = uiEntry.withOverride("PasswordlessCloseTabScreen", PasswordlessCloseTabScreen); - -var SignInUpFooter = uiEntry.withOverride("PasswordlessSignInUpFooter", function PasswordlessSignInUpFooter(_a) { - var termsOfServiceLink = _a.termsOfServiceLink, - privacyPolicyLink = _a.privacyPolicyLink; - var t = translationContext.useTranslation(); - if (termsOfServiceLink === undefined && privacyPolicyLink === undefined) { - return null; - } - return jsxRuntime.jsxs( - "div", - genericComponentOverrideContext.__assign( - { "data-supertokens": "secondaryText privacyPolicyAndTermsAndConditions" }, - { - children: [ - t("PWLESS_SIGN_IN_UP_FOOTER_START"), - termsOfServiceLink !== undefined && - jsxRuntime.jsx( - "a", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "link", - href: termsOfServiceLink, - target: "_blank", - rel: "noopener noreferer", - }, - { children: t("PWLESS_SIGN_IN_UP_FOOTER_TOS") } - ) - ), - termsOfServiceLink !== undefined && - privacyPolicyLink !== undefined && - t("PWLESS_SIGN_IN_UP_FOOTER_AND"), - privacyPolicyLink !== undefined && - jsxRuntime.jsx( - "a", - genericComponentOverrideContext.__assign( - { - "data-supertokens": "link", - href: privacyPolicyLink, - target: "_blank", - rel: "noopener noreferer", - }, - { children: t("PWLESS_SIGN_IN_UP_FOOTER_PP") } - ) - ), - t("PWLESS_SIGN_IN_UP_FOOTER_END"), - ], - } - ) - ); -}); - -var EmailForm = uiEntry.withOverride("PasswordlessEmailForm", function PasswordlessEmailForm(props) { - var _this = this; - var _a; - var userContext = uiEntry.useUserContext(); - return jsxRuntime.jsx(formBase.FormBase, { - clearError: props.clearError, - onError: props.onError, - formFields: [ - { - id: "email", - label: "PWLESS_SIGN_IN_UP_EMAIL_LABEL", - optional: false, - autofocus: true, - placeholder: "", - autoComplete: "email", - // We are using the default validator that allows any string - validate: validators.defaultValidate, - }, - ], - buttonLabel: "PWLESS_SIGN_IN_UP_CONTINUE_BUTTON", - onSuccess: props.onSuccess, - callAPI: function (formFields) { - return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { - var email, validationRes, response; - var _a; - return genericComponentOverrideContext.__generator(this, function (_b) { - switch (_b.label) { - case 0: - email = - (_a = formFields.find(function (field) { - return field.id === "email"; - })) === null || _a === void 0 - ? void 0 - : _a.value; - if (email === undefined) { - throw new STGeneralError__default.default("GENERAL_ERROR_EMAIL_UNDEFINED"); - } - return [4 /*yield*/, props.config.validateEmailAddress(email)]; - case 1: - validationRes = _b.sent(); - if (validationRes !== undefined) { - throw new STGeneralError__default.default(validationRes); - } - return [ - 4 /*yield*/, - props.recipeImplementation.createCode({ - email: email, - userContext: userContext, - }), - ]; - case 2: - response = _b.sent(); - if (response.status === "SIGN_IN_UP_NOT_ALLOWED") { - throw new STGeneralError__default.default(response.reason); - } - return [2 /*return*/, response]; - } - }); - }); - }, - validateOnBlur: false, - showLabels: true, - footer: - (_a = props.footer) !== null && _a !== void 0 - ? _a - : jsxRuntime.jsx(SignInUpFooter, { - privacyPolicyLink: props.config.signInUpFeature.privacyPolicyLink, - termsOfServiceLink: props.config.signInUpFeature.termsOfServiceLink, - }), }); -}); - -function getDefaultExportFromCjs(x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; -} - -var intlTelInputExports$1 = {}; -var intlTelInput$2 = { - get exports() { - return intlTelInputExports$1; - }, - set exports(v) { - intlTelInputExports$1 = v; - }, -}; - -var intlTelInputExports = {}; -var intlTelInput$1 = { - get exports() { - return intlTelInputExports; - }, - set exports(v) { - intlTelInputExports = v; - }, -}; - -/* - * International Telephone Input v17.0.21 - * https://github.com/jackocnr/intl-tel-input.git - * Licensed under the MIT license - */ - -(function (module) { - // wrap in UMD - (function (factory) { - if (module.exports) module.exports = factory(); - else window.intlTelInput = factory(); - })(function (undefined$1) { - return (function () { - // Array of country objects for the flag dropdown. - // Here is the criteria for the plugin to support a given country/territory - // - It has an iso2 code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - // - It has it's own country calling code (it is not a sub-region of another country): https://en.wikipedia.org/wiki/List_of_country_calling_codes - // - It has a flag in the region-flags project: https://github.com/behdad/region-flags/tree/gh-pages/png - // - It is supported by libphonenumber (it must be listed on this page): https://github.com/googlei18n/libphonenumber/blob/master/resources/ShortNumberMetadata.xml - // Each country array has the following information: - // [ - // Country name, - // iso2 code, - // International dial code, - // Order (if >1 country with same dial code), - // Area codes - // ] - var allCountries = [ - ["Afghanistan (‫افغانستان‬‎)", "af", "93"], - ["Albania (Shqipëri)", "al", "355"], - ["Algeria (‫الجزائر‬‎)", "dz", "213"], - ["American Samoa", "as", "1", 5, ["684"]], - ["Andorra", "ad", "376"], - ["Angola", "ao", "244"], - ["Anguilla", "ai", "1", 6, ["264"]], - ["Antigua and Barbuda", "ag", "1", 7, ["268"]], - ["Argentina", "ar", "54"], - ["Armenia (Հայաստան)", "am", "374"], - ["Aruba", "aw", "297"], - ["Ascension Island", "ac", "247"], - ["Australia", "au", "61", 0], - ["Austria (Österreich)", "at", "43"], - ["Azerbaijan (Azərbaycan)", "az", "994"], - ["Bahamas", "bs", "1", 8, ["242"]], - ["Bahrain (‫البحرين‬‎)", "bh", "973"], - ["Bangladesh (বাংলাদেশ)", "bd", "880"], - ["Barbados", "bb", "1", 9, ["246"]], - ["Belarus (Беларусь)", "by", "375"], - ["Belgium (België)", "be", "32"], - ["Belize", "bz", "501"], - ["Benin (Bénin)", "bj", "229"], - ["Bermuda", "bm", "1", 10, ["441"]], - ["Bhutan (འབྲུག)", "bt", "975"], - ["Bolivia", "bo", "591"], - ["Bosnia and Herzegovina (Босна и Херцеговина)", "ba", "387"], - ["Botswana", "bw", "267"], - ["Brazil (Brasil)", "br", "55"], - ["British Indian Ocean Territory", "io", "246"], - ["British Virgin Islands", "vg", "1", 11, ["284"]], - ["Brunei", "bn", "673"], - ["Bulgaria (България)", "bg", "359"], - ["Burkina Faso", "bf", "226"], - ["Burundi (Uburundi)", "bi", "257"], - ["Cambodia (កម្ពុជា)", "kh", "855"], - ["Cameroon (Cameroun)", "cm", "237"], - [ - "Canada", - "ca", - "1", - 1, - [ - "204", - "226", - "236", - "249", - "250", - "289", - "306", - "343", - "365", - "387", - "403", - "416", - "418", - "431", - "437", - "438", - "450", - "506", - "514", - "519", - "548", - "579", - "581", - "587", - "604", - "613", - "639", - "647", - "672", - "705", - "709", - "742", - "778", - "780", - "782", - "807", - "819", - "825", - "867", - "873", - "902", - "905", - ], - ], - ["Cape Verde (Kabu Verdi)", "cv", "238"], - ["Caribbean Netherlands", "bq", "599", 1, ["3", "4", "7"]], - ["Cayman Islands", "ky", "1", 12, ["345"]], - ["Central African Republic (République centrafricaine)", "cf", "236"], - ["Chad (Tchad)", "td", "235"], - ["Chile", "cl", "56"], - ["China (中国)", "cn", "86"], - ["Christmas Island", "cx", "61", 2, ["89164"]], - ["Cocos (Keeling) Islands", "cc", "61", 1, ["89162"]], - ["Colombia", "co", "57"], - ["Comoros (‫جزر القمر‬‎)", "km", "269"], - ["Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)", "cd", "243"], - ["Congo (Republic) (Congo-Brazzaville)", "cg", "242"], - ["Cook Islands", "ck", "682"], - ["Costa Rica", "cr", "506"], - ["Côte d’Ivoire", "ci", "225"], - ["Croatia (Hrvatska)", "hr", "385"], - ["Cuba", "cu", "53"], - ["Curaçao", "cw", "599", 0], - ["Cyprus (Κύπρος)", "cy", "357"], - ["Czech Republic (Česká republika)", "cz", "420"], - ["Denmark (Danmark)", "dk", "45"], - ["Djibouti", "dj", "253"], - ["Dominica", "dm", "1", 13, ["767"]], - ["Dominican Republic (República Dominicana)", "do", "1", 2, ["809", "829", "849"]], - ["Ecuador", "ec", "593"], - ["Egypt (‫مصر‬‎)", "eg", "20"], - ["El Salvador", "sv", "503"], - ["Equatorial Guinea (Guinea Ecuatorial)", "gq", "240"], - ["Eritrea", "er", "291"], - ["Estonia (Eesti)", "ee", "372"], - ["Eswatini", "sz", "268"], - ["Ethiopia", "et", "251"], - ["Falkland Islands (Islas Malvinas)", "fk", "500"], - ["Faroe Islands (Føroyar)", "fo", "298"], - ["Fiji", "fj", "679"], - ["Finland (Suomi)", "fi", "358", 0], - ["France", "fr", "33"], - ["French Guiana (Guyane française)", "gf", "594"], - ["French Polynesia (Polynésie française)", "pf", "689"], - ["Gabon", "ga", "241"], - ["Gambia", "gm", "220"], - ["Georgia (საქართველო)", "ge", "995"], - ["Germany (Deutschland)", "de", "49"], - ["Ghana (Gaana)", "gh", "233"], - ["Gibraltar", "gi", "350"], - ["Greece (Ελλάδα)", "gr", "30"], - ["Greenland (Kalaallit Nunaat)", "gl", "299"], - ["Grenada", "gd", "1", 14, ["473"]], - ["Guadeloupe", "gp", "590", 0], - ["Guam", "gu", "1", 15, ["671"]], - ["Guatemala", "gt", "502"], - ["Guernsey", "gg", "44", 1, ["1481", "7781", "7839", "7911"]], - ["Guinea (Guinée)", "gn", "224"], - ["Guinea-Bissau (Guiné Bissau)", "gw", "245"], - ["Guyana", "gy", "592"], - ["Haiti", "ht", "509"], - ["Honduras", "hn", "504"], - ["Hong Kong (香港)", "hk", "852"], - ["Hungary (Magyarország)", "hu", "36"], - ["Iceland (Ísland)", "is", "354"], - ["India (भारत)", "in", "91"], - ["Indonesia", "id", "62"], - ["Iran (‫ایران‬‎)", "ir", "98"], - ["Iraq (‫العراق‬‎)", "iq", "964"], - ["Ireland", "ie", "353"], - ["Isle of Man", "im", "44", 2, ["1624", "74576", "7524", "7924", "7624"]], - ["Israel (‫ישראל‬‎)", "il", "972"], - ["Italy (Italia)", "it", "39", 0], - ["Jamaica", "jm", "1", 4, ["876", "658"]], - ["Japan (日本)", "jp", "81"], - ["Jersey", "je", "44", 3, ["1534", "7509", "7700", "7797", "7829", "7937"]], - ["Jordan (‫الأردن‬‎)", "jo", "962"], - ["Kazakhstan (Казахстан)", "kz", "7", 1, ["33", "7"]], - ["Kenya", "ke", "254"], - ["Kiribati", "ki", "686"], - ["Kosovo", "xk", "383"], - ["Kuwait (‫الكويت‬‎)", "kw", "965"], - ["Kyrgyzstan (Кыргызстан)", "kg", "996"], - ["Laos (ລາວ)", "la", "856"], - ["Latvia (Latvija)", "lv", "371"], - ["Lebanon (‫لبنان‬‎)", "lb", "961"], - ["Lesotho", "ls", "266"], - ["Liberia", "lr", "231"], - ["Libya (‫ليبيا‬‎)", "ly", "218"], - ["Liechtenstein", "li", "423"], - ["Lithuania (Lietuva)", "lt", "370"], - ["Luxembourg", "lu", "352"], - ["Macau (澳門)", "mo", "853"], - ["Madagascar (Madagasikara)", "mg", "261"], - ["Malawi", "mw", "265"], - ["Malaysia", "my", "60"], - ["Maldives", "mv", "960"], - ["Mali", "ml", "223"], - ["Malta", "mt", "356"], - ["Marshall Islands", "mh", "692"], - ["Martinique", "mq", "596"], - ["Mauritania (‫موريتانيا‬‎)", "mr", "222"], - ["Mauritius (Moris)", "mu", "230"], - ["Mayotte", "yt", "262", 1, ["269", "639"]], - ["Mexico (México)", "mx", "52"], - ["Micronesia", "fm", "691"], - ["Moldova (Republica Moldova)", "md", "373"], - ["Monaco", "mc", "377"], - ["Mongolia (Монгол)", "mn", "976"], - ["Montenegro (Crna Gora)", "me", "382"], - ["Montserrat", "ms", "1", 16, ["664"]], - ["Morocco (‫المغرب‬‎)", "ma", "212", 0], - ["Mozambique (Moçambique)", "mz", "258"], - ["Myanmar (Burma) (မြန်မာ)", "mm", "95"], - ["Namibia (Namibië)", "na", "264"], - ["Nauru", "nr", "674"], - ["Nepal (नेपाल)", "np", "977"], - ["Netherlands (Nederland)", "nl", "31"], - ["New Caledonia (Nouvelle-Calédonie)", "nc", "687"], - ["New Zealand", "nz", "64"], - ["Nicaragua", "ni", "505"], - ["Niger (Nijar)", "ne", "227"], - ["Nigeria", "ng", "234"], - ["Niue", "nu", "683"], - ["Norfolk Island", "nf", "672"], - ["North Korea (조선 민주주의 인민 공화국)", "kp", "850"], - ["North Macedonia (Северна Македонија)", "mk", "389"], - ["Northern Mariana Islands", "mp", "1", 17, ["670"]], - ["Norway (Norge)", "no", "47", 0], - ["Oman (‫عُمان‬‎)", "om", "968"], - ["Pakistan (‫پاکستان‬‎)", "pk", "92"], - ["Palau", "pw", "680"], - ["Palestine (‫فلسطين‬‎)", "ps", "970"], - ["Panama (Panamá)", "pa", "507"], - ["Papua New Guinea", "pg", "675"], - ["Paraguay", "py", "595"], - ["Peru (Perú)", "pe", "51"], - ["Philippines", "ph", "63"], - ["Poland (Polska)", "pl", "48"], - ["Portugal", "pt", "351"], - ["Puerto Rico", "pr", "1", 3, ["787", "939"]], - ["Qatar (‫قطر‬‎)", "qa", "974"], - ["Réunion (La Réunion)", "re", "262", 0], - ["Romania (România)", "ro", "40"], - ["Russia (Россия)", "ru", "7", 0], - ["Rwanda", "rw", "250"], - ["Saint Barthélemy", "bl", "590", 1], - ["Saint Helena", "sh", "290"], - ["Saint Kitts and Nevis", "kn", "1", 18, ["869"]], - ["Saint Lucia", "lc", "1", 19, ["758"]], - ["Saint Martin (Saint-Martin (partie française))", "mf", "590", 2], - ["Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)", "pm", "508"], - ["Saint Vincent and the Grenadines", "vc", "1", 20, ["784"]], - ["Samoa", "ws", "685"], - ["San Marino", "sm", "378"], - ["São Tomé and Príncipe (São Tomé e Príncipe)", "st", "239"], - ["Saudi Arabia (‫المملكة العربية السعودية‬‎)", "sa", "966"], - ["Senegal (Sénégal)", "sn", "221"], - ["Serbia (Србија)", "rs", "381"], - ["Seychelles", "sc", "248"], - ["Sierra Leone", "sl", "232"], - ["Singapore", "sg", "65"], - ["Sint Maarten", "sx", "1", 21, ["721"]], - ["Slovakia (Slovensko)", "sk", "421"], - ["Slovenia (Slovenija)", "si", "386"], - ["Solomon Islands", "sb", "677"], - ["Somalia (Soomaaliya)", "so", "252"], - ["South Africa", "za", "27"], - ["South Korea (대한민국)", "kr", "82"], - ["South Sudan (‫جنوب السودان‬‎)", "ss", "211"], - ["Spain (España)", "es", "34"], - ["Sri Lanka (ශ්‍රී ලංකාව)", "lk", "94"], - ["Sudan (‫السودان‬‎)", "sd", "249"], - ["Suriname", "sr", "597"], - ["Svalbard and Jan Mayen", "sj", "47", 1, ["79"]], - ["Sweden (Sverige)", "se", "46"], - ["Switzerland (Schweiz)", "ch", "41"], - ["Syria (‫سوريا‬‎)", "sy", "963"], - ["Taiwan (台灣)", "tw", "886"], - ["Tajikistan", "tj", "992"], - ["Tanzania", "tz", "255"], - ["Thailand (ไทย)", "th", "66"], - ["Timor-Leste", "tl", "670"], - ["Togo", "tg", "228"], - ["Tokelau", "tk", "690"], - ["Tonga", "to", "676"], - ["Trinidad and Tobago", "tt", "1", 22, ["868"]], - ["Tunisia (‫تونس‬‎)", "tn", "216"], - ["Turkey (Türkiye)", "tr", "90"], - ["Turkmenistan", "tm", "993"], - ["Turks and Caicos Islands", "tc", "1", 23, ["649"]], - ["Tuvalu", "tv", "688"], - ["U.S. Virgin Islands", "vi", "1", 24, ["340"]], - ["Uganda", "ug", "256"], - ["Ukraine (Україна)", "ua", "380"], - ["United Arab Emirates (‫الإمارات العربية المتحدة‬‎)", "ae", "971"], - ["United Kingdom", "gb", "44", 0], - ["United States", "us", "1", 0], - ["Uruguay", "uy", "598"], - ["Uzbekistan (Oʻzbekiston)", "uz", "998"], - ["Vanuatu", "vu", "678"], - ["Vatican City (Città del Vaticano)", "va", "39", 1, ["06698"]], - ["Venezuela", "ve", "58"], - ["Vietnam (Việt Nam)", "vn", "84"], - ["Wallis and Futuna (Wallis-et-Futuna)", "wf", "681"], - ["Western Sahara (‫الصحراء الغربية‬‎)", "eh", "212", 1, ["5288", "5289"]], - ["Yemen (‫اليمن‬‎)", "ye", "967"], - ["Zambia", "zm", "260"], - ["Zimbabwe", "zw", "263"], - ["Åland Islands", "ax", "358", 1, ["18"]], - ]; - // loop over all of the countries above, restructuring the data to be objects with named keys - for (var i = 0; i < allCountries.length; i++) { - var c = allCountries[i]; - allCountries[i] = { - name: c[0], - iso2: c[1], - dialCode: c[2], - priority: c[3] || 0, - areaCodes: c[4] || null, - }; - } - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } - var intlTelInputGlobals = { - getInstance: function getInstance(input) { - var id = input.getAttribute("data-intl-tel-input-id"); - return window.intlTelInputGlobals.instances[id]; - }, - instances: {}, - // using a global like this allows us to mock it in the tests - documentReady: function documentReady() { - return document.readyState === "complete"; - }, - }; - if (typeof window === "object") window.intlTelInputGlobals = intlTelInputGlobals; - // these vars persist through all instances of the plugin - var id = 0; - var defaults = { - // whether or not to allow the dropdown - allowDropdown: true, - // if there is just a dial code in the input: remove it on blur - autoHideDialCode: true, - // add a placeholder in the input with an example number for the selected country - autoPlaceholder: "polite", - // modify the parentClass - customContainer: "", - // modify the auto placeholder - customPlaceholder: null, - // append menu to specified element - dropdownContainer: null, - // don't display these countries - excludeCountries: [], - // format the input value during initialisation and on setNumber - formatOnDisplay: true, - // geoIp lookup function - geoIpLookup: null, - // inject a hidden input with this name, and on submit, populate it with the result of getNumber - hiddenInput: "", - // initial country - initialCountry: "", - // localized country names e.g. { 'de': 'Deutschland' } - localizedCountries: null, - // don't insert international dial codes - nationalMode: true, - // display only these countries - onlyCountries: [], - // number type to use for placeholders - placeholderNumberType: "MOBILE", - // the countries at the top of the list. defaults to united states and united kingdom - preferredCountries: ["us", "gb"], - // display the country dial code next to the selected flag so it's not part of the typed number - separateDialCode: false, - // specify the path to the libphonenumber script to enable validation/formatting - utilsScript: "", - }; - // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes - var regionlessNanpNumbers = [ - "800", - "822", - "833", - "844", - "855", - "866", - "877", - "880", - "881", - "882", - "883", - "884", - "885", - "886", - "887", - "888", - "889", - ]; - // utility function to iterate over an object. can't use Object.entries or native forEach because - // of IE11 - var forEachProp = function forEachProp(obj, callback) { - var keys = Object.keys(obj); - for (var i = 0; i < keys.length; i++) { - callback(keys[i], obj[keys[i]]); - } - }; - // run a method on each instance of the plugin - var forEachInstance = function forEachInstance(method) { - forEachProp(window.intlTelInputGlobals.instances, function (key) { - window.intlTelInputGlobals.instances[key][method](); - }); - }; - // this is our plugin class that we will create an instance of - // eslint-disable-next-line no-unused-vars - var Iti = - /*#__PURE__*/ - (function () { - function Iti(input, options) { - var _this = this; - _classCallCheck(this, Iti); - this.id = id++; - this.telInput = input; - this.activeItem = null; - this.highlightedItem = null; - // process specified options / defaults - // alternative to Object.assign, which isn't supported by IE11 - var customOptions = options || {}; - this.options = {}; - forEachProp(defaults, function (key, value) { - _this.options[key] = customOptions.hasOwnProperty(key) ? customOptions[key] : value; - }); - this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder")); - } - _createClass(Iti, [ - { - key: "_init", - value: function _init() { - var _this2 = this; - // if in nationalMode, disable options relating to dial codes - if (this.options.nationalMode) this.options.autoHideDialCode = false; - // if separateDialCode then doesn't make sense to A) insert dial code into input - // (autoHideDialCode), and B) display national numbers (because we're displaying the country - // dial code next to them) - if (this.options.separateDialCode) { - this.options.autoHideDialCode = this.options.nationalMode = false; - } - // we cannot just test screen size as some smartphones/website meta tags will report desktop - // resolutions - // Note: for some reason jasmine breaks if you put this in the main Plugin function with the - // rest of these declarations - // Note: to target Android Mobiles (and not Tablets), we must find 'Android' and 'Mobile' - this.isMobile = - /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test( - navigator.userAgent - ); - if (this.isMobile) { - // trigger the mobile dropdown css - document.body.classList.add("iti-mobile"); - // on mobile, we want a full screen dropdown, so we must append it to the body - if (!this.options.dropdownContainer) this.options.dropdownContainer = document.body; - } - // these promises get resolved when their individual requests complete - // this way the dev can do something like iti.promise.then(...) to know when all requests are - // complete - if (typeof Promise !== "undefined") { - var autoCountryPromise = new Promise(function (resolve, reject) { - _this2.resolveAutoCountryPromise = resolve; - _this2.rejectAutoCountryPromise = reject; - }); - var utilsScriptPromise = new Promise(function (resolve, reject) { - _this2.resolveUtilsScriptPromise = resolve; - _this2.rejectUtilsScriptPromise = reject; - }); - this.promise = Promise.all([autoCountryPromise, utilsScriptPromise]); - } else { - // prevent errors when Promise doesn't exist - this.resolveAutoCountryPromise = this.rejectAutoCountryPromise = function () {}; - this.resolveUtilsScriptPromise = this.rejectUtilsScriptPromise = function () {}; - } - // in various situations there could be no country selected initially, but we need to be able - // to assume this variable exists - this.selectedCountryData = {}; - // process all the data: onlyCountries, excludeCountries, preferredCountries etc - this._processCountryData(); - // generate the markup - this._generateMarkup(); - // set the initial state of the input value and the selected flag - this._setInitialState(); - // start all of the event listeners: autoHideDialCode, input keydown, selectedFlag click - this._initListeners(); - // utils script, and auto country - this._initRequests(); - }, - }, - { - key: "_processCountryData", - value: function _processCountryData() { - // process onlyCountries or excludeCountries array if present - this._processAllCountries(); - // process the countryCodes map - this._processCountryCodes(); - // process the preferredCountries - this._processPreferredCountries(); - // translate countries according to localizedCountries option - if (this.options.localizedCountries) this._translateCountriesByLocale(); - // sort countries by name - if (this.options.onlyCountries.length || this.options.localizedCountries) { - this.countries.sort(this._countryNameSort); - } - }, - }, - { - key: "_addCountryCode", - value: function _addCountryCode(iso2, countryCode, priority) { - if (countryCode.length > this.countryCodeMaxLen) { - this.countryCodeMaxLen = countryCode.length; - } - if (!this.countryCodes.hasOwnProperty(countryCode)) { - this.countryCodes[countryCode] = []; - } - // bail if we already have this country for this countryCode - for (var i = 0; i < this.countryCodes[countryCode].length; i++) { - if (this.countryCodes[countryCode][i] === iso2) return; - } - // check for undefined as 0 is falsy - var index = priority !== undefined$1 ? priority : this.countryCodes[countryCode].length; - this.countryCodes[countryCode][index] = iso2; - }, - }, - { - key: "_processAllCountries", - value: function _processAllCountries() { - if (this.options.onlyCountries.length) { - var lowerCaseOnlyCountries = this.options.onlyCountries.map(function (country) { - return country.toLowerCase(); - }); - this.countries = allCountries.filter(function (country) { - return lowerCaseOnlyCountries.indexOf(country.iso2) > -1; - }); - } else if (this.options.excludeCountries.length) { - var lowerCaseExcludeCountries = this.options.excludeCountries.map(function ( - country - ) { - return country.toLowerCase(); - }); - this.countries = allCountries.filter(function (country) { - return lowerCaseExcludeCountries.indexOf(country.iso2) === -1; - }); - } else { - this.countries = allCountries; - } - }, - }, - { - key: "_translateCountriesByLocale", - value: function _translateCountriesByLocale() { - for (var i = 0; i < this.countries.length; i++) { - var iso = this.countries[i].iso2.toLowerCase(); - if (this.options.localizedCountries.hasOwnProperty(iso)) { - this.countries[i].name = this.options.localizedCountries[iso]; - } - } - }, - }, - { - key: "_countryNameSort", - value: function _countryNameSort(a, b) { - return a.name.localeCompare(b.name); - }, - }, - { - key: "_processCountryCodes", - value: function _processCountryCodes() { - this.countryCodeMaxLen = 0; - // here we store just dial codes - this.dialCodes = {}; - // here we store "country codes" (both dial codes and their area codes) - this.countryCodes = {}; - // first: add dial codes - for (var i = 0; i < this.countries.length; i++) { - var c = this.countries[i]; - if (!this.dialCodes[c.dialCode]) this.dialCodes[c.dialCode] = true; - this._addCountryCode(c.iso2, c.dialCode, c.priority); - } - // next: add area codes - // this is a second loop over countries, to make sure we have all of the "root" countries - // already in the map, so that we can access them, as each time we add an area code substring - // to the map, we also need to include the "root" country's code, as that also matches - for (var _i = 0; _i < this.countries.length; _i++) { - var _c = this.countries[_i]; - // area codes - if (_c.areaCodes) { - var rootCountryCode = this.countryCodes[_c.dialCode][0]; - // for each area code - for (var j = 0; j < _c.areaCodes.length; j++) { - var areaCode = _c.areaCodes[j]; - // for each digit in the area code to add all partial matches as well - for (var k = 1; k < areaCode.length; k++) { - var partialDialCode = _c.dialCode + areaCode.substr(0, k); - // start with the root country, as that also matches this dial code - this._addCountryCode(rootCountryCode, partialDialCode); - this._addCountryCode(_c.iso2, partialDialCode); - } - // add the full area code - this._addCountryCode(_c.iso2, _c.dialCode + areaCode); - } - } - } - }, - }, - { - key: "_processPreferredCountries", - value: function _processPreferredCountries() { - this.preferredCountries = []; - for (var i = 0; i < this.options.preferredCountries.length; i++) { - var countryCode = this.options.preferredCountries[i].toLowerCase(); - var countryData = this._getCountryData(countryCode, false, true); - if (countryData) this.preferredCountries.push(countryData); - } - }, - }, - { - key: "_createEl", - value: function _createEl(name, attrs, container) { - var el = document.createElement(name); - if (attrs) - forEachProp(attrs, function (key, value) { - return el.setAttribute(key, value); - }); - if (container) container.appendChild(el); - return el; - }, - }, - { - key: "_generateMarkup", - value: function _generateMarkup() { - // if autocomplete does not exist on the element and its form, then - // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can - // easily put the plugin in an inconsistent state e.g. the wrong flag selected for the - // autocompleted number, which on submit could mean wrong number is saved (esp in nationalMode) - if ( - !this.telInput.hasAttribute("autocomplete") && - !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete")) - ) { - this.telInput.setAttribute("autocomplete", "off"); - } - // containers (mostly for positioning) - var parentClass = "iti"; - if (this.options.allowDropdown) parentClass += " iti--allow-dropdown"; - if (this.options.separateDialCode) parentClass += " iti--separate-dial-code"; - if (this.options.customContainer) { - parentClass += " "; - parentClass += this.options.customContainer; - } - var wrapper = this._createEl("div", { - class: parentClass, - }); - this.telInput.parentNode.insertBefore(wrapper, this.telInput); - this.flagsContainer = this._createEl( - "div", - { - class: "iti__flag-container", - }, - wrapper - ); - wrapper.appendChild(this.telInput); - // selected flag (displayed to left of input) - this.selectedFlag = this._createEl( - "div", - { - class: "iti__selected-flag", - role: "combobox", - "aria-controls": "iti-".concat(this.id, "__country-listbox"), - "aria-owns": "iti-".concat(this.id, "__country-listbox"), - "aria-expanded": "false", - }, - this.flagsContainer - ); - this.selectedFlagInner = this._createEl( - "div", - { - class: "iti__flag", - }, - this.selectedFlag - ); - if (this.options.separateDialCode) { - this.selectedDialCode = this._createEl( - "div", - { - class: "iti__selected-dial-code", - }, - this.selectedFlag - ); - } - if (this.options.allowDropdown) { - // make element focusable and tab navigable - this.selectedFlag.setAttribute("tabindex", "0"); - this.dropdownArrow = this._createEl( - "div", - { - class: "iti__arrow", - }, - this.selectedFlag - ); - // country dropdown: preferred countries, then divider, then all countries - this.countryList = this._createEl("ul", { - class: "iti__country-list iti__hide", - id: "iti-".concat(this.id, "__country-listbox"), - role: "listbox", - "aria-label": "List of countries", - }); - if (this.preferredCountries.length) { - this._appendListItems(this.preferredCountries, "iti__preferred", true); - this._createEl( - "li", - { - class: "iti__divider", - role: "separator", - "aria-disabled": "true", - }, - this.countryList - ); - } - this._appendListItems(this.countries, "iti__standard"); - // create dropdownContainer markup - if (this.options.dropdownContainer) { - this.dropdown = this._createEl("div", { - class: "iti iti--container", - }); - this.dropdown.appendChild(this.countryList); - } else { - this.flagsContainer.appendChild(this.countryList); - } - } - if (this.options.hiddenInput) { - var hiddenInputName = this.options.hiddenInput; - var name = this.telInput.getAttribute("name"); - if (name) { - var i = name.lastIndexOf("["); - // if input name contains square brackets, then give the hidden input the same name, - // replacing the contents of the last set of brackets with the given hiddenInput name - if (i !== -1) - hiddenInputName = "" - .concat(name.substr(0, i), "[") - .concat(hiddenInputName, "]"); - } - this.hiddenInput = this._createEl("input", { - type: "hidden", - name: hiddenInputName, - }); - wrapper.appendChild(this.hiddenInput); - } - }, - }, - { - key: "_appendListItems", - value: function _appendListItems(countries, className, preferred) { - // we create so many DOM elements, it is faster to build a temp string - // and then add everything to the DOM in one go at the end - var tmp = ""; - // for each country - for (var i = 0; i < countries.length; i++) { - var c = countries[i]; - var idSuffix = preferred ? "-preferred" : ""; - // open the list item - tmp += "
  • "); - // add the flag - tmp += "
    " - ); - // and the country name and dial code - tmp += "".concat(c.name, ""); - tmp += "+".concat(c.dialCode, ""); - // close the list item - tmp += "
  • "; - } - this.countryList.insertAdjacentHTML("beforeend", tmp); - }, - }, - { - key: "_setInitialState", - value: function _setInitialState() { - // fix firefox bug: when first load page (with input with value set to number with intl dial - // code) and initialising plugin removes the dial code from the input, then refresh page, - // and we try to init plugin again but this time on number without dial code so get grey flag - var attributeValue = this.telInput.getAttribute("value"); - var inputValue = this.telInput.value; - var useAttribute = - attributeValue && - attributeValue.charAt(0) === "+" && - (!inputValue || inputValue.charAt(0) !== "+"); - var val = useAttribute ? attributeValue : inputValue; - var dialCode = this._getDialCode(val); - var isRegionlessNanp = this._isRegionlessNanp(val); - var _this$options = this.options, - initialCountry = _this$options.initialCountry, - nationalMode = _this$options.nationalMode, - autoHideDialCode = _this$options.autoHideDialCode, - separateDialCode = _this$options.separateDialCode; - // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the - // flag, else fall back to the default country - if (dialCode && !isRegionlessNanp) { - this._updateFlagFromNumber(val); - } else if (initialCountry !== "auto") { - // see if we should select a flag - if (initialCountry) { - this._setFlag(initialCountry.toLowerCase()); - } else { - if (dialCode && isRegionlessNanp) { - // has intl dial code, is regionless nanp, and no initialCountry, so default to US - this._setFlag("us"); - } else { - // no dial code and no initialCountry, so default to first in list - this.defaultCountry = this.preferredCountries.length - ? this.preferredCountries[0].iso2 - : this.countries[0].iso2; - if (!val) { - this._setFlag(this.defaultCountry); - } - } - } - // if empty and no nationalMode and no autoHideDialCode then insert the default dial code - if (!val && !nationalMode && !autoHideDialCode && !separateDialCode) { - this.telInput.value = "+".concat(this.selectedCountryData.dialCode); - } - } - // NOTE: if initialCountry is set to auto, that will be handled separately - // format - note this wont be run after _updateDialCode as that's only called if no val - if (val) this._updateValFromNumber(val); - }, - }, - { - key: "_initListeners", - value: function _initListeners() { - this._initKeyListeners(); - if (this.options.autoHideDialCode) this._initBlurListeners(); - if (this.options.allowDropdown) this._initDropdownListeners(); - if (this.hiddenInput) this._initHiddenInputListener(); - }, - }, - { - key: "_initHiddenInputListener", - value: function _initHiddenInputListener() { - var _this3 = this; - this._handleHiddenInputSubmit = function () { - _this3.hiddenInput.value = _this3.getNumber(); - }; - if (this.telInput.form) - this.telInput.form.addEventListener("submit", this._handleHiddenInputSubmit); - }, - }, - { - key: "_getClosestLabel", - value: function _getClosestLabel() { - var el = this.telInput; - while (el && el.tagName !== "LABEL") { - el = el.parentNode; - } - return el; - }, - }, - { - key: "_initDropdownListeners", - value: function _initDropdownListeners() { - var _this4 = this; - // hack for input nested inside label (which is valid markup): clicking the selected-flag to - // open the dropdown would then automatically trigger a 2nd click on the input which would - // close it again - this._handleLabelClick = function (e) { - // if the dropdown is closed, then focus the input, else ignore the click - if (_this4.countryList.classList.contains("iti__hide")) _this4.telInput.focus(); - else e.preventDefault(); - }; - var label = this._getClosestLabel(); - if (label) label.addEventListener("click", this._handleLabelClick); - // toggle country dropdown on click - this._handleClickSelectedFlag = function () { - // only intercept this event if we're opening the dropdown - // else let it bubble up to the top ("click-off-to-close" listener) - // we cannot just stopPropagation as it may be needed to close another instance - if ( - _this4.countryList.classList.contains("iti__hide") && - !_this4.telInput.disabled && - !_this4.telInput.readOnly - ) { - _this4._showDropdown(); - } - }; - this.selectedFlag.addEventListener("click", this._handleClickSelectedFlag); - // open dropdown list if currently focused - this._handleFlagsContainerKeydown = function (e) { - var isDropdownHidden = _this4.countryList.classList.contains("iti__hide"); - if ( - isDropdownHidden && - ["ArrowUp", "Up", "ArrowDown", "Down", " ", "Enter"].indexOf(e.key) !== -1 - ) { - // prevent form from being submitted if "ENTER" was pressed - e.preventDefault(); - // prevent event from being handled again by document - e.stopPropagation(); - _this4._showDropdown(); - } - // allow navigation from dropdown to input on TAB - if (e.key === "Tab") _this4._closeDropdown(); - }; - this.flagsContainer.addEventListener("keydown", this._handleFlagsContainerKeydown); - }, - }, - { - key: "_initRequests", - value: function _initRequests() { - var _this5 = this; - // if the user has specified the path to the utils script, fetch it on window.load, else resolve - if (this.options.utilsScript && !window.intlTelInputUtils) { - // if the plugin is being initialised after the window.load event has already been fired - if (window.intlTelInputGlobals.documentReady()) { - window.intlTelInputGlobals.loadUtils(this.options.utilsScript); - } else { - // wait until the load event so we don't block any other requests e.g. the flags image - window.addEventListener("load", function () { - window.intlTelInputGlobals.loadUtils(_this5.options.utilsScript); - }); - } - } else this.resolveUtilsScriptPromise(); - if (this.options.initialCountry === "auto") this._loadAutoCountry(); - else this.resolveAutoCountryPromise(); - }, - }, - { - key: "_loadAutoCountry", - value: function _loadAutoCountry() { - // 3 options: - // 1) already loaded (we're done) - // 2) not already started loading (start) - // 3) already started loading (do nothing - just wait for loading callback to fire) - if (window.intlTelInputGlobals.autoCountry) { - this.handleAutoCountry(); - } else if (!window.intlTelInputGlobals.startedLoadingAutoCountry) { - // don't do this twice! - window.intlTelInputGlobals.startedLoadingAutoCountry = true; - if (typeof this.options.geoIpLookup === "function") { - this.options.geoIpLookup( - function (countryCode) { - window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase(); - // tell all instances the auto country is ready - // TODO: this should just be the current instances - // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight - // away (e.g. if they have already done the geo ip lookup somewhere else). Using - // setTimeout means that the current thread of execution will finish before executing - // this, which allows the plugin to finish initialising. - setTimeout(function () { - return forEachInstance("handleAutoCountry"); - }); - }, - function () { - return forEachInstance("rejectAutoCountryPromise"); - } - ); - } - } - }, - }, - { - key: "_initKeyListeners", - value: function _initKeyListeners() { - var _this6 = this; - // update flag on keyup - this._handleKeyupEvent = function () { - if (_this6._updateFlagFromNumber(_this6.telInput.value)) { - _this6._triggerCountryChange(); - } - }; - this.telInput.addEventListener("keyup", this._handleKeyupEvent); - // update flag on cut/paste events (now supported in all major browsers) - this._handleClipboardEvent = function () { - // hack because "paste" event is fired before input is updated - setTimeout(_this6._handleKeyupEvent); - }; - this.telInput.addEventListener("cut", this._handleClipboardEvent); - this.telInput.addEventListener("paste", this._handleClipboardEvent); - }, - }, - { - key: "_cap", - value: function _cap(number) { - var max = this.telInput.getAttribute("maxlength"); - return max && number.length > max ? number.substr(0, max) : number; - }, - }, - { - key: "_initBlurListeners", - value: function _initBlurListeners() { - var _this7 = this; - // on blur or form submit: if just a dial code then remove it - this._handleSubmitOrBlurEvent = function () { - _this7._removeEmptyDialCode(); - }; - if (this.telInput.form) - this.telInput.form.addEventListener("submit", this._handleSubmitOrBlurEvent); - this.telInput.addEventListener("blur", this._handleSubmitOrBlurEvent); - }, - }, - { - key: "_removeEmptyDialCode", - value: function _removeEmptyDialCode() { - if (this.telInput.value.charAt(0) === "+") { - var numeric = this._getNumeric(this.telInput.value); - // if just a plus, or if just a dial code - if (!numeric || this.selectedCountryData.dialCode === numeric) { - this.telInput.value = ""; - } - } - }, - }, - { - key: "_getNumeric", - value: function _getNumeric(s) { - return s.replace(/\D/g, ""); - }, - }, - { - key: "_trigger", - value: function _trigger(name) { - // have to use old school document.createEvent as IE11 doesn't support `new Event()` syntax - var e = document.createEvent("Event"); - e.initEvent(name, true, true); - // can bubble, and is cancellable - this.telInput.dispatchEvent(e); - }, - }, - { - key: "_showDropdown", - value: function _showDropdown() { - this.countryList.classList.remove("iti__hide"); - this.selectedFlag.setAttribute("aria-expanded", "true"); - this._setDropdownPosition(); - // update highlighting and scroll to active list item - if (this.activeItem) { - this._highlightListItem(this.activeItem, false); - this._scrollTo(this.activeItem, true); - } - // bind all the dropdown-related listeners: mouseover, click, click-off, keydown - this._bindDropdownListeners(); - // update the arrow - this.dropdownArrow.classList.add("iti__arrow--up"); - this._trigger("open:countrydropdown"); - }, - }, - { - key: "_toggleClass", - value: function _toggleClass(el, className, shouldHaveClass) { - if (shouldHaveClass && !el.classList.contains(className)) el.classList.add(className); - else if (!shouldHaveClass && el.classList.contains(className)) - el.classList.remove(className); - }, - }, - { - key: "_setDropdownPosition", - value: function _setDropdownPosition() { - var _this8 = this; - if (this.options.dropdownContainer) { - this.options.dropdownContainer.appendChild(this.dropdown); - } - if (!this.isMobile) { - var pos = this.telInput.getBoundingClientRect(); - // windowTop from https://stackoverflow.com/a/14384091/217866 - var windowTop = window.pageYOffset || document.documentElement.scrollTop; - var inputTop = pos.top + windowTop; - var dropdownHeight = this.countryList.offsetHeight; - // dropdownFitsBelow = (dropdownBottom < windowBottom) - var dropdownFitsBelow = - inputTop + this.telInput.offsetHeight + dropdownHeight < - windowTop + window.innerHeight; - var dropdownFitsAbove = inputTop - dropdownHeight > windowTop; - // by default, the dropdown will be below the input. If we want to position it above the - // input, we add the dropup class. - this._toggleClass( - this.countryList, - "iti__country-list--dropup", - !dropdownFitsBelow && dropdownFitsAbove - ); - // if dropdownContainer is enabled, calculate postion - if (this.options.dropdownContainer) { - // by default the dropdown will be directly over the input because it's not in the flow. - // If we want to position it below, we need to add some extra top value. - var extraTop = - !dropdownFitsBelow && dropdownFitsAbove ? 0 : this.telInput.offsetHeight; - // calculate placement - this.dropdown.style.top = "".concat(inputTop + extraTop, "px"); - this.dropdown.style.left = "".concat(pos.left + document.body.scrollLeft, "px"); - // close menu on window scroll - this._handleWindowScroll = function () { - return _this8._closeDropdown(); - }; - window.addEventListener("scroll", this._handleWindowScroll); - } - } - }, - }, - { - key: "_getClosestListItem", - value: function _getClosestListItem(target) { - var el = target; - while (el && el !== this.countryList && !el.classList.contains("iti__country")) { - el = el.parentNode; - } - // if we reached the countryList element, then return null - return el === this.countryList ? null : el; - }, - }, - { - key: "_bindDropdownListeners", - value: function _bindDropdownListeners() { - var _this9 = this; - // when mouse over a list item, just highlight that one - // we add the class "highlight", so if they hit "enter" we know which one to select - this._handleMouseoverCountryList = function (e) { - // handle event delegation, as we're listening for this event on the countryList - var listItem = _this9._getClosestListItem(e.target); - if (listItem) _this9._highlightListItem(listItem, false); - }; - this.countryList.addEventListener("mouseover", this._handleMouseoverCountryList); - // listen for country selection - this._handleClickCountryList = function (e) { - var listItem = _this9._getClosestListItem(e.target); - if (listItem) _this9._selectListItem(listItem); - }; - this.countryList.addEventListener("click", this._handleClickCountryList); - // click off to close - // (except when this initial opening click is bubbling up) - // we cannot just stopPropagation as it may be needed to close another instance - var isOpening = true; - this._handleClickOffToClose = function () { - if (!isOpening) _this9._closeDropdown(); - isOpening = false; - }; - document.documentElement.addEventListener("click", this._handleClickOffToClose); - // listen for up/down scrolling, enter to select, or letters to jump to country name. - // use keydown as keypress doesn't fire for non-char keys and we want to catch if they - // just hit down and hold it to scroll down (no keyup event). - // listen on the document because that's where key events are triggered if no input has focus - var query = ""; - var queryTimer = null; - this._handleKeydownOnDropdown = function (e) { - // prevent down key from scrolling the whole page, - // and enter key from submitting a form etc - e.preventDefault(); - // up and down to navigate - if ( - e.key === "ArrowUp" || - e.key === "Up" || - e.key === "ArrowDown" || - e.key === "Down" - ) - _this9._handleUpDownKey(e.key); - else if (e.key === "Enter") _this9._handleEnterKey(); - else if (e.key === "Escape") _this9._closeDropdown(); - else if (/^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) { - // jump to countries that start with the query string - if (queryTimer) clearTimeout(queryTimer); - query += e.key.toLowerCase(); - _this9._searchForCountry(query); - // if the timer hits 1 second, reset the query - queryTimer = setTimeout(function () { - query = ""; - }, 1e3); - } - }; - document.addEventListener("keydown", this._handleKeydownOnDropdown); - }, - }, - { - key: "_handleUpDownKey", - value: function _handleUpDownKey(key) { - var next = - key === "ArrowUp" || key === "Up" - ? this.highlightedItem.previousElementSibling - : this.highlightedItem.nextElementSibling; - if (next) { - // skip the divider - if (next.classList.contains("iti__divider")) { - next = - key === "ArrowUp" || key === "Up" - ? next.previousElementSibling - : next.nextElementSibling; - } - this._highlightListItem(next, true); - } - }, - }, - { - key: "_handleEnterKey", - value: function _handleEnterKey() { - if (this.highlightedItem) this._selectListItem(this.highlightedItem); - }, - }, - { - key: "_searchForCountry", - value: function _searchForCountry(query) { - for (var i = 0; i < this.countries.length; i++) { - if (this._startsWith(this.countries[i].name, query)) { - var listItem = this.countryList.querySelector( - "#iti-".concat(this.id, "__item-").concat(this.countries[i].iso2) - ); - // update highlighting and scroll - this._highlightListItem(listItem, false); - this._scrollTo(listItem, true); - break; - } - } - }, - }, - { - key: "_startsWith", - value: function _startsWith(a, b) { - return a.substr(0, b.length).toLowerCase() === b; - }, - }, - { - key: "_updateValFromNumber", - value: function _updateValFromNumber(originalNumber) { - var number = originalNumber; - if ( - this.options.formatOnDisplay && - window.intlTelInputUtils && - this.selectedCountryData - ) { - var useNational = - !this.options.separateDialCode && - (this.options.nationalMode || number.charAt(0) !== "+"); - var _intlTelInputUtils$nu = intlTelInputUtils.numberFormat, - NATIONAL = _intlTelInputUtils$nu.NATIONAL, - INTERNATIONAL = _intlTelInputUtils$nu.INTERNATIONAL; - var format = useNational ? NATIONAL : INTERNATIONAL; - number = intlTelInputUtils.formatNumber( - number, - this.selectedCountryData.iso2, - format - ); - } - number = this._beforeSetNumber(number); - this.telInput.value = number; - }, - }, - { - key: "_updateFlagFromNumber", - value: function _updateFlagFromNumber(originalNumber) { - // if we're in nationalMode and we already have US/Canada selected, make sure the number starts - // with a +1 so _getDialCode will be able to extract the area code - // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag - // from the number), that means we're initialising the plugin with a number that already has a - // dial code, so fine to ignore this bit - var number = originalNumber; - var selectedDialCode = this.selectedCountryData.dialCode; - var isNanp = selectedDialCode === "1"; - if (number && this.options.nationalMode && isNanp && number.charAt(0) !== "+") { - if (number.charAt(0) !== "1") number = "1".concat(number); - number = "+".concat(number); - } - // update flag if user types area code for another country - if (this.options.separateDialCode && selectedDialCode && number.charAt(0) !== "+") { - number = "+".concat(selectedDialCode).concat(number); - } - // try and extract valid dial code from input - var dialCode = this._getDialCode(number, true); - var numeric = this._getNumeric(number); - var countryCode = null; - if (dialCode) { - var countryCodes = this.countryCodes[this._getNumeric(dialCode)]; - // check if the right country is already selected. this should be false if the number is - // longer than the matched dial code because in this case we need to make sure that if - // there are multiple country matches, that the first one is selected (note: we could - // just check that here, but it requires the same loop that we already have later) - var alreadySelected = - countryCodes.indexOf(this.selectedCountryData.iso2) !== -1 && - numeric.length <= dialCode.length - 1; - var isRegionlessNanpNumber = - selectedDialCode === "1" && this._isRegionlessNanp(numeric); - // only update the flag if: - // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp) - // AND - // B) the right country is not already selected - if (!isRegionlessNanpNumber && !alreadySelected) { - // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first - // non-empty index - for (var j = 0; j < countryCodes.length; j++) { - if (countryCodes[j]) { - countryCode = countryCodes[j]; - break; - } - } - } - } else if (number.charAt(0) === "+" && numeric.length) { - // invalid dial code, so empty - // Note: use getNumeric here because the number has not been formatted yet, so could contain - // bad chars - countryCode = ""; - } else if (!number || number === "+") { - // empty, or just a plus, so default - countryCode = this.defaultCountry; - } - if (countryCode !== null) { - return this._setFlag(countryCode); - } - return false; - }, - }, - { - key: "_isRegionlessNanp", - value: function _isRegionlessNanp(number) { - var numeric = this._getNumeric(number); - if (numeric.charAt(0) === "1") { - var areaCode = numeric.substr(1, 3); - return regionlessNanpNumbers.indexOf(areaCode) !== -1; - } - return false; - }, - }, - { - key: "_highlightListItem", - value: function _highlightListItem(listItem, shouldFocus) { - var prevItem = this.highlightedItem; - if (prevItem) prevItem.classList.remove("iti__highlight"); - this.highlightedItem = listItem; - this.highlightedItem.classList.add("iti__highlight"); - if (shouldFocus) this.highlightedItem.focus(); - }, - }, - { - key: "_getCountryData", - value: function _getCountryData(countryCode, ignoreOnlyCountriesOption, allowFail) { - var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries; - for (var i = 0; i < countryList.length; i++) { - if (countryList[i].iso2 === countryCode) { - return countryList[i]; - } - } - if (allowFail) { - return null; - } - throw new Error("No country data for '".concat(countryCode, "'")); - }, - }, - { - key: "_setFlag", - value: function _setFlag(countryCode) { - var prevCountry = this.selectedCountryData.iso2 ? this.selectedCountryData : {}; - // do this first as it will throw an error and stop if countryCode is invalid - this.selectedCountryData = countryCode - ? this._getCountryData(countryCode, false, false) - : {}; - // update the defaultCountry - we only need the iso2 from now on, so just store that - if (this.selectedCountryData.iso2) { - this.defaultCountry = this.selectedCountryData.iso2; - } - this.selectedFlagInner.setAttribute("class", "iti__flag iti__".concat(countryCode)); - // update the selected country's title attribute - var title = countryCode - ? "" - .concat(this.selectedCountryData.name, ": +") - .concat(this.selectedCountryData.dialCode) - : "Unknown"; - this.selectedFlag.setAttribute("title", title); - if (this.options.separateDialCode) { - var dialCode = this.selectedCountryData.dialCode - ? "+".concat(this.selectedCountryData.dialCode) - : ""; - this.selectedDialCode.innerHTML = dialCode; - // offsetWidth is zero if input is in a hidden container during initialisation - var selectedFlagWidth = - this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth(); - // add 6px of padding after the grey selected-dial-code box, as this is what we use in the css - this.telInput.style.paddingLeft = "".concat(selectedFlagWidth + 6, "px"); - } - // and the input's placeholder - this._updatePlaceholder(); - // update the active list item - if (this.options.allowDropdown) { - var prevItem = this.activeItem; - if (prevItem) { - prevItem.classList.remove("iti__active"); - prevItem.setAttribute("aria-selected", "false"); - } - if (countryCode) { - // check if there is a preferred item first, else fall back to standard - var nextItem = - this.countryList.querySelector( - "#iti-".concat(this.id, "__item-").concat(countryCode, "-preferred") - ) || - this.countryList.querySelector( - "#iti-".concat(this.id, "__item-").concat(countryCode) - ); - nextItem.setAttribute("aria-selected", "true"); - nextItem.classList.add("iti__active"); - this.activeItem = nextItem; - this.selectedFlag.setAttribute( - "aria-activedescendant", - nextItem.getAttribute("id") - ); - } - } - // return if the flag has changed or not - return prevCountry.iso2 !== countryCode; - }, - }, - { - key: "_getHiddenSelectedFlagWidth", - value: function _getHiddenSelectedFlagWidth() { - // to get the right styling to apply, all we need is a shallow clone of the container, - // and then to inject a deep clone of the selectedFlag element - var containerClone = this.telInput.parentNode.cloneNode(); - containerClone.style.visibility = "hidden"; - document.body.appendChild(containerClone); - var flagsContainerClone = this.flagsContainer.cloneNode(); - containerClone.appendChild(flagsContainerClone); - var selectedFlagClone = this.selectedFlag.cloneNode(true); - flagsContainerClone.appendChild(selectedFlagClone); - var width = selectedFlagClone.offsetWidth; - containerClone.parentNode.removeChild(containerClone); - return width; - }, - }, - { - key: "_updatePlaceholder", - value: function _updatePlaceholder() { - var shouldSetPlaceholder = - this.options.autoPlaceholder === "aggressive" || - (!this.hadInitialPlaceholder && this.options.autoPlaceholder === "polite"); - if (window.intlTelInputUtils && shouldSetPlaceholder) { - var numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType]; - var placeholder = this.selectedCountryData.iso2 - ? intlTelInputUtils.getExampleNumber( - this.selectedCountryData.iso2, - this.options.nationalMode, - numberType - ) - : ""; - placeholder = this._beforeSetNumber(placeholder); - if (typeof this.options.customPlaceholder === "function") { - placeholder = this.options.customPlaceholder( - placeholder, - this.selectedCountryData - ); - } - this.telInput.setAttribute("placeholder", placeholder); - } - }, - }, - { - key: "_selectListItem", - value: function _selectListItem(listItem) { - // update selected flag and active list item - var flagChanged = this._setFlag(listItem.getAttribute("data-country-code")); - this._closeDropdown(); - this._updateDialCode(listItem.getAttribute("data-dial-code"), true); - // focus the input - this.telInput.focus(); - // put cursor at end - this fix is required for FF and IE11 (with nationalMode=false i.e. auto - // inserting dial code), who try to put the cursor at the beginning the first time - var len = this.telInput.value.length; - this.telInput.setSelectionRange(len, len); - if (flagChanged) { - this._triggerCountryChange(); - } - }, - }, - { - key: "_closeDropdown", - value: function _closeDropdown() { - this.countryList.classList.add("iti__hide"); - this.selectedFlag.setAttribute("aria-expanded", "false"); - // update the arrow - this.dropdownArrow.classList.remove("iti__arrow--up"); - // unbind key events - document.removeEventListener("keydown", this._handleKeydownOnDropdown); - document.documentElement.removeEventListener("click", this._handleClickOffToClose); - this.countryList.removeEventListener("mouseover", this._handleMouseoverCountryList); - this.countryList.removeEventListener("click", this._handleClickCountryList); - // remove menu from container - if (this.options.dropdownContainer) { - if (!this.isMobile) window.removeEventListener("scroll", this._handleWindowScroll); - if (this.dropdown.parentNode) this.dropdown.parentNode.removeChild(this.dropdown); - } - this._trigger("close:countrydropdown"); - }, - }, - { - key: "_scrollTo", - value: function _scrollTo(element, middle) { - var container = this.countryList; - // windowTop from https://stackoverflow.com/a/14384091/217866 - var windowTop = window.pageYOffset || document.documentElement.scrollTop; - var containerHeight = container.offsetHeight; - var containerTop = container.getBoundingClientRect().top + windowTop; - var containerBottom = containerTop + containerHeight; - var elementHeight = element.offsetHeight; - var elementTop = element.getBoundingClientRect().top + windowTop; - var elementBottom = elementTop + elementHeight; - var newScrollTop = elementTop - containerTop + container.scrollTop; - var middleOffset = containerHeight / 2 - elementHeight / 2; - if (elementTop < containerTop) { - // scroll up - if (middle) newScrollTop -= middleOffset; - container.scrollTop = newScrollTop; - } else if (elementBottom > containerBottom) { - // scroll down - if (middle) newScrollTop += middleOffset; - var heightDifference = containerHeight - elementHeight; - container.scrollTop = newScrollTop - heightDifference; - } - }, - }, - { - key: "_updateDialCode", - value: function _updateDialCode(newDialCodeBare, hasSelectedListItem) { - var inputVal = this.telInput.value; - // save having to pass this every time - var newDialCode = "+".concat(newDialCodeBare); - var newNumber; - if (inputVal.charAt(0) === "+") { - // there's a plus so we're dealing with a replacement (doesn't matter if nationalMode or not) - var prevDialCode = this._getDialCode(inputVal); - if (prevDialCode) { - // current number contains a valid dial code, so replace it - newNumber = inputVal.replace(prevDialCode, newDialCode); - } else { - // current number contains an invalid dial code, so ditch it - // (no way to determine where the invalid dial code ends and the rest of the number begins) - newNumber = newDialCode; - } - } else if (this.options.nationalMode || this.options.separateDialCode) { - // don't do anything - return; - } else { - // nationalMode is disabled - if (inputVal) { - // there is an existing value with no dial code: prefix the new dial code - newNumber = newDialCode + inputVal; - } else if (hasSelectedListItem || !this.options.autoHideDialCode) { - // no existing value and either they've just selected a list item, or autoHideDialCode is - // disabled: insert new dial code - newNumber = newDialCode; - } else { - return; - } - } - this.telInput.value = newNumber; - }, - }, - { - key: "_getDialCode", - value: function _getDialCode(number, includeAreaCode) { - var dialCode = ""; - // only interested in international numbers (starting with a plus) - if (number.charAt(0) === "+") { - var numericChars = ""; - // iterate over chars - for (var i = 0; i < number.length; i++) { - var c = number.charAt(i); - // if char is number (https://stackoverflow.com/a/8935649/217866) - if (!isNaN(parseInt(c, 10))) { - numericChars += c; - // if current numericChars make a valid dial code - if (includeAreaCode) { - if (this.countryCodes[numericChars]) { - // store the actual raw string (useful for matching later) - dialCode = number.substr(0, i + 1); - } - } else { - if (this.dialCodes[numericChars]) { - dialCode = number.substr(0, i + 1); - // if we're just looking for a dial code, we can break as soon as we find one - break; - } - } - // stop searching as soon as we can - in this case when we hit max len - if (numericChars.length === this.countryCodeMaxLen) { - break; - } - } - } - } - return dialCode; - }, - }, - { - key: "_getFullNumber", - value: function _getFullNumber() { - var val = this.telInput.value.trim(); - var dialCode = this.selectedCountryData.dialCode; - var prefix; - var numericVal = this._getNumeric(val); - if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) { - // when using separateDialCode, it is visible so is effectively part of the typed number - prefix = "+".concat(dialCode); - } else { - prefix = ""; - } - return prefix + val; - }, - }, - { - key: "_beforeSetNumber", - value: function _beforeSetNumber(originalNumber) { - var number = originalNumber; - if (this.options.separateDialCode) { - var dialCode = this._getDialCode(number); - // if there is a valid dial code - if (dialCode) { - // in case _getDialCode returned an area code as well - dialCode = "+".concat(this.selectedCountryData.dialCode); - // a lot of numbers will have a space separating the dial code and the main number, and - // some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get - // rid of it - // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc - var start = - number[dialCode.length] === " " || number[dialCode.length] === "-" - ? dialCode.length + 1 - : dialCode.length; - number = number.substr(start); - } - } - return this._cap(number); - }, - }, - { - key: "_triggerCountryChange", - value: function _triggerCountryChange() { - this._trigger("countrychange"); - }, - }, - { - key: "handleAutoCountry", - value: function handleAutoCountry() { - if (this.options.initialCountry === "auto") { - // we must set this even if there is an initial val in the input: in case the initial val is - // invalid and they delete it - they should see their auto country - this.defaultCountry = window.intlTelInputGlobals.autoCountry; - // if there's no initial value in the input, then update the flag - if (!this.telInput.value) { - this.setCountry(this.defaultCountry); - } - this.resolveAutoCountryPromise(); - } - }, - }, - { - key: "handleUtils", - value: function handleUtils() { - // if the request was successful - if (window.intlTelInputUtils) { - // if there's an initial value in the input, then format it - if (this.telInput.value) { - this._updateValFromNumber(this.telInput.value); - } - this._updatePlaceholder(); - } - this.resolveUtilsScriptPromise(); - }, - }, - { - key: "destroy", - value: function destroy() { - var form = this.telInput.form; - if (this.options.allowDropdown) { - // make sure the dropdown is closed (and unbind listeners) - this._closeDropdown(); - this.selectedFlag.removeEventListener("click", this._handleClickSelectedFlag); - this.flagsContainer.removeEventListener( - "keydown", - this._handleFlagsContainerKeydown - ); - // label click hack - var label = this._getClosestLabel(); - if (label) label.removeEventListener("click", this._handleLabelClick); - } - // unbind hiddenInput listeners - if (this.hiddenInput && form) - form.removeEventListener("submit", this._handleHiddenInputSubmit); - // unbind autoHideDialCode listeners - if (this.options.autoHideDialCode) { - if (form) form.removeEventListener("submit", this._handleSubmitOrBlurEvent); - this.telInput.removeEventListener("blur", this._handleSubmitOrBlurEvent); - } - // unbind key events, and cut/paste events - this.telInput.removeEventListener("keyup", this._handleKeyupEvent); - this.telInput.removeEventListener("cut", this._handleClipboardEvent); - this.telInput.removeEventListener("paste", this._handleClipboardEvent); - // remove attribute of id instance: data-intl-tel-input-id - this.telInput.removeAttribute("data-intl-tel-input-id"); - // remove markup (but leave the original input) - var wrapper = this.telInput.parentNode; - wrapper.parentNode.insertBefore(this.telInput, wrapper); - wrapper.parentNode.removeChild(wrapper); - delete window.intlTelInputGlobals.instances[this.id]; - }, - }, - { - key: "getExtension", - value: function getExtension() { - if (window.intlTelInputUtils) { - return intlTelInputUtils.getExtension( - this._getFullNumber(), - this.selectedCountryData.iso2 - ); - } - return ""; - }, - }, - { - key: "getNumber", - value: function getNumber(format) { - if (window.intlTelInputUtils) { - var iso2 = this.selectedCountryData.iso2; - return intlTelInputUtils.formatNumber(this._getFullNumber(), iso2, format); - } - return ""; - }, - }, - { - key: "getNumberType", - value: function getNumberType() { - if (window.intlTelInputUtils) { - return intlTelInputUtils.getNumberType( - this._getFullNumber(), - this.selectedCountryData.iso2 - ); - } - return -99; - }, - }, - { - key: "getSelectedCountryData", - value: function getSelectedCountryData() { - return this.selectedCountryData; - }, - }, - { - key: "getValidationError", - value: function getValidationError() { - if (window.intlTelInputUtils) { - var iso2 = this.selectedCountryData.iso2; - return intlTelInputUtils.getValidationError(this._getFullNumber(), iso2); - } - return -99; - }, - }, - { - key: "isValidNumber", - value: function isValidNumber() { - var val = this._getFullNumber().trim(); - var countryCode = this.options.nationalMode ? this.selectedCountryData.iso2 : ""; - return window.intlTelInputUtils - ? intlTelInputUtils.isValidNumber(val, countryCode) - : null; - }, - }, - { - key: "setCountry", - value: function setCountry(originalCountryCode) { - var countryCode = originalCountryCode.toLowerCase(); - // check if already selected - if (!this.selectedFlagInner.classList.contains("iti__".concat(countryCode))) { - this._setFlag(countryCode); - this._updateDialCode(this.selectedCountryData.dialCode, false); - this._triggerCountryChange(); - } - }, - }, - { - key: "setNumber", - value: function setNumber(number) { - // we must update the flag first, which updates this.selectedCountryData, which is used for - // formatting the number before displaying it - var flagChanged = this._updateFlagFromNumber(number); - this._updateValFromNumber(number); - if (flagChanged) { - this._triggerCountryChange(); - } - }, - }, - { - key: "setPlaceholderNumberType", - value: function setPlaceholderNumberType(type) { - this.options.placeholderNumberType = type; - this._updatePlaceholder(); - }, - }, - ]); - return Iti; - })(); - /******************** - * STATIC METHODS - ********************/ - // get the country data object - intlTelInputGlobals.getCountryData = function () { - return allCountries; - }; - // inject a