chore(console-lite): add new stepper component and change deal ticket… (#788)

* chore(console-lite): add new stepper component and change deal ticket steps

* chore(console-lite): remove @mui/material from project

* chore(console-lite): refactor stepper counter styles to make it more legible

* fix(console-lite): market selector z-index overlap

* fix(console-lite): failing stepper tests

* fix(console-lite): fix linting errors

* feat(console-lite): add selected value to stepper.tsx

* chore(console-lite): change label size stepper
This commit is contained in:
Elmar 2022-07-19 00:29:52 +01:00 committed by GitHub
parent 7c2a84805e
commit cbe3e80e33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 341 additions and 253 deletions

View File

@ -43,7 +43,7 @@ export const DealTicketContainer = () => {
return (
<div className="flex">
<div className="md:w-1/2 md:min-w-[500px]">
<div className="w-full md:w-1/2 md:min-w-[500px]">
{marketId ? (
<Container marketId={marketId}>
{(data) => (

View File

@ -1,23 +1,15 @@
import * as React from 'react';
import { useForm, Controller } from 'react-hook-form';
import Box from '@mui/material/Box';
import { Stepper } from '../stepper';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
import {
ExpirySelector,
SideSelector,
TimeInForceSelector,
TypeSelector,
DealTicketAmount,
MarketSelector,
} from '@vegaprotocol/deal-ticket';
import type { Order } from '@vegaprotocol/orders';
import {
VegaWalletOrderTimeInForce as OrderTimeInForce,
VegaWalletOrderType as OrderType,
VegaTxStatus,
} from '@vegaprotocol/wallet';
import { VegaTxStatus } from '@vegaprotocol/wallet';
import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers';
import {
getDefaultOrder,
@ -84,7 +76,6 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const steps = [
{
label: t('Select Market'),
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
component: (
<MarketSelector
market={market}
@ -92,23 +83,10 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
ItemRenderer={MarketNameRenderer}
/>
),
value: market.name,
},
{
label: 'Select Order Type',
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
component: (
<Controller
name="type"
control={control}
render={({ field }) => (
<TypeSelector value={field.value} onSelect={field.onChange} />
)}
/>
),
},
{
label: 'Select Market Position',
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
label: t('Select Direction'),
component: (
<Controller
name="side"
@ -120,9 +98,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
),
},
{
label: 'Select Order Size',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
label: t('Choose Position Size'),
component: (
<DealTicketAmount
orderType={orderType}
@ -138,42 +114,9 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
),
},
{
label: 'Select Time In Force',
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
label: t('Review Trade'),
component: (
<>
<Controller
name="timeInForce"
control={control}
render={({ field }) => (
<TimeInForceSelector
value={field.value}
orderType={orderType}
onSelect={field.onChange}
/>
)}
/>
{orderType === OrderType.Limit &&
orderTimeInForce === OrderTimeInForce.GTT && (
<Controller
name="expiration"
control={control}
render={({ field }) => (
<ExpirySelector
value={field.value}
onSelect={field.onChange}
/>
)}
/>
)}
</>
),
},
{
label: 'Review & Submit Order',
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
component: (
<Box sx={{ mb: 2 }}>
<div className="mb-8">
{invalidText && (
<InputError className="mb-8" data-testid="dealticket-error-message">
{invalidText}
@ -190,7 +133,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
? t('Pending...')
: t('Place order')}
</Button>
</Box>
</div>
),
disabled: true,
},

View File

@ -10,7 +10,7 @@ export const NavItem = ({ iconName, label }: NavItemProps) => {
return (
<div className="flex flex-col md:flex-row items-center justify-start cursor-pointer relative">
<Icon name={iconName} className="mr-8" />
<span>{label}</span>
<span className="text-lg">{label}</span>
</div>
);
};

View File

@ -0,0 +1,55 @@
import * as React from 'react';
import classNames from 'classnames';
import Video from '../header/video';
interface CounterProps {
label: string;
className?: string;
isActive: boolean;
}
type TStyleMap = {
[key: string]: string;
};
const reduceStyles = (styleMap: TStyleMap) =>
Object.keys(styleMap).reduce((acc, curr) => acc + `${styleMap[curr]} `, '');
export const Counter = ({ label, isActive, className }: CounterProps) => {
const generalStyles: TStyleMap = {
shape: 'rounded-full relative aspect-square clip-path-rounded',
border: 'border-black dark:border-white',
colours: 'bg-white dark:bg-black text-black dark:text-white',
children: 'flex items-center justify-center text-center',
};
const unselected: TStyleMap = {
border: 'border',
size: 'w-[30px] md:w-40',
margin: 'mt-[5px] md:ml-[10px] md:mt-0',
};
const selected: TStyleMap = {
colours: 'text-xl text-white',
size: 'w-40 md:w-[60px]',
};
const classes = classNames(
reduceStyles(generalStyles),
isActive ? reduceStyles(selected) : reduceStyles(unselected),
className
).replace(/ +/g, ' '); // remove double space
return (
<div className={classes} aria-hidden>
{isActive && (
<div className="w-full h-full">
<Video />
</div>
)}
<span className="absolute inset-0 flex items-center justify-center">
{label}
</span>
</div>
);
};

View File

@ -1 +1 @@
export { default as Stepper } from './stepper';
export * from './stepper';

View File

@ -0,0 +1,124 @@
import React from 'react';
import { render, waitFor, fireEvent } from '@testing-library/react';
import { Stepper } from './index';
import type { TStep } from './index';
jest.mock('@vegaprotocol/react-helpers', () => {
return {
t: (a: string) => a,
useScreenDimensions: jest.fn(() => ({
isMobile: true,
})),
};
});
// Used to disable the error you get from muted video https://github.com/testing-library/react-testing-library/issues/470
Object.defineProperty(HTMLMediaElement.prototype, 'muted', {
// eslint-disable-next-line @typescript-eslint/no-empty-function
set: () => {},
});
const steps: TStep[] = [
{
label: 'Alpha',
component: <p>Alpha Content</p>,
},
{
label: 'Beta',
component: <p>Beta Content</p>,
},
{
label: 'Gamma',
component: <p>Gamma Content</p>,
},
];
describe('Stepper Component', () => {
it('should render it as a list', async () => {
const { getByLabelText } = await render(<Stepper steps={steps} />);
expect(getByLabelText('Step by step to make a trade')).toBeTruthy();
expect(getByLabelText('Step 1')).toBeTruthy();
expect(getByLabelText('Step 2')).toBeTruthy();
expect(getByLabelText('Step 3')).toBeTruthy();
});
it('should go to the correct tab on click', async () => {
const { getByRole } = await render(<Stepper steps={steps} />);
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'true'
);
fireEvent.click(getByRole('tab', { name: 'Beta' }));
await waitFor(() => getByRole('tab', { name: 'Gamma' }));
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'false'
);
expect(getByRole('tab', { name: 'Beta' })).toHaveAttribute(
'aria-selected',
'true'
);
expect(getByRole('tab', { name: 'Gamma' })).toHaveAttribute(
'aria-selected',
'false'
);
});
it('should go to the correct tab on right/left arrow press', async () => {
const { getByRole } = await render(<Stepper steps={steps} />);
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'true'
);
fireEvent.keyDown(getByRole('tab', { name: 'Beta' }), {
key: 'ArrowRight',
});
await waitFor(() => getByRole('tab', { name: 'Beta' }));
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'false'
);
expect(getByRole('tab', { name: 'Beta' })).toHaveAttribute(
'aria-selected',
'true'
);
fireEvent.keyDown(getByRole('tab', { name: 'Beta' }), { key: 'ArrowLeft' });
await waitFor(() => getByRole('tab', { name: 'Alpha' }));
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'true'
);
expect(getByRole('tab', { name: 'Beta' })).toHaveAttribute(
'aria-selected',
'false'
);
});
it('should go to next tab on next button click', async () => {
const { getByRole } = await render(<Stepper steps={steps} />);
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'true'
);
fireEvent.click(getByRole('button', { name: 'Next' }));
await waitFor(() => getByRole('tab', { name: 'Gamma' }));
expect(getByRole('tab', { name: 'Alpha' })).toHaveAttribute(
'aria-selected',
'false'
);
expect(getByRole('tab', { name: 'Beta' })).toHaveAttribute(
'aria-selected',
'true'
);
expect(getByRole('tab', { name: 'Gamma' })).toHaveAttribute(
'aria-selected',
'false'
);
});
afterEach(() => {
jest.clearAllMocks();
});
});

View File

@ -1,93 +1,157 @@
import * as React from 'react';
import type { ReactNode } from 'react';
import Box from '@mui/material/Box';
import classNames from 'classnames';
import { Button } from '@vegaprotocol/ui-toolkit';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import StepLabel from '@mui/material/StepLabel';
import StepContent from '@mui/material/StepContent';
import Paper from '@mui/material/Paper';
import Divider from '@mui/material/Divider';
import Typography from '@mui/material/Typography';
import { t, useScreenDimensions } from '@vegaprotocol/react-helpers';
import { Counter } from './counter';
type Step = {
export type TStep = {
label: string;
description: string;
component: ReactNode;
disabled?: boolean;
value?: string;
};
interface StepperProps {
steps: Step[];
export interface StepperProps {
steps: TStep[];
className?: string;
}
export default ({ steps }: StepperProps) => {
export const Stepper = ({ steps }: StepperProps) => {
const [activeStep, setActiveStep] = React.useState(0);
const lastStep = steps.length - 1;
const isLastStep = activeStep === lastStep;
const { isMobile } = useScreenDimensions();
const handleClick = (index: typeof activeStep) => {
setActiveStep(index);
};
const handleKeyPress = (event: React.KeyboardEvent<HTMLButtonElement>) => {
if (event.key === 'ArrowLeft' && activeStep > 0) {
return setActiveStep((prevActiveStep) => prevActiveStep - 1);
} else if (event.key === 'ArrowRight' && !isLastStep) {
return setActiveStep((prevActiveStep) => prevActiveStep + 1);
}
return false;
};
const handleNext = () => {
if (!isLastStep) {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleReset = () => {
setActiveStep(0);
}
};
return (
<Paper square elevation={1} sx={{ p: 3, mt: 5 }}>
<Stepper activeStep={activeStep} orientation="vertical">
{steps.map((step, index) => (
<Step key={step.label}>
<StepLabel
optional={
index === steps.length - 1 ? (
<Typography variant="caption">Last step</Typography>
) : null
}
style={{ cursor: 'pointer' }}
<div>
<ol
aria-label={t('Step by step to make a trade')}
className="relative flex md:flex-col justify-between list-none"
>
{steps.map((step, index) => {
const isActive = activeStep === index;
const isFirstStep = !index;
const isLastStep = lastStep === index;
return (
<li
className="flex-1"
key={`${index}-${step.label}`}
aria-label={t(`Step ${index + 1}`)}
>
<div className="flex relative md:pt-16">
{!isFirstStep ? (
<div
aria-hidden
className="flex-auto absolute top-[20px] -left-1/2 right-1/2 md:-top-1/2 md:bottom-1/2 md:left-[29.5px] md:right-auto"
>
<span className="h-full block border-t-1 border-black dark:border-white w-full md:border-l-1 md:border-t-0" />
</div>
) : undefined}
<button
role="tab"
aria-selected={isActive}
type="button"
id={`step-${index}-control`}
aria-controls={`step-${index}-panel`}
onKeyDown={(event) => handleKeyPress(event)}
onClick={() => handleClick(index)}
className="cursor-pointer z-10 flex w-full items-center"
>
<div className="flex-1 flex flex-col md:flex-row items-center w-full text-center">
<Counter
className="md:mr-16"
isActive={isActive}
label={(index + 1).toString()}
/>
<h3
className={classNames(
'md:mt-0 font-alpha uppercase text-black dark:text-white',
{
'mt-8 text-md md:text-2xl': isActive,
'mt-16 text-sm md:text-lg ml-8': !isActive,
}
)}
>
{step.label}
</StepLabel>
<StepContent>
<Typography sx={{ mb: 2 }}>{step.description}</Typography>
</h3>
</div>
{step.value && !isActive && (
<span
aria-label={`Selected value ${step.value}`}
className="text-blue hidden md:block"
>
{step.value}
</span>
)}
</button>
</div>
{!isMobile && (
<div
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
tabIndex={0}
id={`step-${index}-panel`}
aria-labelledby={`step-${index}-control`}
aria-hidden={!isActive}
role="tabpanel"
className={classNames(
'hidden md:block md:border-black md:dark:border-white md:ml-[29.5px] md:pl-[45px]',
{
'invisible h-0': !isActive,
'visible h-full': isActive,
'md:border-l': !isLastStep,
}
)}
>
{step.component}
<Divider sx={{ mb: 2 }} />
<Box>
<div>
</div>
)}
</li>
);
})}
</ol>
{isMobile && (
<div
id={`step-${activeStep}-panel`}
aria-labelledby={`step-${activeStep}-control`}
role="tabpanel"
className="md:hidden mt-32" // md:hidden as fallback
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
tabIndex={0}
>
{steps[activeStep].component}
{!isLastStep && (
<Button
className="w-full !py-8 mt-64 md:sr-only"
boxShadow={false}
variant="secondary"
onClick={handleNext}
disabled={step.disabled}
disabled={steps[activeStep].disabled}
>
{index === steps.length - 1 ? 'Finish' : 'Continue'}
{t('Next')}
</Button>
<Button
variant="inline-link"
disabled={index === 0}
onClick={handleBack}
>
Back
</Button>
</div>
</Box>
</StepContent>
</Step>
))}
</Stepper>
{activeStep === steps.length && (
<Paper square elevation={0} sx={{ p: 3 }}>
<Typography>All steps completed - you&apos;re finished</Typography>
<Button onClick={handleReset}>Reset</Button>
</Paper>
)}
</Paper>
</div>
)}
</div>
);
};

View File

@ -7,6 +7,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link
rel="preload"
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
</head>
<body>
<div id="root" class="h-full max-h-full"></div>

View File

@ -206,7 +206,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
<hr className="md:hidden mb-5" />
<div
className={classNames(
'md:absolute flex flex-col top-[30px] z-10 md:drop-shadow-md md:border-1 md:border-black md:dark:border-white bg-white dark:bg-black text-black dark:text-white min-w-full md:max-h-[200px] overflow-y-auto',
'md:absolute z-20 flex flex-col top-[30px] z-10 md:drop-shadow-md md:border-1 md:border-black md:dark:border-white bg-white dark:bg-black text-black dark:text-white min-w-full md:max-h-[200px] overflow-y-auto',
showPane ? 'block' : 'hidden'
)}
data-testid="market-pane"
@ -221,7 +221,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
role="button"
tabIndex={0}
key={market.id}
className="cursor-pointer focus:bg-white-95 focus:outline-0 dark:focus:bg-black-80 px-20 py-5"
className="bg-white dark:bg-black cursor-pointer focus:bg-white-95 focus:outline-0 dark:focus:bg-black-80 px-20 py-5"
onClick={() => handleMarketSelect(market)}
onKeyDown={(e) => handleItemKeyDown(e, market, i)}
>

View File

@ -1,4 +1,5 @@
const theme = require('./theme');
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
...theme,
@ -25,7 +26,7 @@ module.exports = {
},
},
fontSize: {
...theme.fontSize,
...defaultTheme.fontSize,
capMenu: ['15px', { lineHeight: '24px', letterSpacing: '-0.01em' }],
market: ['15px', { lineHeight: '24px' }],
'ui-small': ['12px', { lineHeight: '14px' }],
@ -42,4 +43,10 @@ module.exports = {
'input-focus-error': 'none',
'input-focus-error-dark': 'none',
},
extend: {
transitionProperty: {
height: 'height',
'max-height': 'max-height',
},
},
};

View File

@ -17,7 +17,6 @@
"@blueprintjs/icons": "^3.32.0",
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@mui/material": "^5.6.2",
"@nrwl/next": "13.10.3",
"@radix-ui/react-accordion": "^0.1.6",
"@radix-ui/react-dialog": "^0.1.5",

120
yarn.lock
View File

@ -1217,7 +1217,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.17.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
@ -2518,86 +2518,6 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
"@mui/base@5.0.0-alpha.78":
version "5.0.0-alpha.78"
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.78.tgz#9d0ee8c913969f60cd7072a6082e3c0652be0b74"
integrity sha512-5L+GNe2M9/tFjQpjK2r837+kzRg/l6D5R9SQbG1wmSWejw5Ei8P+KXIgS/NLNi9g7dUT8bnCyzz9AZKQX1Jsfg==
dependencies:
"@babel/runtime" "^7.17.2"
"@emotion/is-prop-valid" "^1.1.2"
"@mui/types" "^7.1.3"
"@mui/utils" "^5.6.1"
"@popperjs/core" "^2.11.5"
clsx "^1.1.1"
prop-types "^15.7.2"
react-is "^17.0.2"
"@mui/material@^5.6.2":
version "5.6.3"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.6.3.tgz#a5b6cd1b0417fca67a65172530ff5573ab7bc453"
integrity sha512-2VovFsbCEhic29NYoBF7zFrpH2sEOlKXXDhGjzxmWiI9OnC3SX63hapWunjaVsiRINVnjuMHuW1MOs4UtV8Gfg==
dependencies:
"@babel/runtime" "^7.17.2"
"@mui/base" "5.0.0-alpha.78"
"@mui/system" "^5.6.3"
"@mui/types" "^7.1.3"
"@mui/utils" "^5.6.1"
"@types/react-transition-group" "^4.4.4"
clsx "^1.1.1"
csstype "^3.0.11"
hoist-non-react-statics "^3.3.2"
prop-types "^15.7.2"
react-is "^17.0.2"
react-transition-group "^4.4.2"
"@mui/private-theming@^5.6.2":
version "5.6.2"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.6.2.tgz#c42da32f8b9481ba12885176c0168a355727c189"
integrity sha512-IbrSfFXfiZdyhRMC2bgGTFtb16RBQ5mccmjeh3MtAERWuepiCK7gkW5D9WhEsfTu6iez+TEjeUKSgmMHlsM2mg==
dependencies:
"@babel/runtime" "^7.17.2"
"@mui/utils" "^5.6.1"
prop-types "^15.7.2"
"@mui/styled-engine@^5.6.1":
version "5.6.1"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.6.1.tgz#e2c859a4dbdd65af89e77703a0725285aef471fd"
integrity sha512-jEhH6TBY8jc9S8yVncXmoTYTbATjEu44RMFXj6sIYfKr5NArVwTwRo3JexLL0t3BOAiYM4xsFLgfKEIvB9SAeQ==
dependencies:
"@babel/runtime" "^7.17.2"
"@emotion/cache" "^11.7.1"
prop-types "^15.7.2"
"@mui/system@^5.6.3":
version "5.6.3"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.6.3.tgz#a03ad6d61b0b7d304a8af60374e27e71e7818ef7"
integrity sha512-4SRi52a4ttZ2S4EHEDE8arVNuKqyQLTYUTF80WAZ0tQwnG20qwlBtzcrywCGItmVAMl7RUaYopyWOx3yVPvrmQ==
dependencies:
"@babel/runtime" "^7.17.2"
"@mui/private-theming" "^5.6.2"
"@mui/styled-engine" "^5.6.1"
"@mui/types" "^7.1.3"
"@mui/utils" "^5.6.1"
clsx "^1.1.1"
csstype "^3.0.11"
prop-types "^15.7.2"
"@mui/types@^7.1.3":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.1.3.tgz#d7636f3046110bcccc63e6acfd100e2ad9ca712a"
integrity sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==
"@mui/utils@^5.6.1":
version "5.6.1"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.6.1.tgz#4ab79a21bd481555d9a588f4b18061b3c28ea5db"
integrity sha512-CPrzrkiBusCZBLWu0Sg5MJvR3fKJyK3gKecLVX012LULyqg2U64Oz04BKhfkbtBrPBbSQxM+DWW9B1c9hmV9nQ==
dependencies:
"@babel/runtime" "^7.17.2"
"@types/prop-types" "^15.7.4"
"@types/react-is" "^16.7.1 || ^17.0.0"
prop-types "^15.7.2"
react-is "^17.0.2"
"@napi-rs/triples@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c"
@ -3344,7 +3264,7 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
"@popperjs/core@^2.11.5", "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0":
"@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
@ -6316,7 +6236,7 @@
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.0.tgz#a1c3809b0ad61c62cac6d4e0c56d610c910b7654"
integrity sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==
"@types/prop-types@*", "@types/prop-types@^15.7.4":
"@types/prop-types@*":
version "15.7.5"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
@ -6364,13 +6284,6 @@
dependencies:
"@types/react" "*"
"@types/react-is@^16.7.1 || ^17.0.0":
version "17.0.3"
resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a"
integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==
dependencies:
"@types/react" "*"
"@types/react-router-dom@5.3.1":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.1.tgz#76700ccce6529413ec723024b71f01fc77a4a980"
@ -6402,13 +6315,6 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.4":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e"
integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==
dependencies:
"@types/react" "*"
"@types/react-virtualized-auto-sizer@^1.0.0", "@types/react-virtualized-auto-sizer@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4"
@ -10542,7 +10448,7 @@ csstype@^2.5.7:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
csstype@^3.0.11, csstype@^3.0.2, csstype@^3.0.4:
csstype@^3.0.2, csstype@^3.0.4:
version "3.0.11"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
@ -11171,14 +11077,6 @@ dom-helpers@^3.4.0:
dependencies:
"@babel/runtime" "^7.1.2"
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"
@ -18848,16 +18746,6 @@ react-transition-group@2.9.0:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
react-transition-group@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-use-websocket@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/react-use-websocket/-/react-use-websocket-3.0.0.tgz#754cb8eea76f55d31c5676d4abe3e573bc2cea04"