add platform stats and use next font

This commit is contained in:
saml33 2023-11-17 13:53:56 +11:00
parent bd36d90f2c
commit 9d70eac464
25 changed files with 328 additions and 95 deletions

View File

@ -0,0 +1,27 @@
import Tooltip from '../shared/Tooltip'
const HeroStat = ({
title,
tooltipContent,
value,
}: {
title: string
tooltipContent?: string
value: string
}) => {
return (
<div className="col-span-4 sm:col-span-2 lg:col-span-1">
<Tooltip
content={tooltipContent ? tooltipContent : ''}
placement="top-start"
>
<p className="lg:text-lg mb-1">{title}</p>
</Tooltip>
<p className="text-4xl md:text-5xl font-display tracking-tight text-th-fgd-1">
{value}
</p>
</div>
)
}
export default HeroStat

View File

@ -16,9 +16,11 @@ import { useLayoutEffect, useMemo, useRef, useState } from 'react'
import { MotionPathPlugin } from 'gsap/dist/MotionPathPlugin'
import ColorBlur from '../shared/ColorBlur'
import Ottersec from '../icons/Ottersec'
import { MarketData } from '../../types'
import { AppStatsData, MarketData } from '../../types'
import TabsText from '../shared/TabsText'
import MarketCard from './MarketCard'
import { formatNumericValue, numberCompacter } from '../../utils'
import HeroStat from './HeroStat'
gsap.registerPlugin(MotionPathPlugin)
gsap.registerPlugin(ScrollTrigger)
@ -44,9 +46,11 @@ const MOBILE_IMAGE_CLASSES =
const HomePage = ({
perpData,
spotData,
appData,
}: {
perpData: MarketData
spotData: MarketData
appData: AppStatsData
}) => {
const { t } = useTranslation(['common', 'home'])
const [activeMarketTab, setActiveMarketTab] = useState('spot')
@ -67,6 +71,47 @@ const HomePage = ({
return tabs
}, [perpData, spotData])
const formattedSpotData = useMemo(() => {
if (!spotData || !Object.keys(spotData)?.length) return []
const data = Object.entries(spotData)
.sort((a, b) => b[1][0].quote_volume_24h - a[1][0].quote_volume_24h)
.map(([key, value]) => {
const data = value[0]
return { name: key, data }
})
return data
}, [spotData])
const formattedPerpData = useMemo(() => {
if (!perpData || !Object.keys(perpData)?.length) return []
const data = Object.entries(perpData)
.sort((a, b) => b[1][0].quote_volume_24h - a[1][0].quote_volume_24h)
.map(([key, value]) => {
const data = value[0]
return { name: key, data }
})
return data
}, [perpData])
const formattedAppStatsData = useMemo(() => {
if (!appData || !Object.keys(appData).length) return
// volume
const spotVol24h = appData?.openbook_volume_usd_24h || 0
const perpVol24h = appData?.perp_volume_usd_24h || 0
const swapVol24h = appData?.swap_volume_usd_24h || 0
const totalVol24h = spotVol24h + perpVol24h + swapVol24h
// number of trades
const spotTrades24h = appData?.num_openbook_fills_24h || 0
const perpTrades24h = appData?.num_perp_fills_24h || 0
const swapTrades24h = appData?.num_swaps_24h || 0
const totalTrades24h = spotTrades24h + perpTrades24h + swapTrades24h
const weeklyActiveTraders = appData?.weekly_active_mango_accounts || 0
return { totalVol24h, totalTrades24h, weeklyActiveTraders }
}, [appData])
useLayoutEffect(() => {
const ctx = gsap.context((self) => {
const boxes = self.selector('.highlight-features')
@ -216,7 +261,38 @@ const HomePage = ({
</div>
</div>
</SectionWrapper>
<SectionWrapper>
<div className="bg-[url('/images/new/cube-bg.png')] bg-repeat py-12 lg:py-16">
<SectionWrapper noPaddingY>
<div className="grid grid-cols-4 gap-6">
<HeroStat
title={t('markets')}
value={(
formattedSpotData.length + formattedPerpData.length
).toString()}
/>
<HeroStat
title={t('home:active-traders')}
tooltipContent={t('home:tooltip-active-traders')}
value={formatNumericValue(
formattedAppStatsData.weeklyActiveTraders
)}
/>
<HeroStat
title={t('home:daily-volume')}
tooltipContent={t('home:tooltip-daily-volume')}
value={`$${numberCompacter.format(
formattedAppStatsData.totalVol24h
)}`}
/>
<HeroStat
title={t('home:daily-trades')}
tooltipContent={t('home:tooltip-daily-trades')}
value={formatNumericValue(formattedAppStatsData.totalTrades24h)}
/>
</div>
</SectionWrapper>
</div>
<SectionWrapper className="mt-10 md:mt-0">
<div
className="grid grid-cols-6 gap-4 md:gap-6 xl:gap-8"
ref={callouts}
@ -269,10 +345,7 @@ const HomePage = ({
/>
</div>
</SectionWrapper>
{spotData &&
Object.keys(spotData).length &&
perpData &&
Object.keys(perpData).length ? (
{formattedSpotData.length && formattedPerpData.length ? (
<SectionWrapper className="border-t border-th-bkg-3">
<div className="w-full h-full">
<h2 className="mb-4 text-center">{t('markets')}</h2>
@ -289,24 +362,12 @@ const HomePage = ({
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 max-h-[580px] overflow-auto thin-scroll">
{activeMarketTab === 'spot'
? Object.entries(spotData)
.sort(
(a, b) =>
b[1][0].quote_volume_24h - a[1][0].quote_volume_24h
)
.map(([key, value]) => {
const data = value[0]
return <MarketCard name={key} data={data} key={key} />
})
: Object.entries(perpData)
.sort(
(a, b) =>
b[1][0].quote_volume_24h - a[1][0].quote_volume_24h
)
.map(([key, value]) => {
const data = value[0]
return <MarketCard name={key} data={data} key={key} />
})}
? formattedSpotData.map((data) => (
<MarketCard marketData={data} key={data.name} />
))
: formattedPerpData.map((data) => (
<MarketCard marketData={data} key={data.name} />
))}
</div>
</div>
</SectionWrapper>

View File

@ -6,20 +6,21 @@ import SimpleAreaChart from '../shared/SimpleAreaChart'
import { useTranslation } from 'react-i18next'
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/20/solid'
const MarketCard = ({
name,
data,
}: {
type MarketCardData = {
name: string
data: MarketsDataItem
}) => {
}
const MarketCard = ({ marketData }: { marketData: MarketCardData }) => {
const { t } = useTranslation('common')
const { last_price, price_24h, price_history, quote_volume_24h } = data
const { name, data } = marketData
const isSpot = name.includes('/')
const baseSymbol = isSpot ? name.split('/')[0] : name.split('-')[0]
const quoteSymbol = isSpot ? name.split('/')[1] : 'USDC'
const change =
last_price && price_24h ? ((last_price - price_24h) / last_price) * 100 : 0
data?.last_price && data?.price_24h
? ((data.last_price - data.price_24h) / data.last_price) * 100
: 0
return (
<div className="p-4 rounded-lg border border-th-bkg-3">
<div className="flex items-start justify-between">
@ -36,10 +37,10 @@ const MarketCard = ({
<div>
<p className="text-th-fgd-4">{name}</p>
<p className="text-th-fgd-1 font-bold">
{last_price ? (
{data?.last_price ? (
<span>
{quoteSymbol === 'USDC' ? '$' : ''}
{formatNumericValue(last_price)}{' '}
{formatNumericValue(data.last_price)}{' '}
{quoteSymbol !== 'USDC' ? (
<span className="text-th-fgd-4 font-normal">
{quoteSymbol}
@ -54,12 +55,12 @@ const MarketCard = ({
<Change change={change} suffix="%" />
<span className="text-th-fgd-4">|</span>
<p className="whitespace-nowrap">
{quote_volume_24h ? (
{data?.quote_volume_24h ? (
<span>
{quoteSymbol === 'USDC' ? '$' : ''}
{isNaN(quote_volume_24h)
{isNaN(data.quote_volume_24h)
? '0.00'
: numberCompacter.format(quote_volume_24h)}{' '}
: numberCompacter.format(data.quote_volume_24h)}{' '}
{quoteSymbol !== 'USDC' ? (
<span className="text-th-fgd-4 font-normal">
{quoteSymbol}
@ -73,16 +74,18 @@ const MarketCard = ({
</div>
</div>
</div>
{price_history && price_history.length ? (
{data?.price_history && data?.price_history.length ? (
<div className="h-12 w-20">
<SimpleAreaChart
color={
price_history[0].price <=
price_history[price_history.length - 1]?.price
data.price_history[0].price <=
data.price_history[data.price_history.length - 1]?.price
? 'var(--up)'
: 'var(--down)'
}
data={price_history.sort((a, b) => a.time.localeCompare(b.time))}
data={data.price_history.sort((a, b) =>
a.time.localeCompare(b.time)
)}
name={name}
xKey="time"
yKey="price"

View File

@ -1,7 +1,7 @@
import { ReactNode, useEffect, useState } from 'react'
import Footer from '../footer/Footer'
import TopNavigation from '../navigation/TopNavigation'
// import ColorBlur from '../shared/ColorBlur'
import { ttCommons, ttCommonsExpanded, ttCommonsMono } from '../../utils/fonts'
const LayoutWrapper = ({ children }: { children: ReactNode }) => {
const [mounted, setMounted] = useState(false)
@ -15,16 +15,13 @@ const LayoutWrapper = ({ children }: { children: ReactNode }) => {
}
return (
<div className="bg-th-bkg-1">
<main
className={`bg-th-bkg-1 ${ttCommons.variable} ${ttCommonsExpanded.variable} ${ttCommonsMono.variable} font-sans`}
>
<TopNavigation />
{/* <ColorBlur
className="left-0 top-0 animate-blob"
height="25%"
width="50%"
/> */}
<div>{children}</div>
<Footer />
</div>
</main>
)
}

View File

@ -0,0 +1,70 @@
import React, { HTMLAttributes, ReactNode } from 'react'
import Tippy, { TippyProps } from '@tippyjs/react'
import 'tippy.js/animations/scale.css'
import { ttCommons } from '../../utils/fonts'
type TooltipProps = {
content: ReactNode
placement?: TippyProps['placement']
className?: string
children?: ReactNode
delay?: number
show?: boolean
maxWidth?: string
}
const Tooltip = ({
children,
content,
className,
placement = 'top',
delay = 0,
show = true,
maxWidth = '20rem',
}: TooltipProps) => {
if (show) {
return (
<Tippy
animation="scale"
placement={placement}
appendTo={() => document.body}
maxWidth={maxWidth}
interactive
delay={[delay, 0]}
content={
content ? (
<div
className={`${ttCommons.variable} font-sans rounded-md bg-th-bkg-2 p-3 font-body text-sm tracking-wide text-th-fgd-3 outline-none focus:outline-none ${className}`}
style={{ boxShadow: '0px 0px 8px 0px rgba(0,0,0,0.25)' }}
>
{content}
</div>
) : null
}
>
<div className="outline-none focus:outline-none">{children}</div>
</Tippy>
)
} else {
return <>{children}</>
}
}
const Content = ({
className,
children,
}: {
className?: string
} & HTMLAttributes<HTMLDivElement>) => {
return (
<div
className={`inline-block cursor-help border-b border-dashed border-th-fgd-3 border-opacity-20 hover:border-th-bkg-2 ${className}`}
>
{children}
</div>
)
}
Tooltip.Content = Content
export default Tooltip

Binary file not shown.

Binary file not shown.

View File

@ -23,6 +23,7 @@
"dependencies": {
"@headlessui/react": "^1.0.0",
"@heroicons/react": "^2.0.16",
"@tippyjs/react": "^4.2.6",
"decimal.js": "^10.4.3",
"gsap": "^3.11.5",
"i18next": "^22.4.10",

View File

@ -8,17 +8,19 @@ export async function getStaticProps({ locale }: { locale: string }) {
const promises = [
fetch(`${MANGO_DATA_API_URL}/stats/perp-market-summary`),
fetch(`${MANGO_DATA_API_URL}/stats/spot-market-summary`),
fetch(`${MANGO_DATA_API_URL}/stats/mango-protocol-summary`),
]
try {
const data = await Promise.all(promises)
const perpData = await data[0].json()
const spotData = await data[1].json()
const appData = await data[2].json()
return {
props: {
perpData,
spotData,
appData,
...(await serverSideTranslations(locale, [
'common',
'home',
@ -31,8 +33,9 @@ export async function getStaticProps({ locale }: { locale: string }) {
console.error('Failed to fetch market data', e)
return {
props: {
perpData: null, // or an empty array []
spotData: null, // or an empty array []
perpData: null,
spotData: null,
appData: null,
...(await serverSideTranslations(locale, [
'common',
'home',
@ -47,8 +50,9 @@ export async function getStaticProps({ locale }: { locale: string }) {
const Index: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
perpData,
spotData,
appData,
}) => {
return <HomePage perpData={perpData} spotData={spotData} />
return <HomePage perpData={perpData} spotData={spotData} appData={appData} />
}
export default Index

View File

@ -1,4 +1,5 @@
{
"active-traders": "Active Traders",
"borrow-desc": "All tokens on Mango can be borrowed for use in other DeFi activities. Plus, all deposits earn interest without unlock periods.",
"borrow-heading": "Borrow and earn interest",
"build-desc": "Mango is 100% open source and highly composable. Build trading bots, new product integrations, community tools or whatever you desire. Explore the code and get building.",
@ -9,6 +10,8 @@
"competitive-fees-desc": "Low fees for taker trades and rebates for maker trades. Plus, Solana's extremely low transaction costs.",
"cross-margin": "Cross-margin accounts",
"cross-margin-desc": "Leverage across all your positions. Open multiple accounts to isolate your risk.",
"daily-trades": "24h Trades",
"daily-volume": "24h Volume",
"deeply-liquid": "Deeply liquid markets",
"deeply-liquid-desc": "Get the best price with access to all of the liquidity on Solana.",
"explore-the-code": "Explore the code",
@ -28,6 +31,9 @@
"swap-now": "Swap Now",
"token-listings-desc": "Anyone can easily list any token on Mango. A governance proposal is created upon submission and if successful the token will list automatically.",
"token-listings-heading": "Permissionless token listings",
"tooltip-active-traders": "Weekly active Mango Accounts",
"tooltip-daily-trades": "Number of trades across spot, swap and perp",
"tooltip-daily-volume": "Volume across spot, swap and perp",
"trade-your-way": "Trade your way",
"trade-your-way-desc": "Leverage swap or orderbook maxi? Mango is optimized for all devices so you can trade how you want, when you want."
}

View File

@ -1,4 +1,5 @@
{
"active-traders": "Active Traders",
"borrow-desc": "All tokens on Mango can be borrowed for use in other DeFi activities. Plus, all deposits earn interest without unlock periods.",
"borrow-heading": "Borrow and earn interest",
"build-desc": "Mango is 100% open source and highly composable. Build trading bots, new product integrations, community tools or whatever you desire. Explore the code and get building.",
@ -9,6 +10,8 @@
"competitive-fees-desc": "Low fees for taker trades and rebates for maker trades. Plus, Solana's extremely low transaction costs.",
"cross-margin": "Cross-margin accounts",
"cross-margin-desc": "Leverage across all your positions. Open multiple accounts to isolate your risk.",
"daily-trades": "24h Trades",
"daily-volume": "24h Volume",
"deeply-liquid": "Deeply liquid markets",
"deeply-liquid-desc": "Get the best price with access to all of the liquidity on Solana.",
"explore-the-code": "Explore the code",
@ -28,6 +31,9 @@
"swap-now": "Swap Now",
"token-listings-desc": "Anyone can easily list any token on Mango. A governance proposal is created upon submission and if successful the token will list automatically.",
"token-listings-heading": "Permissionless token listings",
"tooltip-active-traders": "Weekly active Mango Accounts",
"tooltip-daily-trades": "Number of trades across spot, swap and perp",
"tooltip-daily-volume": "Volume across spot, swap and perp",
"trade-your-way": "Trade your way",
"trade-your-way-desc": "Leverage swap or orderbook maxi? Mango is optimized for all devices so you can trade how you want, when you want."
}

View File

@ -1,4 +1,5 @@
{
"active-traders": "Active Traders",
"borrow-desc": "All tokens on Mango can be borrowed for use in other DeFi activities. Plus, all deposits earn interest without unlock periods.",
"borrow-heading": "Borrow and earn interest",
"build-desc": "Mango is 100% open source and highly composable. Build trading bots, new product integrations, community tools or whatever you desire. Explore the code and get building.",
@ -9,6 +10,8 @@
"competitive-fees-desc": "Low fees for taker trades and rebates for maker trades. Plus, Solana's extremely low transaction costs.",
"cross-margin": "Cross-margin accounts",
"cross-margin-desc": "Leverage across all your positions. Open multiple accounts to isolate your risk.",
"daily-trades": "24h Trades",
"daily-volume": "24h Volume",
"deeply-liquid": "Deeply liquid markets",
"deeply-liquid-desc": "Get the best price with access to all of the liquidity on Solana.",
"explore-the-code": "Explore the code",
@ -28,6 +31,9 @@
"swap-now": "Swap Now",
"token-listings-desc": "Anyone can easily list any token on Mango. A governance proposal is created upon submission and if successful the token will list automatically.",
"token-listings-heading": "Permissionless token listings",
"tooltip-active-traders": "Weekly active Mango Accounts",
"tooltip-daily-trades": "Number of trades across spot, swap and perp",
"tooltip-daily-volume": "Volume across spot, swap and perp",
"trade-your-way": "Trade your way",
"trade-your-way-desc": "Leverage swap or orderbook maxi? Mango is optimized for all devices so you can trade how you want, when you want."
}

View File

@ -1,4 +1,5 @@
{
"active-traders": "Active Traders",
"borrow-desc": "All tokens on Mango can be borrowed for use in other DeFi activities. Plus, all deposits earn interest without unlock periods.",
"borrow-heading": "Borrow and earn interest",
"build-desc": "Mango is 100% open source and highly composable. Build trading bots, new product integrations, community tools or whatever you desire. Explore the code and get building.",
@ -9,6 +10,8 @@
"competitive-fees-desc": "Low fees for taker trades and rebates for maker trades. Plus, Solana's extremely low transaction costs.",
"cross-margin": "Cross-margin accounts",
"cross-margin-desc": "Leverage across all your positions. Open multiple accounts to isolate your risk.",
"daily-trades": "24h Trades",
"daily-volume": "24h Volume",
"deeply-liquid": "Deeply liquid markets",
"deeply-liquid-desc": "Get the best price with access to all of the liquidity on Solana.",
"explore-the-code": "Explore the code",
@ -28,6 +31,9 @@
"swap-now": "Swap Now",
"token-listings-desc": "Anyone can easily list any token on Mango. A governance proposal is created upon submission and if successful the token will list automatically.",
"token-listings-heading": "Permissionless token listings",
"tooltip-active-traders": "Weekly active Mango Accounts",
"tooltip-daily-trades": "Number of trades across spot, swap and perp",
"tooltip-daily-volume": "Volume across spot, swap and perp",
"trade-your-way": "Trade your way",
"trade-your-way-desc": "Leverage swap or orderbook maxi? Mango is optimized for all devices so you can trade how you want, when you want."
}

View File

@ -1,4 +1,5 @@
{
"active-traders": "Active Traders",
"borrow-desc": "All tokens on Mango can be borrowed for use in other DeFi activities. Plus, all deposits earn interest without unlock periods.",
"borrow-heading": "Borrow and earn interest",
"build-desc": "Mango is 100% open source and highly composable. Build trading bots, new product integrations, community tools or whatever you desire. Explore the code and get building.",
@ -9,6 +10,8 @@
"competitive-fees-desc": "Low fees for taker trades and rebates for maker trades. Plus, Solana's extremely low transaction costs.",
"cross-margin": "Cross-margin accounts",
"cross-margin-desc": "Leverage across all your positions. Open multiple accounts to isolate your risk.",
"daily-trades": "24h Trades",
"daily-volume": "24h Volume",
"deeply-liquid": "Deeply liquid markets",
"deeply-liquid-desc": "Get the best price with access to all of the liquidity on Solana.",
"explore-the-code": "Explore the code",
@ -28,6 +31,9 @@
"swap-now": "Swap Now",
"token-listings-desc": "Anyone can easily list any token on Mango. A governance proposal is created upon submission and if successful the token will list automatically.",
"token-listings-heading": "Permissionless token listings",
"tooltip-active-traders": "Weekly active Mango Accounts",
"tooltip-daily-trades": "Number of trades across spot, swap and perp",
"tooltip-daily-volume": "Volume across spot, swap and perp",
"trade-your-way": "Trade your way",
"trade-your-way-desc": "Leverage swap or orderbook maxi? Mango is optimized for all devices so you can trade how you want, when you want."
}

View File

@ -2,34 +2,6 @@
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'TT Mono';
src: url('/fonts/TT_Commons_Pro_Mono_Regular.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons Expanded';
src: url('/fonts/TT_Commons_Pro_Expanded_DemiBold.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: normal;
src: url('/fonts/TT_Commons_Pro_Regular.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: medium;
src: url('/fonts/TT_Commons_Pro_Medium.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: bold;
src: url('/fonts/TT_Commons_Pro_DemiBold.woff2') format('woff2');
}
/* Reset */
html,
@ -164,6 +136,12 @@ th {
body {
@apply font-body text-sm;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
main {
@apply font-body;
}
button {

View File

@ -5,9 +5,9 @@ module.exports = {
],
theme: {
fontFamily: {
display: ['TT Commons Expanded, sans-serif'],
body: 'TT Commons, sans-serif',
mono: ['TT Mono, mono'],
display: ['var(--font-display)'],
body: ['var(--font-body)'],
mono: ['var(--font-mono)'],
},
extend: {
height: {

View File

@ -1,16 +1,27 @@
export type MarketData = { [key: string]: MarketsDataItem[] }
export type MarketsDataItem = {
base_volume_1h: number
base_volume_24h: number
change_1h: number
change_7d: number
change_24h: number
change_30d: number
last_price: number
price_1h: number
price_24h: number
price_history: { price: number; time: string }[]
quote_volume_1h: number
quote_volume_24h: number
base_volume_1h: number | undefined
base_volume_24h: number | undefined
change_1h: number | undefined
change_7d: number | undefined
change_24h: number | undefined
change_30d: number | undefined
last_price: number | undefined
price_1h: number | undefined
price_24h: number | undefined
price_history: { price: number; time: string }[] | undefined
quote_volume_1h: number | undefined
quote_volume_24h: number | undefined
}
export type AppStatsData = {
weekly_active_mango_accounts: number
perp_volume_usd_24h: number
num_perp_fills_24h: number
swap_volume_usd_24h: number
num_swaps_24h: number
openbook_volume_usd_24h: number
num_openbook_fills_24h: number
open_interest: number
}

32
utils/fonts.ts Normal file
View File

@ -0,0 +1,32 @@
import localFont from 'next/font/local'
export const ttCommonsMono = localFont({
src: '../fonts/TT_Commons_Pro_Mono_Medium.woff2',
variable: '--font-mono',
})
export const ttCommons = localFont({
src: [
{
path: '../fonts/TT_Commons_Pro_Normal.woff2',
weight: '500',
style: 'normal',
},
{
path: '../fonts/TT_Commons_Pro_Medium.woff2',
weight: '600',
style: 'medium',
},
{
path: '../fonts/TT_Commons_Pro_DemiBold.woff2',
weight: '700',
style: 'bold',
},
],
variable: '--font-body',
})
export const ttCommonsExpanded = localFont({
src: '../fonts/TT_Commons_Pro_Expanded_DemiBold.woff2',
variable: '--font-display',
})

View File

@ -701,6 +701,11 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@popperjs/core@^2.9.0":
version "2.11.8"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
"@sinonjs/commons@^1.7.0":
version "1.8.6"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
@ -744,6 +749,13 @@
"@babel/runtime" "^7.12.5"
"@testing-library/dom" "^7.28.1"
"@tippyjs/react@^4.2.6":
version "4.2.6"
resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.6.tgz#971677a599bf663f20bb1c60a62b9555b749cc71"
integrity sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw==
dependencies:
tippy.js "^6.3.1"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@ -6044,6 +6056,13 @@ tiny-invariant@^1.3.1:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
tippy.js@^6.3.1:
version "6.3.7"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
dependencies:
"@popperjs/core" "^2.9.0"
tmp@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"