You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import useLocale, { LocalesMap } from '@/utils/useLocale';
|
|
import { clsx } from 'clsx';
|
|
import { useRouter } from 'next/router';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import styles from './langSwitcher.module.scss';
|
|
import LanguageIcon from '@/assets/icons/language.svg';
|
|
import { CursorEffect } from '@/components/cursor';
|
|
|
|
type LangSwitcherProps = React.DetailedHTMLProps<
|
|
React.HTMLAttributes<HTMLDivElement>,
|
|
HTMLDivElement
|
|
> & {};
|
|
|
|
const locales: LocalesMap = {
|
|
ru: {
|
|
chooseHeader: 'Выберите язык',
|
|
},
|
|
en: {
|
|
chooseHeader: 'Choose language',
|
|
},
|
|
};
|
|
|
|
const localesMap: { [key: string]: string } = {
|
|
en: 'English',
|
|
ru: 'Русский',
|
|
};
|
|
|
|
export function LangSwitcher(props: LangSwitcherProps) {
|
|
const { className: restClassName, ...restProps } = props;
|
|
const router = useRouter();
|
|
const selectorRef = useRef(null);
|
|
const buttonRef = useRef(null);
|
|
const [open, setOpen] = useState(false);
|
|
const t = useLocale(locales);
|
|
const { pathname, asPath, query } = router;
|
|
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
|
|
const handleClose = (event: any) => {
|
|
setOpen(
|
|
event.composedPath().includes(selectorRef.current) ||
|
|
event.composedPath().includes(buttonRef.current)
|
|
);
|
|
};
|
|
|
|
addEventListener('click', handleClose, false);
|
|
|
|
return () => removeEventListener('click', handleClose, false);
|
|
}, [open]);
|
|
|
|
const handleSetLanguage = (locale: string) => () => {
|
|
router.push({ pathname, query }, asPath, { locale });
|
|
setOpen(false);
|
|
};
|
|
|
|
return (
|
|
<div className={clsx(styles.langSwitcher, restClassName)} {...restProps}>
|
|
<CursorEffect
|
|
effectDistance={48}
|
|
effectForce={4}
|
|
cursorPadding={0}
|
|
className={clsx(styles.langSwitcherRoot)}
|
|
>
|
|
<button
|
|
ref={buttonRef}
|
|
className={clsx(styles.currentLanguage, open && styles.hideCurrent)}
|
|
onClick={() => setOpen(true)}
|
|
>
|
|
<LanguageIcon />{' '}
|
|
<span className={styles.currentLangLabel}>
|
|
{localesMap[router.locale || 'en']}
|
|
</span>
|
|
</button>
|
|
</CursorEffect>
|
|
<div
|
|
ref={selectorRef}
|
|
className={clsx(styles.selector, open && styles.openSelector)}
|
|
>
|
|
<h5 className={styles.header}>{t('chooseHeader')}</h5>
|
|
<ul>
|
|
{Object.keys(localesMap).map((locale) => (
|
|
<CursorEffect
|
|
key={locale}
|
|
effectForce={2}
|
|
effectDistance={36}
|
|
cursorPadding={2}
|
|
cursorBorderRadius={8}
|
|
>
|
|
<button onClick={handleSetLanguage(locale)}>
|
|
{localesMap[locale]}
|
|
</button>
|
|
</CursorEffect>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |