From 083e9086827222540a596182bddf4ae979a3fd89 Mon Sep 17 00:00:00 2001 From: Mihaly Lengyel Date: Fri, 20 Oct 2023 00:28:01 +0200 Subject: [PATCH] feat: update pwless to support otp based mfa --- examples/for-tests/src/App.js | 6 +- lib/build/components/assets/linkIcon.d.ts | 2 - lib/build/emailpassword-shared6.js | 63 +- lib/build/emailpassword-shared7.js | 58 + lib/build/emailpasswordprebuiltui.js | 2 +- lib/build/emailverification-shared2.js | 2 +- lib/build/index2.js | 2 +- lib/build/multifactorauthprebuiltui.js | 2 +- lib/build/passwordless-shared2.js | 58 +- lib/build/passwordless-shared3.js | 2400 ++++++++++++----- lib/build/passwordlessprebuiltui.js | 4 +- .../components/features/mfa/index.d.ts | 40 +- .../components/themes/mfa/index.d.ts | 11 + .../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 | 5 + lib/build/recipe/passwordless/prebuiltui.d.ts | 2 +- lib/build/recipe/passwordless/types.d.ts | 76 + .../components/themes/translations.d.ts | 5 + lib/build/sessionprebuiltui.js | 2 +- lib/build/thirdparty-shared2.js | 2 +- .../thirdpartyemailpasswordprebuiltui.js | 4 +- lib/build/thirdpartypasswordlessprebuiltui.js | 16 +- lib/ts/components/assets/linkIcon.tsx | 12 - .../components/themes/styles.css | 16 - .../components/features/mfa/index.tsx | 280 +- .../components/themes/mfa/index.tsx | 175 ++ .../components/themes/mfa/mfaFooter.tsx | 46 + .../components/themes/mfa/mfaHeader.tsx | 53 + .../components/themes/mfa/mfaOTPFooter.tsx | 59 + .../components/themes/mfa/mfaOTPHeader.tsx | 61 + .../components/themes/signInUp/emailForm.tsx | 16 +- .../themes/signInUp/emailOrPhoneForm.tsx | 16 +- .../components/themes/signInUp/index.tsx | 46 +- .../components/themes/signInUp/phoneForm.tsx | 16 +- .../themes/signInUp/userInputCodeForm.tsx | 5 +- .../components/themes/translations.ts | 5 + lib/ts/recipe/passwordless/prebuiltui.tsx | 55 +- lib/ts/recipe/passwordless/recipe.tsx | 38 +- lib/ts/recipe/passwordless/types.ts | 80 + lib/ts/recipe/passwordless/utils.ts | 1 + .../components/themes/signInUp/index.tsx | 12 +- lib/ts/styles/styles.css | 16 + 50 files changed, 2863 insertions(+), 946 deletions(-) delete mode 100644 lib/build/components/assets/linkIcon.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 delete mode 100644 lib/ts/components/assets/linkIcon.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/examples/for-tests/src/App.js b/examples/for-tests/src/App.js index 6273474b2..58b8b2df1 100644 --- a/examples/for-tests/src/App.js +++ b/examples/for-tests/src/App.js @@ -173,7 +173,7 @@ const testContext = getTestContext(); let recipeList = [ MultiFactorAuth.init({ - firstFactors: ["emailpassword", "thirdparty"], + firstFactors: ["otp-phone", "otp-email", "thirdparty"], }), Multitenancy.init({ override: { @@ -871,6 +871,10 @@ function getPasswordlessConfigs({ disableDefaultUI }) { disableDefaultUI, style: theme, }, + mfa: { + disableDefaultUI, + style: theme, + }, }); } diff --git a/lib/build/components/assets/linkIcon.d.ts b/lib/build/components/assets/linkIcon.d.ts deleted file mode 100644 index 35d45fe65..000000000 --- a/lib/build/components/assets/linkIcon.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -export declare const LinkIcon: () => JSX.Element; diff --git a/lib/build/emailpassword-shared6.js b/lib/build/emailpassword-shared6.js index 56d214fab..9a31d6f0a 100644 --- a/lib/build/emailpassword-shared6.js +++ b/lib/build/emailpassword-shared6.js @@ -10,8 +10,8 @@ var React = require("react"); var translations = require("./translations.js"); var translations$1 = require("./emailverification-shared2.js"); var translationContext = require("./translationContext.js"); -var arrowLeftIcon = require("./arrowLeftIcon.js"); var formBase = require("./emailpassword-shared7.js"); +var arrowLeftIcon = require("./arrowLeftIcon.js"); var generalError = require("./emailpassword-shared.js"); var STGeneralError = require("supertokens-web-js/utils/error"); var button = require("./emailpassword-shared2.js"); @@ -56,63 +56,6 @@ 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 HeavyArrowLeftIcon(_a) { - var color = _a.color; - return jsxRuntime.jsx( - "svg", - genericComponentOverrideContext.__assign( - { - 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)", - }), - } - ) - ); -} - -/* - * Component. - */ -function BackButton(_a) { - var onClick = _a.onClick; - return jsxRuntime.jsx( - "button", - genericComponentOverrideContext.__assign( - { onClick: onClick, "data-supertokens": "backButton backButtonCommon" }, - { children: jsxRuntime.jsx(HeavyArrowLeftIcon, { color: "rgb(var(--palette-textTitle))" }) } - ) - ); -} - /* * Component. */ @@ -215,7 +158,9 @@ var EmailPasswordResetPasswordEmail = function (props) { { "data-supertokens": "headerTitle resetPasswordHeaderTitle" }, { children: [ - jsxRuntime.jsx(BackButton, { onClick: props.onBackButtonClicked }), + jsxRuntime.jsx(formBase.BackButton, { + onClick: props.onBackButtonClicked, + }), t("EMAIL_PASSWORD_RESET_HEADER_TITLE"), jsxRuntime.jsx("span", { "data-supertokens": "backButtonPlaceholder backButtonCommon", diff --git a/lib/build/emailpassword-shared7.js b/lib/build/emailpassword-shared7.js index 6415dc169..ba3f5e811 100644 --- a/lib/build/emailpassword-shared7.js +++ b/lib/build/emailpassword-shared7.js @@ -439,6 +439,63 @@ function Label(_a) { ); } +/* 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 HeavyArrowLeftIcon(_a) { + var color = _a.color; + return jsxRuntime.jsx( + "svg", + genericComponentOverrideContext.__assign( + { + 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)", + }), + } + ) + ); +} + +/* + * Component. + */ +function BackButton(_a) { + var onClick = _a.onClick; + return jsxRuntime.jsx( + "button", + genericComponentOverrideContext.__assign( + { onClick: onClick, "data-supertokens": "backButton backButtonCommon" }, + { children: jsxRuntime.jsx(HeavyArrowLeftIcon, { color: "rgb(var(--palette-textTitle))" }) } + ) + ); +} + var FormBase = function (props) { var footer = props.footer, buttonLabel = props.buttonLabel, @@ -768,6 +825,7 @@ var FormBase = function (props) { ); }; +exports.BackButton = BackButton; exports.ErrorIcon = ErrorIcon; exports.FormBase = FormBase; exports.FormRow = FormRow; diff --git a/lib/build/emailpasswordprebuiltui.js b/lib/build/emailpasswordprebuiltui.js index c6277a8b2..e5494d026 100644 --- a/lib/build/emailpasswordprebuiltui.js +++ b/lib/build/emailpasswordprebuiltui.js @@ -30,10 +30,10 @@ require("./session-shared3.js"); require("./session-shared.js"); require("./translations.js"); require("./emailverification-shared2.js"); -require("./arrowLeftIcon.js"); require("./emailpassword-shared7.js"); require("supertokens-web-js/utils/error"); require("./emailpassword-shared2.js"); +require("./arrowLeftIcon.js"); require("./emailpassword-shared.js"); require("./SuperTokensBranding.js"); require("supertokens-web-js/lib/build/error"); diff --git a/lib/build/emailverification-shared2.js b/lib/build/emailverification-shared2.js index 6db26e977..01a454a4d 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="resetPasswordHeaderTitle"] {\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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="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~="resetPasswordHeaderTitle"] {\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 44251fa1e..8a6c1eddd 100644 --- a/lib/build/index2.js +++ b/lib/build/index2.js @@ -303,7 +303,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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/multifactorauthprebuiltui.js b/lib/build/multifactorauthprebuiltui.js index 59f5baa4c..ebb0aedd2 100644 --- a/lib/build/multifactorauthprebuiltui.js +++ b/lib/build/multifactorauthprebuiltui.js @@ -62,7 +62,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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="container"] {\n padding-top: 24px;\n}\n[data-supertokens~="row"] {\n padding-top: 16px;\n padding-bottom: 8px;\n}\n[data-supertokens~="factorChooserList"] {\n padding-top: 4px;\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: 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 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-textSecondary));\n font-size: var(--font-size-0);\n margin: 4px;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n margin-bottom: 32px;\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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="container"] {\n padding-top: 24px;\n}\n[data-supertokens~="row"] {\n padding-top: 16px;\n padding-bottom: 8px;\n}\n[data-supertokens~="factorChooserList"] {\n padding-top: 4px;\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: 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 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-textSecondary));\n font-size: var(--font-size-0);\n margin: 4px;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\n margin-bottom: 32px;\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 f352693b5..d85b31118 100644 --- a/lib/build/passwordless-shared2.js +++ b/lib/build/passwordless-shared2.js @@ -14,27 +14,6 @@ function _interopDefault(e) { var PasswordlessWebJS__default = /*#__PURE__*/ _interopDefault(PasswordlessWebJS); -var LinkIcon = function () { - return jsxRuntime.jsxs( - "svg", - genericComponentOverrideContext.__assign( - { xmlns: "http://www.w3.org/2000/svg", width: "19", height: "16", viewBox: "0 0 19 16", fill: "none" }, - { - children: [ - jsxRuntime.jsx("path", { - d: "M10.9871 11.7876C10.2967 11.7898 9.61895 11.6022 9.0279 11.2453C8.43684 10.8885 7.95517 10.3762 7.63545 9.76427C7.31574 9.15235 7.17027 8.46436 7.21492 7.7754C7.25958 7.08644 7.49264 6.42298 7.88867 5.85745C7.99951 5.70075 8.16806 5.59449 8.35725 5.56206C8.54643 5.52963 8.74075 5.57368 8.89745 5.68452C9.05416 5.79536 9.16042 5.96391 9.19285 6.15309C9.22528 6.34228 9.18123 6.53659 9.07039 6.6933C8.75488 7.13913 8.60843 7.68273 8.65728 8.22672C8.70614 8.77071 8.9471 9.27952 9.337 9.662C9.55327 9.87943 9.81039 10.052 10.0936 10.1697C10.3767 10.2874 10.6804 10.348 10.9871 10.348C11.2938 10.348 11.5974 10.2874 11.8806 10.1697C12.1638 10.052 12.4209 9.87943 12.6372 9.662L16.9605 5.33865C17.3767 4.89673 17.6045 4.31005 17.5954 3.70303C17.5863 3.09602 17.3411 2.51642 16.9118 2.08715C16.4826 1.65788 15.903 1.4127 15.296 1.40362C14.6889 1.39454 14.1023 1.62226 13.6603 2.03849L11.8229 3.87592C11.7557 3.9431 11.676 3.99639 11.5882 4.03275C11.5004 4.06911 11.4063 4.08782 11.3113 4.08782C11.2163 4.08782 11.1222 4.06911 11.0345 4.03275C10.9467 3.99639 10.8669 3.9431 10.7997 3.87592C10.7325 3.80873 10.6793 3.72897 10.6429 3.64119C10.6065 3.55341 10.5878 3.45933 10.5878 3.36432C10.5878 3.26931 10.6065 3.17522 10.6429 3.08744C10.6793 2.99966 10.7325 2.91991 10.7997 2.85272L12.6372 1.0153C13.3543 0.347081 14.3028 -0.0167022 15.2828 0.000589365C16.2628 0.017881 17.1979 0.414897 17.891 1.108C18.5841 1.80109 18.9811 2.73616 18.9984 3.7162C19.0157 4.69623 18.6519 5.64472 17.9837 6.36184L13.6603 10.6852C13.309 11.0356 12.8921 11.3133 12.4334 11.5025C11.9747 11.6916 11.4832 11.7885 10.9871 11.7876Z", - fill: "#1485FF", - }), - jsxRuntime.jsx("path", { - d: "M3.7826 15.3866C3.03483 15.3879 2.3035 15.1672 1.68132 14.7524C1.05914 14.3376 0.574138 13.7474 0.287796 13.0567C0.00145422 12.3659 -0.0733288 11.6057 0.0729281 10.8723C0.219185 10.139 0.579895 9.46563 1.10933 8.93756L5.43268 4.61421C5.78326 4.26285 6.20004 3.9845 6.65891 3.79526C7.11777 3.60603 7.6096 3.50966 8.10595 3.51175C9.10694 3.5154 10.0666 3.91118 10.7792 4.61421C11.4078 5.23969 11.7952 6.06714 11.873 6.95048C11.9508 7.83382 11.7139 8.71624 11.2043 9.44195C11.0935 9.59865 10.925 9.70491 10.7358 9.73734C10.5466 9.76977 10.3523 9.72572 10.1956 9.61488C10.0389 9.50404 9.93261 9.33549 9.90018 9.14631C9.86774 8.95712 9.91179 8.7628 10.0226 8.6061C10.3381 8.16027 10.4846 7.61667 10.4357 7.07268C10.3869 6.52869 10.1459 6.01988 9.75603 5.6374C9.32308 5.18824 8.72968 4.92911 8.10595 4.91684C7.7967 4.92053 7.49134 4.9862 7.20792 5.10997C6.92449 5.23373 6.66877 5.41308 6.45587 5.6374L2.13252 9.96075C1.71629 10.4027 1.48857 10.9894 1.49765 11.5964C1.50673 12.2034 1.75191 12.783 2.18118 13.2122C2.61045 13.6415 3.19005 13.8867 3.79706 13.8958C4.40407 13.9049 4.99075 13.6771 5.43268 13.2609L7.2701 11.4235C7.33729 11.3563 7.41704 11.303 7.50482 11.2666C7.5926 11.2303 7.68669 11.2116 7.7817 11.2116C7.87671 11.2116 7.97079 11.2303 8.05857 11.2666C8.14635 11.303 8.22611 11.3563 8.29329 11.4235C8.36048 11.4907 8.41377 11.5704 8.45013 11.6582C8.48649 11.746 8.5052 11.8401 8.5052 11.9351C8.5052 12.0301 8.48649 12.1242 8.45013 12.212C8.41377 12.2997 8.36048 12.3795 8.29329 12.4467L6.45587 14.2841C6.10457 14.6345 5.68765 14.9122 5.22896 15.1014C4.77026 15.2906 4.27877 15.3875 3.7826 15.3866Z", - fill: "#1485FF", - }), - ], - } - ) - ); -}; - var OTPIcon = function () { return jsxRuntime.jsxs( "svg", @@ -464,6 +443,7 @@ function normalisePasswordlessConfig(config) { validatePhoneNumber: validatePhoneNumber, signInUpFeature: signInUpFeature, linkClickedScreenFeature: normalisePasswordlessBaseConfig(config.linkClickedScreenFeature), + mfaFeature: normalisePasswordlessBaseConfig(config.mfaFeature), contactMethod: config.contactMethod, override: override, } @@ -577,31 +557,31 @@ var Passwordless = /** @class */ (function (_super) { id: "otp-phone", name: "SMS based OTP", description: "Get an OTP code on your phone to complete the authentication request", - path: "/check-auth/otp-phone", + path: "/auth/mfa/otp-phone", logo: OTPIcon, }, - { - id: "link-phone", - name: "SMS based Magic link", - description: "Get a magic link on your phone to complete the authentication request", - path: "/check-auth/link-phone", - logo: LinkIcon, - }, + // { + // id: "link-phone", + // name: "SMS based Magic link", + // description: "Get a magic link on your phone to complete the authentication request", + // path: "/auth/mfa/link-phone", + // logo: LinkIcon, + // }, { id: "otp-email", - name: "SMS based OTP", + name: "Email based OTP", description: "Get an OTP code on your email address to complete the authentication request", - path: "/check-auth/otp-email", + path: "/auth/mfa/otp-email", logo: OTPIcon, }, - { - id: "link-email", - name: "SMS based Magic link", - description: - "Get a magic link on your email address to complete the authentication request", - path: "/check-auth/link-email", - logo: LinkIcon, - }, + // { + // id: "link-email", + // name: "SMS based Magic link", + // description: + // "Get a magic link on your email address to complete the authentication request", + // path: "/auth/mfa/link-email", + // logo: LinkIcon, + // }, ] ); } diff --git a/lib/build/passwordless-shared3.js b/lib/build/passwordless-shared3.js index 8845ee9f2..f89f4c5c4 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-shared3.js"); var componentOverrideContext = require("./passwordless-shared.js"); var React = require("react"); var STGeneralError = require("supertokens-web-js/utils/error"); @@ -12,7 +13,8 @@ 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-shared3.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"); @@ -20,6 +22,7 @@ var checkedRoundIcon = require("./checkedRoundIcon.js"); var formBase = require("./emailpassword-shared7.js"); var validators = require("./emailpassword-shared5.js"); var arrowLeftIcon = require("./arrowLeftIcon.js"); +var multifactorauth = require("./multifactorauth.js"); function _interopDefault(e) { return e && e.__esModule ? e : { default: e }; @@ -56,7 +59,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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="resetPasswordHeaderTitle"] {\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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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/* 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~="resetPasswordHeaderTitle"] {\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 +225,11 @@ 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", /* * 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 +577,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 +637,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, + }), }); }); @@ -2743,79 +2755,1422 @@ 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 [ + 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"); + } + if (response.status === "OK") { + setClearResendNotifTimeout( + setTimeout(function () { + setClearResendNotifTimeout(undefined); + }, 2000) + ); + } + } + return [3 /*break*/, 6]; + case 5: + _a.sent(); + props.onError("SOMETHING_WENT_WRONG_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: [ + { + 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]; + } + 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(jsxRuntime.Fragment, { + 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 secondaryLinkWithLeftArrow", + onClick: function () { + return props.onFactorChooserButtonClicked; + }, + }, + { children: t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER") } + ) + ), + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { + "data-supertokens": "secondaryText secondaryLinkWithLeftArrow", + onClick: function () { + return props.onSignOutClicked; + }, + }, + { + children: [ + jsxRuntime.jsx(arrowLeftIcon.ArrowLeftIcon, { color: "rgb(var(--palette-textPrimary))" }), + t("PWLESS_MFA_FOOTER_LOGOUT"), + ], + } + ) + ), + ], + }); +}); + +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 resetPasswordHeaderTitle" }, + { + children: [ + claim.loading === false && + ((_a = claim.value) === null || _a === void 0 ? void 0 : _a.n.length) === 0 + ? jsxRuntime.jsx(formBase.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 loginAttemptInfo = _a.loginAttemptInfo, + recipeImplementation = _a.recipeImplementation, + onSignOutClicked = _a.onSignOutClicked, + isSetupAllowed = _a.isSetupAllowed; + var t = translationContext.useTranslation(); + var userContext = uiEntry.useUserContext(); + return jsxRuntime.jsx(React.Fragment, { + children: + (isSetupAllowed && + 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"), + ], + } + ) + )) || + 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 MFAOTPHeader = uiEntry.withOverride("PasswordlessMFAOTPHeader", function PasswordlessMFAOTPHeader(_a) { + var _b; + var loginAttemptInfo = _a.loginAttemptInfo, + onBackButtonClicked = _a.onBackButtonClicked, + isSetupAllowed = _a.isSetupAllowed; + var t = translationContext.useTranslation(); + var claim = session.useClaimValue(multifactorauth.MultiFactorAuthClaim); + return jsxRuntime.jsxs(React.Fragment, { + children: [ + jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "headerTitle resetPasswordHeaderTitle" }, + { + children: [ + claim.loading === false && + ((_b = claim.value) === null || _b === void 0 ? void 0 : _b.n.length) === 0 && + isSetupAllowed === false + ? jsxRuntime.jsx(formBase.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 = {})); +/* + * Component. + */ +var MFATheme = function (_a) { + var activeScreen = _a.activeScreen, + featureState = _a.featureState, + onBackButtonClicked = _a.onBackButtonClicked, + props = genericComponentOverrideContext.__rest(_a, ["activeScreen", "featureState", "onBackButtonClicked"]); + var commonProps = { + recipeImplementation: props.recipeImplementation, + config: props.config, + clearError: function () { + return props.dispatch({ type: "setError", error: undefined }); + }, + onError: function (error) { + return props.dispatch({ type: "setError", error: error }); + }, + error: featureState.error, + }; + return activeScreen === MFAScreens.CloseTab + ? jsxRuntime.jsx(CloseTabScreen, genericComponentOverrideContext.__assign({}, commonProps)) + : jsxRuntime.jsxs( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "container" }, + { + children: [ + jsxRuntime.jsx( + "div", + genericComponentOverrideContext.__assign( + { "data-supertokens": "row" }, + { + children: + featureState.loaded && + /* TODO: this doesn't feel great */ (featureState.isSetupAllowed === true || + featureState.loginAttemptInfo !== undefined) && + jsxRuntime.jsxs(React__namespace.default.Fragment, { + children: [ + activeScreen === MFAScreens.UserInputCodeForm + ? jsxRuntime.jsx( + MFAOTPHeader, + genericComponentOverrideContext.__assign({}, commonProps, { + loginAttemptInfo: featureState.loginAttemptInfo, + isSetupAllowed: featureState.isSetupAllowed, + onBackButtonClicked: function () { + return props.recipeImplementation.clearLoginAttemptInfo( + { + userContext: props.userContext, + } + ); + }, + }) + ) + : 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; + } + return jsxRuntime.jsx( + uiEntry.UserContextWrapper, + genericComponentOverrideContext.__assign( + { userContext: props.userContext }, + { + children: jsxRuntime.jsx( + ThemeBase, + genericComponentOverrideContext.__assign( + { loadDefaultFont: !hasFont, userStyles: [props.config.rootStyle, activeStyle] }, + { + children: jsxRuntime.jsx( + MFATheme, + genericComponentOverrideContext.__assign({}, props, { activeScreen: activeScreen }) + ), + } + ) + ), + } + ) + ); +} +function getActiveScreen$1(props) { + if (props.featureState.successInAnotherTab) { + return MFAScreens.CloseTab; + } 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), + { error: action.error } + ); + case "startLogin": + 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"); + var messageQueryParam = genericComponentOverrideContext.getQueryParams("message"); + if (errorQueryParam !== null) { + if (errorQueryParam === "signin") { + error = "SOMETHING_WENT_WRONG_ERROR"; + } else if (errorQueryParam === "restart_link") { + error = "ERROR_SIGN_IN_UP_LINK"; + } else if (errorQueryParam === "custom" && messageQueryParam !== null) { + error = messageQueryParam; + } + } + 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 () { + if (!recipe$1 || !recipeImplementation) { + return undefined; + } + return { + onSuccess: function () { + return recipe.Session.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( + undefined, + 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(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); + React.useEffect( + function () { + if (state.loaded && state.isSetupAllowed === false && state.loginAttemptInfo === undefined) { + void recipe$2.MultiFactorAuth.getInstanceOrThrow().redirectToFactorChooser(); + } + }, + [state.loaded, state.isSetupAllowed, state.loginAttemptInfo] + ); + 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, + }), + ]; + }); + }); + }, + [props.recipe, userContext] + ); + var handleLoadError = React__namespace.useCallback( + // Test this, it may show an empty screen in many cases + function () { + return dispatch({ type: "setError", error: "Getting mfaInfo failed!" }); + }, + [dispatch] + ); // TODO: translation/proper error handling) + var onLoad = React__namespace.useCallback( + function (mfaInfo) { + return genericComponentOverrideContext.__awaiter(_this, void 0, void 0, function () { + var error, + errorQueryParam, + messageQueryParam, + doSetup, + loginAttemptInfo, + isAlreadySetup, + isAllowedToSetup; + return genericComponentOverrideContext.__generator(this, function (_a) { + switch (_a.label) { + case 0: + error = undefined; + errorQueryParam = genericComponentOverrideContext.getQueryParams("error"); + messageQueryParam = genericComponentOverrideContext.getQueryParams("message"); + doSetup = genericComponentOverrideContext.getQueryParams("setup"); + if (errorQueryParam !== null) { + if (errorQueryParam === "signin") { + error = "SOMETHING_WENT_WRONG_ERROR"; + } else if (errorQueryParam === "restart_link") { + error = "ERROR_SIGN_IN_UP_LINK"; + } else if (errorQueryParam === "custom" && messageQueryParam !== null) { + error = messageQueryParam; + } + } + 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*/, 9]; + if (!(props.contactMethod === "EMAIL")) return [3 /*break*/, 5]; + if (!(isAlreadySetup && doSetup !== "true")) return [3 /*break*/, 3]; + // createCode also dispatches the necessary events + return [ + 4 /*yield*/, + recipeImplementation.createCode({ + email: mfaInfo.email, + userContext: userContext, + }), + ]; + case 2: + // createCode also dispatches the necessary events + _a.sent(); + return [3 /*break*/, 4]; + case 3: + if (!mfaInfo.factors.isAllowedToSetup.includes("otp-email")) { + dispatch({ type: "setError", error: "Factor not enabled" }); // TODO: translation + } else { + dispatch({ + type: "load", + loginAttemptInfo: loginAttemptInfo, + error: error, + isAllowedToSetup: true, + }); // since loginAttemptInfo is undefined, this will ask the user for the email + } + _a.label = 4; + case 4: + return [3 /*break*/, 8]; + case 5: + if (!(isAlreadySetup && doSetup !== "true")) return [3 /*break*/, 7]; + // createCode also dispatches the necessary events + return [ + 4 /*yield*/, + recipeImplementation.createCode({ + phoneNumber: mfaInfo.phoneNumber, + userContext: userContext, + }), + ]; + case 6: + // createCode also dispatches the necessary events + _a.sent(); + return [3 /*break*/, 8]; + case 7: + if (!mfaInfo.factors.isAllowedToSetup.includes("otp-phone")) { + dispatch({ type: "setError", error: "Factor not enabled" }); // TODO: translation + } else { + dispatch({ + type: "load", + loginAttemptInfo: loginAttemptInfo, + error: error, + isAllowedToSetup: true, + }); // since loginAttemptInfo is undefined, this will ask the user for the phone number + } + _a.label = 8; + case 8: + return [3 /*break*/, 10]; + case 9: + // 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 = 10; + case 10: + 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: "startLogin", 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 call consume code while callingConsume, so we don't detect + // the session creation 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]; + return [ + 4 /*yield*/, + originalImpl.clearLoginAttemptInfo({ + userContext: input.userContext, + }), + ]; + case 4: + _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, @@ -2909,10 +4264,13 @@ var EmailOrPhoneForm = uiEntry.withOverride( }, 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, + }), }); } ); @@ -3085,470 +4443,97 @@ function SMSLargeIcon() { 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", + transform: "translate(725.5 260.17)", + d: "M0 0h12.461", }), jsxRuntime.jsx("path", { - id: "Line_101", - "data-name": "Line 101", + id: "Line_102", + "data-name": "Line 102", strokeWidth: "1.75px", fill: "none", strokeLinecap: "round", stroke: "#fff", - transform: "translate(725.5 255.25)", - d: "M0 0h9.872", + transform: "translate(725.5 261.92)", + d: "M0 0h12.461", }), ], } ) ), - ], - } - ) - ), - } - ) - ), - } - ) - ); -} - -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 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 () { - 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*/]; - } - }); - }); - }, - [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" }, - { - 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", - 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"), - ], - } - ) - ), - 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"), - ], - } - ) - ), - ], + 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; @@ -3572,141 +4557,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", @@ -3843,7 +4836,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; @@ -3879,19 +4873,48 @@ function SignInUpThemeWrapper(props) { ) ); } -function getActiveScreen(props) { +function getActiveScreen(props, currentDynamicLoginMethods) { + var _a; + var contactMethod = props.config.contactMethod; + 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$2.MultiFactorAuth.getInstance()) === null || _a === void 0 ? void 0 : _a.getFirstFactors(); + } + if (firstFactors !== undefined) { + if (enabledContactMethods.includes("PHONE")) { + if (!firstFactors.includes("otp-phone") && !firstFactors.includes("link-phone")) { + enabledContactMethods = enabledContactMethods.filter(function (c) { + return c !== "PHONE"; + }); + } + } + if (enabledContactMethods.includes("EMAIL")) { + if (!firstFactors.includes("otp-email") && !firstFactors.includes("link-email")) { + enabledContactMethods = enabledContactMethods.filter(function (c) { + return c !== "EMAIL"; + }); + } + } + } + if (enabledContactMethods.length === 0) { + throw new Error("No overlap between first factors and enabled contact methods"); // redirect to access denied? + } 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"); } @@ -4382,6 +5405,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) { @@ -4449,9 +5498,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; } diff --git a/lib/build/passwordlessprebuiltui.js b/lib/build/passwordlessprebuiltui.js index a434bb49d..c37865774 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-shared3.js"); require("./passwordless-shared.js"); var passwordlessprebuiltui = require("./passwordless-shared3.js"); require("./passwordless-shared2.js"); @@ -25,7 +26,6 @@ require("supertokens-web-js/utils/sessionClaimValidatorStore"); require("./recipeModule-shared.js"); require("./session-shared2.js"); require("supertokens-web-js/recipe/session"); -require("./session-shared3.js"); require("./session-shared.js"); require("supertokens-web-js/utils/error"); require("./translations.js"); @@ -36,6 +36,8 @@ require("./checkedRoundIcon.js"); require("./emailpassword-shared7.js"); require("./emailpassword-shared5.js"); require("./arrowLeftIcon.js"); +require("./multifactorauth.js"); +require("./multifactorauth-shared2.js"); require("supertokens-web-js/recipe/passwordless"); require("./authRecipe-shared.js"); diff --git a/lib/build/recipe/passwordless/components/features/mfa/index.d.ts b/lib/build/recipe/passwordless/components/features/mfa/index.d.ts index 02b7a8daa..a408f8cad 100644 --- a/lib/build/recipe/passwordless/components/features/mfa/index.d.ts +++ b/lib/build/recipe/passwordless/components/features/mfa/index.d.ts @@ -1,38 +1,40 @@ import * as React from "react"; import type { FeatureBaseProps } from "../../../../../types"; import type Recipe from "../../../recipe"; -import type { ComponentOverrideMap } from "../../../types"; -import type { PasswordlessSignInUpAction, SignInUpState, SignInUpChildProps } from "../../../types"; +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: ( - state: SignInUpState, - dispatch: React.Dispatch, - userContext: any -) => React.MutableRefObject; -export declare const useFeatureReducer: ( - recipeImpl: RecipeInterface | undefined, + callingConsumeCodeRef: React.MutableRefObject, + recipeImpl: RecipeInterface, + state: MFAState, + dispatch: React.Dispatch, userContext: any -) => [SignInUpState, React.Dispatch]; +) => void; +export declare const useFeatureReducer: () => [MFAState, React.Dispatch]; export declare function useChildProps( recipe: Recipe, - dispatch: React.Dispatch, - state: SignInUpState, - callingConsumeCodeRef: React.MutableRefObject, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", userContext: any, history: any -): SignInUpChildProps; +): MFAChildProps; export declare function useChildProps( recipe: Recipe | undefined, - dispatch: React.Dispatch, - state: SignInUpState, - callingConsumeCodeRef: React.MutableRefObject, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", userContext: any, history: any -): SignInUpChildProps | undefined; -export declare const SignInUpFeature: React.FC< +): MFAChildProps | undefined; +export declare const MFAFeature: React.FC< FeatureBaseProps & { + contactMethod: "PHONE" | "EMAIL"; + flowType: PasswordlessFlowType; recipe: Recipe; useComponentOverrides: () => ComponentOverrideMap; } >; -export default SignInUpFeature; +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..78c70fdbf --- /dev/null +++ b/lib/build/recipe/passwordless/components/themes/mfa/index.d.ts @@ -0,0 +1,11 @@ +/// +import type { MFAProps } from "../../../types"; +export declare enum MFAScreens { + CloseTab = 0, + EmailForm = 1, + PhoneForm = 2, + UserInputCodeForm = 3, +} +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..68e12c3a3 100644 --- a/lib/build/recipe/passwordless/components/themes/translations.d.ts +++ b/lib/build/recipe/passwordless/components/themes/translations.d.ts @@ -52,6 +52,11 @@ 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; "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..d278feb79 100644 --- a/lib/build/recipe/passwordless/prebuiltui.d.ts +++ b/lib/build/recipe/passwordless/prebuiltui.d.ts @@ -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; diff --git a/lib/build/recipe/passwordless/types.d.ts b/lib/build/recipe/passwordless/types.d.ts index 617b38663..e8e91a30f 100644 --- a/lib/build/recipe/passwordless/types.d.ts +++ b/lib/build/recipe/passwordless/types.d.ts @@ -70,6 +70,7 @@ export declare type NormalisedConfig = { disableDefaultUI?: boolean; }; linkClickedScreenFeature: PasswordlessNormalisedBaseConfig; + mfaFeature: PasswordlessNormalisedBaseConfig; contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE"; override: { functions: (originalImplementation: RecipeInterface) => RecipeInterface; @@ -120,7 +121,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 +252,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: "startLogin"; + 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 +305,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; diff --git a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts index b24b59e60..8afcc48ec 100644 --- a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts @@ -54,6 +54,11 @@ 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; "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/sessionprebuiltui.js b/lib/build/sessionprebuiltui.js index 229b076ee..f5a76e021 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="row"] {\n padding-top: 32px;\n padding-bottom: 32px;\n}\n\n[data-supertokens~="divider"] {\n padding: 0;\n margin: 24px 0;\n}\n\n[data-supertokens~="headerTitle"] {\n padding-top: 24px;\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 display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n[data-supertokens~="buttonBase"] {\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'; + '/* 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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/* Override */\n\n[data-supertokens~="row"] {\n padding-top: 32px;\n padding-bottom: 32px;\n}\n\n[data-supertokens~="divider"] {\n padding: 0;\n margin: 24px 0;\n}\n\n[data-supertokens~="headerTitle"] {\n padding-top: 24px;\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 display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n[data-supertokens~="buttonBase"] {\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'; var ThemeBase = function (_a) { var children = _a.children, diff --git a/lib/build/thirdparty-shared2.js b/lib/build/thirdparty-shared2.js index 0d772b125..5be91439b 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="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 4549fc704..21f6ef4ff 100644 --- a/lib/build/thirdpartyemailpasswordprebuiltui.js +++ b/lib/build/thirdpartyemailpasswordprebuiltui.js @@ -32,11 +32,11 @@ require("./session-shared3.js"); require("./session-shared.js"); require("./emailpassword-shared3.js"); require("./emailverification-shared2.js"); -require("./arrowLeftIcon.js"); require("./emailpassword-shared7.js"); require("supertokens-web-js/utils/error"); require("./emailpassword-shared5.js"); require("./emailpassword-shared2.js"); +require("./arrowLeftIcon.js"); require("supertokens-web-js/lib/build/error"); require("./emailpassword-shared4.js"); require("supertokens-web-js/recipe/emailpassword"); @@ -80,7 +80,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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="resetPasswordHeaderTitle"] {\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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="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~="resetPasswordHeaderTitle"] {\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/thirdpartypasswordlessprebuiltui.js b/lib/build/thirdpartypasswordlessprebuiltui.js index 6ba76b277..82c6ed35e 100644 --- a/lib/build/thirdpartypasswordlessprebuiltui.js +++ b/lib/build/thirdpartypasswordlessprebuiltui.js @@ -40,6 +40,8 @@ require("./checkedRoundIcon.js"); require("./emailpassword-shared7.js"); require("./emailpassword-shared5.js"); require("./arrowLeftIcon.js"); +require("./multifactorauth.js"); +require("./multifactorauth-shared2.js"); require("./thirdparty-shared.js"); require("supertokens-web-js/recipe/thirdparty"); require("supertokens-web-js/lib/build/normalisedURLPath"); @@ -79,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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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~="resetPasswordHeaderTitle"] {\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: 300;\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: 800;\n margin-bottom: 2px;\n color: rgb(var(--palette-textTitle));\n}\n[data-supertokens~="headerSubtitle"] {\n margin-bottom: 21px;\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 background-color: transparent;\n border: 0;\n}\n[data-supertokens~="secondaryLinkWithLeftArrow"] {\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 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/* 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~="resetPasswordHeaderTitle"] {\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, @@ -287,14 +289,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, }) diff --git a/lib/ts/components/assets/linkIcon.tsx b/lib/ts/components/assets/linkIcon.tsx deleted file mode 100644 index 6815ac02c..000000000 --- a/lib/ts/components/assets/linkIcon.tsx +++ /dev/null @@ -1,12 +0,0 @@ -export const LinkIcon = () => ( - - - - -); diff --git a/lib/ts/recipe/emailpassword/components/themes/styles.css b/lib/ts/recipe/emailpassword/components/themes/styles.css index 3e617c4bf..d53e036d8 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/passwordless/components/features/mfa/index.tsx b/lib/ts/recipe/passwordless/components/features/mfa/index.tsx index 49eb6f92f..7c2d9504d 100644 --- a/lib/ts/recipe/passwordless/components/features/mfa/index.tsx +++ b/lib/ts/recipe/passwordless/components/features/mfa/index.tsx @@ -20,40 +20,49 @@ 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 } from "../../../../../utils"; -import Session from "../../../../session"; +import { + clearErrorQueryParam, + getQueryParams, + getRedirectToPathFromURL, + useOnMountAPICall, +} from "../../../../../utils"; +import MultiFactorAuth from "../../../../multifactorauth/recipe"; import SessionRecipe from "../../../../session/recipe"; import { getPhoneNumberUtils } from "../../../phoneNumberUtils"; -import SignInUpThemeWrapper from "../../themes/signInUp"; +import MFAThemeWrapper from "../../themes/mfa"; import { defaultTranslationsPasswordless } from "../../themes/translations"; import type { FeatureBaseProps } from "../../../../../types"; import type Recipe from "../../../recipe"; -import type { AdditionalLoginAttemptInfoProperties, ComponentOverrideMap } from "../../../types"; -import type { PasswordlessSignInUpAction, SignInUpState, SignInUpChildProps, NormalisedConfig } from "../../../types"; +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 { User } from "supertokens-web-js/types"; +import type { PasswordlessFlowType } from "supertokens-web-js/recipe/thirdpartypasswordless"; export const useSuccessInAnotherTabChecker = ( - state: SignInUpState, - dispatch: React.Dispatch, + callingConsumeCodeRef: React.MutableRefObject, + recipeImpl: RecipeInterface, + state: MFAState, + dispatch: React.Dispatch, userContext: any ) => { - const callingConsumeCodeRef = useRef(false); - 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 hasSession = await Session.doesSessionExist({ - userContext, - }); - if (hasSession) { + const currLoginAttempt = await recipeImpl.getLoginAttemptInfo({ userContext }); + if ( + currLoginAttempt === undefined || + currLoginAttempt.deviceId !== state.loginAttemptInfo?.deviceId + ) { dispatch({ type: "successInAnotherTab" }); } } @@ -66,22 +75,18 @@ export const useSuccessInAnotherTabChecker = ( // Nothing to clean up return; }, [state.loginAttemptInfo, state.successInAnotherTab]); - - return callingConsumeCodeRef; }; -export const useFeatureReducer = ( - recipeImpl: RecipeInterface | undefined, - userContext: any -): [SignInUpState, React.Dispatch] => { - const [state, dispatch] = React.useReducer( - (oldState: SignInUpState, action: PasswordlessSignInUpAction) => { +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": @@ -110,8 +115,10 @@ export const useFeatureReducer = ( case "startLogin": return { ...oldState, + loaded: true, loginAttemptInfo: action.loginAttemptInfo, error: undefined, + successInAnotherTab: false, }; case "successInAnotherTab": return { @@ -126,6 +133,7 @@ export const useFeatureReducer = ( error: undefined, loaded: false, loginAttemptInfo: undefined, + isSetupAllowed: false, successInAnotherTab: false, }, (initArg) => { @@ -147,106 +155,115 @@ export const useFeatureReducer = ( }; } ); - useEffect(() => { - if (recipeImpl === undefined) { - return; - } - async function load() { - let error: string | undefined = undefined; - const errorQueryParam = getQueryParams("error"); - const messageQueryParam = getQueryParams("message"); - if (errorQueryParam !== null) { - if (errorQueryParam === "signin") { - error = "SOMETHING_WENT_WRONG_ERROR"; - } else if (errorQueryParam === "restart_link") { - error = "ERROR_SIGN_IN_UP_LINK"; - } else if (errorQueryParam === "custom" && messageQueryParam !== null) { - error = messageQueryParam; - } - } - const loginAttemptInfo = await recipeImpl?.getLoginAttemptInfo({ - userContext, - }); - // No need to check if the component is unmounting, since this has no effect then. - dispatch({ type: "load", loginAttemptInfo, error }); - } - if (state.loaded === false) { - void load(); - } - }, [state.loaded, recipeImpl, userContext]); - return [state, dispatch]; }; // We are overloading to explicitly state that if recipe is defined then the return value is defined as well. export function useChildProps( recipe: Recipe, - dispatch: React.Dispatch, - state: SignInUpState, - callingConsumeCodeRef: React.MutableRefObject, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", userContext: any, history: any -): SignInUpChildProps; +): MFAChildProps; export function useChildProps( recipe: Recipe | undefined, - dispatch: React.Dispatch, - state: SignInUpState, - callingConsumeCodeRef: React.MutableRefObject, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", userContext: any, history: any -): SignInUpChildProps | undefined; +): MFAChildProps | undefined; export function useChildProps( recipe: Recipe | undefined, - dispatch: React.Dispatch, - state: SignInUpState, - callingConsumeCodeRef: React.MutableRefObject, + recipeImplementation: RecipeInterface, + state: MFAState, + contactMethod: "PHONE" | "EMAIL", userContext: any, history: any -): SignInUpChildProps | undefined { - const recipeImplementation = React.useMemo( - () => - recipe && - getModifiedRecipeImplementation(recipe.webJSRecipe, recipe.config, dispatch, callingConsumeCodeRef), - [recipe] - ); - +): MFAChildProps | undefined { return useMemo(() => { if (!recipe || !recipeImplementation) { return undefined; } return { - onSuccess: (result: { createdNewRecipeUser: boolean; user: User }) => { + onSuccess: () => { return SessionRecipe.getInstanceOrThrow().validateGlobalClaimsAndHandleSuccessRedirection( - { - rid: recipe.config.recipeId, - successRedirectContext: { - action: "SUCCESS", - isNewRecipeUser: result.createdNewRecipeUser, - user: result.user, - redirectToPath: getRedirectToPathFromURL(), - }, - }, + undefined, 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(history); + }, recipeImplementation: recipeImplementation, config: recipe.config, + contactMethod, }; - }, [state, recipeImplementation]); + }, [contactMethod, state, recipeImplementation]); } -export const SignInUpFeature: React.FC< +export const MFAFeature: React.FC< FeatureBaseProps & { + contactMethod: "PHONE" | "EMAIL"; + flowType: PasswordlessFlowType; recipe: Recipe; useComponentOverrides: () => ComponentOverrideMap; } > = (props) => { const recipeComponentOverrides = props.useComponentOverrides(); const userContext = useUserContext(); - const [state, dispatch] = useFeatureReducer(props.recipe.webJSRecipe, userContext); - const callingConsumeCodeRef = useSuccessInAnotherTabChecker(state, dispatch, userContext); - const childProps = useChildProps(props.recipe, dispatch, state, callingConsumeCodeRef, userContext, props.history)!; + + 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); + + useEffect(() => { + if (state.loaded && state.isSetupAllowed === false && state.loginAttemptInfo === undefined) { + void MultiFactorAuth.getInstanceOrThrow().redirectToFactorChooser(); + } + }, [state.loaded, state.isSetupAllowed, state.loginAttemptInfo]); return ( @@ -256,7 +273,7 @@ export const SignInUpFeature: React.FC< {/* No custom theme, use default. */} {props.children === undefined && ( - + )} {/* Otherwise, custom theme is provided, propagate props. */} @@ -277,12 +294,100 @@ export const SignInUpFeature: React.FC< ); }; -export default SignInUpFeature; +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 }), + [props.recipe, userContext] + ); + const handleLoadError = React.useCallback( + // Test this, it may show an empty screen in many cases + () => dispatch({ type: "setError", error: "Getting mfaInfo failed!" }), + [dispatch] + ); // TODO: translation/proper error handling) + const onLoad = React.useCallback( + async (mfaInfo: { factors: MFAFactorInfo; email?: string; phoneNumber?: string }) => { + let error: string | undefined = undefined; + const errorQueryParam = getQueryParams("error"); + const messageQueryParam = getQueryParams("message"); + const doSetup = getQueryParams("setup"); + if (errorQueryParam !== null) { + if (errorQueryParam === "signin") { + error = "SOMETHING_WENT_WRONG_ERROR"; + } else if (errorQueryParam === "restart_link") { + error = "ERROR_SIGN_IN_UP_LINK"; + } else if (errorQueryParam === "custom" && messageQueryParam !== null) { + error = messageQueryParam; + } + } + 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) { + if (props.contactMethod === "EMAIL") { + if (isAlreadySetup && doSetup !== "true") { + // createCode also dispatches the necessary events + await recipeImplementation!.createCode({ + email: mfaInfo.email!, // We can assume this is set here, since the mfaInfo states that otp-email has been set up + userContext, + }); + } else if (!mfaInfo.factors.isAllowedToSetup.includes("otp-email")) { + dispatch({ type: "setError", error: "Factor not enabled" }); // TODO: translation + } else { + dispatch({ type: "load", loginAttemptInfo, error, isAllowedToSetup: true }); // since loginAttemptInfo is undefined, this will ask the user for the email + } + } else { + if (isAlreadySetup && doSetup !== "true") { + // createCode also dispatches the necessary events + await recipeImplementation!.createCode({ + phoneNumber: mfaInfo.phoneNumber!, // We can assume this is set here, since the mfaInfo states that otp-phone has been set up + userContext, + }); + } else if (!mfaInfo.factors.isAllowedToSetup.includes("otp-phone")) { + dispatch({ type: "setError", error: "Factor not enabled" }); // TODO: translation + } else { + dispatch({ type: "load", loginAttemptInfo, error, isAllowedToSetup: true }); // since loginAttemptInfo is undefined, this will ask the user for the phone number + } + } + } 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, + dispatch: React.Dispatch, callingConsumeCodeRef: React.MutableRefObject ): RecipeInterface { return { @@ -314,6 +419,7 @@ function getModifiedRecipeImplementation( ...input, userContext: { ...input.userContext, additionalAttemptInfo }, }); + if (res.status === "OK") { const loginAttemptInfo = (await originalImpl.getLoginAttemptInfo({ userContext: input.userContext, 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..66ef03637 --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/index.tsx @@ -0,0 +1,175 @@ +/* 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 { SuperTokensBranding } from "../../../../../components/SuperTokensBranding"; +import { hasFontDefined } from "../../../../../styles/styles"; +import UserContextWrapper from "../../../../../usercontext/userContextWrapper"; +import GeneralError from "../../../../emailpassword/components/library/generalError"; +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, +} + +/* + * Component. + */ +const MFATheme: React.FC = ({ + activeScreen, + featureState, + onBackButtonClicked, + ...props +}) => { + 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, + }; + + return activeScreen === MFAScreens.CloseTab ? ( + + ) : ( +
+
+ {featureState.loaded && + /* TODO: this doesn't feel great */ (featureState.isSetupAllowed === true || + featureState.loginAttemptInfo !== undefined) && ( + + {activeScreen === MFAScreens.UserInputCodeForm ? ( + + props.recipeImplementation.clearLoginAttemptInfo({ + userContext: props.userContext, + }) + } + /> + ) : ( + + )} + {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; + } + + return ( + + + + + + ); +} + +export default MFAThemeWrapper; + +export function getActiveScreen(props: Pick) { + if (props.featureState.successInAnotherTab) { + return MFAScreens.CloseTab; + } 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..a575a021d --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaFooter.tsx @@ -0,0 +1,46 @@ +/* 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 && ( +
props.onFactorChooserButtonClicked}> + {t("PWLESS_MFA_FOOTER_CHOOSER_ANOTHER")} +
+ )} +
props.onSignOutClicked}> + + {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..5156fc3be --- /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..dcf63a9b3 --- /dev/null +++ b/lib/ts/recipe/passwordless/components/themes/mfa/mfaOTPFooter.tsx @@ -0,0 +1,59 @@ +/* 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 ArrowLeftIcon from "../../../../../components/assets/arrowLeftIcon"; +import { withOverride } from "../../../../../components/componentOverride/withOverride"; +import { useTranslation } from "../../../../../translation/translationContext"; +import { useUserContext } from "../../../../../usercontext"; + +import type { MFAOTPFooterProps } from "../../../types"; + +export const MFAOTPFooter = withOverride( + "PasswordlessMFAOTPFooter", + function PasswordlessMFAOTPFooter({ + loginAttemptInfo, + recipeImplementation, + onSignOutClicked, + isSetupAllowed, + }: MFAOTPFooterProps): JSX.Element { + const t = useTranslation(); + 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")} +
+ )) || ( +
+ + {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..baac35657 --- /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..deaf38515 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 MultiFactorAuth from "../../../../multifactorauth/recipe"; +import { useDynamicLoginMethods } from "../../../../multitenancy/dynamicLoginMethodsContext"; 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,49 @@ function SignInUpThemeWrapper(props: SignInUpProps): JSX.Element { export default SignInUpThemeWrapper; -export function getActiveScreen(props: Pick) { +export function getActiveScreen( + props: Pick, + currentDynamicLoginMethods: DynamicLoginMethodsContextValue +) { + const contactMethod = props.config.contactMethod; + 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()?.getFirstFactors(); + } + + if (firstFactors !== undefined) { + if (enabledContactMethods.includes("PHONE")) { + if (!firstFactors.includes("otp-phone") && !firstFactors.includes("link-phone")) { + enabledContactMethods = enabledContactMethods.filter((c) => c !== "PHONE"); + } + } + if (enabledContactMethods.includes("EMAIL")) { + if (!firstFactors.includes("otp-email") && !firstFactors.includes("link-email")) { + enabledContactMethods = enabledContactMethods.filter((c) => c !== "EMAIL"); + } + } + } + + if (enabledContactMethods.length === 0) { + throw new Error("No overlap between first factors and enabled contact methods"); // redirect to access denied? + } + 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..b57509954 100644 --- a/lib/ts/recipe/passwordless/components/themes/translations.ts +++ b/lib/ts/recipe/passwordless/components/themes/translations.ts @@ -71,6 +71,11 @@ 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", /* * 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..e76afb17d 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"; @@ -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 diff --git a/lib/ts/recipe/passwordless/recipe.tsx b/lib/ts/recipe/passwordless/recipe.tsx index c070bd1ad..613c27ec4 100644 --- a/lib/ts/recipe/passwordless/recipe.tsx +++ b/lib/ts/recipe/passwordless/recipe.tsx @@ -20,7 +20,7 @@ import PasswordlessWebJS from "supertokens-web-js/recipe/passwordless"; import { PostSuperTokensInitCallbacks } from "supertokens-web-js/utils/postSuperTokensInitCallbacks"; -import { LinkIcon } from "../../components/assets/linkIcon"; +// import { LinkIcon } from "../../components/assets/linkIcon"; import { OTPIcon } from "../../components/assets/otpIcon"; import { SSR_ERROR } from "../../constants"; import { isTest } from "../../utils"; @@ -81,31 +81,31 @@ export default class Passwordless extends AuthRecipe< id: "otp-phone", name: "SMS based OTP", description: "Get an OTP code on your phone to complete the authentication request", - path: "/check-auth/otp-phone", + path: "/auth/mfa/otp-phone", // TODO: websitebasepath logo: OTPIcon, }, - { - id: "link-phone", - name: "SMS based Magic link", - description: "Get a magic link on your phone to complete the authentication request", - path: "/check-auth/link-phone", - logo: LinkIcon, - }, + // { + // id: "link-phone", + // name: "SMS based Magic link", + // description: "Get a magic link on your phone to complete the authentication request", + // path: "/auth/mfa/link-phone", + // logo: LinkIcon, + // }, { id: "otp-email", - name: "SMS based OTP", + name: "Email based OTP", description: "Get an OTP code on your email address to complete the authentication request", - path: "/check-auth/otp-email", + path: "/auth/mfa/otp-email", // TODO: websitebasepath logo: OTPIcon, }, - { - id: "link-email", - name: "SMS based Magic link", - description: - "Get a magic link on your email address to complete the authentication request", - path: "/check-auth/link-email", - logo: LinkIcon, - }, + // { + // id: "link-email", + // name: "SMS based Magic link", + // description: + // "Get a magic link on your email address to complete the authentication request", + // path: "/auth/mfa/link-email", + // logo: LinkIcon, + // }, ] ); } diff --git a/lib/ts/recipe/passwordless/types.ts b/lib/ts/recipe/passwordless/types.ts index bd78c63ce..69c547ac7 100644 --- a/lib/ts/recipe/passwordless/types.ts +++ b/lib/ts/recipe/passwordless/types.ts @@ -106,6 +106,7 @@ export type NormalisedConfig = { disableDefaultUI?: boolean; }; linkClickedScreenFeature: PasswordlessNormalisedBaseConfig; + mfaFeature: PasswordlessNormalisedBaseConfig; contactMethod: "PHONE" | "EMAIL" | "EMAIL_OR_PHONE"; @@ -183,8 +184,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 +327,42 @@ export type SignInUpState = { successInAnotherTab: boolean; }; +export type MFAAction = + | { + type: "load"; + loginAttemptInfo: LoginAttemptInfo | undefined; + isAllowedToSetup: boolean; + error: string | undefined; + } + | { + type: "startLogin"; + 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 +385,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; diff --git a/lib/ts/recipe/passwordless/utils.ts b/lib/ts/recipe/passwordless/utils.ts index d1bc38892..cc5d40eeb 100644 --- a/lib/ts/recipe/passwordless/utils.ts +++ b/lib/ts/recipe/passwordless/utils.ts @@ -71,6 +71,7 @@ export function normalisePasswordlessConfig(config: Config): NormalisedConfig { signInUpFeature, linkClickedScreenFeature: normalisePasswordlessBaseConfig(config.linkClickedScreenFeature), + mfaFeature: normalisePasswordlessBaseConfig(config.mfaFeature), contactMethod: config.contactMethod, diff --git a/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx b/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx index 0a926ee3c..e637fca7e 100644 --- a/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx +++ b/lib/ts/recipe/thirdpartypasswordless/components/themes/signInUp/index.tsx @@ -136,15 +136,19 @@ const SignInUpTheme: React.FC