feat: debounce input sliders (#784)
* feat: debounce input sliders * fix: fixed the debounce function
This commit is contained in:
parent
6d5e7c7325
commit
6ac7708ca5
@ -24,6 +24,7 @@ interface Props {
|
||||
onClose: () => void
|
||||
onChange: (value: BigNumber) => void
|
||||
onAction: (value: BigNumber, isMax: boolean) => void
|
||||
onDebounce: () => void
|
||||
}
|
||||
|
||||
export default function AssetAmountSelectActionModal(props: Props) {
|
||||
@ -36,6 +37,7 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
onClose,
|
||||
onChange,
|
||||
onAction,
|
||||
onDebounce,
|
||||
} = props
|
||||
const [amount, setAmount] = useState(BN_ZERO)
|
||||
const maxAmount = BN(coinBalances.find(byDenom(asset.denom))?.amount ?? 0)
|
||||
@ -74,6 +76,7 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
<TokenInputWithSlider
|
||||
asset={asset}
|
||||
onChange={handleAmountChange}
|
||||
onDebounce={onDebounce}
|
||||
amount={amount}
|
||||
max={maxAmount}
|
||||
hasSelect
|
||||
|
@ -1,8 +1,8 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import AccountSummary from 'components/account/AccountSummary'
|
||||
import AssetImage from 'components/common/assets/AssetImage'
|
||||
import Modal from 'components/Modals/Modal'
|
||||
import AccountSummaryInModal from 'components/account/AccountSummary/AccountSummaryInModal'
|
||||
import Button from 'components/common/Button'
|
||||
import Card from 'components/common/Card'
|
||||
import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
@ -13,7 +13,7 @@ import Switch from 'components/common/Switch'
|
||||
import Text from 'components/common/Text'
|
||||
import TitleAndSubCell from 'components/common/TitleAndSubCell'
|
||||
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
|
||||
import Modal from 'components/Modals/Modal'
|
||||
import AssetImage from 'components/common/assets/AssetImage'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
@ -29,7 +29,6 @@ import { byDenom } from 'utils/array'
|
||||
import { formatPercent } from 'utils/formatters'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { getDebtAmountWithInterest } from 'utils/tokens'
|
||||
import AccountSummaryInModal from 'components/account/AccountSummary/AccountSummaryInModal'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
@ -92,6 +91,7 @@ function BorrowModal(props: Props) {
|
||||
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(account)
|
||||
const totalDebt = BN(getDebtAmount(modal))
|
||||
const accountDebt = account.debts.find(byDenom(asset.denom))?.amount ?? BN_ZERO
|
||||
const markets = useMarkets()
|
||||
|
||||
const [depositBalance, lendBalance] = useMemo(
|
||||
@ -102,34 +102,34 @@ function BorrowModal(props: Props) {
|
||||
[account, asset.denom],
|
||||
)
|
||||
|
||||
const totalDebtRepayAmount = useMemo(
|
||||
() => getDebtAmountWithInterest(totalDebt, apy),
|
||||
[totalDebt, apy],
|
||||
const accountDebtWithInterest = useMemo(
|
||||
() => getDebtAmountWithInterest(accountDebt, apy),
|
||||
[accountDebt, apy],
|
||||
)
|
||||
|
||||
const overpayExeedsCap = useMemo(() => {
|
||||
const marketAsset = markets.find((market) => market.asset.denom === asset.denom)
|
||||
if (!marketAsset) return
|
||||
const overpayAmount = totalDebtRepayAmount.minus(totalDebt)
|
||||
const overpayAmount = accountDebtWithInterest.minus(accountDebt)
|
||||
const marketCapAfterOverpay = marketAsset.cap.used.plus(overpayAmount)
|
||||
|
||||
return marketAsset.cap.max.isLessThanOrEqualTo(marketCapAfterOverpay)
|
||||
}, [markets, asset.denom, totalDebt, totalDebtRepayAmount])
|
||||
}, [markets, asset.denom, accountDebt, accountDebtWithInterest])
|
||||
|
||||
const maxRepayAmount = useMemo(() => {
|
||||
const maxBalance = repayFromWallet
|
||||
? BN(walletBalances.find(byDenom(asset.denom))?.amount ?? 0)
|
||||
: depositBalance.plus(lendBalance)
|
||||
return isRepay
|
||||
? BigNumber.min(maxBalance, overpayExeedsCap ? totalDebt : totalDebtRepayAmount)
|
||||
? BigNumber.min(maxBalance, overpayExeedsCap ? accountDebt : accountDebtWithInterest)
|
||||
: BN_ZERO
|
||||
}, [
|
||||
depositBalance,
|
||||
lendBalance,
|
||||
isRepay,
|
||||
totalDebtRepayAmount,
|
||||
accountDebtWithInterest,
|
||||
overpayExeedsCap,
|
||||
totalDebt,
|
||||
accountDebt,
|
||||
walletBalances,
|
||||
asset.denom,
|
||||
repayFromWallet,
|
||||
@ -149,7 +149,7 @@ function BorrowModal(props: Props) {
|
||||
repay({
|
||||
accountId: account.id,
|
||||
coin: BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
||||
accountBalance: amount.isEqualTo(totalDebtRepayAmount),
|
||||
accountBalance: amount.isEqualTo(accountDebtWithInterest),
|
||||
lend: repayFromWallet ? BNCoin.fromDenomAndBigNumber(asset.denom, BN_ZERO) : lend,
|
||||
fromWallet: repayFromWallet,
|
||||
})
|
||||
@ -172,17 +172,39 @@ function BorrowModal(props: Props) {
|
||||
|
||||
const handleChange = useCallback(
|
||||
(newAmount: BigNumber) => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, newAmount)
|
||||
if (!amount.isEqualTo(newAmount)) setAmount(newAmount)
|
||||
if (!isRepay) return
|
||||
const repayCoin = coin.amount.isGreaterThan(totalDebt)
|
||||
? BNCoin.fromDenomAndBigNumber(asset.denom, totalDebt)
|
||||
: coin
|
||||
simulateRepay(repayCoin, repayFromWallet)
|
||||
},
|
||||
[amount, asset.denom, isRepay, simulateRepay, totalDebt, repayFromWallet],
|
||||
[amount, setAmount],
|
||||
)
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
if (isRepay) {
|
||||
const repayCoin = BNCoin.fromDenomAndBigNumber(
|
||||
asset.denom,
|
||||
amount.isGreaterThan(accountDebt) ? accountDebt : amount,
|
||||
)
|
||||
simulateRepay(repayCoin, repayFromWallet)
|
||||
} else {
|
||||
const borrowCoin = BNCoin.fromDenomAndBigNumber(
|
||||
asset.denom,
|
||||
amount.isGreaterThan(max) ? max : amount,
|
||||
)
|
||||
const target = borrowToWallet ? 'wallet' : isAutoLendEnabled ? 'lend' : 'deposit'
|
||||
simulateBorrow(target, borrowCoin)
|
||||
}
|
||||
}, [
|
||||
amount,
|
||||
isRepay,
|
||||
repayFromWallet,
|
||||
maxRepayAmount,
|
||||
max,
|
||||
asset,
|
||||
borrowToWallet,
|
||||
isAutoLendEnabled,
|
||||
simulateBorrow,
|
||||
simulateRepay,
|
||||
])
|
||||
|
||||
const maxBorrow = useMemo(() => {
|
||||
const maxBorrowAmount = isRepay
|
||||
? BN_ZERO
|
||||
@ -209,13 +231,6 @@ function BorrowModal(props: Props) {
|
||||
setAmount(max)
|
||||
}, [amount, max, handleChange])
|
||||
|
||||
useEffect(() => {
|
||||
if (isRepay) return
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, amount.isGreaterThan(max) ? max : amount)
|
||||
const target = borrowToWallet ? 'wallet' : isAutoLendEnabled ? 'lend' : 'deposit'
|
||||
simulateBorrow(target, coin)
|
||||
}, [isRepay, borrowToWallet, isAutoLendEnabled, simulateBorrow, asset, amount, max])
|
||||
|
||||
if (!modal || !asset) return null
|
||||
return (
|
||||
<Modal
|
||||
@ -257,7 +272,7 @@ function BorrowModal(props: Props) {
|
||||
/>
|
||||
</div>
|
||||
<Text size='xs' className='text-white/50' tag='span'>
|
||||
Borrowed
|
||||
Total Borrowed
|
||||
</Text>
|
||||
</div>
|
||||
</>
|
||||
@ -294,6 +309,7 @@ function BorrowModal(props: Props) {
|
||||
<TokenInputWithSlider
|
||||
asset={asset}
|
||||
onChange={handleChange}
|
||||
onDebounce={onDebounce}
|
||||
amount={amount}
|
||||
max={max}
|
||||
disabled={max.isZero()}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import Button from 'components/common/Button'
|
||||
import Divider from 'components/common/Divider'
|
||||
@ -86,17 +86,10 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
useStore.setState({ fundAndWithdrawModal: null })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const onDebounce = useCallback(() => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(currentAsset.denom, withdrawAmount.plus(debtAmount))
|
||||
simulateWithdraw(withdrawWithBorrowing, coin)
|
||||
}, [
|
||||
amount,
|
||||
withdrawWithBorrowing,
|
||||
currentAsset.denom,
|
||||
debtAmount,
|
||||
simulateWithdraw,
|
||||
withdrawAmount,
|
||||
])
|
||||
}, [withdrawWithBorrowing, currentAsset.denom, debtAmount, simulateWithdraw, withdrawAmount])
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -104,6 +97,7 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
<TokenInputWithSlider
|
||||
asset={currentAsset}
|
||||
onChange={onChangeAmount}
|
||||
onDebounce={onDebounce}
|
||||
onChangeAsset={(asset) => {
|
||||
setAmount(BN_ZERO)
|
||||
setWithdrawWithBorrowing(false)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
||||
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
||||
@ -27,6 +27,7 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
const reclaim = useStore((s) => s.reclaim)
|
||||
const { close } = useLendAndReclaimModal()
|
||||
const { simulateLending } = useUpdatedAccount(currentAccount)
|
||||
const [coin, setCoin] = useState<BNCoin>()
|
||||
|
||||
const { data, action } = config
|
||||
const { asset } = data
|
||||
@ -37,12 +38,16 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
|
||||
const handleAmountChange = useCallback(
|
||||
(value: BigNumber) => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, value)
|
||||
simulateLending(isLendAction, coin)
|
||||
setCoin(BNCoin.fromDenomAndBigNumber(asset.denom, value))
|
||||
},
|
||||
[asset.denom, isLendAction, simulateLending],
|
||||
[asset.denom],
|
||||
)
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
if (!coin) return
|
||||
simulateLending(isLendAction, coin)
|
||||
}, [coin, isLendAction, simulateLending])
|
||||
|
||||
const handleAction = useCallback(
|
||||
(value: BigNumber, isMax: boolean) => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, value)
|
||||
@ -70,6 +75,7 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
onClose={close}
|
||||
onAction={handleAction}
|
||||
onChange={handleAmountChange}
|
||||
onDebounce={onDebounce}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -95,10 +95,6 @@ export default function AccountFundContent(props: Props) {
|
||||
}
|
||||
}, [baseBalance])
|
||||
|
||||
useEffect(() => {
|
||||
simulateDeposits(isLending ? 'lend' : 'deposit', fundingAssets)
|
||||
}, [isLending, fundingAssets, simulateDeposits])
|
||||
|
||||
useEffect(() => {
|
||||
const currentSelectedDenom = fundingAssets.map((asset) => asset.denom)
|
||||
|
||||
@ -125,6 +121,10 @@ export default function AccountFundContent(props: Props) {
|
||||
})
|
||||
}, [])
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
simulateDeposits(isLending ? 'lend' : 'deposit', fundingAssets)
|
||||
}, [isLending, fundingAssets, simulateDeposits])
|
||||
|
||||
const depositCapReachedCoins = useMemo(() => {
|
||||
const depositCapReachedCoins: BNCoin[] = []
|
||||
fundingAssets.forEach((asset) => {
|
||||
@ -159,6 +159,7 @@ export default function AccountFundContent(props: Props) {
|
||||
amount={coin.amount ?? BN_ZERO}
|
||||
isConfirming={isConfirming}
|
||||
updateFundingAssets={updateFundingAssets}
|
||||
onDebounce={onDebounce}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ interface Props {
|
||||
denom: string
|
||||
isConfirming: boolean
|
||||
updateFundingAssets: (amount: BigNumber, denom: string) => void
|
||||
onDebounce: () => void
|
||||
}
|
||||
|
||||
export default function AccountFundRow(props: Props) {
|
||||
@ -23,6 +24,7 @@ export default function AccountFundRow(props: Props) {
|
||||
<TokenInputWithSlider
|
||||
asset={asset}
|
||||
onChange={(amount) => props.updateFundingAssets(amount, asset.denom)}
|
||||
onDebounce={props.onDebounce}
|
||||
amount={props.amount}
|
||||
max={balance}
|
||||
balances={props.balances}
|
||||
|
@ -11,7 +11,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function BorrowActionButtons(props: Props) {
|
||||
const { asset, debt } = props.data
|
||||
const { asset, accountDebt } = props.data
|
||||
const marketAssets = useMarketEnabledAssets()
|
||||
const currentAsset = marketAssets.find((a) => a.denom === asset.denom)
|
||||
|
||||
@ -33,10 +33,10 @@ export default function BorrowActionButtons(props: Props) {
|
||||
leftIcon={<Plus className='w-3' />}
|
||||
onClick={borrowHandler}
|
||||
color='secondary'
|
||||
text={debt ? 'Borrow more' : 'Borrow'}
|
||||
className='min-w-40 text-center'
|
||||
text={accountDebt ? 'Borrow more' : 'Borrow'}
|
||||
className='text-center min-w-40'
|
||||
/>
|
||||
{debt && (
|
||||
{accountDebt && (
|
||||
<Button color='tertiary' leftIcon={<HandCoins />} text='Repay' onClick={repayHandler} />
|
||||
)}
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import classNames from 'classnames'
|
||||
import { ChangeEvent, useCallback } from 'react'
|
||||
import debounce from 'lodash.debounce'
|
||||
import { ChangeEvent, useCallback, useMemo } from 'react'
|
||||
|
||||
import InputOverlay from 'components/common/LeverageSlider/InputOverlay'
|
||||
|
||||
@ -13,20 +14,41 @@ type Props = {
|
||||
marginThreshold?: number
|
||||
wrapperClassName?: string
|
||||
onChange: (value: number) => void
|
||||
onDebounce?: () => void
|
||||
onBlur?: () => void
|
||||
type: LeverageSliderType
|
||||
}
|
||||
|
||||
export type LeverageSliderType = 'margin' | 'long' | 'short'
|
||||
function LeverageSlider(props: Props) {
|
||||
const { value, max, onChange, wrapperClassName, disabled, marginThreshold, onBlur, type } = props
|
||||
const {
|
||||
value,
|
||||
max,
|
||||
onChange,
|
||||
wrapperClassName,
|
||||
disabled,
|
||||
marginThreshold,
|
||||
onBlur,
|
||||
type,
|
||||
onDebounce,
|
||||
} = props
|
||||
const min = props.min ?? 0
|
||||
|
||||
const debounceFunction = useMemo(
|
||||
() =>
|
||||
debounce(() => {
|
||||
if (!onDebounce) return
|
||||
onDebounce()
|
||||
}, 250),
|
||||
[onDebounce],
|
||||
)
|
||||
|
||||
const handleOnChange = useCallback(
|
||||
(event: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(parseFloat(event.target.value))
|
||||
debounceFunction()
|
||||
},
|
||||
[onChange],
|
||||
[onChange, debounceFunction],
|
||||
)
|
||||
|
||||
const markPosPercent = 100 / (max / (marginThreshold ?? 1))
|
||||
|
@ -1,4 +1,5 @@
|
||||
import classNames from 'classnames'
|
||||
import debounce from 'lodash.debounce'
|
||||
import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import Draggable from 'react-draggable'
|
||||
|
||||
@ -19,6 +20,7 @@ const colors = {
|
||||
type Props = {
|
||||
value: number
|
||||
onChange: (value: number) => void
|
||||
onDebounce?: () => void
|
||||
leverage?: {
|
||||
current: number
|
||||
max: number
|
||||
@ -28,6 +30,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export default function Slider(props: Props) {
|
||||
const { value, onChange, onDebounce, leverage, className, disabled } = props
|
||||
const [showTooltip, setShowTooltip] = useToggle()
|
||||
const [sliderRect, setSliderRect] = useState({ width: 0, left: 0, right: 0 })
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
@ -52,6 +55,20 @@ export default function Slider(props: Props) {
|
||||
}
|
||||
}, [sliderRect.left, sliderRect.right, sliderRect.width])
|
||||
|
||||
const debounceFunction = useMemo(
|
||||
() =>
|
||||
debounce(() => {
|
||||
if (!onDebounce) return
|
||||
onDebounce()
|
||||
}, 250),
|
||||
[onDebounce],
|
||||
)
|
||||
|
||||
function handleOnChange(value: number) {
|
||||
onChange(value)
|
||||
debounceFunction()
|
||||
}
|
||||
|
||||
function handleDrag(e: any) {
|
||||
if (!isDragging) {
|
||||
setIsDragging(true)
|
||||
@ -60,24 +77,24 @@ export default function Slider(props: Props) {
|
||||
const current: number = e.clientX
|
||||
|
||||
if (current < sliderRect.left) {
|
||||
props.onChange(0)
|
||||
handleOnChange(0)
|
||||
return
|
||||
}
|
||||
|
||||
if (current > sliderRect.right) {
|
||||
props.onChange(100)
|
||||
handleOnChange(100)
|
||||
return
|
||||
}
|
||||
|
||||
const value = Math.round(((current - sliderRect.left) / sliderRect.width) * 100)
|
||||
const currentValue = Math.round(((current - sliderRect.left) / sliderRect.width) * 100)
|
||||
|
||||
if (value !== props.value) {
|
||||
props.onChange(value)
|
||||
if (currentValue !== value) {
|
||||
handleOnChange(currentValue)
|
||||
}
|
||||
}
|
||||
|
||||
function handleSliderClick(e: ChangeEvent<HTMLInputElement>) {
|
||||
props.onChange(Number(e.target.value))
|
||||
handleOnChange(Number(e.target.value))
|
||||
}
|
||||
|
||||
function handleShowTooltip() {
|
||||
@ -89,21 +106,22 @@ export default function Slider(props: Props) {
|
||||
}
|
||||
|
||||
function getActiveIndex() {
|
||||
if (props.value >= 100) return '5'
|
||||
if (props.value >= 75) return '4'
|
||||
if (props.value >= 50) return '3'
|
||||
if (props.value >= 25) return '2'
|
||||
if (value >= 100) return '5'
|
||||
if (value >= 75) return '4'
|
||||
if (value >= 50) return '3'
|
||||
if (value >= 25) return '2'
|
||||
return '1'
|
||||
}
|
||||
|
||||
const DraggableElement: any = Draggable
|
||||
|
||||
const [positionOffset, position] = useMemo(() => {
|
||||
debounceFunction()
|
||||
return [
|
||||
{ x: (props.value / 100) * -12, y: 0 },
|
||||
{ x: (sliderRect.width / 100) * props.value, y: -2 },
|
||||
{ x: (value / 100) * -12, y: 0 },
|
||||
{ x: (sliderRect.width / 100) * value, y: -2 },
|
||||
]
|
||||
}, [props.value, sliderRect.width])
|
||||
}, [value, sliderRect.width])
|
||||
|
||||
useEffect(() => {
|
||||
handleSliderRect()
|
||||
@ -115,60 +133,60 @@ export default function Slider(props: Props) {
|
||||
ref={ref}
|
||||
className={classNames(
|
||||
'relative min-h-3 w-full transition-opacity',
|
||||
props.className,
|
||||
props.disabled && 'pointer-events-none',
|
||||
className,
|
||||
disabled && 'pointer-events-none',
|
||||
)}
|
||||
onMouseEnter={handleSliderRect}
|
||||
>
|
||||
<input
|
||||
type='range'
|
||||
value={props.value}
|
||||
value={value}
|
||||
onChange={handleSliderClick}
|
||||
onMouseDown={handleShowTooltip}
|
||||
className='absolute z-2 w-full hover:cursor-pointer appearance-none bg-transparent [&::-webkit-slider-thumb]:h-3 [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:appearance-none'
|
||||
/>
|
||||
<div className='absolute flex items-center w-full gap-1.5'>
|
||||
<Mark
|
||||
onClick={props.onChange}
|
||||
onClick={() => handleOnChange(0)}
|
||||
value={0}
|
||||
sliderValue={props.value}
|
||||
disabled={props.disabled}
|
||||
sliderValue={value}
|
||||
disabled={disabled}
|
||||
style={{ backgroundColor: colors['1'] }}
|
||||
/>
|
||||
<Track maxValue={23} sliderValue={props.value} bg='before:gradient-slider-1' />
|
||||
<Track maxValue={23} sliderValue={value} bg='before:gradient-slider-1' />
|
||||
<Mark
|
||||
onClick={props.onChange}
|
||||
onClick={() => handleOnChange(25)}
|
||||
value={25}
|
||||
sliderValue={props.value}
|
||||
disabled={props.disabled}
|
||||
sliderValue={value}
|
||||
disabled={disabled}
|
||||
style={{ backgroundColor: colors['2'] }}
|
||||
/>
|
||||
<Track maxValue={48} sliderValue={props.value} bg='before:gradient-slider-2' />
|
||||
<Track maxValue={48} sliderValue={value} bg='before:gradient-slider-2' />
|
||||
<Mark
|
||||
onClick={props.onChange}
|
||||
onClick={() => handleOnChange(50)}
|
||||
value={50}
|
||||
sliderValue={props.value}
|
||||
disabled={props.disabled}
|
||||
sliderValue={value}
|
||||
disabled={disabled}
|
||||
style={{ backgroundColor: colors['3'] }}
|
||||
/>
|
||||
<Track maxValue={73} sliderValue={props.value} bg='before:gradient-slider-3' />
|
||||
<Track maxValue={73} sliderValue={value} bg='before:gradient-slider-3' />
|
||||
<Mark
|
||||
onClick={props.onChange}
|
||||
onClick={() => handleOnChange(75)}
|
||||
value={75}
|
||||
sliderValue={props.value}
|
||||
disabled={props.disabled}
|
||||
sliderValue={value}
|
||||
disabled={disabled}
|
||||
style={{ backgroundColor: colors['4'] }}
|
||||
/>
|
||||
<Track maxValue={98} sliderValue={props.value} bg='before:gradient-slider-4' />
|
||||
<Track maxValue={98} sliderValue={value} bg='before:gradient-slider-4' />
|
||||
<Mark
|
||||
onClick={props.onChange}
|
||||
onClick={() => handleOnChange(100)}
|
||||
value={100}
|
||||
sliderValue={props.value}
|
||||
disabled={props.disabled}
|
||||
sliderValue={value}
|
||||
disabled={disabled}
|
||||
style={{ backgroundColor: colors['5'] }}
|
||||
/>
|
||||
</div>
|
||||
{!props.disabled && (
|
||||
{!disabled && (
|
||||
<div onMouseEnter={handleShowTooltip} onMouseLeave={handleHideTooltip}>
|
||||
<DraggableElement
|
||||
nodeRef={nodeRef}
|
||||
@ -187,12 +205,12 @@ export default function Slider(props: Props) {
|
||||
)}
|
||||
style={{ background: colors[getActiveIndex()] }}
|
||||
/>
|
||||
{props.leverage ? (
|
||||
{leverage ? (
|
||||
<div className='pt-2.5'>
|
||||
<LeverageLabel
|
||||
leverage={props.leverage.current}
|
||||
leverage={leverage.current}
|
||||
decimals={1}
|
||||
className={props.leverage.current >= 10 ? '-translate-x-2' : '-translate-x-1'}
|
||||
className={leverage.current >= 10 ? '-translate-x-2' : '-translate-x-1'}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
@ -203,7 +221,7 @@ export default function Slider(props: Props) {
|
||||
'absolute h-2 -translate-x-1/2 -bottom-2 left-1/2 -z-1 text-fuchsia',
|
||||
)}
|
||||
/>
|
||||
{props.value.toFixed(0)}%
|
||||
{value.toFixed(0)}%
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
@ -212,19 +230,19 @@ export default function Slider(props: Props) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{props.leverage && (
|
||||
{leverage && (
|
||||
<div className='flex justify-between pt-2'>
|
||||
<LeverageLabel
|
||||
leverage={1}
|
||||
decimals={0}
|
||||
className='-translate-x-0.5'
|
||||
style={{ opacity: props.value < 5 ? 0 : 1 }}
|
||||
style={{ opacity: value < 5 ? 0 : 1 }}
|
||||
/>
|
||||
<LeverageLabel
|
||||
leverage={props.leverage.max || 1}
|
||||
leverage={leverage.max || 1}
|
||||
decimals={0}
|
||||
className='translate-x-1.5'
|
||||
style={{ opacity: props.value > 95 ? 0 : 1 }}
|
||||
style={{ opacity: value > 95 ? 0 : 1 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
@ -12,6 +12,7 @@ interface Props {
|
||||
asset: Asset
|
||||
max: BigNumber
|
||||
onChange: (amount: BigNumber) => void
|
||||
onDebounce?: () => void
|
||||
accountId?: string
|
||||
balances?: BNCoin[]
|
||||
className?: string
|
||||
@ -37,6 +38,11 @@ export default function TokenInputWithSlider(props: Props) {
|
||||
props.onChange(newAmount)
|
||||
}
|
||||
|
||||
function onDebounce() {
|
||||
if (!props.onDebounce) return
|
||||
props.onDebounce()
|
||||
}
|
||||
|
||||
function onChangeAmount(newAmount: BigNumber) {
|
||||
setAmount(newAmount)
|
||||
setPercentage(BN(newAmount).dividedBy(props.max).multipliedBy(100).toNumber())
|
||||
@ -76,6 +82,7 @@ export default function TokenInputWithSlider(props: Props) {
|
||||
<Slider
|
||||
value={percentage || 0}
|
||||
onChange={(value) => onChangeSlider(value)}
|
||||
onDebounce={onDebounce}
|
||||
disabled={props.disabled}
|
||||
leverage={props.leverage}
|
||||
/>
|
||||
|
@ -61,6 +61,10 @@ export function PerpsModule() {
|
||||
previousTradeDirection,
|
||||
])
|
||||
|
||||
const onDebounce = useCallback(() => {
|
||||
// TODO: Implement debounced simulation
|
||||
}, [])
|
||||
|
||||
const setLeverage = useCallback((leverage: number) => {
|
||||
// TODO: Implement leverage setting
|
||||
}, [])
|
||||
@ -116,6 +120,7 @@ export function PerpsModule() {
|
||||
max={10}
|
||||
value={leverage}
|
||||
onChange={setLeverage}
|
||||
onDebounce={onDebounce}
|
||||
type={tradeDirection}
|
||||
/>
|
||||
<LeverageButtons />
|
||||
|
@ -201,7 +201,7 @@ export default function SwapForm(props: Props) {
|
||||
isAutoLendEnabled && !isAutoRepayChecked ? 'lend' : 'deposit',
|
||||
isAutoRepayChecked,
|
||||
)
|
||||
}, 100),
|
||||
}, 250),
|
||||
[simulateTrade, isAutoLendEnabled, isAutoRepayChecked],
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user