react-use#useMedia JavaScript Examples
The following examples show how to use
react-use#useMedia.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AllTokensPage.js From pancake-info-v1 with GNU General Public License v3.0 | 6 votes |
function AllTokensPage() {
const allTokens = useAllTokenData()
useEffect(() => {
window.scrollTo(0, 0)
}, [])
const below600 = useMedia('(max-width: 800px)')
return (
<PageWrapper>
<FullWrapper>
<RowBetween>
<TYPE.largeHeader>Top Tokens</TYPE.largeHeader>
{!below600 && <Search small={true} />}
</RowBetween>
<Panel style={{ marginTop: '6px', padding: below600 && '1rem 0 0 0 ' }}>
<TopTokenList tokens={allTokens} itemMax={50} />
</Panel>
</FullWrapper>
</PageWrapper>
)
}
Example #2
Source File: sidebar-context.js From NextBook with MIT License | 6 votes |
export function SideBarContextProvider(props) {
const isWide = useMedia('(min-width: 1024px)', false)
const [storedSideBar, setStoredSideBar] = useLocalStorage(
'sideBar',
isWide ? true : false
)
const [sideBar, setSideBar] = useState(storedSideBar)
function toggleSideBar() {
setStoredSideBar(!sideBar)
setSideBar((currentValue) => {
return !currentValue
})
}
function hideSideBar() {
setStoredSideBar(false)
setSideBar(false)
}
const context = {
sideBar: sideBar,
toggleSideBar: toggleSideBar,
hideSideBar: hideSideBar
}
return (
<SideBarContext.Provider value={context}>
{props.children}
</SideBarContext.Provider>
)
}
Example #3
Source File: AllTokensPage.js From spooky-info with GNU General Public License v3.0 | 6 votes |
// import CheckBox from '../components/Checkbox'
// import QuestionHelper from '../components/QuestionHelper'
function AllTokensPage() {
const allTokens = useAllTokenData()
useEffect(() => {
window.scrollTo(0, 0)
}, [])
const below600 = useMedia('(max-width: 800px)')
// const [useTracked, setUseTracked] = useState(true)
return (
<PageWrapper>
<FullWrapper>
<RowBetween>
<TYPE.largeHeader>Top Tokens</TYPE.largeHeader>
{!below600 && <Search small={true} />}
</RowBetween>
{/* <AutoRow gap="4px">
<CheckBox checked={useTracked} setChecked={() => setUseTracked(!useTracked)} text={'Hide untracked tokens'} />
<QuestionHelper text="USD amounts may be inaccurate in low liquidity pairs or pairs without ETH or stablecoins." />
</AutoRow> */}
<Panel style={{ marginTop: '6px', padding: below600 && '1rem 0 0 0 ' }}>
<TopTokenList tokens={allTokens} itemMax={50} />
</Panel>
</FullWrapper>
</PageWrapper>
)
}
Example #4
Source File: index.js From pancake-info-v1 with GNU General Public License v3.0 | 5 votes |
export default function GlobalStats() {
const below1295 = useMedia('(max-width: 1295px)')
const below1180 = useMedia('(max-width: 1180px)')
const below1024 = useMedia('(max-width: 1024px)')
const below400 = useMedia('(max-width: 400px)')
const below816 = useMedia('(max-width: 816px)')
const [, setShowPriceCard] = useState(false)
const { oneDayVolumeUSD, oneDayTxns, pairCount } = useGlobalData()
const [ethPrice] = useEthPrice()
const formattedEthPrice = ethPrice ? formattedNum(ethPrice, true) : '-'
const oneDayFees = oneDayVolumeUSD ? formattedNum(oneDayVolumeUSD * 0.002, true) : ''
return (
<Header>
<RowBetween style={{ padding: below816 ? '0.5rem' : '.5rem' }}>
<RowFixed>
{!below400 && (
<TYPE.main
mr={'1rem'}
onMouseEnter={() => {
setShowPriceCard(true)
}}
onMouseLeave={() => {
setShowPriceCard(false)
}}
style={{ position: 'relative' }}
>
BNB Price: <Medium>{formattedEthPrice}</Medium>
</TYPE.main>
)}
{!below1180 && (
<TYPE.main mr={'1rem'}>
Transactions (24H): <Medium>{localNumber(oneDayTxns)}</Medium>
</TYPE.main>
)}
{!below1024 && (
<TYPE.main mr={'1rem'}>
Pairs: <Medium>{localNumber(pairCount)}</Medium>
</TYPE.main>
)}
{!below1295 && (
<TYPE.main mr={'1rem'}>
Fees (24H): <Medium>{oneDayFees}</Medium>
</TYPE.main>
)}
</RowFixed>
</RowBetween>
</Header>
)
}
Example #5
Source File: index.js From botble-graphql-next with MIT License | 5 votes |
Home = () => {
const isWide = useMedia('(min-width: 1024px)', true);
return (
<Layout>
<Head />
<div className="bg-gray-200 py-3 sm:py-6 md:py-10">
<div className="container container-fluid px-2 lg:px-0">
<FeaturedListing />
</div>
</div>
<div className="py-3 sm:py-6 md:py-10">
<div className="container container-fluid px-2 lg:px-0">
<div className="flex">
<NewestListing />
{isWide && (
<div className="ml-6">
<RecentListing />
</div>
)}
</div>
</div>
</div>
<div className="bg-gray-200 py-3 sm:py-6 md:py-10">
<div className="container container-fluid px-2 lg:px-0">
<div className="flex">
<BestForYouListing />
{isWide && (
<div className="ml-6">
<Sidebar />
</div>
)}
</div>
</div>
</div>
<div className="py-3 sm:py-6 md:py-10">
<div className="container container-fluid px-2 lg:px-0">
<h3 className="underline-title underline-title-xl text-xl text-gray-700">
Thư viện ảnh
</h3>
<Gallery />
</div>
</div>
</Layout>
);
}
Example #6
Source File: sidebar.jsx From NextBook with MIT License | 5 votes |
function SideBar() {
const { toc, projectTitle } = config
const sideBarCtx = useContext(SideBarContext)
const isWide = useMedia('(min-width: 770px)', false)
const ref = useRef(null)
useEffect(() => {
if (isWide) {
sideBarCtx.hideSideBar()
}
}, [isWide, sideBarCtx])
useClickAway(ref, () => {
if (!isWide) {
sideBarCtx.hideSideBar()
}
})
const sideBarStyle = sideBarCtx.sideBar
? 'sidebar w-2/3 z-50 h-screen bg-gray-100 dark:bg-gray-800 border-r border-gray-300 dark:border-gray-800 fixed pl-4 text-lg top-10 md:hidden'
: 'sidebar z-50 flex-none md:w-56 xl:w-64 h-screen fixed top-10 md:top-14 hidden md:block'
return (
<aside className={sideBarStyle} ref={ref}>
<div className='w-full pb-40 md:pb-16 h-full overflow-y-auto px-1'>
<div className='flex flex-col md:mt-10'>
<Link href='/'>
<a aria-label={projectTitle}>
<div className='flex flex-col items-center'>
{process.env.NEXT_PUBLIC_USE_LOGO && (
<img
src={`/${process.env.NEXT_PUBLIC_USE_LOGO}`}
alt={projectTitle}
className='w-24 hidden md:inline-block'
/>
)}
<span
className='hidden px-4 text-center md:inline-block font-semibold '
title={projectTitle}
>
{projectTitle}
</span>
</div>
</a>
</Link>
<div className='mt-6 pl-2 leading-loose tracking-wide'>
{toc.map((toc, id) => (
<SideBarSection toc={toc} key={id} />
))}
</div>
</div>
</div>
</aside>
)
}
Example #7
Source File: index.js From spooky-info with GNU General Public License v3.0 | 5 votes |
export default function GlobalStats() {
const below1295 = useMedia('(max-width: 1295px)')
const below1180 = useMedia('(max-width: 1180px)')
const below1024 = useMedia('(max-width: 1024px)')
const below400 = useMedia('(max-width: 400px)')
const below816 = useMedia('(max-width: 816px)')
const [showPriceCard, setShowPriceCard] = useState(false)
const { oneDayVolumeUSD, oneDayTxns, pairCount } = useGlobalData()
const [ethPrice] = useEthPrice()
const formattedEthPrice = ethPrice ? formattedNum(ethPrice, true) : '-'
const oneDayFees = oneDayVolumeUSD ? formattedNum(oneDayVolumeUSD * 0.002, true) : ''
return (
<Header>
<RowBetween style={{ padding: below816 ? '0.5rem' : '.5rem' }}>
<RowFixed>
{!below400 && (
<TYPE.main
mr={'1rem'}
onMouseEnter={() => {
setShowPriceCard(true)
}}
onMouseLeave={() => {
setShowPriceCard(false)
}}
style={{ position: 'relative' }}
>
FTM Price: <Medium>{formattedEthPrice}</Medium>
{showPriceCard && <UniPrice />}
</TYPE.main>
)}
{!below1180 && (
<TYPE.main mr={'1rem'}>
Transactions (24H): <Medium>{localNumber(oneDayTxns)}</Medium>
</TYPE.main>
)}
{!below1024 && (
<TYPE.main mr={'1rem'}>
Pairs: <Medium>{localNumber(pairCount)}</Medium>
</TYPE.main>
)}
{!below1295 && (
<TYPE.main mr={'1rem'}>
Fees (24H): <Medium>{oneDayFees}</Medium>
</TYPE.main>
)}
</RowFixed>
</RowBetween>
</Header>
)
}
Example #8
Source File: index.js From pancake-info-v1 with GNU General Public License v3.0 | 5 votes |
export default function Warning({ type, show, setShow, address }) {
const below800 = useMedia('(max-width: 800px)')
const textContent = below800 ? (
<div>
<Text fontWeight={500} lineHeight={'145.23%'} mt={'10px'}>
Anyone can create and name any BEP20 token on BSC, including creating fake versions of existing tokens and
tokens that claim to represent projects that do not have a token.
</Text>
<Text fontWeight={500} lineHeight={'145.23%'} mt={'10px'}>
Similar to BscScan, this site automatically tracks analytics for all BEP20 tokens independent of token
integrity. Please do your own research before interacting with any BEP20 token.
</Text>
</div>
) : (
<Text fontWeight={500} lineHeight={'145.23%'} mt={'10px'}>
Anyone can create and name any BEP20 token on BSC, including creating fake versions of existing tokens and tokens
that claim to represent projects that do not have a token. Similar to BscScan, this site automatically tracks
analytics for all BEP20 tokens independent of token integrity. Please do your own research before interacting with
any BEP20 token.
</Text>
)
return (
<WarningWrapper show={show}>
<AutoColumn gap="4px">
<RowFixed>
<StyledWarningIcon />
<Text fontWeight={600} lineHeight={'145.23%'} ml={'10px'}>
Token Safety Alert
</Text>
</RowFixed>
{textContent}
{below800 ? (
<div>
<Hover style={{ marginTop: '10px' }}>
<Link
fontWeight={500}
lineHeight={'145.23%'}
color={'#2172E5'}
href={'https://bscscan.com/address/' + address}
target="_blank"
>
View {type === 'token' ? 'token' : 'pair'} contract on BscScan
</Link>
</Hover>
<RowBetween style={{ marginTop: '20px' }}>
<div />
<ButtonDark color={'#f82d3a'} style={{ minWidth: '140px' }} onClick={() => setShow(false)}>
I understand
</ButtonDark>
</RowBetween>
</div>
) : (
<RowBetween style={{ marginTop: '10px' }}>
<Hover>
<Link
fontWeight={500}
lineHeight={'145.23%'}
color={'#2172E5'}
href={'https://bscscan.com/address/' + address}
target="_blank"
>
View {type === 'token' ? 'token' : 'pair'} contract on BscScan
</Link>
</Hover>
<ButtonDark color={'#f82d3a'} style={{ minWidth: '140px' }} onClick={() => setShow(false)}>
I understand
</ButtonDark>
</RowBetween>
)}
</AutoColumn>
</WarningWrapper>
)
}
Example #9
Source File: index.js From spooky-info with GNU General Public License v3.0 | 5 votes |
export default function Title() {
const history = useHistory()
const below1080 = useMedia('(max-width: 1080px)')
return (
<TitleWrapper>
<Flex alignItems="center" style={{ justifyContent: 'space-between' }}>
<RowFixed>
<UniIcon id="link" onClick={() => history.push('/')}>
<img width={!below1080 ? '160px' : '80px'} src={Logo} alt="logo" />
</UniIcon>
</RowFixed>
{below1080 && (
<RowFixed style={{ alignItems: 'flex-end' }}>
<BasicLink to="/home">
<Option activeText={history.location.pathname === '/home' ?? undefined}>Overview</Option>
</BasicLink>
<BasicLink to="/tokens">
<Option
activeText={
(history.location.pathname.split('/')[1] === 'tokens' ||
history.location.pathname.split('/')[1] === 'token') ??
undefined
}
>
Tokens
</Option>
</BasicLink>
<BasicLink to="/pairs">
<Option
activeText={
(history.location.pathname.split('/')[1] === 'pairs' ||
history.location.pathname.split('/')[1] === 'pair') ??
undefined
}
>
Pairs
</Option>
</BasicLink>
</RowFixed>
)}
</Flex>
</TitleWrapper>
)
}
Example #10
Source File: index.js From pancake-info-v1 with GNU General Public License v3.0 | 4 votes |
function MiningPositionList({ miningPositions }) {
// const below500 = useMedia('(max-width: 500px)')
const below740 = useMedia('(max-width: 740px)')
// pagination
const [page, setPage] = useState(1)
const [maxPage, setMaxPage] = useState(1)
const ITEMS_PER_PAGE = 10
// sorting
const [sortDirection, setSortDirection] = useState(true)
const [sortedColumn, setSortedColumn] = useState(SORT_FIELD.VALUE)
useEffect(() => {
setMaxPage(1) // edit this to do modular
setPage(1)
}, [miningPositions])
useEffect(() => {
if (miningPositions) {
let extraPages = 1
if (miningPositions.length % ITEMS_PER_PAGE === 0) {
extraPages = 0
}
setMaxPage(Math.floor(miningPositions.length / ITEMS_PER_PAGE) + extraPages || 1)
}
}, [miningPositions])
const ListItem = ({ miningPosition, index }) => {
const pairPercentage = miningPosition.balance / miningPosition.pairData.totalSupply
const valueUSD = miningPosition.pairData.reserveUSD
const valueFirstPair = miningPosition.pairData.reserve0
const valueSecondPair = miningPosition.pairData.reserve1
const firstPairName = miningPosition.miningPool.pair.token0
const secondPairName = miningPosition.miningPool.pair.token1
const pairAddress = miningPosition.miningPool.pair.id
const firstPairAddress = miningPosition.pairData.token0.id
const secondPairAddress = miningPosition.pairData.token1.id
return (
<DashGrid style={{ opacity: pairPercentage > 0 ? 1 : 0.6 }} focus={true}>
{!below740 && <DataText area="number">{index}</DataText>}
<DataText area="name" justifyContent="flex-start" alignItems="flex-start">
<AutoColumn gap="8px" justify="flex-start" align="flex-start">
<DoubleTokenLogo size={16} a0={firstPairAddress} a1={secondPairAddress} margin={!below740} />
</AutoColumn>
<AutoColumn gap="8px" justify="flex-start" style={{ marginLeft: '20px' }}>
<CustomLink to={'/pair/' + pairAddress}>
<TYPE.main style={{ whiteSpace: 'nowrap' }} to={'/pair/'}>
<FormattedName text={firstPairName + '-' + secondPairName} maxCharacters={below740 ? 10 : 18} />
</TYPE.main>
</CustomLink>
<RowFixed gap="8px" justify="flex-start">
<Link external href={getUniswapAppLink(firstPairAddress)} style={{ marginRight: '.5rem' }}>
<ButtonLight style={{ padding: '4px 6px', borderRadius: '4px' }}>Stake More</ButtonLight>
</Link>
{pairPercentage > 0 && (
<Link external href={getUniswapAppLink(firstPairAddress)}>
<ButtonLight style={{ padding: '4px 6px', borderRadius: '4px' }}>Withdraw</ButtonLight>
</Link>
)}
</RowFixed>
</AutoColumn>
</DataText>
<DataText area="uniswap">
<AutoColumn gap="12px" justify="flex-end">
<TYPE.main>{formattedNum(pairPercentage * valueUSD, true, true)}</TYPE.main>
<AutoColumn gap="4px" justify="flex-end">
<RowFixed>
<TYPE.small fontWeight={400}>{formattedNum(pairPercentage * parseFloat(valueFirstPair))} </TYPE.small>
<FormattedName
text={firstPairName}
maxCharacters={below740 ? 10 : 18}
margin={true}
fontSize={'11px'}
/>
</RowFixed>
<RowFixed>
<TYPE.small fontWeight={400}>{formattedNum(pairPercentage * parseFloat(valueSecondPair))} </TYPE.small>
<FormattedName
text={secondPairName}
maxCharacters={below740 ? 10 : 18}
margin={true}
fontSize={'11px'}
/>
</RowFixed>
</AutoColumn>
</AutoColumn>
</DataText>
</DashGrid>
)
}
const miningPositionsSorted =
miningPositions &&
miningPositions
.sort((p0, p1) => {
if (sortedColumn === SORT_FIELD.VALUE) {
const bal0 = (p0.balance / p0.pairData?.totalSupply) * p0.pairData?.reserveUSD
const bal1 = (p0.balance / p0.pairData?.totalSupply) * p1.pairData?.reserveUSD
return bal0 > bal1 ? (sortDirection ? -1 : 1) : sortDirection ? 1 : -1
}
return 1
})
.slice(ITEMS_PER_PAGE * (page - 1), page * ITEMS_PER_PAGE)
.map((miningPosition, index) => {
return (
<div key={index}>
<ListItem key={index} index={(page - 1) * ITEMS_PER_PAGE + index + 1} miningPosition={miningPosition} />
<Divider />
</div>
)
})
return (
<ListWrapper>
<DashGrid center={true} style={{ height: '32px', padding: 0 }}>
{!below740 && (
<Flex alignItems="flex-start" justifyContent="flexStart">
<TYPE.main area="number">#</TYPE.main>
</Flex>
)}
<Flex alignItems="flex-start" justifyContent="flex-start">
<TYPE.main area="number">Name</TYPE.main>{' '}
</Flex>
<Flex alignItems="center" justifyContent="flexEnd">
<ClickableText
area="uniswap"
onClick={(e) => {
setSortedColumn(SORT_FIELD.VALUE)
setSortDirection(sortedColumn !== SORT_FIELD.VALUE ? true : !sortDirection)
}}
>
{below740 ? 'Value' : 'Liquidity'} {sortedColumn === SORT_FIELD.VALUE ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
</DashGrid>
<Divider />
<List p={0}>{!miningPositionsSorted ? <LocalLoader /> : miningPositionsSorted}</List>
<PageButtons>
<div onClick={() => setPage(page === 1 ? page : page - 1)}>
<Arrow faded={page === 1}>←</Arrow>
</div>
<TYPE.body>{'Page ' + page + ' of ' + maxPage}</TYPE.body>
<div onClick={() => setPage(page === maxPage ? page : page + 1)}>
<Arrow faded={page === maxPage}>→</Arrow>
</div>
</PageButtons>
</ListWrapper>
)
}
Example #11
Source File: index.js From spooky-info with GNU General Public License v3.0 | 4 votes |
Chart = ({ data, chartOption, currencyUnit, symbol }) => {
const [chartData, setChartData] = useState([])
useEffect(() => {
setChartData([])
setChartData(data)
}, [data, chartOption, currencyUnit])
const isMobile = useMedia('(max-width: 40em)')
if (chartOption === 'price' && chartData && data) {
return (
<ChartWrapper>
<ResponsiveContainer aspect={isMobile ? 60 / 22 : 60 / 12}>
<AreaChart margin={{ top: 0, right: 0, bottom: 6, left: 10 }} barCategoryGap={1} data={chartData}>
<CartesianGrid stroke="#f5f5f5" />
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
tickMargin={14}
minTickGap={80}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="dayString"
/>
<YAxis
hide={isMobile}
type="number"
tickMargin={16}
orientation="left"
tickFormatter={(tick) => toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={2}
/>
<YAxis
hide={true}
type="number"
tickMargin={16}
orientation="left"
tickFormatter={(tick) => toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={3}
/>
<Area
strokeWidth={2}
dot={false}
type="monotone"
name={currencyUnit === 'ETH' ? 'Price (ETH/' + symbol + ')' : 'Price (USD/' + symbol + ')'}
dataKey={currencyUnit === 'ETH' ? 'ethPerToken' : 'tokenPriceUSD'}
yAxisId={2}
fill="var(--c-token)"
opacity={'0.4'}
stroke="var(--c-token)"
/>
<Area
strokeWidth={2}
dot={false}
type="monotone"
name={currencyUnit === 'USD' ? 'Inverse (' + symbol + '/USD)' : 'Inverse (' + symbol + '/ETH)'}
dataKey={currencyUnit === 'USD' ? 'tokensPerUSD' : 'tokensPerEth'}
yAxisId={3}
fill="var(--c-token)"
opacity={'0'}
stroke="var(--c-token)"
/>
<Tooltip
cursor={true}
formatter={(val) => toK(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: 'var(--c-zircon)',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
</AreaChart>
</ResponsiveContainer>
</ChartWrapper>
)
}
if (chartOption !== 'volume' && chartData && data) {
return (
<ChartWrapper>
<ResponsiveContainer aspect={isMobile ? 60 / 22 : 60 / 12}>
<AreaChart margin={{ top: 0, right: 0, bottom: 6, left: 10 }} barCategoryGap={1} data={chartData}>
<CartesianGrid stroke="#f5f5f5" />
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
tickMargin={14}
minTickGap={80}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="dayString"
/>
<YAxis
hide={isMobile}
type="number"
tickMargin={16}
orientation="left"
tickFormatter={(tick) => toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
/>
<YAxis
hide={true}
type="number"
tickMargin={16}
orientation="right"
tickFormatter={(tick) => toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={1}
/>
<Tooltip
cursor={true}
formatter={(val) => toK(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: 'var(--c-zircon)',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Area
strokeWidth={2}
dot={false}
type="monotone"
name={'Total Liquidity' + (currencyUnit === 'USD' ? ' (USD)' : ' (ETH)')}
dataKey={currencyUnit === 'USD' ? 'usdLiquidity' : 'ethLiquidity'}
yAxisId={0}
fill="var(--c-token)"
opacity={'0.4'}
stroke="var(--c-token)"
/>
<Area
type="monotone"
name={'Eth Balance'}
dataKey={'ethBalance'}
fill="var(--c-token)"
opacity={'0'}
stroke="var(--c-token)"
/>
<Area
type="monotone"
name={'Token Balance'}
dataKey={'tokenBalance'}
fill="var(--c-token)"
yAxisId={1}
opacity={'0'}
stroke="var(--c-token)"
/>
</AreaChart>
</ResponsiveContainer>
</ChartWrapper>
)
} else {
// volume
return (
<ChartWrapper>
<ResponsiveContainer aspect={isMobile ? 60 / 22 : 60 / 12}>
<BarChart margin={{ top: 0, right: 0, bottom: 6, left: 10 }} barCategoryGap={1} data={chartData}>
<CartesianGrid stroke="#f5f5f5" />
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
minTickGap={80}
tickMargin={14}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="dayString"
/>
<YAxis
hide={isMobile}
type="number"
axisLine={false}
tickMargin={16}
tickFormatter={(tick) => toK(tick)}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
/>
<Tooltip
cursor={true}
formatter={(val) => toK(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: 'var(--c-zircon)',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Bar
type="monotone"
name={'Volume' + (currencyUnit === 'USD' ? ' (USD)' : ' (ETH)')}
dataKey={currencyUnit === 'USD' ? 'usdVolume' : 'ethVolume'}
fill="var(--c-token)"
opacity={'0.4'}
yAxisId={0}
stroke="var(--c-token)"
/>
</BarChart>
</ResponsiveContainer>
</ChartWrapper>
)
}
}
Example #12
Source File: PairPage.js From pancake-info-v1 with GNU General Public License v3.0 | 4 votes |
function PairPage({ pairAddress, history }) {
const {
token0,
token1,
reserve0,
reserve1,
reserveUSD,
trackedReserveUSD,
oneDayVolumeUSD,
volumeChangeUSD,
oneDayVolumeUntracked,
volumeChangeUntracked,
liquidityChangeUSD,
} = usePairData(pairAddress)
useEffect(() => {
document.querySelector('body').scrollTo(0, 0)
}, [])
const transactions = usePairTransactions(pairAddress)
const backgroundColor = useColor(pairAddress)
// liquidity
const liquidity = trackedReserveUSD
? formattedNum(trackedReserveUSD, true)
: reserveUSD
? formattedNum(reserveUSD, true)
: '-'
const liquidityChange = formattedPercent(liquidityChangeUSD)
// mark if using untracked liquidity
const [usingTracked, setUsingTracked] = useState(true)
useEffect(() => {
setUsingTracked(!trackedReserveUSD ? false : true)
}, [trackedReserveUSD])
// volume // volume
const volume =
oneDayVolumeUSD || oneDayVolumeUSD === 0
? formattedNum(oneDayVolumeUSD === 0 ? oneDayVolumeUntracked : oneDayVolumeUSD, true)
: oneDayVolumeUSD === 0
? '$0'
: '-'
// mark if using untracked volume
const [usingUtVolume, setUsingUtVolume] = useState(false)
useEffect(() => {
setUsingUtVolume(oneDayVolumeUSD === 0 ? true : false)
}, [oneDayVolumeUSD])
const volumeChange = formattedPercent(!usingUtVolume ? volumeChangeUSD : volumeChangeUntracked)
// get fees // get fees
const fees =
oneDayVolumeUSD || oneDayVolumeUSD === 0
? usingUtVolume
? formattedNum(oneDayVolumeUntracked * 0.002, true)
: formattedNum(oneDayVolumeUSD * 0.002, true)
: '-'
// token data for usd
const [ethPrice] = useEthPrice()
const token0USD =
token0?.derivedETH && ethPrice ? formattedNum(parseFloat(token0.derivedETH) * parseFloat(ethPrice), true) : ''
const token1USD =
token1?.derivedETH && ethPrice ? formattedNum(parseFloat(token1.derivedETH) * parseFloat(ethPrice), true) : ''
// rates
const token0Rate = reserve0 && reserve1 ? formattedNum(reserve1 / reserve0) : '-'
const token1Rate = reserve0 && reserve1 ? formattedNum(reserve0 / reserve1) : '-'
// formatted symbols for overflow
const formattedSymbol0 = token0?.symbol.length > 6 ? token0?.symbol.slice(0, 5) + '...' : token0?.symbol
const formattedSymbol1 = token1?.symbol.length > 6 ? token1?.symbol.slice(0, 5) + '...' : token1?.symbol
const below1080 = useMedia('(max-width: 1080px)')
const below900 = useMedia('(max-width: 900px)')
const below600 = useMedia('(max-width: 600px)')
const [dismissed, markAsDismissed] = usePathDismissed(history.location.pathname)
useEffect(() => {
window.scrollTo({
behavior: 'smooth',
top: 0,
})
}, [])
const [savedPairs, addPair] = useSavedPairs()
const listedTokens = useListedTokens()
return (
<PageWrapper>
<ThemedBackground backgroundColor={transparentize(0.6, backgroundColor)} />
<span />
<Warning
type={'pair'}
show={!dismissed && listedTokens && !(listedTokens.includes(token0?.id) && listedTokens.includes(token1?.id))}
setShow={markAsDismissed}
address={pairAddress}
/>
<ContentWrapperLarge>
<RowBetween>
<TYPE.body>
<BasicLink to="/pairs">{'Pairs '}</BasicLink>→ {token0?.symbol}-{token1?.symbol}
</TYPE.body>
{!below600 && <Search small={true} />}
</RowBetween>
<WarningGrouping
disabled={
!dismissed && listedTokens && !(listedTokens.includes(token0?.id) && listedTokens.includes(token1?.id))
}
>
<DashboardWrapper>
<AutoColumn gap="40px" style={{ marginBottom: '1.5rem' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
flexWrap: 'wrap',
width: '100%',
}}
>
<RowFixed style={{ flexWrap: 'wrap', minWidth: '100px' }}>
<RowFixed>
{token0 && token1 && (
<DoubleTokenLogo a0={token0?.id || ''} a1={token1?.id || ''} size={32} margin={true} />
)}{' '}
<TYPE.main fontSize={below1080 ? '1.5rem' : '2rem'} style={{ margin: '0 1rem' }}>
{token0 && token1 ? (
<>
<HoverSpan onClick={() => history.push(`/token/${token0?.id}`)}>{token0.symbol}</HoverSpan>
<span>-</span>
<HoverSpan onClick={() => history.push(`/token/${token1?.id}`)}>
{token1.symbol}
</HoverSpan>{' '}
Pair
</>
) : (
''
)}
</TYPE.main>
</RowFixed>
</RowFixed>
<RowFixed
ml={below900 ? '0' : '2.5rem'}
mt={below1080 && '1rem'}
style={{
flexDirection: below1080 ? 'row-reverse' : 'initial',
}}
>
{!!!savedPairs[pairAddress] && !below1080 ? (
<Hover onClick={() => addPair(pairAddress, token0.id, token1.id, token0.symbol, token1.symbol)}>
<StyledIcon>
<PlusCircle style={{ marginRight: '0.5rem' }} />
</StyledIcon>
</Hover>
) : !below1080 ? (
<StyledIcon>
<Bookmark style={{ marginRight: '0.5rem', opacity: 0.4 }} />
</StyledIcon>
) : (
<></>
)}
<Link external href={getPoolLink(token0?.id, token1?.id)}>
<ButtonLight color={backgroundColor}>+ Add Liquidity</ButtonLight>
</Link>
<Link external href={getSwapLink(token0?.id, token1?.id)}>
<ButtonDark ml={!below1080 && '.5rem'} mr={below1080 && '.5rem'} color={backgroundColor}>
Trade
</ButtonDark>
</Link>
</RowFixed>
</div>
</AutoColumn>
<AutoRow
gap="6px"
style={{
width: 'fit-content',
marginTop: below900 ? '1rem' : '0',
marginBottom: below900 ? '0' : '2rem',
flexWrap: 'wrap',
}}
>
<FixedPanel onClick={() => history.push(`/token/${token0?.id}`)}>
<RowFixed>
<TokenLogo address={token0?.id} size={'16px'} />
<TYPE.main fontSize={'16px'} lineHeight={1} fontWeight={500} ml={'4px'}>
{token0 && token1
? `1 ${formattedSymbol0} = ${token0Rate} ${formattedSymbol1} ${
parseFloat(token0?.derivedETH) ? '(' + token0USD + ')' : ''
}`
: '-'}
</TYPE.main>
</RowFixed>
</FixedPanel>
<FixedPanel onClick={() => history.push(`/token/${token1?.id}`)}>
<RowFixed>
<TokenLogo address={token1?.id} size={'16px'} />
<TYPE.main fontSize={'16px'} lineHeight={1} fontWeight={500} ml={'4px'}>
{token0 && token1
? `1 ${formattedSymbol1} = ${token1Rate} ${formattedSymbol0} ${
parseFloat(token1?.derivedETH) ? '(' + token1USD + ')' : ''
}`
: '-'}
</TYPE.main>
</RowFixed>
</FixedPanel>
</AutoRow>
<>
{!below1080 && <TYPE.main fontSize={'1.125rem'}>Pair Stats</TYPE.main>}
<PanelWrapper style={{ marginTop: '1.5rem' }}>
<Panel style={{ height: '100%' }}>
<AutoColumn gap="20px">
<RowBetween>
<TYPE.main>Total Liquidity {!usingTracked ? '(Untracked)' : ''}</TYPE.main>
<div />
</RowBetween>
<RowBetween align="flex-end">
<TYPE.main fontSize={'1.5rem'} lineHeight={1} fontWeight={500}>
{liquidity}
</TYPE.main>
<TYPE.main>{liquidityChange}</TYPE.main>
</RowBetween>
</AutoColumn>
</Panel>
<Panel style={{ height: '100%' }}>
<AutoColumn gap="20px">
<RowBetween>
<TYPE.main>Volume (24hrs) {usingUtVolume && '(Untracked)'}</TYPE.main>
<div />
</RowBetween>
<RowBetween align="flex-end">
<TYPE.main fontSize={'1.5rem'} lineHeight={1} fontWeight={500}>
{volume}
</TYPE.main>
<TYPE.main>{volumeChange}</TYPE.main>
</RowBetween>
</AutoColumn>
</Panel>
<Panel style={{ height: '100%' }}>
<AutoColumn gap="20px">
<RowBetween>
<TYPE.main>Fees (24hrs)</TYPE.main>
<div />
</RowBetween>
<RowBetween align="flex-end">
<TYPE.main fontSize={'1.5rem'} lineHeight={1} fontWeight={500}>
{fees}
</TYPE.main>
<TYPE.main>{volumeChange}</TYPE.main>
</RowBetween>
</AutoColumn>
</Panel>
<Panel style={{ height: '100%' }}>
<AutoColumn gap="20px">
<RowBetween>
<TYPE.main>Pooled Tokens</TYPE.main>
<div />
</RowBetween>
<Hover onClick={() => history.push(`/token/${token0?.id}`)} fade={true}>
<AutoRow gap="4px">
<TokenLogo address={token0?.id} />
<TYPE.main fontSize={20} lineHeight={1} fontWeight={500}>
<RowFixed>
{reserve0 ? formattedNum(reserve0) : ''}{' '}
<FormattedName text={token0?.symbol ?? ''} maxCharacters={8} margin={true} />
</RowFixed>
</TYPE.main>
</AutoRow>
</Hover>
<Hover onClick={() => history.push(`/token/${token1?.id}`)} fade={true}>
<AutoRow gap="4px">
<TokenLogo address={token1?.id} />
<TYPE.main fontSize={20} lineHeight={1} fontWeight={500}>
<RowFixed>
{reserve1 ? formattedNum(reserve1) : ''}{' '}
<FormattedName text={token1?.symbol ?? ''} maxCharacters={8} margin={true} />
</RowFixed>
</TYPE.main>
</AutoRow>
</Hover>
</AutoColumn>
</Panel>
<Panel
style={{
gridColumn: below1080 ? '1' : '2/4',
gridRow: below1080 ? '' : '1/5',
}}
>
<PairChart
address={pairAddress}
color={backgroundColor}
base0={reserve1 / reserve0}
base1={reserve0 / reserve1}
/>
</Panel>
</PanelWrapper>
<TYPE.main fontSize={'1.125rem'} style={{ marginTop: '3rem' }}>
Transactions
</TYPE.main>{' '}
<Panel
style={{
marginTop: '1.5rem',
}}
>
{transactions ? <TxnList transactions={transactions} /> : <Loader />}
</Panel>
<RowBetween style={{ marginTop: '3rem' }}>
<TYPE.main fontSize={'1.125rem'}>Pair Information</TYPE.main>{' '}
</RowBetween>
<Panel
rounded
style={{
marginTop: '1.5rem',
}}
p={20}
>
<TokenDetailsLayout>
<Column>
<TYPE.main>Pair Name</TYPE.main>
<TYPE.main style={{ marginTop: '.5rem' }}>
<RowFixed>
<FormattedName text={token0?.symbol ?? ''} maxCharacters={8} />
-
<FormattedName text={token1?.symbol ?? ''} maxCharacters={8} />
</RowFixed>
</TYPE.main>
</Column>
<Column>
<TYPE.main>Pair Address</TYPE.main>
<AutoRow align="flex-end">
<TYPE.main style={{ marginTop: '.5rem' }}>
{pairAddress.slice(0, 6) + '...' + pairAddress.slice(38, 42)}
</TYPE.main>
<CopyHelper toCopy={pairAddress} />
</AutoRow>
</Column>
<Column>
<TYPE.main>
<RowFixed>
<FormattedName text={token0?.symbol ?? ''} maxCharacters={8} />{' '}
<span style={{ marginLeft: '4px' }}>Address</span>
</RowFixed>
</TYPE.main>
<AutoRow align="flex-end">
<TYPE.main style={{ marginTop: '.5rem' }}>
{token0 && token0.id.slice(0, 6) + '...' + token0.id.slice(38, 42)}
</TYPE.main>
<CopyHelper toCopy={token0?.id} />
</AutoRow>
</Column>
<Column>
<TYPE.main>
<RowFixed>
<FormattedName text={token1?.symbol ?? ''} maxCharacters={8} />{' '}
<span style={{ marginLeft: '4px' }}>Address</span>
</RowFixed>
</TYPE.main>
<AutoRow align="flex-end">
<TYPE.main style={{ marginTop: '.5rem' }} fontSize={16}>
{token1 && token1.id.slice(0, 6) + '...' + token1.id.slice(38, 42)}
</TYPE.main>
<CopyHelper toCopy={token1?.id} />
</AutoRow>
</Column>
<ButtonLight color={backgroundColor}>
<Link color={backgroundColor} external href={'https://bscscan.com/address/' + pairAddress}>
View on BscScan ↗
</Link>
</ButtonLight>
</TokenDetailsLayout>
</Panel>
</>
</DashboardWrapper>
</WarningGrouping>
</ContentWrapperLarge>
</PageWrapper>
)
}
Example #13
Source File: index.js From spooky-info with GNU General Public License v3.0 | 4 votes |
TokenChart = ({ address, color, base }) => {
// settings for the window and candle width
const [chartFilter, setChartFilter] = useState(CHART_VIEW.PRICE)
const [frequency, setFrequency] = useState(DATA_FREQUENCY.HOUR)
const [darkMode] = useDarkModeManager()
const textColor = darkMode ? 'white' : 'black'
// reset view on new address
const addressPrev = usePrevious(address)
useEffect(() => {
if (address !== addressPrev && addressPrev) {
setChartFilter(CHART_VIEW.LIQUIDITY)
}
}, [address, addressPrev])
let chartData = useTokenChartData(address)
const [timeWindow, setTimeWindow] = useState(timeframeOptions.WEEK)
const prevWindow = usePrevious(timeWindow)
// hourly and daily price data based on the current time window
const hourlyWeek = useTokenPriceData(address, timeframeOptions.WEEK, 3600)
const hourlyMonth = useTokenPriceData(address, timeframeOptions.MONTH, 3600)
const hourlyAll = useTokenPriceData(address, timeframeOptions.ALL_TIME, 3600)
const dailyWeek = useTokenPriceData(address, timeframeOptions.WEEK, 86400)
const dailyMonth = useTokenPriceData(address, timeframeOptions.MONTH, 86400)
const dailyAll = useTokenPriceData(address, timeframeOptions.ALL_TIME, 86400)
const priceData =
timeWindow === timeframeOptions.MONTH
? // monthly selected
frequency === DATA_FREQUENCY.DAY
? dailyMonth
: hourlyMonth
: // weekly selected
timeWindow === timeframeOptions.WEEK
? frequency === DATA_FREQUENCY.DAY
? dailyWeek
: hourlyWeek
: // all time selected
frequency === DATA_FREQUENCY.DAY
? dailyAll
: hourlyAll
// switch to hourly data when switched to week window
useEffect(() => {
if (timeWindow === timeframeOptions.WEEK && prevWindow && prevWindow !== timeframeOptions.WEEK) {
setFrequency(DATA_FREQUENCY.HOUR)
}
}, [prevWindow, timeWindow])
// switch to daily data if switche to month or all time view
useEffect(() => {
if (timeWindow === timeframeOptions.MONTH && prevWindow && prevWindow !== timeframeOptions.MONTH) {
setFrequency(DATA_FREQUENCY.DAY)
}
if (timeWindow === timeframeOptions.ALL_TIME && prevWindow && prevWindow !== timeframeOptions.ALL_TIME) {
setFrequency(DATA_FREQUENCY.DAY)
}
}, [prevWindow, timeWindow])
const below1080 = useMedia('(max-width: 1080px)')
const below600 = useMedia('(max-width: 600px)')
let utcStartTime = getTimeframe(timeWindow)
const domain = [(dataMin) => (dataMin > utcStartTime ? dataMin : utcStartTime), 'dataMax']
const aspect = below1080 ? 60 / 32 : below600 ? 60 / 42 : 60 / 22
chartData = chartData?.filter((entry) => entry.date >= utcStartTime)
// update the width on a window resize
const ref = useRef()
const isClient = typeof window === 'object'
const [width, setWidth] = useState(ref?.current?.container?.clientWidth)
useEffect(() => {
if (!isClient) {
return false
}
function handleResize() {
setWidth(ref?.current?.container?.clientWidth ?? width)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [isClient, width]) // Empty array ensures that effect is only run on mount and unmount
return (
<ChartWrapper>
{below600 ? (
<RowBetween mb={40}>
<DropdownSelect options={CHART_VIEW} active={chartFilter} setActive={setChartFilter} color={color} />
<DropdownSelect options={timeframeOptions} active={timeWindow} setActive={setTimeWindow} color={color} />
</RowBetween>
) : (
<RowBetween
mb={
chartFilter === CHART_VIEW.LIQUIDITY ||
chartFilter === CHART_VIEW.VOLUME ||
(chartFilter === CHART_VIEW.PRICE && frequency === DATA_FREQUENCY.LINE)
? 40
: 0
}
align="flex-start"
>
<AutoColumn gap="8px">
<RowFixed>
<OptionButton
active={chartFilter === CHART_VIEW.LIQUIDITY}
onClick={() => setChartFilter(CHART_VIEW.LIQUIDITY)}
style={{ marginRight: '6px' }}
>
Liquidity
</OptionButton>
<OptionButton
active={chartFilter === CHART_VIEW.VOLUME}
onClick={() => setChartFilter(CHART_VIEW.VOLUME)}
style={{ marginRight: '6px' }}
>
Volume
</OptionButton>
<OptionButton
active={chartFilter === CHART_VIEW.PRICE}
onClick={() => {
setChartFilter(CHART_VIEW.PRICE)
}}
>
Price
</OptionButton>
</RowFixed>
{chartFilter === CHART_VIEW.PRICE && (
<AutoRow gap="4px">
<PriceOption
active={frequency === DATA_FREQUENCY.DAY}
onClick={() => {
setTimeWindow(timeframeOptions.MONTH)
setFrequency(DATA_FREQUENCY.DAY)
}}
>
D
</PriceOption>
<PriceOption
active={frequency === DATA_FREQUENCY.HOUR}
onClick={() => setFrequency(DATA_FREQUENCY.HOUR)}
>
H
</PriceOption>
<PriceOption
active={frequency === DATA_FREQUENCY.LINE}
onClick={() => setFrequency(DATA_FREQUENCY.LINE)}
>
<Activity size={14} />
</PriceOption>
</AutoRow>
)}
</AutoColumn>
<AutoRow justify="flex-end" gap="6px" align="flex-start">
<OptionButton
active={timeWindow === timeframeOptions.WEEK}
onClick={() => setTimeWindow(timeframeOptions.WEEK)}
>
1W
</OptionButton>
<OptionButton
active={timeWindow === timeframeOptions.MONTH}
onClick={() => setTimeWindow(timeframeOptions.MONTH)}
>
1M
</OptionButton>
<OptionButton
active={timeWindow === timeframeOptions.ALL_TIME}
onClick={() => setTimeWindow(timeframeOptions.ALL_TIME)}
>
All
</OptionButton>
</AutoRow>
</RowBetween>
)}
{chartFilter === CHART_VIEW.LIQUIDITY && chartData && (
<ResponsiveContainer aspect={aspect}>
<AreaChart margin={{ top: 0, right: 10, bottom: 6, left: 0 }} barCategoryGap={1} data={chartData}>
<defs>
<linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={color} stopOpacity={0.35} />
<stop offset="95%" stopColor={color} stopOpacity={0} />
</linearGradient>
</defs>
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
tickMargin={16}
minTickGap={120}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="date"
tick={{ fill: textColor }}
type={'number'}
domain={['dataMin', 'dataMax']}
/>
<YAxis
type="number"
orientation="right"
tickFormatter={(tick) => '$' + toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
tick={{ fill: textColor }}
/>
<Tooltip
cursor={true}
formatter={(val) => formattedNum(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: color,
color: 'black',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Area
key={'other'}
dataKey={'totalLiquidityUSD'}
stackId="2"
strokeWidth={2}
dot={false}
type="monotone"
name={'Liquidity'}
yAxisId={0}
stroke={darken(0.12, color)}
fill="url(#colorUv)"
/>
</AreaChart>
</ResponsiveContainer>
)}
{chartFilter === CHART_VIEW.PRICE &&
(frequency === DATA_FREQUENCY.LINE ? (
<ResponsiveContainer aspect={below1080 ? 60 / 32 : 60 / 16}>
<AreaChart margin={{ top: 0, right: 10, bottom: 6, left: 0 }} barCategoryGap={1} data={chartData}>
<defs>
<linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={color} stopOpacity={0.35} />
<stop offset="95%" stopColor={color} stopOpacity={0} />
</linearGradient>
</defs>
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
tickMargin={16}
minTickGap={120}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="date"
tick={{ fill: textColor }}
type={'number'}
domain={domain}
/>
<YAxis
type="number"
orientation="right"
tickFormatter={(tick) => '$' + toK(tick)}
axisLine={false}
tickLine={false}
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
tick={{ fill: textColor }}
/>
<Tooltip
cursor={true}
formatter={(val) => formattedNum(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: color,
color: 'black',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Area
key={'other'}
dataKey={'priceUSD'}
stackId="2"
strokeWidth={2}
dot={false}
type="monotone"
name={'Price'}
yAxisId={0}
stroke={darken(0.12, color)}
fill="url(#colorUv)"
/>
</AreaChart>
</ResponsiveContainer>
) : priceData ? (
<ResponsiveContainer aspect={aspect} ref={ref}>
<CandleStickChart data={priceData} width={width} base={base} />
</ResponsiveContainer>
) : (
<LocalLoader />
))}
{chartFilter === CHART_VIEW.VOLUME && (
<ResponsiveContainer aspect={aspect}>
<BarChart margin={{ top: 0, right: 10, bottom: 6, left: 10 }} barCategoryGap={1} data={chartData}>
<XAxis
tickLine={false}
axisLine={false}
interval="preserveEnd"
minTickGap={80}
tickMargin={14}
tickFormatter={(tick) => toNiceDate(tick)}
dataKey="date"
tick={{ fill: textColor }}
type={'number'}
domain={['dataMin', 'dataMax']}
/>
<YAxis
type="number"
axisLine={false}
tickMargin={16}
tickFormatter={(tick) => '$' + toK(tick)}
tickLine={false}
orientation="right"
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
tick={{ fill: textColor }}
/>
<Tooltip
cursor={{ fill: color, opacity: 0.1 }}
formatter={(val) => formattedNum(val, true)}
labelFormatter={(label) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: color,
color: 'black',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Bar
type="monotone"
name={'Volume'}
dataKey={'dailyVolumeUSD'}
fill={color}
opacity={'0.4'}
yAxisId={0}
stroke={color}
/>
</BarChart>
</ResponsiveContainer>
)}
</ChartWrapper>
)
}
Example #14
Source File: index.js From pancake-info-v1 with GNU General Public License v3.0 | 4 votes |
GlobalChart = ({ display }) => {
// chart options
const [chartView, setChartView] = useState(display === 'volume' ? CHART_VIEW.VOLUME : CHART_VIEW.LIQUIDITY)
// time window and window size for chart
const timeWindow = timeframeOptions.ALL_TIME
const [volumeWindow, setVolumeWindow] = useState(VOLUME_WINDOW.DAYS)
// global historical data
const [dailyData, weeklyData] = useGlobalChartData()
const {
totalLiquidityUSD,
oneDayVolumeUSD,
volumeChangeUSD,
liquidityChangeUSD,
oneWeekVolume,
weeklyVolumeChange,
} = useGlobalData()
// based on window, get starttim
let utcStartTime = getTimeframe(timeWindow)
const chartDataFiltered = useMemo(() => {
let currentData = volumeWindow === VOLUME_WINDOW.DAYS ? dailyData : weeklyData
return (
currentData &&
Object.keys(currentData)
?.map((key) => {
let item = currentData[key]
if (item.date > utcStartTime) {
return item
} else {
return
}
})
.filter((item) => {
return !!item
})
)
}, [dailyData, utcStartTime, volumeWindow, weeklyData])
const below800 = useMedia('(max-width: 800px)')
// update the width on a window resize
const ref = useRef()
const isClient = typeof window === 'object'
const [width, setWidth] = useState(ref?.current?.container?.clientWidth)
useEffect(() => {
if (!isClient) {
return false
}
function handleResize() {
setWidth(ref?.current?.container?.clientWidth ?? width)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [isClient, width]) // Empty array ensures that effect is only run on mount and unmount
return chartDataFiltered ? (
<>
{below800 && (
<DropdownSelect options={CHART_VIEW} active={chartView} setActive={setChartView} color={'#4FD8DE'} />
)}
{chartDataFiltered && chartView === CHART_VIEW.LIQUIDITY && (
<ResponsiveContainer aspect={60 / 28} ref={ref}>
<TradingViewChart
data={dailyData}
base={totalLiquidityUSD}
baseChange={liquidityChangeUSD}
title="Liquidity"
field="totalLiquidityUSD"
width={width}
type={CHART_TYPES.AREA}
/>
</ResponsiveContainer>
)}
{chartDataFiltered && chartView === CHART_VIEW.VOLUME && (
<ResponsiveContainer aspect={60 / 28}>
<TradingViewChart
data={chartDataFiltered}
base={volumeWindow === VOLUME_WINDOW.WEEKLY ? oneWeekVolume : oneDayVolumeUSD}
baseChange={volumeWindow === VOLUME_WINDOW.WEEKLY ? weeklyVolumeChange : volumeChangeUSD}
title={volumeWindow === VOLUME_WINDOW.WEEKLY ? 'Volume (7d)' : 'Volume'}
field={volumeWindow === VOLUME_WINDOW.WEEKLY ? 'weeklyVolumeUSD' : 'dailyVolumeUSD'}
width={width}
type={CHART_TYPES.BAR}
useWeekly={volumeWindow === VOLUME_WINDOW.WEEKLY}
/>
</ResponsiveContainer>
)}
{display === 'volume' && (
<RowFixed
style={{
bottom: '70px',
position: 'absolute',
left: '20px',
zIndex: 10,
}}
>
<OptionButton
active={volumeWindow === VOLUME_WINDOW.DAYS}
onClick={() => setVolumeWindow(VOLUME_WINDOW.DAYS)}
>
<TYPE.body>D</TYPE.body>
</OptionButton>
<OptionButton
style={{ marginLeft: '4px' }}
active={volumeWindow === VOLUME_WINDOW.WEEKLY}
onClick={() => setVolumeWindow(VOLUME_WINDOW.WEEKLY)}
>
<TYPE.body>W</TYPE.body>
</OptionButton>
</RowFixed>
)}
</>
) : (
''
)
}
Example #15
Source File: index.js From spooky-info with GNU General Public License v3.0 | 4 votes |
// @TODO rework into virtualized list
function TopTokenList({ tokens, itemMax = 10, useTracked = false }) {
// page state
const [page, setPage] = useState(1)
const [maxPage, setMaxPage] = useState(1)
// sorting
const [sortDirection, setSortDirection] = useState(true)
const [sortedColumn, setSortedColumn] = useState(SORT_FIELD.LIQ)
const below1080 = useMedia('(max-width: 1080px)')
const below680 = useMedia('(max-width: 680px)')
const below600 = useMedia('(max-width: 600px)')
useEffect(() => {
setMaxPage(1) // edit this to do modular
setPage(1)
}, [tokens])
const formattedTokens = useMemo(() => {
return (
tokens &&
Object.keys(tokens)
.filter((key) => {
return !TOKEN_BLACKLIST.includes(key)
})
.map((key) => tokens[key])
)
}, [tokens])
useEffect(() => {
if (tokens && formattedTokens) {
let extraPages = 1
if (formattedTokens.length % itemMax === 0) {
extraPages = 0
}
setMaxPage(Math.floor(formattedTokens.length / itemMax) + extraPages)
}
}, [tokens, formattedTokens, itemMax])
const filteredList = useMemo(() => {
return (
formattedTokens &&
formattedTokens
.sort((a, b) => {
if (sortedColumn === SORT_FIELD.SYMBOL || sortedColumn === SORT_FIELD.NAME) {
return a[sortedColumn] > b[sortedColumn] ? (sortDirection ? -1 : 1) * 1 : (sortDirection ? -1 : 1) * -1
}
return parseFloat(a[sortedColumn]) > parseFloat(b[sortedColumn])
? (sortDirection ? -1 : 1) * 1
: (sortDirection ? -1 : 1) * -1
})
.slice(itemMax * (page - 1), page * itemMax)
)
}, [formattedTokens, itemMax, page, sortDirection, sortedColumn])
const ListItem = ({ item, index }) => {
return (
<DashGrid style={{ height: '48px' }} focus={true}>
<DataText area="name" fontWeight="500">
<Row>
{!below680 && <div style={{ marginRight: '1rem', width: '10px' }}>{index}</div>}
<TokenLogo address={item.id} />
<CustomLink style={{ marginLeft: '16px', whiteSpace: 'nowrap' }} to={'/token/' + item.id}>
<FormattedName
text={below680 ? item.symbol : item.name}
maxCharacters={below600 ? 8 : 16}
adjustSize={true}
link={true}
/>
</CustomLink>
</Row>
</DataText>
{!below680 && (
<DataText area="symbol" color="text" fontWeight="500">
<FormattedName text={item.symbol} maxCharacters={5} />
</DataText>
)}
<DataText area="liq">{formattedNum(item.totalLiquidityUSD, true)}</DataText>
<DataText area="vol">{formattedNum(item.oneDayVolumeUSD, true)}</DataText>
{!below1080 && (
<DataText area="price" color="text" fontWeight="500">
{formattedNum(item.priceUSD, true)}
</DataText>
)}
{!below1080 && <DataText area="change">{formattedPercent(item.priceChangeUSD)}</DataText>}
</DashGrid>
)
}
return (
<ListWrapper>
<DashGrid center={true} style={{ height: 'fit-content', padding: '0 1.125rem 1rem 1.125rem' }}>
<Flex alignItems="center" justifyContent="flexStart">
<ClickableText
color="text"
area="name"
fontWeight="500"
onClick={(e) => {
setSortedColumn(SORT_FIELD.NAME)
setSortDirection(sortedColumn !== SORT_FIELD.NAME ? true : !sortDirection)
}}
>
{below680 ? 'Symbol' : 'Name'} {sortedColumn === SORT_FIELD.NAME ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
{!below680 && (
<Flex alignItems="center">
<ClickableText
area="symbol"
onClick={() => {
setSortedColumn(SORT_FIELD.SYMBOL)
setSortDirection(sortedColumn !== SORT_FIELD.SYMBOL ? true : !sortDirection)
}}
>
Symbol {sortedColumn === SORT_FIELD.SYMBOL ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
)}
<Flex alignItems="center">
<ClickableText
area="liq"
onClick={(e) => {
setSortedColumn(SORT_FIELD.LIQ)
setSortDirection(sortedColumn !== SORT_FIELD.LIQ ? true : !sortDirection)
}}
>
Liquidity {sortedColumn === SORT_FIELD.LIQ ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
<Flex alignItems="center">
<ClickableText
area="vol"
onClick={() => {
setSortedColumn(useTracked ? SORT_FIELD.VOL_UT : SORT_FIELD.VOL)
setSortDirection(
sortedColumn !== (useTracked ? SORT_FIELD.VOL_UT : SORT_FIELD.VOL) ? true : !sortDirection
)
}}
>
Volume (24hrs)
{sortedColumn === (useTracked ? SORT_FIELD.VOL_UT : SORT_FIELD.VOL) ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
{!below1080 && (
<Flex alignItems="center">
<ClickableText
area="price"
onClick={(e) => {
setSortedColumn(SORT_FIELD.PRICE)
setSortDirection(sortedColumn !== SORT_FIELD.PRICE ? true : !sortDirection)
}}
>
Price {sortedColumn === SORT_FIELD.PRICE ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
)}
{!below1080 && (
<Flex alignItems="center">
<ClickableText
area="change"
onClick={(e) => {
setSortedColumn(SORT_FIELD.CHANGE)
setSortDirection(sortedColumn !== SORT_FIELD.CHANGE ? true : !sortDirection)
}}
>
Price Change (24hrs)
{sortedColumn === SORT_FIELD.CHANGE ? (!sortDirection ? '↑' : '↓') : ''}
</ClickableText>
</Flex>
)}
</DashGrid>
<Divider />
<List p={0}>
{filteredList &&
filteredList.map((item, index) => {
return (
<div key={index}>
<ListItem key={index} index={(page - 1) * itemMax + index + 1} item={item} />
<Divider />
</div>
)
})}
</List>
<PageButtons>
<div onClick={() => setPage(page === 1 ? page : page - 1)}>
<Arrow faded={page === 1 ? true : false}>←</Arrow>
</div>
<TYPE.body>{'Page ' + page + ' of ' + maxPage}</TYPE.body>
<div onClick={() => setPage(page === maxPage ? page : page + 1)}>
<Arrow faded={page === maxPage ? true : false}>→</Arrow>
</div>
</PageButtons>
</ListWrapper>
)
}
Example #16
Source File: [slug].js From botble-graphql-next with MIT License | 4 votes |
Post = () => {
const router = useRouter();
const isWide = useMedia('(min-width: 1024px)', true);
const [{error, fetching, data}] = useQuery({
query: queryPost,
variables: {slug: router.query.slug},
});
if (error || fetching) {
const title = error ? error.message : 'Đang tải...';
return (
<Layout title={title}>
<Head title={title} />
<div className="container container-fluid px-2 lg:px-0 py-8">
{error ? (
<Alert content={title} />
) : (
<div className="h-40 sm:64 flex justify-center items-center">
<LoaderIcon />
</div>
)}
</div>
</Layout>
);
}
const title = data.postBySlug.name;
const category = data.postBySlug.categories[0];
return (
<Layout
title={title}
breadcrumb={[
category
? {
title: category.name,
href: '/c/[slug]',
as: `/c/${category.slug}`,
}
: undefined,
{title},
].filter(Boolean)}>
<Head title={title} />
<div className="container container-fluid px-2 lg:px-0 py-8">
<div className="flex">
<div className="flex-grow pb-10">
<h1 className="text-2xl text-gray-800 font-semibold">{title}</h1>
<div className="my-4">
{category && (
<>
<InlineIcon icon={cubeSharpIcon} className="text-fresh-red" />{' '}
<Link href="/c/[slug]" as={`/c/${category.slug}`}>
<a className="inline-block mr-2">
<span className="uppercase text-xs font-medium">
{category.name}
</span>
</a>
</Link>
</>
)}
<span>
<InlineIcon icon={clockIcon} className="text-fresh-red" />{' '}
<small className="uppercase text-xs font-medium">
{format('PP', new Date(data.postBySlug.createdAt))}
</small>
</span>
</div>
<div
dangerouslySetInnerHTML={{__html: data.postBySlug.content}}
className="border-t pt-6"
/>
</div>
{isWide && (
<div className="ml-6">
<RecentListing />
</div>
)}
</div>
</div>
</Layout>
);
}