diff --git a/src/cryptometrics/components/button/Button.js b/src/cryptometrics/components/button/Button.js new file mode 100644 index 0000000000000000000000000000000000000000..cf14da84404ad8460e12220e853e1650154a4a75 --- /dev/null +++ b/src/cryptometrics/components/button/Button.js @@ -0,0 +1,13 @@ +import classNames from "classnames"; +import React from "react"; + +export default function Button({ children, className, onClick }) { + return ( + <button + className={classNames("py-2 px-5 rounded-xl", className)} + onClick={onClick} + > + {children} + </button> + ); +} diff --git a/src/cryptometrics/components/charts/CompareChart.js b/src/cryptometrics/components/charts/CompareChart.js new file mode 100644 index 0000000000000000000000000000000000000000..e37c6ff94dce6110510e7f0a56cbecda3e112211 --- /dev/null +++ b/src/cryptometrics/components/charts/CompareChart.js @@ -0,0 +1,149 @@ +import classNames from "classnames"; +import React, { useState, useRef } from "react"; +import ReactECharts from "echarts-for-react"; +import { useCryptoTimeSeriesRangeData } from "../../queries"; +import moment from "moment"; + +const unixNow = () => { + return moment().unix(); +}; + +const unixSubtractId = (id) => { + return moment().subtract(id[0], id.substring(1)).unix(); +}; + +function CompareChart() { + const [timerange, setTimerange] = useState("6month"); + const chartRef = useRef(null); + const cryptoQuery = useCryptoTimeSeriesRangeData( + "solana", + unixSubtractId(timerange), + unixNow() + ); + const cryptoQuery2 = useCryptoTimeSeriesRangeData( + "avalanche-2", + unixSubtractId(timerange), + unixNow() + ); + + const option = { + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + grid: { + bottom: 30, + right: 10, + top: 10, + left: 50, + }, + dataZoom: [ + { + type: "inside", + }, + ], + xAxis: { + type: "time", + silent: false, + splitLine: { + show: false, + }, + splitArea: { + show: false, + }, + }, + yAxis: { + type: "value", + splitArea: { + show: false, + }, + splitLine: { + show: false, + }, + }, + series: [ + { + type: "line", + data: cryptoQuery.data?.prices, + name: "Solana", + smooth: true, + symbol: "none", + lineStyle: { + width: 3, + shadowOffsetY: 1, + color: "#3590F3", + shadowColor: "#1F51FF", + shadowOffsetX: 1, + shadowBlur: 10, + }, + }, + { + type: "line", + data: cryptoQuery2.data?.prices, + name: "Avalanche", + smooth: true, + symbol: "none", + lineStyle: { + width: 3, + shadowOffsetY: 0, + color: "#06D6A0", + shadowColor: "#39FF14", + shadowOffsetX: 1, + shadowBlur: 10, + }, + }, + ], + }; + + return ( + <div className="dark:bg-dark-600 p-8 rounded-3xl"> + <div className="flex flex-row space-x-3"> + <ToggleButton id="1hour" active={timerange} setActive={setTimerange}> + 1H + </ToggleButton> + <ToggleButton id="1day" active={timerange} setActive={setTimerange}> + 1D + </ToggleButton> + <ToggleButton id="1week" active={timerange} setActive={setTimerange}> + 1W + </ToggleButton> + <ToggleButton id="1month" active={timerange} setActive={setTimerange}> + 1M + </ToggleButton> + <ToggleButton id="6month" active={timerange} setActive={setTimerange}> + 6M + </ToggleButton> + <ToggleButton id="1year" active={timerange} setActive={setTimerange}> + 1Y + </ToggleButton> + </div> + <div className="h-[600px] mt-10"> + <ReactECharts + ref={chartRef} + option={option} + style={{ + height: "100%", + }} + /> + </div> + </div> + ); +} + +function ToggleButton({ children, setActive, active, id }) { + return ( + <button + className={classNames(" px-3 py-2 rounded-md font-light", { + "dark:bg-white dark:text-gray-800": active === id, + "dark:bg-black dark:text-gray-400": active !== id, + })} + onClick={() => setActive(id)} + > + {children} + </button> + ); +} + +export default CompareChart; diff --git a/src/cryptometrics/components/charts/CryptoRowLineChart.js b/src/cryptometrics/components/charts/CryptoRowLineChart.js new file mode 100644 index 0000000000000000000000000000000000000000..b569ae35901e1747de3bb45f756b6aebd269ae27 --- /dev/null +++ b/src/cryptometrics/components/charts/CryptoRowLineChart.js @@ -0,0 +1,20 @@ +import React, { useRef } from "react"; +import ReactECharts from "echarts-for-react"; +import { cryptoLineChartOptions } from "../../constants"; +import { useCryptoTimeSeriesData } from "../../queries"; + +function CryptoRowLineChart({ currencyId, color }) { + const cryptoQuery = useCryptoTimeSeriesData(currencyId, 1, "hourly"); + const chartRef = useRef(null); + return ( + <ReactECharts + ref={chartRef} + option={cryptoLineChartOptions(cryptoQuery.data?.prices, color)} + style={{ + height: "100%", + }} + /> + ); +} + +export default CryptoRowLineChart; diff --git a/src/cryptometrics/components/coin/Coin.js b/src/cryptometrics/components/coin/Coin.js new file mode 100644 index 0000000000000000000000000000000000000000..66c5472149ea771e7bf0c79240201e9c9b8fd087 --- /dev/null +++ b/src/cryptometrics/components/coin/Coin.js @@ -0,0 +1,37 @@ +import React from "react"; + +const Coin = ({ + name, + image, + symbol, + price, + volume, + priceChange, + marketcap, +}) => { + return ( + <div className="coin-container"> + <div className="coin-row"> + <div className="coin"> + <img src={image} alt="crypto" /> + <p className="coin-name">{name}</p> + <p className="coin-symbol">{symbol}</p> + </div> + <div className="coin-data"> + <p className="coin-price">$ {price}</p> + <p className="coin-volume">$ {volume}</p> + {priceChange < 0 ? ( + <p className="coin-percent red">{priceChange.toFixed(2)}%</p> + ) : ( + <p className="coin-percent green">{priceChange.toFixed(2)}%</p> + )} + <p className="coin-marketcap"> + Mkt Cap : {marketcap.toLocaleString()} + </p> + </div> + </div> + </div> + ); +}; + +export default Coin; diff --git a/src/cryptometrics/components/dropdown/FilterDropdown.js b/src/cryptometrics/components/dropdown/FilterDropdown.js new file mode 100644 index 0000000000000000000000000000000000000000..3781d9fd7700a54d32b75feb36059fc301beb4b1 --- /dev/null +++ b/src/cryptometrics/components/dropdown/FilterDropdown.js @@ -0,0 +1,160 @@ +import { ArrowRightIcon } from "@heroicons/react/outline"; +import classNames from "classnames"; +import React, { useState, useEffect } from "react"; +import Button from "../button/Button"; +import { RadioInputForm } from "../radio/RadioForm"; +import { CSSTransition } from "react-transition-group"; + +export function FilterDropdown({ filterOptions, setOpen, addFilter }) { + const [selectedFilter, setSelectedFilter] = useState(null); + + const [radioValue, setRadioValue] = useState("is"); + const [inputValue, setInputValue] = useState(""); + + useEffect(() => { + if (selectedFilter) { + setRadioValue( + filterOptions[selectedFilter].options[ + Object.keys(filterOptions[selectedFilter].options)[0] + ].name + ); + } + }, [filterOptions, selectedFilter]); + + const onRadioChange = ({ target: { value } }) => { + setRadioValue(value); + }; + + const onInputChange = ({ target: { value } }) => { + setInputValue(value); + }; + + const onSelectedFilterChange = (filterId) => { + setSelectedFilter(filterId); + }; + + const onFilterAdd = () => { + addFilter({ + subject: filterOptions[selectedFilter].name, + condition: radioValue, + value: inputValue, + }); + setOpen(false); + }; + + return ( + <div className="absolute flex flex-row z-50"> + <div + className={classNames( + "dark:bg-dark-600 w-56 h-max max-h-72 rounded-xl mt-2 transition-all duration-100 p-1 overflow-y-scroll shadow-lg shadow-dark-600" + )} + > + {Object.keys(filterOptions).map((key) => { + return ( + <FilterDropdownItem + key={"primary_option_" + key} + selected={selectedFilter === key} + id={key} + onClick={onSelectedFilterChange} + > + {filterOptions[key].name} + </FilterDropdownItem> + ); + })} + </div> + <CSSTransition + in={selectedFilter} + classNames="secondary-dropdown" + timeout={300} + unmountOnExit + > + {selectedFilter ? ( + <span className="ml-3"> + <SecondaryFilterDropdown + open={true} + onSelectedFilterChange={onSelectedFilterChange} + radioOptions={filterOptions[selectedFilter]?.options} + radioValue={radioValue} + onRadioChange={onRadioChange} + inputValue={inputValue} + onInputChange={onInputChange} + onFilterAdd={onFilterAdd} + /> + </span> + ) : ( + <div></div> + )} + </CSSTransition> + </div> + ); +} + +export function SecondaryFilterDropdown({ + open, + onSelectedFilterChange, + radioOptions, + radioValue, + onRadioChange, + inputValue, + onInputChange, + onFilterAdd, +}) { + return ( + <div + className={classNames( + "dark:bg-dark-600 w-72 max-h-72 rounded-xl mt-2 transition-all duration-100 px-5 py-2 overflow-y-scroll shadow-lg shadow-dark-600", + { + block: open, + hidden: !open, + } + )} + > + <RadioInputForm + options={radioOptions} + radioValue={radioValue} + onRadioChange={onRadioChange} + inputValue={inputValue} + onInputChange={onInputChange} + /> + <div className="flex flex-row space-x-2 mb-2"> + <Button + className="bg-neutral-100 text-gray-700 font-semibold" + onClick={() => onSelectedFilterChange(null)} + > + Cancel + </Button> + <Button + className="bg-indigo-600 text-white font-semibold w-full" + onClick={onFilterAdd} + > + Filter + </Button> + </div> + </div> + ); +} + +// selected: boolean +function FilterDropdownItem({ children, selected, onClick, id }) { + return ( + <div + className={classNames( + "py-3 px-4 rounded-xl dark:text-neutral-100 hover:bg-dark-800 border-1 transition-all duration-100 cursor-pointer", + { + "border-transparent": !selected, + "bg-dark-800 border-indigo-600 font-semibold": selected, + } + )} + onClick={() => onClick(id)} + > + <div className="flex flex-row items-center"> + {children} + {selected && ( + <span className="ml-auto"> + <ArrowRightIcon className="w-4 h-4" /> + </span> + )} + </div> + </div> + ); +} diff --git a/src/cryptometrics/components/filters/Filter.js b/src/cryptometrics/components/filters/Filter.js new file mode 100644 index 0000000000000000000000000000000000000000..bde9750921c687448ba62bf71d7c22313a20d1e0 --- /dev/null +++ b/src/cryptometrics/components/filters/Filter.js @@ -0,0 +1,46 @@ +import React from "react"; + +export function Filter({ + subject, + condition, + value, + buttonIcon, + onButtonClick, +}) { + return ( + <div className="flex flex-wrap justify-start items-center mx-1 mt-2"> + <div className="py-5 pl-5 pr-1 font-sans bg-dark-600 rounded-l-lg dark:text-white inline-flex h-10 justify-center items-center whitespace-nowrap font-normal"> + <span>{subject} </span> + <span className="font-light dark:text-neutral-300"> + {condition} + </span> + <span>{value}</span> + </div> + + {/* Button */} + <button + onClick={onButtonClick} + className="mr-2 p-2 bg-dark-600 hover:dark:bg-dark-800 rounded-r-lg justify-center items-center h-10 w-10 inline-flex font-thin text-white" + > + <span>{buttonIcon}</span> + </button> + </div> + ); +} + +export function FilterButton({ icon, onClick }) { + return ( + <button + className="mx-1 mt-2 font-sans font-normal bg-dark-600 rounded-lg dark:text-neutral-200 dark:hover:text-indigo-600 inline-flex h-10 w-10 justify-center items-center whitespace-nowrap" + onClick={onClick} + > + {icon} + </button> + ); +} + +export function Filters({ children }) { + return ( + <div className="flex flex-wrap justify-start items-center">{children}</div> + ); +} diff --git a/src/cryptometrics/components/inputs/Input.js b/src/cryptometrics/components/inputs/Input.js new file mode 100644 index 0000000000000000000000000000000000000000..39d33c8322470575ebed1dc6f2a2090a355d30cc --- /dev/null +++ b/src/cryptometrics/components/inputs/Input.js @@ -0,0 +1,15 @@ +import React from "react"; + +function Input({ placeholder, type, onChange, initialValue }) { + return ( + <input + className="w-full h-12 text-base focus:ring-indigo-500 focus:border-indigo-500 border-1 border-transparent font-semibold outline-none dark:text-white px-3 pr-3 rounded-2xl bg-dark-800" + placeholder={placeholder} + type={type ? type : "text"} + onChange={onChange} + defaultValue={initialValue || ""} + ></input> + ); +} + +export default Input; diff --git a/src/cryptometrics/components/inputs/SearchInput.js b/src/cryptometrics/components/inputs/SearchInput.js index 32731bfeebdd90a0cbe4d821986ad8cdd00f1a29..a4bdec5ae4d8199db1f54086cfd8d17831c8d138 100644 --- a/src/cryptometrics/components/inputs/SearchInput.js +++ b/src/cryptometrics/components/inputs/SearchInput.js @@ -1,13 +1,14 @@ import React from "react"; import { SearchIcon } from "@heroicons/react/outline"; -function SearchInput() { +function SearchInput({ onChange }) { return ( <div className="relative"> <input className="w-52 h-12 text-base font-semibold outline-none dark:text-white px-3 pr-10 rounded-2xl bg-dark-700" placeholder="Search" type="text" + onChange={onChange} ></input> <button className="absolute top-0 right-3 bottom-0 w-6"> <SearchIcon className="w-6 h-6 dark:text-white" /> diff --git a/src/cryptometrics/components/radio/RadioForm.js b/src/cryptometrics/components/radio/RadioForm.js new file mode 100644 index 0000000000000000000000000000000000000000..294d3db4da610f311ee98b243a0314a3aed0df72 --- /dev/null +++ b/src/cryptometrics/components/radio/RadioForm.js @@ -0,0 +1,62 @@ +import classNames from "classnames"; +import React from "react"; +import Input from "../inputs/Input"; + +export function RadioInputForm({ + options, + radioValue, + onRadioChange, + inputValue, + onInputChange, +}) { + return ( + <div> + <div className="flex flex-col py-2 space-y-2"> + {Object.keys(options).map((key) => { + return ( + <div key={"radio_option_" + options[key].id}> + <Radio + selected={radioValue} + radioValue={options[key].name} + id={options[key].id} + onChange={onRadioChange} + /> + <div className="my-1"> + {options[key].name === radioValue && ( + <Input + type="text" + placeholder="Enter a value here..." + initialValue={inputValue} + onChange={onInputChange} + /> + )} + </div> + </div> + ); + })} + </div> + </div> + ); +} + +export function Radio({ selected, radioValue, onChange }) { + return ( + <label className="inline-flex items-center w-full"> + <input + type="radio" + className="form-radio h-4 w-4 accent-indigo-600 hover:accent-indigo-700" + value={radioValue} + checked={selected === radioValue} + onChange={onChange} + />{" "} + <span + className={classNames("font-poppins ml-2 text-base", { + "dark:text-white font-extralight": selected !== radioValue, + "dark:text-indigo-500": selected === radioValue, + })} + > + {radioValue} + </span> + </label> + ); +} diff --git a/src/cryptometrics/components/sidebar/Sidebar.js b/src/cryptometrics/components/sidebar/Sidebar.js index a18fe1d5eea25bfdb82b1c816ccce2cfb0844af0..e6f57873b131d1daed4d5049f8ba47fbd6afb544 100644 --- a/src/cryptometrics/components/sidebar/Sidebar.js +++ b/src/cryptometrics/components/sidebar/Sidebar.js @@ -4,9 +4,9 @@ import Link from "next/link"; import classNames from "classnames"; import { ChartBarIcon, GlobeIcon } from "@heroicons/react/outline"; -function Sidebar() { +function Sidebar({ active }) { return ( - <div className="w-64 dark:text-white"> + <div className="w-64 min-w-[16rem] dark:text-white"> {/* Sidebar Head */} <span className="flex justify-center items-center mt-5" id="crypto-logo"> <Image @@ -27,13 +27,13 @@ function Sidebar() { title="Home" icon={<GlobeIcon className="w-6 h-6" />} to="/" - active={true} + active={active === "home"} /> <SidebarItem title="Compare" icon={<ChartBarIcon className="w-6 h-6" />} - to="/map" - active={false} + to="/compare" + active={active === "compare"} /> </nav> </div> diff --git a/src/cryptometrics/components/table/Table.js b/src/cryptometrics/components/table/Table.js new file mode 100644 index 0000000000000000000000000000000000000000..92d9e8aa9a64df5dda1bb8d0499e39609af175b2 --- /dev/null +++ b/src/cryptometrics/components/table/Table.js @@ -0,0 +1,32 @@ +import classNames from "classnames"; +import React from "react"; + +export function Table({ children, className }) { + return <table className={classNames("w-full", className)}>{children}</table>; +} + +export function TableRow({ children, className }) { + return ( + <tr + className={classNames( + "w-full flex justify-between dark:bg-dark-600 my-4 mx-2 px-6 rounded-2xl cursor-pointer text-slate-900 dark:text-white hover:dark:bg-slate-900", + className + )} + > + {children} + </tr> + ); +} + +export function TableCell({ children, className }) { + return ( + <td + className={classNames( + "flex flex-col justify-center items-center align-middle h-20 px-4 font-semibold", + className + )} + > + {children} + </td> + ); +} diff --git a/src/cryptometrics/constants/constants.js b/src/cryptometrics/constants/constants.js index 69f6af6f648f6a4c9c827d6e15ab0997fb257216..5bfc28934fe30fdb11da9d2bf880233e2b6fb3a8 100644 --- a/src/cryptometrics/constants/constants.js +++ b/src/cryptometrics/constants/constants.js @@ -1,4 +1,8 @@ -export const cryptoChartOptions = (colors = [], dark = false) => { +export const cryptoChartOptions = ( + colors = [], + dark = false, + animationsEnabled = false +) => { return { chart: { toolbar: { @@ -7,6 +11,9 @@ export const cryptoChartOptions = (colors = [], dark = false) => { sparkline: { enabled: true, }, + animations: { + enabled: animationsEnabled, + }, }, dataLabels: { enabled: false, @@ -65,6 +72,77 @@ export const cryptoChartOptions = (colors = [], dark = false) => { }; }; +export const cryptoLineChartOptions = (seriesData = [], color = "#3590F3") => { + return { + grid: { + bottom: 10, + right: 10, + top: 10, + left: 10, + }, + xAxis: { + show: false, + type: "time", + silent: false, + splitLine: { + show: false, + }, + splitArea: { + show: false, + }, + }, + yAxis: { + show: false, + type: "value", + splitArea: { + show: false, + }, + splitLine: { + show: false, + }, + min: "dataMin", + max: "dataMax", + }, + series: [ + { + type: "line", + data: seriesData, + name: "Solana", + smooth: true, + symbol: "none", + lineStyle: { + width: 3, + shadowOffsetY: -1, + color: color, + shadowColor: color, + shadowOffsetX: 0, + shadowBlur: 5, + cap: "round", + opacity: 1, + }, + animation: false, + }, + { + type: "scatter", + data: seriesData.slice(-1), + name: "ABC", + smooth: true, + symbol: "circle", + symbolSize: 20, + itemStyle: { + shadowOffsetY: 0, + color: color, + shadowColor: color, + shadowOffsetX: 0, + shadowBlur: 15, + opacity: 0.1, + }, + animation: false, + }, + ], + }; +}; + export const cryptocurrencies = [ { id: "bitcoin", @@ -98,3 +176,56 @@ export const cryptocurrencies = [ name: "Cardano", }, ]; + +export const filterOptions = { + price: { + id: "price", + name: "Price", + options: { + equals: { + id: "equals", + name: "is", + }, + less_than: { + id: "less_than", + name: "is less than", + }, + greater_than: { + id: "greater_than", + name: "is greater than", + }, + }, + }, + name: { + id: "name", + name: "Name", + options: { + equals: { + id: "equals", + name: "is", + }, + less_than: { + id: "contains", + name: "contains", + }, + }, + }, + price_change_percentage: { + id: "price_change_percentage", + name: "Price Change in %", + options: { + equals: { + id: "equals", + name: "is", + }, + less_than: { + id: "less_than", + name: "is less than", + }, + greater_than: { + id: "greater_than", + name: "is greater than", + }, + }, + }, +}; diff --git a/src/cryptometrics/hooks/useFilters.js b/src/cryptometrics/hooks/useFilters.js new file mode 100644 index 0000000000000000000000000000000000000000..145c8d4fe04a63d7d26ef39aa3da2d0dcedbf04a --- /dev/null +++ b/src/cryptometrics/hooks/useFilters.js @@ -0,0 +1,47 @@ +import React, { useState } from "react"; + +/** + * Format of each filter should be: + * { + * subject: "", + * condition: "", + * value: "" + * } + */ +export default function useFilters(initialArray) { + const [filters, setFilters] = useState(initialArray); + + const checkIfFilterExists = (filter) => { + for (let i = 0; i < filters.length; i++) { + if ( + filters[i].subject === filter.subject && + filters[i].condition === filter.condition && + filters[i].value === filter.value + ) { + return true; + } + } + return false; + }; + + const addFilter = (filter) => { + // Check if filter already exists + if (checkIfFilterExists(filter)) { + return; + } + setFilters([...filters, filter]); + }; + + const removeFilter = (filter) => { + setFilters( + filters.filter(({ subject, condition, value }) => { + return ( + subject !== filter.subject || + condition !== filter.condition || + value !== filter.value + ); + }) + ); + }; + return [filters, addFilter, removeFilter]; +} diff --git a/src/cryptometrics/package.json b/src/cryptometrics/package.json index 554054aa83b6b24e92a4f4bf5f69b669cc39e48c..bd3833489663dd3593ed64247daa92a434e80890 100644 --- a/src/cryptometrics/package.json +++ b/src/cryptometrics/package.json @@ -12,12 +12,18 @@ "apexcharts": "^3.33.1", "axios": "^0.26.0", "classnames": "^2.3.1", + "echarts": "^5.3.0", + "echarts-for-react": "^3.0.2", + "moment": "^2.29.1", "next": "12.1.0", + "nprogress": "^0.2.0", "numeral": "^2.0.6", "react": "17.0.2", "react-apexcharts": "^1.3.9", "react-dom": "17.0.2", - "react-query": "^3.34.15" + "react-query": "^3.34.15", + "react-transition-group": "^4.4.2", + "sharp": "^0.30.2" }, "devDependencies": { "autoprefixer": "^10.4.2", diff --git a/src/cryptometrics/pages/_app.js b/src/cryptometrics/pages/_app.js index 22bb7719e0eb539714c246a3bc81ecc2026edade..e5d964ed33967c396f10a5904c04e43630b923fa 100644 --- a/src/cryptometrics/pages/_app.js +++ b/src/cryptometrics/pages/_app.js @@ -1,6 +1,13 @@ import "../styles/globals.css"; import { QueryClient, QueryClientProvider } from "react-query"; import { ReactQueryDevtools } from "react-query/devtools"; +import Router from "next/router"; +import NProgress from "nprogress"; +import "nprogress/nprogress.css"; + +Router.events.on("routeChangeStart", () => NProgress.start()); +Router.events.on("routeChangeComplete", () => NProgress.done()); +Router.events.on("routeChangeError", () => NProgress.done()); const queryClient = new QueryClient(); diff --git a/src/cryptometrics/pages/compare.js b/src/cryptometrics/pages/compare.js new file mode 100644 index 0000000000000000000000000000000000000000..36de567d68189b3320c23c82baea7b2c20671858 --- /dev/null +++ b/src/cryptometrics/pages/compare.js @@ -0,0 +1,32 @@ +import Head from "next/head"; +import Container from "../components/content/Container"; +import Main from "../components/content/Main"; +import BoldGradientHeading from "../components/titles/BoldGradientHeading"; +import Wrapper from "../components/content/Wrapper"; +import Sidebar from "../components/sidebar/Sidebar"; +import CompareChart from "../components/charts/CompareChart"; + +export default function Compare() { + return ( + <div> + <Head> + <title>CryptoMetrics - Compare</title> + <meta name="description" content="CryptoMetrics" /> + <link rel="icon" href="/favicon.ico" /> + </Head> + <Wrapper> + <Sidebar active="compare" /> + <Main> + <Container> + {/* Header */} + <div className="flex flex-row justify-between mb-4"> + {/* Main Project Title */} + <BoldGradientHeading>Compare</BoldGradientHeading> + </div> + <CompareChart /> + </Container> + </Main> + </Wrapper> + </div> + ); +} diff --git a/src/cryptometrics/pages/index.js b/src/cryptometrics/pages/index.js index 114877c45612160934d26f5ddd64ffba8acc8ae0..bfed6c84175464f5641e49087e7441d07fa33043 100644 --- a/src/cryptometrics/pages/index.js +++ b/src/cryptometrics/pages/index.js @@ -1,3 +1,4 @@ +import React, { useState } from "react"; import Head from "next/head"; import Container from "../components/content/Container"; import Main from "../components/content/Main"; @@ -10,35 +11,31 @@ import numeral from "numeral"; import Wrapper from "../components/content/Wrapper"; import Sidebar from "../components/sidebar/Sidebar"; import { Tabs, Tab } from "../components/tabs/Tab"; -import { CollectionIcon, TableIcon } from "@heroicons/react/outline"; +import { + CollectionIcon, + PlusIcon, + TableIcon, + XIcon, +} from "@heroicons/react/outline"; +import useFilters from "../hooks/useFilters"; +import { Filter, FilterButton, Filters } from "../components/filters/Filter"; +import { FilterDropdown } from "../components/dropdown/FilterDropdown"; +import { filterOptions } from "../constants"; +import { Table, TableCell, TableRow } from "../components/table/Table"; +import Image from "next/image"; +import CryptoRowLineChart from "../components/charts/CryptoRowLineChart"; +import classNames from "classnames"; +import Link from "next/link"; export default function Home() { + const [filters, addFilter, removeFilter] = useFilters([]); + const [dropdownOpen, setDropdownOpen] = useState(false); + const [searchText, setSearchText] = useState(""); const listOfCoins = useCryptoList("usd", 21, false); - const filteredCoins = listOfCoins.data?.map((coin) => { - return ( - <CryptoChartCard - key={coin.symbol} - currencyId={coin.id} - currencyName={coin.name} - symbol={coin.symbol.toUpperCase()} - icon={coin.image} - info={"$" + numeral(coin.current_price).format("0,0.[0000000]")} - detail={ - numeral(coin.price_change_percentage_24h).format("+0.0[00]") + "%" - } - detailColor={ - coin.price_change_percentage_24h > 0 - ? "text-green-500" - : "text-red-500" - } - options={cryptoChartOptions( - coin.price_change_percentage_24h > 0 ? ["#3DBAA2"] : ["#FF7A68"], - true - )} - type="area" - /> - ); + const filteredCoins = listOfCoins.data?.filter((coin) => { + return coin.name.toLowerCase().includes(searchText.toLowerCase()); }); + return ( <div> <Head> @@ -47,7 +44,7 @@ export default function Home() { <link rel="icon" href="/favicon.ico" /> </Head> <Wrapper> - <Sidebar /> + <Sidebar active="home" /> <Main> <Container> {/* Header */} @@ -55,7 +52,39 @@ export default function Home() { {/* Main Project Title */} <BoldGradientHeading>Home</BoldGradientHeading> {/* Search Field */} - <SearchInput /> + <SearchInput onChange={(e) => setSearchText(e?.target.value)} /> + </div> + <div className="mb-2"> + <Filters> + {filters.map((filter, idx) => { + return ( + <Filter + key={"filter_" + idx} + subject={filter.subject} + condition={filter.condition} + value={filter.value} + buttonIcon={<XIcon className="w-5 h-5" />} + onButtonClick={() => removeFilter(filter)} + /> + ); + })} + <div className="relative"> + <FilterButton + icon={<PlusIcon className="w-6 h-6" />} + onClick={() => + setDropdownOpen(!dropdownOpen) && addFilter({}) + } + /> + + {dropdownOpen && ( + <FilterDropdown + setOpen={setDropdownOpen} + addFilter={addFilter} + filterOptions={filterOptions} + /> + )} + </div> + </Filters> </div> {/* Main Content */} @@ -65,17 +94,172 @@ export default function Home() { content={<CollectionIcon className="w-6 h-6 dark:text-white" />} > <div className="flex flex-wrap gap-x-10 gap-y-10 mt-3"> - {!listOfCoins.isLoading && filteredCoins} + {!listOfCoins.isLoading && + filteredCoins.map((coin) => { + return ( + <CryptoChartCard + key={coin.symbol} + currencyId={coin.id} + currencyName={coin.name} + symbol={coin.symbol.toUpperCase()} + icon={coin.image} + info={ + "$" + + numeral(coin.current_price).format("0,0.[0000000]") + } + detail={ + numeral(coin.price_change_percentage_24h).format( + "+0.0[00]" + ) + "%" + } + detailColor={ + coin.price_change_percentage_24h > 0 + ? "text-green-500" + : "text-red-500" + } + options={cryptoChartOptions( + coin.price_change_percentage_24h > 0 + ? ["#3DBAA2"] + : ["#FF7A68"], + true + )} + type="area" + /> + ); + })} </div> </Tab> <Tab id="list-view" content={<TableIcon className="w-6 h-6 dark:text-white" />} > - {/* TODO: Add Table Component Here */} - <div className="flex flex-wrap gap-x-10 gap-y-10 mt-3"> - <h1 className="dark:text-white">TABLE</h1> - </div> + <Table> + <TableRow className="h-14 items-center sticky top-0 z-40"> + <TableCell className="w-6 h-10"></TableCell> + <TableCell className="w-24 h-10"> + <p className="font-medium text-base text-center">Name</p> + </TableCell> + <TableCell className="w-24 h-10"> + <p className="font-medium text-base text-center">Price</p> + </TableCell> + <TableCell className="w-[10%] h-10"> + <p className="font-medium text-base text-center"> + Market Cap + </p> + </TableCell> + <TableCell className="w-40 h-10"> + <p className="font-medium text-base text-center"> + 24h change in % + </p> + </TableCell> + <TableCell className="w-40 h-10"> + <p className="font-medium text-base text-center"> + 24h change in $ + </p> + </TableCell> + <TableCell className="h-10"> + <div className="w-52"> + <p className="font-medium text-base text-center"> + Chart + </p> + </div> + </TableCell> + </TableRow> + {!listOfCoins.isLoading && + filteredCoins.map((coin, index) => { + return ( + <Link + key={"table_row_" + index} + href={`/coins/${coin.id}`} + passHref + > + <a> + <TableRow> + <TableCell className="w-6"> + <Image + src={coin.image} + width="32px" + height="32px" + alt={`${coin.id}_icon`} + layout="fixed" + ></Image> + </TableCell> + <TableCell className="w-24"> + <p className="font-medium text-base text-center"> + {coin.name} + </p> + <p className="font-light text-gray-300 text-sm mt-1"> + {coin.symbol.toUpperCase()} + </p> + </TableCell> + <TableCell className="w-24"> + <p className="font-light text-base text-blue-500 mt-1"> + $ + {numeral(coin.current_price).format( + "0,0.[0000000]" + )} + </p> + </TableCell> + <TableCell className="w-[10%]"> + <p className="font-light text-base text-pink-400 mt-1"> + $ + {numeral(coin.market_cap).format( + "0,0.[000]a" + )} + </p> + </TableCell> + <TableCell className="w-40"> + <p + className={classNames( + "font-light text-base mt-1", + { + "text-red-400": + coin.price_change_percentage_24h < 0, + "text-green-400": + coin.price_change_percentage_24h >= 0, + } + )} + > + {numeral( + coin.price_change_percentage_24h + ).format("+0.0[00]")} + % + </p> + </TableCell> + <TableCell className="w-40"> + <p + className={classNames( + "font-light text-base mt-1", + { + "text-red-400": coin.price_change_24h < 0, + "text-green-400": + coin.price_change_24h >= 0, + } + )} + > + {numeral(coin.price_change_24h).format( + "$0,0.[0000]" + )} + </p> + </TableCell> + <TableCell> + <div className="h-[50px] w-52"> + <CryptoRowLineChart + currencyId={coin.id} + color={ + coin.price_change_24h >= 0 + ? "#10B981" + : "#EF4444" + } + /> + </div> + </TableCell> + </TableRow> + </a> + </Link> + ); + })} + </Table> </Tab> </Tabs> </Container> diff --git a/src/cryptometrics/queries/queries.js b/src/cryptometrics/queries/queries.js index 16c2d024af7f2bfac48bb3b875190c848c91ee6f..c214fd7f6fabe099a8d23ade9e6b7a0051ed830b 100644 --- a/src/cryptometrics/queries/queries.js +++ b/src/cryptometrics/queries/queries.js @@ -18,6 +18,23 @@ export function useCryptoTimeSeriesData(name, days = 7, interval = "daily") { ); } +export function useCryptoTimeSeriesRangeData(name, from, to) { + return useQuery( + `${name}_from_${from}_to_${to}`, + () => { + return axios + .get( + `https://api.coingecko.com/api/v3/coins/${name}/market_chart/range?vs_currency=usd&from=${from}&to=${to}` + ) + .then((res) => res.data); + }, + { + refetchOnWindowFocus: false, + staleTime: 5 * 60000, // 5 minutes, + } + ); +} + export function useCryptoList( currency = "usd", numberOfCurrencies = 20, diff --git a/src/cryptometrics/styles/globals.css b/src/cryptometrics/styles/globals.css index edd5ea5ccd584e8cae4aee56df1e61e6c38f3894..c06a668aab6d73e7805fb95f3996ee6f00c3c93f 100644 --- a/src/cryptometrics/styles/globals.css +++ b/src/cryptometrics/styles/globals.css @@ -11,3 +11,145 @@ @apply bg-dark-800; } } + +#nprogress .bar { + background: rgb(37 99 235) !important; +} + +#nprogress .spinner-icon { + border-top-color: rgb(37 99 235) !important; + border-left-color: rgb(37 99 235) !important; +} + +#nprogress .peg { + box-shadow: 0 0 10px rgb(37 99 235), 0 0 5px rgb(37 99 235) !important; +} + +.secondary-dropdown-enter { + opacity: 0; + transform: translateX(-50px); +} +.secondary-dropdown-enter-active { + opacity: 1; + transform: translateX(0); + transition: opacity 300ms, transform 300ms; +} +.secondary-dropdown-exit { + opacity: 1; +} +.secondary-dropdown-exit-active { + opacity: 0; + /* transform: scale(0.9); */ + transform: translateX(-50px); + transition: opacity 300ms, transform 300ms; +} +.coin-app { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 64px; + color: white; +} +.coin-search { + margin-bottom: 64px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.coin-text { + margin-bottom: 32px; + text-align: center; +} +.coin-refresh { + /* padding-left: 8px; */ + width: 100px; + height: 50px; + border-radius: 4px; + border: none; + background: linear-gradient(to right, #50c9c3, #96deda); + margin-bottom: 20px; +} + +.coin-input { + padding-left: 16px; + width: 300px; + height: 50px; + border-radius: 4px; + border: none; + background-image: linear-gradient(to right, #f2709c, #ff9472); +} + +.coin-input::placeholder { + color: #e2e2e2; +} +.coin-container { + font-family: "Poppins", sans-serif; + font-weight: 700; + font-size: 17px; + display: flex; + justify-content: center; +} + +.coin-row { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + height: 80px; + color: white; + width: 1500px; +} + +.coin { + display: flex; + align-items: center; + padding-right: 24px; + min-width: 300px; +} + +.coin .coin-name { + width: 250px; +} + +.coin img { + height: 30px; + width: 30px; + margin-right: 10px; +} + +.coin-symbol { + text-transform: uppercase; +} + +.coin-data { + display: flex; + text-align: right; + justify-content: space-between; + width: 100%; +} + +.coin-price { + width: 110px; +} + +.coin-volume { + width: 155px; +} + +.coin-marketcap { + width: 230px; +} + +.coin-percent { + width: 100px; +} + +.red { + color: #f00606; +} + +.green { + color: #11d811; +} diff --git a/src/cryptometrics/tailwind.config.js b/src/cryptometrics/tailwind.config.js index ebb7692c009e6369070d3a04373a5f3d3efaaf8f..01fdf6ebec9bd1344197ba75c443cd85b08b39da 100644 --- a/src/cryptometrics/tailwind.config.js +++ b/src/cryptometrics/tailwind.config.js @@ -20,10 +20,15 @@ module.exports = { }, colors: { dark: { + 100: "#4b5364", + 200: "#3f4654", + 300: "#343a45", + 400: "#282d36", + 500: "#1d2026", 600: "#121418", 700: "#111317", 800: "#080808", - 900: "#000", + 900: "#060608", }, }, }, diff --git a/src/cryptometrics/yarn.lock b/src/cryptometrics/yarn.lock index a511620a609e17fdbfe42b03e5f74ad2df73734b..1be50638109cec07088e34fdf6c8207de8bf176e 100644 --- a/src/cryptometrics/yarn.lock +++ b/src/cryptometrics/yarn.lock @@ -31,7 +31,7 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": +"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7": version "7.17.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== @@ -258,6 +258,11 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -297,6 +302,19 @@ apexcharts@^3.33.1: svg.resize.js "^1.4.3" svg.select.js "^3.0.1" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + arg@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" @@ -388,6 +406,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + big-integer@^1.6.16: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" @@ -398,6 +421,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -438,6 +470,14 @@ browserslist@^4.19.1: node-releases "^2.0.2" picocolors "^1.0.0" +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -493,11 +533,21 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + classnames@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -517,21 +567,47 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.1.4, color-name@~1.1.4: +color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa" + integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.1.tgz#498aee5fce7fc982606c8875cab080ac0547c884" + integrity sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + core-js-pure@^3.20.2: version "3.21.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cosmiconfig@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" @@ -557,6 +633,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +csstype@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" + integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + damerau-levenshtein@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -583,6 +664,18 @@ debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: dependencies: ms "2.1.2" +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -600,6 +693,16 @@ defined@^1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^2.0.0, detect-libc@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + detect-node@^2.0.4, detect-node@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" @@ -645,16 +748,52 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +echarts-for-react@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz#ac5859157048a1066d4553e34b328abb24f2b7c1" + integrity sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA== + dependencies: + fast-deep-equal "^3.1.3" + size-sensor "^1.0.1" + +echarts@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.3.0.tgz#39342fcf0f763413fecd9d2afd1c415163de694d" + integrity sha512-zENufmwFE6WjM+24tW3xQq4ICqQtI0CGj4bDVDNd3BK3LtaA/5wBp+64ykIyKy3QElz0cieKqSYP4FX9Lv9MwQ== + dependencies: + tslib "2.3.0" + zrender "5.3.0" + electron-to-chromium@^1.4.71: version "1.4.71" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -915,6 +1054,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -992,6 +1136,11 @@ fraction.js@^4.1.2: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1012,6 +1161,20 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1029,6 +1192,11 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1113,6 +1281,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1120,6 +1293,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -1151,11 +1329,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -1170,6 +1353,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -1216,6 +1404,18 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -1274,6 +1474,11 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.2" +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1409,6 +1614,11 @@ microseconds@0.2.0: resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + minimatch@^3.0.4: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1416,11 +1626,21 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.0: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1448,6 +1668,11 @@ nanoid@^3.1.30, nanoid@^3.2.0: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -1476,6 +1701,18 @@ next@12.1.0: "@next/swc-win32-ia32-msvc" "12.1.0" "@next/swc-win32-x64-msvc" "12.1.0" +node-abi@^3.3.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.8.0.tgz#679957dc8e7aa47b0a02589dbfde4f77b29ccb32" + integrity sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw== + dependencies: + semver "^7.3.5" + +node-addon-api@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + node-releases@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" @@ -1491,12 +1728,32 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + numeral@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506" integrity sha1-StCAk21EPCVhrtnyGX7//iX05QY= -object-assign@^4.1.1: +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -1566,7 +1823,7 @@ oblivious-set@1.0.0: resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -1709,12 +1966,37 @@ postcss@^8.4.6: picocolors "^1.0.0" source-map-js "^1.0.2" +prebuild-install@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" + integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prop-types@^15.5.7, prop-types@^15.7.2: + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -1723,6 +2005,14 @@ prop-types@^15.5.7, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.13.1" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -1738,6 +2028,16 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-apexcharts@^1.3.9: version "1.3.9" resolved "https://registry.yarnpkg.com/react-apexcharts/-/react-apexcharts-1.3.9.tgz#d97e53fd513dc6ff73b90c2364c3bdd88d8dad01" @@ -1768,6 +2068,16 @@ react-query@^3.34.15: broadcast-channel "^3.4.1" match-sorter "^6.0.2" +react-transition-group@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" + integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" @@ -1776,6 +2086,28 @@ react@17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" +readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -1847,6 +2179,16 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" @@ -1867,6 +2209,25 @@ semver@^7.3.5: dependencies: lru-cache "^6.0.0" +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +sharp@^0.30.2: + version "0.30.2" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.2.tgz#95b309b2740424702dc19b62a62595dd34a458b1" + integrity sha512-mrMeKI5ECTdYhslPlA2TbBtU3nZXMEBcQwI6qYXjPlu1LpW4HBZLFm6xshMI1HpIdEEJ3UcYp5AKifLT/fEHZQ== + dependencies: + color "^4.2.1" + detect-libc "^2.0.1" + node-addon-api "^4.3.0" + prebuild-install "^7.0.1" + semver "^7.3.5" + simple-get "^4.0.1" + tar-fs "^2.1.1" + tunnel-agent "^0.6.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -1888,6 +2249,37 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0, simple-get@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +size-sensor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/size-sensor/-/size-sensor-1.0.1.tgz#f84e46206d3e259faff1d548e4b3beca93219dbb" + integrity sha512-QTy7MnuugCFXIedXRpUSk9gUnyNiaxIdxGfUjr8xxXOqIB3QvBUYP9+b51oCg2C4dnhaeNk/h57TxjbvoJrJUA== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -1898,6 +2290,24 @@ source-map-js@^1.0.1, source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" @@ -1928,6 +2338,27 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -1945,6 +2376,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + styled-jsx@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" @@ -2051,6 +2487,27 @@ tailwindcss@^3.0.23: quick-lru "^5.1.1" resolve "^1.22.0" +tar-fs@^2.0.0, tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -2073,6 +2530,11 @@ tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" +tslib@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -2085,6 +2547,13 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -2129,7 +2598,7 @@ use-subscription@1.5.1: dependencies: object-assign "^4.1.1" -util-deprecate@^1.0.2: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -2157,6 +2626,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -2181,3 +2657,10 @@ yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +zrender@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.3.0.tgz#297c05dc2521362816c4ddced10a1e306646bbc8" + integrity sha512-Ln2QB5uqI1ftNYMtCRxd+XDq6MOttLgam2tmhKAVA+j0ko47UT+VNlDvKTkqe4K2sJhBvB0EhYNLebqlCTjatQ== + dependencies: + tslib "2.3.0"