feat: lmao so much stuff

This commit is contained in:
Filipe Medeiros 2021-12-01 03:30:59 +00:00
parent 38641f9b8f
commit 070764c408
13 changed files with 327 additions and 140 deletions

View file

@ -50,7 +50,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode",
"svelte.enable-ts-plugin": true,
"workbench.colorTheme": "GitHub Dark Default",
"window.zoomLevel": 1,
"window.zoomLevel": 2,
"redhat.telemetry.enabled": true,
"editor.formatOnPaste": true,
"editor.formatOnSave": true,

View file

@ -8,6 +8,7 @@ import {
ShareIcon,
} from '@heroicons/react/solid'
import clsx from 'clsx'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { FC, useState } from 'react'
@ -55,13 +56,11 @@ const BottomMenu: FC<Props> = ({ className }) => {
)}
>
{pathname !== '/dashboard' && (
<button
disabled={isWelcoming}
className="h-12 p-1 bg-purple-400 rounded shadow-lg hover:bg-purple-400 disabled:hover:bg-purple-400 disabled:cursor-default"
onClick={() => push('/dashboard')}
>
<HomeIcon className="h-full text-purple-50 dark:text-gray-900" />
</button>
<Link href={isWelcoming ? '#' : '/dashboard'}>
<a className="h-12 p-1 bg-purple-400 rounded shadow-lg hover:bg-purple-400 disabled:hover:bg-purple-400 disabled:cursor-default">
<HomeIcon className="h-full text-purple-50 dark:text-gray-900" />
</a>
</Link>
)}
<div>
@ -98,34 +97,36 @@ const BottomMenu: FC<Props> = ({ className }) => {
</button>
)}
<div className="flex h-16">
<button
disabled={isWelcoming}
className={clsx(
'bg-purple-400 px-1 h-16 w-10 hover:bg-purple-400 disabled:hover:bg-purple-400 shadow-md disabled:cursor-default',
leftHanded ? 'rounded-r' : 'rounded-l'
)}
onClick={() => push('/receive/qr')}
>
<LoginIcon
className={
'h-full text-purple-50 dark:text-gray-900 w-full -rotate-child-90'
}
/>
</button>
<div
className={clsx('flex h-16', { 'flex-row-reverse': leftHanded })}
>
<Link href={isWelcoming ? '#' : '/receive/qr'}>
<a
className={clsx(
'bg-purple-400 px-1 h-16 w-10 hover:bg-purple-400 disabled:hover:bg-purple-400 shadow-md disabled:cursor-default',
leftHanded ? 'rounded-r' : 'rounded-l'
)}
>
<LoginIcon
className={
'h-full text-purple-50 dark:text-gray-900 w-full -rotate-child-90'
}
/>
</a>
</Link>
<div className="h-16 p-1 border-t-2 border-b-2 border-purple-400 shadow-lg">
<QrcodeIcon className="h-full text-gray-900 dark:text-purple-100" />
</div>
<button
disabled={isWelcoming}
className={clsx(
'bg-purple-400 px-1 h-16 w-10 rounded-r hover:bg-purple-400 disabled:hover:bg-purple-400 shadow-md disabled:cursor-default',
leftHanded ? 'rounded-l' : 'rounded-r'
)}
onClick={() => push('/send/qr')}
>
<PaperAirplaneIcon className="h-full text-purple-50 dark:text-gray-900 w-full rotate-[30deg] translate-x-1" />
</button>
<Link href={isWelcoming ? '#' : '/send/qr'}>
<a
className={clsx(
'bg-purple-400 px-1 h-16 w-10 hover:bg-purple-400 disabled:hover:bg-purple-400 shadow-md disabled:cursor-default',
leftHanded ? 'rounded-l' : 'rounded-r'
)}
>
<PaperAirplaneIcon className="h-full text-purple-50 dark:text-gray-900 w-full rotate-[30deg] translate-x-1" />
</a>
</Link>
</div>
</div>
</div>

View file

@ -20,7 +20,7 @@ const Layout: FC<Props> = ({ children }) => {
useListenToColorMedia()
return (
<div className="relative flex flex-col w-screen h-screen px-5 pt-4 pb-4 gap-4 dark:text-purple-50 bg-purple-50 dark:bg-gray-900">
<div className="relative flex flex-col w-screen h-screen gap-4 px-5 pt-4 pb-4 dark:text-purple-50 bg-purple-50 dark:bg-gray-900">
<header
className={clsx('flex justify-between items-center', {
'flex-row-reverse': leftHanded,
@ -37,7 +37,7 @@ const Layout: FC<Props> = ({ children }) => {
{pathname !== '/' ? (
<>
<Balance />
<hr className="w-3/4 border-2" />
<hr className="w-1/3 border-2 " />
{children}
<BottomMenu />
</>

View file

@ -3,7 +3,6 @@ import { DownloadIcon, UploadIcon } from '@heroicons/react/solid'
import clsx from 'clsx'
import { FC, useState } from 'react'
import { useCurrentAccount } from '../lib/context/accountContext'
import useAccountHistory from '../lib/hooks/useAccountHistory'
import useAccountReceivable from '../lib/hooks/useAccountReceivable'
import useReceiveNano from '../lib/hooks/useReceiveNano'
@ -55,7 +54,7 @@ const RecentTransactions: FC<Props> = ({ className }) => {
{receivableBlocks.map(receivable => (
<li
key={receivable.hash}
className="flex items-center justify-between px-3 py-3 text-black border-r-4 border-blue-400 rounded shadow bg-purple-50 dark:hover:bg-gray-700 dark:bg-gray-800 dark:text-purple-50 gap-2"
className="flex items-center justify-between px-3 py-3 text-black border-r-4 border-yellow-400 rounded shadow bg-purple-50 dark:hover:bg-gray-700 dark:bg-gray-800 dark:text-purple-50 gap-2"
>
<button
className="contents"
@ -64,7 +63,7 @@ const RecentTransactions: FC<Props> = ({ className }) => {
onBlockReceived(receivable.hash)
}}
>
<ClockIcon className="flex-shrink-0 w-6 text-blue-400" />
<ClockIcon className="flex-shrink-0 w-6 text-yellow-400" />
<div className="overflow-hidden text-left overflow-ellipsis whitespace-nowrap">
{Intl.DateTimeFormat([], {
@ -93,11 +92,11 @@ const RecentTransactions: FC<Props> = ({ className }) => {
</ol>
</section>
)}
{accountHistory !== undefined && accountHistory.history !== '' && (
<section className="flex flex-col flex-1 w-full min-h-0 gap-3">
<h2 className="text-2xl font-semibold text-purple-50">
recent transactions
</h2>
<section className="flex flex-col flex-1 w-full min-h-0 gap-3">
<h2 className="text-2xl font-semibold text-purple-50">
recent transactions
</h2>
{accountHistory !== undefined && accountHistory.history !== '' ? (
<ol className="flex flex-col w-full overflow-auto gap-3">
{accountHistory.history.map(txn => (
<li
@ -140,10 +139,7 @@ const RecentTransactions: FC<Props> = ({ className }) => {
</li>
))}
</ol>
</section>
)}
{!hasReceivable &&
(accountHistory === undefined || accountHistory.history === '') && (
) : (
<div className="pt-8 text-center text-purple-50">
<p className="pb-4">no transactions yet...</p>
<p>
@ -153,6 +149,7 @@ const RecentTransactions: FC<Props> = ({ className }) => {
</p>
</div>
)}
</section>
{false && (
<button
className="px-4 py-2 font-bold bg-purple-200 rounded shadow dark:text-gray-900"

View file

@ -15,8 +15,8 @@ const useDrawQrCode = ({ raw, address }: { raw?: string; address: string }) => {
qr.toCanvas(canvasRef.current, genTxnUrl({ address: address, raw }), {
color: {
light: darkMode ? colors.coolGray['900'] : colors.white,
dark: colors.violet['500'],
light: darkMode ? colors.coolGray['800'] : colors.white,
dark: colors.violet['50'],
},
})
}, [raw, address, canvasRef, darkMode])

13
next.config.mjs Normal file
View file

@ -0,0 +1,13 @@
import withAnalyzer from '@next/bundle-analyzer'
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
compress: true,
}
export default withAnalyzer({
enabled:
process.env.ANALYZE === 'true' && process.env.NODE_ENV !== 'production',
})(nextConfig)

View file

@ -3,7 +3,8 @@
"private": true,
"scripts": {
"dev": "next dev -p 3001",
"build": "next build",
"build": "ANALYZE=true next build",
"build:local": "ANALYZE=true NODE_ENV=development next build",
"export": "next export",
"start": "next start -p 3001",
"test": "echo TODO",
@ -19,6 +20,7 @@
},
"dependencies": {
"@heroicons/react": "^1.0.5",
"@next/bundle-analyzer": "^12.0.4",
"bignumber.js": "^9.0.1",
"cbor": "^8.1.0",
"clsx": "^1.1.1",

View file

@ -1,24 +0,0 @@
import { computeWork } from 'nanocurrency'
import { NextApiHandler } from 'next'
const get: NextApiHandler<string> = async (req, res) => {
if (req.method !== 'GET') {
res.status(405).end()
return
}
const { frontier } = req.query
console.time('computeWork')
const work = await computeWork(frontier as string)
console.timeEnd('computeWork')
if (work === null) {
res.status(500).send(JSON.stringify({ error: "Couldn't compute work" }))
return
}
res.status(200).send(JSON.stringify({ work }))
}
export default get

View file

@ -1,3 +1,4 @@
import { LoginIcon } from '@heroicons/react/outline'
import type { NextPage } from 'next'
import { useAccount } from '../../lib/context/accountContext'
@ -8,12 +9,16 @@ const MyQrCode: NextPage = () => {
const canvasRef = useDrawQrCode({ address: account?.address ?? '' })
return (
<div className="w-full h-full grid gap-6 place-content-center">
<h1 className="text-3xl font-extrabold text-center text-purple-100 dark:text-gray-900">
get scanned!
</h1>
<div className="h-full flex flex-col gap-8">
<span className="flex items-center justify-start gap-2">
<LoginIcon className="-rotate-child-90 dark:text-purple-50 h-7 xs:h-10 text-gray-900 translate-x-1" />
<h1 className="text-3xl sm:text-5xl">receive</h1>
</span>
<canvas className="!w-64 !h-64 rounded-lg shadow-lg" ref={canvasRef} />
<canvas
className="!w-64 !h-64 rounded place-self-center shadow-lg"
ref={canvasRef}
/>
</div>
)
}

View file

@ -1,56 +1,169 @@
import { UploadIcon } from '@heroicons/react/solid'
import { ArrowDownIcon } from '@heroicons/react/outline'
import { PaperAirplaneIcon } from '@heroicons/react/solid'
import Big from 'bignumber.js'
import clsx from 'clsx'
import { Unit, convert } from 'nanocurrency'
import type { NextPage } from 'next'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import useSendNano from '../../lib/hooks/useSendNano'
const Send: NextPage = () => {
const { query, push } = useRouter()
const { address, amount } = query
Big.config({ EXPONENTIAL_AT: 1e9 })
const bigToConvert = new Big(`1${'0'.repeat(30)}`)
const hasAmount = amount !== undefined
const Send: NextPage = () => {
const { query, push, replace, pathname } = useRouter()
const { address, amount } = query as { address?: string; amount?: string }
const [xnoToSend, setXnoToSend] = useState('')
const onXnoAmountChange = useCallback(
(value: string) => {
setXnoToSend(value)
replace({
pathname,
query: {
...query,
amount:
value !== ''
? new Big(value).times(bigToConvert).toString() // since nanocurrency-js can't handle decimals :(
: '',
},
})
},
[replace, pathname, query]
)
const { send } = useSendNano()
const onSend = async () => {
await send(
address as string,
(amount as string) ??
convert(xnoToSend, { from: Unit.Nano, to: Unit.raw })
)
push('/dashboard')
}
const [startX, setStartX] = useState(0)
const [currentX, setCurrentX] = useState(0)
const sliderPercentage = Math.min(
(Math.max(currentX - startX, 0) * 100) / 228 / 100,
1
)
const [sliding, setSliding] = useState(false)
const backToBase = useCallback(() => {
setStartX(0)
setCurrentX(0)
setSliding(false)
}, [setStartX, setCurrentX, setSliding])
useEffect(() => {
if (sliderPercentage === 1) {
const sendNano = async () => {
try {
await send(
address as string,
(amount as string) ??
convert(xnoToSend, { from: Unit.Nano, to: Unit.raw })
)
push('/dashboard')
} catch {
backToBase()
}
}
sendNano()
}
}, [sliderPercentage, push, address, amount, xnoToSend, send, backToBase])
return (
<div>
{hasAmount ? (
<>
<h1>you&apos;re sending</h1>
<h2>
Ӿ {convert(amount as string, { from: Unit.raw, to: Unit.Nano })}
</h2>
<span>to</span>
<h2>{address}</h2>
</>
) : (
<>
<h1>send</h1>
<h2>Ӿ</h2>
<div className="flex flex-col h-full gap-8">
<span className="flex items-center gap-2">
<PaperAirplaneIcon className=" dark:text-purple-50 h-7 xs:h-10 text-gray-900 rotate-[30deg] translate-x-1" />
<h1 className="text-3xl sm:text-5xl">send</h1>
</span>
<form
onSubmit={ev => ev.preventDefault()}
className="flex flex-col gap-3 items-center h-full"
>
<div className="flex items-center gap-3 text-2xl rounded dark:bg-gray-800 py-2 px-4 w-full overflow-hidden dark:focus-within:bg-gray-700">
<label htmlFor="xnoToSend">Ӿ</label>
<input
className="text-gray-900"
name="xno-amount"
id="xno-amount"
maxLength={15}
className="bg-transparent focus:outline-none"
value={xnoToSend}
onChange={({ target: { value } }) => setXnoToSend(value)}
pattern="[0-9]*[\.,]?[0-9]{0,6}"
step="0.000001"
autoComplete="off"
onChange={({ target: { value, validity } }) => {
if (!validity.patternMismatch) onXnoAmountChange(value)
}}
/>
<span>to</span>
<h2>{address}</h2>
</>
)}
<button onClick={onSend}>
send <UploadIcon />
</button>
</div>
<ArrowDownIcon className="h-7" />
<span className="flex-1 text-lg">
<span className="dark:text-purple-400 font-medium">
{address?.substring(0, 10)}
</span>
{address?.substring(10, 21)}
<br />
{address?.substring(21, 42)}
<br />
{address?.substring(42, 56)}
<span className="dark:text-purple-400 font-medium">
{address?.substring(56)}
</span>
</span>
<div
className={clsx(
'dark:bg-gray-800 rounded-full p-2 relative w-72 z-10 transition-opacity',
{
'opacity-50': xnoToSend === '',
}
)}
onMouseMove={ev => {
if (sliding) setCurrentX(ev.clientX)
}}
onMouseUp={() => {
if (sliderPercentage !== 1) backToBase()
}}
onMouseLeave={() => {
if (sliderPercentage !== 1) backToBase()
}}
>
<div
className={clsx(
'dark:bg-purple-50 p-2 rounded-full w-11 z-30 transform-gpu',
{
'transition-transform': !sliding,
}
)}
style={{
transform: `translate3d(${sliderPercentage * 228}px, 0, 0)`,
}}
onTouchStart={ev => {
setSliding(true)
setStartX(ev.touches.item(0).clientX)
}}
onTouchMove={ev => {
if (sliding) setCurrentX(ev.touches.item(0).clientX)
}}
onTouchEnd={() => backToBase()}
onMouseDown={ev => {
setSliding(true)
setStartX(ev.clientX)
}}
>
<PaperAirplaneIcon
className="h-7 dark:text-gray-900 translate-x-0.5"
style={{
transform: `translateX(var(--tw-translate-x)) rotate(${
30 + 60 * sliderPercentage
}deg)`,
}}
/>
</div>
<span
className="absolute text-purple-50 text-2xl left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 select-none"
style={{ opacity: 0.7 - 0.7 * sliderPercentage, zIndex: -10 }}
>
slide to send
</span>
</div>
</form>
</div>
)
}

View file

@ -1,3 +1,4 @@
import { PaperAirplaneIcon } from '@heroicons/react/solid'
import clsx from 'clsx'
import type { NextPage } from 'next'
import { useRouter } from 'next/router'
@ -21,16 +22,17 @@ const ReadQrCode: NextPage = () => {
const { videoLive, videoRef } = useReadQrFromVideo(onQrCodeRead)
return (
<div className="flex flex-col items-center justify-center w-full h-full gap-4">
<h1 className="text-3xl font-semibold text-center text-purple-50">
scan!
</h1>
<div className="flex flex-col h-full gap-8">
<span className="flex items-center gap-2">
<PaperAirplaneIcon className=" dark:text-purple-50 h-7 xs:h-10 text-gray-900 rotate-[30deg] translate-x-1" />
<h1 className="text-3xl sm:text-5xl">send</h1>
</span>
<video
className={clsx('rounded shadow-md', { hidden: !videoLive })}
ref={videoRef}
/>
{!videoLive && (
<div className="w-full h-64 bg-purple-400 rounded animate-pulse"></div>
<div className="w-full h-64 rounded dark:bg-gray-800 animate-pulse"></div>
)}
</div>
)

View file

@ -1,17 +1,28 @@
import type { NextPage } from 'next'
import Link from 'next/link'
import { useRouter } from 'next/router'
const Welcome: NextPage = () => {
const { push } = useRouter()
return (
<div className="flex flex-col justify-center w-full h-full text-center text-purple-50">
<h1 className="mb-3 text-4xl font-bold">hey!</h1>
<p className="mb-2 text-xl font-medium">
do you already have
<br />a <b>nano</b> passphrase
<h1 className="mb-3 text-5xl font-extrabold">hey!</h1>
<p className="mb-3 text-xl font-medium">
do you already have a
<br />
you wanna use?
<b>nano</b> passphrase?
</p>
<div className="flex flex-col justify-center w-full gap-3 mb-6">
<button className="px-5 py-2 text-lg font-bold text-gray-900 transition-all duration-100 rounded shadow-lg bg-purple-50 hover:bg-purple-100 hover:shadow-md active:shadow">
i have a passphrase/seed
</button>
<Link href="/welcome/new">
<a className="px-5 py-2 text-lg font-bold text-gray-900 transition-all duration-100 rounded shadow-lg bg-purple-50 hover:bg-purple-100 hover:shadow-md active:shadow">
what&apos;s a passphrase?
</a>
</Link>
</div>
<aside className="mb-3 text-xs">
your passphrase will{' '}
<b className="font-extrabold">
@ -21,17 +32,6 @@ const Welcome: NextPage = () => {
<br />
and will only be decrypted for a few moments to send nano
</aside>
<div className="flex flex-col justify-center w-full mb-6 gap-3">
<button className="px-5 py-2 text-lg font-bold text-gray-900 rounded shadow-lg dark:bg-gray-900 bg-purple-50 dark:hover:bg-gray-800 hover:shadow-md active:shadow transition-all duration-100 dark:text-purple-50">
i have a passphrase/seed
</button>
<button
className="px-5 py-2 text-lg font-bold text-gray-900 rounded shadow-lg dark:bg-gray-900 bg-purple-50 dark:hover:bg-gray-800 hover:shadow-md active:shadow transition-all duration-100 dark:text-purple-50"
onClick={() => push('/welcome/new')}
>
what&apos;s a passphrase?
</button>
</div>
<p className="text-xs">
<em>
psst: you can already see all the cool buttons below, but they&apos;re

View file

@ -348,6 +348,13 @@
resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c"
integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==
"@next/bundle-analyzer@^12.0.4":
version "12.0.4"
resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-12.0.4.tgz#258141b291f87439362b62684d1e1a9fd5f9ec1b"
integrity sha512-hl9SmruSHMMMjmcUXJYdP12HbencBOpuy4gHPpQLbRmfErUsY7ia+eF5Xt9vAkim7s6HKByoDg7cu6HJQzfpfg==
dependencies:
webpack-bundle-analyzer "4.3.0"
"@next/env@12.0.4":
version "12.0.4"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.4.tgz#effe19526fa51ab2da1a39e594b80a257b3fa1c5"
@ -463,6 +470,11 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@polka/url@^1.0.0-next.20":
version "1.0.0-next.21"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
"@rushstack/eslint-patch@^1.0.6":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
@ -719,6 +731,11 @@ acorn-walk@^7.0.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn-walk@^8.0.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
acorn@8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
@ -729,6 +746,11 @@ acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.0.4:
version "8.6.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
@ -1208,7 +1230,7 @@ chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^4.0.0, chalk@^4.1.1, chalk@^4.1.2:
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -1387,7 +1409,7 @@ colorette@^2.0.16:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
commander@^6.0.0:
commander@^6.0.0, commander@^6.2.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
@ -1711,6 +1733,11 @@ dot-case@^2.1.0:
dependencies:
no-case "^2.2.0"
duplexer@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
ejs@^3.1.3:
version "3.1.6"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a"
@ -2399,6 +2426,13 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
dependencies:
duplexer "^0.1.2"
hard-rejection@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
@ -3109,7 +3143,7 @@ lodash.truncate@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21:
lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -3238,6 +3272,11 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
mime@^2.3.1:
version "2.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@ -3563,6 +3602,11 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
@ -4311,6 +4355,15 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
sirv@^1.0.7:
version "1.0.18"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899"
integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA==
dependencies:
"@polka/url" "^1.0.0-next.20"
mime "^2.3.1"
totalist "^1.0.0"
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@ -4781,6 +4834,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
totalist@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
tr46@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
@ -4985,6 +5043,21 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webpack-bundle-analyzer@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b"
integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA==
dependencies:
acorn "^8.0.4"
acorn-walk "^8.0.0"
chalk "^4.1.0"
commander "^6.2.0"
gzip-size "^6.0.0"
lodash "^4.17.20"
opener "^1.5.2"
sirv "^1.0.7"
ws "^7.3.1"
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
@ -5074,6 +5147,11 @@ write-file-atomic@^3.0.3:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
ws@^7.3.1:
version "7.5.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b"
integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==
xtend@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"