diff --git a/packages/proposal-components/package.json b/packages/proposal-components/package.json
index 8f2748b..bd77afa 100644
--- a/packages/proposal-components/package.json
+++ b/packages/proposal-components/package.json
@@ -7,7 +7,9 @@
"license": "MIT",
"watch": {
"build": {
- "patterns": ["src"],
+ "patterns": [
+ "src"
+ ],
"extensions": "ts,tsx",
"runOnChangeOnly": false
}
@@ -30,17 +32,21 @@
"lint:prettier": "yarn prettier './{src,test}/**/*.{ts,tsx}'"
},
"dependencies": {
+ "@status-waku-voting/core": "^0.1.0",
"@status-waku-voting/proposal-hooks": "^0.1.0",
"@status-waku-voting/react-components": "^0.1.0",
- "@status-waku-voting/core": "^0.1.0",
"ethers": "^5.4.4",
+ "humanize-duration": "^3.27.0",
"react": "^17.0.2",
+ "react-countup": "^5.2.0",
"styled-components": "^5.3.0"
},
"devDependencies": {
"@types/chai": "^4.2.21",
+ "@types/humanize-duration": "^3.25.1",
"@types/mocha": "^9.0.0",
"@types/react": "^17.0.16",
+ "@types/react-countup": "^4.3.1",
"@types/styled-components": "^5.1.12",
"@typescript-eslint/eslint-plugin": "^4.29.0",
"@typescript-eslint/parser": "^4.29.0",
diff --git a/packages/proposal-components/src/assets/assets.d.ts b/packages/proposal-components/src/assets/assets.d.ts
new file mode 100644
index 0000000..4ce4da1
--- /dev/null
+++ b/packages/proposal-components/src/assets/assets.d.ts
@@ -0,0 +1,14 @@
+declare module '*.svg' {
+ const url: string
+ export default url
+}
+
+declare module '*.jpg' {
+ const url: string
+ export default url
+}
+
+declare module '*.png' {
+ const url: string
+ export default url
+}
diff --git a/packages/proposal-components/src/assets/svg/check.svg b/packages/proposal-components/src/assets/svg/check.svg
new file mode 100644
index 0000000..a8589b9
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/check.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/assets/svg/checkWinner.svg b/packages/proposal-components/src/assets/svg/checkWinner.svg
new file mode 100644
index 0000000..f3200ec
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/checkWinner.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/assets/svg/cross.svg b/packages/proposal-components/src/assets/svg/cross.svg
new file mode 100644
index 0000000..728a295
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/cross.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/assets/svg/crossWinner.svg b/packages/proposal-components/src/assets/svg/crossWinner.svg
new file mode 100644
index 0000000..62aa890
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/crossWinner.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/assets/svg/external.svg b/packages/proposal-components/src/assets/svg/external.svg
new file mode 100644
index 0000000..260fa58
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/external.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/assets/svg/indicator.svg b/packages/proposal-components/src/assets/svg/indicator.svg
new file mode 100644
index 0000000..bb2ece7
--- /dev/null
+++ b/packages/proposal-components/src/assets/svg/indicator.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/proposal-components/src/components/Buttons.tsx b/packages/proposal-components/src/components/Buttons.tsx
new file mode 100644
index 0000000..a9e99e8
--- /dev/null
+++ b/packages/proposal-components/src/components/Buttons.tsx
@@ -0,0 +1,92 @@
+import { Button } from '@status-waku-voting/react-components'
+import styled from 'styled-components'
+
+export const Btn = styled(Button)`
+ padding: 11px 0;
+ font-weight: 500;
+ line-height: 22px;
+ text-align: center;
+`
+
+export const VoteBtn = styled(Btn)`
+ width: 44%;
+ padding: 11px 0;
+ font-weight: 500;
+ line-height: 22px;
+ text-align: center;
+
+ &:disabled {
+ background: #f3f3f3;
+ color: #939ba1;
+ }
+
+ @media (max-width: 768px) {
+ width: 48%;
+ }
+`
+
+export const VoteBtnAgainst = styled(VoteBtn)`
+ background-color: #ffeded;
+ color: #c90a0a;
+
+ &:not(:disabled):hover {
+ background: #ffdada;
+ }
+
+ &:not(:disabled):active {
+ background: #fff5f5;
+ }
+`
+export const VoteBtnFor = styled(VoteBtn)`
+ background-color: #edfff4;
+ color: #1d920a;
+
+ &:not(:disabled):hover {
+ background: #ccfee0;
+ }
+
+ &:not(:disabled):active {
+ background: #F3FFF8;
+`
+export const VoteSendingBtn = styled(Btn)`
+ margin-top: 24px;
+ padding: 0;
+ color: #0f3595;
+ height: auto;
+ background: transparent;
+
+ &:hover {
+ color: #5d7be2;
+ }
+
+ &:active {
+ color: #0f3595;
+ }
+
+ &:disabled {
+ color: #676868;
+ }
+`
+
+export const FinalBtn = styled(Btn)`
+ width: 100%;
+ background: #edf1ff;
+ color: #0f3595;
+
+ &:not(:disabled):hover {
+ background: #dbeeff;
+ }
+
+ &:not(:disabled):active {
+ background: #f7f9ff;
+ }
+
+ &:disabled {
+ background: #f3f3f3;
+ color: #939ba1;
+ }
+
+ @media (max-width: 600px) {
+ margin-top: 32px;
+ }
+`
diff --git a/packages/proposal-components/src/components/Proposal.tsx b/packages/proposal-components/src/components/Proposal.tsx
index 79dd730..e394a76 100644
--- a/packages/proposal-components/src/components/Proposal.tsx
+++ b/packages/proposal-components/src/components/Proposal.tsx
@@ -2,11 +2,13 @@ import React from 'react'
import styled from 'styled-components'
import { ProposalHeader } from './ProposalHeader'
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
+import { ProposalList } from './ProposalList'
export function Proposal() {
return (
+
)
}
diff --git a/packages/proposal-components/src/components/ProposalCard.tsx b/packages/proposal-components/src/components/ProposalCard.tsx
new file mode 100644
index 0000000..c2eaa58
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalCard.tsx
@@ -0,0 +1,40 @@
+import React from 'react'
+import styled from 'styled-components'
+import { ProposalInfo } from './ProposalInfo'
+import { ProposalVote } from './ProposalVoteCard/ProposalVote'
+
+export function ProposalCard() {
+ return (
+
+
+
+
+ )
+}
+
+export const Card = styled.div`
+ display: flex;
+ align-items: stretch;
+ margin-top: 24px;
+
+ @media (max-width: 768px) {
+ flex-direction: column;
+ margin-top: 0;
+ padding: 16px 0 32px;
+ border-bottom: 1px solid #e0e0e0;
+ }
+ @media (max-width: 600px) {
+ padding-bottom: 16px;
+ }
+ &:not:first-child {
+ @media (max-width: 768px) {
+ border-top: 1px solid #e0e0e0;
+ }
+ }
+`
diff --git a/packages/proposal-components/src/components/ProposalInfo.tsx b/packages/proposal-components/src/components/ProposalInfo.tsx
new file mode 100644
index 0000000..2c2737a
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalInfo.tsx
@@ -0,0 +1,54 @@
+import React from 'react'
+import styled from 'styled-components'
+import { ViewLink } from './ViewLink'
+
+type ProposalInfoProps = {
+ heading: string
+ text: string
+ address: string
+}
+
+export function ProposalInfo({ heading, text, address }: ProposalInfoProps) {
+ return (
+
+ {heading}
+ {text}
+
+
+ )
+}
+
+export const Card = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 50%;
+ padding: 24px;
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
+ border-radius: 6px 0px 0px 6px;
+
+ @media (max-width: 768px) {
+ width: 100%;
+ margin: 0;
+ border: none;
+ box-shadow: none;
+ padding-bottom: 0;
+ }
+ @media (max-width: 600px) {
+ padding: 0;
+ }
+`
+
+const CardHeading = styled.div`
+ height: 56px;
+ font-weight: bold;
+ font-size: 22px;
+ line-height: 24px;
+ margin-bottom: 8px;
+`
+
+const CardText = styled.div`
+ font-size: 13px;
+ line-height: 18px;
+ margin-bottom: 16px;
+`
diff --git a/packages/proposal-components/src/components/ProposalList.tsx b/packages/proposal-components/src/components/ProposalList.tsx
new file mode 100644
index 0000000..612fb15
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalList.tsx
@@ -0,0 +1,6 @@
+import React from 'react'
+import { ProposalCard } from './ProposalCard'
+
+export function ProposalList() {
+ return
+}
diff --git a/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx b/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx
new file mode 100644
index 0000000..ce4f68b
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx
@@ -0,0 +1,86 @@
+import React, { useState } from 'react'
+import styled from 'styled-components'
+import { useEthers } from '@usedapp/core'
+import { FinalBtn, VoteBtnAgainst, VoteBtnFor } from '../Buttons'
+import { VoteSubmitButton } from './VoteSubmitButton'
+import { VoteChart } from './VoteChart'
+
+interface ProposalVoteProps {
+ vote: number
+ voteWinner?: number
+ hideModalFunction?: (val: boolean) => void
+}
+
+export function ProposalVote({ vote, voteWinner, hideModalFunction }: ProposalVoteProps) {
+ const { account } = useEthers()
+ const [showVoteModal, setShowVoteModal] = useState(false)
+
+ return (
+
+ {voteWinner ? Proposal {voteWinner == 1 ? 'rejected' : 'passed'} : }
+
+
+
+ {voteWinner ? (
+ Finalize the vote
+ ) : (
+
+ Vote Against
+ Vote For
+
+ )}
+
+ {vote && }
+
+ )
+}
+
+export const Card = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 50%;
+ padding: 24px;
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
+ border-radius: 6px 0px 0px 6px;
+ background-color: #fbfcfe;
+
+ @media (max-width: 768px) {
+ width: 100%;
+ box-shadow: none;
+ border-radius: unset;
+ background-color: unset;
+ padding-bottom: 0;
+ }
+
+ @media (max-width: 600px) {
+ flex-direction: column;
+ padding: 16px 0 0;
+ border-bottom: none;
+ }
+`
+
+export const CardHeading = styled.h2`
+ height: 24px;
+ font-weight: bold;
+ font-size: 17px;
+ line-height: 24px;
+ margin: 0;
+ margin-bottom: 15px;
+`
+
+export const VotesBtns = styled.div`
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+
+ @media (max-width: 600px) {
+ margin-top: 24px;
+ }
+`
+
+const CardVoteBottom = styled.div`
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+`
diff --git a/packages/proposal-components/src/components/ProposalVoteCard/VoteChart.tsx b/packages/proposal-components/src/components/ProposalVoteCard/VoteChart.tsx
new file mode 100644
index 0000000..ff8cbe2
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalVoteCard/VoteChart.tsx
@@ -0,0 +1,215 @@
+import React, { useEffect, useState } from 'react'
+import CountUp from 'react-countup'
+import styled from 'styled-components'
+import { addCommas } from '../../helpers/addCommas'
+import { formatTimeLeft } from '../../helpers/fomatTimeLeft'
+import { VoteGraphBar } from './VoteGraphBar'
+import crossIcon from '../../assets/svg/cross.svg'
+import crossWinnerIcon from '../../assets/svg/crossWinner.svg'
+import checkIcon from '../../assets/svg/check.svg'
+import checkWinnerIcon from '../../assets/svg/checkWinner.svg'
+
+export interface VoteChartProps {
+ votesFor: number
+ votesAgainst: number
+ timeLeft: number
+ voteWinner?: number
+ proposingAmount?: number
+ selectedVote?: number
+ isAnimation?: boolean
+ tabletMode?: (val: boolean) => void
+}
+
+export function VoteChart({
+ votesFor,
+ votesAgainst,
+ timeLeft,
+ voteWinner,
+ proposingAmount,
+ selectedVote,
+ isAnimation,
+ tabletMode,
+}: VoteChartProps) {
+ const [mobileVersion, setMobileVersion] = useState(false)
+
+ useEffect(() => {
+ const handleResize = () => {
+ if (window.innerWidth < 600) {
+ setMobileVersion(true)
+ } else {
+ setMobileVersion(false)
+ }
+ }
+ handleResize()
+ window.addEventListener('resize', handleResize)
+ return () => window.removeEventListener('resize', handleResize)
+ }, [])
+
+ const voteSum = votesFor + votesAgainst
+ const graphWidth = (100 * votesAgainst) / voteSum
+
+ let balanceWidth = graphWidth
+
+ if (proposingAmount && selectedVote) {
+ balanceWidth =
+ selectedVote === 0
+ ? (100 * (votesAgainst + proposingAmount)) / (voteSum + proposingAmount)
+ : (100 * votesAgainst) / (voteSum + proposingAmount)
+ }
+
+ return (
+
+
+
+
+
+ {' '}
+ {isAnimation && proposingAmount && selectedVote && selectedVote === 0 ? (
+
+ ) : (
+ addCommas(votesAgainst)
+ )}{' '}
+ ABC
+
+
+ {formatTimeLeft(timeLeft)}
+
+
+
+ {' '}
+ {isAnimation && proposingAmount && selectedVote && selectedVote === 1 ? (
+
+ ) : (
+ addCommas(votesFor)
+ )}{' '}
+ ABC
+
+
+
+
+
+ {formatTimeLeft(timeLeft)}
+
+
+ )
+}
+
+const Votes = styled.div`
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 32px;
+ width: 100%;
+ position: relative;
+
+ @media (max-width: 600px) {
+ margin-bottom: 0;
+ }
+`
+const VotesChart = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: stretch;
+ position: relative;
+ margin-bottom: 13px;
+
+ &.notModal {
+ @media (max-width: 768px) {
+ margin-bottom: 0;
+ }
+ }
+`
+
+const VoteBox = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-content: center;
+ font-size: 12px;
+ text-align: center;
+ font-weight: normal;
+
+ & > span {
+ font-weight: bold;
+ }
+
+ @media (max-width: 768px) {
+ min-width: 70px;
+ }
+
+ @media (max-width: 600px) {
+ min-width: unset;
+ }
+`
+const VoteIcon = styled.img`
+ margin-bottom: 13px;
+`
+const TimeLeft = styled.div`
+ position: absolute;
+ top: 50%;
+ left: calc(50%);
+ transform: translateX(-50%);
+ font-size: 12px;
+ line-height: 16px;
+ letter-spacing: 0.1px;
+ color: #939ba1;
+
+ &.notModal {
+ @media (max-width: 768px) {
+ top: -16px;
+ }
+
+ @media (max-width: 600px) {
+ top: unset;
+ }
+ }
+`
+
+const TimeLeftMobile = styled.div`
+ position: absolute;
+ bottom: -23px;
+ left: calc(50%);
+ transform: translateX(-50%);
+ font-size: 0;
+ line-height: 16px;
+ letter-spacing: 0.1px;
+ color: #939ba1;
+
+ @media (max-width: 600px) {
+ font-size: 12px;
+ }
+`
+
+const VoteGraphBarWrap = styled.div`
+ position: static;
+ display: flex;
+ justify-content: center;
+
+ &.notModal {
+ @media (max-width: 768px) {
+ position: absolute;
+ width: 65%;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ @media (max-width: 600px) {
+ width: 70%;
+ }
+ }
+`
diff --git a/packages/proposal-components/src/components/ProposalVoteCard/VoteGraphBar.tsx b/packages/proposal-components/src/components/ProposalVoteCard/VoteGraphBar.tsx
new file mode 100644
index 0000000..f3d7cc9
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalVoteCard/VoteGraphBar.tsx
@@ -0,0 +1,112 @@
+import React, { useEffect, useState } from 'react'
+import styled from 'styled-components'
+import indicatorIcon from '../../assets/svg/indicator.svg'
+
+function createKeyFrames(votesWidth: number, markerWidth: number) {
+ return `
+ @keyframes fade-in {
+ 0% {
+ width: ${votesWidth}%;
+ }
+ 100% {
+ width: ${markerWidth}%;
+ }
+ }
+ `
+}
+export interface VoteGraphBarProps {
+ balanceWidth?: number
+ graphWidth?: number
+ voteWinner?: number
+ isAnimation?: boolean
+}
+
+export function VoteGraphBar({ graphWidth, balanceWidth, voteWinner, isAnimation }: VoteGraphBarProps) {
+ const markerWidth: number = balanceWidth ? balanceWidth : 0
+ const votesWidth: number = graphWidth ? graphWidth : 0
+ const [keyFrames, setKeyFrames] = useState('')
+ const [style, setStyle] = useState({ width: `${votesWidth}%` })
+
+ useEffect(() => {
+ if (isAnimation) {
+ setStyle({ width: `${markerWidth}%`, animation: 'fade-in 2s ease' })
+ setKeyFrames(createKeyFrames(votesWidth, markerWidth))
+ } else {
+ setStyle({ width: `${votesWidth}%` })
+ }
+ }, [isAnimation, votesWidth])
+
+ return (
+
+
+
+
+
+ )
+}
+
+const VoteGraph = styled.div`
+ position: relative;
+ width: 100%;
+ height: 16px;
+ background-color: ${({ theme }) => (theme.voteWinner === 1 ? '#f1f2f5' : '#edfff4')};
+ border-radius: 10px;
+ padding-top: 5px;
+ border-left: 13px solid ${({ theme }) => (theme.voteWinner === 2 ? '#f1f2f5' : '#ffeded')};
+ border-right: 13px solid ${({ theme }) => (theme.voteWinner === 1 ? '#f1f2f5' : '#edfff4')};
+
+ @media (max-width: 600px) {
+ height: 13px;
+ }
+
+ &::before {
+ content: '';
+ width: 16px;
+ height: 5px;
+ position: absolute;
+ top: -6px;
+ left: calc(50% - 2px);
+ transform: translateX(-50%);
+ background-image: url(${indicatorIcon});
+ background-size: cover;
+
+ @media (max-width: 768px) {
+ width: 9px;
+ height: 3px;
+ left: 50%;
+ }
+
+ @media (max-width: 768px) {
+ top: -4px;
+ }
+ }
+`
+
+const VoteGraphAgainst = styled.div`
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 16px;
+ background-color: ${({ theme }) => (theme.voteWinner === 2 ? '#f1f2f5' : '#ffeded')};
+ transition: width 2s;
+ z-index: 2;
+
+ @media (max-width: 600px) {
+ height: 13px;
+ }
+`
+
+const VoteBalance = styled.div`
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 16px;
+ background-color: transparent;
+ border-right: 2px solid #7e98f4;
+ z-index: 2;
+
+ @media (max-width: 600px) {
+ height: 13px;
+ transition: width 2s;
+ }
+`
diff --git a/packages/proposal-components/src/components/ProposalVoteCard/VoteSubmitButton.tsx b/packages/proposal-components/src/components/ProposalVoteCard/VoteSubmitButton.tsx
new file mode 100644
index 0000000..16d3e4b
--- /dev/null
+++ b/packages/proposal-components/src/components/ProposalVoteCard/VoteSubmitButton.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import { addCommas } from '../../helpers/addCommas'
+import { VoteSendingBtn } from '../Buttons'
+
+interface VoteSubmitButtonProps {
+ votes: number
+ disabled: boolean
+}
+
+export function VoteSubmitButton({ votes, disabled }: VoteSubmitButtonProps) {
+ if (votes > 0) {
+ return {addCommas(votes)} votes need saving
+ }
+ return null
+}
diff --git a/packages/proposal-components/src/components/ViewLink.tsx b/packages/proposal-components/src/components/ViewLink.tsx
new file mode 100644
index 0000000..49d83eb
--- /dev/null
+++ b/packages/proposal-components/src/components/ViewLink.tsx
@@ -0,0 +1,40 @@
+import React from 'react'
+import styled from 'styled-components'
+import externalIcon from '../assets/svg/external.svg'
+
+interface ViewLinkProps {
+ address: string
+}
+
+export function ViewLink({ address }: ViewLinkProps) {
+ return View on Etherscan
+}
+
+export const Link = styled.a`
+ color: #4360df;
+ position: relative;
+ padding-right: 20px;
+ font-size: 15px;
+ line-height: 22px;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+
+ &:active {
+ text-decoration: none;
+ }
+
+ &::after {
+ content: '';
+ width: 16px;
+ height: 16px;
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ background-image: url(${externalIcon});
+ background-size: contain;
+ }
+`
diff --git a/packages/proposal-components/src/helpers/addCommas.ts b/packages/proposal-components/src/helpers/addCommas.ts
new file mode 100644
index 0000000..807c799
--- /dev/null
+++ b/packages/proposal-components/src/helpers/addCommas.ts
@@ -0,0 +1,3 @@
+export function addCommas(votes: number) {
+ return votes.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
+}
diff --git a/packages/proposal-components/src/helpers/fomatTimeLeft.ts b/packages/proposal-components/src/helpers/fomatTimeLeft.ts
new file mode 100644
index 0000000..79b0476
--- /dev/null
+++ b/packages/proposal-components/src/helpers/fomatTimeLeft.ts
@@ -0,0 +1,5 @@
+import timeConvert from 'humanize-duration'
+
+export function formatTimeLeft(timeLeft: number) {
+ return timeLeft > 0 ? timeConvert(timeLeft, { largest: 1, round: true }) + ' left' : 'Vote ended'
+}
diff --git a/yarn.lock b/yarn.lock
index a2c30e5..c129e7e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1174,6 +1174,11 @@
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57"
integrity sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==
+"@types/humanize-duration@^3.25.1":
+ version "3.25.1"
+ resolved "https://registry.yarnpkg.com/@types/humanize-duration/-/humanize-duration-3.25.1.tgz#b6140d5fc00ff3917b3f521784abef4bc0387ccc"
+ integrity sha512-WZU/4bb+lvzyDmZzjJtp++9mfKy6B3lH6gGISgkcz6SU8hMILKRM0vi08TxIsb0dQB4Gzo68MWLmctu6xqUi9g==
+
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
@@ -1271,6 +1276,13 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
+"@types/react-countup@^4.3.1":
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/@types/react-countup/-/react-countup-4.3.1.tgz#5bba8e11c18549c92f9a6efe07e406c92c970f89"
+ integrity sha512-8KwOdVVKhMOdtXJoOg3YXZwWxnFnZtPojNs/DZRlhHTpOYIb1If+9+rVPnwnXDhNhphj5diUCds9E26VtVK8IA==
+ dependencies:
+ react-countup "*"
+
"@types/react-dom@>=16.9.0", "@types/react-dom@^17.0.9":
version "17.0.9"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add"
@@ -3659,6 +3671,11 @@ cosmiconfig@^6.0.0:
path-type "^4.0.0"
yaml "^1.7.2"
+countup.js@^2.0.8:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/countup.js/-/countup.js-2.0.8.tgz#eca0c31c9db3f7769cba494d9315cd52dbaaf1b9"
+ integrity sha512-pW3xwwD+hB+xmtI16xFcuLS0D5hSQqPQWkZOdgpKQyzxCquDNo2VCFPkRw12vmvdpnicXVTcjmYiakG6biwINg==
+
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@@ -6294,6 +6311,11 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+humanize-duration@^3.27.0:
+ version "3.27.0"
+ resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.27.0.tgz#3f781b7cf8022ad587f76b9839b60bc2b29636b2"
+ integrity sha512-qLo/08cNc3Tb0uD7jK0jAcU5cnqCM0n568918E7R2XhMr/+7F37p4EY062W/stg7tmzvknNn9b/1+UhVRzsYrQ==
+
iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -9845,6 +9867,13 @@ rc@^1.2.8:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-countup@*, react-countup@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/react-countup/-/react-countup-5.2.0.tgz#58be5d97acebf767d5c61df5c3a3417b95c45a16"
+ integrity sha512-R6+FIrW8ypwoAe0Q0CZ16OhrgAntnnnch7HrnRAy9miXFKk8jQzVADjNtGSoNUuJeq/ZFiiXCGJCJIAmRJ5fLg==
+ dependencies:
+ countup.js "^2.0.8"
+
react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"