diff --git a/.changeset/fast-items-film.md b/.changeset/fast-items-film.md new file mode 100644 index 00000000000..eb224ec5fce --- /dev/null +++ b/.changeset/fast-items-film.md @@ -0,0 +1,18 @@ +--- +"thirdweb": minor +--- + +Adds a defaultSmsCountryCode configuration option to In-App and Ecosystem Wallets + +```ts +createWallet("inApp", { + auth: { + options: [ + "email", + "phone", + ], + mode: "redirect", + defaultSmsCountryCode: "IN", // Default country code for SMS + }, + }), + ``` diff --git a/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.test.tsx b/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.test.tsx new file mode 100644 index 00000000000..5efbd02ec7c --- /dev/null +++ b/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.test.tsx @@ -0,0 +1,45 @@ +import { describe, expect, it, vi } from "vitest"; +import { + fireEvent, + render, + screen, +} from "../../../../../test/src/react-render.js"; +import { CountrySelector } from "./CountrySelector.js"; + +describe("CountrySelector", () => { + it("renders with default country code", () => { + const setCountryCode = vi.fn(); + render( + , + ); + + const selectElement = screen.getByRole("combobox"); + expect(selectElement).toBeTruthy(); + expect(selectElement).toHaveValue("US +1"); + }); + + it("changes country code on selection", () => { + const setCountryCode = vi.fn(); + render( + , + ); + + const selectElement = screen.getByRole("combobox"); + fireEvent.change(selectElement, { target: { value: "CA +1" } }); + + expect(setCountryCode).toHaveBeenCalledWith("CA +1"); + }); + + it("displays all supported countries", () => { + const setCountryCode = vi.fn(); + render( + , + ); + + const options = screen.getAllByRole("option"); + expect(options.length).toBeGreaterThan(0); + expect( + options.some((option) => option.textContent?.includes("United States")), + ).toBe(true); + }); +}); diff --git a/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.tsx b/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.tsx index 05316f0db42..a7f1c8c8d62 100644 --- a/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.tsx +++ b/packages/thirdweb/src/react/web/wallets/in-app/CountrySelector.tsx @@ -1,9 +1,22 @@ "use client"; -import { useQuery } from "@tanstack/react-query"; import { useRef } from "react"; import { useCustomTheme } from "../../../core/design-system/CustomThemeProvider.js"; import { radius, spacing } from "../../../core/design-system/index.js"; import { StyledOption, StyledSelect } from "../../ui/design-system/elements.js"; +import { + type SupportedSmsCountry, + supportedSmsCountries, +} from "./supported-sms-countries.js"; + +export function getCountrySelector(countryIsoCode: SupportedSmsCountry) { + const country = supportedSmsCountries.find( + (country) => country.countryIsoCode === countryIsoCode, + ); + if (!country) { + return "US +1"; + } + return `${country.countryIsoCode} +${country.phoneNumberCode}`; +} export function CountrySelector({ countryCode, @@ -14,17 +27,7 @@ export function CountrySelector({ }) { const selectRef = useRef(null); - const { data: supportedCountries } = useQuery({ - queryKey: ["supported-sms-countries"], - queryFn: async () => { - const { supportedSmsCountries } = await import( - "./supported-sms-countries.js" - ); - return supportedSmsCountries; - }, - }); - - const supportedCountriesForSms = supportedCountries ?? [ + const supportedCountriesForSms = supportedSmsCountries ?? [ { countryIsoCode: "US", countryName: "United States", @@ -58,7 +61,7 @@ export function CountrySelector({ return ( diff --git a/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.test.tsx b/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.test.tsx new file mode 100644 index 00000000000..16dc8327bcb --- /dev/null +++ b/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.test.tsx @@ -0,0 +1,45 @@ +import { describe, expect, it, vi } from "vitest"; +import { render, screen } from "../../../../../test/src/react-render.js"; +import { getCountrySelector } from "./CountrySelector.js"; +import { InputSelectionUI } from "./InputSelectionUI.js"; + +vi.mock("./CountrySelector.js", async (importOriginal) => ({ + ...(await importOriginal()), + getCountrySelector: vi.fn(), +})); + +describe("InputSelectionUI", () => { + it("should initialize countryCodeInfo with defaultSmsCountryCode", () => { + const mockGetCountrySelector = vi.mocked(getCountrySelector); + mockGetCountrySelector.mockReturnValue("CA +1"); + + render( + , + ); + + expect(screen.getByRole("combobox")).toHaveValue("CA +1"); + }); + + it('should initialize countryCodeInfo with "US +1" if defaultSmsCountryCode is not provided', () => { + render( + , + ); + + expect(screen.getByRole("combobox")).toHaveValue("US +1"); + }); +}); diff --git a/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.tsx b/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.tsx index 50aeeaeefcf..10221015574 100644 --- a/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.tsx +++ b/packages/thirdweb/src/react/web/wallets/in-app/InputSelectionUI.tsx @@ -10,7 +10,8 @@ import { Spacer } from "../../ui/components/Spacer.js"; import { IconButton } from "../../ui/components/buttons.js"; import { Input, InputContainer } from "../../ui/components/formElements.js"; import { Text } from "../../ui/components/text.js"; -import { CountrySelector } from "./CountrySelector.js"; +import { CountrySelector, getCountrySelector } from "./CountrySelector.js"; +import type { SupportedSmsCountry } from "./supported-sms-countries.js"; export function InputSelectionUI(props: { onSelect: (data: string) => void; @@ -22,8 +23,13 @@ export function InputSelectionUI(props: { submitButtonText: string; format?: "phone"; disabled?: boolean; + defaultSmsCountryCode?: SupportedSmsCountry; }) { - const [countryCodeInfo, setCountryCodeInfo] = useState("US +1"); + const [countryCodeInfo, setCountryCodeInfo] = useState( + props.defaultSmsCountryCode + ? getCountrySelector(props.defaultSmsCountryCode) + : "US +1", + ); const [input, setInput] = useState(""); const [error, setError] = useState(); const [showError, setShowError] = useState(false); diff --git a/packages/thirdweb/src/react/web/wallets/in-app/supported-sms-countries.ts b/packages/thirdweb/src/react/web/wallets/in-app/supported-sms-countries.ts index d89146b637b..077a0a04984 100644 --- a/packages/thirdweb/src/react/web/wallets/in-app/supported-sms-countries.ts +++ b/packages/thirdweb/src/react/web/wallets/in-app/supported-sms-countries.ts @@ -1,3 +1,5 @@ +export type SupportedSmsCountry = + (typeof supportedSmsCountries)[number]["countryIsoCode"]; export const supportedSmsCountries = [ { countryIsoCode: "AD", @@ -1183,4 +1185,4 @@ export const supportedSmsCountries = [ countryName: "Zimbabwe", phoneNumberCode: "263", }, -]; +] as const; diff --git a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx index 62f106f9639..7059402b9a8 100644 --- a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx +++ b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx @@ -448,6 +448,9 @@ export const ConnectWalletSocialOptions = ( disabled={props.disabled} emptyErrorMessage={emptyErrorMessage} submitButtonText={locale.submitEmail} + defaultSmsCountryCode={ + wallet.getConfig()?.auth?.defaultSmsCountryCode + } /> ) : (