diff --git a/widget/embedded/src/containers/App/App.tsx b/widget/embedded/src/containers/App/App.tsx index b0e8077bee..a47ab316aa 100644 --- a/widget/embedded/src/containers/App/App.tsx +++ b/widget/embedded/src/containers/App/App.tsx @@ -42,9 +42,7 @@ export function Main() { widgetContext.onConnectWallet(setLastConnectedWalletWithNetwork); }, []); useEffect(() => { - if (config?.language) { - changeLanguage(config.language); - } + changeLanguage(config?.language); }, [config?.language]); return ( diff --git a/widget/embedded/src/hooks/useLanguage.ts b/widget/embedded/src/hooks/useLanguage.ts index 8d1ec4f41a..01b4c21752 100644 --- a/widget/embedded/src/hooks/useLanguage.ts +++ b/widget/embedded/src/hooks/useLanguage.ts @@ -9,7 +9,7 @@ interface UseLanguage { languages: LanguageItem[]; defaultLanguage: Language; activeLanguage: Language; - changeLanguage: (language: Language) => void; + changeLanguage: (language?: Language) => void; } export function useLanguage(): UseLanguage { @@ -22,6 +22,6 @@ export function useLanguage(): UseLanguage { activeLanguage: language, languages, defaultLanguage, - changeLanguage: setLanguage, + changeLanguage: (language) => setLanguage(language || DEFAULT_LANGUAGE), }; } diff --git a/widget/playground/src/components/ItemPicker/ItemPicker.tsx b/widget/playground/src/components/ItemPicker/ItemPicker.tsx index 66aab60dba..7e7935b453 100644 --- a/widget/playground/src/components/ItemPicker/ItemPicker.tsx +++ b/widget/playground/src/components/ItemPicker/ItemPicker.tsx @@ -16,6 +16,7 @@ function ItemPicker(props: PropTypes) { disabled, } = props; + const LogoComponent = logo; return ( @@ -32,12 +33,16 @@ function ItemPicker(props: PropTypes) { <Title> {hasLogo && ( <> - <Image - src={logo} - size={16} - useAsPlaceholder={!logo} - type="circular" - /> + {typeof logo === 'string' || logo === undefined ? ( + <Image + src={logo} + size={16} + useAsPlaceholder={!logo} + type="circular" + /> + ) : ( + LogoComponent && <LogoComponent size={16} /> + )} <Divider size={4} direction="horizontal" /> </> )} diff --git a/widget/playground/src/components/ItemPicker/ItemPicker.types.ts b/widget/playground/src/components/ItemPicker/ItemPicker.types.ts index 28c4ee98d7..e8eb5589c6 100644 --- a/widget/playground/src/components/ItemPicker/ItemPicker.types.ts +++ b/widget/playground/src/components/ItemPicker/ItemPicker.types.ts @@ -1,6 +1,9 @@ export interface PropTypes { onClick: () => void; - value: { label?: string; logo?: string }; + value: { + label?: string; + logo?: string | React.ComponentType<{ size?: number }>; + }; title: string; iconTitle?: React.ReactNode; placeholder?: string; diff --git a/widget/playground/src/components/SingleList/SingleList.tsx b/widget/playground/src/components/SingleList/SingleList.tsx index b3df8c2b73..1a9d489259 100644 --- a/widget/playground/src/components/SingleList/SingleList.tsx +++ b/widget/playground/src/components/SingleList/SingleList.tsx @@ -114,6 +114,7 @@ export function SingleList(props: PropTypes) { }}> <VirtualizedList Item={({ index, style }) => { + const Icon = virtualList[index].Icon; return ( <div style={{ @@ -131,6 +132,8 @@ export function SingleList(props: PropTypes) { size={16} type="circular" /> + ) : Icon ? ( + <Icon size={16} /> ) : null } hasDivider diff --git a/widget/playground/src/components/SingleList/SingleList.types.ts b/widget/playground/src/components/SingleList/SingleList.types.ts index 16dbb8c31e..97a813a416 100644 --- a/widget/playground/src/components/SingleList/SingleList.types.ts +++ b/widget/playground/src/components/SingleList/SingleList.types.ts @@ -3,6 +3,11 @@ export interface PropTypes { icon: React.ReactNode; defaultValue?: string | null; onChange: (item: string) => void; - list: { name: string; value: string | null; image?: string }[]; + list: { + name: string; + value: string | null; + image?: string; + Icon?: React.ComponentType<{ size?: number }>; + }[]; searchPlaceholder?: string; } diff --git a/widget/playground/src/constants/languages.ts b/widget/playground/src/constants/languages.ts index d9a5f7e518..fe1eb36524 100644 --- a/widget/playground/src/constants/languages.ts +++ b/widget/playground/src/constants/languages.ts @@ -1,12 +1,8 @@ +import { English, French, Japanese, Spanish } from '@rango-dev/ui'; + export const LANGUAGES = [ - { - name: 'English (US)', - logo: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/800px-Flag_of_the_United_States.svg.png?20151118161041', - value: 'en', - }, - { - name: 'Turkish', - logo: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Flag_of_Turkey.svg/800px-Flag_of_Turkey.svg.png', - value: 'tr', - }, + { name: 'English', value: 'en', Icon: English }, + { name: 'Spanish', value: 'es', Icon: Spanish }, + { name: 'French', value: 'fr', Icon: French }, + { name: 'Japanese', value: 'ja', Icon: Japanese }, ]; diff --git a/widget/playground/src/containers/StyleLayout/StyleLayout.General.tsx b/widget/playground/src/containers/StyleLayout/StyleLayout.General.tsx index a6e5f384f7..fb35a898f0 100644 --- a/widget/playground/src/containers/StyleLayout/StyleLayout.General.tsx +++ b/widget/playground/src/containers/StyleLayout/StyleLayout.General.tsx @@ -1,6 +1,12 @@ import type { ChangeEvent } from 'react'; -import { BorderRadiusIcon, Divider, FontIcon, Typography } from '@rango-dev/ui'; +import { + BorderRadiusIcon, + Divider, + FontIcon, + LanguageIcon, + Typography, +} from '@rango-dev/ui'; import React, { useCallback, useState } from 'react'; import { ItemPicker } from '../../components/ItemPicker'; @@ -11,15 +17,18 @@ import { DEFAULT_PRIMARY_RADIUS, DEFAULT_SECONDARY_RADIUS, FONTS, + LANGUAGES, } from '../../constants'; import { useConfigStore } from '../../store/config'; import { Field, FieldTitle, GeneralContainer } from './StyleLayout.styles'; +import { ModalState } from './StyleLayout.types'; export function General() { - const [showModal, setShowModal] = useState(false); - const onBack = () => setShowModal(false); + const [modalState, setModalState] = useState<ModalState | null>(null); + const onBack = () => setModalState(null); + const onChangeLanguage = useConfigStore.use.onChangeLanguage(); const onChangeTheme = useConfigStore.use.onChangeTheme(); const borderRadius = useConfigStore.use.config().theme?.borderRadius; @@ -27,7 +36,7 @@ export function General() { useConfigStore.use.config().theme?.secondaryBorderRadius; const fontFamily = useConfigStore.use.config().theme?.fontFamily || FONTS[0].value; - + const language = useConfigStore.use.config().language || LANGUAGES[0].value; const handleFontChange = (value: string) => { if (value) { onChangeTheme({ @@ -37,6 +46,12 @@ export function General() { } onBack(); }; + const handleLanguageChange = (value: string) => { + if (value) { + onChangeLanguage(value); + } + onBack(); + }; const handleBorderRadius = useCallback( (e: ChangeEvent<HTMLInputElement>) => { @@ -60,13 +75,22 @@ export function General() { [secondaryBorderRadius] ); - const handleFontClick = useCallback(() => { - setShowModal(true); - }, []); + const selectedLanguage = LANGUAGES.find((l) => l.value === language); return ( <> <GeneralContainer> + <ItemPicker + onClick={() => setModalState(ModalState.DEFAULT_LANGUAGE)} + value={{ + label: selectedLanguage?.name, + logo: selectedLanguage?.Icon, + }} + title="Default Language" + hasLogo + iconTitle={<LanguageIcon size={18} color="gray" />} + /> + <Divider size={24} /> <Field> <FieldTitle> <BorderRadiusIcon size={18} /> @@ -95,13 +119,13 @@ export function General() { <Divider size={24} /> <ItemPicker - onClick={handleFontClick} + onClick={() => setModalState(ModalState.DEFAULT_FONT)} value={{ label: fontFamily }} title="Fonts" iconTitle={<FontIcon size={18} />} /> </GeneralContainer> - {showModal && ( + {modalState === ModalState.DEFAULT_FONT && ( <OverlayPanel onBack={onBack}> <SingleList onChange={handleFontChange} @@ -113,6 +137,19 @@ export function General() { /> </OverlayPanel> )} + + {modalState === ModalState.DEFAULT_LANGUAGE && ( + <OverlayPanel onBack={onBack}> + <SingleList + onChange={handleLanguageChange} + title="Languages" + icon={<LanguageIcon size={18} color="gray" />} + defaultValue={language} + list={LANGUAGES} + searchPlaceholder="Search Language" + /> + </OverlayPanel> + )} </> ); } diff --git a/widget/playground/src/containers/StyleLayout/StyleLayout.types.ts b/widget/playground/src/containers/StyleLayout/StyleLayout.types.ts index d47ff4cb72..be5cd453b7 100644 --- a/widget/playground/src/containers/StyleLayout/StyleLayout.types.ts +++ b/widget/playground/src/containers/StyleLayout/StyleLayout.types.ts @@ -24,3 +24,8 @@ export type CustomColorsTypes = { }; onResetPreset: () => void; }; + +export enum ModalState { + DEFAULT_FONT = 'font', + DEFAULT_LANGUAGE = 'language', +} diff --git a/widget/ui/src/icons/Language.tsx b/widget/ui/src/icons/Language.tsx new file mode 100644 index 0000000000..c91fc493c6 --- /dev/null +++ b/widget/ui/src/icons/Language.tsx @@ -0,0 +1,55 @@ +import type { SvgIconPropsWithChildren } from '../components/SvgIcon'; + +import React, { createElement } from 'react'; + +import { SvgIcon } from '../components/SvgIcon'; + +function SvgLanguage(props: SvgIconPropsWithChildren) { + return createElement( + SvgIcon, + props, + <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path + d="M15.1145 20.2844C14.9917 20.2844 14.8578 20.251 14.7461 20.1952C14.3331 19.9832 14.1657 19.4811 14.3666 19.0683L16.7554 14.304C16.9006 14.0251 17.1908 13.8466 17.5034 13.8466C17.8159 13.8466 18.1062 14.0251 18.2513 14.3152L20.6401 19.0795C20.8522 19.4923 20.6848 19.9943 20.2606 20.2063C19.8476 20.4183 19.3452 20.251 19.1331 19.827L17.5034 16.5579L15.8736 19.827C15.7173 20.1171 15.4159 20.2844 15.1145 20.2844Z" + fill="currentColor" + /> + <path + d="M19.457 19.4364H15.5277C15.07 19.4364 14.6905 19.057 14.6905 18.5996C14.6905 18.1421 15.07 17.7628 15.5277 17.7628H19.457C19.9147 17.7628 20.2943 18.1421 20.2943 18.5996C20.2943 19.057 19.9259 19.4364 19.457 19.4364Z" + fill="currentColor" + /> + <path + d="M17.492 24C13.9088 24 10.9841 21.0879 10.9841 17.4951C10.9841 13.9024 13.8976 10.9903 17.492 10.9903C21.0753 10.9903 24 13.9024 24 17.4951C24 21.0879 21.0865 24 17.492 24ZM17.492 12.675C14.8241 12.675 12.6585 14.8396 12.6585 17.5063C12.6585 20.1729 14.8241 22.3375 17.492 22.3375C20.1488 22.3375 22.3256 20.1729 22.3256 17.5063C22.3256 14.8396 20.16 12.675 17.492 12.675Z" + fill="currentColor" + /> + <path + d="M4.0298 12.7866C2.79072 12.7866 1.80838 12.4407 1.11629 11.7712C0.379538 11.0571 0 9.97487 0 8.58017V4.20642C0 1.49514 1.49583 0 4.20841 0H8.58425C9.97961 0 11.0512 0.3682 11.7768 1.11576C12.4801 1.841 12.8261 2.88985 12.7927 4.22876V8.58017C12.8261 9.94139 12.4801 11.0125 11.7545 11.7378C11.0289 12.463 9.95727 12.7977 8.57308 12.7754H4.21956C4.14142 12.7866 4.08561 12.7866 4.0298 12.7866ZM4.20841 1.6848C2.41118 1.6848 1.67443 2.42122 1.67443 4.21759V8.59134C1.67443 9.51742 1.87535 10.1868 2.27722 10.5773C2.66792 10.9567 3.29305 11.1241 4.17492 11.113H8.57308C9.51076 11.1353 10.1582 10.9456 10.5489 10.5551C10.9396 10.1646 11.1182 9.50627 11.0959 8.60251V4.20642C11.1182 3.31382 10.9396 2.6778 10.5601 2.28729C10.1694 1.88561 9.49959 1.6848 8.57308 1.6848H4.20841Z" + fill="currentColor" + /> + <path + d="M8.65116 5.9803H4.11903C3.66136 5.9803 3.28182 5.60095 3.28182 5.14349C3.28182 4.68603 3.66136 4.30667 4.11903 4.30667H8.65116C9.10883 4.30667 9.48837 4.68603 9.48837 5.14349C9.48837 5.60095 9.12 5.9803 8.65116 5.9803Z" + fill="currentColor" + /> + <path + d="M6.3963 5.98037C5.93862 5.98037 5.55909 5.60101 5.55909 5.14355V4.38485C5.55909 3.92739 5.93862 3.54803 6.3963 3.54803C6.85398 3.54803 7.23352 3.92739 7.23352 4.38485V5.14355C7.23352 5.60101 6.85398 5.98037 6.3963 5.98037Z" + fill="currentColor" + /> + <path + d="M4.11903 9.5062C3.66136 9.5062 3.28182 9.12684 3.28182 8.66938C3.28182 8.21192 3.66136 7.83256 4.11903 7.83256C5.53672 7.83256 6.6865 6.62757 6.6865 5.13245C6.6865 4.67499 7.06603 4.29564 7.52371 4.29564C7.98139 4.29564 8.36093 4.67499 8.36093 5.13245C8.36093 7.54249 6.46324 9.5062 4.11903 9.5062Z" + fill="currentColor" + /> + <path + d="M8.66231 9.50619C7.62417 9.50619 6.63067 8.9818 5.92741 8.05572C5.64834 7.68752 5.72649 7.16306 6.09487 6.88413C6.46324 6.60519 6.98788 6.68332 7.26695 7.05152C7.64649 7.56476 8.14882 7.84373 8.66231 7.84373C9.11999 7.84373 9.49953 8.22308 9.49953 8.68054C9.49953 9.13801 9.11999 9.50619 8.66231 9.50619Z" + fill="currentColor" + /> + <path + d="M8.65122 23.9999C3.88468 23.9999 0 20.1171 0 15.3528C0 14.8954 0.379538 14.516 0.837215 14.516C1.29489 14.516 1.67443 14.8954 1.67443 15.3528C1.67443 18.6555 3.97398 21.4226 7.0661 22.1478L6.7647 21.6457C6.53028 21.244 6.65308 20.7308 7.05494 20.4964C7.44564 20.2621 7.9703 20.3849 8.20472 20.7865L9.3768 22.7391C9.53308 22.9957 9.5331 23.3193 9.38798 23.5759C9.2317 23.8326 8.95262 23.9999 8.65122 23.9999Z" + fill="currentColor" + /> + <path + d="M23.1629 9.4951C22.7052 9.4951 22.3257 9.11574 22.3257 8.65828C22.3257 5.35564 20.0261 2.58854 16.934 1.86329L17.2354 2.3654C17.4698 2.76707 17.347 3.28035 16.9452 3.51466C16.5545 3.74897 16.0298 3.62623 15.7954 3.22455L14.6233 1.27198C14.467 1.01535 14.467 0.691785 14.6121 0.435161C14.7572 0.16738 15.0363 0.0111685 15.3377 0.0111685C20.1043 0.0111685 23.9889 3.894 23.9889 8.65828C24.0001 9.11574 23.6206 9.4951 23.1629 9.4951Z" + fill="currentColor" + /> + </svg> + ); +} +export default SvgLanguage; diff --git a/widget/ui/src/icons/index.ts b/widget/ui/src/icons/index.ts index bfd279ff81..25c51651ec 100644 --- a/widget/ui/src/icons/index.ts +++ b/widget/ui/src/icons/index.ts @@ -19,6 +19,7 @@ export { default as GasIcon } from './Gas'; export { default as InProgressIcon } from './InProgress'; export { default as InfoErrorIcon } from './InfoError'; export { default as InfoIcon } from './Info'; +export { default as LanguageIcon } from './Language'; export { default as LightModeIcon } from './LightMode'; export { default as LinkIcon } from './Link'; export { default as LoadingIcon } from './Loading'; diff --git a/widget/ui/svgs/resources/fill/Language.svg b/widget/ui/svgs/resources/fill/Language.svg new file mode 100644 index 0000000000..b3b4f9e9e6 --- /dev/null +++ b/widget/ui/svgs/resources/fill/Language.svg @@ -0,0 +1,12 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15.1145 20.2844C14.9917 20.2844 14.8578 20.251 14.7461 20.1952C14.3331 19.9832 14.1657 19.4811 14.3666 19.0683L16.7554 14.304C16.9006 14.0251 17.1908 13.8466 17.5034 13.8466C17.8159 13.8466 18.1062 14.0251 18.2513 14.3152L20.6401 19.0795C20.8522 19.4923 20.6848 19.9943 20.2606 20.2063C19.8476 20.4183 19.3452 20.251 19.1331 19.827L17.5034 16.5579L15.8736 19.827C15.7173 20.1171 15.4159 20.2844 15.1145 20.2844Z" fill="#010101"/> +<path d="M19.457 19.4364H15.5277C15.07 19.4364 14.6905 19.057 14.6905 18.5996C14.6905 18.1421 15.07 17.7628 15.5277 17.7628H19.457C19.9147 17.7628 20.2943 18.1421 20.2943 18.5996C20.2943 19.057 19.9259 19.4364 19.457 19.4364Z" fill="#010101"/> +<path d="M17.492 24C13.9088 24 10.9841 21.0879 10.9841 17.4951C10.9841 13.9024 13.8976 10.9903 17.492 10.9903C21.0753 10.9903 24 13.9024 24 17.4951C24 21.0879 21.0865 24 17.492 24ZM17.492 12.675C14.8241 12.675 12.6585 14.8396 12.6585 17.5063C12.6585 20.1729 14.8241 22.3375 17.492 22.3375C20.1488 22.3375 22.3256 20.1729 22.3256 17.5063C22.3256 14.8396 20.16 12.675 17.492 12.675Z" fill="#010101"/> +<path d="M4.0298 12.7866C2.79072 12.7866 1.80838 12.4407 1.11629 11.7712C0.379538 11.0571 0 9.97487 0 8.58017V4.20642C0 1.49514 1.49583 0 4.20841 0H8.58425C9.97961 0 11.0512 0.3682 11.7768 1.11576C12.4801 1.841 12.8261 2.88985 12.7927 4.22876V8.58017C12.8261 9.94139 12.4801 11.0125 11.7545 11.7378C11.0289 12.463 9.95727 12.7977 8.57308 12.7754H4.21956C4.14142 12.7866 4.08561 12.7866 4.0298 12.7866ZM4.20841 1.6848C2.41118 1.6848 1.67443 2.42122 1.67443 4.21759V8.59134C1.67443 9.51742 1.87535 10.1868 2.27722 10.5773C2.66792 10.9567 3.29305 11.1241 4.17492 11.113H8.57308C9.51076 11.1353 10.1582 10.9456 10.5489 10.5551C10.9396 10.1646 11.1182 9.50627 11.0959 8.60251V4.20642C11.1182 3.31382 10.9396 2.6778 10.5601 2.28729C10.1694 1.88561 9.49959 1.6848 8.57308 1.6848H4.20841Z" fill="#010101"/> +<path d="M8.65116 5.9803H4.11903C3.66136 5.9803 3.28182 5.60095 3.28182 5.14349C3.28182 4.68603 3.66136 4.30667 4.11903 4.30667H8.65116C9.10883 4.30667 9.48837 4.68603 9.48837 5.14349C9.48837 5.60095 9.12 5.9803 8.65116 5.9803Z" fill="#010101"/> +<path d="M6.3963 5.98037C5.93862 5.98037 5.55909 5.60101 5.55909 5.14355V4.38485C5.55909 3.92739 5.93862 3.54803 6.3963 3.54803C6.85398 3.54803 7.23352 3.92739 7.23352 4.38485V5.14355C7.23352 5.60101 6.85398 5.98037 6.3963 5.98037Z" fill="#010101"/> +<path d="M4.11903 9.5062C3.66136 9.5062 3.28182 9.12684 3.28182 8.66938C3.28182 8.21192 3.66136 7.83256 4.11903 7.83256C5.53672 7.83256 6.6865 6.62757 6.6865 5.13245C6.6865 4.67499 7.06603 4.29564 7.52371 4.29564C7.98139 4.29564 8.36093 4.67499 8.36093 5.13245C8.36093 7.54249 6.46324 9.5062 4.11903 9.5062Z" fill="#010101"/> +<path d="M8.66231 9.50619C7.62417 9.50619 6.63067 8.9818 5.92741 8.05572C5.64834 7.68752 5.72649 7.16306 6.09487 6.88413C6.46324 6.60519 6.98788 6.68332 7.26695 7.05152C7.64649 7.56476 8.14882 7.84373 8.66231 7.84373C9.11999 7.84373 9.49953 8.22308 9.49953 8.68054C9.49953 9.13801 9.11999 9.50619 8.66231 9.50619Z" fill="#010101"/> +<path d="M8.65122 23.9999C3.88468 23.9999 0 20.1171 0 15.3528C0 14.8954 0.379538 14.516 0.837215 14.516C1.29489 14.516 1.67443 14.8954 1.67443 15.3528C1.67443 18.6555 3.97398 21.4226 7.0661 22.1478L6.7647 21.6457C6.53028 21.244 6.65308 20.7308 7.05494 20.4964C7.44564 20.2621 7.9703 20.3849 8.20472 20.7865L9.3768 22.7391C9.53308 22.9957 9.5331 23.3193 9.38798 23.5759C9.2317 23.8326 8.95262 23.9999 8.65122 23.9999Z" fill="#010101"/> +<path d="M23.1629 9.4951C22.7052 9.4951 22.3257 9.11574 22.3257 8.65828C22.3257 5.35564 20.0261 2.58854 16.934 1.86329L17.2354 2.3654C17.4698 2.76707 17.347 3.28035 16.9452 3.51466C16.5545 3.74897 16.0298 3.62623 15.7954 3.22455L14.6233 1.27198C14.467 1.01535 14.467 0.691785 14.6121 0.435161C14.7572 0.16738 15.0363 0.0111685 15.3377 0.0111685C20.1043 0.0111685 23.9889 3.894 23.9889 8.65828C24.0001 9.11574 23.6206 9.4951 23.1629 9.4951Z" fill="#010101"/> +</svg>