UNPKG

@web3auth/modal

Version:

Multi chain wallet aggregator for web3Auth

562 lines (558 loc) 26.5 kB
'use strict'; var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var jsxRuntime = require('react/jsx-runtime'); var HCaptcha = require('@hcaptcha/react-hcaptcha'); var auth = require('@web3auth/auth'); var noModal = require('@web3auth/no-modal'); var react = require('react'); var reactI18next = require('react-i18next'); var config = require('../../config.js'); var constants = require('../../constants.js'); var AnalyticsContext = require('../../context/AnalyticsContext.js'); var RootContext = require('../../context/RootContext.js'); var factory = require('../../handlers/factory.js'); var testAccounts = require('../../helper/testAccounts.js'); var localeImport = require('../../localeImport.js'); var utils = require('../../utils.js'); var Image = require('../Image/Image.js'); var SocialLoginList = require('../SocialLoginList/SocialLoginList.js'); var LoginOtp = require('./LoginOtp/LoginOtp.js'); var LoginPasswordLess = require('./LoginPasswordLess/LoginPasswordLess.js'); const restrictedLoginMethods = [auth.AUTH_CONNECTION.SMS_PASSWORDLESS, auth.AUTH_CONNECTION.EMAIL_PASSWORDLESS, auth.AUTH_CONNECTION.AUTHENTICATOR, auth.AUTH_CONNECTION.PASSKEYS, auth.AUTH_CONNECTION.TELEGRAM, auth.AUTH_CONNECTION.CUSTOM]; function Login(props) { // TODO: add appName, isEmailPrimary, isExternalPrimary const { web3authClientId, web3authNetwork, authBuildEnv, appLogo, isModalVisible, handleSocialLoginHeight, socialLoginsConfig, installedExternalWalletConfig, isDark, handleSocialLoginClick, totalExternalWallets, isEmailPasswordLessLoginVisible, isSmsPasswordLessLoginVisible, handleExternalWalletBtnClick, handleExternalWalletClick, areSocialLoginsVisible, showPasswordLessInput, showExternalWalletButton, showExternalWalletCount, showInstalledExternalWallets, logoAlignment = "center", buttonRadius = "pill", deviceDetails } = props; const [t] = reactI18next.useTranslation(undefined, { i18n: localeImport }); const { bodyState, setBodyState } = react.useContext(RootContext.RootContext); const { analytics } = react.useContext(AnalyticsContext.AnalyticsContext); const [countryCode, setCountryCode] = react.useState(""); const [countryFlag, setCountryFlag] = react.useState(""); const [passwordlessErrorMessage, setPasswordlessErrorMessage] = react.useState(""); const [otpErrorMessage, setOtpErrorMessage] = react.useState(""); const [expand, setExpand] = react.useState(false); const [canShowMore, setCanShowMore] = react.useState(false); const [visibleRow, setVisibleRow] = react.useState([]); const [otherRow, setOtherRow] = react.useState([]); const [isPasswordLessCtaClicked, setIsPasswordLessCtaClicked] = react.useState(false); const [showOtpFlow, setShowOtpFlow] = react.useState(false); const [authConnection, setAuthConnection] = react.useState(undefined); const [passwordlessHandler, setPasswordlessHandler] = react.useState(undefined); const [isPasswordLessLoading, setIsPasswordLessLoading] = react.useState(false); const [otpLoading, setOtpLoading] = react.useState(false); const [showCaptcha, setShowCaptcha] = react.useState(false); const [captchaError, setCaptchaError] = react.useState(""); const captchaRef = react.useRef(null); const handleExpand = () => { setExpand(prev => !prev); setIsPasswordLessCtaClicked(false); handleSocialLoginHeight(); }; react.useEffect(() => { const maxOptions = Object.keys(socialLoginsConfig.loginMethods).filter(loginMethodKey => { return socialLoginsConfig.loginMethods[loginMethodKey].showOnModal; }); const visibleRows = []; const otherRows = []; const loginMethodsOrder = (socialLoginsConfig.loginMethodsOrder || []).reduce((acc, method, index) => { acc[method] = index; return acc; }, {}); const loginOptions = Object.keys(socialLoginsConfig.loginMethods).filter(method => { return !socialLoginsConfig.loginMethods[method].showOnModal === false && !restrictedLoginMethods.includes(method); }).sort((a, b) => { var _loginMethodsOrder$a, _loginMethodsOrder$b; const maxOrder = (socialLoginsConfig.loginMethodsOrder || []).length; const aOrder = (_loginMethodsOrder$a = loginMethodsOrder[a]) !== null && _loginMethodsOrder$a !== void 0 ? _loginMethodsOrder$a : maxOrder; const bOrder = (_loginMethodsOrder$b = loginMethodsOrder[b]) !== null && _loginMethodsOrder$b !== void 0 ? _loginMethodsOrder$b : maxOrder; const { mainOption: aMainOption } = socialLoginsConfig.loginMethods[a] || {}; const { mainOption: bMainOption } = socialLoginsConfig.loginMethods[b] || {}; // if both are main options, sort by order if (aMainOption && bMainOption) { return aOrder - bOrder; } // if one is main option, it should be first if (aMainOption) return -1; if (bMainOption) return 1; // if none are main options, sort by order return aOrder - bOrder; }); loginOptions.forEach((method, index) => { var _socialLoginsConfig$u; const connectorConfig = socialLoginsConfig.loginMethods[method]; const name = config.capitalizeFirstLetter(connectorConfig.name || method); const order = index + 1; const isPrimaryBtn = (socialLoginsConfig === null || socialLoginsConfig === void 0 || (_socialLoginsConfig$u = socialLoginsConfig.uiConfig) === null || _socialLoginsConfig$u === void 0 ? void 0 : _socialLoginsConfig$u.primaryButton) === "socialLogin" && order === 1; const loginOptionLength = loginOptions.length; const moreThanFour = loginOptionLength >= 4; const lengthCheck = moreThanFour ? order > 0 && order <= loginOptionLength : order > 0 && order < 4; if (lengthCheck) { visibleRows.push({ method, isDark, isPrimaryBtn, name, connector: socialLoginsConfig.connector, loginParams: { authConnection: connectorConfig.authConnection || method, authConnectionId: connectorConfig.authConnectionId, groupedAuthConnectionId: connectorConfig.groupedAuthConnectionId, extraLoginOptions: connectorConfig.extraLoginOptions, name, login_hint: "" }, order }); } otherRows.push({ method, isDark, isPrimaryBtn, name: name === "Twitter" ? "X" : name, connector: socialLoginsConfig.connector, loginParams: { authConnection: method, authConnectionId: connectorConfig.authConnectionId, groupedAuthConnectionId: connectorConfig.groupedAuthConnectionId, extraLoginOptions: connectorConfig.extraLoginOptions, name, login_hint: "" }, order }); }); setVisibleRow(visibleRows); setOtherRow(otherRows); setCanShowMore(maxOptions.length > 4); // Update the state based on the condition }, [socialLoginsConfig, isDark, buttonRadius]); const handleCustomLogin = async (authConnection, loginHint) => { try { const handler = factory.createPasswordlessHandler(authConnection, { loginHint, web3authClientId, network: web3authNetwork, uiConfig: socialLoginsConfig.uiConfig, authConnection, authBuildEnv }); let token = undefined; if (!testAccounts.isTestAccountPattern(authConnection, loginHint)) { var _captchaRef$current; const res = await ((_captchaRef$current = captchaRef.current) === null || _captchaRef$current === void 0 ? void 0 : _captchaRef$current.execute({ async: true })); if (!res) { throw noModal.WalletLoginError.connectionError("Captcha token is required"); } token = res.response; } const result = await handler.sendVerificationCode({ captchaToken: token }); if (result !== null && result !== void 0 && result.error) { setPasswordlessErrorMessage(t(result.error)); return; } setAuthConnection(authConnection); setShowOtpFlow(true); setPasswordlessHandler(handler); } catch (error) { noModal.log.error(error); } finally { setIsPasswordLessLoading(false); } }; const handleFormSubmit = async loginHint => { setIsPasswordLessLoading(true); if (isEmailPasswordLessLoginVisible) { const isEmailValid = loginHint.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i); if (isEmailValid) { const connectorConfig = socialLoginsConfig.loginMethods[auth.AUTH_CONNECTION.EMAIL_PASSWORDLESS]; if (connectorConfig.isDefault) { return handleSocialLoginClick({ connector: socialLoginsConfig.connector, loginParams: { authConnection: auth.AUTH_CONNECTION.EMAIL_PASSWORDLESS, authConnectionId: connectorConfig.authConnectionId, groupedAuthConnectionId: connectorConfig.groupedAuthConnectionId, extraLoginOptions: connectorConfig.extraLoginOptions, loginHint: loginHint, name: "Email" } }); } else { return handleCustomLogin(auth.AUTH_CONNECTION.EMAIL_PASSWORDLESS, loginHint); } } } if (isSmsPasswordLessLoginVisible) { const number = loginHint.startsWith("+") ? loginHint : `${countryCode}${loginHint}`; const result = await utils.validatePhoneNumber(number); if (result.success) { const finalLoginHint = typeof result.parsed_number === "string" ? result.parsed_number : number; const connectorConfig = socialLoginsConfig.loginMethods[auth.AUTH_CONNECTION.SMS_PASSWORDLESS]; if (connectorConfig.isDefault) { return handleSocialLoginClick({ connector: socialLoginsConfig.connector, loginParams: { authConnection: auth.AUTH_CONNECTION.SMS_PASSWORDLESS, authConnectionId: connectorConfig.authConnectionId, groupedAuthConnectionId: connectorConfig.groupedAuthConnectionId, extraLoginOptions: connectorConfig.extraLoginOptions, loginHint: finalLoginHint, name: "Mobile" } }); } else { setCountryFlag(result.country_flag); return handleCustomLogin(auth.AUTH_CONNECTION.SMS_PASSWORDLESS, finalLoginHint); } } } setPasswordlessErrorMessage(invalidInputErrorMessage); setIsPasswordLessLoading(false); return undefined; }; const title = react.useMemo(() => { if (isEmailPasswordLessLoginVisible && isSmsPasswordLessLoginVisible) return t("modal.social.passwordless-title"); if (isEmailPasswordLessLoginVisible) return t("modal.social.email"); return t("modal.social.phone"); }, [isEmailPasswordLessLoginVisible, isSmsPasswordLessLoginVisible, t]); const placeholder = react.useMemo(() => { if (isEmailPasswordLessLoginVisible && isSmsPasswordLessLoginVisible) return "+(00)123456/name@example.com"; if (isEmailPasswordLessLoginVisible) return "name@example.com"; return "+(00)123456"; }, [isEmailPasswordLessLoginVisible, isSmsPasswordLessLoginVisible]); const invalidInputErrorMessage = react.useMemo(() => { if (isEmailPasswordLessLoginVisible && isSmsPasswordLessLoginVisible) return t("modal.errors-invalid-number-email"); if (isEmailPasswordLessLoginVisible) return t("modal.errors-invalid-email"); return t("modal.errors-invalid-number"); }, [isEmailPasswordLessLoginVisible, isSmsPasswordLessLoginVisible, t]); react.useEffect(() => { const getLocation = async () => { const result = await utils.getUserCountry(); if (result && result.dialCode) { setCountryCode(result.dialCode); } }; if (isSmsPasswordLessLoginVisible) getLocation(); }, [isSmsPasswordLessLoginVisible]); const handleConnectWallet = e => { analytics === null || analytics === void 0 || analytics.track(noModal.ANALYTICS_EVENTS.EXTERNAL_WALLET_LIST_EXPANDED, { total_external_wallets: totalExternalWallets, installed_external_wallets: installedExternalWallets.length }); setIsPasswordLessCtaClicked(false); e.preventDefault(); if (handleExternalWalletBtnClick) handleExternalWalletBtnClick(true); }; const handleOtpComplete = async otp => { setOtpLoading(true); if (otpErrorMessage) setOtpErrorMessage(""); try { var _result$data; const connectorConfig = socialLoginsConfig.loginMethods[authConnection]; const result = await (passwordlessHandler === null || passwordlessHandler === void 0 ? void 0 : passwordlessHandler.verifyCode(otp)); if (result !== null && result !== void 0 && result.error) { setOtpErrorMessage(t(result.error)); return; } if (result !== null && result !== void 0 && (_result$data = result.data) !== null && _result$data !== void 0 && _result$data.id_token) { var _result$data2; return handleSocialLoginClick({ connector: socialLoginsConfig.connector, loginParams: { authConnection: authConnection, authConnectionId: connectorConfig.authConnectionId, groupedAuthConnectionId: connectorConfig.groupedAuthConnectionId, extraLoginOptions: _objectSpread(_objectSpread({}, connectorConfig.extraLoginOptions), {}, { id_token: (_result$data2 = result.data) === null || _result$data2 === void 0 ? void 0 : _result$data2.id_token }), loginHint: passwordlessHandler.passwordlessParams.loginHint, name: passwordlessHandler.name } }); } } catch (error) { noModal.log.error(error); } finally { setOtpLoading(false); } }; /** * Installed wallet click logic: * - For MetaMask: If not injected and on desktop, display QR code for connection. * - If wallet supports multiple chain namespaces, prompt user to select a chain. * - Otherwise, connect directly using the wallet connector. */ const handleInstalledWalletClick = wallet => { var _wallet$chainNamespac; analytics === null || analytics === void 0 || analytics.track(noModal.ANALYTICS_EVENTS.EXTERNAL_WALLET_SELECTED, { connector: wallet.name, wallet_name: wallet.displayName, is_installed: wallet.isInstalled, is_injected: wallet.hasInjectedWallet, chain_namespaces: wallet.chainNamespaces, has_wallet_connect: wallet.hasWalletConnect, has_install_links: wallet.hasInstallLinks, has_wallet_registry_item: !!wallet.walletRegistryItem, total_external_wallets: totalExternalWallets }); // for non-injected Metamask on desktop, show QR code to connect if (wallet.name === noModal.WALLET_CONNECTORS.METAMASK && !wallet.hasInjectedWallet && deviceDetails.platform === "desktop") { handleExternalWalletClick({ connector: wallet.name }); // We should show QR code only if the wallet is not installed. setBodyState(_objectSpread(_objectSpread({}, bodyState), {}, { metamaskQrCode: { show: true, wallet: wallet } })); return; } // when having multiple namespaces, ask user to select one if (((_wallet$chainNamespac = wallet.chainNamespaces) === null || _wallet$chainNamespac === void 0 ? void 0 : _wallet$chainNamespac.length) > 1) { setBodyState(_objectSpread(_objectSpread({}, bodyState), {}, { multiChainSelector: { show: true, wallet: wallet } })); } else { handleExternalWalletClick({ connector: wallet.name }); } }; const installedExternalWallets = react.useMemo(() => { if (showInstalledExternalWallets) return installedExternalWalletConfig; // always show MetaMask return installedExternalWalletConfig.filter(wallet => wallet.name === noModal.WALLET_CONNECTORS.METAMASK); }, [installedExternalWalletConfig, showInstalledExternalWallets]); if (showOtpFlow) { return jsxRuntime.jsx(LoginOtp, { otpLoading: otpLoading, loginHint: passwordlessHandler === null || passwordlessHandler === void 0 ? void 0 : passwordlessHandler.passwordlessParams.loginHint, setShowOtpFlow: setShowOtpFlow, authConnection: authConnection, handleOtpComplete: handleOtpComplete, errorMessage: otpErrorMessage, countryFlag: countryFlag }); } const socialLoginSection = (otherRow = []) => { return jsxRuntime.jsx(SocialLoginList, { otherRow: otherRow, isDark: isDark, visibleRow: visibleRow, canShowMore: canShowMore, handleSocialLoginClick: handleSocialLoginClick, socialLoginsConfig: socialLoginsConfig, handleExpandSocialLogins: handleExpand, buttonRadius: buttonRadius }, "social-login-section"); }; const passwordlessLoginSection = () => { return jsxRuntime.jsx(LoginPasswordLess, { isModalVisible: isModalVisible, isPasswordLessCtaClicked: isPasswordLessCtaClicked, setIsPasswordLessCtaClicked: setIsPasswordLessCtaClicked, title: title, placeholder: placeholder, handleFormSubmit: handleFormSubmit, errorMessage: passwordlessErrorMessage, isDark: isDark, buttonRadius: buttonRadius, isPasswordLessLoading: isPasswordLessLoading }, "passwordless-section"); }; const externalWalletSection = () => { return jsxRuntime.jsxs("div", { className: utils.cn("w3a--flex w3a--w-full w3a--flex-col w3a--items-start w3a--justify-start w3a--gap-y-2"), children: [installedExternalWallets.length > 0 && installedExternalWallets.map(wallet => jsxRuntime.jsxs("button", { type: "button", className: utils.cn("w3a--btn !w3a--justify-between w3a--group w3a--relative w3a--overflow-hidden", { "w3a--rounded-full": buttonRadius === "pill", "w3a--rounded-lg": buttonRadius === "rounded", "w3a--rounded-none": buttonRadius === "square" }), onClick: () => handleInstalledWalletClick(wallet), children: [jsxRuntime.jsx("p", { className: "w3a--max-w-[180px] w3a--truncate w3a--text-base w3a--font-normal w3a--text-app-gray-700 dark:w3a--text-app-white", children: wallet.displayName }), jsxRuntime.jsxs("div", { className: "w3a--absolute w3a--right-4 w3a--top-1/2 w3a--flex w3a--w-auto -w3a--translate-y-1/2 w3a--items-center w3a--gap-x-2 w3a--transition-all w3a--duration-300 group-hover:w3a--translate-x-6 group-hover:w3a--opacity-0", children: [wallet.hasInjectedWallet && jsxRuntime.jsx("span", { className: "w3a--inline-flex w3a--items-center w3a--rounded-md w3a--bg-app-primary-100 w3a--px-2 w3a--py-1 w3a--text-xs w3a--font-medium w3a--text-app-primary-800 \n dark:w3a--border dark:w3a--border-app-primary-400 dark:w3a--bg-transparent dark:w3a--text-app-primary-400", children: t("modal.external.installed") }), jsxRuntime.jsx("figure", { className: "w3a--size-5", children: jsxRuntime.jsx(Image, { imageData: wallet.icon, imageId: `login-${wallet.name}`, hoverImageId: `login-${wallet.name}`, fallbackImageId: "wallet", height: "24", width: "24", isButton: true, extension: wallet.imgExtension || "webp" }) })] }), jsxRuntime.jsx("img", { id: "injected-wallet-arrow", className: "w3a--absolute w3a--right-4 w3a--top-1/2 -w3a--translate-x-10 -w3a--translate-y-1/2 w3a--opacity-0 w3a--transition-all w3a--duration-300\n group-hover:w3a--translate-x-0 group-hover:w3a--opacity-100", src: utils.getIcons(isDark ? "chevron-right-dark" : "chevron-right-light"), alt: "arrow" })] }, wallet.name)), totalExternalWallets > 3 && jsxRuntime.jsxs("button", { type: "button", className: utils.cn("w3a--btn !w3a--justify-between w3a--group w3a--relative w3a--overflow-hidden", { "w3a--rounded-full": buttonRadius === "pill", "w3a--rounded-lg": buttonRadius === "rounded", "w3a--rounded-none": buttonRadius === "square" }), onClick: handleConnectWallet, children: [jsxRuntime.jsx("p", { className: "w3a--text-base w3a--font-normal w3a--text-app-gray-900 dark:w3a--text-app-white", children: t("modal.external.all-wallets") }), showExternalWalletCount && totalExternalWallets > 0 && jsxRuntime.jsx("div", { id: "external-wallet-count", className: "w3a--absolute w3a--right-4 w3a--top-1/2 w3a--w-auto -w3a--translate-y-1/2 w3a--rounded-full w3a--bg-app-primary-100 w3a--px-2.5 w3a--py-0.5 w3a--text-xs w3a--font-medium w3a--text-app-primary-800 w3a--transition-all w3a--delay-300 w3a--duration-300 group-hover:w3a--translate-x-6 group-hover:w3a--opacity-0 group-hover:w3a--delay-0 dark:w3a--border dark:w3a--border-app-primary-500 dark:w3a--bg-transparent dark:w3a--text-app-primary-500", children: totalExternalWallets - 1 }), jsxRuntime.jsx("img", { id: "external-wallet-arrow", className: "w3a--absolute w3a--right-4 w3a--top-1/2 -w3a--translate-x-10 -w3a--translate-y-1/2 w3a--opacity-0 w3a--transition-all w3a--duration-300\n group-hover:w3a--translate-x-0 group-hover:w3a--opacity-100", src: utils.getIcons(isDark ? "chevron-right-dark" : "chevron-right-light"), alt: "arrow" })] })] }, "external-wallets-section"); }; const headerLogo = [constants.DEFAULT_LOGO_DARK, constants.DEFAULT_LOGO_LIGHT].includes(appLogo) ? "" : appLogo; const delimiter = index => { return jsxRuntime.jsxs("div", { className: utils.cn("w3a--flex w3a--w-full w3a--items-center w3a--gap-x-2", headerLogo ? "w3a--my-2" : "w3a--my-4"), children: [jsxRuntime.jsx("div", { className: "w3a--h-px w3a--w-full w3a--bg-app-gray-200 dark:w3a--bg-app-gray-500" }), jsxRuntime.jsx("p", { className: "w3a--text-xs w3a--font-normal w3a--uppercase w3a--text-app-gray-400 dark:w3a--text-app-gray-400", children: "or" }), jsxRuntime.jsx("div", { className: "w3a--h-px w3a--w-full w3a--bg-app-gray-200 dark:w3a--bg-app-gray-500" })] }, `section-delimiter-${index}`); }; const defaultView = () => { var _socialLoginsConfig$u2; const sectionMap = { social: socialLoginSection, passwordless: passwordlessLoginSection, externalWallets: externalWalletSection }; const sectionVisibility = { social: areSocialLoginsVisible, passwordless: showPasswordLessInput, externalWallets: showExternalWalletButton }; const signInMethods = ((_socialLoginsConfig$u2 = socialLoginsConfig.uiConfig) === null || _socialLoginsConfig$u2 === void 0 ? void 0 : _socialLoginsConfig$u2.signInMethods) || ["social", "passwordless", "externalWallets"]; // add missing signInMethods in case uiConfig.signInMethods is not set correctly Object.entries(sectionVisibility).forEach(([method, visibility]) => { if (visibility && !signInMethods.includes(method)) { signInMethods.push(method); } }); const sections = signInMethods.map(method => sectionVisibility[method] && sectionMap[method]()).filter(Boolean); // add delimiter between external wallets and other sections if (sections.length === 3) { const externalWalletIndex = signInMethods.findIndex(section => section === "externalWallets"); if (externalWalletIndex === 0) { // add after it sections.splice(1, 0, delimiter(1)); } else if (externalWalletIndex === 1) { // add before it sections.splice(1, 0, delimiter(1)); // add after it sections.splice(3, 0, delimiter(2)); } else if (externalWalletIndex === 2) { // add before it sections.splice(2, 0, delimiter(1)); } } else if (sections.length === 2) { if (sectionVisibility["externalWallets"]) { sections.splice(1, 0, delimiter(1)); } } return sections; }; const expandedView = () => socialLoginSection(otherRow); return jsxRuntime.jsxs("div", { className: "w3a--flex w3a--flex-col w3a--items-center w3a--gap-y-4 w3a--p-2", children: [jsxRuntime.jsxs("div", { className: utils.cn("w3a--flex w3a--flex-col w3a--items-center w3a--justify-center w3a--gap-y-2 w3a--pt-6", logoAlignment === "center" ? "" : "w3a--w-full"), children: [headerLogo && jsxRuntime.jsx("figure", { className: utils.cn("w3a--mx-auto w3a--h-12 w3a--w-[200px]", logoAlignment === "center" ? "w3a--flex w3a--justify-center w3a--items-center" : "w3a--ml-0 w3a--w-auto"), children: jsxRuntime.jsx("img", { src: headerLogo, alt: "Logo", className: "w3a--size-full w3a--object-contain" }) }), jsxRuntime.jsx("p", { className: utils.cn("w3a--text-app-gray-900 dark:w3a--text-app-white", logoAlignment === "center" ? "w3a--text-center" : "w3a--text-left w3a--w-full w3a--ml-4", headerLogo ? "w3a--text-lg w3a--font-semibold" : "w3a--text-3xl w3a--font-medium"), children: t("modal.social.sign-in") })] }), jsxRuntime.jsx(HCaptcha, { ref: captchaRef, sitekey: config.CAPTCHA_SITE_KEY, size: "invisible", languageOverride: socialLoginsConfig.uiConfig.defaultLanguage, theme: socialLoginsConfig.uiConfig.theme, onOpen: () => setShowCaptcha(true), onClose: () => setShowCaptcha(false), onError: () => setCaptchaError("passwordless.captcha-default-error"), onChalExpired: () => setCaptchaError("passwordless.captcha-default-error") }), captchaError && showCaptcha && jsxRuntime.jsx("p", { className: "-w3a--mt-2 w3a--w-full w3a--pl-6 w3a--text-start w3a--text-xs w3a--font-normal w3a--text-app-red-500 dark:w3a--text-app-red-400", children: t(captchaError) }), !showCaptcha && jsxRuntime.jsxs("div", { className: "w3a--flex w3a--w-full w3a--flex-col w3a--items-center w3a--justify-center w3a--gap-y-2", children: [!expand && defaultView(), expand && expandedView()] })] }); } module.exports = Login;