1
1
mirror of https://github.com/pterodactyl/panel.git synced 2024-11-22 00:52:43 +01:00

Update react, add some V2 components for V1 usage

This commit is contained in:
DaneEveritt 2022-06-05 14:56:42 -04:00
parent 921da09a63
commit 1a5465dc34
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
21 changed files with 564 additions and 43 deletions

View File

@ -4,9 +4,13 @@
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.11",
"@headlessui/react": "^1.6.4",
"@heroicons/react": "^1.0.6",
"@hot-loader/react-dom": "^16.14.0",
"@tailwindcss/forms": "^0.5.2",
"axios": "^0.21.1",
"chart.js": "^2.8.0",
"classnames": "^2.3.1",
"codemirror": "^5.57.0",
"date-fns": "^2.16.1",
"debounce": "^1.2.0",
@ -20,7 +24,7 @@
"i18next-xhr-backend": "^3.2.2",
"qrcode.react": "^1.0.1",
"query-string": "^6.7.0",
"react": "^16.13.1",
"react": "^16.14.0",
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "npm:@hot-loader/react-dom",
"react-fast-compare": "^3.2.0",
@ -64,9 +68,9 @@
"@types/node": "^14.11.10",
"@types/qrcode.react": "^1.0.1",
"@types/query-string": "^6.3.0",
"@types/react": "^16.9.41",
"@types/react": "^16.14.0",
"@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "^16.9.8",
"@types/react-dom": "^16.9.16",
"@types/react-helmet": "^6.0.0",
"@types/react-redux": "^7.1.1",
"@types/react-router": "^5.1.3",
@ -103,7 +107,7 @@
"terser-webpack-plugin": "^4.2.3",
"ts-essentials": "^9.1.2",
"twin.macro": "^2.8.2",
"typescript": "^4.2.4",
"typescript": "^4.7.3",
"webpack": "^4.43.0",
"webpack-assets-manifest": "^3.1.1",
"webpack-bundle-analyzer": "^3.8.0",

View File

@ -0,0 +1,36 @@
import React, { forwardRef } from 'react';
import classNames from 'classnames';
import styles from './style.module.css';
export type ButtonProps = JSX.IntrinsicElements['button'] & {
square?: boolean;
small?: boolean;
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ children, square, small, className, ...rest }, ref) => {
return (
<button
ref={ref}
className={classNames(styles.button, { [styles.square]: square, [styles.small]: small }, className)}
{...rest}
>
{children}
</button>
);
},
);
const TextButton = forwardRef<HTMLButtonElement, ButtonProps>(({ className, ...props }, ref) => (
// @ts-expect-error
<Button ref={ref} className={classNames(styles.text, className)} {...props} />
));
const DangerButton = forwardRef<HTMLButtonElement, ButtonProps>(({ className, ...props }, ref) => (
// @ts-expect-error
<Button ref={ref} className={classNames(styles.danger, className)} {...props} />
));
const _Button = Object.assign(Button, { Text: TextButton, Danger: DangerButton });
export default _Button;

View File

@ -0,0 +1,2 @@
export { default as Button } from './Button';
export { default as styles } from './style.module.css';

View File

@ -0,0 +1,30 @@
.button {
@apply px-4 py-2 inline-flex items-center justify-center;
@apply bg-blue-600 rounded text-base font-semibold text-blue-50 transition-all duration-100;
@apply hover:bg-blue-500 active:bg-blue-500;
&.square {
@apply p-2;
}
&:focus {
@apply ring-[3px] ring-blue-500 ring-offset-2 ring-offset-neutral-700;
}
/* Sizing Controls */
&.small {
@apply px-3 py-1 font-normal focus:ring-2;
&.square {
@apply p-1;
}
}
}
.text {
@apply bg-transparent focus:ring-neutral-300 focus:ring-opacity-50 hover:bg-neutral-500 active:bg-neutral-500;
}
.danger {
@apply bg-red-600 hover:bg-red-500 active:bg-red-500 focus:ring-red-500 text-red-50;
}

View File

@ -0,0 +1,112 @@
import React, { Fragment } from 'react';
import { Dialog as HeadlessDialog, Transition } from '@headlessui/react';
import { Button } from '@/components/elements/button/index';
import styles from './style.module.css';
import { XIcon } from '@heroicons/react/solid';
import { CheckIcon, ExclamationIcon, InformationCircleIcon, ShieldExclamationIcon } from '@heroicons/react/outline';
import classNames from 'classnames';
interface Props {
visible: boolean;
onDismissed: () => void;
title?: string;
children?: React.ReactNode;
}
interface DialogIconProps {
type: 'danger' | 'info' | 'success' | 'warning';
className?: string;
}
const DialogIcon = ({ type, className }: DialogIconProps) => {
const [ Component, styles ] = (function (): [(props: React.ComponentProps<'svg'>) => JSX.Element, string] {
switch (type) {
case 'danger':
return [ ShieldExclamationIcon, 'bg-red-500 text-red-50' ];
case 'warning':
return [ ExclamationIcon, 'bg-yellow-600 text-yellow-50' ];
case 'success':
return [ CheckIcon, 'bg-green-600 text-green-50' ];
case 'info':
return [ InformationCircleIcon, 'bg-primary-500 text-primary-50' ];
}
})();
return (
<div className={classNames('flex items-center justify-center w-10 h-10 rounded-full', styles, className)}>
<Component className={'w-6 h-6'} />
</div>
);
};
const DialogButtons = ({ children }: { children: React.ReactNode }) => (
<>{children}</>
);
const Dialog = ({ visible, title, onDismissed, children }: Props) => {
const items = React.Children.toArray(children || []);
const [ buttons, icon, content ] = [
// @ts-expect-error
items.find(child => child.type === DialogButtons),
// @ts-expect-error
items.find(child => child.type === DialogIcon),
// @ts-expect-error
items.filter(child => ![ DialogIcon, DialogButtons ].includes(child.type)),
];
return (
<Transition show={visible} as={Fragment}>
<HeadlessDialog onClose={() => onDismissed()} className={styles.wrapper}>
<div className={'flex items-center justify-center min-h-screen'}>
<Transition.Child
as={Fragment}
enter={'ease-out duration-200'}
enterFrom={'opacity-0'}
enterTo={'opacity-100'}
leave={'ease-in duration-100'}
leaveFrom={'opacity-100'}
leaveTo={'opacity-0'}
>
<HeadlessDialog.Overlay className={styles.overlay}/>
</Transition.Child>
<Transition.Child
as={Fragment}
enter={'ease-out duration-200'}
enterFrom={'opacity-0 scale-95'}
enterTo={'opacity-100 scale-100'}
leave={'ease-in duration-100'}
leaveFrom={'opacity-100 scale-100'}
leaveTo={'opacity-0 scale-95'}
>
<div className={styles.container}>
<div className={'flex p-6'}>
{icon && <div className={'mr-4'}>{icon}</div>}
<div className={'flex-1'}>
{title &&
<HeadlessDialog.Title className={styles.title}>
{title}
</HeadlessDialog.Title>
}
<HeadlessDialog.Description className={'pr-4'}>
{content}
</HeadlessDialog.Description>
</div>
</div>
{buttons && <div className={styles.button_bar}>{buttons}</div>}
{/* Keep this below the other buttons so that it isn't the default focus if they're present. */}
<div className={'absolute right-0 top-0 m-4'}>
<Button.Text square small onClick={() => onDismissed()} className={'hover:rotate-90'}>
<XIcon className={'w-5 h-5'}/>
</Button.Text>
</div>
</div>
</Transition.Child>
</div>
</HeadlessDialog>
</Transition>
);
};
const _Dialog = Object.assign(Dialog, { Buttons: DialogButtons, Icon: DialogIcon });
export default _Dialog;

View File

@ -0,0 +1,2 @@
export { default as Dialog } from './Dialog';
export { default as styles } from './style.module.css';

View File

@ -0,0 +1,20 @@
.wrapper {
@apply fixed z-10 inset-0 overflow-y-auto;
}
.overlay {
@apply fixed inset-0 bg-gray-900 opacity-50;
}
.container {
@apply relative bg-gray-600 rounded max-w-xl w-full mx-auto shadow-lg;
@apply ring-4 ring-gray-800 ring-opacity-80;
& .title {
@apply font-header text-xl font-medium mb-2 text-white pr-4;
}
& > .button_bar {
@apply px-6 py-3 bg-gray-700 flex items-center justify-end space-x-3 rounded-b;
}
}

View File

@ -0,0 +1,62 @@
import React, { ElementType, forwardRef, useMemo } from 'react';
import { Menu, Transition } from '@headlessui/react';
import styles from './style.module.css';
import classNames from 'classnames';
import DropdownItem from '@/components/elements/dropdown/DropdownItem';
import DropdownButton from '@/components/elements/dropdown/DropdownButton';
interface Props {
as?: ElementType;
children: React.ReactNode;
}
const DropdownGap = ({ invisible }: { invisible?: boolean }) => (
<div className={classNames('border m-2', { 'border-neutral-700': !invisible, 'border-transparent': invisible })}/>
);
type TypedChild = (React.ReactChild | React.ReactFragment | React.ReactPortal) & {
type?: JSX.Element;
}
const Dropdown = forwardRef<typeof Menu, Props>(({ as, children }, ref) => {
const [ Button, items ] = useMemo(() => {
const list = React.Children.toArray(children) as unknown as TypedChild[];
return [
list.filter(child => child.type === DropdownButton),
list.filter(child => child.type !== DropdownButton),
];
}, [ children ]);
if (!Button) {
throw new Error('Cannot mount <Dropdown /> component without a child <Dropdown.Button />.');
}
return (
<Menu as={as || 'div'} className={styles.menu} ref={ref}>
{Button}
<Transition
enter={'transition duration-100 ease-out'}
enterFrom={'transition scale-95 opacity-0'}
enterTo={'transform scale-100 opacity-100'}
leave={'transition duration-75 ease-out'}
leaveFrom={'transform scale-100 opacity-100'}
leaveTo={'transform scale-95 opacity-0'}
>
<Menu.Items className={classNames(styles.items_container, 'w-56')}>
<div className={'px-1 py-1'}>
{items}
</div>
</Menu.Items>
</Transition>
</Menu>
);
});
const _Dropdown = Object.assign(Dropdown, {
Button: DropdownButton,
Item: DropdownItem,
Gap: DropdownGap,
});
export { _Dropdown as default };

View File

@ -0,0 +1,24 @@
import classNames from 'classnames';
import styles from '@/components/elements/dropdown/style.module.css';
import { ChevronDownIcon } from '@heroicons/react/solid';
import { Menu } from '@headlessui/react';
import React from 'react';
interface Props {
className?: string;
animate?: boolean;
children: React.ReactNode;
}
export default ({ className, animate = true, children }: Props) => (
<Menu.Button className={classNames(styles.button, className || 'px-4')}>
{typeof children === 'string' ?
<>
<span className={'mr-2'}>{children}</span>
<ChevronDownIcon aria-hidden={'true'} data-animated={animate.toString()}/>
</>
:
children
}
</Menu.Button>
);

View File

@ -0,0 +1,43 @@
import React, { forwardRef } from 'react';
import { Menu } from '@headlessui/react';
import styles from './style.module.css';
import classNames from 'classnames';
interface Props {
children: React.ReactNode | ((opts: { active: boolean; disabled: boolean }) => JSX.Element);
danger?: boolean;
disabled?: boolean;
className?: string;
icon?: JSX.Element;
onClick?: (e: React.MouseEvent) => void;
}
const DropdownItem = forwardRef<HTMLAnchorElement, Props>(({
disabled,
danger,
className,
onClick,
children,
icon: IconComponent,
}, ref) => {
return (
<Menu.Item disabled={disabled}>
{({ disabled, active }) => (
<a
ref={ref}
href={'#'}
className={classNames(styles.menu_item, {
[styles.danger]: danger,
[styles.disabled]: disabled,
}, className)}
onClick={onClick}
>
{IconComponent}
{typeof children === 'function' ? children({ disabled, active }) : children}
</a>
)}
</Menu.Item>
);
});
export default DropdownItem;

View File

@ -0,0 +1,2 @@
export { default as Dropdown } from './Dropdown';
export * as styles from './style.module.css';

View File

@ -0,0 +1,58 @@
.menu {
@apply relative inline-block text-left;
& .button {
@apply inline-flex justify-center items-center w-full py-2 text-neutral-100 rounded-md;
@apply transition-all duration-100;
&:hover, &[aria-expanded="true"] {
@apply bg-neutral-600 text-white;
}
&:focus, &:focus-within, &:active {
@apply ring-2 ring-opacity-50 ring-neutral-300 text-white;
}
& svg {
@apply w-5 h-5 transition-transform duration-75;
}
&[aria-expanded="true"] svg[data-animated="true"] {
@apply rotate-180;
}
}
& .items_container {
@apply absolute right-0 mt-2 origin-top-right bg-neutral-900 rounded z-10;
}
}
.menu_item {
@apply flex items-center rounded w-full px-2 py-2;
& svg {
@apply w-4 h-4 mr-4 text-neutral-300;
}
&:hover, &:focus {
@apply bg-blue-500 text-blue-50;
& svg {
@apply text-blue-50;
}
}
&.danger {
&:hover, &:focus {
@apply bg-red-500 text-red-50;
& svg {
@apply text-red-50;
}
}
}
&.disabled {
@apply cursor-not-allowed hover:bg-neutral-800 opacity-30 focus:bg-transparent focus:hover:bg-neutral-800;
}
}

View File

@ -0,0 +1,11 @@
import React, { forwardRef } from 'react';
import classNames from 'classnames';
import styles from './styles.module.css';
export default forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(({ className, ...props }, ref) => (
<input
ref={ref}
className={classNames('form-input', styles.text_input, className)}
{...props}
/>
));

View File

@ -0,0 +1,11 @@
import React, { forwardRef } from 'react';
import classNames from 'classnames';
import styles from './styles.module.css';
export default forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(({ className, ...props }, ref) => (
<input
ref={ref}
className={classNames('form-input', styles.text_input, className)}
{...props}
/>
));

View File

@ -0,0 +1,3 @@
export { default as Checkbox } from './Checkbox';
export { default as InputField } from './InputField';
export { default as styles } from './styles.module.css';

View File

@ -0,0 +1,21 @@
.checkbox {
@apply w-4 h-4 rounded-sm border-neutral-500 bg-neutral-600 text-primary-500;
&:focus, &:active {
@apply ring-2 ring-primary-500 ring-offset-2 ring-offset-neutral-700;
}
&.indeterminate:checked {
@apply text-primary-500/50 border border-primary-500;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='white'%3E%3Cpath fill-rule='evenodd' d='M5 10a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1z' clip-rule='evenodd' /%3E%3C/svg%3E");
}
}
.text_input {
@apply transition-all duration-75;
@apply bg-neutral-800 border-neutral-600 rounded px-4 py-2 outline-none;
&:focus {
@apply border-blue-600 ring-2 ring-blue-500;
}
}

View File

@ -0,0 +1,31 @@
import React from 'react';
import { Transition } from '@headlessui/react';
type Duration = `duration-${number}`;
interface Props {
as?: React.ElementType;
duration?: Duration | [ Duration, Duration ];
show: boolean;
children: React.ReactNode;
}
export default ({ children, duration, ...props }: Props) => {
const [ enterDuration, exitDuration ] = Array.isArray(duration)
? duration
: (!duration ? [ 'duration-200', 'duration-100' ] : [ duration, duration ]);
return (
<Transition
{...props}
enter={`ease-out ${enterDuration}`}
enterFrom={'opacity-0'}
enterTo={'opacity-100'}
leave={`ease-in ${exitDuration}`}
leaveFrom={'opacity-100'}
leaveTo={'opacity-0'}
>
{children}
</Transition>
);
};

View File

@ -0,0 +1,8 @@
import { Transition as TransitionComponent } from '@headlessui/react';
import FadeTransition from '@/components/elements/transitions/FadeTransition';
const Transition = Object.assign(TransitionComponent, {
Fade: FadeTransition,
});
export { Transition };

View File

@ -1,3 +1,4 @@
declare module '*.jpg';
declare module '*.png';
declare module '*.svg';
declare module '*.css';

View File

@ -1,28 +1,29 @@
// This allows the use of css={} on JSX elements.
//
// @see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31245
//
// This is just the contents of the @types/styled-components/cssprop.d.ts file
// since using the other method of just importing the one file did not work
// correctly for some reason.
// noinspection ES6UnusedImports
import {} from 'react';
import { ComponentType, ReactElement } from 'react';
// eslint-disable-next-line no-restricted-imports
import { CSSProp } from 'styled-components';
import styledImport, { css as cssImport, CSSProp, StyledComponentProps } from 'styled-components';
declare module 'react' {
interface Attributes {
// NOTE: unlike the plain javascript version, it is not possible to get access
// to the element's own attributes inside function interpolations.
// Only theme will be accessible, and only with the DefaultTheme due to the global
// nature of this declaration.
// If you are writing this inline you already have access to all the attributes anyway,
// no need for the extra indirection.
/**
* If present, this React element will be converted by
* `babel-plugin-styled-components` into a styled component
* with the given css as its styles.
*/
css?: CSSProp;
}
}
declare module 'styled-components' {
interface StyledComponentBase<
C extends string | ComponentType<any>,
// eslint-disable-next-line @typescript-eslint/ban-types
T extends object,
// eslint-disable-next-line @typescript-eslint/ban-types
O extends object = {},
A extends keyof any = never
> extends ForwardRefExoticBase<StyledComponentProps<C, T, O, A>> {
(props: StyledComponentProps<C, T, O, A> & { as?: Element | string; forwardedAs?: never | undefined }): ReactElement<
StyledComponentProps<C, T, O, A>
>;
}
}
declare module 'twin.macro' {
const css: typeof cssImport;
const styled: typeof styledImport;
}

View File

@ -1272,6 +1272,26 @@
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
"@headlessui/react@^1.6.4":
version "1.6.4"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.4.tgz#c73084e23386bef5fb86cd16da3352c3a844bb4c"
integrity sha512-0yqz1scwbFtwljmbbKjXsSGl5ABEYNICVHZnMCWo0UtOZodo2Tpu94uOVgCRjRZ77l2WcTi2S0uidINDvG7lsA==
"@heroicons/react@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"
integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==
"@hot-loader/react-dom@^16.14.0":
version "16.14.0"
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.14.0.tgz#3cfc64e40bb78fa623e59b582b8f09dcdaad648a"
integrity sha512-EN9czvcLsMYmSDo5yRKZOAq3ZGRlDpad1gPtX0NdMMomJXcPE3yFSeFzE94X/NjOaiSVimB7LuqPYpkWVaIi4Q==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.19.1"
"@jridgewell/gen-mapping@^0.3.0":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9"
@ -1471,12 +1491,12 @@
dependencies:
"@types/react" "*"
"@types/react-dom@^16.9.8":
version "16.9.8"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
"@types/react-dom@^16.9.16":
version "16.9.16"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.16.tgz#c591f2ed1c6f32e9759dfa6eb4abfd8041f29e39"
integrity sha512-Oqc0RY4fggGA3ltEgyPLc3IV9T73IGoWjkONbsyJ3ZBn+UPPCYpU2ec0i3cEbJuEdZtkqcCF2l1zf2pBdgUGSg==
dependencies:
"@types/react" "*"
"@types/react" "^16"
"@types/react-helmet@^6.0.0":
version "6.0.0"
@ -1523,13 +1543,19 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/react@^16.9.41":
version "16.9.41"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.41.tgz#925137ee4d2ff406a0ecf29e8e9237390844002e"
integrity sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug==
"@types/react@^16", "@types/react@^16.14.0":
version "16.14.26"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.26.tgz#82540a240ba7207ebe87d9579051bc19c9ef7605"
integrity sha512-c/5CYyciOO4XdFcNhZW1O2woVx86k4T+DO2RorHZL7EhitkNQgSD/SgpdZJAUJa/qjVgOmTM44gHkAdZSXeQuQ==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/styled-components@^5.1.7":
version "5.1.7"
@ -2657,6 +2683,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
clean-set@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/clean-set/-/clean-set-1.1.2.tgz#76d8bf238c3e27827bfa73073ecdfdc767187070"
@ -6994,10 +7025,10 @@ react-transition-group@^4.4.1:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
react@^16.14.0:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
@ -7374,6 +7405,14 @@ scheduler@^0.17.0:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
schema-utils@2.7.0, schema-utils@^2.6.5:
version "2.7.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"
@ -8369,10 +8408,10 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
typescript@^4.7.3:
version "4.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d"
integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==
unbox-primitive@^1.0.1:
version "1.0.1"