Commit 3f1d7ab3 authored by Ian Lapham's avatar Ian Lapham Committed by GitHub

add basic structure for advanced mode (#703)

* add basic structure for advanced mode

* auto dismiss popup

* Remove test code

* remove shadow

* Update advanced section, ui tweaks, balances back inline

* fix memory leak
Co-authored-by: default avatarCallil Capuozzo <callil.capuozzo@gmail.com>
parent 60d7bc45
import React, { useState } from 'react'
import Copy from '../AccountDetails/Copy'
import TokenLogo from '../TokenLogo'
import { Link } from '../../theme/components'
import { TYPE } from '../../theme'
import { Hover } from '../../theme'
import { GreyCard } from '../Card'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'
import { ChevronDown, ChevronUp } from 'react-feather'
import { useWeb3React } from '../../hooks'
import { getEtherscanLink } from '../../utils'
export default function BalanceCard({ token0, balance0, import0, token1, balance1, import1 }) {
const [details0, setDetails0] = useState(false)
const [details1, setDetails1] = useState(false)
const { chainId } = useWeb3React()
return (
<AutoColumn gap="lg">
<GreyCard>
<AutoColumn gap="md">
<TYPE.black>Selected Tokens</TYPE.black>
{token0 && balance0 && (
<Hover onClick={() => setDetails0(!details0)}>
<RowBetween>
<RowFixed>
<TokenLogo address={token0?.address || ''} />
<TYPE.black marginLeft="10px">
{token0?.name} ({token0?.symbol})
</TYPE.black>
</RowFixed>
<RowFixed>
<TYPE.black>{balance0?.toSignificant(6)}</TYPE.black>
{details0 ? (
<ChevronUp size="20" style={{ marginLeft: '10px' }} color="black" />
) : (
<ChevronDown size="20" style={{ marginLeft: '10px' }} color="black" />
)}
</RowFixed>
</RowBetween>
{import0 && <TYPE.yellow style={{ paddingLeft: '32px' }}>Token imported by user</TYPE.yellow>}
</Hover>
)}
{details0 && (
<AutoColumn gap="sm" style={{ marginTop: '2px', marginBottom: '6px' }}>
<RowFixed>
<TYPE.blue style={{ paddingLeft: '32px' }}>Copy token address</TYPE.blue>
<Copy toCopy={token0?.address} />
</RowFixed>
<Link href={getEtherscanLink(chainId, token0?.address, 'address')} style={{ paddingLeft: '32px' }}>
View on etherscan
</Link>
</AutoColumn>
)}
{token1 && balance1 && (
<Hover onClick={() => setDetails1(!details1)}>
<RowBetween>
<RowFixed>
<TokenLogo address={token1?.address || ''} />
<TYPE.black marginLeft="10px">
{token1?.name} ({token1?.symbol})
</TYPE.black>
</RowFixed>
<RowFixed>
<TYPE.black>{balance1?.toSignificant(6)}</TYPE.black>
{details1 ? (
<ChevronUp size="20" style={{ marginLeft: '10px' }} color="black" />
) : (
<ChevronDown size="20" style={{ marginLeft: '10px' }} color="black" />
)}
</RowFixed>
</RowBetween>
{import0 && <TYPE.yellow style={{ paddingLeft: '32px' }}>Token imported by user</TYPE.yellow>}
</Hover>
)}
{details1 && (
<AutoColumn gap="sm" style={{ marginTop: '2px', marginBottom: '6px' }}>
<RowFixed>
<TYPE.blue style={{ paddingLeft: '32px' }}>Copy token address</TYPE.blue>
<Copy toCopy={token1?.address} />
</RowFixed>
<Link href={getEtherscanLink(chainId, token1?.address, 'address')} style={{ paddingLeft: '32px' }}>
View on etherscan
</Link>
</AutoColumn>
)}
</AutoColumn>
</GreyCard>
</AutoColumn>
)
}
...@@ -20,6 +20,10 @@ const Base = styled(RebassButton)` ...@@ -20,6 +20,10 @@ const Base = styled(RebassButton)`
&:disabled { &:disabled {
cursor: auto; cursor: auto;
} }
> * {
user-select: none;
}
` `
export const ButtonPrimary = styled(Base)` export const ButtonPrimary = styled(Base)`
......
...@@ -22,7 +22,7 @@ export const GreyCard = styled(Card)` ...@@ -22,7 +22,7 @@ export const GreyCard = styled(Card)`
` `
export const YellowCard = styled(Card)` export const YellowCard = styled(Card)`
background-color: rgba(243, 190, 30, 0.3); background-color: rgba(243, 132, 30, 0.05);
color: ${({ theme }) => theme.yellow2}; color: ${({ theme }) => theme.yellow2};
font-weight: 500; font-weight: 500;
` `
......
...@@ -6,10 +6,14 @@ import { darken } from 'polished' ...@@ -6,10 +6,14 @@ import { darken } from 'polished'
import TokenLogo from '../TokenLogo' import TokenLogo from '../TokenLogo'
import DoubleLogo from '../DoubleLogo' import DoubleLogo from '../DoubleLogo'
import SearchModal from '../SearchModal' import SearchModal from '../SearchModal'
import { RowBetween } from '../Row'
import { TYPE, Hover } from '../../theme'
import { Input as NumericalInput } from '../NumericalInput' import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useWeb3React } from '../../hooks'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useAddressBalance } from '../../contexts/Balances'
const InputRow = styled.div` const InputRow = styled.div`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
...@@ -39,6 +43,27 @@ const CurrencySelect = styled.button` ...@@ -39,6 +43,27 @@ const CurrencySelect = styled.button`
} }
` `
const LabelRow = styled.div`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
color: ${({ theme }) => theme.text1};
font-size: 0.75rem;
line-height: 1rem;
padding: 0 1.25rem 1rem 1rem;
span:hover {
cursor: pointer;
color: ${({ theme }) => darken(0.2, theme.text2)};
}
`
const ErrorSpan = styled.span`
color: ${({ error, theme }) => error && theme.red1};
:hover {
cursor: pointer;
color: ${({ error, theme }) => error && darken(0.1, theme.red1)};
}
`
const Aligner = styled.span` const Aligner = styled.span`
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -65,9 +90,7 @@ const InputPanel = styled.div` ...@@ -65,9 +90,7 @@ const InputPanel = styled.div`
const Container = styled.div` const Container = styled.div`
border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
/* border: 1px solid ${({ error, theme }) => (error ? theme.red1 : theme.bg2)}; */
border: 1px solid ${({ theme }) => theme.bg2}; border: 1px solid ${({ theme }) => theme.bg2};
background-color: ${({ theme }) => theme.bg1}; background-color: ${({ theme }) => theme.bg1};
` `
...@@ -118,6 +141,8 @@ export default function CurrencyInputPanel({ ...@@ -118,6 +141,8 @@ export default function CurrencyInputPanel({
const { t } = useTranslation() const { t } = useTranslation()
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false)
const { account } = useWeb3React()
const userTokenBalance = useAddressBalance(account, token)
return ( return (
<InputPanel> <InputPanel>
...@@ -164,6 +189,16 @@ export default function CurrencyInputPanel({ ...@@ -164,6 +189,16 @@ export default function CurrencyInputPanel({
</Aligner> </Aligner>
</CurrencySelect> </CurrencySelect>
</InputRow> </InputRow>
{!hideBalance && !!token && (
<LabelRow>
<RowBetween>
<ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan>
<Hover onClick={onMax}>
<TYPE.body fontWeight={500}>Balance: {userTokenBalance?.toSignificant(6)}</TYPE.body>
</Hover>
</RowBetween>
</LabelRow>
)}
</Container> </Container>
{!disableTokenSelect && ( {!disableTokenSelect && (
<SearchModal <SearchModal
......
This diff is collapsed.
...@@ -30,6 +30,7 @@ const HeaderFrame = styled.div` ...@@ -30,6 +30,7 @@ const HeaderFrame = styled.div`
padding: 10px; padding: 10px;
width: calc(100% - 20px); width: calc(100% - 20px);
`}; `};
z-index: 2;
` `
const HeaderElement = styled.div` const HeaderElement = styled.div`
......
...@@ -45,9 +45,9 @@ const MobilePopupInner = styled.div` ...@@ -45,9 +45,9 @@ const MobilePopupInner = styled.div`
const FixedPopupColumn = styled(AutoColumn)` const FixedPopupColumn = styled(AutoColumn)`
position: absolute; position: absolute;
top: 80px; top: 56px;
right: 20px right: 24px;
width: 380px; width: 355px;
${({ theme }) => theme.mediaWidth.upToSmall` ${({ theme }) => theme.mediaWidth.upToSmall`
display: none; display: none;
...@@ -57,7 +57,6 @@ const FixedPopupColumn = styled(AutoColumn)` ...@@ -57,7 +57,6 @@ const FixedPopupColumn = styled(AutoColumn)`
const Popup = styled.div` const Popup = styled.div`
display: inline-block; display: inline-block;
width: 100%; width: 100%;
min-height: 120px;
padding: 1em; padding: 1em;
box-sizing: border-box; box-sizing: border-box;
background-color: white; background-color: white;
...@@ -67,6 +66,7 @@ const Popup = styled.div` ...@@ -67,6 +66,7 @@ const Popup = styled.div`
padding: 20px; padding: 20px;
padding-right: 35px; padding-right: 35px;
z-index: 2; z-index: 2;
overflow: hidden;
${({ theme }) => theme.mediaWidth.upToSmall` ${({ theme }) => theme.mediaWidth.upToSmall`
min-width: 290px; min-width: 290px;
...@@ -96,7 +96,7 @@ export default function App() { ...@@ -96,7 +96,7 @@ export default function App() {
return ( return (
<Popup key={item.key}> <Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} /> <StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content} {React.cloneElement(item.content, { popKey: item.key })}
</Popup> </Popup>
) )
})} })}
...@@ -127,7 +127,7 @@ export default function App() { ...@@ -127,7 +127,7 @@ export default function App() {
return ( return (
<Popup key={item.key}> <Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} /> <StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content} {React.cloneElement(item.content, { popKey: item.key })}
</Popup> </Popup>
) )
})} })}
......
...@@ -26,8 +26,8 @@ const QuestionWrapper = styled.div` ...@@ -26,8 +26,8 @@ const QuestionWrapper = styled.div`
` `
const HelpCircleStyled = styled.img` const HelpCircleStyled = styled.img`
height: 24px; height: 20px;
width: 23px; width: 20px;
` `
const fadeIn = keyframes` const fadeIn = keyframes`
......
...@@ -72,8 +72,6 @@ export default function InputSlider({ value, onChange, override }) { ...@@ -72,8 +72,6 @@ export default function InputSlider({ value, onChange, override }) {
function handleChange(e, val) { function handleChange(e, val) {
setInternalVal(val) setInternalVal(val)
console.log(val)
console.log(debouncedInternalValue)
if (val === debouncedInternalValue) { if (val === debouncedInternalValue) {
onChange(e, val) onChange(e, val)
} }
......
This diff is collapsed.
import React from 'react' import React, { useState, useEffect, useRef } from 'react'
import { Link } from '../../theme/components' import { Link } from '../../theme/components'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
import { useWeb3React } from '../../hooks' import { useWeb3React } from '../../hooks'
import { getEtherscanLink } from '../../utils' import { getEtherscanLink } from '../../utils'
import { usePopups } from '../../contexts/Application'
export default function TxnPopup({ hash, success, summary }) { import { CheckCircle, AlertCircle } from 'react-feather'
import styled from 'styled-components'
const Fader = styled.div`
position: absolute;
bottom: 0px;
left: 0px;
width: ${({ count }) => `calc(100% - (100% / ${150 / count}))`};
height: 2px;
background-color: ${({ theme }) => theme.bg3};
transition: width 100ms linear;
`
function useInterval(callback, delay) {
const savedCallback = useRef()
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback
return () => {}
}, [callback])
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current()
}
if (delay !== null) {
let id = setInterval(tick, delay)
return () => clearInterval(id)
}
return () => {}
}, [delay])
}
const delay = 100
export default function TxnPopup({ hash, success, summary, popKey }) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
let [count, setCount] = useState(1)
const [isRunning, setIsRunning] = useState(true)
const [, , removePopup] = usePopups()
useInterval(
() => {
count > 150 && removePopup(popKey)
setCount(count + 1)
},
isRunning ? delay : null
)
return ( return (
<AutoColumn gap="12px"> <AutoRow onMouseEnter={() => setIsRunning(false)} onMouseLeave={() => setIsRunning(true)}>
<TYPE.body>Transaction {success ? 'confirmed.' : 'failed.'}</TYPE.body> {success ? (
<TYPE.green>{summary ? summary : 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}</TYPE.green> <CheckCircle color={'#27AE60'} size={24} style={{ paddingRight: '24px' }} />
<Link href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</Link> ) : (
</AutoColumn> <AlertCircle color={'#FF6871'} size={24} style={{ paddingRight: '24px' }} />
)}
<AutoColumn gap="8px">
<TYPE.body fontWeight={500}>
{summary ? summary : 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}
</TYPE.body>
<Link href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</Link>
</AutoColumn>
<Fader count={count} />
</AutoRow>
) )
} }
...@@ -414,7 +414,6 @@ export function useAllBalances(): Array<TokenAmount> { ...@@ -414,7 +414,6 @@ export function useAllBalances(): Array<TokenAmount> {
let newBalances = {} let newBalances = {}
Object.keys(state[chainId]).map(address => { Object.keys(state[chainId]).map(address => {
return Object.keys(state[chainId][address]).map(tokenAddress => { return Object.keys(state[chainId][address]).map(tokenAddress => {
// console.log(allTokens[tokenAddress])
if (state[chainId][address][tokenAddress].value) { if (state[chainId][address][tokenAddress].value) {
// fix if ETH found in local storage from old storage // fix if ETH found in local storage from old storage
if (tokenAddress === 'ETH') { if (tokenAddress === 'ETH') {
......
...@@ -46,6 +46,8 @@ const BodyWrapper = styled.div` ...@@ -46,6 +46,8 @@ const BodyWrapper = styled.div`
max-width: calc(355px + 4rem); max-width: calc(355px + 4rem);
width: 90%; width: 90%;
} }
z-index: 1;
` `
const Body = styled.div` const Body = styled.div`
...@@ -72,7 +74,6 @@ export default function App() { ...@@ -72,7 +74,6 @@ export default function App() {
</HeaderWrapper> </HeaderWrapper>
<BodyWrapper> <BodyWrapper>
<Popups /> <Popups />
<Body> <Body>
<Web3ReactManager> <Web3ReactManager>
<BrowserRouter> <BrowserRouter>
......
...@@ -14,9 +14,9 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel' ...@@ -14,9 +14,9 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import { Text } from 'rebass' import { Text } from 'rebass'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
import { Plus } from 'react-feather' import { Plus } from 'react-feather'
import { BlueCard, LightCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { ButtonPrimary, ButtonLight } from '../../components/Button' import { ButtonPrimary, ButtonLight } from '../../components/Button'
import { BlueCard, LightCard, GreyCard } from '../../components/Card'
import Row, { AutoRow, RowBetween, RowFlat, RowFixed } from '../../components/Row' import Row, { AutoRow, RowBetween, RowFlat, RowFixed } from '../../components/Row'
import { useToken } from '../../contexts/Tokens' import { useToken } from '../../contexts/Tokens'
...@@ -688,6 +688,11 @@ function AddLiquidity({ token0, token1, step = false }) { ...@@ -688,6 +688,11 @@ function AddLiquidity({ token0, token1, step = false }) {
error={outputError} error={outputError}
pair={pair} pair={pair}
/> />
{tokens[Field.OUTPUT] && tokens[Field.INPUT] && (
<LightCard padding="1rem" borderRadius={'20px'}>
<PriceBar />
</LightCard>
)}
{showOutputApprove ? ( {showOutputApprove ? (
<ButtonLight <ButtonLight
onClick={() => { onClick={() => {
...@@ -721,11 +726,6 @@ function AddLiquidity({ token0, token1, step = false }) { ...@@ -721,11 +726,6 @@ function AddLiquidity({ token0, token1, step = false }) {
{!noLiquidity && ( {!noLiquidity && (
<FixedBottom> <FixedBottom>
<AutoColumn> <AutoColumn>
{tokens[Field.OUTPUT] && (
<GreyCard pt={2} mb={2}>
<PriceBar />
</GreyCard>
)}
<PositionCard <PositionCard
pairAddress={pair?.liquidityToken?.address} pairAddress={pair?.liquidityToken?.address}
token0={tokens[Field.INPUT]} token0={tokens[Field.INPUT]}
......
...@@ -7,7 +7,6 @@ import { TokenAmount, JSBI, Route, WETH, Percent, Token, Pair } from '@uniswap/s ...@@ -7,7 +7,6 @@ import { TokenAmount, JSBI, Route, WETH, Percent, Token, Pair } from '@uniswap/s
import TokenLogo from '../../components/TokenLogo' import TokenLogo from '../../components/TokenLogo'
import DoubleLogo from '../../components/DoubleLogo' import DoubleLogo from '../../components/DoubleLogo'
import PositionCard from '../../components/PositionCard' import PositionCard from '../../components/PositionCard'
// import NumericalInput from '../../components/NumericalInput'
import ConfirmationModal from '../../components/ConfirmationModal' import ConfirmationModal from '../../components/ConfirmationModal'
import CurrencyInputPanel from '../../components/CurrencyInputPanel' import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
...@@ -266,9 +265,6 @@ export default function RemoveLiquidity({ token0, token1 }) { ...@@ -266,9 +265,6 @@ export default function RemoveLiquidity({ token0, token1 }) {
parsedAmounts[Field.LIQUIDITY] && parsedAmounts[Field.LIQUIDITY] &&
pair.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false) pair.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false)
// controlled input for percetange input
// const [percentageInput, setPercentageInput] = useState(0)
// derived percent for advanced mode // derived percent for advanced mode
const derivedPerecent = const derivedPerecent =
userLiquidity && userLiquidity &&
...@@ -285,15 +281,6 @@ export default function RemoveLiquidity({ token0, token1 }) { ...@@ -285,15 +281,6 @@ export default function RemoveLiquidity({ token0, token1 }) {
) )
} }
// update controlled perctenage when derived is updated
// useEffect(() => {
// if (derivedPerecent) {
// setPercentageInput(parseFloat(derivedPerecent))
// } else {
// setPercentageInput(0)
// }
// }, [derivedPerecent])
// get formatted amounts // get formatted amounts
const formattedAmounts = { const formattedAmounts = {
[Field.LIQUIDITY]: [Field.LIQUIDITY]:
...@@ -608,7 +595,7 @@ export default function RemoveLiquidity({ token0, token1 }) { ...@@ -608,7 +595,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
pendingText={pendingText} pendingText={pendingText}
title="You will recieve" title="You will recieve"
/> />
<AutoColumn gap="20px"> <AutoColumn gap="md">
<LightCard> <LightCard>
<AutoColumn gap="20px"> <AutoColumn gap="20px">
<RowBetween> <RowBetween>
......
...@@ -106,6 +106,11 @@ export const TYPE = { ...@@ -106,6 +106,11 @@ export const TYPE = {
{children} {children}
</Text> </Text>
), ),
black: ({ children, ...rest }) => (
<Text fontWeight={500} color={theme().text1} {...rest}>
{children}
</Text>
),
largeHeader: ({ children, ...rest }) => ( largeHeader: ({ children, ...rest }) => (
<Text fontWeight={600} fontSize={24} {...rest}> <Text fontWeight={600} fontSize={24} {...rest}>
{children} {children}
...@@ -122,7 +127,7 @@ export const TYPE = { ...@@ -122,7 +127,7 @@ export const TYPE = {
</Text> </Text>
), ),
body: ({ children, ...rest }) => ( body: ({ children, ...rest }) => (
<Text fontWeight={400} fontSize={16} color={'#888D9B'} {...rest}> <Text fontWeight={400} fontSize={16} color={'#191B1F'} {...rest}>
{children} {children}
</Text> </Text>
), ),
...@@ -131,6 +136,11 @@ export const TYPE = { ...@@ -131,6 +136,11 @@ export const TYPE = {
{children} {children}
</Text> </Text>
), ),
yellow: ({ children, ...rest }) => (
<Text fontWeight={500} color={theme().yellow2} {...rest}>
{children}
</Text>
),
green: ({ children, ...rest }) => ( green: ({ children, ...rest }) => (
<Text fontWeight={500} color={theme().green1} {...rest}> <Text fontWeight={500} color={theme().green1} {...rest}>
{children} {children}
......
...@@ -12927,10 +12927,12 @@ react-error-overlay@^6.0.4: ...@@ -12927,10 +12927,12 @@ react-error-overlay@^6.0.4:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.4.tgz#0d165d6d27488e660bc08e57bdabaad741366f7a" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.4.tgz#0d165d6d27488e660bc08e57bdabaad741366f7a"
integrity sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA== integrity sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==
react-feather@^1.1.6: react-feather@^2.0.8:
version "1.1.6" version "2.0.8"
resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-1.1.6.tgz#2a547e3d5cd5e383d3da0128d593cbdb3c1b32f7" resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-2.0.8.tgz#455baf1470f756a57e2ad6c72545444ce5925781"
integrity sha512-iCofWhTjX+vQwvDmg7o6vg0XrUg1c41yBDZG+l83nz1FiCsleJoUgd3O+kHpOeWMXuPrRIFfCixvcqyOLGOgIg== integrity sha512-J0dCEOvOxpovHeOVj3+8mAhN3/UERTfX6rSxnV6x4E+0s+STY536jhSjRfpSvTQA0SSFjYr4KrpPfdsLmK+zZg==
dependencies:
prop-types "^15.7.2"
react-focus-lock@^1.17.7: react-focus-lock@^1.17.7:
version "1.19.1" version "1.19.1"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment