0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

feat(console): add a11y lint to ac (#2066)

This commit is contained in:
simeng-li 2022-10-09 15:07:09 +08:00 committed by GitHub
parent 50ae65e674
commit 37d2b0ce5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 438 additions and 49 deletions

View file

@ -29,7 +29,7 @@
"@parcel/transformer-sass": "2.7.0",
"@parcel/transformer-svg-react": "2.7.0",
"@silverhand/eslint-config": "1.0.0",
"@silverhand/eslint-config-react": "1.0.0",
"@silverhand/eslint-config-react": "1.1.0",
"@silverhand/essentials": "^1.2.1",
"@silverhand/ts-config": "1.0.0",
"@silverhand/ts-config-react": "1.0.0",

View file

@ -1,12 +1,13 @@
import { useLogto, IdTokenClaims } from '@logto/react';
import classNames from 'classnames';
import { useEffect, useRef, useState, MouseEvent } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Dropdown, { DropdownItem } from '@/components/Dropdown';
import { Ring as Spinner } from '@/components/Spinner';
import { generateAvatarPlaceHolderById } from '@/consts/avatars';
import SignOut from '@/icons/SignOut';
import { onKeyDownHandler } from '@/utilities/a11y';
import UserInfoSkeleton from '../UserInfoSkeleton';
import * as styles from './index.module.scss';
@ -43,13 +44,18 @@ const UserInfo = () => {
<>
<div
ref={anchorRef}
role="button"
tabIndex={0}
className={classNames(styles.container, showDropdown && styles.active)}
onKeyDown={onKeyDownHandler(() => {
setShowDropdown(true);
})}
onClick={() => {
setShowDropdown(true);
}}
>
{/* TODO: revert after SDK updated */}
<img src={picture ? String(picture) : generateAvatarPlaceHolderById(id)} />
<img src={picture ? String(picture) : generateAvatarPlaceHolderById(id)} alt="avatar" />
<div className={styles.wrapper}>
<div className={styles.name}>{username}</div>
</div>
@ -66,7 +72,7 @@ const UserInfo = () => {
<DropdownItem
className={classNames(styles.dropdownItem, isLoading && styles.loading)}
icon={<SignOut className={styles.signOutIcon} />}
onClick={(event: MouseEvent<HTMLLIElement>) => {
onClick={(event) => {
event.stopPropagation();
if (isLoading) {

View file

@ -6,6 +6,7 @@ import ErrorDark from '@/assets/images/error-dark.svg';
import Error from '@/assets/images/error.svg';
import { useTheme } from '@/hooks/use-theme';
import { KeyboardArrowDown, KeyboardArrowUp } from '@/icons/Arrow';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './index.module.scss';
@ -33,7 +34,12 @@ const AppError = ({ title, errorCode, errorMessage, callStack, children }: Props
{errorMessage}
{callStack && (
<span
role="button"
tabIndex={0}
className={styles.expander}
onKeyDown={onKeyDownHandler(() => {
setIsDetailsOpen(!isDetailsOpen);
})}
onClick={() => {
setIsDetailsOpen(!isDetailsOpen);
}}

View file

@ -5,6 +5,7 @@ import { TFuncKey, useTranslation } from 'react-i18next';
import Copy from '@/icons/Copy';
import Eye from '@/icons/Eye';
import EyeClosed from '@/icons/EyeClosed';
import { onKeyDownHandler } from '@/utilities/a11y';
import IconButton from '../IconButton';
import Tooltip from '../Tooltip';
@ -57,6 +58,11 @@ const CopyToClipboard = ({
return (
<div
className={classNames(styles.container, styles[variant], className)}
role="button"
tabIndex={0}
onKeyDown={onKeyDownHandler((event) => {
event.stopPropagation();
})}
onClick={(event) => {
event.stopPropagation();
}}

View file

@ -40,6 +40,7 @@ const DeleteConfirmModal = ({
{children}
{expectedInput && (
<TextInput
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
value={input}
placeholder={inputPlaceholder}

View file

@ -20,6 +20,8 @@ const Drawer = ({ title, subtitle, isOpen, children, onClose }: Props) => {
return (
<ReactModal
shouldCloseOnOverlayClick
// Styling purpose
// eslint-disable-next-line jsx-a11y/aria-role
role="drawer"
isOpen={isOpen}
className={styles.content}

View file

@ -1,10 +1,12 @@
import classNames from 'classnames';
import { MouseEvent, ReactNode } from 'react';
import { MouseEvent, KeyboardEvent, ReactNode } from 'react';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './DropdownItem.module.scss';
type Props = {
onClick?: (event: MouseEvent<HTMLLIElement>) => void;
onClick?: (event: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>) => void;
className?: string;
children: ReactNode | Record<string, unknown>;
icon?: ReactNode;
@ -20,7 +22,13 @@ const DropdownItem = ({
iconClassName,
type = 'default',
}: Props) => (
<li className={classNames(styles.item, styles[type], className)} onClick={onClick}>
<li
role="menuitem"
tabIndex={0}
className={classNames(styles.item, styles[type], className)}
onKeyDown={onKeyDownHandler(onClick)}
onClick={onClick}
>
{icon && <span className={classNames(styles.icon, iconClassName)}>{icon}</span>}
{children}
</li>

View file

@ -3,6 +3,7 @@ import { ReactNode, RefObject, useRef } from 'react';
import ReactModal from 'react-modal';
import usePosition, { HorizontalAlignment } from '@/hooks/use-position';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './index.module.scss';
@ -61,7 +62,13 @@ const Dropdown = ({
>
<div ref={overlayRef} className={styles.dropdownContainer}>
{title && <div className={classNames(styles.title, titleClassName)}>{title}</div>}
<ul className={classNames(styles.list, className)} onClick={onClose}>
<ul
className={classNames(styles.list, className)}
role="menu"
tabIndex={0}
onClick={onClose}
onKeyDown={onKeyDownHandler({ Enter: onClose, Esc: onClose })}
>
{children}
</ul>
</div>

View file

@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import * as textButtonStyles from '@/components/TextButton/index.module.scss';
import Minus from '@/icons/Minus';
import { onKeyDownHandler } from '@/utilities/a11y';
import ConfirmModal from '../ConfirmModal';
import IconButton from '../IconButton';
@ -85,7 +86,13 @@ const MultiTextInput = ({ title, value, onChange, onKeyPress, error, placeholder
)}
</div>
))}
<div className={classNames(textButtonStyles.button, styles.addAnother)} onClick={handleAdd}>
<div
role="button"
tabIndex={0}
className={classNames(textButtonStyles.button, styles.addAnother)}
onKeyDown={onKeyDownHandler(handleAdd)}
onClick={handleAdd}
>
{t('general.add_another')}
</div>
<ConfirmModal

View file

@ -71,6 +71,8 @@ const Radio = ({
styles[size],
className
)}
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
role="radio"
tabIndex={tabIndex}
onClick={isDisabled ? undefined : onClick}
onKeyPress={handleKeyPress}

View file

@ -3,6 +3,7 @@ import { ReactEventHandler, ReactNode, useRef, useState } from 'react';
import { KeyboardArrowDown, KeyboardArrowUp } from '@/icons/Arrow';
import Close from '@/icons/Close';
import { onKeyDownHandler } from '@/utilities/a11y';
import Dropdown, { DropdownItem } from '../Dropdown';
import IconButton from '../IconButton';
@ -65,6 +66,12 @@ const Select = <T extends string>({
className
)}
role="button"
tabIndex={0}
onKeyDown={onKeyDownHandler(() => {
if (!isReadOnly) {
setIsOpen(true);
}
})}
onClick={() => {
if (!isReadOnly) {
setIsOpen(true);

View file

@ -1,6 +1,8 @@
import classNames from 'classnames';
import { Link, useLocation } from 'react-router-dom';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './TabNavItem.module.scss';
type Props = {
@ -16,7 +18,14 @@ const TabNavItem = ({ children, href, isActive, onClick }: Props) => {
return (
<div className={classNames(styles.link, selected && styles.selected)}>
{href ? <Link to={href}>{children}</Link> : <a onClick={onClick}>{children}</a>}
{href ? (
<Link to={href}>{children}</Link>
) : (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a role="tab" tabIndex={0} onKeyDown={onKeyDownHandler(onClick)} onClick={onClick}>
{children}
</a>
)}
</div>
);
};

View file

@ -1,8 +1,9 @@
import classNames from 'classnames';
import { ReactNode, useState } from 'react';
import { ReactNode, useState, useCallback } from 'react';
import AnimateHeight, { Height } from 'react-animate-height';
import ArrowRight from '@/assets/images/triangle-right.svg';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './index.module.scss';
@ -15,14 +16,26 @@ const DetailsSummary = ({ children }: Props) => {
const [isExpanded, setIsExpanded] = useState(false);
const [height, setHeight] = useState<Height>(0);
const onClickHandler = useCallback(() => {
setIsExpanded(!isExpanded);
setHeight(height === 0 ? 'auto' : 0);
}, [height, isExpanded]);
return (
<div className={classNames(styles.container, isExpanded && styles.expanded)}>
<div
role="button"
tabIndex={0}
className={styles.summary}
onClick={() => {
setIsExpanded(!isExpanded);
setHeight(height === 0 ? 'auto' : 0);
}}
onKeyDown={onKeyDownHandler({
Esc: () => {
setIsExpanded(false);
setHeight(0);
},
Enter: onClickHandler,
' ': onClickHandler,
})}
onClick={onClickHandler}
>
<ArrowRight className={styles.arrow} />
{summary}

View file

@ -1,6 +1,6 @@
import { AdminConsoleKey } from '@logto/phrases';
import classNames from 'classnames';
import { PropsWithChildren, useEffect, useRef, useState } from 'react';
import { PropsWithChildren, useEffect, useRef, useState, useCallback } from 'react';
import Button from '@/components/Button';
import Card from '@/components/Card';
@ -10,6 +10,7 @@ import IconButton from '@/components/IconButton';
import Index from '@/components/Index';
import Spacer from '@/components/Spacer';
import { KeyboardArrowDown, KeyboardArrowUp } from '@/icons/Arrow';
import { onKeyDownHandler } from '@/utilities/a11y';
import * as styles from './index.module.scss';
@ -54,13 +55,24 @@ const Step = ({
}
}, [isExpanded]);
const onToggle = useCallback(() => {
setIsExpanded((expand) => !expand);
}, [setIsExpanded]);
return (
<Card key={title} ref={ref} className={styles.card}>
<div
role="button"
tabIndex={0}
className={styles.header}
onClick={() => {
setIsExpanded(!isExpanded);
}}
onKeyDown={onKeyDownHandler({
Esc: () => {
setIsExpanded(false);
},
Enter: onToggle,
' ': onToggle,
})}
onClick={onToggle}
>
<Index
className={styles.index}

View file

@ -55,6 +55,7 @@ const CreateForm = ({ onClose }: Props) => {
<form>
<FormField isRequired title="api_resources.api_name">
<TextInput
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
{...register('name', { required: true })}
placeholder={t('api_resources.api_name_placeholder')}

View file

@ -88,6 +88,7 @@ const ConnectorDetails = () => {
<div className={styles.logoContainer}>
<img
src={theme === AppearanceMode.DarkMode && data.logoDark ? data.logoDark : data.logo}
alt="logo"
className={styles.logo}
/>
</div>

View file

@ -75,6 +75,7 @@ const ConnectorName = ({ type, connectors, onClickSetup }: Props) => {
<div className={styles.logoContainer}>
<img
className={styles.logo}
alt="logo"
src={
theme === AppearanceMode.DarkMode && connector.logoDark
? connector.logoDark

View file

@ -119,7 +119,7 @@ const CreateForm = ({ onClose, isOpen: isFormOpen, type }: Props) => {
>
<div className={styles.connector}>
<div className={styles.logo}>
<img src={logo} />
<img src={logo} alt="logo" />
</div>
<div className={styles.content}>
<div className={styles.name}>

View file

@ -9,6 +9,7 @@ import Dropdown, { DropdownItem } from '@/components/Dropdown';
import Index from '@/components/Index';
import { useTheme } from '@/hooks/use-theme';
import useUserPreferences from '@/hooks/use-user-preferences';
import { onKeyDownHandler } from '@/utilities/a11y';
import useGetStartedMetadata from '../../hook';
import * as styles from './index.module.scss';
@ -28,14 +29,27 @@ const GetStartedProgress = () => {
return null;
}
const showDropDown = () => {
setShowDropdown(true);
};
const hideDropDown = () => {
setShowDropdown(false);
};
return (
<>
<div
ref={anchorRef}
role="button"
tabIndex={0}
className={classNames(styles.container, showDropdown && styles.active)}
onClick={() => {
setShowDropdown(true);
}}
onKeyDown={onKeyDownHandler({
Esc: hideDropDown,
Enter: showDropDown,
' ': showDropDown,
})}
onClick={showDropDown}
>
<Icon className={styles.icon} />
<span>
@ -52,9 +66,7 @@ const GetStartedProgress = () => {
horizontalAlign="end"
title={t('get_started.progress_dropdown_title')}
titleClassName={styles.dropdownTitle}
onClose={() => {
setShowDropdown(false);
}}
onClose={hideDropDown}
>
{data.map(({ id, title, isComplete, onClick }, index) => (
<DropdownItem

View file

@ -8,6 +8,7 @@ import Card from '@/components/Card';
import ConfirmModal from '@/components/ConfirmModal';
import Spacer from '@/components/Spacer';
import useUserPreferences from '@/hooks/use-user-preferences';
import { onKeyDownHandler } from '@/utilities/a11y';
import Skeleton from './components/Skeleton';
import useGetStartedMetadata from './hook';
@ -26,6 +27,14 @@ const GetStarted = () => {
navigate('/dashboard');
};
const showConfirmModalHandler = () => {
setShowConfirmModal(true);
};
const hideConfirmModalHandler = () => {
setShowConfirmModal(false);
};
return (
<div className={styles.container}>
<div className={styles.header}>
@ -36,10 +45,15 @@ const GetStarted = () => {
<span>
{t('get_started.subtitle_part2')}
<span
role="button"
tabIndex={0}
className={styles.hideButton}
onClick={() => {
setShowConfirmModal(true);
}}
onClick={showConfirmModalHandler}
onKeyDown={onKeyDownHandler({
Enter: showConfirmModalHandler,
' ': showConfirmModalHandler,
Esc: hideConfirmModalHandler,
})}
>
{t('get_started.hide_this')}
</span>
@ -70,9 +84,7 @@ const GetStarted = () => {
confirmButtonType="primary"
confirmButtonText="get_started.hide_this"
onConfirm={hideGetStarted}
onCancel={() => {
setShowConfirmModal(false);
}}
onCancel={hideConfirmModalHandler}
>
{t('get_started.confirm_message')}
</ConfirmModal>

View file

@ -195,12 +195,14 @@ const Preview = ({ signInExperience, className }: Props) => {
<PhoneInfo />
</div>
)}
{
// The missing of attribute "sandbox" is intended since the source is trusted
/* eslint-disable react/iframe-missing-sandbox */
}
<iframe ref={previewRef} src="/sign-in?preview=true" tabIndex={-1} />
{/* eslint-enable react/iframe-missing-sandbox */}
<iframe
ref={previewRef}
// Allow all sandbox rules
sandbox={undefined}
src="/sign-in?preview=true"
tabIndex={-1}
title={t('sign_in_exp.preview.title')}
/>
</div>
</div>
</div>

View file

@ -113,7 +113,7 @@ const UserConnectors = ({ userId, connectors, onDelete }: Props) => {
<tr key={target}>
<td>
<div className={styles.connectorName}>
<img src={logo} />
<img src={logo} alt="logo" />
<div className={styles.name}>
<UnnamedTrans resource={name} />
</div>

View file

@ -100,6 +100,7 @@ const UserDetails = () => {
className={styles.avatar}
src={data.avatar || generateAvatarPlaceHolderById(userId)}
referrerPolicy="no-referrer"
alt="avatar"
/>
<div className={styles.metadata}>
<div className={styles.name}>{data.name ?? '-'}</div>

View file

@ -58,6 +58,7 @@ const CreateForm = ({ onClose }: Props) => {
<form>
<FormField isRequired title="users.create_form_username">
<TextInput
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
{...register('username', {
required: true,

View file

@ -133,6 +133,7 @@ const Users = () => {
subtitle={id}
icon={
<img
alt="avatar"
className={styles.avatar}
src={avatar || generateAvatarPlaceHolderById(id)}
/>

View file

@ -0,0 +1,21 @@
import { KeyboardEventHandler, KeyboardEvent } from 'react';
type callbackHandler<T> = ((event: KeyboardEvent<T>) => void) | undefined;
type callbackHandlerMap<T> = Record<string, callbackHandler<T>>;
export const onKeyDownHandler =
<T = Element>(callback?: callbackHandler<T> | callbackHandlerMap<T>): KeyboardEventHandler<T> =>
(event) => {
const { key } = event;
if (typeof callback === 'function' && [' ', 'Enter'].includes(key)) {
callback(event);
event.preventDefault();
}
if (typeof callback === 'object') {
callback[key]?.(event);
event.preventDefault();
}
};

270
pnpm-lock.yaml generated
View file

@ -111,7 +111,7 @@ importers:
'@parcel/transformer-sass': 2.7.0
'@parcel/transformer-svg-react': 2.7.0
'@silverhand/eslint-config': 1.0.0
'@silverhand/eslint-config-react': 1.0.0
'@silverhand/eslint-config-react': 1.1.0
'@silverhand/essentials': ^1.2.1
'@silverhand/ts-config': 1.0.0
'@silverhand/ts-config-react': 1.0.0
@ -175,7 +175,7 @@ importers:
'@parcel/transformer-sass': 2.7.0_@parcel+core@2.7.0
'@parcel/transformer-svg-react': 2.7.0_@parcel+core@2.7.0
'@silverhand/eslint-config': 1.0.0_swk2g7ygmfleszo5c33j4vooni
'@silverhand/eslint-config-react': 1.0.0_3jdvf2aalbcoibv3m53iflhmym
'@silverhand/eslint-config-react': 1.1.0_3jdvf2aalbcoibv3m53iflhmym
'@silverhand/essentials': 1.2.1
'@silverhand/ts-config': 1.0.0_typescript@4.7.4
'@silverhand/ts-config-react': 1.0.0_typescript@4.7.4
@ -1052,6 +1052,14 @@ packages:
'@babel/helper-plugin-utils': 7.17.12
dev: true
/@babel/runtime-corejs3/7.19.1:
resolution: {integrity: sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==}
engines: {node: '>=6.9.0'}
dependencies:
core-js-pure: 3.25.5
regenerator-runtime: 0.13.9
dev: true
/@babel/runtime/7.17.9:
resolution: {integrity: sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==}
engines: {node: '>=6.9.0'}
@ -1064,6 +1072,13 @@ packages:
dependencies:
regenerator-runtime: 0.13.9
/@babel/runtime/7.19.0:
resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==}
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.13.9
dev: true
/@babel/template/7.16.7:
resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==}
engines: {node: '>=6.9.0'}
@ -3878,6 +3893,28 @@ packages:
- typescript
dev: true
/@silverhand/eslint-config-react/1.1.0_3jdvf2aalbcoibv3m53iflhmym:
resolution: {integrity: sha512-I9mmOLMaGtdqr6qMFnYLBUFfhkfLJxl1X9venb+Ek9+IvVr9x9LsgVpgB8CYXIlwwJCUdXAE0VmocISvbBr9BQ==}
engines: {node: ^16.0.0 || ^18.0.0}
peerDependencies:
stylelint: ^14.9.1
dependencies:
'@silverhand/eslint-config': 1.0.0_swk2g7ygmfleszo5c33j4vooni
eslint-config-xo-react: 0.27.0_5dhhqh7zhie7fohiouyxntxzve
eslint-plugin-jsx-a11y: 6.6.1_eslint@8.21.0
eslint-plugin-react: 7.29.3_eslint@8.21.0
eslint-plugin-react-hooks: 4.3.0_eslint@8.21.0
stylelint: 14.9.1
stylelint-config-xo-scss: 0.15.0_eqpuutlgonckfyjzwkrpusdvaa
transitivePeerDependencies:
- eslint
- eslint-import-resolver-webpack
- postcss
- prettier
- supports-color
- typescript
dev: true
/@silverhand/eslint-config/1.0.0_swk2g7ygmfleszo5c33j4vooni:
resolution: {integrity: sha512-cRA24+tuVGi8DQpBT7l7qssHZgQCLHoF+4E9/pAmDDLF7rYcImObaBbnkl4DRbeLHQAWvml2If4Xig9K+BZYdQ==}
engines: {node: ^16.0.0 || ^18.0.0}
@ -5090,6 +5127,14 @@ packages:
/argparse/2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
/aria-query/4.2.2:
resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==}
engines: {node: '>=6.0'}
dependencies:
'@babel/runtime': 7.19.0
'@babel/runtime-corejs3': 7.19.1
dev: true
/aria-query/5.0.0:
resolution: {integrity: sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==}
engines: {node: '>=6.0'}
@ -5120,6 +5165,17 @@ packages:
is-string: 1.0.7
dev: true
/array-includes/3.1.5:
resolution: {integrity: sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
es-abstract: 1.20.4
get-intrinsic: 1.1.1
is-string: 1.0.7
dev: true
/array-union/2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
@ -5163,6 +5219,10 @@ packages:
pvutils: 1.1.3
dev: true
/ast-types-flow/0.0.7:
resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==}
dev: true
/astral-regex/1.0.0:
resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==}
engines: {node: '>=4'}
@ -5191,6 +5251,11 @@ packages:
engines: {node: '>= 4.0.0'}
dev: true
/axe-core/4.4.3:
resolution: {integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==}
engines: {node: '>=4'}
dev: true
/axios/0.25.0:
resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==}
dependencies:
@ -5199,6 +5264,10 @@ packages:
- debug
dev: true
/axobject-query/2.2.0:
resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==}
dev: true
/babel-jest/28.1.3_@babel+core@7.17.9:
resolution: {integrity: sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
@ -6027,8 +6096,8 @@ packages:
engines: {node: '>=10'}
hasBin: true
dependencies:
JSONStream: 1.3.5
is-text-path: 1.0.1
JSONStream: 1.3.5
lodash: 4.17.21
meow: 8.1.2
split2: 3.2.2
@ -6080,6 +6149,11 @@ packages:
yargs: 16.2.0
dev: true
/core-js-pure/3.25.5:
resolution: {integrity: sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg==}
requiresBuild: true
dev: true
/core-js/3.21.1:
resolution: {integrity: sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==}
requiresBuild: true
@ -6295,6 +6369,10 @@ packages:
d3-array: 2.12.1
dev: true
/damerau-levenshtein/1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
dev: true
/dargs/7.0.0:
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
engines: {node: '>=8'}
@ -6454,6 +6532,14 @@ packages:
dependencies:
object-keys: 1.1.1
/define-properties/1.1.4:
resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==}
engines: {node: '>= 0.4'}
dependencies:
has-property-descriptors: 1.0.0
object-keys: 1.1.1
dev: true
/delay/4.4.1:
resolution: {integrity: sha512-aL3AhqtfhOlT/3ai6sWXeqwnw63ATNpnUiN4HL7x9q+My5QtHlO3OIkasmug9LKzpheLdmUKGRKnYXYAS7FQkQ==}
engines: {node: '>=6'}
@ -6769,11 +6855,41 @@ packages:
unbox-primitive: 1.0.1
dev: true
/es-abstract/1.20.4:
resolution: {integrity: sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
es-to-primitive: 1.2.1
function-bind: 1.1.1
function.prototype.name: 1.1.5
get-intrinsic: 1.1.3
get-symbol-description: 1.0.0
has: 1.0.3
has-property-descriptors: 1.0.0
has-symbols: 1.0.3
internal-slot: 1.0.3
is-callable: 1.2.7
is-negative-zero: 2.0.2
is-regex: 1.1.4
is-shared-array-buffer: 1.0.2
is-string: 1.0.7
is-weakref: 1.0.2
object-inspect: 1.12.2
object-keys: 1.1.1
object.assign: 4.1.4
regexp.prototype.flags: 1.4.3
safe-regex-test: 1.0.0
string.prototype.trimend: 1.0.5
string.prototype.trimstart: 1.0.5
unbox-primitive: 1.0.2
dev: true
/es-to-primitive/1.2.1:
resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
engines: {node: '>= 0.4'}
dependencies:
is-callable: 1.2.4
is-callable: 1.2.7
is-date-object: 1.0.5
is-symbol: 1.0.4
dev: true
@ -6992,6 +7108,28 @@ packages:
- supports-color
dev: true
/eslint-plugin-jsx-a11y/6.6.1_eslint@8.21.0:
resolution: {integrity: sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==}
engines: {node: '>=4.0'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
dependencies:
'@babel/runtime': 7.19.0
aria-query: 4.2.2
array-includes: 3.1.5
ast-types-flow: 0.0.7
axe-core: 4.4.3
axobject-query: 2.2.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
eslint: 8.21.0
has: 1.0.3
jsx-ast-utils: 3.3.3
language-tags: 1.0.5
minimatch: 3.1.2
semver: 6.3.0
dev: true
/eslint-plugin-no-use-extend-native/0.5.0:
resolution: {integrity: sha512-dBNjs8hor8rJgeXLH4HTut5eD3RGWf9JUsadIfuL7UosVQ/dnvOKwxEcRrXrFxrMZ8llUVWT+hOimxJABsAUzQ==}
engines: {node: '>=6.0.0'}
@ -7664,10 +7802,24 @@ packages:
/function-bind/1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
/function.prototype.name/1.1.5:
resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
es-abstract: 1.20.4
functions-have-names: 1.2.3
dev: true
/functional-red-black-tree/1.0.1:
resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=}
dev: true
/functions-have-names/1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
dev: true
/gauge/2.7.4:
resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=}
dependencies:
@ -7717,6 +7869,13 @@ packages:
has: 1.0.3
has-symbols: 1.0.3
/get-intrinsic/1.1.3:
resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
has-symbols: 1.0.3
/get-package-type/0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
@ -7776,7 +7935,7 @@ packages:
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
get-intrinsic: 1.1.3
dev: true
/get-tsconfig/4.2.0:
@ -8017,6 +8176,10 @@ packages:
resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==}
dev: true
/has-bigints/1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
dev: true
/has-flag/3.0.0:
resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=}
engines: {node: '>=4'}
@ -8025,6 +8188,12 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
/has-property-descriptors/1.0.0:
resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
dependencies:
get-intrinsic: 1.1.1
dev: true
/has-symbols/1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
@ -8612,7 +8781,7 @@ packages:
resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.1.1
get-intrinsic: 1.1.3
has: 1.0.3
side-channel: 1.0.4
dev: true
@ -8645,7 +8814,7 @@ packages:
/is-bigint/1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
dependencies:
has-bigints: 1.0.1
has-bigints: 1.0.2
dev: true
/is-binary-path/2.1.0:
@ -8684,6 +8853,11 @@ packages:
engines: {node: '>= 0.4'}
dev: true
/is-callable/1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
dev: true
/is-ci/2.0.0:
resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==}
hasBin: true
@ -8881,6 +9055,12 @@ packages:
resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==}
dev: true
/is-shared-array-buffer/1.0.2:
resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
dependencies:
call-bind: 1.0.2
dev: true
/is-ssh/1.3.3:
resolution: {integrity: sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==}
dependencies:
@ -9084,7 +9264,7 @@ packages:
jest-util: 28.1.3
jest-validate: 28.1.3
prompts: 2.4.2
yargs: 17.4.1
yargs: 17.6.0
transitivePeerDependencies:
- '@types/node'
- supports-color
@ -9112,7 +9292,7 @@ packages:
jest-util: 28.1.3
jest-validate: 28.1.3
prompts: 2.4.2
yargs: 17.4.1
yargs: 17.6.0
transitivePeerDependencies:
- '@types/node'
- supports-color
@ -9966,6 +10146,14 @@ packages:
object.assign: 4.1.2
dev: true
/jsx-ast-utils/3.3.3:
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
engines: {node: '>=4.0'}
dependencies:
array-includes: 3.1.5
object.assign: 4.1.4
dev: true
/just-diff-apply/5.3.1:
resolution: {integrity: sha512-dgFenZnMsc1xGNqgdtgnh7DK+Oy352CE3VZLbzcbQpsBs9iI2K3M0IRrdgREZ72eItTjbl0suRyvKRdVQa9GbA==}
dev: true
@ -10124,6 +10312,16 @@ packages:
engines: {node: '>=14.16'}
dev: true
/language-subtag-registry/0.3.22:
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
dev: true
/language-tags/1.0.5:
resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==}
dependencies:
language-subtag-registry: 0.3.22
dev: true
/lazy-cache/0.2.7:
resolution: {integrity: sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==}
engines: {node: '>=0.10.0'}
@ -11765,6 +11963,16 @@ packages:
object-keys: 1.1.1
dev: true
/object.assign/4.1.4:
resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
has-symbols: 1.0.3
object-keys: 1.1.1
dev: true
/object.entries/1.1.5:
resolution: {integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==}
engines: {node: '>= 0.4'}
@ -13491,6 +13699,15 @@ packages:
define-properties: 1.1.3
dev: true
/regexp.prototype.flags/1.4.3:
resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
functions-have-names: 1.2.3
dev: true
/regexpp/3.2.0:
resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
engines: {node: '>=8'}
@ -13745,6 +13962,14 @@ packages:
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
/safe-regex-test/1.0.0:
resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.3
is-regex: 1.1.4
dev: true
/safe-regex/2.1.1:
resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==}
dependencies:
@ -13862,7 +14087,7 @@ packages:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
get-intrinsic: 1.1.3
object-inspect: 1.12.2
/signal-exit/3.0.7:
@ -14339,6 +14564,14 @@ packages:
define-properties: 1.1.3
dev: true
/string.prototype.trimend/1.0.5:
resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
es-abstract: 1.20.4
dev: true
/string.prototype.trimstart/1.0.4:
resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==}
dependencies:
@ -14346,6 +14579,14 @@ packages:
define-properties: 1.1.3
dev: true
/string.prototype.trimstart/1.0.5:
resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.4
es-abstract: 1.20.4
dev: true
/string_decoder/0.10.31:
resolution: {integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=}
dev: true
@ -15140,6 +15381,15 @@ packages:
which-boxed-primitive: 1.0.2
dev: true
/unbox-primitive/1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
dependencies:
call-bind: 1.0.2
has-bigints: 1.0.2
has-symbols: 1.0.3
which-boxed-primitive: 1.0.2
dev: true
/unbzip2-stream/1.4.3:
resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==}
dependencies: