MP-1566: Deposit funds modal (#33)

* feat: deposit account modal

* style: button default colors to match wireframes

* react-query-devtools package added

* slider moved to separate component
This commit is contained in:
Gustavo Mauricio 2022-10-25 11:31:36 +01:00 committed by GitHub
parent d3a1e9f3f1
commit 55d0910d10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 425 additions and 324 deletions

View File

@ -1,7 +1,6 @@
import React, { useMemo, useState } from 'react'
import { XMarkIcon } from '@heroicons/react/24/solid'
import { toast } from 'react-toastify'
import * as Slider from '@radix-ui/react-slider'
import Button from 'components/Button'
import Container from 'components/Container'
@ -17,6 +16,7 @@ import Tooltip from 'components/Tooltip'
import ContainerSecondary from 'components/ContainerSecondary'
import Spinner from 'components/Spinner'
import useCalculateMaxBorrowAmount from 'hooks/useCalculateMaxBorrowAmount'
import Slider from 'components/Slider'
const BorrowFunds = ({ tokenDenom, onClose }: any) => {
const [amount, setAmount] = useState(0)
@ -113,14 +113,10 @@ const BorrowFunds = ({ tokenDenom, onClose }: any) => {
</div>
</ContainerSecondary>
<ContainerSecondary>
<div className="relative mb-4 flex flex-1 items-center">
<Slider.Root
className="relative flex h-[20px] w-full cursor-pointer touch-none select-none items-center"
value={[percentageValue]}
min={0}
max={100}
step={1}
onValueChange={(value) => {
<Slider
className="mb-6"
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(tokenDenom)
// limit decimal precision based on token contract decimals
@ -128,21 +124,8 @@ const BorrowFunds = ({ tokenDenom, onClose }: any) => {
setAmount(newAmount)
}}
>
<Slider.Track className="relative h-[6px] grow rounded-full bg-gray-400">
<Slider.Range className="absolute h-[100%] rounded-full bg-blue-600" />
</Slider.Track>
<Slider.Thumb className="flex h-[20px] w-[20px] items-center justify-center rounded-full bg-white !outline-none">
<div className="relative top-5 text-xs">{percentageValue.toFixed(0)}%</div>
</Slider.Thumb>
</Slider.Root>
<button
className="ml-4 rounded-md bg-blue-600 py-1 px-2 text-xs font-semibold text-white"
onClick={() => setAmount(maxValue)}
>
MAX
</button>
</div>
onMaxClick={() => setAmount(maxValue)}
/>
</ContainerSecondary>
<ContainerSecondary className="flex items-center justify-between">
<div className="flex">

View File

@ -1,7 +1,6 @@
import React, { useMemo, useState } from 'react'
import { XMarkIcon } from '@heroicons/react/24/solid'
import { toast } from 'react-toastify'
import * as Slider from '@radix-ui/react-slider'
import Button from 'components/Button'
import Container from 'components/Container'
@ -13,6 +12,7 @@ import BigNumber from 'bignumber.js'
import useAllBalances from 'hooks/useAllBalances'
import ContainerSecondary from 'components/ContainerSecondary'
import Spinner from 'components/Spinner'
import Slider from 'components/Slider'
const RepayFunds = ({ tokenDenom, amount: repayAmount, onClose }: any) => {
const [amount, setAmount] = useState(0)
@ -91,14 +91,10 @@ const RepayFunds = ({ tokenDenom, amount: repayAmount, onClose }: any) => {
</div>
</ContainerSecondary>
<ContainerSecondary>
<div className="relative mb-4 flex flex-1 items-center">
<Slider.Root
className="relative flex h-[20px] w-full cursor-pointer touch-none select-none items-center"
value={[percentageValue]}
min={0}
max={100}
step={1}
onValueChange={(value) => {
<Slider
className="mb-6"
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(tokenDenom)
// limit decimal precision based on token contract decimals
@ -106,21 +102,8 @@ const RepayFunds = ({ tokenDenom, amount: repayAmount, onClose }: any) => {
setAmount(newAmount)
}}
>
<Slider.Track className="relative h-[6px] grow rounded-full bg-gray-400">
<Slider.Range className="absolute h-[100%] rounded-full bg-blue-600" />
</Slider.Track>
<Slider.Thumb className="flex h-[20px] w-[20px] items-center justify-center rounded-full bg-white !outline-none">
<div className="relative top-5 text-xs">{percentageValue.toFixed(0)}%</div>
</Slider.Thumb>
</Slider.Root>
<button
className="ml-4 rounded-md bg-blue-600 py-1 px-2 text-xs font-semibold text-white"
onClick={() => setAmount(maxValue)}
>
MAX
</button>
</div>
onMaxClick={() => setAmount(maxValue)}
/>
</ContainerSecondary>
</div>
<Button className="w-full" onClick={handleSubmit} disabled={isSubmitDisabled}>

View File

@ -12,7 +12,7 @@ const Button = React.forwardRef<any, Props>(
<button
ref={ref}
onClick={onClick}
className={`overflow-hidden text-ellipsis rounded-3xl bg-green-500 py-2 px-5 text-sm font-semibold text-white ${className} ${
className={`overflow-hidden text-ellipsis rounded-md bg-blue-500 py-2 px-5 text-sm font-semibold text-white ${className} ${
disabled ? 'opacity-40' : ''
}`}
disabled={disabled}

View File

@ -1,169 +0,0 @@
import React, { useEffect, useMemo, useState } from 'react'
import * as Slider from '@radix-ui/react-slider'
import BigNumber from 'bignumber.js'
import { Switch } from '@headlessui/react'
import useLocalStorageState from 'use-local-storage-state'
import Button from '../Button'
import useAllowedCoins from 'hooks/useAllowedCoins'
import useDepositCreditAccount from 'hooks/useDepositCreditAccount'
import useCreditManagerStore from 'stores/useCreditManagerStore'
import useAllBalances from 'hooks/useAllBalances'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
import ContainerSecondary from 'components/ContainerSecondary'
const FundAccount = () => {
const [amount, setAmount] = useState(0)
const [selectedToken, setSelectedToken] = useState('')
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
const [lendAssets, setLendAssets] = useLocalStorageState(`lendAssets_${selectedAccount}`, {
defaultValue: false,
})
const { data: balancesData } = useAllBalances()
const { data: allowedCoinsData, isLoading: isLoadingAllowedCoins } = useAllowedCoins()
const { mutate } = useDepositCreditAccount(
selectedAccount || '',
selectedToken,
BigNumber(amount)
.times(10 ** getTokenDecimals(selectedToken))
.toNumber()
)
useEffect(() => {
if (allowedCoinsData && allowedCoinsData.length > 0) {
// initialize selected token when allowedCoins fetch data is available
setSelectedToken(allowedCoinsData[0])
}
}, [allowedCoinsData])
const walletAmount = useMemo(() => {
if (!selectedToken) return 0
return BigNumber(balancesData?.find((balance) => balance.denom === selectedToken)?.amount ?? 0)
.div(10 ** getTokenDecimals(selectedToken))
.toNumber()
}, [balancesData, selectedToken])
const handleValueChange = (value: number) => {
if (value > walletAmount) {
setAmount(walletAmount)
return
}
setAmount(value)
}
const maxValue = walletAmount
const percentageValue = isNaN(amount) ? 0 : (amount * 100) / maxValue
return (
<>
<ContainerSecondary className="mb-2 p-3">
<p className="mb-6 text-sm">
Transfer assets from your injective wallet to your Mars credit account. If you dont have
any assets in your injective wallet use the injective bridge to transfer funds to your
injective wallet.
</p>
{isLoadingAllowedCoins ? (
<p>Loading...</p>
) : (
<>
<div className="mb-4 text-sm">
<div className="mb-1 flex justify-between">
<div>Asset:</div>
<select
className="bg-transparent"
onChange={(e) => {
setSelectedToken(e.target.value)
if (e.target.value !== selectedToken) setAmount(0)
}}
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
</option>
))}
</select>
</div>
<div className="flex justify-between">
<div>Amount:</div>
<input
type="number"
className="border border-black/50 bg-transparent px-2"
value={amount}
onChange={(e) => handleValueChange(e.target.valueAsNumber)}
/>
</div>
</div>
<p className="text-sm">In wallet: {walletAmount.toLocaleString()}</p>
{/* SLIDER - initial implementation to test functionality */}
{/* TODO: will need to be revamped later on */}
<div className="relative mb-6 flex flex-1 items-center">
<Slider.Root
className="relative flex h-[20px] w-full cursor-pointer touch-none select-none items-center"
value={[percentageValue]}
min={0}
max={100}
step={1}
onValueChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(selectedToken)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))
setAmount(newAmount)
}}
>
<Slider.Track className="relative h-[6px] grow rounded-full bg-gray-400">
<Slider.Range className="absolute h-[100%] rounded-full bg-blue-600" />
</Slider.Track>
<Slider.Thumb className="flex h-[20px] w-[20px] items-center justify-center rounded-full bg-white !outline-none">
<div className="relative top-5 text-xs">{percentageValue.toFixed(0)}%</div>
</Slider.Thumb>
</Slider.Root>
<button
className="ml-4 rounded-md bg-blue-600 py-1 px-2 text-xs font-semibold text-white"
onClick={() => setAmount(maxValue)}
>
MAX
</button>
</div>
</>
)}
</ContainerSecondary>
<ContainerSecondary className="mb-2 flex items-center justify-between">
<div>
<h3 className="font-bold">Lending Assets</h3>
<div className="text-sm text-[#585A74]/50">Lend assets from account to earn yield.</div>
</div>
<Switch
checked={lendAssets}
onChange={setLendAssets}
className={`${
lendAssets ? 'bg-blue-600' : 'bg-gray-400'
} relative inline-flex h-6 w-11 items-center rounded-full`}
>
<span
className={`${
lendAssets ? 'translate-x-6' : 'translate-x-1'
} inline-block h-4 w-4 transform rounded-full bg-white transition`}
/>
</Switch>
</ContainerSecondary>
<Button
className="w-full !rounded-lg"
onClick={() => mutate()}
disabled={amount === 0 || !amount}
>
Fund
</Button>
</>
)
}
export default FundAccount

View File

@ -7,14 +7,14 @@ import useCreditManagerStore from 'stores/useCreditManagerStore'
import useWalletStore from 'stores/useWalletStore'
import useCreditAccountPositions from 'hooks/useCreditAccountPositions'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
import FundAccount from './FundAccount'
import useTokenPrices from 'hooks/useTokenPrices'
import useAccountStats from 'hooks/useAccountStats'
import useMarkets from 'hooks/useMarkets'
import ContainerSecondary from 'components/ContainerSecondary'
import FundAccountModal from 'components/FundAccountModal'
const CreditManager = () => {
const [isFund, setIsFund] = useState(false)
const [showFundWalletModal, setShowFundWalletModal] = useState(false)
const address = useWalletStore((s) => s.address)
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
@ -48,35 +48,22 @@ const CreditManager = () => {
return (
<div className="absolute inset-0 left-auto w-[400px] border-l border-white/20 bg-background-2 p-2">
<ContainerSecondary className="mb-2">
{isFund ? (
<div className="flex items-center justify-between">
<h3 className="font-bold">Fund Account</h3>
<Button className="rounded-md" onClick={() => setIsFund(false)}>
Cancel
</Button>
</div>
) : (
<div className="flex gap-3">
<Button className="flex-1 rounded-md" onClick={() => setIsFund(true)}>
<ContainerSecondary className="mb-2 flex gap-3">
<Button className="flex-1 rounded-md" onClick={() => setShowFundWalletModal(true)}>
Fund
</Button>
<Button className="flex-1 rounded-md" onClick={() => alert('TODO')}>
<Button
className="flex-1 rounded-md"
onClick={() => alert('TODO')}
disabled={!positionsData || positionsData.coins.length === 0}
>
Withdraw
</Button>
</div>
)}
</ContainerSecondary>
{isFund ? (
<FundAccount />
) : (
<>
<ContainerSecondary className="mb-2 text-sm">
<div className="mb-1 flex justify-between">
<div>Total Position:</div>
<div className="font-semibold">
{formatCurrency(accountStats?.totalPosition ?? 0)}
</div>
<div className="font-semibold">{formatCurrency(accountStats?.totalPosition ?? 0)}</div>
</div>
<div className="flex justify-between">
<div>Total Liabilities:</div>
@ -135,8 +122,11 @@ const CreditManager = () => {
</>
)}
</ContainerSecondary>
</>
)}
<FundAccountModal
key={`fundModal_${selectedAccount}`}
show={showFundWalletModal}
onClose={() => setShowFundWalletModal(false)}
/>
</div>
)
}

View File

@ -0,0 +1,220 @@
import React, { useEffect, useMemo, useState } from 'react'
import Image from 'next/image'
import { Transition, Dialog, Switch } from '@headlessui/react'
import BigNumber from 'bignumber.js'
import { toast } from 'react-toastify'
import useLocalStorageState from 'use-local-storage-state'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
import ContainerSecondary from './ContainerSecondary'
import useCreditManagerStore from 'stores/useCreditManagerStore'
import Button from './Button'
import Spinner from './Spinner'
import useAllBalances from 'hooks/useAllBalances'
import useAllowedCoins from 'hooks/useAllowedCoins'
import useDepositCreditAccount from 'hooks/useDepositCreditAccount'
import Slider from 'components/Slider'
const FundAccountModal = ({ show, onClose }: any) => {
const [amount, setAmount] = useState(0)
const [selectedToken, setSelectedToken] = useState('')
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
const [lendAssets, setLendAssets] = useLocalStorageState(`lendAssets_${selectedAccount}`, {
defaultValue: false,
})
const { data: balancesData } = useAllBalances()
const { data: allowedCoinsData, isLoading: isLoadingAllowedCoins } = useAllowedCoins()
const { mutate, isLoading } = useDepositCreditAccount(
selectedAccount || '',
selectedToken,
BigNumber(amount)
.times(10 ** getTokenDecimals(selectedToken))
.toNumber(),
{
onSuccess: () => {
setAmount(0)
toast.success(`${amount} ${getTokenSymbol(selectedToken)} successfully Deposited`)
onClose()
},
}
)
useEffect(() => {
if (allowedCoinsData && allowedCoinsData.length > 0) {
// initialize selected token when allowedCoins fetch data is available
setSelectedToken(allowedCoinsData[0])
}
}, [allowedCoinsData])
const walletAmount = useMemo(() => {
if (!selectedToken) return 0
return BigNumber(balancesData?.find((balance) => balance.denom === selectedToken)?.amount ?? 0)
.div(10 ** getTokenDecimals(selectedToken))
.toNumber()
}, [balancesData, selectedToken])
const handleValueChange = (value: number) => {
if (value > walletAmount) {
setAmount(walletAmount)
return
}
setAmount(value)
}
const maxValue = walletAmount
const percentageValue = isNaN(amount) ? 0 : (amount * 100) / maxValue
return (
<Transition appear show={show} as={React.Fragment}>
<Dialog as="div" className="relative z-10" onClose={onClose}>
<Transition.Child
as={React.Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-80" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4">
<Transition.Child
as={React.Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="flex min-h-[520px] w-full max-w-3xl transform overflow-hidden rounded-2xl bg-[#585A74] align-middle shadow-xl transition-all">
{isLoading && (
<div className="absolute inset-0 z-40 grid place-items-center bg-black/50">
<Spinner />
</div>
)}
<div className="flex flex-1 flex-col items-start justify-between bg-[#4A4C60] p-6">
<div>
<p className="text-bold mb-3 text-xs uppercase text-white/50">About</p>
<h4 className="mb-4 text-xl leading-8">
Bringing the next generation of video creation to the Metaverse.
<br />
Powered by deep-learning.
</h4>
</div>
<Image src="/logo.svg" alt="mars" width={150} height={50} />
</div>
<div className="flex flex-1 flex-col p-4">
<Dialog.Title as="h3" className="mb-4 text-center font-medium">
Fund Account {selectedAccount}
</Dialog.Title>
<ContainerSecondary className="mb-2 p-3">
<p className="mb-6 text-sm text-[#585A74]/50">
Transfer assets from your injective wallet to your Mars credit account. If you
dont have any assets in your injective wallet use the injective bridge to
transfer funds to your injective wallet.
</p>
{isLoadingAllowedCoins ? (
<p>Loading...</p>
) : (
<>
<div className="mb-2 rounded-md border border-[#585A74] text-sm">
<div className="mb-1 flex justify-between border-b border-[#585A74] p-2">
<div className="font-bold">Asset:</div>
<select
className="bg-transparent outline-0"
onChange={(e) => {
setSelectedToken(e.target.value)
if (e.target.value !== selectedToken) setAmount(0)
}}
value={selectedToken}
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
</option>
))}
</select>
</div>
<div className="flex justify-between p-2">
<div className="font-bold">Amount:</div>
<input
type="number"
className="bg-transparent text-right outline-0"
value={amount}
min="0"
onChange={(e) => handleValueChange(e.target.valueAsNumber)}
onBlur={(e) => {
if (e.target.value === '') setAmount(0)
}}
/>
</div>
</div>
<p className="mb-2 text-sm">In wallet: {walletAmount.toLocaleString()}</p>
<Slider
className="mb-6"
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(selectedToken)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))
setAmount(newAmount)
}}
onMaxClick={() => setAmount(maxValue)}
/>
</>
)}
</ContainerSecondary>
<ContainerSecondary className="mb-2 flex items-center justify-between">
<div>
<h3 className="font-bold">Lending Assets</h3>
<div className="text-sm text-[#585A74]/50">
Lend assets from account to earn yield.
</div>
</div>
<Switch
checked={lendAssets}
onChange={setLendAssets}
className={`${
lendAssets ? 'bg-blue-600' : 'bg-gray-400'
} relative inline-flex h-6 w-11 items-center rounded-full`}
>
<span
className={`${
lendAssets ? 'translate-x-6' : 'translate-x-1'
} inline-block h-4 w-4 transform rounded-full bg-white transition`}
/>
</Switch>
</ContainerSecondary>
<Button
className="mt-auto w-full"
onClick={() => mutate()}
disabled={amount === 0 || !amount}
>
Fund Account
</Button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)
}
export default FundAccountModal

39
components/Slider.tsx Normal file
View File

@ -0,0 +1,39 @@
import React from 'react'
import * as RadixSlider from '@radix-ui/react-slider'
type Props = {
className?: string
value: number
onChange: (value: number[]) => void
onMaxClick: () => void
}
const Slider = ({ className, value, onChange, onMaxClick }: Props) => {
return (
<div className={`relative flex flex-1 items-center ${className || ''}`}>
<RadixSlider.Root
className="relative flex h-[20px] w-full cursor-pointer touch-none select-none items-center"
value={[value]}
min={0}
max={100}
step={1}
onValueChange={(value) => onChange(value)}
>
<RadixSlider.Track className="relative h-[6px] grow rounded-full bg-gray-400">
<RadixSlider.Range className="absolute h-[100%] rounded-full bg-blue-600" />
</RadixSlider.Track>
<RadixSlider.Thumb className="flex h-[20px] w-[20px] items-center justify-center rounded-full bg-white !outline-none">
<div className="relative top-5 text-xs">{value.toFixed(0)}%</div>
</RadixSlider.Thumb>
</RadixSlider.Root>
<button
className="ml-4 rounded-md bg-blue-600 py-1 px-2 text-xs font-semibold text-white"
onClick={onMaxClick}
>
MAX
</button>
</div>
)
}
export default Slider

View File

@ -18,7 +18,7 @@ const WalletPopover = ({ children }: { children: React.ReactNode }) => {
return (
<Popover className="relative">
<Popover.Button as={Button} className="w-[200px]">
<Popover.Button as={Button} className="w-[200px] !rounded-3xl !bg-green-500">
{children}
</Popover.Button>
@ -79,7 +79,10 @@ const Wallet = () => {
{address ? (
<WalletPopover>{formatWalletAddress(address)}</WalletPopover>
) : (
<Button className="w-[200px]" onClick={() => setShowConnectModal(true)}>
<Button
className="w-[200px] !rounded-3xl !bg-green-500"
onClick={() => setShowConnectModal(true)}
>
Connect Wallet
</Button>
)}

View File

@ -1,5 +1,5 @@
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { useEffect, useState } from 'react'
import { toast } from 'react-toastify'
@ -9,7 +9,14 @@ import { contractAddresses } from 'config/contracts'
import { hardcodedFee } from 'utils/contants'
import { queryKeys } from 'types/query-keys-factory'
const useDepositCreditAccount = (accountId: string, denom: string, amount: number) => {
const useDepositCreditAccount = (
accountId: string,
denom: string,
amount: number,
options?: {
onSuccess?: () => void
}
) => {
const [signingClient, setSigningClient] = useState<SigningCosmWasmClient>()
const address = useWalletStore((s) => s.address)
@ -62,7 +69,7 @@ const useDepositCreditAccount = (accountId: string, denom: string, amount: numbe
queryClient.invalidateQueries(queryKeys.tokenBalance(address, denom))
queryClient.invalidateQueries(queryKeys.creditAccountsPositions(accountId))
toast.success('Deposited Successfully')
options?.onSuccess && options.onSuccess()
},
}
)

View File

@ -18,6 +18,7 @@
"@radix-ui/react-slider": "^1.0.0",
"@sentry/nextjs": "^7.12.1",
"@tanstack/react-query": "^4.3.4",
"@tanstack/react-query-devtools": "^4.12.0",
"@tanstack/react-table": "^8.5.15",
"@tippyjs/react": "^4.2.6",
"bech32": "^2.0.0",

View File

@ -5,6 +5,7 @@ import { ToastContainer, Zoom } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.min.css'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import detectEthereumProvider from '@metamask/detect-provider'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import '../styles/globals.css'
import Layout from 'components/Layout'
@ -41,7 +42,10 @@ function MyApp({ Component, pageProps }: AppProps) {
<link rel="icon" href="/favicon.svg" />
</Head>
<QueryClientProvider client={queryClient}>
<Layout>{address ? <Component {...pageProps} /> : <div>No wallet connected</div>}</Layout>
<ReactQueryDevtools initialIsOpen={false} />
<Layout>
<Component {...pageProps} />
</Layout>
<ToastContainer
autoClose={1500}
closeButton={false}

View File

@ -2140,11 +2140,27 @@
dependencies:
tslib "^2.4.0"
"@tanstack/match-sorter-utils@^8.1.1":
version "8.5.14"
resolved "https://registry.yarnpkg.com/@tanstack/match-sorter-utils/-/match-sorter-utils-8.5.14.tgz#12efcd536abe491d09521e0242bc4d51442f8a8a"
integrity sha512-lVNhzTcOJ2bZ4IU+PeCPQ36vowBHvviJb2ZfdRFX5uhy7G0jM8N34zAMbmS5ZmVH8D2B7oU82OWo0e/5ZFzQrw==
dependencies:
remove-accents "0.4.2"
"@tanstack/query-core@4.3.4":
version "4.3.4"
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.3.4.tgz#b93da17232fda91ec08ef14d2ca1d8326fc599f2"
integrity sha512-NLAe3j5Vk1yYEtoPP5fPGPjRzkZPx67KUM3f14L3InziJZJ0wVecCh7uKfgYkbRKJSeq6PlbND7iuCGdTplN6Q==
"@tanstack/react-query-devtools@^4.12.0":
version "4.12.0"
resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-4.12.0.tgz#18f341185f0a5580fc8b2daf8197389108be7131"
integrity sha512-gUV+aKpwgP7Cfp2+vwgu6krXCytncGWjTqFcnzC1l2INOf8dRi8/GEupYF7npxD9ky72FTuxc5+TI/lC8eB0Eg==
dependencies:
"@tanstack/match-sorter-utils" "^8.1.1"
superjson "^1.10.0"
use-sync-external-store "^1.2.0"
"@tanstack/react-query@^4.3.4":
version "4.3.4"
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.3.4.tgz#91a4232a967de04a0662d63d53b18ecc3e11c7e2"
@ -3006,6 +3022,13 @@ cookie@^0.4.1:
resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
copy-anything@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.2.tgz#7189171ff5e1893b2287e8bf574b8cd448ed50b1"
integrity sha512-CzATjGXzUQ0EvuvgOCI6A4BGOo2bcVx8B+eC2nF862iv9fopnPQwlrbACakNCHRIJbCSBj+J/9JeDf60k64MkA==
dependencies:
is-what "^4.1.6"
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
@ -4375,6 +4398,11 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
is-what@^4.1.6:
version "4.1.7"
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc"
integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==
is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz"
@ -5514,6 +5542,11 @@ regjsparser@^0.9.1:
dependencies:
jsesc "~0.5.0"
remove-accents@0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5"
integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==
repeat-element@^1.1.2:
version "1.1.4"
resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz"
@ -5949,6 +5982,13 @@ sucrase@^3.20.0:
pirates "^4.0.1"
ts-interface-checker "^0.1.9"
superjson@^1.10.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/superjson/-/superjson-1.11.0.tgz#f6e2ae0d8fbac61c3fca09ab6739ac9678414d1b"
integrity sha512-6PfAg1FKhqkwWvPb2uXhH4MkMttdc17eJ91+Aoz4s1XUEDZFmLfFx/xVA3wgkPxAGy5dpozgGdK6V/n20Wj9yg==
dependencies:
copy-anything "^3.0.2"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"