未验证 提交 c0281d33 编写于 作者: P Peter Pan 提交者: GitHub

dark mode (#814)

* feat: dark mode support

* chore: use redux to manage global state

* chore: update dependencies

* build: increase yarn network timeout to avoid build error in github action

* feat: dark mode support

* chore: add module preload
上级 7ecc58e7
......@@ -38,17 +38,17 @@
"version": "yarn format && git add -A"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.0.1",
"@typescript-eslint/parser": "4.0.1",
"eslint": "7.8.1",
"@typescript-eslint/eslint-plugin": "4.1.1",
"@typescript-eslint/parser": "4.1.1",
"eslint": "7.9.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-prettier": "3.1.4",
"eslint-plugin-react": "7.20.6",
"eslint-plugin-react-hooks": "4.1.0",
"husky": "4.2.5",
"eslint-plugin-react-hooks": "4.1.2",
"husky": "4.3.0",
"lerna": "3.22.1",
"lint-staged": "10.3.0",
"prettier": "2.1.1",
"lint-staged": "10.4.0",
"prettier": "2.1.2",
"rimraf": "3.0.2",
"typescript": "4.0.2",
"yarn": "1.22.5"
......
......@@ -36,12 +36,12 @@
"dependencies": {
"@visualdl/server": "2.0.9",
"open": "7.2.1",
"ora": "5.0.0",
"ora": "5.1.0",
"pm2": "4.4.1",
"yargs": "15.4.1"
"yargs": "16.0.3"
},
"devDependencies": {
"@types/node": "14.6.4",
"@types/node": "14.10.3",
"@types/yargs": "15.0.5",
"cross-env": "7.0.2",
"ts-node": "9.0.0",
......
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-console */
const path = require('path');
const {promises: fs} = require('fs');
const {BosClient} = require('@baiducloud/sdk');
const mime = require('mime-types');
const endpoint = process.env.BOS_ENDPOINT || 'http://bj.bcebos.com';
const ak = process.env.BOS_AK;
const sk = process.env.BOS_SK;
const version = process.env.CDN_VERSION || 'latest';
const config = {
endpoint,
credentials: {
ak,
sk
}
};
const bucket = 'visualdl-static';
const client = new BosClient(config);
async function getFiles(dir) {
const result = [];
try {
const files = await fs.readdir(dir, {withFileTypes: true});
for (const file of files) {
if (file.isFile()) {
const name = path.join(dir, file.name);
result.push({
name,
mime: mime.lookup(name),
size: (await fs.stat(name)).size
});
} else if (file.isDirectory()) {
result.push(...(await getFiles(path.join(dir, file.name))));
}
}
} catch (e) {
console.error(e);
}
return result;
}
async function main(directory) {
if (!ak || !sk) {
console.error('No AK and SK specified!');
process.exit(1);
}
let files = [];
try {
const stats = await fs.stat(directory);
if (stats.isDirectory()) {
files = (await getFiles(directory)).map(file => ({filename: path.relative(directory, file.name), ...file}));
} else if (stats.isFile()) {
files.push({
filename: path.relative(path.basename(directory)),
name: directory,
mime: mime.lookup(directory),
size: stats.size
});
} else {
console.error(`${directory} does not exist!`);
process.exit(1);
}
} catch (e) {
console.error(e);
process.exit(1);
}
for (const file of files) {
(function (f) {
client
.putObjectFromFile(bucket, `assets/${version}/${f.filename}`, f.name, {
'content-length': f.size,
'content-type': `${f.mime}; charset=utf-8`
})
.then(() => console.log([f.name, f.mime, f.size].join(', ')))
.catch(error => console.error(f, error));
})(file);
}
}
module.exports = main;
......@@ -33,3 +33,5 @@ process.env.SNOWPACK_PUBLIC_API_TOKEN_KEY = process.env.API_TOKEN_KEY || '';
process.env.SNOWPACK_PUBLIC_LANGUAGES = process.env.LANGUAGES || 'en,zh';
// default language
process.env.SNOWPACK_PUBLIC_DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE || 'en';
// theme
process.env.SNOWPACK_PUBLIC_THEME = process.env.THEME || '';
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const {promises: fs} = require('fs');
const ENV_INJECT = 'const env = window.__snowpack_env__ || {}; export default env;';
const dest = path.resolve(__dirname, '../dist/__snowpack__');
const envFile = path.join(dest, 'env.js');
module.exports = async () => {
await fs.rename(envFile, path.join(dest, 'env.local.js'));
await fs.writeFile(envFile, ENV_INJECT, 'utf-8');
};
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const {promises: fs} = require('fs');
const {minify} = require('html-minifier');
const dist = path.resolve(__dirname, '../dist');
const input = path.join(dist, 'index.html');
const output = path.join(dist, 'index.tpl.html');
function envProviderTemplate(baseUri) {
return `
<script type="module">
import env from '${baseUri}/__snowpack__/env.local.js'; window.__snowpack_env__ = env;
</script>
`;
}
const ENV_PROVIDER = envProviderTemplate(process.env.SNOWPACK_PUBLIC_BASE_URI);
const ENV_TEMPLATE_PROVIDER = envProviderTemplate('%BASE_URI%');
function injectProvider(content, provider) {
const scriptPos = content.indexOf('<script ');
return content.slice(0, scriptPos) + provider + content.slice(scriptPos);
}
function prependPublicPath(content, publicPath) {
return content.replace(/\b(src|href)=(['"]?)([^'"\s>]*)/gi, (_matched, attr, quote, url) => {
if (/^\/(_dist_|__snowpack__|web_modules|favicon.ico)\b/.test(url)) {
url = publicPath + url;
}
return attr + '=' + quote + url;
});
}
async function writeMinified(file, content) {
await fs.writeFile(
file,
minify(content, {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
sortAttributes: true,
sortClassName: true
}),
'utf-8'
);
}
module.exports = async () => {
const index = await fs.readFile(input, 'utf-8');
const indexWithPublicPath = prependPublicPath(index, process.env.SNOWPACK_PUBLIC_PATH);
const injected = injectProvider(indexWithPublicPath, ENV_PROVIDER);
await writeMinified(input, injected);
const template = prependPublicPath(index, '%PUBLIC_URL%');
const injectedTemplate = injectProvider(template, ENV_TEMPLATE_PROVIDER);
await writeMinified(output, injectedTemplate);
};
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-console */
require('dotenv').config();
require('./environment');
const path = require('path');
const {promises: fs} = require('fs');
const {BosClient} = require('@baiducloud/sdk');
const mime = require('mime-types');
const {minify} = require('html-minifier');
const endpoint = process.env.BOS_ENDPOINT || 'http://bj.bcebos.com';
const ak = process.env.BOS_AK;
const sk = process.env.BOS_SK;
const version = process.env.CDN_VERSION || 'latest';
const config = {
endpoint,
credentials: {
ak,
sk
}
};
const bucket = 'visualdl-static';
const client = new BosClient(config);
async function getFiles(dir) {
const result = [];
try {
const files = await fs.readdir(dir, {withFileTypes: true});
for (const file of files) {
if (file.isFile()) {
const name = path.join(dir, file.name);
result.push({
name,
mime: mime.lookup(name),
size: (await fs.stat(name)).size
});
} else if (file.isDirectory()) {
result.push(...(await getFiles(path.join(dir, file.name))));
}
}
} catch (e) {
console.error(e);
}
return result;
}
async function pushCdn(directory) {
if (!ak || !sk) {
console.error('No AK and SK specified!');
process.exit(1);
}
let files = [];
try {
const stats = await fs.stat(directory);
if (stats.isDirectory()) {
files = (await getFiles(directory)).map(file => ({filename: path.relative(directory, file.name), ...file}));
} else if (stats.isFile()) {
files.push({
filename: path.relative(path.basename(directory)),
name: directory,
mime: mime.lookup(directory),
size: stats.size
});
} else {
console.error(`${directory} does not exist!`);
process.exit(1);
}
} catch (e) {
console.error(e);
process.exit(1);
}
for (const file of files) {
(function (f) {
client
.putObjectFromFile(bucket, `assets/${version}/${f.filename}`, f.name, {
'content-length': f.size,
'content-type': `${f.mime}; charset=utf-8`
})
.then(() => console.log([f.name, f.mime, f.size].join(', ')))
.catch(error => console.error(f, error));
})(file);
}
}
const pushCdn = require('./cdn');
const injectTemplate = require('./inject-template');
const injectEnv = require('./inject-env');
const dist = path.resolve(__dirname, '../dist');
const dest = path.join(dist, '__snowpack__');
const publicDir = path.resolve(__dirname, '../public');
function envProviderTemplate(baseUri) {
return `
<script type="module">
import env from '${baseUri}/__snowpack__/env.local.js'; globalThis.env = env;
</script>
`;
}
const ENV_INJECT = 'const env = globalThis.env || {}; export default env;';
const ENV_PROVIDER = envProviderTemplate(process.env.SNOWPACK_PUBLIC_BASE_URI);
const ENV_TEMPLATE_PROVIDER = envProviderTemplate('%BASE_URI%');
async function injectProvider(input, provider, output) {
const file = await fs.readFile(input, 'utf-8');
const scriptPos = file.indexOf('<script ');
const newFile = file.slice(0, scriptPos) + provider + file.slice(scriptPos);
await fs.writeFile(
output || input,
minify(newFile, {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
sortAttributes: true,
sortClassName: true
}),
'utf-8'
);
}
async function main() {
await injectProvider(path.join(dist, 'index.html'), ENV_PROVIDER);
await injectProvider(path.join(publicDir, 'index.html'), ENV_TEMPLATE_PROVIDER, path.join(dist, 'index.tpl.html'));
await injectTemplate();
const envFile = path.join(dest, 'env.js');
await fs.rename(envFile, path.join(dest, 'env.local.js'));
await fs.writeFile(envFile, ENV_INJECT, 'utf-8');
await injectEnv();
if (process.env.CDN_VERSION) {
// TODO: do not upload index.html & index.tpl.html & __snowpack__/env.local.js
......
......@@ -48,10 +48,10 @@
"i18next-fetch-backend": "3.0.0",
"lodash": "4.17.20",
"mime-types": "2.1.27",
"moment": "2.27.0",
"moment": "2.28.0",
"nprogress": "0.2.0",
"polished": "3.6.6",
"query-string": "6.13.1",
"query-string": "6.13.2",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-helmet": "6.1.0",
......@@ -59,9 +59,11 @@
"react-input-range": "1.3.0",
"react-is": "16.13.1",
"react-rangeslider": "2.2.0",
"react-redux": "7.2.1",
"react-router-dom": "5.2.0",
"react-spinners": "0.9.0",
"react-toastify": "6.0.8",
"redux": "4.0.5",
"styled-components": "5.2.0",
"swr": "0.3.0",
"tippy.js": "6.2.6"
......@@ -74,14 +76,15 @@
"@baiducloud/sdk": "1.0.0-rc.22",
"@snowpack/app-scripts-react": "1.10.0",
"@snowpack/plugin-dotenv": "2.0.1",
"@snowpack/plugin-run-script": "2.1.1",
"@snowpack/plugin-optimize": "0.2.1",
"@snowpack/plugin-run-script": "2.1.2",
"@svgr/core": "5.4.0",
"@testing-library/jest-dom": "5.11.4",
"@testing-library/react": "11.0.2",
"@testing-library/react": "11.0.4",
"@types/d3-format": "1.3.1",
"@types/echarts": "4.6.5",
"@types/file-saver": "2.0.1",
"@types/jest": "26.0.13",
"@types/jest": "26.0.14",
"@types/loadable__component": "5.13.0",
"@types/lodash": "4.14.161",
"@types/mime-types": "2.1.0",
......@@ -90,6 +93,7 @@
"@types/react-dom": "16.9.8",
"@types/react-helmet": "6.1.0",
"@types/react-rangeslider": "2.2.3",
"@types/react-redux": "7.1.9",
"@types/react-router-dom": "5.1.5",
"@types/snowpack-env": "2.3.0",
"@types/styled-components": "5.1.3",
......@@ -102,9 +106,9 @@
"html-minifier": "4.0.0",
"http-proxy-middleware": "1.0.5",
"jest": "26.4.2",
"snowpack": "2.10.1",
"snowpack": "2.11.1",
"typescript": "4.0.2",
"yargs": "15.4.1"
"yargs": "16.0.3"
},
"engines": {
"node": ">=12",
......
......@@ -32,6 +32,7 @@
"imports": "Imports",
"inputs": "Inputs",
"license": "License",
"location": "Location",
"name": "Name",
"outputs": "Outputs",
"producer": "Producer",
......
......@@ -32,6 +32,7 @@
"imports": "导入",
"inputs": "输入",
"license": "许可证",
"location": "位置",
"name": "名称",
"outputs": "输出",
"producer": "框架",
......
......@@ -16,6 +16,14 @@ module.exports = {
extends: '@snowpack/app-scripts-react',
plugins: [
'@snowpack/plugin-dotenv',
[
'@snowpack/plugin-optimize',
{
minifyHTML: false, // we will do it later in post-build
preloadModules: true,
target: ['chrome63', 'firefox67', 'safari11.1', 'edge79'] // browsers support es module
}
],
[
'@snowpack/plugin-run-script',
{
......@@ -43,7 +51,7 @@ module.exports = {
port
},
buildOptions: {
baseUrl: process.env.SNOWPACK_PUBLIC_PATH || '/',
baseUrl: '/', // set it in post-build
clean: true
},
installOptions: {
......
import React, {FunctionComponent, Suspense, useEffect, useMemo, useState} from 'react';
import React, {FunctionComponent, Suspense, useCallback, useEffect, useMemo, useState} from 'react';
import {Redirect, Route, BrowserRouter as Router, Switch, useLocation} from 'react-router-dom';
import {THEME, matchMedia} from '~/utils/theme';
import {headerHeight, position, size} from '~/utils/style';
import BodyLoading from '~/components/BodyLoading';
......@@ -10,10 +11,12 @@ import NProgress from 'nprogress';
import Navbar from '~/components/Navbar';
import {SWRConfig} from 'swr';
import {ToastContainer} from 'react-toastify';
import {actions} from '~/store';
import {fetcher} from '~/utils/fetch';
import init from '@visualdl/wasm';
import routes from '~/routes';
import styled from 'styled-components';
import {useDispatch} from 'react-redux';
import {useTranslation} from 'react-i18next';
const BASE_URI: string = import.meta.env.SNOWPACK_PUBLIC_BASE_URI;
......@@ -74,6 +77,22 @@ const App: FunctionComponent = () => {
})();
}, [inited]);
const dispatch = useDispatch();
const toggleTheme = useCallback(
(e: MediaQueryListEvent) => dispatch(actions.theme.setTheme(e.matches ? 'dark' : 'light')),
[dispatch]
);
useEffect(() => {
if (!THEME) {
matchMedia.addEventListener('change', toggleTheme);
return () => {
matchMedia.removeEventListener('change', toggleTheme);
};
}
}, [toggleTheme]);
return (
<div className="app">
<Helmet defaultTitle="VisualDL" titleTemplate="%s - VisualDL">
......
import React, {FunctionComponent} from 'react';
import {WithStyled, asideWidth, borderColor, rem, size} from '~/utils/style';
import {WithStyled, asideWidth, rem, size, transitionProps} from '~/utils/style';
import styled from 'styled-components';
......@@ -7,9 +7,10 @@ export const AsideSection = styled.section`
margin: ${rem(20)};
&:not(:last-child) {
border-bottom: 1px solid ${borderColor};
border-bottom: 1px solid var(--border-color);
padding-bottom: ${rem(20)};
margin-bottom: 0;
${transitionProps('border-color')}
}
`;
......
import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {
WithStyled,
primaryActiveColor,
primaryBackgroundColor,
primaryColor,
primaryFocusedColor,
rem,
size,
textLightColor,
textLighterColor
} from '~/utils/style';
import {WithStyled, primaryColor, rem, size, transitionProps} from '~/utils/style';
import {AudioPlayer} from '~/utils/audio';
import type {BlobResponse} from '~/utils/fetch';
......@@ -28,35 +18,39 @@ import useRequest from '~/hooks/useRequest';
import {useTranslation} from 'react-i18next';
const Container = styled.div`
background-color: ${primaryBackgroundColor};
background-color: var(--audio-background-color);
border-radius: ${rem(8)};
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 ${rem(20)};
${transitionProps('background-color')}
> .control {
font-size: ${rem(16)};
${size(rem(16), rem(16))}
line-height: 1;
margin: 0 ${rem(10)};
color: ${primaryColor};
color: var(--primary-color);
cursor: pointer;
${transitionProps('color')}
&.volumn {
font-size: ${rem(20)};
${size(rem(20), rem(20))}
}
&.disabled {
color: ${textLightColor};
color: var(--text-light-color);
cursor: not-allowed;
}
&:hover {
color: ${primaryFocusedColor};
color: var(--primary-focused-color);
}
&:active {
color: ${primaryActiveColor};
color: var(--primary-active-color);
}
}
......@@ -66,9 +60,10 @@ const Container = styled.div`
}
> .time {
color: ${textLighterColor};
color: var(--text-lighter-color);
font-size: ${rem(12)};
margin: 0 ${rem(5)};
${transitionProps('color')}
}
`;
......@@ -82,15 +77,16 @@ const VolumnSlider = styled(Slider)`
outline: none;
border-radius: ${rem(2)};
user-select: none;
${transitionProps('color')}
--color: ${primaryColor};
--color: var(--primary-color);
&:hover {
--color: ${primaryFocusedColor};
--color: var(--primary-focused-color);
}
&:active {
--color: ${primaryActiveColor};
--color: var(--primary-active-color);
}
.rangeslider__fill {
......@@ -102,6 +98,7 @@ const VolumnSlider = styled(Slider)`
border-bottom-right-radius: ${rem(2)};
border-top: ${rem(4)} solid var(--color);
box-sizing: content-box;
${transitionProps(['background-color', 'color'])}
}
.rangeslider__handle {
......@@ -111,6 +108,7 @@ const VolumnSlider = styled(Slider)`
left: -${rem(2)};
border-radius: 50%;
outline: none;
${transitionProps('background-color')}
.rangeslider__handle-tooltip,
.rangeslider__handle-label {
......
import React, {FunctionComponent} from 'react';
import {position, primaryColor, size} from '~/utils/style';
import {position, primaryColor, size, transitionProps} from '~/utils/style';
import HashLoader from 'react-spinners/HashLoader';
import styled from 'styled-components';
......@@ -7,12 +7,13 @@ import styled from 'styled-components';
const Wrapper = styled.div`
${size('100vh', '100vw')}
${position('fixed', 0, 0, 0, 0)}
background-color: rgba(255, 255, 255, 0.8);
background-color: var(--mask-color);
display: flex;
justify-content: center;
align-items: center;
overscroll-behavior: none;
cursor: progress;
${transitionProps('background-color')}
`;
const BodyLoading: FunctionComponent = () => {
......
import React, {FunctionComponent} from 'react';
import {
WithStyled,
borderActiveColor,
borderColor,
borderFocusedColor,
borderRadius,
css,
dangerActiveColor,
dangerColor,
dangerFocusedColor,
ellipsis,
em,
half,
primaryActiveColor,
primaryColor,
primaryFocusedColor,
sameBorder,
textColor,
textInvertColor,
textLighterColor,
transitionProps
} from '~/utils/style';
import {WithStyled, borderRadius, css, ellipsis, em, half, sameBorder, transitionProps} from '~/utils/style';
import type {Icons} from '~/components/Icon';
import RawIcon from '~/components/Icon';
import {colors} from '~/utils/theme';
import styled from 'styled-components';
const height = em(36);
const colors = {
primary: {
default: primaryColor,
active: primaryActiveColor,
focused: primaryFocusedColor
},
danger: {
default: dangerColor,
active: dangerActiveColor,
focused: dangerFocusedColor
}
};
const defaultColor = {
default: borderColor,
active: borderActiveColor,
focused: borderFocusedColor
default: 'var(--border-color)',
focused: 'var(--border-focused-color)',
active: 'var(--border-active-color)'
} as const;
type colorTypes = keyof typeof colors;
......@@ -61,13 +29,14 @@ const Wrapper = styled.a<{type?: colorTypes; rounded?: boolean; disabled?: boole
border-radius: ${props => (props.rounded ? half(height) : borderRadius)};
${props => (props.type ? '' : sameBorder({color: defaultColor.default}))}
background-color: ${props => (props.type ? colors[props.type].default : 'transparent')};
color: ${props => (props.disabled ? textLighterColor : props.type ? textInvertColor : textColor)};
color: ${props =>
props.disabled ? 'var(--text-lighter-color)' : props.type ? colors[props.type].text : 'var(--text-color)'};
cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
display: inline-block;
vertical-align: top;
text-align: center;
padding: 0 ${em(20)};
${transitionProps(['background-color', 'border-color'])}
${transitionProps(['background-color', 'border-color', 'color'])}
${ellipsis()}
&:hover,
......
import React, {FunctionComponent, useCallback, useEffect, useState} from 'react';
import {
WithStyled,
backgroundColor,
borderRadius,
headerHeight,
math,
primaryColor,
rem,
sameBorder,
size,
transitionProps
} from '~/utils/style';
import {WithStyled, borderRadius, headerHeight, math, rem, sameBorder, size, transitionProps} from '~/utils/style';
import ee from '~/utils/event';
import styled from 'styled-components';
......@@ -21,13 +10,13 @@ const Div = styled.div<{maximized?: boolean; divWidth?: string; divHeight?: stri
props.maximized ? `calc(100vh - ${headerHeight} - ${rem(40)})` : props.divHeight || 'auto',
props.maximized ? '100%' : props.divWidth || '100%'
)}
background-color: ${backgroundColor};
background-color: var(--background-color);
${sameBorder({radius: math(`${borderRadius} * 2`)})}
${transitionProps(['border-color', 'box-shadow'])}
${transitionProps(['border-color', 'box-shadow', 'background-color'])}
position: relative;
&:hover {
border-color: ${primaryColor};
border-color: var(--primary-color);
box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.05);
}
`;
......
import React, {FunctionComponent, useState} from 'react';
import {
backgroundColor,
borderRadius,
em,
rem,
size,
textColor,
textLighterColor,
transitionProps
} from '~/utils/style';
import {borderRadius, em, rem, size, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import styled from 'styled-components';
const Wrapper = styled.div`
background-color: ${backgroundColor};
background-color: var(--background-color);
border-radius: ${borderRadius};
${transitionProps('background-color')}
& + & {
margin-top: ${rem(4)};
......@@ -28,14 +20,16 @@ const Header = styled.div`
justify-content: space-between;
align-items: center;
padding: 0 ${em(20)};
color: ${textLighterColor};
color: var(--text-lighter-color);
cursor: pointer;
${transitionProps('color')}
> h3 {
color: ${textColor};
color: var(--text-color);
flex-grow: 1;
margin: 0;
font-weight: 700;
${transitionProps('color')}
}
> .total {
......@@ -44,8 +38,9 @@ const Header = styled.div`
`;
const Content = styled.div`
border-top: 1px solid #eee;
border-top: 1px solid var(--border-color);
padding: ${rem(20)};
${transitionProps('border-color')}
`;
const CollapseIcon = styled(Icon)<{opened?: boolean}>`
......
import React, {FunctionComponent, PropsWithChildren, useCallback, useEffect, useMemo, useState} from 'react';
import {Trans, useTranslation} from 'react-i18next';
import {WithStyled, backgroundColor, headerHeight, link, primaryColor, rem, textLighterColor} from '~/utils/style';
import {WithStyled, headerHeight, link, primaryColor, rem, transitionProps} from '~/utils/style';
import BarLoader from 'react-spinners/BarLoader';
import Chart from '~/components/Chart';
......@@ -53,15 +53,16 @@ const Empty = styled.div<{height?: string}>`
width: 100%;
text-align: center;
font-size: ${rem(16)};
color: ${textLighterColor};
color: var(--text-lighter-color);
line-height: ${rem(24)};
height: ${props => props.height ?? 'auto'};
padding: ${rem(320)} 0 ${rem(70)};
background-color: ${backgroundColor};
background-color: var(--background-color);
background-image: url(${`${PUBLIC_PATH}/images/empty.svg`});
background-repeat: no-repeat;
background-position: calc(50% + ${rem(25)}) ${rem(70)};
background-size: ${rem(280)} ${rem(244)};
${transitionProps(['color', 'background-color'])}
${link}
`;
......@@ -131,7 +132,7 @@ const ChartPage = <T extends Item>({
}
return 0;
}),
[items] // eslint-disable-line react-hooks/exhaustive-deps
[items]
);
const total = useMemo(() => Math.ceil(matchedTags.length / pageSize), [matchedTags]);
......@@ -173,7 +174,7 @@ const ChartPage = <T extends Item>({
)}
</Wrapper>
),
[withChart, loading, chartSize, t] // eslint-disable-line react-hooks/exhaustive-deps
[withChart, loading, chartSize, t]
);
return (
......
import React, {FunctionComponent, useCallback, useState} from 'react';
import {
WithStyled,
em,
primaryActiveColor,
primaryColor,
primaryFocusedColor,
rem,
textColor,
textLightColor,
textLighterColor,
transitionProps
} from '~/utils/style';
import {WithStyled, em, rem, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import type {Icons} from '~/components/Icon';
......@@ -28,19 +17,19 @@ const Toolbox = styled.div<{reversed?: boolean}>`
const ToolboxItem = styled.a<{active?: boolean; reversed?: boolean}>`
cursor: pointer;
color: ${props => (props.active ? primaryColor : textLighterColor)};
color: ${props => (props.active ? 'var(--primary-color)' : 'var(--text-lighter-color)')};
${transitionProps('color')}
&:hover {
color: ${props => (props.active ? primaryFocusedColor : textLightColor)};
color: ${props => (props.active ? 'var(--primary-focused-color)' : 'var(--text-light-color)')};
}
&:active {
color: ${props => (props.active ? primaryActiveColor : textColor)};
color: ${props => (props.active ? 'var(--primary-active-color)' : 'var(--text-color)')};
}
& + & {
${props => `margin-${props.reversed ? 'right' : 'left'}: ${rem(14)};`}
margin: ${props => (props.reversed ? `0 ${rem(14)} 0 0` : `0 0 0 ${rem(14)}`)};
}
`;
......
import React, {FunctionComponent, useCallback, useEffect, useState} from 'react';
import {
WithStyled,
backgroundColor,
darken,
ellipsis,
em,
half,
lighten,
math,
position,
primaryColor,
sameBorder,
size,
textInvertColor,
textLighterColor,
transitionProps
} from '~/utils/style';
import {WithStyled, ellipsis, em, half, math, position, sameBorder, size, transitionProps} from '~/utils/style';
import styled from 'styled-components';
......@@ -43,20 +27,21 @@ const Input = styled.input.attrs<{disabled?: boolean}>(props => ({
`;
const Inner = styled.div<{checked?: boolean; size?: string; disabled?: boolean}>`
color: ${props => (props.checked ? textInvertColor : 'transparent')};
color: ${props => (props.checked ? 'var(--text-invert-color)' : 'transparent')};
flex-shrink: 0;
${props => size(math(`${checkSize} * ${props.size === 'small' ? 0.875 : 1}`))}
margin: ${half(`${height} - ${checkSize}`)} 0;
margin-right: ${em(10)};
${props => sameBorder({color: props.disabled || !props.checked ? textLighterColor : primaryColor})};
${props =>
sameBorder({color: props.disabled || !props.checked ? 'var(--text-lighter-color)' : 'var(--primary-color)'})};
background-color: ${props =>
props.disabled
? props.checked
? textLighterColor
: lighten(1 / 3, textLighterColor)
? 'var(--text-lighter-color)'
: 'var(--text-lighter-color)'
: props.checked
? primaryColor
: backgroundColor};
? 'var(--primary-color)'
: 'var(--background-color)'};
background-image: ${props => (props.checked ? `url("${checkMark}")` : 'none')};
background-repeat: no-repeat;
background-position: center center;
......@@ -66,14 +51,19 @@ const Inner = styled.div<{checked?: boolean; size?: string; disabled?: boolean}>
${Wrapper}:hover > & {
border-color: ${props =>
props.disabled ? textLighterColor : props.checked ? primaryColor : darken(0.1, textLighterColor)};
props.disabled
? 'var(--text-lighter-color)'
: props.checked
? 'var(--primary-color)'
: 'var(--text-lighter-color)'};
}
`;
const Content = styled.div<{disabled?: boolean}>`
line-height: ${height};
flex-grow: 1;
${props => (props.disabled ? `color: ${textLighterColor};` : '')}
${props => (props.disabled ? 'color: var(--text-lighter-color);' : '')}
${transitionProps('color')}
${ellipsis()}
`;
......
import React, {FunctionComponent} from 'react';
import {backgroundColor, contentHeight, contentMargin, headerHeight, position} from '~/utils/style';
import {contentHeight, contentMargin, headerHeight, position, transitionProps} from '~/utils/style';
import BodyLoading from '~/components/BodyLoading';
import styled from 'styled-components';
......@@ -16,11 +16,12 @@ const Article = styled.article`
const Aside = styled.aside`
flex: none;
background-color: ${backgroundColor};
background-color: var(--background-color);
height: ${`calc(100vh - ${headerHeight})`};
${position('sticky', headerHeight, 0, null, null)}
overflow-x: hidden;
overflow-y: auto;
${transitionProps('background-color')}
`;
type ContentProps = {
......
import React, {FunctionComponent} from 'react';
import {Trans, useTranslation} from 'react-i18next';
import {WithStyled, backgroundColor, em, link, rem, size, textColor, textLightColor} from '~/utils/style';
import {WithStyled, em, link, rem, size, transitionProps} from '~/utils/style';
import styled from 'styled-components';
......@@ -10,9 +10,10 @@ const Wrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background-color: ${backgroundColor};
background-color: var(--background-color);
height: 100%;
width: 100%;
${transitionProps('background-color')}
> .image {
background-image: url(${`${PUBLIC_PATH}/images/empty.svg`});
......@@ -24,13 +25,15 @@ const Wrapper = styled.div`
> .inner {
width: calc(50% - ${rem(280)});
color: ${textLightColor};
color: var(--text-light-color);
${transitionProps('color')}
${link}
h4 {
color: ${textColor};
color: var(--text-color);
font-size: ${em(18)};
font-weight: 700;
${transitionProps('color')}
}
p {
......
import {GlobalDispatchContext, GlobalStateContext, globalState} from '~/hooks/useGlobalState';
import React, {useReducer} from 'react';
import type {FunctionComponent} from 'react';
import type {GlobalState as GlobalStateType} from '~/hooks/useGlobalState';
interface GlobalDispatch {
(state: GlobalStateType, newState: Partial<GlobalStateType>): GlobalStateType;
}
// TODO: use redux
const GlobalState: FunctionComponent = ({children}) => {
const [state, dispatch] = useReducer<GlobalDispatch>(
(state, newState) =>
Object.entries(newState).reduce(
(m, [key, value]) => {
if (m.hasOwnProperty(key)) {
m[key] = {...m[key], ...value};
} else {
m[key] = value;
}
return m;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{...state} as any
),
globalState
);
return (
<GlobalStateContext.Provider value={state}>
<GlobalDispatchContext.Provider value={dispatch}>{children}</GlobalDispatchContext.Provider>
</GlobalStateContext.Provider>
);
};
export default GlobalState;
import type {Argument as ArgumentType, Property as PropertyType} from '~/resource/graph/types';
import React, {FunctionComponent, useMemo, useState} from 'react';
import {borderColor, em, sameBorder, textLightColor, textLighterColor} from '~/utils/style';
import {em, sameBorder, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import styled from 'styled-components';
......@@ -41,16 +41,18 @@ const Wrapper = styled.div`
cursor: pointer;
font-size: ${em(14)};
margin-left: ${em(10)};
color: ${textLighterColor};
color: var(--text-lighter-color);
${transitionProps('color')}
&:hover,
&:active {
color: ${textLightColor};
color: var(--text-light-color);
}
}
&:not(:first-child) {
border-top: 1px solid ${borderColor};
border-top: 1px solid var(--border-color);
${transitionProps('border-color')}
}
}
`;
......
import type {Documentation, OpenedResult, Properties, SearchItem, SearchResult} from '~/resource/graph/types';
import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {backgroundColor, borderColor, contentHeight, position, primaryColor, rem, size} from '~/utils/style';
import {contentHeight, position, primaryColor, rem, size, transitionProps} from '~/utils/style';
import ChartToolbox from '~/components/ChartToolbox';
import HashLoader from 'react-spinners/HashLoader';
import logo from '~/assets/images/netron.png';
import styled from 'styled-components';
import {toast} from 'react-toastify';
import useTheme from '~/hooks/useTheme';
import {useTranslation} from 'react-i18next';
const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH;
......@@ -22,11 +23,12 @@ const toolboxHeight = rem(40);
const Wrapper = styled.div`
position: relative;
height: ${contentHeight};
background-color: ${backgroundColor};
background-color: var(--background-color);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
${transitionProps('background-color')}
`;
const RenderContent = styled.div<{show: boolean}>`
......@@ -41,8 +43,9 @@ const RenderContent = styled.div<{show: boolean}>`
const Toolbox = styled(ChartToolbox)`
height: ${toolboxHeight};
border-bottom: 1px solid ${borderColor};
border-bottom: 1px solid var(--border-color);
padding: 0 ${rem(20)};
${transitionProps('border-color')}
`;
const Content = styled.div`
......@@ -57,13 +60,13 @@ const Content = styled.div`
> .powered-by {
display: block;
${position('absolute', null, null, rem(20), rem(30))}
color: #ddd;
color: var(--graph-copyright-color);
font-size: ${rem(14)};
user-select: none;
img {
height: 1em;
opacity: 0.5;
filter: var(--graph-copyright-logo-filter);
vertical-align: middle;
}
}
......@@ -125,6 +128,8 @@ const Graph = React.forwardRef<GraphRef, GraphProps>(
) => {
const {t} = useTranslation('graph');
const theme = useTheme();
const [ready, setReady] = useState(false);
const [loading, setLoading] = useState(false);
const [rendered, setRendered] = useState(false);
......@@ -204,6 +209,8 @@ const Graph = React.forwardRef<GraphRef, GraphProps>(
ready
]);
useEffect(() => (ready && dispatch('toggle-theme', theme)) || undefined, [dispatch, theme, ready]);
useImperativeHandle(ref, () => ({
export(type) {
dispatch('export', type);
......
import React, {FunctionComponent} from 'react';
import {backgroundColor, borderColor, rem, textLightColor} from '~/utils/style';
import {rem, transitionProps} from '~/utils/style';
import styled from 'styled-components';
import {useTranslation} from 'react-i18next';
const Sidebar = styled.div`
height: 100%;
background-color: ${backgroundColor};
background-color: var(--background-color);
`;
const Title = styled.div`
......@@ -15,13 +15,15 @@ const Title = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid ${borderColor};
border-bottom: 1px solid var(--border-color);
margin: 0 ${rem(20)};
${transitionProps('border-color')}
> .close {
flex: none;
color: ${textLightColor};
color: var(--text-light-color);
cursor: pointer;
${transitionProps('color')}
}
`;
......
import React, {FunctionComponent} from 'react';
import {backgroundColor, em, size} from '~/utils/style';
import {em, size, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import Properties from '~/components/GraphPage/Properties';
......@@ -14,8 +14,9 @@ const Dialog = styled.div`
width: 100vw;
height: 100vh;
overscroll-behavior: none;
background-color: rgba(255, 255, 255, 0.8);
background-color: var(--mask-color);
z-index: 999;
${transitionProps('background-color')}
> .modal {
width: ${em(536)};
......@@ -28,11 +29,12 @@ const Dialog = styled.div`
> .modal-header {
padding: 0 ${em(40, 18)};
height: ${em(47, 18)};
background-color: #eee;
background-color: var(--model-header-background-color);
display: flex;
justify-content: space-between;
align-items: center;
font-size: ${em(18)};
${transitionProps('background-color')}
> .modal-title {
flex: auto;
......@@ -49,9 +51,10 @@ const Dialog = styled.div`
> .modal-body {
padding: ${em(40)};
background-color: ${backgroundColor};
background-color: var(--background-color);
overflow: auto;
max-height: calc(80vh - ${em(47)});
${transitionProps('background-color')}
}
}
`;
......
import React, {FunctionComponent, useCallback} from 'react';
import {Trans, useTranslation} from 'react-i18next';
import {borderRadius, em, textLightColor} from '~/utils/style';
import {borderRadius, em, transitionProps} from '~/utils/style';
import type {Documentation as DocumentationType} from '~/resource/graph/types';
import GraphSidebar from '~/components/GraphPage/GraphSidebar';
......@@ -46,11 +46,12 @@ const Documentation = styled.div`
pre {
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
background-color: rgba(216, 216, 216, 0.5);
color: ${textLightColor};
background-color: var(--code-background-color);
color: var(--code-color);
padding: ${em(10)};
border-radius: ${borderRadius};
overflow: auto;
${transitionProps('color')}
code {
background-color: transparent;
......@@ -61,10 +62,11 @@ const Documentation = styled.div`
code {
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
background-color: rgba(216, 216, 216, 0.5);
color: ${textLightColor};
background-color: var(--code-background-color);
color: var(--code-color);
padding: ${em(2)} ${em(4)};
border-radius: ${em(2)};
${transitionProps('color')}
}
`;
......
import React, {FunctionComponent, useCallback, useEffect, useState} from 'react';
import type {SearchItem, SearchResult} from '~/resource/graph/types';
import {
backgroundColor,
backgroundFocusedColor,
css,
ellipsis,
em,
primaryColor,
rem,
sameBorder,
size,
textLightColor,
transitionProps,
triangle
} from '~/utils/style';
import {css, ellipsis, em, rem, sameBorder, size, transitionProps, triangle} from '~/utils/style';
import Field from '~/components/Field';
import SearchInput from '~/components/SearchInput';
......@@ -32,17 +19,19 @@ const SearchField = styled(Field)`
}
> a:last-child {
color: ${primaryColor};
color: var(--primary-color);
cursor: pointer;
margin-left: ${rem(10)};
flex: none;
${transitionProps('color')}
}
`;
const Empty = styled.div`
padding: ${rem(100)} 0;
text-align: center;
color: ${textLightColor};
color: var(--text-light-color);
${transitionProps('color')}
`;
const Wrapper = styled.div`
......@@ -59,7 +48,7 @@ const Item = styled.li`
padding: ${em(10)} ${em(12)};
cursor: pointer;
width: 100%;
background-color: ${backgroundColor};
background-color: var(--background-color);
display: flex;
align-items: center;
${transitionProps('background-color')}
......@@ -71,7 +60,7 @@ const Item = styled.li`
}
&:hover {
background-color: ${backgroundFocusedColor};
background-color: var(--background-focused-color);
}
`;
......
import React, {FunctionComponent, useCallback, useState} from 'react';
import {em, primaryColor, sameBorder, size, textLightColor} from '~/utils/style';
import {em, sameBorder, size, transitionProps} from '~/utils/style';
import Button from '~/components/Button';
import Icon from '~/components/Icon';
......@@ -12,18 +12,21 @@ const DropZone = styled.div<{actived: boolean}>`
width: '1px',
type: 'dashed',
radius: em(16),
color: props.actived ? primaryColor : undefined
color: props.actived ? 'var(--primary-color)' : undefined
})}
background-color: ${props => (props.actived ? '#f2f6ff' : '#f9f9f9')};
background-color: ${props =>
props.actived ? 'var(--graph-uploader-active-background-color)' : 'var(--graph-uploader-background-color)'};
${size('43.2%', '68%')}
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
${transitionProps('border-color', 'background-color')}
> .upload-icon {
font-size: ${em(64)};
color: ${primaryColor};
color: var(--primary-color);
${transitionProps('color')}
}
> span {
......@@ -45,11 +48,12 @@ const SupportTable = styled.table`
line-height: 2;
&:first-of-type {
color: ${textLightColor};
color: var(--text-light-color);
text-align: right;
padding-right: ${em(10)};
font-size: ${em(16)};
width: ${em(250)};
${transitionProps('color')}
}
}
`;
......
import {WithStyled, borderFocusedColor, em, half, sameBorder, textLighterColor, transitionProps} from '~/utils/style';
import {WithStyled, em, half, sameBorder, transitionProps} from '~/utils/style';
import React from 'react';
import styled from 'styled-components';
......@@ -13,15 +13,19 @@ const StyledInput = styled.input<{rounded?: boolean}>`
display: inline-block;
outline: none;
${props => sameBorder({radius: !props.rounded || half(height)})};
${transitionProps('border-color')}
background-color: var(--input-background-color);
color: var(--text-color);
caret-color: var(--text-color);
${transitionProps(['border-color', 'background-color', 'caret-color', 'color'])}
&:hover,
&:focus {
border-color: ${borderFocusedColor};
border-color: var(--border-focused-color);
}
&::placeholder {
color: ${textLighterColor};
color: var(--text-lighter-color);
${transitionProps('color')}
}
`;
......
......@@ -2,7 +2,7 @@ import * as chart from '~/utils/chart';
import React, {useEffect, useImperativeHandle} from 'react';
import {WithStyled, primaryColor} from '~/utils/style';
import useECharts, {Options, Wrapper} from '~/hooks/useECharts';
import useECharts, {Options, Wrapper, useChartTheme} from '~/hooks/useECharts';
import type {EChartOption} from 'echarts';
import GridLoader from 'react-spinners/GridLoader';
......@@ -46,6 +46,8 @@ const LineChart = React.forwardRef<LineChartRef, LineChartProps & WithStyled>(
onInit
});
const theme = useChartTheme();
useImperativeHandle(ref, () => ({
restore: () => {
echart?.dispatchAction({
......@@ -79,6 +81,7 @@ const LineChart = React.forwardRef<LineChartRef, LineChartProps & WithStyled>(
)
},
options,
theme,
defaults
);
if ((chartOptions?.xAxis as EChartOption.XAxis).type === 'time') {
......@@ -106,7 +109,7 @@ const LineChart = React.forwardRef<LineChartRef, LineChartProps & WithStyled>(
);
}
echart?.setOption(chartOptions, {notMerge: true});
}, [options, data, title, i18n.language, echart]);
}, [options, data, title, theme, i18n.language, echart]);
return (
<Wrapper ref={wrapper} className={className}>
......
import {Link, LinkProps, useLocation} from 'react-router-dom';
import React, {FunctionComponent, useCallback, useEffect, useMemo, useState} from 'react';
import {
backgroundFocusedColor,
border,
borderRadius,
navbarBackgroundColor,
navbarHighlightColor,
navbarHoverBackgroundColor,
primaryColor,
rem,
size,
textColor,
textInvertColor,
transitionProps
} from '~/utils/style';
import {border, borderRadius, rem, size, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import Language from '~/components/Language';
......@@ -52,13 +39,14 @@ function appendApiToken(url: string) {
}
const Nav = styled.nav`
background-color: ${navbarBackgroundColor};
color: ${textInvertColor};
background-color: var(--navbar-background-color);
color: var(--navbar-text-color);
${size('100%')}
padding: 0 ${rem(20)};
display: flex;
justify-content: space-between;
align-items: stretch;
${transitionProps(['background-color', 'color'])}
> .left {
display: flex;
......@@ -97,12 +85,12 @@ const NavItem = styled.div<{active?: boolean}>`
display: inline-flex;
justify-content: center;
align-items: center;
background-color: ${navbarBackgroundColor};
background-color: var(--navbar-background-color);
cursor: pointer;
${transitionProps('background-color')}
&:hover {
background-color: ${navbarHoverBackgroundColor};
background-color: var(--navbar-hover-background-color);
}
&.nav-item {
......@@ -121,7 +109,7 @@ const NavItem = styled.div<{active?: boolean}>`
.nav-text {
margin: ${rem(20)};
padding: ${rem(10)} 0 ${rem(7)};
${props => border('bottom', rem(3), 'solid', props.active ? navbarHighlightColor : 'transparent')}
${props => border('bottom', rem(3), 'solid', props.active ? 'var(--navbar-highlight-color)' : 'transparent')}
${transitionProps('border-bottom')}
text-transform: uppercase;
}
......@@ -138,11 +126,11 @@ const NavItemChild = styled.div<{active?: boolean}>`
&,
&:visited {
color: ${props => (props.active ? primaryColor : textColor)};
color: ${props => (props.active ? 'var(--primary-color)' : 'var(--text-color)')};
}
&:hover {
background-color: ${backgroundFocusedColor};
background-color: var(--background-focused-color);
}
> a {
......
import React, {FunctionComponent, useEffect, useState} from 'react';
import {ellipsis, size, textLighterColor} from '~/utils/style';
import {ellipsis, size, transitionProps} from '~/utils/style';
import Field from '~/components/Field';
import RangeSlider from '~/components/RangeSlider';
......@@ -13,10 +13,11 @@ import {useTranslation} from 'react-i18next';
const relativeFormatter = format('.2f');
const TimeDisplay = styled.div`
color: ${textLighterColor};
color: var(--text-lighter-color);
font-size: 0.857142857em;
padding-left: 1.666666667em;
margin-bottom: 0.416666667em;
${transitionProps('color')}
`;
const Label = styled.span<{color: string}>`
......
......@@ -2,17 +2,11 @@ import {EventContext, ValueContext} from '~/components/RadioGroup';
import React, {FunctionComponent, PropsWithChildren, useCallback, useContext} from 'react';
import {
WithStyled,
backgroundColor,
borderColor,
borderFocusedColor,
borderRadius,
borderRadiusShortHand,
ellipsis,
em,
primaryColor,
sameBorder,
textColor,
textInvertColor,
transitionProps
} from '~/utils/style';
......@@ -24,23 +18,22 @@ const maxWidth = em(144);
const Button = styled.a<{selected?: boolean}>`
cursor: pointer;
background-color: ${props => (props.selected ? primaryColor : backgroundColor)};
color: ${props => (props.selected ? textInvertColor : textColor)};
background-color: ${props => (props.selected ? 'var(--primary-color)' : 'var(--background-color)')};
color: ${props => (props.selected ? 'var(--primary-text-color)' : 'var(--text-color)')};
height: ${height};
line-height: calc(${height} - 2px);
min-width: ${minWidth};
padding: 0 ${em(8)};
text-align: center;
${ellipsis(maxWidth)}
${props => sameBorder({color: props.selected ? primaryColor : borderColor})};
${props => sameBorder({color: props.selected ? 'var(--primary-color)' : 'var(--border-color)'})};
${transitionProps(['color', 'border-color', 'background-color'])}
/* bring selected one to top in order to cover the sibling's border */
${props =>
props.selected ? 'position: relative;' : ''}
${props => (props.selected ? 'position: relative;' : '')}
&:hover {
border-color: ${props => (props.selected ? primaryColor : borderFocusedColor)};
border-color: ${props => (props.selected ? 'var(--primary-color)' : 'var(--border-focused-color)')};
}
&:first-of-type {
......
......@@ -33,7 +33,7 @@ const RadioGroup = <T extends unknown>({
setSelected(value);
onChange?.(value);
},
[onChange] // eslint-disable-line react-hooks/exhaustive-deps
[onChange]
);
return (
......
import InputRange, {Range} from 'react-input-range';
import React, {FunctionComponent, useCallback} from 'react';
import {
WithStyled,
backgroundColor,
em,
half,
position,
primaryActiveColor,
primaryColor,
primaryFocusedColor,
sameBorder,
size,
textLighterColor
} from '~/utils/style';
import {WithStyled, em, half, position, sameBorder, size, transitionProps} from '~/utils/style';
import styled from 'styled-components';
const height = em(20);
const railHeight = em(4);
const thumbSize = em(12);
const railColor = '#DBDEEB';
const Wrapper = styled.div<{disabled?: boolean}>`
height: ${height};
......@@ -32,14 +19,14 @@ const Wrapper = styled.div<{disabled?: boolean}>`
display: none;
}
--color: ${primaryColor};
--color: var(--primary-color);
&:hover {
--color: ${primaryFocusedColor};
--color: var(--primary-focused-color);
}
&:active {
--color: ${primaryActiveColor};
--color: var(--primary-active-color);
}
&__track {
......@@ -49,16 +36,18 @@ const Wrapper = styled.div<{disabled?: boolean}>`
${size(railHeight, '100%')}
${position('absolute', '50%', null, null, null)}
margin-top: -${half(railHeight)};
background-color: ${railColor};
background-color: var(--slider-rail-color);
border-radius: ${half(railHeight)};
${transitionProps('background-color')}
}
&--active {
height: ${railHeight};
position: absolute;
background-color: ${props => (props.disabled ? textLighterColor : 'var(--color)')};
background-color: ${props => (props.disabled ? 'var(--text-lighter-color)' : 'var(--color)')};
border-radius: ${half(railHeight)};
outline: none;
${transitionProps('background-color')}
}
}
......@@ -72,10 +61,11 @@ const Wrapper = styled.div<{disabled?: boolean}>`
${props =>
sameBorder({
width: em(3),
color: props.disabled ? textLighterColor : 'var(--color)',
color: props.disabled ? 'var(--text-lighter-color)' : 'var(--color)',
radius: half(thumbSize)
})}
background-color: ${backgroundColor};
background-color: var(--slider-gripper-color);
${transitionProps(['border-color', 'background-color'])}
}
}
`;
......
import React, {FunctionComponent, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {ellipsis, em, primaryColor, rem, size, textLightColor, textLighterColor} from '~/utils/style';
import {ellipsis, em, primaryColor, rem, size, transitionProps} from '~/utils/style';
import ChartToolbox from '~/components/ChartToolbox';
import GridLoader from 'react-spinners/GridLoader';
......@@ -47,9 +47,10 @@ const Title = styled.div<{color: string}>`
font-size: ${em(14)};
flex-shrink: 0;
flex-grow: 0;
color: ${textLightColor};
color: var(--text-light-color);
${ellipsis()}
max-width: 50%;
${transitionProps('color')}
&::before {
content: '';
......@@ -81,8 +82,9 @@ const Footer = styled.div`
`;
const FooterInfo = styled.div`
color: ${textLighterColor};
color: var(--text-lighter-color);
font-size: ${rem(12)};
${transitionProps('color')}
> * {
display: inline-block;
......
import React, {FunctionComponent, useCallback, useEffect, useState} from 'react';
import {em, textLightColor} from '~/utils/style';
import {em, transitionProps} from '~/utils/style';
import RangeSlider from '~/components/RangeSlider';
import styled from 'styled-components';
......@@ -8,9 +8,10 @@ import {useTranslation} from 'react-i18next';
const Label = styled.div`
display: flex;
justify-content: space-between;
color: ${textLightColor};
color: var(--text-light-color);
font-size: ${em(12)};
margin-bottom: ${em(5)};
${transitionProps('color')}
> :not(:first-child) {
flex-grow: 0;
......
import React, {FunctionComponent, useEffect, useMemo} from 'react';
import {WithStyled, backgroundColor, position, primaryColor, size} from '~/utils/style';
import {WithStyled, position, primaryColor, size, transitionProps} from '~/utils/style';
import useECharts, {useChartTheme} from '~/hooks/useECharts';
import GridLoader from 'react-spinners/GridLoader';
import styled from 'styled-components';
import useECharts from '~/hooks/useECharts';
const Wrapper = styled.div`
position: relative;
background-color: ${backgroundColor};
background-color: var(--background-color);
${transitionProps('background-color')}
> .echarts {
height: 100%;
......@@ -70,17 +71,20 @@ const ScatterChart: FunctionComponent<ScatterChartProps & WithStyled> = ({data,
gl,
autoFit: true
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {tooltip, ...theme} = useChartTheme(gl);
const chartOptions = useMemo(
() => ({
...(gl ? options3D : options2D),
...theme,
series:
data?.map(series => ({
...(gl ? series3D : series2D),
...series
})) ?? []
}),
[gl, data]
[gl, data, theme]
);
useEffect(() => {
......
import Input, {InputProps, padding} from '~/components/Input';
import React, {FunctionComponent, useCallback, useRef} from 'react';
import {WithStyled, math, position, textColor, textLightColor, textLighterColor} from '~/utils/style';
import {WithStyled, math, position, transitionProps} from '~/utils/style';
import Icon from '~/components/Icon';
import styled from 'styled-components';
......@@ -24,7 +24,8 @@ const SearchIcon = styled(Icon)`
transform-origin: center;
${position('absolute', '50%', null, null, padding)}
pointer-events: none;
color: ${textLighterColor};
color: var(--text-lighter-color);
${transitionProps('color')}
`;
const CloseIcon = styled(Icon)`
......@@ -33,14 +34,15 @@ const CloseIcon = styled(Icon)`
transform-origin: center;
${position('absolute', '50%', padding, null, null)}
cursor: pointer;
color: ${textLighterColor};
color: var(--text-lighter-color);
${transitionProps('color')}
&:hover {
color: ${textLightColor};
color: var(--text-light-color);
}
&:active {
color: ${textColor};
color: var(--text-color);
}
`;
......
import React, {FunctionComponent, useCallback, useEffect, useMemo, useState} from 'react';
import {
WithStyled,
backgroundColor,
backgroundFocusedColor,
borderColor,
borderFocusedColor,
borderRadius,
borderRadiusShortHand,
css,
......@@ -12,9 +8,7 @@ import {
em,
math,
sameBorder,
selectedColor,
size,
textLighterColor,
transitionProps
} from '~/utils/style';
......@@ -34,15 +28,13 @@ const Wrapper = styled.div<{opened?: boolean}>`
max-width: 100%;
display: inline-block;
position: relative;
background-color: ${backgroundColor};
background-color: var(--background-color);
${sameBorder({radius: true})}
${props => (props.opened ? borderRadiusShortHand('bottom', '0') : '')}
${transitionProps(
'border-color'
)}
${transitionProps('border-color', 'background-color')}
&:hover {
border-color: ${borderFocusedColor};
border-color: var(--border-focused-color);
}
`;
......@@ -53,7 +45,8 @@ const Trigger = styled.div<{selected?: boolean}>`
justify-content: space-between;
align-items: center;
cursor: pointer;
${props => (props.selected ? '' : `color: ${textLighterColor}`)}
${props => (props.selected ? '' : 'color: var(--text-lighter-color)')}
${transitionProps('color')}
`;
const TriggerIcon = styled(Icon)<{opened?: boolean}>`
......@@ -81,17 +74,18 @@ const List = styled.div<{opened?: boolean; empty?: boolean}>`
left: -1px;
padding: ${padding} 0;
border: inherit;
border-top-color: ${borderColor};
border-top-color: var(--border-color);
${borderRadiusShortHand('bottom', borderRadius)}
display: ${props => (props.opened ? 'block' : 'none')};
z-index: 9999;
line-height: 1;
background-color: inherit;
box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.05);
${transitionProps(['border-color', 'color'])}
${props =>
props.empty
? {
color: textLighterColor,
color: 'var(--text-lighter-color)',
textAlign: 'center'
}
: ''}
......@@ -106,14 +100,14 @@ const listItem = css`
${transitionProps(['color', 'background-color'])}
&:hover {
background-color: ${backgroundFocusedColor};
background-color: var(--background-focused-color);
}
`;
const ListItem = styled.div<{selected?: boolean}>`
${ellipsis()}
${listItem}
${props => (props.selected ? `color: ${selectedColor};` : '')}
${props => (props.selected ? `color: var(--select-selected-text-color);` : '')}
`;
const MultipleListItem = styled(Checkbox)<{selected?: boolean}>`
......@@ -167,7 +161,6 @@ const Select = <T extends unknown>({
setValue
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
const isSelected = useMemo(() => !!(multiple ? (value as T[]) && (value as T[]).length !== 0 : (value as T)), [
multiple,
value
......@@ -178,7 +171,7 @@ const Select = <T extends unknown>({
(onChange as OnSingleChange<T>)?.(mutateValue);
setIsOpenedFalse();
},
[setIsOpenedFalse, onChange] // eslint-disable-line react-hooks/exhaustive-deps
[setIsOpenedFalse, onChange]
);
const changeMultipleValue = useCallback(
(mutateValue: T, checked: boolean) => {
......@@ -195,7 +188,7 @@ const Select = <T extends unknown>({
setValue(newValue);
(onChange as OnMultipleChange<T>)?.(newValue);
},
[value, onChange] // eslint-disable-line react-hooks/exhaustive-deps
[value, onChange]
);
const ref = useClickOutside<HTMLDivElement>(setIsOpenedFalse);
......@@ -207,11 +200,10 @@ const Select = <T extends unknown>({
? {value: item as T, label: item + ''}
: (item as SelectListItem<T>)
) ?? [],
[propList] // eslint-disable-line react-hooks/exhaustive-deps
[propList]
);
const isListEmpty = useMemo(() => list.length === 0, [list]);
// eslint-disable-next-line react-hooks/exhaustive-deps
const findLabelByValue = useCallback((v: T) => list.find(item => item.value === v)?.label ?? '', [list]);
const label = useMemo(
() =>
......@@ -220,7 +212,7 @@ const Select = <T extends unknown>({
? (value as T[]).map(findLabelByValue).join(' / ')
: findLabelByValue(value as T)
: placeholder || t('common:select'),
[multiple, value, findLabelByValue, isSelected, placeholder, t] // eslint-disable-line react-hooks/exhaustive-deps
[multiple, value, findLabelByValue, isSelected, placeholder, t]
);
return (
......
import React, {FunctionComponent, useCallback, useState} from 'react';
import {borderColor, borderFocusedColor, rem, size, transitionProps} from '~/utils/style';
import {height, padding} from '~/components/Input';
import {rem, size, transitionProps} from '~/utils/style';
import BigNumber from 'bignumber.js';
import RangeSlider from '~/components/RangeSlider';
......@@ -17,14 +17,17 @@ const Input = styled.input`
display: inline-block;
outline: none;
padding: ${padding};
${transitionProps('border-color')}
${transitionProps(['border-color', 'color', 'caret-color'])}
border: none;
border-bottom: 1px solid ${borderColor};
border-bottom: 1px solid var(--border-color);
text-align: center;
background-color: transparent;
color: var(--text-color);
caret-color: var(--text-color);
&:hover,
&:focus {
border-bottom-color: ${borderFocusedColor};
border-bottom-color: var(--border-focused-color);
}
`;
......
......@@ -2,8 +2,8 @@ import * as chart from '~/utils/chart';
import type {EChartOption, ECharts, EChartsConvertFinder} from 'echarts';
import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {WithStyled, primaryColor} from '~/utils/style';
import useECharts, {Options, Wrapper} from '~/hooks/useECharts';
import {WithStyled, primaryColor, transitionProps} from '~/utils/style';
import useECharts, {Options, Wrapper, useChartTheme} from '~/hooks/useECharts';
import GridLoader from 'react-spinners/GridLoader';
import defaultsDeep from 'lodash/defaultsDeep';
......@@ -13,11 +13,12 @@ import useThrottleFn from '~/hooks/useThrottleFn';
const Tooltip = styled.div`
position: absolute;
z-index: 1;
background-color: rgba(0, 0, 0, 0.75);
color: #fff;
background-color: var(--tooltip-background-color);
color: var(--tooltip-text-color);
border-radius: 4px;
padding: 5px;
display: none;
${transitionProps(['color', 'background-color'])}
`;
type renderItem = NonNullable<EChartOption.SeriesCustom['renderItem']>;
......@@ -150,6 +151,8 @@ const StackChart = React.forwardRef<StackChartRef, StackChartProps & WithStyled>
[pointerLabelFormatter]
);
const theme = useChartTheme();
const chartOptions = useMemo<EChartOption>(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {color, colorAlt, toolbox, series, ...defaults} = chart;
......@@ -213,9 +216,10 @@ const StackChart = React.forwardRef<StackChartRef, StackChartProps & WithStyled>
]
},
options,
theme,
defaults
);
}, [options, title, rawData, minX, maxX, minY, maxY, negativeY, renderItem, axisPointerLabelFormatter]);
}, [options, title, theme, rawData, minX, maxX, minY, maxY, negativeY, renderItem, axisPointerLabelFormatter]);
const mouseout = useCallback(() => {
setHighlight(null);
......
import React, {FunctionComponent} from 'react';
import {
WithStyled,
backgroundColor,
em,
half,
lightActiveColor,
lightColor,
lightFocusedColor,
primaryColor,
transitionProps
} from '~/utils/style';
import {WithStyled, em, half, transitionProps} from '~/utils/style';
import styled from 'styled-components';
......@@ -21,17 +11,17 @@ const Span = styled.span<{active?: boolean}>`
line-height: ${height};
display: inline-block;
border-radius: ${half(height)};
color: ${prop => (prop.active ? backgroundColor : primaryColor)};
background-color: ${prop => (prop.active ? primaryColor : lightColor)};
color: ${prop => (prop.active ? 'var(--background-color)' : 'var(--primary-color)')};
background-color: ${prop => (prop.active ? 'var(--primary-color)' : 'var(--tag-background-color)')};
cursor: pointer;
${transitionProps(['color', 'background-color'])}
&:hover {
background-color: ${prop => (prop.active ? primaryColor : lightFocusedColor)};
background-color: ${prop => (prop.active ? 'var(--primary-color)' : 'var(--tag-focused-background-color)')};
}
&:active {
background-color: ${prop => (prop.active ? primaryColor : lightActiveColor)};
background-color: ${prop => (prop.active ? 'var(--primary-color)' : 'var(--tag-active-background-color)')};
}
`;
......
import {MutableRefObject, useCallback, useEffect, useLayoutEffect, useRef, useState} from 'react';
import {maskColor, position, primaryColor, size, textColor} from '~/utils/style';
import {MutableRefObject, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
import {position, primaryColor, size} from '~/utils/style';
import type {ECharts} from 'echarts';
import {dataURL2Blob} from '~/utils/image';
import {saveAs} from 'file-saver';
import styled from 'styled-components';
import {themes} from '~/utils/theme';
import useTheme from '~/hooks/useTheme';
export type Options = {
loading?: boolean;
......@@ -26,6 +28,7 @@ const useECharts = <T extends HTMLElement, W extends HTMLElement = HTMLDivElemen
const ref = useRef<T | null>(null);
const echartInstance = useRef<ECharts | null>(null);
const [echart, setEchart] = useState<ECharts | null>(null);
const theme = useTheme();
const onInit = useRef(options.onInit);
const onDispose = useRef(options.onDispose);
......@@ -82,14 +85,14 @@ const useECharts = <T extends HTMLElement, W extends HTMLElement = HTMLDivElemen
echartInstance.current?.showLoading('default', {
text: '',
color: primaryColor,
textColor,
maskColor,
textColor: themes[theme].textColor,
maskColor: themes[theme].maskColor,
zlevel: 0
});
} else {
echartInstance.current?.hideLoading();
}
}, [options.loading]);
}, [options.loading, theme]);
const wrapper = useRef<W | null>(null);
useLayoutEffect(() => {
......@@ -138,3 +141,128 @@ export const Wrapper = styled.div`
align-items: center;
}
`;
export const useChartTheme = (gl?: boolean) => {
const theme = useTheme();
const tt = useMemo(() => themes[theme], [theme]);
if (gl) {
return {
title: {
textStyle: {
color: tt.textColor
}
},
tooltip: {
backgroundColor: tt.tooltipBackgroundColor,
borderColor: tt.tooltipBackgroundColor,
textStyle: {
color: tt.tooltipTextColor
}
},
xAxis3D: {
nameTextStyle: {
color: tt.textLighterColor
},
axisLabel: {
color: tt.textLighterColor
},
axisLine: {
lineStyle: {
color: tt.borderColor
}
},
splitLine: {
lineStyle: {
color: tt.borderColor
}
}
},
yAxis3D: {
nameTextStyle: {
color: tt.textLighterColor
},
axisLabel: {
color: tt.textLighterColor
},
axisLine: {
lineStyle: {
color: tt.borderColor
}
},
splitLine: {
lineStyle: {
color: tt.borderColor
}
}
},
zAxis3D: {
nameTextStyle: {
color: tt.textLighterColor
},
axisLabel: {
color: tt.textLighterColor
},
axisLine: {
lineStyle: {
color: tt.borderColor
}
},
splitLine: {
lineStyle: {
color: tt.borderColor
}
}
}
};
}
return {
title: {
textStyle: {
color: tt.textColor
}
},
tooltip: {
backgroundColor: tt.tooltipBackgroundColor,
borderColor: tt.tooltipBackgroundColor,
textStyle: {
color: tt.tooltipTextColor
}
},
xAxis: {
nameTextStyle: {
color: tt.textLighterColor
},
axisLabel: {
color: tt.textLighterColor
},
axisLine: {
lineStyle: {
color: tt.borderColor
}
},
splitLine: {
lineStyle: {
color: tt.borderColor
}
}
},
yAxis: {
nameTextStyle: {
color: tt.textLighterColor
},
axisLabel: {
color: tt.textLighterColor
},
axisLine: {
lineStyle: {
color: tt.borderColor
}
},
splitLine: {
lineStyle: {
color: tt.borderColor
}
}
}
};
};
import {createContext, useContext} from 'react';
import type {Dispatch} from 'react';
export interface GlobalState {
scalar: {
runs: string[];
};
histogram: {
runs: string[];
};
image: {
runs: string[];
};
audio: {
runs: string[];
};
prCurve: {
runs: string[];
};
graph: {
model: FileList | File[] | null;
};
}
export const globalState: GlobalState = {
scalar: {
runs: []
},
histogram: {
runs: []
},
image: {
runs: []
},
audio: {
runs: []
},
prCurve: {
runs: []
},
graph: {
model: null
}
};
export const GlobalStateContext = createContext<GlobalState>(globalState);
export const GlobalDispatchContext = createContext<Dispatch<Partial<GlobalState>>>(() => void 0);
const useGlobalState = () => [useContext(GlobalStateContext), useContext(GlobalDispatchContext)] as const;
export default useGlobalState;
......@@ -23,7 +23,7 @@ function useRequest<D = unknown, E extends Error = Error>(
config?: ConfigInterface<D, E, fetcherFn<D>>
): Response<D, E> {
const {data, error, ...other} = useSWR<D, E>(key, fetcher, config);
const loading = useMemo(() => !!key && !data && !error, [key, data, error]);
const loading = useMemo(() => !!key && data === void 0 && !error, [key, data, error]);
useEffect(() => {
if (error) {
......
import type {Run, Tag, TagWithSingleRun, TagsData} from '~/types';
import {actions, selectors} from '~/store';
import {color, colorAlt} from '~/utils/chart';
import {useCallback, useEffect, useMemo, useReducer} from 'react';
import {useDispatch, useSelector} from 'react-redux';
import type {Page} from '~/store/runs/types';
import {cache} from 'swr';
import camelCase from 'lodash/camelCase';
import groupBy from 'lodash/groupBy';
import intersection from 'lodash/intersection';
import intersectionBy from 'lodash/intersectionBy';
import uniq from 'lodash/uniq';
import useGlobalState from '~/hooks/useGlobalState';
import useQuery from '~/hooks/useQuery';
import {useRunningRequest} from '~/hooks/useRequest';
......@@ -160,7 +161,7 @@ const reducer = (state: State, action: Action): State => {
};
// TODO: refactor to improve performance
const useTagFilter = (type: string, running: boolean) => {
const useTagFilter = (type: Page, running: boolean) => {
const query = useQuery();
const {data, loading, error} = useRunningRequest<TagsData>(`/${type}/tags`, running);
......@@ -168,13 +169,9 @@ const useTagFilter = (type: string, running: boolean) => {
// clear cache in order to fully reload data when switching page
useEffect(() => () => cache.delete(`/${type}/tags`), [type]);
const pageName = useMemo(() => camelCase(type), [type]);
const [globalState, globalDispatch] = useGlobalState();
const storedRuns = useMemo(
() => ((globalState as unknown) as Record<string, {runs: string[]}>)[camelCase(pageName)]?.runs ?? [],
[pageName, globalState]
);
const storeDispatch = useDispatch();
const selector = useMemo(() => selectors.runs.getRunsByPage(type), [type]);
const storedRuns = useSelector(selector);
const runs: string[] = useMemo(() => data?.runs ?? [], [data]);
const tags: Tags = useMemo(
......@@ -222,15 +219,9 @@ const useTagFilter = (type: string, running: boolean) => {
});
}
}, [queryRuns, state.runs]);
useEffect(
() =>
globalDispatch({
[pageName]: {
runs: state.globalRuns
}
}),
[pageName, state.globalRuns, globalDispatch]
);
useEffect(() => {
storeDispatch(actions.runs.setSelectedRuns(type, state.globalRuns));
}, [storeDispatch, state.globalRuns, type]);
const tagsWithSingleRun = useMemo(
() =>
......
import {selectors} from '~/store';
import {useSelector} from 'react-redux';
const useTheme = () => useSelector(selectors.theme.theme);
export default useTheme;
......@@ -2,10 +2,11 @@ import '~/utils/i18n';
import App from './App';
import BodyLoading from '~/components/BodyLoading';
import GlobalState from '~/components/GlobalState';
import {GlobalStyle} from '~/utils/style';
import {Provider} from 'react-redux';
import React from 'react';
import ReactDOM from 'react-dom';
import store from '~/store';
const TELEMETRY_ID: string = import.meta.env.SNOWPACK_PUBLIC_TELEMETRY_ID;
......@@ -23,9 +24,9 @@ ReactDOM.render(
<React.StrictMode>
<GlobalStyle />
<React.Suspense fallback={<BodyLoading />}>
<GlobalState>
<Provider store={store}>
<App />
</GlobalState>
</Provider>
</React.Suspense>
</React.StrictMode>,
document.getElementById('root')
......
......@@ -3,7 +3,9 @@ import type {Documentation, OpenedResult, Properties, SearchItem, SearchResult}
import GraphComponent, {GraphRef} from '~/components/GraphPage/Graph';
import React, {FunctionComponent, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import Select, {SelectProps} from '~/components/Select';
import {actions, selectors} from '~/store';
import {primaryColor, rem, size} from '~/utils/style';
import {useDispatch, useSelector} from 'react-redux';
import type {BlobResponse} from '~/utils/fetch';
import Button from '~/components/Button';
......@@ -20,7 +22,6 @@ import Search from '~/components/GraphPage/Search';
import Title from '~/components/Title';
import Uploader from '~/components/GraphPage/Uploader';
import styled from 'styled-components';
import useGlobalState from '~/hooks/useGlobalState';
import useRequest from '~/hooks/useRequest';
import {useTranslation} from 'react-i18next';
......@@ -71,11 +72,12 @@ const Loading = styled.div`
const Graph: FunctionComponent = () => {
const {t} = useTranslation(['graph', 'common']);
const [globalState, globalDispatch] = useGlobalState();
const storeDispatch = useDispatch();
const storeModel = useSelector(selectors.graph.model);
const graph = useRef<GraphRef>(null);
const file = useRef<HTMLInputElement>(null);
const [files, setFiles] = useState<FileList | File[] | null>(globalState.graph.model);
const [files, setFiles] = useState<FileList | File[] | null>(storeModel);
const onClickFile = useCallback(() => {
if (file.current) {
file.current.value = '';
......@@ -86,11 +88,11 @@ const Graph: FunctionComponent = () => {
(e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target;
if (target && target.files && target.files.length) {
globalDispatch({graph: {model: target.files}});
storeDispatch(actions.graph.setModel(target.files));
setFiles(target.files);
}
},
[globalDispatch]
[storeDispatch]
);
const {data, loading} = useRequest<BlobResponse>(files ? null : '/graph/graph');
......
import ChartPage, {WithChart} from '~/components/ChartPage';
import React, {FunctionComponent, useCallback, useEffect, useMemo, useState} from 'react';
import type {Run, StepInfo, Tag} from '~/resource/pr-curve';
import {borderColor, rem} from '~/utils/style';
import {rem, transitionProps} from '~/utils/style';
import {AsideSection} from '~/components/Aside';
import Content from '~/components/Content';
......@@ -33,9 +33,10 @@ const StepSliderWrapper = styled.div`
}
+ .run-section {
border-top: 1px solid ${borderColor};
border-top: 1px solid var(--border-color);
margin-top: 0;
padding-top: ${rem(20)};
${transitionProps('border-color')}
}
&:empty + .run-section {
......
import {ActionTypes} from './types';
import type {Model} from './types';
export function setModel(model: Model) {
return {
type: ActionTypes.SET_MODEL,
model
};
}
import type {GraphActionTypes, GraphState} from './types';
import {ActionTypes} from './types';
const initState: GraphState = {
model: null
};
function graphReducer(state = initState, action: GraphActionTypes): GraphState {
switch (action.type) {
case ActionTypes.SET_MODEL:
return {
...state,
model: action.model
};
default:
return state;
}
}
export default graphReducer;
import type {RootState} from '../index';
export const model = (state: RootState) => state.graph.model;
export type Model = FileList | File[] | null;
export enum ActionTypes {
SET_MODEL = 'SET_MODEL'
}
export interface GraphState {
model: Model;
}
export type Page = keyof GraphState;
interface SetModelAction {
type: ActionTypes.SET_MODEL;
model: Model;
}
export type GraphActionTypes = SetModelAction;
import * as graphActions from './graph/actions';
import * as graphSelectors from './graph/selectors';
import * as runsActions from './runs/actions';
import * as runsSelectors from './runs/selectors';
import * as themeActions from './theme/actions';
import * as themeSelectors from './theme/selectors';
import {combineReducers, createStore} from 'redux';
import graphReducer from './graph/reducers';
import runsReducer from './runs/reducers';
import themeReducer from './theme/reducers';
const rootReducer = combineReducers({
graph: graphReducer,
theme: themeReducer,
runs: runsReducer
});
export default createStore(rootReducer);
export const selectors = {
graph: graphSelectors,
runs: runsSelectors,
theme: themeSelectors
};
export const actions = {
graph: graphActions,
runs: runsActions,
theme: themeActions
};
export type RootState = ReturnType<typeof rootReducer>;
import type {Page, Runs} from './types';
import {ActionTypes} from './types';
export function setSelectedRuns(page: Page, runs: Runs) {
return {
type: ActionTypes.SET_SELECTED_RUNS,
page,
runs
};
}
import type {RunsActionTypes, RunsState} from './types';
import {ActionTypes} from './types';
const initState: RunsState = {
scalar: [],
histogram: [],
image: [],
audio: [],
'pr-curve': []
};
function runsReducer(state = initState, action: RunsActionTypes): RunsState {
switch (action.type) {
case ActionTypes.SET_SELECTED_RUNS:
return {
...state,
[action.page]: action.runs
};
default:
return state;
}
}
export default runsReducer;
import type {Page} from './types';
import type {RootState} from '../index';
export const getRunsByPage = (page: Page) => (state: RootState) => state.runs[page];
export type Runs = string[];
export enum ActionTypes {
SET_SELECTED_RUNS = 'SET_SELECTED_RUNS'
}
export interface RunsState {
scalar: Runs;
histogram: Runs;
image: Runs;
audio: Runs;
'pr-curve': Runs;
}
export type Page = keyof RunsState;
interface SetSelectedRunsAction {
type: ActionTypes.SET_SELECTED_RUNS;
page: Page;
runs: Runs;
}
export type RunsActionTypes = SetSelectedRunsAction;
import {ActionTypes} from './types';
import type {Theme} from './types';
export function setTheme(theme: Theme) {
return {
type: ActionTypes.SET_THEME,
theme
};
}
import type {ThemeActionTypes, ThemeState} from './types';
import {ActionTypes} from './types';
import {theme} from '~/utils/theme';
const initState: ThemeState = {
theme
};
function themeReducer(state = initState, action: ThemeActionTypes): ThemeState {
switch (action.type) {
case ActionTypes.SET_THEME:
return {
...state,
theme: action.theme
};
default:
return state;
}
}
export default themeReducer;
import type {RootState} from '../index';
export const theme = (state: RootState) => state.theme.theme;
import type {Theme} from '~/utils/theme';
export type {Theme} from '~/utils/theme';
export enum ActionTypes {
SET_THEME = 'SET_THEME'
}
export interface ThemeState {
theme: Theme;
}
interface SetThemeAction {
type: ActionTypes.SET_THEME;
theme: Theme;
}
export type ThemeActionTypes = SetThemeAction;
import {colors} from '~/utils/theme';
import {format} from 'd3-format';
import {primaryColor} from '~/utils/style';
export const color = [
'#2932E1',
......@@ -44,6 +44,7 @@ export const colorAlt = [
export const title = {
textStyle: {
color: '#000',
fontSize: 16,
fontWeight: 'bold'
},
......@@ -54,6 +55,10 @@ export const title = {
export const tooltip = {
trigger: 'axis',
backgroundColor: 'rgba(0, 0, 0, 0.75)',
borderColor: 'rgba(0, 0, 0, 0.75)',
textStyle: {
color: '#fff'
},
hideDelay: 100,
enterable: false,
axisPointer: {
......@@ -62,11 +67,11 @@ export const tooltip = {
show: true
},
lineStyle: {
color: '#2932E1',
color: colors.primary.default,
type: 'dashed'
},
crossStyle: {
color: '#2932E1',
color: colors.primary.default,
type: 'dashed'
}
}
......@@ -139,6 +144,10 @@ export const yAxis = {
type: 'value',
name: '',
splitNumber: 4,
nameTextStyle: {
fontSize: 12,
color: '#666'
},
axisLine: {
lineStyle: {
color: '#CCC'
......@@ -163,7 +172,7 @@ export const series = {
hoverAnimation: false,
animationDuration: 100,
lineStyle: {
color: primaryColor,
color: colors.primary.default,
width: 1.5
}
};
......@@ -4,6 +4,7 @@ import 'react-toastify/dist/ReactToastify.css';
import * as polished from 'polished';
import {colors, variables} from '~/utils/theme';
import {createGlobalStyle, keyframes} from 'styled-components';
import {css} from 'styled-components';
......@@ -17,7 +18,7 @@ export {
fontFace as fontFaceShortHand
} from 'polished';
const {math, size, lighten, darken, normalize, transitions, border, position} = polished;
const {math, size, normalize, transitions, border, position} = polished;
// sizes
const fontSize = '14px';
......@@ -31,35 +32,11 @@ export const asideWidth = rem(260);
export const borderRadius = '4px';
export const progressSpinnerSize = '20px';
// colors
export const primaryColor = '#2932E1';
export const dangerColor = '#FF3912';
export const primaryFocusedColor = lighten(0.08, primaryColor);
export const primaryActiveColor = lighten(0.12, primaryColor);
export const dangerFocusedColor = lighten(0.08, dangerColor);
export const dangerActiveColor = lighten(0.12, dangerColor);
export const selectedColor = '#1A73E8';
export const lightColor = '#F4F5FC';
export const lightFocusedColor = darken(0.03, lightColor);
export const lightActiveColor = darken(0.06, lightColor);
export const textColor = '#333';
export const textLightColor = '#666';
export const textLighterColor = '#999';
export const textInvertColor = '#FFF';
export const bodyBackgroundColor = '#F4F4F4';
export const primaryBackgroundColor = '#F2F6FF';
export const backgroundColor = '#FFF';
export const backgroundFocusedColor = '#F6F6F6';
export const borderColor = '#DDD';
export const borderFocusedColor = darken(0.15, borderColor);
export const borderActiveColor = darken(0.3, borderColor);
export const navbarBackgroundColor = '#1527C2';
export const navbarHoverBackgroundColor = lighten(0.05, navbarBackgroundColor);
export const navbarHighlightColor = '#596cd6';
export const progressBarColor = '#FFF';
export const maskColor = 'rgba(255, 255, 255, 0.8)';
export const tooltipBackgroundColor = 'rgba(0, 0, 0, 0.6)';
export const tooltipTextColor = '#FFF';
// shims
// TODO: remove and use colors in theme instead
export const primaryColor = colors.primary.default;
export const primaryFocusedColor = colors.primary.focused;
export const primaryActiveColor = colors.primary.active;
// transitions
export const duration = '75ms';
......@@ -72,12 +49,12 @@ export const sameBorder = (
| number
| {width?: string | number; type?: string; color?: string; radius?: string | boolean},
type = 'solid',
color = borderColor,
color = 'var(--border-color)',
radius?: string | boolean
) => {
if ('object' === typeof width) {
type = width.type ?? 'solid';
color = width.color ?? borderColor;
color = width.color ?? 'var(--border-color)';
radius = width.radius === true ? borderRadius : width.radius;
width = width.width ?? '1px';
}
......@@ -99,16 +76,16 @@ export const transitionProps = (props: string | string[], args?: string | {durat
export const link = css`
a {
color: ${primaryColor};
color: var(--primary-color);
cursor: pointer;
${transitionProps('color')};
&:hover {
color: ${primaryFocusedColor};
color: var(--primary-focused-color);
}
&:active {
color: ${primaryActiveColor};
color: var(--primary-active-color);
}
}
`;
......@@ -130,6 +107,8 @@ export type WithStyled = {
export const GlobalStyle = createGlobalStyle`
${normalize}
${variables}
html {
font-size: ${fontSize};
font-family: 'Merriweather Sans', Helvetica, Arial, sans-serif;
......@@ -140,8 +119,9 @@ export const GlobalStyle = createGlobalStyle`
html,
body {
height: 100%;
background-color: ${bodyBackgroundColor};
color: ${textColor};
background-color: var(--body-background-color);
color: var(--text-color);
${transitionProps(['background-color', 'color'])}
}
a {
......@@ -162,19 +142,21 @@ export const GlobalStyle = createGlobalStyle`
}
#nprogress .bar {
background: ${progressBarColor};
background-color: var(--progress-bar-color);
z-index: 99999;
${position('fixed', 0, null, null, 0)}
${size('2px', '100%')}
${transitionProps('background-color')}
}
#nprogress .peg {
display: block;
${position('absolute', null, 0, null, null)}
${size('100%', rem(100))}
box-shadow: 0 0 rem(10) ${progressBarColor}, 0 0 ${rem(5)} ${progressBarColor};
box-shadow: 0 0 rem(10) var(--progress-bar-color), 0 0 ${rem(5)} var(--progress-bar-color);
opacity: 1;
transform: rotate(3deg) translate(0px, -${rem(4)});
${transitionProps('box-shadow')}
}
#nprogress .spinner {
......@@ -188,11 +170,13 @@ export const GlobalStyle = createGlobalStyle`
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: ${progressBarColor};
border-left-color: ${progressBarColor};
border-top-color: var(--progress-bar-color);
border-left-color: var(--progress-bar-color);
border-radius: 50%;
animation: ${spinner} 400ms linear infinite;
${transitionProps('border-color')}
}
.nprogress-custom-parent {
......@@ -213,7 +197,8 @@ export const GlobalStyle = createGlobalStyle`
}
.Toastify__toast--default {
color: ${textColor};
color: var(--text-color);
${transitionProps('color')}
}
.Toastify__toast-body {
......@@ -223,10 +208,11 @@ export const GlobalStyle = createGlobalStyle`
[data-tippy-root] .tippy-box {
z-index: 10002;
color: ${textColor};
background-color: ${backgroundColor};
box-shadow: 0 0 10px 0 rgba(0,0,0,0.10);
color: var(--text-color);
background-color: var(--background-color);
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
border-radius: ${borderRadius};
${transitionProps(['color', 'background-color'])}
> .tippy-content {
padding: 0;
......@@ -234,22 +220,26 @@ export const GlobalStyle = createGlobalStyle`
display: flow-root;
}
> .tippy-arrow {
${transitionProps('border-color')}
}
&[data-placement^='top'] > .tippy-arrow::before {
border-top-color: ${backgroundColor};
border-top-color: var(--background-color);
}
&[data-placement^='bottom'] > .tippy-arrow::before {
border-bottom-color: ${backgroundColor};
border-bottom-color: var(--background-color);
}
&[data-placement^='left'] > .tippy-arrow::before {
border-left-color: ${backgroundColor};
border-left-color: var(--background-color);
}
&[data-placement^='right'] > .tippy-arrow::before {
border-right-color: ${backgroundColor};
border-right-color: var(--background-color);
}
&[data-theme~='tooltip'] {
color: ${tooltipTextColor};
background-color: ${tooltipBackgroundColor};
color: var(--tooltip-text-color);
background-color: var(--tooltip-background-color);
box-shadow: none;
> .tippy-content {
......@@ -257,16 +247,16 @@ export const GlobalStyle = createGlobalStyle`
}
&[data-placement^='top'] > .tippy-arrow::before {
border-top-color: ${tooltipBackgroundColor};
border-top-color: var(--tooltip-background-color);
}
&[data-placement^='bottom'] > .tippy-arrow::before {
border-bottom-color: ${tooltipBackgroundColor};
border-bottom-color: var(--tooltip-background-color);
}
&[data-placement^='left'] > .tippy-arrow::before {
border-left-color: ${tooltipBackgroundColor};
border-left-color: var(--tooltip-background-color);
}
&[data-placement^='right'] > .tippy-arrow::before {
border-right-color: ${tooltipBackgroundColor};
border-right-color: var(--tooltip-background-color);
}
}
}
......
import {darken, lighten} from 'polished';
import {css} from 'styled-components';
import kebabCase from 'lodash/kebabCase';
export type Theme = 'light' | 'dark';
export const THEME: Theme | undefined = import.meta.env.SNOWPACK_PUBLIC_THEME;
export const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
export const theme = THEME || (matchMedia.matches ? 'dark' : 'light');
export const colors = {
primary: {
default: '#2932e1',
focused: lighten(0.08, '#2932e1'),
active: lighten(0.12, '#2932e1'),
text: '#fff'
},
danger: {
default: '#ff3912',
focused: lighten(0.08, '#ff3912'),
active: lighten(0.12, '#ff3912'),
text: '#fff'
}
} as const;
export const themes = {
light: {
textColor: '#333',
textLightColor: '#666',
textLighterColor: '#999',
textInvertColor: '#fff',
backgroundColor: '#fff',
backgroundFocusedColor: '#f6f6f6',
bodyBackgroundColor: '#f4f4f4',
borderColor: '#ddd',
borderFocusedColor: darken(0.15, '#ddd'),
borderActiveColor: darken(0.3, '#ddd'),
navbarTextColor: '#fff',
navbarBackgroundColor: '#1527c2',
navbarHoverBackgroundColor: lighten(0.05, '#1527c2'),
navbarHighlightColor: '#596cd6',
tagBackgroundColor: '#f4f5fc',
tagFocusedBackgroundColor: darken(0.03, '#f4f5fc'),
tagActiveBackgroundColor: darken(0.06, '#f4f5fc'),
inputBackgroundColor: '#fff',
selectSelectedTextColor: '#1a73e8',
sliderRailColor: '#dbdeeb',
sliderGripperColor: '#fff',
modelHeaderBackgroundColor: '#eee',
codeColor: '#666',
codeBackgroundColor: 'rgba(216, 216, 216, 0.5)',
audioBackgroundColor: '#f2f6ff',
tooltipTextColor: '#fff',
tooltipBackgroundColor: 'rgba(0, 0, 0, 0.6)',
progressBarColor: '#fff',
maskColor: 'rgba(255, 255, 255, 0.8)',
graphUploaderBackgroundColor: '#f9f9f9',
graphUploaderActiveBackgroundColor: '#f2f6ff',
graphCopyrightColor: '#ddd',
graphCopyrightLogoFilter: 'opacity(25%)'
},
dark: {
textColor: '#cfcfd1',
textLightColor: '#575757',
textLighterColor: '#757575',
textInvertColor: '#000',
backgroundColor: '#1d1d1f',
backgroundFocusedColor: '#333',
bodyBackgroundColor: '#121214',
borderColor: '#3f3f42',
borderFocusedColor: lighten(0.15, '#3f3f42'),
borderActiveColor: lighten(0.3, '#3f3f42'),
navbarTextColor: '#fff',
navbarBackgroundColor: '#262629',
navbarHoverBackgroundColor: lighten(0.05, '#262629'),
navbarHighlightColor: '#fff',
tagBackgroundColor: '#333',
tagFocusedBackgroundColor: lighten(0.3, '#333'),
tagActiveBackgroundColor: lighten(0.4, '#333'),
inputBackgroundColor: '#262629',
selectSelectedTextColor: '#1a73e8',
sliderRailColor: '#727275',
sliderGripperColor: '#cfcfd1',
modelHeaderBackgroundColor: '#303033',
codeColor: '#cfcfd1',
codeBackgroundColor: '#3f3f42',
audioBackgroundColor: '#303033',
tooltipTextColor: '#d1d1d1',
tooltipBackgroundColor: '#292929',
progressBarColor: '#fff',
maskColor: 'rgba(0, 0, 0, 0.8)',
graphUploaderBackgroundColor: '#262629',
graphUploaderActiveBackgroundColor: '#303033',
graphCopyrightColor: '#565657',
graphCopyrightLogoFilter: 'invert(35%) sepia(5%) saturate(79%) hue-rotate(202deg) brightness(88%) contrast(86%)'
}
} as const;
function generateColorVariables(color: typeof colors) {
return Object.entries(color)
.map(([name, variant]) =>
Object.entries(variant)
.map(([key, value]) => {
if (key === 'default') {
return `--${kebabCase(name)}-color: ${value};`;
}
return `--${kebabCase(name)}-${kebabCase(key)}-color: ${value};`;
})
.join('\n')
)
.join('\n');
}
function generateThemeVariables(theme: Record<string, string>) {
return Object.entries(theme)
.map(([key, value]) => `--${kebabCase(key)}: ${value};`)
.join('\n');
}
const mediaQuery = css`
@media (prefers-color-scheme: dark) {
${generateThemeVariables(themes.dark)}
}
`;
export const variables = css`
:root {
${generateColorVariables(colors)}
${generateThemeVariables(themes[THEME || 'light'])}
${(!THEME && mediaQuery) || ''}
}
`;
......@@ -34,7 +34,7 @@
"devDependencies": {
"@types/express": "4.17.8",
"@types/mkdirp": "1.0.1",
"@types/node": "14.6.4",
"@types/node": "14.10.3",
"@types/node-fetch": "2.5.7",
"@types/rimraf": "3.0.0",
"cpy-cli": "3.1.1",
......
......@@ -41,8 +41,8 @@
},
"devDependencies": {
"@types/express": "4.17.8",
"@types/faker": "4.1.12",
"@types/node": "14.6.4",
"@types/faker": "5.1.0",
"@types/node": "14.10.3",
"cpy-cli": "3.1.1",
"rimraf": "3.0.2",
"ts-node": "9.0.0",
......
......@@ -40,16 +40,17 @@
"pako": "1.0.11"
},
"devDependencies": {
"autoprefixer": "9.8.6",
"autoprefixer": "10.0.0",
"copy-webpack-plugin": "6.1.0",
"css-loader": "4.2.2",
"css-loader": "4.3.0",
"html-webpack-plugin": "4.4.1",
"mini-css-extract-plugin": "0.11.0",
"postcss-loader": "3.0.0",
"mini-css-extract-plugin": "0.11.2",
"postcss": "8.0.5",
"postcss-loader": "4.0.2",
"rimraf": "3.0.2",
"sass": "1.26.10",
"sass-loader": "10.0.2",
"terser": "5.3.0",
"terser": "5.3.1",
"webpack": "4.44.1",
"webpack-cli": "3.3.12"
},
......
......@@ -62,6 +62,8 @@ host.BrowserHost = class {
return this._view.toggleNames(data);
case 'toggle-direction':
return this._view.toggleDirection(data);
case 'toggle-theme':
return this._view.toggleTheme(data);
case 'export':
return this._view.export(`${document.title}.${data}`);
case 'change-graph':
......
......@@ -45,6 +45,10 @@ text {
font-size: 11px;
text-rendering: geometricPrecision;
fill: #000;
.dark & {
fill: #CFCFD1;
}
}
.node-item {
......@@ -184,6 +188,10 @@ text {
.node-attribute path {
fill: #fff;
stroke-width: 0;
.dark & {
fill: #262629;
}
}
.graph-item-input {
......
......@@ -105,6 +105,10 @@ view.View = class {
return this._showHorizontal;
}
toggleTheme(theme) {
this._host.document.body.className = theme;
}
_reload() {
this._host.status('loading');
if (this._model && this._activeGraph) {
......
......@@ -46,7 +46,7 @@
"devDependencies": {
"@types/enhanced-resolve": "3.0.6",
"@types/express": "4.17.8",
"@types/node": "14.6.4",
"@types/node": "14.10.3",
"@visualdl/mock": "2.0.9",
"cross-env": "7.0.2",
"nodemon": "2.0.4",
......
......@@ -2337,16 +2337,16 @@
once "^1.4.0"
"@octokit/request@^5.2.0":
version "5.4.8"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.8.tgz#13ad36e172bb57e78bacf02cd86210d1f7412f04"
integrity sha512-mWbxjsARJzAq5xp+ZrQfotc+MHFz3/Am2qATJwflv4PZ1TjhgIJnr60PCVdZT9Z/tl+uPXooaVgeviy1KkDlLQ==
version "5.4.9"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.9.tgz#0a46f11b82351b3416d3157261ad9b1558c43365"
integrity sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA==
dependencies:
"@octokit/endpoint" "^6.0.1"
"@octokit/request-error" "^2.0.0"
"@octokit/types" "^5.0.0"
deprecation "^2.0.0"
is-plain-object "^5.0.0"
node-fetch "^2.3.0"
node-fetch "^2.6.1"
once "^1.4.0"
universal-user-agent "^6.0.0"
......@@ -2380,9 +2380,9 @@
"@types/node" ">= 8"
"@octokit/types@^5.0.0", "@octokit/types@^5.0.1":
version "5.4.1"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.4.1.tgz#d5d5f2b70ffc0e3f89467c3db749fa87fc3b7031"
integrity sha512-OlMlSySBJoJ6uozkr/i03nO5dlYQyE05vmQNZhAh9MyO4DPBP88QlwsDVLmVjIMFssvIZB6WO0ctIGMRG+xsJQ==
version "5.5.0"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b"
integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==
dependencies:
"@types/node" ">= 8"
......@@ -2532,6 +2532,14 @@
is-module "^1.0.0"
resolve "^1.17.0"
"@rollup/plugin-replace@^2.3.3":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.3.tgz#cd6bae39444de119f5d905322b91ebd4078562e7"
integrity sha512-XPmVXZ7IlaoWaJLkSCDaa0Y6uVo5XQYHhiMFzOd5qSv5rE+t/UJToPIOE56flKIxBFQI27ONsxb7dqHnwSsjKQ==
dependencies:
"@rollup/pluginutils" "^3.0.8"
magic-string "^0.25.5"
"@rollup/pluginutils@^3.0.4", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
......@@ -2589,10 +2597,10 @@
"@babel/core" "^7.10.5"
workerpool "^6.0.0"
"@snowpack/plugin-build-script@^2.0.6":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-build-script/-/plugin-build-script-2.0.6.tgz#95c85cc6c4c53763a91a2d170633918ecd0d3cc8"
integrity sha512-qtvXQq54MaBYJrCTa+DaK/KzUXYBkRukaGzIdhpqW/xzOknCjpufiQIy0VUzxwRQk0OlLC6/h3sV1hSMsoTVJw==
"@snowpack/plugin-build-script@^2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-build-script/-/plugin-build-script-2.0.7.tgz#1d133030ceac51efce471b66622d1b7320d5ab9f"
integrity sha512-f1fZN0Blsfk25oMBf62wvhHm6v7DUG0W85+JFKzYI6SHOIHrYL37o9xaJX7RJpn2kEKCRymWsQo4PclQdnL77w==
dependencies:
execa "^4.0.3"
npm-run-path "^4.0.1"
......@@ -2605,6 +2613,19 @@
dotenv "^8.2.0"
dotenv-expand "^5.1.0"
"@snowpack/plugin-optimize@0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-optimize/-/plugin-optimize-0.2.1.tgz#00862eeda14d6d2681fc11414ad42d97677fbb17"
integrity sha512-d/XxaSafJ8WmJruSzPibD9BsmadSS1H+CPq1l3/6Dan9VJYwZ+dOrqMbAKWNGdbsYniJED+HkLRR1r2jBUSr2A==
dependencies:
csso "^4.0.3"
es-module-lexer "^0.3.24"
esbuild "^0.6.28"
glob "^7.1.6"
html-minifier "^4.0.0"
kleur "^4.1.1"
p-queue "^6.6.1"
"@snowpack/plugin-react-refresh@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-react-refresh/-/plugin-react-refresh-2.1.0.tgz#7e8c66250e5823413155c027d2cd4f3d1216d1e1"
......@@ -2612,10 +2633,10 @@
dependencies:
react-refresh "^0.8.3"
"@snowpack/plugin-run-script@2.1.1", "@snowpack/plugin-run-script@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-run-script/-/plugin-run-script-2.1.1.tgz#f0f71cab5e0a482dfceb3306ae3e7d9cab859746"
integrity sha512-ZLOcu6n+eLDNxTxKlKK/+smn9PWr/epUKGPw8tBHr3qdKQ64WNpCVr0jnafanzWpzQWD8k92J8POfskKMuEI5Q==
"@snowpack/plugin-run-script@2.1.2", "@snowpack/plugin-run-script@^2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@snowpack/plugin-run-script/-/plugin-run-script-2.1.2.tgz#51a620f99cc8ba4a23d3fc5c748f3c16aada7ad4"
integrity sha512-120uF0GKpEY/jHRuOZnxH8siLPXDSKB44Fy9d+zMWybsVvkIvV7pqcT9T9ojnth6QRB+f39tPaiqt+Ej/ByBjg==
dependencies:
execa "^4.0.3"
npm-run-path "^4.0.1"
......@@ -2714,10 +2735,10 @@
dependencies:
defer-to-connect "^2.0.0"
"@testing-library/dom@^7.23.0":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.1.tgz#0e8acd042070f2c1b183fbfe5c0d38b3194ad3c0"
integrity sha512-TemHWY59gvzcScGiE5eooZpzYk9GaED0TuuK4WefbIc/DQg0L5wOpnj7MIEeAGF3B7Ekf1kvmVnQ97vwz4Lmhg==
"@testing-library/dom@^7.24.2":
version "7.24.2"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.2.tgz#6d2b7dd21efbd5358b98c2777fc47c252f3ae55e"
integrity sha512-ERxcZSoHx0EcN4HfshySEWmEf5Kkmgi+J7O79yCJ3xggzVlBJ2w/QjJUC+EBkJJ2OeSw48i3IoePN4w8JlVUIA==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/runtime" "^7.10.3"
......@@ -2741,13 +2762,13 @@
lodash "^4.17.15"
redent "^3.0.0"
"@testing-library/react@11.0.2":
version "11.0.2"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.0.2.tgz#4588cc537085907bd1d98b531eb247dbbf57b1cc"
integrity sha512-iOuNNHt4ZgMH5trSKC4kaWDcKzUOf7e7KQIcu7xvGCd68/w1EegbW89F9T5sZ4IjS0gAXdvOfZbG9ESZ7YjOug==
"@testing-library/react@11.0.4":
version "11.0.4"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.0.4.tgz#c84082bfe1593d8fcd475d46baee024452f31dee"
integrity sha512-U0fZO2zxm7M0CB5h1+lh31lbAwMSmDMEMGpMT3BUPJwIjDEKYWOV4dx7lb3x2Ue0Pyt77gmz/VropuJnSz/Iew==
dependencies:
"@babel/runtime" "^7.11.2"
"@testing-library/dom" "^7.23.0"
"@testing-library/dom" "^7.24.2"
"@tippyjs/react@4.1.0":
version "4.1.0"
......@@ -2878,10 +2899,10 @@
"@types/qs" "*"
"@types/serve-static" "*"
"@types/faker@4.1.12":
version "4.1.12"
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-4.1.12.tgz#065d37343677df1aa757c622650bd14666c42602"
integrity sha512-0MEyzJrLLs1WaOCx9ULK6FzdCSj2EuxdSP9kvuxxdBEGujZYUOZ4vkPXdgu3dhyg/pOdn7VCatelYX7k0YShlA==
"@types/faker@5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.1.0.tgz#72ba5762e0ac00c52c79e08a482962908c4959ff"
integrity sha512-7iK+rNvtSmG3FcAgI67BphmQVzBPkI6SCjJqR/SXxGr6tDUoMovkhGYIxNICEfy/trTgiGQL2v1tKPuFEXIrQg==
"@types/file-saver@2.0.1":
version "2.0.1"
......@@ -2904,11 +2925,11 @@
"@types/node" "*"
"@types/history@*":
version "4.7.7"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896"
integrity sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg==
version "4.7.8"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934"
integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==
"@types/hoist-non-react-statics@*":
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
......@@ -2960,10 +2981,10 @@
dependencies:
"@types/istanbul-lib-report" "*"
"@types/jest@*", "@types/jest@26.0.13":
version "26.0.13"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.13.tgz#5a7b9d5312f5dd521a38329c38ee9d3802a0b85e"
integrity sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA==
"@types/jest@*", "@types/jest@26.0.14":
version "26.0.14"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.14.tgz#078695f8f65cb55c5a98450d65083b2b73e5a3f3"
integrity sha512-Hz5q8Vu0D288x3iWXePSn53W7hAjP0H7EQ6QvDO9c7t46mR0lNOLlfuwQ+JkVxuhygHzlzPX+0jKdA3ZgSh+Vg==
dependencies:
jest-diff "^25.2.1"
pretty-format "^25.2.1"
......@@ -3027,10 +3048,10 @@
"@types/node" "*"
form-data "^3.0.0"
"@types/node@*", "@types/node@14.6.4", "@types/node@>= 8":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
"@types/node@*", "@types/node@14.10.3", "@types/node@>= 8":
version "14.10.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.3.tgz#5ae1f119c96643fc9b19b2d1a83bfa2ec3dbb7ea"
integrity sha512-zdN0hor7TLkjAdKTnYW+Y22oIhUUpil5ZD1V1OFq0CR0CLKw+NdR6dkziTfkWRLo6sKzisayoj/GNpNbe4LY9Q==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
......@@ -3048,9 +3069,9 @@
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
"@types/prettier@^2.0.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.0.tgz#5f96562c1075ee715a5b138f0b7f591c1f40f6b8"
integrity sha512-hiYA88aHiEIgDmeKlsyVsuQdcFn3Z2VuFd/Xm/HCnGnPD8UFU5BM128uzzRVVGEzKDKYUrRsRH9S2o+NUy/3IA==
version "2.1.1"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.1.tgz#be148756d5480a84cde100324c03a86ae5739fb5"
integrity sha512-2zs+O+UkDsJ1Vcp667pd3f8xearMdopz/z54i99wtRDI5KLmngk7vlrYZD0ZjKHaROR03EznlBbVY9PfAEyJIQ==
"@types/prop-types@*":
version "15.7.3"
......@@ -3058,9 +3079,9 @@
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/qs@*":
version "6.9.4"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a"
integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==
version "6.9.5"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b"
integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==
"@types/range-parser@*":
version "1.2.3"
......@@ -3082,9 +3103,9 @@
"@types/react" "*"
"@types/react-native@*":
version "0.63.17"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.17.tgz#364402e33b2805cadfe703d5a84f2e84ad684000"
integrity sha512-xSU9JCHKGqC5Mxnqoc5xs4dquo2bW3ttNqz7IWRtHqEKQvbDcXUgZPNNqEKBiq+5ifMcJs5Dex7jgu8ywKoXBA==
version "0.63.18"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.18.tgz#748d82c6453befe97285393ad9530472d8de56af"
integrity sha512-WwEWqmHiqFn61M1FZR/+frj+E8e2o8i5cPqu9mjbjtZS/gBfCKVESF2ai/KAlaQECkkWkx/nMJeCc5eHMmLQgw==
dependencies:
"@types/react" "*"
......@@ -3095,6 +3116,16 @@
dependencies:
"@types/react" "*"
"@types/react-redux@7.1.9":
version "7.1.9"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.9.tgz#280c13565c9f13ceb727ec21e767abe0e9b4aec3"
integrity sha512-mpC0jqxhP4mhmOl3P4ipRsgTgbNofMRXJb08Ms6gekViLj61v1hOZEKWDCyWsdONr6EjEA6ZHXC446wdywDe0w==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react-router-dom@5.1.5":
version "5.1.5"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090"
......@@ -3143,9 +3174,9 @@
"@types/node" "*"
"@types/semver@^7.1.0":
version "7.3.3"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.3.tgz#3ad6ed949e7487e7bda6f886b4a2434a2c3d7b1a"
integrity sha512-jQxClWFzv9IXdLdhSaTf16XI3NYe6zrEbckSpb5xhKfPbWgIyAY0AFyWWWfaiDcBuj3UHmMkCIwSRqpKMTZL2Q==
version "7.3.4"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
"@types/serve-static@*":
version "1.13.5"
......@@ -3242,61 +3273,61 @@
resolved "https://registry.yarnpkg.com/@types/zrender/-/zrender-4.0.0.tgz#a6806f12ec4eccaaebd9b0d816f049aca6188fbd"
integrity sha512-s89GOIeKFiod2KSqHkfd2rzx+T2DVu7ihZCBEBnhFrzvQPUmzvDSBot9Fi1DfMQm9Odg+rTqoMGC38RvrwJK2w==
"@typescript-eslint/eslint-plugin@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.0.1.tgz#88bde9239e29d688315718552cf80a3490491017"
integrity sha512-pQZtXupCn11O4AwpYVUX4PDFfmIJl90ZgrEBg0CEcqlwvPiG0uY81fimr1oMFblZnpKAq6prrT9a59pj1x58rw==
"@typescript-eslint/eslint-plugin@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.1.1.tgz#78d5b18e259b13c2f4ec41dd9105af269a161a75"
integrity sha512-Hoxyt99EA9LMmqo/5PuWWPeWeB3mKyvibfJ1Hy5SfiUpjE8Nqp+5QNd9fOkzL66+fqvIWSIE+Ett16LGMzCGnQ==
dependencies:
"@typescript-eslint/experimental-utils" "4.0.1"
"@typescript-eslint/scope-manager" "4.0.1"
"@typescript-eslint/experimental-utils" "4.1.1"
"@typescript-eslint/scope-manager" "4.1.1"
debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.0.1.tgz#7d9a3ab6821ad5274dad2186c1aa0d93afd696eb"
integrity sha512-gAqOjLiHoED79iYTt3F4uSHrYmg/GPz/zGezdB0jAdr6S6gwNiR/j7cTZ8nREKVzMVKLd9G3xbg1sV9GClW3sw==
"@typescript-eslint/experimental-utils@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.1.1.tgz#52ff4e37c93113eb96385a4e6d075abece1ea72d"
integrity sha512-jzYsNciHoa4Z3c1URtmeT/bamYm8Dwfw6vuN3WHIE/BXb1iC4KveAnXDErTAZtPVxTYBaYn3n2gbt6F6D2rm1A==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/scope-manager" "4.0.1"
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/typescript-estree" "4.0.1"
"@typescript-eslint/scope-manager" "4.1.1"
"@typescript-eslint/types" "4.1.1"
"@typescript-eslint/typescript-estree" "4.1.1"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.0.1.tgz#73772080db7a7a4534a35d719e006f503e664dc3"
integrity sha512-1+qLmXHNAWSQ7RB6fdSQszAiA7JTwzakj5cNYjBTUmpH2cqilxMZEIV+DRKjVZs8NzP3ALmKexB0w/ExjcK9Iw==
"@typescript-eslint/parser@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.1.1.tgz#324b4b35e314075adbc92bd8330cf3ef0c88cf3e"
integrity sha512-NLIhmicpKGfJbdXyQBz9j48PA6hq6e+SDOoXy7Ak6bq1ebGqbgG+fR1UIDAuay6OjQdot69c/URu2uLlsP8GQQ==
dependencies:
"@typescript-eslint/scope-manager" "4.0.1"
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/typescript-estree" "4.0.1"
"@typescript-eslint/scope-manager" "4.1.1"
"@typescript-eslint/types" "4.1.1"
"@typescript-eslint/typescript-estree" "4.1.1"
debug "^4.1.1"
"@typescript-eslint/scope-manager@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.0.1.tgz#24d93c3000bdfcc5a157dc4d32b742405a8631b5"
integrity sha512-u3YEXVJ8jsj7QCJk3om0Y457fy2euEOkkzxIB/LKU3MdyI+FJ2gI0M4aKEaXzwCSfNDiZ13a3lDo5DVozc+XLQ==
"@typescript-eslint/scope-manager@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.1.1.tgz#bdb8526e82435f32b4ccd9dd4cec01af97b48850"
integrity sha512-0W8TTobCvIIQ2FsrYTffyZGAAFUyIbEHq5EYJb1m7Rpd005jrnOvKOo8ywCLhs/Bm17C+KsrUboBvBAARQVvyA==
dependencies:
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/visitor-keys" "4.0.1"
"@typescript-eslint/types" "4.1.1"
"@typescript-eslint/visitor-keys" "4.1.1"
"@typescript-eslint/types@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.0.1.tgz#1cf72582f764931f085cb8230ff215980fe467b2"
integrity sha512-S+gD3fgbkZYW2rnbjugNMqibm9HpEjqZBZkTiI3PwbbNGWmAcxolWIUwZ0SKeG4Dy2ktpKKaI/6+HGYVH8Qrlg==
"@typescript-eslint/types@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.1.1.tgz#57500c4a86b28cb47094c1a62f1177ea279a09cb"
integrity sha512-zrBiqOKYerMTllKcn+BP+i1b7LW/EbMMYytroXMxUTvFPn1smkCu0D7lSAx29fTUO4jnwV0ljSvYQtn2vNrNxA==
"@typescript-eslint/typescript-estree@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.0.1.tgz#29a43c7060641ec51c902d9f50ac7c5866ec479f"
integrity sha512-zGzleORFXrRWRJAMLTB2iJD1IZbCPkg4hsI8mGdpYlKaqzvKYSEWVAYh14eauaR+qIoZVWrXgYSXqLtTlxotiw==
"@typescript-eslint/typescript-estree@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.1.1.tgz#2015a84d71303ecdb6f46efd807ac19a51aab490"
integrity sha512-2AUg5v0liVBsqbGxBphbJ0QbGqSRVaF5qPoTPWcxop+66vMdU1h4CCvHxTC47+Qb+Pr4l2RhXDd41JNpwcQEKw==
dependencies:
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/visitor-keys" "4.0.1"
"@typescript-eslint/types" "4.1.1"
"@typescript-eslint/visitor-keys" "4.1.1"
debug "^4.1.1"
globby "^11.0.1"
is-glob "^4.0.1"
......@@ -3304,12 +3335,12 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/visitor-keys@4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.0.1.tgz#d4e8de62775f2a6db71c7e8539633680039fdd6c"
integrity sha512-yBSqd6FjnTzbg5RUy9J+9kJEyQjTI34JdGMJz+9ttlJzLCnGkBikxw+N5n2VDcc3CesbIEJ0MnZc5uRYnrEnCw==
"@typescript-eslint/visitor-keys@4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.1.1.tgz#bb05664bf4bea28dc120d1da94f3027d42ab0f6f"
integrity sha512-/EOOXbA2ferGLG6RmCHEQ0lTTLkOlXYDgblCmQk3tIU7mTPLm4gKhFMeeUSe+bcchTUsKeCk8xcpbop5Zr/8Rw==
dependencies:
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/types" "4.1.1"
eslint-visitor-keys "^2.0.0"
"@webassemblyjs/ast@1.9.0":
......@@ -3485,9 +3516,9 @@ JSONStream@^1.0.4, JSONStream@^1.3.4:
through ">=2.2.7 <3"
abab@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
abbrev@1:
version "1.1.1"
......@@ -3575,9 +3606,9 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4:
version "6.12.4"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234"
integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==
version "6.12.5"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
......@@ -3850,9 +3881,9 @@ assign-symbols@^1.0.0:
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
ast-types@0.x.x:
version "0.14.1"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.1.tgz#0b415043770d7a2cbe4b2770271cbd7d2c9f61b9"
integrity sha512-pfSiukbt23P1qMhNnsozLzhMLBs7EEeXqPyvPmnuZM+RMfwfqwDbSVKYflgGuVI7/VehR4oMks0igzdNAg4VeQ==
version "0.14.2"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd"
integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==
dependencies:
tslib "^2.0.1"
......@@ -3926,17 +3957,16 @@ autobind-decorator@^1.3.4:
resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-1.4.3.tgz#4c96ffa77b10622ede24f110f5dbbf56691417d1"
integrity sha1-TJb/p3sQYi7eJPEQ9du/VmkUF9E=
autoprefixer@9.8.6:
version "9.8.6"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
autoprefixer@10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.0.0.tgz#4afbe9eb902ffb5d7a9ef6d36013948fdb34601f"
integrity sha512-rFlVYthz6Iw0LhEYryiGGyjTGofebWie3ydvtqTCJiwWe+z6y8H35b4cadYbOUcYlP495TNeVktW+ZZqxbPW4Q==
dependencies:
browserslist "^4.12.0"
caniuse-lite "^1.0.30001109"
browserslist "^4.14.2"
caniuse-lite "^1.0.30001131"
colorette "^1.2.1"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^7.0.32"
postcss-value-parser "^4.1.0"
aws-sign2@~0.7.0:
......@@ -4320,7 +4350,7 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
browserslist@^4.12.0, browserslist@^4.8.5, browserslist@^4.9.1:
browserslist@^4.12.0, browserslist@^4.14.2, browserslist@^4.8.5, browserslist@^4.9.1:
version "4.14.2"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce"
integrity sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==
......@@ -4590,10 +4620,10 @@ camelize@^1.0.0:
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125:
version "1.0.30001125"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001125.tgz#2a1a51ee045a0a2207474b086f628c34725e997b"
integrity sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==
caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001131:
version "1.0.30001131"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz#afad8a28fc2b7a0d3ae9407e71085a0ead905d54"
integrity sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==
capture-exit@^2.0.0:
version "2.0.0"
......@@ -4816,6 +4846,15 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
cliui@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3"
integrity sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
clone-deep@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
......@@ -5191,7 +5230,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cosmiconfig@^5.0.0, cosmiconfig@^5.1.0:
cosmiconfig@^5.1.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
......@@ -5348,10 +5387,10 @@ css-color-keywords@^1.0.0:
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
css-loader@4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.2.tgz#b668b3488d566dc22ebcf9425c5f254a05808c89"
integrity sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg==
css-loader@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e"
integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==
dependencies:
camelcase "^6.0.0"
cssesc "^3.0.0"
......@@ -5363,7 +5402,7 @@ css-loader@4.2.2:
postcss-modules-scope "^2.2.0"
postcss-modules-values "^3.0.0"
postcss-value-parser "^4.1.0"
schema-utils "^2.7.0"
schema-utils "^2.7.1"
semver "^7.3.2"
css-modules-loader-core@^1.1.0:
......@@ -5405,6 +5444,14 @@ css-to-react-native@^3.0.0:
css-color-keywords "^1.0.0"
postcss-value-parser "^4.0.2"
css-tree@1.0.0-alpha.39:
version "1.0.0-alpha.39"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
dependencies:
mdn-data "2.0.6"
source-map "^0.6.1"
css-what@2.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
......@@ -5429,6 +5476,13 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
csso@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903"
integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==
dependencies:
css-tree "1.0.0-alpha.39"
cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
......@@ -6067,9 +6121,9 @@ domelementtype@1, domelementtype@^1.3.1:
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
domelementtype@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
version "2.0.2"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971"
integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==
domexception@^2.0.1:
version "2.0.1"
......@@ -6182,9 +6236,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.570"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f"
integrity sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg==
electron-updater@4.3.1:
version "4.3.1"
......@@ -6355,7 +6409,7 @@ es-abstract@^1.18.0-next.0:
string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1"
es-module-lexer@^0.3.17:
es-module-lexer@^0.3.24:
version "0.3.25"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.25.tgz#24a1abcb9c5dc96923a8e42be033b801f788de06"
integrity sha512-H9VoFD5H9zEfiOX2LeTWDwMvAbLqcAyA2PIb40TOAvGpScOjit02oTGWgIh+M0rx2eJOKyJVM9wtpKFVgnyC3A==
......@@ -6381,15 +6435,15 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
esbuild@^0.6.11:
version "0.6.33"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.6.33.tgz#13504da1a582b892ae37ea303566d9f419e5a70e"
integrity sha512-TGf0q04top/0mVst0IzcbgAYc9W1W+ovbrZAHAQSUB2U+lYMu9Fwd8lkGxlhMdnctjEunGBD0qwahJj6k40izA==
esbuild@^0.6.28:
version "0.6.34"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.6.34.tgz#76565a60e006f45d5f273b6e59e61ed0816551f5"
integrity sha512-InRdL/Q96pUucPqovJzvuLhquZr6jOn81FDVwFjCKz1rYKIm9OdOC+7Fs4vr6x48vKBl5LzKgtjU39BUpO636A==
escalade@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4"
integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==
version "3.1.0"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e"
integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==
escape-goat@^2.0.0:
version "2.1.1"
......@@ -6442,10 +6496,10 @@ eslint-plugin-prettier@3.1.4:
dependencies:
prettier-linter-helpers "^1.0.0"
eslint-plugin-react-hooks@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.0.tgz#6323fbd5e650e84b2987ba76370523a60f4e7925"
integrity sha512-36zilUcDwDReiORXmcmTc6rRumu9JIM3WjSvV0nclHoUQ0CNrX866EwONvLR/UqaeqFutbAnVu8PEmctdo2SRQ==
eslint-plugin-react-hooks@4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.2.tgz#2eb53731d11c95826ef7a7272303eabb5c9a271e"
integrity sha512-ykUeqkGyUGgwTtk78C0o8UG2fzwmgJ0qxBGPp2WqRKsTwcLuVf01kTDRAtOsd4u6whX2XOC8749n2vPydP82fg==
eslint-plugin-react@7.20.6:
version "7.20.6"
......@@ -6473,11 +6527,11 @@ eslint-scope@^4.0.3:
estraverse "^4.1.1"
eslint-scope@^5.0.0, eslint-scope@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
dependencies:
esrecurse "^4.1.0"
esrecurse "^4.3.0"
estraverse "^4.1.1"
eslint-utils@^2.0.0, eslint-utils@^2.1.0:
......@@ -6497,10 +6551,10 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@7.8.1:
version "7.8.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa"
integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w==
eslint@7.9.0:
version "7.9.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.9.0.tgz#522aeccc5c3a19017cf0cb46ebfd660a79acf337"
integrity sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.1.3"
......@@ -6566,7 +6620,7 @@ esquery@^1.2.0:
dependencies:
estraverse "^5.1.0"
esrecurse@^4.1.0:
esrecurse@^4.1.0, esrecurse@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
......@@ -7214,7 +7268,7 @@ gensync@^1.0.0-beta.1:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
get-caller-file@^2.0.1:
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
......@@ -7461,9 +7515,9 @@ globby@^9.2.0:
slash "^2.0.0"
got@^11.1.4:
version "11.6.1"
resolved "https://registry.yarnpkg.com/got/-/got-11.6.1.tgz#a307122fc136c446f676f7b939d89dbc6ed6b909"
integrity sha512-6izGvOsrd/4CsIdQMgweFOTCtS4sAwJTuCzIuVoTbCDzt3+wa3eGIHhSIMgEF6gfCDenslGlMUmAdPap5DkirQ==
version "11.6.2"
resolved "https://registry.yarnpkg.com/got/-/got-11.6.2.tgz#79d7bb8c11df212b97f25565407a1f4ae73210ec"
integrity sha512-/21qgUePCeus29Jk7MEti8cgQUNXFSWfIevNIk4H7u1wmXNDrGPKPY6YsPY+o9CIT/a2DjCjRz0x1nM9FtS2/A==
dependencies:
"@sindresorhus/is" "^3.1.1"
"@szmarczak/http-timer" "^4.0.5"
......@@ -7570,7 +7624,7 @@ has-glob@^1.0.0:
dependencies:
is-glob "^3.0.0"
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
......@@ -7715,7 +7769,7 @@ html-minifier-terser@^5.0.1:
relateurl "^0.2.7"
terser "^4.6.3"
html-minifier@4.0.0:
html-minifier@4.0.0, html-minifier@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56"
integrity sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==
......@@ -7872,15 +7926,15 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
husky@4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36"
integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==
husky@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.0.tgz#0b2ec1d66424e9219d359e26a51c58ec5278f0de"
integrity sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==
dependencies:
chalk "^4.0.0"
ci-info "^2.0.0"
compare-versions "^3.6.0"
cosmiconfig "^6.0.0"
cosmiconfig "^7.0.0"
find-versions "^3.2.0"
opencollective-postinstall "^2.0.2"
pkg-dir "^4.2.0"
......@@ -7965,13 +8019,6 @@ ignore@^5.1.4:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
import-cwd@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=
dependencies:
import-from "^2.1.0"
import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
......@@ -7988,13 +8035,6 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
parent-module "^1.0.0"
resolve-from "^4.0.0"
import-from@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
integrity sha1-M1238qev/VOqpHHUuAId7ja387E=
dependencies:
resolve-from "^3.0.0"
import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
......@@ -8481,6 +8521,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isbinaryfile@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b"
integrity sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
......@@ -9108,9 +9153,9 @@ keyv@^3.0.0:
json-buffer "3.0.0"
keyv@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.1.tgz#9fe703cb4a94d6d11729d320af033307efd02ee6"
integrity sha512-xz6Jv6oNkbhrFCvCP7HQa8AaII8y8LRpoSm661NOKLr4uHuBwhX4epXrPQgF3+xdJnN4Esm5X0xwY4bOlALOtw==
version "4.0.2"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.2.tgz#586777fc38c28badebd4d9cb5e000c09a2bc2777"
integrity sha512-EApxc1YZC/Uf+8dsrGqDqUK3cW8oPLgyeATzELkyAFE9OTf2jpFbi2qLtlrONy+SMmupkR3p5jGWeMEd0Z/ZHg==
dependencies:
json-buffer "3.0.1"
......@@ -9143,15 +9188,15 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
kleur@^4.1.0:
kleur@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.1.tgz#80b49dd7d1afeba41b8dcdf4ecfff9252205fc52"
integrity sha512-BsNhM6T/yTWFG580CRnYhT3LfUuPK7Hwrm+W2H0G8lK/nogalP5Nsrh/cHjxVVkzl0sFm7z8b8rNcZCfKxeoxA==
klona@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.3.tgz#98274552c513583ad7a01456a789a2a0b4a2a538"
integrity sha512-CgPOT3ZadDpXxKcfV56lEQ9OQSZ42Mk26gnozI+uN/k39vzD8toUhRQoqsX0m9Q3eMPEfsLWmtyUpK/yqST4yg==
version "2.0.4"
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
latest-version@^5.0.0:
version "5.1.0"
......@@ -9222,15 +9267,23 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
line-column@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2"
integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=
dependencies:
isarray "^1.0.0"
isobject "^2.0.0"
lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
lint-staged@10.3.0:
version "10.3.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.3.0.tgz#388c3d440590c45c339e7163f669ea69ae90b1e0"
integrity sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw==
lint-staged@10.4.0:
version "10.4.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.4.0.tgz#d18628f737328e0bbbf87d183f4020930e9a984e"
integrity sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg==
dependencies:
chalk "^4.1.0"
cli-truncate "^2.1.0"
......@@ -9582,6 +9635,11 @@ md5.js@^1.3.4:
inherits "^2.0.1"
safe-buffer "^5.1.2"
mdn-data@2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978"
integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
......@@ -9773,10 +9831,10 @@ mini-create-react-context@^0.4.0:
"@babel/runtime" "^7.5.5"
tiny-warning "^1.0.3"
mini-css-extract-plugin@0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.0.tgz#3918953075109d4ca204bf1e8a393a78d3cc821f"
integrity sha512-dVWGuWJlQw2lZxsxBI3hOsoxg1k3DruLR0foHQLSkQMfk+qLJbv9dUk8fjmjWQKN9ef2n54ehA2FjClAsQhrWQ==
mini-css-extract-plugin@0.11.2:
version "0.11.2"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.2.tgz#e3af4d5e04fbcaaf11838ab230510073060b37bf"
integrity sha512-h2LknfX4U1kScXxH8xE9LCOqT5B+068EAj36qicMb8l4dqdJoyHcmWmpd+ueyZfgu/POvIn+teoUnTtei2ikug==
dependencies:
loader-utils "^1.1.0"
normalize-url "1.9.1"
......@@ -9933,10 +9991,10 @@ moment-timezone@^0.5.x:
dependencies:
moment ">= 2.9.0"
moment@2.27.0, "moment@>= 2.9.0":
version "2.27.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d"
integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==
moment@2.28.0, "moment@>= 2.9.0":
version "2.28.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.28.0.tgz#cdfe73ce01327cee6537b0fafac2e0f21a237d75"
integrity sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw==
move-concurrently@^1.0.1:
version "1.0.1"
......@@ -9999,6 +10057,11 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
nanoid@^3.1.12:
version "3.1.12"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
......@@ -10091,7 +10154,7 @@ node-fetch-npm@^2.0.2:
json-parse-better-errors "^1.0.0"
safe-buffer "^5.1.1"
node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0:
node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.5.0, node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
......@@ -10384,7 +10447,7 @@ object-inspect@^1.7.0, object-inspect@^1.8.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
......@@ -10397,14 +10460,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.2:
version "1.1.2"
......@@ -10520,10 +10583,10 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
ora@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.0.0.tgz#4f0b34f2994877b49b452a707245ab1e9f6afccb"
integrity sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw==
ora@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.1.0.tgz#b188cf8cd2d4d9b13fd25383bc3e5cba352c94f8"
integrity sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==
dependencies:
chalk "^4.1.0"
cli-cursor "^3.1.0"
......@@ -10686,7 +10749,7 @@ p-queue@^4.0.0:
dependencies:
eventemitter3 "^3.1.0"
p-queue@^6.2.1:
p-queue@^6.6.1:
version "6.6.1"
resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.1.tgz#578891ada028a61371ec2692b26614d1b7d2b10a"
integrity sha512-miQiSxLYPYBxGkrldecZC18OTLjdUqnlRebGzPRiVxB8mco7usCmm7hFuxiTvp93K18JnLtE4KMMycjAu/cQQg==
......@@ -11126,23 +11189,16 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-load-config@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003"
integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==
dependencies:
cosmiconfig "^5.0.0"
import-cwd "^2.0.0"
postcss-loader@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d"
integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==
postcss-loader@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.0.2.tgz#b9e55a6126ee67bb7b94bbfcbf1aa24c69f11229"
integrity sha512-u7Qoa6GSPIeg9/hHbNnXspzuD5jjCIWKgk1fJ/gGJPS0uaj6Whk2zjXhDAiHZyYSrDmIzUQk7GgwRF22eRIQGQ==
dependencies:
loader-utils "^1.1.0"
postcss "^7.0.0"
postcss-load-config "^2.0.0"
schema-utils "^1.0.0"
cosmiconfig "^7.0.0"
klona "^2.0.3"
loader-utils "^2.0.0"
schema-utils "^2.7.1"
semver "^7.3.2"
postcss-modules-extract-imports@1.1.0:
version "1.1.0"
......@@ -11231,6 +11287,16 @@ postcss@6.0.1:
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@8.0.5:
version "8.0.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.0.5.tgz#8210e2363f85c35a88a188ce7a0828e93b1088d4"
integrity sha512-3rDm6KR0jHstte3aL3ugrCyFA1UXY90SWNwRZ2WTmRf/QpOqM35mm0FrRR+HHZQ5fY9+nXFat1nl2ekYJf0P4w==
dependencies:
colorette "^1.2.1"
line-column "^1.0.2"
nanoid "^3.1.12"
source-map "^0.6.1"
postcss@^6.0.1:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
......@@ -11240,10 +11306,10 @@ postcss@^6.0.1:
source-map "^0.6.1"
supports-color "^5.4.0"
postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.32"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.34"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20"
integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==
dependencies:
chalk "^2.4.2"
source-map "^0.6.1"
......@@ -11276,10 +11342,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
prettier@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6"
integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==
prettier@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5"
integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==
pretty-error@^2.1.1:
version "2.1.1"
......@@ -11513,10 +11579,10 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
query-string@6.13.1:
version "6.13.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.1.tgz#d913ccfce3b4b3a713989fe6d39466d92e71ccad"
integrity sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA==
query-string@6.13.2:
version "6.13.2"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.2.tgz#3585aa9412c957cbd358fd5eaca7466f05586dda"
integrity sha512-BMmDaUiLDFU1hlM38jTFcRt7HYiGP/zt1sRzrIWm5zpeEuO1rkbPS0ELI3uehoLuuhHDCS8u8lhFN3fEN4JzPQ==
dependencies:
decode-uri-component "^0.2.0"
split-on-first "^1.0.0"
......@@ -11665,7 +11731,7 @@ react-input-range@1.3.0:
autobind-decorator "^1.3.4"
prop-types "^15.5.8"
react-is@16.13.1, react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
react-is@16.13.1, react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
......@@ -11678,6 +11744,17 @@ react-rangeslider@2.2.0:
classnames "^2.2.3"
resize-observer-polyfill "^1.4.2"
react-redux@7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985"
integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==
dependencies:
"@babel/runtime" "^7.5.5"
hoist-non-react-statics "^3.3.0"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.9.0"
react-refresh@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
......@@ -11920,6 +11997,14 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redux@4.0.5, redux@^4.0.0:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
......@@ -12269,9 +12354,9 @@ rollup-pluginutils@^2.8.1:
estree-walker "^0.6.1"
rollup@^2.23.0:
version "2.26.11"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.11.tgz#4fc31de9c7b83d50916fc8395f8c3d24730cdaae"
integrity sha512-xyfxxhsE6hW57xhfL1I+ixH8l2bdoIMaAecdQiWF3N7IgJEMu99JG+daBiSZQjnBpzFxa0/xZm+3pbCdAQehHw==
version "2.27.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.0.tgz#f2b70a8dd583bc3675b36686289aa9a51e27af4f"
integrity sha512-1WlbhNdzhLjdhh2wsf6CDxmuBAYG+5O53fYqCcGv8aJOoX/ymCfCY6oZnvllXZzaC/Ng+lPPwq9EMbHOKc5ozA==
optionalDependencies:
fsevents "~2.1.2"
......@@ -12398,7 +12483,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
schema-utils@^2.7.0, schema-utils@^2.7.1:
schema-utils@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
......@@ -12659,10 +12744,10 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
snowpack@2.10.1:
version "2.10.1"
resolved "https://registry.yarnpkg.com/snowpack/-/snowpack-2.10.1.tgz#a20360392ed8022cda7e7f8d0842040a62cd2448"
integrity sha512-x7/iI8K8bjFjkeQqnlVIP+huT3d8eHshr9st2cPNHDn1OCzdgWO6PCixq22uPH2UMFBdpEMy3Jq2+HusiwncUA==
snowpack@2.11.1:
version "2.11.1"
resolved "https://registry.yarnpkg.com/snowpack/-/snowpack-2.11.1.tgz#8565bed98806162bc1b001d3796c8863b18a2084"
integrity sha512-trEBfCRUaPLaoMZdyDyLdzQfQGy2tOrr0gGeSV8AVjos3m412s2mWsfhYEGCT1AE/t0mrGMhj7ccVz5fh5yOnQ==
dependencies:
"@babel/plugin-syntax-import-meta" "^7.10.4"
"@rollup/plugin-alias" "^3.0.1"
......@@ -12670,8 +12755,9 @@ snowpack@2.10.1:
"@rollup/plugin-inject" "^4.0.2"
"@rollup/plugin-json" "^4.0.0"
"@rollup/plugin-node-resolve" "^9.0.0"
"@snowpack/plugin-build-script" "^2.0.6"
"@snowpack/plugin-run-script" "^2.1.1"
"@rollup/plugin-replace" "^2.3.3"
"@snowpack/plugin-build-script" "^2.0.7"
"@snowpack/plugin-run-script" "^2.1.2"
cacache "^15.0.0"
cachedir "^2.3.0"
chokidar "^3.4.0"
......@@ -12680,8 +12766,8 @@ snowpack@2.10.1:
css-modules-loader-core "^1.1.0"
deepmerge "^4.2.2"
detect-port "^1.3.0"
es-module-lexer "^0.3.17"
esbuild "^0.6.11"
es-module-lexer "^0.3.24"
esbuild "^0.6.28"
etag "^1.8.1"
execa "^4.0.3"
find-cache-dir "^3.3.1"
......@@ -12690,13 +12776,14 @@ snowpack@2.10.1:
got "^11.1.4"
http-proxy "^1.18.1"
is-builtin-module "^3.0.0"
isbinaryfile "^4.0.6"
jsonschema "^1.2.5"
kleur "^4.1.0"
kleur "^4.1.1"
mime-types "^2.1.26"
mkdirp "^1.0.3"
npm-run-path "^4.0.1"
open "^7.0.4"
p-queue "^6.2.1"
p-queue "^6.6.1"
resolve-from "^5.0.0"
rimraf "^3.0.0"
rollup "^2.23.0"
......@@ -12825,9 +12912,9 @@ spdx-expression-parse@^3.0.0:
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.5"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
version "3.0.6"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce"
integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==
split-on-first@^1.0.0:
version "1.1.0"
......@@ -13232,15 +13319,20 @@ swr@0.3.0:
dependencies:
fast-deep-equal "2.0.1"
symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
systeminformation@^4.23.3:
version "4.27.3"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.27.3.tgz#3fc00b34425807915294f4ed3e86bbc7c85ee1b8"
integrity sha512-0Nc8AYEK818h7FI+bbe/kj7xXsMD5zOHvO9alUqQH/G4MHXu5tHQfWqC/bzWOk4JtoQPhnyLgxMYncDA2eeSBw==
version "4.27.4"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.27.4.tgz#6c43460ea615b95e19813dee8f8c543e199367c7"
integrity sha512-VlFlxbkvSddq16F/nHC0GRaKBZOKWbAuRbck4G9muHhCUcDKskhNkVbaBBFxxqwcp0IyVozLS96eAVmkRZTG4w==
table@^5.2.3:
version "5.4.6"
......@@ -13339,10 +13431,10 @@ terser-webpack-plugin@^1.4.3:
webpack-sources "^1.4.0"
worker-farm "^1.7.0"
terser@5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.0.tgz#c481f4afecdcc182d5e2bdd2ff2dc61555161e81"
integrity sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==
terser@5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.1.tgz#f50fe20ab48b15234fe9bdd86b10148ad5fca787"
integrity sha512-yD80f4hdwCWTH5mojzxe1q8bN1oJbsK/vfJGLcPZM/fl+/jItIVNKhFIHqqR71OipFWMLgj3Kc+GIp6CeIqfnA==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
......@@ -14263,6 +14355,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
......@@ -14373,6 +14474,11 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
y18n@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.1.tgz#1ad2a7eddfa8bce7caa2e1f6b5da96c39d99d571"
integrity sha512-/jJ831jEs4vGDbYPQp4yGKDYPSCCEQ45uZWJHE1AoYBzqdZi8+LDWas0z4HrmJXmKdpFsTiowSHXdxyFhpmdMg==
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
......@@ -14420,22 +14526,23 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs@15.4.1, yargs@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
yargs-parser@^20.0.0:
version "20.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.0.0.tgz#c65a1daaa977ad63cebdd52159147b789a4e19a9"
integrity sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==
yargs@16.0.3:
version "16.0.3"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c"
integrity sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"
find-up "^4.1.0"
get-caller-file "^2.0.1"
cliui "^7.0.0"
escalade "^3.0.2"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^4.2.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^18.1.2"
y18n "^5.0.1"
yargs-parser "^20.0.0"
yargs@^13.3.2:
version "13.3.2"
......@@ -14470,6 +14577,23 @@ yargs@^14.2.2:
y18n "^4.0.0"
yargs-parser "^15.0.1"
yargs@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"
find-up "^4.1.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^4.2.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^18.1.2"
yarn@1.22.5:
version "1.22.5"
resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.5.tgz#1933b7635429ca00847222dd9d38f05646e2df23"
......
......@@ -18,6 +18,7 @@ build_frontend() {
API_URL="{{API_URL}}" \
API_TOKEN_KEY="{{API_TOKEN_KEY}}" \
TELEMETRY_ID="{{TELEMETRY_ID}}" \
THEME="{{THEME}}" \
PATH="$PATH" \
./scripts/build.sh
......
......@@ -90,8 +90,8 @@ def create_app(args):
PUBLIC_PATH=public_path,
BASE_URI=public_path,
API_URL=api_path,
API_TOKEN_KEY='',
TELEMETRY_ID='63a600296f8a71f576c4806376a9245b' if args.telemetry else ''
TELEMETRY_ID='63a600296f8a71f576c4806376a9245b' if args.telemetry else '',
THEME='' if args.theme is None else args.theme
)
@app.route('/')
......
......@@ -26,6 +26,8 @@ default_cache_timeout = 20
default_public_path = '/app'
default_product = 'normal'
support_themes = ['light', 'dark']
class DefaultArgs(object):
def __init__(self, args):
......@@ -40,6 +42,7 @@ class DefaultArgs(object):
self.model = args.get('model', '')
self.product = args.get('product', default_product)
self.telemetry = args.get('telemetry', True)
self.theme = args.get('theme', None)
self.dest = args.get('dest', '')
self.behavior = args.get('behavior', '')
......@@ -65,6 +68,11 @@ def validate_args(args):
logger.error('Public path should always start with a `/`.')
sys.exit(-1)
# theme not support
if args.theme is not None and args.theme not in support_themes:
logger.error('Theme {} is not support.'.format(args.theme))
sys.exit(-1)
def format_args(args):
# set default public path according to API mode option
......@@ -101,6 +109,7 @@ class ParseArgs(object):
self.model = args.model
self.product = args.product
self.telemetry = args.telemetry
self.theme = args.theme
self.dest = args.dest
self.behavior = args.behavior
......@@ -194,6 +203,14 @@ def parse_args():
default=True,
help="disable telemetry"
)
parser.add_argument(
"--theme",
action="store",
dest="theme",
default=None,
choices=support_themes,
help="set theme"
)
parser.add_argument(
'dest',
nargs='?',
......
......@@ -21,6 +21,13 @@ from flask import (Response, send_from_directory)
class Template(object):
extname = [".html", ".js", ".css"]
defaults = {
'PUBLIC_PATH': '/app',
'API_TOKEN_KEY': '',
'TELEMETRY_ID': '',
'THEME': ''
}
def __init__(self, path, **context):
if not os.path.exists(path):
raise Exception("template file does not exist.")
......@@ -33,7 +40,9 @@ class Template(object):
rel_path = os.path.relpath(file_path, path).replace(os.path.sep, '/')
with open(file_path, "r", encoding="UTF-8") as f:
content = f.read()
for key, value in context.items():
envs = self.defaults.copy()
envs.update(context)
for key, value in envs.items():
content = content.replace("{{" + key + "}}", value)
self.files[rel_path] = content, mimetypes.guess_type(file)[0]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册