diff --git a/packages/modal/src/default.ts b/packages/modal/src/default.ts index 935cbe194..eaffb100c 100644 --- a/packages/modal/src/default.ts +++ b/packages/modal/src/default.ts @@ -1,6 +1,7 @@ import type { OPENLOGIN_NETWORK_TYPE, OpenLoginOptions } from "@toruslabs/openlogin-utils"; import { CHAIN_NAMESPACES, CustomChainConfig, getChainConfig, IAdapter, IBaseProvider, WALLET_ADAPTER_TYPE, WALLET_ADAPTERS } from "@web3auth/base"; import { CommonPrivateKeyProvider } from "@web3auth/base-provider"; +import { UIConfig } from "@web3auth/ui"; export async function getPrivateKeyProvider(chainConfig: CustomChainConfig): Promise> { if (chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) { @@ -24,8 +25,9 @@ export const getDefaultAdapterModule = async (params: { customChainConfig: Partial & Pick; sessionTime?: number; web3AuthNetwork?: OPENLOGIN_NETWORK_TYPE; + uiConfig?: Omit; }): Promise> => { - const { name, customChainConfig, clientId, sessionTime, web3AuthNetwork } = params; + const { name, customChainConfig, clientId, sessionTime, web3AuthNetwork, uiConfig } = params; if (!Object.values(CHAIN_NAMESPACES).includes(customChainConfig.chainNamespace)) throw new Error(`Invalid chainNamespace: ${customChainConfig.chainNamespace}`); const finalChainConfig = { @@ -73,7 +75,7 @@ export const getDefaultAdapterModule = async (params: { ...defaultOptions, clientId, chainConfig: { ...finalChainConfig }, - adapterSettings: { ...(defaultOptions.adapterSettings as OpenLoginOptions), clientId, network: web3AuthNetwork }, + adapterSettings: { ...(defaultOptions.adapterSettings as OpenLoginOptions), clientId, network: web3AuthNetwork, whiteLabel: uiConfig }, sessionTime, web3AuthNetwork, privateKeyProvider, diff --git a/packages/modal/src/modalManager.ts b/packages/modal/src/modalManager.ts index c575ba7bf..6062c9fa3 100644 --- a/packages/modal/src/modalManager.ts +++ b/packages/modal/src/modalManager.ts @@ -15,7 +15,7 @@ import { import { CommonJRPCProvider } from "@web3auth/base-provider"; import { Web3AuthNoModal, Web3AuthNoModalOptions } from "@web3auth/no-modal"; import type { OpenloginAdapter } from "@web3auth/openlogin-adapter"; -import { getAdapterSocialLogins, LOGIN_MODAL_EVENTS, LoginModal, OPENLOGIN_PROVIDERS, UIConfig } from "@web3auth/ui"; +import { getAdapterSocialLogins, getUserLanguage, LOGIN_MODAL_EVENTS, LoginModal, OPENLOGIN_PROVIDERS, UIConfig } from "@web3auth/ui"; import { defaultEvmDappModalConfig, @@ -26,7 +26,6 @@ import { } from "./config"; import { getDefaultAdapterModule, getPrivateKeyProvider } from "./default"; import { AdaptersModalConfig, IWeb3AuthModal, ModalConfig } from "./interface"; -import { getUserLanguage } from "./utils"; export interface Web3AuthOptions extends Web3AuthNoModalOptions { /** @@ -77,19 +76,12 @@ export class Web3Auth extends Web3AuthNoModal implements IWeb3AuthModal { throw new Error(`Invalid chainNamespace provided: ${providedChainConfig.chainNamespace}`); } - // get userLanguage - const defaultLanguage = getUserLanguage(this.options.uiConfig?.defaultLanguage); + if (!this.options.uiConfig.defaultLanguage) this.options.uiConfig.defaultLanguage = getUserLanguage(this.options.uiConfig.defaultLanguage); + if (!this.options.uiConfig.mode) this.options.uiConfig.mode = "auto"; this.loginModal = new LoginModal({ - theme: this.options.uiConfig?.theme, - appName: this.options.uiConfig?.appName || "blockchain", - appLogo: this.options.uiConfig?.appLogo || "", + ...this.options.uiConfig, adapterListener: this, - displayErrorsOnModal: this.options.uiConfig?.displayErrorsOnModal, - defaultLanguage, - modalZIndex: this.options.uiConfig?.modalZIndex || "99998", - loginGridCol: this.options.uiConfig?.loginGridCol || 3, - primaryButton: this.options.uiConfig?.primaryButton || "socialLogin", }); this.subscribeToLoginModalEvents(); } @@ -131,6 +123,7 @@ export class Web3Auth extends Web3AuthNoModal implements IWeb3AuthModal { clientId: this.options.clientId, sessionTime: this.options.sessionTime, web3AuthNetwork: this.options.web3AuthNetwork, + uiConfig: this.options.uiConfig, }); this.walletAdapters[adapterName] = ad; @@ -159,7 +152,7 @@ export class Web3Auth extends Web3AuthNoModal implements IWeb3AuthModal { const openloginAdapter = this.walletAdapters[adapterName] as OpenloginAdapter; if (!openloginAdapter.privateKeyProvider) { const currentPrivateKeyProvider = await getPrivateKeyProvider(openloginAdapter.chainConfigProxy as CustomChainConfig); - openloginAdapter.setAdapterSettings({ privateKeyProvider: currentPrivateKeyProvider }); + openloginAdapter.setAdapterSettings({ privateKeyProvider: currentPrivateKeyProvider, whiteLabel: this.options.uiConfig }); } } diff --git a/packages/modal/src/utils.ts b/packages/modal/src/utils.ts deleted file mode 100644 index 5b09e0b02..000000000 --- a/packages/modal/src/utils.ts +++ /dev/null @@ -1,25 +0,0 @@ -interface NavigatorLanguage { - userLanguage?: string; -} - -export const languageMap = { - en: "english", - de: "german", - ja: "japanese", - ko: "korean", - zh: "mandarin", - es: "spanish", - fr: "french", - pt: "portuguese", - nl: "dutch", -}; - -export const getUserLanguage = (defaultLanguage: string | undefined) => { - let userLanguage = defaultLanguage; - if (!userLanguage) { - const browserLanguage = - typeof window !== "undefined" ? (window.navigator as NavigatorLanguage).userLanguage || window.navigator.language || "en-US" : "en-US"; - userLanguage = browserLanguage.split("-")[0]; - } - return Object.prototype.hasOwnProperty.call(languageMap, userLanguage) ? userLanguage : "en"; -}; diff --git a/packages/ui/src/interfaces.ts b/packages/ui/src/interfaces.ts index 5f315c0d0..631c116f7 100644 --- a/packages/ui/src/interfaces.ts +++ b/packages/ui/src/interfaces.ts @@ -1,26 +1,10 @@ import { SafeEventEmitter } from "@toruslabs/openlogin-jrpc"; +import { WhiteLabelData } from "@toruslabs/openlogin-utils"; import { BaseAdapterConfig, IWalletConnectExtensionAdapter, LoginMethodConfig, WALLET_ADAPTER_TYPE } from "@web3auth/base"; // TODO: change whitelabel settings and pass ui whitelabel to openlogin. // capture whitelabel only once -export interface UIConfig { - /** - * App name to display in the UI. - */ - appName?: string; - - /** - * Logo for your app. - */ - appLogo?: string; - - /** - * theme for the modal - * - * @defaultValue `auto` - */ - theme?: "light" | "dark" | "auto"; - +export interface UIConfig extends WhiteLabelData { /** * order of how login methods are shown * @@ -28,21 +12,6 @@ export interface UIConfig { */ loginMethodsOrder?: string[]; - /** - * language which will be used by web3auth. app will use browser language if not specified. if language is not supported it will use "en" - * en: english - * de: german - * ja: japanese - * ko: korean - * zh: mandarin - * es: spanish - * fr: french - * pt: portuguese - * nl: dutch - * - */ - defaultLanguage?: string; - /** * Z-index of the modal and iframe * @defaultValue 99998 diff --git a/packages/ui/src/loginModal.tsx b/packages/ui/src/loginModal.tsx index bf9a04f23..da3677ee6 100644 --- a/packages/ui/src/loginModal.tsx +++ b/packages/ui/src/loginModal.tsx @@ -30,6 +30,7 @@ import { SocialLoginEventType, UIConfig, } from "./interfaces"; +import { getUserLanguage } from "./utils"; function createWrapper(parentZIndex: string): HTMLElement { const existingWrapper = document.getElementById("w3a-parent-container"); @@ -48,44 +49,37 @@ function createWrapper(parentZIndex: string): HTMLElement { } class LoginModal extends SafeEventEmitter { - private appName: string; - - private appLogo: string; - - private modalZIndex: string; - - private isDark: boolean; + private uiConfig: UIConfig; private stateEmitter: SafeEventEmitter; - private displayErrorsOnModal = true; - - private defaultLanguage: string; - - constructor({ appName, appLogo, adapterListener, theme = "auto", displayErrorsOnModal = true, defaultLanguage, modalZIndex = "99998" }: UIConfig) { + constructor(uiConfig: UIConfig) { super(); - this.appName = appName || "blockchain"; - this.modalZIndex = modalZIndex || "99998"; - - // set theme - if (theme === "dark" || (theme === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches)) { - this.isDark = true; - } else { - this.isDark = false; - } - - this.appLogo = appLogo || (this.isDark ? DEFAULT_LOGO_DARK : DEFAULT_LOGO_LIGHT); + this.uiConfig = uiConfig; + + if (!uiConfig.logoDark) this.uiConfig.logoDark = DEFAULT_LOGO_DARK; + if (!uiConfig.logoLight) this.uiConfig.logoLight = DEFAULT_LOGO_LIGHT; + if (!uiConfig.mode) this.uiConfig.mode = "auto"; + if (!uiConfig.modalZIndex) this.uiConfig.modalZIndex = "99998"; + if (typeof uiConfig.displayErrorsOnModal === "undefined") this.uiConfig.displayErrorsOnModal = true; + if (!uiConfig.defaultLanguage) this.uiConfig.defaultLanguage = "en"; + if (!uiConfig.appName) this.uiConfig.appName = "Web3Auth"; + if (!uiConfig.loginGridCol) this.uiConfig.loginGridCol = 3; + if (!uiConfig.primaryButton) this.uiConfig.primaryButton = "socialLogin"; + if (!uiConfig.defaultLanguage) this.uiConfig.defaultLanguage = getUserLanguage(uiConfig.defaultLanguage); this.stateEmitter = new SafeEventEmitter(); - this.displayErrorsOnModal = displayErrorsOnModal; - this.defaultLanguage = defaultLanguage; - this.subscribeCoreEvents(adapterListener); + this.subscribeCoreEvents(this.uiConfig.adapterListener); + } + + get isDark(): boolean { + return this.uiConfig.mode === "dark" || (this.uiConfig.mode === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches); } initModal = async (): Promise => { const darkState = { isDark: this.isDark }; - const useLang = this.defaultLanguage || "en"; + const useLang = this.uiConfig.defaultLanguage || "en"; // Load new language resource if (useLang === "de") { @@ -170,7 +164,7 @@ class LoginModal extends SafeEventEmitter { }); return resolve(); }); - const container = createWrapper(this.modalZIndex); + const container = createWrapper(this.uiConfig.modalZIndex); if (darkState.isDark) { container.classList.add("dark"); } else { @@ -186,8 +180,8 @@ class LoginModal extends SafeEventEmitter { handleShowExternalWallets={this.handleShowExternalWallets} handleExternalWalletClick={this.handleExternalWalletClick} handleSocialLoginClick={this.handleSocialLoginClick} - appLogo={this.appLogo} - appName={this.appName} + appLogo={darkState.isDark ? this.uiConfig.logoDark : this.uiConfig.logoLight} + appName={this.uiConfig.appName} /> ); @@ -310,7 +304,7 @@ class LoginModal extends SafeEventEmitter { listener.on(ADAPTER_EVENTS.ERRORED, (error: Web3AuthError) => { log.error("error", error, error.message); if (error.code === 5000) { - if (this.displayErrorsOnModal) + if (this.uiConfig.displayErrorsOnModal) this.setState({ modalVisibility: true, postLoadingMessage: error.message || "modal.post-loading.something-wrong", diff --git a/packages/ui/src/utils.ts b/packages/ui/src/utils.ts index 94348b55c..ab165feaf 100644 --- a/packages/ui/src/utils.ts +++ b/packages/ui/src/utils.ts @@ -1,4 +1,5 @@ import { get, post } from "@toruslabs/http-helpers"; +import { LANGUAGE_TYPE } from "@toruslabs/openlogin-utils"; import { log, LoginMethodConfig, WALLET_ADAPTERS } from "@web3auth/base"; import { OPENLOGIN_PROVIDERS, OPENLOGIN_PROVIDERS_NAMES } from "./config"; @@ -85,7 +86,7 @@ export const validatePhoneNumber = async (phoneNumber: string): Promise = { en: "english", de: "german", ja: "japanese", @@ -96,3 +97,17 @@ export const languageMap = { pt: "portuguese", nl: "dutch", }; + +interface NavigatorLanguage { + userLanguage?: string; +} + +export const getUserLanguage = (defaultLanguage: string | undefined): LANGUAGE_TYPE => { + let userLanguage = defaultLanguage; + if (!userLanguage) { + const browserLanguage = + typeof window !== "undefined" ? (window.navigator as NavigatorLanguage).userLanguage || window.navigator.language || "en-US" : "en-US"; + userLanguage = browserLanguage.split("-")[0]; + } + return Object.prototype.hasOwnProperty.call(languageMap, userLanguage) ? (userLanguage as LANGUAGE_TYPE) : "en"; +};