feat: add i18n
This commit is contained in:
parent
0e16b4f70a
commit
3516914ad3
BIN
offline_node_modules/cross-fetch-npm-4.0.0-9c67668db4-386727dc4c.zip
generated
Normal file
BIN
offline_node_modules/cross-fetch-npm-4.0.0-9c67668db4-386727dc4c.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/html-parse-stringify-npm-3.0.1-5762cd4b01-159292753d.zip
generated
Normal file
BIN
offline_node_modules/html-parse-stringify-npm-3.0.1-5762cd4b01-159292753d.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/i18next-browser-languagedetector-npm-8.0.0-fcff5207d7-08a7c747ec.zip
generated
Normal file
BIN
offline_node_modules/i18next-browser-languagedetector-npm-8.0.0-fcff5207d7-08a7c747ec.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/i18next-http-backend-npm-2.5.2-6cbbe5e7c3-57cfbeeea4.zip
generated
Normal file
BIN
offline_node_modules/i18next-http-backend-npm-2.5.2-6cbbe5e7c3-57cfbeeea4.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/i18next-npm-23.11.5-27df1f473c-b0bec64250.zip
generated
Normal file
BIN
offline_node_modules/i18next-npm-23.11.5-27df1f473c-b0bec64250.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/node-fetch-npm-2.7.0-587d57004e-b55786b602.zip
generated
Normal file
BIN
offline_node_modules/node-fetch-npm-2.7.0-587d57004e-b55786b602.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/react-i18next-npm-14.1.2-9873475bd7-cb8a83b369.zip
generated
Normal file
BIN
offline_node_modules/react-i18next-npm-14.1.2-9873475bd7-cb8a83b369.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/tr46-npm-0.0.3-de53018915-047cb209a6.zip
generated
Normal file
BIN
offline_node_modules/tr46-npm-0.0.3-de53018915-047cb209a6.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/void-elements-npm-3.1.0-4f43780839-0b8686f9f9.zip
generated
Normal file
BIN
offline_node_modules/void-elements-npm-3.1.0-4f43780839-0b8686f9f9.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/webidl-conversions-npm-3.0.1-60310f6a2b-5612d5f3e5.zip
generated
Normal file
BIN
offline_node_modules/webidl-conversions-npm-3.0.1-60310f6a2b-5612d5f3e5.zip
generated
Normal file
Binary file not shown.
BIN
offline_node_modules/whatwg-url-npm-5.0.0-374fb45e60-1588bed84d.zip
generated
Normal file
BIN
offline_node_modules/whatwg-url-npm-5.0.0-374fb45e60-1588bed84d.zip
generated
Normal file
Binary file not shown.
@ -38,12 +38,16 @@
|
|||||||
"@mui/material": "5.15.19",
|
"@mui/material": "5.15.19",
|
||||||
"@react-spring/web": "9.7.3",
|
"@react-spring/web": "9.7.3",
|
||||||
"classnames": "2.5.1",
|
"classnames": "2.5.1",
|
||||||
|
"i18next": "23.11.5",
|
||||||
|
"i18next-browser-languagedetector": "8.0.0",
|
||||||
|
"i18next-http-backend": "2.5.2",
|
||||||
"notistack": "3.0.1",
|
"notistack": "3.0.1",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dnd": "16.0.1",
|
"react-dnd": "16.0.1",
|
||||||
"react-dnd-html5-backend": "16.0.1",
|
"react-dnd-html5-backend": "16.0.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
|
"react-i18next": "14.1.2",
|
||||||
"react-router-dom": "6.23.1",
|
"react-router-dom": "6.23.1",
|
||||||
"workbox-core": "7.1.0",
|
"workbox-core": "7.1.0",
|
||||||
"workbox-precaching": "7.1.0",
|
"workbox-precaching": "7.1.0",
|
||||||
|
|||||||
4
public/locales/en/analyze-page.json
Normal file
4
public/locales/en/analyze-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Analyze Page",
|
||||||
|
"toolbar": "Analyze Page Toolbar"
|
||||||
|
}
|
||||||
5
public/locales/en/error-page.json
Normal file
5
public/locales/en/error-page.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"title": "Something goes wrong",
|
||||||
|
"toolbar": "Unhandled error",
|
||||||
|
"404-toolbar": "Page does not exist"
|
||||||
|
}
|
||||||
4
public/locales/en/payments-page.json
Normal file
4
public/locales/en/payments-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Payments Page",
|
||||||
|
"toolbar": "Payments Page Toolbar"
|
||||||
|
}
|
||||||
4
public/locales/en/schedule-page.json
Normal file
4
public/locales/en/schedule-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Schedule Page",
|
||||||
|
"toolbar": "Schedule Page Toolbar"
|
||||||
|
}
|
||||||
5
public/locales/en/sidebar.json
Normal file
5
public/locales/en/sidebar.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"analyze-page-link": "Analyze",
|
||||||
|
"payments-page-link": "Payments list",
|
||||||
|
"schedule-page-link": "Schedule"
|
||||||
|
}
|
||||||
3
public/locales/en/translation.json
Normal file
3
public/locales/en/translation.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"language": "English"
|
||||||
|
}
|
||||||
4
public/locales/ru/analyze-page.json
Normal file
4
public/locales/ru/analyze-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Аналитика",
|
||||||
|
"toolbar": "Доска аналитики"
|
||||||
|
}
|
||||||
5
public/locales/ru/error-page.json
Normal file
5
public/locales/ru/error-page.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"title": "Что-то пошло не так",
|
||||||
|
"toolbar": "Произошла непредвиденная ошибка",
|
||||||
|
"404-toolbar": "Такой страницы не существует"
|
||||||
|
}
|
||||||
4
public/locales/ru/payments-page.json
Normal file
4
public/locales/ru/payments-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "Платежи",
|
||||||
|
"toolbar": "Доска платежей"
|
||||||
|
}
|
||||||
4
public/locales/ru/schedule-page.json
Normal file
4
public/locales/ru/schedule-page.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"title": "График платежей",
|
||||||
|
"toolbar": "Доска графика платежей"
|
||||||
|
}
|
||||||
5
public/locales/ru/sidebar.json
Normal file
5
public/locales/ru/sidebar.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"analyze-page-link": "Аналитика",
|
||||||
|
"payments-page-link": "Список платежей",
|
||||||
|
"schedule-page-link": "График платежей"
|
||||||
|
}
|
||||||
3
public/locales/ru/translation.json
Normal file
3
public/locales/ru/translation.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"language": "Русский"
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
|
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
|
||||||
import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted';
|
import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted';
|
||||||
import PieChartIcon from '@mui/icons-material/PieChart';
|
import PieChartIcon from '@mui/icons-material/PieChart';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { createBrowserRouter, Navigate, RouterProvider as RRDRouterProvider } from 'react-router-dom';
|
import { createBrowserRouter, Navigate, RouterProvider as RRDRouterProvider } from 'react-router-dom';
|
||||||
|
|
||||||
import { AnalyzePage, AnalyzePageToolbar } from 'pages/AnalyzePage';
|
import { AnalyzePage, AnalyzePageToolbar } from 'pages/AnalyzePage';
|
||||||
@ -11,6 +11,7 @@ import { PaymentsPage, PaymentsPageToolbar } from 'pages/PaymentsPage';
|
|||||||
import { SchedulePage, SchedulePageToolbar } from 'pages/SchedulePage';
|
import { SchedulePage, SchedulePageToolbar } from 'pages/SchedulePage';
|
||||||
|
|
||||||
import { AsideMenuLayout } from 'widgets/AsideMenuLayout';
|
import { AsideMenuLayout } from 'widgets/AsideMenuLayout';
|
||||||
|
import { PageLoader } from 'widgets/PageLoader';
|
||||||
|
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import type { RouteObject } from 'react-router-dom';
|
import type { RouteObject } from 'react-router-dom';
|
||||||
@ -23,76 +24,78 @@ type PageListItem = {
|
|||||||
Toolbar?: ReactNode;
|
Toolbar?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const pages: PageListItem[] = [
|
const RouterProvider = () => {
|
||||||
{
|
const { t } = useTranslation('sidebar');
|
||||||
icon: <PieChartIcon />,
|
|
||||||
title: 'Аналитика',
|
|
||||||
path: '/analyze',
|
|
||||||
Content: (
|
|
||||||
<Suspense fallback={<CircularProgress />}>
|
|
||||||
<AnalyzePage />
|
|
||||||
</Suspense>
|
|
||||||
),
|
|
||||||
Toolbar: <AnalyzePageToolbar />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <CalendarMonthIcon />,
|
|
||||||
title: 'График платежей',
|
|
||||||
path: '/schedule',
|
|
||||||
Content: (
|
|
||||||
<Suspense fallback={<CircularProgress />}>
|
|
||||||
<SchedulePage />
|
|
||||||
</Suspense>
|
|
||||||
),
|
|
||||||
Toolbar: <SchedulePageToolbar />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <FormatListBulletedIcon />,
|
|
||||||
title: 'Список платежей',
|
|
||||||
path: '/payments',
|
|
||||||
Content: (
|
|
||||||
<Suspense fallback={<CircularProgress />}>
|
|
||||||
<PaymentsPage />
|
|
||||||
</Suspense>
|
|
||||||
),
|
|
||||||
Toolbar: <PaymentsPageToolbar />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const routes: RouteObject[] = pages.map((page) => ({
|
const pages: PageListItem[] = [
|
||||||
path: page.path,
|
{
|
||||||
element: (
|
icon: <PieChartIcon />,
|
||||||
|
title: t('analyze-page-link'),
|
||||||
|
path: '/analyze',
|
||||||
|
Content: <AnalyzePage />,
|
||||||
|
Toolbar: <AnalyzePageToolbar />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <CalendarMonthIcon />,
|
||||||
|
title: t('schedule-page-link'),
|
||||||
|
path: '/schedule',
|
||||||
|
Content: <SchedulePage />,
|
||||||
|
Toolbar: <SchedulePageToolbar />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <FormatListBulletedIcon />,
|
||||||
|
title: t('payments-page-link'),
|
||||||
|
path: '/payments',
|
||||||
|
Content: <PaymentsPage />,
|
||||||
|
Toolbar: <PaymentsPageToolbar />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const Fallback = (
|
||||||
<AsideMenuLayout
|
<AsideMenuLayout
|
||||||
Content={page.Content}
|
Content={<PageLoader />}
|
||||||
pages={pages}
|
pages={pages}
|
||||||
Toolbar={page.Toolbar}
|
|
||||||
/>
|
/>
|
||||||
),
|
);
|
||||||
errorElement: (
|
const routes: RouteObject[] = pages.map((page) => ({
|
||||||
<AsideMenuLayout
|
path: page.path,
|
||||||
Content={<ErrorPage />}
|
element: (
|
||||||
pages={pages}
|
<Suspense fallback={Fallback}>
|
||||||
Toolbar={<ErrorPageToolbar />}
|
<AsideMenuLayout
|
||||||
/>
|
Content={page.Content}
|
||||||
),
|
pages={pages}
|
||||||
}));
|
Toolbar={page.Toolbar}
|
||||||
const router = createBrowserRouter([
|
/>
|
||||||
...routes,
|
</Suspense>
|
||||||
{
|
),
|
||||||
path: '/',
|
|
||||||
element: <Navigate replace to="/analyze" />,
|
|
||||||
errorElement: (
|
errorElement: (
|
||||||
<AsideMenuLayout
|
<Suspense fallback={Fallback}>
|
||||||
Content={<ErrorPage type="404" />}
|
<AsideMenuLayout
|
||||||
pages={pages}
|
Content={<ErrorPage />}
|
||||||
Toolbar={<ErrorPageToolbar type="404" />}
|
pages={pages}
|
||||||
/>
|
Toolbar={<ErrorPageToolbar />}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
),
|
),
|
||||||
},
|
}));
|
||||||
]);
|
|
||||||
|
|
||||||
const RouterProvider = () => (
|
const router = createBrowserRouter([
|
||||||
<RRDRouterProvider router={router} />
|
...routes,
|
||||||
);
|
{
|
||||||
|
path: '/',
|
||||||
|
element: <Navigate replace to="/analyze" />,
|
||||||
|
errorElement: (
|
||||||
|
<AsideMenuLayout
|
||||||
|
Content={<ErrorPage type="404" />}
|
||||||
|
pages={pages}
|
||||||
|
Toolbar={<ErrorPageToolbar type="404" />}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RRDRouterProvider router={router} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default RouterProvider;
|
export default RouterProvider;
|
||||||
|
|||||||
1
src/features/LangSwitcher/index.ts
Normal file
1
src/features/LangSwitcher/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as LangSwitcher } from './ui/LangSwitcher.ui';
|
||||||
30
src/features/LangSwitcher/ui/LangSwitcher.ui.tsx
Normal file
30
src/features/LangSwitcher/ui/LangSwitcher.ui.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import i18next from 'i18n';
|
||||||
|
|
||||||
|
import { LANGUAGE } from 'shared/constants';
|
||||||
|
|
||||||
|
import type { FC, ChangeEventHandler } from 'react';
|
||||||
|
|
||||||
|
const LangSwitcher: FC = () => {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
|
const onChangedHandler = useCallback<ChangeEventHandler<HTMLSelectElement>>(async (e) => {
|
||||||
|
await i18next.changeLanguage(e.target.value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select value={i18n.language} onChange={onChangedHandler}>
|
||||||
|
{Object.entries(LANGUAGE).map(([lang, params]) => (
|
||||||
|
<option key={lang} value={lang}>
|
||||||
|
{params.emoji}
|
||||||
|
|
||||||
|
{params.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LangSwitcher;
|
||||||
22
src/i18n.ts
Normal file
22
src/i18n.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import i18n from 'i18next';
|
||||||
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
|
import Backend from 'i18next-http-backend';
|
||||||
|
import { initReactI18next } from 'react-i18next';
|
||||||
|
|
||||||
|
import type { HttpBackendOptions } from 'i18next-http-backend';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
i18n
|
||||||
|
.use(Backend)
|
||||||
|
.use(LanguageDetector)
|
||||||
|
.use(initReactI18next)
|
||||||
|
.init<HttpBackendOptions>({
|
||||||
|
fallbackLng: 'en',
|
||||||
|
debug: process.env.NODE_ENV === 'development',
|
||||||
|
load: 'currentOnly',
|
||||||
|
backend: {
|
||||||
|
loadPath: 'locales/{{lng}}/{{ns}}.json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import './i18n';
|
||||||
import 'shared/styles/fonts/fonts.css';
|
import 'shared/styles/fonts/fonts.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
type AnalyzePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
type AnalyzePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
const AnalyzePage: FC<AnalyzePageProps> = (props) => (
|
const AnalyzePage: FC<AnalyzePageProps> = (props) => {
|
||||||
<div {...props}>
|
const { t } = useTranslation('analyze-page');
|
||||||
Analyze page
|
|
||||||
</div>
|
return (
|
||||||
);
|
<div {...props}>
|
||||||
|
{t('title')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default AnalyzePage;
|
export default AnalyzePage;
|
||||||
|
|||||||
@ -1,15 +1,20 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
type AnalyzePageToolbarProps = ToolbarProps;
|
type AnalyzePageToolbarProps = ToolbarProps;
|
||||||
const AnalyzePageToolbar: FC<AnalyzePageToolbarProps> = (props) => (
|
const AnalyzePageToolbar: FC<AnalyzePageToolbarProps> = (props) => {
|
||||||
<Toolbar {...props}>
|
const { t } = useTranslation('analyze-page');
|
||||||
<Typography noWrap component="div" variant="h6">
|
|
||||||
Analyze Page Toolbar
|
return (
|
||||||
</Typography>
|
<Toolbar {...props}>
|
||||||
</Toolbar>
|
<Typography noWrap component="div" variant="h6">
|
||||||
);
|
{t('toolbar')}
|
||||||
|
</Typography>
|
||||||
|
</Toolbar>
|
||||||
|
);
|
||||||
|
};
|
||||||
export default AnalyzePageToolbar;
|
export default AnalyzePageToolbar;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Grid } from '@mui/material';
|
import { Grid } from '@mui/material';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import _404Image from 'public/assets/images/404.png';
|
import _404Image from 'public/assets/images/404.png';
|
||||||
import OopsImage from 'public/assets/images/oops.png';
|
import OopsImage from 'public/assets/images/oops.png';
|
||||||
@ -16,6 +17,8 @@ const ErrorPage: FC<ErrorPageProps> = (props) => {
|
|||||||
...restProps
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const { t } = useTranslation('error-page');
|
||||||
|
|
||||||
if (type === 'ErrorBoundary') {
|
if (type === 'ErrorBoundary') {
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
@ -28,7 +31,7 @@ const ErrorPage: FC<ErrorPageProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
Что-то пошло не так
|
{t('title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@ -8,17 +9,19 @@ export type ErrorPageToolbarProps = ToolbarProps & {
|
|||||||
type?: '404' | 'ErrorBoundary';
|
type?: '404' | 'ErrorBoundary';
|
||||||
};
|
};
|
||||||
|
|
||||||
const TITLE: Record<NonNullable<ErrorPageToolbarProps['type']>, string> = {
|
|
||||||
404: 'Страницы не существует',
|
|
||||||
ErrorBoundary: 'Непредвиденная ошибка',
|
|
||||||
};
|
|
||||||
|
|
||||||
const ErrorPageToolbar: FC<ErrorPageToolbarProps> = (props) => {
|
const ErrorPageToolbar: FC<ErrorPageToolbarProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
type = 'ErrorBoundary',
|
type = 'ErrorBoundary',
|
||||||
...restProps
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const { t } = useTranslation('error-page');
|
||||||
|
|
||||||
|
const TITLE: Record<NonNullable<ErrorPageToolbarProps['type']>, string> = {
|
||||||
|
404: t('404-toolbar'),
|
||||||
|
ErrorBoundary: t('toolbar'),
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toolbar {...restProps}>
|
<Toolbar {...restProps}>
|
||||||
<Typography noWrap component="div" variant="h6">
|
<Typography noWrap component="div" variant="h6">
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
export type PaymentsPageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
export type PaymentsPageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
const PaymentsPage: FC<PaymentsPageProps> = (props) => (
|
const PaymentsPage: FC<PaymentsPageProps> = (props) => {
|
||||||
<div {...props}>
|
const { t } = useTranslation('payments-page');
|
||||||
Payments Page
|
|
||||||
</div>
|
return (
|
||||||
);
|
<div {...props}>
|
||||||
|
{t('title')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default PaymentsPage;
|
export default PaymentsPage;
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
export type PaymentsPageToolbarProps = ToolbarProps;
|
export type PaymentsPageToolbarProps = ToolbarProps;
|
||||||
const PaymentsPageToolbar: FC<PaymentsPageToolbarProps> = (props) => (
|
const PaymentsPageToolbar: FC<PaymentsPageToolbarProps> = (props) => {
|
||||||
<Toolbar {...props}>
|
const { t } = useTranslation('payments-page');
|
||||||
<Typography noWrap component="div" variant="h6">
|
|
||||||
Payments Page Toolbar
|
return (
|
||||||
</Typography>
|
<Toolbar {...props}>
|
||||||
</Toolbar>
|
<Typography noWrap component="div" variant="h6">
|
||||||
);
|
{t('toolbar')}
|
||||||
|
</Typography>
|
||||||
|
</Toolbar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default PaymentsPageToolbar;
|
export default PaymentsPageToolbar;
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
export type SchedulePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
export type SchedulePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
const SchedulePage: FC<SchedulePageProps> = (props) => (
|
const SchedulePage: FC<SchedulePageProps> = (props) => {
|
||||||
<div {...props}>
|
const { t } = useTranslation('schedule-page');
|
||||||
Schedule Page
|
|
||||||
</div>
|
return (
|
||||||
);
|
<div {...props}>
|
||||||
|
{t('title')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default SchedulePage;
|
export default SchedulePage;
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
type SchedulePageToolbarProps = ToolbarProps;
|
type SchedulePageToolbarProps = ToolbarProps;
|
||||||
const SchedulePageToolbar: FC<SchedulePageToolbarProps> = (props) => (
|
const SchedulePageToolbar: FC<SchedulePageToolbarProps> = (props) => {
|
||||||
<Toolbar {...props}>
|
const { t } = useTranslation('schedule-page');
|
||||||
<Typography noWrap component="div" variant="h6">
|
|
||||||
Schedule Page Toolbar
|
return (
|
||||||
</Typography>
|
<Toolbar {...props}>
|
||||||
</Toolbar>
|
<Typography noWrap component="div" variant="h6">
|
||||||
);
|
{t('toolbar')}
|
||||||
|
</Typography>
|
||||||
|
</Toolbar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default SchedulePageToolbar;
|
export default SchedulePageToolbar;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export { DAYS_IN_WEEK, MONTHS, WEEK_DAYS } from './date';
|
export { DAYS_IN_WEEK, MONTHS, WEEK_DAYS } from './date';
|
||||||
export { MONTHS_LABEL, WEEK_DAYS_LABEL } from './locale';
|
export { MONTHS_LABEL, WEEK_DAYS_LABEL, LANGUAGE } from './locale';
|
||||||
export type {
|
export type {
|
||||||
MonthsKeys,
|
MonthsKeys,
|
||||||
MonthsValues,
|
MonthsValues,
|
||||||
|
|||||||
@ -136,3 +136,14 @@ export const WEEK_DAYS_LABEL: Record<WeekDaysValues, WeekDaysLabelLocale> = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LANGUAGE = {
|
||||||
|
ru: {
|
||||||
|
name: 'Русский',
|
||||||
|
emoji: '🇷🇺',
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
name: 'English',
|
||||||
|
emoji: '🇬🇧',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import { animated, useTransition } from '@react-spring/web';
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { LangSwitcher } from 'features/LangSwitcher';
|
||||||
|
|
||||||
import { DesktopAppBar, MobileAppBar } from './components/AppBar';
|
import { DesktopAppBar, MobileAppBar } from './components/AppBar';
|
||||||
import { AsideMenuContext, AsideMenuProvider } from './components/AsideMenuProvider';
|
import { AsideMenuContext, AsideMenuProvider } from './components/AsideMenuProvider';
|
||||||
import { DesktopDrawer } from './components/DesktopDrawer';
|
import { DesktopDrawer } from './components/DesktopDrawer';
|
||||||
@ -15,6 +17,7 @@ import { MobileDrawer } from './components/MobileDrawer';
|
|||||||
|
|
||||||
import type { MenuItemProps } from './components/MenuItem/ui/MenuItem.ui';
|
import type { MenuItemProps } from './components/MenuItem/ui/MenuItem.ui';
|
||||||
import type { BoxProps } from '@mui/material/Box/Box';
|
import type { BoxProps } from '@mui/material/Box/Box';
|
||||||
|
// eslint-disable-next-line import/max-dependencies
|
||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
|
|
||||||
export const DESKTOP_DRAWER_WIDTH = 250;
|
export const DESKTOP_DRAWER_WIDTH = 250;
|
||||||
@ -32,7 +35,6 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
Toolbar,
|
Toolbar,
|
||||||
...restProps
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { desktopDrawerOpen, setMobileDrawerOpen } = useContext(AsideMenuContext);
|
const { desktopDrawerOpen, setMobileDrawerOpen } = useContext(AsideMenuContext);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobileView = useMediaQuery(theme.breakpoints.down('sm'));
|
const isMobileView = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
@ -49,7 +51,7 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
const AnimatedContent = (
|
const AnimatedContent = (
|
||||||
<>
|
<>
|
||||||
{transitions((styles) => (
|
{transitions((styles) => (
|
||||||
<animated.div style={styles}>
|
<animated.div style={{ ...styles, height: '100%' }}>
|
||||||
{Content}
|
{Content}
|
||||||
</animated.div>
|
</animated.div>
|
||||||
))}
|
))}
|
||||||
@ -85,6 +87,8 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
</MobileDrawer>
|
</MobileDrawer>
|
||||||
|
|
||||||
{AnimatedToolBar}
|
{AnimatedToolBar}
|
||||||
|
|
||||||
|
<LangSwitcher />
|
||||||
</MobileAppBar>
|
</MobileAppBar>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -113,14 +117,16 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
</List>
|
</List>
|
||||||
</DesktopDrawer>
|
</DesktopDrawer>
|
||||||
|
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1, height: '100vh' }}>
|
||||||
{ Boolean(Toolbar) && (
|
{ Boolean(Toolbar) && (
|
||||||
<DesktopAppBar position="static">
|
<DesktopAppBar position="static">
|
||||||
{AnimatedToolBar}
|
{AnimatedToolBar}
|
||||||
|
|
||||||
|
<LangSwitcher />
|
||||||
</DesktopAppBar>
|
</DesktopAppBar>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Box component="main" sx={{ p: 3 }}>
|
<Box component="main" sx={{ p: 3, height: '100%' }}>
|
||||||
{AnimatedContent}
|
{AnimatedContent}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
1
src/widgets/PageLoader/index.ts
Normal file
1
src/widgets/PageLoader/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as PageLoader } from './ui/PageLoader.ui';
|
||||||
20
src/widgets/PageLoader/ui/PageLoader.ui.tsx
Normal file
20
src/widgets/PageLoader/ui/PageLoader.ui.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
|
||||||
|
const CenteredDiv = styled('div')(
|
||||||
|
() => ({
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const PageLoader = () => (
|
||||||
|
<CenteredDiv>
|
||||||
|
<CircularProgress />
|
||||||
|
</CenteredDiv>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default PageLoader;
|
||||||
114
yarn.lock
114
yarn.lock
@ -2671,7 +2671,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/runtime@npm:^7.11.2":
|
"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.23.2":
|
||||||
version: 7.24.7
|
version: 7.24.7
|
||||||
resolution: "@babel/runtime@npm:7.24.7"
|
resolution: "@babel/runtime@npm:7.24.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7769,6 +7769,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"cross-fetch@npm:4.0.0":
|
||||||
|
version: 4.0.0
|
||||||
|
resolution: "cross-fetch@npm:4.0.0"
|
||||||
|
dependencies:
|
||||||
|
node-fetch: "npm:^2.6.12"
|
||||||
|
checksum: 10c0/386727dc4c6b044746086aced959ff21101abb85c43df5e1d151547ccb6f338f86dec3f28b9dbddfa8ff5b9ec8662ed2263ad4607a93b2dc354fb7fe3bbb898a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
|
"cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
resolution: "cross-spawn@npm:7.0.3"
|
resolution: "cross-spawn@npm:7.0.3"
|
||||||
@ -10579,6 +10588,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"html-parse-stringify@npm:^3.0.1":
|
||||||
|
version: 3.0.1
|
||||||
|
resolution: "html-parse-stringify@npm:3.0.1"
|
||||||
|
dependencies:
|
||||||
|
void-elements: "npm:3.1.0"
|
||||||
|
checksum: 10c0/159292753d48b84d216d61121054ae5a33466b3db5b446e2ffc093ac077a411a99ce6cbe0d18e55b87cf25fa3c5a86c4d8b130b9719ec9b66623259000c72c15
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"html-webpack-plugin@npm:5.6.0":
|
"html-webpack-plugin@npm:5.6.0":
|
||||||
version: 5.6.0
|
version: 5.6.0
|
||||||
resolution: "html-webpack-plugin@npm:5.6.0"
|
resolution: "html-webpack-plugin@npm:5.6.0"
|
||||||
@ -10751,6 +10769,33 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"i18next-browser-languagedetector@npm:8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "i18next-browser-languagedetector@npm:8.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.23.2"
|
||||||
|
checksum: 10c0/08a7c747ec18a0743b54390a0b42836d814b15fb49c92b90c259298e6a6e7e001ff9df99d0fd308283a34fceea53b4d9053aa1695a37f696bc04160017bbb524
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"i18next-http-backend@npm:2.5.2":
|
||||||
|
version: 2.5.2
|
||||||
|
resolution: "i18next-http-backend@npm:2.5.2"
|
||||||
|
dependencies:
|
||||||
|
cross-fetch: "npm:4.0.0"
|
||||||
|
checksum: 10c0/57cfbeeea40a751134e1521fac89b14b780c9ad87b74a4f7d7168a88a8b603efed9f5df455dddbb408f7e268eae5aa0a6888e47b9f10cb9482d812d4d6997ffa
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"i18next@npm:23.11.5":
|
||||||
|
version: 23.11.5
|
||||||
|
resolution: "i18next@npm:23.11.5"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.23.2"
|
||||||
|
checksum: 10c0/b0bec64250a3e529d4c51e2fc511406a85c5dde3d005d3aabe919551ca31dfc0a8f5490bf6e44649822e895a1fa91a58092d112367669cd11b2eb89e6ba90d1a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:0.4.24":
|
"iconv-lite@npm:0.4.24":
|
||||||
version: 0.4.24
|
version: 0.4.24
|
||||||
resolution: "iconv-lite@npm:0.4.24"
|
resolution: "iconv-lite@npm:0.4.24"
|
||||||
@ -13039,6 +13084,9 @@ __metadata:
|
|||||||
eslint-config-ksv741: "npm:0.0.3"
|
eslint-config-ksv741: "npm:0.0.3"
|
||||||
eslint-import-resolver-webpack: "npm:0.13.8"
|
eslint-import-resolver-webpack: "npm:0.13.8"
|
||||||
husky: "npm:9.0.11"
|
husky: "npm:9.0.11"
|
||||||
|
i18next: "npm:23.11.5"
|
||||||
|
i18next-browser-languagedetector: "npm:8.0.0"
|
||||||
|
i18next-http-backend: "npm:2.5.2"
|
||||||
identity-obj-proxy: "npm:3.0.0"
|
identity-obj-proxy: "npm:3.0.0"
|
||||||
jest: "npm:29.7.0"
|
jest: "npm:29.7.0"
|
||||||
jest-environment-jsdom: "npm:29.7.0"
|
jest-environment-jsdom: "npm:29.7.0"
|
||||||
@ -13050,6 +13098,7 @@ __metadata:
|
|||||||
react-dnd: "npm:16.0.1"
|
react-dnd: "npm:16.0.1"
|
||||||
react-dnd-html5-backend: "npm:16.0.1"
|
react-dnd-html5-backend: "npm:16.0.1"
|
||||||
react-dom: "npm:18.3.1"
|
react-dom: "npm:18.3.1"
|
||||||
|
react-i18next: "npm:14.1.2"
|
||||||
react-router-dom: "npm:6.23.1"
|
react-router-dom: "npm:6.23.1"
|
||||||
standard-version: "npm:9.5.0"
|
standard-version: "npm:9.5.0"
|
||||||
ts-jest: "npm:29.1.4"
|
ts-jest: "npm:29.1.4"
|
||||||
@ -13156,6 +13205,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"node-fetch@npm:^2.6.12":
|
||||||
|
version: 2.7.0
|
||||||
|
resolution: "node-fetch@npm:2.7.0"
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: "npm:^5.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"node-forge@npm:^1":
|
"node-forge@npm:^1":
|
||||||
version: 1.3.1
|
version: 1.3.1
|
||||||
resolution: "node-forge@npm:1.3.1"
|
resolution: "node-forge@npm:1.3.1"
|
||||||
@ -14857,6 +14920,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-i18next@npm:14.1.2":
|
||||||
|
version: 14.1.2
|
||||||
|
resolution: "react-i18next@npm:14.1.2"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.23.9"
|
||||||
|
html-parse-stringify: "npm:^3.0.1"
|
||||||
|
peerDependencies:
|
||||||
|
i18next: ">= 23.2.3"
|
||||||
|
react: ">= 16.8.0"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
react-native:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/cb8a83b3696639f083dc9f770d9d9e0681c0fe56f6b5fe24cd6facce08d363c37bd3440078e9d63abacabd7037b783e6b4e4d0c935de9c8dda7820bd4ef7e329
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-is@npm:^16.13.1, react-is@npm:^16.7.0":
|
"react-is@npm:^16.13.1, react-is@npm:^16.7.0":
|
||||||
version: 16.13.1
|
version: 16.13.1
|
||||||
resolution: "react-is@npm:16.13.1"
|
resolution: "react-is@npm:16.13.1"
|
||||||
@ -16587,6 +16668,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"tr46@npm:~0.0.3":
|
||||||
|
version: 0.0.3
|
||||||
|
resolution: "tr46@npm:0.0.3"
|
||||||
|
checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"trim-newlines@npm:^3.0.0":
|
"trim-newlines@npm:^3.0.0":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "trim-newlines@npm:3.0.1"
|
resolution: "trim-newlines@npm:3.0.1"
|
||||||
@ -17134,6 +17222,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"void-elements@npm:3.1.0":
|
||||||
|
version: 3.1.0
|
||||||
|
resolution: "void-elements@npm:3.1.0"
|
||||||
|
checksum: 10c0/0b8686f9f9aa44012e9bd5eabf287ae0cde409b9a2854c5a2335cb83920c957668ac5876e3f0d158dd424744ac411a7270e64128556b451ed3bec875ef18534d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"w3c-xmlserializer@npm:^4.0.0":
|
"w3c-xmlserializer@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "w3c-xmlserializer@npm:4.0.0"
|
resolution: "w3c-xmlserializer@npm:4.0.0"
|
||||||
@ -17171,6 +17266,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"webidl-conversions@npm:^3.0.0":
|
||||||
|
version: 3.0.1
|
||||||
|
resolution: "webidl-conversions@npm:3.0.1"
|
||||||
|
checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"webidl-conversions@npm:^4.0.2":
|
"webidl-conversions@npm:^4.0.2":
|
||||||
version: 4.0.2
|
version: 4.0.2
|
||||||
resolution: "webidl-conversions@npm:4.0.2"
|
resolution: "webidl-conversions@npm:4.0.2"
|
||||||
@ -17415,6 +17517,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"whatwg-url@npm:^5.0.0":
|
||||||
|
version: 5.0.0
|
||||||
|
resolution: "whatwg-url@npm:5.0.0"
|
||||||
|
dependencies:
|
||||||
|
tr46: "npm:~0.0.3"
|
||||||
|
webidl-conversions: "npm:^3.0.0"
|
||||||
|
checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"whatwg-url@npm:^7.0.0":
|
"whatwg-url@npm:^7.0.0":
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
resolution: "whatwg-url@npm:7.1.0"
|
resolution: "whatwg-url@npm:7.1.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user