add token select modal; fix content widths;
This commit is contained in:
parent
771ee63ea5
commit
375d369573
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
"extends": "next/core-web-vitals",
|
||||
"rules": {
|
||||
"@next/next/no-img-element": 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ const Home = () => {
|
|||
<div className="mt-8">
|
||||
<div className="flex-col space-y-4">
|
||||
<div className="mx-auto flex max-w-7xl justify-center space-x-4">
|
||||
<div className="w-full space-y-6">
|
||||
<div className="flex-grow space-y-6">
|
||||
<SwapTokenChart
|
||||
inputTokenId={inputTokenInfo?.extensions?.coingeckoId}
|
||||
outputTokenId={outputTokenInfo?.extensions?.coingeckoId}
|
||||
|
|
|
@ -1,40 +1,50 @@
|
|||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import Image from 'next/image'
|
||||
import { useState } from 'react'
|
||||
import mangoStore from '../store/state'
|
||||
import SelectTokenModal from './swap/SelectTokenModal'
|
||||
|
||||
type TokenSelectProps = {
|
||||
token: string
|
||||
onChange: (x?: any) => void
|
||||
onChange: (x: string) => void
|
||||
}
|
||||
|
||||
const TokenSelect = ({ token, onChange }: TokenSelectProps) => {
|
||||
const [showTokenSelectModal, setShowTokenSelectModal] = useState(false)
|
||||
const group = mangoStore((s) => s.group)
|
||||
|
||||
const handleTokenSelect = (sym: string) => {
|
||||
setShowTokenSelectModal(false)
|
||||
onChange(sym)
|
||||
}
|
||||
|
||||
if (!group) return null
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div className="flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="30"
|
||||
height="30"
|
||||
src={`/icons/${token.toLowerCase()}.svg`}
|
||||
/>
|
||||
</div>
|
||||
<label htmlFor="tokenIn" className="sr-only">
|
||||
Token
|
||||
</label>
|
||||
<select
|
||||
id="tokenIn"
|
||||
name="tokenIn"
|
||||
autoComplete="token"
|
||||
className="text-mango-200 h-full rounded-md border-transparent bg-transparent pr-10 text-lg font-bold focus:ring-0"
|
||||
onChange={onChange}
|
||||
value={token}
|
||||
<>
|
||||
<div
|
||||
onClick={() => setShowTokenSelectModal(true)}
|
||||
className="-ml-3 flex h-full items-center rounded-full py-2 px-4 hover:cursor-pointer hover:shadow-lg hover:drop-shadow-lg hover:backdrop-brightness-125"
|
||||
>
|
||||
{Array.from(group.banksMap.keys()).map((symbol) => {
|
||||
return <option key={symbol}>{symbol}</option>
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mr-3 flex min-w-[24px] items-center">
|
||||
<Image
|
||||
alt=""
|
||||
width="30"
|
||||
height="30"
|
||||
src={`/icons/${token.toLowerCase()}.svg`}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xl text-th-fgd-2">{token}</div>
|
||||
<ChevronDownIcon className="ml-1.5 h-5 w-5 text-th-fgd-3" />
|
||||
</div>
|
||||
{showTokenSelectModal ? (
|
||||
<SelectTokenModal
|
||||
isOpen={showTokenSelectModal}
|
||||
onClose={() => setShowTokenSelectModal(false)}
|
||||
onTokenSelect={handleTokenSelect}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ const NotificationList = () => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`text-th-fgd-1 pointer-events-none fixed inset-0 z-50 flex items-end px-4 py-6 sm:p-6`}
|
||||
className={`pointer-events-none fixed bottom-0 left-0 z-50 flex w-full items-end px-4 py-6 text-th-fgd-1 sm:p-6`}
|
||||
>
|
||||
<div className={`flex w-full flex-col`}>
|
||||
{reversedNotifications.map((n) => (
|
||||
|
@ -127,31 +127,31 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
leaveTo="-translate-y-2 sm:translate-y-0 sm:-translate-x-48"
|
||||
>
|
||||
<div
|
||||
className={`border-th-bkg-4 bg-th-bkg-3 pointer-events-auto mt-2 w-full max-w-sm overflow-hidden rounded-md border shadow-lg ring-1 ring-black ring-opacity-5`}
|
||||
className={`pointer-events-auto mt-2 w-full max-w-sm overflow-hidden rounded-md border border-th-bkg-4 bg-th-bkg-3 shadow-lg ring-1 ring-black ring-opacity-5`}
|
||||
>
|
||||
<div className={`relative flex items-center px-2 py-2.5`}>
|
||||
<div className={`flex-shrink-0`}>
|
||||
{type === 'success' ? (
|
||||
<CheckCircleIcon className={`text-th-green mr-1 h-7 w-7`} />
|
||||
<CheckCircleIcon className={`mr-1 h-7 w-7 text-th-green`} />
|
||||
) : null}
|
||||
{type === 'info' && (
|
||||
<InformationCircleIcon
|
||||
className={`text-th-primary mr-1 h-7 w-7`}
|
||||
className={`mr-1 h-7 w-7 text-th-primary`}
|
||||
/>
|
||||
)}
|
||||
{type === 'error' && (
|
||||
<XCircleIcon className={`text-th-red mr-1 h-7 w-7`} />
|
||||
<XCircleIcon className={`mr-1 h-7 w-7 text-th-red`} />
|
||||
)}
|
||||
{type === 'confirm' && (
|
||||
<Loading className="text-th-fgd-3 mr-1 h-7 w-7" />
|
||||
<Loading className="mr-1 h-7 w-7 text-th-fgd-3" />
|
||||
)}
|
||||
</div>
|
||||
<div className={`ml-2 flex-1`}>
|
||||
<div className={`text-normal text-th-fgd-1 font-bold`}>
|
||||
<div className={`text-normal font-bold text-th-fgd-1`}>
|
||||
{parsedTitle || title}
|
||||
</div>
|
||||
{description ? (
|
||||
<p className={`text-th-fgd-3 mb-0 mt-0.5 leading-tight`}>
|
||||
<p className={`mb-0 mt-0.5 leading-tight text-th-fgd-3`}>
|
||||
{description}
|
||||
</p>
|
||||
) : null}
|
||||
|
@ -179,7 +179,7 @@ const Notification = ({ notification }: { notification: Notification }) => {
|
|||
<div className={`absolute right-2 top-2 flex-shrink-0`}>
|
||||
<button
|
||||
onClick={hideNotification}
|
||||
className={`text-th-fgd-4 md:hover:text-th-primary focus:outline-none`}
|
||||
className={`text-th-fgd-4 focus:outline-none md:hover:text-th-primary`}
|
||||
>
|
||||
<span className={`sr-only`}>Close</span>
|
||||
<svg
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
import {
|
||||
memo,
|
||||
useMemo,
|
||||
useState,
|
||||
PureComponent,
|
||||
useEffect,
|
||||
ChangeEvent,
|
||||
} from 'react'
|
||||
import { SearchIcon } from '@heroicons/react/outline'
|
||||
import Image from 'next/image'
|
||||
import { FixedSizeList } from 'react-window'
|
||||
|
||||
import Modal from '../shared/Modal'
|
||||
import { Token } from '../../types/jupiter'
|
||||
import mangoStore from '../../store/state'
|
||||
|
||||
const generateSearchTerm = (item: Token, searchValue: string) => {
|
||||
const normalizedSearchValue = searchValue.toLowerCase()
|
||||
const values = `${item.symbol} ${item.name}`.toLowerCase()
|
||||
|
||||
const isMatchingWithSymbol =
|
||||
item.symbol.toLowerCase().indexOf(normalizedSearchValue) >= 0
|
||||
const matchingSymbolPercent = isMatchingWithSymbol
|
||||
? normalizedSearchValue.length / item.symbol.length
|
||||
: 0
|
||||
|
||||
return {
|
||||
token: item,
|
||||
matchingIdx: values.indexOf(normalizedSearchValue),
|
||||
matchingSymbolPercent,
|
||||
}
|
||||
}
|
||||
|
||||
const startSearch = (items: Token[], searchValue: string) => {
|
||||
return items
|
||||
.map((item) => generateSearchTerm(item, searchValue))
|
||||
.filter((item) => item.matchingIdx >= 0)
|
||||
.sort((i1, i2) => i1.matchingIdx - i2.matchingIdx)
|
||||
.sort((i1, i2) => i2.matchingSymbolPercent - i1.matchingSymbolPercent)
|
||||
.map((item) => item.token)
|
||||
}
|
||||
|
||||
type ItemRendererProps = {
|
||||
data: any
|
||||
index: number
|
||||
style: any
|
||||
}
|
||||
|
||||
class ItemRenderer extends PureComponent<ItemRendererProps> {
|
||||
render() {
|
||||
// Access the items array using the "data" prop:
|
||||
const tokenInfo: Token = this.props.data.items[this.props.index]
|
||||
|
||||
return (
|
||||
<div style={this.props.style}>
|
||||
<button
|
||||
key={tokenInfo?.address}
|
||||
className="flex w-full cursor-pointer items-center justify-between rounded-none py-4 px-2 font-normal focus:bg-th-bkg-3 focus:outline-none md:hover:bg-th-bkg-4"
|
||||
onClick={() => this.props.data.onSubmit(tokenInfo.symbol)}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<picture>
|
||||
<source srcSet={tokenInfo?.logoURI} type="image/webp" />
|
||||
<img
|
||||
src={tokenInfo?.logoURI}
|
||||
width="24"
|
||||
height="24"
|
||||
alt={tokenInfo?.symbol}
|
||||
/>
|
||||
</picture>
|
||||
<div className="ml-4">
|
||||
<div className="text-left text-th-fgd-2">
|
||||
{tokenInfo?.symbol || 'unknown'}
|
||||
</div>
|
||||
<div className="text-left text-th-fgd-4">
|
||||
{tokenInfo?.name || 'unknown'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const popularTokenSymbols = ['USDC', 'SOL', 'USDT', 'MNGO', 'BTC', 'ETH']
|
||||
|
||||
const SelectTokenModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
onTokenSelect,
|
||||
}: {
|
||||
isOpen: boolean
|
||||
onClose: (x?: any) => void
|
||||
onTokenSelect: (x: string) => void
|
||||
}) => {
|
||||
const [search, setSearch] = useState('')
|
||||
const tokens = mangoStore.getState().jupiterTokens
|
||||
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
||||
|
||||
const popularTokens = useMemo(() => {
|
||||
return walletTokens?.length
|
||||
? tokens.filter((token) => {
|
||||
const walletMints = walletTokens.map((tok) => tok.mint.toString())
|
||||
return !token?.name || !token?.symbol
|
||||
? false
|
||||
: popularTokenSymbols.includes(token.symbol) &&
|
||||
walletMints.includes(token.address)
|
||||
})
|
||||
: tokens.filter((token) => {
|
||||
return !token?.name || !token?.symbol
|
||||
? false
|
||||
: popularTokenSymbols.includes(token.symbol)
|
||||
})
|
||||
}, [walletTokens, tokens])
|
||||
|
||||
useEffect(() => {
|
||||
function onEscape(e: any) {
|
||||
if (e.keyCode === 27) {
|
||||
onClose?.()
|
||||
}
|
||||
}
|
||||
window.addEventListener('keydown', onEscape)
|
||||
return () => window.removeEventListener('keydown', onEscape)
|
||||
}, [onClose])
|
||||
|
||||
const tokenInfos = useMemo(() => {
|
||||
if (tokens?.length) {
|
||||
const filteredTokens = tokens.filter((token) => {
|
||||
return !token?.name || !token?.symbol ? false : true
|
||||
})
|
||||
if (walletTokens?.length) {
|
||||
const walletMints = walletTokens.map((tok) => tok.mint.toString())
|
||||
return filteredTokens.sort(
|
||||
(a, b) =>
|
||||
walletMints.indexOf(b.address) - walletMints.indexOf(a.address)
|
||||
)
|
||||
} else {
|
||||
return filteredTokens
|
||||
}
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}, [tokens, walletTokens])
|
||||
|
||||
const handleUpdateSearch = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearch(e.target.value)
|
||||
}
|
||||
|
||||
const sortedTokens = search ? startSearch(tokenInfos, search) : tokenInfos
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<div className="flex flex-col pb-2 md:h-2/3">
|
||||
<div className="flex items-center text-lg text-th-fgd-4">
|
||||
<SearchIcon className="h-8 w-8" />
|
||||
<input
|
||||
type="text"
|
||||
className="ml-4 flex-1 bg-transparent focus:outline-none"
|
||||
placeholder="Search by token or paste address"
|
||||
autoFocus
|
||||
value={search}
|
||||
onChange={handleUpdateSearch}
|
||||
/>
|
||||
</div>
|
||||
{popularTokens.length && onTokenSelect ? (
|
||||
<div className="mt-8 flex flex-wrap">
|
||||
{popularTokens.map((token) => (
|
||||
<button
|
||||
className="mx-1 mb-2 flex items-center rounded-md border border-th-bkg-4 py-1 px-3 hover:border-th-fgd-3 focus:border-th-fgd-2"
|
||||
onClick={() => onTokenSelect(token.symbol)}
|
||||
key={token.address}
|
||||
>
|
||||
<Image
|
||||
alt=""
|
||||
width="16"
|
||||
height="16"
|
||||
src={`/icons/${token.symbol.toLowerCase()}.svg`}
|
||||
/>
|
||||
<span className="ml-1.5 text-th-fgd-1">{token.symbol}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="-ml-6 mt-2 w-[600px] border-t border-th-bkg-4"></div>
|
||||
<FixedSizeList
|
||||
width="100%"
|
||||
height={403}
|
||||
itemData={{ items: sortedTokens, onSubmit: onTokenSelect }}
|
||||
itemCount={sortedTokens.length}
|
||||
itemSize={72}
|
||||
className="thin-scroll"
|
||||
>
|
||||
{ItemRenderer}
|
||||
</FixedSizeList>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(SelectTokenModal)
|
|
@ -25,23 +25,29 @@ const Swap = () => {
|
|||
setAmountIn(e.target.value)
|
||||
}
|
||||
|
||||
const handleTokenInSelect = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||
const inputTokenInfo = tokens.find((t: any) => t.symbol === e.target.value)
|
||||
const handleTokenInSelect = (symbol: string) => {
|
||||
const inputTokenInfo = tokens.find((t: any) => t.symbol === symbol)
|
||||
set((s) => {
|
||||
s.inputTokenInfo = inputTokenInfo
|
||||
})
|
||||
setInputToken(e.target.value)
|
||||
setInputToken(symbol)
|
||||
}
|
||||
|
||||
const handleTokenOutSelect = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||
const outputTokenInfo = tokens.find((t: any) => t.symbol === e.target.value)
|
||||
const handleTokenOutSelect = (symbol: string) => {
|
||||
const outputTokenInfo = tokens.find((t: any) => t.symbol === symbol)
|
||||
set((s) => {
|
||||
s.outputTokenInfo = outputTokenInfo
|
||||
})
|
||||
setOutputToken(e.target.value)
|
||||
setOutputToken(symbol)
|
||||
}
|
||||
|
||||
const handleSwitchTokens = () => {
|
||||
const inputTokenInfo = tokens.find((t: any) => t.symbol === inputToken)
|
||||
const outputTokenInfo = tokens.find((t: any) => t.symbol === outputToken)
|
||||
set((s) => {
|
||||
s.inputTokenInfo = outputTokenInfo
|
||||
s.outputTokenInfo = inputTokenInfo
|
||||
})
|
||||
setInputToken(outputToken)
|
||||
setOutputToken(inputToken)
|
||||
}
|
||||
|
@ -90,21 +96,21 @@ const Swap = () => {
|
|||
<ContentBox className="max-w-md">
|
||||
<div className="">
|
||||
<div className="mt-1 flex-col rounded-md bg-th-bkg-1 py-2 px-6">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center justify-between">
|
||||
<TokenSelect token={inputToken} onChange={handleTokenInSelect} />
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
name="amountIn"
|
||||
id="amountIn"
|
||||
className="tex-th-fgd-2 w-full rounded-lg border-none bg-transparent text-right text-2xl focus:ring-0"
|
||||
className="w-full rounded-lg border-none bg-transparent text-right text-2xl text-th-fgd-3 focus:outline-none"
|
||||
placeholder="0.00"
|
||||
value={amountIn}
|
||||
onChange={handleAmountInChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="mb-1">
|
||||
<label
|
||||
htmlFor="default-range"
|
||||
className="block text-sm font-medium text-gray-900 dark:text-gray-300"
|
||||
|
@ -122,9 +128,9 @@ const Swap = () => {
|
|||
{/* <SwitchVerticalIcon className="default-transition h-10 w-10 rounded-full border-4 border-th-bkg-1 bg-th-bkg-2 p-1.5 text-th-fgd-3 md:hover:text-th-primary" /> */}
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-4 flex items-center justify-between rounded-md py-2 px-6">
|
||||
<div className="mt-4 flex items-center justify-between py-2 px-6">
|
||||
<TokenSelect token={outputToken} onChange={handleTokenOutSelect} />
|
||||
<div className="tex-th-fgd-2 w-full text-right text-2xl">
|
||||
<div className="w-full cursor-context-menu text-right text-2xl text-th-fgd-3">
|
||||
{amountOut ? numberFormat.format(amountOut) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -97,40 +97,6 @@ const SwapTokenChart: FunctionComponent<SwapTokenChartProps> = ({
|
|||
setChartData(formattedData.filter((d: any) => d.price))
|
||||
}
|
||||
|
||||
// Alternative chart data. Needs a timestamp tolerance to get data points for each asset
|
||||
|
||||
// const getChartData = async () => {
|
||||
// const now = Date.now() / 1000
|
||||
// const inputResponse = await fetch(
|
||||
// `https://api.coingecko.com/api/v3/coins/${inputTokenId}/market_chart/range?vs_currency=usd&from=${
|
||||
// now - 1 * 86400
|
||||
// }&to=${now}`
|
||||
// )
|
||||
|
||||
// const outputResponse = await fetch(
|
||||
// `https://api.coingecko.com/api/v3/coins/${outputTokenId}/market_chart/range?vs_currency=usd&from=${
|
||||
// now - 1 * 86400
|
||||
// }&to=${now}`
|
||||
// )
|
||||
// const inputData = await inputResponse.json()
|
||||
// const outputData = await outputResponse.json()
|
||||
|
||||
// const data = inputData?.prices.concat(outputData?.prices)
|
||||
|
||||
// const formattedData = data.reduce((a, c) => {
|
||||
// const found = a.find(
|
||||
// (price) => c[0] >= price.time - 120000 && c[0] <= price.time + 120000
|
||||
// )
|
||||
// if (found) {
|
||||
// found.price = found.inputPrice / c[1]
|
||||
// } else {
|
||||
// a.push({ time: c[0], inputPrice: c[1] })
|
||||
// }
|
||||
// return a
|
||||
// }, [])
|
||||
// setChartData(formattedData.filter((d) => d.price))
|
||||
// }
|
||||
|
||||
const getInputTokenInfo = async () => {
|
||||
const response = await fetch(
|
||||
`https://api.coingecko.com/api/v3/coins/${inputTokenId}?localization=false&tickers=false&developer_data=false&sparkline=false
|
||||
|
@ -247,7 +213,7 @@ const SwapTokenChart: FunctionComponent<SwapTokenChartProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
{!hideChart ? (
|
||||
<div className="mt-6 h-36 w-full" ref={observe}>
|
||||
<div className="mt-6 h-36" ref={observe}>
|
||||
<AreaChart
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
env: {
|
||||
BROWSER: true,
|
||||
},
|
||||
images: {
|
||||
domains: ['raw.githubusercontent.com'],
|
||||
},
|
||||
reactStrictMode: true,
|
||||
webpack: (config, { isServer }) => {
|
||||
if (!isServer) {
|
||||
// don't resolve 'fs' module on the client to prevent this error on build --> Error: Can't resolve 'fs'
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
"@types/node": "17.0.23",
|
||||
"@types/react": "18.0.3",
|
||||
"@types/react-dom": "18.0.0",
|
||||
"@types/react-window": "^1.8.5",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"eslint": "8.13.0",
|
||||
"eslint-config-next": "12.1.5",
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
getTokenAccountsByOwnerWithWrappedSol,
|
||||
TokenAccount,
|
||||
} from '../utils/tokens'
|
||||
import { Token } from '../types/jupiter'
|
||||
|
||||
const DEVNET_GROUP = new PublicKey(
|
||||
'A9XhGqUUjV992cD36qWDY8wDiZnGuCaUWtSE3NGXjDCb'
|
||||
|
@ -41,7 +42,7 @@ export type MangoStore = {
|
|||
connection: Connection
|
||||
group: Group | undefined
|
||||
client: MangoClient
|
||||
jupiterTokens: any[]
|
||||
jupiterTokens: Token[]
|
||||
mangoAccount: MangoAccount | undefined
|
||||
markets: Serum3Market[] | undefined
|
||||
notificationIdCounter: number
|
||||
|
|
|
@ -124,5 +124,5 @@ module.exports = {
|
|||
// textColor: ['disabled'],
|
||||
// },
|
||||
// },
|
||||
plugins: [require('@tailwindcss/forms')],
|
||||
plugins: [],
|
||||
}
|
||||
|
|
|
@ -9,3 +9,13 @@ export type Routes = {
|
|||
routesInfos: RouteInfo[]
|
||||
cached: boolean
|
||||
}
|
||||
|
||||
export interface Token {
|
||||
chainId: number // 101,
|
||||
address: string // 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||
symbol: string // 'USDC',
|
||||
name: string // 'Wrapped USDC',
|
||||
decimals: number // 6,
|
||||
logoURI: string // 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/BXXkv6z8ykpG1yuvUDPgh732wzVHB69RnB9YgSYh3itW/logo.png',
|
||||
tags: string[] // [ 'stablecoin' ]
|
||||
}
|
||||
|
|
22
yarn.lock
22
yarn.lock
|
@ -10,7 +10,7 @@
|
|||
core-js-pure "^3.20.2"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580"
|
||||
integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==
|
||||
|
@ -1143,6 +1143,13 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-window@^1.8.5":
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.5.tgz#285fcc5cea703eef78d90f499e1457e9b5c02fc1"
|
||||
integrity sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@18.0.3":
|
||||
version "18.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.3.tgz#baefa397561372015b9f8ba5bc83bc3f84ae8fcb"
|
||||
|
@ -3231,6 +3238,11 @@ md5.js@^1.3.4:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
"memoize-one@>=3.1.1 <6":
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
|
||||
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
|
@ -3787,6 +3799,14 @@ react-transition-group@2.9.0:
|
|||
prop-types "^15.6.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react-window@1.8.6:
|
||||
version "1.8.6"
|
||||
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112"
|
||||
integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
memoize-one ">=3.1.1 <6"
|
||||
|
||||
react@18.0.0:
|
||||
version "18.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96"
|
||||
|
|
Loading…
Reference in New Issue