Add accessibility settings where you can disable keyboard shortcuts (#2157)

An accessibility requirement dictates that our custom shortcut system must be allowed to be disabled. A new accessibility settings page has been added to the user profile, similar to the theme settings. It is persisted in local storage.

Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
Konstantin Schaper
2022-11-16 16:50:17 +01:00
committed by GitHub
parent 4a556dda8b
commit 19938b3af8
34 changed files with 293 additions and 197 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -47,3 +47,9 @@ Diese können global oder repository-spezifisch sein oder in einem komplett ande
Sie werden automatisch in der Übersicht im SCM-Manager mit aufgelistet.
Um die Tastenkürzel eines Plugins innerhalb der Benutzerdokumentation zu finden, verweisen wir hier auf die
Dokumentation des jeweiligen Plugins.
### Barrierefreiheit
Das oben beschriebene System kann in den Profileinstellungen unter "Barrierefreiheit" deaktiviert werden.
![Einstellungen der Barrierefreiheit](assets/accessibility_settings.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -45,3 +45,9 @@ Plugins can introduce new shortcuts.
They may be global, repository-specific or connected to an entirely different context.
They will automatically be included in the summary generated within the SCM-Manager.
To find the shortcuts outside the SCM-Manager, please refer to the documentation of the plugin.
### Accessibility
The system described above can be disabled in the profile settings under "Accessibility".
![Accessibility Settings](assets/accessibility_settings.png)

View File

@@ -0,0 +1,2 @@
- type: added
description: Accessibility settings where you can disable keyboard shortcuts ([#2157](https://github.com/scm-manager/scm-manager/pull/2157))

View File

@@ -15,7 +15,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/plugin-scripts": "^1.2.2",
"@scm-manager/prettier-config": "^2.11.1",

View File

@@ -14,7 +14,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/plugin-scripts": "^1.2.2",
"@scm-manager/prettier-config": "^2.11.1",

View File

@@ -14,7 +14,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/plugin-scripts": "^1.2.2",
"@scm-manager/prettier-config": "^2.11.1",

View File

@@ -14,7 +14,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/plugin-scripts": "^1.2.2",
"@scm-manager/prettier-config": "^2.11.1",

View File

@@ -17,7 +17,7 @@
"fluent-ffmpeg": "^2.1.2"
},
"devDependencies": {
"@scm-manager/eslint-config": "^2.16.0"
"@scm-manager/eslint-config": "^2.17.0"
},
"prettier": "@scm-manager/prettier-config",
"eslintConfig": {

View File

@@ -19,7 +19,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/tsconfig": "^2.13.0",

View File

@@ -28,7 +28,7 @@
"devDependencies": {
"@scm-manager/prettier-config": "^2.11.1",
"@scm-manager/ui-api": "2.39.2-SNAPSHOT",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@babel/core": "^7.17.8",
"@scm-manager/tsconfig": "^2.12.0",
"@storybook/addon-essentials": "^6.4.20",

View File

@@ -24,7 +24,7 @@
"@scm-manager/ui-shortcuts": "2.39.2-SNAPSHOT",
"@scm-manager/ui-text": "2.39.2-SNAPSHOT",
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/tsconfig": "^2.13.0",

View File

@@ -1619,6 +1619,16 @@ exports[`Storyshots Footer Default 1`] = `
footer.user.theme
</a>
</li>
<li>
<a
className=""
data-testid="footer-user-accessibility"
href="/me/settings/accessibility"
onClick={[Function]}
>
footer.user.accessibility
</a>
</li>
</ul>
</section>
<section
@@ -1776,6 +1786,16 @@ exports[`Storyshots Footer Full 1`] = `
footer.user.theme
</a>
</li>
<li>
<a
className=""
data-testid="footer-user-accessibility"
href="/me/settings/accessibility"
onClick={[Function]}
>
footer.user.accessibility
</a>
</li>
<li>
<a
className=""
@@ -1972,6 +1992,16 @@ exports[`Storyshots Footer With Avatar 1`] = `
footer.user.theme
</a>
</li>
<li>
<a
className=""
data-testid="footer-user-accessibility"
href="/me/settings/accessibility"
onClick={[Function]}
>
footer.user.accessibility
</a>
</li>
</ul>
</section>
<section
@@ -2121,6 +2151,16 @@ exports[`Storyshots Footer With Plugin Links 1`] = `
footer.user.theme
</a>
</li>
<li>
<a
className=""
data-testid="footer-user-accessibility"
href="/me/settings/accessibility"
onClick={[Function]}
>
footer.user.accessibility
</a>
</li>
<li>
<a
className=""

View File

@@ -101,6 +101,11 @@ const Footer: FC<Props> = ({ me, version, links }) => {
<FooterSection title={meSectionTile}>
<NavLink to="/me" label={t("footer.user.profile")} testId="footer-user-profile" />
<NavLink to="/me/settings/theme" label={t("footer.user.theme")} testId="footer-user-theme" />
<NavLink
to="/me/settings/accessibility"
label={t("footer.user.accessibility")}
testId="footer-user-accessibility"
/>
{me?._links?.password && (
<NavLink to="/me/settings/password" label={t("profile.changePasswordNavLink")} />
)}

View File

@@ -22,7 +22,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/tsconfig": "^2.13.0",

View File

@@ -21,7 +21,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@types/react": "^17.0.1",

View File

@@ -18,7 +18,7 @@
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"tsup": "^5.12.6"
},
"babel": {

View File

@@ -21,7 +21,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/plugin-scripts": "^1.2.2",
"@scm-manager/prettier-config": "^2.10.1",

View File

@@ -31,7 +31,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/prettier-config": "^2.10.1",
"webpack-bundle-analyzer": "^4.5.0"
},

View File

@@ -27,7 +27,7 @@
"@types/mousetrap": "1.6.5",
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/tsconfig": "^2.13.0",
"@testing-library/react-hooks": "8.0.1",
"@testing-library/react": "12.1.5",

View File

@@ -15,7 +15,7 @@
"react-diff-view": "^2.4.10"
},
"devDependencies": {
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/prettier-config": "^2.11.1",
"css-loader": "^6.5.0",
"html-webpack-plugin": "^5.5.0",

View File

@@ -24,7 +24,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/tsconfig": "^2.13.0",

View File

@@ -23,7 +23,7 @@
},
"devDependencies": {
"@scm-manager/babel-preset": "^2.13.1",
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/prettier-config": "^2.10.1",
"@scm-manager/tsconfig": "^2.13.0",

View File

@@ -15,7 +15,7 @@
"lint": "eslint src"
},
"devDependencies": {
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/tsconfig": "^2.13.0"
},
"babel": {

View File

@@ -37,7 +37,7 @@
"build": "webpack-cli --mode=production --config=../ui-scripts/src/webpack.config.js"
},
"devDependencies": {
"@scm-manager/eslint-config": "^2.16.0",
"@scm-manager/eslint-config": "^2.17.0",
"@scm-manager/jest-preset": "^2.13.0",
"@scm-manager/ui-tests": "2.39.2-SNAPSHOT",
"@testing-library/react": "^12.1.5",

View File

@@ -116,6 +116,15 @@
"displayName": "Systemstandard",
"description": "Verwendet die Standardeinstellung des Systems"
}
},
"accessibility": {
"navLink": "Barrierefreiheit",
"subtitle": "Barrierefreiheit",
"deactivateShortcuts": {
"label": "Tastaturkürzel deaktivieren",
"helpText": "Deaktiviert alle speziellen Tastaturkombinationen, welche die Barrierefreiheit beeinträchtigen könnten."
},
"submit": "Speichern"
}
},
"password": {
@@ -133,7 +142,8 @@
"footer": {
"user": {
"profile": "Profil",
"theme": "Design"
"theme": "Design",
"accessibility": "Barrierefreiheit"
},
"information": {
"title": "Information"

View File

@@ -117,6 +117,15 @@
"displayName": "System default",
"description": "Use the default setting of the system"
}
},
"accessibility": {
"navLink": "Accessibility",
"subtitle": "Accessibility",
"deactivateShortcuts": {
"label": "Deactivate Shortcuts",
"helpText": "Disable all custom shortcuts which could negatively impact accessibility."
},
"submit": "Submit"
}
},
"password": {
@@ -134,7 +143,8 @@
"footer": {
"user": {
"profile": "Profile",
"theme": "Theme"
"theme": "Theme",
"accessibility": "Accessibility"
},
"information": {
"title": "Information"

View File

@@ -0,0 +1,46 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import useLocalStorage from "./useLocalStorage";
import { useCallback, useState } from "react";
const LOCAL_STORAGE_KEY = "scm.accessibility";
export type AccessibilityConfig = {
deactivateShortcuts: boolean;
};
export const useAccessibilityConfig = () => {
const [value, updateConfig] = useLocalStorage<AccessibilityConfig>(LOCAL_STORAGE_KEY, { deactivateShortcuts: false });
const [isLoading, setLoading] = useState(false);
const setValue = useCallback(
(newConfig: AccessibilityConfig) => {
setLoading(true);
updateConfig(newConfig);
window.location.reload();
},
[updateConfig]
);
return { value, setValue, isLoading } as const;
};

View File

@@ -0,0 +1,60 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { FC } from "react";
import { ButtonGroup, Checkbox, SubmitButton, Subtitle } from "@scm-manager/ui-components";
import { useTranslation } from "react-i18next";
import { useForm } from "react-hook-form";
import { AccessibilityConfig, useAccessibilityConfig } from "../accessibilityConfig";
const Accessibility: FC = () => {
const [t] = useTranslation("commons");
const { value: accessibilityConfig, setValue: setAccessibilityConfig, isLoading } = useAccessibilityConfig();
const {
register,
handleSubmit,
formState: { isDirty },
} = useForm<AccessibilityConfig>({
mode: "onChange",
defaultValues: accessibilityConfig,
});
return (
<>
<Subtitle>{t("profile.accessibility.subtitle")}</Subtitle>
<form onSubmit={handleSubmit(setAccessibilityConfig)}>
<Checkbox
label={t("profile.accessibility.deactivateShortcuts.label")}
helpText={t("profile.accessibility.deactivateShortcuts.helpText")}
{...register("deactivateShortcuts")}
/>
<ButtonGroup className="is-justify-content-flex-end">
<SubmitButton label={t("profile.accessibility.submit")} disabled={!isDirty} loading={isLoading} />
</ButtonGroup>
</form>
</>
);
};
export default Accessibility;

View File

@@ -34,7 +34,7 @@ import {
SecondaryNavigationColumn,
StateMenuContextProvider,
SubNavigation,
urls
urls,
} from "@scm-manager/ui-components";
import ChangeUserPassword from "./ChangeUserPassword";
import ProfileInfo from "./ProfileInfo";
@@ -45,6 +45,7 @@ import SetApiKeys from "../users/components/apiKeys/SetApiKeys";
import SetApiKeysNavLink from "../users/components/navLinks/SetApiKeysNavLink";
import { useRequiredMe } from "@scm-manager/ui-api";
import Theme from "./Theme";
import Accessibility from "./Accessibility";
const Profile: FC = () => {
const match = useRouteMatch();
@@ -63,7 +64,7 @@ const Profile: FC = () => {
subtitle={t("profile.error-subtitle")}
error={{
name: t("profile.error"),
message: t("profile.error-message")
message: t("profile.error-message"),
}}
/>
);
@@ -71,7 +72,7 @@ const Profile: FC = () => {
const extensionProps = {
me,
url
url,
};
return (
@@ -85,6 +86,9 @@ const Profile: FC = () => {
<Route path={`${url}/settings/theme`} exact>
<Theme />
</Route>
<Route path={`${url}/settings/accessibility`} exact>
<Accessibility />
</Route>
{mayChangePassword && (
<Route path={`${url}/settings/password`}>
<ChangeUserPassword me={me} />
@@ -120,6 +124,7 @@ const Profile: FC = () => {
title={t("profile.settingsNavLink")}
>
<NavLink to={`${url}/settings/theme`} label={t("profile.theme.navLink")} />
<NavLink to={`${url}/settings/accessibility`} label={t("profile.accessibility.navLink")} />
{mayChangePassword && (
<NavLink to={`${url}/settings/password`} label={t("profile.changePasswordNavLink")} />
)}

View File

@@ -24,6 +24,7 @@
import { useActiveModals } from "@scm-manager/ui-components";
import { usePauseShortcuts } from "@scm-manager/ui-shortcuts";
import { useAccessibilityConfig } from "../accessibilityConfig";
/**
* Keyboard shortcuts are not active in modals using {@link useActiveModals} to determine whether any modals are open.
@@ -32,5 +33,8 @@ import { usePauseShortcuts } from "@scm-manager/ui-shortcuts";
*/
export default function usePauseShortcutsWhenModalsActive() {
const areModalsActive = useActiveModals();
usePauseShortcuts(areModalsActive);
const {
value: { deactivateShortcuts },
} = useAccessibilityConfig();
usePauseShortcuts(deactivateShortcuts || areModalsActive);
}

View File

@@ -0,0 +1,45 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import { useEffect, useState } from "react";
export default function useLocalStorage<T>(
key: string,
initialValue: T
): [value: T, setValue: (value: T | ((previousConfig: T) => T)) => void] {
const [value, setValue] = useState<T>(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
return initialValue;
}
});
useEffect(() => localStorage.setItem(key, JSON.stringify(value)), [key, value]);
return [value, setValue];
}

169
yarn.lock
View File

@@ -2242,7 +2242,7 @@
"@babel/preset-typescript" "^7.16.7"
babel-plugin-styled-components "^1.13.3"
"@scm-manager/eslint-config@2.17.0":
"@scm-manager/eslint-config@2.17.0", "@scm-manager/eslint-config@^2.17.0":
version "2.17.0"
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-2.17.0.tgz#b29b65f131a520cb47b5355d16fac99beb1ca881"
integrity sha512-wbYI6g09NNhpyHSjRwStB7P0xRE6WxC30HZzmNpTN+2aqI0UZidkybCzTKMjAwW587uitg0z1g/cbntyXwYQFw==
@@ -2262,27 +2262,6 @@
eslint-plugin-react-hooks "^2.1.2"
jest "^26.6.3"
"@scm-manager/eslint-config@^2.16.0":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-2.16.0.tgz#fe682a1e1d53355c13fff8bffd9b44505e734a63"
integrity sha512-x1o+2RKnTOkuEfNz6zAir6lAaapBWtwy7PLMrs+d7i5kEfE9gJwNOYZqORxBdGZ3u3r6w/PJCc+LNEmOHdwxUA==
dependencies:
"@typescript-eslint/eslint-plugin" "^5.19.0"
"@typescript-eslint/parser" "^5.19.0"
babel-eslint "^10.0.3"
eslint "^7.32.0"
eslint-config-airbnb-base "^14.2.0"
eslint-config-prettier "^6.4.0"
eslint-config-react-app "^5.0.2"
eslint-plugin-flowtype "^4.3.0"
eslint-plugin-import "^2.18.2"
eslint-plugin-jsx-a11y "^6.2.3"
eslint-plugin-prettier "^3.1.1"
eslint-plugin-react "^7.16.0"
eslint-plugin-react-hooks "^2.1.2"
eslint-plugin-tailwindcss "^3.6.0"
jest "^26.6.3"
"@scm-manager/integration-test-runner@^3.3.0":
version "3.4.1"
resolved "https://registry.yarnpkg.com/@scm-manager/integration-test-runner/-/integration-test-runner-3.4.1.tgz#6b7745cda03b44456e1e7e6e15762748406e1503"
@@ -4764,21 +4743,12 @@ acorn-jsx@^5.3.1:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn-node@^1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
dependencies:
acorn "^7.0.0"
acorn-walk "^7.0.0"
xtend "^4.0.2"
acorn-walk@^6.0.1:
version "6.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
acorn-walk@^7.0.0, acorn-walk@^7.1.1, acorn-walk@^7.2.0:
acorn-walk@^7.1.1, acorn-walk@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
@@ -4798,7 +4768,7 @@ acorn@^6.0.1, acorn@^6.4.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1:
acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -5034,11 +5004,6 @@ are-we-there-yet@^2.0.0:
delegates "^1.0.0"
readable-stream "^3.6.0"
arg@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -6190,7 +6155,7 @@ camel-case@^4.1.1, camel-case@^4.1.2:
pascal-case "^3.1.2"
tslib "^2.0.3"
camelcase-css@2.0.1, camelcase-css@^2.0.1:
camelcase-css@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
@@ -6682,7 +6647,7 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.1.4, color-name@~1.1.4:
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
@@ -7579,11 +7544,6 @@ define-property@^2.0.2:
is-descriptor "^1.0.2"
isobject "^3.0.1"
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -7703,25 +7663,11 @@ detect-port@^1.3.0:
address "^1.0.1"
debug "^2.6.0"
detective@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
dependencies:
acorn-node "^1.8.2"
defined "^1.0.0"
minimist "^1.2.6"
devtools-protocol@0.0.1019158:
version "0.0.1019158"
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1019158.tgz#4b08d06108a784a2134313149626ba55f030a86f"
integrity sha512-wvq+KscQ7/6spEV7czhnZc9RM/woz1AY+/Vpd8/h2HFMwJSdTliu7f/yr1A6vDdJfKICZsShqsYpEQbdhg8AFQ==
didyoumean@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
@@ -7780,11 +7726,6 @@ discontinuous-range@1.0.0:
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
dlv@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@@ -8547,15 +8488,6 @@ eslint-plugin-react@^7.16.0:
semver "^6.3.0"
string.prototype.matchall "^4.0.7"
eslint-plugin-tailwindcss@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.6.0.tgz#b29605a53b5c27b7e74986ca7fcc0c6bdc435ad3"
integrity sha512-gWLGNWHuhh5ngwkJ2sgSByanpRw2s5GdrM2ff2/w8Ho2mWh2MyGvpnFZpL4b0XT/C0WF9zlq57+vFHJOeFhMkg==
dependencies:
fast-glob "^3.2.5"
postcss "^8.4.4"
tailwindcss "^3.1.3"
eslint-scope@5.1.1, eslint-scope@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
@@ -8958,7 +8890,7 @@ fast-glob@^2.2.6:
merge2 "^1.2.3"
micromatch "^3.1.10"
fast-glob@^3.2.11, fast-glob@^3.2.5, fast-glob@^3.2.9:
fast-glob@^3.2.9:
version "3.2.11"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
@@ -9630,13 +9562,6 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
dependencies:
is-glob "^4.0.1"
glob-parent@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
dependencies:
is-glob "^4.0.3"
glob-promise@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.4.0.tgz#b6b8f084504216f702dc2ce8c9bc9ac8866fdb20"
@@ -13943,11 +13868,6 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
object-hash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
object-inspect@^1.12.0, object-inspect@^1.7.0, object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
@@ -14591,7 +14511,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.0, picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pify@^2.0.0, pify@^2.2.0, pify@^2.3.0:
pify@^2.0.0, pify@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
@@ -14805,22 +14725,6 @@ postcss-flexbugs-fixes@^4.2.1:
dependencies:
postcss "^7.0.26"
postcss-import@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
dependencies:
postcss-value-parser "^4.0.0"
read-cache "^1.0.0"
resolve "^1.1.7"
postcss-js@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==
dependencies:
camelcase-css "^2.0.1"
postcss-load-config@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484"
@@ -14829,7 +14733,7 @@ postcss-load-config@2.0.0:
cosmiconfig "^4.0.0"
import-cwd "^2.0.0"
postcss-load-config@^3.0.1, postcss-load-config@^3.1.4:
postcss-load-config@^3.0.1:
version "3.1.4"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
@@ -14982,13 +14886,6 @@ postcss-modules@4.3.1:
postcss-modules-values "^4.0.0"
string-hash "^1.1.1"
postcss-nested@5.0.6:
version "5.0.6"
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc"
integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==
dependencies:
postcss-selector-parser "^6.0.6"
postcss-normalize-charset@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed"
@@ -15075,7 +14972,7 @@ postcss-reduce-transforms@^5.1.0:
dependencies:
postcss-value-parser "^4.2.0"
postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9:
version "6.0.10"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
@@ -15098,7 +14995,7 @@ postcss-unique-selectors@^5.1.1:
dependencies:
postcss-selector-parser "^6.0.5"
postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
@@ -15111,7 +15008,7 @@ postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0
picocolors "^0.2.1"
source-map "^0.6.1"
postcss@^8.1.10, postcss@^8.2.1, postcss@^8.2.15, postcss@^8.4.12, postcss@^8.4.14, postcss@^8.4.4, postcss@^8.4.7:
postcss@^8.1.10, postcss@^8.2.1, postcss@^8.2.15, postcss@^8.4.12, postcss@^8.4.7:
version "8.4.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
@@ -15507,11 +15404,6 @@ quick-lru@^4.0.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
quick-lru@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
raf@^3.4.0, raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -15923,13 +15815,6 @@ react@^17.0.1:
loose-envify "^1.1.0"
object-assign "^4.1.1"
read-cache@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
dependencies:
pify "^2.3.0"
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -16707,7 +16592,7 @@ resolve@1.1.7:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2, resolve@^1.9.0:
resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.3.2, resolve@^1.9.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@@ -18060,34 +17945,6 @@ table@^6.0.9:
string-width "^4.2.3"
strip-ansi "^6.0.1"
tailwindcss@^3.1.3:
version "3.1.6"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.6.tgz#bcb719357776c39e6376a8d84e9834b2b19a49f1"
integrity sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==
dependencies:
arg "^5.0.2"
chokidar "^3.5.3"
color-name "^1.1.4"
detective "^5.2.1"
didyoumean "^1.2.2"
dlv "^1.1.3"
fast-glob "^3.2.11"
glob-parent "^6.0.2"
is-glob "^4.0.3"
lilconfig "^2.0.5"
normalize-path "^3.0.0"
object-hash "^3.0.0"
picocolors "^1.0.0"
postcss "^8.4.14"
postcss-import "^14.1.0"
postcss-js "^4.0.0"
postcss-load-config "^3.1.4"
postcss-nested "5.0.6"
postcss-selector-parser "^6.0.10"
postcss-value-parser "^4.2.0"
quick-lru "^5.1.1"
resolve "^1.22.1"
tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
@@ -19937,7 +19794,7 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1:
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==