Add customization options to the icon display and download (#113)

* feat: ability to customize icons before downloading PNG or SVG

* feat: change color input to be a graphical color picker

* feat: tweak appearance of new inputs

* fix: switch to correct Chakra-UI@Next slider syntax

* fix: make default color `currentColor` and also add Reset button
This commit is contained in:
Frank Riccobono
2020-10-31 07:53:25 -04:00
committed by GitHub
parent f3c3fea228
commit 51fd3af446
11 changed files with 437 additions and 38 deletions

View File

@@ -20,6 +20,7 @@
"lucide-react": "^0.1.2-beta.1", "lucide-react": "^0.1.2-beta.1",
"next": "^9.5.4", "next": "^9.5.4",
"react": "^16.13.1", "react": "^16.13.1",
"react-color": "^2.18.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-spring": "^8.0.27" "react-spring": "^8.0.27"
}, },
@@ -32,6 +33,7 @@
"@types/react": "^16.9.35", "@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
"babel-jest": "^26.5.2", "babel-jest": "^26.5.2",
"cheerio": "^1.0.0-rc.3",
"jest": "^26.5.2", "jest": "^26.5.2",
"react-test-renderer": "^16.13.1", "react-test-renderer": "^16.13.1",
"typescript": "^3.9.5" "typescript": "^3.9.5"

View File

@@ -0,0 +1,63 @@
import { SyntheticEvent, useEffect, useRef, useState } from 'react';
import { FormLabel, Icon, Input, InputGroup, InputLeftElement } from '@chakra-ui/core';
import { CustomPicker } from 'react-color';
const { Saturation, Hue } = require('react-color/lib/components/common');
type ColorPickerProps = {
value: string;
hex: string;
hsl: string;
hsv: string;
onChange: (s: string, e: SyntheticEvent) => void;
};
function ColorPicker({ hsv, hsl, onChange, hex, value: color }: ColorPickerProps) {
const [value, setValue] = useState(color);
const input = useRef<HTMLInputElement>(null);
useEffect(() => {
if (color !== value && input.current !== document.activeElement) {
setValue(color === "currentColor" ? color : String(color).toUpperCase());
}
}, [color]);
const handleChange = (e) => {
let value = e.target.value;
setValue(value);
onChange(value, e);
};
return (
<div>
<FormLabel htmlFor="color" fontWeight={'bold'}>
Color
</FormLabel>
<InputGroup>
<InputLeftElement
children={
<Icon>
<rect x={0} width={24} y={0} height={24} fill={value} rx={2} />
</Icon>
}
/>
<Input value={value} name="color" onChange={handleChange} ref={input} />
</InputGroup>
<div
style={{
width: '100%',
paddingBottom: '75%',
position: 'relative',
overflow: 'hidden',
}}
>
<Saturation hsl={hsl} hsv={hsv} onChange={onChange} />
</div>
<div style={{ minHeight: '1em', position: 'relative', margin: 2 }}>
<Hue hsl={hsl} onChange={onChange} direction={'horizontal'} />
</div>
</div>
);
}
export default CustomPicker(ColorPicker);

View File

@@ -0,0 +1,47 @@
import { createContext, useState } from 'react';
interface ICustomIconStyle {
color: string;
setColor: (s: string) => void;
strokeWidth: number;
setStroke: (n: number) => void;
size: number;
setSize: (n: number) => void;
resetStyle: () => void;
}
const DEFAULT_STYLE = {
color: 'currentColor',
strokeWidth: 2,
size: 24,
}
export const IconStyleContext = createContext<ICustomIconStyle>({
color: 'currentColor',
setColor: (s: string) => null,
strokeWidth: 2,
setStroke: (n: number) => null,
size: 24,
setSize: (n: number) => null,
resetStyle: ()=>null
});
export function CustomizeIconContext({ children }) {
const [color, setColor] = useState(DEFAULT_STYLE.color);
const [stroke, setStroke] = useState(DEFAULT_STYLE.strokeWidth);
const [size, setSize] = useState(DEFAULT_STYLE.size);
function resetStyle(){
setColor(DEFAULT_STYLE.color);
setStroke(DEFAULT_STYLE.strokeWidth);
setSize(DEFAULT_STYLE.size);
}
return (
<IconStyleContext.Provider
value={{ color, setColor, strokeWidth: stroke, setStroke, size, setSize, resetStyle }}
>
{children}
</IconStyleContext.Provider>
);
}

View File

@@ -1,14 +1,8 @@
import { import {Button, Flex, Link, Stack, Text,} from "@chakra-ui/core";
Button,
Flex,
Stack,
Text,
Link,
} from "@chakra-ui/core";
import download from "downloadjs"; import download from "downloadjs";
import JSZip from "jszip"; import JSZip from "jszip";
import { Download, GitHub } from 'lucide-react'; import { Download, GitHub } from 'lucide-react';
import theme from "../lib/theme"; import {IconCustomizerDrawer} from "./IconCustomizerDrawer";
function generateZip(icons) { function generateZip(icons) {
const zip = new JSZip(); const zip = new JSZip();
@@ -44,6 +38,7 @@ const Header = ({ data }) => {
> >
Download all Download all
</Button> </Button>
<IconCustomizerDrawer/>
<Button <Button
as="a" as="a"
leftIcon={<GitHub/>} leftIcon={<GitHub/>}

View File

@@ -0,0 +1,96 @@
import { useContext, useState } from 'react';
import { IconStyleContext } from './CustomizeIconContext';
import { Edit } from 'lucide-react';
import {
Button,
Drawer,
DrawerBody,
DrawerCloseButton,
DrawerContent,
DrawerHeader,
DrawerOverlay,
FormControl,
FormLabel,
Grid,
Slider,
SliderFilledTrack,
SliderThumb,
SliderTrack,
Flex,
Text,
} from '@chakra-ui/core';
import ColorPicker from './ColorPicker';
export function IconCustomizerDrawer() {
const [showCustomize, setShowCustomize] = useState(false);
const { color, setColor, size, setSize, strokeWidth, setStroke, resetStyle } = useContext(IconStyleContext);
return (
<>
<Button as="a" leftIcon={<Edit />} size="lg" onClick={() => setShowCustomize(true)}>
Customize
</Button>
<Drawer isOpen={showCustomize} placement="right" onClose={() => setShowCustomize(false)}>
<DrawerOverlay />
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Customize Icons</DrawerHeader>
<DrawerBody>
<Grid gridGap={'1em'}>
<FormControl>
<ColorPicker
color={color}
value={color}
onChangeComplete={(col) => setColor(col.hex)}
/>
</FormControl>
<FormControl>
<FormLabel htmlFor="stroke">
<Flex>
<Text flexGrow={1} fontWeight={'bold'}>
Stroke
</Text>
<Text>{strokeWidth}px</Text>
</Flex>
</FormLabel>
<Slider
value={strokeWidth}
onChange={setStroke}
min={0.5}
max={3}
step={0.5}
name={'stroke'}
>
<SliderTrack>
<SliderFilledTrack bg={color} />
</SliderTrack>
<SliderThumb />
</Slider>
</FormControl>
<FormControl>
<FormLabel htmlFor="size">
<Flex>
<Text flexGrow={1} fontWeight={'bold'}>
Size
</Text>
<Text>{size}px</Text>
</Flex>
</FormLabel>
<Slider value={size} onChange={setSize} min={12} max={64} step={1} name={'size'}>
<SliderTrack>
<SliderFilledTrack bg={color} />
</SliderTrack>
<SliderThumb />
</Slider>
</FormControl>
<FormControl>
<Button onClick={resetStyle}>Reset</Button>
</FormControl>
</Grid>
</DrawerBody>
</DrawerContent>
</Drawer>
</>
);
}

View File

@@ -4,11 +4,21 @@ import theme from "../lib/theme";
import download from 'downloadjs'; import download from 'downloadjs';
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import { X as Close } from 'lucide-react'; import { X as Close } from 'lucide-react';
import {useContext, useRef} from "react";
import {IconStyleContext} from "./CustomizeIconContext";
import {IconWrapper} from "./IconWrapper";
type IconDownload = {
src: string;
name: string;
};
const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => { const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => {
const toast = useToast(); const toast = useToast();
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const { tags = [], name } = icon; const { tags = [], name } = icon;
const {color, strokeWidth, size} = useContext(IconStyleContext);
const iconRef = useRef<SVGSVGElement>(null);
const { transform, opacity } = useSpring({ const { transform, opacity } = useSpring({
opacity: isOpen ? 1 : 0, opacity: isOpen ? 1 : 0,
@@ -34,12 +44,12 @@ const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => {
minWidth: "160px", minWidth: "160px",
maxHeight: "240px", maxHeight: "240px",
maxWidth: "240px", maxWidth: "240px",
color: (isLight ? theme.colors.gray[800] : theme.colors.white), color: color,
}); });
const downloadIcon = ({src, name}) => download(src, `${name}.svg`, 'image/svg+xml'); const downloadIcon = ({src, name} : IconDownload) => download(src, `${name}.svg`, 'image/svg+xml');
const copyIcon = ({src, name}) => { const copyIcon = ({src, name} : IconDownload) => {
copy(src); copy(src);
toast({ toast({
title: "Copied!", title: "Copied!",
@@ -49,10 +59,10 @@ const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => {
}); });
} }
const donwloadPNG = ({src, name}) => { const downloadPNG = ({src, name}: IconDownload) => {
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = 24; canvas.width = size;
canvas.height = 24; canvas.height = size;
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
const image = new Image(); const image = new Image();
@@ -129,10 +139,18 @@ const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => {
padding={0} padding={0}
> >
<div <div
dangerouslySetInnerHTML={{ __html: icon.src }}
style={iconStyling(colorMode == "light")} style={iconStyling(colorMode == "light")}
className="icon-large" className="icon-large"
/> >
<IconWrapper
content={icon.content}
stroke={color}
strokeWidth={strokeWidth}
height={size}
width={size}
ref={iconRef}
/>
</div>
<svg className="icon-grid" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={colorMode == "light" ? '#E2E8F0' : theme.colors.gray[600]} strokeWidth="0.1" xmlns="http://www.w3.org/2000/svg"> <svg className="icon-grid" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={colorMode == "light" ? '#E2E8F0' : theme.colors.gray[600]} strokeWidth="0.1" xmlns="http://www.w3.org/2000/svg">
{ Array.from({ length:23 }, (_, i) => ( { Array.from({ length:23 }, (_, i) => (
@@ -169,13 +187,13 @@ const IconDetailOverlay = ({ isOpen = true, onClose, icon }) => {
</Button> */} </Button> */}
</Box> </Box>
<ButtonGroup spacing={4}> <ButtonGroup spacing={4}>
<Button variant="solid" onClick={() => downloadIcon(icon)} mb={1}> <Button variant="solid" onClick={() => downloadIcon({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
Download SVG Download SVG
</Button> </Button>
<Button variant="solid" onClick={() => copyIcon(icon)} mb={1}> <Button variant="solid" onClick={() => copyIcon({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
Copy SVG Copy SVG
</Button> </Button>
<Button variant="solid" onClick={() => donwloadPNG(icon)} mb={1}> <Button variant="solid" onClick={() => downloadPNG({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
Download PNG Download PNG
</Button> </Button>
</ButtonGroup> </ButtonGroup>

View File

@@ -2,9 +2,13 @@ import { Button, Flex, Grid, Text, useToast } from "@chakra-ui/core";
import download from 'downloadjs'; import download from 'downloadjs';
import Link from 'next/link' import Link from 'next/link'
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import {useContext} from "react";
import {IconStyleContext} from "./CustomizeIconContext";
import {IconWrapper} from "./IconWrapper";
const IconList = ({icons}) => { const IconList = ({icons}) => {
const toast = useToast(); const toast = useToast();
const {color, size, strokeWidth} = useContext(IconStyleContext);
return ( return (
<Grid <Grid
@@ -15,7 +19,7 @@ const IconList = ({icons}) => {
{ icons.map((icon) => { { icons.map((icon) => {
// @ts-ignore // @ts-ignore
const actualIcon = icon.item ? icon.item : icon; const actualIcon = icon.item ? icon.item : icon;
const { name, src } = actualIcon; const { name, content } = actualIcon;
return ( return (
<Link key={name} href={`/?iconName=${name}`} as={`/icon/${name}`} scroll={false}> <Link key={name} href={`/?iconName=${name}`} as={`/icon/${name}`} scroll={false}>
@@ -46,7 +50,13 @@ const IconList = ({icons}) => {
alignItems="center" alignItems="center"
> >
<Flex direction="column" align="center" justify="center"> <Flex direction="column" align="center" justify="center">
<div dangerouslySetInnerHTML={{ __html: src }} /> <IconWrapper
content={content}
stroke={color}
strokeWidth={strokeWidth}
height={size}
width={size}
/>
<Text marginTop={5}>{name}</Text> <Text marginTop={5}>{name}</Text>
</Flex> </Flex>
</Button> </Button>

View File

@@ -0,0 +1,27 @@
import { forwardRef, SVGProps } from 'react';
interface IconWrapperProps extends SVGProps<SVGSVGElement> {
content: string;
}
export const IconWrapper = forwardRef<SVGSVGElement, IconWrapperProps>((props, ref) => {
const defaultAttrs : SVGProps<SVGSVGElement>= {
xmlns: 'http://www.w3.org/2000/svg',
width: '24px',
height: '24px',
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: '2px',
strokeLinecap: 'round',
strokeLinejoin: 'round',
};
const { content, ...rest } = props;
const attrs = {
...defaultAttrs,
...rest,
};
return <svg ref={ref} {...attrs} dangerouslySetInnerHTML={{ __html: content }} />;
});

View File

@@ -1,5 +1,6 @@
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import cheerio from 'cheerio';
import tags from '../../../tags.json'; import tags from '../../../tags.json';
const directory = path.join(process.cwd(), "../icons"); const directory = path.join(process.cwd(), "../icons");
@@ -16,10 +17,14 @@ export function getData(name) {
const fullPath = path.join(directory, `${name}.svg`); const fullPath = path.join(directory, `${name}.svg`);
const fileContents = fs.readFileSync(fullPath, "utf8"); const fileContents = fs.readFileSync(fullPath, "utf8");
const $ = cheerio.load(fileContents);
const content = $("svg").html();
return { return {
name, name,
tags: tags[name] || [], tags: tags[name] || [],
src: fileContents, src: fileContents,
content: content
}; };
} }

View File

@@ -5,6 +5,7 @@ import IconOverview from "../components/IconOverview";
import IconDetailOverlay from "../components/IconDetailOverlay"; import IconDetailOverlay from "../components/IconDetailOverlay";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import Header from "../components/Header"; import Header from "../components/Header";
import {CustomizeIconContext} from "../components/CustomizeIconContext";
const IndexPage = ({ data }) => { const IndexPage = ({ data }) => {
const router = useRouter(); const router = useRouter();
@@ -12,13 +13,15 @@ const IndexPage = ({ data }) => {
return ( return (
<Layout> <Layout>
<IconDetailOverlay <CustomizeIconContext>
isOpen={!!router.query.iconName} <IconDetailOverlay
icon={getIcon(router.query.iconName)} isOpen={!!router.query.iconName}
onClose={() => router.push('/')} icon={getIcon(router.query.iconName)}
/> onClose={() => router.push('/')}
<Header {...{data}}/> />
<IconOverview {...{data}}/> <Header {...{data}}/>
<IconOverview {...{data}}/>
</CustomizeIconContext>
</Layout> </Layout>
); );
}; };

View File

@@ -1519,6 +1519,11 @@
version "0.2.5" version "0.2.5"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
"@icons/material@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -2495,6 +2500,11 @@ bn.js@^5.1.1:
version "5.1.3" version "5.1.3"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
boolbase@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -2756,6 +2766,18 @@ char-regex@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
cheerio@^1.0.0-rc.3:
version "1.0.0-rc.3"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6"
integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==
dependencies:
css-select "~1.2.0"
dom-serializer "~0.1.1"
entities "~1.1.1"
htmlparser2 "^3.9.1"
lodash "^4.15.0"
parse5 "^3.0.1"
chokidar@2.1.8, chokidar@^2.1.8: chokidar@2.1.8, chokidar@^2.1.8:
version "2.1.8" version "2.1.8"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
@@ -3079,6 +3101,21 @@ css-loader@4.3.0:
schema-utils "^2.7.1" schema-utils "^2.7.1"
semver "^7.3.2" semver "^7.3.2"
css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=
dependencies:
boolbase "~1.0.0"
css-what "2.1"
domutils "1.5.1"
nth-check "~1.0.1"
css-what@2.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
css.escape@^1.5.0, css.escape@^1.5.1: css.escape@^1.5.0, css.escape@^1.5.1:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
@@ -3280,6 +3317,13 @@ dom-accessibility-api@^0.5.1:
version "0.5.3" version "0.5.3"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.3.tgz#0ea493c924d4070dfbf531c4aaca3d7a2c601aab" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.3.tgz#0ea493c924d4070dfbf531c4aaca3d7a2c601aab"
dom-serializer@0, dom-serializer@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
dependencies:
domelementtype "^2.0.1"
entities "^2.0.0"
dom-serializer@1.0.1: dom-serializer@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.0.1.tgz#79695eb49af3cd8abc8d93a73da382deb1ca0795" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.0.1.tgz#79695eb49af3cd8abc8d93a73da382deb1ca0795"
@@ -3288,13 +3332,6 @@ dom-serializer@1.0.1:
domhandler "^3.0.0" domhandler "^3.0.0"
entities "^2.0.0" entities "^2.0.0"
dom-serializer@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
dependencies:
domelementtype "^2.0.1"
entities "^2.0.0"
dom-serializer@^1.0.1: dom-serializer@^1.0.1:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58"
@@ -3303,10 +3340,23 @@ dom-serializer@^1.0.1:
domhandler "^3.0.0" domhandler "^3.0.0"
entities "^2.0.0" entities "^2.0.0"
dom-serializer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0"
integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==
dependencies:
domelementtype "^1.3.0"
entities "^1.1.1"
domain-browser@^1.1.1: domain-browser@^1.1.1:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
domelementtype@^2.0.1: domelementtype@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971"
@@ -3323,12 +3373,27 @@ domhandler@3.0.0:
dependencies: dependencies:
domelementtype "^2.0.1" domelementtype "^2.0.1"
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
dependencies:
domelementtype "1"
domhandler@^3.0.0, domhandler@^3.3.0: domhandler@^3.0.0, domhandler@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a"
dependencies: dependencies:
domelementtype "^2.0.1" domelementtype "^2.0.1"
domutils@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=
dependencies:
dom-serializer "0"
domelementtype "1"
domutils@2.1.0: domutils@2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.1.0.tgz#7ade3201af43703fde154952e3a868eb4b635f16" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.1.0.tgz#7ade3201af43703fde154952e3a868eb4b635f16"
@@ -3337,6 +3402,14 @@ domutils@2.1.0:
domelementtype "^2.0.1" domelementtype "^2.0.1"
domhandler "^3.0.0" domhandler "^3.0.0"
domutils@^1.5.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
dependencies:
dom-serializer "0"
domelementtype "1"
domutils@^2.0.0: domutils@^2.0.0:
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.2.tgz#7ee5be261944e1ad487d9aa0616720010123922b" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.2.tgz#7ee5be261944e1ad487d9aa0616720010123922b"
@@ -3411,6 +3484,11 @@ enhanced-resolve@^4.3.0:
memory-fs "^0.5.0" memory-fs "^0.5.0"
tapable "^1.0.0" tapable "^1.0.0"
entities@^1.1.1, entities@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
entities@^2.0.0: entities@^2.0.0:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
@@ -4020,6 +4098,18 @@ htmlparser2@4.1.0:
domutils "^2.0.0" domutils "^2.0.0"
entities "^2.0.0" entities "^2.0.0"
htmlparser2@^3.9.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
dependencies:
domelementtype "^1.3.1"
domhandler "^2.3.0"
domutils "^1.5.1"
entities "^1.1.1"
inherits "^2.0.1"
readable-stream "^3.1.1"
http-signature@~1.2.0: http-signature@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@@ -4929,7 +5019,7 @@ lodash.sortby@^4.7.0:
version "4.7.0" version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20:
version "4.17.20" version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
@@ -4988,6 +5078,11 @@ map-visit@^1.0.0:
dependencies: dependencies:
object-visit "^1.0.0" object-visit "^1.0.0"
material-colors@^1.2.1:
version "1.2.6"
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
md5.js@^1.3.4: md5.js@^1.3.4:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -5380,6 +5475,13 @@ npm-run-path@^4.0.0:
dependencies: dependencies:
path-key "^3.0.0" path-key "^3.0.0"
nth-check@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
dependencies:
boolbase "~1.0.0"
nwsapi@^2.2.0: nwsapi@^2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
@@ -5537,6 +5639,13 @@ parse5@5.1.1:
version "5.1.1" version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
parse5@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==
dependencies:
"@types/node" "*"
pascalcase@^0.1.1: pascalcase@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@@ -5758,7 +5867,7 @@ prompts@^2.0.1:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.4" sisteransi "^1.0.4"
prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
dependencies: dependencies:
@@ -5850,6 +5959,18 @@ react-clientside-effect@^1.2.2:
dependencies: dependencies:
"@babel/runtime" "^7.0.0" "@babel/runtime" "^7.0.0"
react-color@^2.18.1:
version "2.18.1"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.18.1.tgz#2cda8cc8e06a9e2c52ad391a30ddad31972472f4"
integrity sha512-X5XpyJS6ncplZs74ak0JJoqPi+33Nzpv5RYWWxn17bslih+X7OlgmfpmGC1fNvdkK7/SGWYf1JJdn7D2n5gSuQ==
dependencies:
"@icons/material" "^0.2.4"
lodash "^4.17.11"
material-colors "^1.2.1"
prop-types "^15.5.10"
reactcss "^1.2.0"
tinycolor2 "^1.4.1"
react-dom@^16.13.1: react-dom@^16.13.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
@@ -5948,6 +6069,13 @@ react@^16.14.0:
object-assign "^4.1.1" object-assign "^4.1.1"
prop-types "^15.6.2" prop-types "^15.6.2"
reactcss@^1.2.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==
dependencies:
lodash "^4.0.1"
read-pkg-up@^7.0.1: read-pkg-up@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
@@ -5977,7 +6105,7 @@ read-pkg@^5.2.0:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^3.5.0, readable-stream@^3.6.0: readable-stream@^3.1.1, readable-stream@^3.5.0, readable-stream@^3.6.0:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
dependencies: dependencies:
@@ -6765,6 +6893,11 @@ tinycolor2@1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
tinycolor2@^1.4.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
tmpl@1.0.x: tmpl@1.0.x:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"