feat(textpage): add text page layout

This commit is contained in:
Pavel Torbeev 2023-09-09 03:24:52 +03:00
parent 89d6b794bb
commit 3815bb7b5e
17 changed files with 670 additions and 14 deletions

View File

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@popperjs/core": "^2.11.8",
"@react-pdf/renderer": "^3.1.12",
"@seznam/compose-react-refs": "^1.0.6",
"@tanstack/react-query": "^4.33.0",
@ -13,6 +14,7 @@
"@types/node": "^16.7.13",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/react-transition-group": "^4.4.6",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"axios": "^1.4.0",
@ -35,8 +37,10 @@
"react-dropzone": "^14.2.3",
"react-helmet": "^6.1.0",
"react-hook-form": "^7.45.4",
"react-popper": "^2.3.0",
"react-router-dom": "^6.15.0",
"react-scripts": "5.0.1",
"react-transition-group": "^4.4.5",
"sanitize.css": "^13.0.0",
"sass": "^1.66.1",
"ts-key-enum": "^2.0.12",

View File

@ -1,19 +1,18 @@
import {Route, Routes} from 'react-router-dom';
import {ChatPage} from '../../pages/chat';
import {CHAT_PAGE_ROUTE, HOME_PAGE_ROUTE} from './routes';
import {HomePage} from '../../pages/home';
import {DefaultLayout} from '../../pages/_layouts/DefaultLayout';
import { Route, Routes } from 'react-router-dom';
import { ChatPage } from '../../pages/chat';
import { HomePage } from '../../pages/home';
import { DefaultLayout } from '../../pages/_layouts/DefaultLayout';
import { TextPage } from '../../pages/text';
import { CHAT_PAGE_ROUTE, HOME_PAGE_ROUTE, TEXT_PAGE_ROUTE } from './routes';
export const AppRoutes = () => {
return (
<Routes>
<Route element={<DefaultLayout />}>
<Route path={CHAT_PAGE_ROUTE} element={<ChatPage />} />
<Route path={HOME_PAGE_ROUTE} element={<HomePage />} />
<Route path={TEXT_PAGE_ROUTE} element={<TextPage />} />
</Route>
</Routes>
);
};

View File

@ -0,0 +1,5 @@
import { TEXT_PAGE_PARAM, TEXT_PAGE_ROUTE } from './routes';
export class PathBuilder {
static getTextPath = (id: number) => TEXT_PAGE_ROUTE.replace(`:${TEXT_PAGE_PARAM}`, String(id));
}

View File

@ -1,2 +1,3 @@
export * from './AppRoutes';
export * from './routes';
export * from './routes';
export * from './PathBuilder';

View File

@ -1,2 +1,5 @@
export const CHAT_PAGE_ROUTE = `/chat`;
export const HOME_PAGE_ROUTE = `/`;
export const TEXT_PAGE_PARAM = 'textId';
export const TEXT_PAGE_ROUTE = `/text/:${TEXT_PAGE_PARAM}`;

View File

@ -0,0 +1,51 @@
@import 'src/app/styles/vars';
.Link {
@include reset-button;
@include transition(border-color, color);
position: relative;
cursor: pointer;
&:hover,
&:active,
&:focus {
text-decoration: none;
outline: none;
}
}
.Link_disabled {
cursor: default;
}
.Link_standalone {
&.Link_size_large {
@include text-body-l-regular;
}
&.Link_size_medium {
@include text-body-m-regular;
}
&.Link_size_small {
@include text-body-s-regular;
}
}
.Link_variant_primary {
color: $color-brand-primary;
&.Link_hover:not(.Link_disabled),
&:hover:not(.Link_disabled, :active) {
color: $color-brand-hover;
}
&:active {
color: $color-brand-active;
}
}
.Link_underlined {
border-bottom: 1px solid currentcolor;
}

View File

@ -0,0 +1,119 @@
import React, { ElementType, JSX, MouseEvent } from 'react';
import clsx from 'clsx';
import { PolyExtends } from '../../utils/types';
import s from './Link.module.scss';
export const LinkDefaultComponent = 'a';
export type LinkDefaultComponentType = typeof LinkDefaultComponent;
export enum LinkVariant {
PRIMARY = 'primary'
// SECONDARY = 'secondary'
}
export enum LinkSize {
LARGE = 'large',
MEDIUM = 'medium',
SMALL = 'small'
}
export interface LinkPropsSelf<ComponentType extends React.ElementType> {
/**
* Дополнительный css-класс корневого элемента
*/
className?: string;
/**
* Основной слот
*/
children?: React.ReactNode;
/**
* Вариант оформления ссылки ("primary", "secondary")
*/
variant?: LinkVariant;
/**
* Вариант размера ссылки ("large", "medium", "small")
*/
size?: LinkSize;
/**
* hover состояние
*/
hover?: boolean;
/**
* Состояние неактивной ссылки. Компонент недоступен для действий пользователя
*/
disabled?: boolean;
/**
* Применять ли фиксированные свойства шрифта.
* Если не передать standalone, то свойства шрифта наследуются от родителя.
* Полезно в случае, если Link используется самостоятельно вне текстового блока.
*/
standalone?: boolean;
/**
* Подчеркивание ссылки
*/
underlined?: boolean;
/**
* Реф на корневой элемент
*/
innerRef?: React.ComponentProps<ComponentType>['ref'];
/**
* Событие клика
* @param e - объект события
*/
onClick?: (e: MouseEvent) => void;
}
export interface LinkComponentProps {
className: string;
onClick: (e: MouseEvent) => void;
}
export type LinkProps<ComponentType extends React.ElementType<LinkComponentProps> = LinkDefaultComponentType> =
PolyExtends<ComponentType, LinkPropsSelf<ComponentType>, React.ComponentProps<ComponentType>>;
export function Link(props: LinkProps<'button'>): JSX.Element;
export function Link<ComponentType extends ElementType>(props: LinkProps<ComponentType>): JSX.Element;
export function Link<ComponentType extends React.ElementType<LinkComponentProps> = LinkDefaultComponentType>({
className,
children,
variant = LinkVariant.PRIMARY,
size = LinkSize.MEDIUM,
disabled,
standalone,
underlined,
onClick,
component,
innerRef,
hover,
...props
}: LinkProps<ComponentType>) {
const handleClick = (e: MouseEvent) => {
if (disabled) e.preventDefault();
onClick?.(e);
};
const Component = component || LinkDefaultComponent;
// Тайпскрипт жалуется на сложный union тип, поэтому используем createElement
return React.createElement(
Component,
{
ref: innerRef,
className: clsx(
s.Link,
s[`Link_variant_${variant}`],
s[`Link_size_${size}`],
{
[s.Link_underlined]: underlined,
[s.Link_disabled]: disabled,
[s.Link_standalone]: standalone,
[s.Link_hover]: hover
},
className
),
onClick: handleClick,
...props
},
<>{children}</>
);
}

View File

@ -0,0 +1 @@
export * from './Link';

View File

@ -0,0 +1,66 @@
@import 'src/app/styles/vars';
.Tooltip {
display: flex;
}
.Tooltip__trigger {
position: relative;
}
.Tooltip__contentWrapper {
z-index: 1;
transition: opacity 0.15s ease-out;
}
.Tooltip__contentWrapper_entering,
.Tooltip__contentWrapper_entered {
opacity: 1;
}
.Tooltip__contentWrapper_exiting,
.Tooltip__contentWrapper_exited {
opacity: 0;
}
.Tooltip__title {
@include text-header-h4;
margin-bottom: $spacing-small-3x;
}
.Tooltip__content {
@include text-body-s-regular;
display: flex;
flex-direction: column;
padding: 8px 12px;
color: $color-text-quaternary;
border-radius: $radius-medium;
background-color: $color-text-primary;
}
.Tooltip__arrow {
color: $color-text-primary;
border: 7px solid transparent;
}
.Tooltip__arrow_top {
bottom: -13px;
border-top-color: currentcolor;
}
.Tooltip__arrow_right {
left: -13px;
border-right-color: currentcolor;
}
.Tooltip__arrow_bottom {
top: -13px;
border-bottom-color: currentcolor;
}
.Tooltip__arrow_left {
right: -13px;
border-left-color: currentcolor;
}

View File

@ -0,0 +1,146 @@
import React, { memo, ReactNode, useCallback, useRef, useState } from 'react';
import { usePopper } from 'react-popper';
import { Transition } from 'react-transition-group';
import clsx from 'clsx';
import { Placement } from '@popperjs/core';
import { useSingleTimeout } from '../../hooks/useSingleTimeout';
import { useToggle } from '../../hooks/useToggle';
import { useIsMobile } from '../../hooks/useIsMobile';
import s from './Tooltip.module.scss';
export interface TooltipProps {
className?: string;
children?: React.ReactElement;
title?: ReactNode;
content?: ReactNode;
placement?: Placement;
disableOnMobile?: boolean;
offset?: [number, number];
classes?: {
content?: string;
trigger?: string;
};
bgColor?: string;
}
const placementMapper: Partial<Record<Placement, string>> = {
bottom: 'bottom',
'bottom-start': 'bottom',
'bottom-end': 'bottom',
left: 'left',
'left-start': 'left',
'left-end': 'left',
right: 'right',
'right-start': 'right',
'right-end': 'right',
top: 'top',
'top-start': 'top',
'top-end': 'top'
};
export const Tooltip = memo((props: TooltipProps) => {
const {
title,
content,
children,
className,
placement = 'auto',
disableOnMobile,
classes,
offset = [0, 11],
bgColor
} = props;
const [isVisible, { set: setVisible, unset: unsetVisible }] = useToggle();
const isMobile = useIsMobile();
const nodeRef = useRef(null);
const [referenceElement, setReferenceElement] = useState<HTMLSpanElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
strategy: 'fixed',
placement: placement,
modifiers: [
{ name: 'offset', options: { offset } },
{ name: 'arrow', options: { element: arrowElement } },
{ name: 'flip', options: { fallbackPlacements: ['bottom-start', 'top-start', 'right', 'left'] } },
{ name: 'preventOverflow', options: { rootBoundary: 'viewport', tether: false, altAxis: true } }
]
});
const timeout = useSingleTimeout();
const set = useCallback(() => {
timeout.clear();
setVisible();
}, [setVisible, timeout]);
const unset = useCallback(() => {
timeout.set(unsetVisible, 50);
}, [unsetVisible, timeout]);
if (isMobile && disableOnMobile) {
return <>{children}</>;
}
return (
<div className={clsx(s.Tooltip, className)}>
<span
className={clsx(s.Tooltip__trigger, classes?.trigger)}
onMouseEnter={set}
onMouseLeave={unset}
ref={setReferenceElement}>
{children}
</span>
{content && (
<Transition unmountOnExit nodeRef={nodeRef} timeout={150} in={isVisible}>
{(state) => (
<div
ref={nodeRef}
className={clsx(s.Tooltip__contentWrapper, s[`Tooltip__contentWrapper_${state}`])}
onMouseEnter={set}
onMouseLeave={unset}>
<div
className={clsx(s.Tooltip__content, classes?.content)}
ref={setPopperElement}
style={{
...styles.popper,
backgroundColor: bgColor
}}
{...attributes.popper}>
{title && <div className={s.Tooltip__title}>{title}</div>}
{content}
<div
className={clsx(
s.Tooltip__arrow,
s[
`Tooltip__arrow_${
attributes.popper?.['data-popper-placement']
? placementMapper[attributes.popper?.['data-popper-placement'] as Placement]
: ''
}`
]
)}
ref={setArrowElement}
style={{
...styles.arrow,
color: bgColor
}}
{...attributes.arrow}
/>
</div>
</div>
)}
</Transition>
)}
</div>
);
});
Tooltip.displayName = 'Tooltip';

View File

@ -0,0 +1 @@
export * from './Tooltip';

View File

@ -1,6 +1,7 @@
import { Outlet } from 'react-router-dom';
import { Link, Outlet } from 'react-router-dom';
import clsx from 'clsx';
import { ReactFCC } from '../../../utils/ReactFCC';
import { HOME_PAGE_ROUTE } from '../../../app/routes';
import cbrLogoSrc from './assets/cbr-logo.svg';
import cpLogoSrc from './assets/cp-logo.svg';
import mopusLogoSrc from './assets/mopus-logo.svg';
@ -11,9 +12,9 @@ export const DefaultLayout: ReactFCC = () => {
<div className={s.DefaultLayout}>
<div className={s.DefaultLayout__container}>
<header className={s.DefaultLayout__header}>
<div className={s.DefaultLayout__logoMopusContainer}>
<Link to={HOME_PAGE_ROUTE} className={s.DefaultLayout__logoMopusContainer} reloadDocument>
<img className={s.DefaultLayout__logo} src={mopusLogoSrc} alt={''} />
</div>
</Link>
<img className={clsx(s.DefaultLayout__logo, s.DefaultLayout__logo_cp)} src={cpLogoSrc} alt={''} />
<img className={clsx(s.DefaultLayout__logo, s.DefaultLayout__logo_cbr)} src={cbrLogoSrc} alt={''} />
</header>

View File

@ -0,0 +1,80 @@
@import 'src/app/styles/vars';
.TextPage {
padding-bottom: $spacing-medium-x;
}
.TextPage__title {
margin-bottom: $spacing-small-x;
}
.TextPage__props {
@include flex-col;
row-gap: $spacing-small-3x;
margin-bottom: $spacing-small;
}
.TextPage__prop {
font-size: $font-size-14;
line-height: $line-height-20;
}
.TextPage__tooltip {
display: inline-block;
}
.TextPage__underline {
text-decoration: underline;
cursor: pointer;
}
.TextPage__summary {
margin-bottom: $spacing-small;
}
.TextPage__summaryHeading {
margin-bottom: $spacing-small-x;
}
.TextPage__summaryText {
}
.TextPage__summaryLink {
display: block;
margin-bottom: $spacing-small-4x;
width: fit-content;
&:last-of-type {
margin-bottom: $spacing-small-x;
}
}
.TextPage__full {
}
.TextPage__fullHeading {
margin-bottom: $spacing-small-x;
}
.TextPage__fullText {
line-height: $line-height-24;
@include mobile-up {
border: 1px solid $color-border-default;
padding: $spacing-medium $spacing-small;
border-radius: $radius-small;
}
@include mobile-down {
border-top: 1px solid $color-border-default;
border-bottom: 1px solid $color-border-default;
padding: $spacing-small-x 0;
}
}
.TextPage__tag {
display: inline-block;
background-color: #efe1ae;
padding: 0 2px;
margin: 0 -2px;
}

119
src/pages/text/TextPage.tsx Normal file
View File

@ -0,0 +1,119 @@
import { FC } from 'react';
import { Heading, HeadingSize } from '../../components/Heading';
import { useUrlParam } from '../../hooks/useUrlParam';
import { TEXT_PAGE_PARAM } from '../../app/routes';
import { ETextVariants, Text } from '../../components/Text';
import { getPercentageColor } from '../../utils/getPercentageColor';
import { Tooltip } from '../../components/Tooltip';
import { Link } from '../../components/Link';
import s from './TextPage.module.scss';
export const TextPage: FC = () => {
const textId = useUrlParam(TEXT_PAGE_PARAM, { parser: parseInt });
return (
<div className={s.TextPage}>
<Heading size={HeadingSize.H2} className={s.TextPage__title}>
Результат обработки запроса {textId}
</Heading>
<div className={s.TextPage__props}>
<Text className={s.TextPage__prop} variant={ETextVariants.PROGRAMMING_CODE_REGULAR}>
Имя файла: file.txt
</Text>
<Text component={'div'} className={s.TextPage__prop} variant={ETextVariants.PROGRAMMING_CODE_REGULAR}>
Результат по{' '}
<Tooltip className={s.TextPage__tooltip} content={'Языковая модель (Berd)'}>
<span className={s.TextPage__underline}>нейросетевому</span>
</Tooltip>{' '}
методу: АА+ | Accuracy: <span style={{ color: getPercentageColor(0.95) }}>0.95</span>
</Text>
<Text component={'div'} className={s.TextPage__prop} variant={ETextVariants.PROGRAMMING_CODE_REGULAR}>
Результат по{' '}
<Tooltip className={s.TextPage__tooltip} content={'Лемматизация + TF/IDF + RandomForest'}>
<span className={s.TextPage__underline}>статистическому</span>
</Tooltip>{' '}
методу: АА+ | Accuracy: <span style={{ color: getPercentageColor(0.71) }}>0.71</span>
</Text>
<Text component={'div'} className={s.TextPage__prop} variant={ETextVariants.PROGRAMMING_CODE_REGULAR}>
Результат по методу{' '}
<Tooltip className={s.TextPage__tooltip} content={'Berd + Annoy'}>
<span className={s.TextPage__underline}>похожести</span>
</Tooltip>{' '}
: АА+ | Accuracy: <span style={{ color: getPercentageColor(0.63) }}>0.63</span>
</Text>
</div>
<div className={s.TextPage__summary}>
<Heading size={HeadingSize.H4} className={s.TextPage__summaryHeading}>
Summary
</Heading>
<Text className={s.TextPage__summaryText} variant={ETextVariants.BODY_M_REGULAR}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</Text>
</div>
<div className={s.TextPage__full}>
<Heading size={HeadingSize.H4} className={s.TextPage__fullHeading}>
Полный текст
</Heading>
<Link className={s.TextPage__summaryLink}>Скачать DOCX</Link>
<Link className={s.TextPage__summaryLink}>Скачать PDF</Link>
<Text className={s.TextPage__fullText} variant={ETextVariants.BODY_M_REGULAR}>
Повышение кредитного рейтинга Акционерного общества «Уральская сталь» (далее «Уральская сталь», Компания)
вызвано улучшением качественной оценки ликвидности в связи с рефинансированием краткосрочного банковского
кредита посредством выпуска облигационного займа с погашением в 2025 году. Также{' '}
<span className={s.TextPage__tag}>пересмотр стратегических планов</span> по реализации ряда инвестиционных
проектов способствовал улучшению показателя «капитальные затраты к выручке». Улучшение ценовой конъюнктуры на
мировом рынке чугуна обеспечило запуск доменной печи 3, находившейся ранее в резерве, что окажет
дополнительное положительное влияние на денежный поток Компании в 2023 году. Кредитный рейтинг Компании
определяется средними рыночной позицией, бизнес-профилем и уровнем корпоративного управления, а также средней
оценкой за размер бизнеса. Показатели рентабельности, ликвидности, долговой нагрузки, обслуживания долга и
денежного потока получили высокие оценки. «Уральская сталь» один из крупнейших в России производителей
товарного чугуна, мостостали и стали для производства труб большого диаметра (ТБД). В начале 2022 года
Акционерное общество «Загорский трубный завод» ( рейтинг АКРА rating, прогноз «Стабильный» ; далее ЗТЗ)
<span className={s.TextPage__tag}>приобрело 100% уставного капитала</span> Компании у АО «ХК «МЕТАЛЛОИНВЕСТ» (
рейтинг АКРА rating, прогноз «Стабильный» ). Ключевые факторы оценки Средняя оценка рыночной позиции
обусловлена оценкой рыночных позиций «Уральской стали» по основным видам продукции (мостосталь, штрипс и
чугун), взвешенных с учетом их доли в консолидированной выручке Компании. Средняя оценка бизнес-профиля
Компании определяется: низкой оценкой степени вертикальной интеграции, которая отсутствует в Компании,
поскольку она не обеспечена собственными углем и железорудным сырьем; средней оценкой за долю продукции с
высокой добавленной стоимостью, которая учитывает сталь для ТБД и мостосталь как высокотехнологичные виды
продукции; средней оценкой за характеристику и диверсификацию рынков сбыта, так как рынки сбыта основной
продукции «Уральской стали» характеризуются умеренной цикличностью и насыщенностью, а продуктовый портфель
Компании умеренно диверсифицирован. Средняя оценка географической диверсификации является следствием наличия
экспорта чугуна, толстолистового проката и заготовки, доля которого формирует до{' '}
<span className={s.TextPage__tag}>50% консолидированной выручки</span>
Компании. С одной стороны, это обуславливает высокую оценку субфактора «доступность и диверсификация рынков
сбыта», а с другой очень низкую оценку субфактора «концентрация на одном заводе». Средний уровень
корпоративного управления обусловлен прозрачной структурой бизнеса и успешной реализацией Компанией стратегии
роста и расширения продуктового портфеля. Топ-менеджмент Компании представлен экспертами с большим опытом
работы в отрасли. «Уральская сталь» применяет отдельные элементы системы риск-менеджмента (например,
хеджирование валютного риска в определенных случаях), однако единые документы по стратегии и управлению
рисками, а также по дивидендной политике пока не утверждены. Совет директоров и ключевые комитеты пока не
сформированы. Структура бизнеса проста. Компания готовит отчетность по МСФО. Высокая оценка финансового
риск-профиля Компании обусловлена: высокой оценкой за рентабельность (рентабельность по FFO до процентов и
налогов за 2022 год составила 12% и ожидается АКРА на уровне{' '}
<span className={s.TextPage__tag}>около 18%</span> в 2023-м); высокой оценкой за обслуживание долга (отношение
FFO до чистых процентных платежей к процентным платежам составило 24,7х по результатам 2022 года и
прогнозируется АКРА на уровне около 11,7х в 2023-м); высокой оценкой за долговую нагрузку (отношение общего
долга с учетом поручительства по долгу ЗТЗ к FFO до чистых процентных платежей ожидается АКРА на уровне 2,5х
(0,8х без учета поручительств) по результатам 2023 года); средней оценкой размера бизнеса (абсолютное значение
годового FFO до чистых процентных платежей и налогов менее 30 млрд руб.). Высокая оценка уровня ликвидности.
</Text>
</div>
{/*<div className={s.TextPage__downloads}>*/}
{/* <a href="#">Скачать DOCX</a>*/}
{/*</div>*/}
</div>
);
};

1
src/pages/text/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './TextPage';

View File

@ -0,0 +1,7 @@
/**
* @param value from 0 to 1
*/
export const getPercentageColor = (value: number) => {
const hue = (value * 120).toString(10);
return ['hsl(', hue, ', 60%, 50%)'].join('');
};

View File

@ -1113,6 +1113,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8"
integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.5", "@babel/template@^7.3.3":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
@ -1709,6 +1716,11 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
"@popperjs/core@^2.11.8":
version "2.11.8"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
"@react-pdf/fns@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@react-pdf/fns/-/fns-2.0.1.tgz#8948464044fc8a69975d9d07b1a12673377b72e2"
@ -2381,6 +2393,13 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.6":
version "4.4.6"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e"
integrity sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.0.0":
version "18.2.21"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9"
@ -4262,6 +4281,14 @@ dom-converter@^0.2.0:
dependencies:
utila "~0.4"
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-serializer@0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@ -6926,7 +6953,7 @@ lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -8357,7 +8384,7 @@ react-error-overlay@^6.0.11:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
react-fast-compare@^3.1.1:
react-fast-compare@^3.0.1, react-fast-compare@^3.1.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
@ -8392,6 +8419,14 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-popper@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba"
integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==
dependencies:
react-fast-compare "^3.0.1"
warning "^4.0.2"
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@ -8472,6 +8507,16 @@ react-side-effect@^2.1.0:
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.2.tgz#dc6345b9e8f9906dc2eeb68700b615e0b4fe752a"
integrity sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==
react-transition-group@^4.4.5:
version "4.4.5"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
@ -9876,6 +9921,13 @@ walker@^1.0.7:
dependencies:
makeerror "1.0.12"
warning@^4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
dependencies:
loose-envify "^1.0.0"
watchpack@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"