Skip to content

Commit

Permalink
use DynamicIcon in NetworkIcon, WalletIcon, TokenIcon
Browse files Browse the repository at this point in the history
  • Loading branch information
0xa3k5 committed Aug 17, 2024
1 parent 31e35b2 commit 06eef9d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 282 deletions.
74 changes: 9 additions & 65 deletions packages/react/src/NetworkIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,21 @@
import { forwardRef, ReactElement, useState, useEffect } from 'react'
import { networks } from '@web3icons/core/metadata'
import { INetworkMetadata } from '@web3icons/core'
import { forwardRef } from 'react'
import { NetworkIconProps } from './types'
import { toKebabCase, toPascalCase, NETWORK_ICON_IMPORT_MAP } from './utils'

const findNetwork = (network: string): INetworkMetadata | undefined => {
const networkObj = networks.find(
(net) =>
net.id.toLowerCase() === toKebabCase(network) ||
net.name.toLowerCase() === network.toLowerCase() ||
net.shortname?.toLowerCase() === network.toLowerCase(),
)
return networkObj
}

const DynamicIconLoader = forwardRef<SVGSVGElement, NetworkIconProps>(
(
{ network, size, className, variant, color }: NetworkIconProps,
ref,
): ReactElement | null => {
const [IconComponent, setIconComponent] = useState<ReactElement | null>(
null,
)

useEffect(() => {
const loadIcon = async () => {
const matchedNetwork = findNetwork(network)
if (!matchedNetwork) {
console.error(`Network not found: ${network}`)
return
}

const iconName = `Network${toPascalCase(matchedNetwork.name)}`
const importFunction =
NETWORK_ICON_IMPORT_MAP[iconName] ??
NETWORK_ICON_IMPORT_MAP[`Network${toPascalCase(matchedNetwork.id)}`]

if (importFunction) {
try {
const { default: ImportedIcon } = await importFunction()
setIconComponent(
<ImportedIcon
ref={ref}
network={network}
size={size}
color={color}
className={className}
variant={variant}
/>,
)
} catch (error) {
console.error(`Error loading icon: ${iconName}`, error)
}
}
}

loadIcon()
}, [network, ref, size, className, variant, color])

return IconComponent
},
)
import { findNetwork } from './utils'
import { DynamicIcon } from './DynamicIcon'

export const NetworkIcon = forwardRef<SVGSVGElement, NetworkIconProps>(
({ network, size, className, variant = 'mono', color }, ref) => {
({ network, size, className, variant = 'mono', color, fallback }, ref) => {
const metadata = findNetwork({ network })
return (
<DynamicIconLoader
network={network}
<DynamicIcon
type="network"
metadata={metadata}
size={size}
className={className}
variant={variant}
color={color}
ref={ref}
fallback={fallback}
/>
)
},
Expand Down
149 changes: 17 additions & 132 deletions packages/react/src/TokenIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,117 +1,7 @@
import { forwardRef, ReactElement, useEffect, useState } from 'react'
import { ITokenMetadata, tokens } from '@web3icons/core'
import { forwardRef } from 'react'
import { TokenIconProps } from './types'
import { TOKEN_ICON_IMPORT_MAP } from './utils'

const findToken = (
symbol?: string,
address?: string,
network?: string,
): ITokenMetadata | undefined => {
if (symbol) {
return tokens.find(
(token) => token.symbol.toLowerCase() === symbol.toLowerCase(),
)
} else if (address && network) {
return tokens.find(
(token) =>
token.addresses[network]?.toLowerCase() === address.toLowerCase(),
)
}
return undefined
}

const DynamicIconLoader = forwardRef<SVGSVGElement, TokenIconProps>(
(
{
symbol,
size,
className,
variant,
color,
address,
network,
defaultImg,
}: TokenIconProps,
ref,
): ReactElement | null => {
const [IconComponent, setIconComponent] = useState<ReactElement | null>(
null,
)

useEffect(() => {
const loadIcon = async () => {
const tokenData = findToken(symbol, address, network)

if (!tokenData) {
setIconComponent(
<img
ref={ref as React.RefObject<HTMLImageElement>}
src={defaultImg}
alt="default icon"
className={className}
style={{ width: size, height: size }}
/>,
)
return
}

const iconName = `Token${tokenData.symbol.toUpperCase()}`
const importFunction = TOKEN_ICON_IMPORT_MAP[iconName]

if (importFunction) {
try {
const { default: ImportedIcon } = await importFunction()
setIconComponent(
<ImportedIcon
ref={ref}
symbol={tokenData.symbol}
size={size}
color={color}
className={className}
variant={variant}
/>,
)
} catch (error) {
console.error(`Error loading icon: ${iconName}`, error)
setIconComponent(
<img
ref={ref as React.RefObject<HTMLImageElement>}
src={defaultImg}
alt="default icon"
className={className}
style={{ width: size, height: size }}
/>,
)
}
} else {
setIconComponent(
<img
ref={ref as React.RefObject<HTMLImageElement>}
src={defaultImg}
alt="defult icon"
className={className}
style={{ width: size, height: size }}
/>,
)
}
}
loadIcon()
}, [
symbol,
address,
network,
ref,
size,
className,
variant,
color,
defaultImg,
])

return IconComponent
},
)
import { findToken } from './utils'
import { DynamicIcon } from './DynamicIcon'

export const TokenIcon = forwardRef<SVGSVGElement, TokenIconProps>(
(
Expand All @@ -123,28 +13,23 @@ export const TokenIcon = forwardRef<SVGSVGElement, TokenIconProps>(
color,
address,
network,
defaultImg,
fallback,
},
ref,
) => {
const props = {
color,
size,
variant,
className,
ref,
defaultImg,
}

if (symbol) {
return <DynamicIconLoader symbol={symbol} {...props} />
}

if (address && network) {
return (
<DynamicIconLoader address={address} network={network} {...props} />
)
}
const metadata = findToken(symbol ? { symbol } : { address, network })
return (
<DynamicIcon
type="token"
metadata={metadata}
className={className}
color={color}
fallback={fallback}
ref={ref}
size={size}
variant={variant}
/>
)
},
)

Expand Down
103 changes: 18 additions & 85 deletions packages/react/src/WalletIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,24 @@
import { forwardRef, ReactElement, useState, useEffect } from 'react'
import { IWalletMetadata, wallets } from '@web3icons/core'
import { forwardRef } from 'react'
import { WalletIconProps } from './types'
import { toKebabCase, toPascalCase, WALLET_ICON_IMPORT_MAP } from './utils'

const findWallet = (wallet: string): IWalletMetadata | undefined => {
const walletObj = wallets.find(
(w) =>
w.id.toLowerCase() === toKebabCase(wallet) ||
w.name.toLowerCase() === wallet.toLowerCase(),
)
return walletObj
}

const DynamicIconLoader = forwardRef<SVGSVGElement, WalletIconProps>(
(
{ id, name, size, className, variant, color }: WalletIconProps,
ref,
): ReactElement | null => {
// prettier-ignore
const [IconComponent, setIconComponent] = useState<ReactElement | null>(null)

useEffect(() => {
const loadIcon = async () => {
const matchedWallet = findWallet(name ?? id)
if (!matchedWallet) {
return
}

const importFunction =
WALLET_ICON_IMPORT_MAP[`Wallet${toPascalCase(matchedWallet.name)}`] ??
WALLET_ICON_IMPORT_MAP[`Wallet${toPascalCase(matchedWallet.id)}`]

if (importFunction) {
try {
const { default: ImportedIcon } = await importFunction()
setIconComponent(
<ImportedIcon
ref={ref}
name={name}
id={id}
size={size}
color={color}
className={className}
variant={variant}
/>,
)
} catch (error) {
console.error(`Error loading icon: ${matchedWallet.name}`, error)
}
}
}

loadIcon()
}, [name, id, ref, size, className, variant, color])

return IconComponent
},
)
import { DynamicIcon } from './DynamicIcon'
import { findWallet } from './utils'

export const WalletIcon = forwardRef<SVGSVGElement, WalletIconProps>(
({ id, name, size, className, variant = 'mono', color }, ref) => {
if (id) {
return (
<DynamicIconLoader
id={id}
name={name}
size={size}
className={className}
variant={variant}
color={color}
ref={ref}
/>
)
}

if (name) {
return (
<DynamicIconLoader
name={name}
size={size}
className={className}
variant={variant}
color={color}
ref={ref}
/>
)
}
({ id, name, size, className, variant = 'mono', color, fallback }, ref) => {
const metadata = findWallet({ wallet: id ?? name })

return (
<DynamicIcon
metadata={metadata}
type="wallet"
size={size}
className={className}
variant={variant}
color={color}
ref={ref}
fallback={fallback}
/>
)
},
)

Expand Down

0 comments on commit 06eef9d

Please sign in to comment.